/* Tidelands — coastal / Japanese-Scandinavian minimal. Mobile-browser-first.
   Design priority: AIRY. Big tap targets, generous spacing, uncluttered. */

/* ── THEME ─────────────────────────────────────────────────────
   Two palettes, one stylesheet. DARK is the default (:root). LIGHT is opted in
   via <html data-theme="light">. Everything below reads these variables, so a
   theme is just a set of values — no duplicated rules.
   The stat chip on a tile stays a light chip with dark numbers in BOTH themes,
   so all the earlier legibility/contrast work (v12–v14) carries over verbatim;
   only surfaces, text, terrain tints, ownership and accents change per theme. */
:root {
  /* theme-independent */
  --radius: 18px;
  --radius-sm: 12px;
  --gap: 16px;
  --tap: 48px;

  /* ── DARK (default) — calm coastal night: deep slate, soft contrast ── */
  --bg1: #0f171e;
  --bg2: #0a1015;
  --panel: #182530;
  --panel-2: #21313f;
  --ink: #e7eef3;
  --muted: #93a4b1;
  --line: #2c3d4a;
  --accent: #46b3a6;
  --accent-ink: #86d8cd;
  --accent-rgb: 70, 179, 166;
  --shadow: 0 6px 20px rgba(0, 0, 0, 0.40);
  --shadow-lg: 0 14px 34px rgba(0, 0, 0, 0.52);

  /* solid faction accents (cost pips, stripes, dots) — read on dark cards */
  --land: #5b8c5a; --water: #3d84b8; --fire: #d9694b;
  --city: #b08968; --animals: #c9a227; --neutral: #94a0ac;

  /* terrain TINT overlays — lifted + a touch stronger so they read on dark */
  --tint-land: #79ad78; --tint-water: #5fa0d6; --tint-fire: #e08872;
  --tint-city: #cc9f7c; --tint-animals: #d6ba58; --tint-neutral: #8493a0;
  --terrain-op: 0.26; --terrain-op-neutral: 0.15;

  /* ownership — brightness backbone holds: yours LIGHTER than the dark board,
     theirs DARKER; hue stays blue-vs-terracotta (colour-blind safe) */
  --own-bg: #26394a; --own-border: #5b93cf;
  --enemy-bg: #241a17; --enemy-border: #d3745a; --enemy-scrim: rgba(0, 0, 0, 0.22);

  --star: #8fdccf; --star-halo: rgba(0, 0, 0, 0.55);
  --danger: #e57c65;
  --lock: #d9a862;
  --bar-bg: rgba(18, 28, 37, 0.92);
  --overlay-bg: rgba(0, 0, 0, 0.58);
  /* primary button: a MUTED teal (not the glary accent) with a bright label */
  --btn-bg: #2b7d71;
  --btn-fg: #f3fffb;
  /* terrain/faction emoji on tiles: solid + a soft light halo so even the dark
     glyphs (paw, city) separate from the dark board */
  --ic-op: 0.95;
  --ic-glow: drop-shadow(0 0 1.4px rgba(255,255,255,0.85)) drop-shadow(0 0 0.5px rgba(255,255,255,0.7));
}

/* ── LIGHT — the original airy coastal day palette ── */
:root[data-theme="light"] {
  --bg1: #f2f7f8;
  --bg2: #e7eef0;
  --panel: #ffffff;
  --panel-2: #f7fafb;
  --ink: #2b3640;
  --muted: #6f7c88;
  --line: #e3eaec;
  --accent: #2f9e93;
  --accent-ink: #1d6f67;
  --accent-rgb: 47, 158, 147;
  --shadow: 0 6px 20px rgba(40, 70, 80, 0.08);
  --shadow-lg: 0 12px 34px rgba(40, 70, 80, 0.14);

  --land: #5b8c5a; --water: #3d84b8; --fire: #d9694b;
  --city: #b08968; --animals: #c9a227; --neutral: #94a0ac;

  --tint-land: #5b8c5a; --tint-water: #3d84b8; --tint-fire: #d9694b;
  --tint-city: #b08968; --tint-animals: #c9a227; --tint-neutral: #94a0ac;
  --terrain-op: 0.16; --terrain-op-neutral: 0.08;

  --own-bg: #eef5fb; --own-border: #3d72a4;
  --enemy-bg: #e7d5cf; --enemy-border: #c15f4c; --enemy-scrim: rgba(96, 52, 42, 0.10);

  --star: #1d6f67; --star-halo: rgba(255, 255, 255, 0.9);
  --danger: #b1493a;
  --lock: #9a6b34;
  --bar-bg: rgba(255, 255, 255, 0.92);
  --overlay-bg: rgba(30, 45, 52, 0.42);
  --btn-bg: #2f9e93;
  --btn-fg: #ffffff;
  --ic-op: 0.55;
  --ic-glow: none;
}

