/* ============================================================
   NAV — the site header, one definition for every page.

   NO PAGE CARRIES THE PILL ANY MORE: Vishal had it removed from the
   homepage on 2026-09-26 and from every case page, at every width, on
   2026-09-27. Its rules below and in the per-page phone sheets are
   unused; the theme toggle is the only live part of the nav layer.

   This file is the single source of truth for the pill. It was
   pulled out of style.css so that bloom / fire-island / sarson /
   visual — which carry no stylesheet of their own and used to have
   the nav painted INTO their SVG artwork — render exactly the same
   header as index.html rather than a look-alike.

   Geometry is the Figma rect: x=425.5 y=39.5 w=589 h=38 r=19 with a
   1px #EBEBEB stroke. A stroke paints from the centre, so the
   border-box is 590x39 at 425,39. Labels are PP Neue Montreal Book
   (350) 12/12 on a 53 baseline, ink lefts 487 / 619 / 755 / 918.

   Only the Book weight is declared here: these four pages load no
   other type, and the nav is the only text they have.
   ============================================================ */
/* ============================================================
   PALETTE — five named colours, then the roles they play.

   Vishal's spec:
     Warm Ivory   main background
     Soft Black   hero / dark sections
     Charcoal     primary text
     Warm Grey    secondary text / dividers
     Burnt Orange small accent only          Ratio 70 / 25 / 5

   The five anchors are FIXED — they never change with the theme.
   Everything below them is a role that maps onto an anchor, and
   `html.inv` swaps which anchor each role points at. So retuning the
   brand is five hex values here and nothing else anywhere.

   Only index.html carries `inv`, so the light scheme is homepage-only
   until another page opts in by adding the class to its <html>.

   NOT themed on purpose:
     · THE HERO. It keeps its ivory plane, its soft-black plate and
       the type each carries, in both modes — Vishal's call. Only
       .hero__veil follows the theme — it is the handoff colour, and
       is currently inert (the wash was removed; see js/main.js).
     · the two glass panels (s4, s9) and the copy on them. They float
       over the sections' own photography, which no theme touches.
     · the nav pill and the theme toggle — they are contrast-adaptive
       and pick their ink from the pixels under them (main.js
       initNavContrast), so they use the anchors directly.
   ============================================================ */
:root{
  /* ---- the five anchors ---- */
  --c-ivory:#F7F4EE;
  /* Pure black since 2026-09-27, at Vishal's request (was #141110). The name
     stayed so nothing else had to change. js/main.js keeps copies (SOFT_BLACK
     and the two page-transition overlays). */
  --c-soft-black:#000000;
  --c-charcoal:#2A2724;
  /* 4.56:1 on the ivory — AA for the small secondary lines it carries.
     #7D746A read closer to the spec's grey but landed at 4.18. */
  --c-warm-grey:#776E64;
  /* Burnt Orange. Deepened from #C15A28 once the CTAs became solid fills:
     ivory label text on the lighter tone measured 4.02, under AA. At #B04E1F
     the label reads 4.84 and the accent still clears 3:1 as a stroke on BOTH
     grounds (4.84 on ivory, 3.96 on black). */
  --c-accent:#B04E1F;
  --c-ivory-0:rgba(247,244,238,0); /* transparent ivory, for the sweep's stops */

  /* ---- roles: DARK theme (Soft Black ground, Warm Ivory type) ---- */
  --c-bg:var(--c-soft-black);
  --c-ink:var(--c-ivory);
  --c-secondary:#8B8279;          /* Warm Grey lifted to hold on soft black */
  --c-panel:#1E1A18;              /* s10 panel, lifted off the ground */
  --c-panel-2:#191614;            /* s6 letterbox */
  --c-hair:rgba(139,130,121,.26); /* dividers */
  --c-swatch:#3A3532;             /* s3 media placeholder */
  --c-media-bg:#1B1816;           /* mobile: ground under every lazy frame */
  --c-hint-shadow:rgba(0,0,0,.7); /* swipe chevron */
}
html.inv{
  /* ---- roles: LIGHT theme (white ground, Charcoal type) ----
     Pure white since 2026-09-26, at Vishal's request; the ivory stays as
     type and highlights. js/main.js initNavContrast keeps a copy (GROUND_LIGHT). */
  --c-bg:#FFFFFF;
  --c-ink:var(--c-charcoal);
  --c-secondary:var(--c-warm-grey);
  --c-panel:#EDE7DD;
  --c-panel-2:#F1EBE2;
  --c-hair:rgba(119,110,100,.26);
  --c-swatch:#DED7CB;
  --c-media-bg:#E8E1D6;
  --c-hint-shadow:rgba(20,17,16,.35);
}


