/* Drops Gummy Regatta — base shell styles. Comic/cel-shaded visual target:
   dark diagonal-hatch HUD panels, Formiga display headings, Work Sans body,
   ink (#101828) as the outline/UI ink color. Later tasks add gameplay UI
   inside #hud / #menus / #touchUI without touching this file's structure. */

@font-face {
  font-family: "Formiga";
  src: url("../assets/fonts/Formiga-Bold.woff2") format("woff2"),
       url("../assets/fonts/Formiga-Bold.woff") format("woff");
  font-weight: 700; font-style: normal; font-display: swap;
}
@font-face {
  font-family: "Work Sans";
  src: url("../assets/fonts/worksans_n4.woff2") format("woff2"),
       url("../assets/fonts/worksans_n4.woff") format("woff");
  font-weight: 400; font-style: normal; font-display: swap;
}

html, body {
  margin: 0; height: 100%; overflow: hidden;
  background: #101828;
  font-family: "Work Sans", "Avenir Next", "Segoe UI", system-ui, sans-serif;
  font-weight: 400; color: #101828;
  touch-action: none; overscroll-behavior: none; -webkit-user-select: none; user-select: none;
}

h1, h2, h3, .heading {
  font-family: "Formiga", "Avenir Next", "Segoe UI", system-ui, sans-serif;
  font-weight: 700;
}

canvas#c { display: block; touch-action: none; }

/* Full-viewport overlay containers. Empty for now — later tasks populate
   and manage display on these; keep them non-interactive by default so the
   canvas underneath stays clickable/draggable until UI actually needs it. */
#hud, #menus, #touchUI {
  position: fixed; inset: 0; pointer-events: none; user-select: none;
}
/* Above #blackout (z-index 9) — a positioned element with z-index:auto paints
   below one with a z-index whatever the DOM order says, and the EATEN summary
   has to come up OUT of the dark rather than behind it. */
#menus { z-index: 10; }

/* Dark diagonal-hatch panel — reusable HUD/menu background. Repeating
   thin ink stripes over a near-black base, comic-book shading style. */
.panel {
  background-color: #171f2e;
  background-image: repeating-linear-gradient(
    45deg,
    rgba(255, 255, 255, 0.05) 0px,
    rgba(255, 255, 255, 0.05) 2px,
    transparent 2px,
    transparent 10px
  );
  border: 2px solid #101828;
  border-radius: 12px;
  color: #f5f7fa;
  box-shadow: 0 4px 18px rgba(16, 24, 40, 0.45);
}

#dev {
  position: fixed; left: 8px; bottom: 8px; z-index: 10;
  color: #7be8b0; font: 12px/1.5 monospace;
  background: rgba(16, 24, 40, 0.75); padding: 6px 9px; border-radius: 6px;
  pointer-events: none; white-space: pre;
}

.hidden { display: none !important; }

/* ---------- touch controls (js/input.js) ----------
   #touchUI stays display:none until js/input.js confirms TOUCH (real touch
   device or ?touch), then adds .active. Individual controls opt back into
   pointer-events since the #touchUI container itself stays none so it never
   blocks canvas drags on non-touch layouts that happen to load the module. */
#touchUI { display: none; }
#touchUI.active { display: block; }

/* SAFE AREA — every fixed edge offset below is wrapped in max(designed-gap,
   env(safe-area-inset-*)) so the thumb controls clear a notch, a home
   indicator or a rounded corner on a modern phone instead of sitting half
   under it. `env()` resolves to 0px on anything without insets (and on a
   browser that doesn't know the function the whole max() is dropped, falling
   back to the plain value in the shorthand above it), so this costs nothing
   on desktop. Landscape is the case that actually bites: the notch lands on
   the LEFT or RIGHT rail, exactly where the joystick and the button stack
   live. Note index.html must ship `viewport-fit=cover` for the insets to be
   non-zero — it does. */
