/* ============================================================
   Mira & Yetix Adventures: Glowroot, Mission 1
   HUD, cards, controls
   Palette: gold on deep violet, warm forest. No flat modern UI.
   ============================================================ */

:root{
  --void:#241338;
  --void-deep:#1a0e2b;
  --void-soft:#38205a;
  --gold:#f7b53f;
  --gold-lt:#ffe1a0;
  --gold-hud:#ffd76a;
  --gold-dk:#a86a14;
  --violet:#8b3fd6;
  --violet-lt:#c77dff;
  --moss:#7ea63a;
  --coral:#ff5a4d;
  --cream:#f2e8d5;
  --serif: Georgia, "Palatino Linotype", "Book Antiqua", "Times New Roman", serif;
  --sans: "Trebuchet MS", "Segoe UI", system-ui, sans-serif;
  --safe-t: env(safe-area-inset-top, 0px);
  --safe-b: env(safe-area-inset-bottom, 0px);
  --safe-l: env(safe-area-inset-left, 0px);
  --safe-r: env(safe-area-inset-right, 0px);
}

*{ box-sizing:border-box; -webkit-tap-highlight-color:transparent; }

html,body{
  margin:0; padding:0; width:100%; height:100%;
  background:var(--void-deep); overflow:hidden;
  font-family:var(--sans); color:var(--cream);
  overscroll-behavior:none; touch-action:none;
  user-select:none; -webkit-user-select:none;
}

#stage{ position:fixed; inset:0; overflow:hidden; }
#view{ position:absolute; inset:0; width:100%; height:100%; display:block; }

.hidden{ display:none !important; }

/* ---------- shared storybook panel look ---------- */
.panel{
  position:relative;
  background:
    radial-gradient(120% 90% at 50% 0%, rgba(139,63,214,.30), transparent 62%),
    linear-gradient(180deg, #2f1a4e 0%, #241338 55%, #1c0f2e 100%);
  border:2px solid rgba(247,181,63,.55);
  border-radius:16px;
  box-shadow:
    0 0 0 4px rgba(26,14,43,.85),
    0 0 34px rgba(139,63,214,.45),
    inset 0 1px 0 rgba(255,225,160,.35),
    inset 0 -20px 40px rgba(0,0,0,.35);
}
/* bark/crystal facet notches down each side */
.panel::before,.panel::after{
  content:""; position:absolute; top:10px; bottom:10px; width:7px;
  background:repeating-linear-gradient(180deg,
      rgba(247,181,63,.55) 0 6px, transparent 6px 13px);
  opacity:.75;
}
.panel::before{ left:5px; border-radius:4px; }
.panel::after{ right:5px; border-radius:4px; }

/* ============================================================
   HUD
   ============================================================ */
#hud{
  position:absolute; inset:0; pointer-events:none;
  padding: calc(10px + var(--safe-t)) calc(12px + var(--safe-r)) calc(10px + var(--safe-b)) calc(12px + var(--safe-l));
  font-family:var(--sans);
}

/* ---- hearts: chunky faceted gems ---- */
/* The hearts and the shield badge share one row: the badge is a life resource
   like they are, and a row that is already on the screen cannot collide with
   anything on a narrow phone the way a chip in its own corner can. */
#liferow{ position:absolute; left:calc(12px + var(--safe-l)); top:calc(10px + var(--safe-t));
  display:flex; align-items:center; gap:10px; }
#hearts{ display:flex; gap:7px; }
.gem{
  width:34px; height:38px;
  clip-path:polygon(50% 0%,100% 26%,100% 74%,50% 100%,0% 74%,0% 26%);
  background:
    linear-gradient(160deg,#ffd9d3 0%,#ff7a6c 26%,#ff5a4d 48%,#c62f26 76%,#8e1d18 100%);
  box-shadow:0 0 12px rgba(255,90,77,.75), inset 0 2px 6px rgba(255,255,255,.4);
  transition:transform .12s ease, filter .25s ease;
}
.gem.spent{
  background:linear-gradient(160deg,#4b3a56 0%,#2c1c3c 60%,#1d1130 100%);
  box-shadow:inset 0 0 8px rgba(0,0,0,.7);
  filter:saturate(.25);
}
.gem.hit{ animation:gemHit .45s ease; }
@keyframes gemHit{
  0%{ transform:scale(1) rotate(0) }
  25%{ transform:scale(1.45,.6) rotate(-11deg) }
  50%{ transform:scale(.7,1.35) rotate(8deg) }
  75%{ transform:scale(1.15,.9) rotate(-4deg) }
  100%{ transform:scale(1) rotate(0) }
}

/* ---- the shield badge ---- */
#shieldchip{ display:flex; align-items:center; gap:5px;
  font-family:var(--serif); font-weight:700; letter-spacing:.10em;
  font-size:clamp(9px,1.6vh,12px); color:#ffe9b0;
  text-shadow:0 0 10px rgba(247,181,63,.95), 0 1px 3px #000; white-space:nowrap; }
#shieldchip i{ width:clamp(12px,2.4vh,16px); height:clamp(12px,2.4vh,16px); border-radius:50%;
  border:2px solid var(--gold-hud); box-shadow:0 0 12px var(--gold-hud);
  animation:shPulse 1.05s ease infinite; }
#shieldchip b{ font-size:1.1em; color:#fff3cd; }
@keyframes shPulse{ 0%,100%{ transform:scale(1); opacity:1 } 50%{ transform:scale(1.2); opacity:.65 } }

/* ---- the falling sky: Mission 5's countdown to the giant asteroid ----
   Amber like the shield badge, because it sits beside it, and red once the
   last ten seconds are running. It turns calm and stops moving when both
   heroes are already through the door, so a number that no longer matters
   does not keep shouting. */
#impactchip{ display:flex; align-items:center; gap:5px;
  font-family:var(--serif); font-weight:700; letter-spacing:.10em;
  font-size:clamp(9px,1.6vh,12px); color:#ffd9b0;
  text-shadow:0 0 10px rgba(255,138,52,.95), 0 1px 3px #000; white-space:nowrap; }
#impactchip i{ width:clamp(12px,2.4vh,16px); height:clamp(12px,2.4vh,16px);
  border-radius:50%; background:radial-gradient(circle at 38% 32%,#ffd9a0,#ff7a2f 62%,#7d2a06);
  box-shadow:0 0 12px rgba(255,138,52,.9); animation:impPulse 1.4s ease infinite; }
#impactchip b{ font-size:1.1em; color:#fff1de; font-variant-numeric:tabular-nums; }
#impactchip.hot{ color:#ff9a86; text-shadow:0 0 12px rgba(255,74,52,1), 0 1px 3px #000; }
#impactchip.hot i{ animation-duration:.45s; box-shadow:0 0 16px rgba(255,74,52,1); }
#impactchip.hot b{ color:#ffd9d2; }
#impactchip.safe{ color:#9ff5e6; text-shadow:0 0 10px rgba(53,224,200,.9), 0 1px 3px #000; }
#impactchip.safe i{ background:radial-gradient(circle at 38% 32%,#dffdf7,#35e0c8 62%,#10685c);
  box-shadow:0 0 12px rgba(53,224,200,.9); animation:none; }
#impactchip.safe b{ color:#e6fffb; }
@keyframes impPulse{ 0%,100%{ transform:scale(1); opacity:1 } 50%{ transform:scale(1.25); opacity:.7 } }

/* ---- score + combo ---- */
#scorewrap{
  position:absolute; left:50%; top:calc(6px + var(--safe-t)); transform:translateX(-50%);
  text-align:center; width:min(46vw,340px);
}
#score{
  font-family:var(--serif); font-weight:700;
  font-size:clamp(26px,5.2vh,46px); line-height:1;
  color:#ffe9b0; letter-spacing:.04em;
  text-shadow:0 0 14px rgba(247,181,63,.9), 0 2px 0 #8a5a12, 0 0 34px rgba(139,63,214,.7);
}
#combo{
  font-family:var(--serif); font-weight:700; letter-spacing:.06em;
  font-size:clamp(13px,2.4vh,22px); line-height:1.15; min-height:1em;
  color:var(--violet-lt); opacity:0;
  text-shadow:0 0 12px rgba(199,125,255,.95), 0 0 26px rgba(139,63,214,.8);
  transition:opacity .2s ease;
}
#combo.on{ opacity:1; }
#combo.pop{ animation:comboPop .26s ease; }
@keyframes comboPop{ 0%{ transform:scale(1) } 45%{ transform:scale(1.5) } 100%{ transform:scale(1) } }

