/* ═══════════════════════════════════════════════════════════════════
   Pasarguard Shop v2  —  app.css   (REDESIGN drop-in)
   Tokens · Base · Layout · Responsive · Legacy aliases
   Load order is load-bearing:  app.css  ▸  glass.css
   ═══════════════════════════════════════════════════════════════════ */

/* ── §1  Webfont (Vazirmatn) — self-hosted (A-I) ───────────────────────
   Operators in the deployment market (Iran) commonly cannot reach Google's
   CDN, so the previous render-blocking @import left users permanently on
   Tahoma. Self-host the woff2 files under assets/fonts/ so the font loads
   from the same origin. font-display: swap means text paints with the
   Tahoma fallback immediately and reflows once the woff2 arrives. If the
   files aren't present (fresh checkout), the fallback chain still works —
   it just doesn't pick up Vazirmatn's Persian metrics until ops drops the
   binaries in. See assets/fonts/README.md for the download recipe. */
@font-face{
  font-family: 'Vazirmatn';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('/assets/fonts/Vazirmatn-Regular.woff2') format('woff2');
}
@font-face{
  font-family: 'Vazirmatn';
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url('/assets/fonts/Vazirmatn-Medium.woff2') format('woff2');
}
@font-face{
  font-family: 'Vazirmatn';
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url('/assets/fonts/Vazirmatn-SemiBold.woff2') format('woff2');
}
@font-face{
  font-family: 'Vazirmatn';
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url('/assets/fonts/Vazirmatn-Bold.woff2') format('woff2');
}
@font-face{
  font-family: 'Vazirmatn';
  font-style: normal;
  font-weight: 800;
  font-display: swap;
  src: url('/assets/fonts/Vazirmatn-ExtraBold.woff2') format('woff2');
}

/* ──────────────────────────────────────────────────────────────────
   §2  THEME TOKENS — 34 design systems, one mapping.
       Palettes ported from vibefarsi.ir/themes/<slug> (the curated thirty-three)
       and from §16 of the operator's reference document (one `daisy-*` survivor).
       Every value is a literal converted from that theme's own `oklch()`
       tokens; the source token is quoted on each palette block so a future
       edit can be re-derived instead of guessed. The oklch→sRGB conversion
       and the AA tuning are asserted by bin/test_theme_systems.php, which
       recomputes the contrast of every pair below from this file.

       THE `daisy-*` BLOCKS ARE A BULK IMPORT AND ARE MEANT TO BE PRUNABLE.
       They arrived on an explicit brief («همه رو اضافه کن تا بعد من بررسی کنم
       و بگم کدوما دلیت بشن»), so deleting one is expected: remove its entry
       from lib/Theme.php::SYSTEMS and its block here, and nothing else. The
       test suite fails if the two lists ever disagree, which is what makes a
       hand-prune safe. Their provenance is in each block's own comment.
       Thirty-five of them arrived; thirty-four have gone.

       THREE LAYERS, one job each:
         §2.0  scales   — type, spacing, motion, layout. Radii are NOT here:
                          they are part of a design system, so they come
                          from --p-radius in §2.2.
         §2.1  palettes — one block per system, primitives only (--p-*). No
                          component rule reads a --p-* name.
         §2.2  mapping  — the ONE place a --p-* becomes a token a component
                          consumes (--bg, --card, --border, --text, …).

       TWO ATTRIBUTES, and this is the part to get right:
         data-theme = "dark" | "light"  — POLARITY. Carries the ~220
                      polarity overrides in glass.css and the `color-scheme`
                      that drives native controls. Never a theme name.
         data-sys   = the design-system slug.
       vibefarsi applies its themes with `data-theme="<slug>"`; here that
       attribute already means polarity and glass.css keys off it, so the
       slug rides on data-sys. Both are written by the same bootstrap in
       <head> (theme_bootstrap() in config.php), from the admin's per-
       polarity choice, before first paint.
       Every system therefore resolves to the data-theme of its own polarity.
       A palette matching a polarity its system does not have is a bug, and
       bin/test_theme_systems.php fails on it.

       ORDER IS LOAD-BEARING in §2.1: the dark base rule matches EVERY dark
       system and the light base every light one, so each system's own block
       comes after its polarity's base and overrides only what it changes.
       Same specificity, later wins. A block placed BEFORE its base is a
       block that does nothing.
       ────────────────────────────────────────────────────────────── */

/* ── §2.0  Scales — the same numbers in every system ────────────────── */
:root {
  /* Type scale */
  --fs-1:  0.82rem;
  --fs-2:  0.95rem;
  --fs-3:  1.05rem;
  --fs-4:  1.2rem;
  --fs-5:  1.5rem;
  --fs-6:  1.85rem;
  --fs-hero: 2.6rem;

  /* Spacing scale */
  --sp-1:  4px;
  --sp-2:  8px;
  --sp-3:  12px;
  --sp-3-5: 14px;
  --sp-4:  16px;
  --sp-4-5: 18px;
  --sp-5:  20px;
  --sp-6:  24px;
  --sp-7:  32px;
  --sp-8:  48px;

  /* Radii — from the system's own `--radius` (its card radius), scaled
     proportionally. Every value is computed at use time, so a palette only has
     to declare `--p-radius` and nothing here needs keeping in sync. The span
     runs from lapis's 6px (meant to be sharp, so --r-1 keeps a 4px floor) to
     twitter's 18px; the comment here used to calibrate the ladder against
     pomegranate's 16px, which was pruned 2026-09-23. */
  --r-1:  max(4px, calc(var(--p-radius) * 0.5));
  --r-2:  calc(var(--p-radius) * 0.75);
  --r-3:  var(--p-radius);
  --r-4:  calc(var(--p-radius) * 1.25);
  --r-5:  calc(var(--p-radius) * 1.5);
  --r-full: 999px;
  --r:    var(--r-3);   /* legacy alias */
  --r-sm: var(--r-1);

  /* Motion */
  --ease:      cubic-bezier(.2,.7,.2,1);
  --ease-out:  cubic-bezier(.16,1,.3,1);
  --dur-1:     120ms;
  --dur-2:     220ms;
  --dur-3:     380ms;

  /* Layout */
  --mob-nav-h:        68px;
  --container-max:    1200px;
  --gutter:           16px;
}

/* ── §2.1  Palettes ─────────────────────────────────────────────────── */

/* graphite — گرافیت, the dark default. oklch: bg .115/.002/285,
   card .14, muted .175, popover .16, fg .975, muted-fg .63, brand .8/.165/65,
   ring .7, primary .975, radius 10px.
   "Near-black background, near-white text, primary button white with black
   text. Borders white at 8%, one amber brand accent for small highlights." */
html[data-theme="dark"],
html[data-sys="graphite"] {
  color-scheme: dark;
  --p-bg:            #050506;
  --p-bg-deep:       #020202;
  --p-card:          #09090a;
  --p-muted:         #101011;
  --p-elev:          #0d0d0e;
  --p-nav:           #070708;
  --p-input-bg:      #060607;
  --p-border:        rgba(255,255,255,0.08);   /* the reference's own */
  --p-border-soft:   rgba(255,255,255,0.05);
  --p-input-border:  rgba(255,255,255,0.11);
  --p-blob-1-a:      0.20;
  --p-fg:            #f7f7f7;
  --p-fg-rgb:        247,247,247;
  --p-muted-fg:      #89898b;
  --p-text-soft:     #4b4b4d;
  --p-brand:         #ffa747;   /* amber — the one accent */
  --p-brand-rgb:     255,167,71;
  --p-brand-ink-rgb: 255,192,131;
  --p-on-brand:      #2c1400;   /* oklch(.22 .06 60) — label on a brand fill */
  --p-brand-2:       #ffbf80;
  --p-action:        #f7f7f7;   /* the white button */
  --p-on-action:     #1a1a1a;
  --p-ring:          #9e9e9e;
  --p-hover:         #161617;
  --p-radius:        10px;

  /* Polarity chrome — identical in all five dark systems, so it lives in
     the dark base and the alternates inherit it. */
  --p-soft-a:   0.16;   /* brand tint fills  */
  --p-strong-a: 0.42;   /* brand border edge */
  --p-glow-a:   0.35;
  --p-shadow-sm: 0 1px 3px rgba(0,0,0,0.30);
  --p-shadow:    0 10px 30px rgba(0,0,0,0.38);
  --p-shadow-lg: 0 24px 60px rgba(0,0,0,0.52);
  --p-success:         #2acc8a;      /* oklch(.75 .16 160) */
  --p-success-rgb:     42,204,138;
  --p-success-text-rgb: 88,237,169;
  --p-warn:            #fab72a;      /* oklch(.82 .16 80)  */
  --p-warn-rgb:        250,183,42;
  --p-warn-text-rgb:   255,224,173;
  --p-danger:          #f14d4c;      /* oklch(.65 .2 25)   */
  --p-danger-rgb:      241,77,76;
  --p-danger-text-rgb: 255,132,125;
  /* Ink for a SOLID --p-danger fill. White was 2.32–4.11:1 in twelve of the
     fourteen dark systems, so every one of them wants dark ink; #000000 clears
     4.54 (retro-arcade, the tightest) to 9.07 (catppuccin). See §2.2. */
  --p-on-danger:       #000000;
  --p-auth-card:    var(--p-card);   /* opaque: a translucent near-black over a
                                        near-black page is the same pixel */
  --p-auth-input:   rgba(0,0,0,0.35);   /* recessed field, never hue-tinted */
  --p-auth-glow:    0 28px 80px rgba(0,0,0,0.60);
  --p-blob-2-a:     0.14;
  --p-blob-3-a:     0.09;
}

/* paper — کاغذ, the light default. oklch: bg .985/.004/85, card 1/0/0,
   muted .955, fg .2/.01/60, muted-fg .47, brand .68/.17/55, ring .5,
   primary .2, radius 12px.
   "Warm paper background, ink-dark text and primary button. Borders ink at
   12%." Its brand is the one that needed the most tuning: oklch L .68 orange
   is 2.7:1 as link text on this background, so --p-brand is the same hue
   darkened to L .57 where it clears AA. */
html[data-theme="light"],
html[data-sys="paper"] {
  color-scheme: light;
  --p-bg:            #fbfaf7;
  --p-bg-deep:       #f0eeeb;
  --p-card:          #ffffff;
  --p-muted:         #f2f0ec;
  --p-elev:          #ffffff;
  --p-nav:           #fefcfa;
  --p-input-bg:      #ffffff;
  --p-border:        rgba(26,21,18,0.12);   /* the reference's own */
  --p-border-soft:   rgba(26,21,18,0.07);
  --p-input-border:  rgba(26,21,18,0.16);
  --p-blob-1-a:      0.12;
  --p-fg:            #1a1512;
  --p-fg-rgb:        26,21,18;
  --p-muted-fg:      #615953;
  --p-text-soft:     #9f9994;
  --p-brand:         #b05a00;   /* oklch(.68 .17 55) darkened to L .56 */
  --p-brand-rgb:     176,90,0;
  --p-brand-ink-rgb: 134,67,0;
  --p-on-brand:      #ffffff;
  --p-brand-2:       #9b4e00;
  --p-action:        #1a1512;   /* the ink button */
  --p-on-action:     #ffffff;
  --p-ring:          #6c6158;
  --p-hover:         #eeebe5;
  --p-radius:        12px;

  --p-soft-a:   0.12;
  --p-strong-a: 0.40;
  --p-glow-a:   0.14;
  --p-shadow-sm: 0 1px 2px rgba(30,40,70,0.05);
  --p-shadow:    0 6px 22px rgba(30,40,70,0.07);
  --p-shadow-lg: 0 18px 48px rgba(30,40,70,0.10);
  --p-success:         #008758;      /* oklch(.55 .15 160) */
  --p-success-rgb:     0,135,88;
  --p-success-text-rgb: 0,102,65;
  --p-warn:            #b45309;      /* R5-01: amber-brown primitive, ≥4.57:1 on all 9 light base inheritors */
  --p-warn-rgb:        180,83,9;
  --p-warn-text-rgb:   122,78,0;     /* R5-04: ≥6.55:1 text ink across light backgrounds */
  --p-danger:          #d73337;      /* oklch(.58 .2 25)   */
  --p-danger-rgb:      215,51,55;
  --p-danger-text-rgb: 178,0,27;
  /* The light half of the same rule, and it goes the other way: these danger
     fills are 4.35–5.44:1 under white ink and every dark candidate is worse.
     Four systems override it to #000000 where their own fill is brighter —
     see the palettes below. */
  --p-on-danger:       #ffffff;
  --p-auth-card:    rgba(255,255,255,0.92);   /* translucent on paper, opaque would
                                                 be invisible against the page */
  --p-auth-input:   #ffffff;
  /* R3-16: the light card floats on a light page — the drop shadow is a soft
     elevation cue, not a scrim. Black 0.60 here read as a bruise under white. */
  --p-auth-glow:    0 28px 80px rgba(15,18,30,0.18);
  --p-blob-2-a:     0.09;
  --p-blob-3-a:     0.06;
}

