/* ROOFTOP QUEST — the HUD.
 *
 * Everything here is one flat class layer. Nothing uses an #id, and nothing
 * uses a descendant chain longer than it needs: the root element is #hud, so a
 * single `#hud .hud-tl { ... }` would score 1,1,0 and quietly outrank every
 * plain `.hud-*` rule after it. The first person to add a modifier class would
 * find it did nothing and the HUD would sit in the wrong corner with no error.
 * Keep every layout rule in here at 0,1,0 or 0,2,0.
 *
 * THE WHOLE HUD IS ONE GRID. That is not a style preference. src/selftest.js
 * asserts that no two [data-panel] boxes intersect, and two boxes in different
 * grid areas cannot. Four absolutely-positioned corners can, and did, the
 * moment a zone name got long enough to reach the middle of the screen.
 *
 * Areas:      tl  tc  tr        top-left card, clock pill, buttons + qualified
 *            mid mid mid        the toast, vertically centred
 *             bc  bc  bc        the progress rail
 *             bl  bl  br        control legend, look hint
 *
 * Under 680px the clock pill drops onto its own row, because the middle column
 * is `auto` and an auto column will not shrink: past that width it starts
 * squeezing the side columns until their content spills into each other.
 *
 * Everything is pointer-events:none except the real controls, or a drag to look
 * that happens to start over a card gets eaten by the card.
 */

/* ------------------------------------------------------------------ frame */

.hud {
  position: fixed;
  inset: 0;
  z-index: var(--z-hud);
  display: grid;
  padding: var(--gutter);
  gap: var(--s-4);
  grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr);
  grid-template-rows: auto minmax(0, 1fr) auto auto;
  grid-template-areas:
    "tl  tc  tr"
    "mid mid mid"
    "bc  bc  bc"
    "bl  bl  br";
  pointer-events: none;
}

/* The class sets `display`, so the UA's [hidden] rule loses. Say it here. */
.hud[hidden] { display: none; }

.hud button,
.hud [data-ui] { pointer-events: auto; }

/* src/ui/icons.js emits class `ico` (not `icon`) and sizes itself at 1em, so
 * the --icon-size tokens on .btn--round / .pill / .chip never reach the glyph
 * on their own. Bind them here, scoped, so the landing keeps its own sizing.
 *
 * ⚠ The countdown and the results card are SIBLINGS of .hud, not children of
 * it — src/ui/hud.js builds three roots inside #hud so the two overlays can sit
 * above the pointer-events:none layer. A bare `.hud .ico` therefore never
 * reaches them, and every --icon-size in the results section below is dead:
 * the crown badge came out at 1em (15px) inside its 56px disc. Name all three. */
.hud .ico,
.hud-count .ico,
.hud-results .ico {
  display: block;
  flex: 0 0 auto;
  width: var(--icon-size);
  height: var(--icon-size);
}

/* ------------------------------------------------------------- top left */

.hud-tl {
  grid-area: tl;
  display: grid;
  justify-items: start;
  gap: var(--s-2);
  min-width: 0;
}

.hud-brand {
  display: flex;
  align-items: center;
  gap: var(--s-2);
  --icon-size: 26px;
  filter: drop-shadow(0 2px 0 rgba(18, 14, 32, 0.4));
}

/* The mark carries the lockup on its own, so it is drawn a shade heavier than
 * the HUD's other icons. Same glyph, no second copy. */
.hud-brand .ico { stroke-width: 2.4; color: var(--c-green); }

.hud-brand__name {
  font-family: var(--display);
  font-size: var(--fs-lg);
  font-weight: var(--fw-black);
  letter-spacing: var(--tr-title);
  text-transform: uppercase;
  text-shadow: var(--sh-text);
}

.hud-zone {
  display: grid;
  gap: 3px;
  /* ⚠ min-width:auto beats max-width, so without this the card is floored at
   * its min-content width and grows back out of the tl column — 4px over at
   * 320px, and straight into the buttons the moment a word gets longer. */
  min-width: 0;
  max-width: min(360px, 100%);
}

