* { 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, #14532d 0%, #166534 55%, #14532d 100%);
  color: #ecfdf5; 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: #fbbf24; color: #14532d; 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: #a7f3d0; }

.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 -- seven columns divide whatever is left, so 28px of margin is
   9% off every card on the narrowest phone. The menu and help screens keep
   their padding; only the board gives it up. */
#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: #a7f3d0; 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: #ecfdf5; font-family: inherit; }
.tierCard small { display: block; color: #a7f3d0; font-weight: 700; font-size: 11.5px; }
.tierCard .te { font-size: 26px; display: block; }
.tierCard.sel { border-color: #fbbf24; background: rgba(251,191,36,0.14); }
/* Settings, behind a disclosure. Same shape as word-search and cross-math 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); }
.field { display: flex; align-items: center; gap: 10px; margin: 7px 0; }
.field .lbl { flex: 0 0 104px; font-size: 13.5px; font-weight: 800; color: #a7f3d0; }
.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: #ecfdf5; font-family: inherit; font-weight: 800; font-size: 13.5px; cursor: pointer; padding: 4px 2px; }
.seg button.on { background: #fbbf24; border-color: #d97706; color: #14532d; min-height: 44px;}
#optNote { font-size: 12.5px; line-height: 1.45; color: #a7f3d0; 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: #ecfdf5; border: 3px solid rgba(255,255,255,0.14); cursor: pointer; font-family: inherit; }
button.big:active { transform: translateY(2px); }
button.big.primary { background: #fbbf24; border-color: #d97706; color: #14532d; min-height: 44px;}
#statsLine { color: #a7f3d0; font-weight: 700; font-size: 13px; }

/* play */
#playTop { display: flex; align-items: center; justify-content: space-between; font-weight: 800; padding: 2px 2px 6px; font-size: 15px; min-height: 22px; }
#doneOut { color: #a7f3d0; }
#timeOut { color: #d1fae5; font-variant-numeric: tabular-nums; }
#scoreOut { color: #fbbf24; }

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

/* The "dealing" line. It exists because the deal SEARCHES for a winnable hand
   before it shows one, and a blank table for even 200ms reads as a dead tap.
   It sits over the table rather than replacing the screen, so nothing jumps. */
#dealNote { position: absolute; inset: 0; display: flex; align-items: center; justify-content: center; font-weight: 800; color: #a7f3d0; pointer-events: none; text-align: center; padding: 20px; }
#dealNote:empty { display: none; }

/* The control pad. A readout that grows and a tap target that cannot shrink
   must not share a row (docs/offline-pwa.md) — so the counters above are their
   own row and the pad is its own grid with a hard floor on height. */
#pad { flex: none; display: grid; grid-template-columns: repeat(3, 1fr); gap: 8px; padding: 8px 0 max(4px, env(safe-area-inset-bottom)); }
.pb { min-height: 52px; border-radius: 14px; background: rgba(0,0,0,0.22); border: 3px solid rgba(255,255,255,0.14); color: #ecfdf5; font-size: 20px; font-weight: 800; font-family: inherit; cursor: pointer; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 1px; touch-action: manipulation; }
.pb span { font-size: 11px; font-weight: 800; letter-spacing: 0.02em; color: #a7f3d0; }
.pb:active { transform: translateY(2px); background: rgba(0,0,0,0.34); }
/* A disabled Undo is greyed, not hidden: a button that disappears takes its
   own explanation with it, and the player is left wondering where it went. */
.pb:disabled { opacity: 0.4; cursor: default; }
.pb:disabled:active { transform: none; }

/* 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(2,20,10,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(2,20,10,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: #a7f3d0; 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. The suit
   swatches are built from cards.js and the ink colours come from render.js —
   nothing here restates a colour the game paints, which is how a legend ends
   up showing a shade the product no longer uses. */
.lgSub { font-weight: 800; font-size: 13.5px; color: #a7f3d0; margin: 10px 0 5px; }
.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; }

.lgCard { display: inline-flex; flex-direction: column; align-items: center; justify-content: center; background: #fff; border: 1px solid #94a3b8; border-radius: 3px; line-height: 1; }
.lgCard b { font-size: 11px; font-weight: 800; }
.lgCard i { font-style: normal; font-size: 12px; }

.lgBack { width: 26px; height: 37px; border-radius: 3px; background: #1d4ed8; border: 1px solid #1e3a8a; box-shadow: inset 0 0 0 3px #1d4ed8, inset 0 0 0 4px rgba(255,255,255,0.22); }
.lgSlot { width: 26px; height: 37px; border-radius: 3px; border: 2px dashed rgba(255,255,255,0.45); display: flex; align-items: center; justify-content: center; font-size: 14px; color: rgba(255,255,255,0.6); }
.lgSlot.lgEmpty { border-style: dashed; }
.lgRing { width: 26px; height: 37px; border-radius: 4px; background: rgba(255,255,255,0.1); }
.lgRing.gold  { box-shadow: 0 0 0 3px #fbbf24; }
.lgRing.green { box-shadow: 0 0 0 3px #22c55e; }
.lgRing.blue  { box-shadow: 0 0 0 3px #38bdf8; }

.lgTxt { display: flex; flex-direction: column; min-width: 0; }
.lgTxt b { font-size: 14px; font-weight: 800; }
.lgTxt small { font-size: 12.5px; color: #a7f3d0; line-height: 1.3; font-weight: 600; }

#toast { position: fixed; left: 50%; bottom: 84px; transform: translateX(-50%); background: #ffffff; color: #14532d; 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. If the document scrolls
   too, the header scrolls away and a drag that reaches the end of the inner
   region chains out and drags the whole table under the player's thumb. */
html, body { overflow: hidden; overscroll-behavior: none; }
.scr { overscroll-behavior: contain; }

/* 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: #a7f3d0; }
