/* ============================================================================
   VSaaS — Centinela Azul · Premium Console Scale-Up
   Shared design system. Loaded by BOTH the user panel (/app/) and the
   admin panel (/admin/). The admin panel adds only small additive rules on top.
   Pure CSS — no build tools, no framework, no CDN.
   ----------------------------------------------------------------------------
   Premium "night-glass security console", scaled up: deep midnight-navy canvas,
   one disciplined solid-cobalt accent (no neon cyan), hardware-style status
   LEDs, tabular monospace numerals for everything quantitative, a full-viewport
   split-screen auth, a greeting hero, larger metric tiles, and taller camera
   cards with a 16:9 preview zone. Bigger type, wider column, more air.
   ============================================================================ */

/* ---------------------------------------------------------------------------
   1. SELF-HOSTED FONTS (optional — graceful fallback to system stack)
   Place Inter woff2 files under /app/fonts/. If absent, @font-face simply
   resolves to nothing and the system stack below takes over — zero breakage.
   --------------------------------------------------------------------------- */
@font-face {
  font-family: 'Inter';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('/app/fonts/Inter-Regular.woff2') format('woff2');
}
@font-face {
  font-family: 'Inter';
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url('/app/fonts/Inter-Medium.woff2') format('woff2');
}
@font-face {
  font-family: 'Inter';
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url('/app/fonts/Inter-SemiBold.woff2') format('woff2');
}
@font-face {
  font-family: 'Inter';
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url('/app/fonts/Inter-Bold.woff2') format('woff2');
}

/* ---------------------------------------------------------------------------
   2. DESIGN TOKENS  (palette LOCKED — only scale / spacing / layout changed)
   --------------------------------------------------------------------------- */
:root {
  /* Surfaces & canvas */
  --bg: #0B1220;
  --surface: #161D2E;
  --surface-2: #1F2940;
  --surface-input: #0E1626;

  /* Brand / accent — one calm solid blue (no neon) */
  --primary: #2563EB;
  --primary-hover: #1D4ED8;
  --primary-ink: #FFFFFF;
  --accent: #60A5FA;

  /* Semantic state */
  --success: #22C55E;
  --success-text: #86EFAC;
  --warning: #F59E0B;
  --warning-text: #FCD34D;
  --danger: #EF4444;
  --danger-text: #FCA5A5;

  /* Type */
  --text: #E6EAF2;
  --muted: #8A94A8;

  /* Lines */
  --border: #273349;
  --border-strong: #34425C;

  /* Radii — bumped one notch for a softer, more premium silhouette */
  --radius: 18px;
  --radius-sm: 12px;
  --radius-lg: 22px;
  --radius-pill: 999px;

  /* Shadows — deepened one notch; add --shadow-lg for hero / auth depth */
  --shadow: 0 14px 36px -12px rgba(2, 6, 16, 0.62), 0 3px 8px -4px rgba(2, 6, 16, 0.52);
  --shadow-soft: 0 8px 20px -10px rgba(2, 6, 16, 0.50);
  --shadow-lg: 0 18px 48px -12px rgba(2, 6, 16, 0.70);
  --shadow-primary: 0 8px 20px -8px rgba(37, 99, 235, 0.38);

  /* Glass */
  --glass-bg: rgba(22, 29, 46, 0.80);
  --glass-border: rgba(110, 130, 180, 0.14);
  --glass-blur: blur(14px) saturate(135%);

  /* Focus & glow */
  --focus-ring: 0 0 0 3px rgba(37, 99, 235, 0.45);
  --glow-live: 0 0 0 2px rgba(34, 197, 94, 0.16), 0 0 10px rgba(34, 197, 94, 0.30);

  /* Gradients — solid-feel blue, no cyan neon */
  --gradient-primary: linear-gradient(135deg, #2563EB 0%, #1D4ED8 100%);
  --gradient-hero: radial-gradient(120% 90% at 80% -10%, rgba(37, 99, 235, 0.12) 0%, rgba(37, 99, 235, 0.06) 30%, rgba(11, 18, 32, 0) 60%);

  /* Spacing scale (4 / 8 / 12 / 16 / 20 / 24 / 28 / 32 / 40 / 48 / 64) */
  --sp-1: 4px;
  --sp-2: 8px;
  --sp-3: 12px;
  --sp-4: 16px;
  --sp-5: 20px;
  --sp-6: 24px;
  --sp-7: 28px;
  --sp-8: 32px;
  --sp-10: 40px;
  --sp-12: 48px;
  --sp-16: 64px;

  /* Font size scale — base raised to 15px; whole scale enlarged */
  --fs-xs: 12.5px;
  --fs-sm: 13.5px;
  --fs-base: 15px;
  --fs-md: 16px;
  --fs-lg: 22px;
  --fs-xl: 30px;
  --fs-2xl: 40px;
  --fs-3xl: 48px;   /* dashboard greeting */
  --fs-hero: 52px;  /* login headline ceiling for clamp() */

  /* Motion */
  --dur-fast: 120ms;
  --dur-base: 200ms;
  --dur-slow: 320ms;
  --easing: cubic-bezier(0.22, 1, 0.36, 1);

  /* Layout */
  --tap: 46px;          /* default control min-height */
  --tap-input: 52px;    /* input / select / textarea min-height */
  --content-max: 1180px;

  /* Font stacks */
  --font: 'Inter', system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
  --mono: 'JetBrains Mono', 'SFMono-Regular', 'SF Mono', Menlo, Consolas, 'Liberation Mono', monospace;

  /* Back-compat aliases for any legacy markup still using old names */
  --card: var(--surface);
  --green: var(--success);
  --red: var(--danger);
  --primary-700: var(--primary-hover);
}

/* ---------------------------------------------------------------------------
   3. RESET & BASE
   --------------------------------------------------------------------------- */
*, *::before, *::after { box-sizing: border-box; }

html { -webkit-text-size-adjust: 100%; }

body {
  margin: 0;
  min-height: 100vh;
  font-family: var(--font);
  font-size: var(--fs-base);
  line-height: 1.55;
  letter-spacing: -0.005em;
  font-feature-settings: 'cv05', 'ss01';
  color: var(--text);
  background-color: var(--bg);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

/* Fixed, non-scrolling hero glow painted top-right over the whole canvas. */
body::before {
  content: '';
  position: fixed;
  inset: 0;
  background: var(--gradient-hero);
  pointer-events: none;
  z-index: 0;
}

/* Keep real content above the glow layer. */
.topbar, .container, .modal, .toast-container, .bottom-nav, .fab, .auth-split { position: relative; z-index: 1; }

h1, h2, h3, h4 {
  margin: 0 0 var(--sp-3);
  font-weight: 700;
  line-height: 1.22;
  letter-spacing: -0.013em;
  color: var(--text);
}
h2 { font-size: var(--fs-lg); margin: var(--sp-1) 0 var(--sp-4); }   /* 22px */
h3 { font-size: 18px; font-weight: 600; }
h4 { font-size: var(--fs-md); }

a { color: var(--accent); text-decoration: none; }
a:hover { text-decoration: underline; }

code, kbd, pre, .num, .mono { font-family: var(--mono); }

/* Tabular monospace numerals — instrument readout alignment. */
.num {
  font-family: var(--mono);
  font-variant-numeric: tabular-nums;
  font-feature-settings: 'tnum' 1;
}

/* Utility */
.hidden { display: none !important; }
.muted { color: var(--muted); }
.sr-only {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0, 0, 0, 0); white-space: nowrap; border: 0;
}

/* Universal accessible focus ring. */
:focus-visible {
  outline: none;
  box-shadow: var(--focus-ring);
  border-radius: var(--radius-sm);
}

/* ---------------------------------------------------------------------------
   4. APP SHELL — layout + sticky topbar + brand
   --------------------------------------------------------------------------- */
.container {
  max-width: var(--content-max);
  margin: 0 auto;
  padding: var(--sp-4);
  /* leave room for the mobile bottom nav / FAB */
  padding-bottom: calc(var(--sp-10) + 72px);
}
@media (min-width: 641px) {
  .container {
    padding: var(--sp-7) 28px;
    padding-bottom: var(--sp-10);
  }
}

/* Auth modifier — let the split escape the centered column entirely. */
.container.is-auth {
  max-width: none;
  padding: 0;
}

/* Sticky glass topbar — taller (64px), inner content aligned to the 1180 column */
.topbar {
  position: sticky;
  top: 0;
  z-index: 10;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-4);
  min-height: 64px;
  padding: var(--sp-2) var(--sp-4);
  background: var(--glass-bg);
  -webkit-backdrop-filter: var(--glass-blur);
  backdrop-filter: var(--glass-blur);
  border-bottom: 1px solid var(--glass-border);
}
@media (min-width: 641px) {
  .topbar { padding: var(--sp-2) 28px; }
}
/* Optional inner wrapper to align the topbar to the 1180px column. */
.topbar-inner {
  width: 100%;
  max-width: var(--content-max);
  margin: 0 auto;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-4);
}

