/* =============================================================
   FLINT & FLUX — main.css
   Single master stylesheet. No per-page CSS. No inline styles.

   ORDER OF SECTIONS
     0.  FONT FACES             (self-hosted Source Sans 3, variable)
     1.  TOKENS                (brand + semantic + scale + motion)
     2.  ACCESSIBILITY STATES  (text size, contrast, motion-off)
     3.  RESET + BASE
     4.  TYPOGRAPHY            (headings, lead, eyebrow, kicker, statement)
     5.  LAYOUT PRIMITIVES     (.wrap, .stage + variants, .hexbg)
     6.  MOTION                (.rv + variants, keyframes)
     7.  COMPONENTS            (buttons, header, nav, forms, cards, footer, a11y widget)
     8.  PAGE PATTERNS         (hero, trustbar, svc, managed, port, why, tier, about, contact, closer, prose)
     9.  RESPONSIVE
   ============================================================= */


/* =============================================================
   0. FONT FACES
   Self-hosted Source Sans 3 (variable axis, Latin subset).
   Two files cover every weight/style this site uses:
     - source-sans-3-latin.woff2          weights 200-900, normal
     - source-sans-3-latin-italic.woff2   weights 200-900, italic
   Each ~28 KB. font-display: swap so layout isn't blocked on the
   font fetch; fallback stack in --font-sans renders first.
   ============================================================= */
@font-face{
  font-family:'Source Sans 3';
  font-style:normal;
  font-weight:200 900;
  font-display:swap;
  src:url('/assets/fonts/source-sans-3-latin.woff2') format('woff2');
}
@font-face{
  font-family:'Source Sans 3';
  font-style:italic;
  font-weight:200 900;
  font-display:swap;
  src:url('/assets/fonts/source-sans-3-latin-italic.woff2') format('woff2');
}


/* =============================================================
   1. TOKENS
   ============================================================= */
:root{
  /* ---- brand palette (do not modify) ---- */
  --bone:#f5f4f3;
  --bone-soft:rgba(245,244,243,.72);
  --bone-mute:rgba(245,244,243,.5);
  --bone-faint:rgba(245,244,243,.08);
  --blush:#e9d5de;
  --ink:#222226;
  --ink-deep:#1c1b20;
  --ink-violet:#26242e;
  --slate-d:#393941;
  --orange:#d14627;
  --orange-d:#b63826;
  --blue:#2f4b68;

  /* ---- semantic surface (dark default) ----
     Components bind to these. .stage--light, .stage--violet, etc.
     re-bind these inside their scope, so a single ruleset works
     on both registers without forking. */
  --surface:       var(--ink);
  --surface-alt:   var(--ink-deep);
  --surface-card:  var(--ink-violet);
  --text:          var(--bone);
  --text-soft:     var(--bone-soft);
  --text-mute:     var(--bone-mute);
  --hairline:      var(--bone-faint);
  --accent:        var(--orange);
  --accent-hover:  var(--orange-d);
  --hex-stroke:    rgba(255,255,255,.025);
  --hex-glyph:     rgba(255,255,255,.02);

  /* ---- typography ---- */
  --font-sans:'Source Sans 3','Source Sans Pro',-apple-system,BlinkMacSystemFont,'Segoe UI',sans-serif;

  /* Text-size accessibility scale. The widget sets a11y-text-lg
     or a11y-text-xl on <html>, which rebinds --type-scale below
     (see section 2). Every --fs-* token below multiplies by it,
     so toggling text size actually scales the whole type system. */
  --type-scale: 1;

  /* fluid type scale — every size is a single token, no inline clamp() */
  --fs-display:  calc(clamp(56px, 8.4vw, 104px) * var(--type-scale));
  --fs-hero:     calc(clamp(40px, 6.4vw, 76px)  * var(--type-scale));
  --fs-h1:       calc(clamp(34px, 5vw,   58px)  * var(--type-scale));
  --fs-h2:       calc(clamp(30px, 4vw,   46px)  * var(--type-scale));
  --fs-h3:       calc(20px * var(--type-scale));
  --fs-body:     calc(16px * var(--type-scale));
  --fs-lead:     calc(19px * var(--type-scale));
  --fs-small:    calc(14px * var(--type-scale));
  --fs-eyebrow:  calc(12px * var(--type-scale));

  /* statement variants */
  --fs-statement-display: calc(clamp(48px, 8vw,   96px) * var(--type-scale));
  --fs-statement-hero:    calc(clamp(36px, 5.5vw, 64px) * var(--type-scale));
  --fs-statement-inline:  calc(clamp(20px, 2.6vw, 30px) * var(--type-scale));

  --fw-reg:400;
  --fw-semi:600;
  --fw-bold:700;
  --fw-black:900;

  --lh-tight:1.04;
  --lh-snug:1.18;
  --lh-base:1.45;
  --lh-body:1.62;

  --tracking-tight:-.01em;
  --tracking-flat:0;
  --tracking-wide:.1em;
  --tracking-wider:.18em;
  --tracking-widest:.32em;

  /* ---- spacing scale (8px ramp) ---- */
  --sp-1:8px;
  --sp-2:16px;
  --sp-3:24px;
  --sp-4:32px;
  --sp-5:40px;
  --sp-6:56px;
  --sp-7:72px;
  --sp-8:96px;
  --sp-9:120px;
  --sp-10:144px;

  /* stage padding — generous internal breathing room, content-driven
     height (round 3: dropped the enforced 100svh per stage). */
  --stage-pad-y: clamp(64px, 7vw, 96px);

  /* ---- layout ---- */
  --maxw:1180px;
  --maxw-narrow:760px;
  --gutter:32px;
  --radius:6px;
  --radius-lg:10px;
  --stage-min-h:100svh;

  /* ---- motion vocabulary ----
     Snap eases lead. Soft is for parity transitions only. */
  --ease-snap:    cubic-bezier(.2,.8,.2,1);
  --ease-soft:    cubic-bezier(.25,.46,.45,.94);
  --ease-in-out:  cubic-bezier(.65,0,.35,1);
  --ease-flip:    cubic-bezier(.7,0,.2,1);

  --dur-quick:180ms;
  --dur:320ms;
  --dur-stage:820ms;   /* reveal duration — deliberate, clearly visible (round 3) */
  --dur-flip:420ms;

  --reveal-distance:48px;

  /* legacy alias — kept so existing rules using var(--ease) still work */
  --ease:var(--ease-snap);
}


/* =============================================================
   2. ACCESSIBILITY STATES
   ============================================================= */
/* Text-size states. The --type-scale custom property (declared in
   :root above) is multiplied into every --fs-* token, so changing
   it here actually resizes the whole type system, including the
   px-based and clamp()-based sizes. font-size on html also bumps
   so any future rem-based sizes scale identically. */
html.a11y-text-lg{--type-scale:1.125;font-size:112.5%}
html.a11y-text-xl{--type-scale:1.25;font-size:125%}

html.a11y-contrast{
  --bone:#ffffff;
  --bone-soft:#ffffff;
  --bone-mute:#dddddd;
  --bone-faint:rgba(255,255,255,.25);
  --ink:#000000;
  --ink-deep:#000000;
  --ink-violet:#0a0a0a;
  --slate-d:#1a1a1a;
  --orange:#ff7a3d;
  --orange-d:#ff5a1f;
  --blue:#5b8fc4;
  --hex-stroke:transparent;
  --hex-glyph:transparent;
}
html.a11y-contrast .hexbg::before{display:none}
html.a11y-contrast a:focus,
html.a11y-contrast button:focus{outline:3px solid var(--accent);outline-offset:3px}

html.a11y-motion-off *,
html.a11y-motion-off *::before,
html.a11y-motion-off *::after{
  animation:none!important;
  transition:none!important;
}
@media (prefers-reduced-motion:reduce){
  *,*::before,*::after{animation:none!important;transition:none!important}
}


