:root {
  /* Design tokens — the source of truth. Do not add new colors here;
     derive tints from these with color-mix()/rgba in component CSS. */
  --bg-primary: #0A0E14;
  --bg-card: #10151F;
  --border-card: #1E2530;
  --accent-primary: #00D9A0;
  --accent-secondary: #00B8D4;
  --text-muted: #8A8F98;

  /* Structural tokens (layout, not palette) */
  --font-sans: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", sans-serif;
  --container-max: 1120px;
  --radius-sm: 8px;
  --radius-md: 12px;
  --radius-lg: 16px;
  --radius-xl: 24px;
}

/* ── Auth-gate flash prevention ───────────────────────────────────────────
   Every page with a <body data-auth="protected"|"guest-only"> attribute
   (js/auth.js's applyAuthRouting()) decides whether to redirect via an
   ASYNC /auth/me call -- but script tags at the bottom of <body> (the
   convention every page here follows) only start running after the
   browser has already parsed and painted the page's full markup once.
   Without this rule, that gap let the wrong content paint first and
   actually be visible for a moment: a protected page's full shell (plus
   any page-script's own early error toast, since toasts append to
   <body> too) before a redirect to login.html, or -- reported directly --
   login.html's own full form before an already-authenticated visitor got
   bounced to their real destination.

   This is the exact same visibility-hidden technique applyAuthRouting's
   own bfcache-restore fix already uses (see auth.js's header comment on
   that), just applied to the ordinary first-load path too: hide via a
   plain attribute selector (works before any script has run, since the
   attribute is already in the raw HTML) and let applyAuthRouting() add
   .auth-ready the moment it confirms this page is actually staying (no
   redirect pending) -- never on the two branches that DO redirect, since
   the page is navigating away regardless and should stay invisible. Every
   page carrying data-auth loads both this stylesheet and auth.js (see
   this file's own module docstring on scope), so nothing is ever left
   permanently hidden with no code to reveal it. */
body[data-auth]:not(.auth-ready) {
  visibility: hidden;
}

/* ==========================================================================
   App design system (Phase 0 of the unified in-app visual redesign).

   Scope: authenticated app pages (Dashboard, Connections, Backups, Restore,
   API Keys, Billing, Settings, Profile, Notifications, Help Center, Admin
   Dashboard) and the auth pages (login/signup/forgot-password/reset-
   password). Deliberately NOT wired into the tokens above -- index.html,
   terms.html and privacy.html keep rendering off --bg-primary/--bg-card/
   --accent-primary/--accent-secondary/--text-muted exactly as before,
   untouched by this redesign. New "--app-*" names below are additive so
   nothing repaints until a page is deliberately migrated to them in a
   later phase.

   Defined here (not a second file) per this redesign's own instruction to
   extend the existing token system rather than create a parallel one.
   Applied nowhere yet -- this block is foundation only.
   ========================================================================== */
