/* ══════════════════════════════════════════════════════════════════════════
   12MaR — the website's design system.

   ⛔ NOTHING HERE IS INVENTED. Every colour is a token from
   lib/core/theme/app_colors.dart, both faces are the variable TTFs the app
   itself bundles (assets/fonts/), and the component shapes below — the header,
   the player card, the amber panel, the compete rows — are the app's own
   screens rebuilt in HTML. Somebody who has played the game should recognise
   every one of them. Change the app's palette and change this file with it.

   Single dark theme, on purpose: 12MaR is a dark premium board game and the
   store's feature graphic already commits to that ground. A light variant would
   be a second identity. Every colour is therefore painted explicitly — nothing
   is left to inherit from the browser.
   ══════════════════════════════════════════════════════════════════════════ */

@font-face {
  font-family: 'Montserrat';
  src: url('fonts/Montserrat.ttf') format('truetype-variations');
  font-weight: 100 900;
  font-display: swap;
}
/* ⛔ INTER IS NOT SHIPPED, AND THAT IS A DELIBERATE TRADE.
   The app bundles Montserrat AND Inter, and this site began by copying both.
   Measured: Inter is 876 KB raw / 460 KB gzipped, Montserrat 745 KB / 295 KB —
   1.6 MB of font for a page whose text is 20 KB, on a connection that is mostly
   Pakistani mobile data. Both are variable faces carrying ~2,800 glyphs (Latin,
   Cyrillic, Greek, Vietnamese); this site uses about a hundred of them, and
   there is no font subsetter on this machine to cut them down (no pip, no
   fonttools) — so the choice was which whole file to ship, not how much of each.

   Montserrat stays because it IS the brand: the wordmark, every heading, and the
   Play Store feature graphic are all set in it, and a visitor would see the
   difference immediately. Inter goes because it is the BODY face at 16px, where
   it is very close to what a phone already has — nobody will see its absence,
   and everybody would feel the 460 KB. If a subsetter ever becomes available,
   subset both and bring Inter back; that is the better answer, not this one. */

:root {
  /* ── surfaces (AppColors) ─────────────────────────────────────────────── */
  --deep:          #120E08;
  --ground:        #181209;
  --ground-warm:   #1B1409;
  --surface:       #211B11;
  --surface-2:     #251F15;
  --surface-3:     #30291E;
  --line:          #3B3429;
  --line-2:        #40382D;

  /* ── brand ────────────────────────────────────────────────────────────── */
  --amber:         #FFB300;
  --amber-dark:    #D99100;
  --amber-light:   #FFD79B;
  --amber-glow:    #FFBA38;
  --amber-container:#432C00;

  /* ── the opponent's side ──────────────────────────────────────────────── */
  --blue:          #2C96E5;
  --blue-light:    #99CBFF;
  --blue-deep:     #003355;

  /* ── text ─────────────────────────────────────────────────────────────── */
  --ink:           #EEE0D0;
  --ink-dim:       #D6C4AC;
  --ink-faint:     #9E8E78;
  --ink-ghost:     #514532;

  /* ── semantic ─────────────────────────────────────────────────────────── */
  --good:          #7BE3A0;
  --warn:          #FFBA38;
  --danger:        #FFB4AB;

  --display: 'Montserrat', system-ui, sans-serif;
  --body: system-ui, -apple-system, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;

  --radius: 16px;
  --radius-sm: 10px;
  --pad: clamp(1rem, 4vw, 2.5rem);
  --measure: 62ch;
}

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

html { scroll-behavior: smooth; }
@media (prefers-reduced-motion: reduce) { html { scroll-behavior: auto; } }

body {
  margin: 0;
  background: var(--deep);
  color: var(--ink);
  font-family: var(--body);
  font-size: 16px;
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
  /* The warm bloom the app paints behind its lobby. Fixed, so it does not
     travel with the scroll and turn into a stripe. */
  background-image:
    radial-gradient(120% 70% at 50% -10%, rgba(255,179,0,.10) 0%, transparent 58%),
    radial-gradient(90% 60% at 50% 108%, rgba(255,179,0,.05) 0%, transparent 60%);
  background-attachment: fixed;
}

/* ══ اردو ═══════════════════════════════════════════════════════════════════
   Nastaliq needs far more room between lines than Latin does — set once here
   rather than per-component, so a page that flips does not need a second
   stylesheet. Every layout below uses logical properties, which is what makes
   the flip free.                                                             */
/* ⛔ THE READER'S OWN PAKISTANI FONT COMES FIRST, and only then ours.
   Owner: *"Pakistani font"*. Nastaliq is the script Urdu is actually read in —
   a Naskh fallback looks Arabic to a Pakistani eye, which is the failure to
   avoid. Jameel Noori Nastaleeq is what is installed on most Pakistani
   machines and what Urdu publishing uses; Alvi and Nafees are the other two in
   circulation. If the reader has any of them the page uses it and downloads
   nothing. Noto Nastaliq Urdu, fetched from Google only when اردو is chosen, is
   the guarantee for everybody else — never the first choice.
   ⚠️ `serif` last, never `sans-serif`: a sans fallback renders Urdu in a Naskh
   face, which is exactly the wrong look. */
