/* Design System — canonical token layer for YOKU ONE.
   VARIANT A — "One Platform" (2026-09-25), a local-only design-system
   exploration branch (`design-variant-a-oneplatform`), never pushed to
   master/Railway. Source: Documents\YokuOne\one-platform-design-system.zip
   — a React/tokens package built for this exact product ("branch staff
   count stock, franchise owners watch branches, HQ runs campaigns and
   reviews submissions"). This app is FastAPI+Jinja2+vanilla CSS, so the
   React component bundle isn't usable directly; what's ported here is the
   package's token layer (`project/tokens.css`) remapped onto THIS file's
   existing variable names, so every rule in style.css/yoku-one.css/
   admin.css re-themes with zero template edits — same trick the Harbor
   Mist swap this replaces used.

   Semantic mapping (this system's 3-step surface ladder lines up almost
   exactly with One Platform's): --surface (page bg) = their surface-page;
   --surface-raised (cards) = their surface (white — "cards on a tinted
   page"); --surface-sunken (recessed-inside-a-card) = their surface-sunken.
   Their `aqua-600` (a secondary UI-strength hue, "not for text") takes our
   --accent-500 fill-only role; their `seasonal` purple is a near 1:1 match
   for this app's one deliberate violet hue, so --violet-tint/--on-violet
   map onto it rather than being re-derived. Where the source gives only
   2 steps and this file wants 3-4 (--primary-50..300, --ink-tertiary),
   the nearest source step is reused — marked DERIVED, same pattern the
   Harbor Mist block used.

   Radius: One Platform's stated principle is "Nothing is square" — every
   container takes a radius token, escalating from 6 to 28px. Re-scaled
   (not copied 1:1) onto this file's existing 4-step ladder so nothing
   downstream needs a new class: xs 2→6, sm(default control) 4→12,
   md(cards) 6→16, lg(modals) 8→20. Genuinely rounder than the previous
   2/4/6/8 system — that IS the point of trying this direction. */
