/* ════════════════════════════════════════════════════════════════════════
   Inlight IT — enhancement layer
   Injected LAST in <head> so it wins on equal specificity.
   Nothing here introduces a new token, colour or radius: it reads
   --gold / --svc / --border / --mono from whatever the page already sets.
   Every progressive feature is wrapped in @supports; the unenhanced
   state is always the usable state.
   ═══════════════════════════════════════════════════════════════════════ */

/* ── 1 · Chrome offset ────────────────────────────────────────────────────
   The location pages stack a fixed nav (76px) AND a sticky .snav (~46px).
   The previous flat 100px landed every .snav anchor underneath the bars.
   One variable, redeclared where the chrome differs.                      */
/* Declared on :root, not body — a var() inside a custom property is
   substituted where it is declared, so an override further down the tree
   would never reach a calc() written up here. */
:root{
  --inl-nav:  66px;   /* Astro shell .nav-header, measured */
  --inl-snav:  0px;   /* sticky section nav, where the page has one */
  --inl-air:  12px;   /* clearance below the bars — small enough that a dark
                         preceding band does not read as a stripe under a
                         light bar, large enough that the section's top rule
                         does not collide with the nav */
  --inl-chrome: calc(var(--inl-nav) + var(--inl-snav) + var(--inl-air));
}
:root:has(nav.nav){ --inl-nav: 77px; }   /* location prototypes' own nav */
:root:has(.snav) { --inl-snav: 50px; }
@media(max-width:760px){
  :root{ --inl-air: 10px; }
  :root:has(nav.nav){ --inl-snav: 45px; }
}

/* scroll-padding on the scroller is the right primitive for fixed chrome:
   one declaration covers every anchor, in-page nav, :target and find-in-page
   landing. The per-section scroll-margin the pages carried (100px flat, and
   64px of scroll-padding on the hub, which silently stacked with it) is
   zeroed so the two do not add up. */
html{ scroll-padding-top:var(--inl-chrome); }
section[id][id][id],[id][id][id].sec,details[id][id][id]{ scroll-margin-top:0; }

/* The section nav was pinned at a flat top:76px — tuned for the location
   pages' 77px nav. On the Astro shell the header is 66px, which left an
   11px strip of page content showing through between the two bars.
   Repeated class to out-specify the shell's `.snav[data-astro-cid-…]`. */
.snav.snav.snav{ top:var(--inl-nav); }

/* ── 2 · Skip link ────────────────────────────────────────────────────────
   With a fixed nav plus a 10-item .snav there were ~30 tab stops before
   the first word of content on every page.                                */
.skip-link{
  position:fixed;left:16px;top:-72px;z-index:2000;
  display:inline-block;padding:13px 20px;
  font-family:var(--mono,ui-monospace,monospace);font-size:11px;
  letter-spacing:.1em;text-transform:uppercase;text-decoration:none;
  color:#fff;background:#0F2A22;border:1px solid var(--gold,#C9A84C);
  border-radius:2px;transition:top .18s ease;
}
.skip-link:focus{ top:16px; }
@media(prefers-reduced-motion:reduce){ .skip-link{ transition:none; } }

/* ── 3 · Focus visibility ─────────────────────────────────────────────────
   The location pages carried 18 focus rules against the shell's ~180.
   Gold on light, gold-bright on the dark bands so it survives the ground. */
