/* ==========================================================================
   Singapore TOTO — Data-Driven Number Generator
   Design goal: clean / modern / trustworthy / data-oriented — NOT a casino
   look (no neon, no gold, no slot-machine motifs). Mobile-first, then
   progressively enhanced for tablet/desktop (see breakpoints at the bottom
   of each section below: 640 / 768 / 1024px).

   IMPORTANT (see project history): a previous project (01-korea-lotto) had a
   production bug where `overflow: hidden` on a flex-height container blocked
   vertical scrolling on real iPhones. This file deliberately avoids:
     - overflow: hidden on html/body or any full-height layout container
     - height: 100vh / 100dvh locks on scrollable containers
     - position: fixed wrappers around scrollable content
   ========================================================================== */

:root {
  --color-bg: #f7f8fa;
  --color-surface: #ffffff;
  --color-surface-alt: #eef1f5;
  --color-border: #dde2e8;
  --color-text: #1a2233;
  --color-text-muted: #5b6472;
  --color-text-faint: #8a93a1;

  --color-primary: #145da0;
  --color-primary-dark: #0d3f70;
  --color-primary-contrast: #ffffff;
  --color-accent: #0f9d78;
  --color-accent-contrast: #ffffff;
  --color-warn: #b45309;
  --color-danger: #c0392b;

  --color-mode-random: #5b6472;
  --color-mode-balanced: #145da0;
  --color-mode-trend: #0f9d78;

  --ball-bg: #ffffff;
  --ball-border: #c7cedb;
  --ball-text: #1a2233;
  --ball-additional-bg: var(--color-primary);
  --ball-additional-text: #ffffff;

  --radius-sm: 8px;
  --radius-md: 14px;
  --radius-lg: 20px;
  --radius-pill: 999px;

  --shadow-sm: 0 1px 2px rgba(20, 30, 50, 0.06);
  --shadow-md: 0 4px 16px rgba(20, 30, 50, 0.08);
  --shadow-lg: 0 12px 32px rgba(20, 30, 50, 0.12);

  --space-1: 4px;
  --space-2: 8px;
  --space-3: 12px;
  --space-4: 16px;
  --space-5: 24px;
  --space-6: 32px;
  --space-7: 48px;

  --max-width: 1120px;
  --font-sans: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial,
    "PingFang SC", "Microsoft YaHei", "Noto Sans SC", sans-serif;
}

@media (prefers-color-scheme: dark) {
  :root {
    --color-bg: #0f1420;
    --color-surface: #171e2c;
    --color-surface-alt: #1e2635;
    --color-border: #2a3244;
    --color-text: #e9edf3;
    --color-text-muted: #a7b0c0;
    --color-text-faint: #6d7688;

    --color-primary: #4da3e0;
    --color-primary-dark: #7fc0f0;
    --color-primary-contrast: #06131f;
    --color-accent: #2fbf95;
    --color-accent-contrast: #06131f;

    --color-mode-random: #a7b0c0;
    --color-mode-balanced: #4da3e0;
    --color-mode-trend: #2fbf95;

    --ball-bg: #1e2635;
    --ball-border: #34405a;
    --ball-text: #e9edf3;
    --ball-additional-bg: var(--color-primary);
    --ball-additional-text: #06131f;

    --shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.3);
    --shadow-md: 0 4px 16px rgba(0, 0, 0, 0.35);
    --shadow-lg: 0 12px 32px rgba(0, 0, 0, 0.45);
  }
}

* {
  box-sizing: border-box;
}

/* The `hidden` attribute must always win, even over elements whose class
   sets `display: grid/flex` (equal specificity to the UA's [hidden] rule,
   so without this it would NOT actually hide — verified via screenshot). */
[hidden] {
  display: none !important;
}

html {
  /* No height lock, no overflow lock — the page must always be free to grow
     taller than the viewport and scroll normally on every device. */
  -webkit-text-size-adjust: 100%;
  /* Reserve the vertical scrollbar's width unconditionally, so switching
     between a tall view (a vertical scrollbar renders) and a short view (it
     doesn't) never changes document.documentElement.clientWidth — without
     this, the centered `.wrap` (max-width + margin:auto) shifts a few px
     left/right between views since it centers against that width. Supported
     in every engine this project targets (Chromium 94+, Safari 17+); no
     JS/per-view fallback needed. */
  scrollbar-gutter: stable;
}

body {
  margin: 0;
  min-height: 100%;
  background: var(--color-bg);
  color: var(--color-text);
  font-family: var(--font-sans);
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden; /* guard against accidental horizontal overflow only */
}

img, svg {
  max-width: 100%;
}

a {
  color: var(--color-primary);
}

button {
  font-family: inherit;
}

.wrap {
  width: 100%;
  max-width: var(--max-width);
  margin: 0 auto;
  padding-left: var(--space-4);
  padding-right: var(--space-4);
}

@media (min-width: 1024px) {
  .wrap {
    padding-left: var(--space-6);
    padding-right: var(--space-6);
  }
}

/* ---------- Header ------------------------------------------------------- */

.site-header {
  position: sticky;
  top: 0;
  z-index: 40;
  background: var(--color-surface);
  border-bottom: 1px solid var(--color-border);
  transition: box-shadow 0.2s ease;
  /* This element's own height changes (compact-mode padding/logo/tagline)
     as the page scrolls — without this, browser scroll-anchoring can nudge
     scrollY to compensate for that height change, which re-triggers the
     compact-mode threshold and creates a feedback loop (see app.js). */
  overflow-anchor: none;
}

.site-header__inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
  padding-top: var(--space-3);
  padding-bottom: var(--space-3);
  transition: padding 0.15s ease;
}

.site-header.is-compact .site-header__inner {
  padding-top: 8px;
  padding-bottom: 8px;
}

.site-header.is-compact {
  box-shadow: var(--shadow-sm);
}

.brand {
  display: flex;
  align-items: center;
  min-width: 0;
  flex: none;
}

/* header-logo.png is a complete brand mark (TOTO ball + "SG TOTO
   SmartPick" wordmark + tagline) — sized by height only so its own aspect
   ratio is never distorted; width follows automatically. */
.brand__logo {
  display: block;
  height: 36px;
  width: auto;
  object-fit: contain;
  transition: height 0.15s ease;
}

.site-header.is-compact .brand__logo {
  height: 34px;
}

/* Mobile header (<768px, hamburger visible): center the logo on the true
   header/viewport midpoint instead of the flex row's leftover space.
   .site-header__inner (via .wrap) has symmetric left/right padding, so
   centering against its own box lands on the same X as centering against
   the viewport. Pulling .brand out of flow leaves .hamburger-btn as the
   sole flex item, which justify-content:space-between would then push to
   the start — margin-left:auto keeps it pinned right. Logo size/ratio and
   header height are untouched (absolute positioning doesn't affect either). */
