/* =========================================================================
   Understory — interface
   A naturalist field-guide look: warm paper tones, moss and amber accents,
   thin rules, frosted glass. The HUD stays small so the forest is the subject.
   ========================================================================= */

:root {
  --moss:      #8fae62;
  --moss-deep: #5d7a3c;
  --amber:     #e8b45c;
  --ember:     #e8894a;
  --mist:      #9fd8e8;
  --still:     #c9b6f2;
  --clay:      #c2704a;
  --bean:      #ff8b4a;
  --threat:    #e0523a;

  --ink:       #f2eee2;
  --ink-soft:  #d8d2c2;
  --ink-dim:   #a9a396;
  --ink-mute:  #9d9784;

  --panel:     rgba(24, 27, 20, 0.74);
  --panel-hi:  rgba(46, 52, 38, 0.62);
  --line:      rgba(226, 219, 198, 0.18);
  --line-hi:   rgba(226, 219, 198, 0.42);

  --display: "Segoe UI Variable Display", "Segoe UI", system-ui, sans-serif;
  --serif: Georgia, "Iowan Old Style", "Times New Roman", serif;
  --mono: "Consolas", "Cascadia Mono", ui-monospace, monospace;

  --ease-out: cubic-bezier(.16, 1, .3, 1);
  --ease-in-out: cubic-bezier(.65, 0, .35, 1);
}


* { box-sizing: border-box; margin: 0; padding: 0; }

html, body {
  width: 100%; height: 100%;
  overflow: hidden;
  background: #10130d;
  color: var(--ink);
  font-family: var(--display);
  font-size: 15px;
  -webkit-font-smoothing: antialiased;
  user-select: none;
  cursor: default;
}
body.playing { cursor: none; }

#app { position: fixed; inset: 0; }
#gl { position: absolute; inset: 0; width: 100%; height: 100%; display: block; }

.layer { position: absolute; inset: 0; z-index: 10; }

/* `hidden` must beat id-based display rules (e.g. #menuLayer is a flexbox). */
[hidden] { display: none !important; }

.micro-label {
  font-size: 10.5px;
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--ink-mute);
  font-weight: 600;
}

/* ======================================================= LOADING ======== */

#loading {
  position: absolute; inset: 0; z-index: 60;
  display: flex; align-items: center; justify-content: center;
  background:
    radial-gradient(ellipse at 50% 42%, #2a3222 0%, #151a10 55%, #0b0e08 100%);
  transition: opacity .65s var(--ease-in-out);
}
#loading.done { opacity: 0; pointer-events: none; }
.load-inner { text-align: center; width: min(420px, 80vw); }
.load-mark {
  color: var(--moss); width: 130px; margin: 0 auto 20px;
  opacity: .9;
}
.load-mark svg { width: 100%; height: auto; overflow: visible; }
.load-mark path {
  stroke-dasharray: 240; stroke-dashoffset: 240;
  animation: draw 2.6s var(--ease-in-out) infinite;
}
@keyframes draw {
  0%   { stroke-dashoffset: 240; opacity: .2; }
  45%  { stroke-dashoffset: 0; opacity: 1; }
  85%  { stroke-dashoffset: -240; opacity: .2; }
  100% { stroke-dashoffset: -240; opacity: 0; }
}
.load-title {
  font-family: var(--serif);
  font-size: 30px; letter-spacing: .20em; color: var(--ink);
  margin-bottom: 26px; font-weight: 400;
}
.load-track {
  height: 2px; background: rgba(226,219,198,.14); border-radius: 2px;
  overflow: hidden; margin-bottom: 14px;
}
.load-bar {
  height: 100%; width: 100%; transform: scaleX(0); transform-origin: left;
  background: linear-gradient(90deg, var(--moss-deep), var(--moss), var(--amber));
  transition: transform .35s var(--ease-out);
}
.load-label {
  font-size: 12px; letter-spacing: .12em; color: var(--ink-mute);
  font-style: italic; font-family: var(--serif);
}

/* =========================================================== HUD ======== */

#hud { pointer-events: none; }

.hud-corner { position: absolute; display: flex; flex-direction: column; gap: 12px; }
.hud-corner.tl { top: 24px; left: 28px; align-items: flex-start; }
.hud-corner.tr { top: 24px; right: 28px; align-items: flex-end; }
.hud-corner.bl { bottom: 26px; left: 28px; }
.hud-corner.br { bottom: 26px; right: 28px; }

.score-block { animation: hud-in .7s var(--ease-out) both; }
.score-row { display: flex; align-items: baseline; gap: 10px; }