/* ============================================================
   THEME FADE

   The palette lives in custom properties, and a custom property is not
   animatable: flipping `html.inv` recomputes every var() in one go, which
   is why the toggle snapped. What IS animatable is the property that
   CONSUMED it, so the fade goes on the consumers — all of them, since the
   tokens are read in ~120 places across six stylesheets and listing them
   would go stale the first time a section is added.

   Armed only while `.theming` is on the root. js/restore.js adds it on the
   click, flushes style so the transition exists in the before-change
   style — arming and flipping in one recalc animates nothing — and drops
   it when the fade is over. Left on, every element on the page would carry
   a transition for the whole session and any scripted colour change would
   run a beat behind whatever set it.

   Colour properties only, deliberately. transform, opacity and filter are
   left out: GSAP and the Web Animations API drive those all over this site
   (the curtains, every scroll reveal, the s4 deck), and a blanket
   transition on them would fight every one of those.
   ============================================================ */
:root{ --theme-fade:450ms }

html.theming,
html.theming *,
html.theming *::before,
html.theming *::after{
  transition:
    background-color var(--theme-fade) ease,
    /* the seam ramp under the hero is a gradient, and so is pendulo's
       mobile fade-out — without this they snap while the ground behind
       them fades. Same-shape gradients interpolate; anything that cannot
       (a gradient to `none`) simply lands at the end, as it does today. */
    background-image  var(--theme-fade) ease,
    border-color     var(--theme-fade) ease,
    color            var(--theme-fade) ease,
    fill             var(--theme-fade) ease,
    stroke           var(--theme-fade) ease,
    box-shadow       var(--theme-fade) ease !important;
}
/* the class is still added — this is the single place that decides the
   fade does not play, so nothing downstream has to ask again */
@media (prefers-reduced-motion: reduce){
  html.theming,
  html.theming *,
  html.theming *::before,
  html.theming *::after{ transition:none !important }
}


/* ============================================================
   THEME TOGGLE — top right, on the nav's own scaled layer so it
   sits at artboard coordinates and scales with everything else.

   Its colours are NOT tokenised. Like the pill it is painted over
   whatever happens to be under it — at rest that is the portrait —
   so main.js's sampler drives it through .is-on-dark, exactly as it
   drives the four labels. Which GLYPH shows is the part that reads
   the theme: a sun while the page is dark, a moon while it is light,
   i.e. the mode the button would take you to.

   39x39 at 1349,39 — the pill's own top and height, and the same 52px
   right margin the hero's headline and CTA keep on the left.
   ============================================================ */
.themetoggle{
  position:absolute;
  left:1349px; top:39px;
  width:39px; height:39px;
  box-sizing:border-box;
  border:1px solid #E4DED3;
  border-radius:50%;
  background:rgba(0,0,0,.01);
  display:grid; place-items:center;
  padding:0;
  color:var(--c-charcoal);
  cursor:pointer;
  pointer-events:auto;
  -webkit-tap-highlight-color:transparent;
  transition:color .4s cubic-bezier(.4,0,.2,1),
             border-color .4s cubic-bezier(.4,0,.2,1);
}
.themetoggle.is-on-dark{ color:var(--c-ivory); border-color:rgba(247,244,238,.22) }
.themetoggle__icon{
  display:block;
  width:19px; height:19px;
  transition:transform .5s cubic-bezier(.215,.61,.355,1);
}
.themetoggle:hover .themetoggle__icon{ transform:rotate(35deg) }
.themetoggle:focus-visible{ outline:2px solid currentColor; outline-offset:3px }
/* The case pages' toggle. Their header sits over the artwork's dark top in
   BOTH modes — those artboards are baked SVG and cannot follow the theme —
   so it takes the ivory treatment outright instead of waiting for a sampler
   that only the homepage runs. */