/* Brand: "REC"/shield lozenge in accent gradient + wordmark */
.brand {
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  font-size: 17px;
  font-weight: 800;
  letter-spacing: -0.013em;
  color: var(--text);
}
.brand .brand-mark,
.brand::before {
  content: '';
  display: inline-block;
  width: 32px;
  height: 32px;
  border-radius: 9px;
  background: var(--gradient-primary);
  box-shadow: var(--shadow-primary);
  flex: 0 0 auto;
}
/* If markup supplies its own .brand-mark element, suppress the ::before token */
.brand:has(.brand-mark)::before { display: none; }
.brand-mark {
  position: relative;
  display: inline-grid;
  place-items: center;
}
.brand-mark::after {
  content: 'REC';
  font-family: var(--mono);
  font-size: 8.5px;
  font-weight: 700;
  letter-spacing: 0.04em;
  color: var(--primary-ink);
}
.brand .sub { color: var(--muted); font-weight: 500; }

/* "ADMIN" accent pill in the topbar / brand lockup (admin only) */
.admin-pill {
  display: inline-flex;
  align-items: center;
  padding: 4px 11px;
  border-radius: var(--radius-pill);
  font-size: var(--fs-xs);
  font-weight: 800;
  letter-spacing: 0.07em;
  color: var(--accent);
  background: rgba(37, 99, 235, 0.14);
  border: 1px solid rgba(96, 165, 250, 0.32);
}

/* Right-side user box */
.userbox {
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  font-size: var(--fs-base);
  color: var(--muted);
}
.userbox .email { font-family: var(--mono); font-size: var(--fs-sm); }

/* Row with space-between (kept from legacy markup) */
.rowbetween {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-4);
}

/* ---------------------------------------------------------------------------
   4b. GREETING HERO (dashboard band, top of .container — user + admin)
   --------------------------------------------------------------------------- */
.hero {
  position: relative;
  overflow: hidden;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-6);
  margin: var(--sp-2) 0 var(--sp-8);
  padding: var(--sp-8) var(--sp-7);
  background:
    var(--gradient-hero),
    radial-gradient(420px circle at 14% 30%, rgba(37, 99, 235, 0.12), transparent 70%),
    var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-soft);
}
.hero .hero-text { min-width: 0; }
.hero h1, .hero .hero-title {
  margin: 0;
  font-size: clamp(30px, 4.4vw, var(--fs-3xl));
  font-weight: 700;
  line-height: 1.12;
  letter-spacing: -0.02em;
}
.hero .hero-sub {
  margin: var(--sp-2) 0 0;
  font-size: 17px;
  color: var(--muted);
  line-height: 1.4;
}
.hero .hero-actions { flex: 0 0 auto; display: flex; gap: var(--sp-3); }

@media (max-width: 640px) {
  .hero {
    margin: 0 0 var(--sp-6);
    padding: var(--sp-6) var(--sp-5);
  }
  .hero h1, .hero .hero-title { font-size: clamp(26px, 8vw, 30px); }
  .hero .hero-sub { font-size: var(--fs-base); }
  .hero .hero-actions { display: none; } /* FAB takes over on mobile */
}

/* ---------------------------------------------------------------------------
   5. CARDS (.card / .cam / .metric base)
   --------------------------------------------------------------------------- */
.card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: var(--sp-6);
  box-shadow: var(--shadow-soft);
}

/* Camera card — taller console card: 16:9 preview header + left status rail */
.cam {
  position: relative;
  overflow: hidden;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: var(--sp-6);
  box-shadow: var(--shadow-soft);
  transition: transform var(--dur-base) var(--easing),
              box-shadow var(--dur-base) var(--easing),
              border-color var(--dur-base) var(--easing);
}
/* 3px left status rail */
.cam::before {
  content: '';
  position: absolute;
  left: 0; top: 0; bottom: 0;
  width: 3px;
  z-index: 2;
  background: var(--gradient-primary); /* default = active */
}
.cam.suspended::before { background: var(--danger); }
.cam.por-vencer::before { background: var(--warning); }

/* "En vivo" — thin animated top hairline when an event arrived <5 min ago */
.cam.live::after {
  content: '';
  position: absolute;
  top: 0; left: 0; right: 0;
  height: 2px;
  z-index: 3;
  background: linear-gradient(90deg, transparent, var(--accent), var(--primary), transparent);
  background-size: 200% 100%;
  animation: hairline-sweep 2.4s linear infinite;
}
@keyframes hairline-sweep {
  0% { background-position: 200% 0; }
  100% { background-position: -200% 0; }
}

/* Hover lift — pointer devices only */
@media (hover: hover) and (pointer: fine) {
  .cam:hover {
    transform: translateY(-3px);
    box-shadow: var(--shadow);
    border-color: var(--border-strong);
  }
}

.cam h3 { margin: 0; font-size: 18px; font-weight: 600; }

/* 16:9 CSS preview header (OPTIONAL element: <div class="cam-preview">).
   Gradient placeholder; overlay slots for REC LED, last-seen, status badge.
   Pulls flush to the card edges and sits above the body padding. */
.cam-preview {
  position: relative;
  margin: calc(var(--sp-6) * -1) calc(var(--sp-6) * -1) var(--sp-5);
  aspect-ratio: 16 / 9;
  background:
    radial-gradient(120% 140% at 50% 0%, rgba(37, 99, 235, 0.10), transparent 60%),
    linear-gradient(160deg, var(--surface-2) 0%, var(--bg) 100%);
  border-bottom: 1px solid var(--border);
  overflow: hidden;
}
/* Faint camera-lens glyph centered behind overlays */
.cam-preview::after {
  content: '';
  position: absolute;
  top: 50%; left: 50%;
  width: 44px; height: 44px;
  transform: translate(-50%, -50%);
  border-radius: 50%;
  border: 2px solid var(--border-strong);
  box-shadow: 0 0 0 6px rgba(255, 255, 255, 0.02);
  opacity: 0.55;
}
/* REC LED badge — top-left overlay */
.cam-preview .rec {
  position: absolute;
  top: var(--sp-3); left: var(--sp-3);
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 4px 9px;
  font-family: var(--mono);
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.06em;
  color: var(--text);
  background: rgba(11, 18, 32, 0.62);
  border: 1px solid var(--glass-border);
  border-radius: var(--radius-pill);
  -webkit-backdrop-filter: blur(6px);
  backdrop-filter: blur(6px);
}
.cam-preview .rec::before {
  content: '';
  width: 7px; height: 7px;
  border-radius: 50%;
  background: var(--danger);
  box-shadow: 0 0 8px rgba(239, 68, 68, 0.6);
  animation: breathe-rec 1.6s ease-in-out infinite;
}
@keyframes breathe-rec { 0%, 100% { opacity: 1; } 50% { opacity: 0.4; } }
/* Status badge overlay — top-right; place a .badge here */
.cam-preview .preview-badge { position: absolute; top: var(--sp-3); right: var(--sp-3); }
/* Last-seen timestamp — bottom-left overlay */
.cam-preview .preview-time {
  position: absolute;
  bottom: var(--sp-3); left: var(--sp-3);
  font-family: var(--mono);
  font-size: 12px;
  color: var(--text);
  padding: 3px 8px;
  background: rgba(11, 18, 32, 0.62);
  border-radius: var(--radius-sm);
  -webkit-backdrop-filter: blur(6px);
  backdrop-filter: blur(6px);
}