.hud-zone__row {
  display: flex;
  /* Wraps for the same reason: an unwrappable icon + word sets the card's own
   * floor. Let the course name drop under the flag before the card widens. */
  flex-wrap: wrap;
  align-items: center;
  gap: var(--s-2);
  --icon-size: 17px;
}

.hud-zone__row .ico { color: var(--c-green); }

.hud-zone__course {
  font-size: var(--fs-md);
  font-weight: var(--fw-black);
  letter-spacing: var(--tr-tight);
  text-transform: uppercase;
  line-height: var(--lh-snug);
}

.hud-zone__line { color: var(--c-text-mute); }
.hud-zone__name { color: var(--c-text-dim); }

/* Restarted from JS on every zone change; see setZone(). */
.hud-zone.is-new { animation: ps-pop-in 420ms var(--ease-pop); }

/* ----------------------------------------------------------- top centre */

.hud-clock {
  grid-area: tc;
  justify-self: center;
  align-self: start;
  --icon-size: 19px;
}

.hud-clock .ico { color: var(--c-butter); }
.hud-clock__place { color: var(--c-text); }
.hud-clock__time { color: var(--c-cyan); }

/* Outside the qualifying places. Colour is the only warning the player gets
 * that finishing is not the same as getting through. */
.hud-clock.is-risk .ico,
.hud-clock.is-risk .hud-clock__place { color: var(--c-pink-hot); }

/* ------------------------------------------------------------ top right */

.hud-tr {
  grid-area: tr;
  display: grid;
  justify-items: end;
  gap: var(--s-2);
  min-width: 0;
}

.hud-btns {
  display: flex;
  flex-wrap: wrap;
  justify-content: flex-end;
  gap: var(--s-2);
}

/* Each round button holds BOTH states of its glyph and swaps by class. The
 * alternative is rewriting innerHTML with an <svg> string, which src/ui/icons.js
 * warns about: dropped into an HTML element it can come back namespaced wrong
 * and render nothing at all. */
.hud-swap > .ico:nth-child(2) { display: none; }
.hud-swap.is-alt > .ico:nth-child(1) { display: none; }
.hud-swap.is-alt > .ico:nth-child(2) { display: block; }

.hud-qual {
  display: grid;
  gap: 2px;
  justify-items: end;
  text-align: right;
  min-width: 0;
}

.hud-qual__n {
  font-size: var(--fs-lg);
  color: var(--c-green);
  line-height: 1.1;
}

.hud-qual__still {
  display: flex;
  align-items: center;
  gap: var(--s-1);
  --icon-size: 13px;
  color: var(--c-text-mute);
}

/* Every qualifying place is taken. Nobody else is getting through this heat. */
.hud-qual.is-full .hud-qual__n { color: var(--c-pink-hot); }

/* ---------------------------------------------------------------- toast */

.hud-toast {
  grid-area: mid;
  justify-self: center;
  align-self: center;
  display: flex;
  align-items: center;
  gap: var(--s-3);
  max-width: min(560px, 100%);
  padding: var(--s-3) var(--s-5);
  border-radius: var(--r-pill);
  background: var(--c-surface);
  -webkit-backdrop-filter: var(--blur-card);
  backdrop-filter: var(--blur-card);
  border: 1px solid var(--c-line-strong);
  box-shadow: var(--sh-3);
  font-size: var(--fs-md);
  font-weight: var(--fw-black);
  letter-spacing: var(--tr-tight);
  text-align: center;
  --icon-size: 20px;
  opacity: 0;
  transform: translateY(-16px) scale(0.96);
  transition:
    opacity var(--dur-2) var(--ease-out),
    transform var(--dur-3) var(--ease-pop);
}

.hud-toast[hidden] { display: none; }
.hud-toast.is-in { opacity: 1; transform: none; }
.hud-toast .ico { color: var(--c-butter); }

