/* ===========================================================
   SCANNER RUSH · Sarpy Scanner
   1980s scanner console: charcoal panel, warm off-white text,
   muted CRT green, restrained red, amber.

   The console is deliberately WIDER than a phone-shaped game.
   Sarpy County is wider than it is tall and is now drawn that
   way, so a narrow box would letterbox the map into a strip.
   The width is capped at 560 and the map gets the top half; the
   timeline takes the rest, which is the best thing that could
   be in that space anyway.
   =========================================================== */

:root {
  /* Console shell */
  --black:      #07080A;
  --panel:      #101317;
  --panel-2:    #161A20;
  --panel-3:    #1D222A;
  --hair:       rgba(236,227,210,.13);   /* thin grid lines */
  --hair-soft:  rgba(236,227,210,.07);

  /* Type */
  --ink:        #ECE3D2;                 /* warm off-white */
  --ink-dim:    #9B9484;
  --ink-faint:  #655F55;

  /* Accents, deliberately muted */
  --green:      #5BC08A;
  --amber:      #E9B44C;
  --orange:     #E07A42;
  --blue:       #6BA3D6;
  --red:        #D14A3E;

  --mono: ui-monospace, "SF Mono", SFMono-Regular, Menlo, Consolas, "Roboto Mono", "Courier New", monospace;
  --ui: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;

  --gap: 8px;
  --radius: 4px;                         /* console hardware, not SaaS cards */
}

* { box-sizing: border-box; }

/* Screens and takeover cards are display:flex, which would otherwise win
   against the hidden attribute. Everything here is shown and hidden with
   [hidden], so it has to beat them. */
[hidden] { display: none !important; }

html, body {
  height: 100%;
  margin: 0;
  overflow: hidden;                      /* a game, not a document */
  background: var(--black);
  -webkit-text-size-adjust: 100%;
  overscroll-behavior: none;
}

body {
  font-family: var(--mono);
  color: var(--ink);
  /* Stops double-tap zoom and rubber-banding from fighting the taps. */
  touch-action: manipulation;
  -webkit-user-select: none;
  user-select: none;
  -webkit-tap-highlight-color: transparent;
}

/* ── Cabinet ────────────────────────────────────────────────────────── */

.cabinet {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  height: 100%;
  background:
    radial-gradient(ellipse at 50% 0%, rgba(107,163,214,.07), transparent 62%),
    radial-gradient(ellipse at 50% 100%, rgba(233,180,76,.05), transparent 58%),
    var(--black);
}

.console {
  position: relative;
  display: flex;
  flex-direction: column;
  width: min(100vw, 560px);
  height: min(100dvh, 900px);
  padding: calc(env(safe-area-inset-top, 0px) + 8px) 10px calc(env(safe-area-inset-bottom, 0px) + 10px);
  gap: var(--gap);
  overflow: hidden;
  background: var(--panel);
  background-image:
    linear-gradient(180deg, rgba(107,163,214,.045), transparent 30%),
    repeating-linear-gradient(90deg, var(--hair-soft) 0 1px, transparent 1px 34px);
}

@media (min-width: 600px) and (min-height: 700px) {
  .console {
    border: 1px solid rgba(236,227,210,.16);
    border-radius: 10px;
    box-shadow: 0 0 0 10px #0B0D10, 0 24px 70px rgba(0,0,0,.8);
  }
}

/* ── CRT glass ──────────────────────────────────────────────────────── */

.crt {
  position: absolute;
  inset: 0;
  z-index: 60;
  pointer-events: none;
  background:
    repeating-linear-gradient(180deg, rgba(0,0,0,.26) 0 1px, transparent 1px 3px),
    radial-gradient(ellipse at 50% 50%, transparent 54%, rgba(0,0,0,.5) 100%);
  mix-blend-mode: multiply;
  animation: flicker 5.5s steps(1, end) infinite;
}

@keyframes flicker {
  0%, 93%, 100% { opacity: 1; }
  94%           { opacity: .9; }
  95%           { opacity: 1; }
  96%           { opacity: .93; }
}

/* ── HUD ────────────────────────────────────────────────────────────── */

.hud { flex: 0 0 auto; }

.hud__top,
.hud__bottom {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 8px;
}

.hud__bottom { margin-top: 3px; }

/* "pixel-inspired" without a webfont: heavy, tight, letterspaced caps
   with a hard 1px shadow so the glyphs read as stamped. */
.hud__title {
  font-size: 13px;
  font-weight: 700;
  letter-spacing: .16em;
  color: var(--ink);
  text-shadow: 1px 1px 0 rgba(0,0,0,.9), 0 0 12px rgba(236,227,210,.2);
}