.cam .rowbetween { gap: var(--sp-3); }

/* Thin stat strip below the header — richer band */
.cam .stat-strip {
  margin: var(--sp-4) calc(var(--sp-6) * -1) 0;
  padding: var(--sp-3) var(--sp-6);
  background: var(--surface-2);
  color: var(--muted);
  font-size: var(--fs-sm);
}
.cam .stat-strip .num { color: var(--text); font-weight: 700; }

/* Meta line (FTP id + LED) */
.cam .meta {
  margin: var(--sp-4) 0;
  color: var(--muted);
  font-size: var(--fs-base);
  line-height: 1.8;
}
.cam .meta code { font-family: var(--mono); color: var(--text); }

.cam .actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-2);
  margin-top: var(--sp-5);
}

/* Contextual subscription banner inside a card */
.cam-banner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-3);
  margin: var(--sp-4) calc(var(--sp-6) * -1) 0;
  padding: var(--sp-3) var(--sp-6);
  font-size: var(--fs-base);
}
.cam-banner.warn { background: rgba(245, 158, 11, 0.10); color: var(--warning-text); }
.cam-banner.danger { background: rgba(239, 68, 68, 0.10); color: var(--danger-text); }

/* ---------------------------------------------------------------------------
   6. GRID HELPERS  (camera grid: 2-up <=1023px, 3-up >=1024px @ 1180 width)
   --------------------------------------------------------------------------- */
.grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--sp-5);
}
@media (min-width: 560px) {
  .grid { grid-template-columns: repeat(auto-fill, minmax(320px, 1fr)); }
}

/* Generic section spacing helper */
.section { margin-top: var(--sp-10); }
.section-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-4);
  margin: var(--sp-10) 0 var(--sp-5);
}
.section-head:first-child { margin-top: 0; }
.section-head h2 { margin: 0; }

/* ---------------------------------------------------------------------------
   7. BUTTONS (.btn + .primary / .ghost / .danger + .sm / .lg)
   --------------------------------------------------------------------------- */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--sp-2);
  min-height: var(--tap);
  padding: 12px 20px;
  border: 1px solid transparent;
  border-radius: var(--radius-sm);
  font-family: inherit;
  font-size: var(--fs-base);
  font-weight: 600;
  line-height: 1;
  white-space: nowrap;
  cursor: pointer;
  user-select: none;
  transition: background var(--dur-base) var(--easing),
              border-color var(--dur-base) var(--easing),
              transform var(--dur-fast) var(--easing),
              filter var(--dur-fast) var(--easing),
              box-shadow var(--dur-base) var(--easing);
}
.btn:active { transform: scale(0.98); }

.btn.sm {
  min-height: 38px;
  padding: 8px 14px;
  font-size: var(--fs-sm);
}

/* Large variant — login "Entrar" + dashboard "+ Agregar cámara" */
.btn.lg {
  min-height: 48px;
  padding: 0 24px;
  font-size: var(--fs-md);
}

/* Primary — gradient fill */
.btn.primary {
  background: var(--gradient-primary);
  color: var(--primary-ink);
  box-shadow: var(--shadow-primary);
}
@media (hover: hover) and (pointer: fine) {
  .btn.primary:hover {
    background: var(--primary-hover);
    filter: brightness(1.04);
    transform: translateY(-1px);
  }
}

/* Ghost — transparent outlined */
.btn.ghost {
  background: transparent;
  color: var(--text);
  border-color: var(--border);
}
@media (hover: hover) and (pointer: fine) {
  .btn.ghost:hover {
    background: var(--surface-2);
    border-color: var(--border-strong);
  }
}

/* Danger — destructive, danger-tinted */
.btn.danger {
  background: transparent;
  color: var(--danger-text);
  border-color: rgba(239, 68, 68, 0.35);
}
@media (hover: hover) and (pointer: fine) {
  .btn.danger:hover { background: rgba(239, 68, 68, 0.10); }
}

/* Block / full-width */
.btn.block { width: 100%; }

/* Disabled + async-busy */
.btn:disabled,
.btn[aria-disabled='true'] {
  opacity: 0.5;
  box-shadow: none;
  cursor: not-allowed;
  pointer-events: none;
}
/* Async loading: lock width, swap label for an inline spinner */
.btn.is-loading {
  position: relative;
  color: transparent !important;
  pointer-events: none;
}
.btn.is-loading::after {
  content: '';
  position: absolute;
  width: 18px;
  height: 18px;
  border-radius: 50%;
  border: 2px solid currentColor;
  border-top-color: transparent;
  color: var(--primary-ink);
  animation: spin 0.7s linear infinite;
}
.btn.ghost.is-loading::after,
.btn.danger.is-loading::after { color: var(--text); }

/* Icon-only round button (timeline play/download, modal close) */
.btn.icon {
  min-height: 42px;
  width: 42px;
  padding: 0;
  border-radius: var(--radius-pill);
  font-size: var(--fs-md);
}
.btn.icon.sm { min-height: 38px; width: 38px; }

/* ---------------------------------------------------------------------------
   8. SPINNER (standalone)
   --------------------------------------------------------------------------- */
.spinner {
  display: inline-block;
  width: 18px;
  height: 18px;
  border-radius: 50%;
  border: 2px solid var(--border-strong);
  border-top-color: var(--accent);
  animation: spin 0.7s linear infinite;
  vertical-align: middle;
}
.spinner.lg { width: 28px; height: 28px; border-width: 3px; }
@keyframes spin { to { transform: rotate(360deg); } }

/* ---------------------------------------------------------------------------
   9. BADGES + STATUS LEDs
   --------------------------------------------------------------------------- */
.badge {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 5px 11px;
  border-radius: var(--radius-pill);
  font-size: var(--fs-xs);
  font-weight: 700;
  letter-spacing: 0.03em;
  line-height: 1.2;
}
/* Leading LED dot on every badge */
.badge::before {
  content: '';
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: currentColor;
  flex: 0 0 auto;
}

.badge.active {
  background: rgba(34, 197, 94, 0.14);
  color: var(--success-text);
}
.badge.active::before {
  background: var(--success);
  box-shadow: var(--glow-live);
  animation: breathe 1.6s ease-in-out infinite;
}
.badge.suspended {
  background: rgba(239, 68, 68, 0.14);
  color: var(--danger-text);
}
.badge.suspended::before { background: var(--danger); }

.badge.por-vencer {
  background: rgba(245, 158, 11, 0.14);
  color: var(--warning-text);
}
.badge.por-vencer::before { background: var(--warning); }

@keyframes breathe {
  0%, 100% { box-shadow: 0 0 0 2px rgba(34, 197, 94, 0.10), 0 0 4px rgba(34, 197, 94, 0.20); }
  50% { box-shadow: var(--glow-live); }
}

