/* ==========================================================================
   IDW-26 - surveyed.v1.css
   "THE SURVEYED SHEET" (Rev D) - the shared design layer promoted from the
   homepage (SHT 01) so every sheet carries the same identity:

     - a distinctive variable type system (Bricolage Grotesque display that
       recompresses at scale / Hanken Grotesk body / Geist Mono machine register)
     - a page-wide live WebGL FIELD (field.v1.js) read vivid behind the hero,
       veiled to a subtle living atmosphere behind the content
     - flat POSTER surfaces (hairline + space, not shadow-stacks)
     - bracketed drafting kickers, an amber dimension rule, a generous rhythm
     - motion that varies by mass and arrives (curves from tokens.v1.css)

   LOAD ORDER (after the Rev B sheets, so this upgrades their defaults):
     tokens.v1.css -> frame.v1.css -> components.v1.css -> surveyed.v1.css
   Page <head> must load the three families and the field:
     Bricolage Grotesque + Hanken Grotesk + Geist Mono (Google Fonts)
     <script src="shared/reveal.v1.js" defer></script>
     <script src="shared/field.v1.js" defer></script>   (after reveal.v1.js)
   Page <body> first child: <canvas id="glhero" aria-hidden="true"></canvas>
   The hero <section> takes the .page-hero modifier (field shown vivid there).
   Legal pages (body.doc-light) opt out of the dark field automatically below.
   ========================================================================== */

/* ==========================================================================
   1. TYPE - the three voices (tokens carry the families + the scale)
   ========================================================================== */
body{font-family:var(--font)}

/* brand voice: Bricolage display with true optical sizing */
.display,.h1-sheet,.h2-sheet{font-family:var(--font-display);font-optical-sizing:auto;text-wrap:balance}
.display{
  font-size:clamp(2.75rem, 1.1rem + 5vw, 5.5rem);
  font-weight:560;line-height:.95;letter-spacing:-.04em;
  font-variation-settings:'opsz' 80,'wght' 560;
}
.h1-sheet{
  font-size:clamp(2.4rem, 1.2rem + 4.4vw, 5rem);
  font-weight:560;line-height:.98;letter-spacing:-.035em;
  font-variation-settings:'opsz' 72,'wght' 560;
}
.h2-sheet{
  font-size:var(--t-h2);line-height:1.02;letter-spacing:-.025em;
  font-weight:540;font-variation-settings:'opsz' 40;
}

/* human voice: Hanken for prose + card titles (inherits --font; named here so
   intent is explicit and a later token swap stays surgical) */
.lede,.slab p,.slab h3,.prose,.nd-l,.sr-value{font-family:var(--font)}
.lede{font-size:var(--t-lede);font-weight:360;line-height:1.6;color:var(--ink-lede)}

/* machine voice: Geist Mono for the whole annotation / drafting register */
.kicker,.annot,.dim-fig,.dim-labels,.tb-label,.tb-cert,.bk-h,.footer-h,
.thumb-no,.chip,.sr-label,.sf-head>span,.sf-readout,.nd-d,.cta-ghost,
.scn-tag,.scn-metric{
  font-family:var(--font-mono);
}
.tb-fig,.dim-fig,.sr-value,.sf-readout{font-feature-settings:'tnum' 1,'zero' 1}

/* ==========================================================================
   2. THE LIVE FIELD - fixed flowing-gradient behind the WHOLE page.
   field.v1.js renders it; this is the canvas chrome + the CSS twilight wash
   fallback (shown when WebGL is unavailable or before the canvas is ready).
   ========================================================================== */
body{
  background:
    radial-gradient(120% 60% at 50% -2%, rgba(37,99,235,.07), transparent 60%),
    radial-gradient(70% 40% at 88% 6%, rgba(245,156,0,.03), transparent 60%),
    linear-gradient(180deg, #0b0e16 0%, #0a0b11 30%, #08080b 70%);
  background-attachment:fixed;
}
#glhero{
  /* width/height:100% (NOT 100vw/100vh): <canvas> is a REPLACED element, so
     inset:0 alone leaves it at its intrinsic 300x150 - it needs an explicit
     size. 100% resolves against the fixed containing block (the layout
     viewport), so it fills the screen WITHOUT the 100vw scrollbar overshoot.
     field.v1.js reads the element's own clientWidth for the render buffer. */
  position:fixed;top:0;left:0;width:100%;height:100%;z-index:0;display:block;
  pointer-events:none;opacity:0;transition:opacity 1.1s ease;
}
#glhero.ready{opacity:1}
/* fine static grain over the field - enriches it, kills banding (not animated) */
body::after{
  content:'';position:fixed;inset:0;z-index:0;pointer-events:none;
  opacity:.03;mix-blend-mode:overlay;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='140' height='140'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='2' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
  background-size:140px 140px;
}
/* content + footer sit above the field */
main{position:relative;z-index:1}
.footer{position:relative;z-index:1}
/* the sticky nav floats over the live field. When backdrop-filter is
   unavailable, its 55% glass would let the field bleed through illegibly -
   give it a near-opaque fallback so the nav stays readable. */