@media (max-width: 767px) {
  .site-header__inner {
    position: relative;
  }

  .brand {
    position: absolute;
    left: 50%;
    top: 50%;
    transform: translate(-50%, -50%);
  }

  .hamburger-btn {
    margin-left: auto;
  }
}

/* Desktop nav + lang switch — hidden below 768px, hamburger shown instead */

.site-nav-desktop {
  display: none;
  flex: 1;
  justify-content: center;
  gap: var(--space-5);
  font-size: 0.86rem;
}

.site-nav-desktop a {
  color: var(--color-text-muted);
  text-decoration: none;
  font-weight: 600;
  padding-bottom: 4px;
  border-bottom: 2px solid transparent; /* reserved in both states so becoming active never shifts row height */
}

.site-nav-desktop a:hover {
  color: var(--color-primary);
}

/* Current top-level view: blue text + bolder weight + underline — three
   cues together, not color alone (see accessibility requirement). */
.site-nav-desktop a.is-active {
  color: var(--color-primary);
  font-weight: 700;
  border-bottom-color: var(--color-primary);
}

.lang-switch {
  display: flex;
  align-items: center;
  gap: 2px;
  background: var(--color-surface-alt);
  border-radius: var(--radius-pill);
  padding: 3px;
  flex: none;
}

.lang-switch--desktop {
  display: none;
}

.lang-switch__btn {
  appearance: none;
  border: 0;
  background: transparent;
  color: var(--color-text-muted);
  font-size: 0.78rem;
  font-weight: 600;
  padding: 10px 12px;
  border-radius: var(--radius-pill);
  cursor: pointer;
  min-height: 40px;
  touch-action: manipulation;
}

.lang-switch__btn.is-active {
  background: var(--color-surface);
  color: var(--color-primary);
  box-shadow: var(--shadow-sm);
}

/* Hamburger toggle (mobile/tablet only) */

.hamburger-btn {
  appearance: none;
  border: 1px solid var(--color-border);
  background: var(--color-surface);
  border-radius: var(--radius-sm);
  width: 40px;
  height: 40px;
  flex: none;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 4px;
  cursor: pointer;
  touch-action: manipulation;
}

.hamburger-btn span {
  display: block;
  width: 18px;
  height: 2px;
  border-radius: 1px;
  background: var(--color-text);
  transition: transform 0.15s ease, opacity 0.15s ease;
}

.hamburger-btn.is-open span:nth-child(1) { transform: translateY(6px) rotate(45deg); }
.hamburger-btn.is-open span:nth-child(2) { opacity: 0; }
.hamburger-btn.is-open span:nth-child(3) { transform: translateY(-6px) rotate(-45deg); }

.mobile-menu {
  border-top: 1px solid var(--color-border);
  padding: var(--space-4);
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
}

.mobile-menu__nav {
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
}

.mobile-menu__nav a {
  display: flex;
  color: var(--color-text);
  text-decoration: none;
  padding: 10px 4px;
  border-radius: var(--radius-sm);
}

.mobile-menu__nav a:active {
  background: var(--color-surface-alt);
}

/* Underline lives on an inner span (not the row-width anchor) so it hugs
   the text instead of spanning the full row — same visual language as
   .site-nav-desktop's active tab (blue + bold + underline), no background
   tint or left bar. border-bottom is reserved in both states so becoming
   active never shifts the row's height/text position. */
.mobile-menu__nav a > span {
  font-weight: 600;
  font-size: 0.95rem;
  padding-bottom: 2px;
  border-bottom: 2px solid transparent;
}

.mobile-menu__nav a.is-active > span {
  color: var(--color-primary);
  font-weight: 700;
  border-bottom-color: var(--color-primary);
}

.lang-switch--mobile {
  align-self: flex-start;
}

@media (min-width: 768px) {
  .site-nav-desktop { display: flex; }
  .lang-switch--desktop { display: flex; }
  .hamburger-btn { display: none; }
  .mobile-menu { display: none !important; }

  .brand__logo { height: 48px; }
  .site-header.is-compact .brand__logo { height: 38px; }
}

/* ---------- Layout -------------------------------------------------------- */

main {
  padding-top: var(--space-5);
  padding-bottom: var(--space-7);
}

.section {
  margin-bottom: var(--space-6);
}

@media (min-width: 1024px) {
  .section {
    margin-bottom: var(--space-7);
  }
}

.card {
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  padding: var(--space-5);
  box-shadow: var(--shadow-sm);
}

.grid-3 {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--space-4);
}

@media (min-width: 640px) {
  .grid-3 {
    grid-template-columns: 1fr 1fr;
  }
}

@media (min-width: 1024px) {
  .grid-3 {
    grid-template-columns: repeat(3, 1fr);
  }
}

h1, h2, h3, h4 {
  margin: 0 0 var(--space-2);
  line-height: 1.25;
}

h2 {
  font-size: 1.05rem;
  font-weight: 800;
}

h3 {
  font-size: 0.92rem;
  font-weight: 700;
}

h4 {
  font-size: 0.86rem;
  font-weight: 700;
  margin-top: var(--space-4);
}

h4:first-child {
  margin-top: 0;
}

p {
  margin: 0 0 var(--space-3);
  color: var(--color-text-muted);
  font-size: 0.9rem;
}

.eyebrow {
  font-size: 0.7rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--color-text-faint);
}

/* ---------- Hero / Generator ----------------------------------------------- */

.card--hero {
  border: 1.5px solid color-mix(in srgb, var(--color-primary) 25%, var(--color-border));
  box-shadow: var(--shadow-md);
}

.hero__title {
  font-size: 1.3rem;
  font-weight: 800;
}

.hero__lead {
  font-size: 0.86rem;
  margin-bottom: var(--space-4);
}

@media (min-width: 1024px) {
  .card--hero {
    padding: var(--space-6);
  }
  .hero__title {
    font-size: 1.55rem;
  }
  .hero__lead {
    font-size: 0.92rem;
  }
}

/* ---------- Mode selector --------------------------------------------------- */

.mode-selector {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: var(--space-2);
}

.mode-btn {
  appearance: none;
  cursor: pointer;
  border: 1.5px solid var(--color-border);
  border-top: 3px solid var(--color-border);
  background: var(--color-surface);
  border-radius: var(--radius-md);
  padding: var(--space-3) var(--space-2);
  text-align: center;
  min-height: 68px;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 2px;
  touch-action: manipulation;
  position: relative;
}

.mode-btn__label {
  font-weight: 800;
  font-size: 0.82rem;
  color: var(--color-text);
}

.mode-btn__hint {
  font-size: 0.68rem;
  color: var(--color-text-faint);
}

.mode-btn__badge {
  position: absolute;
  top: -9px;
  left: 50%;
  transform: translateX(-50%);
  font-size: 0.6rem;
  font-weight: 700;
  color: #fff;
  background: var(--color-mode-balanced);
  padding: 2px 8px;
  border-radius: var(--radius-pill);
  text-transform: uppercase;
  letter-spacing: 0.04em;
}