#joyBase {
  position: fixed; left: 22px; bottom: 22px; width: 124px; height: 124px;
  left: max(22px, env(safe-area-inset-left));
  bottom: max(22px, env(safe-area-inset-bottom));
  border-radius: 50%; pointer-events: auto; touch-action: none;
  background: radial-gradient(circle, rgba(255, 255, 255, 0.16), rgba(255, 255, 255, 0.05) 70%);
  border: 2px solid #101828; box-shadow: 0 4px 18px rgba(16, 24, 40, 0.45);
}
#joyKnob {
  position: absolute; left: 50%; top: 50%; width: 56px; height: 56px;
  margin: -28px 0 0 -28px; border-radius: 50%; pointer-events: none;
  background: linear-gradient(135deg, #f5f7fa, #d8e0ea);
  border: 2px solid #101828; box-shadow: 0 2px 12px rgba(16, 24, 40, 0.4);
}

.touchBtn {
  position: fixed; z-index: 5; width: 68px; height: 68px; border-radius: 50%;
  pointer-events: auto; touch-action: none; cursor: pointer;
  display: flex; align-items: center; justify-content: center;
  font-size: 26px; line-height: 1; color: #f5f7fa;
  background-color: #171f2e;
  background-image: repeating-linear-gradient(
    45deg,
    rgba(255, 255, 255, 0.08) 0px,
    rgba(255, 255, 255, 0.08) 2px,
    transparent 2px,
    transparent 10px
  );
  border: 2px solid #101828; box-shadow: 0 4px 18px rgba(16, 24, 40, 0.45);
  transition: transform 0.08s ease;
}
.touchBtn.pressed { transform: scale(0.9); }

/* Edge offsets go through max(..., env(safe-area-inset-*)) — see the note
   above #joyBase. #btnEnd stacks 94px above #btnJump, so its bottom offset
   adds the same inset rather than taking the larger of the two (which would
   collapse the gap between the two buttons on an inset device). */
#btnJump {
  right: 26px; bottom: 34px; width: 78px; height: 78px; font-size: 30px;
  right: max(26px, env(safe-area-inset-right));
  bottom: max(34px, env(safe-area-inset-bottom));
}
#btnMenu {
  right: 20px; top: 20px;
  right: max(20px, env(safe-area-inset-right));
  top: max(20px, env(safe-area-inset-top));
}
#btnEnd {
  right: 26px; bottom: 128px;
  right: max(26px, env(safe-area-inset-right));
  bottom: calc(94px + max(34px, env(safe-area-inset-bottom)));
  --hold: 0;
}
#btnEnd::before {
  content: ""; position: absolute; inset: -4px; border-radius: 50%; z-index: -1;
  background: conic-gradient(#ffcf4d calc(var(--hold, 0) * 360deg), transparent 0deg);
}

/* Per-state touch controls. js/game.js writes #touchUI's data-state on every
   state change. Hidden with opacity + pointer-events rather than display:none
   ON PURPOSE: a finger already holding #btnEnd when the hold completes (which
   changes state) must still receive its touchend on that element, and a
   display:none element never does — the action would stay stuck down. */
#touchUI:not([data-state="play"]) #joyBase,
#touchUI:not([data-state="play"]) #btnJump,
#touchUI:not([data-state="play"]) #btnEnd,
#touchUI[data-state="menu"] #btnMenu,
#touchUI[data-state="summary"] #btnMenu,
/* Task 14 fix (mobile pass): the flavor log is 11 tiles, so #pauseScreen's
   .screenPanel (max-height: calc(100vh - 48px), see below) runs nearly the
   full viewport height on a phone in EITHER orientation — there is no clear
   corner left for a floating button to sit in without landing on top of the
   grid (confirmed in-browser at both 375x812 and 812x375: the panel's own
   bounding box overlapped the bottom-left corner completely in both). The
   panel already has its own RESUME button reachable by tap/scroll, so the
   floating ☰ is pure redundancy here — simplest correct fix is not to show
   it, rather than chase a repositioning that has no safe spot to land in. */
#touchUI[data-state="paused"] #btnMenu {
  opacity: 0; pointer-events: none;
}

/* Touch HUD layout. The thumb controls own the bottom-right corner (jump +
   END) and the top-right is the gummy counter, so on touch the speed dial
   moves up under the counter and ☰ moves to the left rail under the logo.
   `body.touch` is set by js/input.js when it activates #touchUI. */
body.touch #speedDial { top: 74px; bottom: auto; }
/* The ☰ moves to the left rail on touch, so it takes the LEFT inset here (the
   base rule's right inset no longer applies once right:auto). */
body.touch #btnMenu {
  left: 18px; top: 60px; right: auto;
  left: max(18px, env(safe-area-inset-left));
  top: calc(40px + max(20px, env(safe-area-inset-top)));
}
body.touch #padIndicator { left: 96px; top: 72px; }