:root, [data-theme="light"] {
  --surface: #f1f5fb; /* One Platform surface-page — the tinted scroll background every card floats on. */
  --surface-sunken: #f7f9fd; /* Their surface-sunken — recessed areas inside a card: table headers, disabled fields. */
  --surface-raised: #ffffff; /* Their surface — cards, sheets, input fields are white on the tinted page. */
  --border: #e4ebf5; /* Hairline dividers/card outlines only — under 3:1, decorative. */
  --border-strong: #7e93b0; /* Controls that must be perceivable: inputs, selects, outline buttons. 3.1:1. */
  --ink: #0f1b2d; /* Primary text. 17.3:1+ on every surface step. */
  --ink-secondary: #5b6b82; /* Captions, helper text, secondary labels (their ink-muted). */
  --ink-tertiary: #5f7089; /* Their ink-subtle — placeholders, inactive labels; the lightest tone that still reads. */
  --primary-50: #f4f8ff; /* Their brand-050 — faintest tint (info-note bg, selected row). */
  --primary-100: #e8f1fe; /* Their brand-100 — hover bg for ghost/tertiary buttons and chips, icon-tile fill. */
  --primary-200: #e8f1fe; /* DERIVED — source has no 3rd tint step; reuses brand-100. */
  --primary-300: #e8f1fe; /* DERIVED — disabled primary-button fill. */
  --primary-500: #0d66f9; /* Their brand-600 — THE brand blue. Primary button, active tab, icon glyphs. 4.9:1 on white. */
  --primary-600: #0a4fc4; /* Their brand-700 — pressed state of brand-600. */
  --primary-700: #082f76; /* DERIVED — brand-700 darkened further; source stops at one pressed step. */
  --brand-deep: #0d66f9; /* Same value as primary-500 — kept as its own token, same reasoning as the previous spec. */
  --on-brand-deep: #ffffff;
  --on-primary: #ffffff;
  --logo-plate: #ffffff; /* Ground for third-party brand logos (dark ink, drawn for white) — stays white in dark mode. */
  --accent-100: #e3fbfa; /* DERIVED pale aqua tint — source gives no light tint step for aqua. */
  --aqua-400: #5ffff5; /* One Platform aqua-400 — the wordmark's second half (YOKU ONE / CS / จัดซื้อ) on the brand band, both themes. Bold large type on blue only. */
  --accent-500: #23c9c2; /* Their aqua-600 — chart series two, illustration accents. A FILL, never text, same rule as the previous spec's gold. */
  --accent-700: #0f1b2d; /* = ink, following the same "soft tint carries ink" rule as before. */
  --focus: #0d66f9; /* Their focus-ring = brand-600 in light mode. 2px solid, 2px offset. */
  --brand-text: #0a52cc; /* Their brand-text: blue TEXT and links (6.79:1 on white). primary-500 is a fill — as small text in dark mode it fails 4.5:1. */
  --success: #0f7a4a; /* Their success — the ปกติ state. 4.8:1 on success-surface. */
  --success-tint: #e6f6ee;
  /* Status-pill words (Kuang + the COO's mockup, 2026-10-02): the Pill Contrast Rule.
     A short bold status word on its own tint may sit at 2.5:1 or more; everything
     else (sentences, dates, numbers, captions) keeps 4.5:1 and uses --on-* below.
     Vivid like the mockup, each solved to its ratio on its tint:
     success 2.8:1, warning 2.6:1 (the mockup's 2.1 was under the floor), danger
     3.4:1, info ~2.8:1. Pills only: never body text. */
  --pill-success: #27a652;
  --pill-warning: #f2760a;
  --pill-danger: #f2392c;
  --pill-info: #12a399;
  --on-success: #0f7a4a; /* Already accessible on its own tint per the source; no separate darker step given. The most vivid green still 4.5:1 on its tint. */
  /* Status dots (2026-09-29, Kuang: brighter status pills): the 6px dot before a badge's word takes a
     BRIGHT shade of its hue, the word stays the readable one. Decorative, so under 3:1 is fine. */
  --success-dot: #22c55e;
  --danger-dot: #f04438;
  --info-dot: #23c9c2;
  --on-info: #0e7a72; /* Info badge text: deep teal, 4.8:1 on --accent-100 (was ink: aqua itself is 1.9:1). */
  --warning: #b45309; /* Warning text/icon/border — the ใกล้หมด, ด่วน, รอตรวจสอบ state. Vivid amber (Kuang, 2026-09-29; was the brown #8a5200): the most saturated amber still 4.6:1 on --warning-tint, 5.0:1 on white. */
  --warning-tint: #f9f4eb; /* The one warning yellow, every warning surface (Kuang's pick 2026-09-28; was #fff4e2, too saturated). */
  --warning-tint-hover: #f5eedc; /* Pointer hover on anything already --warning-tint (Kuang's pick 2026-09-29). */
  --on-warning: #b45309;
  --warning-dot: #fc8b1c; /* The status dot before a warning badge's word: the reference's bright orange. Decorative (the word carries the state), so it may sit under 3:1. */
  --danger: #c8231c; /* The หมด / ด่วนมาก state. Text/icon role: flips lighter in dark mode below. A purer red since 2026-09-29 (was #c0272d): 4.95:1 on --danger-tint, 5.7:1 on white. */
  --danger-tint: #fdeceb;
  --danger-tint-hover: color-mix(in srgb, var(--danger) 12%, var(--card)); /* Hover on a ด่วนมาก row; unchanged in light. */
  --on-danger: #c8231c;
  --danger-solid: #d92d20; /* Added 2026-09-25 (design audit): their danger-solid — notification count bubbles, badges,
     .btn-danger. Deliberately does NOT flip with the theme the way --danger does (dark-mode --danger is a pale salmon
     for text-on-surface legibility, which is unreadable as a fill with white text) — a fixed saturated red is the same
     "one solid state colour" role --success-solid already plays. */
  --on-danger-solid: #ffffff; /* Same in both themes — the source's own pairing. */
  --violet-tint: #f2ecfe; /* Their seasonal-surface — a near-exact match for this app's one violet hue. */
  --on-violet: #6d28d9; /* Their seasonal. */
}