.score-value {
  font-family: var(--mono);
  font-size: 34px; font-weight: 600; line-height: 1;
  color: var(--ink);
  text-shadow: 0 1px 10px rgba(0,0,0,.7), 0 0 30px rgba(0,0,0,.5);
  font-variant-numeric: tabular-nums;
}
.score-value.bump { animation: score-bump .38s var(--ease-out); }
@keyframes score-bump {
  0%   { transform: scale(1); }
  30%  { transform: scale(1.08); color: #fff6df; }
  100% { transform: scale(1); }
}

.mult-chip {
  font-family: var(--mono); font-size: 13px; font-weight: 600;
  padding: 2px 8px; border-radius: 999px;
  border: 1px solid rgba(143,174,98,.45);
  color: var(--moss); background: rgba(143,174,98,.12);
  opacity: 0; transform: translateY(3px);
  transition: opacity .3s, transform .3s var(--ease-out),
              color .25s, border-color .25s, background .25s;
}
.mult-chip.on { opacity: 1; transform: none; }
.mult-chip.hot {
  color: var(--amber); border-color: rgba(232,180,92,.55);
  background: rgba(232,180,92,.14);
}

.combo {
  width: 172px; opacity: 0; transform: translateX(-8px);
  transition: opacity .32s, transform .32s var(--ease-out);
}
.combo.on { opacity: 1; transform: none; }
.combo-head { display: flex; justify-content: space-between; align-items: baseline; margin-bottom: 5px; }
.combo-word { font-size: 10.5px; letter-spacing: .16em; text-transform: uppercase; color: var(--ink-mute); }
.combo-count { font-family: var(--mono); font-size: 13px; font-weight: 600; color: var(--moss); }
.combo-track { height: 2px; background: rgba(226,219,198,.15); border-radius: 2px; overflow: hidden; }
.combo-fill {
  height: 100%; width: 100%; transform-origin: left center;
  background: linear-gradient(90deg, var(--moss), var(--amber));
}

.stat { display: flex; align-items: baseline; gap: 10px; animation: hud-in .7s var(--ease-out) both; }
.stat b {
  font-family: var(--mono); font-size: 16px; font-weight: 600;
  color: var(--ink-soft); min-width: 52px; text-align: right;
  font-variant-numeric: tabular-nums;
  text-shadow: 0 1px 8px rgba(0,0,0,.65);
}
.stat.fps b { font-size: 13px; color: var(--ink-mute); }

@keyframes hud-in {
  from { opacity: 0; transform: translateY(-6px); filter: blur(3px); }
  to   { opacity: 1; transform: none; filter: none; }
}

/* Surge meter */
.boost { width: 190px; animation: hud-in .7s .06s var(--ease-out) both; }
.boost-head { display: flex; justify-content: space-between; align-items: baseline; margin-bottom: 6px; }
.boost-hint {
  font-size: 10px; letter-spacing: .1em; text-transform: uppercase;
  color: var(--ink-mute);
  border: 1px solid var(--line); border-radius: 3px; padding: 1px 6px;
  transition: color .25s, border-color .25s, background .25s;
}
.boost.active .boost-hint {
  color: #1a1f14; background: var(--amber); border-color: var(--amber);
}
.boost-track {
  position: relative; height: 4px; border-radius: 3px;
  background: rgba(226,219,198,.14); overflow: hidden;
}
.boost-fill {
  height: 100%; width: 100%; transform-origin: left center;
  background: linear-gradient(90deg, var(--moss-deep), var(--moss) 55%, var(--amber));
  transition: background .25s;
}
.boost.empty .boost-fill { background: linear-gradient(90deg, #6b3a2a, var(--clay)); }
.boost.active .boost-fill { filter: brightness(1.25); }
.boost-notch { position: absolute; top: 0; bottom: 0; left: 12%; width: 1px; background: rgba(226,219,198,.3); }

/* Strike charges (Chase run) */
.charge { width: 190px; margin-bottom: 14px; animation: hud-in .7s .02s var(--ease-out) both; }
.charge-head { display: flex; justify-content: space-between; align-items: baseline; margin-bottom: 6px; }
.charge-hint {
  font: 600 10px/1 var(--display); letter-spacing: .09em; text-transform: uppercase;
  color: var(--ink-mute);
  border: 1px solid var(--line); border-radius: 3px; padding: 1px 6px;
  transition: color .25s, border-color .25s, background .25s;
}
.charge.ready .charge-hint {
  color: #1a1207; background: var(--bean); border-color: var(--bean);
}
.charge-pips { display: flex; gap: 6px; }
.charge-pip {
  flex: 1; height: 5px; border-radius: 3px;
  background: rgba(226,219,198,.13);
  border: 1px solid transparent;
  transition: background .3s var(--ease-out), box-shadow .3s var(--ease-out),
              border-color .3s;
}
.charge-pip.on {
  background: linear-gradient(90deg, var(--ember), var(--bean));
  border-color: rgba(255,139,74,.55);
  box-shadow: 0 0 12px rgba(255,139,74,.55);
}
.charge-pip.spend { animation: pip-spend .42s var(--ease-out); }
@keyframes pip-spend {
  0%   { transform: scaleY(2.4); box-shadow: 0 0 22px rgba(255,180,120,.95); }
  100% { transform: scaleY(1); box-shadow: none; }
}
.charge.gained .charge-pips { animation: pip-gain .5s var(--ease-out); }
@keyframes pip-gain {
  0%   { transform: scale(1.14); filter: brightness(1.7); }
  100% { transform: scale(1); filter: none; }
}

/* Status rail: player effects on the left, spider effects on the right. */
.status-rail {
  position: absolute; left: 50%; bottom: 74px; transform: translateX(-50%);
  display: flex; gap: 8px; pointer-events: none;
}
.status-pill {
  display: flex; align-items: center; gap: 7px;
  padding: 6px 12px 6px 10px; border-radius: 999px;
  background: var(--panel); border: 1px solid var(--line);
  backdrop-filter: blur(10px) saturate(.9);
  font: 600 10px/1 var(--display); letter-spacing: .15em;
  text-transform: uppercase; color: var(--ink-soft);
  animation: pill-in .38s var(--ease-out) both;
  position: relative; overflow: hidden;
}
.status-pill.leaving { animation: pill-out .3s var(--ease-in-out) forwards; }
.status-pill .glyph { font-size: 13px; line-height: 1; }
.status-pill .life {
  position: absolute; left: 0; bottom: 0; height: 2px; width: 100%;
  transform-origin: left center; background: currentColor; opacity: .75;
}
.status-pill.surge { color: #7fe9ff; border-color: rgba(127,233,255,.42); }
.status-pill.frost { color: #b6dcff; border-color: rgba(182,220,255,.42); }
.status-pill.stun  { color: #ffd08a; border-color: rgba(255,208,138,.45); }
.status-pill.surge .glyph { animation: pill-throb 1.1s ease-in-out infinite; }
@keyframes pill-throb { 0%,100% { opacity: .55; } 50% { opacity: 1; } }
@keyframes pill-in {
  from { opacity: 0; transform: translateY(8px) scale(.94); }
  to   { opacity: 1; transform: none; }
}
@keyframes pill-out {
  to { opacity: 0; transform: translateY(-6px) scale(.96); }
}

/* Threat indicator (Chase run) */
.threat {
  position: absolute; left: 50%; top: 50%;
  width: 210px; height: 210px; margin: -105px 0 0 -105px;
  pointer-events: none;
  opacity: 0;
  transition: opacity .45s var(--ease-out);
}
.threat.on { opacity: 1; }
.threat-ring {
  position: absolute; inset: 0; border-radius: 50%;
  border: 1px solid rgba(224,82,58,.30);
  transform: scale(var(--threat-scale, 1));
  transition: transform .3s var(--ease-out), border-color .3s;
}
.threat.close .threat-ring { border-color: rgba(224,82,58,.62); }
.threat-arrow {
  position: absolute; inset: 0;
  transform: rotate(var(--threat-angle, 0deg));
  transition: transform .12s linear;
}
.threat-arrow span {
  position: absolute; left: 50%; top: -2px; width: 0; height: 0;
  margin-left: -7px;
  border-left: 7px solid transparent;
  border-right: 7px solid transparent;
  border-bottom: 12px solid var(--threat);
  filter: drop-shadow(0 0 7px rgba(224,82,58,.85));
}
.threat-label {
  position: absolute; left: 0; right: 0; bottom: -22px; text-align: center;
  font: 600 10px/1 var(--display); letter-spacing: .22em; text-transform: uppercase;
  color: var(--threat); opacity: .82;
}
.threat.close .threat-label { animation: threat-throb 1.1s ease-in-out infinite; }
@keyframes threat-throb {
  0%, 100% { opacity: .45; }
  50%      { opacity: 1; }
}
.threat-vignette {
  position: absolute; inset: 0; pointer-events: none;
  box-shadow: inset 0 0 200px rgba(150,26,10,.85);
  opacity: 0;
  transition: opacity .35s var(--ease-out);
}

/* Strike flash */
.strike-flash {
  position: absolute; inset: 0; pointer-events: none;
  background: radial-gradient(circle at 50% 56%,
    rgba(255,196,140,.55), rgba(255,120,60,.12) 42%, transparent 68%);
  opacity: 0;
}
.strike-flash.go { animation: strike 420ms var(--ease-out); }
@keyframes strike {
  0%   { opacity: 0; transform: scale(1.25); }
  18%  { opacity: 1; transform: scale(1); }
  100% { opacity: 0; transform: scale(.94); }
}

/* Clearing dial */
.radar-frame {
  position: relative; width: 138px; height: 138px;
  animation: hud-in .7s .12s var(--ease-out) both;
  opacity: .92;
}
#radar { width: 100%; height: 100%; display: block; }
.radar-ring {
  position: absolute; inset: 0; border-radius: 50%;
  border: 1px solid rgba(226,219,198,.16);
  box-shadow: inset 0 0 24px rgba(0,0,0,.45);
  pointer-events: none;
}
.radar-label { position: absolute; bottom: -15px; right: 2px; font-size: 9px; }

/* Power-up rail */
.powerup-rail {
  position: absolute; bottom: 26px; left: 50%; transform: translateX(-50%);
  display: flex; gap: 10px;
}
.pu {
  display: flex; align-items: center; gap: 8px;
  padding: 6px 13px 6px 10px;
  border: 1px solid rgba(226,219,198,.20);
  border-radius: 999px;
  background: rgba(20, 24, 17, .55);
  backdrop-filter: blur(10px);
  animation: pu-in .4s var(--ease-out) both;
  position: relative; overflow: hidden;
}
.pu.leaving { animation: pu-out .34s var(--ease-in-out) forwards; }
@keyframes pu-in { from { opacity: 0; transform: translateY(10px) scale(.9); } to { opacity: 1; transform: none; } }
@keyframes pu-out { to { opacity: 0; transform: translateY(-8px) scale(.94); } }
.pu .glyph { font-size: 14px; line-height: 1; }
.pu .name {
  font-size: 10px; letter-spacing: .14em; text-transform: uppercase;
  font-weight: 600; color: var(--ink-soft);
}
.pu .timer {
  position: absolute; left: 0; bottom: 0; height: 1.5px;
  background: currentColor; transform-origin: left center; width: 100%;
}
.pu.expiring { animation: pu-warn .5s infinite alternate; }
@keyframes pu-warn { to { border-color: rgba(226,219,198,.5); } }

/* Reticle: barely there */
.reticle {
  position: absolute; top: 50%; left: 50%;
  width: 30px; height: 30px; margin: -15px 0 0 -15px;
  opacity: .16; transition: opacity .3s, transform .3s var(--ease-out);
}
.reticle svg { width: 100%; height: 100%; overflow: visible; }
.ret-ring { fill: none; stroke: var(--ink); stroke-width: 1; opacity: .5; }
.ret-dot { fill: var(--ink); }
.reticle.boosting { opacity: .32; transform: scale(1.3); }
.reticle.danger { opacity: .6; }
.reticle.danger .ret-ring { stroke: var(--clay); }
.reticle.danger .ret-dot { fill: var(--clay); }

/* Floating score */
.popup-layer { position: absolute; inset: 0; overflow: hidden; }
.popup {
  position: absolute;
  font-family: var(--mono); font-size: 20px; font-weight: 600;
  color: #fff6df;
  text-shadow: 0 0 3px rgba(0,0,0,.9), 0 2px 12px rgba(0,0,0,.85);
  white-space: nowrap;
  animation: popup-rise 1.3s var(--ease-out) forwards;
  transform: translate(-50%, -50%);
}
.popup .sub {
  display: block; font-family: var(--display);
  font-size: 10px; letter-spacing: .16em; text-transform: uppercase;
  opacity: .9; text-align: center; margin-top: 3px; font-weight: 600;
  text-shadow: 0 0 3px rgba(0,0,0,.9);
}
.popup.gold { color: var(--amber); }
.popup.power { color: var(--mist); }
@keyframes popup-rise {
  0%   { opacity: 0; transform: translate(-50%, -50%) scale(.75); }
  18%  { opacity: 1; transform: translate(-50%, -62%) scale(1.05); }
  35%  { transform: translate(-50%, -68%) scale(1); }
  100% { opacity: 0; transform: translate(-50%, -125%) scale(.97); }
}

/* Centre messages */
.center-msg {
  position: absolute; top: 44%; left: 50%; transform: translate(-50%, -50%);
  text-align: center; pointer-events: none;
}
.count-num {
  font-family: var(--serif); font-size: 96px; font-weight: 400; line-height: 1;
  color: var(--ink); text-shadow: 0 4px 30px rgba(0,0,0,.8);
  animation: count-pop .9s var(--ease-out) forwards;
}
@keyframes count-pop {
  0%   { opacity: 0; transform: scale(1.5); filter: blur(10px); }
  25%  { opacity: 1; transform: scale(1); filter: blur(0); }
  72%  { opacity: 1; }
  100% { opacity: 0; transform: scale(.94); }
}
.go-word {
  font-family: var(--serif); font-size: 62px; letter-spacing: .1em;
  color: var(--moss); text-shadow: 0 4px 30px rgba(0,0,0,.8);
  animation: count-pop .85s var(--ease-out) forwards;
}
.toast {
  font-size: 14px; letter-spacing: .22em; text-transform: uppercase;
  font-weight: 600; color: var(--ink);
  text-shadow: 0 2px 14px rgba(0,0,0,.85);
  animation: toast 1.1s var(--ease-out) forwards;
}
@keyframes toast {
  0%   { opacity: 0; transform: translateY(12px); }
  22%  { opacity: 1; transform: none; }
  75%  { opacity: 1; }
  100% { opacity: 0; transform: translateY(-10px); }
}

.danger-frame, .powerup-flash { position: absolute; inset: 0; pointer-events: none; opacity: 0; }
.danger-frame {
  box-shadow: inset 0 0 150px rgba(150, 60, 35, .55);
  transition: opacity .16s linear;
}
.powerup-flash { transition: opacity .6s var(--ease-out); }

/* ========================================================= MENUS ======== */

#menuLayer { display: flex; align-items: center; justify-content: center; }

.menu-backdrop {
  position: absolute; inset: 0;
  background:
    radial-gradient(ellipse at 50% 45%, rgba(10,13,8,.10) 0%, rgba(10,13,8,.52) 60%, rgba(8,10,6,.80) 100%);
  transition: backdrop-filter .5s, background .5s;
}
/* On the title the forest is the hero, so barely veil it. */
#menuLayer.title-active .menu-backdrop {
  background:
    linear-gradient(to bottom, rgba(8,10,6,.62) 0%, rgba(8,10,6,.18) 34%,
                    rgba(8,10,6,.30) 68%, rgba(8,10,6,.72) 100%);
  backdrop-filter: blur(1.5px);
}
#menuLayer.in-run .menu-backdrop { backdrop-filter: blur(7px); }

.version-tag {
  position: absolute; bottom: 18px; left: 22px; z-index: 3;
  font-size: 10px; letter-spacing: .16em; color: rgba(226,219,198,.30);
  opacity: 0; transition: opacity .4s;
}
#menuLayer.title-active .version-tag { opacity: 1; }

.screen {
  position: relative; z-index: 2;
  display: flex; flex-direction: column; align-items: center;
  width: min(1000px, 92vw); max-height: 100vh; padding: 24px 0;
  animation: screen-in .5s var(--ease-out) both;
}
.screen.leaving { animation: screen-out .3s var(--ease-in-out) forwards; }
@keyframes screen-in {
  from { opacity: 0; transform: translateY(14px); filter: blur(6px); }
  to   { opacity: 1; transform: none; filter: none; }
}
@keyframes screen-out {
  to { opacity: 0; transform: translateY(-8px); filter: blur(5px); }
}

/* --- title --- */
.title-wrap { text-align: center; margin-bottom: 34px; }
.eyebrow {
  font-size: 11px; letter-spacing: .34em; text-transform: uppercase;
  color: #bcd894; margin-bottom: 14px;
  text-shadow: 0 2px 8px rgba(0,0,0,.9);
  animation: fade-up .7s .05s var(--ease-out) both;
}
.logo {
  font-family: var(--serif);
  font-size: clamp(46px, 7.4vw, 92px);
  font-weight: 400; letter-spacing: .02em; line-height: 1;
  color: var(--ink);
  text-shadow: 0 2px 6px rgba(0,0,0,.85), 0 8px 44px rgba(0,0,0,.8);
  animation: fade-up .8s .14s var(--ease-out) both;
  white-space: nowrap;
}
.logo-a { color: var(--ink); }
.logo-b { color: var(--moss); font-style: italic; }
.logo-rule {
  height: 1px; width: 46%; margin: 20px auto 14px;
  background: linear-gradient(90deg, transparent, var(--line-hi), transparent);
  animation: rule-in .9s .34s var(--ease-out) both;
}
@keyframes rule-in { from { transform: scaleX(0); opacity: 0; } to { transform: none; opacity: 1; } }
.tagline {
  font-family: var(--serif); font-style: italic;
  font-size: 15px; letter-spacing: .04em; color: var(--ink-soft);
  text-shadow: 0 2px 8px rgba(0,0,0,.9);
  animation: fade-up .7s .38s var(--ease-out) both;
}
@keyframes fade-up {
  from { opacity: 0; transform: translateY(10px); filter: blur(4px); }
  to   { opacity: 1; transform: none; filter: none; }
}

/* --- menu rows --- */
.menu { display: flex; flex-direction: column; gap: 1px; width: min(460px, 88vw); pointer-events: auto; }
.menu.compact { width: min(320px, 88vw); margin-top: 24px; }
.settings-menu { width: 100%; }

.row {
  position: relative;
  display: flex; align-items: center; justify-content: space-between; gap: 18px;
  padding: 11px 16px 11px 22px;
  border: 1px solid transparent; border-radius: 4px;
  cursor: pointer; color: var(--ink-mute);
  transition: color .22s, background .22s, border-color .22s,
              transform .22s var(--ease-out);
  animation: row-in .5s var(--ease-out) both;
}
.row::before {
  content: ""; position: absolute; left: 6px; top: 50%;
  width: 2px; height: 0; background: var(--moss);
  transform: translateY(-50%); border-radius: 2px;
  transition: height .25s var(--ease-out);
}
.row:hover { color: var(--ink-soft); background: rgba(143,174,98,.06); }
.row.sel {
  color: var(--ink);
  background: linear-gradient(90deg, rgba(143,174,98,.14), rgba(143,174,98,.02) 72%);
  border-color: rgba(143,174,98,.22);
  transform: translateX(3px);
}
.row.sel::before { height: 56%; }
.row.disabled { opacity: .35; pointer-events: none; }

.row .label {
  font-size: 15px; letter-spacing: .06em; font-weight: 500;
  text-shadow: 0 1px 6px rgba(0,0,0,.75);
}
.row .value {
  font-size: 13px; color: var(--moss);
  display: flex; align-items: center; gap: 10px;
  font-variant-numeric: tabular-nums;
}
.row .hint {
  font-size: 11px; letter-spacing: .02em; color: var(--ink-mute);
  max-width: 260px; text-align: right; font-style: italic;
  font-family: var(--serif);
}
.arrow { opacity: 0; transition: opacity .2s; font-size: 12px; }
.row.sel .arrow { opacity: .7; }

.slider { position: relative; width: 120px; height: 2px; background: rgba(226,219,198,.18); border-radius: 2px; }
.slider .fill { position: absolute; inset: 0 auto 0 0; border-radius: 2px; background: var(--moss); }
.slider .knob {
  position: absolute; top: 50%; width: 8px; height: 8px; border-radius: 50%;
  background: var(--ink); transform: translate(-50%, -50%);
  box-shadow: 0 1px 4px rgba(0,0,0,.6);
}

.toggle {
  width: 34px; height: 16px; border-radius: 999px;
  background: rgba(226,219,198,.12); border: 1px solid var(--line);
  position: relative; transition: background .25s, border-color .25s;
}
.toggle i {
  position: absolute; top: 2px; left: 2px; width: 10px; height: 10px;
  border-radius: 50%; background: var(--ink-mute);
  transition: transform .26s var(--ease-out), background .25s;
}
.toggle.on { background: rgba(143,174,98,.26); border-color: rgba(143,174,98,.5); }
.toggle.on i { transform: translateX(18px); background: var(--moss); }

@keyframes row-in {
  from { opacity: 0; transform: translateX(-10px); filter: blur(3px); }
  to   { opacity: 1; transform: none; filter: none; }
}

/* All-time records, under the game-over grid. */
.records {
  display: flex; justify-content: center; flex-wrap: wrap; gap: 4px 22px;
  margin: 16px 0 2px;
  font: 500 11px/1.5 var(--display); letter-spacing: .10em;
  text-transform: uppercase; color: var(--ink-mute);
  animation: hud-in .6s .42s var(--ease-out) both;
}
.records b { color: var(--ink-soft); font-weight: 600; letter-spacing: .04em; }

/* Update available */
.update-panel { text-align: center; }
.update-mark {
  color: var(--moss); width: 108px; margin: 2px auto 12px;
  animation: update-breathe 3.4s var(--ease-in-out) infinite;
}
.update-mark svg { width: 100%; height: auto; overflow: visible; }
@keyframes update-breathe {
  0%, 100% { opacity: .55; transform: translateY(0); }
  50%      { opacity: 1;   transform: translateY(-3px); }
}
.update-body {
  margin: 6px 0 2px; font: 400 15px/1.6 var(--serif);
  color: var(--ink-soft);
}
.update-meta {
  font: 500 10px/1.6 var(--display); letter-spacing: .14em;
  text-transform: uppercase; color: var(--ink-mute); margin-bottom: 6px;
}
.update-panel .menu { margin: 14px auto 0; }

/* In-run notice: present, but never in the way. */
.update-chip {
  position: absolute; left: 50%; bottom: 26px; transform: translateX(-50%);
  display: flex; align-items: center; gap: 8px;
  padding: 7px 14px; border-radius: 999px;
  background: var(--panel); border: 1px solid var(--line);
  backdrop-filter: blur(10px) saturate(.9);
  font: 600 10px/1 var(--display); letter-spacing: .16em;
  text-transform: uppercase; color: var(--ink-soft);
  animation: chip-in .6s var(--ease-out) both;
  pointer-events: none;
}
.update-dot {
  width: 6px; height: 6px; border-radius: 50%; background: var(--moss);
  box-shadow: 0 0 8px rgba(143,174,98,.9);
  animation: update-pulse 2.2s ease-in-out infinite;
}
@keyframes update-pulse { 0%,100% { opacity: .4; } 50% { opacity: 1; } }
@keyframes chip-in {
  from { opacity: 0; transform: translate(-50%, 10px); }
  to   { opacity: 1; transform: translate(-50%, 0); }
}

/* --- panels --- */
.panel-screen { justify-content: center; }
.panel {
  position: relative; width: 100%;
  padding: 34px 38px 28px;
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: 6px;
  box-shadow: 0 24px 70px rgba(0,0,0,.55), inset 0 1px 0 rgba(255,255,255,.04);
  backdrop-filter: blur(16px) saturate(.9);
  max-height: 88vh;
  overflow-x: hidden; overflow-y: auto;
}
.panel.narrow { width: min(440px, 92vw); }
/* On a short window the settings list runs past the panel. A soft inset edge
   says "there is more below" without adding a scrollbar to the design. */
.panel.overflowing {
  box-shadow: 0 24px 70px rgba(0,0,0,.55), inset 0 1px 0 rgba(255,255,255,.04),
              inset 0 -34px 26px -26px rgba(8,10,6,.92);
}
.panel::-webkit-scrollbar { width: 8px; height: 0; }
.panel::-webkit-scrollbar-track { background: transparent; }
.panel::-webkit-scrollbar-thumb {
  background: rgba(226,219,198,.14); border-radius: 4px;
  border: 2px solid transparent; background-clip: padding-box;
}

.panel-title {
  font-family: var(--serif); font-weight: 400;
  font-size: 24px; letter-spacing: .10em;
  text-align: center; margin-bottom: 26px; color: var(--ink);
}
.panel-title.danger { color: var(--clay); }

/* --- how to play --- */
.howto-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 24px 40px; }
.howto-block.wide { grid-column: 1 / -1; }
.howto-block h3 {
  font-size: 10.5px; letter-spacing: .22em; text-transform: uppercase;
  color: var(--moss); margin-bottom: 12px; font-weight: 600;
}
.keylist { list-style: none; display: flex; flex-direction: column; gap: 9px; }
.keylist li { display: flex; align-items: center; gap: 7px; font-size: 13.5px; color: var(--ink-mute); }
.keylist li span { margin-left: 6px; color: var(--ink-soft); }
kbd {
  font-family: var(--display); font-size: 10.5px; font-weight: 600;
  letter-spacing: .04em; padding: 3px 7px; min-width: 26px; text-align: center;
  border: 1px solid var(--line); border-radius: 3px;
  background: rgba(226,219,198,.06); color: var(--ink-soft);
}
.bullets { list-style: none; display: flex; flex-direction: column; gap: 9px; }
.bullets li {
  font-size: 13.5px; line-height: 1.55; color: var(--ink-mute);
  padding-left: 15px; position: relative;
}
.bullets li::before {
  content: "—"; position: absolute; left: 0; color: var(--moss); opacity: .7;
}
.bullets b { color: var(--ink-soft); font-weight: 600; }
.bullets em { color: var(--clay); font-style: normal; }

.orb-legend { display: grid; grid-template-columns: repeat(3, 1fr); gap: 12px 30px; }
.orb-item {
  display: grid; grid-template-columns: 11px 74px 1fr;
  align-items: center; gap: 9px; font-size: 12.5px; color: var(--ink-mute);
}
.orb-item b { font-size: 11px; letter-spacing: .1em; color: var(--ink-soft); text-transform: uppercase; }
.dot { width: 10px; height: 10px; border-radius: 50%; display: inline-block; flex: none; }
.dot.spirit { background: #ffd98a; box-shadow: 0 0 10px rgba(255,217,138,.8); }
.dot.ember  { background: #ff9a4a; box-shadow: 0 0 10px rgba(255,154,74,.8); }
.dot.mist   { background: #9fd8e8; box-shadow: 0 0 10px rgba(159,216,232,.7); }
.dot.still  { background: #c9b6f2; box-shadow: 0 0 10px rgba(201,182,242,.7); }
.dot.lure   { background: #ffd88a; box-shadow: 0 0 10px rgba(255,216,138,.7); }
.dot.bean   { background: var(--bean); box-shadow: 0 0 12px rgba(255,139,74,.9); }
.dot.surge  { background: #63e8ff; box-shadow: 0 0 12px rgba(99,232,255,.9); }
.dot.frost  { background: #9fd0ff; box-shadow: 0 0 12px rgba(159,208,255,.85); }
@media (max-width: 1000px) { .orb-legend { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 700px)  { .orb-legend { grid-template-columns: 1fr; } }

/* --- pause --- */
.pause-stats {
  display: flex; justify-content: center; gap: 34px; margin-bottom: 24px;
  padding-bottom: 20px; border-bottom: 1px solid var(--line);
}
.pause-stat { text-align: center; }
.pause-stat b {
  display: block; font-family: var(--mono); font-size: 24px; color: var(--ink);
  margin-top: 4px; font-weight: 600;
}

/* --- game over --- */
.gameover-head { text-align: center; margin-bottom: 6px; }
.cause {
  font-family: var(--serif); font-style: italic;
  font-size: 13px; color: var(--clay); margin-top: -16px; margin-bottom: 20px;
}
.best-banner {
  text-align: center; font-size: 11px; letter-spacing: .3em; font-weight: 600;
  text-transform: uppercase; color: var(--amber);
  padding: 9px; margin-bottom: 18px;
  border-top: 1px solid rgba(232,180,92,.28);
  border-bottom: 1px solid rgba(232,180,92,.28);
  animation: best-pulse 2.2s infinite alternate var(--ease-in-out);
}
@keyframes best-pulse { to { color: #fff0cd; letter-spacing: .33em; } }

.final-score { text-align: center; margin-bottom: 24px; }
.final-value {
  font-family: var(--mono); font-size: 56px; font-weight: 600; line-height: 1.1;
  color: var(--ink); font-variant-numeric: tabular-nums;
}
.stat-grid {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(110px, 1fr));
  gap: 16px; margin-bottom: 26px; padding: 20px 0;
  border-top: 1px solid var(--line); border-bottom: 1px solid var(--line);
}
.stat-cell { text-align: center; animation: fade-up .55s var(--ease-out) both; }
.stat-cell b {
  display: block; font-family: var(--mono); font-size: 20px;
  color: var(--ink-soft); margin-top: 5px; font-weight: 600;
}
.stat-cell.hl b { color: var(--amber); }

#bootError {
  position: fixed; inset: 0; z-index: 100; display: flex;
  align-items: center; justify-content: center; padding: 40px;
  background: #10130d; color: #d98f74; font-family: var(--mono);
  font-size: 13px; white-space: pre-wrap; text-align: left; overflow: auto;
}

@media (max-width: 900px) {
  .howto-grid { grid-template-columns: 1fr; }
  .panel { padding: 24px 20px; }
  .hud-corner.tl, .hud-corner.tr { top: 16px; }
  .hud-corner.tl, .hud-corner.bl { left: 18px; }
  .hud-corner.tr, .hud-corner.br { right: 18px; }
  .score-value { font-size: 27px; }
}
@media (max-height: 780px) {
  .logo { font-size: clamp(36px, 6vw, 66px); }
  .title-wrap { margin-bottom: 22px; }
  .row { padding: 9px 16px 9px 22px; }
}

@media (prefers-reduced-motion: reduce) {
  * { animation-duration: .01ms !important; animation-iteration-count: 1 !important; }
}

/* ==========================================================================
   MOBILE
   Landscape-first, safe-area aware, and sized for thumbs rather than cursors.
   ========================================================================== */

:root {
  --safe-t: env(safe-area-inset-top, 0px);
  --safe-r: env(safe-area-inset-right, 0px);
  --safe-b: env(safe-area-inset-bottom, 0px);
  --safe-l: env(safe-area-inset-left, 0px);
}

/* The HUD pulls in from the notch, the Dynamic Island and rounded corners. */
.hud-corner.tl { top: calc(20px + var(--safe-t)); left: calc(22px + var(--safe-l)); }
.hud-corner.tr { top: calc(20px + var(--safe-t)); right: calc(22px + var(--safe-r)); }
.hud-corner.bl { bottom: calc(20px + var(--safe-b)); left: calc(22px + var(--safe-l)); }
.hud-corner.br { bottom: calc(20px + var(--safe-b)); right: calc(22px + var(--safe-r)); }

/* --- touch controls ----------------------------------------------------- */
.touch-layer {
  position: absolute; inset: 0; z-index: 6;
  touch-action: none;
  -webkit-user-select: none; user-select: none;
  -webkit-tap-highlight-color: transparent;
  opacity: var(--touch-opacity, 0.75);
}
.touch-layer[hidden] { display: none !important; }

/* Floating stick: appears where the thumb lands. */
.touch-stick {
  position: absolute; width: 0; height: 0;
  pointer-events: none;
}
.touch-stick-base, .touch-stick-knob {
  position: absolute; border-radius: 50%;
  transform: translate(-50%, -50%);
  left: 0; top: 0;
}
.touch-stick-base {
  width: calc(var(--r, 70px) * 2); height: calc(var(--r, 70px) * 2);
  border: 2px solid rgba(226,219,198,.34);
  background: rgba(20,24,16,.28);
  backdrop-filter: blur(3px);
}
.touch-stick-knob {
  width: calc(var(--r, 70px) * 0.82); height: calc(var(--r, 70px) * 0.82);
  margin-left: 0; margin-top: 0;
  background: rgba(226,219,198,.30);
  border: 2px solid rgba(226,219,198,.62);
  box-shadow: 0 0 18px rgba(143,174,98,.4);
}
.touch-stick-knob { transform: translate(-50%, -50%); }
.touch-stick-knob { will-change: transform; }

/* Ability buttons sit on the opposite side from the stick. */
.touch-buttons {
  position: absolute;
  right: calc(20px + var(--safe-r)); bottom: calc(18px + var(--safe-b));
  display: flex; gap: 14px; align-items: flex-end;
}
body.left-handed .touch-buttons {
  right: auto; left: calc(20px + var(--safe-l));
  flex-direction: row-reverse;
}
.touch-btn {
  width: 82px; height: 82px; border-radius: 50%;
  display: flex; flex-direction: column; align-items: center;
  justify-content: center; gap: 2px;
  background: rgba(24,27,20,.62);
  border: 2px solid var(--line-hi);
  color: var(--ink-soft);
  backdrop-filter: blur(8px);
  font: 600 9px/1 var(--display); letter-spacing: .14em;
  text-transform: uppercase;
  transition: transform .09s var(--ease-out), background .12s, border-color .12s;
}
.touch-btn .glyph { font-size: 22px; line-height: 1; }
.touch-btn.down { transform: scale(.92); background: rgba(60,72,44,.8); }
.touch-btn.boost { border-color: rgba(232,180,92,.55); color: var(--amber); }
.touch-btn.strike { border-color: rgba(255,139,74,.6); color: var(--bean); }
.touch-btn.strike.down { background: rgba(90,44,22,.8); }

/* Camera and pause, small and out of the way. */
.touch-top {
  position: absolute;
  right: calc(20px + var(--safe-r)); top: calc(16px + var(--safe-t));
  display: flex; gap: 10px;
}
body.left-handed .touch-top { right: auto; left: calc(20px + var(--safe-l)); }
.touch-mini {
  width: 46px; height: 46px; border-radius: 12px;
  background: rgba(24,27,20,.58);
  border: 1px solid var(--line);
  color: var(--ink-dim);
  backdrop-filter: blur(8px);
  display: flex; align-items: center; justify-content: center;
  font-size: 15px;
}
.touch-mini:active { background: rgba(60,72,44,.75); }

/* --- rotate gate -------------------------------------------------------- */
.rotate-gate {
  position: fixed; inset: 0; z-index: 60;
  display: flex; align-items: center; justify-content: center;
  background: radial-gradient(circle at 50% 40%, #1d2614, #0b0e08 70%);
  padding: calc(24px + var(--safe-t)) calc(24px + var(--safe-r))
           calc(24px + var(--safe-b)) calc(24px + var(--safe-l));
  text-align: center;
}
.rotate-gate[hidden] { display: none !important; }
.rotate-inner { max-width: 380px; animation: screen-in .5s var(--ease-out) both; }
.rotate-icon { width: 84px; margin: 0 auto 22px; color: var(--moss); }
.rotate-icon svg {
  width: 100%; height: auto;
  animation: rotate-hint 2.6s var(--ease-in-out) infinite;
}
@keyframes rotate-hint {
  0%, 45%  { transform: rotate(0deg); }
  65%, 90% { transform: rotate(-90deg); }
  100%     { transform: rotate(0deg); }
}
.rotate-gate h2 {
  font: 400 30px/1.2 var(--serif); color: var(--ink); margin: 0 0 10px;
  letter-spacing: .01em;
}
.rotate-gate p { font: 400 15px/1.6 var(--serif); color: var(--ink-dim); margin: 0 0 26px; }
.rotate-anyway {
  background: none; border: 1px solid var(--line-hi); color: var(--ink-soft);
  border-radius: 4px; padding: 12px 22px;
  font: 600 10px/1 var(--display); letter-spacing: .16em; text-transform: uppercase;
}
.rotate-anyway:active { background: var(--panel-hi); }

/* --- touch-sized menus -------------------------------------------------- */
@media (pointer: coarse) {
  .row { padding: 15px 20px 15px 24px; min-height: 54px; }
  .row .label { font-size: 15px; }
  .menu { width: min(520px, 92vw); }
  .panel { padding: 26px 22px 22px; max-height: 86vh; }
  .logo { font-size: clamp(34px, 8vw, 58px); }
  .tagline { font-size: 13px; }
  /* Hover styling must never latch on a touchscreen. */
  .row:hover:not(.sel) { background: none; }
}

/* Short landscape phones: the menu has to fit between the notches. */
@media (max-height: 480px) and (orientation: landscape) {
  .title-wrap { margin-bottom: 12px; }
  .logo { font-size: clamp(28px, 6vh, 44px); }
  .logo-rule, .eyebrow { display: none; }
  .tagline { margin-bottom: 8px; font-size: 12px; }
  .row { padding: 10px 18px 10px 22px; min-height: 42px; }
  .screen { padding: 8px 0; }
  .panel { padding: 18px 20px 16px; max-height: 92vh; }
  .records { display: none; }
}

/* Run setup screen */
.setup-panel { text-align: center; }
.setup-preview {
  display: flex; justify-content: center; gap: 26px; flex-wrap: wrap;
  margin: 4px 0 6px;
}
.setup-line { display: flex; flex-direction: column; gap: 4px; }
.setup-line b {
  font: 400 19px/1.2 var(--serif); color: var(--ink);
  letter-spacing: .01em;
}
.setup-best {
  font: 500 10px/1.6 var(--display); letter-spacing: .16em;
  text-transform: uppercase; color: var(--ink-mute); margin-bottom: 10px;
  min-height: 16px;
}
.setup-panel .menu { margin: 0 auto; text-align: left; }

/* --------------------------------------------------------------------------
   Mobile HUD layout.

   The touch controls claim the two bottom corners and the top right, so the
   HUD has to move out of their way rather than sit under them. Everything
   here is scoped to touch devices; the desktop layout is untouched.
   -------------------------------------------------------------------------- */
body.touch-device.playing .hud-corner.br {
  /* The clearing dial moves up out of the ability buttons' corner. */
  bottom: auto;
  top: calc(60px + var(--safe-t));
  right: calc(14px + var(--safe-r));
  transform: scale(.68);
  transform-origin: top right;
  opacity: .82;
}
body.touch-device.playing .hud-corner.bl {
  /* Strike and Surge readouts sit above the steering thumb, not under it. */
  bottom: calc(112px + var(--safe-b));
  left: calc(16px + var(--safe-l));
  transform: scale(.86);
  transform-origin: bottom left;
}
body.touch-device.playing .hud-corner.tr {
  /* Two columns on a phone: everything textual on the left under the score,
     everything interactive on the right. Sharing the right edge with the
     camera button and the clearing dial just stacked them on top of the
     stats. */
  left: calc(22px + var(--safe-l));
  right: auto;
  top: calc(74px + var(--safe-t));
  align-items: flex-start;
  flex-direction: row;
  gap: 16px;
}
body.touch-device.playing .hud-corner.tr .stat {
  align-items: flex-start;
}
body.left-handed.touch-device.playing .hud-corner.tr {
  left: auto; right: calc(22px + var(--safe-r));
  align-items: flex-end;
}
body.left-handed.touch-device.playing .hud-corner.br {
  right: auto; left: calc(14px + var(--safe-l));
  transform-origin: top left;
}
body.left-handed.touch-device.playing .hud-corner.bl {
  left: auto; right: calc(16px + var(--safe-r));
  transform-origin: bottom right;
}
body.touch-device .status-rail { bottom: calc(96px + var(--safe-b)); }
body.touch-device .update-chip { bottom: calc(96px + var(--safe-b)); }

/* Thumbs are not cursors: give the buttons room on a short landscape phone. */
@media (max-height: 440px) and (orientation: landscape) {
  .touch-btn { width: 66px; height: 66px; }
  .touch-btn .glyph { font-size: 18px; }
  .touch-btn .cap { font-size: 8px; }
  .touch-mini { width: 40px; height: 40px; }
  body.touch-device.playing .hud-corner.bl { bottom: calc(92px + var(--safe-b)); }
}

/* ---------------------------------------------------------------- the lens
 *
 * Second person in the Tech Facility. You are not watching the snake, you are
 * watching it through something that is hunting it, so the frame gets that
 * thing's optics: corner brackets, one tracking line, and scan lines you can
 * only see if you look for them.
 *
 * Deliberately gated to this one combination. The woodland's second person is
 * a living observer with no instruments, and putting a targeting reticle in
 * front of it would be a costume rather than a point of view.
 */
.lens {
  position: absolute;
  inset: 0;
  display: none;
  pointer-events: none;
  z-index: 3;
}
body[data-map="tech"][data-view="second"] .lens { display: block; }

.lens::before {
  /* Scan lines. Two pixels on, two off, at four percent - it reads as a
     texture on the image rather than as stripes drawn over it. */
  content: '';
  position: absolute;
  inset: 0;
  background: repeating-linear-gradient(
    to bottom,
    rgba(150, 236, 255, 0.045) 0 1px,
    transparent 1px 3px);
  mix-blend-mode: screen;
}

.lens::after {
  /* A cold cast at the very edge of the frame. */
  content: '';
  position: absolute;
  inset: 0;
  background: radial-gradient(ellipse at center,
    transparent 52%, rgba(10, 60, 76, 0.42) 100%);
}

.lens-b {
  position: absolute;
  width: 3.2vmin;
  height: 3.2vmin;
  border: 1px solid rgba(150, 236, 255, 0.5);
  animation: lens-breathe 3.4s ease-in-out infinite;
}
.lens-b.tl { top: 6vmin; left: 8vmin; border-right: 0; border-bottom: 0; }
.lens-b.tr { top: 6vmin; right: 8vmin; border-left: 0; border-bottom: 0; }
.lens-b.bl { bottom: 6vmin; left: 8vmin; border-right: 0; border-top: 0; }
.lens-b.br { bottom: 6vmin; right: 8vmin; border-left: 0; border-top: 0; }

@keyframes lens-breathe {
  0%, 100% { opacity: 0.32; transform: scale(1); }
  50% { opacity: 0.68; transform: scale(1.06); }
}

.lens-tag {
  position: absolute;
  top: 6vmin;
  left: 50%;
  transform: translateX(-50%);
  font-size: 0.62rem;
  letter-spacing: 0.34em;
  color: rgba(150, 236, 255, 0.55);
  animation: lens-blink 2.1s steps(1, end) infinite;
}
@keyframes lens-blink {
  0%, 62% { opacity: 0.55; }
  63%, 100% { opacity: 0.16; }
}

/* ------------------------------------------------------------ perf readout
 *
 * Deliberately plain and deliberately in the way of nothing: it sits under the
 * score, uses tabular figures so the numbers stop jittering, and is never
 * shown unless it was asked for.
 */
.perf-hud {
  position: absolute;
  top: 9.5rem;
  left: 1.6rem;
  margin: 0;
  padding: 0.5rem 0.7rem;
  font-family: ui-monospace, "SFMono-Regular", Menlo, Consolas, monospace;
  font-size: 0.66rem;
  line-height: 1.45;
  font-variant-numeric: tabular-nums;
  color: #bfe4c8;
  background: rgba(6, 10, 8, 0.62);
  border: 1px solid rgba(160, 200, 170, 0.22);
  border-radius: 4px;
  white-space: pre;
  pointer-events: none;
  z-index: 6;
}
/* On a phone the readout goes top-centre. The corners are all taken - score
 * top left, stats top right, the thumb stick bottom left and the action
 * buttons bottom right - and the whole point of this thing is that it can be
 * read while playing, not that it can be found afterwards. */
body.touch-device .perf-hud {
  top: 0.4rem;
  left: 50%;
  transform: translateX(-50%);
  bottom: auto;
  font-size: 0.54rem;
  line-height: 1.35;
  padding: 0.35rem 0.55rem;
  text-align: left;
}

/* The landscape prompt earns a second line: on a phone the difference between
 * portrait and landscape is not a preference, it is roughly double the usable
 * play area once the browser's own chrome is accounted for. */
.rotate-tip {
  margin-top: 0.6rem;
  font-size: 0.78rem;
  opacity: 0.72;
  max-width: 22rem;
}

/* ==========================================================================
   The Chase run HUD
   ==========================================================================
   Four things and no more: what am I doing, which way, what just happened,
   what changed in the world. Everything is sized for a thumb-held phone
   first - the desktop simply gets the same layout with more room around it.
*/

.run-hud {
  position: absolute;
  inset: 0;
  pointer-events: none;
  z-index: 4;
}

/* The objective strip: one line, top centre, with a progress track under it
 * that fills across the whole objective chain rather than per phase. */
.obj-strip {
  position: absolute;
  top: 0.9rem;
  left: 50%;
  transform: translateX(-50%);
  min-width: 12rem;
  text-align: center;
}
.obj-line {
  font-size: 0.72rem;
  letter-spacing: 0.22em;
  color: #cfe4d6;
  text-shadow: 0 1px 3px rgba(0, 0, 0, 0.8);
}
.obj-track {
  margin-top: 0.34rem;
  height: 2px;
  background: rgba(200, 224, 210, 0.18);
  overflow: hidden;
}
.obj-track i {
  display: block;
  height: 100%;
  background: linear-gradient(90deg, #7ff0d8, #cfe4d6);
  transform: scaleX(0);
  transform-origin: left center;
  transition: transform 0.4s ease-out;
}

/* The compass. One arrow that rotates around the reticle, so it works in all
 * three perspectives and when the target is behind you. */
.obj-compass {
  position: absolute;
  top: 50%;
  left: 50%;
  width: 8.5rem;
  height: 8.5rem;
  margin: -4.25rem 0 0 -4.25rem;
}
.obj-arrow {
  position: absolute;
  top: -0.2rem;
  left: 50%;
  margin-left: -0.42rem;
  width: 0;
  height: 0;
  border-left: 0.42rem solid transparent;
  border-right: 0.42rem solid transparent;
  border-bottom: 0.62rem solid rgba(127, 240, 216, 0.9);
  filter: drop-shadow(0 0 4px rgba(127, 240, 216, 0.55));
}
.obj-dist {
  position: absolute;
  top: 0.75rem;
  left: 50%;
  transform: translateX(-50%);
  font-size: 0.56rem;
  letter-spacing: 0.12em;
  color: rgba(207, 228, 214, 0.75);
}

/* The hunter's trait, named once at the start of the run. */
.trait-chip {
  position: absolute;
  top: 3.4rem;
  left: 50%;
  transform: translateX(-50%);
  padding: 0.5rem 0.9rem;
  background: rgba(40, 8, 6, 0.72);
  border: 1px solid rgba(255, 90, 60, 0.35);
  border-radius: 4px;
  text-align: center;
  animation: chip-in 0.4s ease-out;
}
.trait-chip b {
  display: block;
  font-size: 0.86rem;
  letter-spacing: 0.16em;
  color: #ff9a7a;
}
.trait-chip span {
  display: block;
  margin-top: 0.15rem;
  font-size: 0.62rem;
  color: rgba(240, 210, 200, 0.8);
}
@keyframes chip-in {
  from { opacity: 0; transform: translate(-50%, -0.5rem); }
  to { opacity: 1; transform: translate(-50%, 0); }
}

/* A dynamic event starting. Left side, so it never collides with the
 * objective strip or the score. */
.event-notice {
  position: absolute;
  top: 30%;
  left: 1.6rem;
  max-width: 14rem;
  padding: 0.55rem 0.8rem;
  background: rgba(6, 14, 18, 0.7);
  border-left: 2px solid #7ff0d8;
  border-radius: 0 4px 4px 0;
}
.event-notice.in { animation: notice-in 0.45s ease-out; }
.event-notice b {
  display: block;
  font-size: 0.74rem;
  letter-spacing: 0.18em;
  color: #7ff0d8;
}
.event-notice span {
  display: block;
  margin-top: 0.2rem;
  font-size: 0.62rem;
  line-height: 1.35;
  color: rgba(214, 232, 226, 0.82);
}
@keyframes notice-in {
  from { opacity: 0; transform: translateX(-0.8rem); }
  to { opacity: 1; transform: translateX(0); }
}

/* Skill pops. Right side, stacked, gone in a second and a bit. */
.skill-rail {
  position: absolute;
  top: 22%;
  right: 1.6rem;
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 0.3rem;
}
.skill-pop {
  display: flex;
  align-items: baseline;
  gap: 0.45rem;
  animation: pop-in 0.9s ease-out forwards;
}
.skill-pop b {
  font-size: 0.64rem;
  letter-spacing: 0.2em;
  color: #ffd98a;
}
.skill-pop i {
  font-style: normal;
  font-size: 0.72rem;
  color: #fff3d0;
}
@keyframes pop-in {
  0% { opacity: 0; transform: translateX(0.6rem); }
  18% { opacity: 1; transform: translateX(0); }
  70% { opacity: 1; }
  100% { opacity: 0; transform: translateY(-0.7rem); }
}

/* A stage transition. Big, centred, brief. */
.stage-banner {
  position: absolute;
  top: 34%;
  left: 50%;
  transform: translateX(-50%);
  text-align: center;
}
.stage-banner.in { animation: stage-in 0.55s ease-out; }
.stage-banner b {
  display: block;
  font-size: 1.5rem;
  letter-spacing: 0.32em;
  color: #f2f7f2;
  text-shadow: 0 2px 12px rgba(0, 0, 0, 0.9);
}
.stage-banner span {
  display: block;
  margin-top: 0.35rem;
  font-size: 0.7rem;
  letter-spacing: 0.2em;
  color: rgba(210, 228, 216, 0.72);
}
@keyframes stage-in {
  from { opacity: 0; letter-spacing: 0.6em; }
  to { opacity: 1; letter-spacing: 0.32em; }
}

/* ==========================================================================
   The three-card upgrade offer
   ========================================================================== */

.upgrade-layer {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 1.4rem;
  background: rgba(4, 8, 10, 0.82);
  z-index: 20;
}
.upgrade-title {
  margin: 0;
  font-size: 0.86rem;
  font-weight: 400;
  letter-spacing: 0.34em;
  color: rgba(214, 232, 222, 0.8);
}
.card-list {
  display: flex;
  gap: 1rem;
  padding: 0 1rem;
  max-width: 46rem;
}
.upgrade-card {
  flex: 1 1 0;
  min-width: 0;
  /* A generous tap target: this has to be comfortable with a thumb, in a
   * moment when the player is under pressure and wants to get back to it. */
  min-height: 11rem;
  padding: 1rem 0.9rem;
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
  text-align: left;
  background: linear-gradient(160deg, rgba(22, 32, 30, 0.95),
                                      rgba(12, 18, 20, 0.95));
  border: 1px solid rgba(160, 200, 180, 0.22);
  border-radius: 6px;
  color: inherit;
  font: inherit;
  cursor: pointer;
  transition: transform 0.12s ease-out, border-color 0.12s ease-out;
}
.upgrade-card:hover,
.upgrade-card:focus-visible {
  transform: translateY(-4px);
  border-color: rgba(127, 240, 216, 0.7);
  outline: none;
}
.card-tag {
  font-size: 0.56rem;
  letter-spacing: 0.24em;
  color: rgba(180, 210, 196, 0.6);
}
.card-name {
  font-size: 1.05rem;
  letter-spacing: 0.04em;
  color: #f0f6f2;
}
.card-blurb {
  font-size: 0.7rem;
  line-height: 1.45;
  color: rgba(206, 226, 216, 0.78);
}
/* Family colours, so a run's direction is visible at a glance. */
.fam-surge .card-tag, .fam-surge .card-name { color: #7ff0d8; }
.fam-strike .card-tag, .fam-strike .card-name { color: #ff9a4a; }
.fam-frost .card-tag, .fam-frost .card-name { color: #9fd0ff; }
.fam-move .card-tag, .fam-move .card-name { color: #cfe4a0; }
.fam-util .card-tag, .fam-util .card-name { color: #d8c4f2; }

/* Phones: stack the cards, shrink the chrome, keep the targets big. */
@media (max-width: 780px), (max-height: 460px) {
  .card-list {
    flex-direction: column;
    gap: 0.55rem;
    width: 100%;
    max-width: 26rem;
  }
  .upgrade-card { min-height: 0; padding: 0.7rem 0.8rem; }
  .card-name { font-size: 0.92rem; }
  .card-blurb { font-size: 0.66rem; }
  .upgrade-title { font-size: 0.72rem; }
  .event-notice { top: auto; bottom: 7.5rem; left: 0.8rem; max-width: 11rem; }
  .skill-rail { top: 15%; right: 0.8rem; }
  .stage-banner b { font-size: 1.1rem; }
}

/* The end-of-run rank. Large, singular, and the first thing the eye lands on
 * after the heading - a run's grade is the thing a player repeats to
 * themselves, and the thing they come back to beat. */
.rank-badge {
  margin: 0.6rem auto 0;
  width: 3.2rem;
  height: 3.2rem;
  display: grid;
  place-items: center;
  font-size: 1.55rem;
  letter-spacing: 0.02em;
  border: 1px solid currentColor;
  border-radius: 50%;
  animation: rank-in 0.5s cubic-bezier(0.2, 1.4, 0.4, 1) both;
}
.rank-badge.r-C { color: #9aa79c; }
.rank-badge.r-B { color: #b8d0a8; }
.rank-badge.r-A { color: #7ff0d8; }
.rank-badge.r-S { color: #ffd98a; }
.rank-badge.r-Splus { color: #ff9a4a; box-shadow: 0 0 22px rgba(255,154,74,0.4); }
@keyframes rank-in {
  from { opacity: 0; transform: scale(0.4); }
  to { opacity: 1; transform: scale(1); }
}
.panel-title.won { color: #ffd98a; }

/* Debug report button on the game-over screen.
   Deliberately quiet: it is for testers, and a player who never needs it
   should be able to ignore it without it competing with Run Again. */
.debug-copy {
  display: block;
  margin: 14px auto 0;
  padding: 7px 14px;
  font: inherit;
  font-size: .74rem;
  letter-spacing: .09em;
  text-transform: uppercase;
  color: var(--ink-faint, #7f8b7a);
  background: transparent;
  border: 1px solid currentColor;
  border-radius: 999px;
  opacity: .55;
  cursor: pointer;
}
.debug-copy:hover, .debug-copy:focus-visible { opacity: 1; }
.debug-copy:active { transform: translateY(1px); }
.debug-copy-note {
  margin-top: 6px;
  text-align: center;
  font-size: .72rem;
  letter-spacing: .06em;
  color: var(--ink-soft, #9aa694);
}

/* ---------------------------------------------------------------- mobile ---
   Full-screen blur is the wrong price to pay on a phone.

   The panel screens animate in behind a `filter: blur()` and sit under a
   `backdrop-filter`, both of which make the GPU resolve the whole frame
   through a blur kernel - twice, when one is layered over the other. On a
   desktop that is free. On a phone it lands as a visible hitch at exactly the
   worst moment, because the screen a player sees most often is the one that
   appears the instant they die, and testers described dying as a freeze.

   The motion is kept: opacity and translate are compositor work and cost
   nothing. Only the blurs go. */
body.touch-device .screen { animation: screen-in-flat .42s var(--ease-out) both; }
body.touch-device .screen.leaving {
  animation: screen-out-flat .28s var(--ease-in-out) forwards;
}
@keyframes screen-in-flat {
  from { opacity: 0; transform: translateY(14px); }
  to   { opacity: 1; transform: none; }
}
@keyframes screen-out-flat {
  to { opacity: 0; transform: translateY(-8px); }
}
body.touch-device .panel {
  backdrop-filter: none;
  /* Opaque enough to stand on its own without the blur behind it. */
  background: #191c14;
}
body.touch-device .menu-backdrop,
body.touch-device #menuLayer.in-run .menu-backdrop { backdrop-filter: none; }

/* A phone held in landscape is about 390 CSS pixels tall, and the game-over
   panel was taller than that - so it scrolled, and the first thing to go off
   the top was the line saying what killed you. That line is the answer to the
   question the player is asking, and testers were already unsure whether the
   hunter had caught them or they had hit a wall. It has to be on screen. */
@media (max-height: 520px) {
  .panel { padding: 16px 22px 14px; max-height: 94vh; }
  .gameover-head { margin-bottom: 2px; }
  .cause { font-size: 12px; margin-top: -8px; margin-bottom: 10px; }
  .final-score { margin-bottom: 10px; }
  .final-value { font-size: 34px; }
  .stat-grid {
    gap: 8px 14px; margin-bottom: 12px; padding: 10px 0;
    grid-template-columns: repeat(auto-fit, minmax(88px, 1fr));
  }
  .stat-cell b { font-size: 16px; margin-top: 2px; }
  .records { margin-bottom: 10px; }
  .debug-copy { margin-top: 8px; padding: 5px 12px; }
}
