/* ============================================================
   SiliconPath Law — About, v2.
   A new design language, not the legacy theme restyled. This file is
   self-contained: the v2 layout loads NO legacy stylesheet, so nothing
   from style.css / gabala.css / app.min.css can reach these rules.

   Language: "Filed Record". A warm paper ground with content set as
   filed plates and ruled index rows, the way a case file reads. Brand
   oxblood is the only accent. No yellow, no second hue.
   ============================================================ */

:root{
  --paper:#F7F4EF;
  --paper-2:#EFE9E1;
  --white:#FFFFFF;
  --ink:#241310;

  /* ---- Dark section band -------------------------------------------
     A LIGHTER warm brown, not near-black. The previous stops measured
     0.004-0.016 luminance (16-19.5:1 against white) - so dark they read
     as a black slab rather than a brown one.
     #6B3A2E is 4x the luminance of the old #241310 and still holds
     6.26:1 for the small #E8CFC9 mono labels, which is the tightest
     requirement on these sections. Defined once; every dark section
     uses .band, so changing it here moves the whole site. */
  --band-1:#7A4537;
  --band-2:#6B3A2E;
  --band-deep:#4A2A21;
  --band-glow:rgba(201,145,137,.16);
  --ink-2:#6E5C55;
  --ink-3:#9A8A83;
  --brand:#5A1F1B;
  --brand-2:#7C2E28;
  --brand-wash:#F3E8E5;
  --line:#E4DACF;
  --line-2:#D0C1B4;
  --grid:rgba(90,31,27,.055);

  --display:"Mulish Variable","Mulish",system-ui,sans-serif;
  /* Was "Space Mono". The typewriter face read as a different brand every
     time it appeared - eyebrows, badges, table headers, step numbers - and
     it is not the firm's typeface. Every one of the ~50 use sites resolves
     through this token, so the label VOICE (small, uppercase, tracked out)
     is kept while the letterforms become the brand's own.
     Named --mono still, because the role is "label face", and renaming it
     would mean touching all 50 sites for no behavioural gain. */
  --mono:"Mulish Variable","Mulish",system-ui,sans-serif;
  --container:1240px;
  --gutter:clamp(20px,5vw,48px);

  /* Shape scale, documented: pill for interactive, lg for plates, sm for chrome. */
  --r-lg:22px;
  --r:12px;

  --ease:cubic-bezier(.22,.61,.36,1);
  --lift-1:0 1px 2px rgba(36,19,16,.05),0 4px 12px rgba(36,19,16,.05);
  --lift-2:0 2px 4px rgba(36,19,16,.05),0 16px 36px rgba(36,19,16,.09);
  --lift-3:0 6px 12px rgba(36,19,16,.07),0 40px 80px rgba(36,19,16,.16);
}
*,*::before,*::after{box-sizing:border-box}
html{-webkit-text-size-adjust:100%;scroll-behavior:smooth}
body{margin:0;background:var(--paper);color:var(--ink);
  font-family:var(--display);font-size:1.0625rem;line-height:1.65;font-weight:400;
  font-synthesis-weight:none;-webkit-font-smoothing:antialiased;overflow-x:clip}