/* Standalone LED dot (FTP on/off — REPLACES the 🟢/🔴 emoji).
   Usage: <span class="led on" role="img" aria-label="En línea"></span> */
.led {
  display: inline-block;
  width: 9px;
  height: 9px;
  border-radius: 50%;
  background: var(--border-strong);
  vertical-align: middle;
  flex: 0 0 auto;
}
.led.on {
  background: var(--success);
  box-shadow: 0 0 6px rgba(34, 197, 94, 0.5);
}
.led.off {
  background: var(--danger);
  box-shadow: 0 0 6px rgba(239, 68, 68, 0.4);
}
.led.warn {
  background: var(--warning);
  box-shadow: 0 0 6px rgba(245, 158, 11, 0.45);
}

/* ---------------------------------------------------------------------------
   10. FORMS — inputs, selects, labels, validation
   --------------------------------------------------------------------------- */
.form {
  display: flex;
  flex-direction: column;
  gap: var(--sp-4);
}

label, .field-label {
  display: block;
  margin-bottom: var(--sp-2);
  font-size: var(--fs-sm);
  font-weight: 500;
  color: var(--muted);
}

input,
select,
textarea {
  width: 100%;
  min-height: var(--tap-input);
  padding: 14px 16px;
  font-family: inherit;
  font-size: var(--fs-md);
  color: var(--text);
  background: var(--surface-input);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  transition: border-color var(--dur-base) var(--easing),
              box-shadow var(--dur-base) var(--easing);
  appearance: none;
  -webkit-appearance: none;
}
input::placeholder, textarea::placeholder { color: var(--muted); }

input:focus,
select:focus,
textarea:focus {
  outline: none;
  border-color: var(--primary);
  box-shadow: var(--focus-ring);
}

/* Custom chevron for selects */
select {
  padding-right: 40px;
  background-image: 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='%2394A3C4' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 14px center;
  cursor: pointer;
}

/* Inline validation messages */
.field-error { color: var(--danger-text); font-size: var(--fs-sm); }
.field-ok { color: var(--success-text); font-size: var(--fs-sm); }

/* Auth message line (kept from legacy markup) */
.msg { margin-top: var(--sp-3); min-height: 1.2em; font-size: var(--fs-base); }
.msg.err { color: var(--danger-text); }
.msg.ok { color: var(--success-text); }

.hint { color: var(--muted); font-size: var(--fs-base); }

/* ---------------------------------------------------------------------------
   10b. SPLIT AUTH — full-viewport brand hero + form panel
   Markup (recommended): wrap #authView contents so:
     <div class="auth-split">
       <aside class="auth-hero"> … brand + headline + bullets + trust … </aside>
       <div class="auth-panel"> … existing card markup (tabs/forms) … </div>
     </div>
   Give the parent .container the .is-auth modifier so the split is full-bleed.
   FALLBACK: a bare #authView (current markup, no wrappers) still renders as a
   confident, scaled-up centered premium panel (see the #authView rule below).
   --------------------------------------------------------------------------- */
.auth-split {
  display: grid;
  grid-template-columns: 56% 44%;
  min-height: 100dvh;
  width: 100%;
}

/* LEFT — dark brand canvas with blue CSS glow blobs + faint grid */
.auth-hero {
  position: relative;
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: flex-start;
  gap: var(--sp-7);
  padding: clamp(40px, 6vw, 72px);
  overflow: hidden;
  background:
    radial-gradient(420px circle at 18% 30%, rgba(37, 99, 235, 0.12), transparent 70%),
    radial-gradient(360px circle at 75% 80%, rgba(96, 165, 250, 0.10), transparent 70%),
    var(--gradient-hero),
    var(--bg);
  box-shadow: var(--shadow-lg);
}
/* 3%-opacity hairline grid overlay */
.auth-hero::before {
  content: '';
  position: absolute;
  inset: 0;
  pointer-events: none;
  background-image:
    repeating-linear-gradient(0deg, rgba(39, 51, 73, 0.5) 0 1px, transparent 1px 64px),
    repeating-linear-gradient(90deg, rgba(39, 51, 73, 0.5) 0 1px, transparent 1px 64px);
  opacity: 0.30;
  -webkit-mask-image: radial-gradient(120% 100% at 30% 40%, #000 30%, transparent 80%);
  mask-image: radial-gradient(120% 100% at 30% 40%, #000 30%, transparent 80%);
}
.auth-hero > * { position: relative; z-index: 1; max-width: 560px; width: 100%; }

/* Wordmark lockup top-left */
.auth-hero .auth-wordmark {
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  font-size: 24px;
  font-weight: 800;
  letter-spacing: -0.015em;
  color: var(--text);
}
.auth-hero .auth-wordmark .brand-mark {
  width: 40px; height: 40px; border-radius: 11px;
  background: var(--gradient-primary);
  box-shadow: var(--shadow-primary);
}
.auth-hero .auth-wordmark .brand-mark::after { font-size: 10px; }

.auth-hero .auth-headline {
  margin: 0;
  font-size: clamp(30px, 4.4vw, var(--fs-hero));
  font-weight: 700;
  line-height: 1.12;
  letter-spacing: -0.022em;
  max-width: 14ch;
}
.auth-hero .auth-subhead {
  margin: 0;
  font-size: 18px;
  line-height: 1.5;
  color: var(--muted);
  max-width: 46ch;
}

/* Four value bullets — 2x2 grid */
.auth-hero .auth-bullets {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 18px;
}
.auth-hero .auth-bullet {
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  font-size: var(--fs-base);
  color: var(--text);
  line-height: 1.35;
}
.auth-hero .auth-bullet .bullet-icon,
.auth-hero .auth-bullet .metric-icon {
  flex: 0 0 auto;
  display: inline-grid;
  place-items: center;
  width: 40px; height: 40px;
  border-radius: var(--radius-sm);
  color: var(--accent);
  background: rgba(37, 99, 235, 0.14);
  border: 1px solid var(--accent);
}

/* Trust band pinned at the bottom */
.auth-hero .auth-trust {
  margin-top: auto;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--sp-2) var(--sp-4);
  padding-top: var(--sp-5);
  border-top: 1px solid var(--border);
  font-size: 13px;
  color: var(--muted);
}
.auth-hero .auth-trust .trust-item {
  display: inline-flex;
  align-items: center;
  gap: 7px;
}
.auth-hero .auth-trust .trust-item::before {
  content: '';
  width: 8px; height: 8px;
  border-radius: 50%;
  background: var(--success);
  box-shadow: 0 0 6px rgba(34, 197, 94, 0.5);
  flex: 0 0 auto;
}

/* RIGHT — form panel, lifts off the darker hero */
.auth-panel {
  position: relative;
  display: flex;
  flex-direction: column;
  justify-content: center;
  min-height: 100dvh;
  padding: clamp(32px, 4vw, 64px);
  background: var(--surface);
  border-left: 1px solid var(--border);
  box-shadow: var(--shadow-lg);
}
.auth-panel .auth-card {
  width: 100%;
  max-width: 420px;
  margin: 0 auto;
}
.auth-panel .auth-foot {
  margin-top: auto;
  padding-top: var(--sp-6);
  font-size: 13px;
  color: var(--muted);
  text-align: center;
}
/* Reassurance line under the primary button */
.auth-reassure {
  margin: var(--sp-3) 0 0;
  font-size: 13px;
  color: var(--muted);
  text-align: center;
}

/* When #authView is the panel side, flatten it (the panel IS the surface). */
.auth-split #authView,
.auth-panel #authView {
  max-width: 420px;
  margin: 0 auto;
  padding: 0;
  background: transparent;
  border: none;
  box-shadow: none;
}

/* FALLBACK: bare #authView (no split wrappers) → scaled-up premium panel.
   :not() guards keep this from fighting the split rule above. */