/* ----------------------------------------------------------------- rail */

.hud-rail {
  grid-area: bc;
  justify-self: center;
  align-self: end;
  display: grid;
  justify-items: center;
  /* The marker is 24px tall on a 10px track, so it hangs 7px below the rail.
   * At --s-2 the label sat under it and the two read as one smudge. */
  gap: var(--s-4);
  width: min(620px, 100%);
}

.hud-rail__track {
  position: relative;
  width: 100%;
  height: 10px;
  border-radius: var(--r-pill);
  background: var(--c-surface);
  -webkit-backdrop-filter: var(--blur-card);
  backdrop-filter: var(--blur-card);
  border: 1px solid var(--c-line);
  box-shadow: var(--sh-2);
}

/* scaleX, not width: the fill is written every frame and a width write lays
 * the whole rail out again. A transform is composited. */
.hud-rail__fill {
  position: absolute;
  inset: 0;
  border-radius: inherit;
  background: linear-gradient(90deg, var(--c-cyan), var(--c-green));
  transform: scaleX(0);
  transform-origin: left center;
  will-change: transform;
}

.hud-rail__dot {
  position: absolute;
  top: 50%;
  width: 7px;
  height: 7px;
  margin: 0;
  border-radius: 50%;
  background: var(--c-ink-2);
  border: 1px solid var(--c-line-strong);
  transform: translate(-50%, -50%);
}

.hud-rail__cap {
  position: absolute;
  top: 50%;
  left: 100%;
  display: grid;
  place-items: center;
  width: 26px;
  height: 26px;
  border-radius: 50%;
  background: var(--c-butter);
  color: var(--c-ink);
  border: 2px solid var(--c-ink-2);
  transform: translate(-50%, -50%);
  --icon-size: 14px;
}

/* A full-width layer whose translateX percentage therefore resolves against
 * the TRACK's width, not the marker's. That is the whole trick: the marker can
 * ride the rail every frame without a single layout. */
.hud-rail__travel {
  position: absolute;
  inset: 0;
  transform: translateX(0);
  will-change: transform;
}

.hud-rail__mark {
  position: absolute;
  left: 0;
  top: 50%;
  display: grid;
  place-items: center;
  width: 24px;
  height: 24px;
  border-radius: 50%;
  background: var(--c-green);
  color: var(--c-ink);
  border: 2px solid var(--c-ink-2);
  box-shadow: var(--sh-1);
  transform: translate(-50%, -50%);
  --icon-size: 13px;
}

/* These two labels are the only text in the HUD with no card behind them, and
 * the bottom of the screen is where the sky is at its lightest pink. A drop
 * shadow is not enough there — they need a dark halo on all four sides or they
 * dissolve into the horizon. */
.hud-rail__label,
.hud-hint {
  text-shadow:
    0 1px 2px rgba(18, 14, 32, 0.8),
    0 0 7px rgba(18, 14, 32, 0.55);
}

.hud-rail__label { color: var(--c-text); }
.hud-rail__pct { color: var(--c-green); }

/* ---------------------------------------------------- legend + look hint */

.hud-legend {
  grid-area: bl;
  align-self: end;
  display: flex;
  flex-wrap: wrap;
  gap: var(--s-2);
  min-width: 0;
}

.hud-hint {
  grid-area: br;
  align-self: end;
  justify-self: end;
  text-align: right;
  color: var(--c-text-dim);
  min-width: 0;
}

/* ------------------------------------------------------------ countdown */

.hud-count {
  position: fixed;
  inset: 0;
  z-index: var(--z-overlay);
  display: grid;
  place-items: center;
  pointer-events: none;
  /* ⚠ The toast is also dead-centre, and the countdown fires at exactly the
   * moment the first toast is on screen — so centred-on-centred put a 120px
   * numeral straight through the middle of "Go, go, go!". Bottom padding lifts
   * the numeral off the toast band; it goes on the CONTAINER, not the numeral,
   * because the numeral's pop animation owns its own transform. */
  padding-bottom: 26vh;
}