/* ---------- blackout (rev 2026-08-02: the POV shark attack) ----------
   Ink, not pure black, so the dip matches the outline color the whole game is
   drawn with. NO transition by default: js/game.js drives the opacity from the
   game clock frame by frame, so a CSS transition would both smear the timing
   and keep animating through a pause. `.lift` adds the one transition that IS
   wanted — the summary coming up out of the dark. `.on` is what takes pointer
   events, so a fully transparent overlay never eats a click. */
#blackout {
  position: fixed; inset: 0; z-index: 9; background: #05070d;
  opacity: 0; pointer-events: none;
}
#blackout.on { pointer-events: auto; }
#blackout.lift { transition: opacity 0.5s ease; }

#padDebug {
  position: fixed; left: 8px; top: 8px; z-index: 10; max-width: 44ch;
  font: 12px/1.5 monospace; padding: 8px 10px; pointer-events: none;
  white-space: pre-wrap;
}

/* WebGL context-loss overlay (built by js/game.js — it's the one panel that
   can't live in index.html, since it must be creatable after the renderer is
   already dead). Sits above everything, and is the only overlay in the game
   that takes pointer events unconditionally: by the time it is up, nothing
   else on screen does anything. */
#ctxLost {
  position: fixed; left: 50%; top: 50%; transform: translate(-50%, -50%);
  z-index: 50; width: min(420px, calc(100vw - 48px)); padding: 22px 24px;
  text-align: center; pointer-events: auto;
}
#ctxLost .heading { font-size: 26px; letter-spacing: 0.02em; margin-bottom: 10px; }
#ctxLost p {
  margin: 0 0 18px; font-size: 15px; line-height: 1.5; color: #c8d2e0;
}
#ctxLost .menuBtn { display: block; }

#padToast {
  position: fixed; left: 50%; top: 18px; transform: translate(-50%, -12px);
  z-index: 20; padding: 8px 16px; font: 14px/1.4 "Work Sans", sans-serif;
  pointer-events: none; opacity: 0; transition: opacity 0.2s ease, transform 0.2s ease;
}
#padToast.show { opacity: 1; transform: translate(-50%, 0); }

/* ---------- gameplay HUD (js/ui.js) ---------- */
#hudLogo {
  position: fixed; left: 18px; top: 16px; height: 34px; width: auto;
  filter: drop-shadow(0 2px 6px rgba(16, 24, 40, 0.5));
}

#padIndicator {
  position: fixed; left: 18px; top: 60px; width: 36px; height: 36px;
  border-radius: 50%; display: flex; align-items: center; justify-content: center;
  font-size: 18px;
}

/* Top-right cluster: [volume] [gummy counter]. One flex row so the button sits
   beside a counter whose width changes with the digit count, and so the pair
   takes the safe-area insets once. */
#hudTopRight {
  position: fixed; right: 18px; top: 16px;
  right: max(18px, env(safe-area-inset-right));
  top: max(16px, env(safe-area-inset-top));
  display: flex; align-items: stretch; gap: 10px;
}

#gummyCounter {
  display: flex; align-items: baseline; gap: 8px;
  padding: 10px 16px; pointer-events: none;
}

/* Volume button — the one always-visible-on-the-HUD control (rev 2026-08-02).
   #hud is pointer-events:none, so this opts back in for itself. 44px is the
   minimum comfortable touch target and matches the counter's own height, so
   the row reads as one unit. */
#btnVolume {
  pointer-events: auto; cursor: pointer; touch-action: manipulation;
  width: 44px; min-height: 44px; padding: 0;
  display: flex; align-items: center; justify-content: center;
  font-size: 20px; line-height: 1;
  font-family: inherit;
  transition: transform 0.1s ease, opacity 0.15s ease;
}
#btnVolume:hover { transform: scale(1.06); }
#btnVolume:active { transform: scale(0.92); }
/* Muted reads as "off", not "broken": the glyph already says it, this just
   takes the panel down to the same dimmed register the locked flavor tiles
   use so a glance across the HUD lands on it. */
