/* Chunky arcade UI: big readable meters, minimal chrome (AGENTS.md 31 / 32). */

:root {
  --wood: #7a5230;
  --wood-dark: #4a3220;
  --cream: #f6ecd8;
  --water: #2f7fa8;
  --water-dark: #12212b;
  --good: #6fc47a;
  --warn: #e6c04a;
  --bad: #d95a4a;
  --enemy: #e0714f;
  --player: #6fc47a;
  --ui-font: 'Trebuchet MS', 'Segoe UI', system-ui, sans-serif;
}

* { box-sizing: border-box; }

html, body {
  margin: 0;
  height: 100%;
  background: var(--water-dark);
  color: var(--cream);
  font-family: var(--ui-font);
  overflow: hidden;
  user-select: none;
}

.shell { position: relative; width: 100vw; height: 100vh; }

canvas#game { display: block; width: 100%; height: 100%; outline: none; }

/* ------------------------------------------------------------------ screens */

.screen {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  justify-content: safe center;
  overflow-y: auto;
  gap: clamp(0.4rem, 1.6vh, 0.9rem);
  padding: clamp(0.5rem, 4vh, 2.4rem) 6vw;
  text-align: center;
  background: radial-gradient(circle at 50% 40%, rgba(18, 33, 43, 0.72), rgba(9, 17, 23, 0.94));
  backdrop-filter: blur(2px);
  z-index: 10;
}

.screen.wide {
  justify-content: flex-start;
  /* The panel itself does not scroll - the heading and the back button are
     pinned to it and only the grid between them moves. Scrolling the whole
     screen put the back button below the fold on a short window, so buying a
     roller meant scrolling past thirteen cards to find the way out. */
  overflow: hidden;
  padding-bottom: 2vh;
}
.screen.wide > h2,
.screen.wide > p { flex: 0 0 auto; }
/* The grid is the one part that gives: it takes whatever is left between the
   heading and the button, and scrolls only when even the smallest card size
   will not fit. `min-height: 0` is what allows a flex child to shrink below
   its content at all - without it the grid pushes the button off the panel. */
.screen.wide > .cards {
  flex: 1 1 auto;
  min-height: 0;
  width: 100%;
  overflow-y: auto;
  /* The grid starts under the heading and stays there, whatever room is left
     below it. Centring it in that leftover space was tried and moved the whole
     shelf down the screen on a tall window - the cards belong where they have
     always sat, and it is their size that answers the resolution. */
  align-content: flex-start;
  padding: 0.2rem 0.2rem 0.4rem;
}
/* The back button sits after the cards rather than over them. It was a sticky
   bar with a gradient behind it, which read as a black band across the bottom
   of every panel. */
.screen.wide > .menu.row {
  flex: 0 0 auto;
  width: 100%;
  margin-top: 1rem;
  padding: 0;
}

/* ------------------------------------------------------------- scroll bars */

/* Where a panel does have to scroll, the browser's own bar is a strip of
   Windows grey down the side of a wooden sign. This is the same bar in the
   game's colours: a dark groove with a cream slider in it, no arrow buttons,
   and narrow enough that it does not cost a column of cards.

   The split is not belt and braces. Chromium throws away every ::-webkit-
   rule for an element the moment that element also sets scrollbar-width or
   scrollbar-color, and falls back to its own thin bar - arrow buttons and all,
   which is what it did here. So the standard pair is fenced off behind a query
   that only an engine without ::-webkit-scrollbar answers, i.e. Firefox, and
   Chromium is left with the rules below. */