.hud__clock {
  font-size: 15px;
  font-weight: 700;
  letter-spacing: .06em;
  color: var(--green);
  font-variant-numeric: tabular-nums;
  text-shadow: 0 0 10px rgba(91,192,138,.45);
}

.hud__clock.is-low {
  color: var(--red);
  text-shadow: 0 0 12px rgba(209,74,62,.5);
  animation: tick 1s steps(2, end) infinite;
}

@keyframes tick { 0%, 60% { opacity: 1; } 61%, 100% { opacity: .45; } }

/* The clock is the whole feedback loop now: it moves on every tap, so it
   carries both halves of the economy. Declared after .is-low because the
   panic state and a feed can be on in the same frame, and the feed has to
   win. Watching the number climb back out of the red is the best moment
   the game has. */
.hud__clock.is-feeding {
  color: var(--green);
  animation: clockFeed .18s ease-out 1;
}

.hud__clock.is-draining {
  color: var(--red);
  animation: clockDrain .6s ease-out 1;
}

@keyframes clockFeed {
  0%   { transform: scale(1);    text-shadow: 0 0 10px rgba(91,192,138,.45); }
  40%  { transform: scale(1.14); text-shadow: 0 0 18px rgba(91,192,138,.9); }
  100% { transform: scale(1);    text-shadow: 0 0 10px rgba(91,192,138,.45); }
}

@keyframes clockDrain {
  0%   { transform: translateX(0);    text-shadow: 0 0 14px rgba(209,74,62,.9); }
  15%  { transform: translateX(-3px); }
  30%  { transform: translateX(3px); }
  45%  { transform: translateX(-2px); }
  60%  { transform: translateX(2px); }
  100% { transform: translateX(0);    text-shadow: 0 0 10px rgba(209,74,62,.4); }
}

/* Seconds lost, floating off the clock. Only losses get one, because catches land
   two or three times a second and would turn this into noise. */
.hud__top { position: relative; }

.timefloat {
  position: absolute;
  left: 50%;
  top: 100%;
  transform: translateX(-50%);
  font-size: 12px;
  font-weight: 700;
  letter-spacing: .06em;
  color: var(--red);
  text-shadow: 0 0 10px rgba(209,74,62,.6);
  pointer-events: none;
  animation: timeFloat .9s ease-out forwards;
}

@keyframes timeFloat {
  0%   { opacity: 0; transform: translate(-50%, -4px); }
  18%  { opacity: 1; transform: translate(-50%, 2px); }
  100% { opacity: 0; transform: translate(-50%, 16px); }
}

.hud__score {
  min-width: 72px;
  font-size: 16px;
  font-weight: 700;
  text-align: right;
  color: var(--amber);
  font-variant-numeric: tabular-nums;
  text-shadow: 0 0 10px rgba(233,180,76,.35);
}

.hud__bottom > * {
  font-size: 9.5px;
  font-weight: 700;
  letter-spacing: .18em;
  color: var(--ink-faint);
}

.live { display: inline-flex; align-items: center; gap: 5px; color: var(--ink-dim); }

.live__dot {
  width: 6px; height: 6px;
  border-radius: 50%;
  background: var(--red);
  box-shadow: 0 0 7px var(--red);
  animation: pulse 1.6s ease-in-out infinite;
}

@keyframes pulse { 0%, 100% { opacity: 1; } 50% { opacity: .25; } }

.phase { color: var(--ink-faint); }

.streak {
  min-width: 76px;
  text-align: right;
  letter-spacing: .1em;
  color: var(--ink-faint);
}

.streak.is-hot { color: var(--amber); text-shadow: 0 0 10px rgba(233,180,76,.4); }
.streak.is-bump { animation: bump .28s ease-out; }

@keyframes bump {
  0%   { transform: scale(1); }
  40%  { transform: scale(1.28); }
  100% { transform: scale(1); }
}

/* ── Stage: the county ──────────────────────────────────────────────
   The map box holds a fixed aspect ratio, so the percentage positions
   game.js writes mean the same thing on every screen. */

.stage {
  position: relative;
  display: flex;
  flex: 0 0 auto;
  align-items: center;
  justify-content: center;
  padding: 3px;
  overflow: hidden;
  border: 1px solid var(--hair);
  border-radius: var(--radius);
  background:
    linear-gradient(180deg, rgba(107,163,214,.05), transparent 42%),
    var(--panel-2);
  box-shadow: inset 0 0 30px rgba(0,0,0,.55);
}

