/* ═══════════════════════════════════════════════════════════════════
   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 — single source of truth.
       Tokens kept name-compatible with the previous app.css so that
       PHP inline styles still resolve (var(--accent), var(--text), …).
       ────────────────────────────────────────────────────────────── */
:root,
html[data-theme="dark"] {
  /* ── Background layers — Phase 5 stage 2: NEUTRAL CHARCOAL (not pure
     black). A closely-related-but-distinct ladder: the page↔card gap is
     deliberately small; the separation lives INSIDE the card
     (card < muted/header < hover < elevated). ── */
  --bg:               #131417;            /* page shell — charcoal        */
  --bg-deep:          #0e0f12;
  --bg-dark:          #131417;            /* legacy alias */

  /* ── Solid surfaces (opaque) — the elevation ladder ────────────────── */
  --surface:          #191b20;            /* = card */
  --surface-2:        #202228;            /* muted / table-header step    */
  --card:             #191b20;
  --card-soft:        #202228;
  --surface-solid:    #191b20;

  /* ── Card fills — OPAQUE (shadcn is not glass; blur already removed per
     AUDIT A4). Cards separate from the page by value + border. ── */
  --glass-card-bg:    #191b20;            /* card — one small step over page */
  --glass-elev-bg:    #262932;            /* hover / elevated — top of ladder */
  --glass-btn-bg:     var(--glass-card-bg);
  --glass-nav-bg:     #16171c;            /* nav — between page and card + top border */
  --input-bg:         #15161b;

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

  /* ── Borders — structure comes from borders, not glow (shadcn); kept
     subtle on charcoal so they read as structure, never as a bright edge. */
  --border:           rgba(255,255,255,0.09);
  --border-soft:      rgba(255,255,255,0.055);
  --border-strong:    rgba(95,124,255,0.42);
  --border-b:         var(--border-strong); /* legacy alias */

  /* ── Text — high contrast for Persian script ───────────────────────── */
  --text:             #f4f6fb;
  --text-muted:       #a4acc4;
  --text-soft:        #7f88a6;
  --text-m:           var(--text-muted);    /* legacy alias */
  --text-d:           var(--text-soft);      /* legacy alias */

  /* ── Single brand primary (#5f7cff) ─────────────────────────────────── */
  --primary:          #5f7cff;
  --accent:           var(--primary);       /* unified to --primary (PHASE5-ACCENT) */
  --accent-soft:      rgba(95,124,255,0.16);
  --accent-rgb:       95,124,255;
  /* Solid-button-only accent. White-on-#5f7cff is 3.61:1 — below WCAG AA
     (4.5) for the one control users are steered to press. #5a66f6 is the
     nearest colour that clears it (4.50:1) and is deliberately NOT --accent:
     links, borders and tints keep the brand blue; only filled CTAs shift. */
  --accent-cta:       #5a66f6;
  /* AUTO-DECISION: retired the old purple (#a78bfa) + cyan (#22d3ee)
     secondaries — they were the "inconsistent colors" complaint. Keep the
     two aliases defined but in-family (both blue) so legacy gradients that
     reference them no longer clash with the single accent. */
  --accent-2:         #8ea0ff;
  --accent-3:         #6f9bff;
  --accent2:          var(--accent-2);       /* legacy alias */
  --accent3:          var(--accent-3);

  /* ── shadcn semantic token set (Phase 5 stage 2) — ONE set consumed by
     every page, dual-written alongside the legacy names, defined
     INDEPENDENTLY per theme (no shared :root value both themes inherit).
     NAMING: brand indigo/blue stays on --primary; the shadcn "--accent = hover wash" role lives on
     --hover instead, because repurposing --accent would be the big-bang
     rename SHADCN_TOKENS §2.2 / checklist item 1 says to avoid. ── */
  --background:           var(--bg);
  --foreground:           var(--text);
  --card-foreground:      var(--text);
  --popover:              #202228;              /* elevated surface — menus/dialogs */
  --popover-foreground:   var(--text);
  --primary-foreground:   #ffffff;
  --secondary:            #202228;              /* low-emphasis filled action */
  --secondary-foreground: var(--text);
  --muted:                #202228;              /* subtle surface (headers/chrome) */
  --muted-foreground:     var(--text-muted);
  --accent-foreground:    #ffffff;              /* text on brand accent (--accent above) */
  --hover:                rgba(255,255,255,0.05); /* neutral row/ghost hover wash */
  --destructive:          var(--danger);
  --destructive-foreground: #ffffff;
  --warning:              var(--warn);          /* status only (--success defined above) */
  --ring:                 var(--primary);       /* focus ring (brand-tinted) */
  --input:                rgba(255,255,255,0.13); /* form control edge */

  /* RGB triplets for rgba() composition */
  --success-rgb:      52,199,142;
  --warn-rgb:         240,180,60;
  --danger-rgb:       244,102,102;
  /* PERF/SIMPLIFY: the "readable text on a tinted chip" shade each status
     already uses consistently (badges, tier tags, transaction amounts) --
     deliberately different numbers from --success-rgb/--warn-rgb/--danger-rgb
     above (those are tuned for low-alpha backgrounds/borders, these for
     legible solid text), not a duplicate to collapse into one value. */
  --success-text-rgb: 74,222,128;
  --warn-text-rgb:    252,211,77;
  --danger-text-rgb:  248,113,113;
  /* Completes the *-text-rgb family, which had no accent member. Value is the
     one already hardcoded by .dur-btn.active in this theme. */
  --accent-text-rgb:  199,210,254;

  /* ── Semantic status (color used only for badges/highlights) ───────── */
  --success:          #34c78e;
  --warn:             #f0b43c;
  --danger:           #f46666;
  --ok:               var(--success);   /* legacy alias */
  --err:              var(--danger);

  /* ── Effects — softer, calmer shadows (no harsh glow spam) ─────────── */
  --neon:             0 0 22px rgba(var(--accent-rgb),0.35);
  --shadow-sm:        0 1px 3px rgba(0,0,0,0.30);
  --shadow:           0 10px 30px rgba(0,0,0,0.38);
  --shadow-lg:        0 24px 60px rgba(0,0,0,0.52);
  --glow:             0 0 32px rgba(var(--accent-rgb),0.16);

  /* Auth page tokens */
  --auth-bg:                #0f1220;
  --auth-blob1:             rgba(var(--accent-rgb),0.20);
  --auth-blob2:             rgba(110,155,255,0.14);
  --auth-blob3:             rgba(142,160,255,0.09);
  --auth-card:              rgba(23,26,42,0.80);
  --auth-card-border:       rgba(255,255,255,0.10);
  --auth-card-glow:         0 0 0 1px rgba(255,255,255,0.05), 0 28px 80px rgba(0,0,0,0.60);
  --auth-input:             rgba(10,12,22,0.55);
  --auth-input-border:      rgba(255,255,255,0.12);
  --auth-tabs-bg:           rgba(255,255,255,0.05);
  --auth-tabs-border:       rgba(255,255,255,0.08);
  --toggle-btn-bg:          rgba(255,255,255,0.09);

  /* 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 */
  --r-1:   8px;
  --r-2:   12px;
  --r-3:   16px;
  --r-4:   20px;
  --r-5:   24px;
  --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;
}