@supports not selector(::-webkit-scrollbar) {
  .screen.wide > .cards,
  .debug {
    scrollbar-width: thin;
    scrollbar-color: rgba(246, 236, 216, 0.45) rgba(9, 17, 23, 0.4);
  }
}
.screen.wide > .cards::-webkit-scrollbar,
.debug::-webkit-scrollbar { width: 0.6rem; }
/* the little step arrows at each end are chrome the game has nowhere else */
.screen.wide > .cards::-webkit-scrollbar-button,
.debug::-webkit-scrollbar-button { display: none; }
.screen.wide > .cards::-webkit-scrollbar-track,
.debug::-webkit-scrollbar-track {
  background: rgba(9, 17, 23, 0.4);
  border: 1px solid rgba(246, 236, 216, 0.14);
  border-radius: 0.3rem;
}
.screen.wide > .cards::-webkit-scrollbar-thumb,
.debug::-webkit-scrollbar-thumb {
  background: rgba(246, 236, 216, 0.42);
  border-radius: 0.3rem;
  /* the inset is what keeps the slider sitting *in* the groove rather than
     filling it edge to edge - it is drawn as a transparent border with the
     track showing through it */
  border: 2px solid transparent;
  background-clip: padding-box;
}
.screen.wide > .cards::-webkit-scrollbar-thumb:hover,
.debug::-webkit-scrollbar-thumb:hover { background: var(--cream); background-clip: padding-box; }
.screen.wide > .cards::-webkit-scrollbar-thumb:active,
.debug::-webkit-scrollbar-thumb:active { background: var(--warn); background-clip: padding-box; }

/* Every roller card is the same shape whatever the length of its name, so the
   grid reads as a grid rather than as a ragged pile.

   `--card` is the whole of the responsiveness. The portrait is square and the
   text under it is sized off the same number, so one clamp against the
   viewport height decides how much of the screen the shelf takes. */
.cards.portraits {
  /* Back to wrapping, and back to a 60rem shelf. At full size that is five
     rollers to a row over three rows, exactly the shape the screen has always
     had - the four-column grid it was tried as changed that shape at every
     window, and a fixed column count is what forced the roster to scroll on
     anything under 900px tall.

     Shrinking the cards on a short window is what replaces it: smaller cards
     wrap tighter, so the roster and the BACK button both stay on screen
     instead of the bottom row hiding below the fold. */
  --card: clamp(5.5rem, 14vh, 9.5rem);
  gap: clamp(0.45rem, 1.1vh, 1rem);
  max-width: min(60rem, 94vw);
}
.cards.portraits .card {
  width: var(--card);
  display: flex;
  flex-direction: column;
  padding: 0.5rem 0.6rem 0.7rem;
  text-align: center;
}
.cards.portraits .card h4 {
  font-size: clamp(0.66rem, 1.45vh, 0.92rem);
  line-height: 1.2;
  min-height: 2.4em;
  display: flex;
  align-items: center;
  justify-content: center;
  margin: 0 0 0.2rem;
}
.cards.portraits .card p { font-size: clamp(0.56rem, 1.15vh, 0.72rem); min-height: 2.2em; }
.cards.portraits .card .price {
  margin-top: auto;
  align-self: center;
  font-size: clamp(0.56rem, 1.15vh, 0.75rem);
  /* "110 chips" broken over two lines reads as two facts rather than one */
  white-space: nowrap;
}
.screen.intro { background: radial-gradient(circle at 50% 45%, rgba(18, 33, 43, 0.45), rgba(9, 17, 23, 0.8)); }
.hidden { display: none !important; }

.logo {
  font-size: clamp(2.4rem, min(11vw, 15vh), 7rem);
  line-height: 0.86;
  margin: 0;
  letter-spacing: 0.06em;
  color: var(--cream);
  text-shadow: 0 6px 0 var(--wood-dark), 0 10px 24px rgba(0, 0, 0, 0.6);
}
.logo span { display: block; color: var(--water); }

h2 {
  margin: 0;
  font-size: clamp(1.6rem, 5vw, 3rem);
  letter-spacing: 0.08em;
}
h3 { margin: 1.2rem 0 0.2rem; letter-spacing: 0.1em; opacity: 0.75; font-size: 1rem; }

.kicker { margin: 0; letter-spacing: 0.34em; font-size: 0.8rem; opacity: 0.7; }
.tagline { margin: 0; opacity: 0.8; }
.muted { opacity: 0.7; margin: 0.2rem 0; }
.footnote { font-size: 0.78rem; opacity: 0.55; margin-top: 0.6rem; }
.footnote:empty { display: none; }
.quote { font-style: italic; font-size: clamp(1rem, 2.6vw, 1.4rem); opacity: 0.9; max-width: 34ch; }

/* ------------------------------------------------------------------ buttons */

