* { margin: 0; padding: 0; box-sizing: border-box; -webkit-tap-highlight-color: transparent; }
html, body { height: 100%; }
body {
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
  background: linear-gradient(180deg, #052e16 0%, #166534 55%, #052e16 100%);
  color: #f0fdf4; user-select: none; -webkit-user-select: none;
  touch-action: none; overflow: hidden;
}
#app { height: 100%; display: flex; flex-direction: column; max-width: min(100%, 860px); margin: 0 auto; }

#hdr { display: flex; align-items: center; gap: 8px; padding: 8px 12px; padding-top: max(8px, env(safe-area-inset-top)); }
#hdr .pill { background: rgba(0,0,0,0.22); border: 2px solid rgba(255,255,255,0.16); border-radius: 999px; padding: 6px 11px; font-weight: 800; font-size: 15px; min-width: 44px; min-height: 44px; display: flex; align-items: center; cursor: pointer; justify-content: center; color: inherit; font-family: inherit; }
#hdrHome { border: none; background: #4ade80; color: #052e16; font-size: 18px; }
#hdrStatus { flex: 1; min-width: 0; text-align: center; font-weight: 800; font-size: 14px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; color: #bbf7d0; }

.scr { flex: 1; display: none; flex-direction: column; overflow-y: auto; padding: 6px 14px 18px; }
/* The table gets the full width. 14px of padding either side costs the card
   size directly, and a fanned hand of thirteen divides whatever is left. */
#scr-play { padding: 6px 4px 6px; }
.scr.on { display: flex; }

#scr-menu { align-items: center; text-align: center; gap: 12px; justify-content: center; }
#scr-menu h1 { font-size: clamp(32px, 9vw, 44px); color: #ffffff; }
#scr-menu .sub { color: #bbf7d0; font-weight: 600; margin-bottom: 4px; }
#tierRow { display: flex; gap: 8px; width: 100%; }
.tierCard { flex: 1; background: rgba(0,0,0,0.2); border: 3px solid rgba(255,255,255,0.14); border-radius: 16px; padding: 10px 4px; font-weight: 800; font-size: 14px; line-height: 1.35; cursor: pointer; color: #f0fdf4; font-family: inherit; }
.tierCard small { display: block; color: #bbf7d0; font-weight: 700; font-size: 11.5px; }
.tierCard .te { font-size: 26px; display: block; }
.tierCard.sel { border-color: #4ade80; background: rgba(56,189,248,0.14); }

/* Settings, behind a disclosure. Same shape as every other game so a player
   who has met one has met them all. */
#custom { width: 100%; margin: 2px 0; text-align: left; background: rgba(0,0,0,0.2); border: 3px solid rgba(255,255,255,0.13); border-radius: 16px; padding: 6px 12px 10px; }
#custom > summary { list-style: none; cursor: pointer; font-weight: 800; font-size: 16px; padding: 10px 2px; min-height: 44px; display: flex; align-items: center; gap: 8px; }
#custom > summary::-webkit-details-marker { display: none; }
#custom > summary::before { content: "▸"; transition: transform .12s; }
#custom[open] > summary::before { transform: rotate(90deg); }
/* WRAPS (R-G26.9). A settings row is [label][segmented control], and the
   control's width is decided by its option labels at runtime. Measured at
   320px this row ran 19px past the screen edge, so the last option was
   cut in half — a control you cannot see or reliably hit. Wrapping drops
   the control onto its own line ONLY when it has to; at 375px and wider
   nothing moves. */
.field { display: flex; flex-wrap: wrap; align-items: center; gap: 10px; margin: 7px 0; }
.field .lbl { flex: 0 0 104px; font-size: 13.5px; font-weight: 800; color: #bbf7d0; }
.seg { flex: 1; display: flex; gap: 6px; }
.seg button { flex: 1; min-height: 44px; border-radius: 11px; border: 2px solid rgba(255,255,255,0.16); background: rgba(0,0,0,0.24); color: #f0fdf4; font-family: inherit; font-weight: 800; font-size: 13.5px; cursor: pointer; padding: 4px 2px; }
.seg button.on { background: #4ade80; border-color: #16a34a; color: #052e16; min-height: 44px;}
#optNote { font-size: 12.5px; line-height: 1.45; color: #bbf7d0; font-weight: 600; margin: 8px 2px 2px; }

button.big { width: 100%; border-radius: 16px; min-height: 56px; font-size: 19px; font-weight: 800; background: rgba(0,0,0,0.2); color: #f0fdf4; border: 3px solid rgba(255,255,255,0.14); cursor: pointer; font-family: inherit; }
button.big:active { transform: translateY(2px); }
button.big.primary { background: #4ade80; border-color: #16a34a; color: #052e16; min-height: 44px;}

/* play */
#playTop { display: flex; align-items: center; justify-content: space-between; font-weight: 800; padding: 2px 4px 6px; font-size: 13px; gap: 8px; min-height: 22px; }
#stockOut { color: #bbf7d0; white-space: nowrap; }
#msgOut { flex: 1; text-align: center; color: #dcfce7; font-weight: 800; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
#scoreOut { color: #4ade80; font-variant-numeric: tabular-nums; white-space: nowrap; }
/* R-C19 again, and this one shipped TODAY — hours after the rule was written,
   in a game built by the same hand. The match-score line only appears in a
   match, and appearing changed the stage height and re-laid the whole table.
   Reserved and hidden with `visibility`, like every other row. */
#totRow { display: block; visibility: hidden; height: 18px; padding: 0 4px;
          font-size: 12px; font-weight: 800; color: #bbf7d0; text-align: center;
          overflow: hidden; }
#totRow.on { visibility: visible; }

#stageWrap { flex: 1; position: relative; min-height: 0; }
canvas#stage { display: block; touch-action: none; }

/* THE ROW IS ALWAYS HERE, EVEN WHEN IT IS EMPTY.
   It used to be display:none until there was something to offer, which meant
   showing it shrank #stageWrap, which re-fitted the canvas, which re-laid the
   whole table — cards resized and slid the instant you tapped one, and slid
   back when you chose. Reserving the height permanently removes the cause;
   toggling a class only ever chased the symptom.
   min-height is the 44px touch floor plus its own padding, so an empty row and
   a full one are exactly the same size. */
#actRow { flex: none; display: flex; flex-wrap: nowrap; gap: 6px; justify-content: center;
          align-items: center; min-height: 60px;
          padding: 8px 4px max(4px, env(safe-area-inset-bottom)); }
.actBtn { min-width: 44px; min-height: 44px; padding: 0 14px; border-radius: 12px; flex: 0 1 auto;
          white-space: nowrap; overflow: hidden;
          font-family: inherit; font-weight: 800; font-size: 15px; cursor: pointer;
          color: #f0fdf4; background: rgba(0,0,0,0.24);
          border: 2px solid rgba(255,255,255,0.16); }
.actBtn:active { transform: translateY(2px); }
.actBtn.go { border-color: #4ade80; color: #bbf7d0; }
.actBtn.cancel { border-color: rgba(255,255,255,0.2); }
/* The four suit buttons for an eight. Red suits are red on the button, because
   a player picking a suit is picking the thing they can see on their cards —
   not a word. */
.actBtn.suit { font-size: 26px; padding: 0 16px; line-height: 1; }
.actBtn.suit.red { color: #fca5a5; }
.actBtn.suit.black { color: #f0fdf4; }

/* Centred, and it stays centred. It was moved to the bottom for one release,
   to keep it off the cards it was describing — but that was treating the
   symptom. The panel CARRIES the cards now (see the result rows in app.js), so
   there is nothing behind it that has to be read, and centre is where the most
   important message in the game belongs. A panel in a corner puts its buttons
   next to the home indicator and makes the eye travel for the one thing it
   most wants.
   overflow-y stays: a four-player summary is a tall panel on a short phone,
   and a message that runs off the top is worse than one that scrolls. */
.ovl { position: absolute; inset: 0; display: none; align-items: flex-start; justify-content: center; background: rgba(3,24,12,0.55); border-radius: 12px; padding: 16px; overflow-y: auto; }
.ovl.on { display: flex; }
.ovlCard { text-align: center; width: 100%; max-width: 320px; display: flex; flex-direction: column; gap: 10px; margin: auto;}
/* THE OVERLAY REPORTS ON THE TABLE, SO IT MUST NOT HIDE THE TABLE.
   It was a 90%-opaque curtain over the felt — and what it says is "Robin took
   three tricks", "the pot goes to Kit", "kings and fours". Every one of those
   sentences is about cards the player can no longer see. That is not a tuning
   nit; it is the overlay defeating its own purpose, the same shape as a word
   game refusing a word for being too hard.
   The fix is not just less alpha, which would leave white text on a busy felt.
   The scrim goes down to a dim, and the WORDS move onto a panel of their own,
   so the message is more legible than before and the table is still there
   around it. Overlays whose board is irrelevant once they appear — a game-over
   in an arcade game — are left opaque on purpose. */
.ovlCard { background: rgba(3,24,12,0.96); border: 2px solid rgba(255,255,255,0.16);
            border-radius: 18px; padding: 16px 14px;
            box-shadow: 0 10px 30px rgba(0,0,0,0.45); margin: auto;}

#ovlTitle { font-size: 26px; font-weight: 800; color: #ffffff; }
#ovlSub { color: #bbf7d0; font-weight: 700; min-height: 22px; line-height: 1.45; }

#scr-how .card { background: rgba(0,0,0,0.2); border: 3px solid rgba(255,255,255,0.13); border-radius: 16px; padding: 14px; margin-bottom: 10px; font-size: 15px; line-height: 1.55; font-weight: 600; }
#scr-how h2 { margin-bottom: 8px; color: #ffffff; }

/* The legend (docs/offline-games-pwa.md R-L1). One column of swatches at a
   fixed width so the eye can run the column instead of the text. Every mark is
   built from the same data the table paints with. */
.legend { display: flex; flex-direction: column; gap: 7px; }
.lgRow { display: flex; align-items: center; gap: 10px; }
.lgArt { flex: none; width: 46px; display: flex; align-items: center; justify-content: center; }
.lgTxt { display: flex; flex-direction: column; min-width: 0; }
.lgTxt b { font-size: 14px; font-weight: 800; }
.lgTxt small { font-size: 12.5px; color: #bbf7d0; line-height: 1.3; font-weight: 600; }

/* THE LEGEND CARD IS ONE WIDTH (R-L1).
   It was `min-width`, so "10♦" came out four pixels wider than "A♠" and a row
   of example cards — a straight, a flush, a hand of five — stopped lining up
   at whichever card happened to be a ten. A legend whose job is comparison
   cannot have a column that wanders. Fixed width, and the glyph centres in
   it. */
.lgCard { display: inline-flex; align-items: center; justify-content: center; width: 30px; height: 40px;
          border-radius: 4px; background: #fff; color: #0f172a; font-weight: 800; font-size: 13px;
          border: 1px solid #94a3b8; }
.lgCard.pick { box-shadow: 0 0 0 3px #4ade80; }
.lgCard.dim { color: #64748b; background: #cbd5e1; }
.lgCard.red { color: #dc2626; }
.lgBack { width: 28px; height: 40px; border-radius: 4px; background: #000; border: 1px solid #334155;
          box-shadow: inset 0 0 0 3px #000, inset 0 0 0 5px #ffcd00; }
.lgSuit { display: inline-flex; align-items: center; justify-content: center; min-width: 34px; height: 30px;
          border-radius: 8px; background: #4ade80; color: #052e16; font-weight: 800; font-size: 19px; }
.lgSuit.red { color: #b91c1c; }
.lgDead { display: inline-flex; align-items: center; justify-content: center; min-width: 40px; height: 28px;
          border-radius: 8px; border: 2px solid rgba(255,255,255,0.16); background: rgba(0,0,0,0.24);
          color: #f0fdf4; font-weight: 800; font-size: 11px; opacity: 0.42; }
.lgEight { display: inline-flex; align-items: center; justify-content: center; min-width: 30px; height: 40px;
           border-radius: 4px; background: linear-gradient(135deg,#fff 0%,#fde68a 100%); color: #0f172a;
           font-weight: 800; font-size: 15px; border: 1px solid #ca8a04; }

/* The toast floats in the middle here, not at the bottom where the rest of the
   catalog puts it. This table has something at BOTH ends — the opponents and
   their books at the top, your hand at the bottom — and the toast is the
   running commentary on exactly those two things, so it must not sit on
   either. Two drafts got this wrong in opposite directions: bottom: 84px
   covered the cards, top: 108px covered the opponent it was talking about.
   40% lands in the band between the opponent block and the pond. */
#toast { position: fixed; left: 50%; top: 40%; transform: translate(-50%, -50%); background: #ffffff; color: #052e16; font-weight: 800; padding: 9px 16px; border-radius: 999px; opacity: 0; transition: opacity 0.25s; pointer-events: none; z-index: 40; max-width: calc(100vw - 32px); text-align: center; }
#toast.on { opacity: 1; }

/* docs/offline-pwa.md R-C15 — the PAGE must never scroll. The product is a
   fixed frame: header, a named scroll region, footer. */
html, body { overflow: hidden; overscroll-behavior: none; }
.scr { overscroll-behavior: contain; }


/* THE RESULT ROWS (docs/offline-games-pwa.md, "a result must carry its
   evidence"). One row per player or per team: who, the thing itself, what it
   was worth. Same class names as Poker's showdown, because it is the same idea
   and a second vocabulary for it would drift.
   `#ovlSub` becomes a column here rather than a paragraph, so the rows stack
   and their columns line up. */
#ovlSub { display: flex; flex-direction: column; gap: 5px; min-height: 0; }
.sdRow { display: flex; align-items: center; gap: 7px; padding: 5px 7px;
         border-radius: 10px; background: rgba(255,255,255,0.05);
         border: 2px solid transparent; text-align: left; }
.sdRow.you  { background: rgba(255,255,255,0.10); }
.sdRow.win  { border-color: #4ade80; background: rgba(74,222,128,0.14); }
.sdRow.out  { opacity: 0.55; }
.sdWho   { flex: 0 0 52px; font-size: 13px; font-weight: 800; }
.sdArt   { flex: 1 1 auto; display: flex; gap: 3px; flex-wrap: wrap; min-width: 0; }
.sdHand  { flex: 1 1 auto; font-size: 12px; font-weight: 700; line-height: 1.25;
           color: #bbf7d0; }
.sdSwing { flex: 0 0 auto; font-size: 13px; font-weight: 800;
           font-variant-numeric: tabular-nums; color: #fca5a5; }
.sdSwing.up { color: #4ade80; }
/* A rank or a card inside a result row. Fixed width for the same reason the
   legend's is: rows only form columns if a ten is as wide as an ace. */
.sdCard { display: inline-flex; align-items: center; justify-content: center;
          width: 27px; height: 34px; border-radius: 4px; background: #fff;
          color: #0f172a; font-weight: 800; font-size: 12px;
          border: 1px solid #94a3b8; }
.sdCard.red { color: #dc2626; }

/* The Settings panel's help line. It was in the markup with no rule behind it,
   so it rendered at body size in body colour where every other product shows
   it small and muted -- `just check-settings` found it once the guard started
   deriving the panel's OWN class vocabulary instead of demanding `.field` and
   `.seg` by name. Markup with no rules behind it is not a control. */
.blurb { margin: 6px 0 2px; font-size: 12.5px; line-height: 1.45; color: #bbf7d0; }