html[data-theme="light"] {
  /* Phase 5: NEUTRAL gray page (dropped the blue #f5f7fb tint) so near-white
     cards separate clearly. Separation now comes from a real border, not a
     faint 8%-ink hairline. */
  --bg:               #eef0f3;            /* page — neutral light gray   */
  --bg-deep:          #e6e8ec;
  --bg-dark:          #eef0f3;

  /* Solid surfaces */
  --surface:          #ffffff;
  --surface-2:        #f3f4f6;            /* muted / table-header        */
  --card:             #ffffff;
  --card-soft:        #f7f8fa;
  --surface-solid:    #ffffff;

  /* Card fills — Phase 5: OPAQUE white (dropped 0.78 translucency that
     read as "washed out" over the page). */
  --glass-card-bg:    #ffffff;
  --glass-elev-bg:    #ffffff;
  --glass-btn-bg:     #ffffff;
  --glass-nav-bg:     #ffffff;            /* opaque nav — no page bleed-through */
  --input-bg:         #ffffff;

  --surface-1:        var(--glass-card-bg);
  --surface-3:        var(--glass-elev-bg);
  --glass:            var(--surface-1);
  --glass-b:          var(--surface-2);
  --glass-s:          var(--surface-3);
  --elevated:         var(--surface-solid);
  --card-bg:          var(--glass-card-bg);

  --border:           #e3e5e9;            /* clear soft neutral border   */
  --border-soft:      #eceef1;
  --border-strong:    rgba(79,107,255,0.40);

  --text:             #1d2435;
  --text-muted:       #667085;
  --text-soft:        #8a94a8;
  --text-m:           var(--text-muted);
  --text-d:           var(--text-soft);

  --primary:          #4f6bff;
  --accent:           var(--primary);
  --accent-soft:      rgba(79,107,255,0.12);
  --accent-rgb:       79,107,255;
  /* Same CTA fill in light: white-on-#4f6bff is 4.30:1, also short of AA.
     One shared value keeps the primary button identical across themes. */
  --accent-cta:       #5a66f6;
  --accent-2:         #6a83ff;
  --accent-3:         #3f5cf0;
  --accent2:          var(--accent-2);
  --accent3:          var(--accent-3);

  /* shadcn semantic token set (Phase 5 stage 2) — light-INDEPENDENT values
     (mirror of the dark set; see the dark block for the naming rationale). */
  --background:           var(--bg);
  --foreground:           var(--text);
  --card-foreground:      var(--text);
  --popover:              #ffffff;
  --popover-foreground:   var(--text);
  --primary-foreground:   #ffffff;
  --secondary:            #f3f4f6;
  --secondary-foreground: var(--text);
  --muted:                #f3f4f6;
  --muted-foreground:     var(--text-muted);
  --accent-foreground:    #ffffff;
  --hover:                #f1f2f4;              /* neutral gray hover wash */
  --destructive:          var(--danger);
  --destructive-foreground: #ffffff;
  --warning:              var(--warn);
  --ring:                 var(--primary);
  --input:                #e3e5e9;

  --success-rgb:      5,150,105;
  --warn-rgb:         217,119,6;
  --danger-rgb:       220,38,38;
  --success-text-rgb: 22,101,52;
  --warn-text-rgb:    146,64,14;
  --danger-text-rgb:  185,28,28;
  /* Light accent INK — 7.90:1 on white, vs 4.30:1 for --accent-rgb, which is
     tuned as a fill/border tint and is too light to carry small text. Value is
     the one already hardcoded by .dur-btn.active and .badge-glass.neutral. */
  --accent-text-rgb:  67,56,202;

  --success:          #059669;
  --warn:             #d97706;
  --danger:           #dc2626;
  --ok:               var(--success);
  --err:              var(--danger);

  --neon:             0 0 20px rgba(var(--accent-rgb),0.14);
  --shadow-sm:        0 1px 2px rgba(30,40,70,0.05);
  --shadow:           0 6px 22px rgba(30,40,70,0.07);
  --shadow-lg:        0 18px 48px rgba(30,40,70,0.10);
  --glow:             0 0 24px rgba(var(--accent-rgb),0.08);

  --auth-bg:                #eef1fb;
  --auth-blob1:             rgba(var(--accent-rgb),0.12);
  --auth-blob2:             rgba(106,131,255,0.09);
  --auth-blob3:             rgba(63,92,240,0.06);
  --auth-card:              rgba(255,255,255,0.92);
  --auth-card-border:       rgba(var(--accent-rgb),0.14);
  --auth-card-glow:         0 0 0 1px rgba(var(--accent-rgb),0.07), 0 18px 56px rgba(var(--accent-rgb),0.11);
  --auth-input:             #ffffff;
  --auth-input-border:      rgba(var(--accent-rgb),0.18);
  --auth-tabs-bg:           rgba(var(--accent-rgb),0.06);
  --auth-tabs-border:       rgba(var(--accent-rgb),0.12);
  --toggle-btn-bg:          rgba(var(--accent-rgb),0.10);
}