* { box-sizing: border-box; -webkit-tap-highlight-color: transparent; }
html, body { margin: 0; padding: 0; }
/* The ROOT gets the theme background so the iOS overscroll/rubber-band region and
   the safe-area insets (notch / home indicator) are the theme colour, never the
   browser-default white. Both html and body are painted; body carries the
   gradient, html a matching solid so any overscroll beyond body is still dark. */
html {
  background: var(--bg1);
  min-height: 100%;
}
body {
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
  font-size: 17px;
  line-height: 1.45;
  color: var(--ink);
  background: linear-gradient(160deg, var(--bg1), var(--bg2));
  background-color: var(--bg2);
  min-height: 100vh;
  -webkit-font-smoothing: antialiased;
}
#app {
  max-width: 620px;
  margin: 0 auto;
  padding: max(16px, env(safe-area-inset-top)) 16px calc(24px + env(safe-area-inset-bottom));
  min-height: 100vh;
}

/* ── Type & headings ─────────────────────────────────────────── */
h1, h2, h3 { margin: 0; font-weight: 650; letter-spacing: -0.01em; }
.title { font-size: 30px; letter-spacing: 0.02em; }
.subtitle { color: var(--muted); font-size: 15px; margin-top: 4px; }
.muted { color: var(--muted); }
.center { text-align: center; }

/* ── Top bar ─────────────────────────────────────────────────── */
.topbar {
  display: flex; align-items: center; gap: 12px;
  margin-bottom: 7px; min-height: var(--tap);
}
.topbar .spacer { flex: 1; }
.back {
  display: inline-flex; align-items: center; justify-content: center;
  min-width: var(--tap); min-height: var(--tap); border-radius: var(--radius-sm);
  background: var(--panel); box-shadow: var(--shadow); border: none;
  font-size: 20px; color: var(--ink); cursor: pointer;
}
.pill {
  background: var(--panel); box-shadow: var(--shadow); border-radius: 999px;
  padding: 8px 14px; font-size: 14px; font-weight: 600; color: var(--accent-ink);
}

/* ── Buttons ─────────────────────────────────────────────────── */
button { font-family: inherit; font-size: 16px; }
.btn {
  display: flex; align-items: center; justify-content: center; gap: 8px;
  width: 100%; min-height: 54px; border: none; border-radius: var(--radius);
  background: var(--panel); color: var(--ink); box-shadow: var(--shadow);
  font-size: 17px; font-weight: 600; cursor: pointer; padding: 0 18px;
  transition: transform .06s ease;
}
.btn:active { transform: scale(0.985); }
.btn.primary { background: var(--btn-bg); color: var(--btn-fg); box-shadow: var(--shadow-lg); }
.btn.ghost { background: transparent; box-shadow: none; border: 1.5px solid var(--line); }
.btn.danger { color: var(--danger); }
.btn.small { min-height: var(--tap); font-size: 15px; width: auto; padding: 0 16px; }
.btn-row { display: flex; gap: 12px; }
.btn-row .btn { width: auto; flex: 1; }

.stack { display: flex; flex-direction: column; gap: 14px; }
.stack-lg { display: flex; flex-direction: column; gap: 20px; }

/* ── Home ────────────────────────────────────────────────────── */
.hero { text-align: center; padding: 28px 0 22px; }
.hero .title { font-size: 40px; }
.hero .wave { font-size: 40px; }
.menu { display: flex; flex-direction: column; gap: 14px; margin-top: 8px; }
.menu .btn { justify-content: space-between; }
.menu .btn .lead { display: flex; align-items: center; gap: 12px; }
.menu .btn .ic { font-size: 22px; }
.menu .btn .sub { font-size: 13px; color: var(--muted); font-weight: 500; }
.chev { color: var(--muted); font-size: 20px; }