/* =============================================================
   3. RESET + BASE
   ============================================================= */
*{margin:0;padding:0;box-sizing:border-box}
html{scroll-behavior:smooth}
@media (prefers-reduced-motion:reduce){html{scroll-behavior:auto}}
body{
  font-family:var(--font-sans);
  font-size:var(--fs-body);
  line-height:var(--lh-body);
  background:var(--surface);
  color:var(--text);
  -webkit-font-smoothing:antialiased;
  text-rendering:optimizeLegibility;
  overflow-x:hidden;
}
img,svg{display:block;max-width:100%;height:auto}
a{color:inherit}

/* inline content links inside body copy — accent colour with an
   underline so they read as links (base <a> is color:inherit). */
.sec-head p a,.bio-text p a,.lead a,.contact-info p a,.why-card p a{
  color:var(--accent);text-decoration:none;
  border-bottom:1px solid currentColor;
  transition:color var(--dur-quick) var(--ease-snap),
             border-color var(--dur-quick) var(--ease-snap);
}
.sec-head p a:hover,.bio-text p a:hover,.lead a:hover,.contact-info p a:hover,.why-card p a:hover{
  color:var(--text);border-color:var(--text);
}
button{font:inherit;cursor:pointer;background:none;border:0;color:inherit}

a:focus-visible,
button:focus-visible,
input:focus-visible,
textarea:focus-visible{
  outline:2px solid var(--accent);
  outline-offset:3px;
  border-radius:2px;
}

.skip{
  position:absolute;left:-9999px;top:0;
  background:var(--accent);color:var(--bone);
  padding:12px 18px;font-weight:var(--fw-bold);
  z-index:9999;text-decoration:none;
  letter-spacing:var(--tracking-wide);text-transform:uppercase;font-size:13px;
}
.skip:focus{left:8px;top:8px}


/* =============================================================
   4. TYPOGRAPHY
   ============================================================= */
h1,h2,h3,h4{font-weight:var(--fw-black);text-transform:uppercase}

h1{
  font-size:var(--fs-hero);
  line-height:var(--lh-tight);
  letter-spacing:var(--tracking-tight);
  max-width:14ch;
}
h1 em{font-style:italic;color:var(--accent);text-transform:uppercase}

h2{
  font-size:var(--fs-h2);
  line-height:var(--lh-snug);
  letter-spacing:-.005em;
}
h2 em{font-style:italic;color:var(--accent)}

h3{
  font-size:var(--fs-h3);
  letter-spacing:.02em;
}

p.lead{
  font-size:var(--fs-lead);
  line-height:var(--lh-body);
  color:var(--text-soft);
  font-weight:var(--fw-reg);
}

.eyebrow{
  display:inline-flex;align-items:center;gap:12px;
  font-size:var(--fs-eyebrow);font-weight:var(--fw-bold);
  letter-spacing:var(--tracking-widest);text-transform:uppercase;
  color:var(--accent);margin-bottom:30px;
}
.eyebrow::before{content:"";width:38px;height:2px;background:var(--accent)}

.kicker{
  font-size:var(--fs-eyebrow);font-weight:var(--fw-bold);
  letter-spacing:var(--tracking-widest);text-transform:uppercase;
  color:var(--accent);margin-bottom:18px;
}

/* ---- .statement ----
   Brand signature treatment: uppercase, italic-emphasis word,
   orange underline stroke painted under each visible line.
   Use sparingly, on major statements only.

     <p class="statement statement--hero">
       Creating value by <em>building</em> relationships
     </p>

   Sizes: --display (biggest brand moments), --hero (default),
   --inline (smaller contexts, e.g. closers, callouts).
*/
.statement{
  display:inline-block;
  position:relative;
  font-weight:var(--fw-black);
  text-transform:uppercase;
  letter-spacing:var(--tracking-tight);
  line-height:1.16;
  padding-bottom:.26em;
  font-size:var(--fs-statement-hero);
}
/* Single orange stroke beneath the whole statement block, regardless
   of how many lines it wraps to. inline-block resolves the element's
   width to its laid-out content, so width:100% on the ::after spans
   the block once — no per-line underlines (the old box-decoration-break
   clone read as strikethrough on narrow multi-line statements). */
.statement::after{
  content:"";
  position:absolute;left:0;bottom:0;
  width:100%;height:4px;
  background:var(--accent);
}
.statement em{
  font-style:italic;
  font-weight:var(--fw-black);
  color:var(--accent);
}
.statement--display{font-size:var(--fs-statement-display);line-height:1.08}
.statement--hero   {font-size:var(--fs-statement-hero)}
.statement--inline {font-size:var(--fs-statement-inline);line-height:1.22}

/* Block-wrapper for centering / sizing the statement without
   forcing display:block on the inline element itself */
.statement-wrap{display:block;max-width:24ch}
.statement-wrap--narrow{max-width:18ch}
.statement-wrap--wide  {max-width:32ch}
.statement-wrap--center{margin-left:auto;margin-right:auto;text-align:center}


/* =============================================================
   5. LAYOUT PRIMITIVES
   ============================================================= */
.wrap{max-width:var(--maxw);margin:0 auto;padding:0 var(--gutter)}
.wrap--narrow{max-width:var(--maxw-narrow)}

/* ---- .stage ----
   The scroll-storytelling primitive. Each major home-page section
   is a .stage with a surface modifier. Vertical rhythm comes from
   alternating modifiers down the page, not from whitespace.

     <section class="stage stage--dark">
       <div class="wrap"> ... </div>
     </section>
*/
.stage{
  position:relative;
  padding:var(--stage-pad-y) 0;
  display:grid;
  align-content:center;
  background:var(--surface);
  color:var(--text);
}
/* round 3: stages are content-driven (no enforced 100svh). The hero
   and relationship section opt back into extra presence individually.
   .stage--auto kept as a harmless no-op for existing markup. */
.stage--auto       {min-height:0}
.stage--top        {align-content:start}
.stage--bottom     {align-content:end}

/* surface variants — re-bind the semantic tokens inside scope */
.stage--dark{
  --surface:      var(--ink);
  --surface-alt:  var(--ink-deep);
  --surface-card: var(--ink-violet);
  --text:         var(--bone);
  --text-soft:    var(--bone-soft);
  --text-mute:    var(--bone-mute);
  --hairline:     var(--bone-faint);
  --hex-stroke:   rgba(255,255,255,.025);
  --hex-glyph:    rgba(255,255,255,.02);
}
.stage--ink-violet{
  --surface:      var(--ink-violet);
  --surface-alt:  var(--ink-deep);
  --surface-card: var(--ink);
  --text:         var(--bone);
  --text-soft:    var(--bone-soft);
  --text-mute:    var(--bone-mute);
  --hairline:     var(--bone-faint);
}
.stage--slate{
  --surface:      var(--slate-d);
  --surface-alt:  var(--ink);
  --surface-card: var(--ink-violet);
}
.stage--light{
  --surface:      var(--bone);
  --surface-alt:  #ececea;
  --surface-card: #ffffff;
  --text:         var(--ink);
  --text-soft:    rgba(34,34,38,.74);
  --text-mute:    rgba(34,34,38,.52);
  --hairline:     rgba(34,34,38,.12);
  --hex-stroke:   rgba(34,34,38,.05);
  --hex-glyph:    rgba(34,34,38,.04);
}
.stage--blue{
  --surface:      var(--blue);
  --surface-alt:  #243a52;
  --surface-card: #38597d;
  --text:         var(--bone);
  --text-soft:    rgba(245,244,243,.82);
  --text-mute:    rgba(245,244,243,.62);
  --hairline:     rgba(245,244,243,.14);
}

/* hex texture — atmosphere, not wallpaper.
   Sparse tile (140x160), thin outline, low opacity. Test: the
   viewer shouldn't consciously notice it unless they look. Used
   opt-in per stage (hero, relationship, closer) — copy-heavy
   sections drop .hexbg entirely so the texture doesn't compete. */