/* Dark — One Platform ships this as a full counterpart, not a filter. */
[data-theme="dark"] {
  --surface: #0b1220;
  --surface-sunken: #0e1725;
  --surface-raised: #121c2b;
  --border: #223148;
  --border-strong: #56698a;
  --ink: #eaf0f8;
  --ink-secondary: #9dafc6;
  --ink-tertiary: #8093ac;
  --primary-50: #101c30;
  --primary-100: #13233c;
  --primary-200: #13233c;
  --primary-300: #13233c;
  --primary-500: #1a6ef7;
  --primary-600: #0a4fc4;
  --primary-700: #082f76; /* DERIVED, shared with light — source gives one pressed step per theme. */
  --brand-deep: #1a6ef7;
  --on-brand-deep: #ffffff;
  --on-primary: #ffffff;
  --logo-plate: #ffffff;
  --accent-100: #10302e; /* DERIVED dark aqua tint. */
  --accent-500: #2fd8d0;
  --accent-700: #eaf0f8; /* = ink dark. */
  --focus: #4d8dfb;
  --brand-text: #7cb0ff;
  --success: #5fd39b;
  --success-tint: #0f2a1f;
  --on-success: #5fd39b;
  --pill-success: #5fd39b; /* Dark pills keep their bright, high-contrast words. */
  --pill-warning: #f2b552;
  --pill-danger: #ff9089;
  --pill-info: #2fd8d0;
  --success-dot: #4ade80;
  --danger-dot: #ff7a70;
  --info-dot: #2fd8d0;
  --on-info: #2fd8d0; /* 8.0:1 on the dark aqua tint. */
  --warning: #f2b552;
  --warning-tint: #2b2010;
  --warning-tint-hover: color-mix(in srgb, var(--warning-tint) 90%, var(--warning)); /* ≈ #3f2f17 */
  --on-warning: #f2b552;
  --warning-dot: #f2b552;
  --danger: #ff9089;
  --danger-tint: #2e1617;
  --danger-tint-hover: color-mix(in srgb, var(--danger-tint) 88%, var(--danger)); /* ≈ #472525: the light-theme mix went grey on the dark card. */
  --on-danger: #ff9089;
  --danger-solid: #d92d20; /* Same value as light — deliberately fixed, see the light block's comment. */
  --on-danger-solid: #ffffff;
  --violet-tint: #241a3d;
  --on-violet: #b79cff;
}
:root {
  /* Brand colours (Kuang, 2026-10-02), sampled from each brand's own logo file.
     The same in both themes, like the logo itself. Only for naming a brand (the
     campaign brand chips), never for a state: a status keeps its own palette. */
  --brand-yoguruto: #fecc3f; /* the boy's hat */
  --on-brand-yoguruto: #050708; /* the logo's line black */
  --brand-beluga: #3d7e99; /* the cup's blue, a step deeper so white reads (Kuang's pick; the wordmark green read too dark, too near Nuts' navy) */
  --on-brand-beluga: #ffffff; /* 4.5:1 */
  --brand-nuts: #263678; /* the Nuts, YES! wordmark */
  --on-brand-nuts: #ffffff;
  /* Progress-bar fills (Kuang, 2026-10-02): the same light, vibrant set in both
     themes. The dark theme's green and amber, and the alert red between the
     light theme's dark red and the dark theme's pink. Fills only: the number and
     the level word beside every bar carry the meaning, never the colour alone. */
  --progress-low: #f04438;
  --progress-mid: #f2b552;
  --progress-high: #5fd39b;
  /* Derived blends, referenced from 3+ call sites each (form-field borders,
     icon chips) — defined once here rather than repeating the same
     color-mix() literal at every call site. Resolve lazily against
     whichever theme's --border-strong/--border/--primary-500/--card are
     active, same as any other var() reference. */
  --border-blend: color-mix(in srgb, var(--border-strong) 55%, var(--border) 45%);
  --icon-chip-bg: color-mix(in srgb, var(--primary-500) 55%, var(--card) 45%);
  --space-2: 2px; /* Icon-to-label gap inside a chip or inline tag — the tightest gap in the system. */
  --space-4: 4px; /* Gap between a table cell's stacked lines; icon-to-text gap in a compact list row; dense stat-tile internal padding. */
  --space-8: 8px; /* Vertical padding inside a compact list row or table cell; gap between a label and its control. */
  --space-12: 12px; /* Input and button padding; gap between fields in a form; horizontal padding of a stat tile on mobile. */
  --space-16: 16px; /* Card and panel padding; page gutter on mobile; gap between unrelated controls in a toolbar. */
  --space-24: 24px; /* Gap between grouped sections on a screen; card padding on tablet/desktop; gap between a heading and the content under it. */
  --space-32: 32px; /* Gap between major, unrelated blocks — a page's header and its content, one card group and the next. */
  --space-48: 48px; /* Top padding of a screen; empty-state and onboarding spacing — the most generous step, used sparingly. */
  --radius-xs: 6px; /* Checkboxes, switches, small tags and the inner corner of a nested control. */
  --radius-sm: 12px; /* Buttons, inputs, chips and list rows — the default control radius. */
  --radius-md: 16px; /* Cards, panels, dropdowns and popovers. */
  --radius-lg: 20px; /* Modals, sheets and any large surface — the largest radius in the system. */
  /* One typeface since 2026-10-01: Prompt (Thai + Latin), the COO's call. Headings and body
     are told apart by WEIGHT (body 400, titles 600, figures 700-800), not by family. Both
     variable names are historical (Mitr, then Inter / Noto Sans Thai); they are kept so no
     rule had to change, and now hold the same family. */
  --font-mitr: 'Prompt', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
  --font-noto-sans-thai: 'Prompt', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
  --text-Heading: 600 18px/1.5 var(--font-mitr); /* Headings, headers and any other highlighted text that needs attention — Prompt at 600 (weight, not family, sets it apart from body). */
  --text-body: 400 16px/1.5 var(--font-noto-sans-thai); /* Body copy, descriptions and small text — Prompt at 400. */
}
/* ---------------------------------------------------------------------
   Fleet base. These three rules are mandatory in every app that uses this
   system (DESIGN.md: The +2pt Root Rule, and the button font-family gotcha),
   and they are byte-identical everywhere — so they live in the ONE file the
   README says to copy as-is, instead of in prose each app has to remember.
   Each of them has already been forgotten once and shipped a real bug.
   This file loads after the app's own style.css, so these win. See also
   The Last-Wins Rule.
   --------------------------------------------------------------------- */