/* lapis — لاجورد. oklch: bg .13/.03/275, card .165, muted .2, popover .19,
   fg .97, muted-fg .72, brand .8/.12/255, ring .7/.16/275, primary .7/.16/275,
   radius 6px. "Dark indigo, 6px radius, precise and technical."
   Its primary clears white text only at L .59 (blue-violet holds up under
   darkening), so --p-action is oklch(.59 .16 275). */
html[data-sys="lapis"] {
  --p-bg:            #050613;
  --p-bg-deep:       #02020b;
  --p-card:          #0a0d1d;
  --p-muted:         #111526;
  --p-elev:          #0f1223;
  --p-nav:           #070917;
  --p-input-bg:      #060816;
  --p-border:        rgba(140,153,221,0.18);   /* the reference's own: oklch(.7 .1 275 / 18%) */
  --p-border-soft:   rgba(140,153,221,0.11);
  --p-input-border:  rgba(140,153,221,0.22);
  --p-fg:            #f3f5fc;
  --p-fg-rgb:        243,245,252;
  --p-muted-fg:      #9da3be;
  --p-text-soft:     #555a70;
  --p-brand:         #91c1ff;
  --p-brand-rgb:     145,193,255;
  --p-brand-ink-rgb: 174,209,255;
  --p-on-brand:      #050c1e;
  --p-brand-2:       #add1ff;
  --p-action:        #5f6cd5;
  --p-on-action:     #ffffff;
  --p-ring:          #8394ff;
  --p-hover:         #171b30;
  --p-radius:        6px;
}
/* saffron — زعفران. oklch: bg .14/.015/60, card .17, muted .21, popover .19,
   fg .97/.01/80, muted-fg .72/.04/70, brand .86/.14/85, ring .8/.15/75,
   primary .8/.15/75, radius 8px. "Warm background, gold button with dark
   brown text." The dark label is the reference's own choice and it clears
   AA comfortably — the gold never needed darkening. */
html[data-sys="saffron"] {
  --p-bg:            #0e0804;
  --p-bg-deep:       #070301;
  --p-card:          #160d07;
  --p-muted:         #21160c;
  --p-elev:          #1b120b;
  --p-nav:           #110b06;
  --p-input-bg:      #100a05;
  --p-border:        rgba(244,197,130,0.14);
  --p-border-soft:   rgba(244,197,130,0.08);
  --p-input-border:  rgba(244,197,130,0.18);
  --p-fg:            #f9f4ee;
  --p-fg-rgb:        249,244,238;
  --p-muted-fg:      #b5a18a;
  --p-text-soft:     #685a4b;
  --p-brand:         #fbc959;
  --p-brand-rgb:     251,201,89;
  --p-brand-ink-rgb: 251,215,141;
  --p-on-brand:      #221200;
  --p-brand-2:       #ffdd96;
  --p-action:        #f5ae39;
  --p-on-action:     #241a08;
  --p-ring:          #f5ae39;
  --p-hover:         #2a1c10;
  --p-radius:        8px;
}
/* claude — کلاود (Claude Espresso Dark). Warm dark espresso with terracotta accent. */
html[data-sys="claude"] {
  --p-bg:            #262624;
  --p-bg-deep:       #1b1b19;
  --p-card:          #30302e;
  --p-muted:         #1f1e1d;
  --p-elev:          #383835;
  --p-nav:           #21211f;
  --p-input-bg:      #21211f;
  --p-border:        rgba(250,249,245,0.12);
  --p-border-soft:   rgba(250,249,245,0.06);
  --p-input-border:  rgba(250,249,245,0.16);
  --p-blob-1-a:      0.18;
  --p-fg:            #faf9f5;
  --p-fg-rgb:        250,249,245;
  --p-muted-fg:      #b7b5a9;
  --p-text-soft:     #73726d;
  --p-brand:         #e07a5f;
  --p-brand-rgb:     224,122,95;
  --p-brand-ink-rgb: 240,154,130;
  --p-on-brand:      #140602;
  --p-brand-2:       #f09a82;
  --p-action:        #b84824;
  --p-on-action:     #ffffff;
  --p-ring:          #d97757;
  --p-hover:         #3a3a37;
  --p-radius:        8px;
  --p-success:       #2acc8a;
  --p-success-rgb:   42,204,138;
  --p-success-text-rgb: 88,237,169;
  --p-warn:          #fab72a;
  --p-warn-rgb:      250,183,42;
  --p-warn-text-rgb:   255,224,173;
  --p-danger:        #f14d4c;
  --p-danger-rgb:    241,77,76;
  --p-danger-text-rgb: 255,132,125;
}

/* twitter — توییتر / X (Twitter OLED Dark). Pure black OLED with iconic sky blue. */
html[data-sys="twitter"] {
  --p-bg:            #000000;
  --p-bg-deep:       #000000;
  --p-card:          #17181c;
  --p-muted:         #1e2024;
  --p-elev:          #202227;
  --p-nav:           #0f1012;
  --p-input-bg:      #121316;
  --p-border:        rgba(255,255,255,0.12);
  --p-border-soft:   rgba(255,255,255,0.06);
  --p-input-border:  rgba(255,255,255,0.16);
  --p-blob-1-a:      0.16;
  --p-fg:            #e7e9ea;
  --p-fg-rgb:        231,233,234;
  --p-muted-fg:      #8b98a5;
  --p-text-soft:     #536471;
  --p-brand:         #1c9cf0;
  --p-brand-rgb:     28,156,240;
  --p-brand-ink-rgb: 77,181,244;
  --p-on-brand:      #001b33;
  --p-brand-2:       #4db5f4;
  --p-action:        #0b7bc1;
  --p-on-action:     #ffffff;
  --p-ring:          #1d9bf0;
  --p-hover:         #24262b;
  --p-radius:        18px;
  --p-success:       #00ba7c;
  --p-success-rgb:   0,186,124;
  --p-success-text-rgb: 46,234,166;
  --p-warn:          #f7b928;
  --p-warn-rgb:      247,185,40;
  --p-warn-text-rgb:   255,214,120;
  --p-danger:        #f4212e;
  --p-danger-rgb:    244,33,46;
  --p-danger-text-rgb: 255,107,117;
}

/* vercel — ورسل (Vercel / Geist OLED Dark). Pure black OLED with monochrome precision & blue brand. */
html[data-sys="vercel"] {
  --p-bg:            #000000;
  --p-bg-deep:       #000000;
  --p-card:          #111111;
  --p-muted:         #1a1a1a;
  --p-elev:          #1c1c1c;
  --p-nav:           #0a0a0a;
  --p-input-bg:      #0c0c0c;
  --p-border:        rgba(255,255,255,0.14);
  --p-border-soft:   rgba(255,255,255,0.07);
  --p-input-border:  rgba(255,255,255,0.18);
  --p-blob-1-a:      0.16;
  --p-fg:            #ffffff;
  --p-fg-rgb:        255,255,255;
  --p-muted-fg:      #999999;
  --p-text-soft:     #555555;
  --p-brand:         #0070f3;
  --p-brand-rgb:     0,112,243;
  --p-brand-ink-rgb: 50,145,255;
  --p-on-brand:      #ffffff;
  --p-brand-2:       #3291ff;
  --p-action:        #ffffff;
  --p-on-action:     #000000;
  --p-ring:          #0070f3;
  --p-hover:         #222222;
  --p-radius:        8px;
  --p-success:       #0070f3;
  --p-success-rgb:   0,112,243;
  --p-success-text-rgb: 80,165,255;
  --p-warn:          #f5a623;
  --p-warn-rgb:      245,166,35;
  --p-warn-text-rgb:   255,200,110;
  --p-danger:        #ee0000;
  --p-danger-rgb:    238,0,0;
  --p-danger-text-rgb: 255,100,100;
}
/* nord — شفق قطبی. Arctic frost icy slate night. */
html[data-sys="nord"] {
  --p-bg:            #0c1017;
  --p-bg-deep:       #070a0f;
  --p-card:          #131822;
  --p-muted:         #1c2331;
  --p-elev:          #171e2b;
  --p-nav:           #0f141d;
  --p-input-bg:      #0e131b;
  --p-border:        rgba(136,192,208,0.16);
  --p-border-soft:   rgba(136,192,208,0.09);
  --p-input-border:  rgba(136,192,208,0.22);
  --p-fg:            #eceff4;
  --p-fg-rgb:        236,239,244;
  --p-muted-fg:      #98a8c0;
  --p-text-soft:     #576882;
  --p-brand:         #88c0d0;
  --p-brand-rgb:     136,192,208;
  --p-brand-ink-rgb: 163,213,226;
  --p-on-brand:      #091c28;
  --p-brand-2:       #a3d5e2;
  --p-action:        #43658e;
  --p-on-action:     #ffffff;
  --p-ring:          #88c0d0;
  --p-hover:         #232c3d;
  --p-radius:        8px;
}

/* dracula — دراکولا. Cyberpunk gothic synth pro. */
html[data-sys="dracula"] {
  --p-bg:            #0d0b14;
  --p-bg-deep:       #07050b;
  --p-card:          #151221;
  --p-muted:         #201c32;
  --p-elev:          #1b172a;
  --p-nav:           #100e19;
  --p-input-bg:      #0f0d17;
  --p-border:        rgba(189,147,249,0.18);
  --p-border-soft:   rgba(189,147,249,0.10);
  --p-input-border:  rgba(189,147,249,0.24);
  --p-fg:            #f8f8f2;
  --p-fg-rgb:        248,248,242;
  --p-muted-fg:      #b5accf;
  --p-text-soft:     #675d83;
  --p-brand:         #ff79c6;
  --p-brand-rgb:     255,121,198;
  --p-brand-ink-rgb: 255,146,208;
  --p-on-brand:      #280b1e;
  --p-brand-2:       #ff92d0;
  --p-action:        #bd93f9;
  --p-on-action:     #181228;
  --p-ring:          #bd93f9;
  --p-hover:         #2b2543;
  --p-radius:        10px;
}
/* catppuccin — کت‌پوچین موکا (Catppuccin Mocha Dark). Developer icon violet & lavender. */
html[data-sys="catppuccin"] {
  --p-bg:            #181825;
  --p-bg-deep:       #11111b;
  --p-card:          #1e1e2e;
  --p-muted:         #292c3c;
  --p-elev:          #313244;
  --p-nav:           #14141f;
  --p-input-bg:      #181825;
  --p-border:        rgba(205,214,244,0.14);
  --p-border-soft:   rgba(205,214,244,0.07);
  --p-input-border:  rgba(205,214,244,0.18);
  --p-blob-1-a:      0.16;
  --p-fg:            #cdd6f4;
  --p-fg-rgb:        205,214,244;
  --p-muted-fg:      #a6adc8;
  --p-text-soft:     #6c7086;
  --p-brand:         #cba6f7;
  --p-brand-rgb:     203,166,247;
  --p-brand-ink-rgb: 220,184,255;
  --p-on-brand:      #181825;
  --p-brand-2:       #dcb8ff;
  --p-action:        #cba6f7;
  --p-on-action:     #11111b;
  --p-ring:          #cba6f7;
  --p-hover:         #292a3e;
  --p-radius:        6px;
  --p-success:       #a6e3a1;
  --p-success-rgb:   166,227,161;
  --p-success-text-rgb: 198,245,194;
  --p-warn:          #f9e2af;
  --p-warn-rgb:      249,226,175;
  --p-warn-text-rgb:   255,238,200;
  --p-danger:        #f38ba8;
  --p-danger-rgb:    243,139,168;
  --p-danger-text-rgb: 255,178,199;
}