.themetoggle--static{ color:var(--c-ivory); border-color:rgba(247,244,238,.22) }

/* the glyph is the destination, not the current state */
.themetoggle__moon{ display:none }
html.inv .themetoggle__sun{ display:none }
html.inv .themetoggle__moon{ display:block }

@media (prefers-reduced-motion:reduce){
  .themetoggle,.themetoggle__icon{ transition:none }
  .themetoggle:hover .themetoggle__icon{ transform:none }
}

@font-face{font-family:'PP Neue Montreal';src:url('../assets/fonts/PPNeueMontreal-Book.otf') format('opentype');font-weight:350;font-style:normal;font-display:block}

.navlayer{
  position:fixed;
  left:0; top:0;
  width:100vw; height:0;
  z-index:60;
  pointer-events:none;
}
.navlayer__scale{
  position:relative;
  width:1440px; height:0;
  transform-origin:0 0;
  transform:scale(var(--k));
}

/* pill: SVG rect x=425.5 y=39.5 w=589 h=38 r=19, 1px stroke #EBEBEB */
.nav{
  position:absolute;
  left:425px; top:39px;
  width:590px; height:39px;
  /* self-sufficient: bloom / fire-island / sarson / visual load no reset
     of their own for this component to inherit */
  box-sizing:border-box;
  border:1px solid #E4DED3;        /* the ivory's own hairline */
  border-radius:19.5px;
  background:rgba(0,0,0,.01);
  pointer-events:auto;
  will-change:transform;
}
.nav a{
  position:absolute;
  top:13px;                 /* 53 − 39 − 1(border) */
  font-family:'PP Neue Montreal',Helvetica,Arial,sans-serif;
  font-weight:350;
  font-size:12px;
  line-height:12px;
  color:var(--c-charcoal);
  white-space:nowrap;
  text-decoration:none;
  transition:color .4s cubic-bezier(.4,0,.2,1);
}
/* set per-item by the backdrop sampler when the nav is over dark pixels */
.nav a.is-on-dark{color:var(--c-ivory)}
.nav.is-on-dark{border-color:rgba(247,244,238,.22)}
.nav{transition:border-color .4s cubic-bezier(.4,0,.2,1)}
.nav a:nth-of-type(1){left:61px}    /* 487 − 426 */
.nav a:nth-of-type(2){left:193px}   /* 619 − 426 */
.nav a:nth-of-type(3){left:329px}   /* 755 − 426 */
.nav a:nth-of-type(4){left:492px}   /* 918 − 426 */

/* hover: roll. 15px tall so descenders ("Playground") clear the mask;
   the second copy is offset by that same 15px and animated in px. */
.nav a .roll{
  position:relative;display:block;overflow:hidden;
  height:15px;padding-right:8px;
}
.nav a .roll i{display:block;font-style:normal;will-change:transform}
.nav a .roll i:last-child{position:absolute;left:0;top:15px}


/* ------------------------------------------------------------
   The same pill on every other page.

   Nothing about the header is re-specified here — geometry, type,
   the 1px #EBEBEB hairline and the four ink positions all come from
   .nav above, so the case-study pages cannot drift from the
   homepage. This block only supplies the two things the homepage
   gets from main.js, which those pages do not load:

     · the white label colour the backdrop sampler would set
       (every case-study page is dark under the nav), and
     · the roll, as a CSS transition instead of the GSAP tween.
       15px and .5s power3.out are copied from main.js so the two
       move identically.

   --static drops the layer out of position:fixed. The homepage nav
   stays pinned because a sampler keeps it legible over whatever
   scrolls under it; on the case pages there is no sampler, and a
   white pill pinned over a light photograph disappears. So it sits
   at the artboard's 425,39 and scrolls away with the artwork —
   which is where every one of these pages already had it.
   ------------------------------------------------------------ */