#mode-random.is-active { border-top-color: var(--color-mode-random); background: color-mix(in srgb, var(--color-mode-random) 8%, var(--color-surface)); }
#mode-balanced.is-active { border-top-color: var(--color-mode-balanced); background: color-mix(in srgb, var(--color-mode-balanced) 8%, var(--color-surface)); }
#mode-trend.is-active { border-top-color: var(--color-mode-trend); background: color-mix(in srgb, var(--color-mode-trend) 8%, var(--color-surface)); }

.mode-btn.is-active { border-color: var(--color-border); }
.mode-btn.is-active .mode-btn__label { color: var(--color-text); }

.mode-desc {
  margin-top: var(--space-3);
  font-size: 0.82rem;
  color: var(--color-text-muted);
  min-height: 1.4em;
  margin-bottom: 0;
}

.generate-btn-row {
  display: flex;
  justify-content: center;
  margin-top: var(--space-4);
}

.generate-btn {
  appearance: none;
  cursor: pointer;
  width: auto;
  min-width: 220px;
  border: 0;
  border-radius: var(--radius-md);
  padding: 15px var(--space-4);
  background: linear-gradient(135deg, var(--color-primary), var(--color-primary-dark));
  color: var(--color-primary-contrast);
  font-weight: 800;
  font-size: 0.98rem;
  box-shadow: var(--shadow-md);
  touch-action: manipulation;
  min-height: 52px;
}

.generate-btn:disabled {
  opacity: 0.6;
  cursor: default;
}

.generate-btn:active {
  transform: translateY(1px);
}

@media (min-width: 640px) {
  .generate-btn {
    min-width: 260px;
  }
}

/* Compact informational footer inside the hero card (Data Source /
   Disclaimer). The card itself stays centered (title/mode-selector/button);
   this block is deliberately left-aligned via its own wrapper so a
   multi-line disclaimer reads naturally instead of centering each line. */
.hero__footer {
  text-align: left;
  margin-top: var(--space-5);
  padding-top: var(--space-4);
  border-top: 1px dashed var(--color-border);
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
}

.hero__footer-item {
  text-align: left;
}

.hero__footer-item p {
  margin: 2px 0 0;
  font-size: 0.78rem;
  color: var(--color-text-muted);
}

@media (min-width: 768px) {
  .hero__footer {
    flex-direction: row;
    align-items: flex-start;
    gap: 0;
  }

  .hero__footer-item {
    flex: 1 1 50%;
    min-width: 0;
    padding-right: var(--space-5);
  }

  .hero__footer-item + .hero__footer-item {
    padding-right: 0;
    padding-left: var(--space-5);
    border-left: 1px solid color-mix(in srgb, var(--color-border) 55%, transparent);
  }
}

/* ---------- Results --------------------------------------------------------- */
/* Current Picks (#results) and Recent Picks live in one combined card (see
   .picks-card below) — each set's "label + ball row" head shares
   .pick-set-grid / .pick-set structurally, not just visually. Both stay a
   single 1-column list at every width (Current: 6 rows always; Recent's
   expanded panel: 6 rows) since each only gets half the card's width now.
   Only the ball size differs (Current keeps the larger default .ball;
   Recent adds .ball-row--sm) and Recent tightens the row gap via
   .pick-set-grid--recent. */

.pick-set-grid {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
}

/* Current Picks only (Recent Picks keeps its own gap via
   .pick-set-grid--recent below) — tighter set-to-set gap since each set is
   now a compact one-line row instead of a multi-line block. */
.pick-set-grid--current {
  gap: 8px;
}

.pick-set {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: var(--space-3);
}

.pick-set__label {
  flex: none;
  min-width: 40px;
  font-size: 0.7rem;
  font-weight: 700;
  color: var(--color-text-faint);
}

.ball-row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-2);
}

.ball {
  width: 40px;
  height: 40px;
  flex: none;
  border-radius: 50%;
  background: var(--ball-bg);
  border: 2px solid var(--ball-border);
  color: var(--ball-text);
  display: flex;
  align-items: center;
  justify-content: center;
  font-weight: 800;
  font-size: 0.92rem;
}

.ball--additional {
  background: var(--ball-additional-bg);
  color: var(--ball-additional-text);
  border-color: var(--ball-additional-bg);
}

/* Set row: SET label + balls + analysis trigger all on one line. .pick-set
   is shared with Recent Picks (label+ball-row only, no button there), so the
   trigger is added as a sibling in this wrapping row rather than inside
   .pick-set itself — .results-set__row is what actually goes flex/space-between. */
.results-set__row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-2);
}

.results-set__row .pick-set {
  flex: 1 1 auto;
  min-width: 0;
}

.result-set__summary {
  margin-top: 3px;
  font-size: 0.72rem;
  color: var(--color-text-muted);
  font-weight: 600;
}

.analysis-toggle {
  appearance: none;
  border: 0;
  background: transparent;
  color: var(--color-primary);
  font-size: 0.74rem;
  font-weight: 700;
  padding: 4px 6px;
  display: flex;
  align-items: center;
  gap: 4px;
  cursor: pointer;
  touch-action: manipulation;
  flex: none;
  white-space: nowrap;
  min-height: 32px;
}

.analysis-toggle svg {
  transition: transform 0.15s ease;
}

.analysis-toggle[aria-expanded="true"] svg {
  transform: rotate(180deg);
}

/* Tinted panel (same surface-alt tone as Recent Picks / Pattern Snapshot) so
   the analysis grid reads as secondary detail, not primary content sitting
   directly on the card's white background. */
.analysis-grid {
  margin-top: var(--space-4);
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 6px var(--space-3);
  padding: 8px var(--space-3);
  background: var(--color-surface-alt);
  border-radius: var(--radius-sm);
}

@media (min-width: 480px) {
  .analysis-grid {
    grid-template-columns: repeat(3, 1fr);
  }
}

.analysis-item__label {
  font-size: 0.62rem;
  font-weight: 700;
  color: var(--color-text-faint);
  text-transform: uppercase;
  letter-spacing: 0.03em;
  margin-bottom: 2px;
}

.analysis-item__value {
  font-size: 0.76rem;
  font-weight: 700;
  color: var(--color-text);
}

.dots {
  letter-spacing: 1.5px;
  color: var(--color-primary);
  font-size: 0.76rem;
}

.dots .dim {
  color: var(--color-border);
}

/* ---------- Current Picks + Recent Picks combined card ----------------------- */
/* One outer card holds both — Current Picks (left) is the primary generated
   result, Recent Picks (right) stays a secondary/reference history list
   (smaller type, tinted rows, no shadow) so it never visually outweighs the
   current result beside it. Stacked below 1024px, side-by-side above it. */

.picks-card {
  margin-top: var(--space-4);
}

.picks-combined {
  display: flex;
  flex-direction: column;
  gap: var(--space-5);
}

.picks-combined__col h3 {
  margin-bottom: var(--space-3);
}

/* Current Picks header only — Recent Picks' header keeps its existing
   spacing (.recent-picks-head already sets its own margin-bottom). */