/* supabase — سوپابیس (Supabase Emerald Dark). Dark charcoal with vivid green. */
html[data-sys="supabase"] {
  --p-bg:            #121212;
  --p-bg-deep:       #0a0a0a;
  --p-card:          #171717;
  --p-muted:         #1f1f1f;
  --p-elev:          #242424;
  --p-nav:           #141414;
  --p-input-bg:      #141414;
  --p-border:        rgba(255,255,255,0.12);
  --p-border-soft:   rgba(255,255,255,0.06);
  --p-input-border:  rgba(255,255,255,0.16);
  --p-blob-1-a:      0.16;
  --p-fg:            #e2e8f0;
  --p-fg-rgb:        226,232,240;
  --p-muted-fg:      #a2a2a2;
  --p-text-soft:     #666666;
  --p-brand:         #3ecf8e;
  --p-brand-rgb:     62,207,142;
  --p-brand-ink-rgb: 110,231,183;
  --p-on-brand:      #022618;
  --p-brand-2:       #6ee7b7;
  --p-action:        #3ecf8e;
  --p-on-action:     #022618;
  --p-ring:          #3ecf8e;
  --p-hover:         #242424;
  --p-radius:        8px;
  --p-success:       #3ecf8e;
  --p-success-rgb:   62,207,142;
  --p-success-text-rgb: 110,231,183;
  --p-warn:          #fbbf24;
  --p-warn-rgb:      251,191,36;
  --p-warn-text-rgb:   255,214,110;
  --p-danger:        #f87171;
  --p-danger-rgb:    248,113,113;
  --p-danger-text-rgb: 255,160,160;
}

/* cosmic-night — شب کیهانی (Cosmic Night Indigo Dark). Deep night indigo with glowing purple. */
html[data-sys="cosmic-night"] {
  --p-bg:            #0f0f1a;
  --p-bg-deep:       #07070e;
  --p-card:          #1a1a2e;
  --p-muted:         #222244;
  --p-elev:          #252540;
  --p-nav:           #121222;
  --p-input-bg:      #121222;
  --p-border:        rgba(164,143,255,0.16);
  --p-border-soft:   rgba(164,143,255,0.08);
  --p-input-border:  rgba(164,143,255,0.22);
  --p-blob-1-a:      0.18;
  --p-fg:            #e2e2f5;
  --p-fg-rgb:        226,226,245;
  --p-muted-fg:      #a0a0c0;
  --p-text-soft:     #5e5e80;
  --p-brand:         #a48fff;
  --p-brand-rgb:     164,143,255;
  --p-brand-ink-rgb: 185,166,255;
  --p-on-brand:      #0f0f1a;
  --p-brand-2:       #b9a6ff;
  --p-action:        #a48fff;
  --p-on-action:     #0f0f1a;
  --p-ring:          #a48fff;
  --p-hover:         #282848;
  --p-radius:        8px;
  --p-success:       #4db6ac;
  --p-success-rgb:   77,182,172;
  --p-success-text-rgb: 140,225,217;
  --p-warn:          #ffb74d;
  --p-warn-rgb:      255,183,77;
  --p-warn-text-rgb:   255,214,140;
  --p-danger:        #ff5470;
  --p-danger-rgb:    255,84,112;
  --p-danger-text-rgb: 255,145,165;
}

/* amethyst-haze — مه ارغوانی (Amethyst Haze Dark). Hazy violet velvet. */
/* tangerine — تنگرین سرمه‌ای (Tangerine Navy Dark). Tech dark navy with electric orange. */
html[data-sys="tangerine"] {
  --p-bg:            #1c2433;
  --p-bg-deep:       #111722;
  --p-card:          #2a3040;
  --p-muted:         #343c4f;
  --p-elev:          #384257;
  --p-nav:           #1f2737;
  --p-input-bg:      #1c2433;
  --p-border:        rgba(255,255,255,0.12);
  --p-border-soft:   rgba(255,255,255,0.06);
  --p-input-border:  rgba(255,255,255,0.16);
  --p-blob-1-a:      0.16;
  --p-fg:            #e5e5e5;
  --p-fg-rgb:        229,229,229;
  --p-muted-fg:      #9cb0c6;
  --p-text-soft:     #63758b;
  --p-brand:         #f06e4b;
  --p-brand-rgb:     240,110,75;
  --p-brand-ink-rgb: 255,136,103;
  --p-on-brand:      #09101c;
  --p-brand-2:       #ff8867;
  --p-action:        #f06e4b;
  --p-on-action:     #09101c;
  --p-ring:          #f06e4b;
  --p-hover:         #384157;
  --p-radius:        12px;
  --p-success:       #34d399;
  --p-success-rgb:   52,211,153;
  --p-success-text-rgb: 110,231,183;
  --p-warn:          #fbbf24;
  --p-warn-rgb:      251,191,36;
  --p-warn-text-rgb:   255,214,110;
  --p-danger:        #ef4444;
  --p-danger-rgb:    239,68,68;
  --p-danger-text-rgb: 255,130,130;
}

/* caffeine — کافئین دارک (Caffeine Dark Roast). Deep dark espresso with caramel cream. */
html[data-sys="caffeine"] {
  --p-bg:            #111111;
  --p-bg-deep:       #080808;
  --p-card:          #191919;
  --p-muted:         #232323;
  --p-elev:          #282828;
  --p-nav:           #141414;
  --p-input-bg:      #141414;
  --p-border:        rgba(255,224,194,0.14);
  --p-border-soft:   rgba(255,224,194,0.07);
  --p-input-border:  rgba(255,224,194,0.18);
  --p-blob-1-a:      0.16;
  --p-fg:            #eeeeee;
  --p-fg-rgb:        238,238,238;
  --p-muted-fg:      #b4b4b4;
  --p-text-soft:     #666666;
  --p-brand:         #ffe0c2;
  --p-brand-rgb:     255,224,194;
  --p-brand-ink-rgb: 255,240,224;
  --p-on-brand:      #1a110a;
  --p-brand-2:       #fff0e0;
  --p-action:        #ffe0c2;
  --p-on-action:     #1a110a;
  --p-ring:          #ffe0c2;
  --p-hover:         #282828;
  --p-radius:        8px;
  --p-success:       #4ade80;
  --p-success-rgb:   74,222,128;
  --p-success-text-rgb: 134,239,172;
  --p-warn:          #fbbf24;
  --p-warn-rgb:      251,191,36;
  --p-warn-text-rgb:   255,214,110;
  --p-danger:        #e54d2e;
  --p-danger-rgb:    229,77,46;
  --p-danger-text-rgb: 255,140,120;
}

