/* ============================================================================
   IRON TEMPLE AURA — UNIFIED DESIGN SYSTEM
   Single source of truth for the premium redesign (Phase 7 / RD-0).
   Built from scratch. Plain CSS, no build step. Brand-driven, brace-safe.

   FILE MAP (built incrementally across RD-0.x tickets):
     [RD-0.1] 1. TOKENS  2. BRAND BRIDGE  3. RESET / BASE          [done]
     [RD-0.2] 4. PRIMITIVES (surface / glass / hero / grain / aurora) [done]
     [RD-0.3] 5. COMPONENTS A (buttons, inputs, cards, chips, badges) [done]
     [RD-0.4] 6. COMPONENTS B (tables, tabs, modal/sheet/drawer, toast) [done]
     [RD-0.5] 7. NAV SHELL (sidebar, topbar, mobile bottom-nav)        [done]
     [RD-0.6] 8. MOTION (paired with ds-motion.js)                    [done]
     [RD-0.7] 9. AMBIENT BACKGROUND + 3D loader hooks                 [done]
   ========================================================================== */

/* ============================================================================
   1. TOKENS
   ========================================================================== */
:root {
  /* ---- Spacing scale (4px base) ---- */
  --s-1: 4px;  --s-2: 8px;  --s-3: 12px; --s-4: 16px; --s-5: 24px;
  --s-6: 32px; --s-7: 40px; --s-8: 48px; --s-10: 64px; --s-12: 80px;

  /* ---- Radius ---- */
  --r-xs: 8px; --r-sm: 12px; --r-md: 18px; --r-lg: 24px; --r-xl: 32px; --r-pill: 999px;

  /* ---- Typography ---- */
  --font-display: 'Outfit', system-ui, -apple-system, sans-serif;
  --font-body: 'Inter', system-ui, -apple-system, sans-serif;
  --fs-eyebrow: 11px; --fs-cap: 12px; --fs-sm: 13px; --fs-body: 15px;
  --fs-lead: 18px; --fs-h3: 20px; --fs-h2: 24px; --fs-h1: clamp(32px, 7vw, 72px);
  --lh-tight: 1.05; --lh-snug: 1.3; --lh-body: 1.6;
  --ls-eyebrow: 0.14em; --ls-tight: -0.02em;
  --fw-reg: 400; --fw-med: 500; --fw-semi: 600; --fw-bold: 700; --fw-black: 900;

  /* ---- Elevation / surfaces (premium dark) ---- */
  --bg-0: #05060a;  --bg-1: #080b10;  --bg-2: #0c111a;
  --surface: rgba(18, 24, 33, 0.72);
  --glass: rgba(255, 255, 255, 0.04);
  --glass-2: rgba(255, 255, 255, 0.06);
  --border: rgba(255, 255, 255, 0.10);
  --border-hi: rgba(255, 255, 255, 0.18);

  /* ---- Text ---- */
  --text: #f8fafc; --text-sub: #cbd5e1; --text-muted: #94a3b8; --text-faint: #64748b;

  /* ---- Semantic status (brand-independent) ---- */
  --ok: #10b981; --ok-glow: rgba(16, 185, 129, 0.18);
  --warn: #f59e0b; --warn-glow: rgba(245, 158, 11, 0.16);
  --danger: #ef4444; --danger-glow: rgba(239, 68, 68, 0.16);
  --info: #4b8cff; --info-glow: rgba(75, 140, 255, 0.16);
  --gold: #fbbf24; --silver: #cbd5e1; --bronze: #cd7f32;

  /* ---- Shadows / blur ---- */
  --shadow-sm: 0 4px 14px rgba(0, 0, 0, 0.30);
  --shadow-card: 0 24px 70px rgba(0, 0, 0, 0.40);
  --shadow-pop: 0 30px 80px rgba(0, 0, 0, 0.55);
  --blur: 18px; --blur-sm: 12px; --blur-lg: 28px;

  /* ---- Motion ---- */
  --ease-out: cubic-bezier(0.22, 1, 0.36, 1);
  --ease-spring: cubic-bezier(0.2, 0.8, 0.2, 1);
  --ease-in-out: cubic-bezier(0.65, 0, 0.35, 1);
  --dur-fast: 0.18s; --dur: 0.35s; --dur-slow: 0.6s;

  /* ---- Z-index layers ---- */
  --z-bg: 0; --z-content: 10; --z-nav: 100; --z-overlay: 1000; --z-toast: 2000; --z-confetti: 9999;

  /* ---- Layout ---- */
  --container: 1180px; --container-narrow: 640px; --sidebar-w: 248px;
}

/* ============================================================================
   2. BRAND BRIDGE
   Maps per-gym vars emitted by app/services/branding.py
   (--brand, --brand-dark, --brand-light, --brand-contrast, --brand-bg)
   into semantic accent tokens. Every premium surface reads these, so each
   gym's color themes the whole UI automatically. Fallbacks keep it safe.
   ========================================================================== */