/* ── Lists / cards ───────────────────────────────────────────── */
.card-surface { background: var(--panel); border-radius: var(--radius); box-shadow: var(--shadow); padding: 18px; }
.list { display: flex; flex-direction: column; gap: 12px; }
.row-item {
  display: flex; align-items: center; gap: 14px; width: 100%;
  background: var(--panel); border: none; border-radius: var(--radius);
  box-shadow: var(--shadow); padding: 14px 16px; min-height: 64px; cursor: pointer; text-align: left;
}
.row-item .num {
  width: 40px; height: 40px; flex: none; border-radius: 12px; display: grid; place-items: center;
  background: var(--panel-2); font-weight: 700; color: var(--accent-ink);
}
.row-item .grow { flex: 1; }
.row-item .name { font-weight: 600; }
.row-item .meta { font-size: 13px; color: var(--muted); }
.row-item.locked { opacity: 0.5; }
.row-item .status-ic { font-size: 20px; }
.row-item .bestpill {
  flex: 0 0 auto; font-size: 11px; font-weight: 700; color: var(--accent-ink);
  background: var(--panel-2); border: 1px solid var(--line); border-radius: 999px;
  padding: 2px 9px; white-space: nowrap;
}

/* ── Puzzle / game board ─────────────────────────────────────── */
/* NEVER wrap: a wrapped HUD pushed the board down and cost a row of tiles.
   The row is nowrap and the labels are allowed to shrink instead. */
.hud {
  display: flex; align-items: center; gap: 10px; flex-wrap: nowrap;
  background: var(--panel); border-radius: var(--radius); box-shadow: var(--shadow);
  padding: 6px 12px; margin-bottom: 6px;   /* slimmer HUD → more room for the board */
}
.hud .stat { display: flex; flex-direction: column; line-height: 1.05; }
.hud .stat b { font-size: 16px; }
.hud .stat { min-width: 0; }
.hud .stat span { font-size: clamp(9px, 2.6vw, 11px); color: var(--muted); text-transform: uppercase;
  letter-spacing: .03em; white-space: nowrap; }
.hud .stat b { white-space: nowrap; }
.hud .flow b { color: var(--water); }
/* Next turn's income, shown right on the Flow figure. It is derived live from
   incomeFor(), so capturing a tile visibly bumps it the moment it happens. */
.hud .inc {
  font-style: normal; font-weight: 700; font-size: 11px; margin-left: 3px;
  color: var(--accent-ink); vertical-align: 2px; letter-spacing: -.01em;
  white-space: nowrap;
}
.hud .obj b { color: var(--accent-ink); }

.board {
  /* Tiles are capped so a 3x3 doesn't blow up to 110px and push the hand off
     screen, and the cap also shrinks with available height so the HUD + board +
     hand fit together. Floor keeps every tile comfortably tappable.
     --cols/--rows are set inline per level by app.js. */
  --gapv: clamp(5px, 1.8vw, 10px);
  --tile-cap: clamp(44px, calc((100vh - 540px) / var(--rows, 5)), 90px);
  display: grid; gap: var(--gapv); margin: 2px auto 10px;
  width: 100%;
  max-width: calc(var(--cols, 5) * var(--tile-cap) + (var(--cols, 5) - 1) * var(--gapv));
  touch-action: manipulation;
}
@supports (height: 100svh) {
  .board { --tile-cap: clamp(44px, calc((100svh - 540px) / var(--rows, 5)), 90px); }
}
.tile {
  /* NO min-height: a min-height plus aspect-ratio forced a min WIDTH larger than
     the grid track on 6-column boards, overflowing the board. The square now
     always matches its column exactly. container-type lets the numbers inside
     scale to the TILE (cqw) instead of the viewport. */
  position: relative; aspect-ratio: 1 / 1; border-radius: 14px; border: 1.5px solid var(--line);
  background: var(--panel); cursor: pointer;
  overflow: hidden; min-height: 0; min-width: 0;
  container-type: inline-size;
  /* THREE ZONES, so nothing can ever land on top of anything else:
       row 1  top band     — terrain icon (left) + objective star (right)
       row 2  the middle   — the stat block, and ONLY the stat block
       row 3  bottom band  — keyword badges (left) + wall-trait badge (right)
     The corner glyphs are absolutely positioned into the bands; the stat block
     is a grid item pinned to row 2, so it physically cannot reach a corner.
     Bands scale with the viewport (a container cannot size itself in cqw). */
  --band: clamp(11px, 3.3vw, 16px);
  display: grid; grid-template-rows: var(--band) 1fr var(--band);
  justify-items: center;
}
.tile .terrain { position: absolute; inset: 0; opacity: var(--terrain-op); }
.tile.t-land .terrain { background: var(--tint-land); }
.tile.t-water .terrain { background: var(--tint-water); }
.tile.t-fire .terrain { background: var(--tint-fire); }
.tile.t-city .terrain { background: var(--tint-city); }
.tile.t-animals .terrain { background: var(--tint-animals); }
.tile.t-neutral .terrain { background: var(--tint-neutral); opacity: var(--terrain-op-neutral); }
/* Corner glyphs live in the bands and scale with the tile. */
.tile .terrain-ic {
  position: absolute; top: 1px; left: 4px; z-index: 2; line-height: 1;
  font-size: clamp(8px, 17cqw, 12px); opacity: var(--ic-op); filter: var(--ic-glow);
}