.map {
  position: relative;
  aspect-ratio: 1000 / 620;
  width: 100%;
}

.map__svg { position: absolute; inset: 0; width: 100%; height: 100%; }

.map__land {
  fill: #141920;
  stroke: rgba(236,227,210,.24);
  stroke-width: 3;
  stroke-linejoin: round;
}

.map__river {
  fill: none;
  stroke: #24455C;
  stroke-width: 7;
  stroke-linecap: round;
  stroke-linejoin: round;
  opacity: .9;
}

.map__road {
  fill: none;
  stroke: rgba(236,227,210,.15);
  stroke-width: 2.5;
  stroke-linecap: round;
}

.map__road--big { stroke: rgba(233,180,76,.3); stroke-width: 4; }

.map__towns, .map__beams, .map__calls { position: absolute; inset: 0; }
.map__towns { pointer-events: none; z-index: 2; }
.map__beams { pointer-events: none; z-index: 4; }
.map__calls { z-index: 6; }

/* ── Town labels ────────────────────────────────────────────────────── */

.town {
  position: absolute;
  display: flex;
  align-items: center;
  gap: 3px;
  translate: -50% -50%;
  white-space: nowrap;
}

.town__dot { width: 3px; height: 3px; border-radius: 50%; background: rgba(236,227,210,.5); }

.town__name {
  font-size: 7.5px;
  font-weight: 700;
  letter-spacing: .12em;
  color: rgba(236,227,210,.34);
  text-transform: uppercase;
}

/* ── The receiver: a radio set in the empty south-west corner ──────
   It sits OUTSIDE the county line on purpose, because that is where you are,
   listening to the place rather than standing in it. The element is
   anchored by its ANTENNA TIP, not its centre, because the tip is the
   point CONFIG.base names and the point every beam lands on. */

.base {
  position: absolute;
  z-index: 5;
  width: clamp(78px, 18%, 108px);
  /* Put the antenna tip (93.9%, 7.7% of the artwork) on the anchor point. */
  translate: -93.9% -7.7%;
  pointer-events: none;
}

.base__set { display: block; width: 100%; height: auto; overflow: visible; }

.base__mast {
  fill: none;
  stroke: var(--ink-dim);
  stroke-width: 4;
  stroke-linecap: round;
}

.base__tip {
  fill: var(--amber);
  filter: drop-shadow(0 0 5px var(--amber));
}

.base__case {
  fill: #191E25;
  stroke: rgba(236,227,210,.4);
  stroke-width: 3;
}

.base__grille {
  fill: none;
  stroke: rgba(236,227,210,.3);
  stroke-width: 3;
  stroke-linecap: round;
}