.hexbg{position:relative}
.hexbg::before{
  content:"";position:absolute;inset:0;pointer-events:none;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='140' height='160' viewBox='0 0 140 160'%3E%3Cpath d='M70 0L130 35V105L70 140L10 105V35z' fill='none' stroke='white' stroke-width='1.4'/%3E%3C/svg%3E");
  background-size:140px 160px;
  opacity:.38;
  mix-blend-mode:overlay;
}
/* Light stages: multiply with a white-stroke pattern is a no-op,
   so the texture intentionally doesn't appear on .stage--light. */
.stage--light .hexbg::before{display:none}
.hexbg>*{position:relative;z-index:1}


/* =============================================================
   6. MOTION
   ============================================================= */
/* base reveal (kept compatible with site.js observer) */
.rv{
  opacity:0;
  transform:translateY(var(--reveal-distance));
  transition:opacity var(--dur-stage) var(--ease-snap),
             transform var(--dur-stage) var(--ease-snap);
}
.rv.in{opacity:1;transform:none}

/* reveal variants — compose with .rv */
.rv--up    {transform:translateY(var(--reveal-distance))}
.rv--down  {transform:translateY(calc(var(--reveal-distance) * -1))}
.rv--left  {transform:translateX(calc(var(--reveal-distance) * -1))}
.rv--right {transform:translateX(var(--reveal-distance))}
.rv--fade  {transform:none}
.rv--scale {transform:scale(.96)}
.rv.in.rv--left,.rv.in.rv--right,.rv.in.rv--scale{transform:none}

/* mask reveal — image / surface uncovers from the left edge,
   matching the brand's reversed-F directional language */
.rv--mask{
  clip-path:inset(0 100% 0 0);
  transform:none;
  transition:clip-path var(--dur-stage) var(--ease-snap),
             opacity var(--dur) var(--ease-snap);
}
.rv--mask.in{clip-path:inset(0 0 0 0)}

/* accent-stroke draw — for the underline-flourish moments */
.rv--stroke{
  position:relative;
  transform:none;
}
.rv--stroke::after{
  content:"";position:absolute;left:0;bottom:-6px;
  height:3px;width:100%;
  background:var(--accent);
  transform:scaleX(0);transform-origin:left center;
  transition:transform var(--dur-stage) var(--ease-snap);
}
.rv--stroke.in::after{transform:scaleX(1)}

/* delay rungs — handy for staggers if a section wants more
   structure than the modulo stagger applied by site.js */
.rv--d1{transition-delay:80ms}
.rv--d2{transition-delay:160ms}
.rv--d3{transition-delay:240ms}
.rv--d4{transition-delay:320ms}


/* =============================================================
   7. COMPONENTS
   ============================================================= */

/* ---- buttons ---- */
.btn{
  display:inline-flex;align-items:center;gap:10px;
  padding:16px 30px;border-radius:5px;
  font-size:13.5px;font-weight:var(--fw-bold);
  letter-spacing:var(--tracking-wide);text-transform:uppercase;
  text-decoration:none;
  transition:background var(--dur) var(--ease-snap),
             color var(--dur) var(--ease-snap),
             border-color var(--dur) var(--ease-snap),
             transform var(--dur-quick) var(--ease-snap);
}
.btn-primary{
  background:var(--orange);color:var(--bone);
  border:1px solid var(--orange);
}
/* color-flip hover, matching .btn-portal: orange-on-bone with a lift. */
.btn-primary:hover,
.btn-primary:focus-visible{
  background:var(--bone);color:var(--orange);border-color:var(--orange);
  transform:translateY(-1px);
}
.btn-primary:active{
  transform:translateY(0);
  background:rgba(245,244,243,.95);
}
.btn-ghost{
  background:rgba(255,255,255,.04);color:var(--text);
  border:1px solid rgba(245,244,243,.4);
}
.btn-ghost:hover{border-color:var(--text);background:rgba(255,255,255,.09)}
.stage--light .btn-ghost:hover{background:rgba(0,0,0,.04)}

/* ---- header ---- */
/* ---- topbar ----
   Thin contact/pricing bar above the main nav. Sits in normal flow
   (not sticky) so it scrolls away; only .site-header below stays
   pinned. Hidden on mobile where it would crowd the hamburger. */
.topbar{
  background:var(--ink-deep);
  border-bottom:1px solid rgba(245,244,243,.08);
}
.topbar-inner{
  display:flex;align-items:center;justify-content:space-between;
  height:36px;
}
.topbar a{
  display:inline-flex;align-items:center;gap:7px;
  color:var(--bone-mute);text-decoration:none;
  font-size:12.5px;letter-spacing:.04em;
  transition:color var(--dur-quick) var(--ease-snap);
}
.topbar a:hover{color:var(--bone)}
.topbar a i{color:var(--accent);font-size:12px}
.topbar-contact{display:flex;align-items:center;gap:26px}
.topbar-actions a{
  text-transform:uppercase;letter-spacing:.14em;
  font-size:11.5px;font-weight:var(--fw-bold);color:var(--bone-soft);
}
.topbar-actions a:hover{color:var(--accent)}

.site-header{
  position:sticky;top:0;z-index:50;
  background:rgba(34,34,38,.88);
  backdrop-filter:blur(10px);
  border-bottom:1px solid var(--hairline);
  transition:background var(--dur) var(--ease-snap),
             border-color var(--dur) var(--ease-snap);
}
/* stub: TODO #4 will toggle this when the stage in view is light */
.site-header--over-light{
  background:rgba(245,244,243,.9);
  color:var(--ink);
  border-bottom-color:rgba(34,34,38,.1);
}
.site-header .nav{display:flex;align-items:center;justify-content:space-between;height:78px}

.brand{display:flex;align-items:center;text-decoration:none;color:inherit}
.brand-img{height:38px;width:auto;display:block}

/* ---- nav ---- */
.primary-nav{display:flex;align-items:center;gap:38px;list-style:none}
/* :not(.btn-portal) so the Client Portal button is governed only by
   its own .btn-portal rules — the nav-link color/underline/hover here
   is more specific than .btn-portal and was overriding the color flip
   (hover text went bone-on-bone = invisible). */
.primary-nav a:not(.btn-portal){
  position:relative;
  color:var(--text-soft);text-decoration:none;
  font-size:14.5px;font-weight:var(--fw-semi);
  letter-spacing:.11em;text-transform:uppercase;
  padding-bottom:5px;
  transition:color var(--dur-quick) var(--ease-snap);
}
/* orange underline: scales in from the left on hover (feels like the
   link is about to become active) and sits persistent on the current
   page. */
.primary-nav a:not(.btn-portal)::after{
  content:"";position:absolute;left:0;bottom:0;
  width:100%;height:2px;background:var(--accent);
  transform:scaleX(0);transform-origin:left center;
  transition:transform 200ms var(--ease-snap);
}
.primary-nav a:not(.btn-portal):hover{color:var(--text)}
.primary-nav a:not(.btn-portal):hover::after{transform:scaleX(1)}
.primary-nav a:not(.btn-portal)[aria-current="page"]{color:var(--text)}
.primary-nav a:not(.btn-portal)[aria-current="page"]::after{transform:scaleX(1)}

.btn-portal{
  display:inline-flex;align-items:center;gap:8px;
  background:var(--orange);color:var(--bone);
  padding:11px 20px;border-radius:4px;
  font-size:12.5px;font-weight:var(--fw-bold);
  letter-spacing:var(--tracking-wide);text-transform:uppercase;
  text-decoration:none;
  border:1px solid var(--orange-d);
  transition:background 200ms var(--ease-snap),
             color 200ms var(--ease-snap),
             border-color 200ms var(--ease-snap),
             transform var(--dur-quick) var(--ease-snap);
}
/* color-flip on hover/focus: orange-on-bone, with the lift kept for
   tactile feedback. The lock SVG uses stroke:currentColor so it flips
   with the text. */
