:root {
  /* ---- 8.3 token layer (new) ---- */
  /* The smallest text anywhere (build 24, R-036): 11 px. */
  --text-micro: 0.6875rem;
  --card-w: 76px;
  --card-h: 108px;
  --space-1: 4px;
  --space-2: 8px;
  --space-3: 12px;
  --space-4: 16px;
  --space-5: 24px;
  --space-6: 32px;
  --radius-xs: 4px;
  --radius-sm: 6px;
  --radius-md: 8px;
  --radius-lg: 12px;
  --radius-xl: 16px;
  --radius-2xl: 20px;
  --radius-full: 50%;
  --z-base: 1;
  --z-zone: 10;
  --z-hand: 100;
  --z-chat: 150;
  --z-panel: 200;
  --z-chrome: 250;
  --z-overlay: 300;
  --z-toast: 1000;
  --z-banner: 1100;
  /* Motion (render/motion.js uses the same curves): strong ease-out for
     things arriving or answering a tap, ease-in-out for moves on screen. */
  --ease-out: cubic-bezier(0.23, 1, 0.32, 1);
  --ease-in-out: cubic-bezier(0.65, 0, 0.35, 1);
  --team-ns: #f0b44a;
  --team-ew: #62d2cb;
  --safe-b: env(safe-area-inset-bottom, 0px);
  /* Phase 1 clearance model — measured live by public/clearance.js, which
     writes these on :root (inline, so it wins). These are pre-JS fallbacks. */
  --hand-h: 140px;
  --chat-h: 0px;
  --chrome-h: 0px;
  /* ---- existing tokens (values unchanged; card tokens alias the new names) ---- */
  --card-width: var(--card-w);
  --card-height: var(--card-h);
  --card-small-width: 50px;
  --card-small-height: 75px;
  --red: #c62828;
  --black: #1b1b1b;
  --bg: #0f261a;
  --bg-2: #14301f;
  --table: #1c5234;
  --felt: #1f5c3a;
  --felt-edge: #123823;
  --panel: #10241a;
  --panel-2: #173024;
  --panel-border: rgba(255, 255, 255, 0.09);
  --gold: #e3b54a;
  --gold-strong: #f0c65e;
  --text: #eef3ef;
  --text-dim: #a8bcae;
  --border: rgba(255, 255, 255, 0.12);
  --good: #6fcf8e;
  --bad: #ef7d6f;
  --shadow-lg: 0 18px 48px rgba(0, 0, 0, 0.45);
}

*, *::before, *::after {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}

/* Sleek modern scrollbars */
::-webkit-scrollbar {
  width: 6px;
  height: 6px;
}

::-webkit-scrollbar-track {
  background: rgba(0, 0, 0, 0.2);
  border-radius: 4px;
}

::-webkit-scrollbar-thumb {
  background: rgba(218, 165, 32, 0.4);
  border-radius: 4px;
}

::-webkit-scrollbar-thumb:hover {
  background: rgba(218, 165, 32, 0.75);
}

* {
  scrollbar-width: thin;
  scrollbar-color: rgba(218, 165, 32, 0.4) rgba(0, 0, 0, 0.2);
}

body {
  font-family: system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
  background: radial-gradient(120% 90% at 50% 0%, var(--bg-2) 0%, var(--bg) 60%) fixed;
  background-color: var(--bg);
  color: var(--text);
  min-height: 100vh;
  min-height: 100dvh;
  overflow-x: hidden;
  max-width: 100vw;
  display: flex;
  flex-direction: column;
  touch-action: manipulation;
  -webkit-touch-callout: none;
  -webkit-user-select: none;
  user-select: none;
}

#app {
  display: flex;
  flex-direction: column;
  flex: 1;
  min-height: 100vh;
  min-height: 100dvh;
}

/* App Shell — persistent DOM slots */
#phase-root {
  flex: 1;
  display: flex;
  flex-direction: column;
  min-height: 0;
  /* Single owner of the bottom-rail clearance; --hand-h is measured by
     public/clearance.js and includes the chat dock when it is open. */
  padding-bottom: calc(var(--hand-h) + var(--space-4));
}
/* At the table the felt itself ends at the hand rail (.game-table's
   height), so the extra 16 px only made the page 16 px taller than the
   window: it scrolled by 16 at every size (B24 pass 2 N-012). */
body.at-table #phase-root { padding-bottom: var(--hand-h); }

/* Bottom rail: #hand-slot is fixed to the viewport bottom. The chat and
   The chat slot holds a floating sheet (chat.css) and take no layout space,
   so --chat-h stays 0. Clearance model: public/clearance.js. */
#chat-slot {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  height: 0;
  z-index: var(--z-chat);
}

/* The hand bar itself is a static block inside this fixed slot. */
#hand-slot {
  position: fixed;
  bottom: var(--chat-h, 0px);
  left: 0;
  right: 0;
  z-index: var(--z-hand);
}

/* Top rail (score bar + toolbar). Height is measured by public/clearance.js
   and published as --chrome-h.
   The ☰ menu hangs out of the score bar. That bar's backdrop-filter flattens
   the dropdown into the rail, so on a wide window the felt and the seats
   (z-index 1) paint over it and Leave / Coach sit under the table. The rail
   stays above the felt at every size. Dialogs and toasts are z-index 1000. */