:root {
  --accent: var(--brand, #14b8a6);
  --accent-dark: var(--brand-dark, #0f766e);
  --accent-light: var(--brand-light, #5eead4);
  --on-accent: var(--brand-contrast, #06100d);
  --app-bg: var(--brand-bg, var(--bg-0));

  /* Derived accent tints (graceful fallback for no color-mix support) ----- */
  --accent-glow: rgba(20, 184, 166, 0.22);
  --accent-soft: rgba(20, 184, 166, 0.10);
  --accent-line: rgba(20, 184, 166, 0.28);
  --accent-grad: linear-gradient(135deg, var(--accent), var(--accent-light));
}
@supports (background: color-mix(in srgb, red, blue)) {
  :root {
    --accent-glow: color-mix(in srgb, var(--accent) 22%, transparent);
    --accent-soft: color-mix(in srgb, var(--accent) 10%, transparent);
    --accent-line: color-mix(in srgb, var(--accent) 28%, transparent);
  }
}

/* ============================================================================
   3. RESET / BASE
   ========================================================================== */
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }

html { -webkit-text-size-adjust: 100%; text-size-adjust: 100%; scroll-behavior: smooth; }

body {
  font-family: var(--font-body);
  font-size: var(--fs-body);
  line-height: var(--lh-body);
  color: var(--text);
  background: var(--app-bg);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-rendering: optimizeLegibility;
  min-height: 100vh;
  min-height: 100dvh;
}

h1, h2, h3, h4 { font-family: var(--font-display); font-weight: var(--fw-black); line-height: var(--lh-snug); color: #fff; }
h1 { font-size: var(--fs-h1); line-height: var(--lh-tight); letter-spacing: var(--ls-tight); }
h2 { font-size: var(--fs-h2); }
h3 { font-size: var(--fs-h3); }

p { margin: 0; }
small { font-size: var(--fs-sm); }
strong, b { font-weight: var(--fw-bold); }

a { color: var(--accent-light); font-weight: var(--fw-semi); text-decoration: none; transition: color var(--dur-fast) var(--ease-out); }
a:hover { color: var(--accent); }

img, svg, video { max-width: 100%; height: auto; display: block; }
ul, ol { list-style: none; }
button, input, select, textarea { font: inherit; color: inherit; }
button { cursor: pointer; background: none; border: 0; }

/* Eyebrow utility (used across hero/section headers) */
.ds-eyebrow {
  font-family: var(--font-display);
  font-size: var(--fs-eyebrow);
  font-weight: var(--fw-black);
  letter-spacing: var(--ls-eyebrow);
  text-transform: uppercase;
  color: var(--accent-light);
}

/* Gradient text helper */
.ds-gradient-text {
  background: var(--accent-grad);
  -webkit-background-clip: text;
  background-clip: text;
  -webkit-text-fill-color: transparent;
  color: transparent;
}

/* Accessibility ----------------------------------------------------------- */
:where(a, button, input, select, textarea, [tabindex]):focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
  border-radius: var(--r-xs);
}
.ds-visually-hidden {
  position: absolute !important;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0, 0, 0, 0); white-space: nowrap; border: 0;
}

::selection { background: var(--accent); color: var(--on-accent); }

/* Custom scrollbar (subtle, premium) */
* { scrollbar-width: thin; scrollbar-color: var(--border-hi) transparent; }
*::-webkit-scrollbar { width: 10px; height: 10px; }
*::-webkit-scrollbar-thumb { background: var(--border-hi); border-radius: var(--r-pill); border: 2px solid transparent; background-clip: content-box; }
*::-webkit-scrollbar-thumb:hover { background: var(--text-faint); background-clip: content-box; }

/* ============================================================================
   4. PRIMITIVES
   Reusable structural layers. Every component composes from these.
   ========================================================================== */

/* 4.1 Surface — solid opaque card base ----------------------------------- */
.ds-surface {
  background: var(--bg-1);
  border: 1px solid var(--border);
  border-radius: var(--r-lg);
}

/* 4.2 Glass — frosted translucent layer (the signature look) ------------- */
.ds-glass {
  position: relative;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r-lg);
  -webkit-backdrop-filter: blur(var(--blur)) saturate(140%);
  backdrop-filter: blur(var(--blur)) saturate(140%);
  box-shadow: var(--shadow-sm);
}
/* Soft top sheen that sells the glass depth */
.ds-glass::before {
  content: "";
  position: absolute; inset: 0;
  border-radius: inherit;
  padding: 1px;
  background: linear-gradient(160deg, rgba(255,255,255,0.16), rgba(255,255,255,0) 40%);
  -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  -webkit-mask-composite: xor;
  mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  mask-composite: exclude;
  pointer-events: none;
}
/* Fallback for browsers without backdrop-filter — use opaque surface */
@supports not ((-webkit-backdrop-filter: blur(1px)) or (backdrop-filter: blur(1px))) {
  .ds-glass { background: var(--bg-2); }
}

/* 4.3 Elevated — raised glass for modals / popovers / key cards --------- */
.ds-elevated {
  background: var(--surface);
  border: 1px solid var(--border-hi);
  border-radius: var(--r-lg);
  -webkit-backdrop-filter: blur(var(--blur-lg)) saturate(150%);
  backdrop-filter: blur(var(--blur-lg)) saturate(150%);
  box-shadow: var(--shadow-card);
}

/* 4.4 Hero — full-bleed banner with 3D grid + brand orbs ---------------- */
.ds-hero {
  position: relative;
  overflow: hidden;
  isolation: isolate;
  border-radius: var(--r-xl);
  background:
    radial-gradient(120% 140% at 15% 0%, var(--accent-soft), transparent 55%),
    radial-gradient(100% 120% at 100% 0%, rgba(75,140,255,0.10), transparent 50%),
    var(--bg-1);
}
/* perspective grid floor */
.ds-hero::before {
  content: "";
  position: absolute; inset: -2px;
  z-index: -1;
  background-image:
    linear-gradient(var(--border) 1px, transparent 1px),
    linear-gradient(90deg, var(--border) 1px, transparent 1px);
  background-size: 44px 44px;
  -webkit-mask-image: radial-gradient(80% 60% at 50% 0%, #000 0%, transparent 75%);
  mask-image: radial-gradient(80% 60% at 50% 0%, #000 0%, transparent 75%);
  opacity: 0.5;
}
/* floating brand glow orb */
.ds-hero::after {
  content: "";
  position: absolute;
  top: -120px; right: -80px;
  width: 360px; height: 360px;
  z-index: -1;
  border-radius: 50%;
  background: radial-gradient(circle, var(--accent-glow), transparent 70%);
  filter: blur(20px);
  animation: ds-orb-float 9s var(--ease-in-out) infinite alternate;
}
@keyframes ds-orb-float {
  from { transform: translate3d(0, 0, 0) scale(1); }
  to   { transform: translate3d(-30px, 36px, 0) scale(1.12); }
}

/* 4.5 Grain — fine film noise overlay (adds expensive, tactile feel) ---- */
.ds-grain { position: relative; }
.ds-grain::after {
  content: "";
  position: absolute; inset: 0;
  z-index: 1;
  pointer-events: none;
  border-radius: inherit;
  opacity: 0.045;
  mix-blend-mode: overlay;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='2' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
}

/* 4.6 Aurora — ambient drifting mesh background (brand-tinted) ---------- */
.ds-aurora {
  position: fixed;
  inset: 0;
  z-index: var(--z-bg);
  pointer-events: none;
  overflow: hidden;
  background: var(--app-bg);
}
.ds-aurora::before, .ds-aurora::after {
  content: "";
  position: absolute;
  width: 60vmax; height: 60vmax;
  border-radius: 50%;
  filter: blur(80px);
  opacity: 0.5;
  will-change: transform;
}
.ds-aurora::before {
  top: -20vmax; left: -10vmax;
  background: radial-gradient(circle, var(--accent-glow), transparent 60%);
  animation: ds-aurora-a 26s var(--ease-in-out) infinite alternate;
}
.ds-aurora::after {
  bottom: -25vmax; right: -15vmax;
  background: radial-gradient(circle, rgba(75,140,255,0.18), transparent 60%);
  animation: ds-aurora-b 32s var(--ease-in-out) infinite alternate;
}
@keyframes ds-aurora-a {
  from { transform: translate3d(0,0,0) rotate(0deg); }
  to   { transform: translate3d(12vmax, 8vmax, 0) rotate(40deg); }
}
@keyframes ds-aurora-b {
  from { transform: translate3d(0,0,0) rotate(0deg); }
  to   { transform: translate3d(-14vmax, -6vmax, 0) rotate(-30deg); }
}

/* ============================================================================
   5. COMPONENTS A — buttons, inputs, cards, chips, badges, pills
   ========================================================================== */

/* 5.1 Buttons ------------------------------------------------------------- */
.ds-btn {
  display: inline-flex; align-items: center; justify-content: center; gap: var(--s-2);
  font-family: var(--font-display); font-weight: var(--fw-bold); font-size: var(--fs-sm); line-height: 1;
  height: 44px; padding: 0 var(--s-5);
  border-radius: var(--r-pill); border: 1px solid transparent;
  white-space: nowrap; user-select: none;
  transition: transform var(--dur-fast) var(--ease-spring), box-shadow var(--dur) var(--ease-out),
              background var(--dur) var(--ease-out), border-color var(--dur) var(--ease-out);
}
.ds-btn:active { transform: translateY(1px) scale(0.98); }
.ds-btn--primary { background: var(--accent-grad); color: var(--on-accent); box-shadow: 0 8px 24px var(--accent-glow); }
.ds-btn--primary:hover { box-shadow: 0 14px 36px var(--accent-glow); }
.ds-btn--secondary {
  background: var(--glass-2); color: var(--text); border-color: var(--border-hi);
  -webkit-backdrop-filter: blur(var(--blur-sm)); backdrop-filter: blur(var(--blur-sm));
}
.ds-btn--secondary:hover { border-color: var(--accent-line); }
.ds-btn--ghost { background: transparent; color: var(--text-sub); }
.ds-btn--ghost:hover { background: var(--glass); color: var(--text); }
.ds-btn--danger { background: var(--danger); color: #fff; box-shadow: 0 8px 24px var(--danger-glow); }
.ds-btn--sm { height: 36px; font-size: var(--fs-cap); padding: 0 var(--s-4); }
.ds-btn--lg { height: 54px; font-size: var(--fs-body); padding: 0 var(--s-7); }
.ds-btn--block { width: 100%; }
.ds-btn--icon { width: 44px; padding: 0; }
.ds-btn[disabled], .ds-btn:disabled { opacity: 0.5; cursor: not-allowed; pointer-events: none; }
.ds-btn.is-loading { color: transparent !important; pointer-events: none; position: relative; }
.ds-btn.is-loading::after {
  content: ""; position: absolute; width: 18px; height: 18px; border-radius: 50%;
  border: 2px solid rgba(255,255,255,0.4); border-top-color: #fff; animation: ds-spin 0.7s linear infinite;
}
@keyframes ds-spin { to { transform: rotate(360deg); } }

/* 5.2 Form fields --------------------------------------------------------- */
.ds-field { display: flex; flex-direction: column; gap: var(--s-2); }
.ds-label { font-size: var(--fs-cap); font-weight: var(--fw-semi); color: var(--text-sub); }
.ds-input, .ds-textarea, .ds-select {
  width: 100%; height: 46px; padding: 0 var(--s-4); color: var(--text);
  background: var(--glass); border: 1px solid var(--border); border-radius: var(--r-sm);
  transition: border-color var(--dur-fast) var(--ease-out), box-shadow var(--dur-fast) var(--ease-out), background var(--dur-fast) var(--ease-out);
}
.ds-textarea { height: auto; min-height: 104px; padding: var(--s-3) var(--s-4); line-height: var(--lh-body); resize: vertical; }
.ds-input::placeholder, .ds-textarea::placeholder { color: var(--text-faint); }
.ds-input:focus, .ds-textarea:focus, .ds-select:focus {
  outline: none; border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-soft); background: var(--glass-2);
}
.ds-input.is-invalid, .ds-textarea.is-invalid, .ds-select.is-invalid { border-color: var(--danger); box-shadow: 0 0 0 3px var(--danger-glow); }
.ds-select {
  -webkit-appearance: none; appearance: none; padding-right: var(--s-8);
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='14' height='14' fill='none' stroke='%2394a3b8' stroke-width='2'%3E%3Cpath d='M3 5l4 4 4-4'/%3E%3C/svg%3E");
  background-repeat: no-repeat; background-position: right var(--s-4) center;
}
.ds-hint { font-size: var(--fs-cap); color: var(--text-muted); }
.ds-hint--error { color: var(--danger); }

/* 5.3 Toggle -------------------------------------------------------------- */
.ds-toggle { position: relative; display: inline-flex; width: 46px; height: 26px; flex: none; }
.ds-toggle input { position: absolute; inset: 0; width: 100%; height: 100%; margin: 0; opacity: 0; cursor: pointer; z-index: 2; }
.ds-toggle__track { flex: 1; border-radius: var(--r-pill); background: var(--border-hi); transition: background var(--dur) var(--ease-out); }
.ds-toggle__track::after {
  content: ""; position: absolute; top: 3px; left: 3px; width: 20px; height: 20px; border-radius: 50%;
  background: #fff; box-shadow: var(--shadow-sm); transition: transform var(--dur) var(--ease-spring);
}
.ds-toggle input:checked + .ds-toggle__track { background: var(--accent); }
.ds-toggle input:checked + .ds-toggle__track::after { transform: translateX(20px); }

/* 5.4 Segmented control --------------------------------------------------- */
.ds-segment { display: inline-flex; gap: 4px; padding: 4px; background: var(--glass); border: 1px solid var(--border); border-radius: var(--r-pill); }
.ds-segment button {
  padding: 6px var(--s-4); border-radius: var(--r-pill); font-size: var(--fs-cap); font-weight: var(--fw-semi);
  color: var(--text-muted); transition: color var(--dur-fast), background var(--dur-fast);
}
.ds-segment button.is-active { background: var(--accent); color: var(--on-accent); }

/* 5.5 Cards --------------------------------------------------------------- */
.ds-card {
  padding: var(--s-5); background: var(--surface); border: 1px solid var(--border); border-radius: var(--r-lg);
  -webkit-backdrop-filter: blur(var(--blur)); backdrop-filter: blur(var(--blur));
}
.ds-card__head { display: flex; align-items: center; justify-content: space-between; margin-bottom: var(--s-4); }
.ds-card__title { font-family: var(--font-display); font-weight: var(--fw-bold); font-size: var(--fs-lead); }
.ds-card__foot { margin-top: var(--s-4); padding-top: var(--s-4); border-top: 1px solid var(--border); }

/* 5.6 Stat tile ----------------------------------------------------------- */
.ds-stat { display: flex; flex-direction: column; gap: var(--s-2); padding: var(--s-5); background: var(--surface); border: 1px solid var(--border); border-radius: var(--r-lg); }
.ds-stat__label { font-size: var(--fs-cap); font-weight: var(--fw-semi); text-transform: uppercase; letter-spacing: 0.08em; color: var(--text-muted); }
.ds-stat__value { font-family: var(--font-display); font-weight: var(--fw-black); font-size: 32px; line-height: 1; }
.ds-stat__delta { display: inline-flex; align-items: center; gap: 4px; font-size: var(--fs-cap); font-weight: var(--fw-bold); }
.ds-stat__delta--up { color: var(--ok); }
.ds-stat__delta--down { color: var(--danger); }

/* 5.7 Metric card (top accent bar) --------------------------------------- */
.ds-metric { position: relative; overflow: hidden; }
.ds-metric::before { content: ""; position: absolute; top: 0; left: 0; right: 0; height: 3px; background: var(--accent-grad); }

/* 5.8 Chips / pills / badges --------------------------------------------- */
.ds-chip {
  display: inline-flex; align-items: center; gap: 6px; padding: 6px var(--s-3); border-radius: var(--r-pill);
  background: var(--glass); border: 1px solid var(--border); font-size: var(--fs-cap); font-weight: var(--fw-semi); color: var(--text-sub);
  transition: background var(--dur-fast), border-color var(--dur-fast), color var(--dur-fast);
}
.ds-chip:hover { border-color: var(--border-hi); }
.ds-chip.is-active { background: var(--accent-soft); border-color: var(--accent-line); color: var(--accent-light); }

.ds-pill {
  display: inline-flex; align-items: center; padding: 4px var(--s-3); border-radius: var(--r-pill);
  font-size: var(--fs-eyebrow); font-weight: var(--fw-black); letter-spacing: 0.06em; text-transform: uppercase;
  background: var(--accent-soft); color: var(--accent-light);
}

.ds-badge {
  display: inline-flex; align-items: center; gap: 6px; padding: 4px 10px; border-radius: var(--r-pill);
  font-size: var(--fs-cap); font-weight: var(--fw-bold); border: 1px solid transparent;
}
.ds-badge__dot { width: 6px; height: 6px; border-radius: 50%; background: currentColor; }
.ds-badge--ok { background: var(--ok-glow); color: var(--ok); }
.ds-badge--warn { background: var(--warn-glow); color: var(--warn); }
.ds-badge--danger { background: var(--danger-glow); color: var(--danger); }
.ds-badge--info { background: var(--info-glow); color: var(--info); }

/* ============================================================================
   6. COMPONENTS B — tables, tabs, overlays (modal/sheet/drawer), toast, skeleton
   Behavior glue lives in app/static/js/ds-ui.js
   ========================================================================== */

/* 6.1 Tabs ---------------------------------------------------------------- */
.ds-tabs { display: flex; gap: var(--s-2); border-bottom: 1px solid var(--border); }
.ds-tab {
  position: relative; padding: var(--s-3) var(--s-2);
  font-weight: var(--fw-semi); font-size: var(--fs-sm); color: var(--text-muted);
  transition: color var(--dur-fast) var(--ease-out);
}
.ds-tab:hover { color: var(--text-sub); }
.ds-tab.is-active { color: var(--text); }
.ds-tab.is-active::after {
  content: ""; position: absolute; left: 0; right: 0; bottom: -1px; height: 2px;
  background: var(--accent-grad); border-radius: var(--r-pill);
}

/* 6.2 Table --------------------------------------------------------------- */
.ds-table-wrap {
  overflow-x: auto; border: 1px solid var(--border); border-radius: var(--r-lg);
  background: var(--surface); -webkit-backdrop-filter: blur(var(--blur)); backdrop-filter: blur(var(--blur));
}
.ds-table { width: 100%; border-collapse: collapse; font-size: var(--fs-sm); }
.ds-table thead th {
  position: sticky; top: 0; z-index: 1; background: var(--bg-2);
  text-align: left; padding: var(--s-3) var(--s-4); white-space: nowrap;
  font-size: var(--fs-cap); font-weight: var(--fw-bold); text-transform: uppercase; letter-spacing: 0.06em; color: var(--text-muted);
}
.ds-table tbody td { padding: var(--s-3) var(--s-4); border-top: 1px solid var(--border); color: var(--text-sub); }
.ds-table tbody tr { transition: background var(--dur-fast) var(--ease-out); }
.ds-table tbody tr:hover { background: var(--glass); }
@media (max-width: 720px) {
  .ds-table thead { display: none; }
  .ds-table, .ds-table tbody, .ds-table tr, .ds-table td { display: block; width: 100%; }
  .ds-table tr { border-top: 1px solid var(--border); padding: var(--s-2) 0; }
  .ds-table tbody td { border: 0; display: flex; justify-content: space-between; gap: var(--s-4); padding: var(--s-2) var(--s-4); }
  .ds-table tbody td::before { content: attr(data-label); color: var(--text-muted); font-weight: var(--fw-semi); }
}

/* 6.3 Modal --------------------------------------------------------------- */
.ds-modal-backdrop {
  position: fixed; inset: 0; z-index: var(--z-overlay);
  display: flex; align-items: center; justify-content: center; padding: var(--s-4);
  background: rgba(3, 4, 8, 0.6); -webkit-backdrop-filter: blur(8px); backdrop-filter: blur(8px);
  opacity: 0; visibility: hidden; transition: opacity var(--dur) var(--ease-out), visibility var(--dur);
}
.ds-modal-backdrop.is-open { opacity: 1; visibility: visible; }
.ds-modal {
  width: 100%; max-width: 480px; max-height: 90vh; overflow-y: auto; padding: var(--s-6);
  background: var(--surface); border: 1px solid var(--border-hi); border-radius: var(--r-lg);
  -webkit-backdrop-filter: blur(var(--blur-lg)); backdrop-filter: blur(var(--blur-lg)); box-shadow: var(--shadow-pop);
  transform: translateY(12px) scale(0.98); transition: transform var(--dur) var(--ease-spring);
}
.ds-modal-backdrop.is-open .ds-modal { transform: none; }
.ds-modal__head { display: flex; align-items: center; justify-content: space-between; margin-bottom: var(--s-4); }
.ds-modal__title { font-family: var(--font-display); font-weight: var(--fw-bold); font-size: var(--fs-h3); }
.ds-modal__foot { display: flex; gap: var(--s-3); justify-content: flex-end; margin-top: var(--s-6); }

/* 6.4 Bottom sheet (mobile) ---------------------------------------------- */
.ds-sheet {
  position: fixed; left: 0; right: 0; bottom: 0; z-index: var(--z-overlay);
  padding: var(--s-5); padding-bottom: max(var(--s-5), env(safe-area-inset-bottom));
  background: var(--surface); border-top: 1px solid var(--border-hi); border-radius: var(--r-xl) var(--r-xl) 0 0;
  -webkit-backdrop-filter: blur(var(--blur-lg)); backdrop-filter: blur(var(--blur-lg)); box-shadow: var(--shadow-pop);
  transform: translateY(100%); transition: transform var(--dur) var(--ease-spring);
}
.ds-sheet.is-open { transform: none; }
.ds-sheet__handle { width: 40px; height: 4px; margin: 0 auto var(--s-4); border-radius: var(--r-pill); background: var(--border-hi); }

/* 6.5 Side drawer --------------------------------------------------------- */
.ds-drawer {
  position: fixed; top: 0; right: 0; bottom: 0; z-index: var(--z-overlay);
  width: min(420px, 90vw); padding: var(--s-6); overflow-y: auto;
  background: var(--surface); border-left: 1px solid var(--border-hi);
  -webkit-backdrop-filter: blur(var(--blur-lg)); backdrop-filter: blur(var(--blur-lg)); box-shadow: var(--shadow-pop);
  transform: translateX(100%); transition: transform var(--dur) var(--ease-spring);
}
.ds-drawer.is-open { transform: none; }

/* 6.6 Toast --------------------------------------------------------------- */
.ds-toast-region {
  position: fixed; top: var(--s-5); right: var(--s-5); z-index: var(--z-toast);
  display: flex; flex-direction: column; gap: var(--s-3); max-width: 360px; pointer-events: none;
}
.ds-toast {
  pointer-events: auto; padding: var(--s-3) var(--s-4);
  background: var(--surface); border: 1px solid var(--border-hi); border-left: 3px solid var(--accent); border-radius: var(--r-sm);
  -webkit-backdrop-filter: blur(var(--blur)); backdrop-filter: blur(var(--blur)); box-shadow: var(--shadow-card);
  font-size: var(--fs-sm); color: var(--text); animation: ds-toast-in var(--dur) var(--ease-spring);
}
.ds-toast--ok { border-left-color: var(--ok); }
.ds-toast--warn { border-left-color: var(--warn); }
.ds-toast--danger { border-left-color: var(--danger); }
.ds-toast.is-leaving { animation: ds-toast-out var(--dur) var(--ease-out) forwards; }
@keyframes ds-toast-in { from { opacity: 0; transform: translateX(20px); } to { opacity: 1; transform: none; } }
@keyframes ds-toast-out { to { opacity: 0; transform: translateX(20px); } }
@media (max-width: 560px) { .ds-toast-region { left: var(--s-4); right: var(--s-4); max-width: none; } }

/* 6.7 Skeleton loader ----------------------------------------------------- */
.ds-skeleton { position: relative; overflow: hidden; background: var(--glass-2); border-radius: var(--r-sm); }
.ds-skeleton::after {
  content: ""; position: absolute; inset: 0; transform: translateX(-100%);
  background: linear-gradient(90deg, transparent, rgba(255,255,255,0.06), transparent); animation: ds-shimmer 1.4s infinite;
}
@keyframes ds-shimmer { to { transform: translateX(100%); } }
.ds-skeleton--text { height: 12px; margin: 6px 0; }
.ds-skeleton--title { height: 20px; width: 60%; }
.ds-skeleton--avatar { width: 44px; height: 44px; border-radius: 50%; }

/* ============================================================================
   7. NAV SHELL — app layout, sidebar, topbar, mobile bottom-nav
   Mobile drawer toggle handled by ds-ui.js ([data-ds-nav-toggle]).
   ========================================================================== */

/* 7.1 Shell grid ---------------------------------------------------------- */
.ds-shell { display: grid; grid-template-columns: var(--sidebar-w) 1fr; min-height: 100vh; min-height: 100dvh; }
.ds-shell.is-collapsed { --sidebar-w: 76px; }

/* 7.2 Sidebar ------------------------------------------------------------- */
.ds-sidebar {
  position: sticky; top: 0; height: 100vh; height: 100dvh;
  display: flex; flex-direction: column; gap: var(--s-2);
  padding: var(--s-5) var(--s-3);
  background: var(--bg-1); border-right: 1px solid var(--border); overflow-y: auto;
}
.ds-sidebar__brand { display: flex; align-items: center; gap: var(--s-3); padding: 0 var(--s-2) var(--s-5); }
.ds-sidebar__logo {
  flex: none; width: 36px; height: 36px; border-radius: var(--r-sm);
  display: grid; place-items: center; background: var(--accent-grad); color: var(--on-accent);
  font-family: var(--font-display); font-weight: var(--fw-black);
}
.ds-sidebar__name { font-family: var(--font-display); font-weight: var(--fw-bold); font-size: var(--fs-lead); white-space: nowrap; overflow: hidden; }
.ds-nav { display: flex; flex-direction: column; gap: 2px; }
.ds-nav__section { margin-top: var(--s-4); padding: 0 var(--s-3) var(--s-1); font-size: var(--fs-eyebrow); letter-spacing: var(--ls-eyebrow); text-transform: uppercase; color: var(--text-faint); font-weight: var(--fw-bold); }
.ds-nav__item {
  position: relative; display: flex; align-items: center; gap: var(--s-3);
  padding: 10px var(--s-3); border-radius: var(--r-sm);
  color: var(--text-muted); font-weight: var(--fw-semi); font-size: var(--fs-sm); white-space: nowrap;
  transition: background var(--dur-fast) var(--ease-out), color var(--dur-fast) var(--ease-out);
}
.ds-nav__item:hover { background: var(--glass); color: var(--text); }
.ds-nav__item.is-active { background: var(--accent-soft); color: var(--accent-light); }
.ds-nav__item.is-active::before { content: ""; position: absolute; left: 0; top: 8px; bottom: 8px; width: 3px; border-radius: var(--r-pill); background: var(--accent); }
.ds-nav__icon { flex: none; width: 20px; height: 20px; display: grid; place-items: center; }
.ds-nav__label { overflow: hidden; }
.ds-sidebar__foot { margin-top: auto; padding-top: var(--s-4); }
/* Collapsed (icon-only) */
.ds-shell.is-collapsed .ds-sidebar__name,
.ds-shell.is-collapsed .ds-nav__label,
.ds-shell.is-collapsed .ds-nav__section { display: none; }
.ds-shell.is-collapsed .ds-nav__item { justify-content: center; }
.ds-shell.is-collapsed .ds-sidebar__brand { justify-content: center; }

/* 7.3 Main column + topbar ----------------------------------------------- */
.ds-main { display: flex; flex-direction: column; min-width: 0; }
.ds-topbar {
  position: sticky; top: 0; z-index: var(--z-nav);
  display: flex; align-items: center; gap: var(--s-4); padding: var(--s-3) var(--s-5);
  background: rgba(8, 11, 16, 0.7); -webkit-backdrop-filter: blur(var(--blur)); backdrop-filter: blur(var(--blur));
  border-bottom: 1px solid var(--border);
}
.ds-topbar__title { font-family: var(--font-display); font-weight: var(--fw-bold); font-size: var(--fs-h3); margin-right: auto; }
.ds-topbar__search { flex: 1; max-width: 420px; }
.ds-content { flex: 1; padding: var(--s-6) var(--s-5); }
.ds-content__inner { max-width: var(--container); margin: 0 auto; }

/* 7.4 Burger (mobile only) ----------------------------------------------- */
.ds-burger { display: none; width: 40px; height: 40px; border-radius: var(--r-sm); place-items: center; color: var(--text); }
.ds-burger:hover { background: var(--glass); }

/* 7.5 Scrim (mobile nav drawer) ------------------------------------------ */
.ds-scrim {
  position: fixed; inset: 0; z-index: calc(var(--z-overlay) - 1);
  background: rgba(3, 4, 8, 0.5); -webkit-backdrop-filter: blur(4px); backdrop-filter: blur(4px);
  opacity: 0; visibility: hidden; transition: opacity var(--dur) var(--ease-out), visibility var(--dur);
}
.ds-scrim.is-open { opacity: 1; visibility: visible; }

/* 7.6 Bottom nav (mobile only) ------------------------------------------- */
.ds-bottom-nav { display: none; }
.ds-bottom-nav__item {
  display: flex; flex-direction: column; align-items: center; gap: 4px; min-width: 56px;
  padding: 6px 10px; border-radius: var(--r-sm); color: var(--text-muted); font-size: 10px; font-weight: var(--fw-semi);
}
.ds-bottom-nav__item.is-active { color: var(--accent-light); }
.ds-bottom-nav__icon { width: 22px; height: 22px; }

/* 7.7 Responsive: collapse shell to single column + drawer + bottom-nav -- */
@media (max-width: 960px) {
  .ds-shell { grid-template-columns: 1fr; }
  .ds-sidebar {
    position: fixed; top: 0; left: 0; bottom: 0; z-index: var(--z-overlay); width: 248px;
    transform: translateX(-100%); transition: transform var(--dur) var(--ease-spring);
  }
  .ds-sidebar.is-open { transform: none; }
  .ds-burger { display: grid; }
  .ds-bottom-nav {
    position: fixed; left: 0; right: 0; bottom: 0; z-index: var(--z-nav);
    display: flex; justify-content: space-around;
    padding: 8px 8px max(8px, env(safe-area-inset-bottom));
    background: rgba(8, 11, 16, 0.85); -webkit-backdrop-filter: blur(var(--blur)); backdrop-filter: blur(var(--blur));
    border-top: 1px solid var(--border);
  }
  .ds-content { padding: var(--s-5) var(--s-4) 96px; }
}

/* ============================================================================
   8. MOTION — utility classes (behavior in app/static/js/ds-motion.js)
   ========================================================================== */
.reveal { opacity: 0; transform: translateY(16px); transition: opacity var(--dur-slow) var(--ease-out), transform var(--dur-slow) var(--ease-out); }
.reveal.is-visible { opacity: 1; transform: none; }
.reveal--left { transform: translateX(-22px); }
.reveal--right { transform: translateX(22px); }
.reveal--scale { transform: scale(0.96); }
.reveal--left.is-visible, .reveal--right.is-visible, .reveal--scale.is-visible { transform: none; }

.ds-tilt { transition: transform var(--dur) var(--ease-out); transform-style: preserve-3d; will-change: transform; }

.ds-pulse { animation: ds-pulse 2s var(--ease-in-out) infinite; }
@keyframes ds-pulse { 0%, 100% { opacity: 1; } 50% { opacity: 0.45; } }

.ds-live { position: relative; display: inline-flex; width: 8px; height: 8px; flex: none; }
.ds-live__dot { width: 8px; height: 8px; border-radius: 50%; background: var(--ok); }
.ds-live::after { content: ""; position: absolute; inset: 0; border-radius: 50%; background: var(--ok); animation: ds-ping 1.6s var(--ease-out) infinite; }
@keyframes ds-ping { 0% { transform: scale(1); opacity: 0.6; } 100% { transform: scale(2.6); opacity: 0; } }

/* ============================================================================
   9. AMBIENT BACKGROUND + 3D LOADER (behavior in app/static/js/ds-ambient.js)
   Aurora layer styles are in 4.6; ds-ambient.js auto-mounts .ds-aurora unless
   <body data-ds-aurora="off">. Vignette + Spline 3D host hooks below.
   ========================================================================== */
.ds-ambient-vignette {
  position: fixed; inset: 0; z-index: var(--z-bg); pointer-events: none;
  background: radial-gradient(120% 90% at 50% -10%, transparent 40%, rgba(0, 0, 0, 0.55) 100%);
}

.ds-spline {
  position: relative; overflow: hidden; isolation: isolate;
  border-radius: var(--r-lg); background: var(--bg-1); min-height: 240px;
}
.ds-spline spline-viewer {
  display: block; width: 100%; height: 100%;
  opacity: 0; transition: opacity var(--dur-slow) var(--ease-out);
}
.ds-spline.is-loaded spline-viewer { opacity: 1; }
.ds-spline__poster { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
.ds-spline.is-fallback { background: radial-gradient(circle at 50% 40%, var(--accent-soft), var(--bg-1) 70%); }
/* loading shimmer until the 3D scene is ready (hidden once loaded/fallback) */
.ds-spline:not(.is-loaded):not(.is-fallback)::after {
  content: ""; position: absolute; inset: 0; pointer-events: none;
  background: linear-gradient(110deg, transparent 30%, var(--glass-2) 50%, transparent 70%);
  background-size: 200% 100%; animation: ds-ambient-shimmer 1.6s infinite;
}
@keyframes ds-ambient-shimmer { from { background-position: 200% 0; } to { background-position: -200% 0; } }

/* ============================================================================
   REDUCED MOTION — global guard
   ========================================================================== */
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after { animation-duration: 0.001ms !important; animation-iteration-count: 1 !important; transition-duration: 0.001ms !important; }
  .ds-hero::after, .ds-aurora::before, .ds-aurora::after, .ds-skeleton::after, .ds-pulse, .ds-live::after { animation: none !important; }
  .ds-spline:not(.is-loaded):not(.is-fallback)::after { animation: none !important; }
  .reveal { opacity: 1 !important; transform: none !important; }
  .ds-tilt { transform: none !important; }
}

/* ============================================================================
   UI_ACTION_STATE — loading / empty / success / error slots (Req 17.5–17.8)
   Behavior glue lives in app/static/js/ui-state.js. A [data-states] container
   shows exactly one child [data-state] slot at a time; the others carry the
   native `hidden` attribute so no stale spinner survives a settled state.
   ========================================================================== */
[data-states] > [data-state][hidden] { display: none !important; }

.ui-state__loading {
  display: flex; flex-direction: column; gap: var(--s-2, 8px);
  padding: var(--s-4, 16px) 0;
}
.ui-state__loading .ds-skeleton--text { width: 100%; }

.ui-state__empty,
.ui-state__error {
  display: flex; flex-direction: column; align-items: center; gap: var(--s-2, 8px);
  text-align: center;
  padding: var(--s-6, 24px) var(--s-4, 16px);
  border: 1px solid var(--border, rgba(255,255,255,0.08));
  border-radius: var(--r-md, 12px);
  background: var(--glass-1, rgba(255,255,255,0.02));
  color: var(--text-muted, #94a3b8);
}
.ui-state__empty p,
.ui-state__error p { margin: 0; font-size: var(--fs-sm, 0.9rem); line-height: 1.5; }

/* Error slot leans on the warning/danger palette without shouting a raw error. */
.ui-state__error {
  border-color: rgba(245, 158, 11, 0.28);
  background: rgba(245, 158, 11, 0.08);
  color: var(--text, #e2e8f0);
}

/* ============================================================================
   Upgrade_Teaser + field-level validation error (Phase 7, task 25.3)
   Composed from existing tokens/primitives (.ds-card / .ds-badge / .ds-btn) so
   locked features and client-side validation errors inherit the current design
   without re-skinning any existing component.
   ========================================================================== */
.ds-upsell-teaser {
  display: flex; align-items: flex-start; gap: var(--s-4);
  border-style: dashed;
}
.ds-upsell-teaser--compact { padding: var(--s-4); gap: var(--s-3); }
.ds-upsell-teaser__icon {
  flex: 0 0 auto; display: inline-flex; align-items: center; justify-content: center;
  width: 40px; height: 40px; border-radius: var(--r-md, 12px);
  background: var(--info-glow, rgba(56,132,255,0.14)); color: var(--info, #3b82f6);
}
.ds-upsell-teaser__body { flex: 1 1 auto; min-width: 0; }
.ds-upsell-teaser__title { display: block; font-family: var(--font-display); font-weight: var(--fw-bold); }
.ds-upsell-teaser__desc { margin: var(--s-1, 4px) 0 var(--s-2, 8px); color: var(--text-sub); font-size: var(--fs-sm); }
.ds-upsell-teaser__cta { flex: 0 0 auto; align-self: center; }

.ds-field-error {
  margin: 4px 0 0; color: var(--danger, #ef4444);
  font-size: var(--fs-cap, 0.8rem); font-weight: var(--fw-bold, 700);
}
[aria-invalid="true"] { border-color: var(--danger, #ef4444) !important; }
