/* ============================================================
   Gin Rummy — stylesheet
   Rules 7-9 / PART 55-61: this is the completed Canasta Rummy
   design system reused verbatim — tokens, spacing, typography,
   buttons, cards, panels, overlays, zone grid and the compact
   mobile layout — so the suite reads as one product. Gin-specific
   components are appended at the END rather than by forking the
   shared rules. Per Rule 10 the COMPOSITION is purpose-built for
   two players; only the look and feel is inherited.

   Renderer constraints carried over: no `gap`/`row-gap`/
   `column-gap`, no `inset:` shorthand, no double-position gradient
   colour stops. Spacing uses margins throughout.
   ============================================================ */
:root{
  --table-bg:#123D34;
  --table-deep:#0D3029;

  --text-primary:#F6F7F4;
  --text-secondary:#C7D0CC;
  --text-muted:#8E9A96;

  --action:#F0B84B;
  --action-text:#1A1F1D;

  --our-team:#62C4FF;
  --their-team:#D8B26A;

  --success:#62C58B;
  --danger:#E45B64;
  --frozen:#82C7E8;

  --card-bg:#FAFAF7;
  --card-black:#202322;
  --card-red:#D84A52;

  --line:rgba(255,255,255,.12);
  --line-soft:rgba(255,255,255,.07);
  --panel:rgba(0,0,0,.20);

  --space-1:4px;  --space-2:8px;  --space-3:12px;
  --space-4:16px; --space-5:24px; --space-6:32px;

  --radius:10px;

  /* Card geometry is driven by BOTH vw and vh so the composition is
     guaranteed to fit the viewport height, not just its width — the
     measured cause of the previous build's 300px desktop overflow. */
  /* PART 22: Gin shows 10-11 cards, not a Canasta-sized hand, so the
     cards can be bigger — 76-86px wide at desktop. */
  --card-w:clamp(48px, min(7vw, 11.7vh), 86px);
  --card-h:calc(var(--card-w) / .70);
  --pile-w:clamp(50px, min(6.4vw, 11.1vh), 82px);
  --pile-h:calc(var(--pile-w) / .70);
  --meld-w:clamp(30px, min(3.6vw, 6.3vh), 52px);
  --meld-h:calc(var(--meld-w) / .70);
  --back-w:clamp(20px, min(2.6vw, 4.6vh), 40px);
  --back-h:calc(var(--back-w) / .70);

  --font-ui:'Inter',-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,Helvetica,Arial,sans-serif;
  --font-mono:'IBM Plex Mono',ui-monospace,monospace;
  --font-display:'Playfair Display',Georgia,serif;
}

*{ box-sizing:border-box; }
html,body{ margin:0; padding:0; height:100%; }

