/* =========================================================
   DAYVISION — DV·01 SPECTRA
   Aesthetic: optical-instrument catalogue × editorial gallery.
   Warm paper, ink navy, one spectrum accent used exactly once.
   ========================================================= */

:root{
  /* Cream and sage, lifted from the parent site's own solarpunk reality
     (index.html, :root[data-reality="solarpunk"]) rather than invented, so the
     two match exactly instead of approximately. */
  /* District Vision's own values. The ground is the load-bearing one: #F2F2F2
     rather than white is what makes the page read as paper rather than as a
     default browser window, and it is what the product cutouts glow against. */
  --paper:        #DDE4E6;
  --paper-deep:   #CFD8DB;
  /* the one deviation: this act keeps a ground of its own, pulled to a whisper
     so it sits inside the system rather than beside it */
  --paper-green:  #DBE6DE;
  --reverse:      #FFFFFF;

  --ink:          #1D1D1D;
  --bg-dark:      #1D1D1D;
  /* Body copy is grey, not black — that is why the whole thing feels hushed.
     Set at #5A5B5D rather than their #6D6E70: theirs measures 4.1:1 on this
     ground, under AA for small text, and this page carries far more running
     copy than a shop does. #6D6E70 is kept for labels, which are short. */
  --text-on-light:#5A5B5D;
  --text-on-dark: #F2F2F2;
  --muted-light:  #5F6062;
  --muted-dark:   #BABFC3;
  --rule-light:   rgba(29,29,29,.15);
  --rule-dark:    rgba(242,242,242,.18);
  --slate:        #373F47;

  /* One hit, high saturation, surrounded by silence — so it is NOT spent on
     the label layer, which would put it on screen a dozen times. It also fails
     AA as small text on either ground (4.25:1 on paper, 3.61:1 on ink), which
     is a second reason to keep it off type and on fills. */
  --signal:       #E11F26;
  --signal-lift:  #E11F26;
  --growth:       #6D6E70;
  --spectrum: linear-gradient(90deg,var(--ink) 0%,var(--slate) 60%,var(--signal) 100%);

  --font-display: 'Work Sans', 'Helvetica Neue', sans-serif;
  --font-body:    'Work Sans', 'Helvetica Neue', sans-serif;
  --font-mono:    'Work Sans', 'Helvetica Neue', sans-serif;

  --ease: cubic-bezier(.22,1,.36,1);
}

*,*::before,*::after{ box-sizing:border-box; }

html{ scrollbar-width:none; }
html::-webkit-scrollbar{ display:none; }

body{
  margin:0;
  background:var(--paper);
  color:var(--text-on-light);
  font-family:var(--font-body);
  -webkit-font-smoothing:antialiased;
  text-rendering:optimizeLegibility;
  overflow-x:hidden;
}

img,svg{ max-width:100%; }
a{ color:inherit; text-decoration:none; }
ul{ margin:0; padding:0; list-style:none; }

::selection{ background:var(--ink); color:var(--paper); }

/* =========================================================
   ATMOSPHERE — grain + crop marks
   ========================================================= */
.grain{
  position:fixed; inset:-50%; z-index:60;
  pointer-events:none; opacity:.30; mix-blend-mode:multiply;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='180' height='180'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.82' numOctaves='3'/%3E%3C/filter%3E%3Crect width='180' height='180' filter='url(%23n)' opacity='.42'/%3E%3C/svg%3E");
  animation:grainshift 6s steps(6) infinite;
}
@keyframes grainshift{
  0%{transform:translate(0,0)} 20%{transform:translate(-2%,1%)}
  40%{transform:translate(1%,-2%)} 60%{transform:translate(-1%,2%)}
  80%{transform:translate(2%,1%)} 100%{transform:translate(0,0)}
}

.edge-marks{ position:fixed; inset:0; z-index:55; pointer-events:none; }
.mk{
  position:absolute; width:14px; height:14px;
  border:0 solid var(--rule-light);
  transition:border-color .5s var(--ease);
}
.mk-tl{ top:22px; left:22px;  border-top-width:1px; border-left-width:1px; }
.mk-tr{ top:22px; right:22px; border-top-width:1px; border-right-width:1px; }
.mk-bl{ bottom:22px; left:22px;  border-bottom-width:1px; border-left-width:1px; }
.mk-br{ bottom:22px; right:22px; border-bottom-width:1px; border-right-width:1px; }
body.is-dark .mk{ border-color:var(--rule-dark); }

/* =========================================================
   HEADER
   ========================================================= */
.site-header{
  position:fixed; top:0; left:0; right:0; z-index:70;
  padding:1.9rem 3.2vw;
  transition:color .5s var(--ease);
}
.site-header nav{
  display:flex; align-items:center; justify-content:space-between; gap:2rem;
}

.logo{ display:flex; align-items:baseline; gap:.7rem; }
.logo-mark{
  font-family:var(--font-display);
  font-weight:500;
  font-size:1.081rem; letter-spacing:-.023em; line-height:1;
}
.logo-word{
  font-family:var(--font-mono); font-weight:400;
  font-size:0.797rem; letter-spacing:.32em; text-transform:uppercase;
  opacity:.62;
}

.nav-links{
  display:flex; gap:2.4rem;
  font-family:var(--font-mono); font-weight:400;
  font-size:0.82rem; letter-spacing:.19em; text-transform:uppercase;
}
.nav-links a{ position:relative; padding-bottom:.3rem; opacity:.72; transition:opacity .3s; }
.nav-links a::after{
  content:''; position:absolute; left:0; bottom:0; height:1px; width:0;
  background:currentColor; transition:width .45s var(--ease);
}
.nav-links a:hover{ opacity:1; }
.nav-links a:hover::after{ width:100%; }

.nav-cta{ display:flex; align-items:center; gap:1.6rem; }
.nav-model{
  font-family:var(--font-mono); font-size:0.797rem;
  letter-spacing:.24em; opacity:.45;
}
.nav-buy{
  font-family:var(--font-mono); font-size:0.808rem;
  letter-spacing:.19em; text-transform:uppercase;
  padding:.62rem 1.25rem;
  border:1px solid currentColor; border-radius:100px;
  transition:background .4s var(--ease), color .4s var(--ease);
}
.nav-buy:hover{ background:var(--ink); color:var(--paper); border-color:var(--ink); }
body.is-dark .site-header{ color:var(--text-on-dark); }
body.is-dark .nav-buy:hover{ background:var(--paper); color:var(--ink); border-color:var(--paper); }

/* =========================================================
   PROGRESS RAIL
   ========================================================= */
.progress-rail{
  position:fixed; right:3.2vw; top:50%; transform:translateY(-50%);
  width:1px; height:26vh; z-index:65;
  background:var(--rule-light); pointer-events:none;
  transition:background .5s var(--ease);
}
body.is-dark .progress-rail{ background:var(--rule-dark); }
.progress-tick{
  position:absolute; right:0; width:7px; height:1px;
  background:var(--rule-light); transition:background .5s var(--ease);
}
body.is-dark .progress-tick{ background:var(--rule-dark); }
.progress-tick[data-t="0"]{ top:0 } .progress-tick[data-t="25"]{ top:25% }
.progress-tick[data-t="50"]{ top:50% } .progress-tick[data-t="75"]{ top:75% }
.progress-tick[data-t="100"]{ top:100% }
.progress-fill{
  position:absolute; top:0; left:0; width:1px; height:0%;
  background:var(--ink); transition:background .5s var(--ease);
}
body.is-dark .progress-fill{ background:var(--paper); }