.hud-count[hidden] { display: none; }

.hud-count__n {
  font-family: var(--display);
  font-size: var(--fs-display);
  font-weight: var(--fw-black);
  line-height: var(--lh-tight);
  letter-spacing: var(--tr-title);
  color: var(--c-cream);
  /* Four offsets rather than a stroke: -webkit-text-stroke thins the counters
   * of a rounded face at this size and the numeral goes hollow. */
  text-shadow:
    0 6px 0 var(--c-ink-2),
    3px 0 0 var(--c-ink-2),
    -3px 0 0 var(--c-ink-2),
    0 -3px 0 var(--c-ink-2);
}

/* The animation lives on its own class so restarting it (remove, reflow, add)
 * never strips the numeral of its type and colour for a frame. */
.hud-count__n.is-tick { animation: ps-pop-in 380ms var(--ease-pop); }

.hud-count.is-go .hud-count__n { color: var(--c-green); }

/* -------------------------------------------------------------- results */

.hud-results {
  position: fixed;
  inset: 0;
  z-index: var(--z-modal);
  display: grid;
  /* The scroll lives out here, not on the card: a card that scrolls its own
   * body clips the crown badge hanging over its top edge, because overflow-y
   * on its own quietly drags overflow-x along with it. */
  place-items: center;
  place-items: safe center;
  overflow: auto;
  padding: var(--gutter);
  background: rgba(18, 14, 32, 0.52);
  -webkit-backdrop-filter: blur(8px);
  backdrop-filter: blur(8px);
  pointer-events: auto;
  animation: ps-fade-in var(--dur-3) var(--ease-out);
}

.hud-results[hidden] { display: none; }

.hud-results__card {
  position: relative;
  width: min(430px, 100%);
  /* A grid item's automatic minimum is its min-content width, so ONE line in
   * here that refuses to wrap sets the floor for the whole card and it stops
   * fitting a 320px phone. Everything inside must be able to break. */
  min-width: 0;
  display: grid;
  gap: var(--s-3);
  justify-items: center;
  text-align: center;
  /* Room for the badge above and a matching breath below, so a short window
   * scrolls to something that still looks composed. */
  margin: 32px 0;
  animation: ps-rise-in var(--dur-3) var(--ease-pop);
}

/* Half on, half off the top edge. Sitting fully inside the card it reads as a
 * bullet point; hanging over the rim it reads as a badge. */
.hud-results__badge {
  position: absolute;
  top: -30px;
  left: 50%;
  transform: translateX(-50%);
  display: grid;
  place-items: center;
  width: 56px;
  height: 56px;
  border-radius: 50%;
  background: var(--c-butter);
  color: var(--c-ink);
  border: 3px solid var(--c-ink-2);
  box-shadow: var(--sh-2);
  --icon-size: 26px;
}

.hud-results.is-lost .hud-results__badge { background: var(--c-lilac); }

/* Wraps, because it is the longest unbreakable-looking line on the card and a
 * flex row does not wrap on its own. */
.hud-results__eyebrow {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: var(--s-2);
  margin-top: var(--s-3);
  --icon-size: 13px;
  color: var(--c-text-mute);
}

.hud-results__head {
  font-family: var(--display);
  font-size: var(--fs-3xl);
  text-transform: uppercase;
  color: var(--c-green);
  text-shadow: var(--sh-text);
}

.hud-results.is-lost .hud-results__head { color: var(--c-pink); }

.hud-results__sub {
  color: var(--c-text-dim);
  font-size: var(--fs-sm);
  max-width: 30ch;
}

.hud-results__stats {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: var(--s-2);
  width: 100%;
  margin-top: var(--s-1);
}

/* Two rows, the label's row flexible. "FINISH TIME" wraps to two lines where
 * "SPILLS" does not, and without this the three numbers sit on three different
 * baselines — which is the one thing a row of stat tiles must not do. */