/* retro-arcade — رترو آرکید (Retro Arcade / Solarized Dark). Deep teal solarized with vibrant magenta. */
html[data-sys="retro-arcade"] {
  --p-bg:            #002b36;
  --p-bg-deep:       #001f27;
  --p-card:          #073642;
  --p-muted:         #0e4554;
  --p-elev:          #124f60;
  --p-nav:           #032f3c;
  --p-input-bg:      #032f3c;
  --p-border:        rgba(147,161,161,0.18);
  --p-border-soft:   rgba(147,161,161,0.09);
  --p-input-border:  rgba(147,161,161,0.24);
  --p-blob-1-a:      0.18;
  --p-fg:            #93a1a1;
  --p-fg-rgb:        147,161,161;
  --p-muted-fg:      #ffffff;   /* was #7ba2a8 — 3.79:1 on --p-muted, under AA.
                                   Its own --p-fg (#93a1a1) is 3.93 there and
                                   also fails, so the ink is white, not the
                                   body colour. */
  --p-text-soft:     #466269;
  --p-brand:         #f056a0;
  --p-brand-rgb:     240,86,160;
  --p-brand-ink-rgb: 255,121,184;
  --p-on-brand:      #002b36;
  --p-brand-2:       #ff79b8;
  --p-action:        #b51a66;
  --p-on-action:     #ffffff;
  --p-ring:          #f472b6;
  --p-hover:         #104d5e;
  --p-radius:        4px;
  --p-success:       #2aa198;
  --p-success-rgb:   42,161,152;
  --p-success-text-rgb: 90,215,205;
  --p-warn:          #b58900;
  --p-warn-rgb:      181,137,0;
  --p-warn-text-rgb:   235,190,50;
  --p-danger:        #dc322f;
  --p-danger-rgb:    220,50,47;
  --p-danger-text-rgb: 255,120,120;
}

/* claude-light — کلاود روشن (Claude Warm Paper Light). Ivory paper with warm terracotta. */
html[data-sys="claude-light"] {
  --p-bg:            #faf9f5;
  --p-bg-deep:       #efece3;
  --p-card:          #ffffff;
  --p-muted:         #f2efe6;
  --p-elev:          #ffffff;
  --p-nav:           #fbfaf7;
  --p-input-bg:      #ffffff;
  --p-border:        rgba(61,57,41,0.12);
  --p-border-soft:   rgba(61,57,41,0.06);
  --p-input-border:  rgba(61,57,41,0.16);
  --p-blob-1-a:      0.12;
  --p-fg:            #141413;
  --p-fg-rgb:        20,20,19;
  --p-muted-fg:      #6b6a65;
  --p-text-soft:     #9a9890;
  --p-brand:         #b54a2b;
  --p-brand-rgb:     181,74,43;
  --p-brand-ink-rgb: 145,53,27;
  --p-on-brand:      #ffffff;
  --p-brand-2:       #91351b;
  --p-action:        #b84824;
  --p-on-action:     #ffffff;
  --p-ring:          #b54a2b;
  --p-hover:         #ebe7dc;
  --p-radius:        8px;
  --p-success:       #008758;
  --p-success-rgb:   0,135,88;
  --p-success-text-rgb: 0,102,65;
  --p-warn:          #b45309;
  --p-warn-rgb:      180,83,9;
  --p-warn-text-rgb:   122,78,0;
  --p-danger:        #d73337;
  --p-danger-rgb:    215,51,55;
  --p-danger-text-rgb: 178,0,27;
}

/* twitter-light — توییتر روشن (Twitter Clear Sky Blue Light). Clean white with vibrant sky blue. */
html[data-sys="twitter-light"] {
  --p-bg:            #ffffff;
  --p-bg-deep:       #f0f3f4;
  --p-card:          #f7f8f8;
  --p-muted:         #eff2f4;
  --p-elev:          #ffffff;
  --p-nav:           #ffffff;
  --p-input-bg:      #ffffff;
  --p-border:        rgba(15,20,25,0.11);
  --p-border-soft:   rgba(15,20,25,0.06);
  --p-input-border:  rgba(15,20,25,0.15);
  --p-blob-1-a:      0.10;
  --p-fg:            #0f1419;
  --p-fg-rgb:        15,20,25;
  --p-muted-fg:      #536471;
  --p-text-soft:     #8b98a5;
  --p-brand:         #0c7abf;
  --p-brand-rgb:     12,122,191;
  --p-brand-ink-rgb: 9,92,144;
  --p-on-brand:      #ffffff;
  --p-brand-2:       #095c90;
  --p-action:        #0b7bc1;
  --p-on-action:     #ffffff;
  --p-ring:          #0a66a5;
  --p-hover:         #e7ecf0;
  --p-radius:        18px;
  --p-success:       #008758;
  --p-success-rgb:   0,135,88;
  --p-success-text-rgb: 0,110,72;
  --p-warn:          #b45309;
  --p-warn-rgb:      180,83,9;
  --p-warn-text-rgb:   141,95,0;
  --p-danger:        #f4212e;
  --p-danger-rgb:    244,33,46;
  --p-danger-text-rgb: 190,0,15;
  /* White on #f4212e is 4.11:1. */
  --p-on-danger:       #000000;   /* 5.10:1 */
}

/* vercel-light — ورسل روشن (Vercel Clean Slate Light). Pure clean white and black with Vercel blue. */
html[data-sys="vercel-light"] {
  --p-bg:            #fafafa;
  --p-bg-deep:       #eaeaea;
  --p-card:          #ffffff;
  --p-muted:         #f0f0f0;
  --p-elev:          #ffffff;
  --p-nav:           #ffffff;
  --p-input-bg:      #ffffff;
  --p-border:        rgba(0,0,0,0.10);
  --p-border-soft:   rgba(0,0,0,0.05);
  --p-input-border:  rgba(0,0,0,0.14);
  --p-blob-1-a:      0.10;
  --p-fg:            #000000;
  --p-fg-rgb:        0,0,0;
  --p-muted-fg:      #555555;
  --p-text-soft:     #888888;
  --p-brand:         #0060df;
  --p-brand-rgb:     0,96,223;
  --p-brand-ink-rgb: 0,71,171;
  --p-on-brand:      #ffffff;
  --p-brand-2:       #0047ab;
  --p-action:        #000000;
  --p-on-action:     #ffffff;
  --p-ring:          #0070f3;
  --p-hover:         #ebebeb;
  --p-radius:        8px;
  --p-success:       #0070f3;
  --p-success-rgb:   0,112,243;
  --p-success-text-rgb: 0,70,180;
  --p-warn:          #b45309;
  --p-warn-rgb:      180,83,9;
  --p-warn-text-rgb:   122,78,0;
  --p-danger:        #ee0000;
  --p-danger-rgb:    238,0,0;
  --p-danger-text-rgb: 190,0,0;
}

/* zinc — زینک. Modern cool slate neutral light. */
html[data-sys="zinc"] {
  --p-bg:            #f8fafc;
  --p-bg-deep:       #f1f5f9;
  --p-card:          #ffffff;
  --p-muted:         #f1f5f9;
  --p-elev:          #ffffff;
  --p-nav:           #ffffff;
  --p-input-bg:      #ffffff;
  --p-border:        rgba(15,23,42,0.11);
  --p-border-soft:   rgba(15,23,42,0.06);
  --p-input-border:  rgba(15,23,42,0.15);
  --p-fg:            #0f172a;
  --p-fg-rgb:        15,23,42;
  --p-muted-fg:      #475569;
  --p-text-soft:     #94a3b8;
  --p-brand:         #1d4ed8;
  --p-brand-rgb:     29,78,216;
  --p-brand-ink-rgb: 30,64,175;
  --p-on-brand:      #ffffff;
  --p-brand-2:       #1e40af;
  --p-action:        #0f172a;
  --p-on-action:     #ffffff;
  --p-ring:          #2563eb;
  --p-hover:         #e2e8f0;
  --p-radius:        8px;
}

/* rose — رز. Blush petal luxury light. */
html[data-sys="rose"] {
  --p-bg:            #fff5f7;
  --p-bg-deep:       #ffe4e9;
  --p-card:          #ffffff;
  --p-muted:         #ffe4e9;
  --p-elev:          #ffffff;
  --p-nav:           #fffbfa;
  --p-input-bg:      #ffffff;
  --p-border:        rgba(190,18,60,0.12);
  --p-border-soft:   rgba(190,18,60,0.07);
  --p-input-border:  rgba(190,18,60,0.16);
  --p-fg:            #1c0b11;
  --p-fg-rgb:        28,11,17;
  --p-muted-fg:      #5c4049;
  --p-text-soft:     #9f7d87;
  --p-brand:         #be123c;
  --p-brand-rgb:     190,18,60;
  --p-brand-ink-rgb: 159,18,57;
  --p-on-brand:      #ffffff;
  --p-brand-2:       #9f1239;
  --p-action:        #be123c;
  --p-on-action:     #ffffff;
  --p-ring:          #e11d48;
  --p-hover:         #fce7ec;
  --p-radius:        14px;
}

html[data-sys="emerald-light"] {
  --p-bg:            #f0fdf4;
  --p-bg-deep:       #dcfce7;
  --p-card:          #ffffff;
  --p-muted:         #dcfce7;
  --p-elev:          #ffffff;
  --p-nav:           #fafdfb;
  --p-input-bg:      #ffffff;
  --p-border:        rgba(4,120,87,0.12);
  --p-border-soft:   rgba(4,120,87,0.07);
  --p-input-border:  rgba(4,120,87,0.16);
  --p-fg:            #062316;
  --p-fg-rgb:        6,35,22;
  --p-muted-fg:      #355b4a;
  --p-text-soft:     #739886;
  --p-brand:         #047857;
  --p-brand-rgb:     4,120,87;
  --p-brand-ink-rgb: 6,95,70;
  --p-on-brand:      #ffffff;
  --p-brand-2:       #065f46;
  --p-action:        #047857;
  --p-on-action:     #ffffff;
  --p-ring:          #059669;
  --p-hover:         #d1fae5;
  --p-radius:        10px;
}
/* cobalt-light — کبالت. Stripe blue corporate light. */
html[data-sys="cobalt-light"] {
  --p-bg:            #f0f7ff;
  --p-bg-deep:       #e0effe;
  --p-card:          #ffffff;
  --p-muted:         #e0effe;
  --p-elev:          #ffffff;
  --p-nav:           #f8fbff;
  --p-input-bg:      #ffffff;
  --p-border:        rgba(29,78,216,0.12);
  --p-border-soft:   rgba(29,78,216,0.07);
  --p-input-border:  rgba(29,78,216,0.16);
  --p-fg:            #081b3d;
  --p-fg-rgb:        8,27,61;
  --p-muted-fg:      #384e72;
  --p-text-soft:     #7890b5;
  --p-brand:         #1d4ed8;
  --p-brand-rgb:     29,78,216;
  --p-brand-ink-rgb: 30,64,175;
  --p-on-brand:      #ffffff;
  --p-brand-2:       #1e40af;
  --p-action:        #1d4ed8;
  --p-on-action:     #ffffff;
  --p-ring:          #2563eb;
  --p-hover:         #dbeafe;
  --p-radius:        6px;
}

/* lavender-light — اسطوخودوس. Soft lilac & purple pastel light. */
html[data-sys="lavender-light"] {
  --p-bg:            #fbf7ff;
  --p-bg-deep:       #f3e8ff;
  --p-card:          #ffffff;
  --p-muted:         #f3e8ff;
  --p-elev:          #ffffff;
  --p-nav:           #fdfbfa;
  --p-input-bg:      #ffffff;
  --p-border:        rgba(109,40,217,0.12);
  --p-border-soft:   rgba(109,40,217,0.07);
  --p-input-border:  rgba(109,40,217,0.16);
  --p-fg:            #1e0e37;
  --p-fg-rgb:        30,14,55;
  --p-muted-fg:      #55426f;
  --p-text-soft:     #917dae;
  --p-brand:         #6d28d9;
  --p-brand-rgb:     109,40,217;
  --p-brand-ink-rgb: 91,33,182;
  --p-on-brand:      #ffffff;
  --p-brand-2:       #5b21b6;
  --p-action:        #6d28d9;
  --p-on-action:     #ffffff;
  --p-ring:          #7c3aed;
  --p-hover:         #ece0fd;
  --p-radius:        12px;
}

/* sunset-light — غروب. Warm terracotta tangerine energetic light. */
html[data-sys="sunset-light"] {
  --p-bg:            #fff7ed;
  --p-bg-deep:       #ffedd5;
  --p-card:          #ffffff;
  --p-muted:         #ffedd5;
  --p-elev:          #ffffff;
  --p-nav:           #fffaf5;
  --p-input-bg:      #ffffff;
  --p-border:        rgba(194,65,12,0.12);
  --p-border-soft:   rgba(194,65,12,0.07);
  --p-input-border:  rgba(194,65,12,0.16);
  --p-fg:            #2b1005;
  --p-fg-rgb:        43,16,5;
  --p-muted-fg:      #6b4938;
  --p-text-soft:     #a88470;
  --p-brand:         #c2410c;
  --p-brand-rgb:     194,65,12;
  --p-brand-ink-rgb: 154,52,18;
  --p-on-brand:      #ffffff;
  --p-brand-2:       #9a3412;
  --p-action:        #c2410c;
  --p-on-action:     #ffffff;
  --p-ring:          #9a3412;
  --p-hover:         #fed7aa;
  --p-radius:        10px;
}

html[data-sys="cyan-light"] {
  --p-bg:            #f0fdfa;
  --p-bg-deep:       #ccfbf1;
  --p-card:          #ffffff;
  --p-muted:         #ccfbf1;
  --p-elev:          #ffffff;
  --p-nav:           #f8fefd;
  --p-input-bg:      #ffffff;
  --p-border:        rgba(14,116,144,0.12);
  --p-border-soft:   rgba(14,116,144,0.07);
  --p-input-border:  rgba(14,116,144,0.16);
  --p-fg:            #042229;
  --p-fg-rgb:        4,34,41;
  --p-muted-fg:      #325761;
  --p-text-soft:     #6f99a4;
  --p-brand:         #0e7490;
  --p-brand-rgb:     14,116,144;
  --p-brand-ink-rgb: 21,94,117;
  --p-on-brand:      #ffffff;
  --p-brand-2:       #155e75;
  --p-action:        #0e7490;
  --p-on-action:     #ffffff;
  --p-ring:          #0891b2;
  --p-hover:         #bbf7d0;
  --p-radius:        12px;
}

/* minimal-gray — مینیمال. Swiss monochrome pure gray light. */
html[data-sys="minimal-gray"] {
  --p-bg:            #f4f4f5;
  --p-bg-deep:       #e4e4e7;
  --p-card:          #ffffff;
  --p-muted:         #e4e4e7;
  --p-elev:          #ffffff;
  --p-nav:           #fafafa;
  --p-input-bg:      #ffffff;
  --p-border:        rgba(24,24,27,0.12);
  --p-border-soft:   rgba(24,24,27,0.06);
  --p-input-border:  rgba(24,24,27,0.16);
  --p-fg:            #09090b;
  --p-fg-rgb:        9,9,11;
  --p-muted-fg:      #44444c;
  --p-text-soft:     #8e8e93;
  --p-brand:         #18181b;
  --p-brand-rgb:     24,24,27;
  --p-brand-ink-rgb: 9,9,11;
  --p-on-brand:      #ffffff;
  --p-brand-2:       #09090b;
  --p-action:        #18181b;
  --p-on-action:     #ffffff;
  --p-ring:          #27272a;
  --p-hover:         #d4d4d8;
  --p-radius:        6px;
}

/* catppuccin-light — کت‌پوچین لاته (Catppuccin Latte Light). Community pastel lavender milk. */
html[data-sys="catppuccin-light"] {
  --p-bg:            #eff1f5;
  --p-bg-deep:       #e6e9ef;
  --p-card:          #ffffff;
  --p-muted:         #dce0e8;
  --p-elev:          #ffffff;
  --p-nav:           #f5f7fa;
  --p-input-bg:      #ffffff;
  --p-border:        rgba(76,79,105,0.12);
  --p-border-soft:   rgba(76,79,105,0.06);
  --p-input-border:  rgba(76,79,105,0.16);
  --p-blob-1-a:      0.10;
  --p-fg:            #4c4f69;
  --p-fg-rgb:        76,79,105;
  --p-muted-fg:      #4c4f69;   /* was #65687e — 4.14:1 on --p-muted, under AA.
                                   The block's own --p-fg clears it at 6.03. */
  --p-text-soft:     #9ca0b0;
  --p-brand:         #6a1bcf;
  --p-brand-rgb:     106,27,207;
  --p-brand-ink-rgb: 85,20,170;
  --p-on-brand:      #ffffff;
  --p-brand-2:       #5c1dae;
  --p-action:        #6a1bcf;
  --p-on-action:     #ffffff;
  --p-ring:          #8839ef;
  --p-hover:         #e6e9ef;
  --p-radius:        6px;
  --p-success:       #34801f;
  --p-success-rgb:   52,128,31;
  --p-success-text-rgb: 40,110,25;
  --p-warn:          #b45309;
  --p-warn-rgb:      180,83,9;
  --p-warn-text-rgb:   155,90,0;
  --p-danger:        #d20f39;
  --p-danger-rgb:    210,15,57;
  --p-danger-text-rgb: 170,0,30;
}

html[data-sys="supabase-light"] {
  --p-bg:            #fcfcfc;
  --p-bg-deep:       #f1f1f1;
  --p-card:          #ffffff;
  --p-muted:         #ededed;
  --p-elev:          #ffffff;
  --p-nav:           #ffffff;
  --p-input-bg:      #ffffff;
  --p-border:        rgba(23,23,23,0.11);
  --p-border-soft:   rgba(23,23,23,0.06);
  --p-input-border:  rgba(23,23,23,0.15);
  --p-blob-1-a:      0.10;
  --p-fg:            #171717;
  --p-fg-rgb:        23,23,23;
  --p-muted-fg:      #525252;
  --p-text-soft:     #888888;
  --p-brand:         #006239;
  --p-brand-rgb:     0,98,57;
  --p-brand-ink-rgb: 0,76,44;
  --p-on-brand:      #ffffff;
  --p-brand-2:       #004c2c;
  --p-action:        #006239;
  --p-on-action:     #ffffff;
  --p-ring:          #047857;
  --p-hover:         #ededed;
  --p-radius:        8px;
  --p-success:       #006239;
  --p-success-rgb:   0,98,57;
  --p-success-text-rgb: 0,76,44;
  --p-warn:          #b45309;
  --p-warn-rgb:      180,83,9;
  --p-warn-text-rgb:   130,55,0;
  --p-danger:        #ca3214;
  --p-danger-rgb:    202,50,20;
  --p-danger-text-rgb: 160,30,5;
}

/* vintage-paper — کاغذ آنتیک (Vintage Paper / Antique Editorial Light). Rich editorial warm sepia. */
html[data-sys="vintage-paper"] {
  --p-bg:            #f5f1e6;
  --p-bg-deep:       #ebe3d2;
  --p-card:          #fffcf5;
  --p-muted:         #ece5d8;
  --p-elev:          #fffcf5;
  --p-nav:           #faf6eb;
  --p-input-bg:      #fffcf5;
  --p-border:        rgba(74,63,53,0.13);
  --p-border-soft:   rgba(74,63,53,0.07);
  --p-input-border:  rgba(74,63,53,0.18);
  --p-blob-1-a:      0.10;
  --p-fg:            #4a3f35;
  --p-fg-rgb:        74,63,53;
  --p-muted-fg:      #73604e;
  --p-text-soft:     #9f8a75;
  --p-brand:         #8c5d2e;
  --p-brand-rgb:     140,93,46;
  --p-brand-ink-rgb: 110,71,31;
  --p-on-brand:      #ffffff;
  --p-brand-2:       #6e471f;
  --p-action:        #8c5d2e;
  --p-on-action:     #ffffff;
  --p-ring:          #7a4a1f;
  --p-hover:         #ece5d8;
  --p-radius:        4px;
  --p-success:       #2e7d32;
  --p-success-rgb:   46,125,50;
  --p-success-text-rgb: 25,90,30;
  --p-warn:          #b45309;
  --p-warn-rgb:      180,83,9;
  --p-warn-text-rgb:   130,55,0;
  --p-danger:        #b54a35;
  --p-danger-rgb:    181,74,53;
  --p-danger-text-rgb: 145,45,25;
}

/* sage-garden — باغ مریم‌گلی (Sage Garden / Biophilic Light). Biophilic soothing sage green. */
html[data-sys="sage-garden"] {
  --p-bg:            #f8f7f4;
  --p-bg-deep:       #edebe4;
  --p-card:          #ffffff;
  --p-muted:         #e8e6e1;
  --p-elev:          #ffffff;
  --p-nav:           #fbfbfa;
  --p-input-bg:      #ffffff;
  --p-border:        rgba(26,31,46,0.11);
  --p-border-soft:   rgba(26,31,46,0.06);
  --p-input-border:  rgba(26,31,46,0.15);
  --p-blob-1-a:      0.10;
  --p-fg:            #1a1f2e;
  --p-fg-rgb:        26,31,46;
  --p-muted-fg:      #5a646c;
  --p-text-soft:     #8a959f;
  --p-brand:         #3c614b;
  --p-brand-rgb:     60,97,75;
  --p-brand-ink-rgb: 43,74,55;
  --p-on-brand:      #ffffff;
  --p-brand-2:       #2b4a37;
  --p-action:        #3c614b;
  --p-on-action:     #ffffff;
  --p-ring:          #5a836c;
  --p-hover:         #eae7e0;
  --p-radius:        6px;
  --p-success:       #3c614b;
  --p-success-rgb:   60,97,75;
  --p-success-text-rgb: 30,65,45;
  --p-warn:          #b45309;
  --p-warn-rgb:      180,83,9;
  --p-warn-text-rgb:   130,55,0;
  --p-danger:        #c73e3a;
  --p-danger-rgb:    199,62,58;
  --p-danger-text-rgb: 155,30,25;
}

/* amber-minimal — کهربای مینیمال (Amber Minimal / Golden Touch Light). Crisp white with golden amber touch. */
html[data-sys="amber-minimal"] {
  --p-bg:            #ffffff;
  --p-bg-deep:       #f3f4f6;
  --p-card:          #ffffff;
  --p-muted:         #f9fafb;
  --p-elev:          #ffffff;
  --p-nav:           #ffffff;
  --p-input-bg:      #ffffff;
  --p-border:        rgba(38,38,38,0.11);
  --p-border-soft:   rgba(38,38,38,0.06);
  --p-input-border:  rgba(38,38,38,0.15);
  --p-blob-1-a:      0.10;
  --p-fg:            #262626;
  --p-fg-rgb:        38,38,38;
  --p-muted-fg:      #6b7280;
  --p-text-soft:     #9ca3af;
  --p-brand:         #b45309;
  --p-brand-rgb:     180,83,9;
  --p-brand-ink-rgb: 146,64,14;
  --p-on-brand:      #ffffff;
  --p-brand-2:       #92400e;
  --p-action:        #b45309;
  --p-on-action:     #ffffff;
  --p-ring:          #92400e;
  --p-hover:         #fffbeb;
  --p-radius:        6px;
  --p-success:       #059669;
  --p-success-rgb:   5,150,105;
  --p-success-text-rgb: 4,115,80;
  --p-warn:          #b45309;
  --p-warn-rgb:      180,83,9;
  --p-warn-text-rgb:   130,55,0;
  --p-danger:        #dc2626;
  --p-danger-rgb:    220,38,38;
  --p-danger-text-rgb: 170,15,15;
}

/* notebook — دفترچه یادداشت (Notebook / Handcrafted Minimal Light). Minimal journal with sketch pencil borders. */
html[data-sys="notebook"] {
  --p-bg:            #f9f9f9;
  --p-bg-deep:       #eeeeee;
  --p-card:          #ffffff;
  --p-muted:         #e3e3e3;
  --p-elev:          #ffffff;
  --p-nav:           #fbfbfb;
  --p-input-bg:      #ffffff;
  --p-border:        rgba(116,114,114,0.22);
  --p-border-soft:   rgba(116,114,114,0.12);
  --p-input-border:  rgba(116,114,114,0.26);
  --p-blob-1-a:      0.10;
  --p-fg:            #3a3a3a;
  --p-fg-rgb:        58,58,58;
  --p-muted-fg:      #5c5c5c;
  --p-text-soft:     #8a8a8a;
  --p-brand:         #404040;
  --p-brand-rgb:     64,64,64;
  --p-brand-ink-rgb: 38,38,38;
  --p-on-brand:      #ffffff;
  --p-brand-2:       #262626;
  --p-action:        #404040;
  --p-on-action:     #ffffff;
  --p-ring:          #52525b;
  --p-hover:         #eaeaea;
  --p-radius:        10px;
  --p-success:       #2e7d32;
  --p-success-rgb:   46,125,50;
  --p-success-text-rgb: 25,90,30;
  --p-warn:          #b45309;
  --p-warn-rgb:      180,83,9;
  --p-warn-text-rgb:   130,55,0;
  --p-danger:        #c87a7a;
  --p-danger-rgb:    200,122,122;
  --p-danger-text-rgb: 155,70,70;
  /* White on #c87a7a is 3.22:1 — the worst in the set. */
  --p-on-danger:       #000000;   /* 6.52:1 */
}

/* tangerine-light — تنگرین سان‌لایت (Tangerine Sunlight Light). Crisp cool ground with appetizing tangerine. */
html[data-sys="tangerine-light"] {
  --p-bg:            #e8ebed;
  --p-bg-deep:       #dbe0e3;
  --p-card:          #ffffff;
  --p-muted:         #f4f5f7;
  --p-elev:          #ffffff;
  --p-nav:           #f2f4f6;
  --p-input-bg:      #ffffff;
  --p-border:        rgba(51,51,51,0.12);
  --p-border-soft:   rgba(51,51,51,0.06);
  --p-input-border:  rgba(51,51,51,0.16);
  --p-blob-1-a:      0.10;
  --p-fg:            #333333;
  --p-fg-rgb:        51,51,51;
  --p-muted-fg:      #525e68;
  --p-text-soft:     #84929d;
  --p-brand:         #ba3805;
  --p-brand-rgb:     186,56,5;
  --p-brand-ink-rgb: 145,40,2;
  --p-on-brand:      #ffffff;
  --p-brand-2:       #9a3412;
  --p-action:        #ba3805;
  --p-on-action:     #ffffff;
  --p-ring:          #9a3412;
  --p-hover:         #dfe3e6;
  --p-radius:        12px;
  --p-success:       #059669;
  --p-success-rgb:   5,150,105;
  --p-success-text-rgb: 4,115,80;
  --p-warn:          #b45309;
  --p-warn-rgb:      180,83,9;
  --p-warn-text-rgb:   130,55,0;
  --p-danger:        #ef4444;
  --p-danger-rgb:    239,68,68;
  --p-danger-text-rgb: 185,25,25;
  /* White on #ef4444 is 3.76:1. */
  --p-on-danger:       #000000;   /* 5.58:1 */
}
/* daisy-nord — §16.27 `daisy-nord` (light). Mapped from the source's
   base-100/200/300 + content model: base-100 is the page and base-200 the card in
   dark, and the pair is swapped in light so a card can sit ON the page. Brand and
   action are contrast-corrected to AA against --p-bg / --p-action — the source's
   raw primary is a FILL and is not legible as link text on its own page. */
html[data-sys="daisy-nord"] {
  color-scheme: light;
  --p-bg:            #e5e9f0;
  --p-bg-deep:       #d8dee9;
  --p-card:          #eceff4;
  --p-muted:         #d8dee9;
  --p-elev:          #eceff4;
  --p-nav:           #eceff4;
  --p-input-bg:      #eceff4;
  --p-border:        rgba(46,52,64,0.12);
  --p-border-soft:   rgba(46,52,64,0.06);
  --p-input-border:  rgba(46,52,64,0.18);
  --p-blob-1-a:      0.1;
  --p-fg:            #2e3440;
  --p-fg-rgb:        46,52,64;
  --p-muted-fg:      #2e3440;   /* was #63676f — 4.20:1 on --p-muted, under AA.
                                   The block's own --p-fg clears it at 9.25. */
  --p-text-soft:     #aaafb8;
  --p-brand:         #49688e;
  --p-brand-rgb:     73,104,142;
  --p-brand-ink-rgb: 45,66,96;
  --p-on-brand:      #ffffff;
  --p-brand-2:       #3c5574;
  --p-action:        #5e81ac;
  --p-on-action:     #03060b;
  --p-ring:          #3c5574;
  --p-hover:         #d8dee9;
  --p-radius:        8px;
  --p-success:       #5f7a3a;
  --p-success-rgb:   95,122,58;
  --p-success-text-rgb: 84,110,63;
  --p-warn:          #b45309;
  --p-warn-rgb:      180,83,9;
  --p-warn-text-rgb: 132,96,23;
  --p-danger:        #bf616a;
  --p-danger-rgb:    191,97,106;
  --p-danger-text-rgb: 172,70,80;
  /* White on #bf616a is 4.09:1. */
  --p-on-danger:       #000000;   /* 5.13:1 */
}

/* ── §2.2  The mapping — primitives become the tokens components read ──
   Custom properties resolve at USE time, so this can sit before the
   palettes without ordering risk: --bg here is a promise that --p-bg will
   have a value on this element by the time anything paints.

   Note the one place our semantics differ from the reference's, on purpose:
   vibefarsi's `--brand` is the hue and its `--primary` is the action fill
   (white in graphite, ink in paper). Our `--accent` is the ink — it is what
   `a{}`, badge text and focus tints use — and our `--primary` /
   `--accent-cta` are the fill. Both roles are mapped, one to each, so no
   colour has to serve as both a legible link and a filled button. That also
   retires the old hand-tuned `--accent-cta` override: the fill/label pair is
   now a property of the system, and AA for it is asserted per system. */
:root {
  /* Background layers */
  --bg:             var(--p-bg);
  --bg-deep:        var(--p-bg-deep);
  --bg-dark:        var(--p-bg);

  /* Surfaces */
  --surface:        var(--p-card);
  --surface-2:      var(--p-muted);
  --card:           var(--p-card);
  --card-soft:      var(--p-muted);
  --surface-solid:  var(--p-card);
  --glass-card-bg:  var(--p-card);
  --glass-elev-bg:  var(--p-elev);
  --glass-btn-bg:   var(--p-card);
  --glass-nav-bg:   var(--p-nav);
  --input-bg:       var(--p-input-bg);

  /* legacy aliases (older components still read these) */
  --surface-1:      var(--p-card);
  --surface-3:      var(--p-elev);
  --glass:          var(--p-card);
  --glass-b:        var(--p-muted);
  --glass-s:        var(--p-elev);
  --elevated:       var(--p-card);
  --card-bg:        var(--p-card);

  /* Borders. These two — and `--input` below — are the only tokens in §2 that
     fail WCAG SC 1.4.11 (the 3:1 non-text floor): measured 1.16–1.45 and
     1.24–1.67 across all 34 systems, uniformly, by design. Raising them is a
     product decision that visibly rewrites the design language, so they are
     REPORTED rather than asserted, and the decision is recorded open in
     docs/audit/theme-non-text-contrast-20260923.md. Do not "fix" one system. */
  --border:         var(--p-border);
  --border-soft:    var(--p-border-soft);
  --border-strong:  rgba(var(--p-brand-rgb), var(--p-strong-a));
  --border-b:       var(--border-strong);

  /* Text */
  --text:           var(--p-fg);
  --text-muted:     var(--p-muted-fg);
  --text-soft:      var(--p-text-soft);
  --text-m:         var(--p-muted-fg);
  --text-d:         var(--p-text-soft);

  /* Brand — two roles, see the note above */
  --primary:        var(--p-action);
  --accent:         var(--p-brand);
  --accent-soft:    rgba(var(--p-brand-rgb), var(--p-soft-a));
  --accent-rgb:     var(--p-brand-rgb);
  --accent-cta:     var(--p-action);
  /* --accent-2/-3 are read as TEXT and ICONS (a:hover, auth icons, the empty
     state), not as fills — so they stay in the brand's ink family. Mapping
     them to the action fill would have put lapis's #5f6cd5 on lapis's page
     at 2.5:1. */
  --accent-2:       var(--p-brand-2);
  --accent-3:       var(--p-brand);
  --accent2:        var(--p-brand-2);
  --accent3:        var(--p-brand);

  /* shadcn semantic set — the same names the palettes arrive in, so a
     vibefarsi theme (or a future seventh) drops in without a rename. */
  --background:              var(--p-bg);
  --foreground:              var(--p-fg);
  --card-foreground:         var(--p-fg);
  --popover:                 var(--p-elev);
  --popover-foreground:      var(--p-fg);
  --primary-foreground:      var(--p-on-action);
  --secondary:               var(--p-muted);
  /* `--secondary` is `--p-muted` — literally the same primitive — so its label
     is the same token. It was `--p-fg`, i.e. BODY ink on a muted chip, which is
     3.93:1 in retro-arcade (and is what `bots.php:1139` paints today by
     inheriting the body colour onto a `var(--muted)` block). */
  --secondary-foreground:    var(--p-muted-fg);
  --muted:                   var(--p-muted);
  --muted-foreground:        var(--p-muted-fg);
  --accent-foreground:       var(--p-on-brand);
  --hover:                   var(--p-hover);
  --destructive:             var(--p-danger);
  /* The last label token in this block to be a literal rather than a primitive.
     `#ffffff` cleared AA in only 18 of the 34 systems (2.32:1 in catppuccin,
     3.22 in notebook), and nothing consumed it — which is exactly how it stayed
     wrong. See `--p-on-danger` in each polarity base. */
  --destructive-foreground:  var(--p-on-danger);
  --warning:                 var(--p-warn);
  --ring:                    var(--p-ring);
  --input:                   var(--p-input-border);

  /* Status */
  --success:        var(--p-success);
  --warn:           var(--p-warn);
  --danger:         var(--p-danger);
  --ok:             var(--p-success);
  --err:            var(--p-danger);
  --success-rgb:        var(--p-success-rgb);
  --warn-rgb:           var(--p-warn-rgb);
  --danger-rgb:         var(--p-danger-rgb);
  --success-text-rgb:   var(--p-success-text-rgb);
  --warn-text-rgb:      var(--p-warn-text-rgb);
  --danger-text-rgb:    var(--p-danger-text-rgb);
  --accent-text-rgb:    var(--p-brand-ink-rgb);

  /* Effects */
  --neon:           0 0 22px rgba(var(--p-brand-rgb), var(--p-glow-a));
  --glow:           0 0 32px rgba(var(--p-brand-rgb), var(--p-glow-a));
  --shadow-sm:      var(--p-shadow-sm);
  --shadow:         var(--p-shadow);
  --shadow-lg:      var(--p-shadow-lg);

  /* Auth page — every tint is derived from the palette's own triplets, so
     the login page follows the chosen system instead of staying blue.
     (It used to carry its own literals, which is why a lapis or turquoise
     panel kept amber blobs behind a blue page: measured on the running
     page, not reasoned about.) */
  --auth-bg:                    var(--p-bg);
  --auth-blob1:                 rgba(var(--p-brand-rgb), var(--p-blob-1-a));
  --auth-blob2:                 rgba(var(--p-brand-rgb), var(--p-blob-2-a));
  --auth-blob3:                 rgba(var(--p-brand-rgb), var(--p-blob-3-a));
  --auth-card:                  var(--p-auth-card);
  --auth-card-border:           rgba(var(--p-brand-rgb), 0.10);
  --auth-card-glow:             0 0 0 1px rgba(var(--p-fg-rgb),0.05), var(--p-auth-glow);
  --auth-input:                 var(--p-auth-input);
  --auth-input-border:          rgba(var(--p-brand-rgb), 0.12);
  --auth-tabs-bg:               rgba(var(--p-fg-rgb), 0.05);
  --auth-tabs-border:           rgba(var(--p-fg-rgb), 0.08);
  --toggle-btn-bg:              rgba(var(--p-fg-rgb), 0.09);
}

/* ──────────────────────────────────────────────────────────────────
   §3  RESET & BASE
   ────────────────────────────────────────────────────────────────── */
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }

/* Global overflow-safety nets — fix mobile overflow bugs caused by
   long Persian numbers and inputs without min-width:0 on grid children. */
/* Commit 6 (#71): `overflow-x: hidden` makes html AND body scroll containers on
   BOTH axes (it computes overflow-y to `auto`). Any `position: sticky` descendant
   then resolves its scrollport to <body> — which never actually scrolls, since the
   document scrolls on <html> — so sticky silently degraded to static. `clip` does
   the same horizontal-spill clipping WITHOUT creating a scroll container, leaving
   overflow-y `visible` and sticky working. `hidden` stays first as the fallback
   for engines predating `clip` (Chrome <90 / Firefox <81 / Safari <16), which
   simply ignore the second declaration. */
html, body { max-width: 100%; overflow-x: hidden; overflow-x: clip; }
img, video, svg, canvas, iframe { max-width: 100%; height: auto; }
input, select, textarea, button { max-width: 100%; }

html {
  direction: rtl;
  font-size: 15px;
  -webkit-tap-highlight-color: transparent;
  /* iOS Safari inflates text when a page is rotated to landscape and the
     layout is narrower than the viewport — the "boost". It is applied PER
     BLOCK and unevenly, so a page whose type was measured at 15px/16px root
     renders at a different size in landscape than in portrait: the fixed
     bottom nav, the sticky impersonate bar and the table column widths are
     all computed for the portrait metrics and land wrong. `100%` (not `none`)
     pins the text to the declared size while still honouring the user's own
     browser text-size preference, which `none` would discard. The prefix is
     the only one any engine ever read; the unprefixed twin is for spec
     completeness and is inert today. */
  -webkit-text-size-adjust: 100%;
  text-size-adjust: 100%;
  scroll-behavior: smooth;
  /* M10 STAGE J — STABLE GUTTER. A page tall enough to scroll lost its
     scrollbar's width from `clientWidth`, a short page did not, and every
     `position:fixed` edge in the shell (the rail first) moved by that width
     between them: measured `rail.right` = 1430 on a tall page and 1440 on a
     short one at a 1440px viewport, i.e. the operator's "the sidebar is a bit
     wider on some pages". Reserving the gutter on the ROOT makes a scrollbar
     and no-scrollbar page report the same `clientWidth`, so the two agree.
     Present on both hosts' engines (Chrome 94+, Firefox 97+, Safari 18.2+);
     where it is ignored the declaration is inert and the old behaviour
     returns, which is why bin/test_one_measure.php asserts it is DECLARED
     here and on `.nav-rail` rather than measuring a browser. */
  scrollbar-gutter: stable;
}
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after { animation-duration: 1ms !important; transition-duration: 1ms !important; }
}