.top-chrome {
  flex-shrink: 0;
  position: relative;
  z-index: var(--z-chrome);
}

/* ≤1024px: keep the score bar + toolbar pinned while the game content scrolls. */
@media (max-width: 1024px) {
  .top-chrome {
    position: sticky;
    top: 0;
  }
}

/* ---- Top bar: scores, hand context, menu ---- */
.score-bar.top-bar {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 8px 14px;
  /* Keep the bar clear of the top inset (notch/status bar) in standalone PWA. */
  padding-top: calc(8px + env(safe-area-inset-top, 0px));
  background: rgba(6, 18, 12, 0.72);
  backdrop-filter: blur(10px);
  border-bottom: 1px solid var(--panel-border);
  /* Above the Coach strip in this rail. The strip is the next sibling, and
     the filter above flattens the menu into this bar; without a stacking
     level the strip paints over the top of the open menu. */
  position: relative;
  z-index: 1;
}

.score-pills {
  display: flex;
  gap: 8px;
  min-width: 0;
  flex: 0 1 auto;
}

.score-pill {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  grid-template-rows: auto 4px;
  column-gap: 12px;
  row-gap: 4px;
  align-items: center;
  padding: 6px 12px 7px;
  border-radius: 12px;
  background: rgba(255, 255, 255, 0.04);
  border: 1px solid var(--panel-border);
  min-width: 0;
  max-width: 260px;
}

.score-pill.is-mine {
  background: rgba(255, 255, 255, 0.07);
  border-color: rgba(255, 255, 255, 0.16);
}

.pill-names {
  font-size: 0.8rem;
  font-weight: 600;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  min-width: 0;
}

.pill-score {
  font-size: 1.15rem;
  font-weight: 800;
  font-variant-numeric: tabular-nums;
  text-align: right;
}

.pill-end { display: inline-flex; align-items: center; gap: 8px; justify-self: end; }
.pill-downs { display: inline-flex; align-items: center; gap: 3px; color: var(--text-dim); font-size: var(--text-micro, 0.6875rem); font-weight: 600; letter-spacing: 0.03em; text-transform: uppercase; white-space: nowrap; }
.pill-downs-label { margin-right: 1px; }
.pill-pip { width: 8px; height: 8px; border-radius: 50%; border: 1.5px solid currentColor; box-sizing: border-box; }
.pill-pip.is-used { background: var(--gold); border-color: var(--gold); }
.pill-downs.has-used { color: var(--gold); }

.pill-bar {
  grid-column: 1 / -1;
  height: 4px;
  border-radius: 4px;
  background: rgba(255, 255, 255, 0.08);
  overflow: hidden;
}

.pill-bar > span {
  display: block;
  height: 100%;
  border-radius: 4px;
  background: currentColor;
  transition: width 0.6s var(--ease-out);
}

.score-pill.team-ns { color: var(--team-ns); }
.score-pill.team-ew { color: var(--team-ew); }
.score-pill .pill-score { color: var(--text); }

.hand-context {
  display: flex;
  flex: 1;
  justify-content: center;
  gap: 8px;
  min-width: 0;
  flex-wrap: wrap;
}

.ctx-chip {
  font-size: 0.82rem;
  padding: 4px 10px;
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.06);
  border: 1px solid var(--panel-border);
  white-space: nowrap;
  color: var(--text-dim);
}

.ctx-chip b { color: var(--text); }
.ctx-chip.is-quiet { opacity: 0.8; }

.trump-glyph {
  display: inline-block;
  font-size: 1.1em;
  line-height: 1;
  color: #fff;
  vertical-align: -1px;
}

