/* ============================================================
   BACKPACK CRM — Base Design System
   Core variables, reset, layout, and shared components
   ============================================================ */

/* === Self-hosted Inter (variable, 400-700) — no CDN dependency === */
/* cyrillic */
@font-face {
  font-family: 'Inter';
  font-style: normal;
  font-weight: 100 900;
  font-display: swap;
  src: url('/fonts/inter-cyrillic.woff2') format('woff2');
  unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}
/* cyrillic-ext */
@font-face {
  font-family: 'Inter';
  font-style: normal;
  font-weight: 100 900;
  font-display: swap;
  src: url('/fonts/inter-cyrillic-ext.woff2') format('woff2');
  unicode-range: U+0460-052F, U+1C80-1C8A, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
}
/* latin */
@font-face {
  font-family: 'Inter';
  font-style: normal;
  font-weight: 100 900;
  font-display: swap;
  src: url('/fonts/inter-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
/* latin-ext */
@font-face {
  font-family: 'Inter';
  font-style: normal;
  font-weight: 100 900;
  font-display: swap;
  src: url('/fonts/inter-latin-ext.woff2') format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

/* === CSS Custom Properties === */

/* === Manrope (display) ===
   Headings only. Softer, more geometric shapes than Inter, which keeps the
   interface from reading as purely utilitarian — while Inter stays on body
   text, tables and numbers where its tabular figures and small-size
   legibility matter more. Subset per script so an English-only user never
   downloads the Cyrillic file. */
@font-face {
  font-family: 'Manrope';
  font-style: normal;
  font-weight: 200 800;
  font-display: swap;
  src: url('/fonts/manrope-cyrillic.woff2') format('woff2');
  unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}
@font-face {
  font-family: 'Manrope';
  font-style: normal;
  font-weight: 200 800;
  font-display: swap;
  src: url('/fonts/manrope-cyrillic-ext.woff2') format('woff2');
  unicode-range: U+0460-052F, U+1C80-1C8A, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
}
@font-face {
  font-family: 'Manrope';
  font-style: normal;
  font-weight: 200 800;
  font-display: swap;
  src: url('/fonts/manrope-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'Manrope';
  font-style: normal;
  font-weight: 200 800;
  font-display: swap;
  src: url('/fonts/manrope-latin-ext.woff2') format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

:root {
  /* === Brand ===
     Deep evergreen. Two things it buys over the previous orange: almost
     every CRM in this category is blue, so green reads as chosen rather
     than default; and white text on this green measures 8.2:1, where the
     orange managed 2.9:1 and failed on its own primary buttons. */
  --primary: #1f5943;
  --primary-hover: #16402f;
  --primary-active: #102e24;
  --primary-light: #4caf82;
  --primary-dark: #16402f;             /* legacy alias */
  --primary-bg: #eaf3ee;               /* tinted surface for active nav, badges */
  --primary-bg-strong: #d7e9df;        /* hover on primary-bg surfaces */
  --primary-border: rgba(31, 89, 67, 0.30);
  --primary-ring: rgba(31, 89, 67, 0.18);

  --theme-color-1: #1f5943;
  --theme-color-2: #2a7a58;
  --theme-color-3: #4caf82;
  --theme-color-4: #7cc9a3;
  --theme-color-5: #a7d8bf;
  --theme-color-6: #cfe3d8;

  /* === Semantic status colors — paired bg/fg for soft pill badges === */
  --success: #16a34a;
  --success-bg: #ecfdf5;
  --success-fg: #047857;
  --warning: #d97706;
  --warning-bg: #fef3c7;
  --warning-fg: #92400e;
  --danger: #dc2626;
  --danger-bg: #fef2f2;
  --danger-fg: #b91c1c;
  --info: #2563eb;
  --info-bg: #eff6ff;
  --info-fg: #1d4ed8;
  --neutral-bg: #f1f5f9;
  --neutral-fg: #475569;

  /* === Surfaces ===
     `--surface` is the page-level white card; `--surface-muted` is the
     subtle tint used for striped rows / inset panels. */
  --bg-body: #f6f7f9;
  --surface: #ffffff;
  --surface-muted: #fafbfc;
  --surface-hover: #f5f6f8;
  --surface-sunken: #eef0f3;

  /* === Borders === */
  --border: #e4e6eb;
  --border-strong: #cdd1d9;
  --border-light: #f0f1f4;

  /* === Text === */
  --text-primary: #0f172a;
  --text-secondary: #475569;
  --text-muted: #94a3b8;

  /* === Scrollbars ===
     Ink at low opacity rather than a fixed grey, so the thumb sits on any
     surface it happens to overlap and darkens on hover instead of jumping
     to a different colour. */
  --scrollbar-thumb: rgba(15, 23, 42, 0.22);
  --scrollbar-thumb-hover: rgba(15, 23, 42, 0.42);
  --scrollbar-track: transparent;

  /* === Typography ===
     Two families with distinct jobs: Manrope sets headings, Inter carries
     everything that has to stay legible small or line up in a column. */
  --font-sans: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
  --font-display: 'Manrope', 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;

  /* === Layout === */
  --sidebar-width: 100px;
  --header-height: 70px;

  /* === Radius scale === */
  --radius-sm: 8px;
  --radius-md: 10px;
  --radius-lg: 12px;
  --radius-xl: 16px;
  --radius-2xl: 20px;
  --radius-full: 9999px;

  /* === Shadow scale ===
     Layered (small + larger) so cards lift cleanly without crushing the
     border. Used in this order: sm (button/control rest), md (card rest),
     lg (card hover, modal backdrop), xl (popover/modal). */
  --shadow-sm: 0 1px 2px rgba(15, 23, 42, 0.04);
  --shadow-md: 0 1px 3px rgba(15, 23, 42, 0.04), 0 6px 16px rgba(15, 23, 42, 0.05);
  --shadow-lg: 0 1px 3px rgba(15, 23, 42, 0.05), 0 12px 28px rgba(15, 23, 42, 0.08);
  --shadow-xl: 0 4px 8px rgba(15, 23, 42, 0.06), 0 24px 48px rgba(15, 23, 42, 0.12);
  --shadow-card: var(--shadow-md);
  --shadow-card-hover: var(--shadow-lg);

  --ring: 0 0 0 3px var(--primary-ring);

  --transition-fast: 0.15s cubic-bezier(0.4, 0, 0.2, 1);
  --transition-base: 0.2s cubic-bezier(0.4, 0, 0.2, 1);
  --transition-smooth: 0.3s cubic-bezier(0.4, 0, 0.2, 1);

  /* Ready-made transition lists. `transition: all` also animates layout
     properties (width, padding, top…), so every hover forced a relayout;
     these name only compositor-friendly properties. */
  --anim-ui-fast: background-color var(--transition-fast), border-color var(--transition-fast), color var(--transition-fast), box-shadow var(--transition-fast), transform var(--transition-fast), opacity var(--transition-fast);
  --anim-ui: background-color var(--transition-base), border-color var(--transition-base), color var(--transition-base), box-shadow var(--transition-base), transform var(--transition-base), opacity var(--transition-base);
  --anim-ui-smooth: background-color var(--transition-smooth), border-color var(--transition-smooth), color var(--transition-smooth), box-shadow var(--transition-smooth), transform var(--transition-smooth), opacity var(--transition-smooth);

  /* 8px spacing scale */
  --space-1: 8px;
  --space-2: 16px;
  --space-3: 24px;
  --space-4: 32px;
  --space-5: 40px;
  --space-6: 48px;
  --space-8: 64px;

  /* === Accent & payment-method palettes (centralised from per-file hexes) === */
  --danger-soft: #ef4444;            /* delete icons, soft danger borders */
  --accent-teal: #14b8a6;
  --accent-teal-bg: #f0fdfa;
  --method-cash-bg: #fef3c7;
  --method-cash-fg: #b45309;
  --method-cash-soft: #fffbeb;
  --method-cash-border: #fde68a;
  --method-card-bg: #dbeafe;
  --method-card-fg: var(--info-fg);
  --method-card-soft: var(--info-bg);
  --method-card-border: #bfdbfe;
  --method-click-bg: #cffafe;
  --method-click-fg: #0e7490;
  --method-click-soft: #ecfeff;
  --method-click-border: #a5f3fc;

  /* === Tint palette ===
     Soft coloured surfaces (schedule blocks, award chips). Paired bg/fg so
     the dark theme can swap a pale wash for a translucent one without any
     component rule changing. */
  --tint-green-bg: #d1fae5;   --tint-green-fg: #15803d;
  --tint-pink-bg: #fce7f3;    --tint-pink-fg: #db2777;
  --tint-orange-bg: #ffedd5;  --tint-orange-fg: #ea580c;
  --tint-purple-bg: #ede9fe;  --tint-purple-fg: #7c3aed;
  --tint-yellow-bg: #fef9c3;  --tint-yellow-fg: #a16207;
  /* Chips and floating buttons that sit on top of tinted/!image surfaces. */
  --overlay-chip: rgba(255, 255, 255, 0.7);
  --overlay-btn: rgba(255, 255, 255, 0.85);
}

/* ============================================================
   DARK THEME
   Only tokens are redefined — no component rule is duplicated, which is
   what the earlier sweep of hardcoded colours into tokens bought us.

   The theme is applied as data-theme on <html> by the server from a
   cookie, so the correct palette is in the very first byte of HTML and
   there is no flash of the wrong theme before JS runs. "system" leaves
   the attribute off and lets prefers-color-scheme decide.
   ============================================================ */
:root[data-theme="dark"],
:root[data-theme="system"] {
  color-scheme: dark;

  /* Surfaces: a warm-neutral ramp rather than pure greys, so the orange
     brand doesn't read as a foreign accent sitting on top of it. */
  --bg-body: #12161b;
  --surface: #191f26;
  --surface-muted: #1e242c;
  --surface-hover: #242b34;
  --surface-sunken: #0e1216;

  --border: #2b333d;
  --border-strong: #3b4550;
  --border-light: #222932;

  --text-primary: #e7ecf2;
  --text-secondary: #a7b3c1;
  --text-muted: #74808d;

  /* Same idea inverted: a light thumb, still translucent. A fixed grey
     here was the old behaviour and read as a bright bar on dark. */
  --scrollbar-thumb: rgba(231, 236, 242, 0.20);
  --scrollbar-thumb-hover: rgba(231, 236, 242, 0.38);
  --scrollbar-track: transparent;

  /* Brand tints become translucent washes: a fixed light tint would glow
     against dark surfaces. */
  --primary: #2a7a58;
  --primary-hover: #2f8663;
  --primary-active: #24694f;
  --primary-bg: rgba(76, 175, 130, 0.14);
  --primary-bg-strong: rgba(76, 175, 130, 0.24);
  --primary-border: rgba(76, 175, 130, 0.42);
  --primary-ring: rgba(76, 175, 130, 0.26);

  /* Status pills: dark wash background, lightened foreground so the text
     clears contrast against it rather than against white. */
  --success: #22c55e;
  --success-bg: rgba(34, 197, 94, 0.15);
  --success-fg: #4ade80;
  --warning: #f59e0b;
  --warning-bg: rgba(245, 158, 11, 0.15);
  --warning-fg: #fbbf24;
  --danger: #f05252;
  --danger-bg: rgba(240, 82, 82, 0.15);
  --danger-fg: #fca5a5;
  --danger-soft: #f05252;
  --info: #3b82f6;
  --info-bg: rgba(59, 130, 246, 0.15);
  --info-fg: #93c5fd;
  --neutral-bg: #242b34;
  --neutral-fg: #a7b3c1;

  --accent-teal: #2dd4bf;
  --accent-teal-bg: rgba(45, 212, 191, 0.14);

  --method-cash-bg: rgba(245, 158, 11, 0.18);
  --method-cash-fg: #fbbf24;
  --method-cash-soft: rgba(245, 158, 11, 0.10);
  --method-cash-border: rgba(245, 158, 11, 0.32);
  --method-card-bg: rgba(59, 130, 246, 0.18);
  --method-card-fg: #93c5fd;
  --method-card-soft: rgba(59, 130, 246, 0.10);
  --method-card-border: rgba(59, 130, 246, 0.32);
  --method-click-bg: rgba(34, 211, 238, 0.18);
  --method-click-fg: #67e8f9;
  --method-click-soft: rgba(34, 211, 238, 0.10);
  --method-click-border: rgba(34, 211, 238, 0.32);

  /* Shadows do almost nothing on dark surfaces; depth comes from the
     surface ramp instead, so these mainly anchor floating layers. */
  --shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.32);
  --shadow-md: 0 1px 3px rgba(0, 0, 0, 0.36), 0 6px 16px rgba(0, 0, 0, 0.30);
  --shadow-lg: 0 1px 3px rgba(0, 0, 0, 0.40), 0 12px 28px rgba(0, 0, 0, 0.40);
  --shadow-xl: 0 4px 8px rgba(0, 0, 0, 0.44), 0 24px 48px rgba(0, 0, 0, 0.52);

  --tint-green-bg: rgba(34, 197, 94, 0.18);   --tint-green-fg: #4ade80;
  --tint-pink-bg: rgba(236, 72, 153, 0.18);   --tint-pink-fg: #f9a8d4;
  --tint-orange-bg: rgba(234, 88, 12, 0.20);  --tint-orange-fg: #fdba74;
  --tint-purple-bg: rgba(139, 92, 246, 0.20); --tint-purple-fg: #c4b5fd;
  --tint-yellow-bg: rgba(234, 179, 8, 0.18);  --tint-yellow-fg: #fde047;
  --overlay-chip: rgba(255, 255, 255, 0.10);
  --overlay-btn: rgba(25, 31, 38, 0.85);
}

/* "system" only counts as dark when the OS asks for dark. Re-stating the
   light values keeps an explicit data-theme="system" from being stuck on
   the dark palette in a light environment. */
@media (prefers-color-scheme: light) {
  :root[data-theme="system"] {
    color-scheme: light;
    --bg-body: #f6f7f9;
    --surface: #ffffff;
    --surface-muted: #fafbfc;
    --surface-hover: #f5f6f8;
    --surface-sunken: #eef0f3;
    --border: #e4e6eb;
    --border-strong: #cdd1d9;
    --border-light: #f0f1f4;
    --text-primary: #0f172a;
    --text-secondary: #475569;
    --text-muted: #94a3b8;
    --primary: #1f5943;
    --primary-hover: #16402f;
    --primary-active: #102e24;
    --primary-bg: #eaf3ee;
    --primary-bg-strong: #d7e9df;
    --primary-border: rgba(31, 89, 67, 0.30);
    --primary-ring: rgba(31, 89, 67, 0.18);
    --success: #16a34a; --success-bg: #ecfdf5; --success-fg: #047857;
    --warning: #d97706; --warning-bg: #fef3c7; --warning-fg: #92400e;
    --danger: #dc2626;  --danger-bg: #fef2f2;  --danger-fg: #b91c1c;
    --danger-soft: #ef4444;
    --info: #2563eb;    --info-bg: #eff6ff;    --info-fg: #1d4ed8;
    --neutral-bg: #f1f5f9; --neutral-fg: #475569;
    --accent-teal: #14b8a6; --accent-teal-bg: #f0fdfa;
    --method-cash-bg: #fef3c7; --method-cash-fg: #b45309;
    --method-cash-soft: #fffbeb; --method-cash-border: #fde68a;
    --method-card-bg: #dbeafe; --method-card-fg: #1d4ed8;
    --method-card-soft: #eff6ff; --method-card-border: #bfdbfe;
    --method-click-bg: #cffafe; --method-click-fg: #0e7490;
    --method-click-soft: #ecfeff; --method-click-border: #a5f3fc;
    --shadow-sm: 0 1px 2px rgba(15, 23, 42, 0.04);
    --shadow-md: 0 1px 3px rgba(15, 23, 42, 0.04), 0 6px 16px rgba(15, 23, 42, 0.05);
    --shadow-lg: 0 1px 3px rgba(15, 23, 42, 0.05), 0 12px 28px rgba(15, 23, 42, 0.08);
    --shadow-xl: 0 4px 8px rgba(15, 23, 42, 0.06), 0 24px 48px rgba(15, 23, 42, 0.12);
    --tint-green-bg: #d1fae5;  --tint-green-fg: #15803d;
    --tint-pink-bg: #fce7f3;   --tint-pink-fg: #db2777;
    --tint-orange-bg: #ffedd5; --tint-orange-fg: #ea580c;
    --tint-purple-bg: #ede9fe; --tint-purple-fg: #7c3aed;
    --tint-yellow-bg: #fef9c3; --tint-yellow-fg: #a16207;
    --overlay-chip: rgba(255, 255, 255, 0.7);
    --overlay-btn: rgba(255, 255, 255, 0.85);
  }
}


/* === Reset === */
*,*::before,*::after { margin:0; padding:0; box-sizing:border-box; }
html { scroll-behavior: smooth; }
body {
  font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
  background: var(--bg-body);
  color: var(--text-primary);
  min-height: 100vh;
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-rendering: optimizeLegibility;
}
a { text-decoration:none; color:inherit; transition: color var(--transition-fast); }
::selection { background: var(--primary); color: #fff; }
:focus-visible { outline: 2px solid var(--primary); outline-offset: 2px; border-radius: 4px; }

/* Scrollbars.

   Two engines, two mechanisms, and they are mutually exclusive: from
   Chromium 121 onwards, setting scrollbar-width or scrollbar-color on an
   element makes it *ignore* the ::-webkit-scrollbar pseudo-elements for
   that element. Applying both unconditionally therefore switches off the
   custom thumb in the very browser most people use.

   So the standard properties are fenced behind engines that have no
   ::-webkit-scrollbar — Firefox — and Chromium and Safari get the pill.
   macOS overlay scrollbars ignore both and stay native, which is right. */
@supports not selector(::-webkit-scrollbar) {
  * {
    scrollbar-width: thin;
    scrollbar-color: var(--scrollbar-thumb) var(--scrollbar-track);
  }
}

::-webkit-scrollbar { width: 12px; height: 12px; }
::-webkit-scrollbar-track { background: var(--scrollbar-track); }
::-webkit-scrollbar-thumb {
  background: var(--scrollbar-thumb);
  border-radius: 999px;
  /* Transparent border read as padding: the thumb becomes a slim pill with
     air around it rather than a bar filling the gutter. */
  border: 4px solid transparent;
  background-clip: content-box;
}
::-webkit-scrollbar-thumb:hover {
  background: var(--scrollbar-thumb-hover);
  background-clip: content-box;
}
/* No stepper arrows — the default Windows scrollbar draws them and they
   have no place in this system. */
::-webkit-scrollbar-button { display: none; width: 0; height: 0; }
::-webkit-scrollbar-corner { background: transparent; }

/* === Layout === */
.app-layout { display:flex; min-height:100vh; }

/* === Content Area === */
.content-area { padding:28px; flex:1; }

.page-header {
  display:flex; align-items:center; justify-content:space-between;
  margin-bottom:20px; flex-wrap:wrap; gap:12px;
}
.page-header h1 {
  font-size:24px; font-weight:700; color:var(--text-primary);
  display:flex; align-items:center; gap:10px;
  letter-spacing: -0.3px;
}
.page-header h1 svg { display:none; }

.page-subtitle {
  font-size:14px; font-weight:400; color:var(--text-secondary); margin-left:12px;
}

.count-badge {
  display:inline-flex; align-items:center; justify-content:center;
  min-width:24px; height:24px; padding:0 8px;
  border-radius:var(--radius-full);
  background:var(--primary);
  color:#fff; font-size:12px; font-weight:600;
}

.search-info { font-size:14px; color:var(--text-secondary); margin-bottom:16px; }
.search-info a { color:var(--primary); font-weight:500; }

/* === Buttons ===
   Single source of truth for every button across the app. Component-
   specific buttons (.gv-submit-btn, .sl-add-btn, .sa-btn-primary, etc.)
   inherit hover-lift + focus ring via the .btn-base block further below. */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  padding: 10px 20px;
  border-radius: var(--radius-full);
  font-size: 14px;
  font-weight: 600;
  font-family: inherit;
  line-height: 1.2;
  cursor: pointer;
  border: 1px solid transparent;
  background: transparent;
  color: var(--text-primary);
  transition: background var(--transition-fast), border-color var(--transition-fast),
              color var(--transition-fast), box-shadow var(--transition-fast),
              transform var(--transition-fast);
  white-space: nowrap;
  user-select: none;
}
.btn:focus-visible { outline: none; box-shadow: var(--ring); }
.btn:active { transform: translateY(0) scale(0.98); }
.btn:disabled, .btn[disabled] { opacity: .55; cursor: not-allowed; transform: none !important; box-shadow: none !important; }

.btn-primary {
  background: var(--primary);
  color: #fff;
  box-shadow: 0 1px 2px rgba(31, 89, 67, .25);
}
.btn-primary:hover {
  background: var(--primary-hover);
  box-shadow: 0 4px 12px rgba(31, 89, 67, .28);
  transform: translateY(-1px);
}
.btn-primary:active { background: var(--primary-active); }

.btn-secondary {
  background: var(--surface);
  color: var(--text-secondary);
  border-color: var(--border);
}
.btn-secondary:hover {
  background: var(--surface-hover);
  color: var(--text-primary);
  border-color: var(--border-strong);
  transform: translateY(-1px);
}

.btn-danger {
  background: var(--danger);
  color: #fff;
}
.btn-danger:hover { filter: brightness(0.95); transform: translateY(-1px); }

.btn-ghost {
  background: transparent;
  color: var(--text-secondary);
  border-color: transparent;
}
.btn-ghost:hover { background: var(--surface-hover); color: var(--text-primary); }

.btn-small { padding: 6px 12px; font-size: 12px; }
.btn-large { padding: 12px 26px; font-size: 15px; }

/* Soft tinted action buttons used in tables (Edit / Delete). */
.btn-edit {
  background: var(--info-bg);
  color: var(--info-fg);
}
.btn-edit:hover { background: #e0ecff; transform: translateY(-1px); }
.btn-delete {
  background: var(--danger-bg);
  color: var(--danger-fg);
}
.btn-delete:hover { background: #fee2e2; transform: translateY(-1px); }

/* Per-component submit buttons share the primary look + focus ring. */
.gv-submit-btn,
.sv-submit-btn,
.sv-add-group-btn,
.tv-submit-btn,
.login-lc-btn,
.login-super-btn,
.sl-add-btn,
.gl-add-btn {
  cursor: pointer;
  transition: background var(--transition-fast), border-color var(--transition-fast),
              color var(--transition-fast), box-shadow var(--transition-fast),
              transform var(--transition-fast);
}
.gv-submit-btn:focus-visible,
.sv-submit-btn:focus-visible,
.sv-add-group-btn:focus-visible,
.tv-submit-btn:focus-visible,
.login-lc-btn:focus-visible,
.login-super-btn:focus-visible,
.sl-add-btn:focus-visible,
.gl-add-btn:focus-visible {
  outline: none;
  box-shadow: var(--ring);
}
.gv-submit-btn:hover,
.sv-submit-btn:hover,
.sv-add-group-btn:hover,
.tv-submit-btn:hover,
.sl-add-btn:hover,
.gl-add-btn:hover { transform: translateY(-1px); }
.gv-submit-btn:active,
.sv-submit-btn:active,
.sv-add-group-btn:active,
.tv-submit-btn:active,
.sl-add-btn:active,
.gl-add-btn:active { transform: translateY(0) scale(0.98); }

/* === Cards (shared base) ===
   One radius (xl, 16px), one resting shadow (md), one hover shadow (lg).
   Border stays on at rest so the surface reads as a "card" rather than a
   floating glow; hover slightly raises and softens the border.
   .stat-card is intentionally excluded — it lives inside a continuous
   strip on the dashboard with its own radius/border-right styling. */
.form-card, .detail-card, .section-block, .recent-activity, .welcome-banner {
  background: var(--surface);
  border-radius: var(--radius-xl);
  border: 1px solid var(--border);
  box-shadow: var(--shadow-md);
  padding: 24px;
  transition: box-shadow var(--transition-base), border-color var(--transition-base),
              transform var(--transition-base);
}
.detail-card:hover, .section-block:hover {
  box-shadow: var(--shadow-lg);
  border-color: var(--border-light);
}

/* === Forms === */
.form-card { max-width:640px; }
.form-group { margin-bottom:20px; position: relative; }
.form-group label {
  display:block; font-size:13px; font-weight:600;
  color:var(--text-primary); margin-bottom:6px;
}
.form-group input, .form-group select, .form-group textarea {
  width: 100%;
  padding: 11px 14px;
  background: var(--surface);
  border: 1.5px solid var(--border);
  border-radius: 12px;
  color: var(--text-primary);
  font-family: inherit;
  font-size: 14px;
  line-height: 1.4;
  transition: border-color var(--transition-base), box-shadow var(--transition-base), background var(--transition-base);
  appearance: none;
  -webkit-appearance: none;
}
/* Custom select chevron — keep native semantics, drop the default arrow */
.form-group select {
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='14' height='14' viewBox='0 0 24 24' fill='none' stroke='%2364748b' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><polyline points='6 9 12 15 18 9'/></svg>");
  background-repeat: no-repeat;
  background-position: right 12px center;
  padding-right: 36px;
  cursor: pointer;
}
.form-group input[type="date"], .form-group input[type="time"] {
  /* Native date/time inputs need their internal arrow visible — undo appearance reset */
  appearance: auto;
  -webkit-appearance: auto;
}
.form-group input[type="file"] {
  padding: 8px 10px;
  background: #f8fafc;
  cursor: pointer;
}
.form-group input[type="checkbox"], .form-group input[type="radio"] {
  width: auto;
  padding: 0;
}
.form-group input:hover, .form-group select:hover, .form-group textarea:hover {
  border-color: #c9cdd3;
}
.form-group input:focus, .form-group select:focus, .form-group textarea:focus {
  outline: none;
  border-color: var(--primary);
  box-shadow: 0 0 0 3px rgba(241, 128, 36, 0.16);
  background: #fffdfa;
}
/* Invalid-input styling: .input-error (legacy), .is-invalid (new shared name).
   Also covers nested checkbox-group invalidation for the days picker etc. */
.form-group input.input-error, .form-group select.input-error, .form-group textarea.input-error,
.form-group input.is-invalid, .form-group select.is-invalid, .form-group textarea.is-invalid,
.form-group .checkbox-group.is-invalid {
  border-color: var(--danger);
  box-shadow: 0 0 0 3px rgba(220,53,69,0.1);
}
.form-group input.input-error:focus,
.form-group input.is-invalid:focus,
.form-group select.is-invalid:focus,
.form-group textarea.is-invalid:focus { border-color: var(--danger); box-shadow: 0 0 0 3px rgba(220,53,69,0.15); }
.form-group .checkbox-group.is-invalid {
  padding: 6px 10px;
  border: 1.5px solid var(--danger);
  border-radius: var(--radius-md);
}

/* Per-field error label. Two class names supported so old and new templates
   keep working; keep them visually identical. */
.field-error,
.form-error {
  display: block;
  font-size: 12px;
  color: var(--danger);
  margin-top: 6px;
  font-weight: 500;
  line-height: 1.35;
}
.field-error::before,
.form-error::before {
  /* tiny inline-block dot so the message reads as "alert" not "label" */
  content: "";
  display: inline-block;
  width: 5px; height: 5px;
  border-radius: 50%;
  background: var(--danger);
  margin-right: 6px;
  vertical-align: middle;
  transform: translateY(-1px);
}
.required-star { color: var(--danger); margin-left: 2px; }

/* === Language switcher === */
.lang-switch {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 3px;
  background: rgba(0,0,0,0.04);
  border-radius: 999px;
}
.lang-switch-btn {
  display: inline-block;
  padding: 4px 10px;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: .04em;
  color: var(--text-muted);
  background: transparent;
  border: 0;
  border-radius: 999px;
  cursor: pointer;
  font-family: inherit;
  transition: background var(--transition-fast), color var(--transition-fast);
}
.lang-switch-btn:hover { color: var(--text-primary); }
.lang-switch-btn--active {
  background: var(--surface);
  color: var(--text-primary);
  cursor: default;
  box-shadow: 0 1px 2px rgba(0,0,0,0.06);
}
.form-group input::placeholder, .form-group textarea::placeholder { color:var(--text-muted); }
.form-group textarea { resize:vertical; min-height:80px; }
.form-row { display:grid; grid-template-columns:1fr 1fr; gap:16px; }
.form-actions { display:flex; gap:10px; padding-top:8px; }

/* Per-group student status badges */
.sv-status-active { color: var(--success); }
.sv-status-frozen { color: #1e88e5; }
.sv-status-archived { color: var(--text-muted); }
.sv-billing-note { font-size: 11px; font-weight: 400; opacity: 0.8; }
.gv-student-status-badge {
  display: inline-flex; align-items: center;
  padding: 2px 8px;
  border-radius: var(--radius-full);
  font-size: 11px; font-weight: 600;
  margin-left: 4px;
}
.gv-status-frozen {
  background: #e3f2fd;
  color: #1e88e5;
}


.checkbox-group { display:flex; flex-wrap:wrap; gap:8px; }
.checkbox-group label {
  display:inline-flex; align-items:center; gap:6px;
  padding:8px 14px;
  background:var(--bg-body); border:1px solid var(--border);
  border-radius:var(--radius-sm);
  font-size:13px; font-weight:500; color:var(--text-secondary);
  cursor:pointer; transition: var(--anim-ui); user-select:none;
}
.checkbox-group label:hover { border-color:var(--primary); color:var(--text-primary); transform: translateY(-1px); }
.checkbox-group input[type="checkbox"] { width:16px; height:16px; accent-color:var(--primary); }
.checkbox-group label:has(input:checked) {
  background:var(--primary-bg); border-color:var(--primary); color:var(--primary);
}

/* === Data Table === */
.data-table {
  width:100%; border-collapse:collapse;
  background: var(--surface);
  border-radius:var(--radius-lg);
  overflow:hidden;
  border:1px solid var(--border);
  box-shadow:var(--shadow-card);
}
.data-table thead th {
  padding:14px 16px;
  text-align:left;
  font-size:12px; font-weight:600;
  color:var(--text-secondary);
  background:#f8f9fb;
  border-bottom:1px solid var(--border);
  text-transform: uppercase;
  letter-spacing: 0.4px;
}
.data-table tbody td {
  padding:14px 16px;
  font-size:14px;
  color:var(--text-primary);
  border-bottom:1px solid var(--border-light);
  vertical-align:middle;
}
.data-table tbody tr:last-child td { border-bottom:none; }
.data-table tbody tr { transition: var(--anim-ui); }
.data-table tbody tr:hover { background:var(--primary-bg); }

.table-link { color:var(--primary); font-weight:600; }
.table-link:hover { text-decoration:underline; }
.actions-cell { display:flex; gap:6px; align-items:center; }
.inline-form { display:inline; }

.tag {
  display: inline-flex; align-items: center;
  padding: 3px 10px;
  border-radius: var(--radius-full);
  font-size: 12px; font-weight: 600; letter-spacing: .01em;
  background: var(--primary-bg);
  color: var(--primary-active);
  border: 0;
}
.muted { color:var(--text-muted); }

/* === Empty State === */
.empty-state {
  text-align: center;
  padding: 56px 20px 48px;
  background: linear-gradient(180deg, var(--surface) 0%, var(--surface-muted) 100%);
  border-radius: var(--radius-xl);
  border: 1px dashed var(--border-strong);
  box-shadow: var(--shadow-sm);
}
.empty-state-icon {
  width: 64px; height: 64px;
  margin: 0 auto 18px;
  border-radius: var(--radius-full);
  background: var(--primary-bg);
  display: flex; align-items: center; justify-content: center;
  color: var(--primary);
  box-shadow: inset 0 0 0 6px var(--surface);
}
.empty-state-icon svg { stroke: var(--primary); }
.empty-state p { color: var(--text-secondary); font-size: 15px; margin-bottom: 18px; }

/* === Alerts === */
.alert {
  padding:12px 16px;
  border-radius:var(--radius-sm);
  font-size:14px; margin-bottom:20px; font-weight:500;
}
.alert-error { background:var(--danger-bg); color:var(--danger); border:1px solid #fecaca; }
.alert-success { background:var(--success-bg); color:var(--success); border:1px solid #bbf7d0; }
.alert-info { background:var(--info-bg); color:var(--info); border:1px solid #bae6fd; }
.alert-warning { background:var(--warning-bg); color:var(--warning-fg); border:1px solid var(--method-cash-border); }

/* === Avatars === */
.avatar {
  border-radius:var(--radius-full);
  display:inline-flex; align-items:center; justify-content:center;
  font-weight:600; flex-shrink:0; color:#fff;
}
.avatar-sm { width:32px; height:32px; font-size:12px; }
.avatar-md { width:38px; height:38px; font-size:14px; }
.avatar-lg { width:48px; height:48px; font-size:16px; }
.avatar-gradient-1 { background:#f97316; }
.avatar-gradient-2 { background:#ec4899; }
.avatar-gradient-3 { background:var(--accent-teal); }
.avatar-gradient-4 { background:#eab308; }
.avatar-gradient-5 { background:#8b5cf6; }
.avatar-gradient-6 { background:#06b6d4; }

/* === Detail View (shared) === */
.detail-grid {
  display:grid;
  grid-template-columns:repeat(auto-fill, minmax(300px, 1fr));
  gap:20px; margin-bottom:24px;
}
.detail-card h3 {
  font-size:15px; font-weight:600;
  display:flex; align-items:center; gap:8px;
  margin-bottom:16px; padding-bottom:12px;
  border-bottom:1px solid var(--border-light);
}
.detail-card h3 svg { color:var(--text-muted); }
.detail-row {
  display:flex; justify-content:space-between;
  padding:8px 0; font-size:14px;
  border-bottom:1px solid var(--border-light);
}
.detail-row:last-child { border-bottom:none; }
.detail-label { font-weight:500; color:var(--text-secondary); }

.section-block { margin-bottom:24px; }
.section-block h2 {
  font-size:17px; font-weight:600;
  margin-bottom:16px;
  display:flex; align-items:center; gap:8px;
}

/* === Filter Bar === */
.filter-bar {
  background: var(--surface); border:1px solid var(--border);
  border-radius:var(--radius-lg);
  padding:16px 20px; margin-bottom:16px;
  box-shadow:var(--shadow-card);
  transition: box-shadow var(--transition-base);
}
.filter-bar:focus-within {
  box-shadow: var(--shadow-md);
}
.filter-form { display:flex; align-items:center; gap:10px; flex-wrap:wrap; }
.filter-form input, .filter-form select {
  padding:8px 14px;
  background: var(--surface); border:1px solid var(--border);
  border-radius:var(--radius-full);
  color:var(--text-primary);
  font-family:inherit; font-size:13px;
  transition: border-color var(--transition-fast);
  min-width:150px;
}
.filter-form input { flex:1; min-width:200px; }
.filter-form input:focus, .filter-form select:focus {
  outline:none; border-color:var(--primary);
  box-shadow:0 0 0 3px var(--primary-ring);
}

/* === Status Badges ===
   Soft-pill pattern: muted tinted background, deeper-tone text, no
   border. Reads as a label, not a button — easier to scan a long list. */
.status-badge {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding: 3px 10px;
  border-radius: var(--radius-full);
  font-size: 12px;
  font-weight: 600;
  letter-spacing: .01em;
  text-transform: capitalize;
  border: 0;
  white-space: nowrap;
}
.status-paid    { background: var(--success-bg); color: var(--success-fg); }
.status-partial { background: var(--warning-bg); color: var(--warning-fg); }
.status-unpaid  { background: var(--danger-bg);  color: var(--danger-fg); }
.status-balance-positive { background: var(--success-bg); color: var(--success-fg); }
.status-balance-negative { background: var(--danger-bg);  color: var(--danger-fg); }
.status-balance-zero     { background: var(--neutral-bg); color: var(--neutral-fg); }
/* Generic role/state pills used in detail pages and lists. */
.status-active   { background: var(--success-bg); color: var(--success-fg); }
.status-inactive { background: var(--warning-bg); color: var(--warning-fg); }
.status-frozen   { background: var(--info-bg);    color: var(--info-fg); }
.status-archived { background: var(--neutral-bg); color: var(--neutral-fg); }
.status-completed { background: var(--neutral-bg); color: var(--neutral-fg); }

/* === Modal === */
.modal-overlay {
  position: fixed;
  top: 0; left: 0;
  width: 100%; height: 100%;
  background: rgba(15, 23, 42, 0.42);
  backdrop-filter: blur(6px) saturate(120%);
  -webkit-backdrop-filter: blur(6px) saturate(120%);
  display: flex; align-items: center; justify-content: center;
  z-index: 9999;
  padding: 16px;
  animation: fadeIn 0.18s ease;
}
.modal-overlay.hiding { animation: fadeOut 0.15s ease forwards; }
@keyframes fadeIn { from { opacity: 0 } to { opacity: 1 } }
@keyframes fadeOut { from { opacity: 1 } to { opacity: 0 } }

.modal-box {
  background: var(--surface);
  border-radius: var(--radius-2xl);
  padding: 28px 28px 24px;
  max-width: 440px;
  width: 100%;
  box-shadow: var(--shadow-xl);
  border: 1px solid var(--border-light);
  text-align: center;
  animation: modalIn 0.22s cubic-bezier(0.34, 1.56, 0.64, 1);
}
@keyframes modalIn {
  from { transform: translateY(12px) scale(0.97); opacity: 0 }
  to   { transform: translateY(0)    scale(1);    opacity: 1 }
}

.modal-icon {
  width: 52px; height: 52px;
  border-radius: var(--radius-full);
  display: flex; align-items: center; justify-content: center;
  margin: 0 auto 14px;
}
/* Type variants — paired with the status colour tokens so soft pill
   badges and modal accents look part of the same family. */
.modal-icon-danger  { background: var(--danger-bg); }  .modal-icon-danger  svg { stroke: var(--danger); }
.modal-icon-warning { background: var(--warning-bg); } .modal-icon-warning svg { stroke: var(--warning); }
.modal-icon-success { background: var(--success-bg); } .modal-icon-success svg { stroke: var(--success); }
.modal-icon-info    { background: var(--info-bg); }    .modal-icon-info    svg { stroke: var(--info); }
/* Legacy class names still used by older callers. */
.modal-icon.danger  { background: var(--danger-bg); }  .modal-icon.danger  svg { stroke: var(--danger); }

.modal-box h3 { font-size: 18px; font-weight: 700; margin-bottom: 8px; color: var(--text-primary); letter-spacing: -0.01em; }
.modal-box p  { font-size: 14px; color: var(--text-secondary); margin-bottom: 22px; line-height: 1.55; }
.modal-actions { display: flex; gap: 10px; justify-content: center; }

/* Confirm button colours per type — share the .btn hover-lift + focus
   ring from the unified button block above. */
.modal-btn-danger  { background: var(--danger); color: #fff; border-color: transparent; }
.modal-btn-danger:hover  { background: var(--danger-fg); }
.modal-btn-warning { background: var(--warning); color: #fff; border-color: transparent; }
.modal-btn-warning:hover { background: var(--method-cash-fg); }
.modal-btn-success { background: var(--success); color: #fff; border-color: transparent; }
.modal-btn-success:hover { background: #15803d; }
.modal-btn-info    { background: var(--info); color: #fff; border-color: transparent; }
.modal-btn-info:hover    { background: var(--info-fg); }

/* === Global portal dropdown === */
.drop-menu {
  display: none;
  position: fixed;
  z-index: 9100;
  background: var(--surface);
  border: 1px solid var(--border-light);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-lg);
  padding: 6px;
  min-width: 165px;
  animation: dropMenuIn 0.14s cubic-bezier(0.34, 1.56, 0.64, 1);
}
@keyframes dropMenuIn {
  from { opacity: 0; transform: scale(0.96) translateY(-4px); }
  to   { opacity: 1; transform: scale(1)    translateY(0);    }
}
/* Items inside the portal inherit all the per-page dropdown item styles */
.drop-menu a, .drop-menu button {
  display: flex; align-items: center; gap: 8px;
  width: 100%; padding: 9px 12px;
  border-radius: 8px;
  font-size: 13px; font-weight: 500;
  color: var(--text-primary);
  text-decoration: none;
  background: none; border: none;
  cursor: pointer; font-family: inherit; text-align: left;
  transition: background var(--transition-fast), color var(--transition-fast);
  box-sizing: border-box;
}
.drop-menu a:hover, .drop-menu button:hover { background: var(--surface-hover); }
.drop-menu .sl-dropdown-danger,
.drop-menu .gv-sdd-danger,
.drop-menu .gl-menu-danger,
.drop-menu .teacher-dd-danger { color: var(--danger-fg); }
.drop-menu .sl-dropdown-danger:hover,
.drop-menu .gv-sdd-danger:hover,
.drop-menu .gl-menu-danger:hover,
.drop-menu .teacher-dd-danger:hover { background: var(--danger-bg); color: var(--danger-fg); }
.drop-menu .sl-dropdown-success,
.drop-menu .gv-sdd-success,
.drop-menu .gv-sdd-action { color: var(--success-fg); }
.drop-menu .sl-dropdown-success:hover,
.drop-menu .gv-sdd-success:hover,
.drop-menu .gv-sdd-action:hover { background: var(--success-bg); color: var(--success-fg); }
.drop-menu form { margin: 0; padding: 0; }

/* === Toast === */
.toast-container {
  position: fixed; top: 20px; right: 20px; z-index: 10000;
  display: flex; flex-direction: column; gap: 10px;
}
.toast {
  background: var(--surface);
  border: 1px solid var(--border-light);
  border-radius: var(--radius-lg);
  padding: 12px 18px;
  font-size: 14px; font-weight: 500;
  display: flex; align-items: center; gap: 10px;
  box-shadow: var(--shadow-lg);
  animation: toastIn 0.32s cubic-bezier(0.34, 1.56, 0.64, 1);
  color: var(--text-primary);
  min-width: 220px;
}
@keyframes toastIn { from { opacity: 0; transform: translateX(20px) } to { opacity: 1; transform: translateX(0) } }
.toast-out { animation:slideOut 0.3s ease forwards; }
@keyframes slideIn { from{transform:translateX(100%);opacity:0} to{transform:translateX(0);opacity:1} }
@keyframes slideOut { from{transform:translateX(0);opacity:1} to{transform:translateX(100%);opacity:0} }

/* ============================================================
   POLISH — Typography, Spacing, Animations, UX Improvements
   ============================================================ */

/* === 1. Typography Hierarchy === */
.page-title {
  font-size: 28px;
  font-weight: 700;
  color: var(--text-primary);
  letter-spacing: -0.5px;
  margin-bottom: var(--space-3);
  line-height: 1.2;
}
.section-title {
  font-size: 18px;
  font-weight: 600;
  color: var(--text-primary);
  margin-bottom: var(--space-2);
  letter-spacing: -0.2px;
}
.label {
  font-size: 13px;
  font-weight: 500;
  color: var(--text-secondary);
}
.text-lg { font-size: 18px; }
.text-sm { font-size: 13px; }
.text-xs { font-size: 11px; }
.text-muted { color: var(--text-muted); }
.text-bold { font-weight: 700; }
.text-semibold { font-weight: 600; }

/* === 2. Global Input Focus Improvement === */
input, select, textarea {
  padding: 10px 14px;
  border-radius: var(--radius-sm);
  border: 1.5px solid var(--border);
  transition: var(--anim-ui);
  background: var(--surface);
  font-family: inherit;
  font-size: 14px;
  color: var(--text-primary);
}
input:focus, select:focus, textarea:focus {
  border-color: var(--primary);
  box-shadow: 0 0 0 3px var(--primary-ring);
  outline: none;
}
input:hover, select:hover, textarea:hover {
  border-color: #c9cdd3;
}
input::placeholder, textarea::placeholder {
  color: var(--text-muted);
}

/* === 3. Spacing Utility Classes (8px scale) === */
.mt-0 { margin-top: 0; }
.mt-1 { margin-top: var(--space-1); }
.mt-2 { margin-top: var(--space-2); }
.mt-3 { margin-top: var(--space-3); }
.mt-4 { margin-top: var(--space-4); }
.mt-5 { margin-top: var(--space-5); }
.mt-6 { margin-top: var(--space-6); }

.mb-0 { margin-bottom: 0; }
.mb-1 { margin-bottom: var(--space-1); }
.mb-2 { margin-bottom: var(--space-2); }
.mb-3 { margin-bottom: var(--space-3); }
.mb-4 { margin-bottom: var(--space-4); }

.pt-0 { padding-top: 0; }
.pt-2 { padding-top: var(--space-2); }
.pt-3 { padding-top: var(--space-3); }
.pt-4 { padding-top: var(--space-4); }

.pb-2 { padding-bottom: var(--space-2); }
.pb-3 { padding-bottom: var(--space-3); }
.pb-4 { padding-bottom: var(--space-4); }

.gap-1 { gap: var(--space-1); }
.gap-2 { gap: var(--space-2); }
.gap-3 { gap: var(--space-3); }
.gap-4 { gap: var(--space-4); }

/* === 4. Form Grid Layout === */
.form-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--space-3);
}
.form-grid .form-group-full {
  grid-column: 1 / -1;
}
@media (max-width: 600px) {
  .form-grid { grid-template-columns: 1fr; }
}

/* === 5. Page Fade-in Animation === */
.content-area {
  animation: pageFadeIn 0.22s cubic-bezier(0.2, 0.7, 0.3, 1);
}
@keyframes pageFadeIn {
  from {
    opacity: 0;
    transform: translateY(6px);
  }
  to {
    opacity: 1;
    transform: none;
  }
}

/* === 6. Enhanced Button Micro-interactions === */
.btn {
  transition: var(--anim-ui);
}
.btn:hover {
  transform: translateY(-1px);
}
.btn:active {
  transform: translateY(0) scale(0.98);
}

/* === 7. Enhanced Card Interactions === */
.stat-card,
.detail-card,
.section-block,
.form-card {
  transition: var(--anim-ui-smooth);
}
.stat-card:hover {
  transform: translateY(-3px);
  box-shadow: var(--shadow-card-hover);
}

/* === 8. Enhanced Table Readability === */
.data-table thead th {
  font-size: 12px;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--text-secondary);
  padding: 14px 16px;
  background: #f8f9fb;
  font-weight: 600;
}
.data-table tbody td {
  padding: 14px 16px;
  font-size: 14px;
}
.data-table tbody tr {
  transition: background 0.15s ease;
}
.data-table tbody tr:hover {
  background: #fafafa;
}

/* === 9. Content Area Container === */
.content-area {
  padding: var(--space-4);
}

/* === 10. Improved Empty States === */
.empty-state {
  padding: var(--space-8) var(--space-3);
}
.empty-state p {
  font-size: 15px;
  line-height: 1.6;
}

/* === 11. Section Divider === */
.section-divider {
  height: 1px;
  background: var(--border);
  margin: var(--space-4) 0;
}

/* === 12. Status Dot Indicators === */
.status-dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  display: inline-block;
  flex-shrink: 0;
}
.status-dot.active { background: var(--success); }
.status-dot.warning { background: var(--warning); }
.status-dot.danger { background: var(--danger); }
.status-dot.muted { background: var(--text-muted); }

/* === 13. Smooth Scrollbar for horizontal scroll === */
.horizontal-scroll {
  overflow-x: auto;
  scroll-behavior: smooth;
  -webkit-overflow-scrolling: touch;
}
/* Inherits the global scrollbar treatment — it used to carry its own
   greys and its own height, which made three different scrollbars visible
   on one page. */

/* === 14. Link Styles === */
a.link-primary {
  color: var(--primary);
  font-weight: 500;
  transition: var(--anim-ui-fast);
}
a.link-primary:hover {
  color: var(--primary-dark);
  text-decoration: underline;
}

/* === 15. Form Validation Indicators === */
.form-group.has-error input,
.form-group.has-error select,
.form-group.has-error textarea {
  border-color: var(--danger);
  box-shadow: 0 0 0 3px rgba(220, 38, 38, 0.1);
}
.form-group.has-error label {
  color: var(--danger);
}
.field-error {
  display: block;
  font-size: 12px;
  color: var(--danger);
  margin-top: 4px;
  font-weight: 500;
}
.form-group.has-success input,
.form-group.has-success select,
.form-group.has-success textarea {
  border-color: var(--success);
  box-shadow: 0 0 0 3px rgba(22, 163, 74, 0.1);
}
.input-error {
  border-color: var(--danger) !important;
  box-shadow: 0 0 0 3px rgba(220, 38, 38, 0.1) !important;
}

/* === 16. Button Loading States === */
.btn-loading {
  pointer-events: none;
  opacity: 0.75;
  position: relative;
  color: transparent !important;
}
.btn-loading::after {
  content: '';
  position: absolute;
  width: 16px;
  height: 16px;
  top: 50%;
  left: 50%;
  margin-top: -8px;
  margin-left: -8px;
  border: 2px solid rgba(255, 255, 255, 0.3);
  border-top-color: #fff;
  border-radius: 50%;
  animation: btnSpin 0.6s linear infinite;
}
.btn-secondary.btn-loading::after {
  border-color: rgba(0, 0, 0, 0.15);
  border-top-color: var(--text-secondary);
}
@keyframes btnSpin {
  to { transform: rotate(360deg); }
}

/* === 17. Skeleton Loaders === */
.skeleton {
  background: linear-gradient(90deg, #f0f0f0 25%, #e0e0e0 50%, #f0f0f0 75%);
  background-size: 200% 100%;
  animation: skeletonPulse 1.5s ease-in-out infinite;
  border-radius: var(--radius-sm);
}
.skeleton-text {
  height: 14px;
  margin-bottom: 8px;
  border-radius: 4px;
}
.skeleton-text:last-child {
  width: 60%;
}
.skeleton-circle {
  border-radius: var(--radius-full);
}
.skeleton-card {
  height: 120px;
  border-radius: var(--radius-lg);
}
@keyframes skeletonPulse {
  0% { background-position: 200% 0; }
  100% { background-position: -200% 0; }
}

/* === 18. Loading Spinner === */
.spinner {
  display: inline-block;
  width: 24px;
  height: 24px;
  border: 3px solid var(--border);
  border-top-color: var(--primary);
  border-radius: 50%;
  animation: btnSpin 0.7s linear infinite;
}
.spinner-sm { width: 16px; height: 16px; border-width: 2px; }
.spinner-lg { width: 40px; height: 40px; border-width: 4px; }
.spinner-center {
  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--space-6) 0;
}

/* === 19. Breadcrumb Navigation === */
.breadcrumb {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 4px;
  font-size: 13px;
  margin-bottom: var(--space-2);
  color: var(--text-muted);
}
.breadcrumb-item {
  display: inline-flex;
  align-items: center;
  gap: 4px;
}
.breadcrumb-item + .breadcrumb-item::before {
  content: '';
  display: inline-block;
  width: 16px;
  height: 16px;
  background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%239ca3af' stroke-width='2'%3E%3Cpolyline points='9 18 15 12 9 6'/%3E%3C/svg%3E") center/contain no-repeat;
  margin-right: 4px;
  flex-shrink: 0;
}
.breadcrumb-item a {
  color: var(--text-secondary);
  font-weight: 500;
  transition: color var(--transition-fast);
}
.breadcrumb-item a:hover {
  color: var(--primary);
}
.breadcrumb-item.active {
  color: var(--text-primary);
  font-weight: 600;
}

/* === 20. Alert Variants === */
.alert-warning { background: var(--warning-bg); color: var(--warning); border: 1px solid var(--method-cash-border); }
.alert-info { background: var(--info-bg); color: var(--info); border: 1px solid var(--method-card-border); }

/* ============================================================
   REDUCED MOTION
   Honour the OS-level "minimise animation" setting. Transitions collapse
   to ~1ms rather than 0 so transitionend listeners still fire, and the
   skeleton shimmer holds a steady tone instead of pulsing.
   ============================================================ */
@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
    scroll-behavior: auto !important;
  }
  .content-area { animation: none !important; }
  .skeleton { animation: none !important; opacity: 0.7; }
}

/* ============================================================
   TYPOGRAPHY SYSTEM
   Applied at the end so it wins over the per-page stylesheets without
   editing each of them.

   The split is deliberate: Manrope on text headings for warmth, Inter
   everywhere a glyph has to be read small or line up in a column.
   Numbers stay on Inter specifically for its tabular figures — in a
   proportional face, digits have different widths, so a column of money
   never aligns and a counter visibly jitters as it changes.
   ============================================================ */

body { font-family: var(--font-sans); }

/* --- Text headings: display face, tighter tracking as size grows --- */
h1, h2, h3, h4,
.page-title,
.page-header h1,
.sl-title,
.gl-title,
.tv-page-title,
.gv-page-title h1,
.sa-page-title,
.sa-modal-title,
.modal-box h3,
.login-lc-title,
.login-super-title,
.glogin-name,
.sv-name,
.sv-section-header h2,
.gv-attendance-header h2,
.gv-placeholder-panel h3,
.dash-schedule-title,
.reports-table-title,
.sa-section-title {
  font-family: var(--font-display);
  letter-spacing: -0.018em;
  line-height: 1.25;
}

/* Large headings need proportionally tighter tracking — letter-spacing that
   looks right at 14px reads loose at 28px. */
.page-title,
.sl-title,
.gl-title,
.tv-page-title,
.sa-page-title,
.gv-page-title h1,
.page-header h1 {
  letter-spacing: -0.028em;
}

/* --- Numbers: Inter, tabular figures, and now a real 800 --- */
.stat-number,
.att-summary-num,
.att-rate-val,
.att-lesson-num,
.dash-income-total,
.sa-stat-value,
.course-card-price,
.balance-text,
.sv-balance-pill,
.sv-ledger-amount,
.sv-method-chip-amount,
.gv-lb-pts-value,
.gv-award-total,
.gv-student-num,
.gl-row-num,
.gl-student-count,
.gl-cell-num,
.count-badge,
.reports-debt-amount,
.dash-income-total-debt {
  font-family: var(--font-sans);
  font-variant-numeric: tabular-nums;
  font-feature-settings: 'tnum' 1;
}

/* Any table cell holding a figure benefits from the same treatment. */
.sl-table td,
.gl-table td,
.sv-payments-table td,
.att-table td {
  font-variant-numeric: tabular-nums;
}

/* --- Body rhythm --- */
/* 1.6 is comfortable for prose but loose for dense UI rows; 1.55 keeps
   paragraphs readable without stretching table rows. */
body { line-height: 1.55; }
p { line-height: 1.65; }

/* Small uppercase labels need positive tracking — tight caps read as a
   solid block. */
.sl-table thead th,
.gl-table thead th,
.att-section-title,
.sa-table thead th {
  letter-spacing: 0.05em;
}

/* ============================================================
   FROSTED SURFACES
   Scoped deliberately. backdrop-filter forces the compositor to re-sample
   whatever sits behind the element, so it is applied only to things that
   are small, transient, or on a sparse page: modal scrims, dropdowns, and
   the login/blocked screens.

   Data surfaces — tables, cards, the sidebar — stay opaque. Frosting a
   50-row table means a recomposite on every scroll frame, which on the
   low-end Android devices this app runs on is the difference between
   smooth and visibly stuttering.
   ============================================================ */

.modal-overlay,
.sv-modal-overlay,
.gv-modal-overlay,
.tv-modal-overlay,
.sa-modal-overlay,
.sidebar-overlay {
  backdrop-filter: blur(6px) saturate(120%);
  -webkit-backdrop-filter: blur(6px) saturate(120%);
}

/* Floating menus: a light frost separates them from busy content behind
   without the hard edge of a fully opaque panel. These are small and only
   painted while open. */
.quick-add-dropdown,
.search-dropdown,
.header-user-dropdown,
.user-dropdown,
.sl-dropdown,
.gl-menu-dropdown,
.sv-dropdown,
.sv-print-dropdown,
.sv-payment-dropdown,
.teacher-card-dropdown,
.gv-student-dropdown {
  backdrop-filter: blur(14px) saturate(150%);
  -webkit-backdrop-filter: blur(14px) saturate(150%);
}

/* Translucency is only safe where the blur actually lands; without it the
   panel would show raw content straight through. */
@supports ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .quick-add-dropdown,
  .search-dropdown,
  .header-user-dropdown,
  .user-dropdown,
  .sl-dropdown,
  .gl-menu-dropdown,
  .sv-dropdown,
  .sv-print-dropdown,
  .sv-payment-dropdown,
  .teacher-card-dropdown,
  .gv-student-dropdown {
    background-color: color-mix(in srgb, var(--surface) 82%, transparent);
  }
}

/* The blur is decorative; someone who asked for less motion has usually
   also asked for less visual processing. */
@media (prefers-reduced-transparency: reduce) {
  .modal-overlay, .sv-modal-overlay, .gv-modal-overlay, .tv-modal-overlay,
  .sa-modal-overlay, .sidebar-overlay,
  .quick-add-dropdown, .search-dropdown, .header-user-dropdown, .user-dropdown,
  .sl-dropdown, .gl-menu-dropdown, .sv-dropdown, .sv-print-dropdown,
  .sv-payment-dropdown, .teacher-card-dropdown, .gv-student-dropdown {
    backdrop-filter: none !important;
    -webkit-backdrop-filter: none !important;
    background-color: var(--surface);
  }
}