:where(a,button,summary,select,input,textarea,[tabindex]):focus-visible{
  outline:2px solid var(--gold,#C9A84C);
  outline-offset:3px;
  border-radius:2px;
}
:is(.hero-dark,.why-dark,.evwall,.rmx-dark,.sec.cta,.manifesto,.stats,.foot,.site-footer)
  :where(a,button,summary,[tabindex]):focus-visible{
  outline-color:var(--gold-bright,#E8C766);
}

/* Screen-reader-only utility (used by the filter live region) */
.inl-vh{
  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;
}

/* ── 4 · Typography ───────────────────────────────────────────────────────
   Headlines were balanced in exactly one place per page.                  */
h1,h2,h3,.sp-h,.hero h1,.cap-head h2,.sitsel-opt{ text-wrap:balance; }
/* `pretty` is scoped to narrow measures only. On the 820px .lede it optimised
   for last-line length and broke mid-phrase instead ("...the standard does
   not: clear / ownership..."), which read worse than the ragged original. */
.idc-lead,.pti p,.faq-a p,.cm,.csub,.mled-m > span,.sp-a,.sp-b{ text-wrap:pretty; }

/* ── 5 · Horizontal rails ─────────────────────────────────────────────────
   Every rail on the site chained its scroll to the page on trackpad and
   on touch, which is the main "the page jumped" complaint on mobile.      */
.rs-track,.cases,.lgr-row,.snav .wrap,.tkr-set,.sitsel-opts,.cmp-stack,
.split-ix,.idgrid .split-ix{
  overscroll-behavior-x:contain;
  -webkit-overflow-scrolling:touch;
}
/* The client marquee paused on hover but not on focus — a keyboard user
   tabbing into a logo could not stop it moving. */
.lgr:focus-within .lgr-track{ animation-play-state:paused; }

/* ── 6 · Off-screen rendering cost ────────────────────────────────────────
   These pages run to 15 sections. `auto` (not a fixed px) lets the browser
   remember the real measured height, which is what keeps in-page anchor
   jumps and the scrollbar stable.                                          */
@supports (content-visibility:auto){
  @media(min-width:1px){
    .sec:not(.cta):not(:first-of-type),
    section.sec:not(.cta):not(:first-of-type){
      content-visibility:auto;
      contain-intrinsic-size:auto 720px;
    }
  }
}

/* ── 7 · Scroll-driven progress ───────────────────────────────────────────
   Replaces a JS scroll listener writing transform on every frame.
   Safari 26 / iOS 26 and Chrome 115+ take this path; everything older
   keeps the JS, which is left in place and self-disables when supported.  */
@supports (animation-timeline:scroll()){
  @media(prefers-reduced-motion:no-preference){
    .scroll-progress i{
      transform-origin:0 50%;
      animation:inl-progress linear both;
      animation-timeline:scroll(root block);
    }
    @keyframes inl-progress{ from{transform:scaleX(0);} to{transform:scaleX(1);} }
  }
}

/* Own hook, set on <html> in the head so folded content never flashes open.
   Deliberately NOT the pages' existing `.has-js`: that class is only added by
   the location-page inline script, so anything keyed to it was inert on the
   three Astro pages — which is why the ledger fold below did nothing on the
   hub until this was separated out. */

/* ── 8 · Disclosure without max-height ────────────────────────────────────
   The "who we work with" cards animated on max-height:0 → 280px, which
   clips any card whose copy runs long and eases on the wrong curve.
   grid-template-rows 0fr → 1fr measures itself and — unlike
   interpolate-size, which is Chromium-only — animates correctly in
   Safari, so it works on iPhone.                                          */
.inl-js .idcards .idc-more{
  display:grid;
  grid-template-rows:0fr;
  max-height:none;
  opacity:0;
  transition:grid-template-rows .42s cubic-bezier(.2,.7,.3,1),opacity .28s;
}
.inl-js .idcards .idc-more > *{ overflow:hidden; min-height:0; }
/* The inner <p> carried margin-top:10px. Neither margin nor padding on the
   grid item collapses with a 0fr track, so the closed card kept a 10px
   sliver of open state. Zero it and animate the spacing back in. */
.inl-js .idcards .idc-more p{
  margin-top:0; padding-top:0;
  transition:padding-top .42s cubic-bezier(.2,.7,.3,1);
}
.inl-js .idcards > div.hit .idc-more p{ padding-top:10px; }
.inl-js .idcards > div.hit .idc-more{ grid-template-rows:1fr; opacity:1; }
@media(prefers-reduced-motion:reduce){
  .inl-js .idcards .idc-more{ transition:none; }
}

/* The card heading is now a real button. It must look exactly like the h3
   it replaced — the control is the whole card, the button is the a11y
   handle and the keyboard target. */
.idcards h3{ margin:0 0 9px; }
.idcards h3 .idc-btn{
  display:block;width:100%;text-align:left;
  font:inherit;color:inherit;letter-spacing:inherit;
  background:none;border:0;padding:0;margin:0;cursor:pointer;
}
.idcards h3 .idc-btn:focus-visible{ outline-offset:4px; }

/* ── 9 · Mobile ───────────────────────────────────────────────────────────
   Touch targets to 44px, and dvh so iOS Safari's collapsing toolbar
   does not crop the hero.                                                 */
@media(max-width:760px){
  .snav a{ display:flex;align-items:center;min-height:44px;padding-block:0; }
  .idgrid .split-ix button,.sitsel-opt,.rs-ctrls button,.faq-row summary{
    min-height:44px;
  }
  .idgrid .split-ix{ gap:8px; }
}
@supports (height:100dvh){
  .hero-section.hero-dark{ min-height:auto; }
  .hero-full,.hero-100{ min-height:100dvh; }
}

/* ── 10 · Reduced motion catch-all ────────────────────────────────────────
   The pages gate motion in JS but a few CSS animations ran regardless.    */
@media(prefers-reduced-motion:reduce){
  .lgr-track,.mled-foot .pdot,.cg-pulse{ animation:none!important; }
  *,*::before,*::after{ scroll-behavior:auto!important; }
}


/* ── 11 · Section closing note ────────────────────────────────────────────
   The line under the case cards was marked up as `.lede` — the large intro
   style — but positioned as an outro, so it read as text that had fallen out
   of the card grid rather than as a deliberate close. Same words, given the
   treatment of a closing statement and tied back to the gold thread. */
.sec-close{
  max-width:820px;margin:30px 0 0;padding-top:18px;
  border-top:1px solid var(--border,#E4EAE7);
  font-size:14.5px;line-height:1.66;color:var(--ink-light,#546070);
}
.sec-close::before{
  content:'';display:inline-block;width:18px;height:2px;
  background:var(--gold,#C9A84C);vertical-align:middle;margin-right:11px;
}
.evwall .sec-close,.why-dark .sec-close{
  border-top-color:rgba(255,255,255,.14);color:rgba(255,255,255,.68);
}

/* ── 12 · The two walls ───────────────────────────────────────────────────
   Both use one mechanism so they read as the same idea: the copy is clamped
   to a peek, a gold chevron marks the row as openable, and the full text is
   still in the DOM for search engines and for find-in-page.

   Clamped by max-height rather than -webkit-line-clamp because line-clamp
   cannot be transitioned; the ceiling is set well above any real paragraph
   so nothing is ever cut off when open. A mask fades the clamped line so the
   truncation reads as deliberate rather than as a rendering fault. */
.inl-js .mled-r{ align-items:flex-start; }
.inl-js .mled-m{ display:block; }

.inl-js .mled-m .mled-tog{
  display:flex;align-items:baseline;gap:10px;width:100%;
  background:none;border:0;padding:0;margin:0;cursor:pointer;
  font:inherit;color:inherit;text-align:left;
}
.inl-js .mled-m .mled-tog b{ flex:1; }
.inl-js .mled-m .mled-chev{
  flex:none;width:8px;height:8px;margin-top:2px;
  border-right:1.5px solid var(--gold-deep,#b88a2e);
  border-bottom:1.5px solid var(--gold-deep,#b88a2e);
  transform:rotate(45deg);transform-origin:60% 60%;
  transition:transform .3s cubic-bezier(.2,.7,.3,1);
}
.inl-js .mled-r.is-open .mled-chev{ transform:rotate(-135deg); }

.inl-js .mled-m > span{
  max-height:1.62em;overflow:hidden;
  -webkit-mask-image:linear-gradient(180deg,#000 62%,transparent 100%);
  mask-image:linear-gradient(180deg,#000 62%,transparent 100%);
  transition:max-height .4s cubic-bezier(.2,.7,.3,1);
}
.inl-js .mled-r.is-open .mled-m > span{
  max-height:24em;
  -webkit-mask-image:none;mask-image:none;
}
.inl-js .mled-r.is-open{ background:var(--warm-white,#FAF8F4); }

/* Expand-all sits in the ledger's existing footer rather than adding chrome */
.inl-js .mled-foot{ justify-content:space-between; }
.inl-js .mled-all{
  background:none;border:0;padding:4px 0;cursor:pointer;
  font:inherit;font-family:var(--mono,monospace);font-size:9.5px;
  letter-spacing:.11em;text-transform:uppercase;
  color:var(--gold-bright,#E8C766);border-bottom:1px solid rgba(232,199,102,.45);
}
.inl-js .mled-all:hover{ border-bottom-color:var(--gold-bright,#E8C766); }

/* Same clamp on the "who we work with" lead copy, released when the card
   opens — so a closed card is number, title and a two-line peek. */
.inl-js .idcards .idc-lead{
  max-height:3.25em;overflow:hidden;
  -webkit-mask-image:linear-gradient(180deg,#000 68%,transparent 100%);
  mask-image:linear-gradient(180deg,#000 68%,transparent 100%);
  transition:max-height .42s cubic-bezier(.2,.7,.3,1);
}
.inl-js .idcards > div.hit .idc-lead{
  max-height:16em;
  -webkit-mask-image:none;mask-image:none;
}
@media(prefers-reduced-motion:reduce){
  .inl-js .mled-m > span,.inl-js .idcards .idc-lead,.inl-js .mled-chev{
    transition:none;
  }
}

/* A clamp applied to copy that already fits reads as a rendering fault — the
   reader sees a fade and expects more text behind it. Measured at runtime:
   anything that fits opts out of both the clamp and the mask. */
.inl-js .mled-m > span.inl-fits,
.inl-js .idcards .idc-lead.inl-fits{
  max-height:none;
  -webkit-mask-image:none;mask-image:none;
}
.inl-js .mled-r:not(:has(.inl-fits)) .mled-tog{ cursor:pointer; }
.inl-js .mled-r:has(.inl-fits) .mled-chev{ opacity:.25; }