.picks-combined__col:first-child h3 {
  margin-bottom: 8px;
}

.picks-empty-text {
  color: var(--color-text-faint);
  font-size: 0.86rem;
  margin: 0;
}

@media (min-width: 1024px) {
  .picks-combined {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 0;
    /* align-items: stretch (default) — not "start". With a single grid row,
       stretch makes both columns fill the row's full height (driven by
       min-height below), so the divider border-left on the second column
       always reaches the card's bottom edge instead of stopping wherever
       that column's own content happens to end. */
    /* Reference height = the tallest of the 7 required-invariant states,
       measured after compaction: Recent (3 items, 1 open + 2 collapsed) is
       ~422px and Current Picks closed is ~428px, but Current Picks with one
       analysis panel open is ~536px (6 metrics in a tinted grid can't shrink
       below readable without stripping the analysis panel's spec-required
       content) — that state governs, so it's the real measured floor here,
       not the Recent-only figure. All shorter states stretch up to match via
       align-items: stretch. */
    min-height: 537px;
  }

  .picks-combined__col:first-child {
    padding-right: var(--space-5);
  }

  .picks-combined__col + .picks-combined__col {
    padding-left: var(--space-5);
    border-left: 1px solid color-mix(in srgb, var(--color-border) 55%, transparent);
  }
}

/* ---------- Recent Picks (Generator generation history) --------------------- */

.recent-picks-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
  margin-bottom: var(--space-3);
}

.recent-picks-head h3 {
  margin-bottom: 0;
}

/* Subtle at rest — this is a local-storage-only, non-recoverable-but-low-
   stakes action (max 3 saved generations), so no red fill button and no
   confirmation modal, just a quiet tint toward --color-danger on
   hover/focus to hint that it clears data. */
.clear-picks-btn {
  appearance: none;
  flex: none;
  border: 0;
  background: transparent;
  color: var(--color-text-faint);
  font-weight: 700;
  font-size: 0.72rem;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  cursor: pointer;
  padding: 6px 8px;
  border-radius: var(--radius-sm);
  touch-action: manipulation;
  min-height: 32px;
}

.clear-picks-btn:hover {
  color: var(--color-danger);
  background: var(--color-surface-alt);
}

.clear-picks-btn:focus-visible {
  outline: 2px solid var(--color-danger);
  outline-offset: 2px;
}

.recent-picks {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}

.recent-pick {
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  background: var(--color-surface-alt);
  overflow: hidden;
}

.recent-pick__trigger {
  appearance: none;
  width: 100%;
  border: 0;
  background: transparent;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
  padding: 10px 14px;
  text-align: left;
  touch-action: manipulation;
  min-height: 44px;
}

.recent-pick__meta {
  font-size: 0.8rem;
  font-weight: 600;
  color: var(--color-text-muted);
}

.recent-pick__trigger[aria-expanded="true"] .recent-pick__meta {
  color: var(--color-text);
  font-weight: 700;
}

.recent-pick__chevron {
  flex: none;
  color: var(--color-text-faint);
  transition: transform 0.15s ease;
}

.recent-pick__trigger[aria-expanded="true"] .recent-pick__chevron {
  transform: rotate(180deg);
}

/* Layout comes from the shared .pick-set-grid (see Results section above) —
   this only adds the panel's own padding. .pick-set-grid--recent tightens
   the grid's gap to Recent Picks' original compact spacing. */
.recent-pick__panel {
  padding: 2px 14px var(--space-3);
}

.pick-set-grid--recent {
  gap: 6px;
}

@media (min-width: 1024px) {
  .pick-set-grid--recent {
    gap: 6px var(--space-4);
  }
}

/* ---------- Info cards (latest draw / next draw / coverage) ---------------- */

.additional-row {
  margin-top: var(--space-3);
  padding-top: var(--space-3);
  border-top: 1px dashed var(--color-border);
  display: flex;
  align-items: center;
  gap: var(--space-3);
}

.additional-row__label {
  font-size: 0.72rem;
  font-weight: 700;
  color: var(--color-text-faint);
  text-transform: uppercase;
  letter-spacing: 0.03em;
}

.stat-row {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  padding: 7px 0;
  border-bottom: 1px dashed var(--color-border);
  font-size: 0.85rem;
  gap: var(--space-3);
}

.stat-row:last-child {
  border-bottom: 0;
}

.stat-row__label {
  color: var(--color-text-muted);
}

.stat-row__value {
  font-weight: 700;
  text-align: right;
}

.countdown {
  display: flex;
  gap: var(--space-2);
  margin-top: var(--space-3);
}

.countdown__unit {
  flex: 1;
  background: var(--color-surface-alt);
  border-radius: var(--radius-sm);
  text-align: center;
  padding: var(--space-2) 4px;
}

.countdown__num {
  font-size: 1.15rem;
  font-weight: 800;
  color: var(--color-primary);
  display: block;
}

.countdown__unit-label {
  font-size: 0.65rem;
  color: var(--color-text-faint);
  text-transform: uppercase;
}

.tz-row {
  display: flex;
  justify-content: space-between;
  gap: var(--space-4);
  margin-top: var(--space-3);
  flex-wrap: wrap;
}

.tz-block {
  flex: 1;
  min-width: 140px;
}

.tz-block__label {
  font-size: 0.68rem;
  color: var(--color-text-faint);
  text-transform: uppercase;
  letter-spacing: 0.03em;
  margin-bottom: 2px;
}

.tz-block__value {
  font-weight: 800;
  font-size: 1rem;
}

.badge {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  font-size: 0.68rem;
  font-weight: 700;
  padding: 3px 9px;
  border-radius: var(--radius-pill);
  background: var(--color-surface-alt);
  color: var(--color-text-muted);
}

.badge--source {
  color: var(--color-accent);
}

/* ---------- Guide (How It Works): left nav + right content viewer ----------- */

.info-section > h2 {
  margin-bottom: var(--space-2);
}

/* Desktop (1024px+) sidebar-nav + content pane; hidden below 1024px in
   favor of .guide-accordion (mobile accordion, see below). */
.guide-layout {
  display: none;
}

@media (min-width: 1024px) {
  .guide-accordion {
    display: none;
  }

  .guide-layout {
    display: grid;
    grid-template-columns: minmax(200px, 1fr) 3fr;
    gap: var(--space-6);
    align-items: start;
    /* Breathing room below the intro (h2 + .section-lead) above it. No
       prior rule set this — .section-lead's own margin-bottom (var(--space-3),
       12px) is a shared sitewide rule left untouched; this margin-top
       collapses with it (adjoining sibling margins take the larger value,
       they don't sum) so the rendered gap ends up exactly var(--space-6). */
    margin-top: var(--space-6);
  }

  .guide-nav {
    display: flex;
    flex-direction: column;
    gap: 2px;
    position: sticky;
    top: var(--space-5);
  }
}