@supports not ((backdrop-filter:blur(1px)) or (-webkit-backdrop-filter:blur(1px))){
  .nav{background:rgba(11,14,22,.94)}
}

/* every section paints a dark veil so the field reads as a subtle living
   atmosphere (~20% behind), plus a soft ambient glow off the top edge and a
   1px machined edge-light so sections breathe into one another */
.sheet-section:not(.page-hero){
  background:
    radial-gradient(72% 260px at 50% 0, var(--sec-amb, transparent), transparent 72%),
    linear-gradient(0deg, rgba(8,9,13,.8), rgba(8,9,13,.8));
  box-shadow:inset 0 1px 0 rgba(255,255,255,.045);
}
/* opt a section into a blue/amber breath off its top:  style="--sec-amb:..." */

/* generous poster rhythm */
.sheet-section{padding-block:clamp(88px, 6vw + 40px, 148px)}

/* ==========================================================================
   3. HERO (.page-hero) - the field shown VIVID, a contrast scrim under the
   monumental left-datum type. Drop .page-hero on the page's first section.
   ========================================================================== */
.page-hero{
  position:relative;background:transparent;isolation:isolate;overflow:hidden;
  padding-block:clamp(72px, 5vw + 40px, 128px);
}
/* contrast scrim over the live gradient - keeps the headline + lede crisp
   wherever the field flows beneath them (left + bottom weighted to match the
   left-anchored hero composition) */
.page-hero::before{
  content:'';position:absolute;inset:0;z-index:0;pointer-events:none;
  background:
    linear-gradient(90deg, rgba(8,9,15,.88) 0%, rgba(8,9,15,.66) 46%, rgba(8,9,15,.24) 78%, transparent 100%),
    linear-gradient(0deg, rgba(8,9,15,.66) 0%, rgba(8,9,15,.06) 42%, transparent 64%);
}
/* narrow widths: content is full-bleed, so the scrim must weight vertically
   (the left->right weighting no longer covers the wrapped lede over a bright
   field patch) */
@media (max-width:760px){
  .page-hero::before{
    background:linear-gradient(0deg, rgba(8,9,15,.86) 0%, rgba(8,9,15,.62) 45%, rgba(8,9,15,.32) 75%, rgba(8,9,15,.12) 100%);
  }
}
.page-hero > *{position:relative;z-index:1}
/* left-anchored monument by default */
.page-hero .kicker{justify-content:flex-start}
/* the word-rise mask (.line{overflow:hidden} in components.v1.css) must never
   clip glyph descenders (the y/g/p tails) OR the amber dimension rule, which
   sits just below the baseline at bottom:-.1em. Enlarge the clip box downward
   and cancel it with a matching negative margin so vertical rhythm is unchanged
   (mirrors the homepage's .home-hero .display .line fix). */
.page-hero .h1-sheet .line,
.page-hero .display .line{padding-bottom:.2em;margin-bottom:-.2em}

/* the amber dimension rule surveyed under a hero word/phrase:
   <span class="amber-rule">door.</span>  (drawn in on .in) */
.amber-rule{position:relative;display:inline-block}
.amber-rule::after{
  content:'';position:absolute;left:.02em;right:-.6em;bottom:-.1em;height:2px;
  background:var(--amber);transform:scaleX(0);transform-origin:left;
}
html.js .amber-rule::after{transition:transform 1s var(--ease-draw) .5s}
html.js .in .amber-rule::after,html.js .amber-rule.in::after{transform:scaleX(1)}
html.no-motion .amber-rule::after{transform:scaleX(1);transition:none}

/* ==========================================================================
   4. BRACKETED DRAFTING KICKER - the connective signature. The shared amber
   bar becomes amber braces in the machine register.
   ========================================================================== */
.kicker{
  display:inline-flex;align-items:baseline;gap:.5em;
  font-weight:500;letter-spacing:.14em;text-transform:uppercase;
  color:var(--ink-3);
}
.kicker::before{content:'{';width:auto;height:auto;background:none;color:var(--amber);font-weight:600}
.kicker::after{content:'}';color:var(--amber);font-weight:600}
.kicker-n{color:var(--amber)}

/* ==========================================================================
   5. FLAT POSTER SURFACES - kill the shadow-stacks; hierarchy via hairline +
   space + a thin top sheen. Surfaces go opaque so the live field never bleeds
   through text. (--surface remapped opaque for dark pages; doc-light keeps
   its paper white via the higher-specificity body.doc-light rule in tokens.)
   ========================================================================== */