#authView.card:not(.auth-card) {
  max-width: 460px;
  margin: clamp(48px, 9vh, 96px) auto 0;
  padding: clamp(32px, 5vw, 48px);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-lg);
}
#authView h2 { font-size: var(--fs-xl); }   /* "Bienvenido" 30px */

/* Mobile: split stacks; hero becomes a compact top banner */
@media (max-width: 860px) {
  .auth-split {
    grid-template-columns: 1fr;
    min-height: auto;
  }
  .auth-hero {
    padding: var(--sp-6) var(--sp-5) var(--sp-5);
    gap: var(--sp-4);
    box-shadow: none;
    min-height: auto;
  }
  .auth-hero::before { opacity: 0.18; }
  .auth-hero .auth-headline { font-size: 28px; max-width: none; }
  .auth-hero .auth-subhead,
  .auth-hero .auth-bullets { display: none; }       /* hide bullets on mobile */
  .auth-hero .auth-trust {
    margin-top: var(--sp-2);
    padding-top: var(--sp-3);
  }
  .auth-hero .auth-trust .trust-item.collapse { display: none; } /* keep one line */
  .auth-panel {
    min-height: auto;
    padding: var(--sp-6) var(--sp-5) calc(var(--sp-10) + 16px);
    border-left: none;
    border-top: 1px solid var(--border);
    box-shadow: none;
  }
  .auth-panel .auth-foot { margin-top: var(--sp-6); }
}

/* ---------------------------------------------------------------------------
   11. TABS (auth switcher) — segmented, taller
   --------------------------------------------------------------------------- */
.tabs {
  display: flex;
  gap: 4px;
  margin-bottom: var(--sp-5);
  padding: 4px;
  background: var(--surface-input);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
}
.tab {
  flex: 1;
  min-height: 46px;
  padding: 10px;
  font-family: inherit;
  font-size: var(--fs-base);
  font-weight: 500;
  color: var(--muted);
  background: transparent;
  border: 1px solid transparent;
  border-radius: 9px;
  cursor: pointer;
  transition: all var(--dur-base) var(--easing);
}
.tab.active {
  color: var(--primary-ink);
  background: var(--gradient-primary);
  border-color: transparent;
  font-weight: 600;
  box-shadow: var(--shadow-primary);
}

/* Segmented control (plan selector 1 / 3 / 6 meses, status filter chips) */
.segmented {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: var(--sp-3);
  margin-top: 18px;            /* headroom so the "Recomendado" ribbon never clips the title */
}
.seg-card {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 3px;
  padding: 20px 12px 16px;
  text-align: center;
  background: var(--surface-input);
  border: 1.5px solid var(--border);
  border-radius: var(--radius);
  cursor: pointer;
  transition: border-color var(--dur-base) var(--easing),
              background var(--dur-base) var(--easing),
              box-shadow var(--dur-base) var(--easing),
              transform var(--dur-base) var(--easing);
}
@media (hover: hover) {
  .seg-card:hover { border-color: var(--border-strong); transform: translateY(-2px); }
}
.seg-card.featured { border-color: rgba(37, 99, 235, 0.45); }
.seg-card.selected {
  border-color: var(--primary);
  background: rgba(37, 99, 235, 0.10);
  box-shadow: var(--focus-ring);
}
.seg-card .term { font-size: var(--fs-md); font-weight: 700; color: var(--text); }
.seg-card .total {
  font-family: var(--mono); font-size: 21px; font-weight: 800;
  color: var(--text); letter-spacing: -0.02em; line-height: 1.1;
}
.seg-card .price,
.seg-card .permonth { font-family: var(--mono); font-size: var(--fs-xs); color: var(--muted); }
.seg-card .hint { font-size: 11px; color: var(--muted); margin-top: 3px; line-height: 1.25; }
.seg-card .save { font-size: var(--fs-xs); font-weight: 700; color: var(--success-text); }
.seg-card .check {
  position: absolute; top: 8px; right: 8px;
  width: 20px; height: 20px; border-radius: 50%;
  display: none; align-items: center; justify-content: center;
  background: var(--primary); color: #fff;
}
.seg-card.selected .check { display: flex; }
/* "Recomendado" ribbon — centered above the card; .segmented margin-top gives it room */
.seg-card .popular {
  position: absolute;
  top: -10px; left: 50%;
  transform: translateX(-50%);
  padding: 3px 11px;
  white-space: nowrap;
  font-size: 10px;
  font-weight: 800;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--primary-ink);
  background: var(--primary);
  border-radius: var(--radius-pill);
  box-shadow: var(--shadow-soft);
}

/* Filter chips */
.chips { display: flex; flex-wrap: wrap; gap: var(--sp-2); }
.chip {
  min-height: 38px;
  padding: 7px 16px;
  font-size: var(--fs-sm);
  font-weight: 500;
  color: var(--muted);
  background: transparent;
  border: 1px solid var(--border);
  border-radius: var(--radius-pill);
  cursor: pointer;
  transition: all var(--dur-base) var(--easing);
}
.chip.active {
  color: var(--text);
  background: rgba(37, 99, 235, 0.12);
  border-color: var(--primary);
}

/* Search / filter bar */
.searchbar {
  display: flex;
  gap: var(--sp-3);
  margin: var(--sp-3) 0 var(--sp-5);
  flex-wrap: wrap;
}
.searchbar input, .searchbar select { flex: 1; min-width: 180px; }

/* ---------------------------------------------------------------------------
   12. MODALS / OVERLAYS (+ bottom-sheet on mobile)
   --------------------------------------------------------------------------- */
.modal {
  position: fixed;
  inset: 0;
  z-index: 50;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--sp-4);
  background: rgba(5, 8, 16, 0.66);
  -webkit-backdrop-filter: blur(4px);
  backdrop-filter: blur(4px);
  animation: overlay-in var(--dur-base) var(--easing);
}
@keyframes overlay-in { from { opacity: 0; } to { opacity: 1; } }

.modal-body {
  width: 100%;
  max-width: 480px;
  max-height: 90vh;
  overflow: auto;
  padding: var(--sp-6);
  background: var(--surface-2);
  border: 1px solid var(--glass-border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-lg);
  animation: modal-in var(--dur-base) var(--easing);
}
.modal-body.wide { max-width: 820px; }
@keyframes modal-in {
  from { opacity: 0; transform: scale(0.96); }
  to { opacity: 1; transform: scale(1); }
}

/* Modal header: title + circular ghost close */
.modal-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-3);
  margin-bottom: var(--sp-5);
}
.modal-head h3 { margin: 0; font-size: var(--fs-lg); font-weight: 600; }

/* Drag handle (visible only on the mobile bottom sheet) */
.sheet-handle {
  display: none;
  width: 40px;
  height: 4px;
  margin: 0 auto var(--sp-4);
  border-radius: var(--radius-pill);
  background: var(--border-strong);
}

/* Sticky footer action row inside modals */
.modal-footer {
  position: sticky;
  bottom: 0;
  display: flex;
  justify-content: flex-end;
  gap: var(--sp-2);
  margin: var(--sp-5) calc(var(--sp-6) * -1) calc(var(--sp-6) * -1);
  padding: var(--sp-4) var(--sp-6);
  background: var(--surface-2);
  border-top: 1px solid var(--border);
}

/* Mobile: slide up as a bottom sheet */
@media (max-width: 640px) {
  .modal { align-items: flex-end; padding: 0; }
  .modal-body {
    max-width: 100%;
    max-height: 92vh;
    border-radius: var(--radius-lg) var(--radius-lg) 0 0;
    animation: sheet-up var(--dur-slow) var(--easing);
  }
  .sheet-handle { display: block; }
  @keyframes sheet-up {
    from { transform: translateY(100%); }
    to { transform: translateY(0); }
  }
}