.guide-nav__item {
  appearance: none;
  width: 100%;
  text-align: left;
  border: none;
  border-left: 3px solid transparent;
  background: transparent;
  color: var(--color-text-muted);
  font-size: 0.86rem;
  font-weight: 500;
  padding: 10px 14px;
  border-radius: 0 var(--radius-sm) var(--radius-sm) 0;
  cursor: pointer;
  touch-action: manipulation;
}

.guide-nav__item:hover {
  background: var(--color-surface-alt);
  color: var(--color-text);
}

.guide-nav__item:focus-visible {
  outline: 2px solid var(--color-primary);
  outline-offset: 2px;
}

.guide-nav__item.is-active {
  background: color-mix(in srgb, var(--color-primary) 10%, var(--color-surface));
  border-left-color: var(--color-primary);
  color: var(--color-primary);
  font-weight: 700;
}

.guide-content {
  min-width: 0;
}

/* ---------- Guide mobile accordion (<1024px) --------------------------------- */
/* Single-open accordion: same 7 sections/content as the desktop nav+pane
   above, duplicated here as markup (both read the same data-i18n keys and
   glossary data, so there is one source of truth for the actual copy). */

.guide-accordion {
  margin-top: var(--space-4);
}

.guide-accordion__item {
  margin-bottom: var(--space-2);
}

.guide-accordion__item:last-child {
  margin-bottom: 0;
}

.guide-accordion__trigger {
  appearance: none;
  width: 100%;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  background: var(--color-surface);
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
  padding: 12px 14px;
  font-weight: 500;
  font-size: 0.88rem;
  color: var(--color-text);
  text-align: left;
  touch-action: manipulation;
  min-height: 48px;
}

.guide-accordion__trigger:focus-visible {
  outline: 2px solid var(--color-primary);
  outline-offset: 2px;
}

.guide-accordion__trigger[aria-expanded="true"] {
  background: color-mix(in srgb, var(--color-primary) 8%, var(--color-surface));
  border-color: var(--color-primary);
  border-radius: var(--radius-md) var(--radius-md) 0 0;
  color: var(--color-primary);
  font-weight: 700;
}

.guide-accordion__chevron {
  flex: none;
  color: var(--color-text-faint);
  transition: transform 0.15s ease;
}

.guide-accordion__trigger[aria-expanded="true"] .guide-accordion__chevron {
  transform: rotate(180deg);
  color: var(--color-primary);
}

.guide-accordion__panel {
  border: 1px solid var(--color-border);
  border-top: none;
  border-radius: 0 0 var(--radius-md) var(--radius-md);
  padding: var(--space-4) 14px;
}

.guide-accordion__panel h4 {
  margin: var(--space-4) 0 var(--space-2);
  font-size: 0.9rem;
}

.guide-accordion__panel h4:first-of-type {
  margin-top: 0;
}

.guide-accordion__panel p {
  font-size: 0.88rem;
  color: var(--color-text-muted);
  margin: 0 0 var(--space-3);
  line-height: 1.5;
}

.guide-accordion__panel ul {
  margin: 0 0 var(--space-3);
  padding-left: 1.15em;
  color: var(--color-text-muted);
  font-size: 0.88rem;
  line-height: 1.5;
}

.guide-accordion__panel li {
  margin-bottom: var(--space-2);
}

.guide-accordion__panel .guide-source {
  font-size: 0.78rem;
}

.guide-accordion__panel > *:last-child {
  margin-bottom: 0;
}

.guide-panel h3 {
  margin: 0 0 var(--space-3);
  font-size: 1.05rem;
}

.guide-panel h4 {
  margin: var(--space-4) 0 var(--space-2);
  font-size: 0.9rem;
}

.guide-panel h4:first-of-type {
  margin-top: 0;
}

.guide-panel p {
  font-size: 0.88rem;
  color: var(--color-text-muted);
  margin: 0 0 var(--space-3);
}

.guide-panel ul {
  margin: 0 0 var(--space-3);
  padding-left: 1.15em;
  color: var(--color-text-muted);
  font-size: 0.88rem;
}

.guide-panel li {
  margin-bottom: var(--space-2);
}

.guide-panel .guide-source {
  font-size: 0.78rem;
}

.guide-panel > *:last-child {
  margin-bottom: 0;
}

/* ---------- Glossary ---------------------------------------------------------- */

.glossary-search {
  margin: 0 0 var(--space-5);
}

.glossary-search input {
  appearance: none;
  width: 100%;
  border: 1.5px solid var(--color-border);
  border-radius: var(--radius-sm);
  padding: 10px 12px;
  font-size: 0.9rem;
  background: var(--color-surface);
  color: var(--color-text);
  min-height: 44px;
}

.glossary-search input:focus {
  outline: 2px solid var(--color-primary);
  outline-offset: 1px;
}

.glossary-empty {
  color: var(--color-text-muted);
  font-size: 0.86rem;
  padding: var(--space-3) 0;
  margin: 0;
}

.glossary-group {
  margin-bottom: var(--space-5);
}

.glossary-group:last-child {
  margin-bottom: 0;
}

.glossary-group__letter {
  font-size: 0.72rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--color-text-faint);
  border-bottom: 1px solid var(--color-border);
  padding-bottom: var(--space-2);
  margin-bottom: var(--space-2);
}

.glossary-item {
  display: grid;
  grid-template-columns: 1fr;
  gap: 2px;
  padding: var(--space-3) 0;
  border-bottom: 1px dashed var(--color-border);
}

.glossary-item:last-child {
  border-bottom: none;
}

.glossary-item__term {
  font-weight: 700;
  font-size: 0.86rem;
  color: var(--color-text);
}

.glossary-item__term-secondary {
  display: block;
  font-weight: 400;
  font-size: 0.72rem;
  color: var(--color-text-faint);
  margin-top: 1px;
}

.glossary-item__def {
  font-size: 0.84rem;
  color: var(--color-text-muted);
}

@media (min-width: 1024px) {
  .glossary-item {
    grid-template-columns: 30% 1fr;
    gap: var(--space-4);
    align-items: baseline;
  }
}

.disclaimer {
  background: color-mix(in srgb, var(--color-warn) 10%, var(--color-surface));
  border: 1px solid color-mix(in srgb, var(--color-warn) 35%, var(--color-border));
  border-radius: var(--radius-md);
  padding: var(--space-4);
  margin-top: var(--space-4);
}

.disclaimer p {
  color: var(--color-text);
  margin-bottom: 0;
  font-size: 0.86rem;
}

/* ---------- Loading / empty / error states ---------------------------------- */

.state-message {
  text-align: center;
  padding: var(--space-6) var(--space-4);
  color: var(--color-text-muted);
  font-size: 0.88rem;
  grid-column: 1 / -1;
}

.spinner {
  width: 28px;
  height: 28px;
  border-radius: 50%;
  border: 3px solid var(--color-border);
  border-top-color: var(--color-primary);
  margin: 0 auto var(--space-3);
  animation: spin 0.8s linear infinite;
}

@keyframes spin {
  to { transform: rotate(360deg); }
}