img,svg,video{display:block;max-width:100%}
a{color:inherit;text-decoration:none}
h1,h2,h3,h4{margin:0;font-weight:800;letter-spacing:-.032em;line-height:1.08;text-wrap:balance}
p{margin:0;text-wrap:pretty}
ul{margin:0;padding:0;list-style:none}
::selection{background:var(--brand);color:#fff}
:focus-visible{outline:3px solid var(--brand);outline-offset:3px;border-radius:5px}
.wrap{width:100%;max-width:var(--container);margin-inline:auto;padding-inline:var(--gutter)}
.sr{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;
  clip:rect(0 0 0 0);white-space:nowrap;border:0}
.skip{position:absolute;left:16px;top:-100px;z-index:200;padding:12px 20px;
  background:var(--brand);color:#fff;font-weight:800;border-radius:8px;transition:top .2s var(--ease)}
.skip:focus{top:16px}
/* Drafting grid under everything, fading at the edges. */
.grid-bg{position:fixed;inset:0;z-index:0;pointer-events:none;
  background-image:linear-gradient(var(--grid) 1px,transparent 1px),
                   linear-gradient(90deg,var(--grid) 1px,transparent 1px);
  background-size:48px 48px;
  mask-image:radial-gradient(120% 85% at 50% 22%,#000 0%,transparent 80%);
  -webkit-mask-image:radial-gradient(120% 85% at 50% 22%,#000 0%,transparent 80%)}
/* ── type ─────────────────────────────────────────────── */
/* No leading dash. It carried no information the uppercase mono label does
   not already carry, and beside a large headline it read as clutter. The
   label separates itself with tracking and the space beneath it instead. */
.eyebrow{display:inline-block;margin-bottom:14px;
  font-family:var(--mono);font-size:.68rem;font-weight:700;letter-spacing:.22em;
  text-transform:uppercase;color:var(--brand)}
.h-display{font-size:clamp(2.1rem,4.6vw,3.7rem);font-weight:900;letter-spacing:-.044em;
  line-height:1.04;text-wrap:balance}
.h-sec{font-size:clamp(1.85rem,3.9vw,3rem);font-weight:900;letter-spacing:-.038em;line-height:1.05}
.h-card{font-size:clamp(1.08rem,1.7vw,1.32rem);font-weight:800;letter-spacing:-.02em;line-height:1.25}
.lead{font-size:clamp(1.02rem,1.4vw,1.2rem);line-height:1.62;color:var(--ink-2);max-width:60ch}
.body{color:var(--ink-2);font-size:.98rem;line-height:1.7}
.mono{font-family:var(--mono);font-size:.68rem;font-weight:700;letter-spacing:.16em;text-transform:uppercase}
/* ── buttons. Standalone classes, never layered on a legacy name. ── */
/* ---- Primary CTA -------------------------------------------------------
   A shine sweep rather than a fill: the old ::after slid an INK panel up from
   below at z-index:-1 inside an isolate context, which painted OVER the
   element's own background. On the featured pricing card - white background,
   oxblood text by design - that turned the button near-black on near-black.
   Measured: text rgb(90,31,27) on a rgb(36,19,16) panel.

   The sweep is a gradient highlight that crosses the face, so it inherits
   whatever background the button actually has and can never hide it. That
   makes it safe on the brand ground AND on the inverted white variant. */
.cta{display:inline-flex;align-items:center;justify-content:center;gap:.55em;
  min-height:52px;padding:15px 28px;border:0;border-radius:999px;
  /* A lit gradient, not a flat fill. Light at the top edge, deep at the
     bottom, so the pill reads as a formed object rather than a coloured
     rectangle - the single biggest difference between a modern button and
     a 2012 one. */
  background:linear-gradient(176deg,#7C2E28 0%,var(--brand) 46%,#4A1714 100%);
  color:#fff;cursor:pointer;
  font-family:var(--display);font-size:.98rem;font-weight:800;
  letter-spacing:-.012em;
  white-space:nowrap;position:relative;overflow:hidden;isolation:isolate;
  /* Three layers doing three jobs: a soft coloured halo that grounds the
     button on the page, a tight contact shadow, and an inner top highlight
     that catches the "light" the gradient implies.
     Negative spread larger than half the blur keeps the shadow UNDER the
     button instead of spreading sideways into its neighbour. */
  box-shadow:
    0 10px 24px -16px rgba(90,31,27,.55),
    0 2px 5px -3px rgba(36,19,16,.32),
    inset 0 1px 0 rgba(255,255,255,.22),
    inset 0 -1px 0 rgba(0,0,0,.16);
  transition:transform .26s var(--ease),box-shadow .26s var(--ease),
    filter .26s var(--ease)}

/* The trailing arrow. It is the affordance: a label alone says what the
   button is, an arrow says it goes somewhere. Hidden from AT because it
   adds no information the label does not already carry. */
.cta::after{content:"";width:.62em;height:.62em;flex:none;
  margin-left:-.08em;position:relative;z-index:1;
  border-right:2.2px solid currentColor;border-top:2.2px solid currentColor;
  transform:rotate(45deg) translate(-.06em,.06em);
  transition:transform .3s var(--ease)}
.cta:hover::after,.cta:focus-visible::after{
  transform:rotate(45deg) translate(.12em,-.12em)}
/* The label sits above the sweep. */
.cta > *{position:relative;z-index:1}
/* The sweep. Parked off the left edge, crosses on hover. Skewed so the
   leading edge reads as a highlight travelling across a curved surface
   rather than a rectangle sliding past. */
.cta::before{content:"";position:absolute;top:-50%;bottom:-50%;left:-60%;
  width:45%;z-index:0;pointer-events:none;
  background:linear-gradient(90deg,
    transparent 0%,
    rgba(255,255,255,.10) 28%,
    rgba(255,255,255,.42) 50%,
    rgba(255,255,255,.10) 72%,
    transparent 100%);
  transform:translateX(0) skewX(-18deg);
  transition:transform .62s cubic-bezier(.22,.61,.36,1)}
.cta:hover::before,
.cta:focus-visible::before{transform:translateX(340%) skewX(-18deg)}
/* Lift plus a WIDER, softer halo. Raising a button without growing its
   shadow reads as sliding, not rising. */
.cta:hover{transform:translateY(-2px);color:#fff;
  box-shadow:
    0 18px 34px -18px rgba(90,31,27,.62),
    0 3px 7px -3px rgba(36,19,16,.3),
    inset 0 1px 0 rgba(255,255,255,.3),
    inset 0 -1px 0 rgba(0,0,0,.16);
  filter:saturate(1.05) brightness(1.04)}
/* Press feedback: the button must feel like it heard the click. */
.cta:active{transform:translateY(0) scale(.975);
  box-shadow:
    0 3px 8px -6px rgba(90,31,27,.5),
    inset 0 2px 5px rgba(0,0,0,.22);
  transition-duration:.09s}
.cta:focus-visible{outline:2px solid var(--brand-2);outline-offset:3px}
/* ---- CTA row spacing ---------------------------------------------------
   Every CTA row (.hh__b, .mh__b, .fin__b, .hero__btns, .end__btns ...) was
   declaring gap:12px separately. At 12px the primary's shadow closed the
   gap and the pair read as one joined control. Owned here so the whole site
   moves together, using :has so no row markup has to change. */
.hh__b,.mh__b,.fin__b,.hero__btns,.end__btns,.hx__b,.cl__b,
:is(div,p,nav):has(> .cta + .cta-2),
:is(div,p,nav):has(> .cta + .cta-inv),
:is(div,p,nav):has(> .cta-2 + .cta),
:is(div,p,nav):has(> .cta-inv + .cta){gap:clamp(12px,1.4vw,18px)}
/* Inverted variant (white button on a brand ground): the sweep must be
   OXBLOOD there, since a white sweep on white is invisible. */
.prc__c--hero .cta::before,
.cta--inv::before{background:linear-gradient(90deg,
  transparent 0%,rgba(90,31,27,.05) 28%,rgba(90,31,27,.16) 50%,
  rgba(90,31,27,.05) 72%,transparent 100%)}
@media(prefers-reduced-motion:reduce){
  /* The sweep is decoration; the press feedback is information, so that
     stays. Movement goes. */
  .cta::before{display:none}
  /* The arrow STAYS - it is an affordance, not decoration. Only its travel
     is removed. */
  .cta::after,.cta:hover::after{transition:none;
    transform:rotate(45deg) translate(-.06em,.06em)}
  .cta,.cta:hover,.cta:active{transform:none;transition:background .2s linear}
}
/* The ghost pairs with .cta, so its box must match: same height, same
   padding, same type size. A 54px ghost beside a 52px primary reads as a
   mistake at a glance. */
.cta-2{display:inline-flex;align-items:center;justify-content:center;gap:.55em;
  min-height:52px;padding:15px 28px;border:1.5px solid var(--line-2);border-radius:999px;
  background:transparent;color:var(--brand);cursor:pointer;
  font-family:var(--display);font-size:.98rem;font-weight:800;letter-spacing:-.012em;white-space:nowrap;
  transition:border-color .28s var(--ease),color .28s var(--ease),
    background .28s var(--ease),transform .28s var(--ease)}
.cta-2:hover{border-color:var(--brand);color:var(--brand);
  background:rgba(90,31,27,.05);transform:translateY(-2px)}
.cta-2:active{transform:translateY(0) scale(.985)}
/* ── NAV: new. Slim, paper-tinted, underline on hover. ── */
.nv{position:fixed;inset:0 0 auto;z-index:90;border-bottom:1px solid transparent;
  padding-top:env(safe-area-inset-top);
  /* A standing ground. Fully transparent let the page paint through the
     links mid-scroll; this is always present, and .stuck only deepens it. */
  background:rgba(247,244,239,.82);
  backdrop-filter:blur(14px) saturate(150%);
  -webkit-backdrop-filter:blur(14px) saturate(150%);
  /* Background snaps (120ms); only the hairline and shadow ease. A 340ms
     background fade is longer than a flick scroll, so the bar was still
     see-through exactly when content arrived underneath it. */
  transition:background-color .12s linear,backdrop-filter .12s linear,
    border-color .34s var(--ease),box-shadow .34s var(--ease)}
.nv.stuck{background:rgba(247,244,239,.94);border-bottom-color:var(--line);
  box-shadow:0 1px 20px -8px rgba(36,19,16,.22);
  backdrop-filter:blur(18px) saturate(165%);-webkit-backdrop-filter:blur(18px) saturate(165%)}
.nv__in{display:flex;align-items:center;gap:20px;min-height:72px;
  max-width:var(--container);margin-inline:auto;padding-inline:var(--gutter)}
.nv__logo{flex:none;line-height:0}
.nv__logo img{width:clamp(146px,15vw,180px);height:auto;
  transition:filter .12s linear}
.nv__links{display:none;margin-left:auto;gap:clamp(10px,2vw,28px)}
.nv__links a{position:relative;display:inline-flex;align-items:center;min-height:44px;
  font-size:.93rem;font-weight:700;color:var(--ink-2);
  /* Matches the bar's own .12s background switch. At .22s the ink was still
     white while the ground had already gone light - 1.38:1 for two frames. */
  transition:color .12s linear}
.nv__links a::after{content:"";position:absolute;left:0;bottom:13px;width:100%;height:2px;
  background:var(--brand);transform:scaleX(0);transform-origin:left;
  transition:transform .3s var(--ease)}
.nv__links a:hover{color:var(--brand)}
.nv__links a:hover::after,.nv__links a[aria-current="page"]::after{transform:scaleX(1)}
.nv__links a[aria-current="page"]{color:var(--brand)}
/* The header button was 50px tall and 184px wide inside a 73px bar - 68% of
   the header height and wider than any nav item, so it dominated the menu.
   Sized down to sit as one item among several. The arrow is dropped: in the
   header the button is a destination, not a step in a flow, and the glyph
   was buying width it did not need. */
.nv__cta{display:none;flex:none;min-height:40px;padding:9px 18px;
  font-size:.84rem;letter-spacing:-.006em;
  box-shadow:
    0 4px 12px -8px rgba(90,31,27,.5),
    inset 0 1px 0 rgba(255,255,255,.2),
    inset 0 -1px 0 rgba(0,0,0,.14)}
.nv__cta::after{display:none}
.nv__cta:hover{transform:translateY(-1px);
  box-shadow:
    0 8px 18px -10px rgba(90,31,27,.55),
    inset 0 1px 0 rgba(255,255,255,.26),
    inset 0 -1px 0 rgba(0,0,0,.14)}
.nv__tog{display:grid;place-content:center;gap:6px;margin-left:auto;width:48px;height:48px;padding:0;
  background:var(--white);border:1.5px solid var(--line-2);border-radius:13px;cursor:pointer}
.nv__tog span{display:block;width:20px;height:2px;background:var(--brand);border-radius:2px;
  transition:transform .3s var(--ease),opacity .2s}
.nv__tog[aria-expanded="true"] span:nth-child(1){transform:translateY(8px) rotate(45deg)}
.nv__tog[aria-expanded="true"] span:nth-child(2){opacity:0}
.nv__tog[aria-expanded="true"] span:nth-child(3){transform:translateY(-8px) rotate(-45deg)}
.dw{position:fixed;inset:0;z-index:88;visibility:hidden;pointer-events:none}
.dw__scrim{position:absolute;inset:0;background:rgba(36,19,16,.44);opacity:0;
  transition:opacity .4s var(--ease)}
.dw__panel{position:absolute;inset:0 0 0 auto;width:min(400px,100%);background:var(--white);
  border-left:1px solid var(--line);box-shadow:var(--lift-3);
  /* NOT var(--gutter): that is clamp(20px,5vw,48px), so at tablet widths it
     hit 48px a side and left only 286px of usable width inside a 400px
     drawer - enough to wrap the longest chip. The gutter is sized for body
     content, not for a fixed-width panel. */
  padding:calc(84px + env(safe-area-inset-top)) clamp(18px,4vw,24px)
    calc(28px + env(safe-area-inset-bottom));
  display:flex;flex-direction:column;overflow-y:auto;overscroll-behavior:contain;
  transform:translateX(101%);transition:transform .44s var(--ease)}
.dw.open{visibility:visible;pointer-events:auto}
.dw.open .dw__scrim{opacity:1}
.dw.open .dw__panel{transform:none}
/* Both shapes: a plain link, and a grouped row holding a link + a toggle. */
.dw .dl{display:flex;align-items:baseline;gap:14px;padding:18px 0;
  border-bottom:1px solid var(--line);font-size:1.26rem;font-weight:800;letter-spacing:-.025em}
.dw .dl i{font-family:var(--mono);font-size:.6rem;font-style:normal;font-weight:700;
  color:var(--brand);letter-spacing:.1em;flex:none}
.dw .dl--row{align-items:center;justify-content:space-between;gap:10px}
.dw .dl__main{display:flex;align-items:baseline;gap:14px;flex:1 1 auto;
  font-size:inherit;font-weight:inherit;letter-spacing:inherit}
/* 44px target: the toggle must be reachable without hitting the link. */
.dw .dl__tog{flex:none;display:grid;place-items:center;width:44px;height:44px;
  margin-right:-10px;padding:0;background:none;border:0;cursor:pointer;
  color:var(--brand);border-radius:12px;
  transition:background .24s var(--ease)}
.dw .dl__tog:hover{background:var(--paper-2)}
/* Same drawn chevron as the desktop caret, larger for touch. */
.dw .dl__tog i{display:block;width:9px;height:9px;border:solid currentColor;
  border-width:0 2px 2px 0;transform:translateY(-3px) rotate(45deg);
  transition:transform .28s var(--ease)}
.dw .dl__tog i::before{display:none}
.dw .dl__tog[aria-expanded="true"] i{transform:translateY(2px) rotate(-135deg)}
/* Collapsed by default; the script animates to a measured scrollHeight,
   because height:auto does not transition. */
.dw .dl__sub{height:0;overflow:hidden;transition:height .38s var(--ease)}
/* Drawer rows match the desktop panel: icon disc, label, arrow at the end. */
.dw .dl__s{display:flex;align-items:center;gap:12px;margin:2px 0;padding:7px 12px 7px 7px;border-radius:999px;
  font-size:.95rem;font-weight:600;color:var(--ink-2);
  transition:background .25s var(--ease),color .25s var(--ease)}
.dw .dl__sub{padding:4px 0 10px}
.dw .dl__sub > .dl__s:not(.dl__s--t){margin-left:22px}
.dw .dl__s--t{margin-top:8px;font-weight:700;color:var(--ink);background:var(--paper-2);line-height:1.3}
.dw .dl__s--t:first-child{margin-top:0}
.dw .dl__s--t .nv__ic{color:#fff;border-color:transparent;background:linear-gradient(160deg,var(--brand-2),var(--brand))}
/* The longest title wrapped to 2 lines in the 400px drawer at tablet widths. */
@media(max-width:1119px){.dw .dl__s--t{font-size:.875rem;letter-spacing:-.015em}}
.dw .dl__s:hover,.dw .dl__s:active{color:#fff;background:linear-gradient(160deg,var(--brand-2),var(--brand))}
.dw .dl__s:hover .nv__ic,.dw .dl__s:active .nv__ic{color:#fff;background:rgba(255,255,255,.14);border-color:rgba(255,255,255,.28)}
.dw .dl__s:hover .nv__go,.dw .dl__s:active .nv__go{color:#fff;opacity:1}
.dw .dl__wrap{border-bottom:1px solid var(--line)}
.dw .dl__wrap .dl{border-bottom:0}
.dw__foot{margin-top:auto;padding-top:26px;display:grid;gap:12px}
.dw__tel{text-align:center;padding:14px;border-radius:13px;border:1px solid var(--line-2);
  font-family:var(--mono);font-weight:700;color:var(--brand)}
/* ── Header-top social strip ──────────────────────────
   Sits above the fixed nav and scrolls away with the page, as on the live
   site. Hidden below 1000px, where the drawer carries these links instead. */
/* NO header social strip. It sat above this bar, collided with the nav links,
   and duplicated accounts the footer already carries - so it was removed
   rather than repaired. --header-h is now the nav alone (73px); it was 109px
   while the 36px strip existed, and every hero pads itself from it. */
@media(min-width:1120px){
  :root{--header-h:73px}
  /* DIRECT CHILDREN ONLY. Without the > these matched the dropdown panel's
     own links, painting white text onto the panel's white background. */
  html.has-dark-hero:not(.nv-stuck) .nv__links > a,
  html.has-dark-hero:not(.nv-stuck) .nv__has > a,
  html.has-dark-hero:not(.nv-stuck) .nv__caret{color:rgba(255,255,255,.9)}
  html.has-dark-hero:not(.nv-stuck) .nv__links > a:hover,
  html.has-dark-hero:not(.nv-stuck) .nv__has > a:hover,
  html.has-dark-hero:not(.nv-stuck) .nv__has:hover .nv__caret{color:#fff}
  html.has-dark-hero:not(.nv-stuck) .nv__links > a::after,
  html.has-dark-hero:not(.nv-stuck) .nv__has > a::after{background:#fff}
  /* The logo is dark artwork; invert it so it reads on the image too. */
  html.has-dark-hero:not(.nv-stuck) .nv__logo img{filter:brightness(0) invert(1)}
}
/* Dark-hero pages: the header is transparent ON the hero by design, so the
   standing ground above must be switched off there - and only there. */
html.has-dark-hero:not(.nv-stuck) .nv{background-color:transparent;
  backdrop-filter:none;-webkit-backdrop-filter:none}
/* The header reads as transparent but is never actually unprotected: a soft
   ink gradient rides behind it so the white links always have a ground, at
   scroll 0 and through the whole window before .nv-stuck trips. */
html.has-dark-hero .nv::before{content:"";position:absolute;inset:0;z-index:-1;
  pointer-events:none;
  background:linear-gradient(180deg,rgba(14,6,5,.72) 0%,rgba(14,6,5,.42) 55%,
    transparent 100%);
  opacity:1;transition:opacity .2s linear}
/* Once the real bar takes over, the gradient goes: two grounds would read
   as a dark smear under a light bar. */
html.has-dark-hero.nv-stuck .nv::before{opacity:0}
/* Below 1000px the strip is hidden but the nav is STILL transparent over the
   hero, so the logo needs the same inversion there. Measured: the mobile
   logo was dark artwork on a dark hero and effectively invisible. */
@media(max-width:1119px){
  html.has-dark-hero:not(.nv-stuck) .nv__logo img{filter:brightness(0) invert(1)}
  html.has-dark-hero:not(.nv-stuck) .nv__tog{background:rgba(255,255,255,.12);
    border-color:rgba(255,255,255,.34);backdrop-filter:blur(10px);
    -webkit-backdrop-filter:blur(10px)}
  html.has-dark-hero:not(.nv-stuck) .nv__tog span{background:#fff}
}
/* ── Desktop submenu panels ──────────────────────────
   Opened by hover OR by the caret's aria-expanded, so the keyboard and
   touch paths work without depending on hover. */
.nv__has{position:relative;display:inline-flex;align-items:center;gap:0;
  /* Pulls the following item back by roughly the caret's width, so a group
     with a caret sits the same visual distance from its neighbour as a plain
     link does. Without it "Our Services" read ~50px from "Our Attorneys"
     while every other pair was 28px. */
  margin-right:-16px}
.nv__caret{display:grid;place-items:center;width:18px;height:44px;padding:0;
  margin-left:-2px;background:none;border:0;cursor:pointer;color:var(--ink-2);
  transition:color .12s linear}
/* The glyph is drawn, not set: bi-plus at 9.92px measured 10x11px and read as
   a stray mark rather than a menu cue. Two borders rotated 45deg give a
   crisp chevron at any size, and it flips to point up when the panel opens. */
.nv__caret i{display:block;width:6px;height:6px;border:solid currentColor;
  border-width:0 1.6px 1.6px 0;transform:translateY(-2px) rotate(45deg);
  transition:transform .28s var(--ease)}
.nv__caret i::before{display:none}
.nv__has:hover .nv__caret{color:var(--brand)}
.nv__caret[aria-expanded="true"]{color:var(--brand)}
.nv__caret[aria-expanded="true"] i{transform:translateY(1px) rotate(-135deg)}
/* ---- The dropdown panels ------------------------------------------------
   Every row is a pill: an icon disc, the label, and an arrow at the end
   that says "this goes somewhere". Hover fills the pill oxblood and turns
   the disc and arrow white. A group's own page leads with a solid disc;
   its child pages hang below it on a hairline, one step in. Resources has
   no groups, so its rows are all full-weight (--flat).
   The panel declares its own ink, so no ancestor state (dark hero,
   scrolled) can leak into it. */
.nv__panel{position:absolute;top:100%;left:-18px;z-index:5;
  min-width:340px;padding:10px;
  background:rgba(255,255,255,.96);
  -webkit-backdrop-filter:blur(18px) saturate(150%);backdrop-filter:blur(18px) saturate(150%);
  border:1px solid var(--line);border-radius:22px;
  box-shadow:0 40px 80px -36px rgba(36,19,16,.4),0 12px 24px -16px rgba(36,19,16,.18);
  opacity:0;visibility:hidden;transform:translateY(-8px) scale(.98);transform-origin:20% 0;
  transition:opacity .26s var(--ease),transform .32s cubic-bezier(.23,1,.32,1),visibility .26s}
.nv__has:hover .nv__panel,
.nv__has:focus-within .nv__panel,
.nv__caret[aria-expanded="true"]+.nv__panel{opacity:1;visibility:visible;transform:none}
.nv__grp+.nv__grp{margin-top:6px;padding-top:6px;border-top:1px solid var(--line)}

/* A row. (.nv__links a gives every nav link an underline ::after; rows
   switch it off.) */
.nv__panel a{display:flex;align-items:center;gap:12px;width:100%;min-height:48px;
  padding:7px 14px 7px 7px;border-radius:999px;white-space:nowrap;
  font-size:.875rem;font-weight:700;letter-spacing:-.012em;line-height:1.3;color:var(--ink);
  transition:background .25s var(--ease),color .25s var(--ease),box-shadow .25s var(--ease)}
.nv__panel a::after{content:none;display:none}
.nv__ic{flex:none;display:grid;place-items:center;width:34px;height:34px;border-radius:50%;
  font-size:.85rem;color:var(--brand);background:var(--brand-wash);border:1px solid rgba(90,31,27,.1);
  transition:background .25s var(--ease),color .25s var(--ease),border-color .25s var(--ease)}
.nv__tx{flex:1 1 auto;min-width:0}
.nv__go{flex:none;margin-left:10px;font-size:.8rem;color:var(--brand);opacity:.4;
  transition:transform .3s cubic-bezier(.23,1,.32,1),opacity .25s var(--ease),color .25s var(--ease)}
/* Doubled scope: outranks the per-kind ink of child and flat rows below. */
.nv__has .nv__panel .nv__grp a:hover,.nv__has .nv__panel .nv__grp a:focus-visible{color:#fff;outline:none;
  background:linear-gradient(160deg,var(--brand-2),var(--brand));
  box-shadow:0 14px 26px -14px rgba(62,20,17,.7)}
.nv__panel a:hover .nv__ic,.nv__panel a:focus-visible .nv__ic{color:#fff;background:rgba(255,255,255,.14);border-color:rgba(255,255,255,.28)}
.nv__panel a:hover .nv__go,.nv__panel a:focus-visible .nv__go{color:#fff;opacity:1;transform:translate(2px,-2px)}

/* A group's own page: a solid disc, a soft paper ground. */
.nv__panel .nv__grpt{background:var(--paper)}
.nv__panel .nv__grpt .nv__ic{color:#fff;border-color:transparent;
  background:linear-gradient(160deg,var(--brand-2),var(--brand))}

/* Child pages: one step in, hung on a hairline from the group's disc. */
.nv__grpl{position:relative;display:grid;gap:2px;margin-top:2px;padding-left:30px}
.nv__grpl::before{content:"";position:absolute;left:23px;top:-2px;bottom:24px;width:1px;background:var(--line-2)}
.nv__grpl a{position:relative;min-height:42px;padding:5px 12px 5px 5px;font-weight:600;color:var(--ink-2)}
.nv__grpl a::before{content:"";position:absolute;left:-7px;top:50%;width:9px;height:1px;background:var(--line-2)}
.nv__grpl .nv__ic{width:30px;height:30px;font-size:.76rem}
/* Resources: no groups, so its rows are full-weight and not indented. */
.nv__panel--flat .nv__grpl{padding-left:0;margin-top:0}
.nv__panel--flat .nv__grpl::before,.nv__panel--flat .nv__grpl a::before{content:none}
.nv__panel--flat .nv__grpl a{min-height:48px;padding:7px 14px 7px 7px;font-weight:700;color:var(--ink)}
.nv__panel--flat .nv__grpl .nv__ic{width:34px;height:34px;font-size:.85rem}
@media(prefers-reduced-motion:reduce){
  .nv__panel,.nv__panel a,.nv__ic,.nv__go{transition:none}
}
@media(min-width:1120px){
  .nv{transition:background .34s var(--ease),border-color .34s var(--ease),
    top .34s var(--ease)}
  .nv__links{display:flex;align-items:center}
  .nv__cta{display:inline-flex}
  .nv__tog,.dw{display:none!important}
}
/* ── shells ─────────────────────────────────────────── */
main{position:relative;z-index:1}
.sec{position:relative;padding-block:clamp(56px,7.5vw,108px)}
.sec--tint{background:var(--paper-2)}
.hero .lead{margin-top:20px}
@media(min-width:680px){
  .hero__stat{margin-top:36px}
}
@media(min-width:960px){
  .hero__media{aspect-ratio:4/5;max-height:clamp(400px,58vh,560px)}
}
@media(min-width:960px){.hero__in{grid-template-columns:1.1fr .9fr}}
/* 2. WHO — offset plate over the image, asymmetric */
.who__in{display:grid;gap:clamp(24px,4vw,0)}
.who__img{border-radius:var(--r-lg);overflow:hidden;aspect-ratio:4/3;border:1px solid var(--line)}
.who__img img{width:100%;height:100%;object-fit:cover}
.who__plate{background:var(--white);border:1px solid var(--line);border-radius:var(--r-lg);
  padding:clamp(24px,3.2vw,40px);box-shadow:var(--lift-2)}
.who__plate p+p{margin-top:14px}
.who__quote{margin-top:22px;padding-left:20px;border-left:3px solid var(--brand);
  font-size:1.04rem;font-weight:700;color:var(--ink);line-height:1.5}
@media(min-width:960px){
  .who__in{grid-template-columns:1fr 1fr;align-items:center}
  .who__plate{margin-left:-14%;position:relative;z-index:2}
}
/* 3. PRINCIPLES — ruled index rows, number in the margin */
.idx{margin-top:clamp(24px,3vw,40px);border-top:1px solid var(--line-2)}
.idx__row{display:grid;gap:10px 28px;padding-block:clamp(22px,2.8vw,34px);
  border-bottom:1px solid var(--line);transition:background .3s var(--ease)}
.idx__row:hover{background:var(--white)}
.idx__n{font-family:var(--mono);font-size:.7rem;font-weight:700;letter-spacing:.14em;color:var(--brand)}
.idx__b p{margin-top:8px}
@media(min-width:820px){.idx__row{grid-template-columns:88px 1fr;padding-inline:14px}}
/* 4. SERVE — role grid. Each role carries its own visa codes, so this is a
   read-and-scan table of contents, not decorative motion. Replaces the earlier
   marquee, which could only show role names and dropped the codes. */
.sg{margin-top:clamp(24px,3vw,40px);display:grid;gap:12px;
  grid-template-columns:1fr;list-style:none;padding:0}
.sg__i{background:var(--white);border:1px solid var(--line);border-radius:var(--r-lg);
  padding:22px 24px;display:grid;gap:8px;justify-items:stretch;
  /* Content sits left; only the badge row needs the full width to lay out. */
  text-align:left;
  transition:transform .4s var(--ease),box-shadow .4s var(--ease)}
.sg__i:hover{transform:translateY(-4px);box-shadow:var(--lift-2)}
.sg__ic{display:grid;place-items:center;width:42px;height:42px;border-radius:12px;
  background:var(--brand-wash);color:var(--brand);font-size:1.05rem;margin-bottom:2px}
.sg__n{font-weight:800;font-size:1.02rem;line-height:1.25;color:var(--ink)}
/* Visa codes as badges rather than one mono run separated by middots. The
   old treatment read as machine output: a single grey string where every code
   had equal weight and none was scannable. Each code is now its own chip, so
   the eye can pick out "EB-1A" without reading the whole line.
   Mono is KEPT for the codes themselves - these are classification codes, and
   the tabular feel is correct for them; it is the run-on line that was wrong. */
.sg__v{display:flex;flex-wrap:wrap;gap:5px;margin:2px 0 0;padding:0;list-style:none}
.sg__v li{font-family:var(--mono);font-size:.68rem;font-weight:700;
  letter-spacing:.03em;line-height:1;
  padding:5px 8px;border-radius:6px;white-space:nowrap;
  color:var(--brand);background:var(--brand-wash);
  border:1px solid rgba(90,31,27,.14);
  transition:background .24s var(--ease),border-color .24s var(--ease),
    color .24s var(--ease)}
/* The card is the hover target, so the badges respond with it rather than
   each one lighting up separately under the cursor. */
.sg__i:hover .sg__v li{background:var(--brand);border-color:var(--brand);color:#fff}
@media(min-width:620px){.sg{grid-template-columns:repeat(2,1fr)}}
@media(min-width:1040px){.sg{grid-template-columns:repeat(4,1fr)}}
/* 5. WHY — stepped plates, deliberately uneven */
.why{margin-top:clamp(24px,3vw,40px);display:grid;gap:14px}
.why__i{background:var(--white);border:1px solid var(--line);border-radius:var(--r-lg);
  padding:clamp(22px,2.8vw,32px);transition:transform .38s var(--ease),box-shadow .38s var(--ease)}
.why__i:hover{transform:translateY(-4px);box-shadow:var(--lift-2)}
.why__ic{display:grid;place-items:center;width:46px;height:46px;border-radius:14px;
  background:var(--brand);color:#fff;font-size:1.18rem;margin-bottom:16px}
.why__tag{margin-top:14px;display:flex;align-items:center;gap:10px;
  font-family:var(--mono);font-size:.72rem;letter-spacing:.1em;
  text-transform:uppercase;color:var(--ink-3)}
.why__tag b{color:var(--brand);font-weight:700}
.why__lnk{color:inherit;text-decoration:none;
  border-bottom:1px solid var(--line-2);transition:border-color .3s var(--ease)}
.why__lnk:hover{border-bottom-color:var(--brand)}
.why__i p{margin-top:8px}
@media(min-width:860px){
  .why{grid-template-columns:repeat(12,1fr)}
  .why__i:nth-child(1){grid-column:1/7}
  .why__i:nth-child(2){grid-column:7/13;margin-top:30px}
  .why__i:nth-child(3){grid-column:1/7}
  .why__i:nth-child(4){grid-column:7/13;margin-top:30px}
}
/* 6. CTA — brand ground, inverted */
.end{position:relative;background:var(--brand);color:#F2E4E1;text-align:center;
  padding-block:clamp(64px,8vw,110px)}
.end h2{color:#fff;max-width:18ch;margin-inline:auto}
.end p{margin:18px auto 0;max-width:58ch;color:#E2C9C4}
.end__btns{display:flex;flex-wrap:wrap;gap:12px;justify-content:center;margin-top:32px}
.end .cta{background:#fff;color:var(--brand);box-shadow:none}
.end .cta::after{background:var(--ink)}
.end .cta:hover{color:#fff}
.end .cta-2{border-color:rgba(255,255,255,.4);color:#fff}
.end .cta-2:hover{border-color:#fff;color:#fff}
/* ── FOOTER ─────────────────────────────────────────────────────────────
   Rebuilt for readability. Measured problems in the previous version:
   a sunset photograph and a particle canvas sat behind the link columns
   (text over moving, bright imagery), the wordmark was cut off at both
   edges, column headings were 10px, and the legal lines sat near the AA
   floor. Now: a calm oxblood-to-ink ground, a contact strip at the top,
   15px links at 11:1+, and every grey on this ground checked >= 7:1.
   Order: contact strip -> columns -> disclaimer -> bottom bar -> wordmark. */
.ft{position:relative;z-index:1;isolation:isolate;overflow:hidden;
  color:#E6D8D4;font-size:.95rem;
  padding-block:clamp(34px,3.6vw,50px) 0;
  /* Paints while the photograph loads. */
  background:linear-gradient(180deg,#2E1410 0%,#1E0C0A 100%)}
/* Oxblood hairline across the top edge: the page closes on a drawn line. */
.ft::before{content:"";position:absolute;inset:0 0 auto;height:1px;z-index:2;
  background:linear-gradient(90deg,transparent,#B65A50 22%,#B65A50 78%,transparent)}
/* The photograph. WebP at three widths with a JPEG fallback (a CSS
   background cannot negotiate format the way <picture> does). Anchored
   bottom-right so the statue and skyline sit at the base, behind the
   wordmark, and the dark sky sits behind the link columns. */
.ft__bg{position:absolute;inset:0;z-index:-1;pointer-events:none;
  background-image:image-set(
    url("../img/bg/footer-bg-1200.webp") type("image/webp"),
    url("../img/bg/footer-bg-1200.jpg") type("image/jpeg"));
  background-size:cover;background-position:70% 100%;background-repeat:no-repeat}
@media(min-width:1280px){
  .ft__bg{background-image:image-set(
    url("../img/bg/footer-bg-1864.webp") type("image/webp"),
    url("../img/bg/footer-bg-1200.jpg") type("image/jpeg"))}
}
@media(max-width:600px){
  .ft__bg{background-image:image-set(
    url("../img/bg/footer-bg-760.webp") type("image/webp"),
    url("../img/bg/footer-bg-1200.jpg") type("image/jpeg"))}
}
/* The scrim: near-solid where text sits, opening toward the base and the
   statue, so the photo is seen without ever sitting bright behind a link. */
.ft__bg::after{content:"";position:absolute;inset:0;
  background:
    linear-gradient(90deg,rgba(24,9,7,.55) 0%,rgba(24,9,7,0) 60%),
    linear-gradient(180deg,rgba(26,10,8,.95) 0%,rgba(26,10,8,.9) 40%,
      rgba(26,10,8,.78) 70%,rgba(20,8,6,.5) 100%)}
.ft__in{position:relative;z-index:1}

/* Column headings: small caps label, white. */
.ft h4{margin:0 0 12px;position:relative;
  font-family:var(--mono);font-size:.72rem;font-weight:800;
  letter-spacing:.16em;text-transform:uppercase;color:#fff}

/* ---- 1. Contact strip ---- */
.ft__reach{padding-bottom:clamp(20px,2.2vw,28px);
  border-bottom:1px solid rgba(255,255,255,.12)}
.ft__cards{margin:0;padding:0;list-style:none;display:grid;gap:12px}
.ft__card{position:relative;display:flex;align-items:center;gap:14px;height:100%;
  padding:12px 16px;border-radius:16px;color:#fff;text-decoration:none;
  background:linear-gradient(168deg,rgba(255,255,255,.075),rgba(255,255,255,.03));
  border:1px solid rgba(255,255,255,.14);
  transition:border-color .3s var(--ease),background .3s var(--ease),transform .3s var(--ease)}
a.ft__card:hover{border-color:rgba(255,255,255,.28);transform:translateY(-3px);
  background:linear-gradient(168deg,rgba(255,255,255,.11),rgba(255,255,255,.045))}
a.ft__card:focus-visible{outline:2px solid #F0DCD8;outline-offset:3px}
.ft__cic{flex:none;display:grid;place-items:center;width:40px;height:40px;border-radius:12px;
  color:#fff;font-size:1rem;
  background:linear-gradient(160deg,#9A3D35,var(--brand));
  box-shadow:0 10px 20px -12px rgba(0,0,0,.7),inset 0 1px 0 rgba(255,255,255,.2);
  transition:rotate .35s var(--ease)}
a.ft__card:hover .ft__cic{rotate:-6deg}
.ft__cv{flex:1 1 auto;min-width:0;font-style:normal;font-weight:700;
  font-size:.95rem;line-height:1.4;color:#fff}
/* An email address must not break mid-word: one line, and the grid below
   guarantees the card is wide enough at every width. */
a[href^="mailto:"] .ft__cv{white-space:nowrap}
.ft__cgo{flex:none;color:#E8B4AC;transition:transform .3s var(--ease)}
a.ft__card:hover .ft__cgo{transform:translate(2px,-2px)}
@media(min-width:700px){
  .ft__cards{grid-template-columns:minmax(0,1fr) minmax(0,1fr)}
  .ft__cards li:last-child{grid-column:1 / -1}
}
/* Small phones: a tighter card so the one-line email still fits. */
@media(max-width:479px){
  .ft__card{gap:12px;padding:14px}
  .ft__cic{width:40px;height:40px;border-radius:12px;font-size:1rem}
  .ft__cv{font-size:.93rem}
  .ft__cgo{display:none}
}
@media(min-width:1200px){
  .ft__cards{grid-template-columns:minmax(0,1.15fr) minmax(0,.85fr) minmax(0,1.2fr)}
  .ft__cards li:last-child{grid-column:auto}
}

/* Footer spotlight: the shared .st-spot idea, footer-scoped so it works on
   every page (cursor-layer.css is per page). A rose glow at z -1 inside the
   card's own stacking context, plus a lit edge pointing at the cursor. */
.ft-spot{isolation:isolate;overflow:hidden}
.ft-spot::before{content:"";position:absolute;z-index:-1;top:50%;left:50%;
  width:460px;height:460px;border-radius:50%;pointer-events:none;opacity:0;
  background:radial-gradient(circle,rgba(240,220,216,.16),transparent 62%);
  transform:translate(-50%,-50%) rotate(calc((var(--spotlight-angle,0) + 90) * 1deg))
    translateY(calc(min(var(--spotlight-distance,0), 200) * -1px));
  transition:opacity .45s var(--ease)}
.ft-spot::after{content:"";position:absolute;inset:0;z-index:2;pointer-events:none;
  border-radius:inherit;padding:1px;opacity:0;
  background:conic-gradient(from calc((var(--spotlight-angle,0) + 90) * 1deg),
    rgba(240,220,216,.85) 0deg,rgba(240,220,216,0) 70deg,
    rgba(240,220,216,0) 290deg,rgba(240,220,216,.85) 360deg);
  -webkit-mask:linear-gradient(#000 0 0) content-box,linear-gradient(#000 0 0);
  -webkit-mask-composite:xor;
  mask:linear-gradient(#000 0 0) content-box exclude,linear-gradient(#000 0 0);
  transition:opacity .45s var(--ease)}
html.st-cursor .ft-spot:hover::before,
html.st-cursor .ft-spot:hover::after{opacity:1}

/* ---- 2. Columns ---- */
.ft__top{display:grid;gap:30px 24px;
  padding-block:clamp(24px,2.6vw,34px);border-bottom:1px solid rgba(255,255,255,.12)}
@media(min-width:360px){
  .ft__top{grid-template-columns:1fr 1fr}
  .ft__brand{grid-column:1 / -1}
}
/* Touch screens keep 40px link targets. */
@media(pointer:coarse){.ft__links a,.ft__ccpa{min-height:40px}}
/* Tablet: the three link lists side by side, and the brand block in two
   columns (logo + blurb | newsletter + social), so the footer is not a
   tall stack. `dense` lets the right-column items fill from the top. */
@media(min-width:700px) and (max-width:1023px){
  .ft__top{grid-template-columns:repeat(3,minmax(0,1fr))}
  .ft__brand{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1fr);
    grid-auto-flow:row dense;column-gap:32px;align-content:start}
  .ft__brand > *{grid-column:2}
  .ft__brand > .ft__logo,.ft__brand > .ft__blurb{grid-column:1}
  .ft__brand > .ft__logo{grid-row:1}
  .ft__brand > .ft__blurb{grid-row:2 / span 4}
  .ft__brand .ft__nlh{margin-top:0!important}
}
@media(min-width:1024px){
  .ft__top{grid-template-columns:1.45fr 1.1fr 1fr .85fr;gap:clamp(30px,4vw,64px)}
  .ft__brand{grid-column:auto}
}
.ft__logo{display:inline-block;margin-bottom:12px}
.ft__logo img{width:180px;
  /* height:auto is load-bearing: without it the HTML height="74" stays
     fixed while width scales, squashing the 5.392:1 artwork. */
  height:auto;filter:brightness(0) invert(1)}
.ft__blurb{margin:0;max-width:40ch;color:#E6D8D4;line-height:1.55}
.ft__links{display:grid;gap:2px}
.ft__links a,.ft__ccpa{position:relative;display:inline-flex;align-items:center;
  min-height:34px;width:fit-content;max-width:100%;
  color:#E6D8D4;text-decoration:none;line-height:1.45;
  transition:color .24s var(--ease),transform .24s var(--ease)}
/* The hovered link brightens and slides a little: movement plus colour. */
.ft__links a:hover,.ft__ccpa:hover{color:#fff;transform:translateX(10px)}
.ft__links a:focus-visible,.ft__ccpa:focus-visible{outline:2px solid #F0DCD8;
  outline-offset:3px;border-radius:4px}

/* Social: 44px targets, magnetic under the cursor layer. */
.ft__soc{margin:14px 0 0;padding:0;list-style:none;display:flex;flex-wrap:wrap;gap:10px}
.ft__soc a{display:grid;place-items:center;width:44px;height:44px;border-radius:50%;
  border:1px solid rgba(255,255,255,.24);color:#F1E6E3;background:rgba(255,255,255,.04);
  transition:background .26s var(--ease),color .26s var(--ease),
    transform .26s var(--ease),border-color .26s var(--ease)}
.ft__soc a:hover{background:var(--brand-2);border-color:var(--brand-2);color:#fff;
  transform:translateY(-3px)}
.ft__soc a:focus-visible{outline:2px solid #F0DCD8;outline-offset:3px}
/* Medium and Substack ship as inline SVG: without a size they fill the
   circle; 16px matches the icon font's optical weight. */
.ft__soc svg{width:16px;height:16px;fill:currentColor;display:block}
html.st-cursor .ft [string="magnetic"]{
  translate:calc(var(--magnetic-x,0) * 1px) calc(var(--magnetic-y,0) * 1px)}

/* ---- 3. Disclaimer + 4. bottom bar ---- */
.ft__disc{margin:0;padding-block:18px;max-width:none;
  font-size:.8rem;line-height:1.7;color:#D6C7C2}
.ft__disc strong{color:#fff}
.ft__bot{display:flex;flex-wrap:wrap;justify-content:space-between;align-items:center;
  gap:10px 28px;padding-block:14px;border-top:1px solid rgba(255,255,255,.12);
  font-size:.84rem;color:#D6C7C2}
.ft__legal{display:flex;flex-wrap:wrap;align-items:center}
.ft__legal a{color:#E6D8D4;text-decoration:none;padding:6px 0;
  transition:color .24s var(--ease)}
.ft__legal a:hover{color:#fff;text-decoration:underline;text-underline-offset:4px}
/* A dot between legal links, drawn by CSS so the markup stays a plain list. */
.ft__legal a + a::before{content:"";display:inline-block;width:3px;height:3px;
  border-radius:50%;background:#B65A50;margin:0 14px;vertical-align:middle;
  transform:translateY(-1px)}

/* ── Newsletter ──────────────────────────────────────
   Class names come from the live markup because newsletter.js binds to them;
   only the appearance is new. Field and button share one rounded shell so the
   pair reads as a single control. */
.ft__nlh{margin:18px 0 10px!important;padding-bottom:0!important;
  font-family:var(--display)!important;font-size:1rem!important;
  font-weight:800!important;letter-spacing:-.02em!important;
  text-transform:none!important;color:#fff!important}
.ft__nlh::after{display:none!important}
.ft__nl{max-width:380px}
.ft__nlrow{display:flex;align-items:stretch;padding:4px;
  background:rgba(255,255,255,.08);border:1px solid rgba(255,255,255,.24);
  border-radius:999px;overflow:hidden;
  transition:border-color .26s var(--ease),background .26s var(--ease)}
.ft__nlrow:focus-within{border-color:#D98A7F;background:rgba(255,255,255,.12)}
.ft__nlrow .input{flex:1 1 auto;min-width:0}
.ft__nl .hs-input{width:100%;height:44px;padding:0 4px 0 16px;
  background:none;border:0;color:#fff;font:inherit;font-size:.92rem}
.ft__nl .hs-input::placeholder{color:#BFAEA9}
.ft__nl .hs-input:focus{outline:none}
.ft__nl .hs_submit{flex:none;display:flex}
.ft__nl .hs-button{height:44px;padding:0 22px;border:0;cursor:pointer;
  background:linear-gradient(176deg,#8A342D,var(--brand));color:#fff;
  font:inherit;font-size:.88rem;font-weight:800;border-radius:999px;
  box-shadow:inset 0 1px 0 rgba(255,255,255,.18);
  transition:filter .24s var(--ease)}
.ft__nl .hs-button:hover{filter:brightness(1.15)}
.ft__nl .hs-button:focus-visible{outline:2px solid #F0DCD8;outline-offset:2px}
/* Honeypot: unreachable and invisible, but NOT display:none - some bots skip
   hidden fields, which would defeat the check. */
.spl-hp{position:absolute;left:-9999px;width:1px;height:1px;overflow:hidden}
.spl-newsletter-status{margin-top:10px;font-size:.84rem;color:#E6D8D4;min-height:1.2em}
.spl-newsletter-fallback{font-size:.86rem;color:#E6D8D4}
/* CCPA control: a button because it reopens the consent banner, styled to
   sit in the link column without looking like a form control. */
.ft__ccpa{padding:0;margin:0;background:none;border:0;cursor:pointer;
  font:inherit;text-align:left}

/* ── Back to top ─────────────────────────────────────
   Fixed, hidden until a viewport has been scrolled. */
.totop{position:fixed;right:clamp(14px,2.4vw,28px);
  bottom:calc(clamp(14px,2.4vw,28px) + env(safe-area-inset-bottom));
  z-index:80;display:grid;place-items:center;width:46px;height:46px;
  padding:0;border-radius:50%;cursor:pointer;
  background:var(--brand);border:1px solid rgba(255,255,255,.2);color:#fff;
  box-shadow:var(--lift-2);
  opacity:0;visibility:hidden;transform:translateY(10px) scale(.9);
  transition:opacity .3s var(--ease),transform .3s var(--ease),
    visibility .3s,background .24s var(--ease)}
.totop.show{opacity:1;visibility:visible;transform:none}
.totop:hover{background:var(--brand-2)}
.totop svg{width:19px;height:19px}
@media print{.totop{display:none}}

/* ---- 5. Wordmark ----
   Tone-on-tone and built into the ground, after the user's reference: the
   firm's name very large, a pale rose barely lifted off the dark footer,
   clear at the top of the letters and DISSOLVING toward the bottom - the
   base of the word fades to nothing instead of being cut by the edge. It
   runs slightly past both sides, which is what makes it read as ground
   rather than as a heading.
   .ft__mf: a warm light that moves through the letters with the cursor
   (StringCursor --x/--y); without the cursor layer it is not shown.
   Decorative only. */
.ft__mark{position:relative;display:grid;margin-top:clamp(8px,1.6vw,22px);
  overflow:hidden;line-height:0;
  -webkit-user-select:none;user-select:none;
  /* The dissolve: solid through the upper letters, gone by the base. */
  -webkit-mask-image:linear-gradient(180deg,#000 0%,#000 38%,rgba(0,0,0,.45) 66%,transparent 94%);
  mask-image:linear-gradient(180deg,#000 0%,#000 38%,rgba(0,0,0,.45) 66%,transparent 94%)}
.ft__mark span{grid-area:1 / 1;display:block;white-space:nowrap;text-align:center;
  font-family:var(--display);font-weight:800;letter-spacing:-.045em;line-height:.9;
  /* A touch wider than the viewport, centred, so the first and last
     letters run just past the edges on both sides (a centred line cannot
     overflow evenly on its own: widen the box and offset by half). */
  width:120%;margin-left:-10%;
  /* ~20px past each edge at 1440: a sliver, as in the reference. */
  font-size:14vw;
  color:transparent;-webkit-background-clip:text;background-clip:text}
.ft__mark b{font-weight:800}
/* Pale rose on the dark ground - lifted just enough to read. */
.ft__mo{background-image:linear-gradient(180deg,
    rgba(246,214,206,.30) 0%,
    rgba(226,170,160,.22) 55%,
    rgba(200,130,118,.12) 100%)}
.ft__mf{opacity:0;
  background-image:radial-gradient(circle 16vw at calc(50% + var(--x,0) * 50%) calc(50% + var(--y,0) * 50%),
    rgba(255,232,224,.5) 0%,rgba(230,160,148,.2) 40%,rgba(230,160,148,0) 72%);
  transition:opacity .6s var(--ease)}
html.st-cursor .ft__mark:hover .ft__mf{opacity:1}

@media(prefers-reduced-motion:reduce){
  .ft__links a,.ft__ccpa,.ft__soc a,.ft__card,.ft__cic{transition:none}
}
/* ── motion: IntersectionObserver reveal, no library ── */
/* Reveal guard. GSAP owns opacity and transform on these elements once the
   motion layer boots, so there is deliberately NO transition here: a CSS
   transition on the same properties fights every tween frame for frame.
   The .in class is still applied (by GSAP's onStart, or wholesale on the
   reduced-motion path) so the page is correct if scripting never runs. */
/* Hidden only when the motion layer will run. .mo-pre is set by a blocking
   script in the layout head, so this applies from the first paint instead of
   after JS boots - which is what caused the visible-then-hidden jump. */
html.mo-pre [data-rv]{opacity:0}
[data-rv].in{opacity:1}
/* No-JS fallback: without the motion layer nothing would ever add .in, so
   reveal everything as soon as the document is parsed. */
html.mo-pre:not(.motion-on) [data-rv]{
  animation:rv-fallback .01s linear 2.5s forwards}
@keyframes rv-fallback{to{opacity:1}}
html.motion-off [data-rv]{opacity:1}
/* Kinetic headings. The mask clips each glyph so it rises out of the line
   rather than fading in place. Spans are generated in JS; the source heading
   keeps its plain text for crawlers, and carries aria-label after splitting. */
[data-kinetic]{overflow:hidden}
.kw{display:inline-block;white-space:nowrap}
.km{display:inline-block;overflow:hidden;vertical-align:top;
  /* Descenders (y g j p q) clip against a tight mask, so give the box room. */
  padding-bottom:.12em;margin-bottom:-.12em}
.kc{display:inline-block;will-change:transform}
@media(prefers-reduced-motion:reduce){
  html{scroll-behavior:auto}
  [data-rv]{opacity:1!important;transform:none!important;transition:none!important}
  .cta,.cta-2,.why__i,.sg__i,.ft__soc a{transition:none}
}
/* ============================================================
   MEDIA HERO - one system, shared by every page with a video or
   image hero. Replaces three near-identical per-page heroes
   (.sh / .eh / .nh) that had drifted apart: heights ranged
   64-85vh, h1 sizes 54-70px, and only some carried an eyebrow.

   THE PROBLEM THIS FIXES
   Measured before: 44-49% of each hero was empty image on the
   right, under a flat scrim that dimmed the whole frame evenly.
   The footage was muddied everywhere and carried nothing.

   THE FIX
   1. A DIRECTIONAL scrim: heavy on the left where the copy sits,
      clearing toward the right so the footage is actually visible
      where it has something to show.
   2. A meta rail occupying the right side, so the space carries
      information instead of reading as an unfinished crop.
   ============================================================ */
.mh{position:relative;isolation:isolate;overflow:hidden;
  /* ONE hero on every page: the full first screen. */
  min-height:clamp(600px,100svh,1000px);display:flex;align-items:center;
  /* Paper shows round the footage as the frame draws in on scroll. */
  background:var(--paper)}
/* The footage layer: video, scrim, grid and light together. It fills the
   hero edge to edge at all times - an earlier clip-path open/draw-in
   exposed the page behind at the sides and read as a rendering fault.
   GSAP gives it a short focus pull on load instead (scale + blur). */
.mh__media{position:absolute;inset:0;z-index:-1;overflow:hidden;background:#1e0c0a}
/* Pre-paint: start soft, so the focus pull never flashes sharp first.
   Filter only - GSAP owns the transform. */
html.mo-pre .mh:not(.mh--light) .mh__media{filter:blur(12px)}
/* --x/--y (StringTune cursor, -1..1) pan the footage a few px; the 3%
   bleed keeps the edges covered. `translate`, so GSAP's scroll transform on
   the video below never competes. */
.mh__pan{position:absolute;inset:-3%;
  translate:calc(var(--x,0) * -14px) calc(var(--y,0) * -10px)}
.mh__v,.mh__img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover}
/* A soft light where the pointer is. */
.mh__lamp{position:absolute;inset:0;pointer-events:none;opacity:0;mix-blend-mode:screen;
  background:radial-gradient(circle 32vw at calc(50% + var(--x,0) * 50%) calc(50% + var(--y,0) * 50%),
    rgba(255,226,212,.15) 0%,rgba(255,226,212,.05) 40%,rgba(255,226,212,0) 70%);
  transition:opacity .6s ease}
html.st-cursor .mh:hover .mh__lamp{opacity:1}
/* The secondary button is styled for paper; over footage it needs a light
   outline and white text (it measured as dark red on the dark scrim). */
.mh:not(.mh--light):not(.mh--glass) .cta-2{color:#fff;border-color:rgba(255,255,255,.55);
  background:rgba(255,255,255,.06);
  -webkit-backdrop-filter:blur(8px);backdrop-filter:blur(8px)}
.mh:not(.mh--light):not(.mh--glass) .cta-2:hover{color:#fff;border-color:#fff;background:rgba(255,255,255,.14)}
/* Magnetic CTAs (tagged by hero-motion.js on desktop). */
html.st-cursor .mh [string="magnetic"]{
  translate:calc(var(--magnetic-x,0) * 1px) calc(var(--magnetic-y,0) * 1px)}
/* Scroll cue. */
.mh__cue{position:absolute;left:50%;bottom:22px;z-index:1;translate:-50% 0;
  width:1px;height:46px;background:rgba(255,255,255,.25);overflow:hidden;pointer-events:none}
.mh__cue i{position:absolute;left:0;top:0;width:1px;height:16px;background:#fff;
  animation:mh-cue 2.2s cubic-bezier(.65,0,.35,1) infinite}
@keyframes mh-cue{0%{transform:translateY(-16px)}100%{transform:translateY(46px)}}
@media(max-width:759px),(max-height:620px){.mh__cue{display:none}}
@media(prefers-reduced-motion:reduce){.mh__cue i{animation:none}}
/* Directional scrim. The left third is nearly opaque so type always has a
   ground; the right clears to a light tint so the footage reads. */
.mh__scrim{position:absolute;inset:0;
  background:
    /* 1. A SPOTLIGHT behind the copy: the type sits in its own pool of
          shade, so it stays readable without darkening the whole frame.
          The old scrim opened at rgba(20,9,8,.92) and crushed 48% of the
          hero below 0.02 luminance - a black sheet over a video. */
    radial-gradient(52% 78% at 20% 50%,
      rgba(16,7,6,.80) 0%,
      rgba(18,8,7,.56) 46%,
      rgba(22,10,9,.22) 74%,
      transparent 100%),
    /* 2. A gentle left-to-right fall, far lighter than before, so the
          footage on the right keeps its detail. */
    linear-gradient(95deg,
      rgba(18,8,7,.40) 0%,
      rgba(22,10,9,.22) 40%,
      rgba(30,14,12,.10) 70%,
      transparent 100%),
    /* 3. A brand-tinted VIGNETTE that frames the image instead of
          flooding it - dark at the corners, clear through the middle. */
    radial-gradient(125% 125% at 50% 45%,
      transparent 46%,
      rgba(42,18,15,.22) 80%,
      rgba(26,11,9,.44) 100%),
    /* 4. A low warm wash ties the footage to the palette. */
    linear-gradient(0deg,rgba(90,31,27,.16),rgba(90,31,27,.16))}

/* AMBIENT MESH. Two slow brand blooms drifting behind the copy, so the hero
   breathes instead of sitting still. Transform/opacity only - compositor
   work, never layout. */
/* ---- CLOSING SECTION -------------------------------------------------
   .fin was redefined in SIX page stylesheets (home, services, eb1a, eb2,
   o1a, e1e2), differing only in trivia - 20ch vs 22ch vs 24ch, 7.5vw vs
   8.5vw. Every new page had to remember to restate it, and the
   extraordinary-ability page did not: its closing section rendered with no
   paper ground and no centring at all, because nothing defined .fin.

   Owned here once. The markup varies slightly across pages - some wrap the
   content in .fin__in, some do not - so both shapes are supported. */
.fin{background:var(--paper-2);border-top:1px solid var(--line);
  padding-block:clamp(62px,8.5vw,110px);text-align:center}
.fin__in{max-width:76ch;margin-inline:auto}
.fin .h-sec{max-width:24ch;margin-inline:auto}
.fin p{margin:18px auto 0;max-width:66ch;color:var(--ink-2);
  font-size:1.02rem;line-height:1.72}
.fin__b{margin-top:30px;display:flex;flex-wrap:wrap;justify-content:center}
/* On a phone the two closing buttons go full width and stack, rather than
   sitting as two short pills on one line. Five page sheets each carried
   their own copy of this. */
@media(max-width:679px){
  .fin__b{flex-direction:column;align-items:stretch}
  .fin__b .cta,.fin__b .cta-2{width:100%}
}

/* Visually hidden, still read aloud. The v2 pages do not load
   fontawesome.min.css, which was the only place .sr-only was defined - so a
   <caption class="sr-only"> rendered as visible text above a table. */
.sr-only{position:absolute!important;width:1px;height:1px;padding:0;margin:-1px;
  overflow:hidden;clip:rect(0,0,0,0);clip-path:inset(50%);white-space:nowrap;
  border:0}

/* ============================================================
   GLASS HERO - .mh--glass
   The light hero, kept CRISP: the copy sits on clean, near-solid paper on
   the left; the page's own footage plays sharp and in full colour on the
   right, fading into the paper between them; the card over the footage is
   a dense frosted white. (A first version laid a milky wash and a blur over
   the whole frame - it read as washed-out and out of focus.)
   ============================================================ */
.mh--glass{background:var(--paper)}
.mh--glass .mh__media{background:var(--paper)}
.mh--glass .mh__scrim{background:
    radial-gradient(46% 60% at 10% 30%,rgba(222,150,138,.16) 0%,rgba(222,150,138,0) 70%),
    linear-gradient(90deg,
      var(--paper) 0%,var(--paper) 38%,
      rgba(247,244,239,.92) 46%,rgba(247,244,239,.55) 56%,
      rgba(247,244,239,.12) 68%,rgba(247,244,239,0) 78%)}
.mh--glass .mh__scrim::before{display:none}
/* A CLEAN bottom edge: no fade into the next section (a dissolve read as
   the hero and the page mixing). The base sheet's ::after (ink foot and a
   one-time light sweep) is switched off; a hairline marks the boundary. */
.mh--glass .mh__scrim::after{display:none}
.mh--glass{border-bottom:1px solid var(--line-2)}
.mh--glass .mh__grid{opacity:1;
  background-image:linear-gradient(rgba(90,31,27,.045) 1px,transparent 1px),
    linear-gradient(90deg,rgba(90,31,27,.045) 1px,transparent 1px);
  -webkit-mask-image:linear-gradient(90deg,#000 0%,#000 40%,transparent 62%);
  mask-image:linear-gradient(90deg,#000 0%,#000 40%,transparent 62%)}
.mh--glass .mh__eyebrow{color:var(--brand)}
.mh--glass .mh__t{color:var(--ink)}
.mh--glass .mh__ln:last-child>span{color:var(--brand)}
.mh--glass .mh__l{color:#4A3833}
/* The card: dense frosted white over the sharp footage. */
.mh--glass .mh__meta{
  background:rgba(255,255,255,.86);
  -webkit-backdrop-filter:blur(14px) saturate(150%);backdrop-filter:blur(14px) saturate(150%);
  border:1px solid rgba(255,255,255,.95);
  box-shadow:0 40px 80px -40px rgba(36,19,16,.45),0 10px 24px -14px rgba(36,19,16,.2)}
.mh--glass .mh__meta li{border-top-color:rgba(90,31,27,.1)}
.mh--glass .mh__meta b{color:var(--ink)}
.mh--glass .mh__meta span{color:#5E4C46}
.mh--glass .mh__meta li::before{background:var(--brand);box-shadow:0 0 0 4px rgba(124,46,40,.14)}
/* Pointer light: a warm blush on the paper (screen would vanish on light). */
.mh--glass .mh__lamp{mix-blend-mode:normal;
  background:radial-gradient(circle 26vw at calc(50% + var(--x,0) * 50%) calc(50% + var(--y,0) * 50%),
    rgba(214,140,128,.12) 0%,rgba(214,140,128,.04) 45%,rgba(214,140,128,0) 72%)}
.mh--glass .mh__cue{background:rgba(90,31,27,.18)}
.mh--glass .mh__cue i{background:var(--brand)}
/* Below 960px the copy spans the width, so the footage sits behind text:
   a stronger, even paper veil keeps it readable there. */
@media(max-width:959px){
  .mh--glass .mh__scrim{background:
    linear-gradient(180deg,rgba(247,244,239,.86) 0%,rgba(247,244,239,.9) 100%)}
}

/* ---- BRIGHT FOOTAGE ---------------------------------------------------
   The scrim above is tuned for dark video. Over pale footage - documents,
   snow, sky, a white studio - its brightest regions punch through: measured
   1.34 against the white headline on the extraordinary-ability video, while
   the AVERAGE over the same area was 9.11. Averages hide this; the floor is
   what legibility depends on.

   So this deepens the copy-side pool and adds a flat base tint, rather than
   darkening the shared scrim and crushing the four heroes that do not need
   it. Opt in with brightMedia on <MediaHero>. */
.mh--bright .mh__scrim{
  background:
    radial-gradient(64% 92% at 22% 50%,
      rgba(14,6,5,.92) 0%,
      rgba(16,7,6,.78) 42%,
      rgba(20,9,8,.46) 72%,
      rgba(22,10,9,.20) 100%),
    linear-gradient(95deg,
      rgba(16,7,6,.62) 0%,
      rgba(18,8,7,.38) 46%,
      rgba(20,9,8,.20) 100%),
    /* A flat floor across the whole frame. This is the layer that actually
       raises the WORST pixel, which the radial gradients alone cannot do. */
    linear-gradient(0deg,rgba(18,8,7,.34),rgba(18,8,7,.34))}

.mh__scrim::before{content:"";position:absolute;inset:-25%;
  pointer-events:none;
  background:
    radial-gradient(30% 34% at 26% 34%,rgba(201,145,137,.20),transparent 64%),
    radial-gradient(26% 30% at 74% 66%,rgba(154,86,68,.24),transparent 66%);
  animation:mh-mesh 34s ease-in-out infinite alternate;
  will-change:transform}
@keyframes mh-mesh{
  from{transform:translate3d(-2.5%,-1.5%,0) scale(1)}
  to{transform:translate3d(2.5%,1.5%,0) scale(1.08)}
}

/* A light sweep that crosses the hero once on load - the "premium" cue,
   used sparingly: it runs a single time, not on a loop. */
.mh__scrim::after{content:"";position:absolute;top:-50%;bottom:-50%;left:-40%;
  width:36%;pointer-events:none;
  background:linear-gradient(90deg,
    transparent,rgba(255,255,255,.055) 45%,rgba(255,255,255,.085) 50%,
    rgba(255,255,255,.055) 55%,transparent);
  transform:translateX(0) skewX(-14deg);
  animation:mh-sweep 2.6s cubic-bezier(.22,.61,.36,1) .35s 1 both}
@keyframes mh-sweep{
  from{transform:translateX(0) skewX(-14deg)}
  to{transform:translateX(420%) skewX(-14deg)}
}

@media(prefers-reduced-motion:reduce){
  .mh__scrim::before,.mh__scrim::after{animation:none}
  .mh__scrim::after{display:none}
}
/* A short ink foot so the section boundary is never a hard cut. */
.mh__scrim::after{content:"";position:absolute;inset:auto 0 0;height:34%;
  background:linear-gradient(180deg,transparent,rgba(16,7,6,.72))}
/* Drafting grid, the same language as the index hero, at very low contrast. */
/* Drafting grid + a drifting particle field, the same language the dark
   band uses, so hero and band read as one system. */
.mh__grid{position:absolute;inset:0;pointer-events:none;opacity:.5;
  animation:mh-grid 46s linear infinite;will-change:transform;
  background-image:
    linear-gradient(rgba(255,255,255,.055) 1px,transparent 1px),
    linear-gradient(90deg,rgba(255,255,255,.055) 1px,transparent 1px);
  background-size:clamp(56px,7vw,96px) clamp(56px,7vw,96px);
  -webkit-mask-image:linear-gradient(100deg,transparent 30%,#000 100%);
  mask-image:linear-gradient(100deg,transparent 30%,#000 100%)}
.mh__in{position:relative;z-index:1;width:100%;
  padding-top:calc(var(--header-h,72px) + env(safe-area-inset-top) + clamp(28px,4.5vh,54px));
  padding-bottom:clamp(40px,6vh,72px);
  display:grid;gap:clamp(28px,4vw,56px);align-items:center}
/* Eyebrow, on ink. Every media hero carries one now; three of five did not. */
.mh__eyebrow{display:inline-block;margin:0 0 16px;
  font-family:var(--mono);font-size:.68rem;font-weight:700;letter-spacing:.22em;
  text-transform:uppercase;color:#E8CFC9}
/* NO ch cap. 17ch resolved to 603px inside a 635px column, so the two
   authored lines re-wrapped into four ragged ones (237/357/298/302px).
   The headline may use its whole column; `balance` evens the rag, and the
   authored line breaks do the rest. */
.mh__t{margin:0;color:#fff;font-weight:900;letter-spacing:-.042em;
  line-height:1.06;font-size:clamp(2rem,4.2vw,3.45rem);
  text-wrap:balance}
/* NO nowrap here. Forcing it clipped the longer headlines (eb1a needs 872px
   in a 635px column). The hero grid gives the copy column more room instead,
   which is what actually fixes the rag. */
/* Each line is its own clipped mask. TRANSFORM IS OWNED BY THE MOTION LAYER -
   setting it here too left a headline pinned below its mask on services. */
.mh__ln{display:block;overflow:hidden;padding-bottom:.09em;margin-bottom:-.09em}
.mh__ln>span{display:block}
html.mo-pre .mh__ln>span{opacity:0}
.mh__l{margin:20px 0 0;max-width:52ch;color:rgba(255,255,255,.9);
  font-size:clamp(1rem,1.3vw,1.1rem);line-height:1.72}
.mh__b{margin-top:30px;display:flex;flex-wrap:wrap;gap:12px}
@media(max-width:679px){.mh__b .cta,.mh__b .cta-2{width:100%;justify-content:center}}
/* ---- The meta rail: what fills the dead 45% ----
   Real facts about the page's subject, set as a filed index. It earns the
   space the crop used to waste, and it gives the eye a second landing
   point instead of one wall of type. */
.mh__meta{display:none;margin:0;padding:clamp(16px,1.6vw,22px) clamp(18px,1.8vw,26px);
  list-style:none;
  /* Its own ground. Without this the labels measured 2.68-3.25:1 over the
     bright part of the footage - the scrim clears here by design, so the
     panel has to carry the contrast itself. */
  background:linear-gradient(135deg,rgba(18,8,7,.80),rgba(26,12,10,.68));
  border:1px solid rgba(255,255,255,.14);border-radius:var(--r-lg);
  backdrop-filter:blur(14px) saturate(140%);
  -webkit-backdrop-filter:blur(14px) saturate(140%);
  box-shadow:0 18px 50px -24px rgba(0,0,0,.7)}
.mh__meta li{position:relative;padding:14px 0 14px 22px;
  border-top:1px solid rgba(255,255,255,.13)}
.mh__meta li:first-child{border-top:0;padding-top:4px}
.mh__meta li:last-child{padding-bottom:4px}
.mh__meta li::before{content:"";position:absolute;left:0;top:calc(50% - 3px);
  width:6px;height:6px;border-radius:50%;background:var(--brand-2);
  box-shadow:0 0 0 4px rgba(124,46,40,.28)}
.mh__meta b{display:block;font-size:.98rem;font-weight:800;letter-spacing:-.02em;
  color:#fff;line-height:1.3}
.mh__meta span{display:block;margin-top:3px;font-family:var(--mono);
  font-size:.66rem;letter-spacing:.14em;text-transform:uppercase;
  color:#D8C3BE}
/* A page's own right-column content (the "aside" slot). Same rule as the
   meta rail: hidden below 960px so it never pushes the CTA off a phone.
   This base rule MUST come before the 960px media query below - placed
   after it, it overrode the query at every width and the column had zero
   size on desktop. */
.mh__aside{display:none;min-width:0}
html.mo-pre .mh__meta li,html.mo-pre .mh__aside{opacity:0}
@media(min-width:960px){
  /* The copy column leads. It was 7fr (635px at 1440), which forced the
     longer headlines into four ragged lines; 8fr gives them the width they
     were written for while the rail keeps its own readable panel. */
  .mh__in{grid-template-columns:minmax(0,8fr) minmax(0,4.6fr)}
  .mh__meta{display:block}
  .mh__aside{display:block}
}
/* Below 960px the rail is hidden rather than stacked: on a phone it would
   push the CTA below the fold, and the copy alone fills the frame. */


/* ── DEV ONLY: unported links ─────────────────────────
   data-todo is emitted by SiteNav/SiteFooter only while running `astro dev`
   (see src/lib/links.ts). It marks a link whose page has no Astro version
   yet, so a local 404 is visibly expected rather than a mystery. The
   attribute is absent from every production build, so these rules never
   match there. */
/* No dimming: a half-opacity link read as broken to reviewers. The marker
   dot appears on hover only, as a quiet "not ported yet" hint for devs. */
[data-todo]{position:relative}
[data-todo]::after{content:"";position:absolute;right:-9px;top:50%;
  translate:0 -50%;width:5px;height:5px;border-radius:50%;
  background:#C0894F;opacity:0;transition:opacity .2s}
[data-todo]:hover::after{opacity:.85}
.nv__panel [data-todo]::after,.ft__links [data-todo]::after{right:-12px}


/* ============================================================
   DARK BAND - the one dark section treatment.

   Six pages each hand-wrote their own near-black gradient. This is the
   single definition: a lighter warm brown, plus a slow ambient
   illustration so the band has life instead of being a flat slab.

   Everything decorative here is behind the content and pointer-events
   none, and all of it stops under prefers-reduced-motion.
   ============================================================ */
/* overflow:clip, not just hidden. An overflow:hidden box is still
   programmatically SCROLLABLE: scrollIntoView, keyboard focus and #anchor
   jumps scroll it internally. On the attorneys page that slid the team
   groups ~1,485px up inside the band, hiding cards under the section above.
   clip draws identically but cannot scroll. hidden stays first as the
   fallback for browsers without clip. */
.band{position:relative;isolation:isolate;overflow:hidden;overflow:clip;color:#fff;
  background:
    radial-gradient(130% 100% at 50% 0%,var(--band-1) 0%,transparent 62%),
    linear-gradient(168deg,var(--band-2) 0%,var(--band-deep) 100%)}

/* Drafting grid - the same language the hero uses, at low contrast so it
   reads as paper texture rather than a pattern. */
.band::before{content:"";position:absolute;inset:0;z-index:0;
  pointer-events:none;opacity:.5;
  background-image:
    linear-gradient(rgba(255,255,255,.05) 1px,transparent 1px),
    linear-gradient(90deg,rgba(255,255,255,.05) 1px,transparent 1px);
  background-size:clamp(56px,7vw,96px) clamp(56px,7vw,96px);
  -webkit-mask-image:radial-gradient(120% 90% at 50% 0%,#000 25%,transparent 78%);
  mask-image:radial-gradient(120% 90% at 50% 0%,#000 25%,transparent 78%)}

/* MESH GRADIENT. Three offset blooms on one layer, drifting and breathing
   together - the soft colour-field look, with no canvas and no library.
   Transform and opacity only, so it never triggers layout. */
.band::after{content:"";position:absolute;inset:-30%;z-index:0;
  pointer-events:none;
  background:
    radial-gradient(34% 38% at 20% 26%,var(--band-glow),transparent 64%),
    radial-gradient(30% 34% at 80% 70%,rgba(154,86,68,.34),transparent 66%),
    radial-gradient(26% 30% at 62% 18%,rgba(90,31,27,.30),transparent 62%);
  animation:band-mesh 30s ease-in-out infinite alternate;
  will-change:transform}
@keyframes band-mesh{
  from{transform:translate3d(-3%,-2%,0) scale(1) rotate(0deg)}
  to{transform:translate3d(3%,2%,0) scale(1.09) rotate(4deg)}
}

/* PARTICLE FIELD. A dot grid, masked to fade toward the centre so it never
   competes with the copy, drifting slowly across the band. One element, one
   transform - far cheaper than a canvas of real particles. */
.band__dots{position:absolute;top:-60px;right:-60px;bottom:-60px;left:-60px;
  z-index:0;pointer-events:none;
  opacity:.5;
  background-image:radial-gradient(rgba(240,220,216,.5) 1px,transparent 1px);
  background-size:26px 26px;
  -webkit-mask-image:
    radial-gradient(60% 55% at 50% 50%,transparent 20%,#000 78%),
    linear-gradient(180deg,#000,transparent 92%);
  mask-image:
    radial-gradient(60% 55% at 50% 50%,transparent 20%,#000 78%),
    linear-gradient(180deg,#000,transparent 92%);
  -webkit-mask-composite:source-in;mask-composite:intersect;
  animation:band-dots 38s linear infinite;
  will-change:transform}
@keyframes band-dots{
  from{transform:translate3d(0,0,0)}
  to{transform:translate3d(26px,-26px,0)}
}

/* Content sits above the decoration. The dots layer is excluded: this rule
   matched it too and turned an absolutely-positioned layer into a relative
   one with zero height, so it painted nothing (measured dotsH:0). */
.band > *:not(.band__dots){position:relative;z-index:1}

/* A hairline in brand oxblood across the top edge, so the band starts on a
   drawn line rather than a colour jump. */
.band{border-top:1px solid rgba(255,255,255,.1)}

/* ---- TYPE ON A BAND -------------------------------------------------
   Generic defaults so ANY section can be dropped onto .band and read
   correctly, instead of each page restating white-on-dark for its own
   class names. Before this, home redefined the whole dark ground under
   .sec--tint and About had no band at all, so the three visa pages, home
   and About each expressed "dark section" differently.

   These are defaults only - a page that needs a different treatment still
   overrides it, because a page stylesheet loads after this one. */
/* Scoped so a LIGHT card sitting on a band is not repainted white-on-white.
   Measured: .cmt__h inside the light commitment panel came out at contrast
   1.0 - invisible - because `.band p` reached into it. Anything inside an
   element marked .on-paper opts out of the whole set. */
.band .eyebrow:not(.on-paper *){color:#E8CFC9}
.band :is(.h-sec,.h-card,h2,h3):not(.on-paper *){color:#fff}
.band :is(.lead,.body,p):not(.on-paper *){color:rgba(255,255,255,.84)}

/* Rules and hairlines invert with the ground. */
.band .idx{border-top-color:rgba(255,255,255,.16)}
.band .idx__row{border-bottom-color:rgba(255,255,255,.16)}
/* The light-ground hover filled the row with white, which on a dark band
   turned the whole row into a white plate. */
.band .idx__row:hover{background:rgba(255,255,255,.05)}
.band .idx__n{color:#E8CFC9;opacity:.75}

@media(prefers-reduced-motion:reduce){
  .band::after,.band__dots{animation:none}
}
/* The field is decoration and costs a repaint on every frame. Phones skip
   it; the mesh alone still gives the band depth. */
@media(max-width:700px){.band__dots{display:none}}


/* The hero grid drifts very slowly - enough to feel alive, slow enough that
   it is never the thing you look at. */
@keyframes mh-grid{
  from{transform:translate3d(0,0,0)}
  to{transform:translate3d(clamp(56px,7vw,96px),clamp(56px,7vw,96px),0)}
}
@media(prefers-reduced-motion:reduce){.mh__grid{animation:none}}


/* ============================================================
   LIGHT HERO - .mh--light
   Same component and geometry as the dark hero, on a paper ground.
   No video: the footage was decorative (it appears nowhere in the source
   copy), and under a scrim it crushed ~48% of the frame to near-black.
   On paper the type leads and the decoration can be delicate.
   ============================================================ */
.mh--light{background:
  radial-gradient(58% 46% at 26% 36%,var(--white) 0%,transparent 66%),
  linear-gradient(168deg,var(--paper) 0%,var(--paper-2) 100%);
  border-bottom:1px solid var(--line)}
/* The video and its scrim are not used in this variant. */
.mh--light .mh__v,
.mh--light .mh__img,
.mh--light .mh__scrim,
.mh--light .mh__lamp,
.mh--light .mh__cue{display:none}
.mh--light .mh__media{background:transparent}

/* Ink flips to the page palette. */
.mh--light .mh__eyebrow{color:var(--brand)}
.mh--light .mh__t{color:var(--ink)}
.mh--light .mh__l{color:var(--ink-2)}

/* Drafting grid in ink rather than white. */
.mh--light .mh__grid{opacity:1;
  background-image:
    linear-gradient(rgba(90,31,27,.055) 1px,transparent 1px),
    linear-gradient(90deg,rgba(90,31,27,.055) 1px,transparent 1px);
  -webkit-mask-image:linear-gradient(115deg,#000 8%,transparent 62%);
  mask-image:linear-gradient(115deg,#000 8%,transparent 62%)}

/* CURSOR-REACTIVE GLOW. A soft brand bloom that follows the pointer, eased
   so it trails rather than snapping. --mx/--my are written by hero-motion.js
   on a rAF, never on the event, so a fast mouse cannot flood the main thread.
   Desktop + fine pointer only; it is decoration, not information. */
.mh--light .mh__aura{position:absolute;inset:0;z-index:0;pointer-events:none;
  opacity:0;transition:opacity .5s var(--ease);
  background:radial-gradient(
    clamp(240px,26vw,420px) clamp(240px,26vw,420px) at var(--mx,50%) var(--my,40%),
    rgba(154,86,68,.16) 0%,
    rgba(201,145,137,.10) 40%,
    transparent 72%)}
.mh--light .mh__aura.is-live{opacity:1}
@media(hover:none),(pointer:coarse),(max-width:760px){
  .mh--light .mh__aura{display:none}
}

/* The meta rail becomes a paper card on the light ground. */
.mh--light .mh__meta{
  background:linear-gradient(168deg,var(--white),var(--paper));
  border:1px solid var(--line);
  backdrop-filter:none;-webkit-backdrop-filter:none;
  box-shadow:0 20px 50px -30px rgba(36,19,16,.4)}
.mh--light .mh__meta li{border-top-color:var(--line)}
.mh--light .mh__meta b{color:var(--ink)}
.mh--light .mh__meta span{color:var(--ink-2)}
.mh--light .mh__meta li::before{background:var(--brand);
  box-shadow:0 0 0 4px rgba(90,31,27,.10)}

/* Particle canvas sits behind everything. Hidden on touch and under
   reduced motion by the script, which never mounts it there. */
.mh--light .mh__dust{position:absolute;inset:0;z-index:0;pointer-events:none;
  opacity:0;transition:opacity 1.2s var(--ease)}
.mh--light .mh__dust.is-live{opacity:1}


/* ============================================================
   KINETIC SCROLL KIT (pages running StringTune's scroll layer:
   html.st-scroll, set by st-core.js - About and Services).
   ============================================================ */
/* Split headings (string="split" + class .kx): letters rise out of their
   word's mask once the heading is on screen (StringTune adds .-inview). */
html.st-scroll .kx .-s-word{display:inline-block;overflow:hidden;vertical-align:top;
  padding-bottom:.12em;margin-bottom:-.12em}
html.st-scroll .kx .-s-char{display:inline-block;transform:translateY(112%);
  transition:transform .8s cubic-bezier(.2,.8,.2,1);
  transition-delay:calc(var(--char-index,0) * 14ms)}
html.st-scroll .kx.-inview .-s-char{transform:none}
/* Plain reveals on scroll-layer pages (an IntersectionObserver adds .in).
   Scoped to .st-scroll: other pages reveal [data-rv] with GSAP, and a CSS
   transition here would fight those tweens. */
html.st-scroll [data-rv]{opacity:0;transform:translateY(18px);
  transition:opacity .7s ease,transform .8s cubic-bezier(.2,.8,.2,1)}
html.st-scroll [data-rv].in{opacity:1;transform:none}
/* Word-by-word scroll highlight (.wlit): words are split at build time
   (span.w with --wi; the paragraph carries --wt), StringProgress writes
   --progress on the paragraph. Each word lights from 16% to full as the
   reading point passes it while the paragraph crosses the screen. */
html.st-scroll .wlit .w{
  opacity:clamp(.16, calc((var(--progress,1) * 2.6 - .5) * var(--wt,1) - var(--wi,0)), 1)}

/* ======================================================================
   HERO PATHWAY NAVIGATOR (the glass hero's right column) - shared by
   every glass hero (Services, About ...). Each page fills it with its own
   real content.
   Three stacked tiles, one per service category: icon, title, the visa
   codes, an arrow. The first is the dark oxblood feature tile (the same
   accent the bento cards use site-wide); the others are dense frosted
   white over the footage. Each tile lights under the pointer (StringTune
   spotlight) and slides a little toward the cursor's side on hover.
   ====================================================================== */
.pnv ul{margin:0;padding:0;list-style:none;display:grid;gap:12px}
.pnv__a{position:relative;display:flex;align-items:center;gap:16px;
  padding:18px 20px;border-radius:20px;text-decoration:none;color:var(--ink);
  background:rgba(255,255,255,.88);
  -webkit-backdrop-filter:blur(14px) saturate(150%);backdrop-filter:blur(14px) saturate(150%);
  border:1px solid rgba(255,255,255,.95);
  box-shadow:0 24px 50px -30px rgba(36,19,16,.45),0 6px 16px -10px rgba(36,19,16,.18);
  transition:transform .35s cubic-bezier(.23,1,.32,1),box-shadow .35s ease}
@media(hover:hover) and (pointer:fine){
  .pnv__a:hover{transform:translateX(-6px);
    box-shadow:0 34px 60px -30px rgba(36,19,16,.55),0 8px 20px -10px rgba(36,19,16,.22)}
}
.pnv__a:active{transform:scale(.98)}
.pnv__a:focus-visible{outline:3px solid var(--brand);outline-offset:3px}
.pnv__ic{flex:none;display:grid;place-items:center;width:48px;height:48px;border-radius:14px;
  font-size:1.15rem;color:var(--brand);background:var(--brand-wash);
  border:1px solid rgba(90,31,27,.12);transition:rotate .35s cubic-bezier(.23,1,.32,1)}
.pnv__a:hover .pnv__ic{rotate:-6deg}
.pnv__txt{flex:1 1 auto;min-width:0;display:grid;gap:8px}
.pnv__t{font-weight:800;font-size:1rem;line-height:1.3;letter-spacing:-.015em}
.pnv__chips{display:flex;flex-wrap:wrap;gap:5px}
.pnv__chips span{font-family:var(--mono);font-size:.64rem;font-weight:700;letter-spacing:.06em;
  padding:3px 8px;border-radius:999px;color:var(--brand);
  background:var(--paper);border:1px solid var(--line-2)}
.pnv__go{flex:none;align-self:flex-start;font-size:.95rem;color:var(--brand);
  transition:transform .3s cubic-bezier(.23,1,.32,1)}
.pnv__a:hover .pnv__go{transform:translate(2px,-2px)}
/* The feature tile. */
.pnv__a--lead{color:#fff;border-color:transparent;
  background:radial-gradient(120% 90% at 100% 0%,rgba(182,90,80,.32) 0%,rgba(182,90,80,0) 60%),
    linear-gradient(160deg,var(--brand-2) 0%,var(--brand) 55%,#3E1411 100%);
  box-shadow:0 30px 60px -30px rgba(62,20,17,.7),inset 0 1px 0 rgba(255,255,255,.14)}
.pnv__a--lead .pnv__ic{color:#fff;background:rgba(255,255,255,.12);border-color:rgba(255,255,255,.22)}
.pnv__a--lead .pnv__chips span{color:#fff;background:rgba(255,255,255,.1);border-color:rgba(255,255,255,.28)}
.pnv__a--lead .pnv__go{color:#F0DCD8}
/* Stagger the tiles in after the hero copy (CSS only, once). */
html.mo-on .pnv li{opacity:0;animation:pnv-in .7s cubic-bezier(.23,1,.32,1) forwards;
  animation-delay:calc(.55s + var(--k,0) * .09s)}
@keyframes pnv-in{from{opacity:0;transform:translateX(22px)}to{opacity:1;transform:none}}
@media(prefers-reduced-motion:reduce){
  .pnv__a,.pnv__ic,.pnv__go{transition:none}
  html.mo-on .pnv li{opacity:1;animation:none}
}
/* A tile's small numbered label (About: "01 Specialty"). */
.pnv__tag{font-family:var(--mono);font-size:.66rem;font-weight:700;letter-spacing:.12em;
  text-transform:uppercase;color:var(--ink-2)}
.pnv__tag b{color:var(--brand);font-weight:800;margin-right:6px}
.pnv__a--lead .pnv__tag{color:rgba(255,255,255,.78)}
.pnv__a--lead .pnv__tag b{color:#F0DCD8}

/* ---- GLASS HERO ON PHONES + TABLETS (<960px) --------------------------
   A full-screen hero left a dead band of veiled footage above the headline
   and below the button. Here the hero sizes to its content, and the page's
   own tiles (the aside) come back as a compact list under the CTA, so the
   first screen carries real content instead of empty video. */
@media(max-width:959px){
  .mh--glass{min-height:0;align-items:flex-start}
  .mh--glass .mh__in{gap:28px;
    padding-top:calc(var(--header-h,72px) + env(safe-area-inset-top) + 32px);
    padding-bottom:40px}
  .mh--glass .mh__cue{display:none}
  .mh--glass .mh__aside{display:block}
  .mh--glass .pnv ul{gap:10px}
  .mh--glass .pnv__a{padding:14px 16px;gap:14px;border-radius:18px;
    box-shadow:0 14px 30px -22px rgba(36,19,16,.45)}
  .mh--glass .pnv__ic{width:42px;height:42px;border-radius:12px;font-size:1.05rem}
  .mh--glass .pnv__txt{gap:6px}
  .mh--glass .pnv__t{font-size:.98rem}
  .mh--glass .pnv__go{align-self:center}
}
@media(min-width:600px) and (max-width:959px){
  .mh--glass .pnv ul{grid-template-columns:1fr 1fr}
  .mh--glass .pnv__a{height:100%}
}
/* Phones: the tiles read heavy. No arrow (the whole tile is the link),
   tighter padding, a softer shadow, smaller icon and chips. */
@media(max-width:599px){
  .mh--glass .pnv__go{display:none}
  .mh--glass .pnv ul{gap:8px}
  .mh--glass .pnv__a{padding:11px 14px;gap:12px;border-radius:16px;
    box-shadow:0 8px 20px -16px rgba(36,19,16,.4)}
  .mh--glass .pnv__ic{width:36px;height:36px;border-radius:10px;font-size:.95rem}
  .mh--glass .pnv__txt{gap:5px}
  .mh--glass .pnv__t{font-size:.92rem}
  .mh--glass .pnv__chips{gap:4px}
  .mh--glass .pnv__chips span{font-size:.58rem;padding:3px 7px}
  .mh--glass .pnv__tag{font-size:.6rem}
}
/* Phones + tablets, final: no tiles in the hero (the same paths and
   differences follow right below it). Just headline, lead and CTA over the
   footage: the veil is near-solid behind the copy and opens toward the
   bottom, so the video shows clearly under the button. */
@media(max-width:959px){
  .mh--glass .mh__aside{display:none}
  .mh--glass .mh__in{padding-bottom:clamp(120px,22vw,180px)}
  .mh--glass .mh__scrim{background:linear-gradient(180deg,
    rgba(247,244,239,.92) 0%,rgba(247,244,239,.88) 45%,
    rgba(247,244,239,.6) 72%,rgba(247,244,239,.12) 100%)}
  .mh--glass .mh__grid{opacity:.35}
}

/* ---- TIGHTER RHYTHM on the kinetic pages (About, Services, Extraordinary
   Ability). Stacked decks, pinned sections and sticky headings already
   give these pages their pauses; full section padding on top of that read
   as heavy empty paper between sections. */
html.st-scroll .sec{padding-block:clamp(44px,5.5vw,80px)}
html.st-scroll .sko{padding-block:clamp(56px,6.5vw,96px)}
/* Only where these are NOT pinned (pinned, they own their own padding). */
@media(max-width:759px),(max-height:599px){
  .ska__sticky,.kcl__sticky{padding-block:clamp(44px,6vw,84px)}
}
html.st-scroll .fin{padding-block:clamp(52px,6vw,88px)}
/* After a stacked deck the cards already end the section; full bottom
   padding on top of that doubled the gap. */
html.st-scroll .skp,html.st-scroll .kd{padding-bottom:clamp(28px,3vw,44px)}
/* Kx headings: a word never breaks at its own hyphen ("E-" / "1/E-2"),
   with or without the motion layer. */
.kx .-s-word{white-space:nowrap}
/* The sand section tone (used by EEA, E-1/E-2 and siblings). */
.sec--sand{background:var(--paper-2,#EFE9E1);border-block:1px solid var(--line,#E4DACF)}

/* ======================================================================
   HERO RIGHT COLUMN - the constellation (MediaHero aside), hub and spokes.
   Component: src/components/v2/Constellation.astro; behaviour:
   src/scripts/constellation.js (aims the spokes, runs the spotlight).
   The firm's mark sits in a glass orb at the left, vertically centred, with
   rings and orbiting particles; the page's items form a column on the
   right, spaced evenly whatever their height or count (flex), on a gentle
   arc. A spoke runs from the orb to each badge, a light pulse travelling
   out along it. A spotlight steps through the badges (hover takes it).
   Depth WITHOUT 3D-tilting any text (a tilted layer rasterises text soft):
   the badges and the hub drift by different amounts toward the pointer
   (StringCursor --x/--y, -1..1) with flat `translate`.
   Hidden below 960px with the rest of the hero aside (shared rule).
   ====================================================================== */
.acn{position:relative;--ox:62px;--orb:104px}
.acn__stage{position:relative;display:flex;min-height:clamp(320px,calc(100svh - var(--header-h,73px) - 220px),420px)}
/* Spokes: a faint dashed line and a short bright dash that runs outward. */
.acn__lines{position:absolute;inset:0;width:100%;height:100%;overflow:visible;pointer-events:none}
.acn__ln,.acn__pulse{fill:none;vector-effect:non-scaling-stroke;stroke-linecap:round}
.acn__ln{stroke:rgba(255,255,255,.78);stroke-width:1.4;stroke-dasharray:3 6;filter:drop-shadow(0 0 2px rgba(62,20,17,.35));transition:stroke-width .4s ease}
.acn__pulse{stroke:#fff;stroke-width:3;stroke-dasharray:8 100;stroke-dashoffset:8;filter:drop-shadow(0 0 4px rgba(255,255,255,.9));
  animation:acn-run 3.2s cubic-bezier(.55,.1,.35,1) infinite;animation-delay:calc(var(--k,0) * .8s)}
@keyframes acn-run{to{stroke-dashoffset:-100}}
.acn__node{fill:#fff;stroke:var(--brand);stroke-width:.35;vector-effect:non-scaling-stroke;filter:drop-shadow(0 0 3px rgba(255,255,255,.9))}
/* The hub: glow, rings, particles and orb share one centre (left, middle)
   and drift a little AGAINST the pointer - the far layer of the depth. */
.acn__hub{position:absolute;left:var(--ox);top:50%;width:0;height:0;pointer-events:none;
  translate:calc(var(--x,0) * -10px) calc(var(--y,0) * -8px);transition:translate .6s cubic-bezier(.23,1,.32,1)}
.acn__glow{position:absolute;left:0;top:0;width:300px;height:300px;translate:-50% -50%;border-radius:50%;
  background:radial-gradient(closest-side,rgba(255,255,255,.4),rgba(240,220,216,.12) 55%,transparent);animation:acn-drift 9s ease-in-out infinite}
@keyframes acn-drift{50%{scale:1.1;opacity:.75}}
.acn__rings i{position:absolute;left:0;top:0;translate:-50% -50%;border-radius:50%}
.acn__rings i:nth-child(1){width:140px;height:140px;border:1px dashed rgba(255,255,255,.75);animation:acn-spin 40s linear infinite}
.acn__rings i:nth-child(2){width:200px;height:200px;border:1px solid rgba(255,255,255,.42)}
.acn__rings i:nth-child(3){width:260px;height:260px;border:1px dotted rgba(255,255,255,.55);animation:acn-spin 70s linear infinite reverse}
@keyframes acn-spin{to{rotate:1turn}}
.acn__sats i{position:absolute;left:0;top:0;animation:acn-spin var(--dur,12s) linear infinite;animation-delay:var(--d0,0s)}
.acn__sats i::after{content:"";position:absolute;left:var(--r,100px);top:-4px;width:8px;height:8px;border-radius:50%;
  background:#fff;box-shadow:0 0 10px 3px rgba(255,255,255,.8),0 0 2px 1px rgba(240,220,216,.9)}
.acn__orb{position:absolute;left:0;top:0;display:grid;place-items:center;width:var(--orb);height:var(--orb);translate:-50% -50%;border-radius:50%;
  background:linear-gradient(115deg,transparent 30%,rgba(255,255,255,.75) 45%,transparent 60%) 200% 0/250% 100% no-repeat,
    radial-gradient(circle at 30% 26%,#fff 0%,rgba(255,255,255,.86) 55%,rgba(243,232,229,.9) 100%);
  border:1px solid rgba(255,255,255,.95);-webkit-backdrop-filter:blur(12px);backdrop-filter:blur(12px);
  box-shadow:0 30px 60px -22px rgba(62,20,17,.55),0 0 0 10px rgba(255,255,255,.28);animation:acn-sheen 5s ease-in-out infinite}
@keyframes acn-sheen{0%,60%{background-position:200% 0,0 0}100%{background-position:-60% 0,0 0}}
.acn__orb::before{content:"";position:absolute;inset:-7px;border-radius:50%;
  background:conic-gradient(from 0deg,transparent 0 12%,#F0DCD8 22%,var(--brand-2) 34%,var(--brand) 42%,transparent 55% 100%);
  -webkit-mask:radial-gradient(farthest-side,transparent calc(100% - 4px),#000 calc(100% - 3px));
  mask:radial-gradient(farthest-side,transparent calc(100% - 4px),#000 calc(100% - 3px));animation:acn-spin 4.5s linear infinite}
.acn__orb::after{content:"";position:absolute;inset:-18px;border-radius:50%;z-index:-1;
  background:radial-gradient(closest-side,rgba(124,46,40,.22),transparent);animation:acn-pulse 3.6s ease-in-out infinite}
@keyframes acn-pulse{50%{transform:scale(1.2);opacity:.5}}
.acn__orb img{position:relative;z-index:1;width:48%;height:48%;object-fit:contain;filter:drop-shadow(0 4px 8px rgba(62,20,17,.25))}
/* The column of badges, right of the hub. Flex spaces them evenly by their
   real heights; the stage grows if they need more room. */
.acn__nav{position:relative;z-index:2;flex:1;display:flex;margin-left:calc(var(--ox) * 2 + 34px);min-width:0}
.acn__list{margin:0;padding:6px 0;list-style:none;flex:1;display:flex;flex-direction:column;justify-content:space-evenly;align-items:flex-start;gap:14px;min-width:0}
/* A gentle arc: the middle badges sit a little further out. */
.acn__b{--d:1;--arc:0px;max-width:calc(100% - var(--arc));margin-left:var(--arc);
  translate:calc(var(--x,0) * var(--d) * 12px) calc(var(--y,0) * var(--d) * 8px);transition:translate .5s cubic-bezier(.23,1,.32,1)}
.acn__stage[data-n="3"] .acn__b--2{--arc:30px}
.acn__stage[data-n="4"] .acn__b--2,.acn__stage[data-n="4"] .acn__b--3{--arc:26px}
.acn__stage[data-n="2"] .acn__b{--arc:10px}
.acn__b--1{--d:1.2}.acn__b--2{--d:.75}.acn__b--3{--d:1.35}.acn__b--4{--d:.9}
.acn__a{display:inline-flex;align-items:center;gap:11px;max-width:100%;padding:9px 16px 9px 9px;border-radius:999px;text-decoration:none;
  font-weight:800;font-size:.92rem;letter-spacing:-.015em;line-height:1.25;color:var(--ink);
  background:rgba(255,255,255,.9);border:1px solid rgba(255,255,255,.95);
  -webkit-backdrop-filter:blur(14px) saturate(150%);backdrop-filter:blur(14px) saturate(150%);
  box-shadow:0 20px 40px -20px rgba(36,19,16,.5);
  animation:acn-bob 6s ease-in-out infinite;animation-delay:calc(var(--k,0) * -1.5s);
  transition:background .35s ease,color .35s ease,box-shadow .35s ease}
@keyframes acn-bob{0%,100%{transform:translateY(0)}50%{transform:translateY(-6px)}}
.acn__ic{flex:none;display:grid;place-items:center;width:36px;height:36px;border-radius:50%;font-size:.92rem;color:#fff;
  background:linear-gradient(160deg,var(--brand-2),var(--brand));transition:background .35s ease,color .35s ease}
.acn__tx{display:grid;gap:2px;min-width:0}
.acn__t{display:block}
.acn__sub{font-family:var(--mono);font-size:.62rem;font-weight:700;letter-spacing:.06em;color:var(--ink-2);overflow-wrap:anywhere}
/* The arrow's space is always reserved (it fades, never grows), so a badge
   never changes width when spotlit - a label that fits stays on one line. */
.acn__go{flex:none;width:14px;opacity:0;translate:-4px 4px;font-size:.85rem;transition:opacity .35s ease,translate .35s ease}
.acn__faces{flex:none;display:flex;padding-left:8px}
.acn__faces img{flex:none;display:block;width:34px;height:34px;aspect-ratio:1;margin-left:-8px;border-radius:50%;object-fit:cover;
  border:2px solid #fff;box-shadow:0 4px 10px -4px rgba(36,19,16,.4)}
.acn__a:focus-visible{outline:3px solid var(--brand);outline-offset:3px}
/* Not a link: quieter, no hover, never spotlit. */
.acn__a--off{cursor:default;background:rgba(255,255,255,.8)}
.acn__a--off .acn__t{color:var(--ink-2)}
.acn__a--off .acn__ic{background:var(--brand-wash);color:var(--brand)}
/* The spotlight (and hover): the badge fills oxblood, its spoke glows. */
.acn__stage[data-on="0"] .acn__b--1 a.acn__a,.acn__stage[data-on="1"] .acn__b--2 a.acn__a,
.acn__stage[data-on="2"] .acn__b--3 a.acn__a,.acn__stage[data-on="3"] .acn__b--4 a.acn__a,a.acn__a:hover{
  background:linear-gradient(160deg,var(--brand-2),var(--brand));color:#fff;border-color:rgba(255,255,255,.25);
  box-shadow:0 0 0 6px rgba(255,255,255,.18),0 26px 46px -18px rgba(62,20,17,.7)}
.acn__stage[data-on="0"] .acn__b--1 a .acn__ic,.acn__stage[data-on="1"] .acn__b--2 a .acn__ic,
.acn__stage[data-on="2"] .acn__b--3 a .acn__ic,.acn__stage[data-on="3"] .acn__b--4 a .acn__ic,a.acn__a:hover .acn__ic{background:#fff;color:var(--brand)}
.acn__stage[data-on="0"] .acn__b--1 a .acn__sub,.acn__stage[data-on="1"] .acn__b--2 a .acn__sub,
.acn__stage[data-on="2"] .acn__b--3 a .acn__sub,.acn__stage[data-on="3"] .acn__b--4 a .acn__sub,a.acn__a:hover .acn__sub{color:rgba(255,255,255,.82)}
.acn__stage[data-on="0"] .acn__b--1 a .acn__go,.acn__stage[data-on="1"] .acn__b--2 a .acn__go,
.acn__stage[data-on="2"] .acn__b--3 a .acn__go,.acn__stage[data-on="3"] .acn__b--4 a .acn__go,a.acn__a:hover .acn__go{opacity:1;translate:0 0}
.acn__stage[data-on="0"] .acn__lines g:nth-child(1) .acn__ln,.acn__stage[data-on="1"] .acn__lines g:nth-child(2) .acn__ln,
.acn__stage[data-on="2"] .acn__lines g:nth-child(3) .acn__ln,.acn__stage[data-on="3"] .acn__lines g:nth-child(4) .acn__ln{
  stroke:#fff;stroke-width:2;stroke-dasharray:none;filter:drop-shadow(0 0 4px rgba(255,255,255,.95))}
/* Badges arrive one after another. */
html.mo-on .acn__b{animation:acn-in .8s cubic-bezier(.2,.8,.2,1) both;animation-delay:calc(.6s + var(--k,0) * .12s)}
@keyframes acn-in{from{opacity:0;scale:.85}to{opacity:1;scale:1}}
@media(prefers-reduced-motion:reduce){
  .acn__hub,.acn__b{translate:none}
  .acn__pulse,.acn__rings i,.acn__orb,.acn__orb::before,.acn__orb::after,.acn__glow,.acn__sats i,.acn__a,html.mo-on .acn__b{animation:none}
  .acn__pulse,.acn__sats{display:none}
}
/* Room for the labels: on heroes carrying a constellation the right column
   is wider (labels stay on one line), and the hub is compact, its centre
   near the column's left edge so the rings spill into the gutter. */
@media(min-width:960px){.mh__in:has(.acn){grid-template-columns:minmax(0,7fr) minmax(0,5fr)}}
.acn{--ox:38px;--orb:90px}
.acn__nav{margin-left:calc(var(--ox) + var(--orb) / 2 + 26px)}
.acn__rings i:nth-child(1){width:130px;height:130px}
.acn__rings i:nth-child(2){width:180px;height:180px}
.acn__rings i:nth-child(3){width:220px;height:220px}
/* Labels that still need two lines (the longest titles) wrap evenly. */
.acn__t{text-wrap:balance}
.acn__a{font-size:.9rem}
/* A gentle tint on the footage behind the constellation, so its white
   spokes, rings and glass badges read clearly over bright video. Brand ink
   (warm oxblood, not grey), under the paper fade, right side only. */
@media(min-width:960px){
  .mh--glass:has(.acn) .mh__scrim{background:
    radial-gradient(46% 60% at 10% 30%,rgba(222,150,138,.16) 0%,rgba(222,150,138,0) 70%),
    linear-gradient(90deg,
      var(--paper) 0%,var(--paper) 38%,
      rgba(247,244,239,.92) 46%,rgba(247,244,239,.55) 56%,
      rgba(247,244,239,.12) 68%,rgba(247,244,239,0) 78%),
    radial-gradient(38% 55% at 76% 52%,rgba(42,16,13,.22) 0%,rgba(42,16,13,0) 75%),
    linear-gradient(90deg,rgba(42,16,13,0) 50%,rgba(42,16,13,.2) 68%,rgba(42,16,13,.3) 100%)}
}
/* Badge portraits: always a true 34px circle (the global img max-width:100%
   squeezed a lone face to 26px), and a fixed-width face area so every
   badge's text starts on the same line, one face or two. */
.acn__faces{width:60px}
.acn__faces img{max-width:none}