#btnVolume[data-level="0"] { opacity: 0.55; }
#gummyCounterLabel {
  font-family: "Formiga", "Avenir Next", "Segoe UI", system-ui, sans-serif;
  font-weight: 700; font-size: 13px; letter-spacing: 0.08em;
}
#gummyCounterEmoji { font-size: 15px; }
#gummyCount {
  font-family: "Formiga", "Avenir Next", "Segoe UI", system-ui, sans-serif;
  font-weight: 700; font-size: 24px; min-width: 1.4ch; text-align: right;
  transform-origin: center; display: inline-block;
}
#gummyCount.bounce { animation: gummyBounce 0.32s cubic-bezier(0.34, 1.56, 0.64, 1); }
@keyframes gummyBounce {
  0% { transform: scale(1); }
  40% { transform: scale(1.45); }
  100% { transform: scale(1); }
}

#gummyToast {
  position: fixed; left: 50%; bottom: 88px; transform: translate(-50%, 12px);
  display: flex; align-items: center; gap: 12px; padding: 10px 18px;
  opacity: 0; transition: opacity 0.25s ease, transform 0.25s ease; pointer-events: none;
  max-width: 86vw;
}
#gummyToast.show { opacity: 1; transform: translate(-50%, 0); }
#toastSwatch {
  width: 26px; height: 26px; border-radius: 50%; flex: none;
  border: 2px solid #101828; box-shadow: inset 0 0 0 2px rgba(255, 255, 255, 0.35);
}
#toastCopy { display: flex; flex-direction: column; line-height: 1.25; white-space: nowrap; }
#toastName {
  font-family: "Formiga", "Avenir Next", "Segoe UI", system-ui, sans-serif;
  font-weight: 700; font-size: 14px; letter-spacing: 0.03em;
}
#toastQuip { font-size: 13px; color: #b9c4d0; font-style: italic; }

/* ===== Flavor Frenzy toast (rev 2026-08-01) =====
   The normal toast's louder sibling: sits above it, scales in with a bit of
   overshoot, then shimmers for the rest of its 2.5s. Kept off the normal
   toast's rules entirely (rather than as a .frenzy modifier) so nothing here
   can regress the one that fires on every single collect. */
#frenzyToast {
  position: fixed; left: 50%; bottom: 152px;
  display: flex; align-items: center; gap: 14px; padding: 12px 24px;
  opacity: 0; pointer-events: none; max-width: 92vw;
  border-color: rgba(247, 197, 30, 0.85);
  box-shadow: 0 0 0 2px rgba(247, 197, 30, 0.25), 0 10px 30px rgba(0, 0, 0, 0.35);
  /* THE RESTING TRANSFORM IS THE *SETTLED* POSE, not the small one frenzyPop
     starts from. An animation's `forwards` fill only applies while the
     animation itself does, so the instant `.show` is stripped the animation
     stops holding anything and the transform falls back to whatever this rule
     says — with scale(0.6) here the toast visibly snapped small and *then*
     faded (observed). Matching this to frenzyPop's 100% keyframe means the
     fade-out has nothing to snap: only opacity changes. */
  transform: translate(-50%, 0) scale(1);
  transition: opacity 0.3s ease;
}
#frenzyToast.show {
  opacity: 1;
  animation: frenzyPop 0.42s cubic-bezier(0.2, 1.5, 0.5, 1) forwards,
             frenzyShimmer 0.9s ease-in-out 0.42s 2;
}
@keyframes frenzyPop {
  0% { transform: translate(-50%, 8px) scale(0.6) rotate(-4deg); }
  55% { transform: translate(-50%, 0) scale(1.12) rotate(2deg); }
  75% { transform: translate(-50%, 0) scale(0.97) rotate(-1deg); }
  100% { transform: translate(-50%, 0) scale(1) rotate(0deg); }
}
/* Shimmer, not a shake: the toast is already doing a lot, and a wobbling
   block of text at the bottom of the screen is hard to read. */
