/* ==========================================================================
   GAME-EXACT MAHJONG TABLE MAT & CLEAN RESPONSIVE TABS SYSTEM
   ========================================================================== */

@font-face {
  font-family: 'Outfit';
  font-style: normal;
  font-weight: 100 900;
  font-display: swap;
  src: url('/assets/fonts/outfit-latin-variable.woff2') format('woff2');
}

:root {
  /* Game-exact Felt Palette */
  --bg-dark: #061310;
  --table-felt-1: #1c6255;
  --table-felt-2: #0a2420;
  --table-felt-3: #061310;
  --panel-bg: rgba(5, 21, 18, 0.88);
  --panel-border: rgba(255, 255, 255, 0.18);
  
  /* Wood Frame Colors */
  --wood-dark: #1b0d06;
  --wood-mid: #33180a;
  --wood-light: #54270f;
  
  /* Game Authentic Accents */
  --gold: #ffc95a;
  --gold-glow: rgba(255, 201, 90, 0.35);
  --crimson: #e45b55;
  --jade: #1f7a34;
  --blue-dots: #1864ab;
  --ink: #f4f0e7;
  --muted: #c6c2b8;
  
  /* Fonts */
  --font-sans: 'Outfit', system-ui, -apple-system, sans-serif;
  --font-chinese: 'KaiTi', 'STKaiti', 'Noto Serif CJK SC', 'Songti SC', serif;
  --font-mono: ui-monospace, 'Cascadia Code', Consolas, monospace;

  /* Header */
  --header-height: 72px;
}

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

html {
  scroll-behavior: smooth;
  font-size: 16px;
}

/* A floor for keyboard focus, declared before anything else so every specific
   ring below still wins. Without it a focused element falls back to the UA's
   1px near-black outline, which on this felt is invisible — that was the case
   for the nine tab panels (they carry tabindex="0" per the ARIA tabs pattern)
   and for the header's link-shaped buttons. */
.mahjong-app :focus-visible {
  outline: 3px solid var(--gold);
  outline-offset: 2px;
}

/* The panel is large, so its ring goes inside rather than around the card. */
.tab-pane:focus-visible {
  outline: 2px dashed var(--gold);
  outline-offset: -6px;
  border-radius: 20px;
}

body.mahjong-app {
  font-family: var(--font-sans);
  background: radial-gradient(circle at 50% 10%, var(--table-felt-1) 0%, var(--table-felt-2) 47%, var(--table-felt-3) 100%);
  color: var(--ink);
  min-height: 100vh;
  line-height: 1.5;
  overflow-x: hidden;
}

/* Scroll Progress Bar */
.scroll-progress-container {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 4px;
  background: rgba(0,0,0,0.4);
  z-index: 10000;
}

