* { 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, #1e1036 0%, #4c1d95 55%, #1e1036 100%);
  color: #f5f3ff; 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: #1e1036; 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: #e9d5ff; }

.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: #e9d5ff; 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: #f5f3ff; font-family: inherit; }
.tierCard small { display: block; color: #e9d5ff; font-weight: 700; font-size: 11.5px; }
.tierCard .te { font-size: 26px; display: block; }
.tierCard.sel { border-color: #fbbf24; 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 18px 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: #e9d5ff; }
.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: #f5f3ff; font-family: inherit; font-weight: 800; font-size: 13.5px; cursor: pointer; padding: 4px 2px; }
.seg button.on { background: #fbbf24; border-color: #7c3aed; color: #1e1036; min-height: 44px;}
#optNote { font-size: 12.5px; line-height: 1.45; color: #e9d5ff; 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: #f5f3ff; 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: #7c3aed; color: #1e1036; 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; }
#handOut { color: #e9d5ff; white-space: nowrap; font-variant-numeric: tabular-nums; }
#msgOut { flex: 1; text-align: center; color: #ede9fe; font-weight: 800; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
#streetOut { color: #fbbf24; white-space: nowrap; }

#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. */
#btnRow { 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)); }
.btn { 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: #f5f3ff; background: rgba(0,0,0,0.24);
          border: 2px solid rgba(255,255,255,0.16); }
.btn:active { transform: translateY(2px); }
/* Deliberately NOT gold. Gold in this game means "the coach picked this", and
   a ring that every button already has is not a recommendation. The first
   draft inherited the accent border from Crazy Eights and the coach's ring
   disappeared into a row of identical gold outlines. */
.btn.go { border-color: rgba(255,255,255,0.22); color: #f5f3ff; min-height: 44px;}
.btn.cancel { border-color: rgba(255,255,255,0.2); min-height: 44px;}
/* 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. */
/* Every action is a word and an icon. "H" and "S" are what a strategy card
   says and they teach nothing; a five-year-old on the Sprout rung is reading
   the button, not decoding it. */
.btn { font-size: 14.5px; padding: 0 12px; min-height: 44px;}
.btn.wide { flex: 1 1 auto; min-height: 44px;}
/* Deliberately NOT gold. Gold in this game means "the coach picked this", and
   a ring every button already has is not a recommendation — the first draft
   inherited the accent border from Crazy Eights and the coach's ring vanished
   into a row of identical gold outlines. */
.btn.go { border-color: rgba(255,255,255,0.22); color: #f5f3ff; min-height: 44px;}

/* The stake chips share the button row: they are never on screen at the same
   time as the actions, and a second reserved strip is 52px of dead felt for
   the whole hand. */
.chipBtn { min-width: 52px; min-height: 44px; border-radius: 12px;
           font-family: inherit; font-weight: 800; font-size: 15px;
           cursor: pointer; color: #f5f3ff; background: rgba(0,0,0,0.24);
           border: 2px solid rgba(255,255,255,0.16); }
.chipBtn.sel { background: #fbbf24; border-color: #7c3aed; color: #1e1036; }

/* The bet sizer. A slider plus a live figure, on the same reserved strip as
   the buttons — R-C19: it appears only when you are raising, so it must not
   change the height of anything when it does. */
#sizeRow { flex: none; display: flex; align-items: center; gap: 10px;
           height: 40px; padding: 0 14px; visibility: hidden; }
#sizeRow.on { visibility: visible; }
#sizeRow input[type=range] { flex: 1 1 auto; accent-color: #fbbf24;
                             height: 32px; }
#sizeOut { flex: none; min-width: 70px; text-align: right; font-weight: 800;
           font-size: 15px; color: #fbbf24; font-variant-numeric: tabular-nums; }

/* A FIXED height, not a minimum. The coach's sentences run one line or three
   depending on the hand, and a text block that grows is a layout participant
   exactly like a row that appears — it pushes the stage and re-lays the table
   mid-decision. Two lines' worth, clipped. (R-C19)
   This rule was missing entirely for the first draft of the game: the element
   was in the markup, rendered, looked fine, and had no rules behind it. */
#msgLine { flex: none; height: 36px; display: flex; align-items: center;
             justify-content: center; text-align: center; padding: 0 12px;
             font-size: 12.5px; font-weight: 700; color: #e9d5ff;
             line-height: 1.22; overflow: hidden; }

/* 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(12,6,26,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(12,6,26,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: #e9d5ff; 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: #e9d5ff; 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: 29px; height: 34px;
          border-radius: 4px; background: #fff; color: #0f172a; font-weight: 800; font-size: 11px;
          border: 1px solid #94a3b8; }
.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; }
.lgChip { display: inline-flex; align-items: center; justify-content: center; min-width: 40px; height: 24px;
          border-radius: 12px; background: #a78bfa; color: #1e1036; font-weight: 800; font-size: 12.5px; }
.lgChip.gold { background: #fbbf24; }
.lgBtn { display: inline-flex; align-items: center; justify-content: center; width: 26px; height: 26px;
         border-radius: 50%; background: #f8fafc; color: #0f172a; font-weight: 800; font-size: 13px;
         border: 2px solid #94a3b8; }
.lgCard.win { box-shadow: 0 0 0 3px #4ade80; }
.lgDead { display: inline-flex; align-items: center; justify-content: center; min-width: 46px; height: 22px;
          border-radius: 11px; background: #f87171; color: #fff; font-weight: 800; font-size: 10.5px; }
.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: #f5f3ff; font-weight: 800; font-size: 11px; opacity: 0.42; }

/* 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: #1e1036; 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 SHOWDOWN TABLE (see finish() in app.js). One row per player: name, their
   actual cards with the ones that made their best five ringed, what the hand
   was, and what it cost or paid. Four columns, and the middle two are the
   reason `.lgCard` has a fixed width — a ten a few pixels wider than an ace
   puts every row's hand name at a different indent. */
#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; }
.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 46px; text-align: left; font-size: 13px; font-weight: 800; }
.sdArt   { flex: 0 0 auto; display: flex; gap: 3px; min-width: 61px; }
.sdHand  { flex: 1 1 auto; text-align: left; font-size: 12px; font-weight: 700;
           color: #e9d5ff; line-height: 1.25; }
.sdSwing { flex: 0 0 auto; font-size: 13px; font-weight: 800;
           font-variant-numeric: tabular-nums; color: #fca5a5; }
.sdSwing.up { color: #4ade80; }

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