/* ──────────────────────────────────────────────────────────────────
   §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;
  scroll-behavior: smooth;
}
@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;
  top: 0;
  z-index: 50;
}
.impersonate-bar strong { color: var(--warn); }

/* ──────────────────────────────────────────────────────────────────
   §9  DESKTOP HEADER (.header / .app-header) + NAV
   ────────────────────────────────────────────────────────────────── */
.header, .app-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-4);
  padding: var(--sp-3) var(--sp-4);
  background: var(--surface-1);
  border: 1px solid var(--border);
  border-radius: var(--r-3);
  position: sticky;
  top: var(--sp-2);
  z-index: 40;
  box-shadow: var(--shadow-sm);
  /* Nav harmony: every page's header is capped at the dashboard's measure and
     centered, even where the page's CONTENT container is wider (.wrap.wide on
     the dense list pages) or where the header sits outside any wrap (the
     representatives page included nav.php before .wrap — full-viewport before
     this rule). One rule, every page: the nav matches the dashboard tab. */
  max-width: var(--container-max);
  margin-inline: auto;
}
/* Vertical harmony for the one page that includes nav.php OUTSIDE a .wrap
   (representatives): inside a wrap, the header's top edge sits below the
   wrap's padding-top (var(--sp-4)); as a direct body child it would sit flush
   with the viewport top. Reproduce the wrap's clearance so the nav hangs at
   exactly the same height as every other page. */