.base__screen { fill: #0A1510; stroke: color-mix(in srgb, var(--green) 55%, transparent); stroke-width: 2; }

.base__trace {
  fill: none;
  stroke: var(--green);
  stroke-width: 2;
  stroke-linejoin: round;
  filter: drop-shadow(0 0 4px var(--green));
}

.base__knob { fill: #0E1217; stroke: var(--ink-faint); stroke-width: 2.5; }

.base__name {
  position: absolute;
  top: 100%;
  left: 42%;
  translate: -50% 3px;
  font-size: 7.5px;
  font-weight: 700;
  letter-spacing: .16em;
  white-space: nowrap;
  color: var(--amber);
  text-shadow: 0 1px 2px rgba(0,0,0,.95);
}

/* It is always listening, so it rings off the antenna tip */
.base__ping {
  position: absolute;
  top: 7.7%;
  left: 93.9%;
  width: 26px;
  height: 26px;
  translate: -50% -50%;
  border: 1px solid var(--amber);
  border-radius: 50%;
  opacity: 0;
  animation: basePing 2.4s ease-out infinite;
}

.base__ping:nth-of-type(2) { animation-delay: 1.2s; }

@keyframes basePing {
  0%   { opacity: .45; scale: .5; }
  100% { opacity: 0; scale: 3; }
}

/* A signal just landed: the tip flares and the trace jumps */
.base.is-hit .base__tip { animation: tipHit .4s ease-out; }
.base.is-hit .base__trace { animation: traceHit .4s ease-out; }

@keyframes tipHit {
  0%   { filter: drop-shadow(0 0 5px var(--amber)); }
  25%  { filter: drop-shadow(0 0 16px var(--amber)) drop-shadow(0 0 28px var(--amber)); }
  100% { filter: drop-shadow(0 0 5px var(--amber)); }
}

@keyframes traceHit {
  0%, 100% { stroke-width: 2; opacity: 1; }
  30%      { stroke-width: 3.4; opacity: 1; filter: drop-shadow(0 0 9px var(--green)); }
}

/* ── The beam: a sine wave running home to the antenna ─────────────
   Two elements on purpose. The outer one carries position, rotation,
   length and the arrive-and-collapse life cycle; the inner one carries
   the wave itself and scrolls it. Putting both on one element means
   the mask animation and the clip animation fight over compositing. */

.beam {
  position: absolute;
  height: 16px;
  transform-origin: 0 50%;
  animation: beamLife var(--beam, .3s) ease-out forwards;
}

@keyframes beamLife {
  0%   { opacity: 0; clip-path: inset(0 100% 0 0); }
  22%  { opacity: 1; clip-path: inset(0 0 0 0); }
  68%  { opacity: 1; clip-path: inset(0 0 0 0); }
  100% { opacity: 0; clip-path: inset(0 0 0 92%); }
}

/* The wave is a mask so it can take the channel colour, and it is
   brighter at the receiving end than at the source. */
.beam__wave {
  position: absolute;
  inset: 0;
  background: linear-gradient(90deg,
    color-mix(in srgb, var(--chan) 22%, transparent), var(--chan));
  filter: drop-shadow(0 0 5px color-mix(in srgb, var(--chan) 70%, transparent));
  -webkit-mask-image: var(--sine);
          mask-image: var(--sine);
  -webkit-mask-repeat: repeat-x;
          mask-repeat: repeat-x;
  -webkit-mask-size: 20px 100%;
          mask-size: 20px 100%;
  -webkit-mask-position: 0 center;
          mask-position: 0 center;
  animation: beamScroll .2s linear infinite;
}

/* One full period of a sine, stroked. Scrolled toward the receiver. */
:root {
  --sine: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='20' height='16' viewBox='0 0 20 16'%3E%3Cpath d='M0 8 Q5 0 10 8 T20 8' fill='none' stroke='%23fff' stroke-width='2.6' stroke-linecap='round'/%3E%3C/svg%3E");
}

@keyframes beamScroll {
  to { -webkit-mask-position: 20px center; mask-position: 20px center; }
}

/* ── Calls: traffic on the air ─────────────────────────────────────── */

.call {
  position: absolute;
  z-index: 7;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 46px;
  height: 46px;
  padding: 0;
  font-family: inherit;
  translate: -50% -50%;
  border: 0;
  background: none;
  cursor: pointer;
  animation: callIn .18s cubic-bezier(.2, 1.6, .4, 1);
}

@keyframes callIn {
  from { opacity: 0; scale: .4; }
  to   { opacity: 1; scale: 1; }
}

/* Expanding pings: this is being broadcast right now. */
.call__ping {
  position: absolute;
  inset: 3px;
  border: 1px solid var(--chan);
  border-radius: 50%;
  opacity: 0;
  animation: callPing 1.15s ease-out infinite;
  pointer-events: none;
}

.call__ping--late { animation-delay: .57s; }

@keyframes callPing {
  0%   { opacity: .75; scale: .7; }
  100% { opacity: 0; scale: 2.1; }
}

/* The countdown. A conic gradient wiped by --spent, which game.js writes
   once per frame. Cheaper than redrawing an SVG arc, and it reads as a
   clock face, which is the whole job. */
.call__ring {
  position: absolute;
  inset: 0;
  border-radius: 50%;
  background:
    conic-gradient(from -90deg,
      transparent 0 var(--spent, 0deg),
      var(--chan) var(--spent, 0deg) 360deg);
  mask: radial-gradient(circle, transparent 62%, #000 64%);
  -webkit-mask: radial-gradient(circle, transparent 62%, #000 64%);
  pointer-events: none;
}

.call::before {
  content: "";
  position: absolute;
  inset: 5px;
  border-radius: 50%;
  background: #0E1217;
  border: 1px solid color-mix(in srgb, var(--chan) 50%, transparent);
  box-shadow: 0 0 16px color-mix(in srgb, var(--chan) 40%, transparent);
}

.call__icon { position: relative; font-size: 19px; line-height: 1; pointer-events: none; }

.call__place {
  position: absolute;
  top: calc(100% - 1px);
  left: 50%;
  translate: -50% 0;
  font-size: 7px;
  font-weight: 700;
  letter-spacing: .08em;
  white-space: nowrap;
  color: var(--chan);
  text-transform: uppercase;
  text-shadow: 0 1px 2px rgba(0,0,0,.95);
  pointer-events: none;
}

/* Running out of air */
.call.is-urgent::before {
  border-color: var(--red);
  box-shadow: 0 0 20px color-mix(in srgb, var(--red) 70%, transparent);
  animation: urgent .3s steps(2, end) infinite;
}

@keyframes urgent { 0%, 60% { opacity: 1; } 61%, 100% { opacity: .5; } }

.call--breaking .call__icon { font-size: 22px; }
.call--breaking::before { border-width: 2px; border-color: var(--red); }

.call.is-gone { pointer-events: none; animation: callOut .26s ease-out forwards; }
@keyframes callOut { to { opacity: 0; scale: 1.8; } }

.call.is-gone.is-lost { animation: callLost .32s ease-out forwards; }
@keyframes callLost { to { opacity: 0; scale: .45; filter: saturate(0); } }

/* ── Score popups and the verdict banner ───────────────────────────── */

.pop {
  position: absolute;
  z-index: 20;
  font-size: 12px;
  font-weight: 700;
  white-space: nowrap;
  color: var(--green);
  text-shadow: 0 1px 0 rgba(0,0,0,.9);
  animation: pop .72s ease-out forwards;
  pointer-events: none;
}

.pop--bad  { color: var(--red); }
.pop--gold { color: var(--amber); }

@keyframes pop {
  0%   { opacity: 0; transform: translate(-50%, 2px); }
  18%  { opacity: 1; transform: translate(-50%, -8px); }
  100% { opacity: 0; transform: translate(-50%, -30px); }
}

.verdict {
  position: absolute;
  top: 6px;
  right: 0;
  left: 0;
  z-index: 30;
  margin: 0;
  font-size: 11.5px;
  font-weight: 700;
  letter-spacing: .2em;
  text-align: center;
  color: var(--ink);
  opacity: 0;
  pointer-events: none;
}

.verdict.is-on { animation: verdict .8s ease-out; }
.verdict--good { color: var(--green); text-shadow: 0 0 12px rgba(91,192,138,.5); }
.verdict--bad  { color: var(--red);   text-shadow: 0 0 12px rgba(209,74,62,.5); }
.verdict--gold { color: var(--amber); text-shadow: 0 0 12px rgba(233,180,76,.5); }

@keyframes verdict {
  0%   { opacity: 0; transform: translateY(-5px); }
  14%  { opacity: 1; transform: translateY(0); }
  70%  { opacity: 1; }
  100% { opacity: 0; }
}

/* ── Takeover: phase announcements ─────────────────────────────────── */

.takeover {
  position: absolute;
  inset: 0;
  z-index: 40;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 10px;
  padding: 0 18px;
  text-align: center;
  background: rgba(7,8,10,.86);
}

/* A milestone is something you REACHED, so it must not cost a call. No scrim
   and no pointer blocking: the name floats over a board that is still fully
   live and still fully tappable underneath it. */
.takeover--flash {
  background: none;
  pointer-events: none;
  animation: flashIn 1.4s ease-out forwards;
}

.takeover--flash .takeover__text {
  text-shadow: 0 0 24px rgba(7,8,10,.95), 0 0 10px rgba(7,8,10,.9);
}

.takeover--flash .takeover__sub {
  text-shadow: 0 0 18px rgba(7,8,10,.95);
}

@keyframes flashIn {
  0%   { opacity: 0; transform: scale(.94); }
  12%  { opacity: 1; transform: scale(1); }
  70%  { opacity: 1; }
  100% { opacity: 0; transform: scale(1.04); }
}

.takeover__sub {
  font-size: 11px;
  font-weight: 700;
  letter-spacing: .18em;
  color: var(--ink);
  animation: fade .3s ease-out .12s both;
}

.takeover__text {
  font-size: clamp(17px, 6vw, 26px);
  font-weight: 700;
  letter-spacing: .14em;
  color: var(--red);
  text-shadow: 0 0 20px rgba(209,74,62,.55);
  animation: slam .45s cubic-bezier(.2, 1.4, .4, 1);
}

@keyframes slam {
  0%   { opacity: 0; transform: scale(1.5); letter-spacing: .5em; }
  100% { opacity: 1; transform: scale(1);   letter-spacing: .14em; }
}

/* Dials the whole console up a notch. Keyed to the TANK running low, not to
   a milestone: it used to fire when you survived far enough and then stay on
   for the rest of the run, which made the game look angrier the better you
   were doing. Now it means you are nearly off air, and it comes back off the
   moment you earn your way out. */
.console.is-dispatch { background-image:
    linear-gradient(180deg, rgba(209,74,62,.09), transparent 34%),
    repeating-linear-gradient(90deg, var(--hair-soft) 0 1px, transparent 1px 34px); }
.console.is-dispatch .stage { box-shadow: inset 0 0 40px rgba(209,74,62,.16); }
.console.is-dispatch .hud__title { color: var(--red); text-shadow: 0 0 12px rgba(209,74,62,.5); }

/* ── The timeline: what the base put out ───────────────────────────── */

.timeline {
  display: flex;
  flex: 1 1 auto;
  flex-direction: column;
  gap: 5px;
  min-height: 0;
  padding: 6px;
  overflow: hidden;
  border: 1px solid var(--hair);
  border-radius: var(--radius);
  background: var(--panel-2);
  box-shadow: inset 0 0 20px rgba(0,0,0,.5);
}

.timeline__idle {
  display: flex;
  align-items: center;
  gap: 8px;
  margin: 0;
  padding: 4px 3px;
  font-size: 11.5px;
  color: var(--ink-faint);
}

.timeline__tag {
  font-size: 8px;
  font-weight: 700;
  letter-spacing: .18em;
}

.caret {
  display: inline-block;
  width: 6px;
  height: 10px;
  margin-left: 3px;
  background: var(--green);
  animation: pulse 1.1s steps(2, end) infinite;
}

.post {
  display: flex;
  flex: 0 0 auto;
  gap: 7px;
  padding: 6px 8px 5px;
  font-family: var(--ui);
  text-align: left;
  border: 1px solid rgba(236,227,210,.13);
  border-radius: 10px;
  background: #15181D;
  animation: postIn .28s cubic-bezier(.2, 1, .4, 1);
}

/* Newest arrives at the top and shoves the rest down */
@keyframes postIn {
  from { opacity: 0; transform: translateY(-10px) scale(.97); }
  to   { opacity: 1; transform: translateY(0) scale(1); }
}

/* The older it is, the quieter it gets, like a timeline scrolling away */
.post:nth-of-type(4) { opacity: .88; }
.post:nth-of-type(5) { opacity: .74; }
.post:nth-of-type(6) { opacity: .58; }
.post:nth-of-type(7) { opacity: .42; }
.post:nth-of-type(8) { opacity: .26; }

.post__avatar {
  flex: 0 0 auto;
  width: 24px;
  height: 24px;
  font-size: 13px;
  line-height: 24px;
  text-align: center;
  border-radius: 50%;
  background: #22272E;
  border: 1px solid rgba(236,227,210,.12);
}

.post__body { flex: 1 1 auto; min-width: 0; }

.post__head {
  display: flex;
  align-items: center;
  gap: 4px;
  font-size: 10px;
  line-height: 1.2;
  color: #71767B;
}

.post__name { font-weight: 700; color: #E7E9EA; white-space: nowrap; }

.post__handle { overflow: hidden; white-space: nowrap; text-overflow: ellipsis; }

.post__text {
  margin: 2px 0 0;
  font-size: 11.5px;
  line-height: 1.32;
  color: #E7E9EA;
  overflow-wrap: anywhere;
}

/* The place tag these accounts actually lead with. */
.post__tag { font-weight: 700; color: var(--chan, var(--ink)); }
.post__tag .post__icon { margin-right: 4px; }

.post__stats {
  display: flex;
  gap: 13px;
  margin-top: 3px;
  font-size: 9.5px;
  color: #71767B;
}

.post--viral { border-color: color-mix(in srgb, var(--amber) 55%, transparent); }
.post--viral .post__stats { color: var(--amber); }

/* ── Screens ────────────────────────────────────────────────────────── */

.screen {
  position: absolute;
  inset: 0;
  z-index: 50;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 10px;
  padding: 24px 22px calc(env(safe-area-inset-bottom, 0px) + 24px);
  overflow-y: auto;
  text-align: center;
  background:
    radial-gradient(ellipse at 50% 38%, rgba(107,163,214,.09), transparent 62%),
    rgba(7,8,10,.965);
  animation: fade .22s ease-out;
}

@keyframes fade { from { opacity: 0; } to { opacity: 1; } }

.screen__emoji { font-size: 42px; line-height: 1; }

.screen__title {
  margin: 0;
  font-size: clamp(30px, 10vw, 46px);
  font-weight: 700;
  letter-spacing: .07em;
  line-height: 1;
  color: var(--ink);
  text-shadow: 2px 2px 0 rgba(0,0,0,.9), 0 0 26px rgba(236,227,210,.25);
}

.screen__lede {
  max-width: 32ch;
  margin: 2px 0 0;
  font-size: 11.5px;
  font-weight: 700;
  letter-spacing: .12em;
  line-height: 1.6;
  color: var(--green);
  text-shadow: 0 0 14px rgba(91,192,138,.35);
}

.screen__tagline {
  margin: 2px 0 0;
  font-size: 9px;
  font-weight: 700;
  letter-spacing: .22em;
  color: var(--ink-faint);
}

.screen__kicker {
  margin: 0;
  font-size: 11.5px;
  font-weight: 700;
  letter-spacing: .3em;
  color: var(--red);
  text-shadow: 0 0 14px rgba(209,74,62,.45);
}

.screen__note {
  max-width: 34ch;
  margin: 0;
  font-size: 10px;
  font-weight: 700;
  letter-spacing: .14em;
  line-height: 1.5;
  color: var(--green);
  overflow-wrap: anywhere;
}

/* How to play: four lines, so nobody has to discover the rules by losing. */
.how {
  max-width: 34ch;
  margin: 2px 0 4px;
  padding: 0;
  font-size: 11.5px;
  line-height: 1.85;
  text-align: left;
  color: var(--ink-dim);
  list-style: none;
}

.how li { position: relative; padding-left: 15px; }
.how li::before { content: "▸"; position: absolute; left: 0; color: var(--green); }
.how strong { color: var(--ink); font-weight: 700; }

/* ── Presented by / newsletter ──────────────────────────────────────── */

.presented {
  margin: 7px 0 0;
  font-size: 13px;
  letter-spacing: .06em;
  color: var(--ink-dim);
}

.presented a {
  color: var(--amber);
  font-weight: 700;
  text-decoration: none;
  border-bottom: 1px solid color-mix(in srgb, var(--amber) 45%, transparent);
}

.signup {
  width: 100%;
  max-width: 320px;
  margin: 4px 0 0;
  padding: 11px 12px 12px;
  border: 1px solid var(--hair);
  border-radius: var(--radius);
  background: rgba(233,180,76,.05);
}

/* The copy wraps at the full content width so its edges line up with the
   input below it. Don't add text-wrap: balance here. It equalises line
   lengths by shrinking the line box, which left the copy 198px wide inside
   a 294px content box: a 48px indent on each side against an input that
   fills the same box edge to edge. */
.signup__title {
  margin: 0 0 7px;
  font-size: 15px;
  font-weight: 700;
  letter-spacing: .04em;
  color: var(--ink);
}

.signup__desc {
  margin: 0 0 10px;
  font-size: 11px;
  line-height: 1.45;
  color: var(--ink-dim);
}

.signup__row { display: flex; gap: 6px; }

.signup__input {
  flex: 1 1 auto;
  min-width: 0;
  padding: 11px 10px;
  font-family: inherit;
  font-size: 14px;
  color: var(--ink);
  background: rgba(0,0,0,.45);
  border: 1px solid var(--hair);
  border-radius: 4px;
  -webkit-user-select: text;
  user-select: text;
}

.signup__input::placeholder { color: var(--ink-faint); }
.signup__input:focus { outline: 2px solid var(--amber); outline-offset: 0; }

/* min-width is the idle label's own width. On submit the text swaps to
   "Sending…", which is 54px narrower, and without the floor the button
   shrinks and the input lurches wider for the length of the request. The
   floor holds it still. auto flex-basis keeps it a floor rather than a
   fixed size, so a wider fallback font grows the button instead of
   clipping the label. */
.signup__go {
  flex: 0 0 auto;
  min-width: 142px;
  padding: 11px 12px;
  font-family: inherit;
  font-size: 12px;
  font-weight: 700;
  letter-spacing: .04em;
  white-space: nowrap;
  color: var(--black);
  background: linear-gradient(180deg, #F2C45C, var(--amber));
  border: 1px solid #F6D489;
  border-radius: 4px;
  cursor: pointer;
}

.signup__go:disabled { opacity: .6; cursor: default; }

.signup__note { margin: 8px 0 0; font-size: 10.5px; line-height: 1.4; color: var(--green); }
.signup__note--error { color: var(--red); }

/* Once an address is in, the form stops asking for another one. */
.signup.is-done .signup__row,
.signup.is-done .signup__desc { display: none; }

/* ── Results ────────────────────────────────────────────────────────── */

.result__score {
  margin: 0;
  font-size: clamp(46px, 15vw, 68px);
  font-weight: 700;
  line-height: 1;
  color: var(--amber);
  font-variant-numeric: tabular-nums;
  text-shadow: 0 0 34px rgba(233,180,76,.4);
}

.result__rank {
  margin: 4px 0 0;
  padding: 7px 16px;
  font-size: clamp(13px, 4.4vw, 17px);
  font-weight: 700;
  letter-spacing: .1em;
  color: var(--green);
  border: 1px solid color-mix(in srgb, var(--green) 45%, transparent);
  border-radius: var(--radius);
  background: rgba(91,192,138,.08);
  text-shadow: 0 0 14px rgba(91,192,138,.35);
}

.result__stats { margin: 0; font-size: 11px; letter-spacing: .05em; color: var(--ink-faint); }

.result__bonus {
  margin: 0;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: .14em;
  color: var(--green);
  text-shadow: 0 0 10px rgba(91,192,138,.4);
}

.actions {
  display: flex;
  flex-direction: column;
  gap: 8px;
  width: 100%;
  max-width: 320px;
  margin-top: 6px;
}

/* The run's feed, reopened under the buttons. With it open the end screen
   stops centring and reads top-down, because the feed is the bottom of a
   column now rather than something floating in the middle of one. */
.screen--end.is-feed {
  justify-content: flex-start;
  gap: 8px;
}

.result__feed {
  display: flex;
  flex-direction: column;
  gap: 5px;
  width: 100%;
  max-width: 320px;
  margin-top: 2px;
  padding: 6px;
  text-align: left;
  border: 1px solid var(--hair);
  border-radius: var(--radius);
  background: var(--panel-2);
  box-shadow: inset 0 0 20px rgba(0,0,0,.5);
  animation: fade .2s ease-out;
}

/* These posts are no longer arriving, they are being read back, so they do
   not re-run the arrival animation on every toggle. */
.result__feed .post { animation: none; }

.result__feed-empty {
  margin: 0;
  padding: 10px 2px;
  font-size: 10px;
  font-weight: 700;
  letter-spacing: .16em;
  text-align: center;
  color: var(--ink-faint);
}

.btn {
  display: block;
  width: 100%;
  max-width: 320px;
  padding: 15px 20px;
  font-family: inherit;
  font-size: 13.5px;
  font-weight: 700;
  letter-spacing: .16em;
  text-align: center;
  text-decoration: none;
  color: var(--black);
  background: linear-gradient(180deg, #F2C45C, var(--amber));
  border: 1px solid #F6D489;
  border-bottom: 3px solid #A87C25;
  border-radius: 6px;
  cursor: pointer;
  transition: transform .06s ease, filter .1s ease;
}

.btn:active { transform: translateY(2px); border-bottom-width: 1px; filter: brightness(1.1); }
.btn:focus-visible { outline: 2px solid var(--ink); outline-offset: 3px; }

.btn--primary { box-shadow: 0 0 28px rgba(233,180,76,.28); }

/* The follow button wears X's colours, because that is what it is. */
.btn--follow {
  color: #fff;
  background: #000;
  border: 1px solid #3A3F44;
  border-bottom: 3px solid #26292D;
  font-size: 12.5px;
}

.btn--ghost {
  padding: 12px 20px;
  color: var(--ink);
  background: transparent;
  border: 1px solid var(--hair);
  border-bottom: 3px solid var(--hair);
}

.btn--toggle {
  width: auto;
  padding: 9px 16px;
  font-size: 10.5px;
  letter-spacing: .14em;
  color: var(--ink-dim);
  background: transparent;
  border: 1px solid var(--hair);
  border-bottom-width: 1px;
}

.btn--toggle[aria-pressed="false"] { color: var(--ink-faint); }

/* ── Short screens ──────────────────────────────────────────────────── */

@media (max-height: 740px) {
  .timeline { gap: 4px; }
  .screen__emoji { font-size: 30px; }
  .screen { gap: 7px; }
  .how { line-height: 1.7; }
}

@media (max-height: 620px) {
  .call { width: 40px; height: 40px; }
  .call__icon { font-size: 16px; }
  .screen__emoji { display: none; }
  .post__stats { display: none; }
}

/* ── Reduced motion: keep the information, drop the movement ────────── */

@media (prefers-reduced-motion: reduce) {
  .crt,
  .live__dot,
  .caret,
  .hud__clock.is-low,
  .hud__clock.is-feeding,
  .hud__clock.is-draining,
  .timefloat,
  .call__ping,
  .base__ping,
  .beam__wave,
  .call.is-urgent::before,
  .takeover__text,
  .takeover--flash,
  .screen { animation: none; }

  /* Urgency still has to be visible without the blink. */
  .call.is-urgent::before { border-color: var(--red); border-width: 2px; }

  /* The beam still needs to arrive, just without the sweep. */
  .beam { animation: fade .14s ease-out forwards; }
  .post { animation: none; }
}