.hidden {
  display: none !important;
}

/* ---------- Footer ------------------------------------------------------ */

.site-footer {
  border-top: 1px solid var(--color-border);
  padding: var(--space-5) 0 var(--space-7);
  color: var(--color-text-faint);
  font-size: 0.76rem;
  text-align: center;
}

/* ---------- Small screens: extra breathing room on the smallest widths --- */

@media (max-width: 374px) {
  .ball {
    width: 36px;
    height: 36px;
    font-size: 0.85rem;
  }
  .mode-btn__label {
    font-size: 0.72rem;
  }
}

/* ==========================================================================
   Data hub views (Results / Statistics / Jackpots / Guide)
   ========================================================================== */

.view {
  display: none;
}

.view.is-active {
  display: block;
}

.panel-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
  margin-bottom: var(--space-2);
}

.panel-head h2 {
  margin-bottom: 0;
}

.section-lead {
  font-size: 0.82rem;
  margin-bottom: var(--space-3);
}

.link-btn {
  appearance: none;
  border: 0;
  background: transparent;
  color: var(--color-primary);
  font-weight: 700;
  font-size: 0.8rem;
  cursor: pointer;
  padding: 6px 0;
  touch-action: manipulation;
  min-height: 32px;
  white-space: nowrap;
}

.cta-row {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-4);
  margin-top: var(--space-3);
}

.csv-note {
  font-size: 0.74rem;
  color: var(--color-text-faint);
}

/* ---- Latest draw prize mini-summary --------------------------------------- */

.prize-mini {
  margin-top: var(--space-3);
  padding-top: var(--space-3);
  border-top: 1px dashed var(--color-border);
  display: flex;
  flex-direction: column;
  gap: 4px;
}

.prize-mini__row {
  display: flex;
  justify-content: space-between;
  font-size: 0.8rem;
}

.prize-mini__row .label {
  color: var(--color-text-muted);
}

.prize-mini__row .value {
  font-weight: 700;
}

/* ---- Cascade badge ---------------------------------------------------------- */

.badge--cascade {
  display: inline-block;
  margin: 4px 0 2px;
  background: color-mix(in srgb, var(--color-warn) 16%, var(--color-surface));
  color: var(--color-warn);
  border: 1px solid color-mix(in srgb, var(--color-warn) 40%, var(--color-border));
}

.cascade-note {
  font-size: 0.68rem;
  color: var(--color-text-faint);
  margin: 0 0 var(--space-2);
}

/* ---- Window / range toggle pills ------------------------------------------- */

.window-toggle {
  display: flex;
  gap: var(--space-2);
  margin-bottom: var(--space-4);
  flex-wrap: wrap;
}

.window-btn {
  appearance: none;
  border: 1.5px solid var(--color-border);
  background: var(--color-surface);
  color: var(--color-text-muted);
  font-weight: 700;
  font-size: 0.8rem;
  border-radius: var(--radius-pill);
  padding: 8px 16px;
  cursor: pointer;
  touch-action: manipulation;
  min-height: 38px;
}

.window-btn.is-active {
  background: var(--color-primary);
  border-color: var(--color-primary);
  color: var(--color-primary-contrast);
}

/* ---- Draw list rows (Recent Draws / Historical Results / Jackpot tables) --- */

.draw-list {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}

.draw-row {
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  background: var(--color-surface-alt);
  padding: var(--space-3);
}

.draw-row__summary {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  flex-wrap: wrap;
  cursor: pointer;
  touch-action: manipulation;
}

.draw-row__meta {
  flex: none;
  min-width: 84px;
}

.draw-row__draw {
  font-weight: 800;
  font-size: 0.85rem;
}

.draw-row__date {
  font-size: 0.72rem;
  color: var(--color-text-faint);
}

.draw-row .ball-row {
  flex: 1;
  min-width: 0;
}

.draw-row__chevron {
  flex: none;
  color: var(--color-text-faint);
  transition: transform 0.15s ease;
}

.draw-row.is-open .draw-row__chevron {
  transform: rotate(180deg);
}

.draw-row__detail {
  margin-top: var(--space-3);
  padding-top: var(--space-3);
  border-top: 1px dashed var(--color-border);
}

.draw-row__detail-table {
  width: 100%;
  border-collapse: collapse;
  font-size: 0.78rem;
}

.draw-row__detail-table th,
.draw-row__detail-table td {
  text-align: right;
  padding: 4px 6px;
  border-bottom: 1px solid var(--color-border);
}

.draw-row__detail-table th:first-child,
.draw-row__detail-table td:first-child {
  text-align: left;
}

@media (min-width: 768px) {
  .draw-list--table .draw-row__summary {
    display: grid;
    grid-template-columns: 84px 1fr 60px 20px;
    align-items: center;
  }
}

/* Recent Draws only (not Historical Results, which stays .draw-list--table's
   1-column layout): 2-column grid on desktop, row-major by DOM order. Expanded
   detail grows its own row without stretching the sibling cell (align-items:
   start), so an open accordion item never overlaps or masonry-shifts the
   adjacent column. */
@media (min-width: 1024px) {
  #recent-draws-list {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: var(--space-2);
    align-items: start;
  }
}

.ball-row--sm .ball {
  width: 30px;
  height: 30px;
  font-size: 0.72rem;
}

/* ---- Search ------------------------------------------------------------------ */

.search-row {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  gap: var(--space-3);
  margin-bottom: var(--space-3);
}

.search-field {
  display: flex;
  flex-direction: column;
  gap: 4px;
  flex: 1;
  min-width: 140px;
}

.search-field label {
  font-size: 0.72rem;
  font-weight: 700;
  color: var(--color-text-faint);
  text-transform: uppercase;
  letter-spacing: 0.03em;
}

.search-field input {
  appearance: none;
  border: 1.5px solid var(--color-border);
  border-radius: var(--radius-sm);
  padding: 10px 12px;
  font-size: 0.9rem;
  background: var(--color-surface);
  color: var(--color-text);
  min-height: 42px;
}

.search-field input:focus {
  outline: 2px solid var(--color-primary);
  outline-offset: 1px;
}

.search-clear {
  flex: none;
}

.search-error {
  color: var(--color-danger);
  font-size: 0.8rem;
  margin-bottom: var(--space-3);
}

/* ---- Historical Results: search instructions under the section title --------- */

.search-range-note {
  font-size: 0.74rem;
  color: var(--color-text-faint);
  margin-top: -6px;
}

/* ---- Pagination --------------------------------------------------------------- */

.pagination {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-4);
  margin-top: var(--space-4);
}

.pg-btn {
  appearance: none;
  border: 1.5px solid var(--color-border);
  background: var(--color-surface);
  color: var(--color-text);
  font-weight: 700;
  font-size: 0.82rem;
  border-radius: var(--radius-sm);
  padding: 8px 16px;
  cursor: pointer;
  touch-action: manipulation;
  min-height: 38px;
}

.pg-btn:disabled {
  opacity: 0.4;
  cursor: default;
}