/* ---- which level this is ---- */
/* Under the hearts, on the left, in the one part of the top of the screen that
   is empty at both shapes. The zone tag on the right names the stretch of road
   the pair are actually on and changes as they run through it; this one names
   the level and does not change. Both are wanted and neither says the other. */
#missiontag{
  position:absolute; left:calc(12px + var(--safe-l)); top:calc(54px + var(--safe-t));
  display:flex; flex-direction:column; align-items:flex-start; gap:1px;
  max-width:min(42vw,210px); pointer-events:none; text-align:left;
}
#missionno{
  font-family:var(--serif); font-weight:700;
  font-size:clamp(12px,2.1vh,17px); line-height:1.1; letter-spacing:.18em;
  color:#ffe9b0; text-shadow:0 0 12px rgba(247,181,63,.9), 0 1px 2px #000;
}
#missionname{
  font-size:clamp(9px,1.6vh,12px); line-height:1.2; letter-spacing:.16em;
  text-transform:uppercase; color:var(--gold-lt); opacity:.92;
  text-shadow:0 0 10px rgba(247,181,63,.7), 0 1px 2px #000;
}

/* ---- right bar ---- */
#rightbar{
  position:absolute; right:calc(12px + var(--safe-r)); top:calc(10px + var(--safe-t));
  display:flex; flex-direction:column; align-items:flex-end; gap:8px;
}
#zone{ display:flex; align-items:center; gap:7px; font-size:clamp(10px,1.8vh,14px); letter-spacing:.10em;
  text-transform:uppercase; color:var(--gold-lt); text-shadow:0 0 10px rgba(247,181,63,.85), 0 1px 2px #000; }
#zoneflag{ width:15px; height:19px; flex:0 0 auto;
  clip-path:polygon(0 0,100% 12%,72% 46%,100% 82%,0 100%);
  background:linear-gradient(180deg,#ffe1a0,#f7b53f 45%,#c07d18);
  box-shadow:0 0 10px rgba(247,181,63,.8); }
#buttons{ display:flex; gap:7px; pointer-events:auto; }
.chip{
  width:34px; height:34px; border-radius:50%; cursor:pointer; position:relative;
  border:2px solid rgba(247,181,63,.6);
  background:radial-gradient(circle at 34% 28%, #6a3aa8 0%, #43217a 46%, #26133f 100%);
  box-shadow:0 0 14px rgba(139,63,214,.6), inset 0 1px 0 rgba(255,255,255,.28);
  padding:0;
}
.chip::after{ content:""; position:absolute; inset:0; display:block; background-repeat:no-repeat; background-position:center; background-size:15px 15px; }
.chip:active{ transform:scale(.92); }
#btnPause::after{ background-image:linear-gradient(var(--gold-hud),var(--gold-hud)),linear-gradient(var(--gold-hud),var(--gold-hud));
  background-size:4px 13px,4px 13px; background-position:calc(50% - 4px) 50%, calc(50% + 4px) 50%; }
#btnPause.paused::after{ background-image:none;
  border-left:11px solid var(--gold-hud); border-top:8px solid transparent; border-bottom:8px solid transparent;
  width:0; height:0; inset:auto; margin:auto; background-size:0; }
#btnMute::after{ background-image:none; }
#btnMute svg{ position:absolute; inset:0; margin:auto; width:17px; height:17px; }
#btnMute.off{ border-color:rgba(255,255,255,.22); }
#btnMute.off svg{ opacity:.35; }

/* ---- the run meter: the pair on the left, the guardian on the right ---- */
#progress{
  position:absolute; left:50%; top:calc(62px + var(--safe-t)); transform:translateX(-50%);
  width:min(76vw,640px); display:flex; align-items:center; gap:7px; pointer-events:none;
}
.pgend{ display:flex; align-items:center; gap:6px; flex:0 0 auto; }
/* the pair share one label, so their two circles overlap into one group */
.pggroup{ display:flex; align-items:center; flex:0 0 auto; }
/* A pair, not a pile. The two circles overlapped by up to eighteen pixels on a
   thirty-eight pixel circle, so the cream of Yetix covered better than a third
   of Mira and the pair read as one blob instead of two adventurers. They still
   touch, so they are a pair, and the first one is drawn in front so the overlap
   is a shoulder in front of a shoulder rather than a face half hidden. */
.pggroup img + img{ margin-left:calc(-1 * clamp(4px,0.8vh,7px)); }
.pggroup img:first-child{ position:relative; z-index:2; }
.pgend img{
  width:clamp(26px,4.8vh,38px); height:clamp(26px,4.8vh,38px); border-radius:50%;
  object-fit:cover; display:block;
  border:2px solid rgba(247,181,63,.6);
  background:radial-gradient(circle at 50% 38%, rgba(90,50,150,.9), rgba(26,14,43,.95));
  box-shadow:0 0 14px rgba(139,63,214,.7), inset 0 0 10px rgba(0,0,0,.55);
  transition:box-shadow .3s ease, border-color .3s ease;
}
.pgname{ font-family:var(--serif); font-size:clamp(8px,1.5vh,12px); letter-spacing:.13em;
  color:rgba(255,225,160,.88); text-shadow:0 1px 3px #000; white-space:nowrap; }
#pgtrack{
  position:relative; flex:1 1 auto; height:clamp(17px,3vh,23px); border-radius:999px;
  background:linear-gradient(180deg,#2b1846,#150a24);
  border:2px solid rgba(247,181,63,.5);
  box-shadow:inset 0 2px 6px rgba(0,0,0,.85), 0 0 12px rgba(139,63,214,.4);
  overflow:hidden;
}
#pgfill{
  position:absolute; left:0; top:0; bottom:0; width:0;
  background:linear-gradient(90deg,#8a5510 0%,#f7b53f 42%,#ffe1a0 72%,#fff6d8 100%);
  box-shadow:0 0 16px rgba(247,181,63,.9);
  transition:width .2s linear;
}
#pgpct{
  position:absolute; right:7px; top:50%; transform:translateY(-50%);
  font-family:var(--serif); font-weight:700; font-size:clamp(9px,1.7vh,13px);
  color:#ffe9b0; text-shadow:0 0 8px rgba(0,0,0,.95), 0 1px 3px #000, 0 0 12px rgba(247,181,63,.8);
}
/* the other player, in a race: where they are along the same corridor */
#pgdot{
  position:absolute; top:50%; left:0; width:9px; height:9px; margin:-4.5px 0 0 -4.5px;
  border-radius:50%; background:var(--violet-lt);
  box-shadow:0 0 12px var(--violet-lt), 0 0 22px rgba(139,63,214,.9);
  transition:left .2s linear;
}
#progress.near #pgBoss{ border-color:var(--violet-lt);
  box-shadow:0 0 20px var(--violet-lt), 0 0 34px rgba(139,63,214,.9);
  animation:bossNear 1.1s ease infinite; }
@keyframes bossNear{ 0%,100%{ transform:scale(1) } 50%{ transform:scale(1.12) } }
#progress.near #pgRight .pgname{ color:var(--violet-lt); text-shadow:0 0 12px rgba(199,125,255,.95), 0 1px 3px #000; }

/* the rival's card in a race */
#rivalcard{
  position:absolute; left:50%; top:calc(104px + var(--safe-t)); transform:translateX(-50%);
  display:flex; align-items:center; gap:8px; padding:3px 12px; border-radius:999px;
  background:rgba(26,14,43,.72); border:1px solid rgba(199,125,255,.4);
  font-size:clamp(9px,1.7vh,13px); letter-spacing:.1em; color:var(--cream);
  text-shadow:0 1px 3px #000; pointer-events:none; white-space:nowrap;
}
#rivalcard b{ font-family:var(--serif); color:var(--violet-lt); letter-spacing:.06em; }
#rivalcard .rsc{ color:var(--gold-hud); font-family:var(--serif); }

/* ---- boss health ---- */
#bosshp{ position:absolute; left:50%; top:calc(66px + var(--safe-t)); transform:translateX(-50%);
  width:min(66vw,560px); text-align:center; }
