:root{--brass:#D9B33C;--brass-bright:#F0CC66;--ink-mut:#AFBFA0;--crimson:#CE3B44;--emerald:#2FA36B}
  /* ---------- IMMERSIVE ENTRANCE ---------- */
  .intro-track{height:400vh;position:relative}  /* 360vh of sequence + 40vh holding the final frame */
  /* 100vh first as the fallback: browsers without dvh support (Chrome <108,
     Safari <15.4, Firefox <101) drop the whole declaration, which collapsed the
     stage to zero height and left 400vh of black with no image. */
  .intro-stage{position:sticky;top:0;height:100vh;height:100dvh;overflow:hidden;background:#02070B}
  .intro-stage::before{content:"";position:absolute;inset:0;z-index:14;pointer-events:none;background:radial-gradient(120% 120% at 50% 50%,transparent 55%,rgba(0,0,0,.5))}
  /* object-fit:cover is the safety net. On mobile the URL bar makes 100dvh
     change mid-scroll, so the canvas BOX can briefly differ in aspect from the
     canvas BITMAP. Without this the browser stretches the bitmap to fill and
     the image visibly squashes vertically. With it, it crops instead. */
  #introCanvas{position:absolute;inset:0;width:100%;height:100%;display:block;object-fit:cover;object-position:center}
  .intro-gate{position:absolute;inset:0;z-index:30;background:#02070B;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:28px;transition:opacity .6s ease;pointer-events:none}
  .intro-gate svg{height:72px;width:auto;animation:gatePulse 1.4s ease-in-out infinite}
  @keyframes gatePulse{0%,100%{opacity:.5}50%{opacity:1}}
  .intro-gate-bar{width:130px;height:2px;background:rgba(217,179,60,.18);border-radius:2px;overflow:hidden}
  .intro-gate-bar span{display:block;height:100%;width:0;background:var(--brass-bright);transition:width .25s ease}
  .intro-coords,.intro-cap{position:absolute;bottom:11%;left:0;right:0;text-align:center;z-index:16;font-family:"Space Mono",monospace;font-size:12.5px;letter-spacing:.3em;text-transform:uppercase;pointer-events:none;color:var(--brass-bright);text-shadow:0 2px 8px rgba(0,0,0,.95),0 0 26px rgba(0,0,0,.85)}
  .intro-beat{position:absolute;top:50%;left:0;right:0;transform:translateY(-50%);text-align:center;z-index:16;pointer-events:none;font-family:"Fraunces",serif;font-style:italic;font-weight:300;font-size:clamp(26px,4.2vw,44px);letter-spacing:.01em;color:var(--ink);text-shadow:0 2px 10px rgba(0,0,0,.95),0 0 34px rgba(0,0,0,.85),0 0 90px rgba(0,0,0,.6);padding:34px 20px;background:radial-gradient(52% 130% at 50% 50%,rgba(2,7,11,.42),rgba(2,7,11,0) 72%)}
  .intro-beat em{font-style:italic;color:var(--brass-bright)}
  .intro-cue{position:absolute;bottom:24px;left:0;right:0;text-align:center;z-index:16;font-family:"Space Mono",monospace;font-size:12.5px;font-weight:700;letter-spacing:.3em;text-transform:uppercase;color:var(--brass-bright);text-shadow:0 2px 8px rgba(0,0,0,.95),0 0 24px rgba(0,0,0,.8)}
  .intro-cue .arr{display:inline-block;margin-left:8px;animation:introBounce 1.6s ease-in-out infinite}
  @keyframes introBounce{0%,100%{transform:translateY(0)}50%{transform:translateY(6px)}}
  @media(max-width:640px){.intro-cue{bottom:78px}}
  .intro-skip{position:absolute;bottom:20px;right:20px;z-index:18;background:rgba(0,0,0,.35);border:1px solid var(--brass);color:var(--brass-bright);font-family:"Space Mono",monospace;font-size:10.5px;letter-spacing:.18em;text-transform:uppercase;padding:9px 14px;border-radius:3px;cursor:pointer;-webkit-backdrop-filter:blur(4px);backdrop-filter:blur(4px)}
  .snd-dock{position:fixed;left:20px;bottom:calc(20px + env(safe-area-inset-bottom,0px));z-index:45;display:flex;align-items:flex-end;gap:12px;transition:opacity .8s}
  @media(max-width:640px){.snd-dock{bottom:20px}.snd-dock .snd-fader{display:none}.snd-dock .snd-ch{display:none}}
  .snd-dock.live.nap{opacity:.72}
  .snd-mute-wrap{display:flex;flex-direction:column;align-items:center;gap:5px}
  .snd-mute{width:64px;height:38px;border-radius:6px;border:1px solid rgba(203,164,59,.45);background:rgba(0,0,0,.45);color:#B4AA97;font-family:"Space Mono",monospace;font-size:11px;letter-spacing:.14em;cursor:pointer;-webkit-backdrop-filter:blur(4px);backdrop-filter:blur(4px);transition:background .35s,color .35s,border-color .35s;touch-action:manipulation}
  .snd-mute.lit{background:#c23b35;border-color:#e07a72;color:#1a0505}
  .snd-ch{font-family:"Space Mono",monospace;font-size:9.5px;letter-spacing:.18em;color:rgba(180,170,151,.6)}
  .snd-fader{display:flex;flex-direction:column;align-items:center;gap:5px;width:0;opacity:0;overflow:hidden;transition:opacity .6s,width .6s;pointer-events:none}
  .snd-dock.live .snd-fader{width:58px;opacity:1;pointer-events:auto}
  .snd-rail{position:relative;width:34px;height:104px;background:rgba(0,0,0,.45);border:1px solid rgba(203,164,59,.3);border-radius:5px;-webkit-backdrop-filter:blur(4px);backdrop-filter:blur(4px);cursor:ns-resize;touch-action:none}
  .snd-rail:focus-visible{outline:2px solid var(--brass-bright);outline-offset:3px}
  .snd-rail:before{content:"";position:absolute;left:50%;top:8px;bottom:8px;width:2px;transform:translateX(-50%);background:rgba(203,164,59,.25);border-radius:1px}
  .snd-cap{position:absolute;left:50%;transform:translate(-50%,50%);bottom:8px;width:22px;height:11px;background:#c8c4b4;border:1px solid #55523f;border-radius:2px;transition:bottom .1s linear}
  .snd-cap i{position:absolute;left:2px;right:2px;top:4px;height:2px;background:#3a382c;display:block}
  .snd-track,.snd-db{font-family:"Space Mono",monospace;font-size:9.5px;letter-spacing:.12em}
  .snd-track{color:rgba(180,170,151,.75)}
  .snd-db{color:#CBA43B}
  .snd-auto{border:0;background:none;color:var(--brass-bright);font:9px "Space Mono",monospace;letter-spacing:.08em;text-transform:uppercase;cursor:pointer;padding:3px}
  .snd-auto[hidden]{display:none}
  .snd-status{position:absolute;left:0;bottom:100%;width:220px;margin-bottom:8px;color:var(--brass-bright);font:10px/1.4 "Space Mono",monospace;pointer-events:none}
  @media(max-width:640px){.intro-beat,.intro-coords,.intro-cap{font-size:10.5px;letter-spacing:.22em;padding:0 24px}}
  /* Reduced motion used to display:none the whole intro track, so these visitors
     landed on the site with no opening at all. Respect the preference by removing
     the MOTION, not the shot: one static viewport showing the final frame. */
  @media(prefers-reduced-motion:reduce){
    .snd-dock{display:none}
    .intro-track{height:100vh;height:100dvh}
    .intro-stage{position:relative;background:#02070B url("photos/entrance/seq/f138.webp?v=hq22") center/cover no-repeat}
    #introCanvas,.intro-gate,.intro-cue,.intro-skip,.intro-coords,.intro-cap{display:none}
  }

  /* ---------- NATIVE STOP ON THE FINAL FRAME ----------
     The film halts on the last shot arriving from either direction and one
     more scroll continues into the site. This is a scroll-snap point the
     browser honours on the compositor, so it costs nothing on the main
     thread. scroll-snap-stop:always is what makes a fast flick stop here
     instead of sailing past. The engine positions #introLanding in script so
     the stop sits exactly on the frame where the film ends, and only turns
     the snapping on once it is actually driving the canvas - a static or
     no-script visitor gets no snap. */
  html.intro-snap{scroll-snap-type:y proximity}
  .intro-landing{position:absolute;left:0;top:0;width:1px;height:1px;pointer-events:none;visibility:hidden}
  html.intro-snap-armed .intro-landing{scroll-snap-align:start;scroll-snap-stop:always}
  @media(prefers-reduced-motion:reduce){html.intro-snap{scroll-snap-type:none}}

  /* ---------- NO SECOND COPY OF THE ENDING BEHIND THE FILM ----------
     hybrid.css paints seqp/f138 as a background on .intro-stage for phones.
     That is the right fallback for a static or no-script visitor, but while
     the engine is actually driving the canvas it puts a second, differently
     cropped copy of the final shot directly behind the film. Any moment the
     canvas is cleared - and resizing it to match the box is exactly that,
     which the URL bar triggers on a phone as you scroll back up - that copy
     shows through, which reads as a flash of another image behind the scene.
     The fallbacks keep theirs; only the live canvas loses it. */
  /* Keyed on has-js (set in the head before any stylesheet), not on a class
     the film engine adds later: that way the rule is already in force at the
     first style pass and the browser never starts the 115 KB download at all.
     Reduced-motion visitors are excluded because for them this background IS
     the intro, and .static keeps it for devices where the canvas fails. */
  @media(max-width:700px) and (prefers-reduced-motion:no-preference){
    html.has-js .intro-track:not(.static) .intro-stage{background-image:none}
  }

  /* Balance the two overlay lines on narrow phones rather than leaving one
     word alone on the second line. Browsers without text-wrap:balance fall
     back to the non-breaking spaces in the caption markup. */
  .intro-cap,.intro-coords{text-wrap:balance}