.pg-status {
  font-size: 0.8rem;
  color: var(--color-text-muted);
  font-weight: 600;
}

/* ---- Statistics: unified header card (period selector + frequency + hot/cold) - */

.stats-block {
  margin-top: var(--space-5);
}

.stats-block--divided {
  padding-top: var(--space-4);
  border-top: 1px dashed var(--color-border);
}

.stats-block h3 {
  margin-bottom: var(--space-3);
}

.hot-cold-grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--space-4);
}

@media (min-width: 640px) {
  .hot-cold-grid {
    grid-template-columns: 1fr 1fr;
  }
}

/* Most Frequent Numbers as one tinted inset panel (title + both columns
   together) — same surface-alt tone as the Pattern Snapshot cards below,
   so bars/counts read as a distinct grouped block instead of sitting
   directly on the card's white background. */
.freq-panel {
  background: var(--color-surface-alt);
  border-radius: var(--radius-md);
  padding: var(--space-4);
}

/* Mobile only: the merged "Most Frequent Numbers & Appearances" title is
   long enough to wrap to 2 lines below ~430px. Scale it down with the
   viewport (not a fixed step) so it always fits on one line without ever
   overflowing the panel — desktop's 0.92rem (see base `h3` rule) is
   untouched since this lives inside a max-width query. */
@media (max-width: 430px) {
  .freq-panel__title {
    font-size: clamp(0.6rem, 4.6vw - 0.5rem, 0.92rem);
    white-space: nowrap;
  }
}

.freq-list {
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
}

/* Top 10 as 5 rows x 2 columns on wider screens (rank 1-5 left, 6-10
   right) — column-major auto-flow preserves ranking order. Single
   column (rank order top-to-bottom) below that. */
@media (min-width: 768px) {
  .freq-list--cols {
    display: grid;
    grid-template-columns: 1fr 1fr;
    grid-template-rows: repeat(5, auto);
    grid-auto-flow: column;
    column-gap: var(--space-6);
    row-gap: var(--space-1);
  }
}

.freq-row {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  padding: 3px 0;
}

.freq-row__ball {
  flex: none;
}

.freq-row__bar-track {
  flex: 1 1 auto;
  max-width: 200px;
  height: 8px;
  border-radius: var(--radius-pill);
  /* Track now sits inside .freq-panel's tinted surface-alt background —
     use the card's white/base surface instead so the track still reads
     as a distinct "channel" instead of disappearing into its container. */
  background: var(--color-surface);
  overflow: hidden;
}

.freq-row__bar-fill {
  display: block; /* it's a <span>; without this its inline-set width has no effect */
  height: 100%;
  background: var(--color-primary);
  border-radius: var(--radius-pill);
}

.freq-row__count {
  flex: none;
  min-width: 2.4em;
  font-size: 0.78rem;
  font-weight: 700;
  color: var(--color-text-muted);
  text-align: right;
}

.hot-cold-block {
  margin-bottom: var(--space-3);
}

.hot-cold-block__label {
  font-size: 0.72rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  margin-bottom: 6px;
}

.hot-cold-block__label.hot { color: var(--color-warn); }
.hot-cold-block__label.cold { color: var(--color-primary); }

.hot-cold-disclaimer {
  font-size: 0.74rem;
  color: var(--color-text-faint);
}

.number-grid {
  display: grid;
  grid-template-columns: repeat(7, 1fr);
  gap: 6px;
}

.number-cell {
  appearance: none;
  cursor: pointer;
  border: 1.5px solid var(--color-border);
  background: var(--color-surface-alt);
  border-radius: var(--radius-sm);
  padding: 6px 2px;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 1px;
  touch-action: manipulation;
  min-height: 44px;
}

.number-cell.is-selected {
  border-color: var(--color-primary);
  background: color-mix(in srgb, var(--color-primary) 12%, var(--color-surface));
}

.number-cell__n {
  font-weight: 800;
  font-size: 0.78rem;
}

.number-cell__c {
  font-size: 0.6rem;
  color: var(--color-text-faint);
}

/* All Numbers + Number Detail: one card, 50:50 on desktop with a
   subtle vertical divider, stacked (grid then detail) on mobile. */
.numdetail-split {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--space-6);
}

@media (min-width: 1024px) {
  .numdetail-split {
    grid-template-columns: 1fr 1fr;
  }
  .numdetail-split__col--detail {
    padding-left: var(--space-6);
    border-left: 1px dashed var(--color-border);
  }
}

.pattern-grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--space-4);
  align-items: start; /* cards have different row counts now (bars) — don't stretch the shorter ones to match the tallest */
}

@media (min-width: 640px) {
  .pattern-grid {
    grid-template-columns: repeat(2, 1fr);
  }
}

@media (min-width: 1024px) {
  .pattern-grid {
    grid-template-columns: repeat(4, 1fr);
  }
}

.pattern-card {
  background: var(--color-surface-alt);
  border-radius: var(--radius-md);
  padding: var(--space-3);
}

.pattern-card__label {
  font-size: 0.68rem;
  font-weight: 700;
  color: var(--color-text-faint);
  text-transform: uppercase;
  letter-spacing: 0.03em;
  margin-bottom: var(--space-2);
}

/* ---- Pattern Snapshot: bar rows (Odd/Even, Number Range, Consecutive) ---- */

.pattern-bars {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}

.pattern-bar-row__top {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: var(--space-2);
  margin-bottom: 3px;
}

.pattern-bar-row__label {
  font-size: 0.78rem;
  font-weight: 700;
  color: var(--color-text);
}

.pattern-bar-row__meta {
  flex: none;
  font-size: 0.7rem;
  font-weight: 600;
  color: var(--color-text-faint);
  white-space: nowrap;
}

.pattern-bar-track {
  height: 8px;
  border-radius: var(--radius-pill);
  background: var(--color-border);
  overflow: hidden;
}

.pattern-bar-fill {
  display: block; /* it's a <span>; without this its inline-set width has no effect */
  height: 100%;
  background: var(--color-primary);
  border-radius: var(--radius-pill);
}

/* ---- Pattern Snapshot: Winning Number Sum (headline average + min/max range) ---- */

.pattern-sum__value {
  font-size: 1.6rem;
  font-weight: 800;
  line-height: 1.1;
  color: var(--color-primary);
}

.pattern-sum__value-label {
  font-size: 0.68rem;
  font-weight: 700;
  color: var(--color-text-faint);
  text-transform: uppercase;
  letter-spacing: 0.03em;
  margin-top: 2px;
  margin-bottom: var(--space-4);
}

.pattern-sum__range {
  display: flex;
  align-items: center;
  gap: var(--space-2);
}

.pattern-sum__range-end {
  flex: none;
  display: flex;
  flex-direction: column;
}

.pattern-sum__range-end--start { align-items: flex-start; }
.pattern-sum__range-end--end { align-items: flex-end; }

.pattern-sum__range-value {
  font-size: 0.8rem;
  font-weight: 700;
  color: var(--color-text-muted);
}