a, button, [role="button"] { touch-action: manipulation; }

body {
  font-family: 'Vazirmatn', 'Tahoma', 'Segoe UI', 'Roboto', sans-serif;
  background: var(--bg);
  color: var(--text);
  min-height: 100vh;
  line-height: 1.65;
  /* Phase 5 stage 3a: reserve the fixed bottom-nav height + the device safe-area
     inset + a 16px gap on the document, so content clears the nav on every page
     (incl. notched phones). The mobile-nav is 68px; env() is 0 off-notch. */
  padding-bottom: calc(var(--mob-nav-h) + env(safe-area-inset-bottom) + var(--sp-4));
  font-feature-settings: "ss01","cv11","liga","kern";
  font-variant-numeric: tabular-nums;
  transition: background var(--dur-2) var(--ease), color var(--dur-2) var(--ease);
}
body.auth-page { padding-bottom: 0; }

/* A-G: ambient background ::before lives in glass.css §50 — the
   declaration here is overridden because glass.css loads second.
   Removing the dead duplicate (incl. the light-theme override) avoids
   diverging-token drift between the two files. */

/* ──────────────────────────────────────────────────────────────────
   §4  SCROLLBAR
   ────────────────────────────────────────────────────────────────── */
/* Phase 5 stage 2: thin, muted scrollbar (was bright accent-blue, read as a
   UI accent). Neutral gray works in both themes. */
