/* ══════════════════════════════════════════════════════════════
   STREET BUD — THE BLOCK AFTER DARK
   Everything 2D. The street itself lives in js/street.js.

   SINGLE THEME, COMMITTED TO DARK — on purpose, not by default.
   The premise is a street after dark; a light variant would be a
   different world, not the same world in another skin. There is
   deliberately no prefers-color-scheme branch to maintain.

   Contrast note: the tertiary tier used to sit at 28% opacity,
   which measured 2.16:1 against the ground — a WCAG failure, and
   it was painting the per-record view counts, which are the whole
   argument of the page. Tertiary now clears 4.5:1 and the view
   counts were promoted a tier. Dark and moody is the look; unreadable
   is a bug.
   ══════════════════════════════════════════════════════════════ */

:root{
  --bg:#050506;
  --asphalt:#0b0c0f;
  --asphalt-hi:#16181d;
  --sodium:#ff9d2f;
  --sodium-deep:#b35c00;
  --filament:#ffd9a0;
  --ink:#f2ece4;
  --muted:rgba(242,236,228,.55);
  --subtle:rgba(242,236,228,.54);
  --line:rgba(255,157,47,.20);

  --disp:'Anton',Impact,'Arial Narrow Bold',sans-serif;
  --mono:'IBM Plex Mono',ui-monospace,SFMono-Regular,Menlo,monospace;

  --pad:clamp(14px,2.6vw,30px);
}

*,*::before,*::after{box-sizing:border-box}
html,body{margin:0;padding:0}
html{background:var(--bg)}

body{
  background:var(--bg);
  color:var(--ink);
  font-family:var(--mono);
  -webkit-font-smoothing:antialiased;
  overflow-x:hidden;
}

.mono{font-family:var(--mono)}

.sr-only{
  position:absolute;width:1px;height:1px;padding:0;margin:-1px;
  overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;border:0;
}

/* ── the WebGL street ─────────────────────────────────────── */
#gl{
  position:fixed;inset:0;width:100%;height:100%;
  display:block;z-index:0;
  background:var(--bg);
}

/* scroll track — JS owns the height */
.track{position:relative;z-index:-1;width:100%;height:600vh;pointer-events:none}

/* ── atmosphere ───────────────────────────────────────────── */
.vignette{
  position:fixed;inset:0;z-index:2;pointer-events:none;
  background:radial-gradient(ellipse 78% 62% at 50% 52%,transparent 38%,rgba(0,0,0,.55) 78%,rgba(0,0,0,.92) 100%);
}

.grain{
  position:fixed;inset:-120px;z-index:3;pointer-events:none;
  opacity:.055;mix-blend-mode:overlay;
  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='.85' numOctaves='3'/%3E%3C/filter%3E%3Crect width='180' height='180' filter='url(%23n)'/%3E%3C/svg%3E");
  animation:grainShift 620ms steps(4) infinite;
}
@keyframes grainShift{
  0%{transform:translate(0,0)}25%{transform:translate(-34px,18px)}
  50%{transform:translate(22px,-30px)}75%{transform:translate(-16px,-14px)}
  100%{transform:translate(0,0)}
}

/* ══════════════════════════════════════════════════════════════
   THRESHOLD — the sodium lamp warming up IS the loading bar.
   Real sodium-vapour lamps take ~5s to reach full output.
   ══════════════════════════════════════════════════════════════ */
.threshold{
  position:fixed;inset:0;z-index:60;
  background:#000;
  display:flex;flex-direction:column;
  align-items:center;justify-content:center;
  gap:clamp(30px,7vh,72px);
  transition:opacity .8s ease,visibility .8s;
}
.threshold.gone{opacity:0;visibility:hidden;pointer-events:none}

.th-lamp{position:relative;width:200px;height:clamp(150px,24vh,220px)}