.scroll-progress-bar {
  height: 100%;
  width: 0%;
  background: linear-gradient(90deg, #ffc95a, #ffd43b);
  box-shadow: 0 0 12px rgba(255, 201, 90, 0.9);
}

/* Header */
.app-header {
  position: sticky;
  top: 0;
  z-index: 100;
  height: var(--header-height);
  background: rgba(4, 16, 13, 0.94);
  backdrop-filter: blur(16px);
  border-bottom: 1px solid var(--panel-border);
}

.header-inner {
  max-width: 1400px;
  margin: 0 auto;
  height: 100%;
  padding: 0 24px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 20px;
}

.brand {
  display: flex;
  align-items: center;
  gap: 14px;
}

.brand-tile {
  flex: 0 0 auto;
  background: #082a23;
  border: 2px solid var(--gold);
  border-radius: 10px;
  width: 50px;
  height: 50px;
  overflow: hidden;
  box-shadow: 0 4px 16px rgba(0,0,0,0.6), inset 0 1px 0 rgba(255,255,255,0.4);
}
.brand-tile img { display: block; width: 100%; height: 100%; object-fit: cover; transform: scale(1.35); }

.brand-text h1 {
  font-size: 1.35rem;
  font-weight: 800;
  color: var(--ink);
  line-height: 1.1;
}

.brand-text .badge {
  font-size: 0.72rem;
  font-weight: 900;
  background: var(--gold);
  color: #151b1a;
  padding: 2px 8px;
  border-radius: 99px;
  text-transform: uppercase;
  letter-spacing: 0.05em;
}

.brand-text .subtitle {
  margin-top: 3px;
  font-size: 0.8rem;
  color: var(--muted);
  line-height: 1.25;
  white-space: nowrap;
}

/* Header Search */
.header-search {
  flex: 0 1 400px;
  position: relative;
  display: flex;
  align-items: center;
}

.header-search input {
  min-height: 44px;
  width: 100%;
  padding: 10px 16px 10px 42px;
  background: rgba(3, 15, 12, 0.75);
  border: 1px solid var(--panel-border);
  border-radius: 99px;
  color: var(--ink);
  font-size: 0.9rem;
  transition: all 0.2s ease;
}

.header-search input:focus {
  outline: none;
  border-color: var(--gold);
  box-shadow: 0 0 0 3px var(--gold-glow);
}

.search-icon {
  position: absolute;
  left: 14px;
  font-size: 0.9rem;
  opacity: 0.6;
}

.search-shortcut {
  position: absolute;
  right: 14px;
  background: rgba(255,255,255,0.1);
  border-radius: 4px;
  padding: 2px 6px;
  font-size: 0.75rem;
  color: var(--muted);
  font-family: var(--font-mono);
}

/* Search results dropdown. Anchored to the input's own box; above the sticky
   header's neighbours but below nothing that matters, since the header is the
   page's topmost layer already. */
.search-results {
  position: absolute;
  top: calc(100% + 8px);
  left: 0;
  right: 0;
  z-index: 80;
  max-height: min(420px, 60vh);
  overflow-y: auto;
  background: var(--bg-dark);
  border: 1px solid var(--panel-border);
  border-radius: 14px;
  box-shadow: 0 18px 40px rgba(0, 0, 0, 0.6);
  scrollbar-width: thin;
}
.search-result {
  display: block;
  width: 100%;
  padding: 10px 14px;
  background: none;
  border: 0;
  border-bottom: 1px solid rgba(255, 255, 255, 0.06);
  color: var(--ink);
  text-align: left;
  font: inherit;
  cursor: pointer;
}
.search-result:last-child { border-bottom: 0; }
.search-result:hover,
.search-result[aria-selected="true"] { background: rgba(255, 201, 90, 0.14); }
.search-result .result-where {
  display: block;
  color: var(--gold);
  font-size: 0.66rem;
  font-weight: 900;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}
.search-result .result-title {
  display: block;
  font-weight: 700;
  font-size: 0.9rem;
  line-height: 1.35;
}
.search-empty { padding: 12px 14px; color: var(--muted); font-size: 0.88rem; }

/* Buttons */
.btn {
  min-height: 44px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  padding: 10px 18px;
  border-radius: 10px;
  font-weight: 800;
  font-size: 0.9rem;
  cursor: pointer;
  border: none;
  transition: all 0.2s ease;
}

.btn-gold {
  background: var(--gold);
  color: #151b1a;
  box-shadow: 0 4px 14px rgba(255, 201, 90, 0.35);
}

.btn-gold:hover {
  transform: translateY(-2px);
  filter: brightness(1.1);
  box-shadow: 0 6px 20px rgba(255, 201, 90, 0.5);
}

.btn-outline {
  color: var(--ink);
  background: rgba(255,255,255,0.05);
  border: 1px solid var(--panel-border);
  text-decoration: none;
}

.btn-outline:hover {
  border-color: var(--gold);
  color: var(--gold);
  transform: translateY(-2px);
}

.header-actions { display: flex; align-items: center; gap: 10px; }
/* The narrow twin of .btn-text, shown only where the full label will not fit. */
.btn-text-short { display: none; }
/* Left to wrap, this label turns the button into a 100px-tall column that
   overflows a 60px header. It is a header control; keep it on one line. */
.header-play-link { white-space: nowrap; flex: 0 0 auto; }
/* When the reader came from the game, this is a return trip, not an invitation
   to go and play. Gold makes it findable in a header the reader is scrolling
   past on the way to the rules. */
.header-play-link.returning { border-color: var(--gold); color: var(--gold); background: rgba(255,201,90,0.12); }

.btn-icon-only {
  padding: 10px 14px;
  font-size: 1.2rem;
  background: rgba(255,255,255,0.08);
  color: var(--ink);
  border: 1px solid var(--panel-border);
}

.mobile-only { display: none !important; }

/* ==========================================================================
   MAHJONG TABLE WOOD FRAME & FELT SURFACE
   ========================================================================== */
.table-outer-wrapper {
  max-width: 1400px;
  margin: 20px auto;
  padding: 0 20px;
}

.table-wood-frame {
  position: relative;
  background: linear-gradient(145deg, var(--wood-dark), var(--wood-mid), var(--wood-dark));
  border-radius: 28px;
  padding: 18px;
  border: 4px solid var(--wood-light);
  box-shadow: 
    0 28px 80px rgba(0,0,0,0.75),
    inset 0 2px 4px rgba(255,255,255,0.2),
    inset 0 -4px 10px rgba(0,0,0,0.8);
}

/* Brass Corner Brackets */
.table-corner {
  position: absolute;
  width: 28px;
  height: 28px;
  border: 3.5px solid var(--gold);
  pointer-events: none;
}
.corner-tl { top: 12px; left: 12px; border-right: none; border-bottom: none; }
.corner-tr { top: 12px; right: 12px; border-left: none; border-bottom: none; }
.corner-bl { bottom: 12px; left: 12px; border-right: none; border-top: none; }
.corner-br { bottom: 12px; right: 12px; border-left: none; border-top: none; }

/* Green Felt Play Mat */
.table-felt-mat {
  background: linear-gradient(135deg, rgba(31,98,83,0.95), rgba(8,42,35,0.98));
  border-radius: 20px;
  padding: 24px;
  border: 1px solid var(--panel-border);
  box-shadow: inset 0 0 60px rgba(0,0,0,0.4);
  min-height: calc(100vh - 160px);
}

/* ==========================================================================
   CLEAN NON-OVERLAPPING WRAPPING TABLE TABS BAR
   ========================================================================== */
.table-mode-tabs {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  background: rgba(3, 15, 12, 0.85);
  border: 1px solid var(--panel-border);
  padding: 10px;
  border-radius: 16px;
  margin-bottom: 24px;
}

.table-tab {
  flex: 0 0 auto;
  padding: 9px 16px;
  border-radius: 10px;
  background: rgba(255, 255, 255, 0.05);
  border: 1px solid var(--panel-border);
  color: var(--muted);
  font-weight: 800;
  font-size: 0.85rem;
  cursor: pointer;
  white-space: nowrap;
  transition: all 0.2s ease;
  display: inline-flex;
  align-items: center;
  gap: 6px;
}

/* Wrapping each tab's emoji in an aria-hidden span made it a flex item, so the
   6px gap replaced the literal space it used to sit next to — about 2px wider
   per tab, which was enough to push the sixth tab onto the second row. */
.tab-icon { margin-inline-end: -2px; }

.table-tab:hover {
  color: var(--ink);
  background: rgba(255, 255, 255, 0.1);
  border-color: rgba(255, 201, 90, 0.5);
}

.table-tab.active {
  background: var(--gold);
  color: #151b1a;
  border-color: var(--gold);
  box-shadow: 0 4px 14px rgba(255, 201, 90, 0.4);
}

.terminology-strip {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 6px;
  margin: -12px 0 18px;
  padding: 8px 10px;
  color: var(--muted);
  background: rgba(3, 15, 12, 0.62);
  border: 1px solid var(--panel-border);
  border-radius: 10px;
  font-size: 0.75rem;
}
.terminology-strip strong {
  flex: 0 0 auto;
  color: var(--gold);
  letter-spacing: .06em;
}
.terminology-strip span {
  display: inline-flex;
  align-items: center;
  min-height: 26px;
  padding: 3px 8px;
  white-space: nowrap;
  background: rgba(17, 55, 47, .78);
  border: 1px solid rgba(255, 201, 90, .2);
  border-radius: 999px;
  line-height: 1.2;
}

/* Tab Panes */
.tab-pane { display: none; }
.tab-pane.active { display: block; }

/* The header is sticky, so a #hash that scrolls its target to viewport top
   parks it underneath. Naming the classes that happen to be link targets today
   is how the eight `<details id="…-detail">` blocks ended up landing behind it;
   every id inside the guide is addressable, so every id gets the offset. */
#guide-main, #guide-main [id] { scroll-margin-top: calc(var(--header-height) + 14px); }
/* main takes focus from the skip link, and a dashed ring around the whole page
   is noise — the scroll position is the feedback that it worked. */
#guide-main:focus { outline: none; }

/* ---- Claim priority, as a ladder ------------------------------------------
   Who may take a discard is the rule most often got wrong at a real table, and
   it was prose plus a three-row table. A ladder reads in one look, and the two
   things that actually decide a contested discard — which call outranks which,
   and who is nearer — sit on the rungs rather than in a sentence underneath. */
.claim-ladder { margin: 16px 0; padding: 0; }
.claim-ladder-steps { list-style: none; margin: 0; padding: 0; display: grid; gap: 8px; counter-reset: none; }
.claim-rung {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  grid-template-areas: "rank call" "rank who" "rank why";
  align-items: center;
  gap: 1px 12px;
  padding: 11px 14px;
  border: 1px solid var(--panel-border);
  border-left: 4px solid var(--gold);
  border-radius: 12px;
  background: rgba(3, 15, 12, 0.6);
}
.claim-rung--1 { border-left-color: #ffc95a; }
.claim-rung--2 { border-left-color: #7fc7a4; }
.claim-rung--3 { border-left-color: #74c0fc; }
.claim-rank { grid-area: rank; align-self: center; color: var(--gold); font-size: 1.05rem; font-weight: 1000; letter-spacing: .02em; }
.claim-rung--2 .claim-rank { color: #7fc7a4; }
.claim-rung--3 .claim-rank { color: #74c0fc; }
.claim-call { grid-area: call; color: var(--ink); font-size: 1rem; font-weight: 1000; line-height: 1.2; }
.claim-who { grid-area: who; color: var(--ink); font-size: .84rem; font-weight: 800; line-height: 1.3; }
.claim-why { grid-area: why; color: var(--muted); font-size: .8rem; font-weight: 600; line-height: 1.35; }
.claim-ladder-tie {
  margin: 10px 0 0; padding: 9px 12px;
  border: 1px dashed var(--panel-border); border-radius: 10px;
  color: var(--ink); font-size: .82rem; line-height: 1.4;
}
.claim-ladder figcaption { margin-top: 8px; color: var(--muted); font-size: .78rem; line-height: 1.4; }

/* ---- Counting the cut, on the picture -------------------------------------
   "Count 12 seats round the table, then 12 stacks along that wall" is two
   sentences a beginner has to hold in their head at once. Watching it happen on
   the diagram once is worth both of them. -------------------------------- */
.count-demo { display: flex; flex-wrap: wrap; align-items: center; justify-content: center; gap: 10px; margin: 12px 0 2px; }
.count-demo-btn {
  min-height: 44px; padding: 10px 18px; border: 2px solid var(--gold); border-radius: 999px;
  background: rgba(255, 201, 90, 0.12); color: var(--gold);
  font: inherit; font-weight: 900; cursor: pointer;
}
.count-demo-btn:hover { background: rgba(255, 201, 90, 0.22); }
.count-demo-btn[disabled] { opacity: .6; cursor: default; }
.count-demo-step { margin: 0; flex: 1 1 220px; min-width: 0; color: var(--ink); font-weight: 800; font-size: .86rem; text-align: left; }
.count-demo-step:empty { display: none; }

/* The seat currently being counted, and the one the count lands on. */
.seat-badge-box.is-counting { border-color: var(--gold); box-shadow: 0 0 0 3px var(--gold-glow), 0 4px 16px rgba(0,0,0,.5); }
.seat-badge-box.is-landed { border-color: var(--gold); background: rgba(255, 201, 90, 0.2); box-shadow: 0 0 0 4px var(--gold-glow), 0 4px 18px rgba(0,0,0,.5); }
/* A stack being counted, and the break itself. */
.wall-stack-3d.is-counting { background: var(--gold) !important; }
.wall-stack-3d.is-break { background: var(--crimson) !important; outline: 2px solid #fff3d2; outline-offset: 1px; }

@media (prefers-reduced-motion: reduce) {
  /* The walkthrough still runs, but it steps rather than sweeps — see
     app.js, which drops the per-step delay to a single settle. */
  .seat-badge-box.is-counting, .seat-badge-box.is-landed,
  .wall-stack-3d.is-counting, .wall-stack-3d.is-break { transition: none !important; }
}

/* Content Block Cards */
.content-block {
  scroll-margin-top: calc(var(--header-height) + 14px);
  background: var(--panel-bg);
  border: 1px solid var(--panel-border);
  border-radius: 20px;
  padding: 28px;
  box-shadow: 0 10px 30px rgba(0,0,0,0.5);
}

.tool-block {
  border-color: rgba(255, 201, 90, 0.4);
  background: radial-gradient(circle at 50% 20%, rgba(29, 104, 89, 0.95), rgba(13, 51, 45, 0.98));
}

.block-header { margin-bottom: 20px; }
.header-tag { font-size: 0.72rem; font-weight: 900; letter-spacing: 0.1em; color: var(--gold); text-transform: uppercase; margin-bottom: 4px; }
.block-header h2 { font-size: 1.55rem; font-weight: 900; color: var(--ink); }
.block-header p { color: var(--muted); font-size: 1rem; line-height: 1.6; margin-top: 4px; }

/* ==========================================================================
   GAME-EXACT 3D PERSPECTIVE MAHJONG TABLE & WALL PINWHEEL (📐)
   ========================================================================== */
.table-illustration-container {
  display: flex;
  justify-content: center;
  margin: 20px 0;
}

/* Real grid areas, not absolute positioning. The seat cards used to be pinned to
   the four edges of a fixed 480px box while the wall was centred on top of them,
   so on every screen narrower than about 760px they cut into the wall and the
   dice — 68px and 65px at 390px wide, and at 320px the WEST and EAST cards
   overlapped each other. Grid cells cannot overlap, so the collision cannot come
   back at a viewport nobody thought to test. */
.table-graphic-box {
  position: relative;
  width: 100%;
  max-width: 700px;
  background: radial-gradient(circle at 50% 30%, #1d6859 0%, #0d332d 60%, #051915 100%);
  border: 4px solid var(--wood-light);
  border-radius: 24px;
  box-shadow: inset 0 0 50px rgba(0,0,0,0.8), 0 16px 40px rgba(0,0,0,0.6);
  display: grid;
  /* The centre column is declared first and given a floor, so the wall keeps its
     size and the seat cards take what is left. Sizing all three from content let
     the cards starve the wall down to 16px at 320px wide. */
  grid-template-columns: minmax(0, 1fr) minmax(clamp(110px, 42vw, 320px), 1.9fr) minmax(0, 1fr);
  grid-template-rows: auto auto auto;
  grid-template-areas:
    "nw north ne"
    "west centre east"
    "sw south se";
  place-items: center;
  gap: 10px;
  padding: 30px 14px 14px;
  overflow: hidden;
}

/* The diagram is an overhead view; saying so removes the commonest source of
   confusion about which direction play runs. */
.table-view-note {
  position: absolute;
  top: 8px;
  left: 50%;
  transform: translateX(-50%);
  /* 0.7rem is 11.2px — the floor the site audit holds body text to. */
  font-size: 0.7rem;
  font-weight: 800;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: rgba(198, 194, 184, 0.78);
  white-space: nowrap;
}

/* 4 Player Active Seat Cards (Game-exact) */
.seat-badge-box {
  background: rgba(3, 15, 12, 0.88);
  border: 1px solid var(--panel-border);
  padding: 7px 12px;
  border-radius: 12px;
  font-size: 0.8rem;
  box-shadow: 0 4px 16px rgba(0,0,0,0.5);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 1px;
  text-align: center;
  z-index: 10;
}

.seat-badge-box.dealer {
  outline: 2px solid var(--gold);
  box-shadow: 0 0 20px rgba(255, 201, 90, 0.4);
}

.seat-wind-tag { font-weight: 900; color: var(--ink); white-space: nowrap; }
.seat-wind-tag.dealer { color: var(--gold); }
/* Below 380px the English word is what pushes the side cards into the wall, so
   the compass letter stands in for it. The full name is a line away in
   .seat-reference, and display:none keeps the unused form out of the a11y tree. */
.wind-short { display: none; }
/* 0.72rem is the floor for this line. It was 0.7rem of a smaller base on phones,
   which measured 9.3px — under the 11px readability floor the site audit uses. */
.seat-info { font-size: 0.72rem; color: var(--muted); line-height: 1.3; }

.seat-top { grid-area: north; }
.seat-bottom { grid-area: south; }
.seat-left { grid-area: west; }
.seat-right { grid-area: east; }

/* Turn order, drawn in the four corner cells the seat cards leave empty. East is
   at the bottom, so play moves bottom -> right -> top -> left: anticlockwise as
   seen from above, always passing to the player on the current player's right. */
.turn-arrow {
  display: block;
  width: 22px;
  height: 22px;
  color: rgba(255, 201, 90, 0.82);
}

.turn-arrow svg { display: block; width: 100%; height: 100%; }

.turn-arrow.corner-nw { grid-area: nw; transform: rotate(180deg); }
.turn-arrow.corner-ne { grid-area: ne; transform: rotate(270deg); }
.turn-arrow.corner-se { grid-area: se; }
.turn-arrow.corner-sw { grid-area: sw; transform: rotate(90deg); }

/* 3D Physical Mahjong Wall Visualizer (Game-exact 38deg Tilt)
   Fluid, not fixed: the wall takes whatever the grid's centre column leaves once
   the seat cards have their space, down to a phone. The old fixed 360x310 felt
   holding a fixed 300px wall is what forced the overlap. */
.center-felt-graphic {
  grid-area: centre;
  container-type: inline-size;
  position: relative;
  width: 100%;
  max-width: 320px;
  aspect-ratio: 1.048 / 1;
  display: grid;
  place-items: center;
}

/* Canonical game wall: 148 tiles, arranged as 74 two-high stacks. The 19-stack
   top/bottom runs and 18-stack side runs meet as a clockwise pinwheel. */
.wall-visual-3d {
  --wall-inset: 9%;
  --wall-overhang: 7%;
  /* Scales with the felt instead of being pinned at 32px, so a stack keeps its
     proportions from a 320px phone up to the 700px desktop box. */
  --wall-depth: clamp(19px, 10.6cqi, 32px);
  --wall-start: calc(var(--wall-inset) + var(--wall-depth));
  --wall-run: calc(100% - var(--wall-inset) - var(--wall-inset) - var(--wall-depth) + var(--wall-overhang));
  position: relative;
  width: 100%;
  aspect-ratio: 1.048 / 1;
  height: auto;
  transform: rotate(-4deg) scaleY(.94);
  transform-origin: center;
  filter: drop-shadow(0 8px 7px rgba(0, 0, 0, .28));
  isolation: isolate;
}

.wall-side-3d {
  position: absolute;
  display: flex;
  gap: 1px;
  align-items: stretch;
  justify-content: stretch;
  overflow: visible;
}

.wall-side-3d.top { top: var(--wall-inset); left: var(--wall-start); width: var(--wall-run); height: var(--wall-depth); }
.wall-side-3d.right { top: var(--wall-start); right: var(--wall-inset); width: var(--wall-depth); height: var(--wall-run); flex-direction: column; }
.wall-side-3d.bottom { right: var(--wall-start); bottom: var(--wall-inset); width: var(--wall-run); height: var(--wall-depth); flex-direction: row-reverse; }
.wall-side-3d.left { left: var(--wall-inset); bottom: var(--wall-start); width: var(--wall-depth); height: var(--wall-run); flex-direction: column-reverse; }

.wall-stack-3d {
  position: relative;
  display: block;
  flex: 1 1 0;
  min-width: 0;
  min-height: 0;
}

.wall-stack-3d::before,
.wall-stack-3d::after {
  content: "";
  position: absolute;
  box-sizing: border-box;
  border: 1px solid #d8dfd5;
  border-radius: 2px;
}

/* The two tiles of each stack are sized off --wall-depth rather than fixed px,
   so they stay in proportion now that the wall itself is fluid. */
.wall-side-3d.top .wall-stack-3d::before,
.wall-side-3d.bottom .wall-stack-3d::before {
  inset: calc(var(--wall-depth) * .44) 0 auto;
  height: calc(var(--wall-depth) * .5);
  background: linear-gradient(180deg, #24c77d 0 68%, #15915a 70% 74%, #f3f3e9 76% 92%, #a9beb2 94% 100%);
  box-shadow: 0 2px 0 #8ba99a, 0 3px 3px rgba(0, 0, 0, .25);
}

.wall-side-3d.top .wall-stack-3d::after,
.wall-side-3d.bottom .wall-stack-3d::after {
  inset: calc(var(--wall-depth) * .03) 0 auto;
  height: calc(var(--wall-depth) * .53);
  background: linear-gradient(180deg, #3add97 0 72%, #1daf6c 74% 78%, #faf9ef 80% 94%, #b9cec2 96% 100%);
  box-shadow: 0 2px 0 #8ba99a, 0 4px 4px rgba(0, 0, 0, .3);
}

.wall-side-3d.left .wall-stack-3d::before,
.wall-side-3d.right .wall-stack-3d::before {
  inset: 0 auto 0 calc(var(--wall-depth) * .44);
  width: calc(var(--wall-depth) * .5);
  background: linear-gradient(90deg, #24c77d 0 68%, #15915a 70% 74%, #f3f3e9 76% 92%, #a9beb2 94% 100%);
  box-shadow: 2px 0 0 #8ba99a, 3px 0 3px rgba(0, 0, 0, .25);
}

.wall-side-3d.left .wall-stack-3d::after,
.wall-side-3d.right .wall-stack-3d::after {
  inset: 0 auto 0 calc(var(--wall-depth) * .03);
  width: calc(var(--wall-depth) * .53);
  background: linear-gradient(90deg, #3add97 0 72%, #1daf6c 74% 78%, #faf9ef 80% 94%, #b9cec2 96% 100%);
  box-shadow: 2px 0 0 #8ba99a, 4px 0 4px rgba(0, 0, 0, .3);
}

/* "19 stacks" / "18 stacks" printed against each run. The caption claimed a
   19/18 split that appeared nowhere on the picture, so nobody could tell which
   side was which. Sits just inside the run, at any wall size. */
.wall-side-3d::after {
  content: attr(data-stacks);
  position: absolute;
  font-size: 0.58rem;
  font-weight: 900;
  letter-spacing: 0.04em;
  color: #cfe9dc;
  background: rgba(4, 22, 18, 0.82);
  border: 1px solid rgba(255, 255, 255, 0.16);
  border-radius: 999px;
  padding: 1px 6px;
  white-space: nowrap;
  pointer-events: none;
}

.wall-side-3d.top::after { top: calc(100% + 5px); left: 50%; transform: translateX(-50%); }
.wall-side-3d.bottom::after { bottom: calc(100% + 5px); left: 50%; transform: translateX(-50%); }
.wall-side-3d.left::after { left: calc(100% + 5px); top: 50%; transform: translateY(-50%); }
.wall-side-3d.right::after { right: calc(100% + 5px); top: 50%; transform: translateY(-50%); }

/* Center Dice & Round Card */
/* Sized in container units off the felt, so the dice stay inside the open middle
   of the wall instead of covering the runs when the wall shrinks. */
.center-dice-box {
  position: absolute;
  z-index: 5;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: clamp(2px, 1.6cqi, 5px);
  background: rgba(3, 15, 12, 0.92);
  border: 2px solid var(--gold);
  padding: clamp(4px, 2.8cqi, 9px) clamp(6px, 4cqi, 13px);
  border-radius: 14px;
  text-align: center;
  box-shadow: 0 8px 24px rgba(0,0,0,0.7);
}

/* The total sits in the caption rather than in the centre card. Inside the card
   its text set the card's width, which on a phone made the card wider than the
   open felt inside the wall and pushed it over the tiles. */
.dice-sum {
  font-weight: 800;
  color: var(--ink);
  white-space: nowrap;
  font-variant-numeric: tabular-nums;
}

.dice-sum strong { color: var(--gold); }

/* Same dice the playable table draws: a white cube with a 3x3 pip grid, and the
   1 and 4 in red as on a real set. The guide previously used the Unicode die
   glyphs (U+2680 and friends), which have no red faces and fall back to empty
   boxes on any device without them — which is what a phone showed. */
.table-dice {
  --die: clamp(14px, 8.6cqi, 27px);
  display: flex;
  align-items: center;
  gap: calc(var(--die) * 0.22);
}

.table-die {
  display: grid;
  grid-template: repeat(3, 1fr) / repeat(3, 1fr);
  width: var(--die);
  height: var(--die);
  padding: calc(var(--die) * 0.15);
  border: 1px solid #d8d2c3;
  border-radius: calc(var(--die) * 0.22);
  background: linear-gradient(145deg, #fffefa, #e8e0cf);
  box-shadow: 0 2px 0 #aaa08e, 0 5px 8px rgba(0, 0, 0, .3);
}

.table-die:nth-child(1) { transform: rotate(-7deg); }
.table-die:nth-child(3) { transform: rotate(6deg); }

.die-pip {
  width: calc(var(--die) * 0.16);
  height: calc(var(--die) * 0.16);
  place-self: center;
  border-radius: 50%;
  background: #18201e;
  box-shadow: inset 0 1px 1px rgba(255, 255, 255, .35);
}

.die-pip.red { background: #d6403a; }

.table-graphic-caption {
  max-width: 700px;
  margin: 10px auto 0;
  text-align: center;
  font-size: 0.84rem;
  line-height: 1.5;
  color: var(--muted);
}

.table-graphic-caption strong { color: var(--ink); }

/* Seat detail, at a size that can actually be read. */
.seat-reference {
  list-style: none;
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
  gap: 8px;
  margin-top: 14px;
}

.seat-reference li {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 2px;
  padding: 8px 12px;
  background: rgba(5, 21, 18, 0.6);
  border: 1px solid var(--panel-border);
  border-radius: 10px;
}

.seat-reference li.dealer { border-color: rgba(255, 201, 90, 0.55); }

.seat-ref-wind {
  font-weight: 900;
  font-size: 0.82rem;
  color: var(--ink);
  white-space: nowrap;
}

.seat-reference li.dealer .seat-ref-wind { color: var(--gold); }
.seat-ref-detail { font-size: 0.78rem; color: var(--muted); }
.seat-ref-detail strong { color: var(--gold); }

/* The four notes under the diagram. The picture alone could not say what the
   dice total is for, what a prevailing wind is, or why the runs are 19 and 18 —
   all of which a first-time player asks immediately. */
.table-explainer-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
  gap: 14px;
  margin-top: 22px;
}

.table-explainer {
  background: rgba(5, 21, 18, 0.72);
  border: 1px solid var(--panel-border);
  border-radius: 14px;
  padding: 14px 16px;
}

.table-explainer h3 {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 0.98rem;
  color: var(--gold);
  margin-bottom: 8px;
}

.explainer-icon { font-size: 1.05rem; line-height: 1; }

.table-explainer p {
  font-size: 0.88rem;
  line-height: 1.6;
  color: var(--muted);
}

.table-explainer p + p { margin-top: 8px; }
.table-explainer strong { color: var(--ink); }

.explainer-worked,
.explainer-sum {
  border-left: 3px solid rgba(255, 201, 90, 0.5);
  padding-left: 10px;
}

.explainer-sum {
  font-variant-numeric: tabular-nums;
  color: var(--ink);
}

.explainer-link {
  display: inline-block;
  margin-top: 2px;
  color: var(--gold);
  font-weight: 700;
  text-decoration: none;
  border-bottom: 1px solid rgba(255, 201, 90, 0.4);
}

.explainer-link:hover,
.explainer-link:focus-visible { border-bottom-color: var(--gold); }

.payment-flow-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 16px;
}

/* ==========================================================================
   GAME-EXACT 3D MAHJONG TILES (KAITI TYPOGRAPHY & SUIT PIPS)
   ========================================================================== */
.wood-tile-rack {
  background: linear-gradient(180deg, var(--wood-mid) 0%, var(--wood-dark) 100%);
  border: 2px solid var(--wood-light);
  border-radius: 14px;
  padding: 16px;
  box-shadow: inset 0 2px 4px rgba(255,255,255,0.15), 0 8px 20px rgba(0,0,0,0.6);
}

.tile-tabs { display: flex; gap: 8px; margin-bottom: 16px; overflow-x: auto; padding-bottom: 4px; }
.tile-tab { padding: 8px 16px; border-radius: 99px; background: rgba(255,255,255,0.06); border: 1px solid var(--panel-border); color: var(--muted); font-weight: 800; font-size: 0.85rem; cursor: pointer; white-space: nowrap; }
.tile-tab.active { background: var(--gold); color: #151b1a; border-color: var(--gold); }

.tiles-showcase-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(64px, 1fr));
  gap: 10px;
}

/* 3D Mahjong Tile matching the game */
.mj-tile-card {
  width: 60px;
  height: 82px;
  padding: 0;
  color: inherit;
  font: inherit;
  background-color: #f4ead0;
  background-image: url("../singapore-mahjong/assets/tile-face.png");
  background-repeat: no-repeat;
  background-position: center;
  background-size: 156% 156%;
  border-radius: 8px;
  border: 1px solid transparent;
  box-shadow: 
    0 4px 0 #77694e,
    0 6px 12px rgba(0,0,0,0.4),
    inset 0 1px 0 #ffffff;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  position: relative;
  user-select: none;
  cursor: pointer;
  transition: transform 0.15s ease, box-shadow 0.15s ease;
}

.mj-tile-card:focus-visible {
  outline: 3px solid #fff;
  outline-offset: 3px;
}

.mj-tile-card:hover {
  transform: translateY(-6px);
  box-shadow: 0 8px 0 #77694e, 0 10px 18px rgba(0,0,0,0.5);
}

.mj-tile-card.selected-discard {
  outline: 3px solid var(--crimson);
  transform: translateY(-8px);
}

/* A raised trainer tile was clipped by the rack's scrolling boundary. Keep
   its face in place; an inset ring also survives that boundary. */
#trainerHandRow .mj-tile-card:hover,
#trainerHandRow .mj-tile-card.selected-discard {
  transform: none;
}

#trainerHandRow .mj-tile-card.selected-discard {
  outline-offset: -3px;
}

#trainerHandRow .mj-tile-card:focus-visible {
  outline: 3px solid #225bcc;
  outline-offset: -5px;
}

#trainerFeedback:has(.trainer-choice) {
  display: grid;
  grid-template-columns: 76px minmax(0, 1fr);
  align-items: start;
  gap: 14px;
}

.trainer-choice {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 9px;
  text-align: center;
}

.trainer-choice .trainer-choice-tile {
  width: 54px;
  height: 74px;
  flex: none;
  transform: none;
  cursor: default;
}

.trainer-choice-label { font-size: .82rem; line-height: 1.4; }
.trainer-explanation { min-width: 0; }
.trainer-explanation .feedback-icon { margin-right: .3em; }

/* Exact tile-face language used by the playable Singapore Mahjong table. */
.mj-tile-card > .tile-art {
  position: absolute;
  inset: 4px 4px 15px;
  display: grid;
  place-items: center;
  color: #171b1a;
  font-family: var(--font-chinese);
}

.mj-tile-card .tile-character {
  align-content: center;
  gap: 0;
  line-height: 0.92;
}

.mj-tile-card .tile-character .tile-rank {
  color: #171b1a;
  font-size: 1.42rem;
  font-weight: 900;
}

.mj-tile-card .tile-character .tile-wan {
  color: #b63836;
  font-size: 1.25rem;
  font-weight: 900;
}

.mj-tile-card .tile-suit-svg,
.mj-tile-card .bamboo-eight-svg {
  width: 88%;
  height: 88%;
  overflow: visible;
}

.mj-tile-card .tile-dots,
.mj-tile-card .tile-bamboo-pips {
  position: absolute;
  inset: 3px;
}

.mj-tile-card .tile-dots i,
.mj-tile-card .tile-bamboo-pips i {
  position: absolute;
  left: 50%;
  top: 50%;
  display: block;
  transform: translate(-50%, -50%);
  background: var(--pip-color);
}

.mj-tile-card .tile-dots i {
  width: 9px;
  height: 9px;
  border: 2px solid var(--pip-color);
  border-radius: 50%;
  background: transparent;
  box-shadow: inset 0 0 0 1.5px #f7f0d9;
}

.mj-tile-card .tile-bamboo-pips i {
  width: 5px;
  height: 16px;
  border: 1px solid color-mix(in srgb, var(--pip-color) 75%, #10231d);
  border-radius: 45%;
  box-shadow: inset 0 -4px 0 rgba(255,255,255,.28);
}

.mj-tile-card .tile-bonus {
  align-content: center;
  font-weight: 900;
  line-height: 1;
}

.mj-tile-card .tile-bonus .tile-rank {
  position: absolute;
  left: 2px;
  top: 2px;
  color: #b63836;
  font-size: 0.8rem;
}

.mj-tile-card .tile-bonus > i { color: #d75367; font-size: 1.65rem; font-style: normal; }
.mj-tile-card .tile-season > i { color: #27875d; }
.mj-tile-card .tile-bonus > small { color: #171b1a; font-size: 0.7rem; }
.mj-tile-card .tile-animal { font-family: system-ui, sans-serif; font-size: 2.1rem; }
.mj-tile-card .animal-art svg { display: block; width: 88%; height: 88%; margin: auto; overflow: visible; }
.mj-tile-card .animal-art .animal-line { fill: none; stroke: #164b3c; stroke-width: 2.4; stroke-linecap: round; stroke-linejoin: round; }
.mj-tile-card .animal-art .animal-fill { fill: #df624c; stroke: #164b3c; stroke-width: 1.8; stroke-linejoin: round; }
.mj-tile-card .animal-art .animal-secondary { fill: #2f8163; stroke: #164b3c; stroke-width: 1.8; stroke-linejoin: round; }
.mj-tile-card .animal-art .animal-gold { fill: #e7a83e; stroke: #164b3c; stroke-width: 1.8; stroke-linejoin: round; }
.mj-tile-card .animal-art .animal-cream { fill: #fff2cf; stroke: #164b3c; stroke-width: 1.4; }
.mj-tile-card .animal-art .animal-dark { fill: #164b3c; }
.mj-tile-card .animal-art .animal-cheek { fill: #ed8b85; }
.mj-tile-card .numbered-bonus svg { display: block; width: 86%; height: 86%; margin: auto; overflow: visible; }
.mj-tile-card .numbered-bonus .bonus-line { fill: none; stroke: #164b3c; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }
.mj-tile-card .numbered-bonus .bonus-hanzi { font: 900 12px var(--font-chinese); fill: #173d32; text-anchor: middle; paint-order: stroke; stroke: #fff5d8; stroke-width: 2.2px; stroke-linejoin: round; }
.mj-tile-card .tile-bonus .bonus-number { left: 3%; top: 3%; display: grid; place-items: center; width: 1.25em; height: 1.25em; border: .07em solid #fff3d2; border-radius: 50%; background: #a92b21; color: #fffdf5; box-shadow: 0 .08em .12em rgba(29,52,43,.34); font-family: Georgia,serif; font-size: 1.08em; font-weight: 900; line-height: 1; }
.mj-tile-card .tile-honor { font-size: 2rem; font-weight: 900; }
.mj-tile-card .honor-red { color: #b63836; }
.mj-tile-card .honor-green { color: #176b42; }
.mj-tile-card .honor-wind { color: #171b1a; }
.mj-tile-card .honor-white i {
  width: 29px;
  height: 38px;
  border: 3px solid #176b42;
  box-shadow: inset 0 0 0 3px #f7f0d9;
}

.mj-rank {
  font-family: var(--font-chinese);
  font-size: 1.35rem;
  font-weight: 900;
  line-height: 1;
  color: #171b1a;
}

.mj-suit-name {
  font-family: var(--font-chinese);
  font-size: 1.2rem;
  font-weight: 900;
  line-height: 1;
}

.mj-suit-name.wan { color: var(--crimson); }
.mj-suit-name.suo { color: var(--jade); }
.mj-suit-name.tong { color: var(--blue-dots); }
.mj-suit-name.dragon-red { color: var(--crimson); font-size: 1.7rem; }
.mj-suit-name.dragon-green { color: var(--jade); font-size: 1.7rem; }
.mj-suit-name.dragon-white { 
  width: 22px;
  height: 30px;
  border: 2px solid var(--blue-dots);
  border-radius: 3px;
  box-shadow: inset 0 0 0 2px #fffdf5;
}

.mj-bonus-badge {
  font-size: 1.1rem;
  font-weight: 900;
  font-family: var(--font-chinese);
  color: #d9480f;
}

.mj-label-sub {
  position: absolute;
  bottom: 3px;
  /* 11.04px. Measured at every audit viewport down to 320px: none of the 46
     showcase labels clip or outgrow their tile at this size, so the old 9.6px
     was costing readability for nothing. The narrower rows inside
     .hand-tiles-row have their own rule and their own floor. */
  font-size: 0.69rem;
  font-weight: 800;
  color: #666;
}

/* Combos Showcase Cards */
.combos-showcase-list { display: flex; flex-direction: column; gap: 20px; }
.combo-card-item { background: rgba(3, 15, 12, 0.7); border: 1px solid var(--panel-border); border-radius: 16px; padding: 20px; }
.combo-meta { display: flex; align-items: center; justify-content: space-between; margin-bottom: 6px; }
.combo-name { font-size: 1.1rem; font-weight: 900; color: var(--ink); }
.combo-desc { font-size: 0.94rem; line-height: 1.55; color: var(--muted); margin-bottom: 10px; }
.hand-tiles-row { display: flex; gap: 6px; overflow-x: auto; padding-bottom: 4px; }
/* The row is already set up to scroll, but a flex child shrinks by default, so
   fourteen 60px tiles were dividing a 320px phone into 4px slivers instead of
   overflowing. Hold their width and let the row do what it was written to do. */
.hand-tiles-row .mj-tile-card { flex: 0 0 auto; }

/* Multi-Scenario Discard Trainer */
.scenario-tabs { display: flex; gap: 8px; overflow-x: auto; padding-bottom: 4px; }
.scenario-btn { padding: 8px 14px; border-radius: 8px; background: rgba(255,255,255,0.06); border: 1px solid var(--panel-border); color: var(--muted); font-weight: 800; font-size: 0.85rem; cursor: pointer; white-space: nowrap; }
.scenario-btn.active { background: var(--gold); color: #151b1a; border-color: var(--gold); }
.trainer-box { display: flex; flex-direction: column; gap: 16px; }
.felt-hand-area { background: rgba(0,0,0,0.3); border-radius: 14px; padding: 16px; display: flex; flex-direction: column; gap: 10px; }
.hand-label { display: flex; flex-direction: column; gap: 10px; font-size: 0.9rem; font-weight: 800; line-height: 1.5; color: var(--gold); }
.scenario-question { display: block; }
.scenario-clues { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 8px; }
.scenario-clue { display: flex; flex-direction: column; gap: 2px; padding: 9px 11px; border: 1px solid rgba(255, 201, 90, 0.24); border-radius: 9px; background: rgba(255,255,255,0.05); color: var(--muted); font-size: 0.82rem; font-weight: 650; }
.scenario-clue strong { color: var(--ink); font-size: 0.86rem; }
@media (max-width: 640px) { .scenario-clues { grid-template-columns: 1fr; } }
.trainer-feedback { padding: 14px; border-radius: 10px; font-size: 0.96rem; line-height: 1.55; font-weight: 700; display: flex; align-items: center; gap: 10px; border: 1px solid transparent; }

/* Calculator Grid */
.calculator-grid { display: grid; grid-template-columns: 1.3fr 1fr; gap: 24px; }
.calculator-grid > * { min-width: 0; }
.calc-inputs { display: flex; flex-direction: column; gap: 16px; }
.input-group { min-width: 0; background: rgba(3, 15, 12, 0.6); border: 1px solid var(--panel-border); border-radius: 14px; padding: 18px; }
.group-title { display: block; font-size: 0.85rem; font-weight: 900; color: var(--gold); margin-bottom: 10px; }

.toggle-buttons { display: flex; gap: 10px; }
.mt-2 { margin-top: 10px; }
.btn-toggle { flex: 1; padding: 10px 12px; border-radius: 8px; background: rgba(255, 255, 255, 0.05); border: 1px solid var(--panel-border); color: var(--muted); font-weight: 800; font-size: 0.85rem; cursor: pointer; transition: all 0.2s ease; }
.btn-toggle.active { background: var(--gold); color: #151b1a; border-color: var(--gold); box-shadow: 0 4px 14px rgba(255, 201, 90, 0.4); }

.calc-checkbox-grid { display: flex; flex-direction: column; gap: 6px; }
.calc-select-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(170px, 1fr)); gap: 10px; margin-bottom: 10px; }
.calc-field { display: flex; flex-direction: column; gap: 6px; color: var(--muted); font-size: 0.88rem; font-weight: 700; }
.calc-select { width: 100%; min-width: 0; padding: 10px 12px; border: 1px solid var(--panel-border); border-radius: 9px; background: #0b211b; color: var(--ink); font: inherit; }
.calc-select:focus-visible { outline: 3px solid #fff; outline-offset: 2px; border-color: var(--gold); }
.calc-select-wide { margin-top: 2px; }
.calc-help { margin-top: 10px; color: var(--muted); font-size: 0.86rem; line-height: 1.55; }
.calc-cb { position: relative; display: flex; align-items: center; gap: 10px; padding: 8px 10px; border-radius: 8px; cursor: pointer; user-select: none; transition: background 0.15s ease; }
.calc-cb:hover { background: rgba(255, 255, 255, 0.04); }
.calc-cb input { position: absolute; inline-size: 1px; block-size: 1px; opacity: 0; }
.cb-box { width: 18px; height: 18px; border: 2px solid var(--panel-border); border-radius: 5px; background: rgba(0,0,0,0.3); display: grid; place-items: center; transition: all 0.2s ease; }
.calc-cb input:checked + .cb-box { background: var(--gold); border-color: var(--gold); }
.calc-cb input:checked + .cb-box::after { content: '✓'; color: #151b1a; font-weight: 900; font-size: 0.8rem; }
.calc-cb input:focus-visible + .cb-box { outline: 3px solid #fff; outline-offset: 3px; }
.cb-label { min-width: 0; display: block; width: 100%; color: var(--ink); font-size: 0.94rem; font-weight: 600; line-height: 1.5; white-space: normal; overflow-wrap: anywhere; }

.table-tab:focus-visible,
.dock-item:focus-visible,
.btn-toggle:focus-visible,
.scenario-btn:focus-visible {
  outline: 3px solid #fff;
  outline-offset: 3px;
}

.tai-badge { float: right; margin-left: 8px; font-size: 0.78rem; font-weight: 900; padding: 2px 8px; border-radius: 6px; background: rgba(82, 209, 160, 0.18); color: #52d1a0; }
.tai-badge.max { background: rgba(224, 49, 49, 0.2); color: #ff6b6b; }

/* Scorecard */
.results-card { position: sticky; top: calc(var(--header-height) + 20px); background: rgba(3, 15, 12, 0.94); border: 2px solid var(--gold); border-radius: 18px; padding: 24px; display: flex; flex-direction: column; gap: 18px; box-shadow: 0 12px 36px rgba(0,0,0,0.6); }
.results-header { display: flex; align-items: center; justify-content: space-between; border-bottom: 1px solid var(--panel-border); padding-bottom: 12px; }
.results-header h3 { font-size: 1.1rem; font-weight: 900; color: var(--gold); }
.base-chip-rate { font-size: 0.75rem; color: var(--muted); }

.tai-counter-display { display: flex; align-items: center; gap: 16px; background: rgba(0,0,0,0.4); border-radius: 14px; padding: 16px; }
.tai-number { font-size: 3.2rem; font-weight: 900; line-height: 1; color: var(--gold); font-family: var(--font-mono); min-width: 60px; text-align: center; }
.tai-unit { display: flex; flex-direction: column; gap: 2px; }
.tai-unit span:first-child { font-size: 0.85rem; font-weight: 900; letter-spacing: 0.1em; color: var(--muted); }
.tai-status-text { font-size: 0.88rem; font-weight: 800; color: #ff6b6b; }
.tai-status-text.valid { color: #52d1a0; }

.payout-breakdown { display: flex; flex-direction: column; gap: 6px; }
.breakdown-row { display: flex; justify-content: space-between; font-size: 0.9rem; color: var(--muted); }
.breakdown-row.highlight-row { color: var(--ink); font-weight: 800; }
.breakdown-row strong { color: var(--gold); }

.payout-matrix-box h4 { font-size: 0.8rem; font-weight: 900; color: var(--muted); text-transform: uppercase; margin-bottom: 8px; }
.matrix-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; }
.matrix-seat { background: rgba(255,255,255,0.04); border: 1px solid var(--panel-border); border-radius: 10px; padding: 8px 10px; display: flex; flex-direction: column; }
.matrix-seat.winner-seat { background: rgba(255, 201, 90, 0.15); border-color: var(--gold); }
.seat-label { font-size: 0.72rem; color: var(--muted); }
.seat-amount { font-size: 1rem; font-weight: 900; font-family: var(--font-mono); }
.seat-amount.positive { color: #52d1a0; }
.seat-amount.negative { color: #ff6b6b; }

.calc-alert-box { display: flex; align-items: flex-start; gap: 10px; background: rgba(224, 49, 49, 0.15); border: 1px solid rgba(224, 49, 49, 0.4); padding: 12px; border-radius: 10px; font-size: 0.9rem; line-height: 1.5; color: #ffc9c9; }
.calc-alert-box.info { background: rgba(51, 154, 240, 0.13); border-color: rgba(116, 192, 252, 0.42); color: #d0ebff; }
.calc-counted-box { background: rgba(255,255,255,0.035); border: 1px solid var(--panel-border); border-radius: 10px; padding: 12px; }
.calc-counted-box h4 { margin-bottom: 7px; color: var(--muted); font-size: 0.75rem; letter-spacing: 0.06em; text-transform: uppercase; }
.calc-counted-box ul { padding-left: 18px; color: var(--ink); font-size: 0.88rem; line-height: 1.6; }

/* Rulebook Container */
.rulebook-container { display: grid; grid-template-columns: 240px 1fr; gap: 24px; }
.rulebook-toc { position: sticky; top: calc(var(--header-height) + 20px); height: fit-content; max-height: min(46vh, calc(100vh - var(--header-height) - 40px)); overflow-y: auto; overscroll-behavior-y: contain; touch-action: pan-y; -webkit-overflow-scrolling: touch; scrollbar-gutter: stable; scrollbar-width: thin; scrollbar-color: rgba(255, 201, 90, 0.72) rgba(255,255,255,0.06); background: rgba(3, 15, 12, 0.85); border: 1px solid var(--panel-border); border-radius: 14px; padding: 16px; display: flex; flex-direction: column; gap: 4px; }
.toc-title { font-size: 0.72rem; font-weight: 900; color: var(--gold); letter-spacing: 0.08em; margin-bottom: 8px; }
.toc-scroll-cue { margin: -4px 0 6px; color: var(--muted); font-size: 0.7rem; font-weight: 700; }
.rulebook-toc::-webkit-scrollbar { width: 8px; }
.rulebook-toc::-webkit-scrollbar-track { background: rgba(255,255,255,0.06); border-radius: 999px; }
.rulebook-toc::-webkit-scrollbar-thumb { background: rgba(255, 201, 90, 0.72); border-radius: 999px; }
.toc-link { font-size: 0.86rem; color: var(--muted); text-decoration: none; padding: 6px 8px; border-radius: 6px; }
.toc-link:hover { color: var(--ink); background: rgba(82, 209, 160, 0.15); }
/* min-width:0 is required: as a grid item this defaults to min-width:auto and
   refuses to shrink below its content's min-content width, which pushed the
   rulebook ~14px past a 360px viewport. The same applies to the section cards
   and to any scroll container inside them. */
.rulebook-content { display: flex; flex-direction: column; gap: 24px; min-width: 0; }
.rulebook-content > .content-block { min-width: 0; }
.rulebook-body, .table-scroll { min-width: 0; max-width: 100%; }

/* Cards & Components */
.text-card-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); gap: 16px; }
.info-card { background: rgba(3, 15, 12, 0.7); border: 1px solid var(--panel-border); border-radius: 14px; padding: 18px; display: flex; flex-direction: column; gap: 6px; }
.info-card.highlight-card { background: rgba(31, 98, 83, 0.25); border-color: rgba(82, 209, 160, 0.4); }
.info-card h3 { font-size: 1rem; font-weight: 900; color: var(--ink); }
.info-card p { font-size: 0.96rem; line-height: 1.6; color: var(--muted); }

/* Accurate teaching visuals: every tile face is produced by the same renderer
   as the playable Singapore Mahjong table; these wrappers only arrange them. */
.rule-visual { min-width: 0; margin-top: 16px; padding: 16px; border: 1px solid rgba(255, 201, 90, 0.32); border-radius: 14px; background: linear-gradient(135deg, rgba(31,98,83,.28), rgba(3,15,12,.78)); display: flex; align-items: center; justify-content: space-between; gap: 18px; }
.rule-visual-copy { min-width: 0; flex: 1 1 260px; }
.rule-visual h3 { margin: 2px 0 6px; color: var(--ink); font-size: 1rem; }
.rule-visual p { color: var(--muted); font-size: 0.92rem; line-height: 1.6; }
.rule-visual p strong { color: var(--ink); }
.visual-kicker { color: var(--gold); font-size: 0.7rem; font-weight: 900; letter-spacing: .1em; }

/* Reconciles the 46 faces on the rack with the 148 tiles in the heading. */
.rack-note {
  margin: -6px 0 14px;
  font-size: 0.84rem;
  line-height: 1.55;
  color: var(--muted);
}
.rack-note strong { color: var(--ink); }
.rule-visual-flow { min-width: 0; display: flex; align-items: center; gap: 12px; }
.visual-tile-group { display: flex; flex-direction: column; align-items: center; gap: 7px; }
.visual-label { color: var(--muted); font-size: 0.78rem; font-weight: 800; text-align: center; }
.visual-arrow { color: var(--gold); font-size: 1.4rem; font-weight: 900; }
.forbidden-group { padding: 9px; border: 1px solid rgba(255,107,107,.5); border-radius: 11px; background: rgba(224,49,49,.1); }
.rule-visual-grid { min-width: 0; display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 14px; }
.compact-rule-visual { flex-direction: column; align-items: flex-start; justify-content: flex-start; }
.mini-tile-row, .micro-tile-row { min-width: 0; display: flex; align-items: flex-end; gap: 5px; }
.mini-tile-row .mj-tile-card { width: 43px; height: 59px; flex: 0 0 43px; border-radius: 6px; }
.mini-tile-row .mj-tile-card > .tile-art { inset: 3px 3px 11px; transform: scale(.76); }
.mini-tile-row .mj-label-sub, .micro-tile-row .mj-label-sub { display: none; }
.scroll-tile-row { max-width: 100%; overflow-x: auto; padding: 5px 4px 9px; }
.rule-visual .mj-tile-card, .kong-payment-visual .mj-tile-card { cursor: default; }
.rule-visual .mj-tile-card:hover, .kong-payment-visual .mj-tile-card:hover { transform: none; }
.kong-payment-visual { min-width: 0; display: grid; grid-template-columns: repeat(3, minmax(0,1fr)); gap: 10px; }
.kong-payment-card { min-width: 0; padding: 12px; border: 1px solid var(--panel-border); border-radius: 12px; background: rgba(3,15,12,.72); display: flex; flex-direction: column; gap: 8px; }
.kong-payment-card.concealed { border-color: rgba(255,201,90,.5); }
.kong-payment-card strong { color: var(--ink); font-size: .86rem; line-height: 1.45; }
.micro-tile-row { gap: 2px; }
.micro-tile-row .mj-tile-card { width: 29px; height: 40px; flex: 0 0 29px; border-radius: 4px; box-shadow: 0 2px 0 #77694e, 0 3px 6px rgba(0,0,0,.35); }
.micro-tile-row .mj-tile-card > .tile-art { inset: 2px 2px 7px; transform: scale(.53); }

/* Captioned tile figure. Every worked shape in the rulebook is drawn with the
   same renderer as the playable table, so a reader is never asked to picture a
   hand from prose alone. The rows scroll rather than shrink: a 14-tile hand
   below ~430px would otherwise squeeze the faces past legibility. */
.tile-figure { min-width: 0; margin: 4px 0 0; padding: 14px 16px; border: 1px solid var(--panel-border); border-radius: 14px; background: rgba(3, 15, 12, 0.62); display: flex; flex-direction: column; gap: 12px; }
.tile-figure + .tile-figure { margin-top: 12px; }
.figure-rows { min-width: 0; max-width: 100%; display: flex; flex-wrap: wrap; align-items: flex-end; gap: 14px 18px; }
.figure-rows.figure-scroll { flex-wrap: nowrap; overflow-x: auto; padding-bottom: 6px; }
/* A fourteen-tile row is a single flex item and cannot wrap, so on a narrow
   phone it must scroll rather than bleed out of the card. Two arrangements:
   a wrapping row lets each group scroll its own tiles, while a .figure-scroll
   row scrolls as a whole and its groups must keep their natural width —
   without flex:0 0 auto they compress to a column of wrapped label text with
   the tiles crushed to slivers underneath. */
.tile-figure .visual-tile-group { min-width: 0; max-width: 100%; flex: 0 1 auto; }
.tile-figure .micro-tile-row, .tile-figure .mini-tile-row { max-width: 100%; overflow-x: auto; padding-bottom: 3px; }
.figure-rows.figure-scroll > * { flex: 0 0 auto; max-width: none; }
.figure-rows.figure-scroll .micro-tile-row,
.figure-rows.figure-scroll .mini-tile-row { max-width: none; overflow-x: visible; }
.figure-rows.figure-scroll .visual-label { max-width: 260px; }
.tile-figure figcaption { color: var(--muted); font-size: 0.92rem; line-height: 1.6; }
.tile-figure figcaption strong { color: var(--ink); }
.tile-figure figcaption .verdict-yes { color: #52d1a0; font-weight: 800; }
.tile-figure figcaption .verdict-no { color: #ff8f8f; font-weight: 800; }
.ok-group { padding: 9px; border: 1px solid rgba(82, 209, 160, 0.5); border-radius: 11px; background: rgba(23, 107, 66, 0.16); }
/* 0.7rem is 11.2px. Inheriting 0.78rem*0.83 put all 62 of these at 10.4px. */
.visual-tile-group .visual-label small { display: block; font-size: 0.7rem; font-weight: 700; color: var(--gold); }
.card-tiles { margin-top: 8px; }
.info-card .micro-tile-row, .info-card .mini-tile-row { flex-wrap: wrap; }

/* Restored rulebook prose. The global reset zeroes every margin and padding,
   so running text needs its spacing and list indents restored explicitly or it
   renders as one unbroken block with the list markers clipped at the edge. */
.rulebook-body { display: flex; flex-direction: column; gap: 12px; margin-top: 18px; }
.rulebook-body p, .rulebook-body li { font-size: 1rem; line-height: 1.72; color: var(--muted); }
.rulebook-body strong { color: var(--ink); font-weight: 700; }
.rulebook-body em { color: var(--ink); font-style: italic; }
/* Keep the lists as blocks: making them flex containers would blockify the
   list items and drop their markers. */
.rulebook-body ul, .rulebook-body ol { padding-left: 24px; }
.rulebook-body li { margin-bottom: 8px; }
.rulebook-body li:last-child { margin-bottom: 0; }
.rulebook-body li::marker { color: var(--gold); }
.rulebook-body a { color: var(--gold); text-decoration: underline; text-underline-offset: 2px; }

/* Any prose link that carries no class of its own. Five of them — two figure
   captions and three cross-references — sat outside .rulebook-body and so kept
   the UA's default blue, which measures 2.05:1 against this felt against a 4.5
   requirement. Classed links (.btn, .explainer-link, .source-links a) keep their
   own colour. */
.content-block a:not([class]) {
  color: var(--gold);
  text-decoration: underline;
  text-underline-offset: 2px;
}

/* Inline SVG figures. Kept self-contained: no external assets, sized by
   viewBox so they scale with the column rather than overflowing it. */
.diagram-card { background: rgba(3, 15, 12, 0.7); border: 1px solid var(--panel-border); border-radius: 14px; padding: 16px; display: flex; flex-direction: column; gap: 10px; }
.diagram-card svg { display: block; width: 100%; height: auto; max-width: 340px; margin: 0 auto; }
.diagram-card figcaption { font-size: 0.92rem; line-height: 1.65; color: var(--muted); }
.diagram-card figcaption strong { color: var(--ink); }
.diagram-card figcaption em { color: var(--muted); opacity: 0.85; font-size: 0.95em; }
.diagram-note { font-size: 0.95rem; line-height: 1.65; color: var(--muted); font-style: italic; }

/* Search-first summaries: a direct answer before the interactive table, then an
   app-exact catalogue whose labels keep hand shapes separate from circumstances. */
.guide-answer-card {
  margin: 0 0 20px;
  padding: clamp(18px, 3vw, 28px);
  border: 1px solid rgba(255, 201, 90, 0.52);
  border-radius: 22px;
  background: radial-gradient(circle at 0 0, rgba(255, 201, 90, 0.14), transparent 42%), linear-gradient(145deg, rgba(15, 72, 59, 0.96), rgba(3, 20, 16, 0.97));
  box-shadow: 0 18px 44px rgba(0, 0, 0, 0.34);
}
.guide-answer-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 20px; }
.guide-answer-head h2 { margin-top: 3px; color: var(--ink); font-size: clamp(1.45rem, 3vw, 2.05rem); line-height: 1.16; }
.guide-reviewed { flex: 0 0 auto; display: flex; flex-direction: column; align-items: flex-end; color: var(--muted); font-size: .78rem; line-height: 1.4; }
.guide-reviewed span { color: var(--gold); font-weight: 850; letter-spacing: .04em; text-transform: uppercase; }
.guide-reviewed a { color: inherit; }
.guide-reviewed time { color: var(--ink); font-weight: 750; }
.guide-answer-lead { max-width: 1050px; margin-top: 14px; color: var(--muted); font-size: 1.03rem; line-height: 1.68; }
.guide-answer-lead strong { color: var(--ink); }
.guide-answer-facts { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 10px; margin-top: 18px; }
.guide-answer-facts div { min-width: 0; padding: 12px 14px; border: 1px solid var(--panel-border); border-radius: 12px; background: rgba(0, 0, 0, .22); }
.guide-answer-facts strong, .guide-answer-facts span { display: block; }
.guide-answer-facts strong { color: var(--gold); font-size: 1.12rem; line-height: 1.25; }
.guide-answer-facts span { margin-top: 2px; color: var(--muted); font-size: .82rem; line-height: 1.4; }
.guide-answer-links { display: flex; flex-wrap: wrap; gap: 8px 16px; margin-top: 16px; }
.guide-answer-links a { display: inline-flex; align-items: center; min-height: 44px; color: var(--gold); font-size: .9rem; font-weight: 800; text-underline-offset: 3px; }
.guide-answer-links a::after { content: ' →'; }

.winning-catalogue { scroll-margin-top: calc(var(--header-height) + 14px); display: flex; flex-direction: column; gap: 14px; margin: 22px 0 28px; }
.catalogue-heading { display: flex; align-items: flex-end; justify-content: space-between; gap: 18px; }
.catalogue-heading h3 { margin-top: 3px; color: var(--ink); font-size: 1.24rem; }
.catalogue-heading--secondary { margin-top: 7px; }
.catalogue-key { display: flex; flex-wrap: wrap; justify-content: flex-end; gap: 7px; }
.catalogue-intro { color: var(--muted); font-size: .96rem; line-height: 1.6; }
.rule-status { display: inline-flex; align-items: center; width: fit-content; padding: 3px 8px; border: 1px solid rgba(82, 209, 160, .46); border-radius: 999px; color: #9debc9; background: rgba(23, 107, 66, .2); font-size: .7rem; font-weight: 900; line-height: 1.3; letter-spacing: .025em; vertical-align: middle; }
.rule-status--house { border-color: rgba(255, 201, 90, .56); color: var(--gold); background: rgba(255, 201, 90, .11); }
.winning-catalogue-table { min-width: 800px; }
.winning-catalogue-table td:first-child { color: #9debc9; font-size: .78rem; font-weight: 850; text-transform: uppercase; letter-spacing: .025em; }
.winning-catalogue-table td:last-child { color: var(--ink); }
.ruleset-note { padding: 18px; border: 1px solid var(--panel-border); border-radius: 14px; background: rgba(3, 15, 12, .72); }
.ruleset-note--important { border-color: rgba(255, 201, 90, .52); background: linear-gradient(135deg, rgba(255, 201, 90, .11), rgba(3, 15, 12, .78)); }
.ruleset-note h3 { margin: 7px 0 5px; color: var(--ink); font-size: 1.08rem; }
.ruleset-note p { color: var(--muted); font-size: .94rem; line-height: 1.62; }
.ruleset-note p strong { color: var(--ink); }
.catalogue-section-title { margin: 5px 0 15px; color: var(--ink); font-size: 1.16rem; }

/* Glossary filter */
.glossary-filter { display: flex; flex-wrap: wrap; align-items: center; gap: 10px 14px; margin-bottom: 14px; }
.glossary-filter input[type="search"] {
  flex: 1 1 240px; min-width: 0; padding: 10px 14px; border-radius: 10px;
  background: rgba(3, 15, 12, 0.75); border: 1px solid var(--panel-border);
  color: var(--ink); font-family: var(--font-sans); font-size: 1rem;
}
.glossary-filter input[type="search"]::placeholder { color: var(--muted); opacity: 0.75; }
.glossary-filter input[type="search"]:focus-visible { outline: 2px solid var(--gold); outline-offset: 2px; border-color: var(--gold); }
.glossary-count { font-size: 0.9rem; color: var(--muted); white-space: nowrap; }
/* .glossary-card sets display:flex, which outranks the user-agent
   [hidden]{display:none} rule -- without this, filtered-out cards stay visible. */
.glossary-card[hidden] { display: none !important; }
.sr-only { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0; }

.section-lead { font-size: 1.04rem; line-height: 1.68; color: var(--muted); margin-bottom: 16px; }
.section-lead strong { color: var(--ink); font-weight: 700; }
.mt-3 { margin-top: 16px; }

.step-process-card { display: flex; flex-direction: column; gap: 14px; }
.process-step { display: flex; gap: 14px; background: rgba(3, 15, 12, 0.7); border: 1px solid var(--panel-border); padding: 16px; border-radius: 14px; align-items: flex-start; }
.step-num { width: 32px; height: 32px; background: var(--gold); color: #151b1a; font-weight: 900; border-radius: 50%; display: grid; place-items: center; flex-shrink: 0; }
.step-content h3 { font-size: 1rem; font-weight: 900; color: var(--ink); }
.step-content p { font-size: 0.96rem; line-height: 1.55; color: var(--muted); margin-top: 2px; }

.table-scroll { overflow-x: auto; }
.table-scroll-hint { display: none; color: var(--gold); font-size: 0.84rem; line-height: 1.45; margin: 8px 0; }
.styled-table { width: 100%; border-collapse: collapse; text-align: left; }
.terminology-table { min-width: 760px; }
.styled-table th, .styled-table td { padding: 12px 14px; border-bottom: 1px solid var(--panel-border); font-size: 0.94rem; line-height: 1.5; }
.styled-table th { color: var(--gold); font-weight: 900; background: rgba(0,0,0,0.3); }

.tag { display: inline-block; padding: 2px 8px; border-radius: 6px; font-size: 0.72rem; font-weight: 900; }
.tag-red { background: rgba(224, 49, 49, 0.2); color: #ff6b6b; }
.tag-gold { background: rgba(255, 201, 90, 0.2); color: var(--gold); }
.tag-blue { background: rgba(51, 154, 240, 0.2); color: #74c0fc; }
.text-danger { color: #ff6b6b; }

.callout-box { display: flex; gap: 14px; padding: 18px; border-radius: 14px; }
.danger-callout { background: rgba(224, 49, 49, 0.12); border: 1px solid rgba(224, 49, 49, 0.35); }
.callout-icon { font-size: 1.8rem; }
.callout-body h3 { font-size: 1rem; color: var(--ink); margin-bottom: 4px; }
.callout-body p { font-size: 0.96rem; line-height: 1.55; color: var(--muted); }

.scoring-cards-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(220px, 1fr)); gap: 14px; }
.score-card { background: rgba(3, 15, 12, 0.7); border: 1px solid var(--panel-border); border-radius: 12px; padding: 14px; }
.score-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 6px; }
.score-title { font-weight: 800; color: var(--ink); font-size: 0.9rem; }
.score-tai { font-weight: 900; color: var(--gold); font-size: 0.85rem; flex-shrink: 0; margin-left: 8px; }
.score-desc { font-size: 0.9rem; line-height: 1.5; color: var(--muted); }

.quick-stats-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); gap: 12px; }
.stat-pill { background: rgba(3, 15, 12, 0.8); border: 1px solid var(--panel-border); border-radius: 14px; padding: 14px; display: flex; flex-direction: column; gap: 2px; }
.stat-val { font-size: 1.4rem; font-weight: 900; color: var(--gold); }
.stat-lbl { font-size: 0.86rem; line-height: 1.45; color: var(--muted); }

.mb-4 { margin-bottom: 20px; }
.faq-list { display: flex; flex-direction: column; gap: 10px; }
/* The card's padding used to sit on .faq-item, which left the <summary> — the
   only part that actually toggles — 23px tall across all 32 of them. The padding
   now lives on the summary, so the whole row is the target at 45px, and the card
   looks the same. */
.faq-item { background: rgba(3, 15, 12, 0.7); border: 1px solid var(--panel-border); border-radius: 12px; padding: 0; }
.faq-item summary { padding: 11px 16px; font-size: 1rem; line-height: 1.45; font-weight: 800; color: var(--ink); cursor: pointer; }
.faq-item summary:hover { color: var(--gold); }
.faq-item p { margin: 0 16px; padding-bottom: 12px; font-size: 0.96rem; line-height: 1.6; color: var(--muted); }

.glossary-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(240px, 1fr)); gap: 10px; }
.glossary-card { background: rgba(0,0,0,0.3); border: 1px solid var(--panel-border); padding: 12px; border-radius: 10px; display: flex; flex-direction: column; gap: 2px; }
.glossary-card strong { color: var(--gold); font-size: 0.96rem; }
.glossary-card span { color: var(--muted); font-size: 0.9rem; line-height: 1.5; }

/* Local Singapore context restored from the pre-redesign guide. */
.local-context-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 14px;
}

.context-card {
  min-width: 0;
  display: flex;
  align-items: flex-start;
  gap: 14px;
  padding: 18px;
  border: 1px solid var(--panel-border);
  border-radius: 16px;
  background: linear-gradient(145deg, rgba(12, 57, 47, 0.88), rgba(2, 24, 19, 0.9));
}

.context-card-festive { border-color: rgba(255, 201, 90, 0.5); }
.context-icon { flex: 0 0 auto; font-size: 1.55rem; line-height: 1; }
.context-card h3, .teaching-table h3, .local-practical-grid h3, .guide-cta h2 { color: var(--ink); }
.context-card h3 { margin-bottom: 5px; font-size: 1rem; }
.context-card p { color: var(--muted); font-size: 0.96rem; line-height: 1.6; }
.animal-identity-card { flex-direction: column; justify-content: space-between; }
.animal-identity-card > div:first-child { display: grid; grid-template-columns: auto 1fr; column-gap: 12px; }
.animal-identity-card > div:first-child p { grid-column: 2; }
.animal-identity-card .mini-tile-row { align-self: center; flex-wrap: nowrap; }
.animal-identity-card .mj-tile-card { width: 54px; min-width: 54px; height: 72px; }

.teaching-table {
  scroll-margin-top: calc(var(--header-height) + 14px);
  display: grid;
  grid-template-columns: minmax(220px, .72fr) minmax(0, 1.28fr);
  gap: 22px;
  padding: 22px;
  border: 1px solid rgba(255, 201, 90, 0.44);
  border-radius: 18px;
  background: radial-gradient(circle at 0 0, rgba(255, 201, 90, 0.12), transparent 42%), rgba(3, 20, 16, 0.82);
}

.teaching-table-copy h3 { margin: 8px 0; font-size: 1.25rem; }
.teaching-table-copy p { color: var(--muted); font-size: 0.98rem; line-height: 1.6; }
.teaching-steps { display: grid; gap: 9px; list-style: none; }
.teaching-steps li { min-width: 0; display: grid; grid-template-columns: 34px minmax(0, 1fr); align-items: center; gap: 11px; }
.teaching-steps li > span { width: 34px; height: 34px; display: grid; place-items: center; border-radius: 50%; background: var(--gold); color: #151b1a; font-family: var(--font-mono); font-weight: 900; }
.teaching-steps strong, .teaching-steps small { display: block; }
.teaching-steps strong { color: var(--ink); font-size: .96rem; }
.teaching-steps small { color: var(--muted); font-size: .86rem; line-height: 1.45; }

.local-practical-grid { display: grid; grid-template-columns: minmax(0, 1.15fr) minmax(260px, .85fr); gap: 14px; }
.local-legality, .quiet-table-card { min-width: 0; padding: 20px; border-radius: 16px; }
.local-legality { background: rgba(255, 201, 90, 0.09); border: 1px solid rgba(255, 201, 90, 0.42); }
.quiet-table-card { background: rgba(3, 15, 12, 0.76); border: 1px solid var(--panel-border); }
.local-legality h3, .quiet-table-card h3 { margin: 7px 0 9px; font-size: 1.08rem; }
.local-legality p, .quiet-table-card p, .quiet-table-card li { color: var(--muted); font-size: .94rem; line-height: 1.6; }
.source-links { display: flex; flex-wrap: wrap; gap: 8px 14px; margin-top: 12px; }
.source-links a { color: var(--gold); font-weight: 750; }
.legal-note { margin-top: 10px; font-size: .84rem !important; }
.quiet-table-card ul { margin: 9px 0 13px 1.1rem; display: grid; gap: 5px; }
.local-rules-heading { margin-top: 24px; color: var(--ink); }

.guide-footer {
  max-width: 1400px;
  margin: 18px auto 74px;
  padding: 0 24px;
}

.guide-cta {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 24px;
  padding: 24px;
  border: 1px solid rgba(255, 201, 90, .45);
  border-radius: 18px;
  background: linear-gradient(135deg, rgba(17, 73, 60, .94), rgba(3, 23, 18, .96));
}

.guide-cta-mid { margin: 24px 0; }

.guide-cta h2 { margin: 5px 0; font-size: 1.35rem; }
.guide-cta p { max-width: 760px; color: var(--muted); font-size: .96rem; line-height: 1.55; }
.guide-cta .btn { flex: 0 0 auto; min-height: 44px; text-decoration: none; }
/* Stacked so the second button does not turn the banner into three
   space-between columns.  No nowrap: at 320px these go full width and a
   single unbreakable line is exactly how this page fails its overflow gate. */
.guide-cta-actions { display: flex; flex-direction: column; gap: 10px; flex: 0 0 auto; }
.footer-nav { display: flex; justify-content: center; flex-wrap: wrap; gap: 8px 20px; padding: 18px 8px 0; }
/* 20px tall on its own. These are site navigation, not links inside a
   sentence, so the 24px AA floor applies to the mouse as well as the finger. */
.footer-nav a { color: var(--muted); font-size: .82rem; padding-block: 4px; }
.footer-nav a:hover { color: var(--gold); }

.action-vocabulary {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 9px;
  margin: 2px 0 18px;
}

.action-vocabulary span {
  min-width: 0;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  padding: 10px 12px;
  border: 1px solid var(--panel-border);
  border-radius: 10px;
  background: rgba(3, 15, 12, .74);
}

.action-vocabulary small { color: var(--muted); font-size: .72rem; font-weight: 850; letter-spacing: .05em; }
.action-vocabulary strong { color: var(--gold); font-family: var(--font-chinese); font-size: 1.12rem; }

/* Mobile Bottom Dock */
.mobile-dock {
  position: fixed;
  bottom: 0;
  left: 0;
  right: 0;
  height: 56px;
  background: rgba(4, 16, 13, 0.96);
  backdrop-filter: blur(14px);
  border-top: 1px solid var(--panel-border);
  display: flex;
  justify-content: space-around;
  align-items: center;
  z-index: 1000;
}

/* Each item was sized by its label — 31px wide on a 390px phone, well under a
   finger. They now share the bar equally, so every one is a full-height column
   rather than a word with dead felt around it. */
.dock-item {
  flex: 1 1 0;
  min-width: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 2px;
  height: 100%;
  padding: 0 2px;
  background: none;
  border: none;
  color: var(--muted);
  font-size: 0.7rem;
  cursor: pointer;
}

.dock-item.active { color: var(--gold); }
.dock-icon { font-size: 1.1rem; }

/* Responsive Queries */
@media (max-width: 1024px) {
  .calculator-grid { grid-template-columns: 1fr; }
  .results-card { position: static; }
  .payment-flow-grid { grid-template-columns: 1fr; }
  .rulebook-container { grid-template-columns: 1fr; }
  .rulebook-toc { display: none; }
  .teaching-table, .local-practical-grid { grid-template-columns: 1fr; }
}

@media (max-width: 768px) {
  .mobile-only { display: flex !important; }
  /* .header-play-link used to be hidden here too, which left a phone reader
     with no visible way back to the game at all — the drawer toggle was the
     only surviving header action. Keep it, shortened to fit beside the ☰. */
  .header-search, .header-actions .btn-gold { display: none; }
  .header-play-link { display: inline-flex; padding: 7px 10px; gap: 5px; white-space: nowrap; }
  .header-play-link .btn-text { display: none; }
  .header-play-link .btn-text-short { display: inline; }
  .table-outer-wrapper { padding: 0 8px; margin: 10px auto; }
  .table-wood-frame { padding: 10px; border-radius: 20px; }
  .table-felt-mat { padding: 14px; border-radius: 14px; }
  .content-block { padding: 16px; }
  .table-mode-tabs { gap: 6px; padding: 6px; }
  /* The base rule sets white-space:nowrap, so a long label such as
     "Discard Trainer (Which Tile to Throw?)" could not shrink or wrap and
     pushed the page ~9px wider than a 360px phone. Let it wrap instead. */
  .table-tab { padding: 8px 12px; font-size: 0.82rem; flex: 1 1 auto; justify-content: center; white-space: normal; min-width: 0; text-align: center; }
  .toggle-buttons { flex-direction: column; }
  .calc-select-grid { grid-template-columns: 1fr; }
  .rule-visual { flex-direction: column; align-items: stretch; }
  .rule-visual-grid, .kong-payment-visual { grid-template-columns: 1fr; }
  .rule-visual-flow { justify-content: center; flex-wrap: wrap; }
  .visual-arrow { transform: rotate(90deg); }
  .kong-payment-card { align-items: center; text-align: center; }
  .results-header { align-items: flex-start; gap: 8px; }
  .base-chip-rate { text-align: right; }

  /* The seat cards shed their detail rather than their legibility: the
     flower/season numbers moved into the reference row under the diagram, which
     is what let the wind line stay at a readable size on a phone. */
  .table-graphic-box { gap: 5px; padding: 24px 6px 8px; }
  .seat-badge-box { padding: 4px 6px; border-radius: 9px; }
  .seat-wind-tag { font-size: 0.72rem; }
  /* On a phone the badge carries the wind only; seat number, dealer status and
     the flower/season pairing are all in .seat-reference right below. */
  .seat-info { display: none; }
  .seat-reference { grid-template-columns: 1fr; gap: 6px; margin-top: 12px; }
  .seat-reference li { padding: 7px 10px; }
  .table-graphic-caption { font-size: 0.8rem; }
  .center-dice-box { border-radius: 11px; }
  .wall-side-3d::after { font-size: 0.5rem; padding: 0 4px; }
  .turn-arrow { width: 15px; height: 15px; }
  .table-view-note { top: 6px; }
  .table-explainer-grid { grid-template-columns: 1fr; gap: 10px; margin-top: 16px; }
  .table-explainer { padding: 12px 13px; }
  .local-context-grid { grid-template-columns: 1fr; }
  .context-card, .teaching-table, .local-legality, .quiet-table-card { padding: 15px; }
  .animal-identity-card .mj-tile-card { width: 48px; min-width: 48px; height: 64px; }
  .action-vocabulary { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .action-vocabulary span { padding: 9px 10px; }
  .table-scroll-hint { display: block; }
  .guide-footer { margin: 12px auto 72px; padding: 0 8px; }
  .guide-cta { align-items: stretch; flex-direction: column; padding: 18px; }
  .guide-cta .btn { width: 100%; }
  .guide-cta-actions { width: 100%; }
}

/* The cross layout runs out of room for four spelled-out winds and a usable wall
   at the same time on the narrowest phones still in the audit. Kept after the
   768px block so it wins at equal specificity. */
@media (max-width: 380px) {
  .table-graphic-box { gap: 3px; padding: 22px 4px 8px; }
  .wind-long { display: none; }
  .wind-short { display: inline; }
}

/* Phone portrait: keep the sticky header inside its own height and make the
   nine-section chooser one compact, swipeable row. The previous wrapping grid
   occupied 404px at 390px wide, placing the first guide card 539px down. */
@media (max-width: 768px) {
  :root { --header-height: 60px; }
  .header-inner { padding: 0 12px; gap: 8px; }
  .brand { min-width: 0; gap: 8px; }
  .brand-tile {
    flex: 0 0 auto;
    width: 40px;
    height: 40px;
  }
  .brand-text { min-width: 0; }
  .brand-text h1 {
    font-size: 1rem;
    line-height: 1.15;
    white-space: nowrap;
  }
  .brand-text .badge { padding: 1px 6px; font-size: .7rem; }
  .brand-text .subtitle { display: none; }
  /* The hamburger still has no drawer or click handler, and the calculator is
     in the dock, so this row was hidden entirely. That also removed the only
     link back to the game, which strands anyone who arrived here from it — the
     dock below is section shortcuts, it has no way out. Keep the row, carrying
     just that one link; the dead hamburger needs !important to beat
     .mobile-only. */
  .header-actions { display: flex; }
  .header-actions #drawerToggle { display: none !important; }
  .table-mode-tabs {
    flex-wrap: nowrap;
    justify-content: flex-start;
    gap: 6px;
    margin-bottom: 16px;
    overflow-x: auto;
    overflow-y: hidden;
    overscroll-behavior-inline: contain;
    scroll-snap-type: inline proximity;
    scrollbar-width: thin;
    scrollbar-color: rgba(255, 201, 90, .72) rgba(3, 15, 12, .7);
  }
  .table-tab {
    flex: 0 0 auto;
    min-width: max-content;
    padding: 8px 12px;
    white-space: nowrap;
    scroll-snap-align: start;
  }
  .terminology-strip { display: none; }
}

/* Short phones in landscape need a height-aware layout. Width-only queries
   treated 844x390 as desktop, leaving 129px of brand copy inside a 72px header
   and a 201px wrapped tab block before any guide content. */
@media (max-width: 900px) and (max-height: 500px) and (orientation: landscape) {
  :root { --header-height: 52px; }
  .header-inner { padding: 0 12px; gap: 8px; }
  .brand { min-width: 0; gap: 8px; }
  .brand-tile {
    flex: 0 0 auto;
    width: 36px;
    height: 36px;
  }
  .brand-text { min-width: 0; }
  .brand-text h1 {
    font-size: .96rem;
    line-height: 1.1;
    white-space: nowrap;
  }
  .brand-text .badge { padding: 1px 6px; font-size: .7rem; }
  .brand-text .subtitle,
  .header-search,
  .header-actions,
  .mobile-dock,
  .terminology-strip { display: none !important; }

  .table-outer-wrapper { margin: 6px auto; padding: 0 6px; }
  .table-wood-frame { padding: 8px; border-width: 2px; border-radius: 16px; }
  .table-felt-mat {
    min-height: calc(100vh - 64px);
    padding: 10px;
    border-radius: 12px;
  }
  .table-mode-tabs {
    flex-wrap: nowrap;
    justify-content: flex-start;
    gap: 6px;
    margin-bottom: 12px;
    padding: 6px;
    overflow-x: auto;
    overflow-y: hidden;
    overscroll-behavior-inline: contain;
    scroll-snap-type: inline proximity;
    scrollbar-width: thin;
    scrollbar-color: rgba(255, 201, 90, .72) rgba(3, 15, 12, .7);
  }
  .table-tab {
    flex: 0 0 auto;
    min-width: max-content;
    padding: 7px 10px;
    font-size: .78rem;
    white-space: nowrap;
    scroll-snap-align: start;
  }
  .content-block { padding: 14px; border-radius: 14px; }
  .block-header { margin-bottom: 12px; }
  .block-header h2 { font-size: 1.28rem; }
  .block-header p { font-size: .9rem; line-height: 1.5; }
  /* Short landscape has width to spare and almost no height, so the wall is
     capped rather than stretched and the four notes run two-up. */
  .table-illustration-container { margin: 10px 0; }
  .table-graphic-box { border-width: 3px; border-radius: 18px; padding: 22px 10px 10px; gap: 6px; }
  .center-felt-graphic { max-width: 210px; }
  .seat-badge-box { padding: 4px 8px; border-radius: 9px; }
  .table-explainer-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px; }
  .guide-footer { margin-bottom: 20px; }
}

/* ==========================================================================
   HORIZONTAL SCROLL AFFORDANCES
   A phone draws overlay scrollbars that fade within a second of the page
   settling, so a row that scrolled sideways looked exactly like one that did
   not: the nine-section chooser and the wider tile rows both read as "that is
   all there is". app.js tags every horizontal scroller with `data-scroll-x`
   and keeps `.is-scrollable` / `.at-start` / `.at-end` in step with its own
   scroll position; the rules below turn those into a visible edge fade and a
   bar that stays drawn. Nothing here changes what scrolls — only whether a
   reader can tell.
   ========================================================================== */
[data-scroll-x] {
  --edge-start: 0px;
  --edge-end: 0px;
  scrollbar-width: thin;
  scrollbar-color: rgba(255, 201, 90, 0.7) rgba(3, 15, 12, 0.55);
}
/* Asking for an explicit height opts the element out of the overlay bar that
   iOS and Android hide when idle, which is the whole problem on a phone. */
[data-scroll-x]::-webkit-scrollbar { -webkit-appearance: none; height: 6px; }
[data-scroll-x]::-webkit-scrollbar-track { background: rgba(3, 15, 12, 0.5); border-radius: 999px; }
[data-scroll-x]::-webkit-scrollbar-thumb { background: rgba(255, 201, 90, 0.62); border-radius: 999px; }
[data-scroll-x]::-webkit-scrollbar-thumb:hover { background: rgba(255, 201, 90, 0.9); }

/* The fade exists only on a side that has content past it, so it says both
   "there is more" and, at the end, "that was all". */
[data-scroll-x].is-scrollable {
  -webkit-mask-image: linear-gradient(to right, transparent 0, #000 var(--edge-start), #000 calc(100% - var(--edge-end)), transparent 100%);
  mask-image: linear-gradient(to right, transparent 0, #000 var(--edge-start), #000 calc(100% - var(--edge-end)), transparent 100%);
}
[data-scroll-x].is-scrollable:not(.at-start) { --edge-start: 26px; }
[data-scroll-x].is-scrollable:not(.at-end) { --edge-end: 26px; }

/* A region you can only reach by dragging is not reachable by keyboard, so
   app.js makes the overflowing ones focusable; give that focus a ring. */
[data-scroll-x]:focus-visible { outline: 2px solid var(--gold); outline-offset: 3px; border-radius: 6px; }

/* Room for the bar, so it never sits on top of a tile face. */
.hand-tiles-row.is-scrollable,
.tile-figure .micro-tile-row.is-scrollable,
.tile-figure .mini-tile-row.is-scrollable,
.figure-rows.figure-scroll.is-scrollable { padding-bottom: 11px; }
.tile-tabs.is-scrollable,
.scenario-tabs.is-scrollable { padding-bottom: 9px; }
.table-scroll.is-scrollable { padding-bottom: 4px; }
.table-mode-tabs.is-scrollable { scroll-padding-inline: 14px; }

/* First visit only: the chooser rocks a few pixels and settles back, which is
   the one cue that survives a reader who never looks at the edges. */
@keyframes mj-scroll-nudge {
  0%, 100% { transform: translateX(0); }
  45% { transform: translateX(-12px); }
}
.table-mode-tabs.mj-nudge > .table-tab { animation: mj-scroll-nudge 1.1s ease-in-out 1; }

@media (prefers-reduced-motion: reduce) {
  .table-mode-tabs.mj-nudge > .table-tab { animation: none; }
  /* `html { scroll-behavior: smooth }` animates the browser's own jump to a
     #hash as well as ours, so a reader who asked for less motion was still
     flown 24,000px down the rulebook. The JS honours the preference; the
     stylesheet has to as well or the two disagree. */
  html { scroll-behavior: auto; }
}

/* ==========================================================================
   TILE ROWS THAT FIT THE WIDTH INSTEAD OF SCROLLING
   A fourteen-tile hand at 60px needs 924px. On a phone that meant a sideways
   scroll even in landscape, and a reader comparing the third tile with the
   twelfth could never see both. These rows now wrap into balanced lines and
   size their tiles to whatever width they are given.

   One mechanism drives all three sizes. `--tile-w` is the card width app.js
   settled on and `--tile-k` is that width over the 60px the artwork was drawn
   at; every fixed dimension below is that ratio times its original value, so
   at `--tile-w: 43px` these rules reproduce the old hand-written mini row and
   at 29px the micro row. `--tile-art` nudges the face up a few percent for the
   smaller rows, exactly as the hand-written scales did.
   ========================================================================== */
/* The seeds. app.js overwrites --tile-w / --tile-k per row once it can measure;
   until then these reproduce the sizes the rows have always had. */
.hand-tiles-row { --tile-max: 60px; --tile-w: 60px; --tile-k: 1; --tile-art: 1; }
.tile-figure .mini-tile-row,
.mini-tile-row.scroll-tile-row { --tile-max: 43px; --tile-w: 43px; --tile-k: .717; --tile-art: 1.06; }
.tile-figure .micro-tile-row,
.micro-tile-row.scroll-tile-row { --tile-max: 29px; --tile-w: 29px; --tile-k: .483; --tile-art: 1.1; }

[data-fit-row] {
  flex-wrap: wrap;
  justify-content: center;
  row-gap: 8px;
}
/* Flexbox fits as many tiles per line as happen to go, which turns twelve
   tiles into eight and four. A grid takes the column count app.js worked out,
   so the lines come out even. Only for rows whose children are all tiles —
   one row separates two groups with an arrow, and that is not a column. */
[data-fit-row].tiles-grid {
  display: grid;
  grid-template-columns: repeat(var(--tile-cols, 1), var(--tile-w));
  justify-content: center;
  align-items: end;
}
[data-fit-row] .mj-tile-card {
  flex: 0 0 auto;
  width: var(--tile-w);
  height: calc(var(--tile-w) * 82 / 60);
  border-radius: calc(8px * var(--tile-k));
  box-shadow:
    0 calc(4px * var(--tile-k)) 0 #77694e,
    0 calc(6px * var(--tile-k)) calc(12px * var(--tile-k)) rgba(0, 0, 0, 0.4),
    inset 0 1px 0 #ffffff;
}
[data-fit-row] .mj-tile-card > .tile-art {
  inset: calc(4px * var(--tile-k)) calc(4px * var(--tile-k)) calc(15px * var(--tile-k));
  transform: scale(calc(var(--tile-k) * var(--tile-art)));
}
/* Only the full-size rows carry a written label; the smaller rows have never
   shown one. Below ~40px even "Eye 眼" is wider than the tile it names, so it
   goes and the tile face carries the identity on its own. */
.hand-tiles-row .mj-label-sub {
  bottom: calc(3px * var(--tile-k));
  max-width: 100%;
  padding: 0 2px;
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
  /* Two numbers doing two different jobs, measured rather than guessed.
     0.69rem is 11.04px at a full-size 60px tile, where nothing truncates — the
     old 0.6rem left desktop at 9.6px for no reason. The 9px floor still governs
     the small end: in short landscape the tiles are 43px, and there 10px starts
     clipping "Green 發", "White 白" and "North 風". So the floor stays at 9,
     which truncates nothing. */
  font-size: max(9px, calc(0.69rem * var(--tile-k)));
}
.hand-tiles-row.tiles-tight .mj-label-sub { display: none; }
.hand-tiles-row.tiles-tight .mj-tile-card > .tile-art {
  inset: calc(4px * var(--tile-k));
}

/* A figure that lines several groups up for comparison stacks them when they
   do not fit, rather than running off the side — on a wide screen they still
   sit in one line, because nothing wraps until it has to. The cap is what lets
   a group shrink at all: at max-content width its own tile row is never asked
   to fit anything. */
.figure-rows.figure-scroll { flex-wrap: wrap; overflow-x: visible; }
.figure-rows.figure-scroll > * { max-width: 100%; }

/* Give the tiles the width the nesting was spending on padding. On a 390px phone
   the trainer's row sits six containers deep and was left 242px of it, which is
   what held its tappable tiles to 29px. */
@media (max-width: 768px) {
  .wood-tile-rack { padding: 8px 6px; }
  .guide-answer-head, .catalogue-heading { align-items: flex-start; flex-direction: column; }
  .guide-reviewed { align-items: flex-start; }
  .guide-answer-facts { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .catalogue-key { justify-content: flex-start; }
  .winning-catalogue-table { min-width: 720px; }
  .hand-tiles-row .mj-label-sub { display: none; }
  .combo-card-item { padding: 12px; }
  .felt-hand-area { padding: 10px 6px; }
}

/* Touch targets. These are all comfortably wide; it is only their height that
   fell short of 44px. */
@media (hover: none), (max-width: 768px) {
  .table-tab { padding-block: 12px; }
  .scenario-btn { padding-block: 12px; }
  .toc-link { padding-block: 7px; }
  /* Missed on the first pass: the tile-family filters and the calculator's
     win-type toggle are touch controls too, at 37px and 41px. */
  .tile-tab { padding-block: 12px; }
  .btn-toggle { padding-block: 12px; }
  /* And on the second: the footer is this page's site navigation, and its
     links were 20px tall — under even the 24px AA floor, let alone 44px. */
  .footer-nav a { padding-block: 12px; }
  /* Two pixels short of 44 each. min-height rather than more padding, so the
     number in the rule is the number that gets measured. Every text field
     rather than the two known ones — the glossary filter was missed the first
     time precisely because it carries no class to name. */
  .btn, input[type="text"], input[type="search"], select, textarea { min-height: 44px; }
}

/* ---- Skip link. The page opens with a 14-button tab strip, so keyboard and
   screen-reader users had to walk the whole strip before reaching any content.
   Visible only while focused, in the page's own gold-on-dark palette. ---- */
.skip-link {
  position: absolute;
  left: 8px;
  top: -60px;
  z-index: 999;
  padding: 10px 16px;
  border: 2px solid var(--gold);
  border-radius: 0 0 10px 10px;
  background: var(--bg-dark);
  color: var(--gold);
  font-weight: 800;
  text-decoration: none;
  transition: top 0.15s ease;
}
.skip-link:focus { top: 0; outline: 3px solid var(--gold); outline-offset: 2px; }

/* ---- Print ----------------------------------------------------------------
   Browsers drop backgrounds when printing but keep the text colour, so this
   page printed as near-white ink on white paper: measurably blank. A guide
   with a Quick Cheat Sheet tab is something people put next to the table, so
   it has to survive Ctrl+P.

   What prints is whichever tab is open — that is what the reader chose. The
   chrome around it is not part of the page on paper. --------------------- */
@media print {
  /* Recolour at the source. Gold on white is about 1.7:1 — every heading,
     Tai badge and section number in the guide is gold, so restating them one
     selector at a time would be fifty rules and one of them would be missed. */
  :root {
    --header-height: 0px;
    --gold: #6f4e05;
    --gold-glow: transparent;
    --ink: #14201c;
    --muted: #47554f;
    --panel-bg: transparent;
    --panel-border: #b9c6c0;
    --bg-dark: #ffffff;
  }
  /* The nine places gold is a fill rather than ink: keep them light so the
     dark text on top stays readable when background graphics are printed. */
  .brand-text .badge, .btn-gold, .table-tab.active, .tile-tab.active,
  .scenario-btn.active, .btn-toggle.active, .calc-cb input:checked + .cb-box,
  .step-num, .teaching-steps li > span {
    background: #f5e9c8 !important;
    color: #3d2b02 !important;
    box-shadow: none !important;
  }

  html, body.mahjong-app, .table-wood-frame, .table-felt-mat, .site-footer {
    background: #fff !important;
    color: #14201c;
    box-shadow: none !important;
  }
  body.mahjong-app { font-size: 11pt; }
  .table-wood-frame { border: none !important; padding: 0 !important; }
  .table-felt-mat { border: none !important; padding: 0 !important; min-height: 0 !important; }
  .table-outer-wrapper { padding: 0 !important; margin: 0 !important; max-width: none; }
  .table-corner { display: none !important; }

  /* Navigation, live controls and decoration: all screen-only. */
  .app-header, .mobile-dock, .table-mode-tabs, .progress-container, #progressBar,
  .skip-link, .header-search, .header-actions, .table-scroll-hint, .scroll-hint,
  .back-to-top, .tab-icon, .site-footer .footer-cta {
    display: none !important;
  }

  /* A card is a rule, a table or a worked example. Splitting one across a page
     break is where a printed reference stops being usable. */
  .content-block, .tile-figure, .styled-table tr, .glossary-card, .faq-item,
  .table-explainer, .teaching-table, .cheat-card, .mj-tile-card {
    break-inside: avoid;
  }
  h1, h2, h3, h4 { break-after: avoid; }

  /* Flatten the dark cards to plain bordered blocks. */
  .content-block, .table-explainer, .glossary-card, .faq-item, details,
  .cheat-card, .teaching-table, .results-card {
    background: none !important;
    border-color: #b9c6c0 !important;
    box-shadow: none !important;
    color: #14201c;
  }
  .content-block a:not([class]) { color: #14201c; }

  /* On screen a wide table scrolls sideways. Paper does not scroll, so the
     columns that were behind the edge would simply be missing. */
  .table-scroll { overflow: visible !important; }
  .styled-table { width: 100% !important; font-size: 9.5pt; }
  .styled-table th, .styled-table td { border-color: #b9c6c0 !important; }
  .styled-table thead th { background: #eef2f0 !important; color: #14201c !important; }
  .styled-table thead { display: table-header-group; }   /* repeat on each page */

  /* The tile faces are the content, not decoration — they have to keep their
     colour even with the browser's "background graphics" box unticked. */
  .mj-tile-card, .visual-tile, .mini-tile-row *, .hand-tiles-row *,
  .wall-visual-3d, .wall-side-3d, .table-die, .die-pip, .tile-figure svg {
    -webkit-print-color-adjust: exact;
    print-color-adjust: exact;
  }

  /* Status colours are picked to glow on dark felt: mint #52d1a0 and coral
     #ff6b6b read as about 1.9:1 on white. Same meanings, paper-weight ink. */
  .tai-badge, .verdict-yes, .seat-amount.positive, .calc-alert .alert-icon.ok {
    color: #0d5f42 !important;
  }
  .verdict-no, .seat-amount.negative, .tai-badge.max, .tai-status-text,
  .alert-icon {
    color: #96170f !important;
  }
  .feedback-icon, .alert-msg, .tag-red { color: #96170f !important; }
  .tag-blue { color: #10457a !important; }
  .table-view-note, .rack-note, .calc-help { color: #47554f !important; }
  /* app.js paints these two inline as it answers, so only !important reaches
     them — and the Ping Hu verdict is a thing a reader would want on paper. */
  #trainerFeedback, #pingHuResultBox { color: #3d2b02 !important; }

  /* An off-site reference is worth nothing on paper without its address. */
  .source-links a[href^="http"]::after {
    content: " (" attr(href) ")";
    font-size: 8pt;
    word-break: break-all;
  }
}

/* ==========================================================================
   PHONE SEARCH OVERLAY
   Below 768px the header search bar is display:none, which for a long time
   meant phones simply had no search. The 🔍 button in the header actions
   toggles `body.search-open`, and these rules re-show the existing bar as a
   fixed overlay under the header — same input, same combobox engine, same
   results list. This block sits at the end of the stylesheet on purpose: the
   rules it must beat ("display: none !important" in the phone and
   short-landscape blocks) win on importance, so only a later !important at
   equal-or-higher specificity can reverse them, and keeping it after every
   media block means an open overlay also survives a rotation into landscape.
   ========================================================================== */
.search-toggle { display: none; }

/* The toggle appears exactly where the bar disappears: both switch at 768px,
   so no width shows the two together, or neither. */
@media (max-width: 768px) {
  .search-toggle {
    display: inline-flex;
    justify-content: center;
    min-width: 44px;
    min-height: 44px;
    padding: 7px 10px;
  }
  /* The toggle took the slack the nowrap title was living on, so the title
     must truncate rather than slide underneath the header buttons — and the
     GUIDE badge goes before letters do: truncation was clipping the pill into
     an empty ellipse while the name it decorates survived. */
  .brand-text h1 { overflow: hidden; text-overflow: ellipsis; }
  .brand-text h1 .badge { display: none; }
  .header-actions { flex: 0 0 auto; }
  .search-toggle[aria-expanded="true"] {
    background: var(--gold);
    border-color: var(--gold);
  }
}

body.search-open .header-search {
  display: flex !important;
  position: fixed;
  top: calc(var(--header-height) + 8px);
  left: 10px;
  right: 10px;
  z-index: 90;
  flex: none;
}
body.search-open .header-search input {
  box-shadow: 0 10px 30px rgba(0, 0, 0, 0.55);
  border-color: var(--gold);
}
/* The results list keeps its own anchor inside .header-search; cap it to the
   phone viewport minus the header and the on-screen keyboard's usual reach. */
body.search-open .search-results { max-height: min(50vh, 380px); }

/* Actionable starting paths in the first answer card. */
.guide-start{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:10px;margin:0 0 16px}
.guide-start a{display:flex;flex-direction:column;justify-content:center;min-height:72px;padding:14px 16px;border:1px solid rgba(213,183,112,.35);border-radius:12px;background:#10271f;color:#f5e7be;text-decoration:none}
.guide-start a:first-child{background:#e8c87b;color:#18251b}
.guide-start strong{font-size:1rem}.guide-start span{font-size:.88rem;line-height:1.4;margin-top:3px}
.guide-start a:focus-visible{outline:3px solid #fff;outline-offset:3px}
@media(max-width:650px){.guide-start{grid-template-columns:1fr;gap:7px}.guide-start a{min-height:60px;padding:10px 14px}}