body > .header {
  margin-top: var(--sp-4);
}
.brand {
  display: inline-flex; align-items: center; gap: var(--sp-2);
  font-weight: 700; font-size: var(--fs-3); color: var(--text);
}
.brand .dot {
  width: 10px; height: 10px; border-radius: var(--r-full);
  background: var(--accent);
  box-shadow: 0 0 12px rgba(var(--accent-rgb),0.8);
}
.nav, .app-nav {
  display: none;
  gap: var(--sp-1);           /* Phase 5 stage 3a: tighter item spacing */
}
@media (min-width: 1024px) {
  .nav, .app-nav { display: inline-flex; align-items: center; }
}

/* Phase 5 stage 3a: desktop nav items are GHOST (no strip of bordered pills).
   Inactive = transparent, muted text, neutral hover; active = soft-primary
   fill so the current page stays obvious. */
.nav .btn-glass, .app-nav .btn-glass {
  background: transparent;
  border-color: transparent;
  color: var(--muted-foreground);
  box-shadow: none;
}
.nav .btn-glass:hover, .app-nav .btn-glass:hover {
  background: var(--hover);
  border-color: transparent;
  color: var(--foreground);
}
.nav .btn-glass.primary, .app-nav .btn-glass.primary {
  /* soft-primary fill signals the active page; foreground text keeps contrast
     >=4.5:1 (primary-blue text on the tint was ~3.7:1). */
  background: var(--accent-soft);
  color: var(--foreground);
  border-color: transparent;
}
.nav .btn-glass.primary:hover, .app-nav .btn-glass.primary:hover {
  background: var(--accent-soft);
  color: var(--foreground);
  filter: none;
}

/* Desktop top-nav badge */
.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: var(--danger); color: #fff;
  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); color: #fff; border-color: transparent; }
.btn.primary:hover { background: var(--accent-2); }
/* UI-0292: in light theme --accent-2 (#8b5cf6) under white text is only ~4:1.
   Keep the brand accent on hover and darken it slightly instead of switching
   to the lighter violet, so the white label stays legible. */
html[data-theme="light"] .btn.primary:hover { background: var(--accent); filter: brightness(0.92); }
.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);
}

.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; }
  .wrap { padding: var(--sp-7) var(--sp-6) var(--sp-7); max-width: var(--container-max); }
}
@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);
}

/* End of app.css */