#bosshpframe{
  height:19px; border-radius:5px; padding:2px;
  background:linear-gradient(180deg,#3a2418,#20130c);
  border:2px solid rgba(247,181,63,.55);
  box-shadow:0 0 18px rgba(139,63,214,.55), inset 0 2px 5px rgba(0,0,0,.8);
}
#bossfill{
  height:100%; width:100%; border-radius:3px;
  background:repeating-linear-gradient(90deg, rgba(0,0,0,.30) 0 2px, transparent 2px 26px),
             linear-gradient(180deg,#e5b6ff 0%,#c77dff 30%,#8b3fd6 70%,#5a2091 100%);
  box-shadow:0 0 16px rgba(199,125,255,.9); transition:width .22s ease;
}
#bossname{ margin-top:4px; font-size:clamp(9px,1.6vh,12px); letter-spacing:.22em; color:var(--gold-lt);
  text-shadow:0 0 10px rgba(199,125,255,.9), 0 1px 2px #000; }

/* ---- zone banner ---- */
#zonebanner{
  position:absolute; left:50%; top:38%; transform:translate(-50%,-50%); text-align:center;
  font-family:var(--serif); font-size:clamp(20px,4.4vh,40px); letter-spacing:.14em;
  color:#ffe9b0; opacity:0; pointer-events:none; text-transform:uppercase;
  text-shadow:0 0 18px rgba(247,181,63,.95), 0 0 44px rgba(139,63,214,.8), 0 3px 0 #7a4d10;
}
#zonebanner.show{ animation:zoneIn 2.6s ease forwards; }
@keyframes zoneIn{ 0%{opacity:0;transform:translate(-50%,-50%) scale(.82)} 18%{opacity:1;transform:translate(-50%,-50%) scale(1)} 74%{opacity:1} 100%{opacity:0} }

/* ============================================================
   CUE
   ============================================================ */
/* The cue sits over the brightest, busiest thing on screen: the lit dirt of the
   lane band. Gold on brown and violet on brown are both barely there, so it
   carries its own dark scrim and lives above the play area rather than in it. */
#cuewrap{
  position:absolute; left:50%; bottom:clamp(120px,36vh,300px); transform:translateX(-50%);
  display:flex; flex-direction:column; align-items:center; gap:2px;
  pointer-events:none; text-align:center; opacity:1;
  padding:6px 22px 8px; border-radius:18px;
  background:radial-gradient(ellipse at 50% 55%, rgba(20,10,34,.80) 0%, rgba(20,10,34,.62) 55%, rgba(20,10,34,0) 100%);
}
#cueglyph{ font-size:clamp(30px,7.6vh,62px); line-height:1;
  filter:drop-shadow(0 0 14px currentColor) drop-shadow(0 0 30px currentColor); }
#cueword{
  font-family:var(--serif); font-weight:700; letter-spacing:.16em;
  font-size:clamp(22px,6.2vh,46px); line-height:1.05;
  text-shadow:0 0 16px currentColor, 0 0 42px currentColor, 0 3px 0 rgba(0,0,0,.75);
}
#cuewrap.move{ color:var(--gold-hud); }
#cuewrap.atk{ color:var(--violet-lt); }
/* `backwards` rather than `both`: the fade still starts from nothing, but a
   finished (or never started) fade falls back to the base opacity, so the cue
   can never be left sitting at zero by a stalled animation. That failure looks
   exactly like a cue that never fired, and the player would have no way to tell
   it apart from a bug in the pairing. */
#cuewrap.cue-in{ animation:cueIn .16s ease backwards; }
#cuewrap.cue-out{ animation:cueOut .22s ease both; }
@keyframes cueIn{ from{ opacity:0; transform:translateX(-50%) scale(1.5) } to{ opacity:1; transform:translateX(-50%) scale(1) } }
@keyframes cueOut{ to{ opacity:0; transform:translateX(-50%) scale(.9) } }
#cuewrap.ok #cueword{ color:#bff08a; text-shadow:0 0 18px #7ea63a, 0 0 40px #4e701f; }

/* In the guardian's clearing the cue drops below the boss. The chest core is
   the hit target and it sits mid-frame; a PUNCH the height of a house across
   it hides the one thing the player has to aim at. Smaller and lower, it still
   reads at a glance and leaves the guardian clear. */
body.bossfight #cuewrap{ bottom:clamp(84px,20vh,158px); padding:3px 14px 4px; }
body.bossfight #cueglyph{ font-size:clamp(20px,4.6vh,32px); }
body.bossfight #cueword{ font-size:clamp(16px,4.2vh,26px); letter-spacing:.14em; }

/* lane flash for LEFT / RIGHT */
.laneflash{
  position:absolute; bottom:0; top:36%; width:19%; pointer-events:none; opacity:0;
  background:linear-gradient(0deg, rgba(247,181,63,.42), rgba(247,181,63,0) 78%);
}
.laneflash.go{ animation:laneGo .85s ease-out; }
@keyframes laneGo{ 0%{opacity:0} 22%{opacity:1} 100%{opacity:0} }

/* ============================================================
   Legend
   ============================================================ */
#legend{
  position:absolute; left:calc(10px + var(--safe-l)); bottom:calc(8px + var(--safe-b));
  display:flex; gap:9px; flex-wrap:wrap; max-width:58vw;
  font-size:clamp(8px,1.5vh,11px); letter-spacing:.05em; color:rgba(255,225,160,.78);
  text-shadow:0 1px 3px #000; pointer-events:none;
}
#legend .lg{ display:flex; align-items:center; gap:4px; }
#legend b{ color:var(--gold-hud); font-family:var(--serif); }
#legend.new{ animation:lgPop 1s ease; }
@keyframes lgPop{ 0%{ transform:scale(1.5); filter:brightness(2) } 100%{ transform:scale(1) } }

/* ============================================================
   Touch controls
   ============================================================ */
#touch{ position:absolute; inset:0; pointer-events:none; z-index:6; }
#touch > div{ position:absolute; bottom:calc(10px + var(--safe-b)); display:flex; gap:10px; align-items:flex-end; pointer-events:auto; }
#tbLeft{ left:calc(12px + var(--safe-l)); }
#tbRight{ right:calc(12px + var(--safe-r)); flex-wrap:wrap; justify-content:flex-end; max-width:46vw; }

.tbtn{
  font-family:var(--serif); font-weight:700; letter-spacing:.06em;
  color:#ffe9b0; cursor:pointer; border:2px solid rgba(247,181,63,.62);
  background:radial-gradient(circle at 36% 26%, rgba(120,70,190,.62) 0%, rgba(60,30,105,.55) 52%, rgba(30,16,52,.55) 100%);
  box-shadow:0 0 16px rgba(139,63,214,.5), inset 0 1px 0 rgba(255,255,255,.25);
  backdrop-filter:blur(3px); -webkit-backdrop-filter:blur(3px);
  transition:transform .07s ease, box-shadow .12s ease, background .12s ease;
}
.tbtn.round{ width:clamp(56px,12.4vh,80px); height:clamp(56px,12.4vh,80px); border-radius:50%;
  font-size:clamp(9px,1.7vh,13px); }
#tbLeft .tbtn{ width:clamp(62px,14vh,88px); height:clamp(50px,11vh,66px); border-radius:14px;
  font-size:clamp(16px,3vh,24px); }
.tbtn.atk{ border-color:rgba(199,125,255,.75); box-shadow:0 0 18px rgba(139,63,214,.7), inset 0 1px 0 rgba(255,255,255,.25); }
.tbtn.press{ transform:scale(.9); background:radial-gradient(circle at 40% 30%, rgba(199,125,255,.85), rgba(139,63,214,.6)); box-shadow:0 0 26px rgba(199,125,255,.95); }

/* ============================================================
   Cards (title / game over / victory / pause)
   ============================================================ */
#card{
  position:absolute; inset:0; z-index:10; display:none;
  align-items:center; justify-content:center; padding:14px;
  background:radial-gradient(120% 100% at 50% 40%, rgba(36,19,56,.55), rgba(16,8,26,.90));
  overflow:auto;
}
#card.on{ display:flex; }
/* The end of a run is a card over a scene that is still live: the arena, the
   guardian and the pair are all behind it, and that frame is what tells a
   person where they were when it ended. The wash over them was thick enough
   that the scene read as a dark smear and neither adventurer could be made out
   behind the panel. Thinned only on these cards, which are the game-over,
   victory and escape-result cards: the panel is its own opaque plate, so the
   wash lightens without taking anything the card needs for its own text, and
   the leaderboard, which draws its own wider plate, is left as dark as it was. */
