:root {
  --felt: #2f6a4f;
  --felt-dark: #1f4a37;
  --panel: #374244;
  --panel-dark: #2b3335;
  --panel-light: #4a575a;
  --chips: #009dff;
  --mult: #fe5f55;
  --money: #f3b958;
  --blue: #0099ff;
  --red: #fe5f55;
  --orange: #ff8c1a;
  --green: #4bc292;
  --purple: #8b5cf6;
  --text: #ffffff;
  /* 78 x 104 keeps the 71x95 card sprites' aspect ratio exactly */
  --card-w: 78px;
  --card-h: 104px;
  --joker-w: 92px;
  --joker-h: 124px;
  /* animation pace multiplier, kept in sync with UI.speed (1x-10x) */
  --speed: 1;
  /* high-contrast (four-colour) suits, Balatro's own SO_2 palette – default ON */
  --suit-h: #f83b2f;
  --suit-d: #e29000;
  --suit-s: #4f31b9;
  --suit-c: #008ee6;
}
/* classic two-colour deck */
:root.classic-suits {
  --suit-h: #fe5f55;
  --suit-d: #fe5f55;
  --suit-s: #374649;
  --suit-c: #424e54;
}
.suit-H { color: var(--suit-h); }
.suit-D { color: var(--suit-d); }
.suit-S { color: var(--suit-s); }
.suit-C { color: var(--suit-c); }

* { box-sizing: border-box; -webkit-user-select: none; user-select: none; }
/* touch-action: manipulation kills double-tap zoom and the 300ms click delay
   while still allowing pinch-zoom; no long-press callouts / tap flashes. */
html, body { margin: 0; height: 100%; overflow: hidden; touch-action: manipulation; -webkit-touch-callout: none; -webkit-tap-highlight-color: transparent; -webkit-text-size-adjust: 100%; text-size-adjust: 100%; }
input, textarea { -webkit-user-select: text; user-select: text; -webkit-touch-callout: default; }
body {
  font-family: "Trebuchet MS", "Segoe UI", Verdana, sans-serif;
  font-weight: 700;
  color: var(--text);
  background: radial-gradient(ellipse at 40% 30%, #3a7d5e 0%, var(--felt) 45%, var(--felt-dark) 100%);
}
img { -webkit-user-drag: none; }
button { font-family: inherit; font-weight: 800; }

/* dvh follows the mobile browser's collapsing toolbars (100vh would hide the
   Play button under them); the safe-area padding clears notches / home bar. */
#app {
  height: 100vh; height: 100dvh; display: flex;
  padding: env(safe-area-inset-top, 0px) env(safe-area-inset-right, 0px) env(safe-area-inset-bottom, 0px) env(safe-area-inset-left, 0px);
}
#loading { margin: auto; font-size: 24px; }

/* ---------- layout ---------- */
.sidebar {
  width: 240px; min-width: 240px; padding: 10px; display: flex; flex-direction: column; gap: 8px;
  background: var(--panel); box-shadow: 4px 0 12px rgba(0,0,0,0.4); overflow-y: auto;
}
.main { flex: 1; display: flex; flex-direction: column; min-width: 0; position: relative; }

.box { background: var(--panel-dark); border-radius: 8px; padding: 8px; box-shadow: inset 0 0 0 2px rgba(0,0,0,0.25); }

/* ---------- chip icons ---------- */
/* The little poker chip the game puts in front of a chip count. Built from the
   Small Blind chip in assets/misc/blindchips.png (assets/misc/chips/*.png). */
.chip-ic {
  display: inline-block; vertical-align: -0.16em; flex: none;
  width: 1em; height: 1em; margin-right: 0.28em;
  background: 50% 50% / contain no-repeat;
}
.chip-ic.chip-blue { background-image: url('../assets/misc/chips/chip.png'); }
.chip-ic.chip-red  { background-image: url('../assets/misc/chips/red.png'); }
.chip-ic.chip-gold { background-image: url('../assets/misc/chips/gold.png'); }
.chip-ic.sm { width: 0.85em; height: 0.85em; }
.box-title { font-size: 12px; opacity: 0.8; text-transform: uppercase; letter-spacing: 1px; margin-bottom: 4px; }