.th-post{
  position:absolute;left:50%;top:0;width:5px;height:52%;
  transform:translateX(-50%);
  background:linear-gradient(180deg,#2b2d31,#111316);
  border-radius:2px;
}
.th-arm{
  position:absolute;left:50%;top:50%;width:62px;height:5px;
  background:linear-gradient(90deg,#2b2d31,#16181c);
  border-radius:3px;
  transform:translateX(-2px);
}
.th-head{
  position:absolute;left:calc(50% + 56px);top:calc(50% + 3px);
  width:44px;height:15px;
  transform:translateX(-50%);
  background:#191b1f;
  border-radius:3px 3px 11px 11px;
  display:grid;place-items:center;
  overflow:visible;
}
.th-head i{
  display:block;width:30px;height:7px;border-radius:50%;
  background:#140702;
  box-shadow:0 0 0 rgba(255,157,47,0);
  animation:warmup 5s cubic-bezier(.4,0,.5,1) forwards;
}
.th-cone{
  position:absolute;left:calc(50% + 56px);top:calc(50% + 16px);
  width:270px;height:230px;
  transform:translateX(-50%);
  clip-path:polygon(41% 0,59% 0,100% 100%,0 100%);
  background:linear-gradient(180deg,rgba(255,157,47,.55),rgba(255,157,47,0) 82%);
  opacity:0;
  animation:coneIn 5s cubic-bezier(.4,0,.5,1) forwards;
  filter:blur(5px);
}

@keyframes warmup{
  0%   {background:#140702;box-shadow:0 0 0 0 rgba(255,157,47,0)}
  6%   {background:#7e2c00;box-shadow:0 0 18px 3px rgba(179,92,0,.55)}   /* restrike */
  9%   {background:#180802;box-shadow:0 0 2px 0 rgba(179,92,0,.15)}
  14%  {background:#9c3a00;box-shadow:0 0 26px 5px rgba(179,92,0,.6)}
  17%  {background:#1d0a02;box-shadow:0 0 3px 0 rgba(179,92,0,.2)}
  26%  {background:#b35c00;box-shadow:0 0 34px 7px rgba(179,92,0,.7)}
  55%  {background:#e07d14;box-shadow:0 0 54px 12px rgba(224,125,20,.75)}
  100% {background:var(--filament);box-shadow:0 0 78px 20px rgba(255,157,47,.85)}
}
@keyframes coneIn{
  0%,8%{opacity:0}
  18%{opacity:.16}
  26%{opacity:.30}
  100%{opacity:1}
}

.th-copy{text-align:center;padding:0 var(--pad)}
.th-mark{
  font-family:var(--disp);
  font-size:clamp(46px,11vw,124px);
  line-height:.9;letter-spacing:.012em;
  margin:0;color:var(--ink);
  opacity:0;animation:thIn 1.1s 1.5s ease forwards;
}
.th-sub{
  margin:.85em 0 0;font-size:clamp(9px,1.5vw,12px);
  letter-spacing:.42em;color:var(--sodium);
  opacity:0;animation:thIn 1.1s 2.1s ease forwards;
}
/* ── the crossing signal ──────────────────────────────────────
   Runs on the same 5s clock as the lamp warm-up: red while the
   street loads, amber as it comes up, green when you may walk.
   A pedestrian signal turning green is a better "you may enter"
   than any instruction copy. */
.th-signal{
  --sig-off:#15161a;
  width:42px;padding:6px 5px;margin:2.1em auto 0;
  display:flex;flex-direction:column;gap:5px;align-items:center;
  background:#0b0c0e;
  border:1px solid rgba(242,236,228,.12);
  border-radius:6px;
  opacity:0;animation:thIn 1s 2.4s ease forwards;
}
/* the rim keeps the housing reading as a three-light signal even when
   two of the three are dark */
.th-signal i{
  display:block;width:20px;height:20px;border-radius:50%;
  background:var(--sig-off);
  box-shadow:inset 0 0 0 1px rgba(242,236,228,.09);
}
.th-signal .sig-r{animation:sigR 5s linear forwards}
.th-signal .sig-a{animation:sigA 5s linear forwards}
.th-signal .sig-g{animation:sigG 5s linear forwards}

@keyframes sigR{
  0%,44%  {background:#ff3b30;box-shadow:0 0 16px 3px rgba(255,59,48,.75)}
  46%,100%{background:var(--sig-off);box-shadow:none}
}
@keyframes sigA{
  0%,44%  {background:var(--sig-off);box-shadow:none}
  46%,76% {background:var(--sodium);box-shadow:0 0 16px 3px rgba(255,157,47,.75)}
  78%,100%{background:var(--sig-off);box-shadow:none}
}
@keyframes sigG{
  0%,76%  {background:var(--sig-off);box-shadow:none}
  78%,100%{background:#2fd85f;box-shadow:0 0 18px 4px rgba(47,216,95,.8)}
}

/* once armed the green is locked on, whatever the clock did */
.threshold.walk .th-signal .sig-r,
.threshold.walk .th-signal .sig-a{
  background:var(--sig-off);box-shadow:none;animation:none;
}
.threshold.walk .th-signal .sig-g{
  background:#2fd85f;box-shadow:0 0 18px 4px rgba(47,216,95,.8);animation:none;
}

.th-cue{
  margin:1.3em 0 0;font-size:clamp(11px,1.9vw,15px);
  letter-spacing:.46em;color:var(--subtle);
  text-indent:.46em;                    /* letter-spacing pads the right edge */
}
.threshold.walk .th-cue{
  color:#2fd85f;
  animation:cuePulse 2s ease-in-out infinite;
}
.th-hint{
  margin:.9em 0 0;font-size:clamp(8px,1.15vw,9.5px);
  letter-spacing:.30em;color:var(--subtle);
  text-indent:.30em;
}
@keyframes thIn{to{opacity:1}}
@keyframes cuePulse{0%,100%{opacity:.5}50%{opacity:1}}

/* ══════════════════════════════════════════════════════════════
   HUD
   ══════════════════════════════════════════════════════════════ */
.hud{
  position:fixed;z-index:20;
  font-size:clamp(8.5px,1.15vw,10.5px);
  letter-spacing:.24em;
  opacity:0;transition:opacity .9s ease .2s;
  pointer-events:none;
}
body.walking .hud{opacity:1}

.hud-tl{top:var(--pad);left:var(--pad)}
.hud-tr{top:var(--pad);right:var(--pad);display:flex;flex-direction:column;align-items:flex-end;gap:6px;text-align:right}
.hud-bl{bottom:var(--pad);left:var(--pad);display:flex;flex-direction:column;gap:7px}
.hud-br{bottom:var(--pad);right:var(--pad);pointer-events:auto}

.hud-mark{
  font-family:var(--disp);font-size:clamp(13px,1.9vw,18px);
  letter-spacing:.05em;color:var(--ink);
}

.hud-tr span{
  color:var(--muted);
  padding-right:11px;position:relative;
}
.hud-tr span::after{
  content:'';position:absolute;right:0;top:50%;
  width:5px;height:5px;margin-top:-2.5px;
  border:1px solid var(--line);
}
.hud-tr span:first-child{color:var(--sodium)}
.hud-tr span:first-child::after{background:var(--sodium);border-color:var(--sodium)}

.idx{color:var(--muted)}
.idx b{color:var(--sodium);font-weight:500}
.dist{color:var(--subtle)}

/* sound toggle */
.snd{
  display:flex;align-items:center;gap:9px;
  background:none;border:1px solid var(--line);
  color:var(--muted);cursor:pointer;
  padding:8px 13px;
  font-family:var(--mono);font-size:inherit;letter-spacing:.24em;
  transition:border-color .3s,color .3s;
}
.snd:hover{border-color:var(--sodium);color:var(--ink)}
.snd-bars{display:flex;align-items:flex-end;gap:2px;height:11px}
.snd-bars i{width:2px;height:3px;background:var(--subtle);transition:background .3s}
.snd[aria-pressed="true"]{border-color:var(--sodium);color:var(--sodium)}
.snd[aria-pressed="true"] .snd-bars i{background:var(--sodium);animation:eq .9s ease-in-out infinite}
.snd[aria-pressed="true"] .snd-bars i:nth-child(2){animation-delay:.16s}
.snd[aria-pressed="true"] .snd-bars i:nth-child(3){animation-delay:.32s}
.snd[aria-pressed="true"] .snd-bars i:nth-child(4){animation-delay:.09s}
@keyframes eq{0%,100%{height:3px}50%{height:11px}}

/* ══════════════════════════════════════════════════════════════
   NOW PLATE
   ══════════════════════════════════════════════════════════════ */
.plate{
  position:fixed;z-index:22;
  left:50%;bottom:calc(var(--pad) + 46px);
  transform:translateX(-50%);
  width:min(560px,calc(100vw - var(--pad)*2));
  text-align:center;
  opacity:0;transition:opacity .34s ease;
  pointer-events:none;
}
body.walking .plate{opacity:1}
.plate.swap .plate-in{opacity:0;transform:translateY(7px)}
.plate-in{transition:opacity .3s ease,transform .3s ease}

.plate-yr{
  margin:0 0 9px;font-size:clamp(8.5px,1.15vw,10.5px);
  letter-spacing:.34em;color:var(--sodium);
  display:flex;align-items:center;justify-content:center;gap:9px;
}
.dot{
  width:6px;height:6px;border-radius:50%;background:var(--sodium);
  animation:live 1.9s ease-in-out infinite;
}
@keyframes live{0%,100%{opacity:.3;transform:scale(.8)}50%{opacity:1;transform:scale(1)}}

.plate-title{
  font-family:var(--disp);
  font-size:clamp(28px,6.4vw,62px);
  line-height:.94;letter-spacing:.014em;
  margin:0;color:var(--ink);
  text-shadow:0 0 44px rgba(255,157,47,.30);
}
.plate-cred{
  margin:11px 0 0;font-size:clamp(9px,1.3vw,11px);
  letter-spacing:.26em;color:var(--muted);min-height:1.2em;
}
/* every director who is credited gets named; only James's two are marked */
.plate-cred .dir{color:var(--muted)}
.plate-cred .dir.mine{
  color:var(--filament);
  border-bottom:1px solid var(--sodium);
  padding-bottom:2px;
}
.plate-views{
  margin:8px 0 0;font-size:clamp(9px,1.3vw,11px);
  letter-spacing:.26em;color:var(--ink);opacity:.82;
}
.plate-cta{
  margin:17px 0 0;pointer-events:auto;
  background:none;border:1px solid var(--line);color:var(--muted);
  font-family:var(--mono);font-size:clamp(8.5px,1.15vw,10.5px);
  letter-spacing:.26em;padding:10px 20px;cursor:pointer;
  transition:border-color .3s,color .3s,background .3s;
}
.plate-cta:hover{border-color:var(--sodium);color:var(--bg);background:var(--sodium)}

/* ══════════════════════════════════════════════════════════════
   END OF THE STREET
   ══════════════════════════════════════════════════════════════ */
.endcap{
  position:fixed;inset:0;z-index:24;
  display:flex;flex-direction:column;
  align-items:center;justify-content:center;
  gap:clamp(9px,1.4vh,15px);
  text-align:center;padding:var(--pad);
  background:radial-gradient(ellipse 70% 55% at 50% 50%,rgba(5,5,6,.72),rgba(5,5,6,.97));
  opacity:0;visibility:hidden;pointer-events:none;
  transition:opacity .7s ease,visibility .7s;
}
.endcap.on{opacity:1;visibility:visible;pointer-events:auto}

/* the plate and the walk counter belong to the street, not to the endcap */
body.at-end .plate{opacity:0;pointer-events:none}
body.at-end .hud-bl,
body.at-end .hud-tr{opacity:0}

.end-kicker{font-size:clamp(8.5px,1.15vw,10.5px);letter-spacing:.42em;color:var(--sodium);margin:0}
.end-title{
  font-family:var(--disp);
  font-size:clamp(42px,10.5vw,120px);
  line-height:.9;letter-spacing:.012em;margin:.1em 0 0;
  text-shadow:0 0 60px rgba(255,157,47,.3);
}
.end-sub{font-size:clamp(9px,1.3vw,11px);letter-spacing:.26em;color:var(--muted);margin:.7em 0 0}
.end-line{
  font-size:clamp(9px,1.3vw,11px);letter-spacing:.30em;
  color:var(--subtle);margin:2.4em 0 0;
}
.end-chain{
  font-family:var(--disp);
  font-size:clamp(15px,2.5vw,26px);
  line-height:1.3;letter-spacing:.02em;
  color:var(--muted);margin:1.9em 0 0;
}
.end-chain em{
  font-style:normal;color:var(--filament);
  text-shadow:0 0 34px rgba(255,157,47,.55);
}

.end-links{
  display:flex;flex-wrap:wrap;gap:clamp(14px,3vw,32px);
  justify-content:center;margin-top:2.4em;
}
.end-links a{
  color:var(--muted);text-decoration:none;
  font-size:clamp(9px,1.3vw,11px);letter-spacing:.26em;
  padding-bottom:5px;border-bottom:1px solid transparent;
  transition:color .3s,border-color .3s;
}
.end-links a:hover{color:var(--sodium);border-color:var(--sodium)}
.end-credit{
  margin:3.4em 0 0;font-size:clamp(8px,1.05vw,9.5px);
  letter-spacing:.26em;color:var(--subtle);
}
.end-credit a{color:var(--muted);text-decoration:none;border-bottom:1px solid var(--line)}
.end-credit a:hover{color:var(--sodium)}

/* ══════════════════════════════════════════════════════════════
   LIGHTBOX
   ══════════════════════════════════════════════════════════════ */
.lb{
  position:fixed;inset:0;z-index:80;
  background:rgba(2,2,3,.96);
  display:flex;align-items:center;justify-content:center;
  padding:clamp(16px,5vw,64px);
}
.lb[hidden]{display:none}
.lb-frame{
  width:min(1180px,100%);aspect-ratio:16/9;
  border:1px solid var(--line);
  box-shadow:0 0 100px rgba(255,157,47,.13);
  background:#000;
}
.lb-frame iframe{width:100%;height:100%;border:0;display:block}
.lb-x{
  position:absolute;top:var(--pad);right:var(--pad);
  background:none;border:1px solid var(--line);color:var(--muted);
  font-family:var(--mono);font-size:clamp(8.5px,1.15vw,10.5px);
  letter-spacing:.26em;padding:10px 16px;cursor:pointer;
  transition:border-color .3s,color .3s;
}
.lb-x:hover{border-color:var(--sodium);color:var(--sodium)}

/* ══════════════════════════════════════════════════════════════
   MOBILE
   ══════════════════════════════════════════════════════════════ */
@media (max-width:720px){
  .hud-tr span:nth-child(n+3){display:none}   /* keep two stamps, not four */
  .plate{bottom:calc(var(--pad) + 58px)}
  .snd-txt{display:none}
  .snd{padding:9px 11px}
  .th-lamp{transform:scale(.82)}
}

@media (max-width:420px){
  .hud-bl .dist{display:none}
}

/* ══════════════════════════════════════════════════════════════
   REDUCED MOTION — no warm-up, no dolly easing, no grain drift.
   Content stays fully reachable.
   ══════════════════════════════════════════════════════════════ */
@media (prefers-reduced-motion:reduce){
  *,*::before,*::after{
    animation-duration:.001ms !important;
    animation-iteration-count:1 !important;
    transition-duration:.001ms !important;
  }
  .th-head i{background:var(--filament);box-shadow:0 0 78px 20px rgba(255,157,47,.85)}
  .th-cone{opacity:1}
  .th-mark,.th-sub{opacity:1}
  .grain{animation:none}
}

/* failsafe — if JS never runs, the threshold still clears */
@keyframes thFailsafe{to{opacity:0;visibility:hidden}}
.threshold{animation:thFailsafe .6s 14s forwards}