.btn-portal:hover,
.btn-portal:focus-visible{
  background:var(--bone);color:var(--orange);border-color:var(--orange);
  transform:translateY(-1px);
}
.btn-portal:active{
  transform:translateY(0);
  background:#e7e5e3;
}
.btn-portal svg{width:14px;height:14px}

.menu-toggle{display:none;color:var(--text)}
.menu-toggle svg{width:26px;height:26px}

/* ---- forms ---- */
form.contact-form{display:flex;flex-direction:column;gap:18px}
form.contact-form label{
  font-size:11px;letter-spacing:var(--tracking-wider);text-transform:uppercase;
  font-weight:var(--fw-bold);color:var(--text-mute);margin-bottom:8px;display:block;
}
form.contact-form label .opt{
  text-transform:none;letter-spacing:0;color:var(--text-mute);font-weight:var(--fw-reg);
}
form.contact-form input,
form.contact-form textarea{
  width:100%;background:var(--surface-card);border:1px solid var(--hairline);
  color:var(--text);padding:14px 16px;border-radius:5px;
  font:inherit;font-size:15px;
  transition:border-color var(--dur-quick) var(--ease-snap);
}
form.contact-form input:focus,
form.contact-form textarea:focus{border-color:var(--accent);outline:none}
form.contact-form textarea{resize:vertical;min-height:140px}
form.contact-form button{margin-top:8px;align-self:flex-start}
.form-note{margin-top:4px;font-size:13px;color:var(--text-mute);line-height:1.5}

/* success / error block that replaces the form after submit (site.js
   swaps it in based on the ?sent / ?error redirect param). */