/* +2pt over the browser's 16px default. Almost every size in this system is
   rem-based, so this one line sets the whole app's reading size; an app that
   skips it renders ~14% smaller than its siblings. The body line is NOT
   optional — the shared style.css pins body to a literal 16px, not a rem, so
   body copy would stay small while every heading around it grew. */
html { font-size: calc(16px + 2pt); }
body {
  font-family: var(--font-noto-sans-thai);
  font-size: 1rem;
}

/* Form controls do not inherit body's font-family in any browser — they
   default to the platform UI font — so every button, input and select
   silently renders off-system until this is set. <a>-styled buttons never
   had the problem, which is exactly why it went unnoticed. */
button, input, select, textarea, optgroup { font-family: inherit; }

/* The Page Ladder: one width ladder for the whole fleet, held in a variable
   so a page and any fixed bar it owns share one value. Defined here; APPLIED
   per app, because it is opt-in by design — a long form page wants it, a
   login screen does not:
       .page { max-width: var(--page-max); }
   The console shell opts out with .page.page-app { max-width: none; },
   which wins on specificity with no !important. These steps are separate
   from the system's other breakpoints and coexist with them: 980px is the
   nav shell's posture change, 700/1000/1300px are column counts within a
   page. */
:root { --page-max: 480px; }
@media (min-width: 600px)  { :root { --page-max: 640px; } }
@media (min-width: 900px)  { :root { --page-max: 880px; } }
@media (min-width: 1200px) { :root { --page-max: 1080px; } }