/* =========================================================
   HERO
   ========================================================= */
.hero-standalone{
  position:fixed; inset:0; z-index:20;
  pointer-events:none;
  height:100vh; width:100%;
  background:var(--paper);
  display:flex; flex-direction:column; justify-content:center;
  padding:0 3.2vw;
  overflow:hidden;
}

.hero-rule{ position:absolute; background:var(--rule-light); pointer-events:none; }
.hero-rule-a{ left:3.2vw; right:3.2vw; top:calc(50% - 1px); height:1px; opacity:.5; }
.hero-rule-b{ top:0; bottom:0; left:62%; width:1px; opacity:.35; }

.hero-content{ position:relative; z-index:2; max-width:min(1180px,86vw); }

.hero-mark{
  display:block; width:clamp(74px,7vw,104px); height:auto;
  margin-bottom:1.6rem;
}
.hero-label{ display:block; margin-bottom:2rem; }

.hero-heading{
  font-family:var(--font-display);
  font-weight:500;
  font-size:clamp(2.268rem,5.18vw,5.399rem);
  line-height:.84;
  letter-spacing:-.023em;
  text-transform:uppercase;
  margin:0 0 2.4rem;
  color:var(--ink);
}
.hero-heading .word{ display:block; overflow:hidden; }
.hero-heading .word > span{ display:block; will-change:transform; }

.accent-word > span{
  background:var(--spectrum);
  -webkit-background-clip:text; background-clip:text;
  color:transparent;
  -webkit-text-fill-color:transparent;
}

.hero-tagline{
  font-size:clamp(0.941rem,0.97vw,1.008rem);
  line-height:1.62; color:var(--muted-light);
  max-width:44ch; margin:0;
  font-weight:400;
}

.hero-foot{
  position:absolute; left:3.2vw; bottom:3.4rem; z-index:2;
  display:flex; gap:3.4rem;
}
.hero-spec{ display:flex; flex-direction:column; gap:.5rem; }
.spec-k{
  font-family:var(--font-mono); font-size:0.79rem;
  letter-spacing:.24em; text-transform:uppercase; color:var(--muted-light);
}
.spec-v{
  font-family:var(--font-display);
  font-weight:500;
  font-size:1.069rem; letter-spacing:-.01em;
}

.scroll-indicator{
  position:absolute; right:3.2vw; bottom:3.4rem; z-index:2;
  display:flex; align-items:center; gap:1rem;
}
.scroll-word{
  font-family:var(--font-mono); font-size:0.79rem;
  letter-spacing:.28em; text-transform:uppercase; color:var(--muted-light);
}
.scroll-line{
  display:block; width:64px; height:1px;
  background:var(--rule-light); position:relative; overflow:hidden;
}
.scroll-line i{
  position:absolute; top:0; left:0; height:1px; width:26px;
  background:var(--ink);
  animation:scrolldash 2.1s var(--ease) infinite;
}
@keyframes scrolldash{
  0%{ transform:translateX(-28px) } 60%,100%{ transform:translateX(66px) }
}

/* =========================================================
   CANVAS
   ========================================================= */
.canvas-wrap{
  position:fixed; inset:0; z-index:1;
  /* No circle wipe. The hero above is opaque (--paper, z-index 20) and fades
     out on scroll, so the canvas simply crossfades in behind it. */
}
#canvas{ display:block; width:100%; height:100%; }

#dark-overlay{
  position:fixed; inset:0; z-index:5;
  background:var(--bg-dark);
  opacity:0; pointer-events:none;
}

/* =========================================================
   MARQUEE
   ========================================================= */
.marquee-wrap{
  position:fixed; z-index:8;
  top:7vh; left:0; width:100%;
  overflow:hidden; pointer-events:none;
  opacity:0;
}
.marquee-low{ top:auto; bottom:5vh; }

.marquee-text{
  font-family:var(--font-display);
  font-weight:500;
  font-size:13vw; line-height:1;
  letter-spacing:-.02em; text-transform:uppercase;
  white-space:nowrap; will-change:transform;
  color:var(--ink); opacity:.075;
}
.marquee-text em{ font-style:normal; opacity:.5; }

.marquee-outline{
  color:transparent;
  -webkit-text-stroke:1px rgba(233,238,239,.22);
  opacity:.9;
}

/* =========================================================
   SCROLL SECTIONS
   ========================================================= */
#scroll-container{
  position:relative; z-index:10;
  height:1000vh; width:100%;
}

.scroll-section{
  position:absolute; left:0; width:100%;
  transform:translateY(-50%);
  opacity:0; visibility:hidden;
  pointer-events:none;
}
/* Held still while the section owns the scroll. Parked absolutely, a slide
   travels through the viewport as you scroll and is only fully framed in the
   middle of its pass — which is why the whole slide was never on screen at
   once. Fixed for the length of its window, it stays centred and complete, and
   goes back to scrolling normally on either side of it.

   Safe because the entrance timelines animate the section's CHILDREN, never the
   section itself, so the translateY(-50%) above is not fighting GSAP. */
.scroll-section.is-pinned{ position:fixed; top:50% !important; }

/* text lives in the outer zones — the optic owns the centre */
/* The copy column is deliberately tighter than the optic band: the product
   is a wide, flat object, so width is the only thing that makes it read
   bigger. 31vw of copy still holds four lines of a display heading. */
.align-left { padding-left:8vw;  padding-right:61vw; }
.align-right{ padding-left:61vw; padding-right:8vw; text-align:right; }
.align-left .section-inner,
.align-right .section-inner{ max-width:31vw; }
.align-right .section-inner{ margin-left:auto; }

.section-label{
  display:block;
  font-family:var(--font-mono); font-weight:400;
  font-size:0.82rem; letter-spacing:.26em; text-transform:uppercase;
  color:var(--muted-light);
  margin-bottom:1.5rem;
  position:relative; padding-left:2.6rem;
}
.section-label::before{
  content:''; position:absolute; left:0; top:.42em;
  width:1.8rem; height:1px; background:currentColor; opacity:.55;
}
.align-right .section-label{ padding-left:0; padding-right:2.6rem; }
.align-right .section-label::before{ left:auto; right:0; }

.section-heading{
  font-family:var(--font-display);
  font-weight:500;
  font-size:clamp(1.118rem,1.71vw,1.704rem);
  line-height:1.08; letter-spacing:-.019em;
  margin:0 0 1.7rem; color:var(--ink);
}

.section-body{
  font-size:clamp(0.933rem,0.93vw,1.001rem);
  line-height:1.66; color:var(--text-on-light);
  margin:0 0 1.5rem; max-width:40ch;
}
/* the quote runs wider than the prose measure it is quoted inside */
.section-body:has(em.thesis-quote){ max-width:min(24ch + 16vw, 46ch); }

/* Slide 03 only, hooked on the pull quote it alone carries — no extra class in
   the markup, and the same :has() idiom already used above. Its blocks were
   running long and wide: the quote filled two near-full lines then dropped a
   139px orphan, and the closing paragraph did the same. A tighter measure
   splits each of them over more, shorter rows. */