/* ── OWNERSHIP — blue = yours, terracotta = theirs, grey = nobody. ──────────
   The old cue was a single thin border colour, and its "yours" teal was the
   SAME hue as the actionable highlight — so "mine" and "I can act here" looked
   identical, and the enemy pink washed into warm terrain tints. Ownership now
   reads pre-attentively from THREE redundant channels, so it survives on top of
   every terrain tint and holds up for colour-blind players:
     • hue     cool steel-blue (ally) vs warm terracotta (hostile) — a
               colourblind-SAFE pairing: they separate on the blue–yellow axis
               and in luminance, unlike a red/green pairing
     • bright  your tiles read LIGHT and airy; enemy tiles read visibly DARKER
     • weight  owned & enemy carry a bold 2.5px frame; neutral stays a thin 1.5px
   Teal is now reserved EXCLUSIVELY for the "you can act here" highlight below,
   so ownership and actionability can never be confused again. */
.tile.own {
  border-color: var(--own-border); border-width: 2.5px;
  background: var(--own-bg);            /* yours: lighter than the board */
}
.tile.enemy {
  border-color: var(--enemy-border); border-width: 2.5px;
  background: var(--enemy-bg);          /* theirs: darker/warmer than the board */
}
/* Keep owned airy and push enemy heavier, on top of whatever terrain tint the
   tile already carries. A terrain-independent warm scrim guarantees every enemy
   tile is darker than every owned tile even when the terrains differ. */
.tile.own .terrain   { opacity: 0.12; }
.tile.enemy .terrain { opacity: 0.22; }
.tile.enemy::before {
  content: ""; position: absolute; inset: 0; z-index: 0; pointer-events: none;
  background: var(--enemy-scrim);      /* consistent enemy darkening */
}
.tile.obj { box-shadow: inset 0 0 0 2px rgba(var(--accent-rgb), .35); }
.tile.obj::after {
  content: "★"; position: absolute; top: 1px; right: 4px; z-index: 2; line-height: 1;
  font-size: clamp(9px, 18cqw, 12px); color: var(--star); opacity: 1;
  text-shadow: 0 1px 2px var(--star-halo);
}
/* Once YOU own an objective tile it counts toward the win and can never revert,
   so the "still to take" star is pure clutter — drop it. The star stays on
   objective tiles you do NOT yet own (enemy/neutral), which is the real signal
   and exactly what the "Objectives left" HUD counts. Display-only. */
.tile.own.obj::after { content: none; }
.tile.target { border-color: var(--accent); box-shadow: 0 0 0 3px rgba(var(--accent-rgb), .35); animation: pulse 1.1s infinite; }
.tile.sel { box-shadow: 0 0 0 3px rgba(var(--accent-rgb), .6); border-color: var(--accent); }
@keyframes pulse { 0%,100%{ box-shadow: 0 0 0 3px rgba(var(--accent-rgb), .30);} 50%{ box-shadow: 0 0 0 6px rgba(var(--accent-rgb), .12);} }

.piece {
  grid-row: 2; align-self: center;              /* never enters a band */
  position: relative; z-index: 1; display: grid; place-items: center; gap: 0;
  padding: 1px 4px; border-radius: 9px; max-width: 100%; min-width: 0;
}
/* Both pieces get a solid backing so the numbers never sit on the terrain tint.
   Unit = cool white, wall = warm off-white with a red hairline: you can tell
   which is which at a glance without reading anything. */
.piece.unit {
  background: rgba(255,255,255,.94); box-shadow: 0 1px 3px rgba(0,0,0,.14);
  border: 1px solid rgba(var(--accent-rgb), .30);
}
.piece.defender {
  background: rgba(255,251,249,.94); box-shadow: 0 1px 3px rgba(0,0,0,.14);
  border: 1px solid rgba(177,73,58,.30);
}
.piece.rested { opacity: .55; }
/* Stat lines never wrap and never outgrow the tile. Icons are deliberately
   smaller than the digits — emoji are the width hog (Apple Color Emoji is much
   wider than the digits), which is what clipped two-digit Guards on 6x6. */
.piece .pg { font-weight: 800; line-height: 1.05; white-space: nowrap; max-width: 100%; letter-spacing: -.01em; color: #23303a;
  font-size: clamp(12px, 4.2vw, 18px); }
