/* =============================================================================
   THE REMNANT
   Minimalist, immersive, full-bleed, quiet. No cards, no frames, no UI chrome
   competing with the imagery. Motion is ambient and subtle throughout.
   ============================================================================= */
:root{
  --bg:#0A0A0A;
  --text:#F2EFE9;
  --muted:#A8A399;
  --gold:#C9A84C;
  --gold-soft:rgba(201,168,76,.55);
  --gold-faint:rgba(201,168,76,.22);

  --display:"Spectral",Georgia,"Times New Roman",serif;
  --body:"Inter",-apple-system,BlinkMacSystemFont,"Segoe UI",Helvetica,Arial,sans-serif;

  --header-h:76px;
  --gutter:clamp(1.25rem,5vw,3rem);

  /* ONE VIEWPORT UNIT for everything sized to the screen on the home page.
     On a phone, an inline script in index.html's <head> sets it ONCE, before
     the first paint, to 1% of the visible height with the toolbars showing,
     in px -- and changes it again only when the WIDTH changes (rotation).
     So nothing on the page changes height when the browser's toolbars
     slide in or out. A section that did (the hero, 92% of the screen,
     swung ~92px with a 100px toolbar) re-laid the page out mid-slide, which
     on an iPhone can leave the page stuck short of the top. Elsewhere (and
     before the script) it is plain svh / vh. */
  --vu:1vh;
}
@supports (height:1svh){ :root{--vu:1svh} }
*,*::before,*::after{box-sizing:border-box}
/* clip, not hidden: `hidden` makes the root a scroll container, which iOS
   Safari handles poorly and which can disturb the fixed nav. This is a
   backstop only -- every section below is clipped at its own boundary. */
html{-webkit-text-size-adjust:100%;overflow-x:clip}
body{
  margin:0;background:var(--bg);color:var(--text);
  font-family:var(--body);font-size:clamp(1rem,.55vw + .9rem,1.0625rem);
  line-height:1.65;overflow-x:clip;
}
img{display:block;max-width:100%}
a{color:inherit}
:focus-visible{outline:2px solid var(--gold);outline-offset:3px}

.skip{position:absolute;left:-9999px}
.skip:focus{left:var(--gutter);top:.5rem;z-index:100;background:var(--bg);
  padding:.6rem 1rem;border:1px solid var(--gold-soft)}

/* --- nav ------------------------------------------------------------------ */
/* §7.1 -- the nav was three labels marooned in opposite corners with a dead
   gap between them, in small letter-spaced caps with no weight, rendered
   identically over the near-black hero and the bright sky of the loom. It
   now reads as a designed header: the site's own serif, the links grouped
   tightly rather than flung to the far edge, and a solid bar (it was a
   translucent scrim until content read through it) that holds legibility
   over both. Still restrained -- it must not compete with the imagery. */
.nav{
  position:fixed;inset:0 0 auto 0;height:var(--header-h);z-index:50;max-width:100%;overflow:hidden;
  display:flex;align-items:center;justify-content:space-between;
  padding:0 var(--gutter);
  /* SOLID, on every screen: the scrim's own colour, fully opaque -- no
     transparency, no blur, no faded edge. Everything on the page scrolls
     under it and is simply covered; nothing fades or hides as it nears. */
  background:rgb(8,7,6);
  transition:background .4s ease;
}
/* a hairline of the site's gold along the bottom of the header band */
.nav::after{content:"";position:absolute;left:0;right:0;bottom:0;height:1px;
  background:linear-gradient(to right,transparent,var(--gold-faint) 22%,
    var(--gold-faint) 78%,transparent);opacity:.7}
.nav__home{font-family:var(--display);letter-spacing:.13em;text-transform:uppercase;
  font-size:.86rem;font-weight:500;text-decoration:none;color:var(--text);
  text-shadow:0 1px 3px rgba(0,0,0,.65)}
.nav__links{display:flex;gap:clamp(.9rem,1.8vw,1.6rem);align-items:center}
.nav__links a{
  font-family:var(--display);font-size:.8rem;letter-spacing:.1em;text-transform:uppercase;
  text-decoration:none;color:var(--text);opacity:.78;
  text-shadow:0 1px 3px rgba(0,0,0,.65);
  padding:.35rem .1rem;border-bottom:1px solid transparent;
  transition:opacity .3s,border-color .3s}
.nav__links a:hover,.nav__links a[aria-current="page"]{opacity:1;border-color:var(--gold-soft)}