.section-inner:has(.pullquote) .pullquote{ max-width:22ch; }
.section-inner:has(.pullquote) .section-body{ max-width:30ch; }
.align-right .section-body{ margin-left:auto; }

.section-note{
  font-family:var(--font-mono); font-weight:400;
  font-size:0.805rem; letter-spacing:.15em; text-transform:uppercase;
  color:var(--muted-light); opacity:.72; margin:0;
  padding-top:1.1rem; border-top:1px solid var(--rule-light);
  display:inline-block;
}

/* the one section that earns the spectrum */
.is-spectrum .section-label{
  background:var(--spectrum);
  -webkit-background-clip:text; background-clip:text;
  color:transparent; -webkit-text-fill-color:transparent;
}
.is-spectrum .section-label::before{
  background:var(--signal); opacity:1;
  -webkit-text-fill-color:initial;
}
.is-spectrum .section-note{
  border-top-color:transparent;
  background:var(--spectrum) left top / 100% 1px no-repeat;
}

/* dark-zone text inversion */
.on-dark .section-heading{ color:var(--text-on-dark); }
.on-dark .section-body,
.on-dark .section-label,
.on-dark .section-note{ color:var(--muted-dark); }
.on-dark .section-note{ border-top-color:var(--rule-dark); }

/* =========================================================
   CTA
   ========================================================= */
.cta-heading{
  font-weight:500;
  font-size:clamp(1.553rem,3vw,3.367rem);
  letter-spacing:-.03em; line-height:.86;
}
.cta-row{
  display:flex; align-items:center; gap:2.2rem;
  margin:2.2rem 0 2rem; flex-wrap:wrap;
}
.cta-button{
  display:inline-flex; align-items:center; gap:1rem;
  padding:1.15rem 2.2rem;
  border-radius:100px;
  background:var(--paper); color:var(--ink);
  font-family:var(--font-mono); font-size:0.835rem;
  letter-spacing:.2em; text-transform:uppercase;
  position:relative; overflow:hidden;
  transition:transform .5s var(--ease), color .4s var(--ease);
}
.cta-button::before{
  content:''; position:absolute; inset:0;
  background:var(--spectrum);
  transform:translateY(101%);
  transition:transform .55s var(--ease);
}
.cta-button > *{ position:relative; z-index:1; }
.cta-button svg{ width:19px; height:19px; transition:transform .5s var(--ease); }
@media (hover:hover) and (pointer:fine){
  .cta-button:hover{ transform:translateY(-3px); }
  .cta-button:hover::before{ transform:translateY(0); }
  .cta-button:hover svg{ transform:translateX(5px); }
}

.cta-price{
  font-family:var(--font-display);
  font-weight:500;
  font-size:1.326rem; letter-spacing:-.02em;
  color:var(--text-on-dark);
}

/* =========================================================
   RESPONSIVE
   ========================================================= */
@media (max-width:1100px){
  .nav-links{ display:none; }
  .align-left { padding-right:44vw; }
  .align-right{ padding-left:44vw; }
  .align-left .section-inner,
  .align-right .section-inner{ max-width:48vw; }
}

@media (max-width:768px){
  #scroll-container{ height:660vh; }

  .align-left,.align-right{
    padding:2.4rem 6vw; text-align:left;
  }
  .align-right .section-inner{ margin-left:0; }
  .align-left .section-inner,
  .align-right .section-inner{ max-width:100%; }
  .align-right .section-label{ padding-left:2.6rem; padding-right:0; }
  .align-right .section-label::before{ left:0; right:auto; }
  .align-right .section-body{ margin-left:0; }

  /* legibility panel where the optic sits behind the copy — near-solid, so it
     reads as a page surface rather than a frosted card */
  .section-content .section-inner{
    background:rgba(233,238,239,.95);
    padding:1.8rem 1.5rem;
    border-left:1px solid var(--rule-light);
  }
  .on-dark .section-inner{
    background:rgba(8,12,21,.93);
    border-left-color:var(--rule-dark);
  }

  .section-label{ font-size:0.782rem; letter-spacing:.17em; margin-bottom:1.1rem; }
  .section-heading{ font-size:clamp(1.137rem,4.06vw,1.477rem); }
  .section-note{ font-size:0.778rem; letter-spacing:.1em; }

  .hero-heading{
    font-size:clamp(1.515rem,6.1vw,2.46rem);
    font-weight:500;
  }
  .hero-tagline{ font-size:0.948rem; }
  .cta-heading{ font-size:clamp(1.402rem,5.72vw,2.082rem); }
  .hero-rule{ display:none; }
  .hero-foot{ gap:1.8rem; }
  .spec-v{ font-size:0.967rem; }
  .scroll-indicator{ display:none; }

  .marquee-text{ font-size:22vw; }
  .progress-rail{ display:none; }
  .cta-row{ gap:1.4rem; }
}

@media (prefers-reduced-motion:reduce){
  .grain{ animation:none; }
  .scroll-line i{ animation:none; }
  *{ transition-duration:.01ms !important; }
}

/* =========================================================
   PORTFOLIO CONTEXT
   Back-link into the case-study index, plus the disclosure
   that this is an independent concept rather than the real
   District Vision site.
   ========================================================= */
.backlink{
  display:inline-flex; align-items:center; gap:.6rem;
  font-family:var(--font-mono); font-weight:400;
  font-size:0.82rem; letter-spacing:.19em; text-transform:uppercase;
  padding-bottom:.3rem; position:relative;
  transition:opacity .3s;
}
.backlink span{ transition:transform .4s var(--ease); display:inline-block; }
.backlink::after{
  content:''; position:absolute; left:0; bottom:0; height:1px; width:0;
  background:currentColor; transition:width .45s var(--ease);
}
.backlink:hover::after{ width:100%; }
@media (hover:hover) and (pointer:fine){
  .backlink:hover span{ transform:translateX(-4px); }
}

.disclaimer{
  max-width:46ch; text-transform:none; letter-spacing:.04em;
  line-height:1.7; opacity:.6;
}

@media (max-width:768px){
  .disclaimer{ max-width:100%; }
}

/* =========================================================
   ACT ONE — additions for the argument sections
   ========================================================= */
.section-body--quiet{ color:var(--muted-light); }
.section-body em{ font-style:normal; color:var(--ink); font-weight:500; }
.section-body strong{ font-weight:500; color:var(--ink); }
.section-inner:has(.pullquote) .section-body strong{
  display:block; margin-bottom:.5rem;
  font-size:clamp(1.05rem,1.6vw,1.35rem);
  line-height:1.25; letter-spacing:-.01em;
}
.on-dark .section-body strong{ color:var(--text-on-dark); }

/* The sentence the whole argument turns on. Broken onto its own line and set at
   display scale so it reads as the quotation it is, rather than as the tail of
   the line introducing it. It sits between body and heading in the type scale —
   big enough to stop you, not so big it competes with the section heading above.
   max-width is dropped because .section-body caps at 40ch, which at this size
   would break it into a narrow column. */
.section-body em.thesis-quote{
  display:block;
  margin-top:clamp(.85rem,1.6vw,1.4rem);
  max-width:none;
  font-family:var(--font-display);
  font-weight:500;
  font-size:clamp(1.024rem,1.42vw,1.346rem);
  line-height:1.12;
  letter-spacing:-.013em;
}
.on-dark .section-body em{ color:var(--text-on-dark); }