.pattern-sum__range-caption {
  font-size: 0.64rem;
  font-weight: 700;
  color: var(--color-text-faint);
  text-transform: uppercase;
  letter-spacing: 0.03em;
}

.pattern-sum__range-track {
  position: relative;
  flex: 1 1 auto;
  height: 4px;
  min-width: 40px;
  border-radius: var(--radius-pill);
  background: var(--color-border);
}

.pattern-sum__range-dot {
  position: absolute;
  top: 50%;
  width: 10px;
  height: 10px;
  border-radius: 50%;
  background: var(--color-primary);
  border: 2px solid var(--color-surface-alt);
  transform: translate(-50%, -50%);
}

/* ---- Statistics preview (home) ------------------------------------------------ */

.stats-preview-grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--space-4);
}

@media (min-width: 640px) {
  .stats-preview-grid {
    grid-template-columns: repeat(3, 1fr);
  }
}

.stats-preview-item__label {
  font-size: 0.7rem;
  font-weight: 700;
  color: var(--color-text-faint);
  text-transform: uppercase;
  letter-spacing: 0.03em;
  margin-bottom: 6px;
}

.stats-preview-item__value {
  font-size: 1.3rem;
  font-weight: 800;
}

/* ---- Number detail panel ------------------------------------------------------ */

.number-detail__head {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  margin-bottom: var(--space-4);
}

.number-detail__ball {
  width: 52px;
  height: 52px;
  font-size: 1.15rem;
}

.number-detail__stats {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: var(--space-3);
  margin-bottom: var(--space-4);
}

/* Fixed-column grid at every viewport (no flex-wrap anywhere) so every pill
   shares the same width/height and every column lines up row to row —
   flex-wrap let each row's pill positions drift slightly depending on how
   many digits happened to wrap onto it, and desktop's wider pane made that
   drift visible. 8 columns is close to the pill's natural content width in
   the ~455px detail pane (measured); 5 columns keeps the same fit below
   1024px, unchanged from before. */
.number-detail__appearances {
  display: grid;
  grid-template-columns: repeat(8, 1fr);
  gap: 6px;
}

.number-detail__appearance-chip {
  width: 100%;
  text-align: center;
  font-size: 0.74rem;
  font-weight: 700;
  padding: 4px 4px;
  border-radius: var(--radius-pill);
  background: var(--color-surface-alt);
  color: var(--color-text-muted);
}

@media (max-width: 1023px) {
  .number-detail__appearances {
    grid-template-columns: repeat(5, 1fr);
    gap: var(--space-2);
  }
}

/* ---- Jackpots ------------------------------------------------------------------ */

.jackpot-highlight {
  font-size: 1.6rem;
  font-weight: 800;
  color: var(--color-primary);
  margin-top: var(--space-2);
}

.jackpot-highlight .jh-meta {
  display: block;
  font-size: 0.76rem;
  font-weight: 600;
  color: var(--color-text-faint);
  margin-top: 4px;
}

/* Jackpots tab: Estimated Jackpot / Largest Ever / Largest 12mo in one card. */
.jackpot-summary {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--space-5);
}

@media (min-width: 720px) {
  .jackpot-summary {
    grid-template-columns: repeat(3, 1fr);
    gap: var(--space-6);
  }

  .jackpot-summary__block:not(:first-child) {
    padding-left: var(--space-6);
    border-left: 1px dashed var(--color-border);
  }

  .jackpot-summary__block .eyebrow {
    white-space: nowrap;
  }
}

.jh-meta--standalone {
  display: block;
  font-size: 0.76rem;
  font-weight: 600;
  color: var(--color-text-faint);
  margin-top: 4px;
}

/* Inline "est" suffix next to the amount — stays on the amount's own line,
   unlike .jh-meta (which is block-level and starts a new line). */
.jackpot-highlight .jh-suffix {
  font-size: 0.72rem;
  font-weight: 700;
  color: var(--color-text-faint);
  margin-left: 4px;
}

.jackpot-summary__block .badge--cascade {
  margin-top: var(--space-2);
}

/* Jackpots tab: Top 10 Jackpots + Cascade Draw History side by side. */
.jackpot-tables-grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--space-6);
}

@media (min-width: 1024px) {
  .jackpot-tables-grid {
    grid-template-columns: 1fr 1fr;
  }

  /* Cascade card matches Top 10's card height. flex:1 alone can't cap the
     list — without an explicit max-height the browser has nothing to bound
     the list against during grid track sizing, so it sizes the row to
     whatever content Load More has grown to (the original bug). The actual
     px cap is computed and set inline by views.js's syncCascadeListHeight()
     (Top 10's real rendered height minus this card's own header/lead/button
     chrome), so the list fills exactly the remaining space and the Load
     more button lands flush with Top 10's bottom edge, with no leftover
     gap and no arbitrary hardcoded number here. */
  .jackpot-tables-grid .card--cascade {
    display: flex;
    flex-direction: column;
    min-height: 0;
  }

  .jackpot-tables-grid .card--cascade > h3,
  .jackpot-tables-grid .card--cascade > .section-lead,
  .jackpot-tables-grid .card--cascade > #cascade-load-more-btn {
    flex: none;
  }

  .jackpot-tables-grid .card--cascade > #cascade-history-list {
    flex: 1 1 auto;
    min-height: 0;
    overflow-y: auto;
    padding-right: 4px;
  }
}

#cascade-load-more-btn {
  margin-top: var(--space-3);
}

/* Top 10 Group 1 Jackpots now shares a half-width card with Cascade Draw
   History — shrink the ball row so 7 balls still fit comfortably. */
#jackpot-top10-list .ball {
  width: 30px;
  height: 30px;
  font-size: 0.72rem;
}

/* Draw # / date text must never wrap (EN "Draw 3738" / ZH "第 3738 期",
   dates like ZH "2014年10月13日") — 92px is the measured max-content width
   across the entire historical dataset in both languages, plus headroom. */
#jackpot-top10-list .draw-row__meta,
#cascade-history-list .draw-row__meta {
  min-width: 92px;
}

#jackpot-top10-list .draw-row__draw,
#jackpot-top10-list .draw-row__date,
#cascade-history-list .draw-row__draw,
#cascade-history-list .draw-row__date {
  white-space: nowrap;
}

@media (min-width: 768px) {
  /* 3 real grid items (meta / ball-row / chevron) — sizing the chevron
     column to its own content (auto) instead of a wider fixed track keeps
     it flush with the row's right edge instead of leaving an empty gap
     there, so left and right padding read as balanced. */
  #jackpot-top10-list.draw-list--table .draw-row__summary {
    grid-template-columns: 92px 1fr auto;
  }

  /* 2 real grid items (meta / prize-mini) — no chevron, so no 3rd/4th
     track; the value column now reaches the row's true right edge. */
  #cascade-history-list.draw-list--table .draw-row__summary {
    grid-template-columns: 92px 1fr;
  }
}