/* --- generic full-bleed section ------------------------------------------- */
.bleed{position:relative;width:100%;overflow:hidden}
.bleed__media{position:absolute;inset:0;width:100%;height:100%;object-fit:cover}

/* --- transition zones (§2.1, §6.2) -----------------------------------------
   Every section boundary used to be a hard cut -- a bright image starting
   abruptly against flat black read as a leak rather than a change of place.
   A seam is a graded buffer belonging to both sides: the neighbouring colour
   carried a little way into the image so one environment gives way to the
   next over the scroll instead of at a line.
   `--seam` is the colour of whatever sits on the other side of the edge.
--------------------------------------------------------------------------- */
.seam{position:absolute;left:0;right:0;z-index:3;pointer-events:none;
  height:clamp(90px,calc(16 * var(--vu)),220px)}
.seam--top{top:-1px;background:linear-gradient(to bottom,
  var(--seam,#0A0A0A) 0%, color-mix(in srgb, var(--seam,#0A0A0A) 55%, transparent) 42%, transparent 100%)}
/* §6.1 -- forward pull, by sightline rather than by UI. The hero stops just
   short of the viewport so the next section's edge is always visible, and a
   faint warm bloom sits at the foot of the premise: light from further down
   the page, which the eye follows. No arrows, no "scroll" label. */
.premise::after{content:"";position:absolute;left:0;right:0;bottom:0;
  height:clamp(70px,calc(12 * var(--vu)),150px);pointer-events:none;
  background:linear-gradient(to top,rgba(178,108,44,.16),transparent);
  opacity:.85}
.seam--bottom{bottom:-1px;background:linear-gradient(to top,
  var(--seam,#0A0A0A) 0%, color-mix(in srgb, var(--seam,#0A0A0A) 55%, transparent) 42%, transparent 100%)}
/* color-mix is recent; the fallback is a plain two-stop gradient, which is
   softer than a hard cut even where the mix is unsupported. */
@supports not (background: color-mix(in srgb, red 50%, transparent)){
  .seam--top{background:linear-gradient(to bottom,var(--seam,#0A0A0A),transparent)}
  .seam--bottom{background:linear-gradient(to top,var(--seam,#0A0A0A),transparent)}
}

/* --- hero ----------------------------------------------------------------- */
.hero{min-height:92vh;min-height:calc(92 * var(--vu));display:grid;place-items:center;text-align:center;padding:var(--header-h) var(--gutter) 4rem}
.hero::after{content:"";position:absolute;inset:0;
  background:radial-gradient(ellipse at 50% 55%,rgba(10,10,10,.15),rgba(10,10,10,.78) 78%)}
.hero__inner{position:relative;z-index:2;display:grid;justify-items:center;
  gap:clamp(1.1rem,3vw,1.9rem)}
/* The plate was capped at 430px, which is why it read small against a
   full-bleed hero. It is the title card, so it gets to be the dominant
   element. JUDGMENT CALL: 640px / 74vw is my number, not a recovered one --
   the old cap was deliberate, not a bug. Tune the two values together. */
.hero__logo{width:min(68vw,560px);height:auto;filter:drop-shadow(0 8px 40px rgba(0,0,0,.6))}
/* PLACEHOLDER COPY lives in index.html. This slot is sized for one line at
   desktop and two at phone width; it holds its height either way. */
.hero__tagline{
  margin:0;max-width:30ch;text-align:center;text-wrap:balance;
  font-family:var(--display);font-style:italic;font-weight:400;
  font-size:clamp(.95rem,1.45vw,1.2rem);line-height:1.5;letter-spacing:.01em;
  color:#D9D1C2;text-shadow:0 1px 12px rgba(0,0,0,.7)}

/* --- hero title card (load sequence) --------------------------------------
   Film title card, not a web page load: the plate alone for a beat, then the
   logo, then the line, then the button. Fade and a small scale settle only --
   nothing travels, nothing bounces.
   Gated behind no-preference so that with reduced motion (or in a browser
   that does not support the query) every element is simply visible at full
   opacity. Do NOT move the opacity:0 outside this block. */
@media (prefers-reduced-motion:no-preference){
  .hero__logo{animation:titleCard 1s cubic-bezier(.22,.61,.36,1) 1.2s both}
  .hero__tagline{animation:titleFade 1s cubic-bezier(.22,.61,.36,1) 1.6s both}
  .hero__inner .cta{animation:titleFade 1s cubic-bezier(.22,.61,.36,1) 2.2s both}
}
@keyframes titleCard{
  from{opacity:0;transform:scale(1.035)}
  to{opacity:1;transform:scale(1)}}
@keyframes titleFade{from{opacity:0}to{opacity:1}}
/* §7.2 -- a thin white outline rectangle is pure web-default, and it is the
   first interactive thing a visitor meets. This ties it to the gold and the
   plate motif: a warm struck surface with a lit top edge and a shadowed
   bottom one, the label set in the site's serif. Materially suggestive
   without tipping into a skeuomorphic gimmick. */
.cta{
  position:relative;display:inline-block;
  font-family:var(--display);font-size:.82rem;letter-spacing:.17em;text-transform:uppercase;
  text-decoration:none;color:#F6EBD2;padding:.9rem 2.1rem;
  background:linear-gradient(to bottom,rgba(201,168,76,.20),rgba(120,92,34,.14));
  border:1px solid var(--gold-soft);border-radius:1px;
  box-shadow:inset 0 1px 0 rgba(255,228,160,.28), inset 0 -1px 0 rgba(0,0,0,.35),
             0 10px 26px rgba(0,0,0,.42);
  text-shadow:0 1px 2px rgba(0,0,0,.55);
  transition:background .4s,border-color .4s,box-shadow .4s,color .4s}
.cta:hover{
  color:#FFF6E2;border-color:var(--gold);
  background:linear-gradient(to bottom,rgba(201,168,76,.34),rgba(140,106,38,.22));
  box-shadow:inset 0 1px 0 rgba(255,235,178,.42), inset 0 -1px 0 rgba(0,0,0,.4),
             0 14px 34px rgba(0,0,0,.5), 0 0 26px rgba(201,168,76,.18)}

/* --- premise -------------------------------------------------------------- */
/* §7.3 -- was set far too large and floating in flat black. Scale is cut
   substantially and pulled back into the established type system, and the
   space around it is given some material presence instead of being a void.
   NOTE: this is the restrained option. The engraved-plate treatment is a
   bigger call and has NOT been taken -- see BUILD-NOTES. */
.premise{position:relative;padding:clamp(7rem,calc(20 * var(--vu)),14rem) var(--gutter);
  display:grid;place-items:center;overflow-x:clip}
.premise::before{content:"";position:absolute;inset:0;pointer-events:none;
  background:
    radial-gradient(ellipse 58% 46% at 50% 50%, rgba(86,62,30,.20), transparent 72%),
    radial-gradient(ellipse 120% 60% at 50% 120%, rgba(150,96,38,.10), transparent 70%)}
.premise p{
  position:relative;
  font-family:var(--display);font-weight:400;font-style:italic;
  font-size:clamp(1.12rem,1.85vw,1.6rem);line-height:1.62;letter-spacing:.005em;
  max-width:34ch;text-align:center;margin:0;text-wrap:balance;color:#E9E3D7;
  /* 34ch wraps this line to four narrow lines on desktop. Widened here only:
     the phone wrap is correct as-is, so the override is behind a min-width. */
  text-shadow:0 1px 14px rgba(0,0,0,.6);
}

@media (min-width:861px){ .premise p{max-width:66ch} .hero__tagline{max-width:56ch} }
/* The nav words, ~15% larger on DESKTOP only (.86 -> .99rem, .8 -> .92rem);
   same face, same tracking and spacing style. The phone keeps the sizes
   above and its own tightened set further down. */
@media (min-width:861px){
  .nav__home{font-size:.99rem}
  .nav__links a{font-size:.92rem}
}

/* --- tent ----------------------------------------------------------------- */
.tent{height:100vh;height:calc(100 * var(--vu))}
.tent .bleed__media{transform-origin:52% 58%;animation:tentDrift 46s ease-in-out infinite alternate}
.tent__glow{position:absolute;inset:0;pointer-events:none;mix-blend-mode:screen;
  background:radial-gradient(circle at 46% 62%,rgba(255,180,90,.16),transparent 42%);
  animation:candle 7.5s ease-in-out infinite alternate}
@keyframes tentDrift{from{transform:scale(1.015) translate3d(0,0,0)}to{transform:scale(1.045) translate3d(-.6%,-.5%,0)}}
@keyframes candle{0%{opacity:.55}35%{opacity:.85}60%{opacity:.62}100%{opacity:.92}}

/* --- segments ------------------------------------------------------------
   MOVED. The two stacked scene sections were replaced by one persistent
   canvas; everything that styled them now lives in segments/canvas.css,
   including the light spill, the feathered edges and both backdrops.
   Nothing about a scene belongs in this file any more.
   NB the old `.line` rules lived here and would have collided with the
   canvas's own `.line`, which is why they are gone rather than commented.
--------------------------------------------------------------------------- */

/* --- the loom ------------------------------------------------------------- */
.loom{position:relative;width:100%;background:#0A0A0A;overflow-x:clip}
.loom__stage{position:relative;width:100%;aspect-ratio:2944/1648;
  /* clips the cover-fitted layers and the JS-positioned veil/bands, whose
     warp rectangle legitimately extends past both edges on narrow screens */
  overflow:hidden}
.loom__layer{position:absolute;inset:0;width:100%;height:100%;object-fit:cover}
.loom__rig{z-index:2}
/* the veil is positioned from config, in fractions of the rig image */
.loom__veil{position:absolute;z-index:3;overflow:hidden;
  clip-path:inset(0 0 100% 0);
  will-change:clip-path}
.loom__veil img{width:100%;height:100%;object-fit:fill;display:block}

/* Drape and light (§5.1). The veil is a flat panel; these two overlays give
   it the curvature and the light direction of the cloth around it -- brighter
   where the camp's sun catches it, falling off at the sides where the
   material turns away, and a little shadow under the top beam. */
.loom__veil::before{content:"";position:absolute;inset:0;pointer-events:none;
  background:
    linear-gradient(to bottom, rgba(38,26,14,.30) 0%, rgba(38,26,14,0) 9%),
    linear-gradient(100deg, rgba(30,20,10,.22) 0%, rgba(255,240,210,.10) 38%,
                    rgba(255,240,210,.06) 62%, rgba(30,20,10,.26) 100%);
  mix-blend-mode:multiply;opacity:.9}
.loom__veil.is-woven{transition:clip-path var(--weave-in,1.8s) cubic-bezier(.22,.61,.36,1) var(--weave-delay,.15s)}
/* The boundary between finished cloth and bare warp (§5.1).
   This deliberately lives OUTSIDE .loom__veil: the veil is clipped at the
   weave line, and these threads have to hang past it. A clean rectangular
   cut was the clearest sign the veil was stamped on. */
.loom__weave{position:absolute;z-index:3;pointer-events:none;
  background-image:url("/assets/veil-edge.webp");
  background-repeat:no-repeat;background-size:100% 100%;
  opacity:0;transition:opacity .8s ease .9s}
.loom__weave.is-woven{opacity:.92}

/* PROGRESS LABELS. The loom's width is split into zones, left to right in
   stage order, one per label. Hovering a zone (or tapping it, on a phone)
   shows its label centred on that zone, all of them at one height across
   the loom -- in the warp threads below the woven cloth -- as glowing
   letters: warm cream, held off whatever is behind by a soft dark glow and
   a faint warm halo. No box, no edge. */
.loom__bands{position:absolute;z-index:4;display:grid;grid-auto-flow:column;grid-auto-columns:1fr;
  --label-y:58%}
/* above the camp/rig/veil layers so the seam grades over the whole scene,
   but pointer-events:none keeps the bands tappable underneath */
.loom__stage .seam{z-index:5}
.band{position:relative;border:0;background:none;padding:0;margin:0;cursor:default;height:100%;
  font:inherit;color:inherit;-webkit-tap-highlight-color:transparent}
.band[hidden]{display:none}
.band:focus-visible{outline:1px solid var(--gold-soft);outline-offset:-6px}
/* the stage name, for screen readers only: each zone reads as
   "Manuscript: Season One is being written." */
.band__name{position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0 0 0 0);clip-path:inset(50%);white-space:nowrap}
.band__label{
  position:absolute;left:50%;top:var(--label-y);
  /* --nudge (site.js) keeps a label near the loom's edge on screen */
  transform:translate(calc(-50% + var(--nudge,0px)),-50%) translateY(.35rem);
  width:max-content;max-width:min(30ch,200%);
  font-family:var(--display);font-weight:500;
  font-size:clamp(.82rem,1.1vw,1.08rem);line-height:1.35;letter-spacing:.01em;
  text-align:center;color:#F4E9D1;
  text-shadow:
    0 0 2px rgba(18,11,4,.95), 0 0 9px rgba(18,11,4,.85),
    0 0 20px rgba(18,11,4,.7), 0 0 34px rgba(255,208,140,.22);
  opacity:0;pointer-events:none;transition:opacity .6s ease,transform .6s ease;
}
.band[data-revealed="true"] .band__label{opacity:1;transform:translate(calc(-50% + var(--nudge,0px)),-50%)}

.loom__caption{position:absolute;z-index:5;left:var(--gutter);bottom:clamp(1rem,3vw,2rem);
  font-size:.7rem;letter-spacing:.18em;text-transform:uppercase;color:var(--muted);opacity:.55}

/* --- footer --------------------------------------------------------------- */
.footer{padding:clamp(5rem,calc(14 * var(--vu)),9rem) var(--gutter) clamp(2.5rem,calc(6 * var(--vu)),4rem);
  display:grid;gap:clamp(2.5rem,calc(7 * var(--vu)),4.5rem);justify-items:center;text-align:center;
  overflow-x:clip}
.teaser{display:grid;gap:1rem;justify-items:center;max-width:34ch}
.teaser a{font-family:var(--display);font-size:clamp(1.15rem,2.4vw,1.6rem);
  text-decoration:none;color:var(--text);border-bottom:1px solid var(--gold-faint);
  padding-bottom:.25rem;transition:border-color .4s,letter-spacing .4s}
.teaser a:hover{border-color:var(--gold)}
.teaser p{margin:0;color:var(--muted);font-size:.9rem}
.footer__meta{display:grid;gap:.9rem;justify-items:center;color:var(--muted);font-size:.78rem}
.socials{display:flex;gap:1.5rem}
.socials a{text-decoration:none;letter-spacing:.14em;text-transform:uppercase;font-size:.7rem;
  opacity:.7;transition:opacity .3s}
.socials a:hover{opacity:1}
.footer__meta a{color:inherit;overflow-wrap:anywhere}

/* --- inner pages (About / Join) ------------------------------------------- */
.page{max-width:60ch;margin:0 auto;padding:calc(var(--header-h) + clamp(4rem,12vh,8rem)) var(--gutter) clamp(5rem,12vh,8rem)}
.page h1{font-family:var(--display);font-weight:400;font-size:clamp(1.9rem,4.4vw,3rem);
  line-height:1.2;margin:0 0 clamp(2rem,5vh,3rem)}
.page h2{font-family:var(--display);font-weight:400;font-size:clamp(1.15rem,2.2vw,1.4rem);
  margin:clamp(2.5rem,6vh,3.5rem) 0 .75rem;color:var(--text)}
.page p{margin:0 0 1.35rem;color:#DCD8D0;overflow-wrap:break-word}
.page p.lede{font-family:var(--display);font-size:clamp(1.15rem,2.3vw,1.5rem);line-height:1.5;color:var(--text)}
.page .sig{font-family:var(--display);font-style:italic;color:var(--muted)}
.page hr{border:0;border-top:1px solid rgba(242,239,233,.1);margin:clamp(2.5rem,6vh,3.5rem) 0}

/* --- join form ------------------------------------------------------------
   beehiiv renders the subscribe form inside a CROSS-ORIGIN IFRAME. Nothing
   below can reach inside it: not the font, not the button colour, not the
   button label. Those are set in beehiiv's own form designer and nowhere
   else. See BUILD-NOTES.md for the list of settings that still need changing
   there. Everything here controls only the box the iframe sits in.
--------------------------------------------------------------------------- */
.join-wrap{margin:clamp(2rem,5vh,2.75rem) 0 1.25rem;position:relative}

/* The loader collapses its own container to height:0 and expands it when the
   child posts back a measured height. In testing that height message never
   arrived -- the child only ever sends `child-loaded` and `childReady` -- which
   leaves the form invisible. Force the container open, and cap the iframe,
   whose default is 2000px, so it is not a tall empty block. */
.join-wrap > div,
.join-wrap > div > div{height:auto!important;overflow:visible!important}
.join-wrap iframe{
  width:100%!important;
  /* Measured: the form row is 47px but sits at a fixed ~81px offset inside
     the iframe (beehiiv reserves space for the title/subtitle even when both
     are switched off), so anything under ~140px clips it -- 100px was tried
     and cut the form in half. The success message is a separate toast
     appended to <body>, not inline, so it cannot be clipped by this value.
     Re-measure if the title/subtitle are ever switched back on. */
  height:160px!important;
  display:block;border:0;
}

.join__note{color:var(--muted);font-size:.82rem;max-width:46ch}

/* beehiiv appends its confirmation as <div id="beehiiv-toast"> on <body>,
   styled inline: white, system font, pinned to top:12px at the highest
   possible z-index, where it lands on top of the nav. Inline styles mean
   every override here needs !important. This is the one part of the widget
   that is in our document and therefore stylable at all. If beehiiv changes
   that element's id this silently stops applying -- recheck after any embed
   update. */
#beehiiv-toast{
  top:calc(var(--header-h) + .75rem)!important;
  background:#14120E!important;
  color:var(--text)!important;
  font-family:var(--display)!important;
  font-size:.95rem!important;
  border:1px solid var(--gold-soft)!important;
  border-radius:2px!important;
  box-shadow:0 18px 50px rgba(0,0,0,.6)!important;
  padding:.85rem 1.1rem!important;
}
#beehiiv-toast svg{flex:0 0 auto}

/* --- responsive ----------------------------------------------------------- */
@media (max-width:860px){
  /* the loom is the centrepiece: let it grow taller than the plate on phones
     so the weave and the labels stay legible instead of shrinking to nothing */
  .loom__stage{aspect-ratio:auto;height:62vh;height:calc(62 * var(--vu));min-height:360px}
  /* THE TENT, ZOOMED OUT. The picture is 1.78:1 in a portrait section, and
     filling the section showed only ~25% of its width -- the plates, and
     none of the open door. Now it is a band across the screen showing
     ~55% of its width (--tent-show): from the plates'
     bound edge through the whole door gap (plates ~16-60% across, opening
     ~52-77%; the window is ~19-74%, centred at 46.5%). Above and below it
     the picture fades into the page -- a mask on the picture itself, so
     there is no edge, only dark.
     Where code runs out: filling a portrait screen with this picture means
     either cropping to ~25% of it (as before) or a band like this one --
     a portrait tent image is the real fix. */
  /* THE JOIN WITH THE CANVAS. The band used to sit centred in a whole
     screen, which left ~130px of empty section under it (more in Chrome on
     iPhone, where svh is the tall height) on top of its own fade. Now the
     section ends where the band ends -- the space ABOVE the band is what it
     was, half a screen less half the band -- and the section overlaps the
     canvas by the length of the band's bottom fade, drawn over it (z-index),
     so the fade runs straight into the canvas's room. That overlap lies in
     the canvas's top padding, the strip the nav covers when the canvas is
     in place, so it never reaches a line of text. */
  .tent{
    --tent-show:.55;
    --tent-band:calc(100vw / var(--tent-show) / (1456 / 816));
    height:calc(50vh + var(--tent-band) / 2);
    height:calc(50 * var(--vu) + var(--tent-band) / 2);
    z-index:1;
    margin-bottom:calc(var(--tent-band) * -.18);
  }
  .tent .bleed__media{
    inset:auto 0 0 0;
    height:var(--tent-band);
    object-position:46.5% 50%;transform-origin:50% 55%;
    -webkit-mask-image:linear-gradient(to bottom, transparent 0, #000 18%, #000 82%, transparent 100%);
    mask-image:linear-gradient(to bottom, transparent 0, #000 18%, #000 82%, transparent 100%);
  }
  /* the candle's glow keeps its old place on the picture: the same box as
     the old whole-screen section, around the band (the part below the
     section is clipped, where there was only empty dark before) */
  .tent__glow{
    inset:auto 0;
    height:100vh;height:calc(100 * var(--vu));
    bottom:calc((var(--tent-band) - 100vh) / 2);
    bottom:calc((var(--tent-band) - 100 * var(--vu)) / 2);
  }
}
@media (max-width:520px){
  /* At 375px the wordmark plus both links overran the viewport and forced a
     horizontal scroll. Tighten the gutter and the tracking so they fit. */
  .nav{padding:0 1rem}
  .nav__home{font-size:.68rem;letter-spacing:.1em;white-space:nowrap}
  .nav__links{gap:.85rem}
  .nav__links a{font-size:.6rem;letter-spacing:.08em;white-space:nowrap}
  .band__label{font-size:.8rem;max-width:150%}
  .join-wrap iframe{height:190px!important}   /* the form wraps at phone width */
}
@media (max-width:360px){
  .nav__home{font-size:.62rem}
  .nav__links a{font-size:.56rem;letter-spacing:.06em}
}

/* --- reduced motion ------------------------------------------------------- */
@media (prefers-reduced-motion:reduce){
  *,*::before,*::after{animation:none!important;transition-duration:.01ms!important}
  .tent .bleed__media{transform:scale(1.02)}
  /* The canvas handles reduced motion itself: the engine composes the first
     segment's final state with each signature's settle() and stops. This
     blanket rule is what makes those settles stick. */
}