/* the pulled quote — the sentence the whole argument turns on */
.pullquote{
  margin:0 0 1.8rem; padding:0 0 0 1.4rem;
  border-left:2px solid var(--ink);
  font-family:var(--font-display);
  font-weight:500;
  font-size:clamp(1.061rem,1.48vw,1.383rem);
  line-height:1.24; letter-spacing:-.01em; color:var(--ink);
}

/* two tracks, literally running at different speeds */
.tracks{ display:grid; gap:clamp(2.1rem,3.2vw,3rem); margin:0 0 1.6rem; }
.track{ will-change:transform; }
.track-k{
  display:block; margin-bottom:.5rem;
  font-family:var(--font-mono); font-weight:400;
  font-size:0.797rem; letter-spacing:.22em; text-transform:uppercase;
  color:var(--muted-light);
}
.track-v{
  margin:0; font-size:clamp(0.917rem,0.94vw,0.971rem);
  line-height:1.55; color:var(--ink);
  padding-left:1rem; border-left:1px solid var(--rule-light);
}
.align-right .track-v{
  padding-left:0; padding-right:1rem;
  border-left:none; border-right:1px solid var(--rule-light);
}

/* the proposition's three claims */
.claims{ list-style:none; margin:1.8rem 0 0; padding:0; display:grid; gap:1.3rem; }
.claims li{ padding-top:1rem; border-top:1px solid var(--rule-dark); }
.claim-k{
  display:block; margin-bottom:.45rem;
  font-family:var(--font-mono); font-size:0.805rem;
  letter-spacing:.2em; text-transform:uppercase; color:var(--text-on-dark);
}
.claims p{ margin:0; font-size:0.941rem; line-height:1.55; color:var(--muted-dark); }


/* =========================================================
   THE INSIGHT — the one centred moment
   ========================================================= */
.section-insight{ padding:0 5vw; text-align:center; }
.insight-inner{ max-width:900px; margin:0 auto; }
.section-insight .section-label{
  padding-left:0; display:inline-block; color:var(--muted-dark);
}
.section-insight .section-label::before{ display:none; }

.insight-heading{
  font-family:var(--font-display);
  font-weight:500;
  font-size:clamp(1.288rem,2.25vw,2.158rem);
  line-height:1.02; letter-spacing:-.018em;
  margin:0 0 1.6rem; color:var(--text-on-dark);
}
/* One block now, not two halves. A single child left in a 1fr 1fr grid would
   occupy only the left column, so the grid collapses to one — and takes the
   kicker's measure below it, because a single paragraph run full width at this
   size is a worse line length than the two narrow columns ever were. */
.insight-pair{
  display:grid; grid-template-columns:1fr; gap:2.6rem;
  margin:0 auto 2.4rem; max-width:52ch;
}
.ipair{ padding-top:1rem; border-top:1px solid var(--rule-dark); }
.ipair p{ margin:0; font-size:0.93rem; line-height:1.6; color:var(--muted-dark); }

.insight-kicker{
  margin:0 auto; max-width:34ch;
  font-family:var(--font-display);
  font-weight:500;
  font-size:clamp(1.241rem,2.05vw,1.673rem);
  line-height:1.28; letter-spacing:-.012em; color:var(--text-on-dark);
}

/* =========================================================
   ACTS TWO & THREE — the working document
   These scroll up over the fixed film, so they carry their
   own background and sit above the canvas layer.
   ========================================================= */
.act{ position:relative; z-index:30; }
.act-dark{ background:var(--bg-dark); color:var(--text-on-dark); }
.act-light{ background:var(--paper); color:var(--text-on-light); }

/* The brief and the three strategies, on a pale green.

   Everything inside this act was written against a dark ground and reads the
   *-dark tokens — about twenty-five rules. Rather than rewrite each one, the
   tokens are REDEFINED for this subtree, so every var(--text-on-dark) inside
   resolves to ink, every var(--rule-dark) to the light rule, and so on. Custom
   properties cascade, so the rules themselves need no edit at all. */
.act-green{
  background:var(--paper-green);
  color:var(--text-on-light);
  --text-on-dark: var(--ink);
  --muted-dark:   var(--muted-light);
  --rule-dark:    var(--rule-light);
  --signal-lift:  var(--signal);
}

/* The three things a token remap cannot reach: hover tints and the active tint
   button spell their colours out literally, and each was picked to sit on the
   dark ground. */
.act-green .brief-row:hover,
.act-green .steps li:hover{ background:rgba(20,32,42,.045); }
.act-green .tint-btn.is-on{
  color:var(--paper-green); background:var(--ink); border-color:var(--ink);
}

.doc-sec{ padding:5vh 0 9vh; }
.doc-wrap{ max-width:1240px; margin:0 auto; padding:0 5vw; }

.doc-head{ margin-bottom:1.6rem; max-width:24ch; }
.doc-head .section-label{ padding-left:0; }
.doc-head .section-label::before{ display:none; }
.act-dark .doc-head .section-label{ color:var(--muted-dark); }

.doc-h2{
  font-family:var(--font-display);
  font-weight:500;
  font-size:clamp(1.326rem,2.4vw,2.309rem);
  line-height:.98; letter-spacing:-.019em; margin:0;
}
.act-dark .doc-h2{ color:var(--text-on-dark); }

/* ---- the brief ---- */
.brief{ margin:0; }
.brief-row{
  display:grid; grid-template-columns:200px 1fr; gap:2.5rem;
  padding:1.6rem 1rem 1.6rem 0;
  border-top:1px solid var(--rule-dark);
  transition:background .45s var(--ease), padding-left .45s var(--ease);
}
.brief-row:last-child{ border-bottom:1px solid var(--rule-dark); }
.brief-row:hover{ background:rgba(233,238,239,.045); padding-left:1rem; }
.brief-row dt{
  font-family:var(--font-mono); font-weight:400;
  font-size:0.812rem; letter-spacing:.22em; text-transform:uppercase;
  color:var(--muted-dark); padding-top:.3rem;
  transition:color .4s var(--ease);
}
.brief-row:hover dt{ color:var(--ink); }
.brief-row dd{
  margin:0; font-size:clamp(0.948rem,1.09vw,1.069rem);
  line-height:1.5; color:var(--text-on-dark);
}
.brief-row--never dd{ color:var(--muted-dark); }

/* ---- strategies ---- */
.terr{ padding-top:5rem; margin-top:5rem; border-top:1px solid var(--rule-dark); }
.terr:first-of-type{ padding-top:0; margin-top:0; border-top:none; }

.terr-head{
  display:flex; flex-wrap:wrap; align-items:baseline; gap:1rem; margin-bottom:1rem;
  font-family:var(--font-mono); font-size:0.805rem;
  letter-spacing:.22em; text-transform:uppercase;
}
.terr-idx{ color:var(--muted-light); }
.terr-kind{ color:var(--muted-dark); }
/* The seasonal window, pinned to the far end of the metadata row. Light Hours
   runs on early light, so it only works spring and summer — that is a property
   of the strategy, which is what this row is for, rather than another sentence
   in prose that has been cut hard. */