/* ---------------------------------------------------------------------------
   13. FTP CREDENTIALS PANEL (replaces the <pre> dump)
   --------------------------------------------------------------------------- */
.ftp-creds { display: flex; flex-direction: column; gap: var(--sp-3); }

/* Persistent amber warning bar */
.creds-warn {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  padding: var(--sp-3) var(--sp-4);
  font-size: var(--fs-base);
  color: var(--warning-text);
  background: rgba(245, 158, 11, 0.10);
  border: 1px solid rgba(245, 158, 11, 0.28);
  border-radius: var(--radius-sm);
}

.creds-panel {
  display: flex;
  flex-direction: column;
  background: var(--surface-input);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  overflow: hidden;
}
.cred-row {
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  padding: var(--sp-3) var(--sp-4);
  border-bottom: 1px solid var(--border);
}
.cred-row:last-child { border-bottom: none; }
.cred-row .cred-label {
  width: 76px;
  flex: 0 0 auto;
  font-size: var(--fs-sm);
  color: var(--muted);
}
.cred-row .cred-value {
  flex: 1;
  min-width: 0;
  font-family: var(--mono);
  font-size: var(--fs-base);
  color: var(--text);
  word-break: break-all;
}
.cred-row .btn { flex: 0 0 auto; }

.creds-actions { display: flex; gap: var(--sp-2); flex-wrap: wrap; }

/* Legacy <pre> fallback if markup still uses it */
.ftp-creds pre {
  margin: 0;
  padding: var(--sp-3);
  background: var(--surface-input);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  font-family: var(--mono);
  font-size: var(--fs-base);
  overflow: auto;
}

/* ---------------------------------------------------------------------------
   14. TOASTS (replace every alert/prompt/confirm)
   Container fixed; bottom-center on mobile, top-right on >=640px.
   --------------------------------------------------------------------------- */
.toast-container {
  position: fixed;
  z-index: 100;
  display: flex;
  flex-direction: column;
  gap: var(--sp-2);
  pointer-events: none;
  /* mobile default: bottom-center stack */
  left: 50%;
  bottom: calc(var(--sp-4) + 72px);
  transform: translateX(-50%);
  width: min(440px, calc(100vw - 32px));
}
@media (min-width: 640px) {
  .toast-container {
    left: auto;
    right: var(--sp-5);
    bottom: auto;
    top: var(--sp-5);
    transform: none;
  }
}

.toast {
  position: relative;
  display: flex;
  align-items: flex-start;
  gap: var(--sp-3);
  padding: var(--sp-4) var(--sp-4);
  overflow: hidden;
  pointer-events: auto;
  color: var(--text);
  background: var(--surface-2);
  border: 1px solid var(--glass-border);
  border-radius: 14px;
  box-shadow: var(--shadow);
  -webkit-backdrop-filter: var(--glass-blur);
  backdrop-filter: var(--glass-blur);
  animation: toast-in var(--dur-base) var(--easing);
}
.toast.leaving { animation: toast-out var(--dur-base) var(--easing) forwards; }

/* 4px left accent rail by type */
.toast::before {
  content: '';
  position: absolute;
  left: 0; top: 0; bottom: 0;
  width: 4px;
  background: var(--primary);
}
.toast.success::before { background: var(--success); }
.toast.danger::before, .toast.error::before { background: var(--danger); }
.toast.warning::before { background: var(--warning); }
.toast.info::before { background: var(--primary); }

.toast .toast-icon { flex: 0 0 auto; line-height: 1.4; }
.toast .toast-msg { flex: 1; font-size: var(--fs-base); line-height: 1.45; }
.toast .toast-action {
  flex: 0 0 auto;
  font-weight: 600;
  color: var(--accent);
  background: none;
  border: none;
  cursor: pointer;
  font-size: var(--fs-base);
}
.toast .toast-close {
  flex: 0 0 auto;
  width: 24px; height: 24px;
  display: grid; place-items: center;
  color: var(--muted);
  background: none;
  border: none;
  border-radius: var(--radius-pill);
  cursor: pointer;
}
.toast .toast-close:hover { color: var(--text); }

/* Auto-dismiss progress hairline */
.toast .toast-progress {
  position: absolute;
  left: 0; bottom: 0;
  height: 2px;
  width: 100%;
  background: currentColor;
  opacity: 0.5;
  transform-origin: left;
  animation: toast-progress 4s linear forwards;
}

@keyframes toast-in {
  from { opacity: 0; transform: translateY(8px) scale(0.98); }
  to { opacity: 1; transform: translateY(0) scale(1); }
}
@keyframes toast-out {
  to { opacity: 0; transform: translateY(8px) scale(0.98); }
}
@keyframes toast-progress { from { transform: scaleX(1); } to { transform: scaleX(0); } }

/* ---------------------------------------------------------------------------
   15. TABLES (admin) — taller ops-console rows
   --------------------------------------------------------------------------- */
.table-wrap {
  overflow-x: auto;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--surface);
  box-shadow: var(--shadow-soft);
}
table {
  width: 100%;
  border-collapse: collapse;
  font-size: var(--fs-base);
}
thead th {
  position: sticky;
  top: 0;
  z-index: 1;
  padding: var(--sp-3) var(--sp-4);
  text-align: left;
  font-size: var(--fs-xs);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--muted);
  background: var(--surface-2);
  border-bottom: 1px solid var(--border);
  white-space: nowrap;
}
tbody td {
  padding: var(--sp-3) var(--sp-4);
  min-height: 52px;
  border-bottom: 1px solid var(--border);
  vertical-align: middle;
}
tbody tr:last-child td { border-bottom: none; }
tbody tr:nth-child(even) { background: rgba(255, 255, 255, 0.02); }
@media (hover: hover) and (pointer: fine) {
  tbody tr:hover { background: var(--surface-2); }
}
/* Right-align numeric columns */
td.num, th.num, .col-num { text-align: right; }
td .btn.sm { margin-right: var(--sp-1); }

/* Mobile: collapse rows into "label: value" cards (CSS-only via data-label) */
@media (max-width: 560px) {
  .table-wrap.responsive table,
  .table-wrap.responsive thead,
  .table-wrap.responsive tbody,
  .table-wrap.responsive tr,
  .table-wrap.responsive td { display: block; width: 100%; }
  .table-wrap.responsive thead { display: none; }
  .table-wrap.responsive tr {
    margin: var(--sp-3);
    padding: var(--sp-2);
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    background: var(--surface);
  }
  .table-wrap.responsive td {
    display: flex;
    justify-content: space-between;
    gap: var(--sp-3);
    padding: 10px var(--sp-3);
    border-bottom: 1px solid var(--border);
    text-align: right;
  }
  .table-wrap.responsive td:last-child { border-bottom: none; }
  .table-wrap.responsive td::before {
    content: attr(data-label);
    font-size: var(--fs-sm);
    font-weight: 500;
    color: var(--muted);
    text-align: left;
  }
}

/* ---------------------------------------------------------------------------
   16. STAT / METRIC CARDS (user dashboard + admin metrics)
   4 fixed columns at >=900px; 2-up below.
   --------------------------------------------------------------------------- */
.metrics {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: var(--sp-4);
  margin: var(--sp-2) 0 var(--sp-8);
}
@media (min-width: 900px) {
  .metrics { grid-template-columns: repeat(4, 1fr); }
}

.metric {
  position: relative;
  overflow: hidden;
  padding: var(--sp-6);
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: var(--shadow-soft);
}
/* Faint corner accent glow */
.metric::after {
  content: '';
  position: absolute;
  top: -30%; right: -20%;
  width: 140px; height: 140px;
  background: radial-gradient(circle, rgba(37, 99, 235, 0.10), transparent 70%);
  pointer-events: none;
}

