/* =====================================================================
   Kite design tokens · direction D "Giữ dây" · theme "Dịu sáng · có hồn" (default) + "Dịu tối" (dim)
   Rules: wind for moments, calm sky for work. Personality comes from shape, words and illustration,
   never from saturation or contrast.
   :root                 = light "có hồn" (default for admin, store, learn, hub)
   [data-theme="dim"]    = "Dịu tối", ADMIN ONLY, per-user preference (see DESIGN.md §2)
   --k-*    admin + shared tokens        --k-m-*  moment tokens (deep field, celebrations only)
   --brand-* buyer-facing store/learn/hub tokens (light only; each store may override)
   Contrast = WCAG 2.1, computed. Written as light / dim. AA text ≥ 4.5:1, UI/graphics ≥ 3:1.
   Body ink budget: 10–13:1. No pure white surfaces in admin, no pure white text in dim.
   ===================================================================== */
/* Nunito Sans (variable, wght axis, self-hosted, SIL OFL — packages/ui/src/fonts/LICENSE-OFL.txt):
   the Google Fonts @import this replaced was blocked outright by the
   checkout page's own style-src 'self' CSP (font-src falls back to
   default-src, which has no external host either) — self-hosting works
   under that CSP with no external request, ever, from any consumer of
   this file (Storybook, apps/web via Vite, the Hub checkout/admin pages,
   apps/landing), and never leaks a visitor's IP/UA to Google. Each
   consumer ships the three files below from its own origin (a relative
   url(), same directory the consumer's own copy of this file lives in —
   never a base64 data: URI: that would download every subset with every
   page load regardless of which characters the page actually uses,
   defeating the unicode-range split below and adding it to every app's
   own CSS payload, not just the Hub's). Ported from
   @fontsource-variable/nunito-sans@5.3.0 (wght.css), latin + latin-ext +
   vietnamese subsets only (this product has no cyrillic/greek copy) — a
   page pulls in only the subset(s) its own text actually needs via
   unicode-range, same as the original Google-hosted CSS: run
   `pnpm add -D @fontsource-variable/nunito-sans` in packages/ui to pull a
   newer version's files into packages/ui/src/fonts/ (then re-copy them to
   docs/design/fonts/ and apps/landing/assets/fonts/) to regenerate. */