.trump-glyph.suit-H,
.trump-glyph.suit-D { color: #ff8a80; }

body.four-color-deck .trump-glyph.suit-C { color: #7ee08f; }
body.four-color-deck .trump-glyph.suit-D { color: #82b8ff; }

/* The club where a suit is drawn small (build 28, ISSUES row 89; suit-mark.js):
   the deck's own bolder trefoil, in the text's color and size. A 0.95em box whose
   ink is 0.87em wide and 0.81em tall (the font's club is 0.77 by 0.77), its foot
   a hair below the baseline as the font's glyph sits. The glyph itself stays in
   the markup as hidden text, so the words around it copy and search as before.
   The margins make the mark take 0.91em along the line, which is what the
   system font's club took, so a row of chips (a five-card run at 375 px, where
   the row has no room to spare) wraps exactly where it did. The ink is inset
   0.038em in the box, so the 0.02em overhang of the box holds no ink. */
.club-mark {
  position: relative;
  display: inline-block;
  width: 0.95em;
  height: 0.95em;
  margin: 0 -0.02em;
  vertical-align: -0.11em;
  flex: none;
}
.club-mark svg {
  display: block;
  width: 100%;
  height: 100%;
  fill: currentColor;
}
.club-mark-text {
  position: absolute;
  left: 0;
  top: 0;
  width: 1px;
  height: 1px;
  /* A 1px glyph in a 1px box: it takes no room and overflows nothing. */
  font-size: 1px;
  line-height: 1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

.top-actions {
  display: flex;
  gap: 6px;
  margin-left: auto;
  position: relative;
  flex-shrink: 0;
}

.icon-btn {
  min-height: 44px;
  min-width: 44px;
  padding: 0 12px;
  border-radius: 10px;
  border: 1px solid var(--panel-border);
  background: rgba(255, 255, 255, 0.05);
  color: var(--text);
  font-size: 0.85rem;
  font-weight: 600;
  cursor: pointer;
  transition: background 0.15s, border-color 0.15s;
}

.icon-btn:hover { background: rgba(255, 255, 255, 0.1); }
.icon-btn.menu-btn { font-size: 1.1rem; }

.top-menu {
  position: absolute;
  top: calc(100% + 8px);
  right: 0;
  z-index: var(--z-overlay);
  min-width: 200px;
  padding: 6px;
  border-radius: 14px;
  background: var(--panel);
  border: 1px solid var(--panel-border);
  box-shadow: var(--shadow-lg);
  display: flex;
  flex-direction: column;
  /* A phone on its side is shorter than this list. Keep the panel in the
     window (the page must not grow a scrollbar under the felt) and scroll
     inside it. --chrome-h is the rail the menu hangs from. */
  max-height: calc(100dvh - var(--chrome-h, 72px) - 12px);
  overflow-x: hidden;
  overflow-y: auto;
  overscroll-behavior: contain;
}

.top-menu[hidden] { display: none; }

.menu-item {
  text-align: left;
  padding: 10px 12px;
  min-height: 44px;
  border: 0;
  border-radius: 10px;
  background: transparent;
  color: var(--text);
  font-size: 0.92rem;
  cursor: pointer;
}

.menu-item:hover { background: rgba(255, 255, 255, 0.07); }
.menu-item.is-danger { color: var(--bad); }

/* Teach Me toggle (landing / lobby) */
.teach-toggle {
  font-size: 0.75rem;
  padding: 2px 10px;
  border-radius: 12px;
  border: 1px solid var(--gold);
  background: transparent;
  color: var(--gold);
  cursor: pointer;
  margin-left: 8px;
  transition: background-color 0.2s, color 0.2s, border-color 0.2s;
  min-height: 44px;
  min-width: 44px;
}

.teach-toggle.active {
  background: var(--gold);
  color: #111;
}

.score-ns { color: var(--team-ns); }
.score-ew { color: var(--team-ew); }

/* Game Content */
.game-content {
  flex: 1;
  display: flex;
  flex-direction: column;
  min-height: 0;
}

/* Shared dialog pieces */
.dialog-input {
  width: 100%;
  padding: 0.6rem 0.75rem;
  border-radius: 10px;
  border: 1px solid var(--panel-border);
  background: rgba(0, 0, 0, 0.3);
  color: var(--text);
  font-size: 1rem;
  margin-bottom: 14px;
}

.dialog-actions {
  display: flex;
  gap: 8px;
  justify-content: flex-end;
  flex-wrap: wrap;
}

.dialog-actions.is-centered { justify-content: center; }

/* ========== MOBILE RESPONSIVE (extracted per-component from the style.css mega-block) ========== */
@media (max-width: 600px), (max-height: 500px) {
  :root {
    --card-w: 58px;
    --card-h: 84px;
    --card-width: 58px;
    --card-height: 84px;
    --card-small-width: 40px;
    --card-small-height: 58px;
    /* Fallback only — clearance.js measures the real mobile bar. */
    --hand-h: 100px;
  }
  .score-bar.top-bar {
    gap: 6px;
    padding: 6px 8px;
    padding-top: calc(6px + env(safe-area-inset-top, 0px));
    flex-wrap: wrap;
  }
  .score-pills { flex: 1 1 100%; order: 1; }
  .score-pill { flex: 1 1 0; padding: 4px 8px 5px; }
  .pill-names { font-size: 0.72rem; }
  .pill-score { font-size: 1rem; }
  .pill-downs-label { display: none; }
  .pill-end { gap: 6px; }
  .hand-context { order: 2; justify-content: flex-start; flex-wrap: nowrap; overflow: hidden; }
  .ctx-chip { font-size: 0.74rem; padding: 3px 8px; }
  .top-actions { order: 3; }
  .icon-btn { min-height: 44px; padding: 0 9px; font-size: 0.78rem; }
  /* Fix #6: Teach toggle compact */
  .teach-toggle {
    font-size: var(--text-micro, 0.6875rem);
    padding: 1px 8px;
  }
}

/* Anyone who asked their device for less motion gets no looping or sliding
   animations anywhere (a few components also switch theirs off by name). */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
}

/* Easy view (Settings, as in the app): larger text everywhere, and the hand
   in two rows of bigger cards (see the decks' .hand-two-rows). */
body.easy-view { font-size: 112%; }
body.easy-view .hand.hand-two-rows {
  --card-width: calc(var(--card-w) * 1.4);
  --card-height: calc(var(--card-h) * 1.4);
}