#card.small:not(.boardcard){
  background:radial-gradient(120% 100% at 50% 40%, rgba(36,19,56,.22), rgba(16,8,26,.52));
}
/* The pause banner owns its own element, so no card path can ever turn a paused
   game into a full menu over the play area. It is a strip above the lane: the
   hero, the guardian and everything the player is reading stay visible, and it
   stops well short of the middle of the screen. */
#pausebar{
  position:absolute; left:50%; top:calc(8px + var(--safe-t)); transform:translateX(-50%);
  z-index:11; display:flex; align-items:center; gap:clamp(6px,1.2vw,11px);
  flex-wrap:wrap; justify-content:center;
  /* THE WIDTH IS STATED AND NOT ONLY CAPPED, for the reason the toast states
     its own: a box centred with `left:50%` and no width is sized by
     shrink-to-fit, and the version line inside it is laid out against a width
     the bar has not chosen yet. On a 390-wide phone that produced a bar 195px
     across and 184px tall, the build line wrapping onto two rows inside a
     column narrower than the sentence, and `HOME` alone on a row above it.
     Given its natural width it is 374px across and 88px tall, one row of
     buttons and one of the version, which is also a quarter less of the play
     area covered. Measured at 390x844, 844x390, 1440x900 and 360x640. */
  width:max-content; max-width:96vw;
  padding:clamp(5px,1.1vh,9px) clamp(10px,2vw,18px);
  /* AND THE PILL IS ONLY A PILL WHILE THE BAR IS ONE ROW. 999px is clamped to
     half the box, so a wrapped bar of four rows gets a curve the height of a
     small button cut into each corner, and the corners it cuts off are where
     the last row's text is. The version line sat 16px off the left edge of its
     own background and 20px off the right, over the scene, with no ground
     behind it. A radius that stays under half the height at any height gives
     the same stadium on a single row and a rounded card on three. */
  border-radius:28px;
  background:rgba(26,14,43,.88);
  border:1px solid rgba(199,125,255,.42);
  box-shadow:0 6px 26px rgba(10,4,20,.62);
}
#pausebar.pb-in{ animation:pbIn .16s ease both; }
@keyframes pbIn{ from{ opacity:0; transform:translateX(-50%) translateY(-10px) } to{ opacity:1; transform:translateX(-50%) translateY(0) } }
#pausebar .pb-word{
  font-family:var(--serif); font-weight:700; letter-spacing:.18em;
  font-size:clamp(12px,2.1vh,19px); color:#ffe9b0;
  text-shadow:0 0 12px rgba(199,125,255,.9), 0 1px 2px #000;
}
#pausebar .btn{ margin:0; padding:5px 13px; font-size:clamp(10px,1.8vh,15px); letter-spacing:.1em; }
/* margin:auto rather than centring from the parent: a centred flex item that is
   taller than the box has its top clipped and cannot be scrolled back to, and
   the title card is taller than a phone held in landscape */
#card .panel{ width:100%; max-width:720px; margin:auto; padding:clamp(14px,3vh,26px) clamp(16px,4vw,34px); text-align:center; }
#card.small .panel{ width:100%; max-width:440px; }