/* Icon chip (tint via modifier) — 40px */
.metric-icon {
  display: inline-grid;
  place-items: center;
  width: 40px; height: 40px;
  margin-bottom: var(--sp-4);
  border-radius: var(--radius-sm);
  color: var(--accent);
  background: rgba(37, 99, 235, 0.16);
}
.metric-icon svg { width: 22px; height: 22px; }
.metric-icon.indigo { color: #A5B4FC; background: rgba(99, 102, 241, 0.16); }
.metric-icon.teal { color: var(--success-text); background: rgba(34, 197, 94, 0.14); }
.metric-icon.amber { color: var(--warning-text); background: rgba(245, 158, 11, 0.14); }
.metric-icon.primary { color: var(--accent); background: rgba(37, 99, 235, 0.16); }

/* Big value (legacy markup uses .v / .l) — 40px */
.metric .v,
.metric .metric-value {
  font-family: var(--mono);
  font-variant-numeric: tabular-nums;
  font-size: var(--fs-2xl);
  font-weight: 800;
  line-height: 1.1;
  letter-spacing: -0.02em;
  color: var(--text);
}
.metric .l,
.metric .metric-label {
  margin-top: var(--sp-2);
  font-size: var(--fs-xs);
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--muted);
}

/* Delta chip */
.metric-delta {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  margin-top: var(--sp-3);
  padding: 3px 9px;
  font-size: var(--fs-xs);
  font-weight: 600;
  border-radius: var(--radius-pill);
}
.metric-delta.up { color: var(--success-text); background: rgba(34, 197, 94, 0.12); }
.metric-delta.warn { color: var(--warning-text); background: rgba(245, 158, 11, 0.12); }

/* 1px sparkline underbar slot */
.metric-spark { margin-top: var(--sp-2); height: 18px; opacity: 0.7; }
.metric-spark svg { width: 100%; height: 100%; display: block; }

/* ---------------------------------------------------------------------------
   17. SKELETON LOADERS (shimmer)
   --------------------------------------------------------------------------- */
.skeleton {
  position: relative;
  overflow: hidden;
  background: var(--surface-2);
  border-radius: var(--radius-sm);
  opacity: 0.6;
}
.skeleton::after {
  content: '';
  position: absolute;
  inset: 0;
  transform: translateX(-100%);
  background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.06), transparent);
  animation: shimmer 1.4s ease-in-out infinite;
}
@keyframes shimmer { to { transform: translateX(100%); } }

/* Common skeleton shapes */
.skeleton.line { height: 12px; margin: 8px 0; }
.skeleton.line.short { width: 40%; }
.skeleton.line.medium { width: 65%; }
.skeleton.title { height: 20px; width: 50%; margin-bottom: 14px; }
.skeleton.card { height: 300px; border-radius: var(--radius); }
.skeleton.metric { height: 140px; border-radius: var(--radius); }
.skeleton.row { height: 56px; margin-bottom: 8px; }
.skeleton.avatar { width: 40px; height: 40px; border-radius: 50%; }

/* ---------------------------------------------------------------------------
   18. EMPTY STATES & ERROR STATES
   --------------------------------------------------------------------------- */
.empty {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--sp-3);
  padding: var(--sp-12) var(--sp-4);
  text-align: center;
  color: var(--muted);
}
.empty .empty-icon {
  width: 56px; height: 56px;
  color: var(--border-strong);
  opacity: 0.9;
}
.empty .empty-title {
  font-size: 18px;
  font-weight: 600;
  color: var(--text);
}
.empty .empty-text {
  max-width: 380px;
  font-size: var(--fs-base);
  color: var(--muted);
}
.empty .btn { margin-top: var(--sp-2); }

/* Error state with retry */
.error-state {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--sp-3);
  padding: var(--sp-10) var(--sp-4);
  text-align: center;
  color: var(--muted);
}
.error-state .error-title { font-weight: 600; color: var(--text); }

/* ---------------------------------------------------------------------------
   19. TIMELINE / EVENT ROWS — taller (~56px) console rows
   --------------------------------------------------------------------------- */
.timeline {
  display: flex;
  flex-direction: column;
  gap: var(--sp-2);
  margin-top: var(--sp-4);
}

/* Sticky day header ("Hoy" / "Ayer" / "lun 23 jun") */
.day-header {
  position: sticky;
  top: 0;
  z-index: 1;
  padding: var(--sp-2) 0;
  font-size: var(--fs-sm);
  font-weight: 700;
  color: var(--muted);
  background: var(--surface-2);
  backdrop-filter: var(--glass-blur);
}

.event {
  position: relative;
  display: flex;
  align-items: center;
  gap: var(--sp-4);
  min-height: 56px;
  padding: var(--sp-3) var(--sp-4);
  background: var(--surface-input);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  transition: background var(--dur-base) var(--easing),
              border-color var(--dur-base) var(--easing);
}
.event .ev-icon { flex: 0 0 auto; color: var(--muted); }
.event .ev-main { flex: 1; min-width: 0; }
.event .when { font-size: var(--fs-md); font-weight: 600; color: var(--text); }
.event .sub {
  font-size: var(--fs-sm);
  color: var(--muted);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.event .sub .num { color: var(--text); }
.event .ev-actions { display: flex; gap: var(--sp-2); flex: 0 0 auto; }

/* Selected / playing row */
.event.playing {
  background: var(--surface-2);
  border-color: var(--border-strong);
}
.event.playing::before {
  content: '';
  position: absolute;
  left: 0; top: 0; bottom: 0;
  width: 3px;
  border-radius: var(--radius-pill);
  background: var(--primary);
}

/* ---------------------------------------------------------------------------
   20. VIDEO PLAYER
   --------------------------------------------------------------------------- */
.player {
  width: 100%;
  margin: var(--sp-3) 0;
  border-radius: 14px;
  background: #000;
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.06);
}
.player-badge {
  display: inline-flex;
  gap: var(--sp-2);
  margin-top: calc(var(--sp-2) * -1);
  font-family: var(--mono);
  font-size: var(--fs-xs);
  color: var(--muted);
}

/* ---------------------------------------------------------------------------
   21. MOBILE BOTTOM NAV + FAB (Aurora ergonomics)
   --------------------------------------------------------------------------- */
.bottom-nav {
  display: none; /* shown <=640px */
  position: fixed;
  left: 0; right: 0; bottom: 0;
  z-index: 20;
  justify-content: space-around;
  padding: 6px var(--sp-2);
  padding-bottom: max(6px, env(safe-area-inset-bottom));
  background: var(--glass-bg);
  -webkit-backdrop-filter: var(--glass-blur);
  backdrop-filter: var(--glass-blur);
  border-top: 1px solid var(--glass-border);
  box-shadow: 0 -8px 24px -10px rgba(3, 7, 18, 0.7);
}
.bottom-nav .nav-item {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 2px;
  flex: 1;
  min-height: var(--tap);
  padding: 6px 4px;
  font-size: var(--fs-xs);
  color: var(--muted);
  background: none;
  border: none;
  border-radius: var(--radius-sm);
  cursor: pointer;
}
.bottom-nav .nav-item svg { width: 24px; height: 24px; }
.bottom-nav .nav-item.active {
  color: var(--primary);
  background: rgba(37, 99, 235, 0.12);
}

/* Thumb-reachable FAB */
.fab {
  display: none; /* shown <=640px */
  position: fixed;
  right: var(--sp-4);
  bottom: calc(72px + env(safe-area-inset-bottom));
  z-index: 21;
  min-height: 54px;
  padding: 0 22px;
  align-items: center;
  gap: var(--sp-2);
  font-weight: 600;
  font-size: var(--fs-md);
  color: var(--primary-ink);
  background: var(--gradient-primary);
  border: none;
  border-radius: var(--radius-pill);
  box-shadow: var(--shadow), var(--shadow-primary);
  cursor: pointer;
}