@keyframes frenzyShimmer {
  0%, 100% { box-shadow: 0 0 0 2px rgba(247, 197, 30, 0.25), 0 10px 30px rgba(0, 0, 0, 0.35); }
  50% { box-shadow: 0 0 0 5px rgba(247, 197, 30, 0.5), 0 10px 34px rgba(0, 0, 0, 0.4); }
}
#frenzySwatch {
  width: 34px; height: 34px; border-radius: 8px; flex: none;
  border: 2px solid #101828; box-shadow: inset 0 0 0 2px rgba(255, 255, 255, 0.4);
  animation: frenzySwatchSpin 1.4s ease-in-out infinite;
}
/* The swatch is a little cube now, so it gets to wiggle like one. */
@keyframes frenzySwatchSpin {
  0%, 100% { transform: rotate(-8deg) scale(1); }
  50% { transform: rotate(8deg) scale(1.1); }
}
/* `nowrap` is on the two short lines individually, NOT on the column: the quip
   is a whole sentence, and inheriting nowrap from here pushed the longest one
   (~446px at 13px) straight out through the panel's 92vw cap on a 375px phone,
   where only ~249px of copy width is available beside the swatch. */
#frenzyCopy { display: flex; flex-direction: column; line-height: 1.22; }
#frenzyTitle {
  font-family: "Formiga", "Avenir Next", "Segoe UI", system-ui, sans-serif;
  font-weight: 700; font-size: 13px; letter-spacing: 0.18em; color: #f7c51e;
  white-space: nowrap;
}
#frenzyLine {
  font-family: "Formiga", "Avenir Next", "Segoe UI", system-ui, sans-serif;
  font-weight: 700; font-size: 19px; letter-spacing: 0.03em;
  white-space: nowrap;
}
/* Wraps, and is centred so a two-line quip reads as one balanced block under
   the headline rather than as a ragged tail. 240px is inside the ~249px the
   narrowest supported phone leaves for copy, so the panel never overflows. */
#frenzyQuip {
  font-size: 13px; color: #b9c4d0; font-style: italic;
  max-width: 240px; text-align: center;
}

#speedDial {
  position: fixed; right: 18px; bottom: 22px; width: 128px;
  padding: 10px 12px 8px; display: flex; flex-direction: column; align-items: center;
  pointer-events: none;
}
#speedSvg { width: 100%; height: auto; overflow: visible; }
#speedSvg .dialTrack { fill: none; stroke: rgba(245, 247, 250, 0.25); stroke-width: 5; stroke-linecap: round; }
/* Rotation center is set via the SVG `transform="rotate(deg 50 52)"`
   attribute in js/ui.js's setSpeed(), not CSS transform-origin. */
#speedNeedle { stroke: #ef4b5d; stroke-width: 3; stroke-linecap: round; }
#speedSvg .dialHub { fill: #f5f7fa; }
#speedReadout {
  font-family: "Formiga", "Avenir Next", "Segoe UI", system-ui, sans-serif;
  font-weight: 700; margin-top: -4px;
}
#speedValue { font-size: 20px; }
#speedUnit { font-size: 11px; margin-left: 3px; color: #b9c4d0; font-family: "Work Sans", sans-serif; font-weight: 400; }

/* End-run hold ring (keyboard/pad mirror of the touch #btnEnd ring). The
   dash offset is written by js/ui.js's setEndHold(); the -90deg rotation puts
   the fill's start at 12 o'clock. */
#endHold {
  position: fixed; left: 50%; bottom: 24px; transform: translateX(-50%);
  display: flex; align-items: center; gap: 10px; padding: 8px 16px 8px 10px;
  pointer-events: none;
}
#endHold svg { width: 42px; height: 42px; transform: rotate(-90deg); }
#endHold .endTrack { fill: none; stroke: rgba(245, 247, 250, 0.2); stroke-width: 5; }
#endRing {
  fill: none; stroke: #ffcf4d; stroke-width: 5; stroke-linecap: round;
  stroke-dasharray: 125.66; stroke-dashoffset: 125.66;
}
#endHoldLabel {
  font-family: "Formiga", "Avenir Next", system-ui, sans-serif; font-weight: 700;
  font-size: 13px; letter-spacing: 0.06em;
}

/* Small transient line for menu/run asides ("changed your mind?"). */
#hudNote {
  position: fixed; left: 50%; top: 74px; transform: translate(-50%, -10px);
  padding: 8px 16px; font-size: 14px; opacity: 0; pointer-events: none;
  transition: opacity 0.2s ease, transform 0.2s ease; max-width: 80vw; text-align: center;
}
#hudNote.show { opacity: 1; transform: translate(-50%, 0); }

/* ---------- menus / pause / summary (js/ui.js `menus`) ----------
   #menus itself stays pointer-events:none (see the shared rule above); each
   .screen opts back in only while it is the visible one, so the canvas keeps
   receiving drags in states with no screen up. */