[dir="rtl"] body {
  font-family: 'Jameel Noori Nastaleeq', 'Alvi Nastaleeq', 'Nafees Nastaleeq',
               'Noto Nastaliq Urdu', serif;
  line-height: 2.15;
}
/* ⚠️ NASTALIQ IS SET SMALLER AND LOOSER THAN THE LATIN, and both halves matter.
   The face carries far more vertical detail per line — the strokes cascade — so
   a size that reads as a confident headline in Montserrat becomes a wall four
   lines deep in Nastaliq, and the default leading clips the descenders. */
[dir="rtl"] h1 { font-size: clamp(1.6rem, 4.2vw, 2.6rem); line-height: 1.75; letter-spacing: 0; }
[dir="rtl"] h2 { font-size: clamp(1.15rem, 2.6vw, 1.65rem); line-height: 1.8; letter-spacing: 0; }
[dir="rtl"] h3 { font-size: 0.95rem; line-height: 1.8; }
[dir="rtl"] h1, [dir="rtl"] h2, [dir="rtl"] h3, [dir="rtl"] h4 {
  font-family: 'Jameel Noori Nastaleeq', 'Alvi Nastaleeq', 'Nafees Nastaleeq',
               'Noto Nastaliq Urdu', serif;
}
[dir="rtl"] .lede { font-size: 1rem; }
[dir="rtl"] .cta-panel .big { font-size: 1.2rem; line-height: 1.9; }
[dir="rtl"] .row-card .t, [dir="rtl"] .player-card .name { font-size: .92rem; line-height: 1.9; }
[dir="rtl"] .row-card .s, [dir="rtl"] .faint, [dir="rtl"] .fine { line-height: 1.9; }
[dir="rtl"] .eyebrow { letter-spacing: 0; }
/* The brand never translates and never changes face. */
[dir="rtl"] .wordmark { font-family: var(--display); line-height: 1; direction: ltr; }
/* The class is called nowrap-latin; now it actually is. `id: 1034` breaking
   across two lines inside a card that pins its own height is worse than a class
   name that lies. */
.nowrap-latin { white-space: nowrap; }
[dir="rtl"] .nowrap-latin { font-family: var(--display); }

/* ⚠️ ANY RUN THAT IS LATIN OR NUMERIC IS ISOLATED, in BOTH directions.
   Left to the paragraph's direction, "−2 pt" comes out as "pt 2−" and
   "7:02 LEFT" as "LEFT 7:02" — the bidirectional algorithm reordering a run it
   was never told to keep together. `isolate` tells it. */
/* ⛔ EVERY SELECTOR HERE MUST ALSO APPEAR BELOW, AND VICE VERSA. `unicode-bidi`
   does not inherit, and `direction` has NO EFFECT on an inline box whose
   `unicode-bidi` is `normal` — so isolating the parent and setting the direction
   on the child does nothing whatsoever. `.match-head .chip` / `.chip b` was
   exactly that pair: "7:02 LEFT" went on rendering as "LEFT 7:02" underneath a
   comment insisting it could not. */
.mcard .id, .mcard .beads, .turnbox .clk,
.match-head .chip, .match-head .chip b,
.stat b, .coins, .player-card .sub, .player-card .name, .mcard .nm,
.nowrap-latin, td.num, .legend {
  /* Names too: "Ayesha K." came out as ".Ayesha K" — the full stop is neutral,
     so the paragraph's direction claimed it. */
  unicode-bidi: isolate;
}
/* ⚠️ THE CHIP ITSELF IS ISOLATED BUT NOT FORCED LTR — only the number in it.
   The chip also holds اردو words ("آن لائن میچ", "باقی"), and forcing the whole
   box left-to-right would lay those out backwards. Isolation stops the number
   leaking; `direction` belongs on the number alone. */
[dir="rtl"] .mcard .id, [dir="rtl"] .mcard .beads, [dir="rtl"] .turnbox .clk,
[dir="rtl"] .match-head .chip b, [dir="rtl"] .stat b, [dir="rtl"] .coins,
[dir="rtl"] .player-card .sub, [dir="rtl"] .nowrap-latin, [dir="rtl"] td.num {
  direction: ltr;
}

/* ══ type ═════════════════════════════════════════════════════════════════ */
h1, h2, h3, h4 { font-family: var(--display); margin: 0; text-wrap: balance; }

h1 {
  font-variation-settings: 'wght' 800;
  font-size: clamp(2.1rem, 6.5vw, 4rem);
  line-height: 1.02;
  letter-spacing: -0.02em;
}
h2 {
  font-variation-settings: 'wght' 800;
  font-size: clamp(1.5rem, 3.6vw, 2.3rem);
  line-height: 1.12;
  letter-spacing: -0.015em;
}
h3 {
  font-variation-settings: 'wght' 700;
  font-size: 1.05rem;
  line-height: 1.3;
}

p { margin: 0; }
.stack > * + * { margin-top: 1rem; }
.measure { max-width: var(--measure); }