@font-face {
  font-family: 'Nunito Sans';
  font-style: normal;
  font-display: swap;
  font-weight: 200 1000;
  src: url('./fonts/nunito-sans-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD;
}
@font-face {
  font-family: 'Nunito Sans';
  font-style: normal;
  font-display: swap;
  font-weight: 200 1000;
  src: url('./fonts/nunito-sans-latin-ext.woff2') format('woff2');
  unicode-range: U+0100-02BA,U+02BD-02C5,U+02C7-02CC,U+02CE-02D7,U+02DD-02FF,U+0304,U+0308,U+0329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF;
}
@font-face {
  font-family: 'Nunito Sans';
  font-style: normal;
  font-display: swap;
  font-weight: 200 1000;
  src: url('./fonts/nunito-sans-vietnamese.woff2') format('woff2');
  unicode-range: U+0102-0103,U+0110-0111,U+0128-0129,U+0168-0169,U+01A0-01A1,U+01AF-01B0,U+0300-0301,U+0303-0304,U+0308-0309,U+0323,U+0329,U+1EA0-1EF9,U+20AB;
}

:root{
  color-scheme:light;
  /* ---------- Surfaces ---------- */
  --k-canvas:#E5E8ED;      /* page background (cool, never cream) */
  --k-surface:#F0F2F5;     /* cards, tables, panels, sidebar · vs canvas 1.10:1 (gentle separation) */
  --k-zebra:#EBEEF2;       /* even table rows */
  --k-head:#E6E9EE;        /* table header, wells */
  --k-hover:#E8EBF0;       /* row / item hover */
  --k-select:#DFE4EB;      /* selected row, active nav item (near-neutral) */
  --k-raised:#F5F6F8;      /* inputs, menus: one step above surface (still not white) */
  --k-grain:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='180' height='180'><filter id='n'><feTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='2' stitchTiles='stitch'/><feColorMatrix values='0 0 0 0 .22  0 0 0 0 .27  0 0 0 0 .36  0 0 0 .05 0'/></filter><rect width='100%' height='100%' filter='url(%23n)'/></svg>");  /* ≤2% cool paper grain on canvas */

  /* ---------- Text ---------- */
  --k-ink:#243042;         /* body · 11.9:1 on surface · 10.9:1 on canvas · 10.4:1 on select */
  --k-ink-2:#3F4A5C;       /* secondary · 8.0:1 on surface */
  --k-muted:#4F596A;       /* labels, meta · 6.3:1 surface · 6.1:1 zebra */
  --k-line:#D9DEE6;        /* hairlines */
  --k-line-2:#C7CED8;      /* input and chip borders */

  /* ---------- Cobalt: low chroma, SMALL elements only ---------- */
  --k-cobalt:#3A5BA9;      /* primary button, active marks, focus, progress · on-cobalt text 6.5:1 */
  --k-cobalt-hover:#314E93;
  --k-on-cobalt:#FFFFFF;   /* text on primary button */
  --k-link:#34529E;        /* 6.6:1 on surface */
  --k-focus:#3A5BA9;

  /* ---------- Wing: the one accent. Kite mark + ONE key action per screen + danger ---------- */
  --k-wing:#B94328;        /* 4.8:1 on surface; white text on it 5.3:1 */
  --k-wing-hover:#A03A22;
  --k-on-wing:#FFFFFF;
  --k-danger-line:#B94328; /* outline of destructive buttons */

  /* ---------- Status: low-chroma tint + dark text; paid = dot + ink ---------- */
  --k-paid-dot:#4F9A76;                          /* graphic 3.0:1 on surface; label uses --k-ink */
  --k-wait-bg:#F1E8D3;   --k-wait:#6A5423;       /* 5.9:1 */
  --k-under-bg:#F2E1DB;  --k-under:#9A3D2A;      /* 5.4:1 · underpaid, error, "red state" */
  --k-over-bg:#E4E9F2;   --k-over:#34497A;       /* 7.2:1 · overpaid, info */
  --k-refund-bg:#E7EAEE; --k-refund:#444E5E;     /* 7.0:1 · refunded, neutral, draft */
  --k-ok-bg:#E3EEE7;     --k-ok:#2F6247;         /* 6.0:1 · success message */
  --k-warn-dot:#B08A2E;  --k-bad-dot:#B94328;    /* health dots */

  /* ---------- Personality: string, diamond, sky ---------- */
  --k-string:#8C9DBF;      /* decorative string lines (sidebar, dividers, hero line, bullets) · 2.4:1, non-essential */
  --k-string-strong:#2C4A8F; /* kite outline, hero numerals · 6.6:1 on hero sky */
  --k-cloud:#C2CBD9;       /* stroke-only clouds */
  --k-diamond:var(--k-string); --k-diamond-size:7px; --k-diamond-radius:1.5px;
  /* Time-of-day hero sky (top → bottom), low chroma. Select with data-daypart on the hero. */
  --k-sky-sang-top:#E4E9F2;  --k-sky-sang-bottom:#EEEDF0;   /* 05–10h  "Chào buổi sáng" */
  --k-sky-trua-top:#DCE5F1;  --k-sky-trua-bottom:#EDF1F6;   /* 10–14h  "Chào buổi trưa" */
  --k-sky-chieu-top:#DEE4EE; --k-sky-chieu-bottom:#ECEBEF;  /* 14–18h  "Chào buổi chiều" */
  --k-sky-toi-top:#D8DDE7;   --k-sky-toi-bottom:#E3E5EB;    /* 18–05h  "Chào buổi tối" */
  --k-hero-num:#2C4A8F;    /* hero numerals, weight 700 · 6.6:1 on sky */
  /* Chart */
  --k-bar:#CBD2DD; --k-bar-now:#8FA2C7; --k-bar-label:#4F596A; --k-bar-label-now:#243042;
  /* Toast + pressed chip */
  --k-toast-bg:#243042; --k-toast-ink:#F0F2F5;   /* 11.4:1 */
  --k-chip-on-bg:#243042; --k-chip-on-ink:#F0F2F5; --k-chip-on-count:#C7CED8;

  /* ---------- Gradients: neighbouring low-chroma values only (sky washes). Never a saturated sweep behind text. ---------- */
  --k-wash:var(--k-sky-chieu-top);  /* set per daypart on .k-main[data-daypart] */
  --k-grad-wash:linear-gradient(180deg,var(--k-wash) 0,color-mix(in srgb,var(--k-wash) 40%,transparent) 120px,transparent 240px);  /* canvas top wash; text over it ≥ 10.3:1 ink, 5.5:1 muted */
  --k-grad-side:linear-gradient(180deg,#F2F3F5 0%,#E9EDF3 100%);   /* sidebar paper → sky · ink 11.3:1, muted 6.0:1 at the darkest end */
  --k-grad-sky-mid:#E4E8F0;                                        /* 3rd stop of the hero sky */
  --k-grad-sky-glow:radial-gradient(240px 170px at 86% 28%,rgba(185,67,40,.05),transparent 70%);  /* wing-family horizon glow ≤ 6% near the kite */
  --k-grad-primary:linear-gradient(180deg,#4265B3 0%,#3A5BA9 55%,#34529C 100%);        /* white text 5.6:1 (lightest stop) → 7.4:1 */
  --k-grad-primary-hover:linear-gradient(180deg,#3A5BA9 0%,#314E93 60%,#2E4A8C 100%);  /* white text 6.5:1 → 8.5:1 */
  --k-grad-string-from:#7F93C2; --k-grad-string-to:#C4876F;       /* revenue string: muted cobalt → muted wing (decorative) */
  --k-grad-bar-now-top:#A3B3D3; --k-grad-bar-now-bottom:#7F93BE;  /* today bar, soft vertical */

  /* ---------- MOMENT: deep field, celebrations only (update done, Cất cánh done, first order of the day, learner/buyer moments) ---------- */
  --k-m-900:#132A66; --k-m-700:#1B3A8C; --k-m-500:#2B55B8;
  --k-m-field:linear-gradient(155deg,#132A66 0%,#1B3A8C 62%,#2B55B8 100%);
  --k-m-band:rgba(255,255,255,.06);
  --k-m-ink:#FFFFFF;       /* 13.5:1 on m-900 · 6.8:1 on m-500 (moments are brief; white allowed here) */
  --k-m-ink-2:#C8D4F0;     /* 6.96:1 on m-700 · 4.57:1 worst case on m-500 */
  --k-m-wing:#FF6A45;      /* graphics + large text on field · 4.77:1 on m-900 */
  --k-m-glass:rgba(255,255,255,.10); --k-m-glass-line:rgba(255,255,255,.22);

  /* ---------- Type · Nunito Sans only ---------- */
  --k-font:"Nunito Sans",system-ui,-apple-system,"Segoe UI",sans-serif;
  --k-mono:ui-monospace,SFMono-Regular,Menlo,monospace;
  --k-fs-11:11px; --k-fs-12:12px; --k-fs-13:13px; --k-fs-14:14px; --k-fs-15:15px; --k-fs-16:16px;
  --k-fs-18:18px; --k-fs-20:20px; --k-fs-24:24px; --k-fs-32:32px;
  --k-fs-title:30px; --k-w-title:900; --k-track-title:-.03em;   /* page titles only */
  --k-fs-hero-num:40px; --k-w-hero-num:700;                     /* sky hero numerals, max 3 */
  --k-fs-m-title:48px;     /* celebration titles (weight 900, deep field only) */
  --k-lh-tight:1.2; --k-lh:1.5; --k-lh-body:1.6;
  --k-w-regular:400; --k-w-semi:600; --k-w-bold:700; --k-w-heavy:800; --k-w-black:900;

  /* ---------- Spacing (4px base) ---------- */
  --k-s-1:4px; --k-s-2:8px; --k-s-3:12px; --k-s-4:16px; --k-s-5:20px; --k-s-6:24px; --k-s-7:28px; --k-s-8:32px; --k-s-10:40px; --k-s-12:48px;
  /* ---------- Radii ---------- */
  --k-r-xs:4px; --k-r-sm:8px; --k-r-md:12px; --k-r-lg:20px; --k-r-xl:24px; --k-r-pill:999px;
  /* ---------- Elevation (work = hairlines, not shadows) ---------- */
  --k-sh-pop:0 8px 24px -8px rgba(15,23,41,.18),0 0 0 1px rgba(15,23,41,.06);
  --k-sh-dialog:0 40px 80px -30px rgba(10,20,50,.45);
  --k-scrim:rgba(20,28,42,.40);
  /* ---------- Layout ---------- */
  --k-sidebar:232px; --k-topbar:56px; --k-panel:360px;
  --k-row:40px; --k-row-head:36px; --k-control:40px; --k-hit:44px; --k-hero-slim:64px; --k-content-max:1200px;
  /* ---------- Motion ---------- */
  --k-dur-fast:120ms; --k-dur:200ms; --k-dur-slow:320ms; --k-dur-celebrate:1600ms;
  --k-ease:cubic-bezier(.2,0,0,1); --k-ease-lift:cubic-bezier(.2,.8,.2,1);
  /* ---------- Focus ---------- */
  --k-ring-w:3px; --k-ring-offset:2px; --k-ring-color:var(--k-focus); --k-ring-on-field:#FFFFFF;

  /* ---------- Buyer brand (store / learn / hub). Light only (no dim yet). Soft "có hồn" defaults.
     A store overrides --brand-primary / -on-primary / -accent / -deep / -font / -radius; contrast is checked at save
     (primary vs on-primary ≥ 4.5:1, measured at the LIGHTEST stop of --brand-grad-primary). ---------- */
  --brand-primary:#3A5BA9;             /* low-chroma cobalt · white text 6.5:1 (flat), ≥ 5.3:1 at the gradient's light stop */
  --brand-on-primary:#FFFFFF;
  --brand-accent:#B94328;              /* sale price, "Bán chạy" · 5.0:1 on surface */
  --brand-deep:#132A66;                /* logo tile + buyer MOMENTS only (paid, certificate, purchase success) */
  --brand-font:var(--k-font);
  --brand-radius:12px;
  /* soft surfaces (not overridable per store: comfort is a platform promise) */
  --brand-page:#EEF1F4;                /* page background · ink 11.8:1, muted 6.2:1 */
  --brand-surface:#F6F7F9;             /* cards, header, lesson reader, certificate paper · ink 12.4:1 */
  --brand-raised:#F8F9FB;              /* inputs, secondary buttons · ink 12.7:1 */
  --brand-ink:#243042; --brand-ink-2:#3F4A5C; --brand-muted:#4F596A;   /* 12.4 / 7.9 / 6.6 :1 on surface */
  --brand-line:#DCE1E8; --brand-line-2:#C9D0DA;
  --brand-link:#34529E;                /* 6.9:1 */
  --brand-qr-bg:#FFFFFF;               /* QR tiles stay pure white + black for scanners (the one allowed white) */
  /* buyer gradients follow DESIGN.md "Gradient": neighbouring low-chroma values only */
  --brand-grad-wash:linear-gradient(180deg,#E2E8F1 0,rgba(226,232,241,.4) 130px,transparent 260px);  /* top-of-page sky wash · ink 10.8:1 at the top */
  --brand-grad-primary:linear-gradient(180deg,color-mix(in srgb,var(--brand-primary) 90%,#fff) 0%,var(--brand-primary) 55%,color-mix(in srgb,var(--brand-primary) 88%,#000) 100%);
}

/* =====================================================================
   "Dịu tối" (dim). Admin only: set data-theme="dim" on <html> of admin pages.
   Charcoal, not black; no pure white text; cobalt desaturated; primary uses dark text.
   ===================================================================== */
[data-theme="dim"]{
  color-scheme:dark;
  --k-canvas:#151A21; --k-surface:#1C222B; --k-zebra:#1F2630; --k-head:#212833; --k-hover:#232B36; --k-select:#27303C; --k-raised:#222933;
  --k-grain:none;
  --k-ink:#D5DCE6;         /* 11.6:1 on surface · 12.7:1 on canvas · 9.7:1 on select */
  --k-ink-2:#B3BCC9;       /* 8.3:1 */
  --k-muted:#99A3B3;       /* 6.3:1 surface · 6.0:1 zebra */
  --k-line:#2A323D; --k-line-2:#36404D;
  --k-cobalt:#7C97D6; --k-cobalt-hover:#8DA5DD; --k-on-cobalt:#0F141B;   /* 6.4:1 */
  --k-link:#93A9DE;        /* 6.8:1 */
  --k-focus:#7C97D6;
  --k-wing:#E07A5F; --k-wing-hover:#E88D75; --k-on-wing:#1A1210;          /* wing 5.4:1 on surface */
  --k-danger-line:#E07A5F;
  --k-paid-dot:#5FAE88;    /* 6.0:1 */
  --k-wait-bg:#3A3222;   --k-wait:#E3C58A;       /* 7.6:1 */
  --k-under-bg:#3D2724;  --k-under:#EAA394;      /* 6.7:1 */
  --k-over-bg:#252F42;   --k-over:#A9BCE6;       /* 7.1:1 */
  --k-refund-bg:#2A303A; --k-refund:#B9C1CD;     /* 7.3:1 */
  --k-ok-bg:#1F3329;     --k-ok:#9CCFB2;         /* 7.7:1 */
  --k-warn-dot:#D9B25E;  --k-bad-dot:#E07A5F;
  --k-string:#6B7FA8;    /* 4.0:1 */
  --k-string-strong:#A9BCE6;
  --k-cloud:#394457;
  --k-sky-sang-top:#212A37;  --k-sky-sang-bottom:#1E232C;
  --k-sky-trua-top:#1F2936;  --k-sky-trua-bottom:#1C232D;
  --k-sky-chieu-top:#212836; --k-sky-chieu-bottom:#1E222B;
  --k-sky-toi-top:#1B212B;   --k-sky-toi-bottom:#191E26;
  --k-hero-num:#A9BCE6;    /* 7.9:1 */
  --k-bar:#2F3845; --k-bar-now:#5C73A8; --k-bar-label:#99A3B3; --k-bar-label-now:#D5DCE6;
  --k-toast-bg:#2A3340; --k-toast-ink:#D5DCE6;   /* 9.2:1 */
  --k-chip-on-bg:#D5DCE6; --k-chip-on-ink:#151A21; --k-chip-on-count:#3A4352;
  --k-grad-side:linear-gradient(180deg,#1E242D 0%,#1A2029 100%);  /* ink 11.9:1 at the darker end */
  --k-grad-sky-mid:#1F2531;
  --k-grad-sky-glow:radial-gradient(240px 170px at 86% 28%,rgba(224,122,95,.05),transparent 70%);
  --k-grad-primary:linear-gradient(180deg,#94ACE2 0%,#7C97D6 55%,#7290D0 100%);        /* dark text 8.2:1 → 5.8:1 */
  --k-grad-primary-hover:linear-gradient(180deg,#A0B6E6 0%,#8DA5DD 60%,#86A0DC 100%);
  --k-grad-string-from:#6B7FA8; --k-grad-string-to:#B07563;
  --k-grad-bar-now-top:#6A80B3; --k-grad-bar-now-bottom:#52689C;
  --k-sh-pop:0 8px 24px -8px rgba(0,0,0,.55),0 0 0 1px rgba(255,255,255,.04);
  --k-sh-dialog:0 40px 80px -30px rgba(0,0,0,.7);
  --k-scrim:rgba(5,8,12,.6);
  --k-ring-color:var(--k-focus);
}