/* --- the logo treatment --- */
.logo{ font-family:var(--serif); font-weight:700; margin:0 0 2px; letter-spacing:.02em; line-height:1; }
.logo .l1{
  display:block; font-size:clamp(30px,8.6vh,68px);
  background:linear-gradient(180deg,#fff6d0 0%,#ffe1a0 20%,#f7b53f 42%,#b87418 58%,#ffe9b0 74%,#eaa22a 100%);
  -webkit-background-clip:text; background-clip:text; color:transparent;
  filter:drop-shadow(0 0 16px rgba(168,85,247,.85)) drop-shadow(0 0 46px rgba(139,63,214,.65)) drop-shadow(0 3px 0 rgba(80,44,6,.9));
}
.logo .l2{
  display:block; font-size:clamp(17px,4.4vh,34px); letter-spacing:.14em; margin-top:.18em;
  background:linear-gradient(180deg,#fff6d0 0%,#ffe1a0 22%,#f7b53f 46%,#a86a14 62%,#ffe9b0 80%,#eaa22a 100%);
  -webkit-background-clip:text; background-clip:text; color:transparent;
  filter:drop-shadow(0 0 12px rgba(168,85,247,.8)) drop-shadow(0 2px 0 rgba(80,44,6,.9));
}
.tagline{ font-size:clamp(10px,1.9vh,14px); letter-spacing:.16em; text-transform:uppercase;
  color:rgba(255,225,160,.74); margin:6px 0 12px; }

/* --- hero picker --- */
.heroes{ display:flex; gap:10px; justify-content:center; margin:6px 0 12px; flex-wrap:wrap; }
/* Two heroes, side by side, at every width the page is opened at. Sized from
   the panel rather than from the viewport, because the viewport is not what
   they sit in: at 42vw on a 390px phone each card wanted 164px inside 330px of
   panel, missed by eight, and wrapped to one column. That cost 190px of height
   on the screen where height is scarcest and pushed the last button below the
   fold. The percentage shrinks with the panel; the clamp keeps a card wide
   enough to read and no wider than the laptop wants. */
.hero{
  cursor:pointer; flex:0 1 auto; width:clamp(118px,44%,196px); padding:8px;
  border-radius:13px; border:2px solid rgba(247,181,63,.28);
  background:linear-gradient(180deg, rgba(56,32,90,.7), rgba(26,14,43,.7));
  transition:border-color .15s, transform .12s, box-shadow .15s; text-align:center;
}
.hero:hover{ transform:translateY(-2px); }
.hero.sel{ border-color:var(--gold); box-shadow:0 0 22px rgba(247,181,63,.6), inset 0 0 22px rgba(139,63,214,.35); }
/* The portrait the person sent, whole and proportional. object-fit: contain
   rather than cover because the two pictures are framed differently, one to
   the shoulders and one to the waist, and cropping either to a common box
   would cut the tusks off one and the beanie off the other. */
.hero .hp{ width:100%; height:clamp(112px,23vh,190px); display:block;
  object-fit:contain; object-position:50% 100%; }
.hero canvas{ width:100%; height:clamp(74px,17vh,124px); display:block; }
.hero .hn{ font-family:var(--serif); font-size:clamp(13px,2.5vh,19px); color:#ffe9b0; margin-top:4px;
  text-shadow:0 0 10px rgba(247,181,63,.7); }
.hero .hr{ font-size:clamp(8px,1.5vh,11px); letter-spacing:.08em; color:rgba(255,225,160,.62); }

/* --- difficulty picker ---
   Three buttons in one row at every width, for the same reason the hero cards
   are: a wrapped row costs height on the screen where height is scarcest. The
   label is small and the blurb smaller, so three fit inside the panel of a
   phone held upright without a scroll. */
.diffs{ margin:0 0 8px; }
.diffs .dlabel{ font-size:clamp(8px,1.5vh,11px); letter-spacing:.2em; text-transform:uppercase;
  color:rgba(255,225,160,.55); margin-bottom:5px; }
.diffs .drow{ display:flex; gap:6px; justify-content:center; }
.diff{
  cursor:pointer; flex:1 1 0; min-width:0; padding:6px 4px; border-radius:10px;
  border:2px solid rgba(247,181,63,.24); font:inherit; text-align:center;
  /* a thumb, not a mouse: the row is three buttons across the narrowest phone
     and each one still has to be big enough to hit without looking */
  min-height:46px; display:flex; flex-direction:column; justify-content:center;
  background:linear-gradient(180deg, rgba(50,29,82,.7), rgba(26,14,43,.7));
  transition:border-color .15s, transform .12s, box-shadow .15s;
}
.diff:hover{ transform:translateY(-1px); }
.diff b{ display:block; font-family:var(--serif); font-size:clamp(11px,2.1vh,15px);
  letter-spacing:.05em; color:#ffe9b0; }
.diff span{ display:block; margin-top:2px; font-size:clamp(7px,1.3vh,10px); line-height:1.2;
  letter-spacing:.04em; color:rgba(255,225,160,.6); }
.diff.sel{ border-color:var(--gold); box-shadow:0 0 20px rgba(247,181,63,.55), inset 0 0 18px rgba(139,63,214,.32); }
/* Horror is the one that is meant to read as a warning, so it is the one that
   marks itself in coral rather than in the gold every other choice uses. */
.diff[data-diff="horror"].sel{ border-color:#e8533f; box-shadow:0 0 20px rgba(232,83,63,.6), inset 0 0 18px rgba(139,63,214,.32); }

/* --- missions ---
   The first choice on the card, so it is laid out like the difficulty row and
   sits above it. A level that is not open yet is drawn dimmed rather than
   hidden: a person who cannot see Mission 2 has no reason to finish Mission 1,
   and a person who can see it locked has one. */
.missions{ margin:0 0 8px; }
.missions .dlabel{ font-size:clamp(8px,1.5vh,11px); letter-spacing:.2em; text-transform:uppercase;
  color:rgba(255,225,160,.55); margin-bottom:5px; }
.missions .mrow{ display:flex; gap:6px; justify-content:center; }
.mission{
  cursor:pointer; flex:1 1 0; min-width:0; padding:6px 8px; border-radius:10px;
  border:2px solid rgba(247,181,63,.24); font:inherit; text-align:left;
  min-height:46px; display:flex; flex-direction:column; justify-content:center;
  background:linear-gradient(180deg, rgba(50,29,82,.7), rgba(26,14,43,.7));
  transition:border-color .15s, transform .12s, box-shadow .15s;
}
.mission:hover:not([disabled]){ transform:translateY(-1px); }
.mission b{ display:block; font-family:var(--serif); font-size:clamp(10px,1.9vh,14px);
  letter-spacing:.05em; color:#ffe9b0; }
.mission span{ display:block; margin-top:2px; font-size:clamp(7px,1.3vh,10px); line-height:1.2;
  letter-spacing:.04em; color:rgba(255,225,160,.6); }
.mission.sel{ border-color:var(--gold); box-shadow:0 0 20px rgba(247,181,63,.55), inset 0 0 18px rgba(139,63,214,.32); }
.mission[disabled]{ cursor:default; opacity:.5; }
.mission[disabled] span{ color:rgba(199,125,255,.75); }
/* the second mission wears the ice it is made of, in its own selection ring */
.mission[data-mission="m2"].sel{ border-color:#9fdcff; box-shadow:0 0 20px rgba(159,220,255,.5), inset 0 0 18px rgba(70,150,220,.3); }
.missions .mrowbrowse{ display:flex; justify-content:center; margin-top:6px; }
.missions .mrowbrowse .btn{ padding:6px 14px; font-size:clamp(9px,1.6vh,12px); }

/* --- buttons --- */
.btn{
  font-family:var(--serif); font-weight:700; cursor:pointer;
  font-size:clamp(15px,2.9vh,24px); letter-spacing:.13em;
  padding:.42em 1.35em; margin:5px 5px; border-radius:12px;
  color:#3a1f05; border:2px solid #7a4d10;
  background:linear-gradient(180deg,#fff2c8 0%,#ffd76a 26%,#f7b53f 55%,#d9911f 100%);
  box-shadow:0 0 22px rgba(247,181,63,.55), 0 4px 0 #7a4d10, inset 0 1px 0 rgba(255,255,255,.7);
  transition:transform .08s, box-shadow .15s;
}
.btn:hover{ box-shadow:0 0 34px rgba(199,125,255,.85), 0 0 22px rgba(247,181,63,.75), 0 4px 0 #7a4d10, inset 0 1px 0 rgba(255,255,255,.8); }
.btn:active{ transform:translateY(3px); box-shadow:0 0 26px rgba(199,125,255,.9), 0 1px 0 #7a4d10; }
.btn.ghost{
  color:#ffe9b0; background:linear-gradient(180deg, rgba(90,52,150,.75), rgba(42,22,72,.8));
  border-color:rgba(199,125,255,.6); box-shadow:0 0 16px rgba(139,63,214,.5), 0 3px 0 #1c0f2e;
}
.btn.ghost:hover{ box-shadow:0 0 28px rgba(199,125,255,.9), 0 3px 0 #1c0f2e; }

.keys{ display:grid; grid-template-columns:repeat(auto-fit,minmax(128px,1fr)); gap:5px 12px;
  margin:12px auto 4px; max-width:600px; font-size:clamp(9px,1.7vh,13px); color:rgba(255,225,160,.82); }
.keys div{ display:flex; justify-content:space-between; gap:8px; padding:3px 8px;
  border-bottom:1px solid rgba(247,181,63,.16); }
.keys b{ color:var(--gold-hud); font-family:var(--serif); letter-spacing:.05em; }

.stat{ font-family:var(--serif); font-size:clamp(14px,2.8vh,22px); color:#ffe9b0; margin:4px 0;
  text-shadow:0 0 12px rgba(247,181,63,.7); }
.stat em{ font-style:normal; color:var(--violet-lt); text-shadow:0 0 12px rgba(199,125,255,.9); }
.small{ font-size:clamp(9px,1.6vh,12px); letter-spacing:.08em; color:rgba(255,225,160,.6); margin-top:8px; }

/* ---- the player's name ---- */
.namefield{ display:flex; align-items:center; justify-content:center; gap:8px; margin:10px 0 6px; flex-wrap:wrap; }
.namefield label{ font-size:clamp(9px,1.6vh,12px); letter-spacing:.18em; text-transform:uppercase;
  color:rgba(255,225,160,.78); }
.namefield input{
  font-family:var(--serif); font-weight:700; text-align:center;
  font-size:clamp(12px,2.2vh,17px); letter-spacing:.06em;
  width:min(58vw,240px); padding:5px 10px; border-radius:9px; outline:none;
  color:#ffe9b0; background:rgba(18,9,31,.85);
  border:2px solid rgba(247,181,63,.5);
}
.namefield input:focus{ border-color:var(--gold); box-shadow:0 0 18px rgba(247,181,63,.6); }
.namefield input::placeholder{ color:rgba(255,225,160,.35); }

/* ---- who this is: guest or account, said under the name ---- */
.acctstrip{
  display:flex; flex-wrap:wrap; justify-content:center; align-items:baseline;
  gap:2px 8px; margin:2px auto 4px; max-width:44em; text-align:center;
  /* the strip is the door to the account card, so it has to read as one:
     a real target on a phone held upright, and pressable */
  cursor:pointer; padding:4px 6px; border-radius:10px;
  -webkit-tap-highlight-color:transparent;
}
.acctstrip:hover .alook, .acctstrip:focus-visible .alook{ color:#ffe9b0; }
.acctstrip:focus-visible{ outline:2px solid var(--gold); outline-offset:2px; }
.acctstrip .awho{ font-size:clamp(10px,1.7vh,13px); letter-spacing:.06em;
  color:rgba(255,225,160,.9); }
.acctstrip .awho b{ color:#ffe9b0; }
.acctstrip .akeep{ font-size:clamp(9px,1.5vh,11.5px); line-height:1.5;
  color:rgba(242,232,213,.6); }
/* the strip is the door to the account card, so it has to read as one: gold,
   underlined, and big enough to be a target on a phone held upright */
.acctstrip .alook{ font-size:clamp(9px,1.5vh,11.5px); line-height:1.5;
  color:var(--gold); text-decoration:underline; text-underline-offset:2px; }

/* ---- what an account adds, on the card the button opens ---- */
/* Four of these and three buttons have to fit a phone held upright without a
   button falling off the bottom edge, so the rows are tight by design: a
   card that scrolls is a card where the way out is hidden. */
.benlist{ display:grid; gap:5px; margin-top:8px; text-align:left;
  grid-template-columns:repeat(auto-fit,minmax(215px,1fr)); }
.benrow{
  background:rgba(12,7,20,.55); border:1px solid rgba(199,125,255,.24);
  border-radius:10px; padding:7px 10px; min-width:0;
}
.benrow b{ display:block; font-family:var(--serif); letter-spacing:.02em;
  color:#e3c6ff; font-size:clamp(10.5px,1.7vh,13.5px); }
.benrow span{ display:block; margin-top:3px; line-height:1.42;
  font-size:clamp(9.5px,1.4vh,11.5px); color:rgba(242,232,213,.78); }
#card .btn{ padding:clamp(9px,1.5vh,13px) clamp(10px,2vw,22px); }
/* THE WAY OUT OF THE CARD IS NEVER BELOW THE FOLD, AT ANY SIZE.
   Read off the page rather than assumed: the title card is 856 pixels tall in
   a 390-pixel viewport, 1309 in 800 and 1079 in 650, and the button that
   starts the game began at 527, 770 and 682, so at a phone's height it was a
   scroll away and at a laptop's it was not on the screen at all, or cut
   through the middle of its own letters. Every card the game draws is a
   scroller and the way out is the one thing a person must not have to hunt
   for, so on the title card this one row stays in any window while the rest
   of the card scrolls past it.

   IT IS A SIBLING OF THE SCROLLER AND NOT A STICKY ROW INSIDE IT. A sticky row
   pinned to the foot of a scroller lands on top of whatever the person has
   scrolled to that spot, and on the title card that spot was a control: at 390
   by 844 the pinned PLAY sat exactly over the chosen difficulty button, so a
   tap meant for Medium started the game instead. Read off the page, the two
   boxes overlapped by 55 pixels vertically and the player's own difficulty
   choice was unreachable. Split out of the scroller it takes its own space at
   the foot of the panel and can cover nothing, at any size.

   The fade above it is what settles the bar into the panel's own colour, which
   darkens towards its foot, rather than drawing a hard seam across the card. */
#card .playrow{
  position:relative; z-index:3;
  margin-top:9px; padding:8px 0 5px;
  background:linear-gradient(180deg,
    rgba(26,14,43,0) 0%, rgba(26,14,43,.78) 30%, rgba(26,14,43,.95) 100%);
}
/* THE ONE CARD WHOSE BODY SCROLLS UNDER A BAR THAT IS NOT PART OF IT.
   The panel is a column: the body takes the height that is left and scrolls
   inside it, and the row that starts the game keeps its own height at the
   foot. Nothing overlaps, so nothing the person can press is ever covered. On
   a screen the card already fits the body does not scroll and the panel is
   exactly as tall as its content, which is the card that shipped before this
   change. */
#card.titlecard{ overflow:hidden; }
#card.titlecard .panel{ display:flex; flex-direction:column; max-height:100%; }
#card.titlecard .cardbody{
  flex:1 1 auto; min-height:0;
  overflow-y:auto; overflow-x:hidden;
  -webkit-overflow-scrolling:touch;
  overscroll-behavior:contain;
  /* THE FOLD SAYS SO. This body is the only thing on the first screen that
     scrolls, and it scrolls a long way: measured on this build at 1280 by 720
     the body is 562 pixels tall against 1,116 of content, and at 390 by 844 it
     is 673 against 1,593. Chromium draws no scrollbar for an overlay scroller
     (`offsetWidth - clientWidth` comes back 0), so there was nothing on screen
     to say the card continued: the two portrait cards were sliced flat across
     at the fold, which reads as a broken picture, and the difficulty row's own
     label was cut through with its three buttons under it. The content is
     MASKED, not covered: the last 54 pixels of the body fade out and the
     card's own gradient shows through, so no colour has to be matched to the
     card and nothing is drawn on top of anything. `atop` adds the same fade at
     the top once the body has been scrolled, and `atend` takes the bottom one
     away at the bottom of the scroll so nothing is dimmed when there is
     nothing under it. The two classes are set by cardFade() in js/main.js. */
  -webkit-mask-image:linear-gradient(to bottom,
    #000 0, #000 calc(100% - 54px), transparent 100%);
  mask-image:linear-gradient(to bottom,
    #000 0, #000 calc(100% - 54px), transparent 100%);
}
#card.titlecard .cardbody.atop{
  -webkit-mask-image:linear-gradient(to bottom,
    transparent 0, #000 26px, #000 calc(100% - 54px), transparent 100%);
  mask-image:linear-gradient(to bottom,
    transparent 0, #000 26px, #000 calc(100% - 54px), transparent 100%);
}
#card.titlecard .cardbody.atend{
  -webkit-mask-image:none; mask-image:none;
}
#card.titlecard .cardbody.atend.atop{
  -webkit-mask-image:linear-gradient(to bottom, transparent 0, #000 26px);
  mask-image:linear-gradient(to bottom, transparent 0, #000 26px);
}
#card.titlecard .playrow{ flex:0 0 auto; }
/* the one card that carries a list and three buttons: its logo gives up
   height so the way out stays on the screen */
.logo.tight .l1{ font-size:clamp(24px,6.2vh,44px); }
.logo.tight .l2{ font-size:clamp(15px,3.6vh,26px); margin-top:.12em; }

/* ---- the scoreboard: the best thirteen, always saved ---- */
.board{ margin:12px auto 0; width:min(100%,460px); text-align:left; }
.board .bt{
  display:flex; justify-content:space-between; align-items:baseline; gap:8px;
  font-family:var(--serif); letter-spacing:.16em; text-transform:uppercase;
  font-size:clamp(10px,1.9vh,14px); color:var(--gold-lt); margin-bottom:5px;
  text-shadow:0 0 12px rgba(247,181,63,.8), 0 1px 3px #000;
}
.board .bt small{ font-family:var(--sans); font-size:clamp(7px,1.3vh,10px); letter-spacing:.1em;
  color:rgba(255,225,160,.55); }
.brow{ display:flex; align-items:center; gap:8px; padding:2px 8px; border-radius:7px;
  font-size:clamp(9px,1.7vh,13px); border-bottom:1px solid rgba(247,181,63,.13); }
.brow .rk{ flex:0 0 2.3em; font-family:var(--serif); color:var(--gold-hud); }
.brow .nm{ flex:1 1 auto; min-width:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap;
  color:var(--cream); }
.brow .nm a{ color:inherit; text-decoration:none; border-bottom:1px dotted rgba(255,225,160,.45); }
.brow .sc{ flex:0 0 auto; font-family:var(--serif); color:#ffe9b0; }
.brow.mine{ background:linear-gradient(90deg, rgba(139,63,214,.42), rgba(139,63,214,0)); }
.brow.mine .nm{ color:#e8ccff; }
.brow.podium .rk{ color:#fff3cd; text-shadow:0 0 10px rgba(247,181,63,.9); }
/* THE THIRTEEN PLACES ARE ALWAYS DRAWN. An open one is quieter than a held one
   and is not pretending to be a player: no name, no score, dimmed. */
.brow.open{ opacity:.34; }
.brow.open .nm{ font-style:italic; }
/* the player's own record, set under the thirteen when it is not in them */
.brow.below{ margin-top:4px; border-top:1px solid rgba(247,181,63,.4); border-bottom:none; }
.board .none{ text-align:center; padding:6px 0; font-size:clamp(9px,1.6vh,12px);
  color:rgba(255,225,160,.55); }
/* ---- the board's three settings, one section each ----
   The board is three boards and it says so: each setting owns a section with
   its own name in the head of it, and the setting being played right now is
   marked in its own section so the board somebody is reading is the board they
   are on. The colour per setting is the colour the setting already has on the
   title card, so a name here and a name there are the same name. */
.board .bnote{ text-align:center; margin:0 auto 8px; max-width:430px;
  font-size:clamp(8px,1.4vh,11px); line-height:1.35; color:rgba(255,225,160,.55); }
/* under one another by default; the short-screen rule at the bottom of this
   block turns the same three sections into three columns */
.bcols{ display:block; }
.bcat{ margin-top:8px; padding:1px 0 4px; border-radius:10px;
  border:1px solid rgba(247,181,63,.14); background:rgba(18,9,30,.34); }
.bcat.cur{ border-color:rgba(199,125,255,.5); background:rgba(46,24,74,.42);
  box-shadow:inset 0 0 20px rgba(139,63,214,.22); }
.bhead{ display:flex; align-items:baseline; gap:8px; padding:6px 9px 4px; }
.bname{ font-family:var(--serif); font-weight:700; letter-spacing:.18em;
  text-transform:uppercase; font-size:clamp(10px,1.9vh,14px); }
.bname.easy{ color:#9fe86a; text-shadow:0 0 12px rgba(159,232,106,.55); }
.bname.medium{ color:#f7b53f; text-shadow:0 0 12px rgba(247,181,63,.6); }
.bname.horror{ color:#e8533f; text-shadow:0 0 12px rgba(232,83,63,.6); }
.bhead .bnum{ font-size:clamp(7px,1.3vh,10px); letter-spacing:.1em;
  color:rgba(255,225,160,.5); }
.bhead .byou{ margin-left:auto; font-size:clamp(7px,1.3vh,10px); letter-spacing:.14em;
  text-transform:uppercase; color:#e8ccff; }
.bcat .brow{ padding-left:9px; padding-right:9px; }
/* every row carries its own setting as well as sitting under it */
.brow .dtag{ flex:0 0 auto; font-family:var(--sans); letter-spacing:.12em;
  text-transform:uppercase; font-size:clamp(6px,1.1vh,9px); padding:1px 5px;
  border-radius:5px; border:1px solid currentColor; opacity:.72; }
.brow .dtag.easy{ color:#9fe86a; }
.brow .dtag.medium{ color:#f7b53f; }
.brow .dtag.horror{ color:#e8533f; }
/* ---- the two player section ----
   It sits under the three settings and takes the whole width of the board, so
   its rows are the only ones on this page with room for two names and two
   numbers. A match is drawn as two lines inside one row, each line one player
   with that player's own score at the end of it, which is what makes it
   readable at any width: nothing is worked out from the order of two numbers
   printed side by side. */
.bname.duo{ color:#7fd4ff; text-shadow:0 0 12px rgba(127,212,255,.55); }
.bcat.duo2{ margin-top:10px; border-color:rgba(127,212,255,.22); }
.duo2cols{ display:block; }
.duo2col{ min-width:0; }
.bsub{ padding:6px 9px 2px; font-family:var(--sans); letter-spacing:.14em;
  text-transform:uppercase; font-size:clamp(7px,1.3vh,10px); color:rgba(255,225,160,.5); }
.brow .rk.wl{ font-family:var(--sans); font-weight:700; letter-spacing:.06em; }
.brow.duo.win .rk.wl{ color:#bff08a; text-shadow:0 0 10px rgba(126,166,58,.8); }
.brow.duo.drop .rk.wl{ color:#e8533f; }
.brow .duocol{ display:flex; flex-direction:column; gap:1px; padding:2px 0;
  white-space:normal; }
.brow .duocol .ln{ display:flex; align-items:baseline; gap:6px; min-width:0; }
.brow .duocol .ln b{ flex:0 0 auto; font-weight:400; color:var(--cream); }
.brow .duocol .ln i{ flex:0 1 auto; font-style:normal; font-family:var(--sans);
  letter-spacing:.1em; text-transform:uppercase; font-size:clamp(6px,1.1vh,9px);
  opacity:.66; }
.brow .duocol .ln .sc{ margin-left:auto; }
.brow.duo.mine .duocol .ln b{ color:#e8ccff; }
.board .bnote.duo{ margin-top:6px; margin-bottom:2px; text-align:left; max-width:none;
  padding:0 9px; }
/* A SHORT SCREEN GETS THE SAME THREE SECTIONS SIDE BY SIDE RATHER THAN A
   SCROLL. A phone held sideways is the shape this game is played in and it
   has about three hundred and eighty pixels of height; three stacked lists of
   up to thirteen rows come to about six hundred and cannot be read there
   without scrolling past the way out. Three columns of thirteen can: the
   tallest one decides the height and it is the same thirteen rows the board
   has always shown. Nothing is dropped to fit -- the setting each row was
   played on is still on the row, the count of open places is still there, and
   the column head names its setting in the setting's own colour. */
@media (max-height:560px){
  /* the board's own card is the one panel that widens: three columns of
     thirteen do not fit the four hundred and forty the small card is capped
     at, and the title card beside it stays exactly the width it was */
  #card.boardcard .panel{ max-width:760px; }
  .board{ width:min(100%,740px); margin-top:8px; }
  /* the column heads and the coloured tags say the same thing in this shape,
     and the row is the thing that does not have the width to say it twice */
  .board .bnote{ display:none; }
  .bcols{ display:flex; gap:7px; align-items:flex-start; }
  .bcat{ flex:1 1 0; min-width:0; margin-top:4px; }
  .bcat .brow{ padding-left:7px; padding-right:7px; gap:5px; }
  .bhead{ padding:4px 7px 3px; gap:6px; }
  .bhead .byou{ font-size:7px; letter-spacing:.08em; }
  .brow .dtag{ display:none; }
  .brow .rk{ flex:0 0 1.5em; }
  /* the two player section is two lists of up to thirteen under one head, and
     stacked they are as tall again as the whole board above them. Side by side
     they are the height of one list, which is what keeps this card readable on
     the shape the game is played in. */
  .board .bnote.duo{ display:block; }
  .duo2cols{ display:flex; gap:9px; align-items:flex-start; }
  .duo2col{ flex:1 1 0; min-width:0; }
}

/* ---- the race lobby ---- */
#lobby{ position:absolute; inset:0; z-index:12; display:none; align-items:center; justify-content:center;
  padding:14px; background:radial-gradient(120% 100% at 50% 40%, rgba(36,19,56,.62), rgba(16,8,26,.93));
  overflow:auto; }
#lobby.on{ display:flex; }
#lobby .panel{ width:100%; max-width:520px; margin:auto; padding:clamp(14px,3vh,24px) clamp(16px,4vw,30px); text-align:center; }
.seat{ display:flex; align-items:center; gap:10px; padding:7px 10px; margin:6px 0; border-radius:11px;
  border:2px solid rgba(247,181,63,.25); background:linear-gradient(180deg, rgba(56,32,90,.6), rgba(26,14,43,.6));
  text-align:left; }
.seat.here{ border-color:rgba(247,181,63,.7); box-shadow:0 0 18px rgba(247,181,63,.35); }
.seat .who{ font-family:var(--serif); font-size:clamp(12px,2.2vh,17px); color:#ffe9b0; }
.seat .st{ font-size:clamp(8px,1.5vh,11px); letter-spacing:.1em; color:rgba(255,225,160,.65); }
.seat img{ width:clamp(34px,6vh,48px); height:clamp(34px,6vh,48px); border-radius:50%; object-fit:cover;
  border:2px solid rgba(247,181,63,.55); background:rgba(26,14,43,.9); }
.seat .dot{ width:10px; height:10px; border-radius:50%; background:rgba(255,255,255,.25); flex:0 0 auto; }
.seat.here .dot{ background:#bff08a; box-shadow:0 0 12px #7ea63a; }
/* who is in: the dot is the socket, and the word beside it is the seat */
.seat .st b{ font-weight:600; letter-spacing:.12em; }
.seat .st b.yes{ color:#bff08a; }
.seat .st b.no{ color:rgba(255,225,160,.6); }
/* the waiting line is a control once there is something to try again */
#lobbywait.retry{ cursor:pointer; text-decoration:underline; text-underline-offset:3px; }
#card .btn[disabled]{ opacity:.45; box-shadow:0 4px 0 #3a2a12; transform:none; cursor:default; }
#card .btn[disabled]:hover{ box-shadow:0 4px 0 #3a2a12; }
.linkbox{ display:flex; gap:6px; align-items:center; margin:10px 0 4px; }
.linkbox input{ flex:1 1 auto; min-width:0; font-family:var(--sans); font-size:clamp(9px,1.6vh,12px);
  padding:6px 9px; border-radius:8px; color:#ffe9b0; background:rgba(18,9,31,.85);
  border:2px solid rgba(199,125,255,.45); outline:none; }
.linkbox button{ flex:0 0 auto; }
.waiting{ font-size:clamp(10px,1.8vh,13px); letter-spacing:.12em; color:var(--gold-lt);
  text-shadow:0 0 10px rgba(247,181,63,.8); animation:shPulse 1.6s ease infinite; }
/* the one-answer rule, on the card where the keys are, so it is read before
   the first cue rather than learned by losing a heart to it */
.small.rule{ color:rgba(255,225,160,.92); max-width:34em; margin:10px auto 0; line-height:1.5; }
/* The build stamp. It was drawn at 45 percent and half the size of the note
   above it, which made it a line nobody could read: the version and the count
   are asked to be ON the page, and a number that cannot be read is not on it.
   It is a badge now, with its own ground, so it is legible at every size. */
.small.build{ display:inline-block; color:rgba(255,235,190,.94); letter-spacing:.14em;
  margin-top:12px; padding:5px 12px; border-radius:999px;
  background:rgba(26,14,43,.72); border:1px solid rgba(199,125,255,.34);
  font-size:clamp(10px,1.85vh,13px);
  text-shadow:0 1px 3px #000;
  font-variant-numeric:tabular-nums; }
/* a part of the badge that must not be split down the middle, whatever width
   the badge is given: see the date in `_buildTail` */
.small.build .nb{ white-space:nowrap; }
.pb-ver{ font-size:11px; letter-spacing:.14em; color:rgba(255,225,160,.55);
  font-variant-numeric:tabular-nums; align-self:center; margin-left:4px; }

/* --- the link out to the film --- */
.btn.yt{ display:inline-flex; align-items:center; gap:9px; text-decoration:none;
  background:linear-gradient(180deg,#d92b2b,#8e1218); border-color:#ff7a6a;
  color:#fff4e2; box-shadow:0 0 20px rgba(217,43,43,.42); }
.btn.yt:hover{ background:linear-gradient(180deg,#ee3a34,#a6171c); }
.btn.yt .ytplay{ font-size:.82em; line-height:1; transform:translateY(-1px); }
/* The label is long and the button is not, so on a narrow panel it broke into
   three short lines and pushed the card past the fold. It takes the whole row
   and the space around it instead, which fits it in two lines on the narrowest
   phone and keeps the play glyph and the first word on the same line. */
.btn.yt{ width:100%; max-width:100%; justify-content:center; padding-left:12px; padding-right:12px;
  flex-wrap:wrap; row-gap:2px; line-height:1.25; text-align:center; }
#card.small .logo .l1{ font-size:clamp(24px,6.4vh,48px); }

/* ---- wash / flashes ---- */
#wash{ position:absolute; inset:0; z-index:8; pointer-events:none; opacity:0;
  background:radial-gradient(circle at 50% 55%, #e5c8ff 0%, #b072ff 32%, #6a2bb0 66%, #2a1140 100%); }
#wash.go{ animation:washGo 1.1s ease-out; }
@keyframes washGo{ 0%{opacity:0} 26%{opacity:1} 62%{opacity:.75} 100%{opacity:0} }

#toast{
  position:absolute; left:50%; top:20%; transform:translateX(-50%); z-index:9;
  font-family:var(--serif); font-size:clamp(15px,3vh,26px); letter-spacing:.12em;
  color:#ffe9b0; text-shadow:0 0 16px rgba(247,181,63,.9), 0 0 40px rgba(139,63,214,.8);
  opacity:0; pointer-events:none; text-align:center;
  /* A LONG TOAST IS READ, NOT CLIPPED. One line was held on one line with
     `nowrap`, and a line wider than the window runs off BOTH edges, because it
     is centred: measured on a 390-wide phone, "NO RACE AVAILABLE HERE" was 1px
     too wide, "PRESS AND HOLD THE LINK" 6px, a single achievement 46px, and the
     five a first win unlocks 1778px, 694px past each edge, so the moment a
     person earns anything they read a fragment of the middle of it. It wraps
     inside the window now. The width has to be SAID, not capped: a box with
     `left:50%` and no width shrink-to-fits into the right half of the screen
     only, so a max-width changed nothing and both lines above still stacked,
     at 195px of box ("NO RACE AVAILABLE HERE" three rows tall, five
     achievements five). Given the width, the long line is two rows on a phone
     and the short ones are unchanged. */
  width:min(92vw,34em); white-space:normal;
}
#toast.show{ animation:toastGo 1.5s ease forwards; }
@keyframes toastGo{ 0%{opacity:0;transform:translateX(-50%) translateY(10px)} 16%{opacity:1;transform:translateX(-50%) translateY(0)} 70%{opacity:1} 100%{opacity:0} }

/* ============================================================
   Screen-shape adaptations. Portrait is a first-class shape.
   ============================================================ */
@media (orientation:portrait){
  #hearts .gem{ width:28px; height:31px; }
  #scorewrap{ top:calc(46px + var(--safe-t)); width:70vw; }
  #rightbar{ top:calc(46px + var(--safe-t)); }
  /* On a 390-wide phone the zone name and the score are on the same line and
     the name is long enough to run under the score: the two read as one
     unreadable smear across the top of the screen. The right bar is held to a
     share of the width that cannot reach the middle, and the name gives way
     first, with the pennant and the two chips, which are the parts a person
     presses, keeping their full size. */
  #zone{ font-size:clamp(9px,1.6vh,12px); max-width:38vw; }
  #zonename{ overflow:hidden; white-space:nowrap; text-overflow:ellipsis; min-width:0; }
  #progress{ top:calc(100px + var(--safe-t)); width:94vw; gap:5px; }
  #rivalcard{ top:calc(138px + var(--safe-t)); }
  #bosshp{ top:calc(104px + var(--safe-t)); width:88vw; }
  #cuewrap{ bottom:clamp(140px,26vh,260px); }
  #legend{ max-width:100%; font-size:9px; bottom:calc(4px + var(--safe-b)); }
  #tbRight{ max-width:52vw; }
  .logo .l1{ font-size:clamp(26px,5.4vh,52px); }
}
/* Narrow phones: at 360px the two thumb pads are wider than the screen and the
   attack row lands on top of the lane arrows, so the whole bottom of the page
   becomes one unreadable cluster of buttons. Everything shrinks and the attack
   pad is held to a width that keeps it clear of the arrows. */
@media (max-width:430px){
  .tbtn.round{ width:clamp(44px,10.4vh,58px); height:clamp(44px,10.4vh,58px);
    font-size:clamp(8px,1.5vh,11px); }
  #tbLeft .tbtn{ width:clamp(50px,12vh,68px); height:clamp(42px,9.4vh,54px);
    font-size:clamp(13px,2.6vh,20px); }
  #tbLeft{ gap:7px; }
  #tbRight{ gap:7px; max-width:56vw; }
}
@media (max-width:620px){
  /* the meter's end labels go before the emblems do: the pictures say who is
     who, and a track squeezed to nothing says nothing */
  .pgname{ display:none; }
}
@media (max-height:430px){
  #legend{ display:none; }
  /* still above the lane band: at 64px the cue sat on the dirt it was warning
     about, and gold on lit dirt is not a legible signal */
  #cuewrap{ bottom:clamp(112px,34vh,190px); padding:4px 16px 6px; }
  #cueglyph{ font-size:clamp(24px,6.6vh,34px); }
  #cueword{ font-size:clamp(19px,5.4vh,28px); }
  /* card content is taller than a phone held sideways: everything tightens so
     the scoreboard still fits without a scroll */
  #card .panel{ padding:10px 14px; }
  .logo .l1{ font-size:clamp(22px,7vh,40px); }
  .logo .l2{ font-size:clamp(13px,4vh,22px); }
  .tagline{ margin:4px 0 6px; }
  .heroes{ margin:4px 0 6px; }
  .brow{ font-size:11px; padding:1px 8px; }
  /* three sections cost height that a phone held sideways does not have: the
     section heads give up their padding and the per-row setting tag gives up
     its border before anything legible does */
  .bcat{ margin-top:5px; }
  .bhead{ padding:3px 8px 2px; }
  .brow .dtag{ font-size:8px; padding:0 4px; opacity:.6; }
  .keys{ margin:8px auto 2px; }
  /* the difficulty row is one line of three buttons and it still costs height
     on a phone held sideways, where the card is already the tallest thing on
     screen. The blurbs are the first thing to go: the labels carry the choice
     and the selected one is still obvious from its border. */
  .diffs{ margin:0 0 5px; }
  .diffs .dlabel{ font-size:8px; margin-bottom:2px; }
  .diff{ padding:4px 10px; }
  .diff b{ font-size:12px; }
  .diff span{ display:none; }
  .missions{ margin:0 0 5px; }
  .missions .dlabel{ font-size:8px; margin-bottom:2px; }
  .mission{ min-height:34px; padding:4px 8px; }
  .mission b{ font-size:11px; }
  .mission span{ display:none; }
}