.eyebrow {
  font-family: var(--display);
  font-variation-settings: 'wght' 700;
  font-size: 0.7rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--ink-faint);
}

.lede { font-size: clamp(1.02rem, 2vw, 1.18rem); color: var(--ink-dim); }
.dim  { color: var(--ink-dim); }
.faint{ color: var(--ink-faint); font-size: 0.88rem; }

strong { font-weight: 650; color: var(--ink); }
a { color: var(--amber); text-decoration-color: rgba(255,179,0,.4); text-underline-offset: 3px; }
a:hover { text-decoration-color: var(--amber); }
:focus-visible { outline: 2px solid var(--amber); outline-offset: 3px; border-radius: 4px; }

.wordmark {
  font-family: var(--display);
  font-variation-settings: 'wght' 800;
  letter-spacing: 0.012em;
  background: linear-gradient(176deg, #FFF0D2 4%, var(--amber-light) 34%, var(--amber) 76%, #E09A00 100%);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}

/* ══ shell ════════════════════════════════════════════════════════════════ */
.wrap { max-width: 1160px; margin: 0 auto; padding-inline: var(--pad); }
.narrow { max-width: 760px; margin-inline: auto; }

section { padding-block: clamp(3rem, 8vw, 6rem); }
section.tight { padding-block: clamp(2rem, 5vw, 3.5rem); }

.rule { border: 0; border-top: 1px solid var(--line); margin: 0; }

/* ══ header — the app's own top bar ═══════════════════════════════════════
   The lobby's chrome: the wordmark on one side, round icon buttons on the
   other. Authored once in tools/chrome.html and written into every page by
   tools/sync-chrome.py — do not edit a page's header by hand.              */
.app-header {
  position: sticky;
  top: 0;
  z-index: 40;
  background: rgba(18,14,8,.88);
  backdrop-filter: blur(14px);
  border-bottom: 1px solid var(--line);
}
.app-header .bar {
  max-width: 1160px;
  margin: 0 auto;
  padding: 0.6rem var(--pad);
  display: flex;
  align-items: center;
  gap: 0.75rem;
}
/* A finger needs about 36px. The wordmark is the home link on every page and
   in اردو its line-height put it at 23. Padding, not font-size — the size is
   the brand's. */
.app-header .wordmark {
  font-size: 1.45rem; text-decoration: none; flex: none;
  display: inline-flex; align-items: center; min-height: 40px;
}

.nav { display: flex; align-items: center; gap: 0.15rem; margin-inline-start: auto; }
.nav a {
  font-size: 0.86rem;
  color: var(--ink-dim);
  text-decoration: none;
  padding: 0.45rem 0.7rem;
  border-radius: var(--radius-sm);
  white-space: nowrap;
  transition: color .2s ease, background .2s ease;
}
.nav a:hover { color: var(--ink); background: var(--surface-2); }
/* The current page is named by COLOUR and by a rule under it — colour alone is
   invisible to a colour-blind reader, and this is the only "you are here" the
   site has. */
.nav a[aria-current="page"] {
  color: var(--amber);
  box-shadow: inset 0 -2px 0 var(--amber);
  border-radius: 0;
}

.bar-actions { display: flex; align-items: center; gap: 0.4rem; flex: none; }

/* The round icon buttons from the lobby header. */
.icon-btn {
  width: 40px; height: 40px;
  display: grid; place-items: center;
  border-radius: 12px;
  border: 1px solid var(--line);
  background: var(--surface);
  color: var(--ink-dim);
  cursor: pointer;
  font: inherit;
  flex: none;
  transition: border-color .2s ease, color .2s ease, background .2s ease;
}
.icon-btn:hover { border-color: var(--line-2); color: var(--ink); }

#lang-toggle {
  width: auto;
  padding-inline: 0.85rem;
  font-family: var(--display);
  font-variation-settings: 'wght' 700;
  font-size: 0.8rem;
  letter-spacing: 0.04em;
  color: var(--amber-light);
  border-color: #6B4A16;
  background: var(--amber-container);
}
#lang-toggle:hover { background: #56380A; color: #FFF0D2; }

/* ── the phone's menu ────────────────────────────────────────────────────
   ⛔ THE LINKS ARE HIDDEN, NEVER REMOVED. The first version simply set
   `display:none` on the nav under 520px, which left a phone with no way to
   reach any page at all. The nav becomes a panel instead.                 */
.menu-only { display: none; }

@media (max-width: 860px) {
  .menu-only { display: grid; }

  /* ⛔ THE PANEL IS SHOWN AND HIDDEN, NOT GROWN.

     It animated `max-height` first, and that was two days of nothing: the
     attribute flipped, `visibility` and `overflow` from the same rule applied,
     the inline `max-height: 264px` was on the element — and the computed value
     stayed `0px`. Remove the transition and it opened correctly, every time. A
     height transition that will not start is a whole class of bug for an
     animation nobody asked for; a panel that slides in from under the bar reads
     exactly as well and cannot fail this way. */
  .nav {
    position: absolute;
    inset-inline: 0;
    top: 100%;
    margin: 0;
    display: none;
    flex-direction: column;
    align-items: stretch;
    gap: 0;
    max-height: 72vh;
    overflow-y: auto;
    background: var(--ground);
    border-bottom: 1px solid var(--line);
    box-shadow: 0 22px 40px -24px rgba(0,0,0,.95);
  }
  .nav[data-open] {
    display: flex;
    animation: panel-in .22s cubic-bezier(.2,.7,.3,1);
  }
  @keyframes panel-in {
    from { opacity: 0; transform: translateY(-8px); }
    to   { opacity: 1; transform: none; }
  }
  .nav a {
    padding: 0.85rem var(--pad);
    border-radius: 0;
    border-bottom: 1px solid var(--line);
    font-size: 0.95rem;
  }
  .nav a:last-child { border-bottom: 0; }
  .nav a[aria-current="page"] { box-shadow: inset 3px 0 0 var(--amber); }
  [dir="rtl"] .nav a[aria-current="page"] { box-shadow: inset -3px 0 0 var(--amber); }
}

/* The hamburger becomes a cross while the panel is open. */
#menu-toggle svg path { transition: transform .25s ease, opacity .2s ease; transform-origin: center; }
#menu-toggle[aria-expanded="true"] { color: var(--amber); border-color: #6B4A16; }
#menu-toggle[aria-expanded="true"] .m1 { transform: translateY(4px) rotate(45deg); }
#menu-toggle[aria-expanded="true"] .m2 { opacity: 0; }
#menu-toggle[aria-expanded="true"] .m3 { transform: translateY(-4px) rotate(-45deg); }

@media (prefers-reduced-motion: reduce) {
  .nav, #menu-toggle svg path { transition: none; }
}

/* ══ panels — the app's card language ═════════════════════════════════════ */
.panel {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 1.15rem 1.25rem;
}
.panel.flush { padding: 0; overflow: hidden; }
.panel.deep { background: var(--ground); }

/* ⛔ `min(…, 100%)` INSIDE THE minmax, ALWAYS. A bare `minmax(310px, 1fr)` is a
   column that refuses to be narrower than 310px — so on a 320px phone, once the
   page padding is taken off, the track is WIDER than the space it is in and the
   whole page hangs over the edge. It looked fine at 360 and broke at 320, which
   is a common Android width. The `min()` lets the track collapse instead. */
.grid {
  display: grid;
  gap: 1rem;
  grid-template-columns: repeat(auto-fit, minmax(min(250px, 100%), 1fr));
}
.grid.two { grid-template-columns: repeat(auto-fit, minmax(min(310px, 100%), 1fr)); }

/* ══ the lobby, rebuilt ═══════════════════════════════════════════════════ */
.phone-shell {
  width: min(380px, 100%);
  background: var(--ground);
  border: 1px solid var(--line);
  border-radius: 28px;
  padding: 0.9rem;
  box-shadow: 0 30px 80px -30px rgba(0,0,0,.9), 0 0 0 1px rgba(255,179,0,.06);
}

.player-card {
  display: flex;
  align-items: center;
  gap: 0.7rem;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 0.7rem 0.8rem;
}
.avatar {
  width: 46px; height: 46px;
  border-radius: 50%;
  background: var(--surface-3);
  display: grid; place-items: center;
  font-size: 1.5rem;
  flex: none;
}
/* The name and the line under it are spans in the markup, so they need to be
   told they are lines — otherwise they run together and wrap as one sentence. */
.player-card .who { min-width: 0; display: flex; flex-direction: column; gap: .1rem; }
.player-card .name, .player-card .sub,
.row-card .t, .row-card .s,
.mcard .nm, .mcard .id, .mcard .beads,
.cta-panel .kicker, .cta-panel .big,
.turnbox .lbl, .turnbox .clk { display: block; }
.row-card > span:not(.tile):not(.chev) { min-width: 0; }
.player-card .name {
  font-family: var(--display);
  font-variation-settings: 'wght' 700;
  font-size: 1.05rem;
  line-height: 1.15;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.player-card .sub {
  font-size: 0.76rem;
  color: var(--ink-faint);
  font-variant-numeric: tabular-nums;
}
.coins {
  margin-inline-start: auto;
  display: flex; align-items: center; gap: 0.35rem;
  background: var(--amber-container);
  border: 1px solid #6B4A16;
  color: var(--amber-light);
  border-radius: 999px;
  padding: 0.28rem 0.6rem;
  font-family: var(--display);
  font-variation-settings: 'wght' 700;
  font-size: 0.9rem;
  font-variant-numeric: tabular-nums;
  flex: none;
}
.coin-dot {
  width: 14px; height: 14px; border-radius: 50%; flex: none;
  background: radial-gradient(circle at 34% 28%, #FFF0CF 0%, var(--amber) 46%, #A96C00 100%);
}

/* The one amber panel — the app has exactly one, and so does this site. */
.cta-panel {
  display: flex;
  align-items: center;
  gap: 1rem;
  width: 100%;
  text-align: start;
  border: 0;
  border-radius: var(--radius);
  padding: 1.1rem 1.15rem;
  background: linear-gradient(135deg, var(--amber-glow) 0%, var(--amber) 42%, var(--amber-dark) 100%);
  color: #2A1B00;
  box-shadow: 0 14px 40px -18px rgba(255,179,0,.75);
  text-decoration: none;
}
.cta-panel .kicker {
  font-family: var(--display);
  font-variation-settings: 'wght' 700;
  font-size: 0.66rem;
  letter-spacing: 0.13em;
  text-transform: uppercase;
  opacity: .72;
}
.cta-panel .big {
  font-family: var(--display);
  font-variation-settings: 'wght' 800;
  font-size: 1.55rem;
  line-height: 1.1;
  letter-spacing: -0.01em;
}
.cta-panel .glyph {
  margin-inline-start: auto;
  width: 54px; height: 54px;
  border-radius: 14px;
  background: rgba(0,0,0,.14);
  display: grid; place-items: center;
  font-size: 1.5rem;
  flex: none;
}

/* The COMPETE / PRACTICE rows. */
.row-card {
  display: flex;
  align-items: center;
  gap: 0.85rem;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 0.85rem 0.9rem;
  text-decoration: none;
  color: inherit;
}
a.row-card:hover { border-color: var(--line-2); background: var(--surface-2); }
.row-card .tile {
  width: 44px; height: 44px;
  border-radius: 12px;
  background: var(--surface-3);
  display: grid; place-items: center;
  font-size: 1.25rem;
  flex: none;
}
.row-card .t {
  font-family: var(--display);
  font-variation-settings: 'wght' 700;
  font-size: 1rem;
  line-height: 1.2;
}
.row-card .s { font-size: 0.82rem; color: var(--ink-faint); line-height: 1.35; }
.row-card .chev { margin-inline-start: auto; color: var(--ink-faint); flex: none; }
/* The glyph lives in CSS so each direction gets the RIGHT character rather than
   a mirrored one — a flipped "›" renders as a stray bracket, which is what it
   looked like on the first pass. */
.row-card .chev::before { content: "›"; }
[dir="rtl"] .row-card .chev::before { content: "‹"; }

/* ══ the match screen, rebuilt ════════════════════════════════════════════ */
.match-head {
  display: flex; justify-content: center;
  margin-bottom: 0.7rem;
}
.match-head .chip {
  border: 1px solid var(--line);
  border-radius: 999px;
  padding: 0.3rem 0.85rem;
  font-family: var(--display);
  font-variation-settings: 'wght' 700;
  font-size: 0.78rem;
  letter-spacing: 0.06em;
  color: var(--ink-dim);
  font-variant-numeric: tabular-nums;
}
.match-head .chip b { color: var(--amber); font-variation-settings: 'wght' 800; }

.cards-row { display: grid; grid-template-columns: 1fr auto 1fr; gap: 0.5rem; align-items: stretch; }

.mcard {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: 14px;
  padding: 0.6rem 0.7rem;
  min-width: 0;
}
.mcard.active { border-color: var(--amber); }
.mcard .top { display: flex; align-items: center; gap: 0.35rem; }
.mcard .nm {
  font-family: var(--display);
  font-variation-settings: 'wght' 700;
  font-size: 0.9rem;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.mcard .id { font-size: 0.6rem; color: var(--ink-faint); font-variant-numeric: tabular-nums; }
.mcard .pts {
  font-family: var(--display);
  font-variation-settings: 'wght' 800;
  font-size: 1.2rem;
  line-height: 1.2;
  font-variant-numeric: tabular-nums;
}
.mcard.p1 .pts { color: var(--amber); }
.mcard.p2 .pts { color: var(--blue-light); }
.mcard .beads { font-size: 0.7rem; color: var(--ink-faint); font-variant-numeric: tabular-nums; }
.mcard .dot { width: 22px; height: 22px; border-radius: 50%; background: var(--surface-3); display: grid; place-items: center; font-size: 0.8rem; flex: none; }

.turnbox {
  background: var(--surface);
  border: 1px solid var(--amber);
  border-radius: 14px;
  padding: 0.5rem 0.7rem;
  text-align: center;
  min-width: 96px;
  display: flex; flex-direction: column; justify-content: center; gap: 0.15rem;
}
.turnbox .lbl {
  font-family: var(--display);
  font-variation-settings: 'wght' 700;
  /* 9.6px was below what anybody reads on a phone. */
  font-size: 0.7rem;
  letter-spacing: 0.11em;
  color: var(--amber);
}
.turnbox .clk {
  font-family: var(--display);
  font-variation-settings: 'wght' 800;
  font-size: 1.35rem;
  line-height: 1;
  font-variant-numeric: tabular-nums;
}

/* ══ the board ════════════════════════════════════════════════════════════ */
/* ⛔ THE BOARD IS CAPPED BY THE VIEWPORT'S HEIGHT, NOT ONLY BY ITS COLUMN.
   Owner, 9 Aug 2026: *"board chhota karo, bohat bara — screen pe nazar bhi nahi
   aa raha"*. It was `width: 100%` of a grid column, which on a 1160px page is
   ~530px — and a board is SQUARE, so 530 wide is 530 tall, more than a laptop's
   whole viewport once the header and the frame's padding are counted. Width is
   the wrong axis to constrain a square by. `min(…, 52vh)` makes the height the
   binding limit on a short screen and the column the limit on a tall one. */
.board-frame {
  background: var(--ground);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 0.7rem;
  position: relative;
  width: min(100%, 420px, 52vh);
  margin-inline: auto;
}
/* Inside a phone mock the frame is already bounded by the shell, and a second
   cap there would leave a gap down one side of the phone. */
.phone-shell .board-frame { width: auto; max-width: none; }
svg.board { width: 100%; height: auto; display: block; }

.legend {
  display: flex; flex-wrap: wrap; gap: 0.5rem 1.1rem;
  justify-content: center;
  margin-top: 0.9rem;
  font-size: 0.8rem;
  color: var(--ink-dim);
}
.legend span { display: inline-flex; align-items: center; gap: 0.4rem; }
.legend i { width: 15px; height: 15px; display: inline-block; flex: none; }
.legend i.sq { border-radius: 3px; background: radial-gradient(circle at 34% 28%, #FFF0CF, var(--amber) 46%, #A96C00); }
.legend i.tr { background: radial-gradient(circle at 34% 28%, #FFF0CF, var(--amber) 46%, #A96C00); clip-path: polygon(50% 0, 100% 100%, 0 100%); }
.legend i.ci { border-radius: 50%; background: radial-gradient(circle at 34% 28%, #FFF0CF, var(--amber) 46%, #A96C00); }

/* ══ bits ═════════════════════════════════════════════════════════════════ */
.badge {
  display: inline-flex; align-items: center; gap: 0.45rem;
  border: 1px solid var(--line-2);
  border-radius: 999px;
  padding: 0.4rem 0.85rem;
  font-size: 0.82rem;
  color: var(--ink-dim);
  background: var(--surface);
}
.badge.hot { border-color: rgba(255,179,0,.45); color: var(--amber-light); background: rgba(255,179,0,.07); }

.stat-row {
  display: grid;
  /* ⚠️ 96px, not 120. At 120 the three figures wrapped to 2 + 1 on a phone and
     left a dead cell beside the last one, which reads as a missing number. */
  grid-template-columns: repeat(auto-fit, minmax(96px, 1fr));
  gap: 1px;
  background: var(--line);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  overflow: hidden;
}
.stat { background: var(--ground); padding: 0.9rem clamp(.6rem, 2.5vw, 1rem); }
.stat b {
  display: block;
  font-family: var(--display);
  font-variation-settings: 'wght' 800;
  font-size: clamp(1.2rem, 4vw, 1.5rem);
  color: var(--amber);
  line-height: 1.1;
  font-variant-numeric: tabular-nums;
}
.stat span { display: block; font-size: 0.74rem; color: var(--ink-faint); margin-top: 0.15rem; }

.note {
  border: 1px solid var(--line);
  border-inline-start: 3px solid var(--amber);
  border-radius: var(--radius-sm);
  background: var(--surface);
  padding: 0.95rem 1.1rem;
  color: var(--ink-dim);
  font-size: 0.94rem;
}
.note.stop { border-inline-start-color: var(--danger); }
.note b { color: var(--amber); }
.note.stop b { color: var(--danger); }

ul.ticks { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 0.55rem; }
ul.ticks li { display: flex; gap: 0.6rem; color: var(--ink-dim); font-size: 0.94rem; }
ul.ticks li::before { content: "◆"; color: var(--amber); flex: none; font-size: 0.7rem; line-height: 1.9; }

.shots { display: flex; gap: 1rem; overflow-x: auto; padding-bottom: 0.5rem; scroll-snap-type: x mandatory; }
.shots figure { margin: 0; flex: none; width: 220px; scroll-snap-align: start; }
.shots img {
  width: 100%; height: auto; display: block;
  border-radius: 18px;
  border: 1px solid var(--line);
  background: var(--ground);
}
.shots figcaption { font-size: 0.78rem; color: var(--ink-faint); margin-top: 0.5rem; text-align: center; }

table { width: 100%; border-collapse: collapse; font-size: 0.92rem; }
/* ⚠️ LOGICAL, NOT `padding: a b c d`. The four-value shorthand is top/right/
   bottom/left, so in اردو the column gutter landed on the wrong side of every
   cell — the first column gained an indent and the last lost its padding. */
th, td {
  text-align: start;
  padding-block: 0.6rem;
  padding-inline: 0 0.8rem;
  border-bottom: 1px solid var(--line);
  vertical-align: top;
}
th { color: var(--ink-faint); font-family: var(--display); font-variation-settings: 'wght' 700; font-size: 0.7rem; letter-spacing: 0.1em; text-transform: uppercase; }
tbody tr:last-child td { border-bottom: 0; }
.scroll-x { overflow-x: auto; }

/* ══ footer ═══════════════════════════════════════════════════════════════ */
footer.site {
  border-top: 1px solid var(--line);
  background: var(--deep);
  padding-block: 2.5rem 3rem;
}
footer.site .cols { display: flex; flex-wrap: wrap; gap: 1.5rem 3rem; justify-content: space-between; }
footer.site a { color: var(--ink-dim); text-decoration: none; }
footer.site a:hover { color: var(--amber); }
footer.site .links { display: flex; flex-wrap: wrap; gap: 0.4rem 1.4rem; font-size: 0.9rem; }
footer.site .fine { font-size: 0.8rem; color: var(--ink-faint); max-width: 46ch; }

/* ══ the one orchestrated load ════════════════════════════════════════════
   Lines draw, then beads settle. Nothing else on any page moves.            */
@media (prefers-reduced-motion: no-preference) {
  svg.board .ln {
    stroke-dasharray: var(--len);
    stroke-dashoffset: var(--len);
    animation: draw .75s cubic-bezier(.4,0,.2,1) forwards;
    animation-delay: calc(var(--i) * 28ms);
  }
  svg.board .bd {
    opacity: 0;
    transform-box: fill-box;
    transform-origin: center;
    animation: settle .42s cubic-bezier(.2,.9,.3,1.2) forwards;
    animation-delay: calc(560ms + var(--i) * 34ms);
  }
  .rise { opacity: 0; transform: translateY(14px); animation: rise .6s cubic-bezier(.2,.7,.3,1) forwards; }
  /* Only d2 is used — the hero's second column. The other three were written
     for a stagger that `.reveal` does better, and dead rules read as options. */
  .rise.d2 { animation-delay: .16s; }
}
@keyframes draw   { to { stroke-dashoffset: 0; } }
@keyframes settle { from { opacity: 0; transform: scale(.55); } to { opacity: 1; transform: scale(1); } }
@keyframes rise   { to { opacity: 1; transform: none; } }

/* Skip link — the first thing a keyboard reaches.

   ⚠️ HIDDEN BY CLIP, NOT BY -9999px. The old trick parks the element far off to
   one side, and an element sitting 9,999 pixels outside the viewport is still
   part of the scrollable area — the page picked up a horizontal scrollbar on a
   narrow screen and nothing on it looked wrong. Clipping takes it out of view
   without moving it anywhere. */
.skip {
  position: absolute;
  top: 0.5rem;
  /* ⚠️ PHYSICAL `left`, and this is the one place in the file that wants it.
     `inset-inline-start` puts this on the RIGHT in اردو — which is the edge the
     scrollbar occupies. `right: 8px` is measured from the viewport, not from the
     content width, so the box ended up 7px past the visible area on any page
     tall enough to have a scrollbar. A skip link is a keyboard utility, not
     content; it does not need to change sides with the language, and top-left is
     where a keyboard user expects to find it in either. */
  left: 0.5rem;
  right: auto;
  background: var(--amber); color: #2A1B00;
  padding: 0.5rem 0.9rem;
  border-radius: var(--radius-sm);
  z-index: 100; font-weight: 700;
  white-space: nowrap;
  max-width: calc(100% - 1rem);
  /* ⛔ HIDDEN UPWARDS, NOT SIDEWAYS, AND NOT BY CLIPPING EITHER.
     `-9999px` put the box outside the page and gave every phone a horizontal
     scrollbar. `clip-path` hid the paint but left the box where it was, so an
     overflow check still found it hanging over the inline edge in اردو — where
     "inline start" is the right-hand side. Moving it up its own height leaves
     nothing over any edge in either direction, and it slides down on focus,
     which is also the nicer thing to look at. */
  transform: translateY(calc(-100% - 1rem));
  transition: transform .15s ease;
}
.skip:focus { transform: none; }
@media (prefers-reduced-motion: reduce) { .skip { transition: none; } }

/* ══════════════════════════════════════════════════════════════════════════
   MOVEMENT AND DEPTH — owner, 8 Aug 2026: *"movement wagera, motion graphics,
   jo bhi 3D ho sakta"*, so that *"bande ko lage game mein aa gaya"*.

   Everything below is skipped under prefers-reduced-motion, and skipped means
   the FINAL state renders — never the first frame, which would be a blank page.
   ══════════════════════════════════════════════════════════════════════════ */

/* ── the board as an object on a table ─────────────────────────────────── */
.tilt { perspective: 1200px; perspective-origin: 50% 42%; }
.tilt > * {
  transform: rotateX(var(--rx, 0deg)) rotateY(var(--ry, 0deg)) rotateZ(-0.6deg) translateZ(0);
  transform-style: preserve-3d;
  transition: transform .55s cubic-bezier(.2,.7,.3,1);
  will-change: transform;
}
.tilt.settled > * { transition: transform .18s ease-out; }

/* Depth is what separates a bead from a coloured circle: a real contact shadow
   under it and a rim of light on the board itself. */
.board-frame {
  box-shadow:
    inset 0 1px 0 rgba(255,215,155,.06),
    0 26px 60px -28px rgba(0,0,0,.95);
  background-image: radial-gradient(120% 90% at 50% 8%, rgba(255,179,0,.055), transparent 62%);
}
svg.board .bd, svg.board g[data-cell] {
  filter: drop-shadow(0 5px 5px rgba(0,0,0,.55)) drop-shadow(0 1px 0 rgba(255,240,207,.10));
}
/* The bead being played is lifted off the board while it travels. */
svg.board g.moving {
  filter: drop-shadow(0 14px 12px rgba(0,0,0,.7)) drop-shadow(0 0 14px rgba(255,179,0,.35));
}

.phone-shell {
  transition: transform .5s cubic-bezier(.2,.7,.3,1), box-shadow .5s ease;
  transform-style: preserve-3d;
}

/* ── sections arrive ───────────────────────────────────────────────────── */
.reveal { opacity: 0; transform: translateY(18px); }
.reveal.in {
  opacity: 1; transform: none;
  transition: opacity .7s cubic-bezier(.2,.7,.3,1) var(--d, 0ms),
              transform .7s cubic-bezier(.2,.7,.3,1) var(--d, 0ms);
}
@media (prefers-reduced-motion: reduce) {
  .reveal { opacity: 1; transform: none; }
}

/* ── the drifting beads behind the hero ────────────────────────────────── */
.hero-stage { position: relative; isolation: isolate; }
/* ⚠️ It used to be 110% wide and inset −5%, i.e. deliberately wider than the
   page, and it only looked fine because `overflow-x: clip` on the document was
   hiding it. Relying on a clip to hide a deliberate overflow means every later
   overflow check has to know about this one. It stays inside now. */
#drift {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  z-index: -1;
  pointer-events: none;
}

/* ── the bracket ───────────────────────────────────────────────────────── */
svg.bracket { width: 100%; height: auto; display: block; min-width: 694px; }
.bracket-scroll { overflow-x: auto; padding-bottom: .5rem; }
/* ⚠️ The bracket is drawn left-to-right in its own coordinates, so it is
   NOT flipped for اردو — a bracket that mirrors reads as a different
   tournament running backwards. The scroller around it flips; the drawing
   does not. */
[dir="rtl"] .bracket-scroll { direction: ltr; }

svg.bracket .seat rect { transition: fill .45s ease, stroke .45s ease; }
svg.bracket .seat text { transition: fill .45s ease; }
svg.bracket .seat.pending rect { fill: #181209; stroke: #30291E; }
svg.bracket .seat.pending text { fill: #514532; }
svg.bracket .seat.won rect { fill: #2A2012; stroke: #FFB300; }
svg.bracket .seat.won text { fill: #FFD79B; }
svg.bracket .seat[data-round="3"].won rect { fill: #432C00; }
svg.bracket .link { transition: stroke .5s ease; }
svg.bracket .link.live { stroke: #FFB300; }

/* ── the amber panel breathes, once, on hover ──────────────────────────── */
a.cta-panel { transition: transform .3s cubic-bezier(.2,.7,.3,1), box-shadow .3s ease; }
a.cta-panel:hover { transform: translateY(-2px); box-shadow: 0 20px 50px -18px rgba(255,179,0,.85); }
a.row-card { transition: transform .25s ease, border-color .25s ease, background .25s ease; }
a.row-card:hover { transform: translateX(2px); }
[dir="rtl"] a.row-card:hover { transform: translateX(-2px); }
.shots img { transition: transform .35s cubic-bezier(.2,.7,.3,1), border-color .35s ease; }
.shots figure:hover img { transform: translateY(-5px) scale(1.015); border-color: var(--line-2); }


/* ⛔ NOTHING SCROLLS THE PAGE SIDEWAYS. A single wide child — a table, a
   bracket, a stray absolute — turns the whole document into a horizontal
   scroller, and on a phone that reads as a broken site rather than as one wide
   element. Wide things get their own scroller (.scroll-x, .bracket-scroll,
   .shots); the document does not. */
html, body { overflow-x: clip; max-width: 100%; }
img, svg, canvas, video { max-width: 100%; }


/* ⛔ A LINK ALONE IN A PARAGRAPH IS A CALL TO ACTION, and it was 19px tall.
   WCAG exempts links INSIDE a sentence — a finger aims at the sentence — but
   these sit on their own line with nothing around them to aim at, so they get a
   real target. Inline links in running text are deliberately left alone. */
p > a:only-child {
  display: inline-block;
  padding-block: 0.45rem;
}

/* Two labels were under 11px, which is below what anybody reads comfortably on
   a phone: the amber panel's kicker and the mock card's id line. */
.cta-panel .kicker { font-size: 0.72rem; }
.mcard .id { font-size: 0.72rem; }


/* An email address is something a reader taps, not something they read past —
   and at 19px tall it was the smallest target on the site. Inline links inside
   a sentence keep the WCAG inline exception and are left alone. */
a[href^="mailto:"] { display: inline-block; padding-block: 0.4rem; }


/* The notify link is the only thing on the home page a visitor can act on
   today, and it sat exactly on the 36px line. Give it room. */
#notify-me { min-height: 40px; }