.screen {
  position: fixed; inset: 0; pointer-events: auto; overflow-y: auto;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 18px; padding: 24px; box-sizing: border-box; color: #f5f7fa;
}
#pauseScreen, #summaryScreen { background: rgba(16, 24, 40, 0.72); }
/* The vehicle-select screen deliberately has NO scrim: the three craft are
   real meshes idling on the water behind it and should stay fully visible. */

.screen h1, .screen h2, .screen h3 {
  font-family: "Formiga", "Avenir Next", system-ui, sans-serif; font-weight: 700;
  margin: 0; letter-spacing: 0.04em;
}
.screen .sub { margin: 0; font-size: 14px; color: #b9c4d0; font-style: italic; }
/* The vehicle-select screen has no scrim behind it, so its copy needs its own
   ink halo to stay legible against bright water. */
#menuScreen .sub, .menuHint { color: #f5f7fa; text-shadow: 0 1px 0 #101828, 0 2px 8px rgba(16, 24, 40, 0.9); }
.screenPanel {
  padding: 22px 26px; max-width: min(860px, 94vw); width: 100%;
  display: flex; flex-direction: column; align-items: center; gap: 10px;
  max-height: calc(100vh - 48px); overflow-y: auto;
}

/* Focus is ours, not the browser's: every focusable carries role="button"
   tabindex="-1" and js/ui.js toggles .focused, so keyboard/pad/touch all move
   the same highlight and Enter can never double-fire a DOM-focused button. */
.focused {
  outline: 3px solid #ffcf4d; outline-offset: 3px;
  box-shadow: 0 0 0 3px rgba(255, 207, 77, 0.25), 0 6px 22px rgba(16, 24, 40, 0.5);
}

.menuBtn {
  font-family: "Formiga", "Avenir Next", system-ui, sans-serif; font-weight: 700;
  font-size: 15px; letter-spacing: 0.06em; cursor: pointer;
  padding: 11px 20px; border-radius: 10px; border: 2px solid #101828;
  background: #22304a; color: #f5f7fa; user-select: none; white-space: nowrap;
}
.menuBtn:hover { background: #2c3d5c; }
.btnRow { display: flex; flex-wrap: wrap; gap: 10px; justify-content: center; margin: 6px 0 2px; }

/* ---- vehicle select ---- */
#menuTitleBlock { display: flex; flex-direction: column; align-items: center; gap: 2px; text-align: center; padding-top: 4px; }
#menuLogo { height: 40px; width: auto; filter: drop-shadow(0 2px 6px rgba(16, 24, 40, 0.6)); }
#menuTitle { font-size: clamp(34px, 7vw, 62px); line-height: 1; text-shadow: 0 3px 0 #101828, 0 6px 20px rgba(16, 24, 40, 0.6); }
/* Title at the top, cards at the bottom, nothing in between: the middle band
   of the screen is left clear for the three craft idling on the water behind
   this screen (js/game.js's MENU_CAM_* frames them into exactly that gap). */
#menuScreen { justify-content: space-between; gap: 10px; }
/* max-width keeps the card row from sprawling on a wide monitor; width:100%
   is what stops it overflowing a narrow one (the row is a flex item of this
   column, so without it the cards size the column instead of the reverse). */
#menuBottom { display: flex; flex-direction: column; align-items: center; gap: 10px; width: 100%; max-width: 820px; }

#craftCards { display: flex; gap: 14px; flex-wrap: wrap; justify-content: center; }
.craftCard {
  /* border-box so the 224 is the card's real footprint — with content-box the
     padding and border push each card to 260 and the row of three wraps. */
  box-sizing: border-box;
  width: 224px; padding: 14px 16px; cursor: pointer;
  display: flex; flex-direction: column; gap: 4px;
  transition: transform 0.12s ease;
}
.craftCard.focused { transform: translateY(-6px); }
.craftName {
  font-family: "Formiga", "Avenir Next", system-ui, sans-serif; font-weight: 700;
  font-size: 19px; letter-spacing: 0.04em;
}
.craftQuip { font-size: 12px; color: #b9c4d0; font-style: italic; min-height: 2.6em; line-height: 1.3; }
.statRow { display: flex; align-items: baseline; justify-content: space-between; gap: 10px; }
.statLabel {
  font-family: "Formiga", "Avenir Next", system-ui, sans-serif; font-weight: 700;
  font-size: 11px; letter-spacing: 0.1em; color: #b9c4d0;
}
.stars { color: #ffcf4d; font-size: 14px; letter-spacing: 2px; }
.menuHint { margin: 0 0 4px; font-size: 13px; color: #d3dbe6; }

/* ---- flavor log ---- */
.logHeading { font-size: 18px; margin-top: 8px; }
#flavorGrid {
  display: grid; grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 8px; width: 100%; margin-top: 6px;
}
.flavorTile {
  display: flex; align-items: center; gap: 9px; padding: 8px 10px;
  border: 2px solid #101828; border-radius: 10px; background: #1d2740; cursor: pointer;
}
.flavorTile.locked { background: #141c2c; color: #55627a; }
.tileSwatch {
  width: 20px; height: 20px; border-radius: 50%; flex: none; border: 2px solid #101828;
  box-shadow: inset 0 0 0 2px rgba(255, 255, 255, 0.3);
}
.flavorTile.locked .tileSwatch { background: #101828; box-shadow: none; }
.tileCopy { display: flex; flex-direction: column; line-height: 1.25; min-width: 0; }
.tileName {
  font-family: "Formiga", "Avenir Next", system-ui, sans-serif; font-weight: 700;
  font-size: 12px; letter-spacing: 0.03em; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.tileEffect { font-size: 11px; color: #90a0b6; }
.flavorTile.locked .tileEffect { color: #48546b; }
.tileCounts { font-size: 11px; color: #ffcf4d; }
.flavorTile.locked .tileCounts { color: #55627a; font-style: italic; }
.flavorTile.pulse { animation: tilePulse 0.35s ease; }
@keyframes tilePulse {
  0% { transform: scale(1); }
  45% { transform: scale(1.07); }
  100% { transform: scale(1); }
}

/* ---- summary ---- */
#summaryTitle { font-size: clamp(26px, 5vw, 40px); }
#summaryStats { display: flex; gap: 28px; margin: 10px 0 4px; flex-wrap: wrap; justify-content: center; }
.statBlock { display: flex; flex-direction: column; align-items: center; }
.statBig {
  font-family: "Formiga", "Avenir Next", system-ui, sans-serif; font-weight: 700; font-size: 30px;
}
.statCap { font-size: 11px; letter-spacing: 0.1em; color: #90a0b6; text-transform: uppercase; }
#summaryBars { width: 100%; display: flex; flex-direction: column; gap: 5px; margin: 4px 0; }
.barRow { display: grid; grid-template-columns: 118px 1fr 34px; align-items: center; gap: 10px; }
.barName { font-size: 12px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.barTrack { background: rgba(245, 247, 250, 0.12); border-radius: 6px; height: 14px; overflow: hidden; }
.barFill { display: block; height: 100%; border-radius: 6px; min-width: 3px; }
.barCount {
  font-family: "Formiga", "Avenir Next", system-ui, sans-serif; font-weight: 700;
  font-size: 13px; text-align: right;
}
#summaryBest { margin: 6px 0 0; font-size: 15px; font-style: italic; color: #ffcf4d; text-align: center; }
#leaderboardMount:empty { display: none; }

/* ---- leaderboard (Task 12, js/leaderboard.js) ----
   Statically positioned throughout, per the warning above #leaderboardMount
   in index.html: layoutRows() in this file groups focusables into nav rows
   by offsetTop relative to #summaryScreen, so a position:relative/absolute
   wrapper anywhere in here would silently desync pad/keyboard nav. */
#leaderboardMount { width: 100%; }
.lbPanel {
  width: 100%; display: flex; flex-direction: column; align-items: center;
  gap: 8px; margin: 6px 0 2px; padding-top: 10px;
  border-top: 2px dashed rgba(245, 247, 250, 0.15);
}
.lbHeading { font-size: 18px; margin: 0; }
.lbSub { margin: 0; font-size: 13px; color: #b9c4d0; font-style: italic; text-align: center; }
.lbList { width: 100%; display: flex; flex-direction: column; gap: 3px; margin: 4px 0; }
.lbRow {
  display: grid; grid-template-columns: 24px 1fr 52px 46px; align-items: center; gap: 8px;
  padding: 5px 8px; border-radius: 8px; font-size: 12px;
}
.lbRow:nth-child(odd) { background: rgba(245, 247, 250, 0.04); }
.lbRank { font-family: "Formiga", "Avenir Next", system-ui, sans-serif; font-weight: 700; color: #90a0b6; }
.lbName { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; letter-spacing: 0.03em; }
.lbScore { font-family: "Formiga", "Avenir Next", system-ui, sans-serif; font-weight: 700; text-align: right; }
.lbTime { font-size: 10px; color: #90a0b6; text-align: right; }
.lbRowMine {
  background: rgba(255, 207, 77, 0.2) !important;
  outline: 2px solid #ffcf4d; outline-offset: -2px;
}
.lbRowMine .lbName { color: #ffcf4d; }

.lbEntry { width: 100%; display: flex; flex-direction: column; align-items: center; gap: 8px; margin-top: 4px; }
.lbInputRow { display: flex; gap: 8px; flex-wrap: wrap; justify-content: center; }
.lbInput {
  font-family: "Formiga", "Avenir Next", system-ui, sans-serif; font-weight: 700;
  font-size: 15px; letter-spacing: 0.08em; text-transform: uppercase;
  padding: 10px 14px; border-radius: 10px; border: 2px solid #101828;
  background: #1d2740; color: #f5f7fa; width: 200px; max-width: 60vw;
}
.lbInput:focus { outline: 3px solid #ffcf4d; outline-offset: 2px; }
.lbSaveBtn { padding: 11px 18px; }
.lbPreview {
  font-family: "Formiga", "Avenir Next", system-ui, sans-serif; font-weight: 700;
  font-size: 15px; letter-spacing: 0.12em; color: #ffcf4d; min-height: 1.4em;
}
.lbGrid { display: grid; grid-template-columns: repeat(9, minmax(28px, 1fr)); gap: 6px; width: 100%; }
.lbKey {
  display: flex; align-items: center; justify-content: center;
  font-family: "Formiga", "Avenir Next", system-ui, sans-serif; font-weight: 700;
  font-size: 13px; padding: 8px 4px; border-radius: 8px; border: 2px solid #101828;
  background: #1d2740; cursor: pointer; user-select: none;
}
.lbKeyAction { background: #22304a; color: #ffcf4d; font-size: 11px; }
.lbKeyOk { background: #2f6b4f; }
.lbKeyWide { grid-column: span 2; font-size: 10px; letter-spacing: 0.04em; }
.lbFeedback { min-height: 1.2em; margin: 0; font-size: 12px; color: #ffcf4d; text-align: center; }
.lbError { margin: 4px 0 0; font-size: 12px; color: #ef4b5d; font-style: italic; text-align: center; }
.lbMemorial {
  margin: 6px 0 0; font-family: "Formiga", "Avenir Next", system-ui, sans-serif; font-weight: 700;
  font-size: 15px; color: #ffcf4d; text-align: center;
}
.lbMemorialFoot { margin: 0; font-size: 11px; color: #90a0b6; font-style: italic; text-align: center; }

@media (max-width: 620px) {
  .lbGrid { grid-template-columns: repeat(7, minmax(24px, 1fr)); }
  .lbRow { grid-template-columns: 20px 1fr 44px 38px; font-size: 11px; }
}

@media (max-width: 620px) {
  #flavorGrid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .barRow { grid-template-columns: 92px 1fr 30px; }
  /* Narrow screens: the cards STAY a single row of three. Letting them wrap
     into a stack fills the whole viewport and hides the three craft idling
     behind them, which is most of what the title screen is for — so the cards
     shrink instead and the quip (the one purely decorative line) drops out. */
  #menuTitle { font-size: clamp(26px, 9vw, 40px); }
  #craftCards { gap: 7px; width: 100%; flex-wrap: nowrap; }
  .craftCard { width: auto; flex: 1 1 0; min-width: 0; padding: 8px 7px; gap: 2px; overflow: hidden; }
  .craftQuip { display: none; }
  .craftName { font-size: 12px; letter-spacing: 0; white-space: nowrap; }
  .statRow { gap: 4px; }
  .statLabel { font-size: 8px; letter-spacing: 0.04em; }
  .stars { font-size: 9px; letter-spacing: 0; }
  .menuHint { font-size: 10px; }
}