.navlayer--static{ position:absolute; top:0; left:0 }
.nav--dark a{ color:var(--c-ivory) }
.nav--dark a .roll i{ transition:transform .5s cubic-bezier(.215,.61,.355,1) }
.nav--dark a:hover .roll i{ transform:translateY(-15px) }

@media (prefers-reduced-motion:reduce){
  .nav--dark a .roll i{ transition:none }
}

/* Below the breakpoint the artboard scale would render the pill at
   27%, so the shared nav leaves the artboard and becomes a real bar,
   the same way css/mobile.css treats the homepage's. */
@media (max-width:768px){
  /* relative, not static: these pages scale the artwork iframe up and it
     bleeds above its own box, so the bar needs a stacking context to stay
     on top of it. z-index comes from .navlayer. */
  .navlayer--static{ position:relative; width:auto; height:auto }
  .navlayer--static .navlayer__scale{ width:auto; height:auto; transform:none }
  .navlayer--static .nav{
    position:static;
    display:flex; align-items:center; justify-content:center;
    gap:22px;
    width:max-content; height:44px;
    margin:16px auto 6px;
    padding:0 20px;
    border-radius:22px;
  }
  .navlayer--static .nav a{
    position:static;
    left:auto !important; top:auto !important;
    font-size:13px; line-height:13px;
  }
  .navlayer--static .nav a .roll{ height:16px; padding-right:0 }
  .navlayer--static .nav a .roll i:last-child{ top:16px }
  .navlayer--static .nav--dark a:hover .roll i{ transform:translateY(-16px) }

  /* The "Back" chip. It used to be display:none here, on the reasoning that
     the bar's own Home link goes to the same place — but a phone reader looks
     for the chip, so it stays.

     It cannot hold the desktop's 24,24 unchanged. At 1440 the chip and the
     pill sit side by side because the pill starts at x=425; every case page's
     phone header is a 280x19 glass pill at the artboard's 55,27, which leaves
     31px to the left of it. So the chip keeps the top-left corner and drops
     just below the pill instead — 56 design px is its 46px foot plus a 10px
     gap, scaled by --km because the pill is artboard content and the chip is
     not. `html body` to outrank the pages' own inline .back-btn rule, which
     is parsed after this file. */
  html body .back-btn{
    top:calc(56px * var(--km));
    left:18px;
    padding:8px 14px 8px 11px;
    font-size:12px;
  }
  html body .back-btn svg{ width:9px; height:9px }
}

/* The toggle only exists on the homepage, whose nav layer stays scaled
   (css/mobile.css keeps .navlayer__scale on --km) rather than becoming the
   flex bar the case pages get. So it is still artboard coordinates here:
   19x19 at 356,27 — the pill's own top and height, 15px off the right edge
   and 21px clear of the pill, which ends at 335. */
@media (max-width:768px){
  .themetoggle{
    left:356px; top:27px;
    width:19px; height:19px;
    border-width:.5px;
  }
  .themetoggle__icon{ width:11px; height:11px }
  .themetoggle:hover .themetoggle__icon{ transform:none }

  /* The case pages' header is a real flex bar down here, not an artboard, so
     their toggle is placed against the layer rather than at artboard
     coordinates. The bar is 44px tall under a 16px top margin, so its centre
     is y=38 and a 28px button sits at 24. Two classes, so this outranks the
     artboard placement above. The Back chip is bottom-LEFT; no collision. */
  .navlayer--static .themetoggle{
    left:auto; right:16px; top:24px;
    width:28px; height:28px;
  }
  .navlayer--static .themetoggle .themetoggle__icon{ width:15px; height:15px }
}