:root{--surface:#0f1218}

.slab{
  background:linear-gradient(180deg, rgba(255,255,255,.03), transparent 32%), var(--surface);
  box-shadow:none;border-radius:12px;
}
.slab::after{box-shadow:0 0 0 1px rgba(37,99,235,.25)}
.slab:hover{box-shadow:0 22px 52px -30px rgba(0,0,0,.8)}

.title-block{box-shadow:0 22px 52px -32px rgba(0,0,0,.8);border-radius:12px;overflow:hidden}
.tb-cell{background:var(--surface)}
.tb-cell:hover{background:#12161d}

.chip,.spec-rail,.sheet-thumb{background:var(--surface)}
.sheet-thumb{border-radius:12px}
.nav-drop{background:linear-gradient(180deg, rgba(255,255,255,.03), transparent 40%), var(--surface)}

/* ==========================================================================
   6. MOTION CRAFT - reveal varied by mass + arrival, premium micro-states.
   transform/opacity only (CLS 0); every animated thing reduced-motion gated.
   ========================================================================== */
/* faster + tighter + role-varied reveal; blur resolves early (overrides the
   shared .8s / translateY(18px) / blur(6px) / 120ms in components.v1.css) */
html.js .r{
  --rise:12px; --rblur:4px;
  transform:translateY(var(--rise)); filter:blur(var(--rblur));
  transition:
    opacity var(--t-mid) var(--ease-monument) calc(var(--i,0) * 64ms),
    transform var(--t-mid) var(--ease-monument) calc(var(--i,0) * 64ms),
    filter 300ms var(--ease-monument) calc(var(--i,0) * 64ms);
}
html.js .kicker.r, html.js .lede.r, html.js .h2-sheet.r, html.js h2.r{ --rise:8px; --rblur:3px }
/* heavy surfaces arrive with weight (expo, longer) */
html.js .title-block.r, html.js .slab.r, html.js .home-cta-panel.r{
  --rise:18px; --rblur:5px;
  transition-duration:var(--t-slab),var(--t-slab),360ms;
  transition-timing-function:var(--ease-expo);
}

/* magnetic CTA pull (reveal.v1.js writes --mx/--my + .is-mag; fine pointers) */
.cta-pill,.cta-ghost,.nav-cta{transition:transform .26s var(--ease-out-soft), background .2s var(--ease-monument), box-shadow .2s var(--ease-monument), filter .2s var(--ease-monument)}
@media (hover:hover) and (pointer:fine){
  .cta-pill.is-mag,.cta-ghost.is-mag,.nav-cta.is-mag{transform:translate(var(--mx,0px),var(--my,0px))}
  .cta-pill.is-mag{transform:translate(var(--mx,0px),var(--my,0px)) scale(1.015)}
}
/* the arrow nudges with a tactile overshoot land (Stripe/Linear signature) */
.cta-pill svg{transition:transform .26s var(--ease-spring)}
@media (hover:hover) and (pointer:fine){ .cta-pill:hover svg{transform:translateX(3px)} }

/* nav-link hover = a SLIGHT amber GLOW + tint, never a hard line (client pref:
   "a slight orange glow not a deep orange line"). The static active-page amber
   tick (components.v1.css .nav-link::after via body[data-active]) stays as the
   "you are here" cue on regular links. */
.nav-link{position:relative;transition:color .2s var(--ease-monument),text-shadow .2s var(--ease-monument),box-shadow .2s var(--ease-monument)}
.nav-link:hover,.nav-link:focus-visible{color:var(--amber);text-shadow:0 0 12px rgba(245,156,0,.45);box-shadow:0 0 18px -6px rgba(245,156,0,.4)}

/* ==========================================================================
   7. REDUCED MOTION / SAVE-DATA - neutralise every new transition cleanly.
   ========================================================================== */
html.no-motion .cta-pill,html.no-motion .cta-ghost,html.no-motion .nav-cta,
html.no-motion .cta-pill svg,html.no-motion .nav-link{transition:none}
html.no-motion .cta-pill.is-mag,html.no-motion .cta-ghost.is-mag,html.no-motion .nav-cta.is-mag{transform:none}
html.no-motion body::after{display:none}

/* ==========================================================================
   8. LEGAL PAGES (body.doc-light) - opt OUT of the dark field + veil; the
   light paper register (components.v1.css §13) owns these pages. We keep only
   the type voices + the bracketed kicker for cross-page consistency.
   ========================================================================== */
body.doc-light{background:var(--floor)}
body.doc-light::after{display:none}
body.doc-light #glhero{display:none}
body.doc-light .sheet-section:not(.page-hero){background:none;box-shadow:none}