::-webkit-scrollbar       { width: 6px; height: 6px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-thumb { background: rgba(128,134,150,0.35); border-radius: var(--r-full); }
::-webkit-scrollbar-thumb:hover { background: rgba(128,134,150,0.55); }
* { scrollbar-width: thin; scrollbar-color: rgba(128,134,150,0.35) transparent; }

/* ──────────────────────────────────────────────────────────────────
   §5  TYPOGRAPHY
   ────────────────────────────────────────────────────────────────── */
h1, h2, h3, h4 { font-weight: 700; line-height: 1.3; color: var(--text); text-wrap: balance; }
h1 { font-size: var(--fs-6); }
h2 { font-size: var(--fs-4); }
h3 { font-size: var(--fs-3); }
h4 { font-size: var(--fs-2); }
p  { text-wrap: pretty; }
small, .text-small { font-size: var(--fs-1); color: var(--text-m); }

a  { color: var(--accent); text-decoration: none; transition: color var(--dur-1) var(--ease); }
a:hover { color: var(--accent-2); }

.mono, code, pre { font-family: ui-monospace, "JetBrains Mono", "SF Mono", Menlo, Consolas, monospace; }
[dir="ltr"] { unicode-bidi: isolate; }
.bdi-block { display: inline-flex; unicode-bidi: isolate; }

/* ──────────────────────────────────────────────────────────────────
   §6  LAYOUT WRAPS
   ────────────────────────────────────────────────────────────────── */
.wrap {
  max-width: var(--container-max);
  margin: 0 auto;
  padding: var(--sp-4) var(--gutter) var(--sp-5);  /* nav clearance now on body */
}
.wrap-narrow {
  max-width: 720px;
  margin: 0 auto;
  padding: var(--sp-4) var(--gutter) var(--sp-5);  /* nav clearance now on body */
}
.page-stack > * + * { margin-top: var(--sp-5); }

.row  { display: flex; gap: var(--sp-4); flex-wrap: wrap; }
.col  { flex: 1; min-width: 0; }

.grid-2 { display: grid; gap: var(--sp-3); grid-template-columns: repeat(2, minmax(0,1fr)); }
.grid-3 { display: grid; gap: var(--sp-3); grid-template-columns: repeat(2, minmax(0,1fr)); }
.grid-4 { display: grid; gap: var(--sp-3); grid-template-columns: repeat(2, minmax(0,1fr)); }
@media (min-width: 768px) {
  .grid-3 { grid-template-columns: repeat(3, minmax(0,1fr)); }
  .grid-4 { grid-template-columns: repeat(3, minmax(0,1fr)); }
}
@media (min-width: 1024px) {
  .grid-4 { grid-template-columns: repeat(4, minmax(0,1fr)); }
}

.mb-1 { margin-bottom: var(--sp-2); }
.mb-2 { margin-bottom: var(--sp-4); }
.mb-3 { margin-bottom: var(--sp-5); }
.mt-1 { margin-top: var(--sp-2); }
.mt-2 { margin-top: var(--sp-4); }
.mt-3 { margin-top: var(--sp-5); }

/* CSS-UTILS: ten pixel-named utilities (.mt-0/.mb-0/.m-0/.mt-12/.mb-12/.mt-14/
   .mb-14/.mt-18/.mb-18/.mt-20) sat here, staged for a style="margin-top:14px"
   -> class="mt-14" swap that never ran. Zero call sites; meanwhile the inline
   styles they were to absorb went 299 -> 493. Deleted. Add a utility in the
   same commit as its first call site, never ahead of one. */
.filter-field { min-width: 140px; }

/* Visibility helpers */
.md-up-only { display: none !important; }
.mobile-only { display: block !important; }
@media (min-width: 768px) {
  .md-up-only { display: revert !important; }
  .mobile-only { display: none !important; }
}
.md-hide { display: revert !important; }
@media (min-width: 768px) { .md-hide { display: none !important; } }

/* Visually-hidden for screen readers only */
.sr-only {
  position: absolute !important; width: 1px; height: 1px;
  padding: 0; margin: -1px; overflow: hidden; clip: rect(0,0,0,0); border: 0;
}

/* ──────────────────────────────────────────────────────────────────
   §7  PAGE HEAD SUBCOMPONENTS
   A-E: the layout rule for .page-head / .glass-page-head used to live
   here AND in glass.css §14, fighting property-by-property each time
   the cascade ordering changed. Canonical rule is now in glass.css §14
   (which carries the glass surface treatment too). These selectors only
   style the inner subcomponents, which glass.css §14 does not redeclare.
   ────────────────────────────────────────────────────────────────── */
.head-title { font-size: var(--fs-5); font-weight: 700; }
.head-sub { color: var(--text-m); font-size: var(--fs-1); margin-top: 2px; }
.head-actions { display: flex; gap: var(--sp-2); flex-wrap: wrap; align-items: center; }

/* ──────────────────────────────────────────────────────────────────
   §8  IMPERSONATION BAR
   ────────────────────────────────────────────────────────────────── */
.impersonate-bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-3);
  padding: 10px var(--sp-4);
  /* The warn tint is deliberately translucent, but this bar is `position:
     sticky` — so page content scrolling underneath used to show straight
     through it (KPI cards were legible behind the banner). Layer the tint over
     an OPAQUE page-background so the bar stays readable while pinned. The tint
     itself is unchanged; only an opaque base is added beneath it. */
  background: linear-gradient(135deg, rgba(var(--warn-rgb),0.22), rgba(var(--warn-rgb),0.10)), var(--bg);
  border: 1px solid rgba(var(--warn-rgb),0.40);
  border-radius: var(--r-2);
  color: var(--text);
  margin-bottom: var(--sp-3);
  position: sticky;
  /* `env()` is the safe-area inset and returns 0 unless the viewport meta
     carries `viewport-fit=cover` — which it now does, in every head. So this
     bar, which pins to the very top of a page, must clear the iOS status bar
     or its own text («حساب نماینده») sits under the clock. It is the one
     element on the page that must never be missed: it is how the operator
     knows whose wallet they are about to move. */
  top: env(safe-area-inset-top, 0px);
  z-index: 50;
}
.impersonate-bar strong { color: var(--warn); }

/* ──────────────────────────────────────────────────────────────────
   §9  DESKTOP HEADER + NAV — DELETED 2026-09-21 (M10 stage I)
   ──────────────────────────────────────────────────────────────────
   Four rules stood here and all four named elements that no longer exist in any
   page:
     .header, .app-header { … }          the desktop top bar's container
     body > .header { margin-top: … }    its flush-top clearance for the one page
                                         that included nav.php outside a .wrap
     .brand { … } / .brand .dot { … }    the role chip inside it

   HOW EACH DIED, because they died for different reasons and only one of them
   was this stage's decision:
     • `.brand` and `.brand .dot` lost their only markup in stage I. Verified
       dead first, not assumed: `grep -rn 'class="brand"'` over all of public/
       returned exactly one hit (nav.php, the chip this stage deletes), and the
       class is emitted nowhere else — no PHP, no JS, no classList.add.
     • `body > .header` existed solely for representatives.php, which included
       the nav as a direct body child and needed the `.wrap` padding-top
       reproduced so its nav hung at the same height as every other page's. With
       no wrapper there is no flush-top edge to clear. (Stage I later gave that
       page its own `.wrap`, which removes the reason the rule was written at
       all — the clearance is now the wrap's own padding.)
     • `.header, .app-header` was already down to a single rendering subject by
       stage G, which deleted the horizontal bar (`<nav class="nav"
       id="desktop-nav">`) and deleted ITS rules below. `.app-header` had been
       dead since before that: a repo-wide `grep -rn app-header` over the PHP,
       JS and HTML sources returns no markup and never did in this tree.
   The container the operator was looking at — a full-width white strip holding
   the word «نماینده» at ≥1024px — was `.header` with one child. It is deleted on
   the explicit instruction «حذف شود», and the role moved into the rail. See the
   markup comment in `public/admin/partials/nav.php`.

   DO NOT RE-ADD ANY OF THESE "for the auth pages" or "for a future header".
   `login.php`, `2fa.php` and the other auth surfaces use `body.auth-page`, which
   has its own shell (asserted by bin/test_nav_layout_contract.php §4); the nav
   partial is not rendered on them at all. */
/* M10 stage G — the horizontal desktop top bar is GONE. The `<nav class="nav"
   id="desktop-nav">` block in nav.php was deleted because it painted ALONGSIDE
   .nav-rail at every width ≥1024px (measured: 2 nav surfaces at 1440/1280/1024,
   where the rule is exactly one). With it go its display rules and its
   ghost-button rules:
     .nav,.app-nav{display:none} + @media(min-width:1024px){…display:inline-flex}
     .nav .btn-glass / :hover / .primary / .primary:hover
   VERIFIED DEAD BEFORE DELETION, not assumed: `grep -rn 'app-nav'` over all
   .php/.js/.html/.css outside docs/ returned only these six lines themselves,
   and `grep -rn 'class="nav"\|class="nav '` over public/**.php returned no
   markup at all. Zero dynamic adds too (`classList.add('nav')` etc: none).
   .nav-rail in nav.php now owns the desktop surface and carries its own ghost
   styling; the bottom bar owns ≤1023px. */

/* Badge chip. NOT top-nav-scoped despite the old heading: .nb is rendered by
   deposits.php, representatives.php, my_subscriptions.php, subscriptions.php
   and the «بیشتر» sheet's own rows, so the rule stays.
   Fill/ink pair: it was a SOLID `var(--danger)` under a literal `#fff`, which
   is 3.56:1 in graphite — and `--danger` is `#f14d4c` in *every* dark system,
   so the count was under AA on four of the six. There is no
   `--danger-foreground` to reach for; the house recipe for a semantic chip is
   the one `.badge-glass.danger` already uses (tint fill + `--danger-text-rgb`
   ink), so this is that recipe at chip scale rather than a fifth vocabulary. */