.terr-season{ margin-left:auto; color:var(--muted-dark); opacity:.85; }

.terr-ttl{
  font-family:var(--font-display);
  font-weight:500;
  font-size:clamp(1.326rem,2.29vw,2.082rem);
  line-height:1; letter-spacing:-.02em;
  margin:0 0 1.6rem; color:var(--text-on-dark);
}
.terr-lede{
  max-width:62ch; margin:0 0 2.6rem;
  font-size:clamp(0.948rem,1.03vw,1.016rem); line-height:1.6;
  color:var(--muted-dark);
}
/* Emphasis here has to go LIGHTER, not darker. The strategies run on a deep
   forest ground even though the section carries no .on-dark class, so the
   .section-body strong treatment — which lifts text toward --ink — would have
   hidden this line rather than stressed it. */
.terr-lede strong{ font-weight:500; color:var(--text-on-dark); }
.terr-grid{ display:grid; grid-template-columns:1fr 1fr; gap:4rem; align-items:start; }
.terr-copy p{
  margin:0 0 1.2rem; max-width:52ch;
  font-size:clamp(0.941rem,0.99vw,0.986rem); line-height:1.62; color:var(--muted-dark);
}
.terr-proof{ display:grid; gap:1.6rem; margin-top:2.2rem; }
.proof-k{
  display:block; margin-bottom:.45rem;
  font-family:var(--font-mono); font-size:0.797rem;
  letter-spacing:.22em; text-transform:uppercase; color:var(--text-on-dark);
}
.terr-proof p{ margin:0; font-size:0.926rem; line-height:1.58; }

/* ---- the tint switcher ---- */
.tinter{ margin:-1.4rem 0 0; }
.tint-stage{
  position:relative; overflow:hidden;
  border:1px solid var(--rule-dark);
  background:#e9e7e2;
}
.tint-stage img{
  display:block; width:100%; height:auto;
  filter:brightness(.95) contrast(1.02);
}
/* The tints are photographs now, not a colour wash over one frame — every
   reality/lens pair is its own simulated image — so the multiply overlay this
   replaced is gone. */
/* Bigger, solid, and captioned. At 2.4rem and 55% opacity these read as a
   photo-viewer affordance you scan past — the point of this figure is that
   there are four realities to compare, and nothing said so. Now: a solid ink
   pill on a lit ring, and a standing "4 realities" label under the frame so the
   control announces itself rather than waiting to be discovered. */
.lens-nav{
  position:absolute; top:50%; transform:translateY(-50%);
  width:3.1rem; height:3.1rem; display:grid; place-items:center;
  font-size:1.006rem; line-height:1; cursor:pointer;
  color:var(--paper); background:var(--ink);
  border:2px solid rgba(233,238,239,.85); border-radius:100px;
  box-shadow:0 6px 20px rgba(0,0,0,.38);
  transition:transform .3s var(--ease), background .3s var(--ease), box-shadow .3s var(--ease);
}
.lens-nav:hover{
  background:var(--signal); transform:translateY(-50%) scale(1.09);
  box-shadow:0 8px 26px rgba(0,0,0,.5);
}
.lens-nav:focus-visible{ outline:2px solid var(--signal); outline-offset:3px; }
.lens-prev{ left:1rem; }
.lens-next{ right:1rem; }

/* the standing invitation — it says what the arrows are for */
.lens-hint{
  position:absolute; left:50%; bottom:.85rem; transform:translateX(-50%);
  display:flex; align-items:center; justify-content:center; gap:.5rem;
  text-align:center;
  padding:.42rem .95rem; border-radius:100px;
  background:rgba(20,32,42,.72); backdrop-filter:blur(6px);
  font-family:var(--font-mono); font-size:0.79rem;
  letter-spacing:.2em; text-transform:uppercase; color:var(--paper);
  pointer-events:none;
}

/* a slow nudge on the forward arrow until it is first used, so the control is
   noticed without anything blinking at you */
@keyframes lens-nudge{
  0%,88%,100%{ transform:translateY(-50%) translateX(0); }
  93%        { transform:translateY(-50%) translateX(5px); }
}
.lens-next:not(.is-used){ animation:lens-nudge 4.2s var(--ease) infinite; }
@media (prefers-reduced-motion:reduce){ .lens-next{ animation:none; } }

.lens-reality{
  display:flex; align-items:baseline; justify-content:space-between; gap:1rem;
  margin:.8rem 0 0;
  font-family:var(--font-mono); font-size:0.805rem;
  letter-spacing:.2em; text-transform:uppercase; color:var(--text-on-dark);
}
.lens-reality em{ font-style:normal; color:var(--muted-dark); }
.tint-controls{ display:flex; flex-wrap:wrap; gap:.5rem; margin-top:1rem; }
.tint-btn{
  font-family:var(--font-mono); font-size:0.797rem;
  letter-spacing:.18em; text-transform:uppercase;
  color:var(--muted-dark); background:transparent;
  border:1px solid var(--rule-dark); border-radius:100px;
  padding:.55rem 1.05rem; cursor:pointer;
  transition:color .35s var(--ease), border-color .35s var(--ease), background .35s var(--ease);
}
.tint-btn:hover{ color:var(--text-on-dark); border-color:var(--muted-dark); }
.tint-btn.is-on{
  color:var(--bg-dark); background:var(--text-on-dark); border-color:var(--text-on-dark);
}
.tint-note{
  margin-top:.9rem; font-size:0.91rem; line-height:1.55;
  color:var(--muted-dark); min-height:1.6em;
}

/* ---- numbered steps ---- */
.steps,.monday{ list-style:none; margin:0; padding:0; display:grid; gap:0; }
.steps li,.monday li{
  display:grid; grid-template-columns:5rem 1fr; gap:1.5rem;
  padding:1.8rem 1rem 1.8rem 0;
  border-top:1px solid var(--rule-dark);
  transition:padding-left .45s var(--ease), background .45s var(--ease);
}
.steps li:last-child,.monday li:last-child{ border-bottom:1px solid var(--rule-dark); }
.steps li:hover,.monday li:hover{ padding-left:1rem; background:rgba(233,238,239,.04); }
.step-n{
  font-family:var(--font-display);
  font-weight:500;
  font-size:1.137rem; letter-spacing:-.01em; color:var(--signal-lift);
  line-height:1.1;
}
.steps h4,.monday h4{
  margin:0 0 .5rem;
  font-family:var(--font-display);
  font-weight:500;
  font-size:clamp(0.967rem,1.27vw,1.157rem);
  line-height:1.2; letter-spacing:-.01em; color:var(--text-on-dark);
}
.steps p,.monday p{
  margin:0; max-width:60ch;
  font-size:clamp(0.926rem,0.96vw,0.971rem); line-height:1.6; color:var(--muted-dark);
}

/* Act three sits on paper — invert the borrowed dark tokens */
.act-light .steps li,.act-light .monday li{ border-color:var(--rule-light); }
.act-light .steps li:hover,.act-light .monday li:hover{ background:rgba(20,32,42,.035); }
.act-light .steps h4,.act-light .monday h4{ color:var(--ink); }
.act-light .steps p,.act-light .monday p{ color:var(--muted-light); }
.act-light .step-n{ color:var(--ink); opacity:.32; }