.menu { display: flex; flex-direction: column; gap: clamp(0.35rem, 1.1vh, 0.6rem); min-width: 15rem; }
.menu.row { flex-direction: row; flex-wrap: wrap; justify-content: center; }

button {
  font: inherit;
  font-weight: 700;
  letter-spacing: 0.12em;
  padding: clamp(0.45rem, 1.4vh, 0.75rem) 1.6rem;
  color: var(--water-dark);
  background: var(--cream);
  border: 0;
  border-bottom: 4px solid #b8a184;
  border-radius: 8px;
  cursor: pointer;
  transition: transform 0.08s ease, filter 0.15s ease;
}
button:hover { filter: brightness(1.08); }
button:active { transform: translateY(2px); }
button.ghost { background: transparent; color: var(--cream); border: 2px solid rgba(246, 236, 216, 0.4); }
button.danger { background: var(--bad); color: #fff; }
button:disabled { opacity: 0.4; cursor: not-allowed; }

/* -------------------------------------------------------------------- stats */

.stat-row { display: flex; gap: 2.4rem; }
.stat-row div { display: flex; flex-direction: column; }
.stat-row strong { font-size: 2rem; }
.stat-row small { opacity: 0.6; letter-spacing: 0.14em; font-size: 0.65rem; }

.results { display: grid; grid-template-columns: auto auto; gap: 0.3rem 1.6rem; font-size: 1.05rem; }
.results span:nth-child(odd) { opacity: 0.65; text-align: right; }
.results span:nth-child(even) { font-weight: 700; text-align: left; }

/* -------------------------------------------------------------------- cards */

.cards { display: flex; gap: 1rem; flex-wrap: wrap; justify-content: center; max-width: 60rem; }

.card {
  width: 15rem;
  padding: 1rem;
  background: rgba(246, 236, 216, 0.07);
  border: 2px solid rgba(246, 236, 216, 0.18);
  border-radius: 10px;
  cursor: pointer;
  text-align: left;
  color: var(--cream);
  transition: transform 0.1s ease, border-color 0.15s ease, background 0.15s ease;
}
.card:hover { transform: translateY(-4px); border-color: var(--cream); background: rgba(246, 236, 216, 0.14); }
.card h4 { margin: 0 0 0.35rem; font-size: 1.15rem; letter-spacing: 0.04em; }
.card p { margin: 0; font-size: 0.85rem; opacity: 0.78; line-height: 1.35; }
.card .rarity { display: inline-block; font-size: 0.62rem; letter-spacing: 0.18em; padding: 0.1rem 0.4rem; border-radius: 4px; margin-bottom: 0.4rem; }
.rarity.common { background: #6d7b83; }
.rarity.rare { background: #3f7fbf; }
.rarity.legendary { background: #c9922b; color: #241a05; }

/* What a thing costs, said in colour. Both shops sell across the same spread,
   so one scale covers rollers and skills alike and you can read the shelf
   without reading a single number. The name and the price carry it; the
   description stays cream, because that is the part you actually read. */
.card.tier-common h4 { color: #cfd8dc; }
.card.tier-rare h4 { color: #6fb2ee; }
.card.tier-ultra h4 { color: #c58cf0; }
.card.tier-legendary h4 { color: #e6c04a; }
.card.tier-rare .price { color: #6fb2ee; opacity: 0.95; }
.card.tier-ultra .price { color: #c58cf0; opacity: 0.95; }
.card.tier-legendary .price { color: #e6c04a; opacity: 0.95; }
/* ...and the border picks it up too, so the tier reads before the text does */
.card.tier-rare { border-color: rgba(111, 178, 238, 0.4); }
.card.tier-ultra { border-color: rgba(197, 140, 240, 0.42); }
.card.tier-legendary { border-color: rgba(230, 192, 74, 0.45); }
/* owned and equipped still win - they say what you can do, not what it costs */
.card.owned { border-color: var(--good); }
.card.equipped { border-color: var(--warn); }

.cards.small .card { width: 10.5rem; }
/* Descriptions run to different lengths, so without this the note and the
   price floated at whatever height the text above them happened to end, and a
   row of cards had its bottom two lines on five different baselines. Pinning
   them to the bottom edge lines the row up. */
.cards.small .card { display: flex; flex-direction: column; }
.cards.small .card > p:not(.what) { margin-top: auto; padding-top: 0.6rem; }
.card.owned { border-color: var(--good); }
.card.equipped { border-color: var(--warn); background: rgba(230, 192, 74, 0.14); }
.card.locked { opacity: 0.55; }
.card .price { display: block; margin-top: 0.45rem; font-size: 0.75rem; opacity: 0.8; }

/* ---------------------------------------------------------------------- HUD */

.hud { position: absolute; inset: 0; pointer-events: none; z-index: 5; }

.meters {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 1rem;
  padding: 1.6vh 2.4vw 0;
}

.meter { width: 32vw; max-width: 26rem; }
.meter-name { display: block; font-size: 0.8rem; letter-spacing: 0.2em; opacity: 0.85; margin-bottom: 0.3rem; }
.meter.enemy { text-align: right; }

.bar {
  height: 1.35rem;
  background: rgba(9, 17, 23, 0.65);
  border: 2px solid rgba(246, 236, 216, 0.35);
  border-radius: 4px;
  overflow: hidden;
}
.bar i {
  display: block;
  height: 100%;
  width: 100%;
  background: var(--player);
  transition: width 0.09s linear, background-color 0.2s ease;
}
.meter.enemy .bar i { background: var(--enemy); margin-left: auto; }
.bar i.low { background: var(--warn); }
.bar i.critical { background: var(--bad); animation: pulse 0.35s infinite alternate; }

@keyframes pulse { from { opacity: 0.6; } to { opacity: 1; } }

/* Everything the roller is carrying, under their bar: your passives (your
   actives are already in the hotbar with their cooldowns) and, for the rival,
   their signature ability too - being surprised by an ability you were never
   told they had is not difficulty, it is a missing HUD. */
/* Wraps rather than overflowing: a deep run ends with a dozen passives, and a
   row that runs off the side of the screen loses the last ones you picked. */
.buffs { display: flex; flex-wrap: wrap; gap: 0.3rem; margin-top: 0.35rem; min-height: 1.6rem; }
.meter.enemy .buffs { justify-content: flex-end; }
.buffs.empty { min-height: 0; margin-top: 0; }

.buff {
  position: relative;
  width: 1.6rem;
  height: 1.6rem;
  display: flex;
  align-items: center;
  justify-content: center;
  background: rgba(9, 17, 23, 0.72);
  border: 1px solid rgba(246, 236, 216, 0.3);
  border-radius: 5px;
  /* the HUD around it is pointer-events: none, so opt back in to be hoverable */
  pointer-events: auto;
  cursor: pointer;
  transition: border-color 0.12s ease, background 0.12s ease;
}
.buff .glyph { font-size: 0.95rem; line-height: 1; }
.buff:hover { border-color: var(--cream); background: rgba(30, 48, 60, 0.9); }
/* An active that is also down in the hotbar wears its key, so the two read as
   one skill in two places rather than as two skills. */
.buff .key {
  position: absolute;
  top: -4px;
  right: -2px;
  font-size: 0.55rem;
  font-weight: 700;
  color: var(--warn);
  text-shadow: 0 1px 2px #000;
}
/* How many copies of this skill you hold. Bottom left, so it never fights the
   hotbar key in the top right corner of the same pip. */
.buff .stack {
  position: absolute;
  bottom: -4px;
  left: -2px;
  font-size: 0.55rem;
  font-weight: 700;
  color: var(--good);
  text-shadow: 0 1px 2px #000;
}

/* a signature ability is a threat, not a stat - it gets the rival's colour */
.meter.enemy .buff.active { border-color: var(--enemy); }
.meter.player .buff.active { border-color: var(--warn); }

.center-info { display: flex; flex-direction: column; align-items: center; gap: 0.35rem; font-size: 0.85rem; letter-spacing: 0.16em; }

.spin { position: relative; width: 9rem; height: 0.5rem; background: rgba(9, 17, 23, 0.6); border: 2px solid rgba(246, 236, 216, 0.3); border-radius: 3px; }
.spin i { position: absolute; top: 0; bottom: 0; left: 50%; width: 0; background: var(--cream); transition: none; }
.spin b { position: absolute; top: -3px; bottom: -3px; left: 50%; width: 2px; background: rgba(246, 236, 216, 0.6); }

.rapids {
  position: absolute;
  top: 16vh;
  left: 50%;
  transform: translateX(-50%);
  font-size: clamp(1.4rem, 4vw, 2.6rem);
  font-weight: 800;
  letter-spacing: 0.3em;
  color: var(--bad);
  text-shadow: 0 3px 0 #401410;
  animation: shakeText 0.4s infinite alternate;
}
@keyframes shakeText { from { transform: translateX(-50%) rotate(-1.5deg); } to { transform: translateX(-50%) rotate(1.5deg); } }

.commentary {
  position: absolute;
  top: 26vh;
  left: 50%;
  transform: translateX(-50%);
  font-size: clamp(1.1rem, 3vw, 2rem);
  font-weight: 800;
  letter-spacing: 0.14em;
  opacity: 0;
  color: var(--warn);
  text-shadow: 0 3px 0 rgba(0, 0, 0, 0.5);
}
.commentary.show { animation: popIn 1.4s ease forwards; }
.commentary.enemy { color: var(--enemy); }
@keyframes popIn {
  0% { opacity: 0; transform: translateX(-50%) scale(0.6); }
  15% { opacity: 1; transform: translateX(-50%) scale(1.1); }
  30% { transform: translateX(-50%) scale(1); }
  80% { opacity: 1; }
  100% { opacity: 0; transform: translateX(-50%) translateY(-1.4rem); }
}

.countdown {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: clamp(4rem, 16vw, 11rem);
  font-weight: 800;
  letter-spacing: 0.05em;
  text-shadow: 0 8px 0 var(--wood-dark);
  pointer-events: none;
}
.countdown:empty { display: none; }

/* ----------------------------------------------------------------- tutorial */

.tutorial {
  position: absolute;
  left: 2.4vw;
  top: 50%;
  transform: translateY(-50%);
  width: min(19rem, 32vw);
  padding: 1rem 1.1rem;
  background: rgba(9, 17, 23, 0.82);
  border: 2px solid rgba(246, 236, 216, 0.28);
  border-left: 5px solid var(--warn);
  border-radius: 10px;
  animation: slideIn 0.3s ease;
}
.tutorial.done { border-left-color: var(--good); }

@keyframes slideIn {
  from { opacity: 0; transform: translate(-1.5rem, -50%); }
  to { opacity: 1; transform: translate(0, -50%); }
}

.tutorial-head { display: flex; align-items: baseline; gap: 0.6rem; margin-bottom: 0.45rem; }
.tutorial-step { font-size: 0.65rem; letter-spacing: 0.16em; opacity: 0.55; }
.tutorial h4 { margin: 0; font-size: 1rem; letter-spacing: 0.1em; color: var(--warn); }
.tutorial.done h4 { color: var(--good); }
.tutorial p {
  margin: 0 0 0.7rem;
  font-size: 0.85rem;
  line-height: 1.5;
  opacity: 0.88;
  /* the card is one block of prose now, so its paragraph breaks have to show */
  white-space: pre-line;
}

.tutorial-keys { display: flex; flex-wrap: wrap; gap: 0.35rem; margin-bottom: 0.7rem; }
.keycap {
  min-width: 1.9rem;
  padding: 0.22rem 0.45rem;
  text-align: center;
  font-size: 0.75rem;
  font-weight: 700;
  color: var(--water-dark);
  background: var(--cream);
  border-radius: 5px;
  border-bottom: 3px solid #b8a184;
}
.keycap.wide { min-width: 3.6rem; }

.tutorial-progress {
  height: 0.35rem;
  background: rgba(9, 17, 23, 0.7);
  border-radius: 3px;
  overflow: hidden;
}
.tutorial-progress i {
  display: block;
  height: 100%;
  width: 0;
  background: var(--warn);
  transition: width 0.1s linear;
}
.tutorial.done .tutorial-progress i { background: var(--good); width: 100% !important; }

@media (max-width: 820px) {
  .tutorial { top: auto; bottom: 9rem; transform: none; width: min(17rem, 46vw); animation: none; }
}

.abilities {
  position: absolute;
  bottom: 3vh;
  left: 50%;
  transform: translateX(-50%);
  display: flex;
  gap: 0.8rem;
}
/* A square with the icon in it and its key in the top right corner - the shape
   every game with a hotbar has used for twenty years, because it reads at a
   glance without being looked at. */
.ability {
  position: relative;
  width: 3.4rem;
  height: 3.4rem;
  display: flex;
  align-items: center;
  justify-content: center;
  background: rgba(9, 17, 23, 0.72);
  border: 2px solid rgba(246, 236, 216, 0.35);
  border-radius: 8px;
  overflow: hidden;
}
.ability .glyph { font-size: 1.7rem; line-height: 1; }
/* The square is a button: it presses in, so a click reads as having landed
   even on the frame where the skill was still on cooldown and did nothing. */
.ability:active,
.buff.firable:active { transform: translateY(1px); }
/* The HUD around it is pointer-events: none so clicks reach the canvas, so each
   square has to opt back in or it never sees the pointer and never explains
   itself. */
.ability {
  pointer-events: auto;
  cursor: pointer;
  transition: border-color 0.12s ease, background 0.12s ease;
}
.ability:hover { border-color: var(--cream); background: rgba(30, 48, 60, 0.85); }

/* What the skill under the pointer actually does. The browser's own tooltip is
   too slow to appear and too easy to lose to be any use during a match. */
.skillTip {
  position: absolute;
  transform: translateX(-50%);
  z-index: 8;
  display: flex;
  gap: 0.6rem;
  align-items: flex-start;
  /* Shrink-to-fit would measure the gap between the panel and the right edge of
     the screen, so a pip in the corner got a one-word-per-line sliver. Size it
     on its own content instead and let the clamp in showSkillTip slide it back
     on screen. */
  width: max-content;
  max-width: min(20rem, 80vw);
  padding: 0.6rem 0.75rem;
  background: rgba(9, 17, 23, 0.95);
  border: 2px solid rgba(246, 236, 216, 0.3);
  border-radius: 8px;
  text-align: left;
  pointer-events: none;
}
.skillTip.hidden { display: none; }
.skillTip .tipGlyph { font-size: 1.5rem; line-height: 1.1; }
.skillTip .tipBody { display: flex; flex-direction: column; gap: 0.2rem; }
.skillTip b { font-size: 0.9rem; letter-spacing: 0.06em; color: var(--warn); }
.skillTip i { font-style: normal; font-size: 0.8rem; opacity: 0.85; line-height: 1.35; }
.skillTip .tipMeta {
  font-style: normal;
  font-size: 0.65rem;
  letter-spacing: 0.14em;
  opacity: 0.6;
  margin-top: 0.15rem;
}

/* Skill cards lead with the icon, then say what the skill actually does -
   a name alone tells you nothing about whether you want it. */
/* A fixed box for the icon, not a line of text. Emoji vary in height, so a
   card whose icon happened to be tall pushed its title further down than its
   neighbour's and the row of names came out on four different baselines. */
.card .cardGlyph {
  display: block;
  height: 2.6rem;
  font-size: 2.2rem;
  line-height: 2.6rem;
  margin-bottom: 0.35rem;
}
.card .what {
  margin: 0 0 0.45rem;
  font-size: 0.78rem;
  opacity: 0.9;
  line-height: 1.35;
}
.card:not(:disabled) { cursor: pointer; }
.card:disabled { cursor: not-allowed; }
.ability .key {
  position: absolute;
  top: -1px;
  right: 2px;
  font-size: 0.72rem;
  font-weight: 800;
  color: var(--warn);
  text-shadow: 0 1px 2px #000;
}
/* the name sits under the square, out of the way of the icon */
.ability .name {
  position: absolute;
  top: 100%;
  left: 50%;
  transform: translateX(-50%);
  margin-top: 0.2rem;
  font-size: 0.6rem;
  letter-spacing: 0.08em;
  opacity: 0.75;
  white-space: nowrap;
}
.ability .cd {
  position: absolute;
  inset: 0;
  background: rgba(9, 17, 23, 0.78);
  transform-origin: top;
}
.ability.flash { animation: flash 0.3s ease; }
@keyframes flash { from { background: rgba(230, 192, 74, 0.8); } to { background: rgba(9, 17, 23, 0.65); } }

/* ----------------------------------------------------------------- settings */

.settings { display: flex; flex-direction: column; gap: 0.7rem; min-width: 18rem; }
.settings label { display: flex; justify-content: space-between; align-items: center; gap: 1rem; letter-spacing: 0.08em; }
input[type='range'] { accent-color: var(--water); width: 9rem; }
select { font: inherit; padding: 0.2rem 0.4rem; border-radius: 4px; border: 0; }

/* -------------------------------------------------------------------- debug */

.debug {
  position: absolute;
  top: 1rem;
  right: 1rem;
  width: 17rem;
  max-height: 90vh;
  overflow-y: auto;
  padding: 0.8rem;
  background: rgba(9, 17, 23, 0.92);
  border: 1px solid rgba(246, 236, 216, 0.25);
  border-radius: 8px;
  font-size: 0.75rem;
  z-index: 20;
}
.debug h4 { margin: 0 0 0.6rem; letter-spacing: 0.14em; }
.debug h4 small { opacity: 0.5; font-weight: 400; }
.debug label { display: flex; justify-content: space-between; align-items: center; gap: 0.5rem; margin-bottom: 0.35rem; }
.debug input[type='range'] { width: 8rem; }
.debug .row { display: flex; flex-wrap: wrap; gap: 0.3rem; margin-top: 0.6rem; }
.debug button { padding: 0.35rem 0.6rem; font-size: 0.7rem; border-radius: 5px; }
.debug .readout { font-family: 'Consolas', monospace; opacity: 0.75; line-height: 1.5; margin-top: 0.6rem; white-space: pre; }

@media (max-width: 720px) {
  .meter { width: 38vw; }
  .cards .card { width: 12rem; }
  .stat-row { gap: 1.2rem; }
}

/* While a tutorial step is being read the fight is frozen and everything but
   the panel is dimmed, so the eye has one place to go. */
.tutorial-scrim {
  position: absolute;
  inset: 0;
  background: rgba(6, 8, 14, 0.62);
  z-index: 5;
  pointer-events: none;
  transition: opacity 0.18s ease;
}
.tutorial-scrim.hidden { display: none; }

/* the panel and its button sit above the scrim, at full strength */
.tutorial { z-index: 6; }

.tutorial-continue {
  position: absolute;
  left: 50%;
  bottom: 2.4rem;
  transform: translateX(-50%);
  z-index: 6;
  padding: 0.65rem 2.4rem;
  font: inherit;
  font-size: 0.85rem;
  letter-spacing: 0.18em;
  color: #10141c;
  background: var(--warn);
  border: 0;
  border-radius: 0.3rem;
  cursor: pointer;
  box-shadow: 0 0.4rem 0 rgba(0, 0, 0, 0.35);
  /* The HUD it lives in is pointer-events: none so clicks reach the canvas.
     This button is the one thing in there that has to be clickable. */
  pointer-events: auto;
}
.tutorial-continue:hover { filter: brightness(1.12); }
.tutorial-continue:active { transform: translateX(-50%) translateY(0.2rem); box-shadow: 0 0.2rem 0 rgba(0, 0, 0, 0.35); }
.tutorial-continue.hidden { display: none; }

/* The characters screen is a shop, so the cards are portraits first and text
   second - you buy a roller by looking at them, not by reading a name. */
.cards.portraits .card {
  width: var(--card);
  padding-top: 0.5rem;
}
.card .portrait {
  display: block;
  width: 100%;
  aspect-ratio: 1;
  object-fit: cover;
  border-radius: 0.25rem;
  margin-bottom: clamp(0.25rem, 0.6vh, 0.5rem);
  image-rendering: auto;
}
/* A locked roller is shown, not hidden - you should be able to see what the
   chips are for. Greyed and dimmed reads as "not yet" rather than "missing". */
.card.locked .portrait {
  filter: grayscale(0.85) brightness(0.6);
}
.card.locked:not(:disabled):hover .portrait {
  filter: grayscale(0.35) brightness(0.85);
}