body{
  font-family:var(--font-ui);
  color:var(--text-primary);
  background:radial-gradient(circle at 50% 45%, #174A40 0%, #123D34 60%, #0D3029 100%);
  height:100dvh;
  display:flex;
  flex-direction:column;
  overflow:hidden;
  padding-top:env(safe-area-inset-top);
  padding-bottom:env(safe-area-inset-bottom);
}
.mono{ font-family:var(--font-mono); }

/* ============================================================
   Five-zone frame (§8). Rows are sized so the middle table zone
   absorbs slack and the hand zone is protected last (§98).
   ============================================================ */
.game{
  flex:1 1 auto;
  min-height:0;
  /* A flex item defaults to min-width:auto and will refuse to shrink below
     its min-content width — measured as a 355px frame inside a 320px
     viewport, overflowing every zone by 25px. */
  min-width:0;
  width:min(1200px,100%);
  margin-left:auto; margin-right:auto;
  position:relative;
  display:grid;
  grid-template-rows:auto auto auto auto auto;
  align-content:center;
  align-content:safe center;
  padding:0 clamp(8px,1.6vw,22px);
}
.zone-header, .zone-seats, .zone-table, .zone-status, .zone-hand{
  min-width:0; min-height:0; overflow:hidden;
}

/* ---------------- ZONE 1 — header (45–55px) ---------------- */
.zone-header{
  min-height:46px;
  display:flex; align-items:center; justify-content:space-between;
  padding:var(--space-2) 0 var(--space-1);
  border-bottom:1px solid var(--line-soft);
}
.wordmark .title{
  font-family:var(--font-display); font-weight:800; font-style:italic;
  font-size:clamp(17px,2vw,24px); color:var(--action); white-space:nowrap;
}

.scoreline{ display:flex; align-items:baseline; justify-content:center; flex:1 1 auto; min-width:0; }
.scoreline > *{ margin-left:6px; }
.scoreline > *:first-child{ margin-left:0; }
.team-name{ font-size:12px; font-weight:600; letter-spacing:.04em; text-transform:uppercase; white-space:nowrap; }
.team-name.ours{ color:var(--our-team); }
.team-name.theirs{ color:var(--their-team); }
.team-total{ font-size:17px; font-weight:700; }
.score-dash{ color:var(--text-muted); font-size:13px; }

.header-controls{ display:flex; align-items:center; }
.header-controls > *{ margin-left:var(--space-2); }
.hand-pill{
  font-size:11px; color:var(--text-secondary);
  border:1px solid var(--line); border-radius:999px; padding:3px 9px; white-space:nowrap;
}
/* Icon-only utility buttons always carry a text label beneath the glyph. */
.icon-btn{
  display:flex; flex-direction:column; align-items:center; justify-content:center;
  min-width:44px; min-height:40px; padding:2px 6px;
  background:rgba(255,255,255,.06); border:1px solid var(--line);
  border-radius:var(--radius); color:var(--text-secondary); cursor:pointer;
  font-family:var(--font-ui);
}
.icon-btn:hover{ border-color:var(--action); color:var(--text-primary); }
.icon-btn .icon{ font-size:15px; line-height:1.1; }
.icon-btn .icon-label{ font-size:9px; letter-spacing:.06em; text-transform:uppercase; margin-top:1px; }

/* ---------------- ZONE 2 — partner + opponents (75–100px) ---------------- */
/* All three AI seats share ONE row: West | Partner | East, which also
   mirrors the physical table. Stacking partner above the opponents made
   this zone 173px against the brief's 75-100px budget, and the overspend
   was what forced the meld panels into internal scrolling. */
.zone-seats{
  display:grid;
  grid-template-columns:1fr auto 1fr;
  grid-template-areas:"west partner east";
  align-items:center;
  padding:var(--space-1) 0;
}
.seat-partner{ grid-area:partner; align-items:center; }
.seat-west{ grid-area:west; align-items:flex-start; }
.seat-east{ grid-area:east; align-items:flex-end; }

.seat{ display:flex; flex-direction:column; min-width:0; max-width:100%; overflow:hidden; }
.seat-head{ display:flex; align-items:center; }
.seat-head > *{ margin-left:5px; }
.seat-head > *:first-child{ margin-left:0; }
.seat-dot{
  width:7px; height:7px; border-radius:50%;
  background:transparent; border:1px solid var(--line);
}
.seat.is-acting .seat-dot{ background:var(--action); border-color:var(--action); }
.seat-name{ font-size:13px; font-weight:600; color:var(--text-secondary); white-space:nowrap; }
.seat.is-acting .seat-name{ color:var(--text-primary); font-weight:700; }
.seat-partner .seat-name{ color:var(--our-team); }
.seat-west .seat-name, .seat-east .seat-name{ color:var(--their-team); }
.seat-west .seat-backs .card-back, .seat-east .seat-backs .card-back{
  width:calc(var(--back-w) * .78); height:calc(var(--back-h) * .78);
}
.seat-count{
  font-size:11px; color:var(--text-muted);
  border:1px solid var(--line-soft); border-radius:999px; padding:1px 6px;
}
.seat-backs{ display:flex; margin-top:3px; min-height:2px; }
.seat-backs .card-back{ margin-left:calc(var(--back-w) * -.62); }
.seat-backs .card-back:first-child{ margin-left:0; }
.seat-action{
  font-size:11px; color:var(--text-muted); margin-top:2px;
  max-width:100%; overflow:hidden; text-overflow:ellipsis; white-space:nowrap;
}
.seat.is-acting{ }

/* ---------------- ZONE 3 — main table (220–250px) ---------------- */
.zone-table{
  min-height:0;
  align-items:start;
  display:grid;
  grid-template-columns:minmax(0,1fr) minmax(0,.78fr) minmax(0,1.2fr);
  align-items:stretch;
}
.zone-table > * + *{ margin-left:clamp(8px,1.5vw,22px); }

/* --- meld panels --- */
.meldpanel{ min-width:0; min-height:0; display:flex; flex-direction:column; }
.meldpanel-head{
  display:flex; align-items:baseline; width:100%;
  background:transparent; border:none; padding:0 0 4px;
  border-bottom:1px solid var(--line-soft);
  color:inherit; font-family:var(--font-ui); cursor:default; text-align:left;
}
.meldpanel-head > *{ margin-left:6px; }
.meldpanel-head > *:first-child{ margin-left:0; }
.panel-title{ font-size:13px; font-weight:600; letter-spacing:.05em; text-transform:uppercase; white-space:nowrap; }
.meldpanel.ours .panel-title{ color:var(--our-team); }
.meldpanel.theirs .panel-title{ color:var(--their-team); }
.panel-sub{ font-size:11px; color:var(--text-muted); white-space:nowrap; }
.panel-count{
  font-size:11px; color:var(--text-secondary); margin-left:auto;
  border:1px solid var(--line-soft); border-radius:999px; padding:0 6px;
}
.panel-chevron{ font-size:10px; color:var(--text-muted); display:none; }

.red3-row{ display:flex; align-items:center; flex-wrap:wrap; min-height:0; }
.red3-row:not(:empty){ margin-top:4px; }
.red3-chip{
  display:flex; align-items:center; font-size:11px; font-weight:600;
  border:1px solid var(--line); border-radius:999px; padding:1px 8px; margin-right:6px;
}
.red3-chip.bonus{ color:var(--success); border-color:rgba(98,197,139,.45); }
.red3-chip.penalty{ color:var(--danger); border-color:rgba(228,91,100,.45); }

.meldlist{
  margin-top:6px; min-height:0; flex:0 1 auto; max-height:100%;
  display:flex; flex-wrap:wrap; align-content:flex-start;
  overflow-y:auto; overflow-x:hidden;
}
.meldlist::-webkit-scrollbar{ width:4px; }
.meldlist::-webkit-scrollbar-thumb{ background:var(--line); border-radius:2px; }
.meldlist-empty{ font-size:11px; color:var(--text-muted); font-style:italic; }

.meld{ margin-right:10px; margin-bottom:8px; max-width:100%; }
.meld-header{ display:flex; align-items:baseline; margin-bottom:2px; }
.meld-header > *{ margin-left:5px; }
.meld-header > *:first-child{ margin-left:0; }
.meld-rank{ font-size:12px; font-weight:700; color:var(--text-primary); }
.meld-note{ font-size:10px; color:var(--text-muted); letter-spacing:.04em; text-transform:uppercase; white-space:nowrap; }
.meld.is-canasta .meld-note{ color:var(--success); font-weight:600; }
.meld.is-canasta-mixed .meld-note{ color:var(--their-team); }
.meld-cards{ display:flex; }
.meld-cards > * + *{ margin-left:calc(var(--meld-w) * -.52); }
.meld.is-target .meld-cards{ box-shadow:0 0 0 2px var(--action); border-radius:6px; }
.meld.is-clickable{ cursor:pointer; }

/* --- stock / discard --- */
.zone-piles{
  min-width:0; display:flex; flex-direction:column;
  align-items:center; justify-content:flex-start;
}
.piles{ display:flex; align-items:flex-start; justify-content:center; }
.piles > * + *{ margin-left:clamp(10px,1.6vw,22px); }
.pile{ display:flex; flex-direction:column; align-items:center; }
.pile-card{
  position:relative; width:var(--pile-w); height:var(--pile-h);
  border-radius:8px;
}
.pile-card.stock{ border:2px dashed var(--line); }
.pile-card.stock.has-cards{ border:none; }
.pile-card:focus-visible{ outline:3px solid var(--action); outline-offset:2px; }
.pile-card.is-actionable{ cursor:pointer; box-shadow:0 0 0 2px var(--action), 0 6px 16px rgba(0,0,0,.35); }
.pile-card .card-back{ position:absolute; top:0; left:0; width:var(--pile-w); height:var(--pile-h); }
/* Depth must fall BEHIND the top card. Offsetting by nth-child pushed the
   topmost back right-and-up, leaving the cards beneath exposed along the
   left edge — their white borders read as a clipped card. Counting from the
   end keeps the top card flush at the container origin for any pile depth. */
.pile-card .card-back:last-child{ top:0; left:0; }
.pile-card .card-back:nth-last-child(2){ top:2px; left:2px; }
.pile-card .card-back:nth-last-child(3){ top:4px; left:4px; }
.pile-card .card{ width:var(--pile-w); height:var(--pile-h); }
.pile-empty-note{
  position:absolute; top:50%; left:0; right:0; transform:translateY(-50%);
  text-align:center; font-size:10px; color:var(--text-muted);
}
.pile-meta{ display:flex; align-items:baseline; margin-top:5px; }
.pile-meta > * + *{ margin-left:5px; }
.pile-name{ font-size:11px; letter-spacing:.06em; text-transform:uppercase; color:var(--text-muted); }
.pile-meta .mono{ font-size:12px; color:var(--text-secondary); font-weight:600; }
.pile-state{ margin-top:8px; text-align:center; min-height:16px; }
.pile-flag{
  display:inline-flex; align-items:center; font-size:12px; font-weight:600;
  border-radius:999px; padding:2px 10px;
}
.pile-flag.frozen{ color:var(--frozen); border:1px solid rgba(130,199,232,.45); background:rgba(130,199,232,.08); }
.pile-flag.blocked{ color:var(--danger); border:1px solid rgba(228,91,100,.45); }
.pile-flag.takeable{ color:var(--success); border:1px solid rgba(98,197,139,.45); }

/* ---------------- ZONE 4 — status / current action (55–75px) ---------------- */
.zone-status{
  padding:var(--space-2) 0 var(--space-1);
  border-top:1px solid var(--line-soft);
  text-align:center;
}
.status-strip{
  font-size:12px; color:var(--text-secondary);
  display:flex; align-items:center; justify-content:center; flex-wrap:wrap; min-height:16px;
}
.status-strip .chip{ white-space:nowrap; }
.status-strip .chip + .chip::before{
  content:'·'; color:var(--text-muted); margin-left:8px; margin-right:8px;
}
.status-strip .chip.met{ color:var(--success); font-weight:600; }
.status-strip .chip.unmet{ color:var(--action); font-weight:600; }

.action-line{ display:flex; align-items:center; justify-content:center; flex-wrap:wrap; margin-top:3px; }
.current-action{
  font-size:clamp(15px,1.6vw,20px); font-weight:700; letter-spacing:.01em;
  color:var(--text-primary);
}
.turn-steps{
  display:flex; list-style:none; margin:0; padding:0; margin-left:var(--space-4);
  font-size:11px; letter-spacing:.06em; text-transform:uppercase; color:var(--text-muted);
}
.turn-steps li{ display:flex; align-items:center; margin-left:10px; }
.turn-steps li:first-child{ margin-left:0; }
.turn-steps li + li::before{ content:'\2192'; margin-right:10px; color:var(--line); }
.step-mark{
  width:8px; height:8px; border-radius:50%; border:1px solid var(--line); margin-right:5px;
}
.turn-steps li.is-current{ color:var(--text-primary); font-weight:600; }
.turn-steps li.is-current .step-mark{ background:var(--action); border-color:var(--action); }
.turn-steps li.is-done{ color:var(--success); }
.turn-steps li.is-done .step-mark{ background:var(--success); border-color:var(--success); }

.explain{
  font-size:12px; color:var(--action); min-height:15px; margin-top:2px;
  padding-left:var(--space-3); padding-right:var(--space-3);
}
.explain.is-error{ color:var(--danger); }

/* ---------------- ZONE 5 — human hand (210–250px) ---------------- */
.zone-hand{
  display:flex; flex-direction:column; justify-content:flex-end;
  padding-bottom:var(--space-2);
}
.hand{
  display:flex; flex-direction:column; align-items:center; justify-content:flex-end;
  width:min(940px,100%); margin-left:auto; margin-right:auto;
  padding-top:16px; /* room for the lift on selected cards */
}
.hand-row{ display:flex; justify-content:center; }
.hand-row + .hand-row{ margin-top:6px; }
.hand-row .card{ cursor:pointer; }
.hand .card{ width:var(--card-w); height:var(--card-h); }
.hand .card.selected{
  transform:translateY(-14px); z-index:20;
  box-shadow:0 0 0 3px var(--action), 0 8px 18px rgba(0,0,0,.28);
}
.hand .card:focus-visible{ outline:3px solid var(--action); outline-offset:2px; }

.actionbar{
  display:flex; align-items:center; justify-content:space-between;
  width:min(940px,100%); margin-left:auto; margin-right:auto; margin-top:var(--space-2);
}
.selection-info{ font-size:12px; color:var(--text-secondary); white-space:nowrap; margin-right:var(--space-3); }
.selection-info strong{ color:var(--text-primary); }
.action-buttons{ display:flex; align-items:center; }
.action-buttons > * + *{ margin-left:var(--space-2); }

/* ---------------- buttons ---------------- */
.btn{
  font-family:var(--font-ui); font-weight:700; font-size:15px;
  min-height:44px; padding:10px 18px;
  border-radius:var(--radius); border:1px solid var(--line);
  background:rgba(255,255,255,.06); color:var(--text-primary);
  cursor:pointer; white-space:nowrap;
  transition:transform .08s ease, box-shadow .15s ease, background .15s ease;
}
.btn:hover{ background:rgba(255,255,255,.11); }
.btn:active{ transform:translateY(1px); }
.btn:focus-visible{ outline:3px solid var(--action); outline-offset:2px; }
.btn.secondary{
  background:rgba(255,255,255,.06); border:1px solid var(--line-soft); color:var(--text-secondary);
  font-weight:600; font-size:13px; padding:10px 14px;
}
/* Exactly one gold action at a time (§87) — applied by the controller. */
.btn.is-primary-action{
  background:var(--action); color:var(--action-text); border-color:var(--action);
  box-shadow:0 6px 16px rgba(240,184,75,.25);
}
.btn.is-primary-action:hover{ background:#F5C86B; }
.btn[hidden]{ display:none; }
.btn:disabled{ opacity:.38; cursor:not-allowed; transform:none; box-shadow:none; }
.btn.wide{ width:100%; margin-top:var(--space-3); }

/* ============================================================
   Cards
   ============================================================ */
.card{
  position:relative; width:var(--card-w); height:var(--card-h);
  border-radius:6px; background:var(--card-bg);
  box-shadow:0 3px 8px rgba(0,0,0,.35), inset 0 0 0 1px rgba(0,0,0,.08);
  display:inline-flex; align-items:center; justify-content:center;
  user-select:none; overflow:hidden; flex:0 0 auto;
  transition:transform .12s ease, box-shadow .12s ease;
}
.card.red{ color:var(--card-red); }
.card:not(.red){ color:var(--card-black); }
.card-corner{
  position:absolute; font-family:var(--font-mono); font-weight:700;
  font-size:calc(var(--card-w) * .21); line-height:1.02; text-align:center;
}
.card-corner-top{ top:3px; left:4px; }
.card-corner-bottom{ bottom:3px; right:4px; transform:rotate(180deg); }
.card-centre-suit{ font-size:calc(var(--card-w) * .36); opacity:.85; }
.court-figure{ width:72%; height:62%; display:block; }
.card .wild-tag{
  position:absolute; bottom:2px; left:0; right:0; text-align:center;
  font-family:var(--font-mono); font-size:8px; letter-spacing:.08em;
  color:var(--text-muted);
}

.meld-cards .card{ width:var(--meld-w); height:var(--meld-h); }
.meld-cards .card .card-corner{ font-size:calc(var(--meld-w) * .27); }
.meld-cards .card .card-centre-suit{ font-size:calc(var(--meld-w) * .40); }
.meld-cards .card:not(:last-child) .card-corner-bottom{ display:none; }

.card-back{
  width:var(--back-w); height:var(--back-h); border-radius:6px;
  background:#8E2C3A;
  background-image:
    repeating-linear-gradient(45deg, rgba(250,250,247,.75) 0px, rgba(250,250,247,.75) 1px, transparent 1px, transparent 8px),
    repeating-linear-gradient(-45deg, rgba(250,250,247,.75) 0px, rgba(250,250,247,.75) 1px, transparent 1px, transparent 8px);
  border:2px solid var(--card-bg);
  box-shadow:0 2px 6px rgba(0,0,0,.4);
  flex:0 0 auto;
}

/* ============================================================
   Overlays — scoped to .game, never the whole page
   ============================================================ */
.overlay{
  position:absolute; top:0; left:0; right:0; bottom:0; z-index:40;
  display:none; align-items:center; justify-content:center;
  background:rgba(6,18,15,.82);
  padding:var(--space-4);
}
.overlay.open{ display:flex; }
.overlay-panel{
  background:linear-gradient(165deg,#174A3F 0%,#0D3029 100%);
  border:1px solid var(--line); border-radius:16px;
  box-shadow:0 24px 60px rgba(0,0,0,.55);
  padding:var(--space-5); width:min(440px,100%); max-height:100%;
  overflow-y:auto; text-align:center;
}
.overlay-panel.wide-panel{ width:min(560px,100%); }
.overlay-panel h2{
  font-family:var(--font-display); font-style:italic; color:var(--action);
  margin:0 0 6px; font-size:23px;
}
.overlay-panel p.sub{ font-size:12px; color:var(--text-secondary); margin:0 0 var(--space-4); }

/* end-of-hand breakdown (§130) */
.summary-grid{ text-align:left; }
.summary-team{ margin-bottom:var(--space-4); }
.summary-team h3{
  font-size:12px; letter-spacing:.06em; text-transform:uppercase;
  margin:0 0 6px; padding-bottom:4px; border-bottom:1px solid var(--line-soft);
}
.summary-team.ours h3{ color:var(--our-team); }
.summary-team.theirs h3{ color:var(--their-team); }
.summary-row{
  display:flex; justify-content:space-between; align-items:baseline;
  font-size:13px; padding:3px 0; color:var(--text-secondary);
}
.summary-row .val{ font-family:var(--font-mono); font-weight:600; color:var(--text-primary); }
.summary-row .val.pos{ color:var(--success); }
.summary-row .val.neg{ color:var(--danger); }
.summary-row.total{
  margin-top:5px; padding-top:6px; border-top:1px solid var(--line-soft);
  font-weight:700; color:var(--text-primary); font-size:14px;
}
.running-total{
  display:flex; justify-content:space-between; align-items:baseline;
  border-top:1px solid var(--line); padding-top:var(--space-3); margin-top:var(--space-2);
  font-size:14px;
}
.running-total .rt-pair{ display:flex; flex-direction:column; align-items:flex-start; }
.running-total .rt-label{ font-size:11px; letter-spacing:.06em; text-transform:uppercase; color:var(--text-muted); }
.running-total .rt-val{ font-family:var(--font-mono); font-weight:700; font-size:20px; }
.win-stats{ font-size:13px; color:var(--text-secondary); margin-bottom:var(--space-2); }

.rules-panel{ text-align:left; }
.rules-panel h2, .rules-panel p.sub{ text-align:center; }
.rules-list{ list-style:none; margin:0; padding:0; }
.rules-list li{
  font-size:12.5px; line-height:1.5; color:var(--text-secondary);
  padding:7px 0; border-bottom:1px solid var(--line-soft);
}
.rules-list li:last-child{ border-bottom:none; }

footer{
  flex:0 0 auto;
  text-align:center; font-size:10px; color:#5f716b;
  line-height:1.4; padding:5px 12px;
  max-width:820px; margin-left:auto; margin-right:auto;
}

/* ============================================================
   COMPACT LAYOUT — mobile portrait recomposition (§102–§120).
   Driven by the game container's measured width, so it behaves
   correctly inside an iframe rather than tracking device width.
   Order: action → piles → our melds → hand, with Their Melds
   collapsible because it is the least directly actionable.
   ============================================================ */
.game[data-layout="compact"]{
  --card-w:clamp(50px, 15.2vw, 68px);
  --pile-w:clamp(52px, 15.5vw, 68px);
  --meld-w:clamp(26px, 8.2vw, 38px);
  --back-w:clamp(16px, 4.6vw, 24px);
  /* The height tokens MUST be restated here. A custom property is
     substituted where it is declared, so --card-h declared on :root
     resolves against the :root --card-w and would ignore the overrides
     above — which measured as 63x66 cards (nearly square) on mobile. */
  --card-h:calc(var(--card-w) / .70);
  --pile-h:calc(var(--pile-w) / .70);
  --meld-h:calc(var(--meld-w) / .70);
  --back-h:calc(var(--back-w) / .70);
  padding:0 10px;
  /* Rows size to content; the block centres. Slot 3 is the table zone. */
  grid-template-rows:auto auto auto auto auto;
}
/* Status sits directly above the hand on mobile, so the current action is
   next to the cards the player is touching (§115) — not stranded at the
   top of the screen. Explicit order on every zone; relying on order:0 for
   the rest had pushed the status zone above the header. */
.game[data-layout="compact"] .zone-header{ order:1; min-height:42px; }
.game[data-layout="compact"] .zone-seats{ order:2; }
.game[data-layout="compact"] .zone-table{ order:3; }
.game[data-layout="compact"] .zone-status{
  order:4; border-top:1px solid var(--line-soft); padding:5px 0 4px;
}
.game[data-layout="compact"] .zone-hand{ order:5; padding-bottom:6px; }
.game[data-layout="compact"] .wordmark{ display:none; }
.game[data-layout="compact"] .scoreline{ justify-content:flex-start; }
.game[data-layout="compact"] .team-name{ font-size:10px; }
.game[data-layout="compact"] .team-total{ font-size:15px; }
.game[data-layout="compact"] .hand-pill{ display:none; }
.game[data-layout="compact"] .icon-btn{ min-width:40px; min-height:38px; }

/* Partner + opponents collapse to one compact row (§117). */
.game[data-layout="compact"] .zone-seats{
  display:flex; align-items:center; justify-content:space-between;
  padding:5px 0;
}
.game[data-layout="compact"] .seat{ align-items:center; }
.game[data-layout="compact"] .seat-head > *{ margin-left:4px; }
.game[data-layout="compact"] .seat-name{ font-size:11px; }
.game[data-layout="compact"] .seat-count{ font-size:10px; padding:0 5px; }
.game[data-layout="compact"] .seat-backs{ display:none; }
.game[data-layout="compact"] .seat-action{ display:none; }

.game[data-layout="compact"] .action-line{ flex-direction:column; }
.game[data-layout="compact"] .turn-steps{ display:none; }
.game[data-layout="compact"] .explain{
  font-size:11px; line-height:1.25; max-height:28px; overflow:hidden;
  padding-left:4px; padding-right:4px;
}
.game[data-layout="compact"] .status-strip{ min-height:14px; }
.game[data-layout="compact"] .turn-steps{ margin-left:0; margin-top:4px; }
.game[data-layout="compact"] .current-action{ font-size:clamp(15px,4.4vw,19px); }
.game[data-layout="compact"] .status-strip{ font-size:11px; }

.game[data-layout="compact"] .zone-table{
  display:flex; flex-direction:column; min-height:0;
}
.game[data-layout="compact"] .zone-table > * + *{ margin-left:0; margin-top:8px; }
.game[data-layout="compact"] .zone-piles{ order:1; }
/* Our Melds must win the space fight against Their Melds: measured at
   320px it had collapsed to 0px height while theirs kept 89px. */
.game[data-layout="compact"] .zone-piles{ flex:0 0 auto; }
.game[data-layout="compact"] .meldpanel.ours{ order:2; flex:0 1 auto; min-height:64px; }
.game[data-layout="compact"] .meldpanel.theirs{ order:3; flex:0 0 auto; max-height:34%; }

.game[data-layout="compact"] .meldpanel-head{ cursor:pointer; padding-bottom:5px; }
.game[data-layout="compact"] .panel-chevron{ display:inline; margin-left:6px; transition:transform .15s ease; }
.game[data-layout="compact"] .panel-sub{ display:none; }
.game[data-layout="compact"] .meldpanel.is-collapsed .meldlist{ display:none; }
.game[data-layout="compact"] .meldpanel.is-collapsed .red3-row{ display:none; }
.game[data-layout="compact"] .meldpanel.is-collapsed .panel-chevron{ transform:rotate(-90deg); }
.game[data-layout="compact"] .piles > * + *{ margin-left:22px; }

.game[data-layout="compact"] .actionbar{ flex-direction:row; align-items:center; }
.game[data-layout="compact"] .selection-info{ font-size:11px; margin-right:8px; }
.game[data-layout="compact"] .action-buttons{ justify-content:center; }
.game[data-layout="compact"] .action-buttons .btn{ flex:1 1 auto; min-height:48px; }
.game[data-layout="compact"] .hand .card.selected{ transform:translateY(-16px); }
body[data-layout="compact"] footer{ font-size:9px; padding:3px 10px; line-height:1.3; }

/* ============================================================
   Accessibility
   ============================================================ */
@media (prefers-reduced-motion: reduce){
  *{ transition-duration:.01ms !important; animation-duration:.01ms !important; }
  .hand .card.selected{ transform:none; }
}

/* Compressed meld tail on mobile (§71, §107) — a completed canasta shows a
   short stack plus a count rather than seven overlapping cards. */
.meld-more{
  display:inline-flex; align-items:center; justify-content:center;
  margin-left:6px; padding:0 6px; height:var(--meld-h);
  font-family:var(--font-mono); font-size:11px; font-weight:700;
  color:var(--text-secondary); background:rgba(255,255,255,.08);
  border:1px solid var(--line); border-radius:6px;
}

/* Final compact trims: reclaim the last vertical slack for Our Melds. */
.game[data-layout="compact"] .pile-state{ margin-top:4px; min-height:14px; }
.game[data-layout="compact"] .pile-flag{ font-size:11px; padding:1px 8px; }
.game[data-layout="compact"] .pile-meta{ margin-top:3px; }
.game[data-layout="compact"] .hand{ padding-top:12px; }
.game[data-layout="compact"] .meldlist{ margin-top:4px; }

/* Their Melds sheet (mobile). Scrolls inside the panel, never the table. */
.sheet-meldlist{ max-height:46vh; overflow-y:auto; margin-bottom:var(--space-3); }
.game[data-layout="compact"] .meldpanel.theirs .meldlist{ display:none; }
.game[data-layout="compact"] .meldpanel.theirs .red3-row{ display:none; }
.game[data-layout="compact"] .meldpanel.theirs .panel-chevron{ transform:rotate(-90deg); }

/* §144 — meld the current selection would extend. Softer than an explicit
   tap target, because the player has not chosen it yet. */
.meld.is-suggested .meld-cards{
  box-shadow:0 0 0 2px rgba(240,184,75,.45); border-radius:6px;
}

/* §67 recent-turn log */
.turnlog{ list-style:none; margin:0 0 var(--space-3); padding:0; text-align:left; max-height:44vh; overflow-y:auto; }
.turnlog li{
  font-size:12.5px; line-height:1.45; color:var(--text-secondary);
  padding:7px 0; border-bottom:1px solid var(--line-soft);
}
.turnlog li:last-child{ border-bottom:none; }
.turnlog li.is-you{ color:var(--text-primary); font-weight:600; }
.turnlog-empty{ font-size:12px; color:var(--text-muted); font-style:italic; }

/* §148 expanded meld */
.meld-detail-cards{
  display:flex; flex-wrap:wrap; justify-content:center; margin-bottom:var(--space-3);
}
.meld-detail-cards .card{
  width:clamp(40px,11vw,58px); height:auto; aspect-ratio:.70;
  margin:3px;
}

/* §21 — manual card arrangement */
.hand .card.is-dragging{
  z-index:60; opacity:.92; cursor:grabbing;
  box-shadow:0 0 0 3px var(--action), 0 14px 26px rgba(0,0,0,.42);
}
.hand .card.drop-before{ box-shadow:-3px 0 0 0 var(--action), 0 3px 8px rgba(0,0,0,.35); }
.hand .card.drop-after{ box-shadow:3px 0 0 0 var(--action), 0 3px 8px rgba(0,0,0,.35); }

/* §70 — compact the melds before ever resorting to an internal scrollbar.
   Density is stepped up by the controller only while the panel overflows. */
.meld{ margin-right:8px; margin-bottom:6px; }
.meldlist[data-density="1"]{ --meld-w:clamp(26px, min(3.1vw, 5.4vh), 44px); --meld-h:calc(var(--meld-w) / .70); }
.meldlist[data-density="1"] .meld{ margin-right:6px; margin-bottom:4px; }
.meldlist[data-density="1"] .meld-note{ font-size:9px; }
.meldlist[data-density="2"]{ --meld-w:clamp(22px, min(2.7vw, 4.7vh), 38px); --meld-h:calc(var(--meld-w) / .70); }
.meldlist[data-density="2"] .meld{ margin-right:5px; margin-bottom:3px; }
.meldlist[data-density="2"] .meld-header{ margin-bottom:0; }
.meldlist[data-density="2"] .meld-note{ font-size:9px; }
.meldlist[data-density="1"] .meld-card, .meldlist[data-density="2"] .meld-card{ }

/* Density 3 — text-only meld summaries for the tightest panels. Rank,
   natural/mixed status and card count are all still shown in words. */
.meldlist[data-density="3"] .meld-cards{ display:none; }
.meldlist[data-density="3"] .meld{
  margin-right:8px; margin-bottom:2px;
  border:1px solid var(--line-soft); border-radius:6px; padding:1px 6px;
}
.meldlist[data-density="3"] .meld-header{ margin-bottom:0; }
.meldlist[data-density="3"] .meld-rank{ font-size:11px; }
.meldlist[data-density="3"] .meld-note{ font-size:9px; }

/* Action bar: utilities separate from the contextual primary actions. */
.bar-utility{ display:flex; align-items:center; }
.utility-buttons{ display:flex; align-items:center; margin-left:var(--space-2); }
.utility-buttons > * + *{ margin-left:var(--space-2); }
.game[data-layout="compact"] .actionbar{ flex-direction:column; align-items:stretch; }
.game[data-layout="compact"] .bar-utility{ justify-content:space-between; margin-bottom:6px; }
.game[data-layout="compact"] .utility-buttons .btn{ min-height:38px; padding:7px 12px; font-size:12px; }
.game[data-layout="compact"] .action-buttons{ width:100%; }
.game[data-layout="compact"] .action-buttons .btn{ flex:1 1 0; min-width:0; padding:10px 8px; }
/* Long contextual labels must shrink rather than push the row off-screen. */
.game[data-layout="compact"] .action-buttons .btn{
  overflow:hidden; text-overflow:ellipsis;
}

/* ============================================================
   GIN RUMMY — game-specific components.
   Gin should read as SIMPLER than Canasta, not different (PART 105).
   ============================================================ */

/* PART 5/67 — two-player content stays concentrated centrally rather
   than spread across the full 1200px. */
.zone-seats, .zone-table, .zone-status, .hand, .actionbar{
  width:min(900px,100%); margin-left:auto; margin-right:auto;
}
.game[data-layout="compact"] .zone-seats,
.game[data-layout="compact"] .zone-table,
.game[data-layout="compact"] .zone-status{ width:100%; }

/* PART 11/12/85 — a single compact opponent. */
.zone-seats{ display:flex; flex-direction:column; align-items:center; padding:var(--space-2) 0; }
.opp-backs{ display:flex; justify-content:center; margin-top:4px; }
.opp-backs .card-back{ width:clamp(30px,3.6vw,46px); height:calc(clamp(30px,3.6vw,46px) / .70); }
.opp-backs .card-back + .card-back{ margin-left:-26px; }
.game[data-layout="compact"] .opp-backs .card-back{ width:26px; height:37px; }
.game[data-layout="compact"] .opp-backs .card-back + .card-back{ margin-left:-16px; }

/* PART 15/81 — stock and discard are one decision: always side by side. */
.zone-table{ display:flex; align-items:center; justify-content:center; min-height:0; }
.piles > * + *{ margin-left:clamp(34px,6vw,80px); }

/* PART 29/30/32 — deadwood lives beside the hand, never in the header. */
.deadwood-line{
  display:flex; align-items:baseline; justify-content:center; flex-wrap:wrap;
  margin-top:2px;
}
.deadwood-line .dw-btn{
  background:none; border:none; padding:0; cursor:pointer;
  font-family:var(--font-ui); font-size:clamp(15px,1.5vw,19px); font-weight:700;
  color:var(--text-primary); text-decoration:underline dotted rgba(255,255,255,.3);
}
.deadwood-line .dw-thresh{ font-size:12.5px; color:var(--text-muted); margin-left:8px; }
.deadwood-line .dw-flag{
  font-size:12px; font-weight:700; letter-spacing:.04em; text-transform:uppercase;
  border-radius:999px; padding:2px 10px; margin-left:10px;
}
.dw-flag.knock{ color:var(--action); border:1px solid rgba(240,184,75,.5); background:rgba(240,184,75,.08); }
.dw-flag.gin{ color:var(--success); border:1px solid rgba(98,197,139,.5); background:rgba(98,197,139,.09); }
.deadwood-breakdown{
  font-family:var(--font-mono); font-size:12px; color:var(--text-secondary);
  text-align:center; margin-top:3px; min-height:15px;
}

/* PART 26-28 — meld vs deadwood made visible in the hand itself, using
   spacing and a thin underline rather than tinting whole cards. */
.hand-group{ display:flex; align-items:flex-end; }
.hand-group + .hand-group{ margin-left:clamp(14px,2vw,24px); }
.hand-group.is-deadwood{ margin-left:clamp(22px,3.2vw,32px); }
.hand-group-label{
  font-size:9.5px; font-weight:700; letter-spacing:.09em; text-transform:uppercase;
  text-align:center; margin-top:4px; color:var(--text-muted);
  white-space:nowrap; overflow:visible;
}
.hand-group.is-run .hand-group-label,
.hand-group.is-set .hand-group-label{ color:var(--success); }
.hand-group-wrap{ display:flex; flex-direction:column; }
.hand-group.is-run .hand-group-cards,
.hand-group.is-set .hand-group-cards{ box-shadow:0 2px 0 0 var(--success); border-radius:2px; }
.hand-group-cards{ display:flex; align-items:flex-end; padding-bottom:3px; }

/* PART 13/14/47 — opponent's visible actions. */
.last-action{
  font-size:12px; color:var(--text-secondary); text-align:center;
  margin-top:3px; max-width:100%; overflow:hidden; text-overflow:ellipsis; white-space:nowrap;
}

/* PART 48-52 — transparent end-of-hand scoring. */
.reveal-sides{ text-align:left; }
.reveal-side{ margin-bottom:var(--space-3); }
.reveal-side h3{
  font-size:12px; letter-spacing:.06em; text-transform:uppercase;
  margin:0 0 5px; padding-bottom:4px; border-bottom:1px solid var(--line-soft);
}
.reveal-side.ours h3{ color:var(--our-team); }
.reveal-side.theirs h3{ color:var(--their-team); }
.reveal-melds{ display:flex; flex-wrap:wrap; margin-bottom:5px; }
.reveal-meld{ display:flex; margin-right:10px; margin-bottom:5px; }
.reveal-meld .card{ width:clamp(26px,3.2vw,38px); height:auto; aspect-ratio:.70; }
.reveal-meld .card + .card{ margin-left:calc(clamp(26px,3.2vw,38px) * -.45); }
.reveal-meld.is-deadwood .card{ opacity:.72; }
.reveal-tag{
  font-size:9.5px; letter-spacing:.06em; text-transform:uppercase;
  color:var(--text-muted); align-self:center; margin-left:5px;
}
.laid-off-note{ font-size:12px; color:var(--success); margin-bottom:5px; }