/* =========================================================
   GLARE TEST — strategy two, step 02, made playable
   A port of the standalone instrument. Two rules govern it.

   One: it carries its OWN palette, scoped to .glare-test. The
   instrument names its tokens paper / ink / rule, and so does this
   file — taking the room to night must not reach the page. This is
   the .act-green trick above, applied one level further down.

   Two: therefore every colour inside comes from --gt-*, never from
   --muted-light or --ink directly, or it vanishes at night. Only
   the boxes change; the ground under them stays the act's paper,
   so the figure darkens like a screen in a lit room rather than
   taking the page with it.

   The room is THREE STATES, not a crossfade. Blending a light
   palette continuously into a dark one has to pass through equal
   lightness: at the midpoint the ink and the ground meet on the
   same grey and the wall goes blank — measured at 1.04:1, which is
   invisible, and it sits exactly on the dusk keyframe. The slider
   still moves the physics continuously. Only the palette snaps,
   between the three states already named on the ticks under it.
   Each pair below is checked: 10.2:1 at its worst.
   ========================================================= */
.glare-test{
  --gt-panel:#E7EFE9; --gt-ink:#1D1D1D; --gt-dim:#585F59;
  --gt-rule:rgba(29,29,29,.16);

  margin:3.2rem 0 0; padding:0;
  display:grid; gap:1rem;
}

/* Names the figure, in the same mono label the strategy headers use. Sits
   outside the panel, so it takes the section's own muted tone rather than the
   panel's — which means it follows the act's palette remap like everything
   else on the page. */
.gt-label{
  font-family:var(--font-mono); font-size:.625rem;
  letter-spacing:.2em; text-transform:uppercase;
  color:var(--muted-dark);
}
.glare-test[data-room="dusk"]{
  --gt-panel:#B5C0B7; --gt-ink:#171C18; --gt-dim:#414843;
  --gt-rule:rgba(23,28,24,.22);
}
.glare-test[data-room="night"]{
  --gt-panel:#141B15; --gt-ink:#E4EAE5; --gt-dim:#97A399;
  --gt-rule:rgba(228,234,229,.22);
}
/* the room changes as a state, so anything carrying a colour eases with it.
   The rules below that declare their own transition (opacity, width, filter)
   override this deliberately — those elements are already animating. */
.glare-test *{
  transition:color .45s var(--ease), background-color .45s var(--ease),
             border-color .45s var(--ease);
}
/* ---- stage ---- */
.gt-stage{
  display:grid; grid-template-columns:minmax(0,1.36fr) minmax(272px,.64fr);
  gap:1.375rem;
  /* both boxes run to the same height — they read as one instrument, and the
     panel ending short of the wall made it look like an afterthought bolted on
     beside it */
  align-items:stretch;
}
.gt-wall{
  position:relative; overflow:hidden;
  display:flex; flex-direction:column; min-height:452px;
  padding:2.125rem 1.875rem 1.625rem;
  border:1px solid var(--gt-rule); background:var(--gt-panel); color:var(--gt-ink);
  transition:background .45s var(--ease), border-color .45s var(--ease), color .45s var(--ease);
}
.gt-walltop{
  position:relative; z-index:3;
  display:flex; justify-content:space-between; align-items:baseline;
  font-size:.625rem; letter-spacing:.18em; text-transform:uppercase;
  color:var(--gt-dim); font-weight:500;
}
/* ---- the two views ----
   Stacked in one grid cell rather than swapped in and out of flow, so the wall
   is always as tall as the taller of them and switching never jolts the page.
   The hidden one is visibility:hidden, so it is out of the tab order too. */
.gt-viewer{
  position:relative; z-index:3; margin-top:1.375rem;
  display:grid;
}
.gt-view{
  grid-area:1 / 1; min-width:0;
  /* the scene is 16:9 and the chart is shorter — centring keeps the shorter
     one from hanging off the top of the cell the taller one sets */
  display:grid; align-content:center;
  opacity:0; visibility:hidden;
  transition:opacity .4s var(--ease), visibility .4s var(--ease);
}
.gt-view.is-on{ opacity:1; visibility:visible; }

/* The arrows sit under the frame rather than over it: this viewer holds an eye
   chart half the time, and a pill floating on top of the letters would be
   sitting on the thing you are being asked to read. */