.hud-stat {
  display: grid;
  grid-template-rows: 1fr auto;
  justify-items: center;
  gap: var(--s-1);
  padding: var(--s-3) var(--s-2);
  border-radius: var(--r-md);
  background: var(--c-surface-3);
  border: 1px solid var(--c-line);
  min-width: 0;
}

.hud-stat__k {
  align-self: start;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-wrap: wrap;
  gap: var(--s-1);
  --icon-size: 12px;
  color: var(--c-text-mute);
}

.hud-stat__v {
  font-size: var(--fs-lg);
  color: var(--c-text);
  line-height: 1.1;
}

.hud-results__best {
  color: var(--c-butter);
  min-height: 1.2em;
}

.hud-results__again { margin-top: var(--s-2); }

.hud-results__lobby {
  padding: var(--s-2) var(--s-3);
  color: var(--c-text-mute);
  font-size: var(--fs-sm);
  font-weight: var(--fw-mid);
  border-radius: var(--r-pill);
}

.hud-results__lobby:hover { color: var(--c-text); }

/* ============================================================ responsive */

/* The clock pill moves to its own row before the auto middle column can start
 * crushing the two flexible ones either side of it. */
@media (max-width: 680px) {
  .hud {
    /* Column 2 collapses to nothing: tl spans 1-2 and takes the slack, tr is
     * sized to its buttons. Neither can grow into the other. */
    grid-template-columns: minmax(0, 1fr) 0px auto;
    grid-template-rows: auto auto minmax(0, 1fr) auto auto;
    grid-template-areas:
      "tl  tl  tr"
      "tc  tc  tc"
      "mid mid mid"
      "bc  bc  bc"
      "bl  bl  br";
    gap: var(--s-3);
  }

  .hud-brand { --icon-size: 22px; }
  .hud-brand__name { font-size: var(--fs-md); }
  .hud-zone { padding: var(--s-2) var(--s-3); }
  .hud-zone__course { font-size: var(--fs-sm); }
  .hud-qual { padding: var(--s-2) var(--s-3); }
  .hud-qual__n { font-size: var(--fs-md); }
  .hud-toast { font-size: var(--fs-sm); padding: var(--s-2) var(--s-4); }
}

@media (max-width: 460px) {
  .hud { gap: var(--s-2); }
  .hud .btn--round { width: 36px; height: 36px; --icon-size: 17px; }
  .hud-btns { gap: var(--s-1); }
  .hud-clock { --icon-size: 16px; font-size: var(--fs-sm); padding: var(--s-1) var(--s-3); }
  .hud-zone__line,
  .hud-qual__still,
  .hud-hint { font-size: var(--fs-3xs); letter-spacing: var(--tr-wide); }
  .hud-rail__label { font-size: var(--fs-3xs); }
  .hud-results__card { padding: var(--s-5) var(--s-4); }
  .hud-results__stats { gap: var(--s-1); }
  .hud-stat { padding: var(--s-2) var(--s-1); }
  .hud-stat__v { font-size: var(--fs-md); }
  /* .btn--lg's 48px side padding plus a nowrap label is wider than a 320px
   * phone once the card's own padding is taken off. */
  .hud-results__again { padding: var(--s-3) var(--s-4); font-size: var(--fs-md); }
}

/* No keyboard, no keys to legend. It is the only panel that is pure noise on a
 * phone, and dropping it is what buys the rail its full width. */
@media (pointer: coarse) {
  .hud-legend { display: none; }
}

/* A short window (a landscape phone) has no room for a centre banner between
 * the top cards and the rail; let it overlap nothing by shrinking it. */
@media (max-height: 460px) {
  .hud-toast { padding: var(--s-2) var(--s-4); font-size: var(--fs-sm); }
  .hud-count__n { font-size: clamp(2.5rem, 14vh, 5rem); }
}