.blind-box { display: flex; gap: 8px; align-items: center; background: var(--panel-light); }
.blind-box img { width: 56px; height: 56px; image-rendering: pixelated; }
.blind-box .blind-name { font-size: 15px; line-height: 1.1; }
.blind-box .blind-req { font-size: 20px; color: var(--red); }
.blind-box .blind-reward { font-size: 12px; color: var(--money); }
.blind-box .blind-desc { font-size: 11px; opacity: 0.85; font-weight: 600; }
.blind-box .blind-req small { font-size: 11px; color: #fff; opacity: 0.8; }

.score-box { text-align: center; }
.score-box .score { font-size: 26px; }
/* inline-block so the `bump` scale animation has something to scale */
.score-box .score .num, .calc .chips .num { display: inline-block; }
.hand-box { min-height: 82px; }
.hand-box .hand-name { font-size: 18px; }
.hand-box .hand-name.not-allowed { color: var(--red); text-shadow: 0 0 8px rgba(254,95,85,0.5); }
.hand-box .hand-name.not-allowed + .hand-level { color: var(--red); opacity: 0.9; }
.hand-box .hand-level { font-size: 11px; opacity: 0.8; }
.calc { display: flex; align-items: center; justify-content: center; gap: 6px; margin-top: 4px; }
.calc .chips, .calc .mult { padding: 4px 10px; border-radius: 6px; font-size: 22px; min-width: 70px; text-align: center; }
.calc .chips { background: var(--chips); }
.calc .mult { background: var(--mult); }
.calc .x { font-size: 20px; color: var(--red); }

.stats-row { display: flex; gap: 8px; }
.stat { flex: 1; text-align: center; border-radius: 8px; padding: 6px; background: var(--panel-dark); }
.stat .label { font-size: 11px; opacity: 0.8; }
.stat .value { font-size: 22px; }
.stat.hands .value { color: var(--blue); }
.stat.discards .value { color: var(--red); }
.stat.money { background: var(--panel-dark); flex: 0 0 auto; }
.sidebar .spacer { flex: 1; }
.stat.money .value { color: var(--money); font-size: 26px; }
.stat.ante .value { color: var(--orange); }
.stat.ante .value small { font-size: 12px; color: #fff; opacity: 0.7; }

.sidebar .btn-row { display: flex; gap: 6px; }

/* ---------- buttons ---------- */
.btn {
  border: none; border-radius: 8px; padding: 10px 14px; color: #fff; cursor: pointer; font-size: 15px;
  box-shadow: 0 4px 0 rgba(0,0,0,0.35); transition: transform 0.05s;
}
.btn:active { transform: translateY(3px); box-shadow: 0 1px 0 rgba(0,0,0,0.35); }
.btn:disabled { opacity: 0.4; cursor: not-allowed; }
.btn.blue { background: var(--blue); }
.btn.red { background: var(--red); }
.btn.orange { background: var(--orange); }
.btn.green { background: var(--green); }
.btn.gray { background: var(--panel-light); }
.btn.purple { background: var(--purple); }
.btn.small { padding: 5px 9px; font-size: 12px; }
.btn.big { font-size: 20px; padding: 14px 24px; }

/* ---------- top rows: jokers + consumables ---------- */
.top-row { display: flex; gap: 12px; padding: 10px 14px 0; align-items: flex-start; }
/* min-width:0 lets these flex items shrink below their content width so the
   .slot-cards strip scrolls instead of pushing the consumables off-screen. */
.slot-area { border-radius: 10px; background: rgba(0,0,0,0.18); padding: 6px; min-height: calc(var(--joker-h) + 12px); position: relative; min-width: 0; }
.slot-area.jokers { flex: 1 1 0; }
.slot-area.consumables { flex: 0 0 240px; width: 240px; }
.slot-area .slot-label { position: absolute; bottom: -16px; left: 6px; font-size: 11px; opacity: 0.85; }
.slot-cards { display: flex; gap: 6px; flex-wrap: nowrap; overflow-x: auto; min-height: var(--joker-h); }

/* ---------- middle: table ---------- */
.table { flex: 1; display: flex; flex-direction: column; justify-content: flex-end; padding: 24px 14px 10px; min-height: 0; }
.played-area { min-height: calc(var(--card-h) + 50px); display: flex; justify-content: center; align-items: flex-end; gap: 6px; padding-bottom: 20px; position: relative; }
.hand-area { display: flex; justify-content: center; align-items: flex-end; min-height: calc(var(--card-h) + 30px); padding: 10px 0; }
.hand-cards { display: flex; justify-content: center; position: relative; }
.hand-cards .pcard { margin-left: calc(-1 * var(--fan, 14px)); transition: transform 0.12s; touch-action: none; }
.hand-cards .pcard:first-child { margin-left: 0; }
.hand-cards .pcard:hover { z-index: 5; transform: translateY(-8px); }
.hand-cards .pcard.selected { transform: translateY(-26px); }
.hand-cards .pcard.selected:hover { transform: translateY(-30px); }
/* drag to reorder */
.hand-cards .pcard.dragging { transition: none; z-index: 60; box-shadow: 0 10px 18px rgba(0,0,0,0.55); cursor: grabbing; }
.hand-cards .drop-caret { position: absolute; top: -10px; bottom: -10px; width: 4px; margin-left: -2px; border-radius: 2px; background: var(--money); box-shadow: 0 0 8px rgba(243,185,88,0.9); z-index: 55; pointer-events: none; }
.actions { display: flex; justify-content: center; gap: 14px; align-items: center; padding: 6px 0; }
.actions .sort { display: flex; gap: 4px; flex-direction: column; align-items: center; font-size: 11px; }
.hand-helpers { display: flex; justify-content: center; gap: 10px; padding: 4px 0 8px; }
.hand-score-preview { display: flex; flex-direction: column; gap: 4px; margin-top: 10px; }
.hand-score-preview small { font-size: 11px; opacity: .8; }
.hand-score-preview strong { color: var(--money); font-size: 22px; overflow-wrap: anywhere; }

/* Royal Front: the poker table supplies a persistent territory campaign. */
.conquest { margin: 4px 14px; padding: 12px 14px 8px; border: 1px solid #6c8f89; border-radius: 12px; background: #122f38; box-shadow: 0 5px 18px #10272266; flex-shrink: 0; }
.conquest-header { display: flex; align-items: center; gap: 14px; }
.conquest h2 { margin: 2px 0; font-size: 23px; color: #ffdfa2; letter-spacing: -.5px; }
.conquest-eyebrow { font-size: 9px; letter-spacing: 2px; color: #93b8b9; }
.conquest-stats { display: flex; flex-wrap: wrap; gap: 7px 14px; flex: 1; justify-content: flex-end; font-size: 12px; }
.conquest-stats strong { color: #ffd891; }
.conquest-body { display: flex; align-items: stretch; gap: 12px; }
.conquest-map { display: block; flex: 1; min-width: 0; width: 100%; max-height: 285px; background: radial-gradient(ellipse, #245362, #122f38 72%); }
.territory { cursor: pointer; outline: none; }
.territory polygon { stroke: #173b42; stroke-width: 2.5; transition: filter .12s; }
.territory:hover polygon, .territory:focus polygon { filter: brightness(1.3); stroke: #fff; }
.territory.adjacent polygon { stroke: #a5c4b2; stroke-width: 1.5; }
.territory.source polygon { stroke: #ffdd95; stroke-width: 3; }
.territory.target polygon { stroke: #fff; stroke-width: 3.5; stroke-dasharray: 5 3; }
.territory text { fill: white; pointer-events: none; paint-order: stroke; stroke: #18303877; stroke-width: 2px; }
.territory-name { font-size: 8.5px; font-weight: 600; }
.territory-troops { font-size: 20px; font-weight: 900; }
.map-ocean-label { fill: #7aa5af; font-size: 8px; letter-spacing: 5px; }
.troop-route { fill: none; stroke: #ffe2a3; stroke-width: 2.5; stroke-dasharray: 4 4; animation: troop-march calc(1s / var(--speed)) linear infinite; }
@keyframes troop-march { to { stroke-dashoffset: -16; } }
.conquest-command { width: 218px; flex-shrink: 0; display: flex; flex-direction: column; justify-content: center; gap: 7px; border-left: 1px solid #54767c66; padding: 9px 0 9px 13px; }
.conquest-command h3 { font-size: 15px; margin: 0; }
.conquest-command p { font-size: 11px; font-weight: 500; line-height: 1.4; margin: 0; min-height: 30px; }
.conquest-command small { color: #acc7c5; font-size: 10px; font-weight: 500; }
.conquest-presets, .conquest-reinforce { display: flex; gap: 5px; }
.conquest-presets .btn, .conquest-reinforce .btn { flex: 1; padding: 5px; }
.conquest-footer { display: flex; gap: 12px; justify-content: space-between; flex-wrap: wrap; color: #bdd5cc; font-size: 9px; border-top: 1px solid #54767c66; padding-top: 6px; }
.conquest-log { margin-top: 5px; color: #e8d3a7; font-size: 10px; font-weight: 500; line-height: 1.5; }
.conquest-open { background: #234e60; color: #ffdfa2; border: 1px solid #638080; }
.conquest-modal { width: min(1100px, 96vw); }
.conquest-modal .conquest { margin: 0; }
.conquest-help { color: #c7d6d2; font-size: 12px; line-height: 1.6; font-weight: 500; }
.campaign-main { overflow-y: auto; }
.campaign-main > .top-row { min-height: 72px; padding-top: 8px; padding-bottom: 4px; }
.campaign-main > .top-row .slot-area { min-height: 60px; }
.campaign-main > .top-row .slot-cards:empty { min-height: 45px; }
.campaign-main > .table { min-height: 230px; padding-top: 10px; flex-shrink: 0; }
.campaign-main .played-area { min-height: 0; }
.campaign-main .played-area:empty { padding-bottom: 0; }
.show-map { align-self: center; margin: 6px; }
@media (max-width: 950px) {
  .conquest { margin: 4px 8px; padding: 9px; }
  .conquest-command { width: 180px; }
  .conquest-header { flex-wrap: wrap; gap: 5px; }
  .conquest h2 { font-size: 19px; }
}
@media (max-width: 700px) {
  .conquest-body { flex-direction: column; }
  .conquest-command { width: 100%; border-left: 0; border-top: 1px solid #54767c66; padding-left: 0; }
  .conquest-map { flex: none; min-height: 180px; }
}
.deck-corner { position: absolute; right: 18px; bottom: 16px; text-align: center; font-size: 12px; cursor: pointer; }
.deck-corner .card-back { margin: 0 auto 4px; }

/* ---------- playing cards ---------- */
/* The card face is the game's own sprite (assets/enhancements/bg/*.png, cut out
   of the wiki's Ace-of-Spades enhancement art with the rank/suit painted out),
   stretched over the whole card; the rank/suit corners, the face-card art and
   the seal are drawn on top of it exactly where the real game puts them. */
.pcard {
  width: var(--card-w); height: var(--card-h); border-radius: 7px; position: relative; cursor: pointer;
  background: transparent url('../assets/enhancements/bg/base.png') 50% 50% / 100% 100% no-repeat;
  box-shadow: 0 2px 4px rgba(0,0,0,0.4); color: #222; flex-shrink: 0; overflow: hidden;
}
.pcard .corner { position: absolute; top: 4px; left: 6px; font-size: 20px; line-height: 1; }
.pcard .corner small { display: block; font-size: 16px; }
.pcard .corner-br { position: absolute; bottom: 4px; right: 6px; font-size: 20px; line-height: 1; transform: rotate(180deg); }
.pcard .corner-br small { display: block; font-size: 16px; }
.pcard .center { position: absolute; inset: 0; display: flex; align-items: center; justify-content: center; font-size: 34px; }
.pcard.red { color: #d32f2f; }
.pcard.black { color: #222; }
.pcard.suit-H { color: var(--suit-h); }
.pcard.suit-D { color: var(--suit-d); }
.pcard.suit-S { color: var(--suit-s); }
.pcard.suit-C { color: var(--suit-c); }
/* face-card art: the sprite carries its own corner indices, so the box is
   narrower than the card and object-fit:cover crops them off the sides. */
.pcard .face-art { position: absolute; top: 0; bottom: 0; left: 18.8%; right: 18.8%; pointer-events: none; }
/* multiply keeps the sprite's white paper transparent so enhancement tints show through */
.pcard .face-art img { width: 100%; height: 100%; object-fit: cover; image-rendering: pixelated; display: block; mix-blend-mode: multiply; }
.pcard.has-art .corner, .pcard.has-art .corner-br { text-shadow: 0 0 3px #fff, 0 0 3px #fff, 0 0 2px #fff; z-index: 2; }
.pcard.enh-stone .face-art { display: none; }
.pcard.debuffed { filter: grayscale(1) brightness(0.65); }
.pcard.debuffed::after { content: '✖'; position: absolute; inset: 0; display: flex; align-items: center; justify-content: center; font-size: 40px; color: rgba(200,0,0,0.75); z-index: 8; }
.pcard.facedown, .card-back { background: repeating-linear-gradient(45deg, #b3262c 0 6px, #8e1c22 6px 12px); border: 4px solid #f1e3c4; }
.pcard.facedown > * { display: none; }
.pcard.facedown::before { display: none; }
.card-back { width: var(--card-w); height: var(--card-h); border-radius: 7px; box-shadow: 0 2px 4px rgba(0,0,0,0.4); }

/* enhancements – the real card faces, rank/suit removed */
.pcard.enh-bonus { background-image: url('../assets/enhancements/bg/bonus.png'); }
.pcard.enh-mult  { background-image: url('../assets/enhancements/bg/mult.png'); }
.pcard.enh-wild  { background-image: url('../assets/enhancements/bg/wild.png'); }
.pcard.enh-glass { background-image: url('../assets/enhancements/bg/glass.png'); }
.pcard.enh-steel { background-image: url('../assets/enhancements/bg/steel.png'); }
.pcard.enh-stone { background-image: url('../assets/enhancements/bg/stone.png'); }
.pcard.enh-gold  { background-image: url('../assets/enhancements/bg/gold.png'); }
.pcard.enh-lucky { background-image: url('../assets/enhancements/bg/lucky.png'); }
/* …but the deck back always wins over the face, whatever the enhancement is
   (this rule has to come after the enh-* ones, which are equally specific). */
.pcard.facedown { background-image: repeating-linear-gradient(45deg, #b3262c 0 6px, #8e1c22 6px 12px); }
/* Stone has no rank or suit at all; Glass is genuinely see-through, so the felt
   (or whatever is behind it) shows through its paper. */
.pcard.enh-stone .corner, .pcard.enh-stone .corner-br, .pcard.enh-stone .center { display: none; }
.pcard.enh-glass { box-shadow: 0 2px 4px rgba(0,0,0,0.25); }
/* Wild keeps its rank and suit, but the suit pip is the rainbow blob the sprite
   draws instead of a plain symbol. */
.pcard.enh-wild .corner small, .pcard.enh-wild .corner-br small, .pcard.enh-wild .center {
  background: linear-gradient(150deg, #f83b2f 0%, #e29000 28%, #3fb950 52%, #008ee6 74%, #8b5cf6 100%);
  -webkit-background-clip: text; background-clip: text;
  -webkit-text-fill-color: transparent; color: transparent;
  filter: drop-shadow(0 0 1px rgba(0,0,0,0.35));
}
/* .center fills the whole card, so pin the gradient to a box the size of the
   pip itself or the glyph only ever samples the middle of the rainbow */
.pcard.enh-wild .center { background-size: 42px 42px; background-position: 50% 50%; background-repeat: no-repeat; }

/* ---------- editions ---------- */
/* Balatro draws these with shaders; here each is one cheap ::before wash that
   sweeps its gradient across the card forever. They sit above the art but below
   the debuff cross, and never eat pointer events. */
/* isolate so the wash blends with the card only, never with the table behind it */
.ed-foil, .ed-holographic, .ed-polychrome { position: relative; isolation: isolate; }
.ed-foil::before, .ed-holographic::before, .ed-polychrome::before, .ed-layer {
  content: ''; position: absolute; inset: 0; z-index: 6; pointer-events: none;
  border-radius: inherit; background-repeat: no-repeat;
}
/* Foil: cold blue-silver metal with white light beams raking across it.
   hard-light lets the dark blue stops tint and the pale stops flare. */
.ed-foil::before {
  background-image:
    repeating-linear-gradient(112deg, rgba(255,255,255,0) 0 4%, rgba(255,255,255,0.95) 6%, rgba(255,255,255,0) 9%, rgba(255,255,255,0) 17%),
    linear-gradient(112deg, #1338ad 0%, #9cc4ff 18%, #1c4ec9 38%, #cfe6ff 58%, #12379f 78%, #8ab6ff 100%);
  background-size: 200% 100%, 200% 100%;
  mix-blend-mode: hard-light; opacity: 0.88;
  animation: foil-sweep 5.5s linear infinite;
}
@keyframes foil-sweep { from { background-position: 0 0, 0 0; } to { background-position: 200% 0, 200% 0; } }
/* Holographic: pastel iridescence over a faint lattice, hue drifting round. */
.ed-holographic::before {
  background-image:
    repeating-linear-gradient(60deg, rgba(255,255,255,0.5) 0 1.5%, rgba(255,255,255,0) 1.5% 9%),
    repeating-linear-gradient(-60deg, rgba(255,255,255,0.5) 0 1.5%, rgba(255,255,255,0) 1.5% 9%),
    linear-gradient(115deg, #ff5fd0 0%, #56b8ff 14%, #b57bff 28%, #5fffc0 42%, #ffe06a 56%, #ff7ec4 70%, #56b8ff 85%, #ff5fd0 100%);
  background-size: 100% 100%, 100% 100%, 190% 100%;
  opacity: 0.58;
  animation: holo-sweep 9s linear infinite;
}
@keyframes holo-sweep {
  from { background-position: 0 0, 0 0, 0 0; }
  to   { background-position: 0 0, 0 0, 190% 0; }
}
/* Polychrome: the card is repainted in rainbow – `color` keeps the art's own
   light and shade, so the paper stays pale and only the ink goes technicolour,
   exactly like the sprite. */
.ed-polychrome::before {
  background-image: linear-gradient(150deg, #ff3b30 0%, #ff9500 14%, #ffe600 28%, #34d058 43%, #00c2d6 57%, #2f6fff 71%, #9b30ff 85%, #ff3b30 100%);
  background-size: 140% 240%;
  mix-blend-mode: color; opacity: 1;
  animation: poly-sweep 7s linear infinite;
}
@keyframes poly-sweep { from { background-position: 0 0; } to { background-position: 140% 240%; } }
/* …and a second, gentler pass that tints the white paper too, so the whole card
   shimmers instead of only the ink. */
.ed-polychrome > .ed-layer {
  background-image: linear-gradient(150deg, #ff9a94 0%, #ffd08a 14%, #fff59c 28%, #a6f0bd 43%, #8fe6f2 57%, #a8bdff 71%, #d8a6ff 85%, #ff9a94 100%);
  background-size: 140% 240%;
  mix-blend-mode: multiply; opacity: 0.55;
  animation: poly-sweep 7s linear infinite;
}
.ed-polychrome { filter: saturate(1.3) contrast(1.04); }
/* Foil's white light beams get their own screen pass so they flare instead of
   just lightening the blue. */
.ed-foil > .ed-layer {
  background-image: repeating-linear-gradient(112deg, rgba(255,255,255,0) 0 5%, rgba(255,255,255,0.5) 7.5%, rgba(255,255,255,0) 10%, rgba(255,255,255,0) 22%);
  background-size: 200% 100%;
  mix-blend-mode: screen; opacity: 0.8;
  animation: foil-sweep 5.5s linear infinite;
}
/* Negative: a dark slate card with pale ink – an inversion pulled back toward
   the sprite's cold blue-green. */
.ed-negative { filter: invert(1) hue-rotate(180deg) contrast(0.6) brightness(1.3) sepia(0.3) hue-rotate(148deg) saturate(1.5); }
@media (prefers-reduced-motion: reduce) {
  .ed-foil::before, .ed-holographic::before, .ed-polychrome::before, .ed-layer { animation: none; background-position: 40% 30%; }
}
/* Performance: background-position sweeps repaint every frame, so cards that are
   scrolled out of view (IntersectionObserver in ui.js tags them .ed-off) stop
   animating, and touch devices only animate the main wash – the second pass
   stays still, which halves the per-frame paint on phones. */
.ed-off::before, .ed-off > .ed-layer { animation-play-state: paused; }
:root.touch .ed-foil > .ed-layer, :root.touch .ed-polychrome > .ed-layer { animation: none; background-position: 40% 30%; }

/* ---------- seals ---------- */
/* The wax stamp sits where the sprite puts it: a little up and left of centre,
   overlapping the corner index, on top of everything but the debuff cross. */
.seal {
  position: absolute; left: 18.3%; top: 13.7%; width: 39.4%; height: 30.5%;
  background: 50% 50% / 100% 100% no-repeat; z-index: 5; pointer-events: none;
}
.seal-gold   { background-image: url('../assets/enhancements/bg/seal_gold.png'); }
.seal-red    { background-image: url('../assets/enhancements/bg/seal_red.png'); }
.seal-blue   { background-image: url('../assets/enhancements/bg/seal_blue.png'); }
.seal-purple { background-image: url('../assets/enhancements/bg/seal_purple.png'); }

/* ---------- jokers & consumables ---------- */
.jcard {
  width: var(--joker-w); height: var(--joker-h); border-radius: 7px; position: relative; cursor: pointer; flex-shrink: 0;
  box-shadow: 0 2px 4px rgba(0,0,0,0.4); background: #2b3335; overflow: hidden; transition: transform 0.12s;
}
.jcard:hover { transform: translateY(-6px); z-index: 5; }
.jcard img { width: 100%; height: 100%; object-fit: contain; image-rendering: pixelated; display: block; }
.jcard .fallback { padding: 6px; font-size: 11px; text-align: center; display: flex; align-items: center; justify-content: center; height: 100%; background: linear-gradient(160deg, #6b4fa0, #3d2a66); }
.jcard.disabled { filter: grayscale(1) brightness(0.5); }
.jcard.facedown img, .jcard.facedown .fallback { visibility: hidden; }
.jcard.facedown .ed-layer, .jcard.facedown::before { display: none; }
.jcard.facedown { background: repeating-linear-gradient(45deg, #5a3a8a 0 6px, #3d2a66 6px 12px); }
/* above the edition wash so the label stays readable */
.jcard .badge { position: absolute; top: 3px; left: 3px; font-size: 9px; padding: 1px 4px; border-radius: 4px; background: rgba(0,0,0,0.6); z-index: 7; }
.jcard .status { position: absolute; bottom: 0; left: 0; right: 0; font-size: 10px; background: rgba(0,0,0,0.65); padding: 2px 3px; text-align: center; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; z-index: 7; }
.jcard.unimpl::after { z-index: 7; }
.jcard.dragging { opacity: 0.4; }
.jcard.drag-over { outline: 3px solid var(--money); }
.jcard.highlight, .pcard.highlight { outline: 3px solid var(--money); transform: translateY(-10px) scale(1.06); z-index: 10; }
.jcard.unimpl::after { content: '?'; position: absolute; top: 2px; right: 4px; color: var(--money); font-size: 14px; }
.ccard { width: var(--joker-w); height: var(--joker-h); }

/* ---------- popups (floating score text) ---------- */
.pop { position: absolute; left: 50%; top: -6px; transform: translateX(-50%); padding: 3px 8px; border-radius: 6px; font-size: 14px; white-space: nowrap; z-index: 50; animation: popup calc(0.95s / var(--speed)) ease-out forwards; pointer-events: none; }
.pop.chips { background: var(--chips); } .pop.mult { background: var(--mult); } .pop.money { background: var(--money); color: #222; } .pop.neutral { background: #666; }
@keyframes popup { 0% { transform: translate(-50%, 8px) scale(0.7); opacity: 0; } 15% { transform: translate(-50%, -2px) scale(1.12); opacity: 1; } 30% { transform: translate(-50%, -6px) scale(1); } 75% { opacity: 1; } 100% { transform: translate(-50%, -30px); opacity: 0; } }

/* ---------- scoring animation ---------- */
/* Every duration is divided by --speed, which mirrors the 1x-10x Options setting. */
@keyframes wobble {
  0%   { transform: translateY(-10px) scale(1.06) rotate(0deg); }
  20%  { transform: translateY(-16px) scale(1.14) rotate(-5deg); }
  45%  { transform: translateY(-12px) scale(1.10) rotate(4deg); }
  70%  { transform: translateY(-11px) scale(1.08) rotate(-2deg); }
  100% { transform: translateY(-10px) scale(1.06) rotate(0deg); }
}
.wobble { animation: wobble calc(0.42s / var(--speed)) ease-in-out; }
@keyframes bump { 0% { transform: scale(1); } 40% { transform: scale(1.22); } 100% { transform: scale(1); } }
.bump { animation: bump calc(0.32s / var(--speed)) ease-out; }
@keyframes reveal { 0% { transform: scale(0.82); opacity: 0.4; } 60% { transform: scale(1.06); opacity: 1; } 100% { transform: scale(1); } }
.hand-box.reveal { animation: reveal calc(0.4s / var(--speed)) ease-out; }
@keyframes tally { 0%, 100% { filter: brightness(1); transform: scale(1); } 50% { filter: brightness(1.45); transform: scale(1.12); } }
.calc .chips.tally, .calc .mult.tally { animation: tally calc(0.36s / var(--speed)) ease-in-out 2; }
/* cards dealt into the hand / laid onto the table */
@keyframes deal-in { 0% { opacity: 0; transform: translate(70px, -34px) rotate(10deg); } 100% { opacity: 1; transform: none; } }
.pcard.dealt { animation: deal-in calc(0.3s / var(--speed)) ease-out backwards; }
@keyframes card-play { 0% { transform: translateY(-26px); opacity: 1; } 100% { transform: translateY(-120px) scale(1.05); opacity: 0; } }
@keyframes card-discard { 0% { transform: translateY(-26px); opacity: 1; } 100% { transform: translate(120px, 90px) rotate(22deg); opacity: 0; } }
.score-total.fly { animation: fly-to-score calc(0.36s / var(--speed)) ease-in forwards; }
@keyframes fly-to-score { 0% { transform: translateX(-50%) scale(1); opacity: 1; } 100% { transform: translate(-50%, -140px) scale(0.5); opacity: 0; } }

/* ---------- tooltip ---------- */
.tooltip { position: fixed; z-index: 1000; background: #1b2224; border: 2px solid #4a575a; border-radius: 8px; padding: 8px 10px; width: 240px; font-size: 12px; font-weight: 600; pointer-events: none; box-shadow: 0 6px 20px rgba(0,0,0,0.6); }
.tooltip.hidden { display: none; }
.tooltip .tt-name { font-size: 15px; font-weight: 800; margin-bottom: 3px; }
.tooltip .tt-rarity { display: inline-block; font-size: 10px; padding: 1px 6px; border-radius: 4px; margin-bottom: 4px; }
.tooltip .tt-body { opacity: 0.95; line-height: 1.35; }
.tooltip .tt-status { color: var(--money); margin-top: 4px; }
.tooltip .tt-foot { margin-top: 4px; font-size: 11px; opacity: 0.75; }
.tooltip .tt-warn { color: var(--orange); margin-top: 4px; font-size: 11px; }
.r-Common { background: #009dff; } .r-Uncommon { background: #4bc292; } .r-Rare { background: #fe5f55; } .r-Legendary { background: #8b5cf6; }
.r-Tarot { background: #8b5cf6; } .r-Planet { background: #13afce; } .r-Spectral { background: #4584fa; } .r-Voucher { background: #ff8c1a; } .r-Tag { background: #666; }
.hl-chips { color: var(--chips); } .hl-mult { color: var(--mult); } .hl-money { color: var(--money); } .hl-x { color: var(--red); }

/* ---------- overlays / screens ---------- */
.overlay { position: absolute; inset: 0; display: flex; align-items: center; justify-content: center; background: rgba(0,0,0,0.35); z-index: 20; }
.panel { background: var(--panel); border-radius: 12px; padding: 18px; box-shadow: 0 10px 40px rgba(0,0,0,0.6); max-width: 92%; max-height: 92%; overflow: auto; }
.panel h2 { margin: 0 0 12px; text-align: center; font-size: 26px; }
.panel h3 { margin: 12px 0 6px; font-size: 16px; }

/* blind select */
.blind-select { display: flex; gap: 14px; justify-content: center; align-items: center; padding: 30px 10px; flex: 1; }
.blind-col { width: 210px; background: var(--panel); border-radius: 12px; padding: 12px; text-align: center; box-shadow: 0 8px 24px rgba(0,0,0,0.4); }
.blind-col.current { transform: translateY(-20px); outline: 3px solid var(--money); }
.blind-col.done { opacity: 0.55; }
.blind-col img { width: 72px; height: 72px; image-rendering: pixelated; margin: 6px auto; display: block; }
.blind-col .name { font-size: 17px; min-height: 40px; display: flex; align-items: center; justify-content: center; }
.blind-col .req { font-size: 22px; color: var(--red); }
.blind-col .req small { font-size: 11px; color: #fff; opacity: 0.7; display: block; }
.blind-col .reward { color: var(--money); font-size: 14px; margin-bottom: 8px; }
.blind-col .desc { font-size: 12px; font-weight: 600; opacity: 0.9; min-height: 34px; }
.blind-col .tag-preview { display: flex; align-items: center; gap: 6px; justify-content: center; font-size: 11px; margin-top: 8px; opacity: 0.9; }
.blind-col .tag-preview img { width: 28px; height: 28px; margin: 0; }
.blind-col .status { font-size: 13px; color: var(--money); }

/* shop */
.shop { flex: 1; display: flex; flex-direction: column; padding: 10px 14px; gap: 10px; overflow: auto; }
.shop-row { display: flex; gap: 10px; align-items: stretch; }
.shop-main { flex: 1; background: var(--panel); border-radius: 12px; padding: 10px; display: flex; gap: 10px; align-items: center; min-height: 160px; }
.shop-side { width: 190px; display: flex; flex-direction: column; gap: 8px; }
.shop-items { display: flex; gap: 10px; flex: 1; justify-content: center; align-items: flex-start; flex-wrap: wrap; }
.shop-item { display: flex; flex-direction: column; align-items: center; gap: 4px; }
.shop-item .price { color: var(--money); font-size: 15px; }
.shop-item .buy-row { display: flex; gap: 4px; }
.shop-bottom { display: flex; gap: 10px; }
.shop-box { background: var(--panel); border-radius: 12px; padding: 10px; flex: 1; display: flex; flex-direction: column; align-items: center; gap: 6px; }
.shop-box .title { font-size: 13px; opacity: 0.8; text-transform: uppercase; letter-spacing: 1px; }
.pack-card { width: 100px; height: 130px; border-radius: 8px; display: flex; flex-direction: column; align-items: center; justify-content: center; text-align: center; font-size: 13px; padding: 6px; cursor: pointer; box-shadow: 0 2px 4px rgba(0,0,0,0.4); }
.pack-card { position: relative; background: transparent; box-shadow: none; padding: 0; }
.pack-card img { width: 100%; height: 100%; object-fit: contain; image-rendering: pixelated; border-radius: 8px; }
.pack-card .pack-name { position: absolute; left: 0; right: 0; bottom: 4px; font-size: 10px; text-shadow: 0 1px 2px #000; pointer-events: none; }
.pack-card img + .pack-name { display: none; }
.pack-card:hover { transform: translateY(-4px); }
.pack-arcana { background: linear-gradient(160deg, #6b4fa0, #3d2a66); }
.pack-celestial { background: linear-gradient(160deg, #1d5fa6, #0e2f55); }
.pack-spectral { background: linear-gradient(160deg, #2a6ea8, #123a5c); }
.pack-standard { background: linear-gradient(160deg, #b33a3a, #5c1a1a); }
.pack-buffoon { background: linear-gradient(160deg, #c46a2a, #6b3410); }
.vcard { width: 100px; height: 130px; border-radius: 8px; background: linear-gradient(160deg, #3a6b8f, #1e3a4f); display: flex; align-items: center; justify-content: center; text-align: center; font-size: 13px; padding: 6px; cursor: pointer; box-shadow: 0 2px 4px rgba(0,0,0,0.4); overflow: hidden; }
.vcard img { width: 100%; height: 100%; object-fit: contain; image-rendering: pixelated; }

/* pack opening */
.pack-open { flex: 1; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 14px; padding: 10px; }
.pack-open h2 { margin: 0; }
.pack-cards { display: flex; gap: 12px; flex-wrap: wrap; justify-content: center; }
.pack-choice { display: flex; flex-direction: column; align-items: center; gap: 6px; }

/* cash out */
.cashout { min-width: 380px; }
.cashout .line { display: flex; justify-content: space-between; padding: 4px 0; border-bottom: 1px solid rgba(255,255,255,0.1); font-weight: 600; }
.cashout .line .amt { color: var(--money); }
.cashout .total { font-size: 28px; text-align: center; margin: 12px 0; color: var(--money); }

/* menu */
.menu {
  flex: 1; display: flex; flex-direction: column; align-items: center; gap: 16px;
  /* `safe` keeps the top of the list reachable when the window is too short to
     centre the whole menu – without it the logo and decks get clipped away. */
  justify-content: safe center; overflow-y: auto; padding: 16px 10px;
}
.menu h1 { font-size: 64px; margin: 0; letter-spacing: 4px; text-shadow: 4px 4px 0 rgba(0,0,0,0.4); color: var(--money); }
.menu img.logo { max-width: 420px; }
.deck-grid { display: flex; gap: 10px; flex-wrap: wrap; justify-content: center; max-width: 820px; }
.deck-opt { width: 120px; background: var(--panel); border-radius: 10px; padding: 8px; text-align: center; font-size: 12px; cursor: pointer; border: 3px solid transparent; }
.deck-opt.selected { border-color: var(--money); }
.deck-opt img { width: 60px; height: 80px; object-fit: contain; image-rendering: pixelated; display: block; margin: 0 auto 4px; }
.deck-opt .dname { font-size: 13px; margin-bottom: 3px; }
.deck-opt .ddesc { font-weight: 600; opacity: 0.85; font-size: 11px; }
.seed-row { display: flex; gap: 8px; align-items: center; }
.seed-row input { padding: 8px; border-radius: 6px; border: none; font-family: inherit; font-weight: 700; width: 140px; text-transform: uppercase; }

/* tags in sidebar */
.tags-row { display: flex; gap: 4px; flex-wrap: wrap; }
.tag-chip { width: 34px; height: 34px; border-radius: 6px; background: var(--panel-light); display: flex; align-items: center; justify-content: center; font-size: 10px; overflow: hidden; }
.tag-chip img { width: 100%; height: 100%; object-fit: contain; image-rendering: pixelated; }

/* toasts */
.toasts { position: absolute; top: 10px; right: 14px; z-index: 40; display: flex; flex-direction: column; gap: 4px; pointer-events: none; }
.toast { background: rgba(0,0,0,0.7); padding: 6px 10px; border-radius: 6px; font-size: 12px; animation: fadein 0.2s; }
@keyframes fadein { from { opacity: 0; transform: translateX(20px); } to { opacity: 1; } }

/* run info tables */
.hands-table { width: 100%; border-collapse: collapse; font-size: 13px; }
.hands-table td, .hands-table th { padding: 4px 8px; text-align: left; border-bottom: 1px solid rgba(255,255,255,0.08); }
.hands-table .lv { color: var(--money); }
.hands-table .c { color: var(--chips); } .hands-table .m { color: var(--mult); }
.deck-view { display: flex; flex-direction: column; gap: 6px; }
.deck-view .suit-row { display: flex; gap: 2px; flex-wrap: wrap; }
.deck-view .pcard { transform: scale(0.7); transform-origin: top left; width: var(--card-w); height: var(--card-h); margin-right: calc(var(--card-w) * -0.3); margin-bottom: calc(var(--card-h) * -0.3); cursor: default; }
.deck-view .pcard:hover { transform: scale(0.7); }
.mini-jokers { display: flex; gap: 6px; flex-wrap: wrap; }

.score-total { position: absolute; top: 0; left: 50%; transform: translateX(-50%); font-size: 36px; color: var(--money); text-shadow: 3px 3px 0 rgba(0,0,0,0.5); animation: fadein 0.3s; }
.kbd-hint { font-size: 10px; opacity: 0.6; text-align: center; }

/* save codes / debug */
.code-box { width: 100%; box-sizing: border-box; height: 56px; margin-top: 6px; font: 11px/1.3 monospace; background: #1b1e24; color: #cfd3da; border: 1px solid #3a3f48; border-radius: 6px; padding: 6px; resize: vertical; word-break: break-all; }
.small-note { font-size: 11px; opacity: 0.75; margin: 4px 0; }
.btn.small { padding: 4px 10px; font-size: 12px; }
.seed-row input[placeholder^="Save"] { text-transform: none; font-weight: 400; width: 260px; font-family: monospace; }

/* =====================================================================
   TOUCH + PHONES (poker side). Conquest / Royal Front styles live above and
   belong to the campaign; this block only gives the map a slot.
   ===================================================================== */
/* tapped-open tooltip popover (see showTipFor in ui.js) */
.tooltip.tap { pointer-events: auto; width: min(260px, calc(100vw - 12px)); max-height: calc(100dvh - 12px); overflow-y: auto; }
.tooltip .tt-actions { display: flex; gap: 6px; margin-top: 8px; }
.tooltip .tt-actions .btn { flex: 1; min-height: 42px; padding: 8px 10px; font-size: 14px; }
.r-Pack { background: #c46a2a; } .r-Boss { background: #c44; }
/* game elements: no callouts, no double-tap zoom; the hand keeps touch-action:none */
.jcard, .pcard, .pack-card, .vcard, .tag-chip, .deck-opt, .blind-box, .deck-corner, .btn { touch-action: manipulation; -webkit-touch-callout: none; }
.jcard img, .pcard img, .pack-card img, .vcard img, .tag-chip img, .deck-opt img, .blind-box img, .blind-col img, img.logo { -webkit-touch-callout: none; pointer-events: none; }
/* joker drag on touch (long-press, then drag) */
.slot-cards { position: relative; }
.joker-caret { position: absolute; top: 2px; bottom: 2px; width: 4px; margin-left: -3px; border-radius: 2px; background: var(--money); box-shadow: 0 0 8px rgba(243,185,88,0.9); z-index: 55; pointer-events: none; }
.jcard.dragging-touch { transition: none; z-index: 60; box-shadow: 0 10px 18px rgba(0,0,0,0.55); }
/* no sticky :hover lifts after a tap */
:root.touch .hand-cards .pcard:hover { transform: none; z-index: auto; }
:root.touch .hand-cards .pcard.selected, :root.touch .hand-cards .pcard.selected:hover { transform: translateY(var(--sel-lift, -26px)); }
:root.touch .jcard:hover, :root.touch .pack-card:hover { transform: none; }
:root.touch .jcard.lifted { transform: translateY(-6px) scale(1.08); box-shadow: 0 8px 16px rgba(0,0,0,0.5); z-index: 20; }
/* score pops: jokers clip their overflow and sit in a clipping scroll row, so
   their pop rises from inside the card instead of above it; the outermost
   playing cards on phones anchor their pop inwards (pop-l / pop-r from ui.js) */
.jcard.highlight { overflow: visible; }
.jcard .pop { top: 28%; }
.pop.pop-l { left: 0; animation-name: popup-l; }
.pop.pop-r { left: auto; right: 0; animation-name: popup-r; }
@keyframes popup-l { 0% { transform: translateY(8px) scale(0.7); opacity: 0; } 15% { transform: translateY(-2px) scale(1.12); opacity: 1; } 30% { transform: translateY(-6px) scale(1); } 75% { opacity: 1; } 100% { transform: translateY(-30px); opacity: 0; } }
@keyframes popup-r { 0% { transform: translateY(8px) scale(0.7); opacity: 0; } 15% { transform: translateY(-2px) scale(1.12); opacity: 1; } 30% { transform: translateY(-6px) scale(1); } 75% { opacity: 1; } 100% { transform: translateY(-30px); opacity: 0; } }
/* iOS zooms into any focused field under 16px */
:root.touch input, :root.touch textarea { font-size: 16px; }

/* ---------- shared phone sizing: portrait ≤640 wide, landscape ≤500 tall ---------- */
@media (max-width: 640px) and (orientation: portrait), (max-height: 500px) and (orientation: landscape) {
  :root { --card-w: 56px; --card-h: 75px; --joker-w: 50px; --joker-h: 67px; --hand-reserve: 20px; --sel-lift: -16px; }
  .pcard .corner { top: 3px; left: 4px; font-size: 15px; }
  .pcard .corner-br { bottom: 3px; right: 4px; font-size: 15px; }
  .pcard .corner small, .pcard .corner-br small { font-size: 12px; }
  .pcard .center { font-size: 24px; }
  .pcard.enh-wild .center { background-size: 30px 30px; }
  .pcard.debuffed::after { font-size: 28px; }
  .pcard, .jcard, .card-back { border-radius: 5px; }
  .hand-cards .pcard.selected, .hand-cards .pcard.selected:hover { transform: translateY(var(--sel-lift)); }
  .hand-cards .drop-caret { top: -6px; bottom: -6px; }
  /* legible: nothing under 11px */
  .jcard .badge { font-size: 11px; padding: 0 3px; max-width: calc(100% - 4px); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; top: 2px; left: 2px; }
  .jcard .status { font-size: 11px; padding: 1px 2px; }
  .pack-card .pack-name, .tooltip .tt-rarity, .slot-area .slot-label, .blind-col .tag-preview { font-size: 11px; }
  .kbd-hint { display: none; }
  /* cards dealt in from the right must not open a sideways scrollbar */
  .main, .pack-open, .shop, .blind-select { overflow-x: hidden; }
  .pack-cards .jcard, .shop-items .jcard { width: 64px; height: 86px; }
  /* tap targets ≥ 40px (the campaign's own buttons are left alone) */
  .btn:not(.conquest .btn) { min-height: 40px; }
  .btn.small:not(.conquest .btn) { padding: 6px 10px; font-size: 13px; }
  .btn.big { font-size: 17px; padding: 10px 14px; }
  .tag-chip { width: 40px; height: 40px; }
  /* modals always fit the dynamic viewport and scroll inside */
  #modal-root > .overlay { padding: max(8px, env(safe-area-inset-top)) max(8px, env(safe-area-inset-right)) max(8px, env(safe-area-inset-bottom)) max(8px, env(safe-area-inset-left)); }
  .panel { padding: 14px 12px; max-width: 100%; max-height: 100%; overscroll-behavior: contain; -webkit-overflow-scrolling: touch; }
  #modal-root .panel { max-height: calc(100dvh - 16px - env(safe-area-inset-top) - env(safe-area-inset-bottom)); }
  .overlay > .panel { min-width: min(320px, calc(100vw - 24px)) !important; } /* game-over's inline 360px */
  .panel h2 { font-size: 22px; margin-bottom: 8px; }
  .cashout { min-width: 0; width: min(380px, calc(100vw - 24px)); }
  .cashout .total { font-size: 24px; }
  .hands-table { font-size: 12px; }
  .hands-table td, .hands-table th { padding: 5px 4px; white-space: nowrap; }
  .hands-table td:nth-child(2) { white-space: normal; }
  .deck-view .pcard, .deck-view .pcard:hover { transform: scale(0.8); margin-right: calc(var(--card-w) * -0.2); margin-bottom: calc(var(--card-h) * -0.2); }
  .toasts { top: 6px; right: 8px; max-width: 72vw; }
  .toast { font-size: 13px; }
  .score-total { font-size: 28px; white-space: nowrap; }
  .pop { font-size: 13px; padding: 2px 6px; }
  /* scroll-snapping slot rows: jokers / consumables never overflow the page */
  .slot-cards { gap: 4px; scroll-snap-type: x proximity; overscroll-behavior-x: contain; scrollbar-width: none; min-height: var(--joker-h); }
  .slot-cards::-webkit-scrollbar { display: none; }
  .slot-cards > .jcard { scroll-snap-align: start; }
  /* menu */
  .menu { gap: 10px; padding: 10px 8px 0; }
  .menu img.logo { max-width: min(420px, 88vw); }
  .deck-grid { gap: 6px; }
  .deck-opt { width: calc((100% - 12px) / 3); max-width: 130px; padding: 6px 4px; }
  .deck-opt img { width: 48px; height: 64px; }
  .seed-row { flex-wrap: wrap; justify-content: center; width: 100%; max-width: 520px; }
  .seed-row input { flex: 1 1 140px; min-height: 44px; min-width: 0 !important; }
  .seed-row input[placeholder^="Save"] { width: auto; }
  /* the Play row sticks to the bottom of the scrolling menu, in thumb reach */
  .menu > .seed-row:not([style]) { position: sticky; bottom: 0; z-index: 2; padding: 8px; background: var(--felt-dark); border-radius: 10px 10px 0 0; box-shadow: 0 -4px 12px rgba(0,0,0,0.35); }
  .menu > .seed-row:last-child { padding-bottom: 12px; }
}

/* ---------- portrait phones: sidebar → compact top HUD ---------- */
@media (max-width: 640px) and (orientation: portrait) {
  :root { --top-row-h: 95px; }
  #app { flex-direction: column; }
  #app > .sidebar {
    width: auto; min-width: 0; flex: none; overflow: visible; padding: 6px 8px; gap: 5px;
    display: grid; grid-template-columns: repeat(12, minmax(0, 1fr)); align-items: stretch;
    box-shadow: 0 3px 10px rgba(0,0,0,0.4); z-index: 3;
  }
  .sidebar > * { min-width: 0; }
  .sidebar .stats-row { display: contents; }
  .sidebar .spacer, .sidebar .vouchers-box { display: none; }
  .sidebar .box { padding: 4px 6px; }
  /* HUD rows: [blind | score | money] [hand preview] [hands discards ante round | info options] [campaign] [tags] */
  .sidebar .blind-box { order: 1; } .sidebar .score-box { order: 2; } .sidebar .stat.money { order: 3; }
  .sidebar .hand-box { order: 4; } .sidebar .stat.hands { order: 5; }
  /* the hand preview row only matters while a hand can be played */
  body:not([data-phase="playing"]):not([data-phase="scoring"]) .sidebar .hand-box { display: none; } .sidebar .stat.discards { order: 6; }
  .sidebar .stat.ante { order: 7; } .sidebar .stat.round { order: 8; } .sidebar .run-btns { order: 9; }
  .sidebar > :not(.box):not(.stat):not(.stats-row):not(.run-btns) { order: 10; }
  .sidebar .tags-box { order: 11; }
  .sidebar .blind-box { grid-column: span 5; gap: 6px; min-height: 46px; }
  .sidebar .blind-box > img, .sidebar .blind-box > div[style] { width: 34px !important; height: 34px !important; margin: 0 !important; flex: none; }
  .sidebar .blind-box > div:last-child { min-width: 0; }
  .blind-box .blind-name { font-size: 13px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
  .blind-box .blind-req { font-size: 15px; white-space: nowrap; }
  .blind-box .blind-req small, .blind-box .blind-desc { display: none; }
  .blind-box .blind-reward { font-size: 11px; }
  .blind-box.is-boss .blind-name::after { content: ' \24D8'; opacity: 0.75; }
  .sidebar .score-box { grid-column: span 4; display: flex; flex-direction: column; justify-content: center; }
  .score-box .box-title { font-size: 11px; margin: 0; letter-spacing: 0; white-space: nowrap; }
  /* big scores wrap rather than being cut off */
  .score-box .score { font-size: 17px; line-height: 1.1; overflow-wrap: anywhere; }
  .sidebar .stat.money { grid-column: span 3; display: flex; align-items: center; justify-content: center; padding: 4px; }
  .stat.money .value { font-size: 22px; }
  .sidebar .hand-box { grid-column: 1 / -1; min-height: 48px; display: grid; grid-template-columns: minmax(0, 1fr) auto minmax(0, 0.85fr); column-gap: 8px; align-items: center; padding: 4px 8px; }
  .hand-box .hand-name { grid-column: 1; grid-row: 1; font-size: 15px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
  .hand-box .hand-level { grid-column: 1; grid-row: 2; }
  .hand-box .calc { grid-column: 2; grid-row: 1 / span 2; margin: 0; gap: 4px; }
  .calc .chips, .calc .mult { font-size: 17px; min-width: 50px; padding: 3px 6px; }
  .calc .x { font-size: 15px; }
  .hand-box .hand-score-preview { grid-column: 3; grid-row: 1 / span 2; margin: 0; gap: 0; text-align: right; min-width: 0; }
  .hand-score-preview small { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
  .hand-score-preview strong { font-size: 16px; }
  .sidebar .stat.hands, .sidebar .stat.discards, .sidebar .stat.ante, .sidebar .stat.round { grid-column: span 2; padding: 3px 2px; display: flex; flex-direction: column; justify-content: center; }
  .stat .label { font-size: 11px; }
  .stat .value { font-size: 18px; line-height: 1.1; }
  .stat.ante .value small { font-size: 11px; }
  .sidebar .run-btns { grid-column: span 4; gap: 4px; }
  #app .sidebar .run-btns .btn { padding: 2px; font-size: 12px; white-space: nowrap; min-width: 0; }
  .sidebar .conquest-open { grid-column: 1 / -1; } /* campaign button: full-width slot */
  .sidebar .tags-box { grid-column: 1 / -1; display: flex; align-items: center; gap: 6px; }
  .sidebar .tags-box .box-title { margin: 0; }
  .sidebar .kbd-hint { display: none; }

  .main { flex: 1; min-height: 0; }
  .main > .top-row, .main.campaign-main > .top-row { height: var(--top-row-h); min-height: 0; flex: none; padding: 6px 8px 0; gap: 6px; }
  .top-row .slot-area, .main.campaign-main > .top-row .slot-area { padding: 4px; min-height: calc(var(--joker-h) + 8px); margin-bottom: 14px; }
  .slot-area.consumables { flex: 0 0 auto; width: calc(var(--joker-w) * 2 + 4px + 8px); }
  .slot-area .slot-label { bottom: -15px; left: 4px; }

  /* table: hand + buttons pinned to the bottom (thumb zone) */
  .main > .table { padding: 4px 8px 6px; justify-content: flex-end; }
  .played-area { min-height: calc(var(--card-h) + 26px); padding-bottom: 10px; gap: 3px; }
  .hand-area { min-height: calc(var(--card-h) + 22px); padding: 18px 0 4px; }
  .table > .hand-helpers { order: 1; justify-content: flex-start; gap: 8px; padding: 2px 0 4px; }
  .table > .actions { order: 2; height: 56px; gap: 8px; padding: 2px 0 0; }
  .actions > .btn.big { flex: 1 1 0; max-width: 160px; min-height: 50px; padding: 8px 6px; }
  .actions .sort { gap: 2px; }
  .actions .sort .btn { padding: 4px 8px; }
  .deck-corner { right: 8px; bottom: 64px; display: flex; align-items: center; gap: 5px; min-height: 42px; font-size: 12px; }
  .deck-corner .card-back { width: 26px; height: 35px; border-width: 2px; margin: 0; }
  /* Royal Front slot (.cq-inline, a one-line strip on phones – css/conquest.css):
     it sits between the jokers and the table; the table takes the rest of the
     column so the hand and Play stay pinned to the bottom. If the campaign ever
     grows taller than the room left, the column scrolls instead of clipping. */
  .main > .cq-inline { flex: none; min-width: 0; }
  .main.campaign-main { overflow-y: auto; overflow-x: hidden; }
  .main.campaign-main > .table { flex: 1 0 auto; min-height: 0; padding-top: 4px; }

  /* blind select: stacked rows */
  .blind-select { flex-direction: column; justify-content: flex-start; align-items: stretch; gap: 8px; padding: 8px; overflow-y: auto; min-height: 0; }
  .blind-col { width: auto; display: grid; grid-template-columns: 46px minmax(0, 1fr) auto; column-gap: 10px; row-gap: 1px; align-items: center; text-align: left; padding: 8px 10px; flex: none; }
  .blind-col.current { transform: none; }
  .blind-col > * { grid-column: 2; }
  .blind-col > .name { grid-row: 1; min-height: 0; justify-content: flex-start; font-size: 15px; }
  .blind-col > :nth-child(2) { grid-column: 1; grid-row: 1 / span 4; width: 46px !important; height: 46px !important; margin: 0 !important; align-self: center; }
  .blind-col > .req { grid-row: 2; font-size: 17px; }
  .blind-col .req small { display: none; }
  .blind-col > .reward { grid-row: 3; font-size: 12px; margin: 0; }
  .blind-col > .desc { grid-row: 4; min-height: 0; font-size: 12px; }
  .blind-col > .btn, .blind-col > .status { grid-column: 3; grid-row: 1 / span 2; }
  .blind-col > div:has(> .tag-preview) { grid-column: 3; grid-row: 3 / span 2; display: flex; flex-direction: column; align-items: stretch; }
  .blind-col > .btn.gray { grid-column: 3; grid-row: 3 / span 2; }
  .blind-col .tag-preview { margin-top: 2px; justify-content: flex-end; }

  /* shop: items, then voucher + packs, then Next Round / Reroll at the bottom */
  .shop { padding: 6px 8px 8px; gap: 8px; }
  .shop-row { display: contents; }
  .shop-main { order: 0; min-height: 0; padding: 8px 4px; flex: none; }
  .shop-items { gap: 8px; }
  .shop-items .jcard { width: 64px; height: 86px; }
  .shop-item .buy-row { flex-direction: column; align-items: stretch; }
  .shop-bottom { order: 1; gap: 8px; flex: none; }
  .shop-box { padding: 6px; }
  .shop-box .title { font-size: 11px; }
  .shop-side { order: 2; width: auto; flex-direction: row; margin-top: auto; }
  .shop-side .btn { flex: 1; min-height: 48px; }
  .shop-packs { gap: 6px !important; }
  .pack-card, .vcard { width: 66px; height: 86px; }

  /* booster packs */
  .pack-open { justify-content: flex-start; gap: 6px; padding: 6px 8px; overflow-y: auto; min-height: 0; }
  .pack-open h2 { font-size: 20px; }
  /* one row even for Mega packs, so the hand (Death / Strength targets) stays on screen */
  .pack-cards { gap: 6px; flex-wrap: nowrap; }
  .pack-cards .jcard { width: 58px; height: 78px; }
  .pack-open > div:nth-child(5) { font-size: 12px; text-align: center; }
  .pack-open .hand-cards { margin-top: 16px; }
}

/* ---------- landscape phones: slim sidebar, one-screen table ---------- */
@media (max-height: 500px) and (orientation: landscape) {
  :root { --card-w: 56px; --card-h: 75px; --joker-w: 48px; --joker-h: 64px; --hand-reserve: 200px; --sel-lift: -14px; --top-row-h: 88px; }
  #app > .sidebar {
    width: 172px; min-width: 172px; padding: 6px; gap: 5px;
    display: grid; grid-template-columns: 1fr 1fr; align-content: start;
  }
  .sidebar > * { min-width: 0; }
  .sidebar .stats-row { display: contents; }
  .sidebar .spacer, .sidebar .vouchers-box, .sidebar .kbd-hint { display: none; }
  .sidebar .box { padding: 4px 6px; }
  .sidebar .blind-box, .sidebar .hand-box, .sidebar .run-btns, .sidebar .conquest-open, .sidebar .tags-box { grid-column: 1 / -1; }
  .sidebar .blind-box { order: 1; } .sidebar .score-box { order: 2; } .sidebar .stat.money { order: 3; }
  .sidebar .hand-box { order: 4; } .sidebar .stat.hands { order: 5; } .sidebar .stat.discards { order: 6; }
  .sidebar .stat.ante { order: 7; } .sidebar .stat.round { order: 8; } .sidebar .run-btns { order: 9; }
  .sidebar > :not(.box):not(.stat):not(.stats-row):not(.run-btns) { order: 10; }
  .sidebar .tags-box { order: 11; }
  .sidebar .conquest-open { font-size: 11px; line-height: 1.2; }
  body:not([data-phase="playing"]):not([data-phase="scoring"]) .sidebar .hand-box { display: none; }
  .sidebar .blind-box > img, .sidebar .blind-box > div[style] { width: 32px !important; height: 32px !important; margin: 0 !important; flex: none; }
  .sidebar .blind-box > div:last-child { min-width: 0; }
  .blind-box .blind-name { font-size: 13px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
  .blind-box .blind-req { font-size: 14px; white-space: nowrap; }
  .blind-box .blind-req small, .blind-box .blind-desc { display: none; }
  .blind-box .blind-reward { font-size: 11px; }
  .blind-box.is-boss .blind-name::after { content: ' \24D8'; opacity: 0.75; }
  .score-box .box-title { font-size: 11px; margin: 0; letter-spacing: 0; }
  .score-box .score { font-size: 16px; line-height: 1.1; overflow-wrap: anywhere; }
  .sidebar .stat.money { display: flex; align-items: center; justify-content: center; padding: 3px; }
  .stat.money .value { font-size: 19px; }
  .sidebar .hand-box { min-height: 0; padding: 4px 6px; }
  .hand-box .hand-name { font-size: 14px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
  .calc { margin-top: 2px; gap: 4px; }
  .calc .chips, .calc .mult { font-size: 15px; min-width: 0; flex: 1; padding: 2px 4px; }
  .calc .x { font-size: 13px; }
  .hand-score-preview { flex-direction: row; justify-content: space-between; align-items: baseline; gap: 4px; margin-top: 3px; }
  .hand-score-preview small { white-space: nowrap; }
  .hand-score-preview strong { font-size: 14px; text-align: right; }
  .sidebar .stat { padding: 2px; }
  .stat .label { font-size: 11px; }
  .stat .value { font-size: 16px; line-height: 1.1; }
  .stat.ante .value small { font-size: 11px; }
  .sidebar .run-btns { gap: 4px; }
  .sidebar .run-btns .btn { padding: 4px; }
  .sidebar .tags-box { display: flex; align-items: center; gap: 4px; }
  .sidebar .tags-box .box-title { display: none; }

  .main > .top-row, .main.campaign-main > .top-row { height: var(--top-row-h); min-height: 0; flex: none; padding: 4px 8px 0; gap: 6px; }
  .top-row .slot-area, .main.campaign-main > .top-row .slot-area { padding: 4px; min-height: calc(var(--joker-h) + 8px); margin-bottom: 12px; }
  .slot-area.consumables { flex: 0 0 auto; width: calc(var(--joker-w) * 2 + 4px + 8px); }
  .slot-area .slot-label { bottom: -14px; left: 4px; }
  /* table as a grid: played / hand / [actions | helpers] */
  .main > .table { display: grid; grid-template-columns: minmax(0, 1fr) auto; grid-template-areas: "played played" "hand hand" "actions helpers"; align-content: end; padding: 2px 8px 4px; position: relative; }
  .table > .played-area { grid-area: played; min-height: calc(var(--card-h) + 16px); padding-bottom: 6px; gap: 3px; }
  .table > .hand-area { grid-area: hand; min-height: 0; padding: 16px 0 2px; }
  .table > .actions { grid-area: actions; gap: 8px; padding: 2px 0; justify-content: flex-start; }
  .actions > .btn.big { min-width: 108px; padding: 8px 10px; }
  .actions .sort { flex-direction: row; gap: 4px; }
  .table > .hand-helpers { grid-area: helpers; padding: 2px 0; gap: 6px; align-items: center; }
  .deck-corner { top: 4px; right: 8px; bottom: auto; display: flex; align-items: center; gap: 5px; min-height: 40px; font-size: 12px; }
  .deck-corner .card-back { width: 24px; height: 32px; border-width: 2px; margin: 0; }
  .main > .cq-inline { flex: none; min-width: 0; }
  .main.campaign-main { overflow-y: auto; overflow-x: hidden; }
  .main.campaign-main > .table { flex: 1 0 auto; min-height: 0; }

  .blind-select { padding: 8px; gap: 8px; align-items: flex-start; overflow-y: auto; min-height: 0; }
  .blind-col { width: auto; flex: 1 1 0; min-width: 0; max-width: 210px; padding: 8px; }
  .blind-col.current { transform: none; }
  .blind-col img { width: 44px; height: 44px; margin: 2px auto; }
  .blind-col .name { min-height: 0; font-size: 15px; }
  .blind-col .req { font-size: 18px; }
  .blind-col .desc { min-height: 0; }
  .blind-col .reward { margin-bottom: 4px; }

  /* one row: [items | voucher | packs | Next Round / Reroll] */
  .shop { display: grid; grid-template-columns: minmax(0, 1fr) auto auto auto; align-items: stretch; padding: 6px 8px; gap: 6px; }
  .shop-row, .shop-bottom { display: contents; }
  .shop-main { grid-column: 1; grid-row: 1; min-height: 0; padding: 6px 4px; }
  .shop-bottom > .shop-box:first-child { grid-column: 2; grid-row: 1; }
  .shop-bottom > .shop-box:last-child { grid-column: 3; grid-row: 1; }
  .shop-side { grid-column: 4; grid-row: 1; width: 104px; }
  .shop-items .jcard { width: var(--joker-w); height: var(--joker-h); }
  .shop-side .btn { min-height: 48px; }
  .shop-items { gap: 6px; }
  .shop-item .buy-row { flex-direction: column; align-items: stretch; }
  .shop-box { padding: 4px 6px; }
  .shop-box .title { font-size: 11px; }
  .shop-packs { gap: 6px !important; }
  .pack-card, .vcard { width: 58px; height: 76px; }

  /* [title  Choose n  ·  Skip] / pack cards / hand */
  .pack-open { display: grid; grid-template-columns: auto auto 1fr auto; grid-template-areas: "title choose . skip" "cards cards cards cards" "hand hand hand hand";
    align-content: start; align-items: center; justify-items: center; gap: 4px 12px; padding: 4px 10px; overflow-y: auto; min-height: 0; }
  .pack-open > h2 { grid-area: title; font-size: 18px; }
  .pack-open > div:nth-child(2) { grid-area: choose; }
  .pack-open > .pack-cards { grid-area: cards; gap: 8px; flex-wrap: nowrap; }
  .pack-cards .jcard { width: 52px; height: 70px; }
  .pack-choice { gap: 4px; }
  .pack-open > .btn { grid-area: skip; }
  .pack-open > div:nth-child(5) { display: none; } /* hint line: no room */
  .pack-open > .hand-cards { grid-area: hand; margin-top: 14px; }
  .menu img.logo { max-height: 90px; width: auto; }
}