.gt-viewnav{
  position:relative; z-index:3;
  display:flex; align-items:center; gap:.6rem;
  margin-top:1.1rem;
}
.gt-nav{
  width:2.4rem; height:2.4rem; flex:none;
  display:grid; place-items:center; cursor:pointer;
  font-size:.9rem; line-height:1;
  color:var(--gt-panel); background:var(--gt-ink);
  border:1px solid var(--gt-ink); border-radius:100px;
  transition:transform .3s var(--ease), background .3s var(--ease),
             color .45s var(--ease), border-color .45s var(--ease);
}
.gt-nav:hover{ background:var(--signal); border-color:var(--signal); color:#FFF8EC; transform:scale(1.08); }
.gt-nav:focus-visible{ outline:2px solid var(--signal); outline-offset:3px; }
.gt-viewhint{
  font-family:var(--font-mono); font-size:.625rem;
  letter-spacing:.2em; text-transform:uppercase; color:var(--gt-dim);
}
.gt-viewcount{
  margin-left:auto; font-style:normal;
  font-family:var(--font-mono); font-variant-numeric:tabular-nums;
  font-size:.625rem; letter-spacing:.2em; color:var(--gt-dim);
}
/* a slow nudge until the arrows are first used — the same invitation the tint
   switcher makes in Strategy One, so the two figures behave alike */
@keyframes gt-nudge{
  0%,88%,100%{ transform:translateX(0); }
  93%        { transform:translateX(4px); }
}
#gt-next:not(.is-used){ animation:gt-nudge 4.2s var(--ease) infinite; }
@media (prefers-reduced-motion:reduce){ #gt-next{ animation:none; } }

/* ---- the chart ---- */
/* Centred as one block rather than row by row: the rows are a label column, a
   glyph column and a read mark, and centring each row independently would let
   the label column go ragged as the glyphs shrink down the chart. Sizing to
   max-content and centring that keeps the columns aligned to each other. */
.gt-chart{
  position:relative; z-index:3; display:flex; flex-direction:column; gap:.5rem;
  width:max-content; max-width:100%; margin-inline:auto;
}
.gt-row{ display:flex; align-items:baseline; gap:.9375rem; }
.gt-rowlab{
  min-width:34px; opacity:.65;
  font-family:var(--font-mono); font-variant-numeric:tabular-nums;
  font-size:.656rem; color:var(--gt-dim);
}
.gt-glyphs{
  font-family:var(--font-mono); font-weight:500;
  font-size:clamp(19px,3vw,30px); letter-spacing:.30em; line-height:1.05;
  transition:opacity .5s var(--ease);
}
/* The "last read" mark. :root keeps --signal off type — it fails AA at any
   label size — so the row is marked with a fill and the word stays in ink. */
.gt-readmark{
  display:inline-flex; align-items:center; gap:.4rem; opacity:0;
  font-size:.625rem; letter-spacing:.1em; text-transform:uppercase;
  color:var(--gt-ink); transition:opacity .35s var(--ease);
}
.gt-readmark::before{
  content:""; width:6px; height:6px; border-radius:50%; flex:none;
  background:var(--signal);
}
.gt-row.is-lastread .gt-readmark{ opacity:1; }

/* ---- the light in the room ---- */
.gt-glareorb{
  position:absolute; z-index:2; right:-64px; top:42%;
  width:330px; height:330px; border-radius:50%; opacity:0; pointer-events:none;
  background:radial-gradient(circle,
    rgba(255,244,214,.98) 0%, rgba(255,232,178,.6) 26%, rgba(255,226,164,0) 68%);
  transition:opacity .5s var(--ease);
}
.gt-veil{
  position:absolute; inset:0; z-index:2; opacity:0; pointer-events:none;
  background:linear-gradient(255deg,
    rgba(255,240,206,.92) 0%, rgba(255,240,206,.34) 46%, rgba(255,240,206,.10) 78%);
  transition:opacity .5s var(--ease);
}
.gt-tintwash{
  position:absolute; inset:0; z-index:2; opacity:0; pointer-events:none;
  mix-blend-mode:multiply;
  transition:opacity .5s var(--ease), background .5s var(--ease);
}

/* ---- the score ---- */
.gt-wallfoot{
  margin-top:auto; position:relative; z-index:3; padding-top:1.25rem;
  display:flex; justify-content:space-between; align-items:flex-end;
  gap:1rem; flex-wrap:wrap;
}
.gt-score{ display:flex; align-items:baseline; gap:.625rem; }
.gt-num{
  font-family:var(--font-mono); font-weight:500; font-size:2.25rem;
  font-variant-numeric:tabular-nums; letter-spacing:-.02em;
}
.gt-unit{
  font-size:.625rem; letter-spacing:.15em; text-transform:uppercase;
  color:var(--gt-dim); font-weight:500;
}
/* With no readings table, this is the only spoken result. It carries the whole
   payoff, so it is set at reading weight rather than as a footnote. */
.gt-verdict{
  margin:0; max-width:32ch; text-align:right;
  font-size:.875rem; line-height:1.5; color:var(--gt-ink);
}

/* ---- panel ---- */
.gt-panel{
  display:flex; flex-direction:column;
  border:1px solid var(--gt-rule); background:var(--gt-panel); color:var(--gt-ink);
  transition:background .45s var(--ease), border-color .45s var(--ease), color .45s var(--ease);
}
/* The panel is now as tall as the wall, so the surplus is shared between the
   blocks instead of pooling as dead space under the last one. Grown from their
   natural sizes rather than split evenly: the lens block is more than twice the
   height of the other two, and equal thirds would crush its swatches. */
.gt-pblock{ flex:1 1 auto; }
.gt-pblock{ padding:1.125rem 1.125rem 1.25rem; border-bottom:1px solid var(--gt-rule); }
.gt-pblock:last-child{ border-bottom:none; }
.gt-plabel{
  display:flex; justify-content:space-between; align-items:center;
  margin-bottom:.75rem;
  font-size:.625rem; letter-spacing:.2em; text-transform:uppercase;
  color:var(--gt-dim); font-weight:600;
}
.gt-val{
  font-family:var(--font-mono); font-size:.6875rem;
  letter-spacing:.05em; text-transform:none; color:var(--gt-ink);
}
.gt-lenses{ display:flex; flex-direction:column; gap:6px; }
.gt-lens{
  display:flex; align-items:center; gap:.625rem; width:100%;
  padding:.5625rem .6875rem; cursor:pointer; text-align:left;
  border:1px solid var(--gt-rule); background:transparent; color:var(--gt-ink);
  font-family:var(--font-body); font-size:.781rem; font-weight:400;
  transition:border-color .2s, background .2s;
}
.gt-lens:hover{ border-color:color-mix(in oklab,var(--gt-ink),transparent 55%); }
.gt-lens[aria-pressed="true"]{
  border-color:var(--gt-ink);
  background:color-mix(in oklab,var(--gt-ink),transparent 94%);
}
.gt-lens:focus-visible{ outline:2px solid var(--signal); outline-offset:2px; }
.gt-swatch{
  width:17px; height:17px; border-radius:50%; flex:none;
  border:1px solid color-mix(in oklab,var(--gt-ink),transparent 78%);
}
.gt-sub{
  margin-left:auto; font-family:var(--font-mono);
  font-size:.625rem; color:var(--gt-dim);
}
.gt-toggle{
  width:100%; padding:.75rem; cursor:pointer;
  border:1px solid var(--gt-ink); background:transparent; color:var(--gt-ink);
  font-family:var(--font-body); font-size:.719rem; font-weight:500;
  letter-spacing:.14em; text-transform:uppercase;
  transition:background .25s, color .25s, border-color .25s;
}
.gt-toggle[aria-pressed="true"]{
  background:var(--signal); border-color:var(--signal); color:#FFF8EC;
}
.gt-toggle:focus-visible{ outline:2px solid var(--signal); outline-offset:2px; }
.gt-range{ width:100%; accent-color:var(--signal); cursor:pointer; }
.gt-range:focus-visible{ outline:2px solid var(--signal); outline-offset:3px; }
.gt-ticks{
  display:flex; justify-content:space-between; margin-top:6px;
  font-family:var(--font-mono); font-size:.594rem;
  letter-spacing:.1em; text-transform:uppercase; color:var(--gt-dim);
}

/* ---- the live view ---- */
.gt-viewwrap{
  position:relative; overflow:hidden; aspect-ratio:16/9;
  border:1px solid var(--gt-rule); background:#0A0A08;
}
.gt-viewwrap img{
  width:100%; height:100%; object-fit:cover; display:block;
  transition:filter .5s var(--ease); will-change:filter;
}
.gt-vveil,.gt-vtint{
  position:absolute; inset:0; pointer-events:none;
  transition:opacity .5s var(--ease), background .5s var(--ease);
}
.gt-vveil{
  opacity:0;
  background:linear-gradient(250deg,
    rgba(255,242,212,.98) 0%, rgba(255,240,206,.5) 44%, rgba(255,238,200,.14) 80%);
}
.gt-vtint{ opacity:0; mix-blend-mode:multiply; }

@media (max-width:1000px){
  .gt-stage{ grid-template-columns:1fr; }
  .gt-wall{ min-height:0; }
}
@media (max-width:720px){
  .gt-wall{ padding:1.5rem 1.25rem 1.25rem; }
  .gt-verdict{ max-width:none; text-align:left; }
  .gt-viewhint{ display:none; }
  .gt-num{ font-size:1.875rem; }
}
@media (prefers-reduced-motion:reduce){
  .glare-test *,
  .glare-test *::before{ transition:none !important; }
}

/* ---- the test ---- */
.tests{
  display:grid; grid-template-columns:repeat(2,minmax(0,1fr));
  gap:2.8rem 3rem; max-width:66rem;
}
.test-card{ padding-top:1.2rem; border-top:1px solid var(--rule-light); }
.test-k{
  display:block; margin-bottom:.7rem;
  font-family:var(--font-mono); font-size:0.805rem;
  letter-spacing:.22em; text-transform:uppercase; color:var(--muted-light);
}
.test-card p{
  margin:0; font-size:clamp(0.926rem,0.96vw,0.971rem);
  line-height:1.6; color:var(--muted-light);
}
.test-kicker{
  margin:4rem 0 0;
  font-family:var(--font-display);
  font-weight:500;
  font-size:clamp(1.006rem,1.43vw,1.363rem);
  line-height:1.25; letter-spacing:-.013em; color:var(--ink);
  max-width:24ch;
}


/* ---- footer ---- */
.foot-mail{
  display:block; margin-top:.6rem;
  font-family:var(--font-display);
  font-weight:500;
  font-size:clamp(0.986rem,1.39vw,1.251rem); letter-spacing:-.013em; color:var(--ink);
  position:relative;
}
.foot-mail::after{
  content:''; position:absolute; left:0; bottom:-.15em; height:1px; width:0;
  background:var(--ink); transition:width .5s var(--ease);
}
.foot-mail:hover::after{ width:100%; }


/* ---- scroll reveals (JS-gated so no-JS still reads) ---- */
.js-reveal [data-reveal]{ opacity:0; transform:translateY(28px); }

/* =========================================================
   RESPONSIVE — acts two & three
   ========================================================= */
@media (max-width:1000px){
  .terr-grid{ grid-template-columns:1fr; gap:2.5rem; }
  .tests{ grid-template-columns:1fr; gap:2rem; }
  .insight-pair{ grid-template-columns:1fr; gap:1.8rem; }
}

@media (max-width:768px){
  .doc-sec{ padding:9vh 0; }
  .doc-head{ margin-bottom:3rem; }
  .brief-row{ grid-template-columns:1fr; gap:.6rem; padding:1.3rem 0; }
  .brief-row:hover{ padding-left:0; }
  .steps li,.monday li{ grid-template-columns:2.6rem 1fr; gap:1rem; padding:1.4rem 0; }
  .steps li:hover,.monday li:hover{ padding-left:0; }
  .step-n{ font-size:0.986rem; }
  .insight-heading{ font-size:clamp(1.137rem,4.31vw,1.477rem); }
  .tracks{ gap:2.4rem; }
}

/* =========================================================
   POLISH
   ========================================================= */

/* A full sentence deserves prose, not a mono caption — the
   hairline stays so it still reads as a footing to the block. */
.section-note--prose{
  font-family:var(--font-body); font-weight:400;
  font-size:clamp(0.917rem,0.94vw,0.971rem);
  letter-spacing:0; text-transform:none; line-height:1.6;
  opacity:1; color:var(--muted-light); max-width:46ch;
}

/* Display type breaks on its own terms rather than leaving orphans */
/* Only headings without manual <br> breaks get balanced — the rest
   already carry their line breaks in the markup. */
.insight-kicker,.test-kicker,.terr-lede,
.track-v,.section-note,.pullquote,.section-body,
.claims li p,.ipair p{ text-wrap:balance; }

/* In the document acts the page scrolls continuously under the
   fixed header, so big headings would run through the nav. Act one
   never needs this — its sections are centred in the viewport. */
.site-header::before{
  content:''; position:absolute; inset:0;
  pointer-events:none; z-index:-1; opacity:0;
  transition:opacity .4s var(--ease);
  background:linear-gradient(to bottom,
    var(--paper) 0%, var(--paper) 52%, rgba(233,238,239,0) 100%);
}
body.in-doc .site-header::before{ opacity:1; }
body.in-doc.is-dark .site-header::before{
  background:linear-gradient(to bottom,
    var(--bg-dark) 0%, var(--bg-dark) 52%, rgba(8,12,21,0) 100%);
}


/* A strategy's step list already ends on a rule; the next
   strategy's top border was doubling it. */
.steps li:last-child{ border-bottom:none; }

/* The display headings carry their own line breaks, so the column
   must be wide enough not to re-wrap them. */
.doc-head{ max-width:none; }
.doc-h2{ max-width:22ch; }

/* =========================================================
   COPY GROUND OVER THE LANDSCAPE FRAMES
   The back half of the film is photographic, so a flat
   full-screen scrim strong enough to carry text also turns
   the desert to mud. Give the copy its own directional
   ground on its own side and leave the picture alone.
   ========================================================= */
#scroll-container .scroll-section.on-dark::before{
  /* far taller than the viewport so the gradient box never shows an edge —
     the section itself is only as tall as its copy */
  content:''; position:absolute; top:-75vh; bottom:-75vh; left:0; right:0;
  pointer-events:none;
  background:linear-gradient(to left,
    rgba(6,10,18,.88) 0%, rgba(6,10,18,.74) 24%, rgba(6,10,18,0) 60%);
}
#scroll-container .scroll-section.on-dark.align-left::before{
  background:linear-gradient(to right,
    rgba(6,10,18,.88) 0%, rgba(6,10,18,.74) 24%, rgba(6,10,18,0) 60%);
}
#scroll-container .scroll-section .section-inner{ position:relative; z-index:1; }