.form-result{
  padding:32px 28px;
  border:1px solid var(--hairline);
  border-radius:12px;
  background:var(--ink-violet);
  text-align:left;
}
.form-result i{font-size:32px;margin-bottom:16px;display:block}
.form-result--success i{color:var(--orange)}
.form-result--error i{color:#e2533f}
.form-result h2{
  font-size:22px;font-weight:900;text-transform:uppercase;
  letter-spacing:-.01em;margin:0 0 12px;
}
.form-result p{font-size:15px;line-height:1.55;color:var(--text);margin:0 0 8px}
.form-result p a{color:var(--orange);text-decoration:none}
.form-result p a:hover{text-decoration:underline}
.form-result__sub{color:var(--text-soft);font-size:14px}
.form-result__back{
  display:inline-block;margin-top:24px;font-size:13px;
  color:var(--orange);text-decoration:none;text-transform:uppercase;
  letter-spacing:.12em;font-weight:600;
}
.form-result__back:hover{text-decoration:underline}

/* ---- footer ---- */
.site-footer{
  background:#1a191e;border-top:1px solid var(--hairline);
  padding:72px 0 40px;color:var(--bone);
}
/* lead band: F·F mark one side, tagline statement the other. Gives
   the footer real presence as the last impression (round 3). */
.foot-lead{
  display:flex;align-items:center;justify-content:space-between;gap:40px;
  padding-bottom:48px;margin-bottom:48px;
  border-bottom:1px solid var(--bone-faint);
}
.foot-mark{
  height:84px;width:auto;flex-shrink:0;
  filter:brightness(0) invert(1);   /* monochrome black SVG → bone */
  opacity:.16;
}
.foot-statement{max-width:26ch}
.foot-top{
  display:flex;justify-content:space-between;flex-wrap:wrap;gap:40px;
  padding-bottom:44px;border-bottom:1px solid var(--bone-faint);
}
.foot-brand .bn{font-weight:var(--fw-black);letter-spacing:.14em;font-size:15px;text-transform:uppercase}
.foot-brand .bn .amp{color:var(--accent);font-style:italic;font-weight:var(--fw-semi)}
.foot-brand .bn .cg{color:var(--bone-mute);font-weight:var(--fw-semi);letter-spacing:.2em;font-size:11px;margin-left:6px}
.foot-brand p{margin-top:14px;font-size:14px;color:var(--bone-mute);max-width:34ch;line-height:1.6}
.foot-cols{display:flex;gap:64px;flex-wrap:wrap}
.foot-col h4{
  font-size:11px;letter-spacing:.22em;text-transform:uppercase;
  color:var(--bone-mute);font-weight:var(--fw-bold);margin-bottom:18px;
}
.foot-col a{
  display:block;color:var(--bone-soft);text-decoration:none;
  font-size:14.5px;margin-bottom:11px;
  transition:color var(--dur-quick) var(--ease-snap);
}
.foot-col a:hover{color:var(--accent)}
.foot-bot{
  display:flex;justify-content:space-between;flex-wrap:wrap;gap:14px;
  padding-top:30px;font-size:13px;color:var(--bone-mute);
}
.foot-bot a{color:inherit;text-decoration:none;transition:color var(--dur-quick) var(--ease-snap)}
.foot-bot a:hover{color:var(--orange);text-decoration:underline}

/* ---- accessibility widget (edge popout) ----
   A vertical tab pinned to the right edge of the viewport. Click
   or focus + Enter slides a 360px panel in from the right; the
   tab travels with it so it always reads as an attached handle.
   Clicking outside the panel, pressing Escape, or clicking the tab
   again slides it closed. Tab is keyboard-reachable in normal
   document tab order. */
.a11y-launcher{
  position:fixed;
  top:50%;right:0;
  transform:translateY(-50%);
  z-index:102;
  width:28px;height:40px;
  background:var(--ink-violet);
  color:var(--bone);
  border:1px solid var(--hairline);
  border-right:0;
  border-radius:6px 0 0 6px;
  display:flex;align-items:center;justify-content:center;
  cursor:pointer;
  transition:right 320ms var(--ease-snap),
             background var(--dur) var(--ease-snap),
             color var(--dur) var(--ease-snap);
}
.a11y-launcher:hover,.a11y-launcher:focus-visible{
  background:var(--accent);color:var(--bone);outline:none;
}
.a11y-launcher[aria-expanded="true"]{right:min(340px,86vw)}
.a11y-launcher i{font-size:14px;line-height:1}
/* Icon swap by state: person figure when closed, right chevron when
   open. FA copies the .ico-* marker classes onto the <svg> it renders
   in place of each <i>, so these class-based show/hide rules work
   whether or not the kit has finished replacing the elements. */
.a11y-launcher .ico-open{display:none}
.a11y-launcher[aria-expanded="true"] .ico-closed{display:none}
.a11y-launcher[aria-expanded="true"] .ico-open{display:inline-block}
/* Fallback if the FA kit fails to load: the <i> stays empty, so show
   a unicode glyph (wheelchair / right angle quote) instead of a blank. */
.a11y-launcher .ico-closed:empty::before{content:"\267F";font-size:15px}
.a11y-launcher .ico-open:empty::before{content:"\203A";font-weight:700}

/* 4K-at-100% (viewports >1920px): the 28x40 tab reads tiny. Scale the
   tab and its icon up so it stays legible without feeling oversized at
   standard desktop widths. */
@media (min-width:1920px){
  .a11y-launcher{width:40px;height:56px;border-radius:8px 0 0 8px}
  .a11y-launcher i{font-size:20px}
  .a11y-launcher .ico-closed:empty::before{font-size:21px}
}

/* Content-sized popout, not a full-height drawer (round 5). Pinned to
   the right edge and vertically centered on the same line as the tab,
   so it reads as a compact floating card with space above and below.
   max-height + overflow-y guard short viewports (scrolls internally
   rather than running off-screen). */
.a11y-panel{
  position:fixed;
  top:50%;right:0;
  z-index:101;
  width:min(340px,86vw);
  max-height:calc(100vh - 32px);
  overflow-y:auto;
  background:var(--ink-violet);
  border:1px solid var(--hairline);border-right:0;
  border-radius:8px 0 0 8px;
  padding:28px;
  color:var(--bone);
  transform:translate(100%,-50%);
  transition:transform 320ms var(--ease-snap);
  box-shadow:-14px 0 44px rgba(0,0,0,.5);
}
.a11y-panel.open{transform:translate(0,-50%)}
.a11y-panel h2{
  font-size:14px;letter-spacing:.22em;text-transform:uppercase;
  margin-bottom:24px;color:var(--bone);
  display:flex;align-items:center;gap:10px;
}
.a11y-panel h2 i{color:var(--accent);font-size:16px}
.a11y-row{margin-bottom:22px}
.a11y-row:last-of-type{margin-bottom:24px}
.a11y-row .label{
  font-size:11px;letter-spacing:.2em;text-transform:uppercase;
  color:var(--bone-mute);font-weight:var(--fw-bold);margin-bottom:10px;
}
.a11y-row .opts{display:flex;gap:6px}
.a11y-row .opts button{
  flex:1;padding:10px 8px;background:var(--ink);
  border:1px solid var(--hairline);border-radius:4px;
  color:var(--bone-soft);font-size:12px;font-weight:var(--fw-bold);
  letter-spacing:.08em;text-transform:uppercase;cursor:pointer;
  transition:background var(--dur-quick) var(--ease-snap),
             color var(--dur-quick) var(--ease-snap),
             border-color var(--dur-quick) var(--ease-snap);
}
.a11y-row .opts button[aria-pressed="true"]{
  background:var(--accent);color:var(--bone);border-color:var(--accent-hover);
}
.a11y-row .opts button:hover{border-color:var(--accent)}
.a11y-reset{
  width:100%;padding:10px;background:transparent;
  color:var(--bone-mute);border:1px solid var(--hairline);
  border-radius:4px;cursor:pointer;
  font-size:11px;letter-spacing:.16em;text-transform:uppercase;
  font-weight:var(--fw-bold);
  transition:color var(--dur-quick) var(--ease-snap),
             border-color var(--dur-quick) var(--ease-snap);
}
.a11y-reset:hover{color:var(--bone);border-color:var(--bone-soft)}

/* ---- intro overlay (TODO #3) ----
   First-visit brand moment: charcoal field, conventional F·F mark
   appears, the LEFT F flips to its reversed orientation, the orange
   bullet pulses in, then the whole mark scales down toward the
   upper-left as the overlay fades and reveals the page beneath.

   Gating:
     - sessionStorage 'ff_intro_played' (once per browser session)
     - prefers-reduced-motion or html.a11y-motion-off — skip entirely
     - (scripting: none) — never shows (no script, no skip path)

   Visibility default is "shown" so first-paint lands on the charcoal
   field before site.js boots. site.js dismisses it instantly for
   return visits or plays the sequence for first visits. */
.intro{
  position:fixed;inset:0;z-index:9000;
  background:var(--ink);
  display:flex;align-items:center;justify-content:center;
  opacity:1;
  transition:opacity 480ms var(--ease-snap);
}
@media (scripting:none){.intro{display:none}}

.intro-mark{
  width:clamp(96px,14vw,168px);
  height:auto;
  opacity:0;
  transform:scale(.94);
  transition:opacity 220ms var(--ease-snap),
             transform 480ms var(--ease-snap);
}
.intro--in .intro-mark{opacity:1;transform:scale(1)}

/* The left F — wrapped in a <g> so we can flip it via scaleX(-1)
   about its own visual center. Initial orientation is conventional
   (spine left); after .intro--flipped lands the F&F-correct state
   (spine right, bars left). */
.intro-mark__l{
  transform-origin:46px 50px;
  transform:scaleX(1);
  transition:transform 240ms var(--ease-flip);
}
.intro--flipped .intro-mark__l{transform:scaleX(-1)}

/* Bullet — hidden until the flip lands, then pulses in with a tiny
   overshoot via the snap ease. */
.intro-mark__bullet{
  transform-origin:110px 50px;
  transform:scale(0);
  opacity:0;
  transition:transform 260ms var(--ease-snap),
             opacity 200ms var(--ease-snap);
}
.intro--bullet .intro-mark__bullet{transform:scale(1);opacity:1}

/* Exit — mark shrinks and slides toward the upper-left (where the
   header logo lives) as the overlay opacity fades. Precision-matching
   the header position via viewport math would be brittle on scroll/
   resize; the eye reads the cross-fade with the page's actual header
   mark as continuity. */
.intro--leave{opacity:0;pointer-events:none}
.intro--leave .intro-mark{
  transform:translate(-44vw,-44vh) scale(.2);
  transition:transform 460ms var(--ease-snap);
}


/* =============================================================
   8. PAGE PATTERNS
   These are the v1 section names — kept as scoped classes so
   the existing pages still render. Bodies have been rebound to
   the semantic tokens above so each pattern works on dark and
   light stages alike. Treat any of these as candidates for
   replacement when the home page rebuild lands in TODO #4.
   ============================================================= */

/* ---- block (v1 section wrapper, still used by current pages) ---- */
section.block{padding:var(--sp-9) 0;background:var(--surface);color:var(--text)}
section.block.tight{padding:var(--sp-8) 0}
.sec-head{margin-bottom:var(--sp-7);max-width:62ch}
.sec-head p{margin-top:20px;font-size:17.5px;line-height:var(--lh-body);color:var(--text-soft)}

/* ---- hero (home) ----
   Subtle vertical depth only. The accent radials were removed in
   round 3 (read as noise / seam discoloration, not atmosphere).
   min-height:80vh so the hero dominates the first viewport without
   enforcing a full-height stage. Content centers via .stage's grid. */
.hero{
  background:linear-gradient(160deg,#26242e 0%,#222226 55%,#1c1b20 100%);
  min-height:80vh;
}
.hero p.lead{margin-top:30px;max-width:54ch}
.hero-cta{display:flex;gap:16px;margin-top:44px;flex-wrap:wrap}

/* Hero + page-hero content aligns its LEFT edge with the centered
   1180px container's content edge — i.e. the same x-position as the
   header nav and brand logo — while the right side stays open so the
   content isn't pulled toward center (round 5, retune of round 4).

   margin-left math: on viewports wider than --maxw, the content edge
   sits at (container gap)/2 + gutter, matching where the centered
   .wrap's padding box begins. Below --maxw the max() floors it at the
   plain gutter so content never crashes the edge. Using 100% (not
   100vw) so it resolves against the same content width the nav's
   margin:0 auto uses — no scrollbar-width drift between header and
   hero. */
.hero .wrap,
.page-hero .wrap{
  margin-left:max(var(--gutter), calc((100% - var(--maxw)) / 2 + var(--gutter)));
  margin-right:0;
  padding-left:0;
  max-width:none;
}

/* ---- page hero (subpages) ---- */
.page-hero{
  background:linear-gradient(160deg,#26242e,#1c1b20);
  padding:96px 0 76px;
  border-bottom:1px solid var(--hairline);
}
.page-hero h1{font-size:var(--fs-h1)}
.page-hero p.lead{margin-top:24px;max-width:60ch}

/* ---- trustbar ---- */
.trustbar{
  border-top:1px solid var(--hairline);
  background:var(--surface-alt);padding:30px 0;
}
.trustbar .wrap{display:flex;align-items:center;justify-content:space-between;flex-wrap:wrap;gap:20px}
.trustbar span{
  font-size:12.5px;font-weight:var(--fw-semi);
  letter-spacing:.16em;text-transform:uppercase;
  color:var(--text-mute);
}
.trustbar b{color:var(--text);font-weight:var(--fw-black)}

/* ---- trusted-by logo strip (home) ----
   Monochrome filter unifies logos from different brand worlds
   (military roundel, broadcast, real estate) against the dark band. */
.logo-strip{background:var(--ink);padding:var(--sp-8) 0;border-top:1px solid var(--bone-faint);overflow:hidden}
.logo-strip__label{
  text-align:center;font-size:11px;letter-spacing:.22em;text-transform:uppercase;
  color:var(--orange);font-weight:var(--fw-bold);margin:0 0 var(--sp-5);
}
.logo-strip__viewport{
  width:100%;overflow:hidden;position:relative;
  /* Edge fade so logos resolve in/out instead of hard-cutting. */
  -webkit-mask-image:linear-gradient(90deg,transparent 0,#000 8%,#000 92%,transparent 100%);
  mask-image:linear-gradient(90deg,transparent 0,#000 8%,#000 92%,transparent 100%);
}
.logo-strip__track{
  display:flex;flex-wrap:nowrap;align-items:center;list-style:none;margin:0;padding:0;
  width:max-content;
  animation:logo-scroll 40s linear infinite;
}
/* Per-item right margin (not flex `gap`) so every one of the 18 cells
   carries identical trailing space — including the 9th. That keeps the
   track perfectly periodic, so translateX(-50%) lands seamlessly. A
   trailing-gap-less `gap` would leave a half-gap seam stutter once per loop. */
.logo-strip__track li{flex:0 0 auto;margin-right:64px}
.logo-strip__track img{
  height:48px;width:auto;max-width:180px;object-fit:contain;display:block;
  /* Bright grayscale + slight warm tint (kept from the static strip):
     a flat brightness(0)/invert silhouette collapses the 8th AFHS filled
     roundel into a featureless disc, so preserve luminance instead. */
  filter:grayscale(1) sepia(.18) brightness(1.8) opacity(.85);
  transition:filter .3s var(--ease-snap), transform .2s var(--ease-snap);
}
.logo-strip__track a:hover img,
.logo-strip__track a:focus-visible img{
  filter:grayscale(1) sepia(.18) brightness(2) opacity(1);
  transform:scale(1.05);
}
/* Pause on hover/focus so the click target holds still. */
.logo-strip__viewport:hover .logo-strip__track,
.logo-strip__viewport:focus-within .logo-strip__track{animation-play-state:paused}
@keyframes logo-scroll{
  from{transform:translateX(0)}
  to{transform:translateX(-50%)}
}
@media(prefers-reduced-motion:reduce){
  .logo-strip__track{
    animation:none;flex-wrap:wrap;justify-content:center;
    width:100%;row-gap:var(--sp-5);
  }
  /* The duplicate set exists only to enable the seamless scroll loop.
     With no animation, hide it so the static fallback is one row of 9,
     not two rows of 9. */
  .logo-strip__track li[aria-hidden="true"]{display:none}
}
@media(max-width:640px){
  .logo-strip__track img{height:36px}
  .logo-strip__track li{margin-right:44px}
}

/* ---- services grid ---- */
.svc{background:linear-gradient(180deg,#222226,#1f1e23)}
.svc-grid{
  display:grid;grid-template-columns:repeat(2,1fr);gap:1px;
  background:var(--hairline);border:1px solid var(--hairline);
}
.svc-card{
  background:var(--surface);padding:46px 38px;
  transition:background var(--dur) var(--ease-snap);
}
.svc-card:hover{background:var(--surface-card)}
.svc-card .ic{
  width:50px;height:50px;border:1px solid var(--accent);border-radius:var(--radius);
  display:flex;align-items:center;justify-content:center;margin-bottom:26px;
}
.svc-card .ic svg{width:24px;height:24px;stroke:var(--accent);fill:none;stroke-width:2}
.svc-card h3{margin-bottom:14px}
.svc-card p{font-size:15px;line-height:var(--lh-body);color:var(--text-soft)}
.svc-card p + p{margin-top:16px}
.svc-card .inc-label{color:var(--text);font-weight:var(--fw-bold)}
.svc-card .price-line{color:var(--accent);font-weight:var(--fw-bold);letter-spacing:.04em}
.svc-card .price-line a{color:var(--accent);text-decoration:none}
.svc-card .price-line a:hover{text-decoration:underline}

/* ---- managed band ---- */
.managed{
  background:linear-gradient(165deg,#26242e,#1c1b20);
}
.managed-inner{display:grid;grid-template-columns:1fr 1fr;gap:74px;align-items:center}
.managed h2{max-width:13ch}
.managed .lead{margin-top:22px;font-size:17.5px;line-height:1.64;color:var(--text-soft)}
.price-note{
  margin-top:30px;font-size:14px;letter-spacing:.12em;text-transform:uppercase;
  font-weight:var(--fw-bold);color:var(--accent);
}
.price-note a{color:var(--accent);text-decoration:none}
.price-note a:hover{text-decoration:underline}
.feat{list-style:none}
.feat li{
  display:flex;gap:16px;align-items:flex-start;
  padding:18px 0;border-bottom:1px solid var(--hairline);
  font-size:16px;color:var(--text-soft);
}
.feat li:last-child{border-bottom:0}
.feat li svg{width:20px;height:20px;flex-shrink:0;margin-top:1px;stroke:var(--accent);fill:none;stroke-width:2.2}
.feat li b{color:var(--text);font-weight:var(--fw-bold)}

/* ---- portfolio cards ---- */
.port-grid{display:grid;grid-template-columns:repeat(2,1fr);gap:24px}
/* Home selected-work grid is 3-wide on desktop (clean 3x2 for the six
   entries), 2 on tablet, 1 on mobile. Scoped to #work so the standalone
   /portfolio page keeps its larger 2-wide cards. The id selector beats
   the global .port-grid mobile rule, so these breakpoints win for #work. */
#work .port-grid{grid-template-columns:repeat(3,1fr)}
@media(max-width:980px){#work .port-grid{grid-template-columns:repeat(2,1fr)}}
@media(max-width:640px){#work .port-grid{grid-template-columns:1fr}}
.pcard{
  background:var(--surface-card);border:1px solid var(--hairline);
  border-radius:8px;overflow:hidden;text-decoration:none;color:var(--text);
  display:flex;flex-direction:column;
  transition:transform var(--dur) var(--ease-snap),
             border-color var(--dur) var(--ease-snap);
}
.pcard:hover{transform:translateY(-4px);border-color:rgba(209,70,39,.5)}
.pcard .shot{
  aspect-ratio:16/10;
  background:linear-gradient(135deg,var(--blue),var(--ink-violet));
  position:relative;display:flex;align-items:center;justify-content:center;
  border-bottom:1px solid var(--hairline);
  overflow:hidden;
}
.pcard:nth-child(2) .shot{background:linear-gradient(135deg,#393941,#222226)}
.pcard:nth-child(3) .shot{background:linear-gradient(135deg,#b63826,#26242e)}
.pcard:nth-child(4) .shot{background:linear-gradient(135deg,#2f4b68,#393941)}
.pcard:nth-child(5) .shot{background:linear-gradient(135deg,#26242e,#2f4b68)}
.pcard:nth-child(6) .shot{background:linear-gradient(135deg,#393941,#1c1b20)}
/* When a screenshot is present, it covers the gradient.
   onerror="this.remove()" on the <img> drops it from the DOM if
   the file 404s; the :has() rule then re-shows the URL caption
   beneath, and the gradient stays as graceful fallback. */
.pcard .shot img{
  position:absolute;inset:0;width:100%;height:100%;
  object-fit:cover;display:block;
}
.pcard .shot:has(img) span{display:none}
.pcard .shot span{
  font-size:12px;letter-spacing:.2em;text-transform:uppercase;
  color:rgba(245,244,243,.4);font-weight:var(--fw-bold);
}
.pcard .pbody{padding:28px 30px 32px}
.pcard .ptype{
  font-size:11px;letter-spacing:.24em;text-transform:uppercase;
  color:var(--accent);font-weight:var(--fw-bold);margin-bottom:12px;
}
.pcard h3{font-size:21px;margin-bottom:12px}
.pcard p{font-size:14.5px;line-height:1.58;color:var(--text-soft)}
.pcard .visit{
  margin-top:18px;font-size:12.5px;letter-spacing:.12em;text-transform:uppercase;
  font-weight:var(--fw-bold);color:var(--text-mute);
  display:flex;align-items:center;gap:7px;
}
.pcard:hover .visit{color:var(--accent)}
.todo{
  display:inline-block;font-size:10px;letter-spacing:.18em;
  background:rgba(209,70,39,.18);color:var(--accent);
  padding:3px 8px;border-radius:3px;font-weight:var(--fw-bold);margin-bottom:8px;
}

/* ---- why grid ---- */
.why{background:linear-gradient(180deg,#222226,#1c1b20)}
.why-grid{display:grid;grid-template-columns:repeat(4,1fr);gap:28px}
.why-card{padding:34px 26px;border-top:2px solid var(--accent)}
.why-card .n{
  font-size:13px;font-weight:var(--fw-black);letter-spacing:.2em;
  color:var(--accent);margin-bottom:18px;
}
.why-card h3{font-size:18px;margin-bottom:12px;line-height:1.2}
.why-card p{font-size:14.5px;line-height:var(--lh-body);color:var(--text-soft)}

/* ---- pricing tiers ---- */
.tier-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:24px;margin-top:60px}
.tier{
  background:var(--surface-card);border:1px solid var(--hairline);
  border-radius:8px;padding:40px 32px;position:relative;
  transition:border-color var(--dur) var(--ease-snap),
             transform var(--dur) var(--ease-snap),
             box-shadow var(--dur) var(--ease-snap);
}
.tier:hover{
  border-color:rgba(209,70,39,.45);
  transform:translateY(-6px);
  box-shadow:0 14px 40px rgba(0,0,0,.18);
}
.tier.featured{border-color:var(--accent);border-width:2px;padding:48px 32px}
.tier.featured:hover{
  box-shadow:0 18px 48px rgba(209,70,39,.22);
}
.tier.featured::before{
  content:"Recommended";position:absolute;top:-12px;left:32px;
  background:var(--accent);color:var(--bone);
  font-size:10px;letter-spacing:.2em;text-transform:uppercase;
  font-weight:var(--fw-bold);padding:5px 12px;border-radius:3px;
  transform-origin:center;
}
/* One-shot pulse on first reveal of the featured tier. The .in
   class lands on .tier.featured.rv when the existing reveal
   IntersectionObserver fires (site.js). Runs once, with a small
   delay so it follows the tier's own translate-up reveal. */
.tier.featured.in::before{
  animation: pulse-badge 1200ms var(--ease-snap) 280ms 1 both;
}
@keyframes pulse-badge{
  0%   {transform:scale(1)}
  30%  {transform:scale(1.08)}
  55%  {transform:scale(.98)}
  100% {transform:scale(1)}
}
html.a11y-motion-off .tier.featured.in::before{animation:none}
.tier .tname{
  font-size:13px;letter-spacing:.22em;text-transform:uppercase;
  color:var(--accent);font-weight:var(--fw-bold);margin-bottom:14px;
}
.tier .tprice{font-size:42px;font-weight:var(--fw-black);line-height:1;margin-bottom:6px}
.tier .tprice span{font-size:15px;color:var(--text-mute);font-weight:var(--fw-semi);letter-spacing:.05em}
.tier .ttag{font-size:13.5px;color:var(--text-mute);margin-bottom:28px;line-height:1.5}
.tier ul{list-style:none}
.tier li{
  display:flex;gap:12px;align-items:flex-start;
  padding:11px 0;font-size:14.5px;color:var(--text-soft);line-height:1.5;
}
.tier li svg{width:16px;height:16px;flex-shrink:0;margin-top:3px;stroke:var(--accent);fill:none;stroke-width:2.5}

/* ---- about ---- */
.about-grid{display:grid;grid-template-columns:1.4fr 1fr;gap:74px;align-items:start}
.about-grid p{font-size:17px;line-height:1.7;color:var(--text-soft);margin-bottom:22px}

/* Bio + sticky photo (about.html). Left column scrolls normally,
   right column pins to the viewport. As each .bio-section enters a
   horizontal band roughly at viewport-center, site.js sets
   data-active on .about-photo and the matching <img> cross-fades in.
   The placeholder div sits beneath every <img> and shows through
   whenever no img is currently active or loaded. */
.bio-grid{
  display:grid;
  grid-template-columns:1fr 0.85fr;
  gap:80px;
  align-items:start;
}
.bio-text > .bio-section{margin-bottom:var(--sp-7)}
.bio-text > .bio-section:last-child{margin-bottom:0}
.bio-text .bio-kicker{
  font-size:15px;letter-spacing:.22em;text-transform:uppercase;
  color:var(--accent);font-weight:var(--fw-bold);
  margin-bottom:var(--sp-3);
}
.bio-text p:not(.bio-kicker){
  font-size:17px;line-height:1.7;color:var(--text-soft);
  margin-bottom:var(--sp-3);
}
.bio-text p:not(.bio-kicker):last-child{margin-bottom:0}

.bio-photo-col{position:sticky;top:100px;align-self:start}
.about-photo{
  position:relative;
  aspect-ratio:4/5;
  background:linear-gradient(135deg,var(--ink-violet),var(--slate-d));
  overflow:hidden;
  border-radius:6px;
  border:1px solid var(--hairline);
}
.about-photo img{
  position:absolute;inset:0;
  width:100%;height:100%;
  /* contain (not cover) so the full headshot shows — cover was
     cropping the tops of heads. The frame's gradient fills any
     letterbox/pillarbox honestly. */
  object-fit:contain;
  opacity:0;
  transition:opacity 700ms var(--ease-snap);
}
.about-photo[data-active="1"] img[data-section="1"],
.about-photo[data-active="2"] img[data-section="2"],
.about-photo[data-active="3"] img[data-section="3"]{opacity:1}
/* Note: the .about-photo container keeps its gradient background as
   the fallback if a headshot 404s; no text overlay (round 4). */
.about-stats-band{
  margin-top:var(--sp-8);
  padding-top:var(--sp-7);
  border-top:1px solid var(--hairline);
}

.about-stats{
  display:grid;grid-template-columns:repeat(4,1fr);gap:1px;
  background:var(--hairline);border:1px solid var(--hairline);
  border-radius:8px;overflow:hidden;
}
.about-stats .stat{background:var(--surface-card);padding:32px 28px}
.about-stats .stat .v{font-size:32px;font-weight:var(--fw-black);color:var(--text);line-height:1}
.about-stats .stat .l{
  font-size:11px;letter-spacing:.2em;text-transform:uppercase;
  color:var(--text-mute);font-weight:var(--fw-bold);margin-top:10px;
}

/* ---- contact ---- */
.contact-grid{display:grid;grid-template-columns:1fr 1fr;gap:60px;align-items:start}
.contact-info p{font-size:17px;line-height:1.7;color:var(--text-soft);margin-bottom:24px}
.contact-info .line{
  display:flex;gap:14px;align-items:center;padding:14px 0;
  border-bottom:1px solid var(--hairline);font-size:16px;
}
.contact-info .line:last-of-type{border-bottom:0}
.contact-info .line svg{width:20px;height:20px;stroke:var(--accent);fill:none;stroke-width:2;flex-shrink:0}
.contact-info .line a{color:var(--text);text-decoration:none;font-weight:var(--fw-semi)}
.contact-info .line a:hover{color:var(--accent)}

/* ---- closer ----
   Clean dark stage. The orange glow radial and the hex texture were
   both removed in round 3 (the glow read as a stain across the seam).
   Background falls through to .stage--dark's --surface. */
.closer{
  text-align:center;padding:120px 0;
}
.closer h2{max-width:20ch;margin:0 auto}
.closer p{margin:22px auto 0;max-width:50ch;font-size:17.5px;line-height:1.6;color:var(--text-soft)}
.closer .hero-cta{justify-content:center;margin-top:42px}

/* ---- relationship section (home) ----
   Single-statement centerpiece on a dark stage. Per CLAUDE.md §5
   the relationship is the product; the rendering is the .statement
   component carrying the claim, with a tight supporting lead. */
/* extra vertical breathing room so the centerpiece statement lands,
   in lieu of a min-height (round 3). */
.relate{padding-top:clamp(96px,12vw,160px);padding-bottom:clamp(96px,12vw,160px)}
.relate-block{text-align:center}
.relate-block .eyebrow{margin-bottom:var(--sp-3)}
.relate-block .eyebrow::before{display:none}
.relate-block .statement-wrap{margin:var(--sp-3) auto var(--sp-5)}
.relate-block .lead{max-width:56ch;margin-left:auto;margin-right:auto}

/* ---- testimonials (home) ---- */
.kicker.tcenter{text-align:center;margin-bottom:40px}
.pullquote{max-width:62ch;margin:0 auto 64px;text-align:center;position:relative}
.pullquote::before{
  content:"\201C";display:block;
  font-family:Georgia,'Times New Roman',serif;
  font-size:84px;line-height:.5;color:var(--accent);
  margin-bottom:18px;
}
.pullquote blockquote{
  font-size:clamp(19px,2.4vw,28px);line-height:1.42;
  font-style:italic;font-weight:var(--fw-semi);color:var(--text);
}
.pullquote figcaption{margin-top:30px;display:flex;flex-direction:column;gap:4px}
.tq-name{
  font-weight:var(--fw-bold);color:var(--text);
  text-transform:uppercase;letter-spacing:.1em;font-size:13px;
}
.tq-org{color:var(--text-mute);font-size:13px}
.tcard-row{display:grid;grid-template-columns:repeat(3,1fr);gap:24px}
.tcard{
  display:flex;flex-direction:column;
  background:var(--surface-card);border:1px solid var(--hairline);
  border-radius:8px;padding:28px 26px;
}
.tcard blockquote{
  flex:1;font-style:italic;font-size:14.5px;line-height:1.6;
  color:var(--text-soft);
}
.tcard figcaption{margin-top:22px;display:flex;flex-direction:column;gap:3px}
@media(max-width:860px){
  .tcard-row{grid-template-columns:1fr;gap:18px}
}

/* ---- pricing teaser (home) ----
   Lighter than the full /managed-web tier cards: name, price, one line.
   Detail lives behind the 'see full plans' link. */
.sec-head--center{text-align:center;margin-left:auto;margin-right:auto}
.pteaser-row{display:grid;grid-template-columns:repeat(3,1fr);gap:24px}
.pteaser{
  background:var(--surface-card);border:1px solid var(--hairline);
  border-radius:8px;padding:34px 28px;text-align:center;position:relative;
}
.pteaser--featured{border-color:var(--accent);border-width:2px}
.pt-badge{
  position:absolute;top:-12px;left:50%;transform:translateX(-50%);
  background:var(--accent);color:var(--bone);
  font-size:10px;letter-spacing:.2em;text-transform:uppercase;
  font-weight:var(--fw-bold);padding:5px 12px;border-radius:3px;
}
.pt-name{
  font-size:13px;letter-spacing:.22em;text-transform:uppercase;
  color:var(--accent);font-weight:var(--fw-bold);margin-bottom:12px;
}
.pt-price{font-size:38px;font-weight:var(--fw-black);line-height:1;margin-bottom:14px;color:var(--text)}
.pt-price span{font-size:14px;color:var(--text-mute);font-weight:var(--fw-semi);letter-spacing:.05em}
.pt-desc{font-size:14px;line-height:1.5;color:var(--text-soft)}
.pteaser-cta{text-align:center;margin-top:40px}
.pteaser-cta a{
  color:var(--accent);text-decoration:none;font-weight:var(--fw-bold);
  letter-spacing:.06em;text-transform:uppercase;font-size:13px;
  border-bottom:1px solid transparent;transition:border-color var(--dur-quick) var(--ease-snap);
}
.pteaser-cta a:hover{border-color:var(--accent)}
@media(max-width:860px){
  .pteaser-row{grid-template-columns:1fr;gap:18px}
}

/* ---- in-section CTA bands (home) ----
   Thin one-row prompts between sections; not full closers. */
.inline-cta{background:var(--ink-deep);padding:26px 0;border-top:1px solid var(--bone-faint)}
.inline-cta .wrap{display:flex;align-items:center;justify-content:center;gap:26px;flex-wrap:wrap}
.inline-cta p{font-size:17px;color:var(--bone-soft);font-weight:var(--fw-semi)}
@media(max-width:560px){
  .inline-cta .wrap{flex-direction:column;gap:14px;text-align:center}
}

/* ---- prose (legal / long-form) ---- */
.prose{max-width:720px;margin:0 auto;padding:60px 0 80px}
/* Inside a stage, the stage already provides vertical padding; zero the
   prose's own so they don't stack into excessive whitespace. */
.stage .prose{padding:0}
.prose h2{font-size:24px;margin:42px 0 16px;text-transform:uppercase;letter-spacing:.02em}
.prose h2:first-child{margin-top:0}
.prose h3{font-size:17px;margin:24px 0 10px;text-transform:none;letter-spacing:0}
.prose p,.prose li{font-size:16px;line-height:1.72;color:var(--text-soft);margin-bottom:14px}
.prose ul{padding-left:24px;margin-bottom:18px}
.prose a{color:var(--accent);text-decoration:underline;text-underline-offset:3px}
.prose .meta{
  font-size:12px;letter-spacing:.18em;text-transform:uppercase;
  color:var(--text-mute);font-weight:var(--fw-bold);margin-bottom:30px;
}
.prose .review-flag{
  background:rgba(209,70,39,.1);border-left:3px solid var(--accent);
  padding:14px 18px;margin:24px 0;font-size:14px;color:var(--text-soft);
}
.prose .review-flag b{
  color:var(--accent);text-transform:uppercase;letter-spacing:.1em;font-size:12px;
}


/* =============================================================
   9. RESPONSIVE
   ============================================================= */
@media(max-width:980px){
  .managed-inner,.about-grid,.contact-grid{grid-template-columns:1fr;gap:44px}
  .svc-grid{grid-template-columns:1fr}
  .why-grid{grid-template-columns:repeat(2,1fr)}
  .tier-grid{grid-template-columns:1fr;gap:18px}
  .tier.featured{padding:40px 32px}
}
@media(max-width:760px){
  :root{--gutter:22px}
  .primary-nav{
    display:none;position:absolute;top:78px;left:0;right:0;
    flex-direction:column;align-items:stretch;gap:0;
    background:var(--surface-alt);border-bottom:1px solid var(--hairline);
    padding:14px 22px 22px;
  }
  .primary-nav.open{display:flex}
  .primary-nav li{border-bottom:1px solid var(--hairline)}
  .primary-nav li:last-child{border-bottom:0;padding-top:14px}
  .primary-nav a{display:block;padding:14px 0;font-size:14px}
  .menu-toggle{display:flex}
  .topbar{display:none}
  .port-grid{grid-template-columns:1fr}
  .why-grid{grid-template-columns:1fr}
  .trustbar .wrap{justify-content:flex-start;gap:14px}
  .brand-img{height:30px}
  .about-stats{grid-template-columns:1fr 1fr}
  .bio-grid{grid-template-columns:1fr;gap:48px}
  .bio-photo-col{position:static;max-width:360px;margin:0 auto;width:100%}
  .foot-lead{flex-direction:column;align-items:flex-start;gap:26px}
  .foot-mark{height:60px}
}