.nb {
  display: inline-flex; align-items: center; justify-content: center;
  min-width: 18px; height: 18px; padding: 0 5px;
  margin-inline-start: 6px;
  font-size: 0.7rem; font-weight: 700;
  background: rgba(var(--danger-rgb), 0.22);
  color: rgb(var(--danger-text-rgb));
  border: 1px solid rgba(var(--danger-rgb), 0.5);
  border-radius: var(--r-full);
}

/* Hide bottom-nav on desktop */
@media (min-width: 1024px) {
  body { padding-bottom: 0; }
  .glass-bottom-nav { display: none !important; }   /* .theme-fab dropped — PHASE5-PAYLOAD, see glass.css */
  .wrap, .wrap-narrow { padding-bottom: var(--sp-7); }
  :root { --mob-nav-h: 0px; }
}

/* ──────────────────────────────────────────────────────────────────
   §10  LEGACY ALIASES — keep unchanged PHP markup rendering correctly
        under the new glass system.  These are weak rules; component
        styles in glass.css override them.
   ────────────────────────────────────────────────────────────────── */

/* Card alias */
.card {
  background: var(--surface-1);
  border: 1px solid var(--border);
  border-radius: var(--r-3);
  padding: var(--sp-5);
  box-shadow: var(--shadow);
  position: relative;
  color: var(--text);
}
.card-sm { padding: var(--sp-3); border-radius: var(--r-2); }
.card-title { display: flex; align-items: center; justify-content: space-between; gap: var(--sp-2); margin-bottom: var(--sp-3); font-size: var(--fs-3); font-weight: 700; }

/* Button alias — minimum sane defaults; glass-css does the heavy lifting */
.btn {
  display: inline-flex; align-items: center; justify-content: center;
  gap: 6px;
  min-height: 44px; padding: 10px var(--sp-4);
  border-radius: var(--r-2); border: 1px solid var(--border);
  background: var(--surface-1); color: var(--text);
  font: inherit; font-weight: 600; font-size: var(--fs-2);
  cursor: pointer;
  text-decoration: none;
  transition: background var(--dur-1) var(--ease), transform var(--dur-1) var(--ease), border-color var(--dur-1) var(--ease);
}
.btn:hover  { background: var(--surface-2); }
.btn:active { transform: translateY(1px); }
.btn:disabled, .btn[aria-disabled="true"] { opacity: 0.6; cursor: not-allowed; }
.btn.primary { background: var(--accent-cta); color: var(--primary-foreground); border-color: transparent; }
.btn.primary:hover { filter: brightness(0.94); }
.btn.warn    { background: rgba(var(--warn-rgb),0.18); color: var(--warn); border-color: rgba(var(--warn-rgb),0.35); }
.btn.danger  { background: rgba(var(--danger-rgb),0.18); color: var(--danger); border-color: rgba(var(--danger-rgb),0.35); }
.btn.gray    { background: var(--surface-1); }
.btn.tiny    { min-height: 36px; padding: var(--sp-2) var(--sp-3); font-size: var(--fs-1); }
.btn.sm      { min-height: 40px; padding: var(--sp-2) var(--sp-3-5); font-size: var(--fs-1); }

/* Input alias — kept generic; .glass-input is the canonical */
.input, .form-control, .select, .glass-input, .glass-select, .glass-textarea {
  width: 100%;
  min-height: 48px;
  padding: 0 var(--sp-3);
  background: var(--input-bg);
  border: 1px solid var(--border);
  border-radius: var(--r-2);
  color: var(--text);
  font: inherit; font-size: var(--fs-2);
  outline: none;
  transition: border-color var(--dur-1) var(--ease), box-shadow var(--dur-1) var(--ease), background var(--dur-1) var(--ease);
}
.glass-textarea { min-height: 96px; padding: var(--sp-3); resize: vertical; line-height: 1.6; }
select.input, select.form-control, select.select, select.glass-select { padding-inline-end: var(--sp-7); appearance: none;
  background-image: linear-gradient(45deg, transparent 50%, var(--text-m) 50%), linear-gradient(135deg, var(--text-m) 50%, transparent 50%);
  background-position: calc(var(--sp-3)) calc(50% - 2px), calc(var(--sp-3) + 5px) calc(50% - 2px);
  background-size: 5px 5px, 5px 5px;
  background-repeat: no-repeat;
}
.input::placeholder, .form-control::placeholder, .glass-input::placeholder, .glass-textarea::placeholder { color: var(--text-d); }
.input:focus, .form-control:focus, .select:focus, .glass-input:focus, .glass-select:focus, .glass-textarea:focus {
  border-color: var(--border-strong);
  box-shadow: 0 0 0 4px rgba(var(--accent-rgb),0.18);
}

/* R2-10: native checkboxes and radios missing .glass-check take the system's brand accent
   instead of UA-blue default. */
input[type="checkbox"]:not(.glass-check),
input[type="radio"]:not(.glass-check) {
  accent-color: var(--accent);
}

.form-group { display: flex; flex-direction: column; gap: 6px; margin-bottom: var(--sp-3); }
.form-group > label { font-size: var(--fs-1); color: var(--text-m); font-weight: 600; }
.form-hint { font-size: var(--fs-1); color: var(--text-m); margin-top: 4px; }

/* Alert alias */
.alert {
  padding: var(--sp-3) var(--sp-4);
  border-radius: var(--r-2);
  border: 1px solid var(--border);
  background: var(--surface-1);
  color: var(--text);
  font-size: var(--fs-2);
}
.alert.info    { border-color: rgba(var(--accent-rgb),0.40);  background: rgba(var(--accent-rgb),0.10); }
.alert.success { border-color: rgba(var(--success-rgb),0.40); background: rgba(var(--success-rgb),0.10); color: var(--success); }
.alert.warning { border-color: rgba(var(--warn-rgb),0.40);    background: rgba(var(--warn-rgb),0.10);    color: var(--warn); }
.alert.error,
.alert.danger  { border-color: rgba(var(--danger-rgb),0.40);  background: rgba(var(--danger-rgb),0.10);  color: var(--danger); }

/* Badge alias */
.badge {
  display: inline-flex; align-items: center; gap: var(--sp-1);
  padding: var(--sp-1) 10px;
  font-size: var(--fs-1); font-weight: 600;
  border-radius: var(--r-full);
  background: var(--surface-1); color: var(--text);
  border: 1px solid var(--border);
}
.badge.gray   { color: var(--text-m); }
.badge.rep    { background: rgba(var(--accent-rgb),0.18); color: var(--accent); border-color: rgba(var(--accent-rgb),0.35); }
.badge.active { background: rgba(var(--success-rgb),0.16); color: var(--success); border-color: rgba(var(--success-rgb),0.32); }
.badge.pending,
.badge.warning { background: rgba(var(--warn-rgb),0.18); color: var(--warn); border-color: rgba(var(--warn-rgb),0.35); }
.badge.suspended,
.badge.deleted,
.badge.rejected,
.badge.failed { background: rgba(var(--danger-rgb),0.16); color: var(--danger); border-color: rgba(var(--danger-rgb),0.32); }

/* Table alias — base */
/* PHASE5-TBL: every `.tbl-wrap` twin in the lists below was deleted — zero
   call sites anywhere; admin tables all wrap in `.table-wrap`. */
.table {
  width: 100%; border-collapse: separate; border-spacing: 0;
  font-size: var(--fs-2);
}
.table th {
  text-align: start;
  padding: var(--sp-3) var(--sp-3);
  font-weight: 700; font-size: var(--fs-1);
  color: var(--text-m);
  border-bottom: 1px solid var(--border);
  background: transparent;
}
.table td {
  padding: var(--sp-3);
  border-bottom: 1px solid var(--border);
  color: var(--text);
  vertical-align: middle;
}
.table-wrap { overflow-x: auto; -webkit-overflow-scrolling: touch; }

/* Mobile card-collapse moved entirely to glass.css §47 — every admin
   table is wrapped in .table-wrap with .glass-tx-table / .leaderboard,
   and the glass selectors cover them. Removing the old
   `display: contents` block here prevents the two layouts from
   fighting for the same <td>. See UI_AUDIT_REPORT.md / A-C. */

/* ──────────────────────────────────────────────────────────────────
   §11  RESPONSIVE TWEAKS
   ────────────────────────────────────────────────────────────────── */
@media (min-width: 768px) {
  html { font-size: 15.5px; }
  .wrap { padding: var(--sp-6) var(--sp-6) calc(var(--mob-nav-h) + var(--sp-6)); }
  h1 { font-size: 1.95rem; }
}
@media (min-width: 1024px) {
  html { font-size: 16px; }
  /* M10 STAGE J — the `max-width: var(--container-max)` that stood here is
     deleted, and only it: the padding below is this rule's real work and stays.
     It was a THIRD statement of the desktop measure (`.wrap`'s base rule above,
     this one, and glass.css's grouped rule) and every page that loads this file
     also loads glass.css — verified, 40 files each and no page loads app.css
     alone — so at equal specificity and a later load position glass.css always
     won and this one was dead on arrival. A dead statement of the measure is not
     harmless here: it is the shape that made the last two attempts at this fix
     read as correct while the page rendered something else. The ≤1023px base
     rule above is a different thing and stays — it is the MOBILE measure, the
     only one in effect below this breakpoint. See bin/test_one_measure.php. */
  .wrap { padding: var(--sp-7) var(--sp-6) var(--sp-7); }
}
@media (max-width: 360px) {
  html { font-size: 14px; }
  .wrap { padding-inline: 12px; }
}

/* ──────────────────────────────────────────────────────────────────
   §12  AUTH PAGE BASE (login.php)
   ────────────────────────────────────────────────────────────────── */
body.auth-page {
  background: var(--auth-bg);
  display: grid; place-items: center;
  padding: var(--sp-6) var(--sp-4);
  min-height: 100vh;
}
body.auth-page::before {
  content: ""; position: fixed; inset: 0; pointer-events: none; z-index: 0;
  background:
    radial-gradient(45% 35% at 15% 18%, var(--auth-blob1), transparent 65%),
    radial-gradient(40% 35% at 85% 75%, var(--auth-blob2), transparent 65%),
    radial-gradient(35% 35% at 50% 110%, var(--auth-blob3), transparent 65%);
  filter: blur(10px);
}
body.auth-page .wrap { padding: 0; max-width: 480px; position: relative; z-index: 1; }
.login-card {
  width: 100%;
  background: var(--auth-card);
  border: 1px solid var(--auth-card-border);
  border-radius: var(--r-5);
  padding: var(--sp-7) var(--sp-6);
  box-shadow: var(--auth-card-glow);
}

/* R3 7-03 residual: on these 3 systems the 0.70 opacity of --p-fg is still
   <4.5:1, so the 4 patched muted families go to opaque --text-m
   (= per-system --p-muted-fg, which clears 4.5:1 on all 34). Option B's
   --text-d is NOT used (it resolves to the placeholder token, fails 34/34). */
html[data-sys="retro-arcade"] .glass-row-head, html[data-sys="retro-arcade"] .glass-row .row-id,
html[data-sys="retro-arcade"] .glass-row .row-date, html[data-sys="retro-arcade"] .wallet-hint{ opacity:1; color:var(--text-m); }
html[data-sys="catppuccin-light"] .glass-row-head, html[data-sys="catppuccin-light"] .glass-row .row-id,
html[data-sys="catppuccin-light"] .glass-row .row-date, html[data-sys="catppuccin-light"] .wallet-hint{ opacity:1; color:var(--text-m); }
html[data-sys="vintage-paper"] .glass-row-head, html[data-sys="vintage-paper"] .glass-row .row-id,
html[data-sys="vintage-paper"] .glass-row .row-date, html[data-sys="vintage-paper"] .wallet-hint{ opacity:1; color:var(--text-m); }

/* End of app.css */