/* The insight sits over lit frames — its supporting copy was
   reading as grey-on-grey at the old muted tone. */
.insight-lede,.ipair p{ color:#C6C2BA; }
.insight-inner{
  text-shadow:0 1px 30px rgba(4,7,13,.85), 0 1px 6px rgba(4,7,13,.5);
}

@media (max-width:768px){
  /* the mobile panel already supplies the ground */
  #scroll-container .scroll-section.on-dark::before{ display:none; }
}
.section-insight .section-label{ color:#D8D4CC; }

/* The insight is the one centred block, so its copy sits over the frame
   rather than beside it. A horizontal band — not a circle — carries the
   contrast now that the aperture is gone. */
#scroll-container .section-insight::before{
  content:''; position:absolute; top:-75vh; bottom:-75vh; left:0; right:0;
  pointer-events:none;
  background:linear-gradient(to bottom,
    rgba(6,10,18,0) 0%, rgba(6,10,18,.56) 28%,
    rgba(6,10,18,.56) 72%, rgba(6,10,18,0) 100%);
}
.insight-inner{ position:relative; z-index:1; }

/* ---- the film ---- */
/* Sound is the point of this cut — score plus ambience — so it does not
   autoplay: browsers block audible autoplay anyway, and a portfolio page that
   starts talking at you is worse than one you press play on. preload="none"
   keeps 7.6MB off the initial load; the poster holds the frame until then. */
#film{ padding-top:0; }
/* the label stands alone here, so it does not need the 1.6rem a heading block
   reserves for the h2 beneath it */
.doc-head--bare{ margin-bottom:1rem; }
.film{ margin:0; }
.film video{
  display:block; width:100%; height:auto;
  border:1px solid var(--rule-light);
  background:var(--ink);
}


/* ---- accessibility: transparency and contrast preferences ----
   Honours two OS settings the page previously ignored. Both raise opacity and
   remove blur rather than restyling: the layers keep their job as surfaces,
   they just stop being see-through. */
@media (prefers-reduced-transparency: reduce){
  [class*="chrome"],[class*="glass"],[class*="rail"],[class*="hint"],
  [class*="lens-nav"],[class*="header"],[class*="tint"],[class*="panel"]{
    backdrop-filter:none !important; -webkit-backdrop-filter:none !important;
  }
}
@media (prefers-contrast: more){
  [class*="chrome"],[class*="glass"],[class*="header"],[class*="panel"]{
    backdrop-filter:none !important; -webkit-backdrop-filter:none !important;
  }
}

html{ font-optical-sizing:auto; }