@media (max-width: 640px) {
  .bottom-nav { display: flex; }
  .fab { display: inline-flex; }
  /* Hide desktop-only actions that the bottom nav / FAB replace */
  .desktop-only { display: none !important; }
}
@media (min-width: 641px) {
  .mobile-only { display: none !important; }
}

/* "Nuevos eventos" / "Actualizado" live pill */
.live-pill {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  padding: 6px 14px;
  font-size: var(--fs-sm);
  font-weight: 500;
  color: var(--muted);
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: var(--radius-pill);
  cursor: pointer;
}
.live-pill.fresh { color: var(--accent); border-color: rgba(96, 165, 250, 0.32); }

/* ---------------------------------------------------------------------------
   22. REDUCED MOTION — disable pulses / shimmer / lifts, keep instant states
   --------------------------------------------------------------------------- */
@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;
  }
  .cam:hover { transform: none; }
  .btn.primary:hover, .btn:active { transform: none; }
  .badge.active::before { box-shadow: var(--glow-live); }
  .skeleton::after { display: none; }
  .cam.live::after { animation: none; opacity: 0.6; }
  .cam-preview .rec::before { animation: none; }
}

/* ===========================================================================
   16. LOGIN MOTION — dynamic, CTA-driving animation on the AUTH view only.
   Tasteful & GPU-friendly (opacity / transform / box-shadow). Entirely gated
   behind prefers-reduced-motion:no-preference, so users who opt out of motion
   get the calm, fully-static login (every element visible, no animation).
   =========================================================================== */
@media (prefers-reduced-motion: no-preference) {

  /* (a) Slow drifting blue aurora behind the brand hero — the page feels alive. */
  .auth-hero::after {
    content: '';
    position: absolute;
    inset: -28%;
    z-index: 0;
    pointer-events: none;
    background:
      radial-gradient(38% 38% at 28% 32%, rgba(37, 99, 235, 0.32), transparent 70%),
      radial-gradient(34% 34% at 74% 72%, rgba(96, 165, 250, 0.22), transparent 70%);
    filter: blur(38px);
    opacity: 0.7;
    animation: authAurora 17s var(--easing) infinite alternate;
    will-change: transform;
  }
  @keyframes authAurora {
    0%   { transform: translate3d(-3%, -2%, 0) scale(1); }
    50%  { transform: translate3d(4%, 3%, 0) scale(1.12); }
    100% { transform: translate3d(-2%, 4%, 0) scale(1.04); }
  }

  /* (b) Staggered entrance — replays each time the auth view is revealed. */
  .auth-hero .auth-wordmark,
  .auth-hero .auth-headline,
  .auth-hero .auth-subhead,
  .auth-hero .auth-bullets .auth-bullet,
  .auth-hero .auth-trust,
  .auth-panel .auth-foot {
    opacity: 0;
    animation: authRise 0.6s var(--easing) both;
  }
  .auth-panel .auth-card {
    opacity: 0;
    animation: authRiseCard 0.66s var(--easing) both;
  }
  @keyframes authRise {
    from { opacity: 0; transform: translateY(16px); }
    to   { opacity: 1; transform: none; }
  }
  @keyframes authRiseCard {
    from { opacity: 0; transform: translateY(20px) scale(0.985); }
    to   { opacity: 1; transform: none; }
  }
  .auth-hero .auth-wordmark { animation-delay: 0.05s; }
  .auth-hero .auth-headline { animation-delay: 0.13s; }
  .auth-hero .auth-subhead  { animation-delay: 0.21s; }
  .auth-hero .auth-bullets .auth-bullet:nth-child(1) { animation-delay: 0.29s; }
  .auth-hero .auth-bullets .auth-bullet:nth-child(2) { animation-delay: 0.35s; }
  .auth-hero .auth-bullets .auth-bullet:nth-child(3) { animation-delay: 0.41s; }
  .auth-hero .auth-bullets .auth-bullet:nth-child(4) { animation-delay: 0.47s; }
  .auth-hero .auth-trust    { animation-delay: 0.55s; }
  .auth-panel .auth-card    { animation-delay: 0.16s; }
  .auth-panel .auth-foot    { animation-delay: 0.60s; }

  /* (c) Primary CTA pulls focus: soft glow pulse + a periodic light sweep. */
  .auth-panel .btn.primary {
    position: relative;
    overflow: hidden;
    animation: ctaPulse 2.8s ease-in-out 1.1s infinite;
  }
  @keyframes ctaPulse {
    0%, 100% { box-shadow: var(--shadow-primary); }
    50%      { box-shadow: 0 12px 30px -6px rgba(37, 99, 235, 0.55), 0 0 0 4px rgba(37, 99, 235, 0.14); }
  }
  .auth-panel .btn.primary::before {
    content: '';
    position: absolute;
    top: 0; bottom: 0; left: -65%;
    width: 45%;
    background: linear-gradient(100deg, transparent, rgba(255, 255, 255, 0.30), transparent);
    transform: skewX(-18deg);
    pointer-events: none;
    animation: ctaShine 3.8s ease-in-out 1.6s infinite;
  }
  @keyframes ctaShine {
    0%   { left: -65%; }
    32%  { left: 135%; }
    100% { left: 135%; }
  }
  .auth-panel .btn.primary:hover { transform: translateY(-1px); filter: brightness(1.05); }

  /* (d) Brand mark + live "Stripe" trust LED breathe softly. */
  .auth-hero .auth-wordmark .brand-mark { animation: markGlow 3.2s ease-in-out 0.7s infinite; }
  @keyframes markGlow {
    0%, 100% { box-shadow: var(--shadow-primary); }
    50%      { box-shadow: 0 10px 26px -6px rgba(37, 99, 235, 0.6), 0 0 0 3px rgba(37, 99, 235, 0.12); }
  }
  .auth-hero .auth-trust .trust-item:first-child::before { animation: ledBreathe 1.9s ease-in-out infinite; }
  @keyframes ledBreathe {
    0%, 100% { box-shadow: 0 0 6px rgba(34, 197, 94, 0.5); }
    50%      { box-shadow: 0 0 13px rgba(34, 197, 94, 0.95); }
  }

  /* (e) Smooth focus glow on auth inputs. */
  .auth-panel input { transition: border-color var(--dur-base) var(--easing), box-shadow var(--dur-base) var(--easing); }

  /* (f) MOVING LIGHT SOURCE — a soft spotlight travels around the brand hero,
     brightening the grid + aurora as it passes (screen blend = real light). */
  .auth-hero { isolation: isolate; }
  .auth-hero .auth-spotlight {
    position: absolute;
    top: 0; left: 0;
    z-index: 0;                 /* above the grid/aurora, below the content (z 1) */
    width: clamp(360px, 46%, 640px);
    height: clamp(360px, 46%, 640px);
    max-width: none;
    margin: 0;
    border-radius: 50%;
    pointer-events: none;
    background: radial-gradient(circle at center,
      rgba(125, 175, 255, 0.50) 0%,
      rgba(37, 99, 235, 0.28) 32%,
      rgba(37, 99, 235, 0) 70%);
    filter: blur(22px);
    mix-blend-mode: screen;
    animation: authSpotlight 16s ease-in-out infinite;
    will-change: transform;
  }
  @keyframes authSpotlight {
    0%   { transform: translate(-32%, -22%) scale(1); }
    25%  { transform: translate(118%, -8%)  scale(1.12); }
    50%  { transform: translate(132%, 116%) scale(0.96); }
    75%  { transform: translate(-18%, 130%) scale(1.08); }
    100% { transform: translate(-32%, -22%) scale(1); }
  }
}