.piece .pw { font-weight: 800; line-height: 1.05; white-space: nowrap; max-width: 100%; color: #b1493a;
  font-size: clamp(9px, 2.6vw, 12px); }
.piece .ic { font-size: .72em; opacity: .85; }
.piece .nm { font-size: 9px; color: #6a7784; max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* On six-wide boards there is no room for a name under the numbers — drop it
   rather than crush the stats. Long-press still shows the full detail. */
@container (max-width: 58px) { .piece .nm { display: none; } }
/* Guard is the number you must beat — dark and primary. The counterattack is
   red and secondary. They were both the same red before, which is half of why
   a wall tile read as a smudge. */
.piece.defender .pg { color: #24333d; }
.piece.defender .pw { color: #b1493a; }
/* Scale the on-tile type to the TILE, so a 6x6 board shrinks text automatically
   and two-digit values always fit. Falls back to the vw clamps above. */
@supports (container-type: inline-size) {
  .piece .pg { font-size: clamp(10px, 26cqw, 18px); }
  .piece .pw { font-size: clamp(7.5px, 15cqw, 11px); }
  .piece .nm { font-size: clamp(6px, 11cqw, 9px); }
}
.piece .faction-dot { position: absolute; top: -3px; right: -3px; width: 10px; height: 10px; border-radius: 50%; }

/* ── Hand ────────────────────────────────────────────────────── */
.hand-wrap { position: sticky; bottom: 0; padding-top: 4px; }
.handhead { text-align: right; font-size: 11.5px; color: var(--muted); padding: 0 2px 3px; letter-spacing: .01em; }
.handhead b { color: var(--ink); font-weight: 800; }
/* BETA: the six-card hand is a 3×2 grid (two rows of three) — no scrolling. Cards
   are wider (⅓ width) than the old single row, so they read more clearly. The
   sorted order (most-expensive-affordable first) flows left-to-right, then wraps
   to the second row. */
.hand {
  display: grid; grid-template-columns: repeat(3, 1fr); gap: 6px; padding: 4px 1px 8px;
}
.hcard {
  min-width: 0; min-height: 84px; border-radius: 12px; background: var(--panel);
  box-shadow: var(--shadow); border: 2px solid transparent; padding: 7px 9px; cursor: pointer;
  display: flex; flex-direction: column; gap: 3px;
}
.hcard.sel { border-color: var(--accent); box-shadow: var(--shadow-lg); transform: translateY(-3px); }
.hcard.unafford { opacity: .5; }
.hcard .top { display: flex; align-items: center; justify-content: space-between; }
.hcard .cost { width: 24px; height: 24px; border-radius: 50%; background: var(--water); color: #fff; font-weight: 800; display: grid; place-items: center; font-size: 14px; }
.hcard .fac { font-size: 15px; }
.hcard .cname { font-size: 12.5px; font-weight: 650; line-height: 1.12; overflow: hidden; }
.hcard .cbody { margin-top: auto; }
.hcard .cpg { font-weight: 800; font-size: 14px; }
.hcard .ctext { font-size: 10.5px; color: var(--muted); line-height: 1.2; overflow: hidden; }
/* Two star tracks, each on its own line; marker + label + 5 stars never wrap apart. */
.meta.stars { display: flex; flex-direction: column; gap: 1px; margin-top: 2px; }
.stars .track { display: inline-flex; align-items: center; gap: 4px; white-space: nowrap; }
.stars .track .lbl { font-size: 9px; text-transform: uppercase; letter-spacing: .04em; color: var(--muted); min-width: 20px; }
.stars .track b { letter-spacing: 1.5px; color: var(--accent-ink, var(--accent)); font-size: 12.5px; font-weight: 700; }

/* ── Level-clear (win) result summary ─────────────────────────── */
.winstats {
  margin-top: 16px; padding: 14px 16px; border-radius: var(--radius-sm);
  background: var(--panel-2); border: 1.5px solid var(--line);
  display: flex; flex-direction: column; gap: 10px; text-align: center;
}
.winstats .wcoast { font-size: 13px; font-weight: 700; color: var(--accent-ink, var(--accent)); letter-spacing: .01em; }
.winstats .wstars { display: flex; justify-content: center; gap: 22px; }
.winstats .wstars .track { display: inline-flex; align-items: center; gap: 5px; white-space: nowrap; }
.winstats .wstars .track .lbl { font-size: 9px; text-transform: uppercase; letter-spacing: .04em; color: var(--muted); }
.winstats .wstars .track b { letter-spacing: 2px; color: var(--star); font-size: 15px; }
.winstats .wturns { font-size: 15px; color: var(--ink); }
.winstats .wturns b { color: var(--accent-ink, var(--accent)); }
.winstats .wbest { display: flex; flex-direction: column; gap: 3px; font-size: 12.5px; color: var(--muted); }
.winstats .wbest b { color: var(--ink); font-weight: 700; }
.winstats .newbest { font-style: normal; font-size: 11px; font-weight: 800; color: var(--accent); letter-spacing: .02em; }
.hcard .rar { font-size: 9px; text-transform: uppercase; letter-spacing: .05em; color: var(--muted); }

.gamebar { display: flex; gap: 10px; margin-top: 8px; }
.gamebar .btn { flex: 1; }

/* ── Deck builder / card library gallery ─────────────────────── */
.chips { display: flex; gap: 8px; overflow-x: auto; padding: 4px 0 12px; -webkit-overflow-scrolling: touch; }
.chip {
  flex: 0 0 auto; min-height: 40px; padding: 0 14px; border-radius: 999px; border: 1.5px solid var(--line);
  background: var(--panel); font-size: 14px; font-weight: 600; color: var(--muted); cursor: pointer;
  display: inline-flex; align-items: center; gap: 6px;
}
.chip.on { background: var(--btn-bg); color: var(--btn-fg); border-color: var(--btn-bg); }

.gallery { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; padding-bottom: 120px; }
.gcard {
  background: var(--panel); border-radius: 16px; box-shadow: var(--shadow); padding: 12px;
  display: flex; flex-direction: column; gap: 6px; position: relative; overflow: hidden;
}
.gcard .stripe { position: absolute; left: 0; top: 0; bottom: 0; width: 6px; }
.gcard .ghead { display: flex; align-items: center; justify-content: space-between; }
.gcard .cost { width: 28px; height: 28px; border-radius: 50%; background: var(--panel-2); font-weight: 800; display: grid; place-items: center; font-size: 15px; }
.gcard .fac { font-size: 17px; }
.gcard .gname { font-weight: 650; font-size: 15px; line-height: 1.15; padding-left: 6px; }
.gcard .gpg { font-weight: 800; }
.gcard .gtext { font-size: 12px; color: var(--muted); min-height: 30px; }
.gcard .tier { font-size: 11px; color: var(--muted); }
.stepper { display: flex; align-items: center; gap: 10px; margin-top: 4px; }
.stepper button { width: 40px; height: 40px; border-radius: 12px; border: 1.5px solid var(--line); background: var(--panel-2); font-size: 22px; font-weight: 700; cursor: pointer; color: var(--ink); display: grid; place-items: center; }
.stepper button:disabled { opacity: .35; }
.stepper .cnt { font-weight: 800; min-width: 26px; text-align: center; font-size: 17px; }

/* Sort toggle (Cost / Set) above the gallery. */
.sorttoggle { display: flex; align-items: center; gap: 8px; padding: 0 0 12px; }
.sorttoggle .stlabel { font-size: 12px; color: var(--muted); text-transform: uppercase; letter-spacing: .04em; }
.sorttoggle .chip { min-height: 34px; padding: 0 14px; }
/* Builder controls: Sort + Show toggles share one row and wrap on narrow phones. */
.builder-controls { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 16px; }
.builder-controls .sorttoggle { padding-bottom: 10px; }

/* Home-screen theme toggle. */
.theme-toggle {
  min-height: 40px; padding: 0 18px; border-radius: 999px;
  border: 1.5px solid var(--line); background: var(--panel); color: var(--muted);
  font-size: 13px; font-weight: 650; cursor: pointer; box-shadow: var(--shadow);
}

/* Tucked-away "Start over" — deliberately understated so it can't be hit by
   reflex. Reveals an inline confirm before it will wipe progress. */
.reset-link {
  background: none; border: none; box-shadow: none; cursor: pointer;
  color: var(--muted); opacity: .5; font-size: 11px; padding: 6px 10px;
  text-decoration: underline; text-underline-offset: 3px;
}
.reset-link:hover { opacity: .85; color: var(--danger); }
.reset-confirm {
  display: inline-flex; flex-direction: column; gap: 8px; align-items: center;
  padding: 12px 14px; border: 1.5px solid var(--danger); border-radius: 12px;
  background: var(--panel); box-shadow: var(--shadow);
}
.rc-msg { font-size: 13px; font-weight: 650; color: var(--danger); }
.rc-row { display: flex; gap: 8px; }

/* Full-width section header when the gallery is grouped by set. */
.gallery-divider {
  grid-column: 1 / -1; font-weight: 800; font-size: 13px; color: var(--accent-ink);
  padding: 10px 4px 2px; border-bottom: 2px solid var(--line); margin-top: 4px;
  display: flex; align-items: center; gap: 6px;
}
.gallery-divider:first-child { margin-top: 0; }

/* Locked cards: clearly not-yet-yours, but visible so you see what's coming. */
.gcard.locked { opacity: .55; filter: grayscale(.5); }
.gcard.locked .stripe { filter: grayscale(1); }
.gcard .tier.lockrow { color: var(--lock); font-weight: 700; }


.sticky-bar {
  position: fixed; left: 0; right: 0; bottom: 0; z-index: 20;
  background: var(--bar-bg); backdrop-filter: blur(10px);
  border-top: 1px solid var(--line); padding: 12px 16px calc(12px + env(safe-area-inset-bottom));
}
.sticky-inner { max-width: 620px; margin: 0 auto; display: flex; gap: 12px; align-items: center; }
.sticky-inner .count { font-weight: 800; }
.sticky-inner .count.ok { color: var(--accent-ink); }
.sticky-inner .count.bad { color: var(--danger); }
.namefield { flex: 1; min-height: var(--tap); border: 1.5px solid var(--line); border-radius: 12px; padding: 0 12px; font-size: 15px; font-family: inherit; background: var(--panel); color: var(--ink); }

/* ── Overlays ────────────────────────────────────────────────── */
.overlay {
  position: fixed; inset: 0; z-index: 40; background: var(--overlay-bg);
  display: grid; place-items: center; padding: 24px; backdrop-filter: blur(4px);
}
.sheet {
  background: var(--panel); border-radius: 24px; box-shadow: var(--shadow-lg);
  padding: 26px 22px; width: 100%; max-width: 440px; text-align: center;
}
.sheet h2 { font-size: 24px; margin-bottom: 6px; }
.sheet .big { font-size: 46px; margin-bottom: 6px; }
.reveal { display: flex; gap: 10px; justify-content: center; flex-wrap: wrap; margin: 18px 0; }
.reveal .gcard { width: 120px; }

.faction-pick { display: flex; gap: 10px; justify-content: center; flex-wrap: wrap; margin: 16px 0; }
.faction-pick .chip { font-size: 15px; }

.rules { padding-bottom: 20px; }

/* How-to-play illustrations — lightweight, offline, themed via the shared vars
   so they render correctly in both dark (default) and light. */
.rules-illus { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; margin: 2px 0 14px; }
.legend .lg { display: inline-flex; align-items: center; gap: 7px; font-size: 13px; color: var(--muted); }
.legend .lgtile {
  width: 28px; height: 28px; border-radius: 8px; border: 2.5px solid var(--line);
  background: var(--panel-2); display: grid; place-items: center; font-size: 14px;
}
.legend .lgtile.own { border-color: var(--own-border); background: var(--own-bg); }
.legend .lgtile.enemy { border-color: var(--enemy-border); background: var(--enemy-bg); }
.legend .lgtile.obj { color: var(--star); }
.caprow { font-weight: 700; }
.capchip {
  display: inline-flex; align-items: center; gap: 4px; padding: 6px 10px; border-radius: 10px;
  border: 2px solid var(--line); background: var(--panel-2); color: var(--ink); font-size: 14px; font-weight: 800;
}
.capchip.you { border-color: var(--own-border); }
.capchip.foe { border-color: var(--enemy-border); }
.capop { color: var(--muted); font-weight: 800; font-size: 16px; }
.capwin { color: var(--accent-ink); font-weight: 750; }
.movecross { color: var(--accent); flex: 0 0 auto; }
.movelbl { font-size: 13px; color: var(--muted); line-height: 1.3; }

.rules-list { list-style: none; padding: 0; margin: 4px 0 20px; display: flex; flex-direction: column; gap: 10px; }
.rules-list li {
  position: relative; background: var(--panel); border-radius: 12px; box-shadow: var(--shadow);
  padding: 13px 15px 13px 34px; font-size: 15.5px; line-height: 1.5;
}
.rules-list li::before {
  content: ""; position: absolute; left: 15px; top: 20px; width: 7px; height: 7px;
  border-radius: 50%; background: var(--accent);
}

.sheet.info h2 { font-size: 22px; }
.info-list { text-align: left; display: flex; flex-direction: column; gap: 12px; margin-top: 4px; }
.info-list p { margin: 0; font-size: 16px; line-height: 1.5; background: var(--panel-2); border-radius: 12px; padding: 13px 15px; }
/* On-tile keyword reminders (compact one-letter badges) — see Addendum C. */
.kw-badges { position: absolute; left: 3px; bottom: 1px; display: flex; gap: 2px; z-index: 2; pointer-events: none; }
.kwb {
  min-width: 14px; height: 14px; padding: 0 2px; border-radius: 5px;
  background: var(--accent); color: #fff; font-size: 9px; font-weight: 800;
  line-height: 14px; text-align: center; box-shadow: var(--shadow); letter-spacing: .02em;
}
/* Badges shrink with the tile too, so they never crowd a two-digit number. */
@supports (container-type: inline-size) {
  .kwb {
    min-width: clamp(11px, 24cqw, 14px); height: clamp(11px, 24cqw, 14px);
    line-height: clamp(11px, 24cqw, 14px); font-size: clamp(7.5px, 15cqw, 9.5px);
    border-radius: 4px;
  }
  .kw-badges { left: 3px; bottom: 1px; gap: 1px; }
}

/* Set selector rows can carry a couple of lines of description — keep them airy. */
.row-item .meta { line-height: 1.45; }
.row-item { align-items: center; }

/* ── v5: combat feedback, wall traits, deck stats ─────────────────────────── */
.lastaction {
  text-align: center; font-size: 12.5px; color: var(--muted); min-height: 16px;
  margin: -2px 0 6px; padding: 0 6px;
}
.float {
  position: absolute; z-index: 5; font-weight: 800; font-size: clamp(12px, 26cqw, 18px);
  pointer-events: none; animation: floatUp .95s ease-out forwards; text-shadow: 0 1px 2px rgba(255,255,255,.9);
}
.float.dent, .float.damage { color: var(--danger); }
.float.heal { color: var(--land); }
.float.capture, .float.return { color: var(--accent-ink); }
@keyframes floatUp { 0% { transform: translateY(6px); opacity: 0; } 25% { opacity: 1; } 100% { transform: translateY(-16px); opacity: 0; } }

.wall-badge {
  position: absolute; right: 3px; bottom: 1px; z-index: 2; pointer-events: none;
  min-width: 14px; height: 14px; line-height: 14px; padding: 0 2px; border-radius: 4px;
  background: var(--danger); color: #fff; font-size: 9px; font-weight: 800; text-align: center;
  box-shadow: var(--shadow);
}
@supports (container-type: inline-size) {
  .wall-badge { min-width: clamp(11px, 24cqw, 14px); height: clamp(11px, 24cqw, 14px);
    line-height: clamp(11px, 24cqw, 14px); font-size: clamp(7.5px, 15cqw, 9.5px); }
}

.wallmix { font-size: 14px; letter-spacing: 1px; }

.deckstats {
  display: flex; align-items: flex-end; gap: 14px; background: var(--panel);
  border-radius: var(--radius); box-shadow: var(--shadow); padding: 12px 14px; margin-bottom: 12px;
}
.curve { display: flex; align-items: flex-end; gap: 6px; height: 40px; }
.cbar { display: flex; flex-direction: column; align-items: center; gap: 2px; }
.cbar i { display: block; width: 12px; min-height: 2px; background: var(--accent); border-radius: 3px 3px 0 0; }
.cbar em { font-style: normal; font-size: 10px; color: var(--muted); }
.dsmeta { font-size: 12px; color: var(--muted); line-height: 1.5; margin-left: auto; text-align: right; }

/* Toast — brief bottom-center confirmation. Fixed & hidden by default; the .show
   class (added on toast(), removed by its timer) fades it in/out. Previously this
   rule was MISSING, so the div rendered unstyled in page flow and never hid —
   the last message (e.g. "Deck saved") stayed stuck at the bottom and leaked onto
   the play screen. It is also dismissed on navigation (see go() in app.js). */
.toast {
  position: fixed;
  left: 50%;
  bottom: calc(22px + env(safe-area-inset-bottom, 0px));
  transform: translateX(-50%) translateY(10px);
  z-index: 9999;
  max-width: 86vw;
  padding: 10px 18px;
  border-radius: 999px;
  background: var(--panel);
  color: var(--ink);
  border: 1.5px solid var(--line);
  box-shadow: var(--shadow-lg);
  font-size: 14px;
  font-weight: 650;
  text-align: center;
  opacity: 0;
  pointer-events: none;
  transition: opacity .18s ease, transform .18s ease;
}
.toast.show { opacity: 1; transform: translateX(-50%) translateY(0); }