:root {
  /* Color. Success is a status color, not a brand color -- reserve it for
     backup/connection health signals; never style an entire screen green.

     Updated to the reference palette (Connections page rebuild,
     IMG_4128.PNG) as the new SITE-WIDE default -- not page-scoped this
     time, per explicit instruction that this palette should be adopted
     everywhere over time. Every authenticated page already consumes these
     exact token NAMES via app-shell.css/app-dashboard.css/admin-
     dashboard.css/monitoring-page.css/app-auth.css/app-help.css rather
     than hardcoded hex, so updating the values here is what makes the
     shift actually apply site-wide -- no page-by-page repaint needed.
     The shift itself is subtle (both old and new are very dark navy) by
     design: --app-success/--app-warning/--app-danger/--app-info already
     matched the reference's accent-green/-/accent-red/accent-blue exactly,
     so only background/surface/text needed to move. */
  /* 3-tier background contrast, deliberately visibly distinct (not just
     different in hex) -- sidebar/topnav darkest, main content background
     one step lighter, cards lightest of all so they read as "raised"
     above the content behind them. */
  --app-bg-base: #0A0E1A;
  --app-bg: var(--app-bg-base);
  --app-surface: #101830;
  --app-surface-elevated: #141C36;
  --app-sidebar-bg: #0A1220;
  --app-topnav-bg:
    radial-gradient(circle at 12% -30%, color-mix(in srgb, #1E295E 45%, transparent) 0%, transparent 55%),
    radial-gradient(circle at 88% -30%, color-mix(in srgb, #1E295E 45%, transparent) 0%, transparent 55%),
    #0A0E1A;
  --app-border: rgba(255, 255, 255, 0.08);
  --app-text-primary: #F8FAFC;
  --app-text-secondary: #94A3B8;
  --app-text-muted: #94A3B8;
  --app-text-dim: #64748B;
  --app-success: #10B981;
  --app-warning: #F59E0B;
  --app-danger: #EF4444;
  --app-info: #3B82F6;
  /* Named accent vocabulary matching Connections page */
  --app-accent-green: #10B981;
  --app-accent-blue: #3B82F6;
  --app-accent-cyan: #00E5FF;
  --app-accent-purple: #8B5CF6;
  --app-accent-red: #EF4444;

  /* Ambient radial navy gradient over base matching Connections reference */
  --app-bg-gradient:
    radial-gradient(at 30% 0%, color-mix(in srgb, #1E295E 35%, transparent) 0, transparent 45%),
    radial-gradient(at 90% 60%, color-mix(in srgb, #1E295E 25%, transparent) 0, transparent 50%),
    #0A0E1A;

  /* Layout */
  --app-container-max: 1440px;
  --app-grid-columns: 12;

  /* Spacing scale -- the ONLY spacing values used in app-page CSS added
     from Phase 1 onward. No arbitrary spacing alongside these. */
  --space-8: 8px;
  --space-16: 16px;
  --space-24: 24px;
  --space-32: 32px;
  --space-48: 48px;
  --space-64: 64px;

  /* Typography. Hierarchy comes from size/weight first, color second. */
  --font-app-sans: "Geist", system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", sans-serif;
  --text-body-size: 16px;
  --text-body-weight: 450;
  --text-description-size: 14px;
  --text-label-size: 13px;
  --text-label-weight: 600; /* not specified by the brief; matches typical uppercase-label legibility at 13px -- flagged as a judgment call */
  --text-label-letter-spacing: 1.4px;
  --text-metric-size: 34px;
  --text-metric-weight: 700;
  --text-metric-hero-size: 48px;
  --text-metric-hero-weight: 700;

  /* Icons. Lucide only, stroke 1.75, 20px -- see js/icons.js's
     buildLucideIcon(), which is the actual application point since icons
     are hand-built inline SVG, not CSS-driven. These mirror its defaults
     for documentation/consistency. */
  --icon-size: 20px;
  --icon-stroke-width: 1.75;

  /* Motion. No bounce/scale, ever -- hover is a border/shadow change only. */
  --motion-duration: 180ms;
  --motion-ease: ease-out;

  /* --app-glass-bg-elevated kept (not --app-glass-bg/-border/-blur/
     -radius, all removed) -- the previous "heavy indigo glass" nav/
     sidebar exploration is superseded by this rebuild's flatter, solid
     --app-sidebar-bg/--app-topnav-bg above, but --app-glass-bg-elevated
     is still used as a non-blurred elevated surface (e.g. modals) where
     a plain --app-surface-elevated reads too close to its own card
     background. */
  --app-glass-bg-elevated: rgba(255, 255, 255, 0.09);
}

/* ==========================================================================
   Theme foundation (Phase 3.1).

   New semantic tokens are theme-aware and intentionally keep the existing
   --app-* names as compatibility aliases. Major page palettes are not
   migrated here; they can move from page-local colors to these tokens in
   later, page-specific phases.
   ========================================================================== */
:root {
  color-scheme: dark;

  --color-surface-canvas: #0A0E1A;
  --color-surface-primary: #101830;
  --color-surface-secondary: #101830;
  --color-surface-elevated: #141C36;
  --color-surface-hover: rgba(255, 255, 255, 0.06);
  --color-surface-overlay: rgba(2, 6, 23, 0.72);
  --color-surface-sidebar: var(--sidebar-bg-gradient);
  --color-surface-topbar:
    radial-gradient(circle at 12% -30%, color-mix(in srgb, #1E295E 45%, transparent) 0%, transparent 55%),
    radial-gradient(circle at 88% -30%, color-mix(in srgb, #1E295E 45%, transparent) 0%, transparent 55%),
    #0A0E1A;

  --color-text-primary: #F8FAFC;
  --color-text-secondary: #94A3B8;
  --color-text-muted: #94A3B8;
  --color-text-disabled: #64748B;
  --color-text-inverse: #0F172A;

  --color-border-subtle: rgba(255, 255, 255, 0.06);
  --color-border-default: rgba(255, 255, 255, 0.08);
  --color-border-primary: var(--color-border-default);
  --color-border-strong: rgba(255, 255, 255, 0.16);
  --color-border-focus: #3B82F6;

  --color-brand: #10B981;
  --color-brand-hover: #059669;
  --color-brand-active: #047857;
  --color-brand-soft: rgba(16, 185, 129, 0.14);
  --color-brand-border: rgba(16, 185, 129, 0.28);
  --color-brand-foreground: #ECFDF5;

  --color-success: #10B981;
  --color-success-soft: rgba(16, 185, 129, 0.14);
  --color-success-border: rgba(16, 185, 129, 0.28);
  --color-success-text: #A7F3D0;
  --color-success-on-strong: #052E24;

  --color-info: #3B82F6;
  --color-info-hover: #2563EB;
  --color-info-soft: rgba(59, 130, 246, 0.14);
  --color-info-border: rgba(59, 130, 246, 0.28);
  --color-info-text: #BFDBFE;
  --color-info-on-strong: #FFFFFF;

  --color-cyan: #00E5FF;
  --color-cyan-soft: rgba(0, 229, 255, 0.12);
  --color-cyan-border: rgba(0, 229, 255, 0.28);

  --color-warning: #F59E0B;
  --color-warning-soft: rgba(245, 158, 11, 0.14);
  --color-warning-border: rgba(245, 158, 11, 0.3);
  --color-warning-text: #FDE68A;
  --color-warning-on-strong: #111827;

  --color-danger: #EF4444;
  --color-danger-hover: #DC2626;
  --color-danger-soft: rgba(239, 68, 68, 0.14);
  --color-danger-border: rgba(239, 68, 68, 0.3);
  --color-danger-text: #FECACA;
  --color-danger-on-strong: #FFFFFF;

  --color-purple: #8B5CF6;
  --color-purple-soft: rgba(139, 92, 246, 0.14);

  --color-focus-ring: var(--color-info);
  --color-selected-bg: var(--color-info-soft);
  --color-selected-border: var(--color-info-border);
  --color-disabled-bg: rgba(148, 163, 184, 0.12);
  --color-disabled-border: rgba(148, 163, 184, 0.18);
  --color-disabled-text: var(--color-text-disabled);

  --color-shadow-card: rgba(0, 0, 0, 0.24);
  --color-shadow-modal: rgba(0, 0, 0, 0.45);

  --app-bg-base: var(--color-surface-canvas);
  --app-bg: var(--color-surface-canvas);
  --app-surface: var(--color-surface-primary);
  --app-surface-secondary: var(--color-surface-secondary);
  --app-surface-elevated: var(--color-surface-elevated);
  --app-sidebar-bg: var(--color-surface-sidebar);
  --app-topnav-bg: var(--color-surface-topbar);
  --app-bg-gradient:
    radial-gradient(at 30% 0%, color-mix(in srgb, #1E295E 35%, transparent) 0, transparent 45%),
    radial-gradient(at 90% 60%, color-mix(in srgb, #1E295E 25%, transparent) 0, transparent 50%),
    var(--color-surface-canvas);
  --app-border: var(--color-border-default);
  --app-border-strong: var(--color-border-strong);
  --app-text-primary: var(--color-text-primary);
  --app-text-secondary: var(--color-text-secondary);
  --app-text-muted: var(--color-text-muted);
  --app-text-dim: var(--color-text-disabled);
  --app-success: var(--color-success);
  --app-warning: var(--color-warning);
  --app-danger: var(--color-danger);
  --app-info: var(--color-info);
  --app-accent-green: var(--color-brand);
  --app-accent-blue: var(--color-info);
  --app-accent-cyan: var(--color-cyan);
  --app-accent-purple: var(--color-purple);
  --app-accent-red: var(--color-danger);
  --app-focus-ring: var(--color-focus-ring);
  --app-glass-bg-elevated: var(--color-surface-elevated);
}

:root[data-theme="light"] {
  color-scheme: light;

  --color-surface-canvas: #F7F9FC;
  --color-surface-primary: #FFFFFF;
  --color-surface-secondary: #F8FAFC;
  --color-surface-elevated: #FFFFFF;
  --color-surface-hover: #F8FAFC;
  --color-surface-overlay: rgba(15, 23, 42, 0.42);
  --color-surface-topbar: #FFFFFF;

  --color-text-primary: #0F172A;
  --color-text-secondary: #475569;
  --color-text-muted: #64748B;
  --color-text-disabled: #94A3B8;
  --color-text-inverse: #FFFFFF;

  --color-border-subtle: #F1F5F9;
  --color-border-default: #E2E8F0;
  --color-border-primary: var(--color-border-default);
  --color-border-strong: #CBD5E1;
  --color-border-focus: #2563EB;

  --color-brand: #10B981;
  --color-brand-hover: #059669;
  --color-brand-active: #047857;
  --color-brand-soft: #ECFDF5;
  --color-brand-border: #A7F3D0;
  --color-brand-foreground: #052E24;

  --color-success: #16A34A;
  --color-success-soft: #F0FDF4;
  --color-success-border: #BBF7D0;
  --color-success-text: #166534;
  --color-success-on-strong: #FFFFFF;

  --color-info: #2563EB;
  --color-info-hover: #1D4ED8;
  --color-info-soft: #EFF6FF;
  --color-info-border: #BFDBFE;
  --color-info-text: #1D4ED8;
  --color-info-on-strong: #FFFFFF;

  --color-cyan: #0891B2;
  --color-cyan-soft: #ECFEFF;
  --color-cyan-border: #A5F3FC;

  --color-warning: #D97706;
  --color-warning-soft: #FFFBEB;
  --color-warning-border: #FDE68A;
  --color-warning-text: #92400E;
  --color-warning-on-strong: #FFFFFF;

  --color-danger: #DC2626;
  --color-danger-hover: #B91C1C;
  --color-danger-soft: #FEF2F2;
  --color-danger-border: #FECACA;
  --color-danger-text: #991B1B;
  --color-danger-on-strong: #FFFFFF;

  --color-purple: #7C3AED;
  --color-purple-soft: #F5F3FF;

  --color-focus-ring: var(--color-info);
  --color-selected-bg: var(--color-info-soft);
  --color-selected-border: var(--color-info-border);
  --color-disabled-bg: #F1F5F9;
  --color-disabled-border: #E2E8F0;
  --color-disabled-text: #94A3B8;

  --color-shadow-card: rgba(15, 23, 42, 0.06);
  --color-shadow-modal: rgba(15, 23, 42, 0.18);

  --color-surface-sidebar: #FFFFFF;
  --app-bg-gradient: var(--color-surface-canvas);

  --sidebar-bg-gradient: #FFFFFF;
  --sidebar-active-bg: #ECFDF5;
  --sidebar-surface-bg: #FFFFFF;
  --sidebar-surface-border: #E2E8F0;
  --sidebar-accent-emerald: #10B981;
  --sidebar-accent-green-progress: #22C55E;
  --sidebar-accent-cyan: #06B6D4;
  --sidebar-accent-blue: #2563EB;
  --sidebar-active-indicator-gradient: #10B981;
  --sidebar-text-primary: #0F172A;
  --sidebar-text-nav-inactive: #334155;
  --sidebar-text-muted: #64748B;
}

/* ==========================================================================
   Sidebar exact-palette tokens (sourced from the Connections page reference,
   applied SITE-WIDE to app-shell.css's .app-sidebar -- confirmed intentional
   by Farshad; this is the one shared-chrome component this task authorizes
   going global, unlike the page-scoped Connections-only work above it).

   Deliberately --sidebar-* prefixed rather than the bare --color-text-primary/
   --text-muted/--accent-* names the design brief used: this file already
   has unprefixed --text-muted (line 9, legacy) and --accent-primary/
   -secondary (legacy) consumed by index.html/terms.html/privacy.html --
   redefining those bare names in a later :root block would silently repaint
   those untouched pages too (same specificity, last-in-source wins across
   ALL elements, not just a scoped subtree). The hex values below are exactly
   the brief's own values; only the token NAMES are namespaced to avoid that
   collision and to make "this is sidebar-only" explicit at the call site.
   ========================================================================== */
:root {
  --sidebar-bg-gradient: linear-gradient(135deg, #031338 0%, #01091d 100%);
  /* #081a42 at ~80% opacity, baked into one rgba() rather than a separate
     opacity property so it composites correctly over the gradient behind it. */
  --sidebar-active-bg: rgba(8, 26, 66, 0.8);
  --sidebar-surface-bg: #061536; /* Current Plan card background */
  --sidebar-surface-border: #12295a;
  --sidebar-accent-emerald: #10b981; /* primary accent */
  --sidebar-accent-green-progress: #22c55e; /* progress bar variant */
  --sidebar-accent-cyan: #00f2fe;
  --sidebar-accent-blue: #38bdf8;
  --sidebar-active-indicator-gradient: linear-gradient(180deg, #22c55e, #10b981);
  --sidebar-text-primary: #ffffff;
  --sidebar-text-nav-inactive: #8b9bb4;
  --sidebar-text-muted: #5a6e8c;
}

/* Geist, self-hosted (frontend/fonts/geist/) rather than pulled from a
   runtime CDN, per this codebase's existing no-third-party-runtime-
   dependency convention (see js/icons.js's header for the same reasoning
   applied to icons). Static per-weight files, not a variable font. */
@font-face {
  font-family: "Geist";
  src: url("../fonts/geist/geist-400.d8bce822db.woff2") format("woff2");
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "Geist";
  src: url("../fonts/geist/geist-500.b0a0867cda.woff2") format("woff2");
  font-weight: 500;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "Geist";
  src: url("../fonts/geist/geist-600.b1e6a1dd21.woff2") format("woff2");
  font-weight: 600;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "Geist";
  src: url("../fonts/geist/geist-700.04f948593d.woff2") format("woff2");
  font-weight: 700;
  font-style: normal;
  font-display: swap;
}
