/* Generated from design-system/presentation/source. Do not edit. */

/* source: colors_and_type.css */

/*
 * Alarmas Design System — Colors & Type
 * ---------------------------------------------------------------
 * Base tokens + semantic tokens for the Alarmas home-security /
 * domotics app. Values are lifted 1:1 from the production repo
 * (alexZ2M/macro_repo → src/static/css/themes/variables.css).
 *
 * Use semantic tokens in components (e.g. var(--color-primary),
 * var(--fg-1)). Change themes by toggling [data-theme="..."] on a
 * parent; the default is light.
 * ---------------------------------------------------------------
 */

/* ============================================================
 * FONT STACK
 * ============================================================
 * The product uses the system sans-serif (no web font download),
 * which keeps renders fast on PWA + native Capacitor shells and
 * follows each OS's native Latin metrics.
 */
:root {
  --font-sans: ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont,
               "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
  --font-mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas,
               "Liberation Mono", monospace;

  /* ---- Type scale (rem) ---- */
  --text-xs:   0.75rem;   /* 12 */
  --text-sm:   0.875rem;  /* 14 */
  --text-base: 1rem;      /* 16 */
  --text-md:   1.125rem;  /* 18 */
  --text-lg:   1.25rem;   /* 20 */
  --text-xl:   1.5rem;    /* 24 */
  --text-2xl:  1.875rem;  /* 30 */
  --text-3xl:  2.25rem;   /* 36 */

  /* ---- Weights ---- */
  --weight-regular: 400;
  --weight-medium:  500;
  --weight-semibold: 600;
  --weight-bold:    700;

  /* ---- Line heights ---- */
  --leading-tight:  1.25;
  --leading-snug:   1.375;
  --leading-normal: 1.5;
  --leading-relaxed: 1.625;
}

/* ============================================================
 * SPACING, RADII, SHADOW, MOTION (base tokens)
 * ============================================================ */
:root {
  --space-1:  0.25rem;  /*  4px */
  --space-2:  0.5rem;   /*  8px */
  --space-3:  0.75rem;  /* 12px */
  --space-4:  1rem;     /* 16px */
  --space-5:  1.25rem;  /* 20px */
  --space-6:  1.5rem;   /* 24px */
  --space-8:  2rem;     /* 32px */
  --space-10: 2.5rem;   /* 40px */
  --space-12: 3rem;     /* 48px */

  --radius-sm:   0.375rem; /*  6 */
  --radius-md:   0.5rem;   /*  8 */
  --radius-lg:   0.75rem;  /* 12 */
  --radius-xl:   1rem;     /* 16 */
  --radius-2xl:  1.5rem;   /* 24 */
  --radius-full: 9999px;

  --shadow-sm: 0 1px 2px 0 rgba(0, 0, 0, 0.05);
  --shadow-md: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -2px rgba(0, 0, 0, 0.1);
  --shadow-lg: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -4px rgba(0, 0, 0, 0.1);
  --shadow-xl: 0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 8px 10px -6px rgba(0, 0, 0, 0.1);
  --shadow-glass: 0 8px 32px rgba(0, 0, 0, 0.1);

  --glass-blur: blur(10px); /* @kind other */

  --transition-fast: 150ms ease; /* @kind other */
  --transition-base: 200ms ease; /* @kind other */
  --transition-slow: 300ms ease; /* @kind other */

  /* Motion de despliegue/aparición (kit): UN solo lugar para cambiar la animación
   * de modales (dialog-pop), disclosures (runtime toggleDisclosurePanel, que LEE
   * estos tokens) y overlays. @kind other */
  /* Márgenes verticales SIMÉTRICOS de todo overlay a pantalla completa y altura
   * máxima derivada — un solo lugar para el respiro de los modales. @kind other */
  /* SAFE AREA centralizada: insets del dispositivo (notch/isla/home bar) + un
   * margen de seguridad extra. NORMA: ningún contenido se posiciona con
   * env() a pelo; siempre vía estos tokens. @kind other */
  --safe-top: env(safe-area-inset-top, 0px);
  --safe-right: env(safe-area-inset-right, 0px);
  --safe-bottom: env(safe-area-inset-bottom, 0px);
  --safe-left: env(safe-area-inset-left, 0px);
  --safe-gap: 8px;
  --modal-pad-top: max(24px, calc(var(--safe-top) + var(--safe-gap)));
  --modal-pad-bottom: max(24px, calc(var(--safe-bottom) + var(--safe-gap)));
  --modal-max-h: calc(100dvh - 48px);

  --motion-pop-duration: 240ms;   /* entrada de modales */
  --motion-expand-duration: 220ms; /* despliegue de cards y crecimiento por swap */
  --motion-fade-duration: 200ms;  /* fundido de overlays */
  --motion-ease-out: cubic-bezier(.16, 1, .3, 1);

  --z-dropdown: 100; /* @kind other */
  --z-sticky:   200; /* @kind other */
  --z-modal:    300; /* @kind other */
  --z-toast:    400; /* @kind other */
  --z-tooltip:  500; /* @kind other */
}

/* ============================================================
 * UNIVERSAL SEMANTIC STATE COLORS
 * Green = OK / safe / alarm armed & happy
 * Amber = warning / scheduled / low battery
 * Red   = alarm triggered / error / disconnected
 * Blue  = info / primary
 * ============================================================ */
:root {
  --color-success:       #22c55e;
  --color-success-light: #dcfce7;
  --color-warning:       #f59e0b;
  --color-warning-light: #fef3c7;
  --color-error:         #ef4444;
  --color-error-light:   #fee2e2;
  --color-info:          #3b82f6;
  --color-info-light:    #dbeafe;
  /* Compañeros de alto contraste (texto/icono sobre los *-light). Claro = tinte oscuro. */
  --color-error-700:     #991b1b;
  --color-warning-700:   #92400e;
  --color-success-700:   #166534;
  --color-info-700:      #1e40af;
}

/* ============================================================
 * THEME: LIGHT (default)
 * ============================================================ */
[data-theme="light"],
:root {
  /* Esquema de color nativo — hace que time/date pickers y otros controles
   * del sistema se rendericen en su variante clara. */
  color-scheme: light;
  /* Primary — sky / ocean blue */
  --color-primary:       #3b82f6;
  --color-primary-hover: #2563eb;
  --color-primary-light: #dbeafe;            /* tinte claro para soft (.icon-tile.is-soft.tone-primary) */
  --color-primary-50:    #eff6ff;
  --color-primary-100:   #dbeafe;
  --color-primary-200:   #bfdbfe;
  --color-primary-300:   #93c5fd;
  --color-primary-400:   #60a5fa;
  --color-primary-500:   #3b82f6;
  --color-primary-600:   #2563eb;
  --color-primary-700:   #1d4ed8;
  --color-primary-800:   #1e40af;
  --color-primary-900:   #1e3a8a;

  /* Surfaces */
  --color-bg:       #e2e8f0;                    /* slate-200, canvas behind floating cards */
  --color-bg-alt:   #f1f5f9;                    /* slate-100 */
  --color-surface:  rgba(255, 255, 255, 0.9);    /* default card fill */

  /* Foreground — deep navy ink, per brand */
  --color-text:            #1e293b;  /* slate-800 */
  --color-text-secondary:  #64748b;  /* slate-500 */
  --color-text-muted:      #94a3b8;  /* slate-400 */

  /* Borders */
  --color-border:       #e2e8f0;
  --color-border-light: #f1f5f9;

  /* Glass card */
  --glass-bg:     rgba(255, 255, 255, 0.85);
  --glass-border: rgba(148, 163, 184, 0.3);
  --shadow-glass: 0 8px 32px rgba(0, 0, 0, 0.08);

  /* Component-level accents */
  --color-condition-text: #2563eb;  /* blue conditions inside trigger cards */
  --color-action-text:    #15803d;  /* green actions inside trigger cards */

  --color-toggle-active:   #22c55e;
  --color-toggle-inactive: #cbd5e1;

  --color-schedule-bg:     rgba(245, 158, 11, 0.2);
  --color-schedule-border: rgba(180, 83,  9,  0.5);
  --color-schedule-text:   #b45309;
  --color-schedule-value:  #92400e;

  --color-input-bg:          #ffffff;
  --color-input-dropdown-bg: #ffffff;

  /* Nested card surface — anidado dentro de un glass card. Patrón A
   * (canónico, modo claro): el interior es blanco puro sobre el outer
   * glass translúcido, leyéndose como una superficie limpia y plana
   * dentro del contenedor. */
  --color-card-nested-bg:     #ffffff;            /* white — más brillante que el outer 0.85: en claro el inner se lee como ELEVADO sobre su parent (asimétrico al patrón dark donde inner es más oscuro que outer, por elección estética del usuario) */
  --color-card-nested-border: var(--color-border);

  --color-sensor-bg:         #ffffff;             /* alias de --color-card-nested-bg, mantenido por retrocompat */
  --color-card-inactive-bg:  #cbd5e1;             /* slate-300: un punto más oscuro para despegarse del fondo de sección */
  --color-divider-inner:     #b6c2d0;             /* divisor interno de cards expandidas (kit SensorCard/CameraCard) */

  /* ── Jerarquía de superficies (3 niveles) ────────────────
   * Resuelve que card / input / botón-secundario caigan en el mismo
   * tono dentro de un modal. Aditivo: NO cambia el render actual de
   * la app (se cablea a presets ahora, a la app en Fase 4).
   *   · Nivel 1 Card   → --color-surface / --glass-bg
   *   · Nivel 2 Sunken → input/well, MÁS oscuro que el card
   *   · Nivel 3 Tonal  → secundario/chip, distinto de card y de input */
  --color-surface-sunken:        #f8fafc;  /* slate-50  — recessed well */
  --color-surface-tonal:         #f1f5f9;  /* slate-100 — superficie tonal */
  --color-surface-tonal-hover:   #e2e8f0;  /* slate-200 */
  --color-surface-tonal-border:  var(--color-border);
  --color-trigger-active-bg:   rgba(34, 197, 94, 0.12);
  --color-trigger-inactive-bg: #cbd5e1;
}

/* ============================================================
 * THEME: DARK — night-watch navy with soft sky-blue accents
 * ============================================================ */
[data-theme="dark"] {
  color-scheme: dark;
  --color-primary:       #60a5fa;
  --color-primary-hover: #3b82f6;
  --color-primary-light: #1e40af;            /* tinte profundo (par oscuro de --color-primary-light) */
  --color-primary-50:    #1e3a5f;
  --color-primary-100:   #1e3a8a;
  --color-primary-200:   #1e40af;
  --color-primary-300:   #1d4ed8;
  --color-primary-400:   #2563eb;
  --color-primary-500:   #3b82f6;
  --color-primary-600:   #60a5fa;
  --color-primary-700:   #93c5fd;
  --color-primary-800:   #bfdbfe;
  --color-primary-900:   #dbeafe;

  --color-bg:      #0f172a;               /* slate-900 — deep night */
  --color-bg-alt:  #1e293b;               /* slate-800 */
  --color-surface: rgba(30, 41, 59, 0.9); /* slate-800 @ 90 */

  --color-text:           #f1f5f9;
  --color-text-secondary: #94a3b8;
  --color-text-muted:     #64748b;

  --color-border:       #334155;
  --color-border-light: #1e293b;

  --glass-bg:     rgba(30, 41, 59, 0.85);
  --glass-border: rgba(71, 85, 105, 0.5);
  --shadow-glass: 0 8px 32px rgba(0, 0, 0, 0.4);

  --color-success:       #22c55e;
  --color-success-light: #166534;
  --color-warning:       #fbbf24;
  --color-warning-light: #854d0e;
  --color-error:         #f87171;
  --color-error-light:   #991b1b;
  --color-info:          #60a5fa;
  --color-info-light:    #1e40af;
  /* Compañeros de alto contraste (texto/icono sobre los *-light). Oscuro = tinte claro. */
  --color-error-700:     #fecaca;
  --color-warning-700:   #fde68a;
  --color-success-700:   #bbf7d0;
  --color-info-700:      #bfdbfe;

  --color-condition-text: #93c5fd;
  --color-action-text:    #86efac;

  --color-toggle-active:   #4ade80;
  --color-toggle-inactive: #475569;

  --color-schedule-bg:     rgba(245, 158, 11, 0.15);
  --color-schedule-border: rgba(245, 158, 11, 0.4);
  --color-schedule-text:   #fbbf24;
  --color-schedule-value:  #fde047;

  --color-input-bg:          var(--color-bg-alt);
  --color-input-dropdown-bg: #374151;

  /* Nested card — patrón A: interior más oscuro que el outer glass.
   * En oscuro coincide con el page bg, así el inner card se ve como
   * un hueco/well dentro del contenedor. */
  --color-card-nested-bg:     #0f172a;             /* slate-900 — igual al page bg */
  --color-card-nested-border: rgba(71, 85, 105, 0.35);

  --color-sensor-bg:           #0f172a;            /* alias de --color-card-nested-bg */
  --color-card-inactive-bg:    #0c1222;
  --color-divider-inner:       #475569;            /* divisor interno de cards expandidas (kit) */

  /* Jerarquía de superficies — par oscuro. Tonal = slate-700 (MÁS
   * claro que el card slate-800 = se lee elevado); sunken = slate-900
   * (MÁS oscuro que el card = se hunde). Ambos con borde slate-600/700. */
  --color-surface-sunken:        #0f172a;             /* slate-900 — well */
  --color-surface-tonal:         #334155;             /* slate-700 — elevado */
  --color-surface-tonal-hover:   #475569;             /* slate-600 */
  --color-surface-tonal-border:  #475569;             /* slate-600 — contorno visible */
  --color-trigger-active-bg:   rgba(74, 222, 128, 0.15);
  --color-trigger-inactive-bg: #0f172a;
}

/* ============================================================
 * SEMANTIC TYPOGRAPHY
 * These class hooks map onto what templates actually use.
 * ============================================================ */
html {
  font-family: var(--font-sans);
  font-size: 16px;
  line-height: var(--leading-normal);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  color: var(--color-text);
  background: var(--color-bg);
}

h1, .h1 { font-size: var(--text-3xl); font-weight: var(--weight-bold);    line-height: var(--leading-tight); color: var(--color-text); }
h2, .h2 { font-size: var(--text-2xl); font-weight: var(--weight-semibold); line-height: var(--leading-tight); color: var(--color-text); }
h3, .h3 { font-size: var(--text-xl);  font-weight: var(--weight-semibold); line-height: var(--leading-snug);  color: var(--color-text); }
h4, .h4 { font-size: var(--text-lg);  font-weight: var(--weight-semibold); line-height: var(--leading-snug);  color: var(--color-text); }
h5, .h5 { font-size: var(--text-md);  font-weight: var(--weight-semibold); line-height: var(--leading-snug);  color: var(--color-text); }
h6, .h6 { font-size: var(--text-base);font-weight: var(--weight-semibold); line-height: var(--leading-snug);  color: var(--color-text); }

p, .body {
  font-size: var(--text-base);
  line-height: var(--leading-normal);
  color: var(--color-text-secondary);
}

.meta, small {
  font-size: var(--text-sm);
  color: var(--color-text-muted);
}

.label {
  font-size: var(--text-sm);
  font-weight: var(--weight-medium);
  color: var(--color-text);
}

/* Eyebrow / tracker label that recurs across sensor, trigger and modal
 * section headers. Lifted from the real app kit (location-modals.jsx
 * SectionHeader, "Condiciones"/"Acciones", "Sensor", etc.): always
 * UPPERCASE, bold, wide tracking, slate by default. Consumers override
 * the color contextually (primary-700 for "Condiciones", success-700
 * for "Acciones"). */
.label-tracker {
  font-size: 11px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  font-weight: var(--weight-bold);
  color: var(--color-text-secondary);
}

code, .code {
  font-family: var(--font-mono);
  font-size: 0.875em;
  background-color: var(--color-bg-alt);
  padding: 0.125rem 0.375rem;
  border-radius: var(--radius-sm);
}


/* source: html_export/_shared/css/_activation-code.css */

/* ──────────────────────────────────────────────────────────────
 * Alarmas · ACTIVATION-CODE preset — FUENTE ÚNICA
 * ──────────────────────────────────────────────────────────────
 * Extraído 1:1 del kit (location-modals.jsx · CreateLocationModal
 * paso 2 «Configurar HomeHub»). NO confundir con `_code-block.css`
 * (ese es el código de 8 char de COMPARTIR/CANJEAR, 2 grupos de 4).
 *
 * Aquí: el código de ACTIVACIÓN del HomeHub (formato XXX-XXX) que
 * el usuario introduce en el portal AP del hub. Dos consumidores:
 *   · partials/location_create.html  (paso 2 del alta de ubicación)
 *   · partials/homehub_wizard.html   (reanudar provisioning, initialStep=2)
 *
 * Estructura:
 *   .activation-code            → tarjeta (nested-bg + borde)
 *     .activation-code__row       → código grande centrado + botón copiar (abs. dcha)
 *     .activation-code__meta      → «Expira en 10:00» (clock) · rojo si is-expired
 *     .activation-code__bar        → barra de progreso de caducidad
 *     .activation-code__regen      → enlace «Regenerar código»
 *   .activation-steps           → tarjeta de instrucciones (tinte primary)
 *     .activation-steps__num       → círculo numerado (blanco-sobre-marca)
 *
 * Estado caducado: añadir `is-expired` a .activation-code. */

.activation-code {
  padding: 20px;
  border-radius: 14px;
  text-align: center;
  background: var(--color-card-nested-bg);
  border: 1px solid var(--color-border);
}

.activation-code__row {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
}

.activation-code__code {
  font-size: 34px;
  font-weight: 800;
  letter-spacing: 0.14em;
  text-indent: 0.14em;               /* compensa el tracking final → centrado óptico */
  font-family: var(--font-mono, monospace);
  color: var(--color-text);
  text-transform: uppercase;
}
.activation-code.is-expired .activation-code__code {
  color: var(--color-text-muted);
  opacity: 0.55;
}

/* Botón copiar — cuadrado a la derecha del código. */
.activation-code__copy {
  position: absolute;
  right: 0;
  top: 50%;
  transform: translateY(-50%);
  width: 38px;
  height: 38px;
  border-radius: 10px;
  flex-shrink: 0;
  border: 1px solid var(--color-border);
  background: var(--color-surface-tonal);
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  transition: background .15s ease, border-color .15s ease;
}
.activation-code__copy svg { width: 17px; height: 17px; color: var(--color-text-secondary); }
/* Estado «Copiado» → verde. */
.activation-code__copy.is-copied {
  border-color: var(--color-success);
  background: var(--color-success-light);
}
.activation-code__copy.is-copied svg { color: var(--color-success-700); }

/* Meta: cuenta atrás de caducidad. */
.activation-code__meta {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  margin-top: 10px;
  font-size: 12.5px;
  font-weight: 600;
  color: var(--color-text-secondary);
}
.activation-code__meta svg { width: 14px; height: 14px; color: var(--color-text-muted); }
.activation-code__meta .num { font-variant-numeric: tabular-nums; }
.activation-code.is-expired .activation-code__meta { color: var(--color-error); }
.activation-code.is-expired .activation-code__meta svg { color: var(--color-error); }

/* Barra de progreso de caducidad. */
.activation-code__bar {
  margin-top: 12px;
  height: 6px;
  border-radius: 3px;
  background: var(--color-border);
  overflow: hidden;
}
.activation-code__bar-fill {
  height: 100%;
  border-radius: 3px;
  background: var(--color-primary);
  transition: width 1s linear;
}
.activation-code.is-expired .activation-code__bar-fill { background: var(--color-error); }

/* Enlace «Regenerar código». */
.activation-code__regen {
  margin-top: 14px;
  background: none;
  border: none;
  cursor: pointer;
  color: var(--color-primary);
  font-family: inherit;
  font-size: 13px;
  font-weight: 600;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 0;
}
.activation-code__regen svg { width: 14px; height: 14px; color: var(--color-primary); }

/* ── Tarjeta de instrucciones (tinte primary) ── */
.activation-steps {
  margin-top: 18px;
  padding: 16px;
  border-radius: 14px;
  /* Tinte primary theme-adaptativo (una regla, ambos temas): en claro
   * ≈ primary-50 sobre blanco, en oscuro ≈ velo azul sutil sobre slate. */
  background: color-mix(in srgb, var(--color-primary) 10%, transparent);
  border: 1px solid color-mix(in srgb, var(--color-primary) 28%, transparent);
}
.activation-steps__title {
  font-size: 14px;
  font-weight: 700;
  color: var(--color-primary);
  margin: 0 0 14px;
}
.activation-steps__list { display: grid; gap: 13px; }
.activation-steps__item { display: flex; gap: 12px; align-items: flex-start; }
.activation-steps__num {
  width: 24px;
  height: 24px;
  border-radius: 50%;
  flex-shrink: 0;
  background: var(--color-primary);
  color: #fff;                        /* blanco-sobre-marca (misma excepción que .btn--primary) */
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 12px;
  font-weight: 700;
}
.activation-steps__text {
  font-size: 13.5px;
  color: var(--color-text);
  line-height: 1.45;
  padding-top: 2px;
}
.activation-steps__text strong { color: var(--color-text); font-weight: 700; }
.activation-steps__text .mono { font-family: var(--font-mono, monospace); }


/* source: html_export/_shared/css/_button.css */

/* ──────────────────────────────────────────────────────────────
 * Alarmas · BUTTON preset — FUENTE ÚNICA (CSS recipe)
 * ──────────────────────────────────────────────────────────────
 * Botón canónico + variantes. La app tiene el componente Button
 * (primary/secondary/danger/success/glass); el portal lo re-implementa
 * en .btn-*-themed. Esta receta da paridad app + portal + specimens.
 * ────────────────────────────────────────────────────────────── */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  font-family: inherit; font-size: 14px; font-weight: 600; line-height: 1;
  padding: 11px 16px;
  border: 1px solid transparent;
  border-radius: var(--radius-lg);            /* 12px */
  cursor: pointer; user-select: none;
  text-decoration: none;                      /* paridad kit: <a class="btn"> sin subrayado UA */
  transition: background var(--transition-fast), transform var(--transition-fast), box-shadow var(--transition-fast);
}
.btn:active { transform: translateY(0) !important; }

/* Primary — OVERRIDE saturado: brand blue puro en ambos temas. En oscuro,
 * var(--color-primary)=#60a5fa es la versión pastel y se lee "blanquecino";
 * un CTA pide saturación constante. Mismo patrón que .btn--success y toggles.
 * Sombra compuesta (bevel + sharp + spread) para coherencia con --secondary. */
.btn--primary {
  /* Bevel como gradient sobre el bg (empieza en y=0, sin la franja de 1px del bg
   * puro que dejaba `inset 0 1px 0 white` con offset). El contorno + sombras se mantienen. */
  background:
    linear-gradient(180deg, rgba(255,255,255,0.22) 0, rgba(255,255,255,0) 45%),
    #3b82f6;
  color: #fff;
  box-shadow:
    inset 0 0 0 1px rgba(255,255,255,0.15),
    0 0 0 1px rgba(15,23,42,0.10), 0 1px 1px rgba(15,23,42,0.22),
    0 2px 3px rgba(15,23,42,0.28);
}
.btn--primary:hover {
  background:
    linear-gradient(180deg, rgba(255,255,255,0.22) 0, rgba(255,255,255,0) 45%),
    #2563eb;
  transform: translateY(-1px);
  box-shadow:
    inset 0 0 0 1px rgba(255,255,255,0.15),
    0 0 0 1px rgba(15,23,42,0.10), 0 1px 1px rgba(15,23,42,0.24),
    0 3px 5px rgba(15,23,42,0.32);
}

/* Secundario — superficie TONAL (nivel 3): distinta del card y del input
 * para no fundirse dentro de un modal. Claro = slate-100, oscuro = slate-700
 * (más claro que el card slate-800 → se lee elevado). Texto a contraste pleno.
 * Mejora deliberada sobre el Button de la app — se aplicará al kit en Fase 4.
 *
 * Bevel via linear-gradient sobre el bg (coherente con primary/danger/success).
 * Empieza en y=0 sin gap — evita la franja del bg puro arriba que dejarían
 * los inset shadows con offset. Contorno + sombra externa como antes. */
.btn--secondary {
  background:
    linear-gradient(180deg, rgba(255,255,255,0.50) 0, rgba(255,255,255,0) 45%),
    var(--color-surface-tonal);
  color: var(--color-text);
  border-color: color-mix(in srgb, var(--color-text) 18%, transparent);
  box-shadow:
    0 0 0 1px rgba(15,23,42,0.10), 0 1px 1px rgba(15,23,42,0.22),
    0 2px 3px rgba(15,23,42,0.28);
}
.btn--secondary:hover {
  background:
    linear-gradient(180deg, rgba(255,255,255,0.50) 0, rgba(255,255,255,0) 45%),
    var(--color-surface-tonal-hover);
  color: var(--color-text);
  border-color: color-mix(in srgb, var(--color-text) 28%, transparent);
  box-shadow:
    0 0 0 1px rgba(15,23,42,0.10), 0 1px 1px rgba(15,23,42,0.24),
    0 3px 5px rgba(15,23,42,0.32);
  transform: translateY(-1px);
}
/* En oscuro el bevel blanco al 50% se ve fantasmal sobre slate-700 — bajamos. */
[data-theme="dark"] .btn--secondary {
  background:
    linear-gradient(180deg, rgba(255,255,255,0.08) 0, rgba(255,255,255,0) 45%),
    var(--color-surface-tonal);
  box-shadow:
    0 0 0 1px rgba(0,0,0,0.35), 0 1px 1px rgba(0,0,0,0.50),
    0 2px 3px rgba(0,0,0,0.45);
}
[data-theme="dark"] .btn--secondary:hover {
  background:
    linear-gradient(180deg, rgba(255,255,255,0.08) 0, rgba(255,255,255,0) 45%),
    var(--color-surface-tonal-hover);
  box-shadow:
    0 0 0 1px rgba(0,0,0,0.35), 0 1px 1px rgba(0,0,0,0.52),
    0 3px 5px rgba(0,0,0,0.48);
}

/* Danger — OVERRIDE saturado por la misma razón (var(--color-error)=#f87171 en dark). */
.btn--danger  {
  background:
    linear-gradient(180deg, rgba(255,255,255,0.22) 0, rgba(255,255,255,0) 45%),
    #ef4444;
  color: #fff;
  box-shadow:
    inset 0 0 0 1px rgba(255,255,255,0.15),
    0 0 0 1px rgba(15,23,42,0.10), 0 1px 1px rgba(15,23,42,0.22),
    0 2px 3px rgba(15,23,42,0.28);
}
.btn--danger:hover {
  background:
    linear-gradient(180deg, rgba(255,255,255,0.22) 0, rgba(255,255,255,0) 45%),
    #dc2626;
  transform: translateY(-1px);
  box-shadow:
    inset 0 0 0 1px rgba(255,255,255,0.15),
    0 0 0 1px rgba(15,23,42,0.10), 0 1px 1px rgba(15,23,42,0.24),
    0 3px 5px rgba(15,23,42,0.32);
}
/* Success — OVERRIDE: usa un verde más profundo (green-600) para que el texto
 * blanco supere AA-large (3:1). var(--color-success)=#22c55e da ~2.4:1, falla.
 * Mismo patrón que el override del toggle: el preset toma su propia decisión. */
.btn--success {
  background:
    linear-gradient(180deg, rgba(255,255,255,0.22) 0, rgba(255,255,255,0) 45%),
    #16a34a;
  color: #fff;
  box-shadow:
    inset 0 0 0 1px rgba(255,255,255,0.15),
    0 0 0 1px rgba(15,23,42,0.10), 0 1px 1px rgba(15,23,42,0.22),
    0 2px 3px rgba(15,23,42,0.28);
}
.btn--success:hover {
  background:
    linear-gradient(180deg, rgba(255,255,255,0.22) 0, rgba(255,255,255,0) 45%),
    #15803d;
  transform: translateY(-1px);
  box-shadow:
    inset 0 0 0 1px rgba(255,255,255,0.15),
    0 0 0 1px rgba(15,23,42,0.10), 0 1px 1px rgba(15,23,42,0.24),
    0 3px 5px rgba(15,23,42,0.32);
}

/* En oscuro, sombra neutra más profunda (paralela a la del secondary). */
[data-theme="dark"] .btn--primary,
[data-theme="dark"] .btn--danger,
[data-theme="dark"] .btn--success {
  box-shadow:
    inset 0 0 0 1px rgba(255,255,255,0.10),
    0 0 0 1px rgba(0,0,0,0.35), 0 1px 1px rgba(0,0,0,0.50),
    0 2px 3px rgba(0,0,0,0.45);
}
[data-theme="dark"] .btn--primary:hover,
[data-theme="dark"] .btn--danger:hover,
[data-theme="dark"] .btn--success:hover {
  box-shadow:
    inset 0 0 0 1px rgba(255,255,255,0.10),
    0 0 0 1px rgba(0,0,0,0.35), 0 1px 1px rgba(0,0,0,0.52),
    0 3px 5px rgba(0,0,0,0.48);
}

.btn--glass {
  background: var(--glass-bg); color: var(--color-text);
  -webkit-backdrop-filter: var(--glass-blur, blur(10px)); backdrop-filter: var(--glass-blur, blur(10px));
  border-color: var(--glass-border);
}

/* White — botón blanco sólido para superficies cargadas (login dark, pantallas
 * de emergencia con fondo de color). Misma receta 3D (bevel + sombra compuesta)
 * que --primary/--danger/--success, pero el bg es blanco puro y el color del
 * texto se hereda (a menudo se sobrescribe por contexto: cfg.ack en alarmas).
 * SIEMPRE blanco — incluso en oscuro: la usan superficies cargadas donde el
 * contexto provee el contraste, no el tema del DS. */
.btn--white {
  background:
    linear-gradient(180deg, rgba(255,255,255,0.50) 0, rgba(255,255,255,0) 45%),
    #ffffff;
  color: #1e293b;                 /* texto SIEMPRE oscuro: el botón es blanco en ambos temas */
  border-color: color-mix(in srgb, #1e293b 18%, transparent);
  box-shadow:
    0 0 0 1px rgba(15,23,42,0.10), 0 1px 1px rgba(15,23,42,0.22),
    0 2px 3px rgba(15,23,42,0.28);
}
.btn--white:hover {
  background:
    linear-gradient(180deg, rgba(255,255,255,0.50) 0, rgba(255,255,255,0) 45%),
    #f8fafc;
  border-color: color-mix(in srgb, #1e293b 28%, transparent);
  box-shadow:
    0 0 0 1px rgba(15,23,42,0.10), 0 1px 1px rgba(15,23,42,0.24),
    0 3px 5px rgba(15,23,42,0.32);
  transform: translateY(-1px);
}

/* Surface — botón "blanco puro" que SÍ se adapta al tema (claro = #fff,
 * oscuro = slate-800). Difiere de --secondary (tonal slate-100/slate-700) en
 * que aquí el bg coincide con el card-surface base, no con el nivel tonal-elevado.
 * Útil cuando quieres un dismiss neutro que se funda con la superficie de fondo
 * pero conserve el bevel 3D del sistema (ej. "Hecho" en modales de listado). */
.btn--surface {
  background:
    linear-gradient(180deg, rgba(255,255,255,0.50) 0, rgba(255,255,255,0) 45%),
    var(--color-surface);
  color: var(--color-text);
  border-color: color-mix(in srgb, var(--color-text) 18%, transparent);
  box-shadow:
    0 0 0 1px rgba(15,23,42,0.10), 0 1px 1px rgba(15,23,42,0.22),
    0 2px 3px rgba(15,23,42,0.28);
}
.btn--surface:hover {
  background:
    linear-gradient(180deg, rgba(255,255,255,0.50) 0, rgba(255,255,255,0) 45%),
    var(--color-bg-alt);
  border-color: color-mix(in srgb, var(--color-text) 28%, transparent);
  box-shadow:
    0 0 0 1px rgba(15,23,42,0.10), 0 1px 1px rgba(15,23,42,0.24),
    0 3px 5px rgba(15,23,42,0.32);
  transform: translateY(-1px);
}
/* En oscuro el bevel blanco al 50% se ve fantasmal sobre slate-800 — bajamos
 * (mismo patrón que --secondary). */
[data-theme="dark"] .btn--surface {
  background:
    linear-gradient(180deg, rgba(255,255,255,0.08) 0, rgba(255,255,255,0) 45%),
    var(--color-surface);
  box-shadow:
    0 0 0 1px rgba(0,0,0,0.35), 0 1px 1px rgba(0,0,0,0.50),
    0 2px 3px rgba(0,0,0,0.45);
}
[data-theme="dark"] .btn--surface:hover {
  background:
    linear-gradient(180deg, rgba(255,255,255,0.08) 0, rgba(255,255,255,0) 45%),
    var(--color-bg-alt);
  box-shadow:
    0 0 0 1px rgba(0,0,0,0.35), 0 1px 1px rgba(0,0,0,0.52),
    0 3px 5px rgba(0,0,0,0.48);
}

/* Danger-outline — descarte / acción destructiva en forma OUTLINE: superficie
 * del tema (blanca en claro, slate-800 en oscuro) con BORDE y TEXTO rojos y el
 * MISMO bevel 3D del sistema (gradient + sombra compuesta, como --surface).
 * Menos peso visual que --danger sólido; para "Cancelar", "Revocar acceso",
 * "Desvincular" en tarjetas y secciones de compartir. */
.btn--danger-outline {
  background:
    linear-gradient(180deg, rgba(255,255,255,0.50) 0, rgba(255,255,255,0) 45%),
    var(--color-surface);
  color: var(--color-error);
  border-color: color-mix(in srgb, var(--color-error) 45%, transparent);
  box-shadow:
    0 0 0 1px rgba(15,23,42,0.10), 0 1px 1px rgba(15,23,42,0.22),
    0 2px 3px rgba(15,23,42,0.28);
}
.btn--danger-outline:hover {
  background:
    linear-gradient(180deg, rgba(255,255,255,0.50) 0, rgba(255,255,255,0) 45%),
    color-mix(in srgb, var(--color-error) 9%, var(--color-surface));
  color: var(--color-error);
  border-color: var(--color-error);
  transform: translateY(-1px);
  box-shadow:
    0 0 0 1px rgba(15,23,42,0.10), 0 1px 1px rgba(15,23,42,0.24),
    0 3px 5px rgba(15,23,42,0.32);
}
/* En oscuro: bevel blanco más tenue sobre slate-800 (igual que --surface). */
[data-theme="dark"] .btn--danger-outline {
  background:
    linear-gradient(180deg, rgba(255,255,255,0.06) 0, rgba(255,255,255,0) 45%),
    var(--color-surface);
  box-shadow:
    0 0 0 1px rgba(0,0,0,0.35), 0 1px 1px rgba(0,0,0,0.50),
    0 2px 3px rgba(0,0,0,0.45);
}
[data-theme="dark"] .btn--danger-outline:hover {
  background:
    linear-gradient(180deg, rgba(255,255,255,0.06) 0, rgba(255,255,255,0) 45%),
    color-mix(in srgb, var(--color-error) 16%, var(--color-surface));
  box-shadow:
    0 0 0 1px rgba(0,0,0,0.35), 0 1px 1px rgba(0,0,0,0.52),
    0 3px 5px rgba(0,0,0,0.48);
}

/* Primary-outline — gemelo azul del danger-outline: superficie del tema
 * (blanca en claro, slate-800 en oscuro) con BORDE y TEXTO primarios y el
 * MISMO bevel 3D del sistema. Acción secundaria de acento sin el peso del
 * --primary sólido; para "Copiar código", "Pegar código" y similares. */
.btn--primary-outline {
  background:
    linear-gradient(180deg, rgba(255,255,255,0.50) 0, rgba(255,255,255,0) 45%),
    var(--color-surface);
  color: var(--color-primary);
  border-color: color-mix(in srgb, var(--color-primary) 45%, transparent);
  box-shadow:
    0 0 0 1px rgba(15,23,42,0.10), 0 1px 1px rgba(15,23,42,0.22),
    0 2px 3px rgba(15,23,42,0.28);
}
.btn--primary-outline:hover {
  background:
    linear-gradient(180deg, rgba(255,255,255,0.50) 0, rgba(255,255,255,0) 45%),
    color-mix(in srgb, var(--color-primary) 9%, var(--color-surface));
  color: var(--color-primary);
  border-color: var(--color-primary);
  transform: translateY(-1px);
  box-shadow:
    0 0 0 1px rgba(15,23,42,0.10), 0 1px 1px rgba(15,23,42,0.24),
    0 3px 5px rgba(15,23,42,0.32);
}
/* En oscuro: bevel blanco más tenue sobre slate-800 (igual que --surface). */
[data-theme="dark"] .btn--primary-outline {
  background:
    linear-gradient(180deg, rgba(255,255,255,0.06) 0, rgba(255,255,255,0) 45%),
    var(--color-surface);
  box-shadow:
    0 0 0 1px rgba(0,0,0,0.35), 0 1px 1px rgba(0,0,0,0.50),
    0 2px 3px rgba(0,0,0,0.45);
}
[data-theme="dark"] .btn--primary-outline:hover {
  background:
    linear-gradient(180deg, rgba(255,255,255,0.06) 0, rgba(255,255,255,0) 45%),
    color-mix(in srgb, var(--color-primary) 16%, var(--color-surface));
  box-shadow:
    0 0 0 1px rgba(0,0,0,0.35), 0 1px 1px rgba(0,0,0,0.52),
    0 3px 5px rgba(0,0,0,0.48);
}

/* ──────────────────────────────────────────────────────────────
 * SOFT tintados — acción suave dentro de formularios/cards: fondo al
 * 15% del tono + borde al 30% + texto/icono en el tono `700`. La clave
 * de contraste: `--color-<tono>-700` INVIERTE por tema (oscuro en claro,
 * claro en oscuro), así el texto pasa AA en ambos modos sobre el tinte.
 * Planos (sin bevel) — son acciones secundarias tonales, no CTAs.
 * Reemplazan los pares "Guardar/Eliminar" suaves del editor de triggers. */
.btn--soft-success {
  background: color-mix(in srgb, var(--color-success) 15%, transparent);
  color: var(--color-success-700);
  border-color: color-mix(in srgb, var(--color-success) 30%, transparent);
  box-shadow: none;
  font-weight: 500;
}
.btn--soft-success:hover {
  background: color-mix(in srgb, var(--color-success) 24%, transparent);
  border-color: color-mix(in srgb, var(--color-success) 45%, transparent);
}
.btn--soft-danger {
  background: color-mix(in srgb, var(--color-error) 15%, transparent);
  color: var(--color-error-700);
  border-color: color-mix(in srgb, var(--color-error) 30%, transparent);
  box-shadow: none;
  font-weight: 500;
}
.btn--soft-danger:hover {
  background: color-mix(in srgb, var(--color-error) 24%, transparent);
  border-color: color-mix(in srgb, var(--color-error) 45%, transparent);
}
.btn--soft-primary {
  background: color-mix(in srgb, var(--color-primary) 15%, transparent);
  color: var(--color-primary-700);
  border-color: color-mix(in srgb, var(--color-primary) 30%, transparent);
  box-shadow: none;
  font-weight: 500;
}
.btn--soft-primary:hover {
  background: color-mix(in srgb, var(--color-primary) 24%, transparent);
  border-color: color-mix(in srgb, var(--color-primary) 45%, transparent);
}
/* Neutro — pareja "no seleccionada" de un grupo soft (p.ej. el botón
 * inactivo en un On/Off semántico). Superficie lisa + texto secundario. */
.btn--soft-neutral {
  background: var(--color-surface);
  color: var(--color-text-secondary);
  border-color: var(--color-border);
  box-shadow: none;
  font-weight: 500;
}
.btn--soft-neutral:hover {
  background: var(--color-surface-tonal);
  border-color: color-mix(in srgb, var(--color-text) 22%, transparent);
}

/* Ghost — sin fondo, texto secundario, sin sombra. Para acciones de baja
 * prioridad dentro de cards o secciones expandidas. No tiene bevel ni borde:
 * se distingue por su tipografía y posición, no por superficie. */
.btn--ghost {
  background: transparent;
  color: var(--color-text-secondary);
  border-color: transparent;
  box-shadow: none;
}
.btn--ghost:hover {
  background: var(--color-surface-tonal);
  color: var(--color-text);
  box-shadow: none;
  transform: none;
}

.btn--full { width: 100%; }
.btn--sm   { padding: 8px 12px; font-size: 13px; border-radius: var(--radius-md); }
/* Variante LG — CTA grande de pantalla completa (onboarding del portal):
 * radio 16 (--radius-xl) + padding mayor. Reconcilia los CTAs `rounded-xl`
 * del portal sin forzar el radio 12 estándar a los botones compactos de la app. */
.btn--lg   { padding: 14px 20px; font-size: 15px; border-radius: var(--radius-xl); }
.btn:disabled { opacity: .5; cursor: not-allowed; transform: none !important; }

/* ──────────────────────────────────────────────────────────────
 * Botón-icono ghost (.btn-icon) — standalone, NO extiende .btn.
 * Acción compacta solo-icono en barras de tarjeta (sensor, cámara,
 * ubicación, trigger). El color del glifo lo fija el <Icon>; aquí solo
 * geometría + hover tonal. Centraliza los consts btnIcon/iconBtn.
 *   .btn-icon       30×30   ·   .btn-icon--lg  36×36
 * ────────────────────────────────────────────────────────────── */
.btn-icon {
  width: 30px; height: 30px; flex-shrink: 0;
  display: inline-flex; align-items: center; justify-content: center;
  border: none; background: transparent; border-radius: var(--radius-md);
  cursor: pointer; text-decoration: none; transition: background 150ms ease;
}
.btn-icon:hover { background: var(--color-surface-tonal); }
.btn-icon--lg { width: 36px; height: 36px; }
.btn-icon:disabled { opacity: .5; cursor: not-allowed; }

/* ──────────────────────────────────────────────────────────────
 * Botón de AYUDA (.btn-help) — el "?" estándar de "más información".
 * Círculo 3D con el bevel del sistema (gradient + borde + sombra
 * compuesta, nivel TONAL para destacar sobre cards). Glifo neutro que
 * vira a primario al hover. Pensado para cabeceras de secciones que
 * puedan confundir al usuario. Standalone, NO extiende .btn.
 *   .btn-help  24×24   ·   .btn-help--lg  28×28
 * ────────────────────────────────────────────────────────────── */
.btn-help {
  width: 24px; height: 24px; flex-shrink: 0; padding: 0;
  display: inline-flex; align-items: center; justify-content: center;
  border-radius: 50%;
  border: 1px solid color-mix(in srgb, var(--color-text) 18%, transparent);
  background:
    linear-gradient(180deg, rgba(255,255,255,0.55) 0, rgba(255,255,255,0) 45%),
    var(--color-surface-tonal);
  color: var(--color-text-secondary);
  font-family: inherit; font-size: 12px; font-weight: 700; line-height: 1;
  cursor: pointer;
  box-shadow:
    0 1px 1px rgba(15,23,42,0.18),
    0 2px 3px rgba(15,23,42,0.22);
  transition: background var(--transition-fast), transform var(--transition-fast),
              box-shadow var(--transition-fast), color var(--transition-fast),
              border-color var(--transition-fast);
}
.btn-help:hover {
  color: var(--color-primary);
  border-color: color-mix(in srgb, var(--color-primary) 45%, transparent);
  transform: translateY(-1px);
  box-shadow:
    0 1px 1px rgba(15,23,42,0.20),
    0 3px 5px rgba(15,23,42,0.26);
}
.btn-help:active { transform: translateY(0); }
.btn-help--lg { width: 28px; height: 28px; font-size: 14px; }
/* En oscuro: bevel blanco más tenue sobre slate-700 tonal, borde visible.
 * El glifo sube de contraste (entre secondary y text) para leerse mejor. */
[data-theme="dark"] .btn-help {
  background:
    linear-gradient(180deg, rgba(255,255,255,0.07) 0, rgba(255,255,255,0) 45%),
    var(--color-surface-tonal);
  border-color: var(--color-surface-tonal-border);
  color: color-mix(in srgb, var(--color-text) 70%, var(--color-text-secondary));
  box-shadow:
    0 1px 1px rgba(0,0,0,0.50),
    0 2px 3px rgba(0,0,0,0.45);
}
[data-theme="dark"] .btn-help:hover {
  color: var(--color-primary);
  border-color: color-mix(in srgb, var(--color-primary) 55%, transparent);
}


/* source: html_export/_shared/css/_callout.css */

/* ──────────────────────────────────────────────────────────────
 * Alarmas · CALLOUT (caja de estado) preset — FUENTE ÚNICA · app + portal
 * ──────────────────────────────────────────────────────────────
 * La "caja de estado" tonal: un fondo `*-light` con texto/icono de alto
 * contraste `*-700`, por tono semántico (error · warning · success · info)
 * y theme-aware. Unifica:
 *   · Portal → cuadro "Error de validación", placa con la ✕, bloque
 *     "Reconfigurar WiFi", avisos del asistente.
 *   · App → filas de alerta de SensorCard, .dialog-alert / cascade, etc.
 *
 * Dos superficies, MISMO par de color:
 *   .callout       → caja con texto (+ icono opcional a la izquierda).
 *   .callout-tile  → placa cuadrada con un icono centrado (la ✕ grande).
 * El tono se aplica con un modificador en CUALQUIERA de las dos:
 *   <div class="callout callout--error">…</div>
 *   <div class="callout-tile callout--error"><svg>✕</svg></div>
 * El icono/texto heredan el color del tono vía `currentColor`.
 * ────────────────────────────────────────────────────────────── */

/* Caja con texto */
.callout {
  display: flex; gap: 10px; align-items: flex-start;
  padding: 12px 14px;
  border: 1px solid transparent;
  border-radius: var(--radius-lg);            /* 12px */
  font-size: 13px; line-height: 1.5;
}
.callout > svg { flex-shrink: 0; width: 18px; height: 18px; margin-top: 1px; }
/* Los <p>/<small> internos heredan el color del tono — gana al reset base
 * `p { color: var(--color-text-secondary) }` de colors_and_type.css. */
.callout p, .callout small { color: inherit; }
.callout--center { justify-content: center; text-align: center; }
.callout-strong { font-weight: 600; }         /* línea destacada dentro de la caja */

/* Placa de icono (cuadrado con icono centrado) — mismo par de color */
.callout-tile {
  display: inline-flex; align-items: center; justify-content: center; flex-shrink: 0;
  width: 64px; height: 64px;
  border: 1px solid transparent;
  border-radius: var(--radius-2xl);           /* 24px */
}
.callout-tile > svg { width: 50%; height: 50%; }
.callout-tile--sm { width: 40px; height: 40px; border-radius: var(--radius-lg); }

/* Compacta — filas de alerta densas (SensorCard, cámara, avisos en línea). */
.callout--sm { padding: 6px 10px; gap: 6px; font-size: 12px; border-radius: var(--radius-md); }
.callout--sm > svg { width: 14px; height: 14px; margin-top: 0; }

/* ── Tonos — fondo `*-light` + texto/icono `*-700` (alto contraste, theme-aware).
 *    El borde es el tono saturado a baja opacidad. Sirven igual a .callout y a .callout-tile. */
.callout--error   { background: var(--color-error-light);   color: var(--color-error-700);
                    border-color: color-mix(in srgb, var(--color-error) 22%, transparent); }
.callout--warning { background: var(--color-warning-light); color: var(--color-warning-700);
                    border-color: color-mix(in srgb, var(--color-warning) 22%, transparent); }
.callout--success { background: var(--color-success-light); color: var(--color-success-700);
                    border-color: color-mix(in srgb, var(--color-success) 22%, transparent); }
.callout--info    { background: var(--color-info-light);    color: var(--color-info-700);
                    border-color: color-mix(in srgb, var(--color-info) 22%, transparent); }


/* source: html_export/_shared/css/_chip.css */

/* ──────────────────────────────────────────────────────────────
 * Alarmas · CHIP preset — FUENTE ÚNICA (CSS recipe)
 * ──────────────────────────────────────────────────────────────
 * Geometría única para los tres patrones "pill/chip" que hoy se
 * repiten inline (~10 veces) en el App Kit:
 *   · status-pill  → el átomo <Badge> (dot + texto). El COLOR sigue
 *                    siendo dinámico vía statusTone(tone, tk) — eso es
 *                    inline justificado; aquí solo va la forma.
 *   · type-chip    → el chip de tipo de sensor (sensor.kind): MAYÚSCULAS,
 *                    gris, radio pequeño. Color estático = 100% en CSS.
 *   · count-badge  → el badge numérico de notificaciones.
 *
 * Filosofía idéntica al resto de presets: cambiar la forma del pill
 * en TODO el producto = editar solo este archivo.
 * ────────────────────────────────────────────────────────────── */

/* Base — status-pill: forma del Badge. El consumidor aporta background/
 * color (statusTone) y el color del punto; aquí solo la geometría. */
.chip {
  display: inline-flex; align-items: center; gap: 6px; white-space: nowrap;
  font-family: inherit; font-size: 11px; font-weight: 500; line-height: 1.4;
  padding: 3px 10px; border-radius: 9999px;
  border: 1px solid transparent;
}
.chip > .chip-dot { width: 7px; height: 7px; border-radius: 50%; flex-shrink: 0; }

/* TYPE — chip de tipo de sensor: MAYÚSCULAS, gris tonal, radio 6.
 * Color 100% por token (estático), no necesita inline. */
.chip--type {
  font-size: 10px; font-weight: 600; letter-spacing: .04em; text-transform: uppercase;
  color: var(--color-text-secondary);
  background: rgba(148, 163, 184, .12);
  border-radius: 6px; padding: 3px 7px;
}

/* COUNT — badge numérico (notificaciones). Por defecto primary; el
 * consumidor puede sobrescribir el fondo inline (badgeTone) cuando aplique.
 * Texto SIEMPRE blanco: el fondo puede ser primary o un tono de alerta
 * (rojo/ámbar) según badgeTone, y el blanco mantiene contraste en todos. */
.chip--count {
  min-width: 18px; height: 18px; padding: 0 5px; justify-content: center;
  font-size: 10px; font-weight: 700; border-radius: 9999px;
  color: #fff; background: var(--color-primary);
}


/* source: html_export/_shared/css/_code-block.css */

/* ──────────────────────────────────────────────────────────────
 * Alarmas · CODE-BLOCK preset — FUENTE ÚNICA del bloque de código
 * ──────────────────────────────────────────────────────────────
 * Un solo recipe para los DOS usos del código de 8 caracteres:
 *
 *   · GENERACIÓN — el propietario emite un código para compartir:
 *       contenedor + código en 2 grupos de 4 + cuenta atrás de
 *       caducidad + botón "Copiar código".
 *   · CANJE — el invitado introduce el código que le han pasado:
 *       MISMO contenedor + MISMOS 2 grupos de 4 (editables) + SIN
 *       cuenta atrás + botón "Pegar código".
 *
 * Comparten contenedor, tipografía, cajas y acento. La diferencia
 * (cuenta atrás / copiar-vs-pegar / cajas read-only vs editables)
 * la decide el modo. Cambiar aquí el estilo cambia ambos a la vez. */

.code-block {
  background: var(--color-primary-50);
  border: 1px dashed color-mix(in srgb, var(--color-primary) 40%, transparent);
  border-radius: 14px;
  padding: 16px;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 12px;
}
[data-theme="dark"] .code-block {
  background: color-mix(in srgb, var(--color-primary) 10%, transparent);
}
/* Caducado / inválido — el borde pasa a rojo punteado. */
.code-block.is-expired {
  border-color: color-mix(in srgb, var(--color-error) 40%, transparent);
}

/* Fila del código: 2 grupos de 4 con separador central. */
.code-block__code {
  display: flex;
  align-items: center;
  gap: 10px;
  font-family: var(--font-mono);
}
.code-block.is-expired .code-block__code { opacity: 0.5; }

.code-block__group {
  font-size: 26px;
  font-weight: 700;
  color: var(--color-primary-700);
  letter-spacing: 0.18em;
  text-indent: 0.18em;            /* compensa el tracking final → centrado óptico */
  padding: 6px 12px;
  min-width: 4ch;
  text-align: center;
  background: var(--color-surface);
  border: 1px solid color-mix(in srgb, var(--color-primary) 22%, transparent);
  border-radius: 10px;
  text-transform: uppercase;
}
[data-theme="dark"] .code-block__group {
  background: color-mix(in srgb, var(--color-bg) 60%, transparent);
}
/* Grupo editable (modo canje): input que se ve idéntico a la caja. */
input.code-block__group {
  width: 5ch;
  box-sizing: content-box;        /* el padding 12px va aparte del ancho de texto */
  letter-spacing: 0.14em;
  text-indent: 0.14em;
  font-family: var(--font-mono);
  outline: none;
  caret-color: var(--color-primary);
}
input.code-block__group::placeholder {
  color: var(--color-text-muted);
  opacity: 0.55;
}
input.code-block__group:focus {
  border-color: var(--color-primary);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--color-primary) 18%, transparent);
}

.code-block__sep {
  color: var(--color-primary);
  font-size: 22px;
  font-weight: 700;
  line-height: 1;
}

/* ── Campo ÚNICO (modo canje) ──
 * Un solo input con el código completo. El "·" central es SOLO visual
 * (se inserta al formatear el value para mostrarlo agrupado 4+4), pero
 * el estado guarda el código CRUDO y los handlers copy/cut escriben el
 * código sin formato en el portapapeles. Así pegar un código completo
 * llena todo el campo y copiar devuelve el número limpio. */
.code-block__single {
  font-family: var(--font-mono);
  font-size: 26px;
  font-weight: 700;
  color: var(--color-primary-700);
  letter-spacing: 0.12em;
  text-align: center;
  text-transform: uppercase;
  padding: 6px 18px;
  width: 14ch;
  box-sizing: content-box;
  background: var(--color-surface);
  border: 1px solid color-mix(in srgb, var(--color-primary) 22%, transparent);
  border-radius: 10px;
  outline: none;
  caret-color: var(--color-primary);
}
[data-theme="dark"] .code-block__single {
  background: color-mix(in srgb, var(--color-bg) 60%, transparent);
}
.code-block__single::placeholder { color: var(--color-text-muted); opacity: 0.5; }
.code-block__single:focus {
  border-color: var(--color-primary);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--color-primary) 18%, transparent);
}

/* Fila inferior: meta (cuenta atrás) + acción (copiar / pegar). */
.code-block__meta {
  display: flex;
  align-items: center;
  gap: 14px;
  font-size: 12px;
  color: var(--color-text-secondary);
}
.code-block__time {
  display: inline-flex;
  align-items: center;
  gap: 5px;
}
.code-block__time strong {
  font-family: var(--font-mono);
  font-weight: 600;
  color: var(--color-text);
}
.code-block.is-expired .code-block__time { color: var(--color-error); font-weight: 600; }

/* Las acciones Copiar / Pegar usan el preset de botón 3D
 * `.btn--primary-outline .btn--sm` (definido en _button.css): superficie
 * del tema + borde y texto azules + bevel. El estado "Copiado" cambia a
 * `.btn--success`. Aquí solo se ajusta el tamaño del icono dentro de la
 * fila meta para que case con la tipografía. */
.code-block__meta .btn svg { width: 13px; height: 13px; }


/* source: html_export/_shared/css/_conn-pulse.css */

/* ──────────────────────────────────────────────────────────────
 * Alarmas · CONN-PULSE preset — FUENTE ÚNICA (CSS recipe)
 * Extraído 1:1 del kit (screens.jsx · <style> de Dashboard).
 * Punto de conexión "vivo": pulsa en el color del estado vía las
 * CSS vars --pulse-strong / --pulse-soft (verde por defecto).
 * `off`/desconectado NO lleva la clase (inerte).
 * Uso: <span class="conn-pulse" style="background:...;
 *        --pulse-strong:...; --pulse-soft:..."></span>
 * ────────────────────────────────────────────────────────────── */

@keyframes connPulse {
  0%   { box-shadow: 0 0 0 0   var(--pulse-strong, rgba(34,197,94,0.55)),
                     0 0 0 3px var(--pulse-soft,   rgba(34,197,94,0.22)); }
  70%  { box-shadow: 0 0 0 6px rgba(0,0,0,0),
                     0 0 0 3px var(--pulse-soft,   rgba(34,197,94,0.22)); }
  100% { box-shadow: 0 0 0 0   rgba(0,0,0,0),
                     0 0 0 3px var(--pulse-soft,   rgba(34,197,94,0.22)); }
}
.conn-pulse { animation: connPulse 1.8s ease-out infinite; }
@media (prefers-reduced-motion: reduce) {
  .conn-pulse, .device-card__dot, .location-status--online { animation: none; }
}


/* source: html_export/_shared/css/_disclosure.css */

/* ──────────────────────────────────────────────────────────────
 * Alarmas · DISCLOSURE preset — cabecera de sección colapsable
 * ──────────────────────────────────────────────────────────────
 * El botón-cabecera de un acordeón: ancho completo, transparente,
 * fila con icono/avatar + texto + caret. Centraliza el "chrome"
 * repetido ~15 veces en sharing-profile.jsx (suscripción, idioma,
 * zona horaria, tema, info personal, contraseña, notificaciones,
 * código, invitados…).
 *
 * El giro del caret se deja al consumidor (está ligado al estado
 * `open` del componente) — envuélvelo en .disclosure-caret y aplica
 * el transform inline, o usa [aria-expanded] si lo prefieres:
 *   <button class="disclosure" aria-expanded={open}> … 
 *     <span class="disclosure-caret">▾</span>
 *   </button>
 * (.disclosure[aria-expanded="true"] .disclosure-caret rota solo.)
 *
 * Variantes de densidad por modificador (en vez de overrides inline):
 *   .disclosure--gap-sm   gap 8px
 *   .disclosure--compact  padding 10px 12px, gap 10px
 *   .disclosure--row      min-height 52px (filas de ajustes)
 * ────────────────────────────────────────────────────────────── */

.disclosure {
  width: 100%;
  border: none;
  background: transparent;
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 12px 14px;
  cursor: pointer;
  text-align: left;
  font-family: inherit;
  color: inherit;
}

.disclosure--gap-sm  { gap: 8px; }
.disclosure--compact { gap: 10px; padding: 10px 12px; }
.disclosure--row     { min-height: 52px; }

/* Columna de texto central (crece y trunca). */
.disclosure-main { flex: 1; min-width: 0; }
/* Variante CENTRADA — cabecera de card colapsable sin chevron (icono + título al centro). */
.disclosure--center { justify-content: center; }
.disclosure--center .disclosure-main { flex: 0 1 auto; text-align: center; }

/* Caret — rotación opcional vía aria-expanded (si no, transform inline). */
.disclosure-caret {
  display: flex;
  align-items: center;
  flex-shrink: 0;
  transition: transform .2s ease;
}
.disclosure[aria-expanded="true"] .disclosure-caret { transform: rotate(180deg); }


/* source: html_export/_shared/css/_dropdown-preset.css */

/* ──────────────────────────────────────────────────────────────
 * Alarmas · Inline-Dropdown preset
 * Single-source-of-truth para todas las superficies del componente
 * InlineSelect / .ds. Cualquier consumidor (preview/dropdowns.html,
 * ui_kits/app/location-modals.jsx → InlineSelect, futuros pickers)
 * debe pintar contra estos tokens — nunca hardcodear hex/rgba.
 *
 * Cambiar la paleta del marco azulado, del fondo del activo, de
 * los bordes o del hover SOLO requiere editar este archivo.
 *
 * Estructura visual del componente (anatomía):
 *
 *   ┌──────────────────────────── .ds ────────────────────────────┐
 *   │  bg: --ds-bg   border: --ds-border   radius: --ds-radius     │
 *   │  ┌─── .ds-head ──────────────────────────────────────────┐   │
 *   │  │ [icon]   etiqueta                          chevron    │   │
 *   │  └───────────────────────────────────────────────────────┘   │
 *   │  ┌─── .ds-panel ── bg: --ds-panel-bg ────────────────────┐   │
 *   │  │ ┌─ .ds-search ─ bg: --ds-search-bg ───────────────┐   │   │
 *   │  │ └─────────────────────────────────────────────────┘   │   │
 *   │  │ ┌─ .ds-list ─── bg: --ds-list-bg ──────────────────┐  │   │
 *   │  │ │   .ds-opt                                        │  │   │
 *   │  │ │   .ds-opt.is-active  bg: --ds-opt-active-bg      │  │   │
 *   │  │ └──────────────────────────────────────────────────┘  │   │
 *   │  └────────────────────────────────────────────────────────┘  │
 *   └──────────────────────────────────────────────────────────────┘
 * ────────────────────────────────────────────────────────────── */

:root {
  /* Outer container (header) */
  --ds-radius:            12px;
  --ds-bg:                #ffffff;
  --ds-border:            #e2e8f0;
  --ds-focus-ring:        rgba(59,130,246,.15);

  /* Icon chip (header) */
  --ds-icon-bg:           rgba(59,130,246,0.13);
  --ds-icon-color:        #3b82f6;

  /* Texto del placeholder del trigger: NO es el color del caret (94a3b8 sobre
   * blanco da 2.56:1). Token propio = texto secundario. */
  --ds-placeholder-color: #64748b;

  /* Caret (chevron) */
  --ds-caret-color:       #94a3b8;
  --ds-caret-color-open:  #3b82f6;

  /* Panel — marco exterior cuando está abierto (tinte azul) */
  --ds-panel-bg:          rgba(59,130,246,0.06);
  --ds-panel-border:      rgba(59,130,246,0.15);
  --ds-panel-pad:         8px;
  /* Panel flotante (.ds--floating): fondo OPACO propio + sombra.
   * No reutilizar --ds-bg: es semitransparente (glass de la cabecera). */
  --ds-menu-bg:           #ffffff;
  --ds-menu-shadow:       0 12px 32px rgba(2,6,23,0.14), 0 2px 6px rgba(2,6,23,0.06);

  /* Search input */
  --ds-search-bg:         #ffffff;
  --ds-search-border:     rgba(148,163,184,0.25);
  --ds-search-focus:      #3b82f6;

  /* List — la "tarjeta" blanca interior */
  --ds-list-bg:           #ffffff;
  --ds-list-border:       rgba(148,163,184,0.25);
  --ds-list-radius:       10px;
  --ds-list-max-h:        260px;

  /* Options */
  --ds-opt-divider:       rgba(148,163,184,0.12);
  --ds-opt-hover-bg:      #f8fafc;
  --ds-opt-active-bg:     #dbeafe;   /* primary-100 */
  --ds-opt-active-text:   #1d4ed8;   /* primary-700 */
  --ds-opt-text:          #1e293b;
  --ds-opt-hint:          #64748b;

  /* Check pill */
  --ds-check-bg:          #3b82f6;
  --ds-check-fg:          #ffffff;

  /* Scrollbar de la lista (solo web/desktop; en táctil se oculta) */
  --ds-scroll-thumb:       rgba(148,163,184,0.55);
  --ds-scroll-thumb-hover: rgba(100,116,139,0.85);
}

[data-theme="dark"] {
  --ds-bg:                rgba(30,41,59,0.50);
  --ds-border:            #334155;
  --ds-focus-ring:        rgba(96,165,250,.20);

  --ds-icon-bg:           rgba(96,165,250,0.18);
  --ds-icon-color:        #60a5fa;

  --ds-placeholder-color: #94a3b8;
  --ds-caret-color:       #64748b;
  --ds-caret-color-open:  #60a5fa;

  --ds-panel-bg:          rgba(96,165,250,0.08);
  --ds-panel-border:      rgba(96,165,250,0.20);
  --ds-menu-bg:           #1e293b;
  --ds-menu-shadow:       0 12px 32px rgba(0,0,0,0.45), 0 2px 6px rgba(0,0,0,0.30);

  --ds-search-bg:         rgba(15,23,42,0.55);
  --ds-search-border:     rgba(71,85,105,0.5);
  --ds-search-focus:      #60a5fa;

  --ds-list-bg:           rgba(15,23,42,0.55);
  --ds-list-border:       rgba(71,85,105,0.5);

  --ds-opt-divider:       rgba(71,85,105,0.4);
  --ds-opt-hover-bg:      rgba(148,163,184,0.08);
  --ds-opt-active-bg:     rgba(96,165,250,0.22);
  --ds-opt-active-text:   #93c5fd;
  --ds-opt-text:          #f1f5f9;
  --ds-opt-hint:          #94a3b8;

  --ds-check-bg:          #60a5fa;
  --ds-check-fg:          #0f172a;

  --ds-scroll-thumb:       rgba(100,116,139,0.60);
  --ds-scroll-thumb-hover: rgba(148,163,184,0.90);
}

/* Scope de "tarjeta oscura embebida" — para previews donde una card .dark
 * convive con el resto de cards claras (mismo patrón que usamos en
 * preview/dropdowns.html). Mantiene la API sin tener que duplicar reglas
 * en cada consumidor. */
.card.dark {
  --ds-bg:                rgba(30,41,59,0.50);
  --ds-border:            #334155;
  --ds-focus-ring:        rgba(96,165,250,.20);
  --ds-icon-bg:           rgba(96,165,250,0.18);
  --ds-icon-color:        #60a5fa;
  --ds-placeholder-color: #94a3b8;
  --ds-caret-color:       #64748b;
  --ds-caret-color-open:  #60a5fa;
  --ds-panel-bg:          rgba(96,165,250,0.08);
  --ds-panel-border:      rgba(96,165,250,0.20);
  --ds-menu-bg:           #1e293b;
  --ds-menu-shadow:       0 12px 32px rgba(0,0,0,0.45), 0 2px 6px rgba(0,0,0,0.30);
  --ds-search-bg:         rgba(15,23,42,0.55);
  --ds-search-border:     rgba(71,85,105,0.5);
  --ds-search-focus:      #60a5fa;
  --ds-list-bg:           rgba(15,23,42,0.55);
  --ds-list-border:       rgba(71,85,105,0.5);
  --ds-opt-divider:       rgba(71,85,105,0.4);
  --ds-opt-hover-bg:      rgba(148,163,184,0.08);
  --ds-opt-active-bg:     rgba(96,165,250,0.22);
  --ds-opt-active-text:   #93c5fd;
  --ds-opt-text:          #f1f5f9;
  --ds-opt-hint:          #94a3b8;
  --ds-check-bg:          #60a5fa;
  --ds-check-fg:          #0f172a;
  --ds-scroll-thumb:       rgba(100,116,139,0.60);
  --ds-scroll-thumb-hover: rgba(148,163,184,0.90);
}

/* ──────────────────────────────────────────────────────────────
 * Reglas del componente — todas referencian tokens. No tocar a
 * mano los valores: editar el bloque :root / [data-theme="dark"]
 * de arriba.
 * ────────────────────────────────────────────────────────────── */

.ds {
  border-radius: var(--ds-radius);
  background: var(--ds-bg);
  border: 1px solid var(--ds-border);
  overflow: hidden;
  transition: border-color 150ms ease, box-shadow 150ms ease;
}
.ds.is-focus { border-color: var(--ds-icon-color); box-shadow: 0 0 0 3px var(--ds-focus-ring); }

.ds-head {
  width: 100%; border: none; background: transparent;
  display: flex; align-items: center; gap: 12px;
  padding: 12px; min-height: 48px;
  cursor: pointer; text-align: left; font-family: inherit;
  color: inherit;
}
.ds-head:focus-visible { outline: none; }

.ds-icon {
  width: 30px; height: 30px; border-radius: 8px;
  background: var(--ds-icon-bg);
  display: flex; align-items: center; justify-content: center; flex-shrink: 0;
}
.ds-icon svg { width: 15px; height: 15px; stroke: var(--ds-icon-color); }

.ds-label {
  flex: 1; min-width: 0;
  font-size: 14px; font-weight: 500; color: var(--ds-opt-text);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.ds-label.is-placeholder { color: var(--ds-placeholder-color, #64748b); font-weight: 500; }

.ds-caret { display: flex; transition: transform .2s ease; }
.ds-caret svg { width: 16px; height: 16px; stroke: var(--ds-caret-color); }
.ds.is-open .ds-caret { transform: rotate(180deg); }
.ds.is-open .ds-caret svg { stroke: var(--ds-caret-color-open); }

.ds-panel {
  padding: var(--ds-panel-pad);
  background: var(--ds-panel-bg);
  border-top: 1px solid var(--ds-panel-border);
}
.ds:not(.is-open) .ds-panel { display: none; }

.ds-search {
  position: relative; display: flex; align-items: center;
  margin: 0 0 var(--ds-panel-pad);
}
.ds-search .s {
  position: absolute; left: 10px; width: 14px; height: 14px;
  stroke: var(--ds-caret-color); pointer-events: none;
  display: flex;
}
.ds-search input {
  width: 100%; box-sizing: border-box;
  padding: 8px 32px 8px 30px;
  font-size: 13px; font-family: inherit;
  background: var(--ds-search-bg);
  border: 1px solid var(--ds-search-border);
  border-radius: 9px;
  color: var(--ds-opt-text); outline: none;
}
.ds-search input::placeholder { color: var(--ds-caret-color); }
/* type="search" pinta su PROPIO botón de borrar (WebKit), que se sumaba al
 * .clear del preset: dos X. Se oculta el nativo. */
.ds-search input::-webkit-search-cancel-button, .ds-search input::-webkit-search-decoration { -webkit-appearance: none; appearance: none; display: none; }
.ds-search input:focus { border-color: var(--ds-search-focus); }
.ds-search .clear {
  position: absolute; right: 6px;
  width: 22px; height: 22px; border-radius: 50%; border: none;
  background: rgba(148,163,184,.25);
  display: flex; align-items: center; justify-content: center; cursor: pointer;
}
.ds-search .clear svg { width: 12px; height: 12px; stroke: var(--ds-opt-hint); }

.ds-list {
  background: var(--ds-list-bg);
  border: 1px solid var(--ds-list-border);
  border-radius: var(--ds-list-radius);
  overflow: hidden;
  max-height: var(--ds-list-max-h); overflow-y: auto;
  /* Scrollbar temática (adapta claro/oscuro vía tokens) — Firefox */
  scrollbar-width: thin;
  scrollbar-color: var(--ds-scroll-thumb) transparent;
}
/* Scrollbar temática — WebKit/Blink */
.ds-list::-webkit-scrollbar { width: 8px; }
.ds-list::-webkit-scrollbar-track { background: transparent; }
.ds-list::-webkit-scrollbar-thumb {
  background: var(--ds-scroll-thumb);
  border-radius: 9999px;
  border: 2px solid transparent;
  background-clip: padding-box;
}
.ds-list::-webkit-scrollbar-thumb:hover {
  background: var(--ds-scroll-thumb-hover);
  background-clip: padding-box;
}
/* Móvil/táctil (app nativa / PWA): overlay del sistema, sin barra persistente. */
@media (pointer: coarse) {
  .ds-list { scrollbar-width: none; }
  .ds-list::-webkit-scrollbar { width: 0; display: none; }
}

.ds-opt {
  width: 100%; border: none;
  display: flex; align-items: center; gap: 10px;
  padding: 10px 12px;
  background: transparent;
  cursor: pointer; text-align: left; font-family: inherit;
  transition: background .12s ease;
  color: var(--ds-opt-text);
}
.ds-opt + .ds-opt { border-top: 1px solid var(--ds-opt-divider); }
.ds-opt:hover { background: var(--ds-opt-hover-bg); }
.ds-opt.is-active { background: var(--ds-opt-active-bg); }

.ds-opt-label {
  flex: 1; min-width: 0;
  font-size: 14px; font-weight: 500; color: var(--ds-opt-text);
  line-height: normal;   /* sin esto hereda el 1.5 del body y la fila crece a 60px (kit: 52) */
}
.ds-opt.is-active .ds-opt-label { color: var(--ds-opt-active-text); font-weight: 600; }

.ds-opt-hint { font-size: 12px; color: var(--ds-opt-hint); margin-top: 1px; line-height: normal; }
/* Opción SELECCIONADA: el hint mantenía el tono normal sobre la superficie
 * activa (primary-100 en claro) y bajaba a 3.9:1. Un escalón más de tinta. */
.ds-opt.is-active .ds-opt-hint { color: #475569; }
html[data-theme="dark"] .ds-opt.is-active .ds-opt-hint { color: #cbd5e1; }

.ds-check {
  width: 20px; height: 20px; border-radius: 50%; background: var(--ds-check-bg);
  display: flex; align-items: center; justify-content: center; flex-shrink: 0;
}
.ds-check svg { width: 12px; height: 12px; stroke: var(--ds-check-fg); stroke-width: 3; }
.ds-opt:not(.is-active) .ds-check { display: none; }

.ds-empty {
  padding: 16px 12px; text-align: center;
  font-size: 13px; color: var(--ds-opt-hint);
  background: var(--ds-list-bg); border-radius: var(--ds-list-radius);
  margin-top: 0;
}

/* ──────────────────────────────────────────────────────────────
 * Variante FLOTANTE — .ds--floating
 * ──────────────────────────────────────────────────────────────
 * Por defecto .ds es INLINE: al abrir, el panel forma parte del flujo
 * y EMPUJA el contenido siguiente. Mejor cuando hay sitio de sobra y
 * quieres que nada quede tapado (formularios largos, pantallas amplias).
 *
 * Con .ds--floating el panel se SUPERPONE (absolute + sombra, fondo
 * opaco) y no mueve el layout. Mejor en contenedores con poco espacio
 * vertical, listas al final de una tarjeta, o filas densas.
 *
 * Elección "en función de la ventana": el consumidor puede medir el
 * espacio disponible y conmutar la clase en runtime —
 *   el.classList.toggle('ds--floating', faltaEspacioAbajo);
 *   el.classList.toggle('ds--up',       faltaEspacioAbajo && hayEspacioArriba);
 * (.ds--up abre hacia arriba para no salirse por el borde inferior.)
 * ────────────────────────────────────────────────────────────── */
/* Dentro de un MODAL (.dialog-body) los desplegables flotan SIEMPRE: el
 * panel se superpone en vez de empujar el layout, así el modal no "salta"
 * al abrir/cerrar. Reusa exactamente la receta de .ds--floating. */
.ds--floating,
.dialog-body .ds { overflow: visible; position: relative; }
.ds--floating .ds-panel,
.dialog-body .ds .ds-panel {
  position: absolute;
  top: calc(100% + 6px); left: 0; right: 0;
  z-index: 50;
  /* Sobre contenido arbitrario el panel debe ser OPACO (no el tinte
   * azul translúcido del modo inline) y con marco + sombra completos. */
  background: var(--ds-menu-bg);
  border: 1px solid var(--ds-border);
  border-radius: var(--ds-radius);
  box-shadow: var(--ds-menu-shadow);
}
/* Apertura hacia arriba (cerca del borde inferior de la ventana). */
.ds--floating.ds--up .ds-panel,
.dialog-body .ds.ds--up .ds-panel { top: auto; bottom: calc(100% + 6px); }


/* source: html_export/_shared/css/_dropdown-v2.css */

/* ──────────────────────────────────────────────────────────────
 * Alarmas · Dropdown V2 — "Floating Select" preset
 * ──────────────────────────────────────────────────────────────
 * Extraído del dropdown real "Red WiFi" del portal de provisión.
 * Es una ALTERNATIVA a .ds (V1, _dropdown-preset.css), no un reemplazo:
 *
 *   V1 (.ds)   → combobox rico: chip de icono + buscador integrado +
 *                panel azulado que se expande EN LÍNEA + opción activa
 *                con píldora y check. Para selección entre muchas
 *                opciones con búsqueda (InlineSelect del app kit).
 *
 *   V2 (.dd)   → select FLOTANTE simple: botón tipo input + menú que
 *                se superpone con sombra. Filas con "meta" a la derecha
 *                (barras de señal, candado, check…). Para selects nativos
 *                enriquecidos donde la fila lleva información extra y no
 *                hace falta buscador. Ocupa menos y no empuja el layout.
 *
 * Self-contained y theme-aware (igual que V1): edita SOLO el bloque
 * de tokens; las reglas del componente referencian variables.
 * ────────────────────────────────────────────────────────────── */

:root {
  --dd-radius:          12px;
  --dd-bg:              #ffffff;
  --dd-border:          #e2e8f0;
  --dd-text:            #1e293b;
  --dd-placeholder:     #94a3b8;
  --dd-caret:           #94a3b8;
  --dd-caret-open:      #3b82f6;
  --dd-focus:           #3b82f6;
  --dd-focus-ring:      rgba(59,130,246,0.15);

  /* Menú flotante */
  --dd-menu-bg:         #ffffff;
  --dd-menu-border:     #e2e8f0;
  --dd-menu-shadow:     0 12px 32px rgba(2,6,23,0.14), 0 2px 6px rgba(2,6,23,0.06);
  --dd-menu-max-h:      208px;

  /* Filas */
  --dd-divider:         #e2e8f0;
  --dd-hover-bg:        #eff6ff;          /* primary-50 */
  --dd-active-bg:       #dbeafe;          /* primary-100 */
  --dd-active-text:     #1d4ed8;          /* primary-700 */
  --dd-meta:            #64748b;

  /* Meta WiFi (barras de señal) */
  --dd-bar-on:          #22c55e;
  --dd-bar-off:         #cbd5e1;
  --dd-lock:            #94a3b8;

  /* Check de seleccionado */
  --dd-check:           #3b82f6;
  --dd-check-fg:        #ffffff;
}

[data-theme="dark"] {
  --dd-bg:              rgba(30,41,59,0.55);
  --dd-border:          #334155;
  --dd-text:            #f1f5f9;
  --dd-placeholder:     #64748b;
  --dd-caret:           #64748b;
  --dd-caret-open:      #60a5fa;
  --dd-focus:           #60a5fa;
  --dd-focus-ring:      rgba(96,165,250,0.20);

  --dd-menu-bg:         #1e293b;
  --dd-menu-border:     #334155;
  --dd-menu-shadow:     0 12px 32px rgba(0,0,0,0.45), 0 2px 6px rgba(0,0,0,0.30);

  --dd-divider:         #334155;
  --dd-hover-bg:        rgba(96,165,250,0.14);
  --dd-active-bg:       rgba(96,165,250,0.20);
  --dd-active-text:     #93c5fd;
  --dd-meta:            #94a3b8;

  --dd-bar-on:          #4ade80;
  --dd-bar-off:         #475569;
  --dd-lock:            #64748b;

  --dd-check:           #60a5fa;
  --dd-check-fg:        #0f172a;
}

/* Scope de tarjeta oscura embebida (previews con cards claras y oscuras) */
.card.dark {
  --dd-bg:              rgba(30,41,59,0.55);
  --dd-border:          #334155;
  --dd-text:            #f1f5f9;
  --dd-placeholder:     #64748b;
  --dd-caret:           #64748b;
  --dd-caret-open:      #60a5fa;
  --dd-focus:           #60a5fa;
  --dd-focus-ring:      rgba(96,165,250,0.20);
  --dd-menu-bg:         #1e293b;
  --dd-menu-border:     #334155;
  --dd-menu-shadow:     0 12px 32px rgba(0,0,0,0.45), 0 2px 6px rgba(0,0,0,0.30);
  --dd-divider:         #334155;
  --dd-hover-bg:        rgba(96,165,250,0.14);
  --dd-active-bg:       rgba(96,165,250,0.20);
  --dd-active-text:     #93c5fd;
  --dd-meta:            #94a3b8;
  --dd-bar-on:          #4ade80;
  --dd-bar-off:         #475569;
  --dd-lock:            #64748b;
  --dd-check:           #60a5fa;
  --dd-check-fg:        #0f172a;
}

/* ───────────────────────── Componente ───────────────────────── */

.dd { position: relative; }

/* Botón / valor */
.dd-toggle {
  width: 100%; box-sizing: border-box;
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  padding: 12px 14px; min-height: 48px;
  border-radius: var(--dd-radius);
  background: var(--dd-bg);
  border: 1px solid var(--dd-border);
  color: var(--dd-text);
  font-family: inherit; font-size: 14px; font-weight: 500;
  text-align: left; cursor: pointer;
  transition: border-color 150ms ease, box-shadow 150ms ease;
}
.dd-toggle:focus-visible,
.dd.is-open .dd-toggle { outline: none; border-color: var(--dd-focus); box-shadow: 0 0 0 3px var(--dd-focus-ring); }

.dd-value { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.dd-value.is-placeholder { color: var(--dd-placeholder); }

.dd-caret { display: flex; flex-shrink: 0; transition: transform .2s ease; }
.dd-caret svg { width: 18px; height: 18px; stroke: var(--dd-caret); }
.dd.is-open .dd-caret { transform: rotate(180deg); }
.dd.is-open .dd-caret svg { stroke: var(--dd-caret-open); }

/* Menú flotante */
.dd-menu {
  position: absolute; z-index: 50; top: calc(100% + 6px); left: 0; right: 0;
  background: var(--dd-menu-bg);
  border: 1px solid var(--dd-menu-border);
  border-radius: var(--dd-radius);
  box-shadow: var(--dd-menu-shadow);
  max-height: var(--dd-menu-max-h); overflow-y: auto;
  overflow-x: hidden;
}
.dd:not(.is-open) .dd-menu { display: none; }

/* Fila */
.dd-item {
  width: 100%; box-sizing: border-box; border: none;
  display: flex; align-items: center; justify-content: space-between; gap: 10px;
  padding: 11px 14px;
  background: transparent;
  color: var(--dd-text);
  font-family: inherit; font-size: 14px; text-align: left; cursor: pointer;
  transition: background .12s ease;
}
.dd-item + .dd-item { border-top: 1px solid var(--dd-divider); }
.dd-item:hover { background: var(--dd-hover-bg); }
.dd-item.is-active { background: var(--dd-active-bg); }
.dd-item.is-active .dd-item-label { color: var(--dd-active-text); font-weight: 600; }

.dd-item-main { display: flex; align-items: center; gap: 8px; min-width: 0; }
.dd-item-label { font-weight: 500; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.dd-item-meta { display: inline-flex; align-items: center; gap: 8px; flex-shrink: 0; color: var(--dd-meta); }

/* Candado (red protegida) */
.dd-lock { width: 13px; height: 13px; stroke: var(--dd-lock); flex-shrink: 0; }

/* Barras de señal */
.dd-bars { display: inline-flex; align-items: flex-end; gap: 2px; height: 14px; }
.dd-bar { width: 3px; border-radius: 1px; background: var(--dd-bar-off); }
.dd-bar.b1 { height: 5px; }
.dd-bar.b2 { height: 8px; }
.dd-bar.b3 { height: 11px; }
.dd-bar.b4 { height: 14px; }
.dd-bar.on { background: var(--dd-bar-on); }

/* Check de seleccionado */
.dd-check {
  width: 20px; height: 20px; border-radius: 50%; flex-shrink: 0;
  background: var(--dd-check);
  display: flex; align-items: center; justify-content: center;
}
.dd-check svg { width: 12px; height: 12px; stroke: var(--dd-check-fg); stroke-width: 3; }
.dd-item:not(.is-active) .dd-check { display: none; }

/* Estado vacío */
.dd-empty { padding: 16px 14px; text-align: center; font-size: 13px; color: var(--dd-meta); }


/* source: html_export/_shared/css/_elevation.css */

/* ──────────────────────────────────────────────────────────────
 * Alarmas · ELEVATION preset — sombra "pop" (corta e intensa)
 * ──────────────────────────────────────────────────────────────
 * Relieve CEÑIDO al elemento: dos capas cortas (1–3px) de alta
 * opacidad + un realce interior superior (inset highlight). Da
 * presencia 3D sin el halo difuso de --shadow-lg / .glass--raised.
 * Pensado para controles pequeños seleccionados (toggles, tiles,
 * chips) donde una sombra larga se vería desproporcionada.
 *
 *   <button class="elev-pop"> … </button>
 *
 * Theme-aware: en oscuro las capas suben de opacidad (sombra negra)
 * y el realce interior baja, para que el relieve se lea igual sobre
 * superficies oscuras (donde una sombra suave desaparecería).
 * ────────────────────────────────────────────────────────────── */
.elev-pop,
.glass.elev-pop { /* gana también combinada con .glass (que declara --shadow-glass más tarde) */
  box-shadow:
    0 1px 1px rgba(15, 23, 42, 0.16),
    0 2px 3px rgba(15, 23, 42, 0.20),
    inset 0 1px 0 rgba(255, 255, 255, 0.65);
}
[data-theme="dark"] .elev-pop,
[data-theme="dark"] .glass.elev-pop {
  box-shadow:
    0 1px 1px rgba(0, 0, 0, 0.50),
    0 2px 3px rgba(0, 0, 0, 0.45),
    inset 0 1px 0 rgba(255, 255, 255, 0.06);
}


/* source: html_export/_shared/css/_field.css */

/* ──────────────────────────────────────────────────────────────
 * Alarmas · FIELD preset — FUENTE ÚNICA (CSS recipe)
 * ──────────────────────────────────────────────────────────────
 * Input de texto canónico. Hoy se repite en: app field()/inputStyle,
 * campos de location-modals y sharing-profile, y .input-themed del
 * portal. Receta compartida app + portal + specimens.
 * Nota Fase 3: la app usa hoy bgAlt (#f1f5f9) como fondo en varios
 * sitios y aquí fijamos --color-input-bg como estándar → reconciliar.
 * ────────────────────────────────────────────────────────────── */
.field {
  display: block; width: 100%; box-sizing: border-box;
  padding: 10px 12px;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);            /* 12px */
  /* Nivel 2 (sunken): el input se hunde respecto al card — slate-50 en
   * claro / slate-900 en oscuro. Distinto del botón secundario (tonal). */
  background: var(--color-surface-sunken);
  font-family: inherit; font-size: 14px; color: var(--color-text);
  outline: none;
  transition: border-color var(--transition-fast), box-shadow var(--transition-fast);
}
.field::placeholder { color: var(--color-text-muted); }
.field:focus { border-color: var(--color-primary); box-shadow: 0 0 0 3px rgba(59,130,246,0.18); }
.field:disabled { opacity: .6; cursor: not-allowed; }

.field--sm { padding: 8px 10px; font-size: 13px; border-radius: var(--radius-md); }
/* Variante TEXTAREA — hereda toda la receta del input; sólo añade el alto
 * por líneas (atributo rows) y permite redimensionar en vertical. */
.field--area { resize: vertical; min-height: 0; line-height: 1.5; }
.field--invalid { border-color: var(--color-error); }
.field--invalid:focus { box-shadow: 0 0 0 3px rgba(239,68,68,0.18); }

/* Variante CODE — entrada de PIN/código de activación: monoespaciado, en
 * mayúsculas, tracking amplio y centrado. El text-indent compensa el espacio
 * de tracking final para que el texto quede ópticamente centrado. */
.field--code {
  text-align: center;
  font-family: var(--font-mono);
  font-size: 28px; font-weight: 600;
  letter-spacing: 0.3em; text-indent: 0.3em;
  text-transform: uppercase;
  padding: 12px;
}

.field-label {
  display: block; font-size: 13px; font-weight: 500;
  color: var(--color-text); margin-bottom: 6px;
}
.field-hint { font-size: 12px; color: var(--color-text-secondary); margin-top: 4px; line-height: 1.4; }


/* source: html_export/_shared/css/_filter-row.css */

/* ──────────────────────────────────────────────────────────────
 * Alarmas · FILTER-ROW preset (CSS recipe) — FUENTE ÚNICA
 * ──────────────────────────────────────────────────────────────
 * Fila de chips de filtro estándar del kit (location-modals.jsx · FilterRow).
 * La usan TODOS los modales/paneles con filtros: historial de automatizaciones,
 * historial de sensores, y cualquier lista acotable. Un solo sitio define su
 * forma y color → cambiar aquí reverbera en todos los consumidores.
 *
 * Estructura:
 *   <div class="filter-row">
 *     <span class="eyebrow eyebrow--sm eyebrow--muted filter-row__label">Resultado</span>
 *     <div class="filter-row__chips">
 *       <button class="filter-chip is-active">Todos</button>
 *       <button class="filter-chip filter-chip--ok"><i data-lucide="check"></i> OK</button>
 *       <button class="filter-chip filter-chip--warn"><i data-lucide="alert-triangle"></i> Avisos</button>
 *       <button class="filter-chip filter-chip--err"><i data-lucide="x"></i> Errores</button>
 *     </div>
 *   </div>
 *
 * Reglas del kit:
 *   · Chip "Todos" siempre primero, exclusivo (1 selección por fila).
 *   · Chips de ancho IGUAL (flex:1 1 0), envolviendo si no caben.
 *   · Sheen + sombra 3D SUAVE en TODOS (activos o no); el activo añade lift.
 *   · Relleno activo saturado = window.chipFill (baked abajo: green/blue/amber/red).
 *   · Tono semántico (ok/warn/err): color de identidad siempre; al activarse
 *     se rellena con la versión saturada. Sin tono = chip neutro azul (primary).
 * ────────────────────────────────────────────────────────────── */

.filter-row { margin-bottom: 8px; min-width: 0; width: 100%; }
.filter-row__label { display: block; margin-bottom: 6px; padding-left: 2px; }

.filter-row__chips {
  display: flex; flex-wrap: wrap; gap: 6px;
  padding: 0 0 4px; max-width: 100%;
}

/* Chip base — neutro (sin tono). Estado inactivo. */
.filter-chip {
  flex: 1 1 0; min-width: 0;
  display: inline-flex; align-items: center; justify-content: center; gap: 5px;
  padding: 6px 8px; border-radius: 9999px;
  font-family: inherit; font-size: 11px; font-weight: 600;
  border: none; cursor: pointer; white-space: nowrap;
  color: var(--color-text-secondary);
  background:
    linear-gradient(180deg, rgba(255,255,255,0.30) 0, rgba(255,255,255,0) 50%),
    #ffffff;
  box-shadow: 0 1px 2px rgba(15,23,42,0.14), 0 2px 5px rgba(15,23,42,0.10);
  transition: background .15s ease, color .15s ease, box-shadow .15s ease, transform .15s ease;
}
.filter-chip > i[data-lucide],
.filter-chip > svg { width: 14px; height: 14px; flex-shrink: 0; }

/* Activo neutro → relleno primary (chipFill 'blue'). */
.filter-chip.is-active {
  color: #fff;
  background:
    linear-gradient(180deg, rgba(255,255,255,0.30) 0, rgba(255,255,255,0) 50%),
    var(--color-primary);
  transform: translateY(-0.5px);
}

/* ── Tono OK (verde) ── */
.filter-chip--ok { color: var(--color-success-700); }
.filter-chip--ok:not(.is-active) {
  background:
    linear-gradient(180deg, rgba(255,255,255,0.30) 0, rgba(255,255,255,0) 50%),
    var(--color-success-light);
}
.filter-chip--ok.is-active {
  color: #fff;
  background:
    linear-gradient(180deg, rgba(255,255,255,0.30) 0, rgba(255,255,255,0) 50%),
    color-mix(in srgb, var(--color-success) 88%, #0f172a);
}
/* ── Tono AVISO (ámbar) ── */
.filter-chip--warn { color: var(--color-warning-700); }
.filter-chip--warn:not(.is-active) {
  background:
    linear-gradient(180deg, rgba(255,255,255,0.30) 0, rgba(255,255,255,0) 50%),
    var(--color-warning-light);
}
.filter-chip--warn.is-active {
  color: #fff;
  background:
    linear-gradient(180deg, rgba(255,255,255,0.30) 0, rgba(255,255,255,0) 50%),
    var(--color-warning);
}
/* ── Tono ERROR (rojo) ── */
.filter-chip--err { color: var(--color-error-700); }
.filter-chip--err:not(.is-active) {
  background:
    linear-gradient(180deg, rgba(255,255,255,0.30) 0, rgba(255,255,255,0) 50%),
    var(--color-error-light);
}
.filter-chip--err.is-active {
  color: #fff;
  background:
    linear-gradient(180deg, rgba(255,255,255,0.30) 0, rgba(255,255,255,0) 50%),
    var(--color-error);
}

/* ── Tono INFO (azul) ── identidad primary; para chips de modo "En casa" en el
 * historial de alarma (el kit los colorea con armModeTones home = azul). */
.filter-chip--info { color: var(--color-primary-700); }
.filter-chip--info:not(.is-active) {
  background:
    linear-gradient(180deg, rgba(255,255,255,0.30) 0, rgba(255,255,255,0) 50%),
    var(--color-info-light);
}
.filter-chip--info.is-active {
  color: #fff;
  background:
    linear-gradient(180deg, rgba(255,255,255,0.30) 0, rgba(255,255,255,0) 50%),
    var(--color-primary);
}

/* ── Tema OSCURO ── el relleno saturado se profundiza hacia el color (no hacia
 * el slate, que lo lavaría); el sheen baja a 0.10 y la sombra sube en negro. */
[data-theme="dark"] .filter-chip {
  background:
    linear-gradient(180deg, rgba(255,255,255,0.10) 0, rgba(255,255,255,0) 50%),
    #1e293b;
  box-shadow: 0 1px 2px rgba(0,0,0,0.35), 0 2px 5px rgba(0,0,0,0.25);
}
[data-theme="dark"] .filter-chip.is-active {
  background:
    linear-gradient(180deg, rgba(255,255,255,0.10) 0, rgba(255,255,255,0) 50%),
    color-mix(in srgb, #2563eb 88%, #0b1220);
}
[data-theme="dark"] .filter-chip--ok:not(.is-active),
[data-theme="dark"] .filter-chip--warn:not(.is-active),
[data-theme="dark"] .filter-chip--info:not(.is-active),
[data-theme="dark"] .filter-chip--err:not(.is-active) {
  background-image: linear-gradient(180deg, rgba(255,255,255,0.10) 0, rgba(255,255,255,0) 50%);
}
[data-theme="dark"] .filter-chip--ok.is-active {
  background:
    linear-gradient(180deg, rgba(255,255,255,0.10) 0, rgba(255,255,255,0) 50%),
    color-mix(in srgb, #16a34a 88%, #0b1220);
}
[data-theme="dark"] .filter-chip--warn.is-active {
  background:
    linear-gradient(180deg, rgba(255,255,255,0.10) 0, rgba(255,255,255,0) 50%),
    color-mix(in srgb, #d97706 88%, #0b1220);
}
[data-theme="dark"] .filter-chip--info.is-active {
  background:
    linear-gradient(180deg, rgba(255,255,255,0.10) 0, rgba(255,255,255,0) 50%),
    color-mix(in srgb, #2563eb 88%, #0b1220);
}
[data-theme="dark"] .filter-chip--err.is-active {
  background:
    linear-gradient(180deg, rgba(255,255,255,0.10) 0, rgba(255,255,255,0) 50%),
    color-mix(in srgb, #dc2626 88%, #0b1220);
}


/* source: html_export/_shared/css/_glass.css */

/* ──────────────────────────────────────────────────────────────
 * Alarmas · GLASS preset — FUENTE ÚNICA DE LA VERDAD (CSS recipe)
 * ──────────────────────────────────────────────────────────────
 * La metáfora central de tarjeta. Hoy se re-inline ~15 veces en el
 * kit de la app (con `blur(10px)` hardcodeado) y el portal tiene su
 * propio `.glass-card` por separado. Esta receta única la consumen
 * ambos (y los specimens del DS) — como `_dropdown-preset.css`.
 *
 * Construida sobre los tokens existentes de colors_and_type.css
 * (--glass-bg / --glass-border / --shadow-glass); solo añade el
 * radio y el blur como tokens editables + la clase y sus variantes.
 * ────────────────────────────────────────────────────────────── */
:root {
  /* sutil, no escarchado */
  --glass-blur:   blur(10px); /* @kind other */
  --glass-radius: 16px;         /* --radius-xl */
  /* superficies flotantes */
  --glass-blur-strong: blur(18px); /* @kind other */
  --glass-bg-strong:   rgba(255, 255, 255, 0.97);  /* casi opaco */
}
[data-theme="dark"] {
  --glass-bg-strong: rgba(30, 41, 59, 0.97);
}

.glass {
  /* OPACA (sin translucidez/blur): bajo el `transform: scale()` del marco del
   * device, `backdrop-filter` muestrea mal y teñía las cards de claro→oscuro
   * de izquierda a derecha. Una superficie sólida elimina el artefacto y es
   * lo correcto para una app táctil. Backup translúcido en
   * preview/_glass-translucent-backup.css. */
  background: var(--color-surface);
  border: 1px solid var(--glass-border);
  border-radius: var(--glass-radius);
  box-shadow: var(--shadow-glass);
}

/* Variante INNER — tarjeta anidada dentro de otro glass (patrón A:
 * blanco puro en claro / hueco slate-900 en oscuro). */
.glass--inner {
  background: var(--color-card-nested-bg);
  border-color: var(--color-card-nested-border);
  -webkit-backdrop-filter: none;
  backdrop-filter: none;
}

/* Variante HERO — tiles de bienvenida, radio mayor (--radius-2xl). */
.glass--hero { border-radius: var(--radius-2xl); }

/* Variante FLAT — sin sombra (listas densas, paneles internos). */
.glass--flat { box-shadow: none; }

/* Hover canónico de tarjeta (solo donde sea interactiva). */
.glass--hoverable { transition: transform var(--transition-base), box-shadow var(--transition-base); }
.glass--hoverable:hover { transform: translateY(-2px); box-shadow: var(--shadow-lg); }

/* Variante RAISED — más elevación en REPOSO (la tarjeta "flota" un poco sobre
 * el fondo). Para tarjetas de nivel superior que deben destacar como objetos
 * independientes, p.ej. cada ubicación del dashboard. Sin lift al hover: es
 * una app móvil, el hover no existe en táctil y confundiría en navegador.
 * Sombra theme-aware: más profunda y opaca en oscuro para que se perciba. */
.glass--raised {
  box-shadow: 0 6px 18px rgba(2,6,23,0.12), 0 2px 6px rgba(2,6,23,0.07);
}
[data-theme="dark"] .glass--raised {
  box-shadow: 0 10px 26px rgba(0,0,0,0.5), 0 3px 8px rgba(0,0,0,0.38);
}

/* Variante RAISED-SM — elevación TENUE (un escalón por debajo de --raised).
 * Para despegar ligeramente del fondo elementos anidados (p.ej. sensores
 * dentro de una ubicación) SIN llegar a "flotar" como la tarjeta contenedora,
 * preservando la jerarquía. */
.glass--raised-sm {
  box-shadow: 0 2px 6px rgba(2,6,23,0.08), 0 1px 2px rgba(2,6,23,0.05);
}
[data-theme="dark"] .glass--raised-sm {
  box-shadow: 0 3px 10px rgba(0,0,0,0.4), 0 1px 3px rgba(0,0,0,0.3);
}

/* Variante SOLID — superficie blanca sólida (NO translúcida). Equivale a la
 * apariencia histórica del `<GlassCard>` del App Kit (tk.surface). Úsala donde
 * NO quieras que se vea contenido detrás (listas densas, dashboards, modales
 * de fondo). El blur se mantiene por si hay child con transparencia. */
.glass--solid { background: var(--color-surface); }

/* Variante STRONG — tarjeta flotante sobre fondo cargado (login, bottom-nav):
 * blur mayor (18px) y fondo casi opaco (.97) para legibilidad. Reconcilia el
 * login (blur 18 / .97) y la bottom-nav (blur 16 / .95) bajo una sola receta. */
.glass--strong {
  /* Antes: fondo casi opaco (.97) + blur 18. Ahora sólido pleno por el mismo
   * artefacto de backdrop-filter bajo escalado. */
  background: var(--color-surface);
}


/* source: html_export/_shared/css/_icon-tile.css */

/* ──────────────────────────────────────────────────────────────
 * Alarmas · ICON-TILE preset — FUENTE ÚNICA (CSS recipe)
 * ──────────────────────────────────────────────────────────────
 * Placa redondeada con icono Lucide centrado. Aparece en login,
 * empty states, filas de sensor/cámara, asistente HomeHub y cabecera
 * del portal — siempre con tamaños/tono ad-hoc. Estándar: 3 tamaños y
 * tonos sobre los tokens del DS. El icono va dentro (svg/img) al 55%.
 * ────────────────────────────────────────────────────────────── */
.icon-tile {
  display: inline-flex; align-items: center; justify-content: center; flex-shrink: 0;
  width: 40px; height: 40px;
  border-radius: var(--radius-lg);            /* 12px (md) */
  /* Claro: bg -400 (saturado, menos brillante que -300) + icon -950 (contraste máximo). */
  background: #60a5fa;
  color: #172554;
}
[data-theme="dark"] .icon-tile {
  background: #1d4ed8;
  color: #dbeafe;
}
.icon-tile > svg, .icon-tile > img { width: 55%; height: 55%; display: block; }

/* Tamaños reales del kit */
.icon-tile--sm { width: 32px; height: 32px; border-radius: var(--radius-md); }   /* 8px  */
/* row — filas de sensor/cámara: el tamaño MÁS usado del producto (52, r14). */
.icon-tile--row { width: 52px; height: 52px; border-radius: 14px; }
.icon-tile--lg { width: 56px; height: 56px; border-radius: var(--radius-xl); }   /* 16px */
.icon-tile--xl { width: 64px; height: 64px; border-radius: var(--radius-xl); }

/* Tonos — siempre TINTADOS (la placa sólida primary es el app-icon
 * del login y vive en BRAND, no es un tono de icon-tile). */
/* Tonos — CLARO: bg -400 + icon -950 (máximo contraste, saturado pero no brillante).
 * OSCURO: bg -700 + icon -100 (saturado y luminoso, look "encendido"). */
.icon-tile--success { background: #4ade80; color: #052e16; }
[data-theme="dark"] .icon-tile--success { background: #15803d; color: #dcfce7; }
.icon-tile--warning { background: #fbbf24; color: #451a03; }
[data-theme="dark"] .icon-tile--warning { background: #b45309; color: #fef3c7; }
.icon-tile--error   { background: #f87171; color: #450a0a; }
[data-theme="dark"] .icon-tile--error   { background: #b91c1c; color: #fee2e2; }
.icon-tile--neutral { background: #94a3b8; color: #0f172a; }
[data-theme="dark"] .icon-tile--neutral { background: #475569; color: #f1f5f9; }

/* ──────────────────────────────────────────────────────────────
 * Variante SOFT (.icon-tile.is-soft) — tinte claro
 * ──────────────────────────────────────────────────────────────
 * Placa "suave": fondo *-light + icono saturado + borde sutil.
 * Es el look de las placas de cabecera del portal de provisión
 * (head/rebooting/manual/success). Usa tokens --color-* (válidos en
 * app y portal). Combínala con un .tone-* y, si quieres, un tamaño.
 *   <div class="icon-tile icon-tile--lg is-soft tone-primary">…</div>
 * ────────────────────────────────────────────────────────────── */
.icon-tile.is-soft { border: 1px solid transparent; }
.icon-tile.is-soft.tone-primary {
  background: var(--color-primary-light); color: var(--color-primary);
  border-color: color-mix(in srgb, var(--color-primary) 20%, transparent);
}
.icon-tile.is-soft.tone-success {
  background: var(--color-success-light); color: var(--color-success);
  border-color: color-mix(in srgb, var(--color-success) 20%, transparent);
}
.icon-tile.is-soft.tone-warning {
  background: var(--color-warning-light); color: var(--color-warning);
  border-color: color-mix(in srgb, var(--color-warning) 20%, transparent);
}
.icon-tile.is-soft.tone-error {
  background: var(--color-error-light); color: var(--color-error);
  border-color: color-mix(in srgb, var(--color-error) 20%, transparent);
}


/* source: html_export/_shared/css/_modal.css */

/* ──────────────────────────────────────────────────────────────
 * Alarmas · MODAL preset — FUENTE ÚNICA (CSS recipe)
 * ──────────────────────────────────────────────────────────────
 * Shell de diálogo: scrim + caja + cabecera con título centrado y ×
 * absoluto. Hoy CenterDialog repite el scrim (rgba(2,6,23,.55)+blur 2)
 * y la cabecera 2 veces inline en location-modals. Receta única.
 * ────────────────────────────────────────────────────────────── */
.scrim {
  position: absolute; inset: 0; z-index: var(--z-modal, 300);
  background: rgba(2,6,23,0.55);
  -webkit-backdrop-filter: blur(2px); backdrop-filter: blur(2px);
  display: flex; align-items: center; justify-content: center;
  padding: 16px;
  animation: scrim-in var(--motion-fade-duration) ease; /* kit: dialog-fade-in */
}
@keyframes scrim-in { from { opacity: 0; } to { opacity: 1; } }
/* Entrada del panel — kit location-modals.jsx: dialog-pop 240ms cubic-bezier(.16,1,.3,1) */
@keyframes dialog-pop { from { transform: translateY(8px) scale(0.97); opacity: 0; } to { transform: translateY(0) scale(1); opacity: 1; } }
.scrim .dialog, .profile-modal .dialog, .presentation-modal .dialog, .homehub-modal .dialog, .automation-modal .dialog { animation: dialog-pop var(--motion-pop-duration) var(--motion-ease-out); }
.presentation-modal, .homehub-modal, .automation-modal { animation: scrim-in var(--motion-fade-duration) ease; }
/* NORMA: todo diálogo directo de un overlay a pantalla completa respeta --modal-max-h
 * (con scroll interno); :where() deja que cada preset refine cabecera/pie fijos. */
:where(.profile-modal, .presentation-modal, .homehub-modal, .automation-modal, .scrim) > .dialog { max-height: var(--modal-max-h); overflow: auto; }
/* ESTÁNDAR de modal LARGO: cabecera y pie fijos, cuerpo con scroll. La NORMA
 * de arriba usa :where() (especificidad 0), así que .dialog{overflow:hidden}
 * la gana y un diálogo sin preset propio NO scrollea: este preset lo resuelve
 * de forma reutilizable (sirve con el form envolviendo cuerpo+pie).
 * Los presets equivalentes por pantalla (permissions-dialog, security-dialog,
 * automation-logs, camera-wizard…) deberían migrar aquí. */
/* Variante ANCHA (paletas, editores con rejilla): 430px como el resto de
 * modales de perfil/ubicación. La definición de .dialog vive MÁS ABAJO en esta
 * hoja, así que hace falta doble clase para ganar la cascada. */
.dialog.dialog--wide { max-width: 430px; }
.dialog--scroll { display: flex; flex-direction: column; overflow: hidden; max-height: var(--modal-max-h); }
.dialog--scroll > form { display: flex; flex-direction: column; flex: 1 1 auto; min-height: 0; }
.dialog--scroll > .dialog-body, .dialog--scroll > form > .dialog-body { flex: 1 1 auto; min-height: 0; overflow-y: auto; }
/* Variante para modales PEQUEÑOS (información, confirmaciones cortas): centrados en pantalla. */
.presentation-modal.presentation-modal--center { align-items: center; }
/* NORMA: los modales de ELIMINACIÓN (.dialog--danger) se centran SIEMPRE en pantalla,
 * en cualquier overlay. :has() da especificidad suficiente para ganar a las bases. */
:is(.presentation-modal, .profile-modal, .homehub-modal, .automation-modal, .scrim):has(> .dialog--danger) { align-items: center; }
/* Los overlays declaran display:grid/flex, que PISA la regla UA de [hidden]:
 * un diálogo estático cerrado (hidden) seguía pintado en pantalla. */
.presentation-modal[hidden], .profile-modal[hidden], .homehub-modal[hidden], .automation-modal[hidden], .scrim[hidden] { display: none; }
@media (prefers-reduced-motion: reduce) { .scrim, .profile-modal, .presentation-modal, .homehub-modal, .automation-modal, .scrim .dialog, .profile-modal .dialog, .presentation-modal .dialog, .homehub-modal .dialog, .automation-modal .dialog { animation: none; } }

.dialog {
  width: 100%; max-width: 380px;
  /* Panel OPACO — literal del kit (CenterDialog: isDark ? '#0f172a' : '#f8f8f8').
   * NO --color-surface: ese token es translúcido (rgba(255,255,255,0.9)) y, sobre
   * el .scrim oscuro, deja pasar el velo y ensucia el panel a gris. El kit usa un
   * fondo opaco justo para que el modal se vea idéntico con o sin scrim detrás. */
  background: #f8f8f8;
  border: 1px solid var(--glass-border);
  border-radius: var(--radius-xl);            /* 16px */
  box-shadow: var(--shadow-xl);
  overflow: hidden;
}
[data-theme="dark"] .dialog { background: #0f172a; }   /* kit: slate-900 opaco */
.dialog--sheet { max-width: 100%; align-self: flex-end; border-radius: var(--radius-2xl) var(--radius-2xl) 0 0; }

.dialog-head {
  /* Compacto: 12px vertical (antes 18) — pedido de producto para todos los modales. */
  position: relative; padding: 12px 44px;
  /* Divisor estructural: --color-border (NO --color-border-light, que en
   * oscuro = slate-800 = la superficie del modal y queda invisible). */
  text-align: center; border-bottom: 1px solid var(--color-border);
}
.dialog-title { margin: 0; font-size: 17px; font-weight: 700; letter-spacing: -0.01em; color: var(--color-text); }
.dialog-title--danger { color: var(--color-error); }
.dialog-sub { margin: 3px 0 0; font-size: 12.5px; color: var(--color-text-secondary); }
/* Botón de cerrar — superficie blanca con el bevel 3D del sistema (misma
 * receta que .btn--surface): bisel lineal-gradient + sombra compuesta +
 * contorno. Tono blanco que se adapta al tema (claro = #fff/surface,
 * oscuro = slate-800). El icono × hereda el color del botón. */
.dialog-close {
  /* Centrado vertical real en la cabecera (top/bottom 0 + margin auto — sin
   * transform, que se reserva para el lift del hover). */
  position: absolute; right: 12px; top: 0; bottom: 0; margin: auto 0;
  width: 32px; height: 32px; border-radius: 50%;
  border: 1px solid color-mix(in srgb, var(--color-text) 18%, transparent);
  background:
    linear-gradient(180deg, rgba(255,255,255,0.50) 0, rgba(255,255,255,0) 45%),
    var(--color-surface);
  color: var(--color-text-secondary);
  cursor: pointer; display: inline-flex; align-items: center; justify-content: center;
  box-shadow:
    0 1px 1px rgba(15,23,42,0.22),
    0 2px 3px rgba(15,23,42,0.28);
  transition: background var(--transition-fast), box-shadow var(--transition-fast), transform var(--transition-fast), border-color var(--transition-fast), color var(--transition-fast);
}
.dialog-close:hover {
  background:
    linear-gradient(180deg, rgba(255,255,255,0.50) 0, rgba(255,255,255,0) 45%),
    var(--color-bg-alt);
  border-color: color-mix(in srgb, var(--color-text) 28%, transparent);
  color: var(--color-text);
  box-shadow:
    0 1px 1px rgba(15,23,42,0.24),
    0 3px 5px rgba(15,23,42,0.32);
  transform: translateY(-1px);
}
.dialog-close:active { transform: translateY(0); }
/* En oscuro el bevel blanco al 50% se ve fantasmal sobre slate-800 — se baja
 * (mismo patrón que .btn--surface), y las sombras se hacen neutras profundas. */
/* En oscuro: el botón sube al nivel TONAL (slate-700) — un escalón más claro
 * que el slate-800/900 del modal — con borde slate-600 visible y el × en color
 * pleno, para que el círculo contraste y se vea sin esfuerzo sobre el fondo. */
[data-theme="dark"] .dialog-close {
  background:
    linear-gradient(180deg, rgba(255,255,255,0.10) 0, rgba(255,255,255,0) 45%),
    var(--color-surface-tonal);
  border-color: var(--color-surface-tonal-border);
  color: var(--color-text);
  box-shadow:
    0 1px 1px rgba(0,0,0,0.50),
    0 2px 3px rgba(0,0,0,0.45);
}
[data-theme="dark"] .dialog-close:hover {
  background:
    linear-gradient(180deg, rgba(255,255,255,0.10) 0, rgba(255,255,255,0) 45%),
    var(--color-surface-tonal-hover);
  box-shadow:
    0 1px 1px rgba(0,0,0,0.52),
    0 3px 5px rgba(0,0,0,0.48);
}
.dialog-body { padding: 18px 20px; }
/* Inputs DENTRO de un modal usan el blanco canónico (--color-surface) en vez
 * del sunken por defecto: sobre el panel del diálogo (#f8f8f8 claro / slate-900
 * oscuro) el campo queda limpio y ligeramente elevado, y en oscuro se distingue
 * del panel (slate-800 sobre slate-900) en vez de fundirse. Solo afecta a los
 * .field de modales; el resto del sistema mantiene el input hundido. */
.dialog-body .field {
  background: var(--color-surface);
}
.dialog-foot { padding: 14px 20px; border-top: 1px solid var(--color-border); display: flex; gap: 10px; }
/* El pie reparte el ancho a partes iguales entre sus botones — layout
 * propio del preset, así ningún consumidor lo repite. */
.dialog-foot > .btn { flex: 1; }

/* ── INTENTS (un esqueleto, 4 niveles de fricción creciente) ───────
 * · create   → cabecera neutra + formulario + CTA primary
 * · confirm  → .dialog-title--danger + 1 frase + Eliminar(danger).
 *              Versión COMPACTA (.dialog--compact) para acciones leves
 *              (revocar acceso, eliminar contacto): MISMA cabecera estándar
 *              (título danger + ×) — sólo que el body se ajusta y no scrollea.
 * · cascade  → confirm + lista "Se eliminará" (.dialog-cascade) con
 *              conteos + tecleo del nombre exacto (.dialog-confirm-name).
 *              Para elementos con subelementos: ubicación / sensor / cámara.
 * · critical → cascade llevado al extremo (borrar CUENTA): banner de
 *              alerta + checklist de ack + tecleo de frase + countdown.
 *              El botón queda disabled hasta cumplir las 3 condiciones.  */

/* COMPACT — el modal se ajusta a su contenido y el body NO scrollea (kit:
 * CenterDialog `compact` → body { overflowY:visible; flex:none }). MANTIENE la
 * cabecera estándar (.dialog-head: título + ×) y el borde del pie: es un modal
 * normal, sólo más corto — NO un diálogo sin cabecera. El centrado del texto de
 * apoyo, cuando lo hay, se decide en cada modal (inline), no aquí. */
.dialog--compact .dialog-body { overflow: visible; }

/* Banner de alerta — encabeza los borrados graves (cascade/critical). */
.dialog-alert {
  display: flex; gap: 10px; align-items: flex-start;
  padding: 11px 13px; border-radius: var(--radius-md);
  background: var(--color-error-light);
  border: 1px solid color-mix(in srgb, var(--color-error) 30%, transparent);
  color: var(--color-error-700, var(--color-error));
  font-size: 12.5px; line-height: 1.5; margin-bottom: 14px;
}
.dialog-alert svg { flex-shrink: 0; margin-top: 1px; }

/* Lista de cascada — qué se eliminará en bloque, con conteos reales. */
.dialog-cascade { display: grid; gap: 8px; }
.dialog-cascade-item {
  display: flex; align-items: center; gap: 10px;
  padding: 9px 11px; border-radius: var(--radius-md);
  background: var(--color-error-light); color: var(--color-error-700, var(--color-error));
  font-size: 13px; font-weight: 600;
}
.dialog-cascade-item .n { margin-left: auto; font-variant-numeric: tabular-nums; }

/* Confirmación por tecleo: el nombre/frase exacta en rojo dentro de la etiqueta. */
.dialog-confirm-name { color: var(--color-error); font-weight: 700; }

/* ── CRITICAL: checklist de fricción (las 3 condiciones juntas) ──────
 * Se leen como un bloque "check-list", no como 3 campos sueltos. */
.dialog-checklist {
  display: grid; gap: 10px;
  padding: 12px; border-radius: var(--radius-md);
  /* Superficie de card anidada (preset Neutrales): blanco sobre el glass
   * en claro, "well" slate-900 con borde slate-700 en oscuro. Garantiza
   * contraste en ambos temas — NO usar --color-bg-alt aquí (coincide con
   * la superficie del diálogo en oscuro y el panel se pierde). */
  background: var(--color-card-nested-bg);
  border: 1px solid var(--color-card-nested-border);
}
/* 1) Ack — casilla de "entiendo las consecuencias". */
.dialog-ack { display: flex; gap: 10px; align-items: flex-start; cursor: pointer; font-size: 12.5px; line-height: 1.45; color: var(--color-text); }
.dialog-ack-box {
  width: 20px; height: 20px; border-radius: 6px; flex-shrink: 0;
  border: 2px solid var(--color-border); background: var(--color-surface);
  display: inline-flex; align-items: center; justify-content: center; color: #fff;
}
.dialog-ack[data-checked="true"] .dialog-ack-box { background: var(--color-error); border-color: var(--color-error); }
.dialog-ack[data-checked="false"] .dialog-ack-box svg { display: none; }

/* 3) Countdown — el botón muestra los segundos restantes y está disabled. */
.dialog-countdown { font-variant-numeric: tabular-nums; }

/* ── DANGER HERO — cabecera de aviso de los borrados reales (círculo rojo
 * SÓLIDO con × blanco + glow + texto). Réplica de la cabecera de
 * DeleteLocation/Sensor/Camera del kit. Más fuerte que .dialog-alert:
 * el círculo sólido gana separación del panel en ambos temas. */
.dialog-danger-hero {
  display: flex; align-items: center; gap: 14px; padding: 14px; border-radius: var(--radius-lg);
  background: var(--color-error-light);
  border: 1px solid color-mix(in srgb, var(--color-error) 26%, transparent);
  margin-bottom: 14px;
}
.dialog-danger-hero__icon {
  width: 40px; height: 40px; border-radius: 50%; flex-shrink: 0; color: #fff;
  background: var(--color-error-700);
  display: flex; align-items: center; justify-content: center;
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--color-error) 12%, transparent);
}
.dialog-danger-hero__text { font-size: 13px; line-height: 1.5; color: var(--color-error-700); }
.dialog-danger-hero__text strong { font-weight: 700; }
[data-theme="dark"] .dialog-danger-hero {
  /* Un escalón más profundo que error-light: maroon sobre slate-900, para que
   * el círculo rojo sólido destaque contra el propio panel del diálogo. */
  background: color-mix(in srgb, var(--color-error) 32%, #0b1220);
  border-color: color-mix(in srgb, var(--color-error) 30%, transparent);
}
[data-theme="dark"] .dialog-danger-hero__icon {
  background: var(--color-error);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--color-error) 18%, transparent);
}
[data-theme="dark"] .dialog-danger-hero__text { color: color-mix(in srgb, var(--color-error) 45%, #ffffff); }

/* ── IMPACT LIST — "Se eliminará": lista NEUTRA (superficie hundida) de
 * icono·etiqueta·valor. Distinta de .dialog-cascade (items rojos): aquí el
 * énfasis rojo ya lo lleva el danger-hero; la lista sólo enumera con calma. */
.dialog-impact {
  padding: 14px; border-radius: var(--radius-lg); margin-bottom: 14px;
  background: var(--color-surface-sunken);
  border: 1px solid var(--color-border);
}
.dialog-impact__list { display: grid; gap: 8px; }
.dialog-impact__row { display: flex; align-items: center; justify-content: space-between; gap: 8px; font-size: 13px; }
.dialog-impact__label { display: inline-flex; align-items: center; gap: 8px; color: var(--color-text); }
.dialog-impact__label svg { color: var(--color-text-secondary); }
.dialog-impact__val { color: var(--color-text-secondary); font-weight: 600; font-variant-numeric: tabular-nums; }


/* source: html_export/_shared/css/_pairing.css */

/* ──────────────────────────────────────────────────────────────
 * Alarmas · PAIRING preset — FUENTE ÚNICA del chrome de emparejamiento
 * ──────────────────────────────────────────────────────────────
 * Extraído 1:1 del kit (location-modals.jsx · CreateSensorModal ·
 * <style> del descubrimiento Zigbee «permit-join»). Consumidor:
 *   · partials/sensor_pairing.html
 *
 * Piezas:
 *   .pair-badge (+ --active/--searching)  → pastilla de estado con punto
 *   .pair-pulse                            → punto pulsante (blink de opacidad)
 *   .pair-search (+ --searching)           → botón circular de búsqueda 128px
 *   .pair-radar (+ --delayed)              → anillos de radar (solo al buscar)
 *   .sensor-in                             → entrada de un sensor detectado
 *
 * Nota de excepciones (idénticas a las del kit y a `_button.css`/`_elevation.css`,
 * que son las ÚNICAS fuentes de sombras/sheen crudos del DS):
 *   · base saturada fija #primary-500/#success en AMBOS temas (evita el pastel
 *     de tk.primary en oscuro) — igual que `.btn--primary`.
 *   · sheen rgba(255,255,255,…) y bevel rgba(0,0,0,…) — mismas capas que `.btn`.
 *   · blanco-sobre-marca en icono/label del botón. */

/* ── Pastilla de estado ── */
.pair-badge {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 5px 14px;
  border-radius: 9999px;
  font-size: 12px;
  font-weight: 600;
  letter-spacing: .01em;
  background: var(--color-surface-tonal);   /* inactivo — tonal (slate-100/700), contrasta en ambos temas */
  color: var(--color-text-secondary);
}
.pair-badge__dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--color-text-muted);
  flex-shrink: 0;
}
.pair-badge--active {                        /* «Activando red…» */
  background: var(--color-primary-50);
  color: var(--color-primary-700);
}
.pair-badge--active .pair-badge__dot { background: var(--color-primary); }
.pair-badge--searching {                     /* «Buscando sensores» */
  background: var(--color-success-light);
  color: var(--color-success-700);
}
.pair-badge--searching .pair-badge__dot { background: var(--color-success); }

/* ── Punto pulsante (Emparejado / Actividad detectada) ── */
@keyframes pairPulse { 0%, 100% { opacity: 1; } 50% { opacity: 0.3; } }
.pair-pulse { animation: pairPulse 1.3s ease-in-out infinite; }

/* ── Botón circular de búsqueda ── */
.pair-search {
  position: relative;
  margin: 20px 0 6px;
  width: 148px;
  height: 148px;
  display: flex;
  align-items: center;
  justify-content: center;
}
.pair-search__btn {
  position: relative;
  width: 128px;
  height: 128px;
  border-radius: 50%;
  border: none;
  cursor: pointer;
  color: #fff;                               /* blanco-sobre-marca */
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 6px;
  /* base saturada fija (excepción documentada, = .btn--primary) + sheen */
  background: linear-gradient(180deg, rgba(255,255,255,0.22) 0, rgba(255,255,255,0) 45%), var(--color-primary-500);
  box-shadow:
    inset 0 0 0 1px rgba(255,255,255,0.15),
    0 2px 4px rgba(15,23,42,0.10),
    0 8px 20px rgba(15,23,42,0.15);
  transition: background 240ms ease, transform 160ms ease, box-shadow 160ms ease;
}
[data-theme="dark"] .pair-search__btn {
  box-shadow:
    inset 0 0 0 1px rgba(255,255,255,0.10),
    0 2px 4px rgba(0,0,0,0.30),
    0 8px 20px rgba(0,0,0,0.25);
}
.pair-search__btn:active { transform: translateY(1px) scale(0.98); }
.pair-search__btn svg { width: 34px; height: 34px; color: #fff; }
.pair-search__label {
  font-size: 14px;
  font-weight: 700;
  line-height: 1.1;
  max-width: 110px;
}
/* Buscando: verde + label = cuenta atrás mono grande, icono más pequeño. */
.pair-search--searching .pair-search__btn {
  background: linear-gradient(180deg, rgba(255,255,255,0.22) 0, rgba(255,255,255,0) 45%), var(--color-success);
  cursor: default;
}
.pair-search--searching .pair-search__btn svg { width: 30px; height: 30px; }
.pair-search--searching .pair-search__label {
  font-size: 14px;
  font-family: inherit;
  font-variant-numeric: tabular-nums;
  letter-spacing: .02em;
}

/* ── Anillos de radar (solo al buscar) ── */
@keyframes pairRadar {
  0%   { transform: scale(0.75); opacity: 0.55; }
  80%  { opacity: 0; }
  100% { transform: scale(1.35); opacity: 0; }
}
.pair-radar {
  position: absolute;
  inset: 4px;
  border-radius: 50%;
  border: 2px solid var(--color-success);
  pointer-events: none;
  animation: pairRadar 1.8s ease-out infinite;
}
.pair-radar--delayed { animation-delay: 0.9s; }

/* ── Entrada de un sensor detectado ── */
@keyframes sensorIn {
  from { opacity: 0; transform: translateY(8px); }
  to   { opacity: 1; transform: translateY(0); }
}
.sensor-in { animation: sensorIn 280ms cubic-bezier(.16,1,.3,1); }

@media (prefers-reduced-motion: reduce) {
  .pair-pulse, .sensor-in { animation: none; }
  .pair-radar { display: none; }
}


/* source: html_export/_shared/css/_panel.css */

/* ──────────────────────────────────────────────────────────────
 * Alarmas · PANEL preset — superficie de información embebida
 * ──────────────────────────────────────────────────────────────
 * Caja rectangular sutil para agrupar datos dentro de una tarjeta
 * (resumen de configuración, instrucciones, bloques de detalle).
 * Borde tenue (border ×70% mezclado con text-muted) sobre una
 * superficie tonal. Padding/margen los pone el consumidor (utilidades
 * p-3/p-4 o inline) — el preset solo fija superficie, borde y radio.
 *   .panel        superficie input-bg (resumen)
 *   .panel--alt   superficie bg-alt   (instrucciones / secundaria)
 * ────────────────────────────────────────────────────────────── */
.panel {
  border-radius: var(--radius-lg);            /* 12px */
  background: var(--color-input-bg);
  border: 1px solid color-mix(in srgb, var(--color-border) 70%, var(--color-text-muted));
  text-align: left;
}
.panel--alt { background: var(--color-bg-alt); }


/* source: html_export/_shared/css/_password-strength.css */

/* ──────────────────────────────────────────────────────────────
 * Alarmas · PASSWORD-STRENGTH preset — FUENTE ÚNICA (CSS recipe)
 * Extraído 1:1 del kit (sharing-profile.jsx · PasswordStrength).
 * Medidor de fortaleza: 5 barras + etiqueta. La puntuación (0–5) va
 * en data-score en el contenedor .pwd-meter; las barras se rellenan
 * hasta la puntuación con el color de la escala:
 *   1 muy débil=error · 2 débil=naranja · 3 moderada=warning ·
 *   4 fuerte=lima · 5 excelente=success.
 * La ETIQUETA usa el mismo color en oscuro; en claro usa el par
 * profundo (-700/-800) para contraste sobre fondo claro (como el kit).
 * Uso:
 *   <div class="pwd-meter" data-score="4">
 *     <div class="pwd-bars"><span></span>×5</div>
 *     <span class="pwd-label">Fuerte</span>
 *   </div>
 * ────────────────────────────────────────────────────────────── */

.pwd-meter { display: grid; gap: 6px; margin-top: -2px; }
.pwd-bars  { display: flex; gap: 4px; }
.pwd-bars span {
  flex: 1; height: 4px; border-radius: 2px;
  background: var(--color-border);
  transition: background .2s;
}
.pwd-label { font-size: 11px; font-weight: 600; color: var(--color-text-secondary); }

/* Escala — color de barra por puntuación (n barras rellenas).
 * OJO: acotar a `.pwd-bars span` — `.pwd-label` es también un <span> hijo
 * directo de .pwd-meter y un `span` genérico lo pintaría de color de fondo. */
.pwd-meter[data-score="1"] .pwd-bars span:nth-child(-n+1) { background: var(--color-error); }
.pwd-meter[data-score="2"] .pwd-bars span:nth-child(-n+2) { background: #f97316; }
.pwd-meter[data-score="3"] .pwd-bars span:nth-child(-n+3) { background: var(--color-warning); }
.pwd-meter[data-score="4"] .pwd-bars span:nth-child(-n+4) { background: #84cc16; }
.pwd-meter[data-score="5"] .pwd-bars span:nth-child(-n+5) { background: var(--color-success); }

/* Etiqueta — claro: pares profundos para legibilidad. */
.pwd-meter[data-score="1"] .pwd-label { color: var(--color-error-700); }
.pwd-meter[data-score="2"] .pwd-label { color: #9a3412; }
.pwd-meter[data-score="3"] .pwd-label { color: var(--color-warning-700); }
.pwd-meter[data-score="4"] .pwd-label { color: #3f6212; }
.pwd-meter[data-score="5"] .pwd-label { color: var(--color-success-700); }

/* Etiqueta — oscuro: el color vivo ya contrasta. */
[data-theme="dark"] .pwd-meter[data-score="1"] .pwd-label { color: var(--color-error); }
[data-theme="dark"] .pwd-meter[data-score="2"] .pwd-label { color: #f97316; }
[data-theme="dark"] .pwd-meter[data-score="3"] .pwd-label { color: var(--color-warning); }
[data-theme="dark"] .pwd-meter[data-score="4"] .pwd-label { color: #84cc16; }
[data-theme="dark"] .pwd-meter[data-score="5"] .pwd-label { color: var(--color-success); }

/* Requisito cumplido (lista de reglas del register) */
.pwd-req      { font-size: 12px; display: flex; align-items: center; gap: 6px; color: var(--color-text-secondary); }
.pwd-req.is-met { color: var(--color-success-700); }
[data-theme="dark"] .pwd-req.is-met { color: var(--color-success); }

/* Lista de requisitos (.pwd-reqs) — un ítem por regla. Marca a la izquierda:
 * anillo hueco (pendiente) → check verde (cumplido). Espejo del kit, que usa
 * el icono 'circle' → 'check'. El binder de preview alterna .is-met al teclear. */
.pwd-reqs { display: grid; gap: 3px; margin-top: 2px; }
.pwd-req-mark {
  flex-shrink: 0; position: relative;
  width: 13px; height: 13px; border-radius: 50%;
  border: 1.5px solid currentColor; color: var(--color-text-muted);
  transition: color .15s, border-color .15s;
}
.pwd-req.is-met .pwd-req-mark { border-color: transparent; color: inherit; }
.pwd-req.is-met .pwd-req-mark::after {
  content: ""; position: absolute; left: 4px; top: 1px;
  width: 3px; height: 6.5px;
  border: solid currentColor; border-width: 0 1.7px 1.7px 0;
  transform: rotate(45deg);
}


/* source: html_export/_shared/css/_perm-chip.css */

/* ──────────────────────────────────────────────────────────────
 * Alarmas · PERM-CHIP preset — FUENTE ÚNICA (CSS recipe)
 * Extraído 1:1 del kit (ui_kits/app/sharing-profile.jsx · PermChip).
 * Chip cuadrado 64×64 que actúa como toggle de permiso (Compartir).
 *   · activo (.is-on):  CLARO → "Sólido elevado" (relleno azul suave
 *     + sheen superior, borde primary 45%); OSCURO → "Neón" (centro
 *     translúcido, borde primary vivo 1.5px). Ambos con relieve
 *     corto-intenso (.elev-pop) y texto/icono en primary-700.
 *   · inactivo: superficie plana con borde, contenido atenuado.
 * Uso: <button class="perm-chip [is-on]" role="switch" aria-checked>
 *        <i data-lucide="..."></i><span>Etiqueta</span></button>
 * ────────────────────────────────────────────────────────────── */

.perm-chip {
  width: 64px; height: 64px; flex: 0 0 auto;
  box-sizing: border-box;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 4px; padding: 6px 4px;
  border: 1px solid var(--color-border);
  background: #fff;
  color: var(--color-text-secondary);
  border-radius: 10px;
  font-family: inherit; font-size: 11px; font-weight: 500;
  cursor: pointer;
  transition: background .15s, border-color .15s, color .15s, box-shadow .15s, transform .15s;
  text-align: center; line-height: 1.15;
  overflow: hidden;
}
[data-theme="dark"] .perm-chip {
  background: rgba(15, 23, 42, 0.4);
}
.perm-chip svg, .perm-chip i { width: 16px; height: 16px; flex-shrink: 0; }
.perm-chip span {
  max-width: 100%;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

/* Activo — claro: "Sólido elevado" (sheen + tinte primary sobre blanco). */
.perm-chip.is-on {
  background:
    linear-gradient(180deg, rgba(255,255,255,0.60) 0, rgba(255,255,255,0) 55%),
    color-mix(in srgb, var(--color-primary) 12%, #ffffff);
  border: 1px solid color-mix(in srgb, var(--color-primary) 45%, transparent);
  color: var(--color-primary-700);
  font-weight: 600;
  transform: translateY(-0.5px);
  /* Relieve corto-intenso — mismas capas que .elev-pop (_elevation.css). */
  box-shadow:
    0 0 0 1px rgba(15, 23, 42, 0.06),
    0 1px 1px rgba(15, 23, 42, 0.22),
    0 2px 3px rgba(15, 23, 42, 0.28);
}
/* Activo — oscuro: "Neón" (centro translúcido, borde primary vivo). */
[data-theme="dark"] .perm-chip.is-on {
  background:
    linear-gradient(180deg, rgba(96,165,250,0.10) 0, rgba(96,165,250,0) 60%),
    color-mix(in srgb, var(--color-primary) 14%, transparent);
  border: 1.5px solid var(--color-primary);
  box-shadow:
    0 0 0 1px rgba(0, 0, 0, 0.40),
    0 1px 1px rgba(0, 0, 0, 0.50),
    0 2px 3px rgba(0, 0, 0, 0.45);
}


/* source: html_export/_shared/css/_range.css */

/* ──────────────────────────────────────────────────────────────
 * Alarmas · RANGE preset — FUENTE ÚNICA (CSS recipe)
 * Slider del DS (campos de sensor, retardo de salida). El nativo
 * dejaba el track NO seleccionado al gris del navegador (demasiado
 * oscuro en claro). Aquí el track usa el mismo par que las UsageBar:
 *   claro  → --color-surface-tonal-hover (slate-200)
 *   oscuro → rgba(148,163,184,0.28)
 * El RELLENO (porción seleccionada) lo pinta el consumidor con un
 * gradiente inline (estático) o JS (en vivo):
 *   background: linear-gradient(to right,
 *     var(--color-primary) 0 P%, transparent P% 100%);
 * sobre el track base — por eso el track vive en una capa propia.
 * Uso: <input type="range" class="range" style="--range-fill:70%">
 * ────────────────────────────────────────────────────────────── */

.range {
  -webkit-appearance: none;
  appearance: none;
  width: 100%;
  height: 6px;
  border-radius: 9999px;
  outline: none;
  cursor: pointer;
  background:
    linear-gradient(to right,
      var(--color-primary) 0 var(--range-fill, 50%),
      transparent var(--range-fill, 50%) 100%),
    var(--color-surface-tonal-hover);
}
[data-theme="dark"] .range {
  background:
    linear-gradient(to right,
      var(--color-primary) 0 var(--range-fill, 50%),
      transparent var(--range-fill, 50%) 100%),
    rgba(148, 163, 184, 0.28);
}

/* Thumb — primary con aro blanco y sombra corta (idioma .elev-pop). */
.range::-webkit-slider-thumb {
  -webkit-appearance: none;
  appearance: none;
  width: 18px; height: 18px; border-radius: 50%;
  background: var(--color-primary);
  border: 2px solid #fff;
  box-shadow: 0 1px 2px rgba(15, 23, 42, 0.22), 0 2px 3px rgba(15, 23, 42, 0.18);
  cursor: pointer;
}
.range::-moz-range-thumb {
  width: 18px; height: 18px; border-radius: 50%;
  background: var(--color-primary);
  border: 2px solid #fff;
  box-shadow: 0 1px 2px rgba(15, 23, 42, 0.22), 0 2px 3px rgba(15, 23, 42, 0.18);
  cursor: pointer;
}
[data-theme="dark"] .range::-webkit-slider-thumb { border-color: var(--color-bg); }
[data-theme="dark"] .range::-moz-range-thumb    { border-color: var(--color-bg); }


/* source: html_export/_shared/css/_section-label.css */

/* ──────────────────────────────────────────────────────────────
 * Alarmas · SECTION-LABEL (eyebrow) preset — FUENTE ÚNICA (CSS)
 * ──────────────────────────────────────────────────────────────
 * El rótulo MAYÚSCULAS que encabeza secciones, cards y modales.
 * Hoy se repite ~40 veces inline en los kits con micro-variaciones
 * (fontSize 9/10/11, weight 600/700, letter-spacing .04–.08em,
 * color text2 / textMute / primary700 / success700).
 *
 * Esta receta fija el estándar y expone las variantes reales que
 * usa el producto. La consumen app, portal y specimens del DS.
 * Coherente con el rol .label-tracker de colors_and_type.css.
 * ────────────────────────────────────────────────────────────── */
.eyebrow {
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  line-height: 1.2;
  color: var(--color-text-secondary);   /* slate-500 por defecto */
}

/* Tamaños (los 3 reales del kit) */
.eyebrow--sm { font-size: 10px; }
.eyebrow--xs { font-size: 9px; letter-spacing: 0.04em; }

/* Pesos */
.eyebrow--600 { font-weight: 600; }

/* Colores semánticos (instancias reales) */
.eyebrow--muted { color: var(--color-text-muted); }     /* metadatos terciarios */
.eyebrow--cond  { color: var(--color-condition-text); } /* "Condiciones" (azul) */
.eyebrow--act   { color: var(--color-action-text); }    /* "Acciones" (verde)  */
.eyebrow--danger{ color: var(--color-error); }          /* "Se eliminará"      */


/* source: html_export/_shared/css/_segmented.css */

/* ──────────────────────────────────────────────────────────────
 * Alarmas · SEGMENTED preset — FUENTE ÚNICA (CSS recipe)
 * ──────────────────────────────────────────────────────────────
 * Control segmentado (pestañas tipo iOS). Base común de ArmModeSegmented
 * y CompactModePicker (app) y del segmentado del portal. Track HUNDIDO
 * (well recesado con sombra interior) + pastilla activa ELEVADA con bisel
 * azul brand — lenguaje 3D coherente con .btn--primary. aria-pressed="true".
 * ────────────────────────────────────────────────────────────── */
.segmented {
  display: inline-flex; gap: 4px;
  box-sizing: border-box;          /* el padding/borde no debe sumar al width:100% de --full */
  padding: 4px;
  /* Track hundido: superficie sunken + sombra interior que crea el
   * efecto de carril recesado sobre el que se eleva el activo. */
  background: var(--color-surface-sunken);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);            /* 12px */
  box-shadow: inset 0 1px 2px rgba(15,23,42,0.10);
}
[data-theme="dark"] .segmented {
  /* Borde exterior CLARO (slate-700) para que el control se distinga sobre
   * la card slate-800; el efecto hundido lo aporta la sombra interior. */
  border-color: var(--color-surface-tonal);
  box-shadow: inset 0 1px 3px rgba(0,0,0,0.55);
}
.segmented > button,
.segmented > form > button {
  flex: 1; min-width: 0;
  font-family: inherit; font-size: 13px; font-weight: 600;
  color: var(--color-text-secondary);
  background: transparent; border: 0;
  padding: 7px 14px; border-radius: var(--radius-md);   /* 8px */
  cursor: pointer;
  display: inline-flex; align-items: center; justify-content: center; gap: 6px;
  transition: background var(--transition-fast), color var(--transition-fast), box-shadow var(--transition-fast), transform var(--transition-fast);
}
.segmented > button[aria-pressed="true"],
.segmented > form > button[aria-pressed="true"] {
  /* Activo ELEVADO: pastilla azul brand con bisel (gradiente) + sombra
   * compuesta (elevación neutra + glow azul suave) + contorno interior.
   * Mismo azul en ambos temas (decisión estética del DS). */
  color: #fff;
  background:
    linear-gradient(180deg, rgba(255,255,255,0.26) 0, rgba(255,255,255,0) 48%),
    #3b82f6;
  box-shadow:
    0 1px 2px rgba(15,23,42,0.18),
    0 2px 5px rgba(37,99,235,0.24),
    inset 0 0 0 1px rgba(255,255,255,0.16);
  transform: translateY(-0.5px);
}
.segmented > button:disabled, .segmented > form > button:disabled { opacity: .5; cursor: not-allowed; }

/* El icono del segmento nunca colapsa: tamaño fijo + sin shrink. Sin esto,
 * en una etiqueta larga dentro de un track flex:1 (p.ej. "Desarmado") el SVG
 * se comprimía a pocos px y "desaparecía". 16px casa con el texto de 13px. */
.segmented > button svg, .segmented > form > button svg { width: 16px; height: 16px; flex-shrink: 0; }

/* Variante SOLID — alias histórico: hoy coincide con el default (activo azul
 * relleno). Se mantiene para no romper consumidores existentes. */

/* Variante full-width (ocupa todo el ancho del contenedor) */
.segmented--full { display: flex; width: 100%; }

/* ── ARM segmented · pastilla activa coloreada POR MODO ──────────────
 * Réplica de segActive3D() del kit (sheen + elevación + ring del modo),
 * pero el color sale de los tokens [data-arm-mode] de tone-presets, no del
 * azul brand. La GEOMETRÍA (compact 38–40px / full 58px) la fija el
 * consumidor con estilo inline; este bloque gobierna SOLO el tratamiento
 * del activo, así que editarlo cambia el segmentado de armado (dashboard,
 * panel de ubicación, pantalla Alarma) en bloque. Usa aria-checked (role
 * radio), no aria-pressed, para no colisionar con el activo azul base. */
.segmented > button[data-arm-mode][aria-checked="true"] {
  color: var(--arm-deep);
  background:
    linear-gradient(180deg, rgba(255,255,255,0.45) 0, rgba(255,255,255,0) 48%),
    var(--arm-lt);
  transform: translateY(-0.5px);
  box-shadow:
    0 1px 2px rgba(15,23,42,0.14),
    0 2px 5px rgba(15,23,42,0.10),
    inset 0 0 0 1px color-mix(in srgb, var(--arm-ring) 50%, transparent);
}
/* `away` = modo enfatizado (emphasize:true en ARM_MODE_PRESET): glow
 * exterior + ring doble más grueso, sin salirse del semántico verde. */
.segmented > button[data-arm-mode="away"][aria-checked="true"] {
  box-shadow:
    0 1px 3px rgba(15,23,42,0.14),
    0 3px 10px color-mix(in srgb, var(--arm-ring) 22%, transparent),
    0 0 0 2px color-mix(in srgb, var(--arm-ring) 25%, transparent),
    inset 0 0 0 2px color-mix(in srgb, var(--arm-ring) 67%, transparent);
}
[data-theme="dark"] .segmented > button[data-arm-mode][aria-checked="true"] {
  background:
    linear-gradient(180deg, rgba(255,255,255,0.10) 0, rgba(255,255,255,0) 48%),
    var(--arm-lt);
  box-shadow:
    0 1px 2px rgba(15,23,42,0.35),
    0 2px 5px rgba(15,23,42,0.30),
    inset 0 0 0 1px color-mix(in srgb, var(--arm-ring) 33%, transparent);
}
[data-theme="dark"] .segmented > button[data-arm-mode="away"][aria-checked="true"] {
  box-shadow:
    0 1px 3px rgba(15,23,42,0.40),
    0 3px 10px color-mix(in srgb, var(--arm-ring) 25%, transparent),
    0 0 0 2px color-mix(in srgb, var(--arm-ring) 33%, transparent),
    inset 0 0 0 2px color-mix(in srgb, var(--arm-ring) 53%, transparent);
}


/* source: html_export/_shared/css/_tick.css */

/* ──────────────────────────────────────────────────────────────
 * Alarmas · MARK presets — FUENTE ÚNICA compartida
 * ──────────────────────────────────────────────────────────────
 * Dos presets con la MISMA estética, distinta función:
 *
 *   .tick         → casilla INTERACTIVA (checkbox). Sustituye al
 *                   checkbox nativo. Se aplica sobre <input type="checkbox">.
 *                     <input type="checkbox" class="tick">
 *                     <input type="checkbox" class="tick tick--danger">
 *
 *   .result-mark  → indicador de RESULTADO de solo lectura (pass/fail).
 *                   Mismo cuadro y glifo que .tick pero sin interacción.
 *                   Se aplica sobre un <span> (o cualquier caja):
 *                     <span class="result-mark result-mark--ok"></span>
 *                     <span class="result-mark result-mark--fail"></span>
 *
 * FUENTE ÚNICA DE LA VERDAD: la geometría (tamaño, radio, borde, tamaño
 * de glifo) y los GLIFOS (check / cross en trazo blanco) viven UNA sola
 * vez en la regla base `.tick, .result-mark` como custom properties.
 * Editar ahí reverbera en AMBOS presets — no dupliques valores fuera.
 *
 * El glifo se pinta como background-image (SVG): los <input> no renderizan
 * ::before/::after de forma fiable en todos los navegadores.
 * ────────────────────────────────────────────────────────────── */
.tick,
.result-mark {
  /* — Single source of truth (geometría + glifos) — */
  --mark-size: 20px;
  --mark-radius: 6px;
  --mark-border-width: 2px;
  --mark-glyph-size: 12px;
  /* Glifos compartidos: trazo blanco, stroke 3.5 para buen contraste óptico
   * sobre el relleno saturado, incluso a tamaño pequeño. */
  --mark-check: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='white' stroke-width='3.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M20 6 9 17l-5-5'/%3E%3C/svg%3E");
  --mark-cross: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='white' stroke-width='3.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M18 6 6 18M6 6l12 12'/%3E%3C/svg%3E");

  appearance: none; -webkit-appearance: none;
  box-sizing: border-box;
  flex-shrink: 0; margin: 0; padding: 0;
  width: var(--mark-size); height: var(--mark-size);
  border: var(--mark-border-width) solid var(--color-border);
  border-radius: var(--mark-radius);
  background-color: var(--color-surface);
  background-repeat: no-repeat;
  background-position: center;
  background-size: var(--mark-glyph-size) var(--mark-glyph-size);
  display: inline-flex; align-items: center; justify-content: center;
}

/* Tamaño grande — compartido por ambos presets. */
.tick--lg,
.result-mark--lg {
  --mark-size: 24px;
  --mark-radius: 7px;
  --mark-glyph-size: 14px;
}

/* ── TICK · casilla interactiva ─────────────────────────────── */
.tick {
  cursor: pointer;
  transition: background-color var(--transition-fast), border-color var(--transition-fast), box-shadow var(--transition-fast);
}
.tick:checked {
  background-color: var(--color-primary);
  border-color: var(--color-primary);
  background-image: var(--mark-check);
}
.tick:hover:not(:disabled):not(:checked) { border-color: var(--color-text-muted); }
.tick:focus-visible { outline: none; box-shadow: 0 0 0 3px rgba(59,130,246,0.20); }
.tick:disabled { opacity: .5; cursor: not-allowed; }

/* DANGER — consentimientos de seguridad / acciones destructivas, donde el
 * verde/azul "todo bien" contradiría el peso de la acción. */
.tick--danger:checked { background-color: var(--color-error); border-color: var(--color-error); }
.tick--danger:focus-visible { box-shadow: 0 0 0 3px rgba(239,68,68,0.22); }
.tick--danger:hover:not(:disabled):not(:checked) { border-color: var(--color-error); }

/* ── RESULT-MARK · resultado de solo lectura ────────────────── */
/* No interactivo: sin cursor, sin hover/focus. Mismo cuadro y glifo que
 * .tick. OK = check verde · FAIL = cross rojo (relleno saturado + glifo
 * blanco, idéntico tratamiento que .tick:checked). */
.result-mark--ok {
  /* Verde un punto más profundo que --color-success (verde-500) para que
   * el relleno no quede neón; coherente con el glifo blanco encima. */
  background-color: color-mix(in srgb, var(--color-success) 88%, #0f172a);
  border-color: color-mix(in srgb, var(--color-success) 88%, #0f172a);
  background-image: var(--mark-check);
}
/* En oscuro se atenúa algo más hacia el fondo de noche. */
[data-theme="dark"] .result-mark--ok {
  background-color: color-mix(in srgb, var(--color-success) 70%, #0b1220);
  border-color: color-mix(in srgb, var(--color-success) 70%, #0b1220);
}
.result-mark--fail {
  background-color: var(--color-error);
  border-color: var(--color-error);
  background-image: var(--mark-cross);
}
/* En oscuro el error-500 (token claro) queda lavado bajo el glifo blanco.
 * Profundizamos hacia un rojo SATURADO (no hacia el slate, que desaturaría)
 * para subir el contraste de la X; un punto por debajo de #dc2626 para que
 * no quede demasiado intenso. */
[data-theme="dark"] .result-mark--fail {
  background-color: color-mix(in srgb, #dc2626 88%, #0b1220);
  border-color: color-mix(in srgb, #dc2626 88%, #0b1220);
}


/* source: html_export/_shared/css/_timepicker.css */

/* ──────────────────────────────────────────────────────────────
 * Alarmas · TIMEPICKER preset (CSS recipe) — card chip HH:MM + rueda
 * ──────────────────────────────────────────────────────────────
 * Geometría BAKED desde preview/_timepicker-preset.js (fuente única):
 *   digitW 44 · cellH 36 · visible 5 · cardRadius 12 · chipRadius 8
 *   digitSize 25 · cardPadV 4 · cardPadH 6
 * Tonos = timePickerTones(): card = surface-sunken, chip = surface(claro)/
 * surface-tonal(oscuro), colon = text-secondary, dígito = text.
 * Consumidores: Programación (alarma) · Editar automatización (trigger_form).
 * Si se cambia el preset .js, re-bakear estos valores.
 * ────────────────────────────────────────────────────────────── */

/* Card exterior + par de chips HH:MM — estado REPOSO (tappable → abre rueda). */
.tp-card {
  display: inline-flex; align-items: center; gap: 4px;
  padding: 4px 6px;
  background: #f8fafc; /* kit timePickerTones.cardBg claro */
  border: 1px solid var(--color-border);
  border-radius: 12px;
  font-family: inherit; cursor: pointer;
}
[data-theme="dark"] .tp-card {
  background: rgb(15 23 42 / 50%);   /* kit cardBg oscuro */
  border-color: rgb(15 23 42 / 90%); /* kit cardBorder oscuro */
}
.tp-chip {
  min-width: 44px; height: 36px;
  display: flex; align-items: center; justify-content: center;
  background: #ffffff; /* kit chipBg claro */
  border: 1px solid var(--color-border);
  border-radius: 8px;
  font-size: 22px; font-weight: 700; line-height: 1; /* kit digitSize/700 */
  color: var(--color-text); font-variant-numeric: tabular-nums; letter-spacing: -.02em;
}
[data-theme="dark"] .tp-chip {
  background: rgb(51 65 85 / 85%);    /* kit chipBg oscuro */
  border-color: rgb(71 85 105 / 70%); /* kit chipBorder oscuro */
}
/* Colon centrado por el CENTRO DE TINTA, no por la caja: el glifo ":" tiene su
 * tinta ~4px más baja (respecto a baseline) que el dígito con font 600, así que
 * el centrado de caja lo dejaba ópticamente bajo. Flex + altura de celda + nudge. */
.tp-colon {
  display: flex; align-items: center; justify-content: center;
  height: 36px; line-height: 1;
  font-size: 20px; font-weight: 600;
  color: var(--color-text-secondary); padding: 0 2px;
  transform: translateY(-2px);
}
/* Toma todo el ancho de su columna (Inicio/Fin en el form de rango). */
.tp-card--block { display: flex; justify-content: center; }

/* ── Rueda ABIERTA (5 ítems visibles) — mismo card, columnas scrollables ── */
/* TIMEPICKER · rueda-popover por dígito (kit WheelNumber):
 * el chip queda en flow (visibility hidden al abrir) y la rueda se superpone
 * con el valor actual centrado sobre el chip (top = -PAD_H). cellH 36 · 5
 * visibles · pads de (180-36)/2 = 72. Scroll infinito + inercia en el JS. */
.tp-digit { position: relative; display: inline-flex; width: 44px; height: 36px; flex-shrink: 0; }
.tp-digit .tp-chip { width: 100%; cursor: pointer; }
.tp-chip--hidden { visibility: hidden; }
.tp-pop { position: absolute; top: -72px; left: -4px; right: -4px; z-index: 30; overflow: hidden; background: #ffffff; border: 1px solid var(--color-border); border-radius: 10px; box-shadow: 0 12px 32px rgb(15 23 42 / 12%); animation: wheel-pop 140ms ease-out; } /* kit wheelBg/shadow claro */
[data-theme="dark"] .tp-pop { background: rgb(15 23 42 / 96%); border-color: #334155; box-shadow: 0 12px 32px rgb(0 0 0 / 50%); } /* kit wheelBg/wheelBorder/shadow oscuro */
@keyframes wheel-pop { from { opacity: 0; transform: scale(.94); } to { opacity: 1; transform: scale(1); } }
.tp-pop__scroll { height: 180px; overflow-y: auto; scroll-snap-type: y mandatory; scrollbar-width: none; -ms-overflow-style: none; touch-action: pan-y; }
.tp-pop__scroll::-webkit-scrollbar { display: none; width: 0; height: 0; }
.tp-pop__pad { height: 72px; pointer-events: none; }
/* Mientras la rueda se coloca en el valor actual (primer montaje del x-for),
 * los dígitos van ocultos — evita el destello del 00 de la primera copia. */
.tp-pop__scroll[data-placing] .tp-item { visibility: hidden; }
.tp-item { height: 36px; display: flex; align-items: center; justify-content: center; scroll-snap-align: center; color: var(--color-text); font-size: 18px; font-weight: 600; font-variant-numeric: tabular-nums; letter-spacing: -.02em; line-height: 1; opacity: .22; cursor: pointer; user-select: none; transition: opacity .12s ease, font-size .12s ease; }
.tp-item.is-near { opacity: .5; }
.tp-item.is-center { opacity: 1; font-size: 22px; font-weight: 700; cursor: default; }
/* Banda central — hairlines que marcan el slot activo (kit). */
.tp-pop__band { position: absolute; left: 4px; right: 4px; top: 72px; height: 36px; border-top: 1px solid rgb(15 23 42 / 12%); border-bottom: 1px solid rgb(15 23 42 / 12%); pointer-events: none; } /* kit band claro */
[data-theme="dark"] .tp-pop__band { border-top-color: rgb(148 163 184 / 30%); border-bottom-color: rgb(148 163 184 / 30%); } /* kit band oscuro */


/* source: html_export/_shared/css/_toggle.css */

/* ──────────────────────────────────────────────────────────────
 * Alarmas · TOGGLE preset — FUENTE ÚNICA (CSS recipe)
 * ──────────────────────────────────────────────────────────────
 * Switch on/off. La app tiene el componente Toggle; el portal usa
 * .sw por separado. Reconciliado al estándar de la APP (44×24, knob 18,
 * desplazamiento 20); el portal (.sw 44×26) se alinea a esta geometría.
 * Usa los tokens de color del DS. Activa con .is-on o aria-checked.
 * ────────────────────────────────────────────────────────────── */
.toggle {
  position: relative; flex-shrink: 0;
  width: 44px; height: 24px; padding: 0; border: 0;
  border-radius: 9999px;
  background: var(--color-toggle-inactive);
  /* Contorno definidor (prueba) — mismo idioma que el `0 0 0 1px` de los
   * botones: separa el track de superficies recesadas (triggers inactivos)
   * donde el toggle OFF se fundía con el fondo. Negro translúcido → se
   * adapta a ambos temas sin theme-split. */
  box-shadow: inset 0 0 0 1px rgba(15, 23, 42, 0.28);
  cursor: pointer;
  transition: background var(--transition-base);
}
[data-theme="dark"] .toggle {
  box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.55);
}
.toggle::after {
  content: ''; position: absolute; top: 3px; left: 3px;
  width: 18px; height: 18px; border-radius: 50%;
  background: #fff; box-shadow: 0 1px 2px rgba(0,0,0,0.2);
  transition: transform var(--transition-base);
}
.toggle.is-on, .toggle[aria-checked="true"] {
  /* Activo — OVERRIDE: usa siempre el hex saturado de marca (no la versión
   * pastel que el DS aplica en dark a --color-toggle-active). El control on
   * pide saturación constante en ambos temas para no leerse "blanquecino". */
  background: #22c55e;
}
.toggle.is-on::after, .toggle[aria-checked="true"]::after { transform: translateX(20px); }

/* Tono alternativo: usar el primary en vez del verde (ajustes no-alarma).
 * OVERRIDE saturado (ver nota arriba): brand blue puro en ambos temas. */
.toggle--primary.is-on, .toggle--primary[aria-checked="true"] { background: #3b82f6; }
/* Tono peligro (p. ej. el switch de pánico del portal) — OVERRIDE saturado. */
.toggle--danger.is-on, .toggle--danger[aria-checked="true"] { background: #ef4444; }

.toggle:disabled { opacity: .5; cursor: not-allowed; }


/* source: html_export/_shared/css/tone-presets.css */

/* ──────────────────────────────────────────────────────────────
 * Alarmas · tone-presets.css — GENERADO · NO EDITAR A MANO
 * Fuente: _shared/presets/_arm-mode-preset.js · _schedule-preset.js · _status-tone.js
 * Regenerar tras editar cualquiera de esos presets. Valores resueltos
 * 1:1 contra armModeTones()/scheduleTones() (literales theme-split) y
 * statusTone() (tokens CSS theme-aware). Es la fuente de verdad de TONO
 * portable: ninguna pieza hardcodea color de estado/modo/horario.
 * ────────────────────────────────────────────────────────────── */

/* ═══ ARM MODE · paleta genérica — usa --tone/--tone-lt/--tone-deep/--tone-ring ═══ */
[data-tone="neutral"] { --tone:#64748b; --tone-lt:rgba(100,116,139,0.28); --tone-deep:#1e293b; --tone-ring:#475569; }
[data-tone="blue"] { --tone:#3b82f6; --tone-lt:#bfdbfe; --tone-deep:#1e3a8a; --tone-ring:#3b82f6; }
[data-tone="green"] { --tone:#22c55e; --tone-lt:#bbf7d0; --tone-deep:#14532d; --tone-ring:#22c55e; }
[data-tone="red"] { --tone:#ef4444; --tone-lt:#fecaca; --tone-deep:#7f1d1d; --tone-ring:#ef4444; }
[data-tone="amber"] { --tone:#f59e0b; --tone-lt:#fde68a; --tone-deep:#78350f; --tone-ring:#f59e0b; }

[data-theme="dark"] [data-tone="neutral"] { --tone:#94a3b8; --tone-lt:rgba(148,163,184,0.22); --tone-deep:#f1f5f9; --tone-ring:#94a3b8; }
[data-theme="dark"] [data-tone="blue"] { --tone:#60a5fa; --tone-lt:#1e40af; --tone-deep:#93c5fd; --tone-ring:#60a5fa; }
[data-theme="dark"] [data-tone="green"] { --tone:#4ade80; --tone-lt:#166534; --tone-deep:#bbf7d0; --tone-ring:#4ade80; }
[data-theme="dark"] [data-tone="red"] { --tone:#f87171; --tone-lt:#991b1b; --tone-deep:#fecaca; --tone-ring:#f87171; }
[data-theme="dark"] [data-tone="amber"] { --tone:#fbbf24; --tone-lt:#854d0e; --tone-deep:#fde68a; --tone-ring:#fbbf24; }

/* ═══ ARM MODE · por estado [data-arm-mode] (mapeo actual: disarmed→neutral · home→blue · away→green) ═══ */
[data-arm-mode="disarmed"] { --arm-tone:#64748b; --arm-lt:rgba(100,116,139,0.28); --arm-deep:#1e293b; --arm-ring:#475569; }
[data-arm-mode="home"] { --arm-tone:#3b82f6; --arm-lt:#bfdbfe; --arm-deep:#1e3a8a; --arm-ring:#3b82f6; }
[data-arm-mode="away"] { --arm-tone:#22c55e; --arm-lt:#bbf7d0; --arm-deep:#14532d; --arm-ring:#22c55e; }

[data-theme="dark"] [data-arm-mode="disarmed"] { --arm-tone:#94a3b8; --arm-lt:rgba(148,163,184,0.22); --arm-deep:#f1f5f9; --arm-ring:#94a3b8; }
[data-theme="dark"] [data-arm-mode="home"] { --arm-tone:#60a5fa; --arm-lt:#1e40af; --arm-deep:#93c5fd; --arm-ring:#60a5fa; }
[data-theme="dark"] [data-arm-mode="away"] { --arm-tone:#4ade80; --arm-lt:#166534; --arm-deep:#bbf7d0; --arm-ring:#4ade80; }

/* ═══ SCHEDULE · [data-schedule] — usa --sched-bg/--sched-border/--sched-text/--sched-value ═══ */
/* Default (preset actual: palette="amber") aplicado en :root → cualquier chip sin data-schedule lo hereda. */
:root { --sched-bg:rgba(245,158,11,0.2); --sched-border:rgba(180,83,9,0.5); --sched-text:#b45309; --sched-value:#92400e; }
[data-theme="dark"] { --sched-bg:rgba(245,158,11,0.15); --sched-border:rgba(245,158,11,0.4); --sched-text:#fbbf24; --sched-value:#fde047; }

[data-schedule="amber"] { --sched-bg:rgba(245,158,11,0.2); --sched-border:rgba(180,83,9,0.5); --sched-text:#b45309; --sched-value:#92400e; }
[data-schedule="blue"] { --sched-bg:rgba(59,130,246,0.12); --sched-border:rgba(37,99,235,0.40); --sched-text:#1d4ed8; --sched-value:#1e3a8a; }
[data-schedule="green"] { --sched-bg:rgba(34,197,94,0.18); --sched-border:rgba(22,101,52,0.40); --sched-text:#15803d; --sched-value:#14532d; }
[data-schedule="red"] { --sched-bg:rgba(239,68,68,0.16); --sched-border:rgba(153,27,27,0.40); --sched-text:#991b1b; --sched-value:#7f1d1d; }
[data-schedule="purple"] { --sched-bg:rgba(168,85,247,0.12); --sched-border:rgba(126,34,206,0.40); --sched-text:#7e22ce; --sched-value:#581c87; }
[data-schedule="neutral"] { --sched-bg:rgba(100,116,139,0.18); --sched-border:rgba(71,85,105,0.40); --sched-text:#475569; --sched-value:#334155; }

[data-theme="dark"] [data-schedule="amber"] { --sched-bg:rgba(245,158,11,0.15); --sched-border:rgba(245,158,11,0.4); --sched-text:#fbbf24; --sched-value:#fde047; }
[data-theme="dark"] [data-schedule="blue"] { --sched-bg:rgba(59,130,246,0.18); --sched-border:rgba(96,165,250,0.45); --sched-text:#93c5fd; --sched-value:#bfdbfe; }
[data-theme="dark"] [data-schedule="green"] { --sched-bg:rgba(34,197,94,0.18); --sched-border:rgba(34,197,94,0.45); --sched-text:#86efac; --sched-value:#bbf7d0; }
[data-theme="dark"] [data-schedule="red"] { --sched-bg:rgba(239,68,68,0.18); --sched-border:rgba(248,113,113,0.45); --sched-text:#fca5a5; --sched-value:#fecaca; }
[data-theme="dark"] [data-schedule="purple"] { --sched-bg:rgba(168,85,247,0.18); --sched-border:rgba(192,132,252,0.45); --sched-text:#d8b4fe; --sched-value:#e9d5ff; }
[data-theme="dark"] [data-schedule="neutral"] { --sched-bg:rgba(148,163,184,0.18); --sched-border:rgba(148,163,184,0.45); --sched-text:#cbd5e1; --sched-value:#e2e8f0; }

/* ═══ STATUS TONE · [data-status] — usa --st-bg/--st-fg/--st-dot (tokens theme-aware) ═══ */
/* icono Lucide por estado en data-status-icon (lo lee el consumidor): ok→check · warn→alert-triangle · err→x · info→info · neutral→circle */
[data-status="ok"] { --st-bg:var(--color-success-light); --st-fg:var(--color-success-700); --st-dot:var(--color-success); }
[data-status="warn"] { --st-bg:var(--color-warning-light); --st-fg:var(--color-warning-700); --st-dot:var(--color-warning); }
[data-status="err"] { --st-bg:var(--color-error-light); --st-fg:var(--color-error-700); --st-dot:var(--color-error); }
[data-status="info"] { --st-bg:var(--color-info-light); --st-fg:var(--color-primary-700); --st-dot:var(--color-primary); }
[data-status="neutral"] { --st-bg:var(--color-bg-alt); --st-fg:var(--color-text-secondary); --st-dot:var(--color-text-muted); }
/* Consumidor genérico (paridad kit): todo .chip con data-status se tiñe con los tokens STATUS. */
.chip[data-status] { background: var(--st-bg); color: var(--st-fg); }
.chip[data-status] .chip-dot { background: var(--st-dot); }


/* presentation runtime foundation */

*, *::before, *::after { box-sizing: border-box; }
html { color-scheme: light; background: var(--color-bg); }
html[data-theme="dark"] { color-scheme: dark; }
body { margin: 0; min-height: 100vh; background: var(--color-bg); color: var(--color-text); font-family: var(--font-sans); }
button, input, select, textarea { font: inherit; }
button, a { -webkit-tap-highlight-color: transparent; }
a { color: inherit; }
[hidden], [data-cloak] { display: none !important; }
.htmx-indicator { opacity: 0; }
.htmx-request .htmx-indicator, .htmx-request.htmx-indicator { opacity: 1; transition: opacity 200ms ease-in; }
.presentation-shell { min-height: 100vh; min-height: 100dvh; display: flex; flex-direction: column; }
.presentation-topbar { position: sticky; top: 0; z-index: var(--z-sticky); display: flex; align-items: center; justify-content: space-between; height: calc(56px + var(--safe-top)); padding: var(--safe-top) max(12px, var(--safe-right)) 0 max(12px, var(--safe-left)); background: var(--color-primary); color: #fff; }
.presentation-topbar > strong { color: #0f172a; }
.presentation-topbar-button { display: grid; place-items: center; width: 40px; height: 40px; padding: 0; border: 0; border-radius: 8px; background: transparent; color: #fff; cursor: pointer; }
.presentation-topbar-spacer { width: 40px; height: 40px; }
.presentation-shell-menu { position: fixed; top: calc(56px + var(--safe-top)); left: 12px; z-index: var(--z-modal); display: grid; width: min(260px, calc(100vw - 24px)); padding: 8px; border: 1px solid var(--color-border); border-radius: var(--radius-lg); background: var(--color-surface); box-shadow: var(--shadow-lg); }
.presentation-shell-menu[hidden] { display: none; }
.presentation-shell-menu a { display: flex; align-items: center; gap: 10px; min-height: 42px; padding: 9px 10px; border-radius: 8px; color: var(--color-text); text-decoration: none; }
.presentation-shell-menu a[aria-current="page"] { background: var(--color-primary-light); color: var(--color-primary-700); }
.skip-link { position: fixed; top: -5rem; left: 1rem; z-index: calc(var(--z-modal) + 1); }
.skip-link:focus { top: max(1rem, calc(var(--safe-top) + var(--safe-gap))); }
.presentation-brand { display: inline-flex; align-items: center; gap: 10px; font-weight: var(--weight-bold); text-decoration: none; }
.presentation-main { width: min(100%, 720px); margin: 0 auto; padding: 16px max(16px, var(--safe-right)) 104px max(16px, var(--safe-left)); }
.presentation-stack { display: flex; flex-direction: column; gap: 14px; }
.presentation-bottom-nav { position: fixed; right: 0; bottom: 0; left: 0; z-index: var(--z-sticky); display: grid; grid-template-columns: repeat(5, minmax(0, 1fr)); padding: 8px max(10px, var(--safe-right)) max(8px, var(--safe-bottom)) max(10px, var(--safe-left)); background: color-mix(in srgb, var(--color-surface) 92%, transparent); border-top: 1px solid var(--color-border); backdrop-filter: blur(18px); }
.presentation-nav-item { display: grid; justify-items: center; gap: 3px; min-height: 46px; padding: 5px 2px; color: var(--color-text-secondary); font-size: 11px; text-decoration: none; }
.presentation-nav-item[aria-current="page"] { color: var(--color-primary-700); }
.presentation-nav-item span { max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* Sprite glyph. `:where(svg)` keeps the selector at class specificity while excluding the dropdown preset's <span class="ds-icon"> chip, which shares the name. */
:where(svg).ds-icon { display: inline-block; flex: 0 0 auto; width: var(--icon-size); height: var(--icon-size); fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }
.icon-tile > svg.ds-icon { width: var(--icon-size); height: var(--icon-size); }
.ds-icon--xs { --icon-size: 12px; } .ds-icon--sm { --icon-size: 14px; } .ds-icon--md { --icon-size: 16px; } .ds-icon--lg { --icon-size: 20px; } .ds-icon--xl { --icon-size: 24px; }
/* The chip rule also lands on the glyph <svg>; the glyph never paints its own box — only an explicit wrapper (icon-tile, chip) may. */
svg.ds-icon { background: none; border-radius: 0; }
/* Kit disclosure carets: text2 by default, muted on the profile screen (sharing-profile.jsx). */
.disclosure-caret { color: var(--color-text-secondary); }
.profile-proof .disclosure-caret { color: var(--color-text-muted); }
.public-hero { min-height: calc(100vh - 130px); display: grid; place-items: center; text-align: center; }
.public-hero-card { width: min(100%, 430px); padding: 28px 22px; }
.public-actions { display: grid; gap: 10px; margin-top: 22px; }
.profile-proof { padding-bottom: 12px; }
.profile-hero { padding: 20px 16px 16px; display: flex; flex-direction: column; align-items: center; gap: 10px; text-align: center; }
.profile-hero h1 { margin: 0; color: var(--color-text); font-size: 18px; line-height: 1.3; }
.profile-hero p { margin: 2px 0 0; color: var(--color-text-secondary); font-size: 13px; }
.profile-hero .chip { background: var(--color-primary-100); color: var(--color-primary-700); font-weight: 600; letter-spacing: .04em; }
.profile-avatar { position: relative; display: grid; place-items: center; width: 80px; height: 80px; border-radius: 50%; background: var(--color-primary-light); color: var(--color-primary-700); font-size: 24px; font-weight: 700; }
.profile-avatar > img { display: block; width: 100%; height: 100%; border-radius: inherit; }
.profile-avatar-edit { position: absolute; right: -2px; bottom: -2px; display: grid; place-items: center; width: 28px; height: 28px; padding: 0; border: 3px solid var(--color-surface); border-radius: 50%; background: var(--color-primary); color: #fff; cursor: pointer; }
/* Densidad del kit (sharing-profile.jsx): título 14/500 y descripción 12 con
 * 1px de separación — el line-height heredado del body (16/24) inflaba la fila
 * 12px sobre el kit. La tipografía va en el CONTENEDOR, no solo en strong:
 * varias filas llevan el título como texto plano (Cambiar contraseña, Idioma,
 * Zona horaria, Tema) y quedaban a 16/400. line-height normal, como el kit
 * (con 1.25/1.35 la fila subía a 59 en vez de 56). Centralizado aquí: aplica a
 * TODA fila disclosure y a las profile-setting-row, que comparten patrón. */
:is(.disclosure-main, .profile-setting-copy) { display: grid; flex: 1; min-width: 0; gap: 1px; text-align: left; font-size: 14px; font-weight: 500; line-height: normal; }
:is(.disclosure-main, .profile-setting-copy) small { color: var(--color-text-secondary); font-size: 12px; font-weight: 400; line-height: normal; }
:is(.disclosure-main, .profile-setting-copy) strong { font-size: 14px; font-weight: 500; line-height: normal; }
/* Compartir usa 600 en los títulos de fila (nombre de invitado, cabecera de
 * card); el perfil, 500. Ambos pesos son del kit: no es uniforme. */
:is(.sharing-entity__row, .sharing-card, .sharing-grant, .sharing-owner-row) .disclosure-main strong { font-weight: 600; }
.profile-section-label { padding: 0 4px; margin-top: 4px; color: #475569; }
[data-theme="dark"] .profile-section-label { color: var(--color-text-secondary); }
.profile-row + .profile-row, .profile-row + div, section[data-profile-group] > .profile-row { border-top: 1px solid var(--color-border); }
/* Cualquier fila que no sea la primera del grupo lleva separador, sea el
 * contenedor section o div y venga detrás de otra fila o de un panel abierto
 * (caso «Cambiar contraseña» tras «Información personal»). */
[data-profile-group] > .profile-row:not(:first-child) { border-top: 1px solid var(--color-border); }
/* Dentro del panel de notificaciones el separador va por HIJO, no por
 * adyacencia: el partial de dispositivos mete su diálogo de borrado (oculto)
 * entre las dos filas, así que `.profile-row + .profile-row` no casaba nunca y
 * el 1px se lo llevaba el diálogo. */
#profile-notifications-panel > .profile-row { border-top: 1px solid var(--color-border); }
.profile-row + [hidden], [hidden] + .profile-row { border-top-width: 0; }
#profile-notifications-panel > .profile-row { border-top-width: 1px; }
.profile-row-value { max-width: 42%; overflow: hidden; color: var(--color-text-secondary); font-size: 13px; font-weight: 400; text-overflow: ellipsis; white-space: nowrap; }
.profile-panel { padding: 4px 14px 14px; border-top: 1px solid var(--color-border); }
.profile-loading, .profile-inline-result { color: var(--color-text-secondary); font-size: 13px; }
.profile-form { display: grid; gap: 10px; padding-top: 10px; }
.profile-field { display: grid; gap: 5px; }
.profile-field-control { display: flex; align-items: center; gap: 8px; min-height: 42px; padding: 0 10px; border: 1px solid var(--color-card-nested-border); border-radius: 10px; background: var(--color-card-nested-bg); color: var(--color-text-muted); }
.profile-field-control input { min-width: 0; flex: 1; padding: 10px 0; border: 0; outline: 0; background: transparent; color: var(--color-text); }
.profile-password-toggle { display: grid; flex: 0 0 32px; place-items: center; width: 32px; height: 32px; padding: 0; border: 0; border-radius: 8px; background: transparent; color: var(--color-text-muted); cursor: pointer; }
.profile-password-toggle:hover, .profile-password-toggle:focus-visible { background: var(--color-bg-alt); color: var(--color-text); }
.profile-setting-row { display: flex; align-items: center; gap: 12px; min-height: 56px; padding: 10px 0; color: var(--color-text); text-decoration: none; }
.profile-setting-row + .profile-setting-row { border-top: 1px solid var(--color-border); }
.profile-setting-copy { display: grid; flex: 1; gap: 1px; }
.profile-setting-copy small { color: var(--color-text-secondary); font-size: 12px; }
.profile-devices { display: grid; gap: 10px; }
.profile-devices__toolbar { display: flex; align-items: center; justify-content: space-between; gap: 10px; padding-top: 10px; }
.profile-devices__toolbar p { margin: 0; color: var(--color-text-secondary); font-size: 12px; }
.profile-device-list { display: grid; gap: 8px; }
.profile-device-row { display: flex; align-items: center; gap: 10px; padding: 10px; border: 1px solid var(--color-card-nested-border); border-radius: 10px; background: var(--color-card-nested-bg); }
.profile-device-copy { display: grid; min-width: 0; flex: 1; gap: 2px; }
.profile-device-copy > strong, .profile-device-copy > small { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.profile-device-copy > small { color: var(--color-text-muted); font-size: 11px; }
.profile-device-actions { display: flex; gap: 5px; }
.profile-device-editor { display: grid; grid-template-columns: minmax(0, 1fr) auto auto; gap: 5px; }
.profile-device-editor .field { min-width: 0; }
.profile-device-row .btn--sm { min-width: 34px; padding-right: 7px; padding-left: 7px; }
@media (max-width: 440px) { .profile-devices__toolbar { align-items: flex-start; flex-direction: column; } .profile-device-row { align-items: flex-start; } .profile-device-editor { grid-template-columns: 1fr 1fr; } .profile-device-editor .field { grid-column: 1 / -1; } }
.profile-alarm-history { display: grid; gap: 10px; padding-top: 10px; }
.profile-history-list { display: grid; gap: 7px; }
.profile-history-row { display: grid; grid-template-columns: auto minmax(0, 1fr) auto; align-items: center; gap: 9px; padding: 9px; border: 1px solid var(--color-border); border-radius: 10px; background: var(--color-card-nested-bg); }
.profile-history-row > div { display: grid; min-width: 0; gap: 2px; }
.profile-history-row strong { overflow: hidden; font-size: 12px; text-overflow: ellipsis; white-space: nowrap; }
.profile-history-row time, .profile-history-row > span:last-child, .profile-history-row > a { color: var(--color-text-muted); font-size: 11px; }
.profile-history-row > a { color: var(--color-error); font-weight: 600; }
.profile-history-state { display: grid; justify-items: center; gap: 8px; padding: 14px; color: var(--color-text-secondary); text-align: center; }
.profile-history-state p { margin: 0; font-size: 12px; }
.profile-history-active { text-decoration: none; }
/* input-compat del preset .toggle (_toggle.css): geometría/track/knob/dark vienen del preset; aquí sólo se neutraliza el checkbox UA y se mapea :checked a los OVERRIDE saturados del preset. */
input.toggle { -webkit-appearance: none; appearance: none; margin: 0; }
input.toggle:checked { background: #22c55e; }
input.toggle:checked::after { transform: translateX(20px); }
input.toggle.toggle--primary:checked { background: #3b82f6; }
input.toggle.toggle--danger:checked { background: #ef4444; }
.profile-danger { padding: 14px; border: 1px solid color-mix(in srgb, var(--color-error) 45%, transparent); border-radius: var(--radius-xl); background: color-mix(in srgb, var(--color-error-light) 72%, transparent); }
.profile-danger > p { display: flex; align-items: flex-start; gap: 10px; margin: 0 0 12px; color: var(--color-error-700); font-size: 12px; line-height: 1.5; }
.profile-modal { position: fixed; inset: 0; z-index: var(--z-modal); display: grid; align-items: start; overflow: auto; padding: var(--modal-pad-top) 16px var(--modal-pad-bottom); background: rgba(2, 6, 23, .55); backdrop-filter: blur(2px); animation: scrim-in var(--motion-fade-duration) ease; }
.profile-modal > .dialog { width: min(100%, 430px); margin: 0 auto; }
.profile-modal--critical { padding: max(64px, calc(var(--safe-top) + var(--safe-gap))) max(24px, var(--safe-right)) max(64px, calc(var(--safe-bottom) + var(--safe-gap))) max(24px, var(--safe-left)); }
.profile-delete-dialog { display: flex; flex-direction: column; width: 100%; max-width: 380px; max-height: var(--modal-max-h); }
.profile-delete-dialog .dialog-title { margin: 0; }
.profile-delete-dialog .dialog-sub { margin: 3px 0 0; }
.profile-delete-form { display: flex; min-height: 0; flex: 1; flex-direction: column; }
/* Padding SIMÉTRICO: el par 20/6 era un apaño para dejar hueco a la barra de
 * scroll y desplazaba todo el contenido 14px a la izquierda (7 vs 21). */
.profile-delete-body { min-height: 0; flex: 1; padding-right: 20px; padding-left: 20px; overflow-y: auto; }
.profile-delete-impact { margin-bottom: 22px; }
.profile-delete-loss-heading { margin: 0 0 10px; }
.profile-loss-list { display: grid; gap: 0; padding: 0; margin: 0; overflow: hidden; border: 1px solid var(--color-border); border-radius: var(--radius-lg); background: var(--color-bg-alt); list-style: none; }
.profile-loss-list li { display: flex; align-items: center; gap: 12px; min-height: 46px; padding: 11px 14px; background: var(--color-surface); color: var(--color-text-secondary); font-size: 13.5px; }
.profile-loss-list li + li { border-top: 1px solid var(--color-border); }
.profile-loss-list .ds-icon { color: var(--color-error); }
.profile-loss-list strong { min-width: 22px; color: var(--color-text); font-size: 14px; font-variant-numeric: tabular-nums; }
.profile-loss-list li > span:last-child { text-transform: lowercase; }
.profile-delete-friction { display: grid; gap: 14px; padding: 14px; border: 1px solid color-mix(in srgb, var(--color-error) 22%, transparent); border-radius: var(--radius-lg); background: color-mix(in srgb, var(--color-error) 8%, transparent); }
.profile-delete-ack { display: flex; align-items: center; gap: 12px; color: var(--color-text); font-size: 13px; line-height: 1.45; cursor: pointer; }
.profile-delete-phrase { display: grid; gap: 6px; color: var(--color-text-secondary); font-size: 12px; font-weight: 500; }
.profile-delete-phrase strong { padding: 1px 6px; border: 1px solid var(--color-border); border-radius: 4px; background: var(--color-bg-alt); color: var(--color-text); font-family: ui-monospace, SFMono-Regular, Menlo, monospace; }
.profile-delete-phrase .field { width: 100%; padding: 10px 12px; border-radius: 10px; font-size: 14px; }
[data-confirmation-state="ready"] .profile-delete-phrase .field { border-color: var(--color-error); box-shadow: 0 0 0 4px color-mix(in srgb, var(--color-error) 12%, transparent); }
.profile-delete-password .profile-field { gap: 6px; }
.profile-delete-password .profile-field-control { background: var(--color-surface); }
.profile-delete-footer { flex: 0 0 auto; padding-right: 20px; padding-left: 20px; background: #f8f8f8; }
html[data-theme="dark"] .profile-delete-footer { background: #0f172a; }
.profile-delete-footer .btn { min-width: 0; }
.profile-delete-ready-label { display: none; }
[data-confirmation-state="ready"] .profile-delete-ready-label { display: inline; }
[data-confirmation-state="ready"] .profile-delete-countdown-label { display: none; }
.dialog-actions { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; margin-top: 8px; }
.profile-avatar-partial { display: grid; gap: 12px; }
.profile-avatar-preview { display: flex; align-items: center; gap: 14px; }
/* En el editor, el preview vive FUERA del cuerpo scrolleable (banda fija entre
 * cabecera y cuerpo) para que el avatar se vea siempre al recorrer opciones.
 * Nota: sticky dentro de un .dialog-body en grid no sirve — el área de rejilla
 * limita el desplazamiento del elemento. */
.profile-avatar-preview--pinned { flex: 0 0 auto; padding: 14px 20px; border-bottom: 1px solid var(--color-border); }
.profile-avatar-preview .profile-avatar { width: 64px; height: 64px; font-size: 20px; }
.profile-avatar-preview > div { display: grid; gap: 3px; }
.profile-avatar-preview small { color: var(--color-text-secondary); }
.subscription-sections { display: grid; gap: 18px; }
.subscription-section { display: grid; gap: 10px; }
.subscription-section + .subscription-section { padding-top: 16px; border-top: 1px solid var(--color-border); }
.subscription-section h3 { display: flex; align-items: center; gap: 8px; margin: 0; font-size: 14px; }
.subscription-summary, .subscription-usage { display: grid; gap: 12px; padding: 12px; border-radius: var(--radius-lg); background: var(--color-card-nested-bg); }
.subscription-summary-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 10px; }
.subscription-summary-head > div { display: flex; align-items: center; gap: 8px; }
.subscription-summary h4, .subscription-empty h4 { margin: 0; }
.subscription-facts { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 8px; margin: 0; }
.subscription-facts div { display: grid; gap: 2px; }
.subscription-facts dt { color: var(--color-text-muted); font-size: 11px; }
.subscription-facts dd { margin: 0; font-size: 13px; font-weight: 600; }
.subscription-empty { display: grid; justify-items: center; gap: 8px; padding: 18px; color: var(--color-text-secondary); text-align: center; }
.subscription-state { display: grid; justify-items: center; gap: 8px; padding: 16px; text-align: center; }
.usage-row { display: grid; gap: 6px; }
.usage-row > div { display: flex; justify-content: space-between; gap: 12px; font-size: 13px; }
.usage-row progress { width: 100%; height: 8px; accent-color: var(--color-primary); }
.payment-list { display: grid; gap: 1px; padding: 0; margin: 0; overflow: hidden; border-radius: var(--radius-lg); list-style: none; }
.payment-list li { display: flex; align-items: center; gap: 10px; padding: 10px; background: var(--color-card-nested-bg); }
.payment-list li > span:first-child { display: grid; flex: 1; }
.payment-list small { color: var(--color-text-muted); }
.dashboard-proof { padding-bottom: 12px; }
.dashboard-hero { display: flex; align-items: center; gap: 14px; padding: 16px; }
.dashboard-avatar { display: grid; flex: 0 0 auto; place-items: center; width: 52px; height: 52px; overflow: hidden; border-radius: 50%; background: var(--color-primary-light); color: var(--color-primary-700); font-size: 18px; font-weight: 700; }
.dashboard-avatar img { display: block; width: 100%; height: 100%; }
.dashboard-hero__copy { min-width: 0; }
.dashboard-hero h1 { margin: 0; color: var(--color-text); font-size: 18px; line-height: 1.3; }
.dashboard-hero p { margin: 3px 0 0; color: var(--color-text-secondary); font-size: 13px; }
.dashboard-emergency { display: flex; align-items: center; gap: 12px; color: var(--color-text); text-decoration: none; }
.dashboard-emergency > span:nth-child(2) { display: grid; min-width: 0; flex: 1; gap: 2px; }
.dashboard-emergency strong, .dashboard-emergency small { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.dashboard-emergency small { color: var(--color-text-secondary); font-size: 12px; }
.dashboard-section { display: grid; gap: 10px; }
.dashboard-section__header { display: flex; align-items: center; justify-content: space-between; gap: 12px; min-height: 28px; padding: 0 4px; }
.dashboard-section__header h2 { display: flex; align-items: center; gap: 8px; margin: 0; color: var(--color-text); font-size: 17px; font-weight: 600; }
.dashboard-section__header h2 .ds-icon { color: var(--color-primary); }
.dashboard-section__action { display: inline-flex; align-items: center; gap: 4px; color: var(--color-primary-700); font-size: 13px; font-weight: 600; text-decoration: none; }
.dashboard-section__action--disabled { padding: 0; border: 0; background: transparent; color: var(--color-text-muted); cursor: not-allowed; }
.dashboard-section__count { color: color-mix(in srgb, var(--color-text) 35%, var(--color-text-secondary)); font-size: 12px; }
.dashboard-location-list { display: grid; gap: 10px; }
.location-panel { overflow: hidden; }
.location-panel--pending { border: 2px dashed var(--glass-border); }
.location-panel__refresh { display: none; }
.location-panel__header { display: flex; align-items: center; gap: 9px; min-height: 64px; padding: 10px 12px; }
.location-panel__header--offline { border-top: 2px solid var(--color-error); }
.location-panel__header--pending { min-height: 62px; }
.drag-handle, .device-drag-handle { display: grid; flex: 0 0 auto; place-items: center; color: var(--color-text-muted); cursor: grab; opacity: .65; }
.location-panel__toggle { display: flex; min-width: 0; flex: 1; align-items: center; gap: 10px; padding: 0; border: 0; background: transparent; color: var(--color-text); text-align: left; cursor: pointer; }
.location-panel__identity { display: grid; min-width: 0; flex: 1; gap: 1px; }
.location-panel__identity strong { overflow: hidden; font-size: 14px; letter-spacing: -.015em; text-overflow: ellipsis; white-space: nowrap; }
.location-panel__identity small { overflow: hidden; color: var(--color-text-secondary); font-size: 11px; text-overflow: ellipsis; white-space: nowrap; }
.location-arm { display: flex; flex: 0 0 auto; gap: 3px; padding: 3px; border-radius: 10px; }
.location-arm form { display: contents; }
.location-arm a, .location-arm button, .location-arm span[data-arm-mode] { margin: 0; padding: 0; border: 0; background: transparent; font: inherit; cursor: pointer; }
.location-arm span[data-arm-mode] { cursor: default; }
.location-arm a, .location-arm button, .location-arm span[data-arm-mode] { display: grid; place-items: center; width: 38px; height: 42px; border-radius: 7px; color: var(--color-text-secondary); text-decoration: none; transition: background var(--transition-fast), color var(--transition-fast), box-shadow var(--transition-fast), transform var(--transition-fast); }
/* Espejo del tratamiento ARM de _segmented.css (su selector '> button' nunca
 * casa con estos <a> de navegación); consume los tokens --arm-* de
 * tone-presets. Mantener sincronizado con el bloque ARM del recipe. */
.location-arm [data-arm-mode][aria-checked="true"] { color: var(--arm-deep); background: linear-gradient(180deg, rgba(255,255,255,0.45) 0, rgba(255,255,255,0) 48%), var(--arm-lt); transform: translateY(-0.5px); box-shadow: 0 1px 2px rgba(15,23,42,0.14), 0 2px 5px rgba(15,23,42,0.10), inset 0 0 0 1px color-mix(in srgb, var(--arm-ring) 50%, transparent); }
.location-arm [data-arm-mode="away"][aria-checked="true"] { box-shadow: 0 1px 3px rgba(15,23,42,0.14), 0 3px 10px color-mix(in srgb, var(--arm-ring) 22%, transparent), 0 0 0 2px color-mix(in srgb, var(--arm-ring) 25%, transparent), inset 0 0 0 2px color-mix(in srgb, var(--arm-ring) 67%, transparent); }
html[data-theme="dark"] .location-arm [data-arm-mode][aria-checked="true"] { background: linear-gradient(180deg, rgba(255,255,255,0.10) 0, rgba(255,255,255,0) 48%), var(--arm-lt); box-shadow: 0 1px 2px rgba(15,23,42,0.35), 0 2px 5px rgba(15,23,42,0.30), inset 0 0 0 1px color-mix(in srgb, var(--arm-ring) 33%, transparent); }
html[data-theme="dark"] .location-arm [data-arm-mode="away"][aria-checked="true"] { box-shadow: 0 1px 3px rgba(15,23,42,0.40), 0 3px 10px color-mix(in srgb, var(--arm-ring) 25%, transparent), 0 0 0 2px color-mix(in srgb, var(--arm-ring) 33%, transparent), inset 0 0 0 2px color-mix(in srgb, var(--arm-ring) 53%, transparent); }
.location-status { width: 9px; height: 9px; flex: 0 0 auto; border-radius: 50%; }
.location-status--online { background: var(--color-success); box-shadow: 0 0 0 3px color-mix(in srgb, var(--color-success) 22%, transparent); --pulse-strong: color-mix(in srgb, var(--color-success) 55%, transparent); --pulse-soft: color-mix(in srgb, var(--color-success) 22%, transparent); animation: connPulse 1.8s ease-out infinite; }
.location-status--offline { background: var(--color-error); box-shadow: 0 0 0 3px color-mix(in srgb, var(--color-error) 22%, transparent); }
.location-panel__body { padding: 14px; border-top: 1px solid var(--color-border); }
.location-pending { display: grid; justify-items: center; gap: 8px; padding: 18px 16px; margin: 0 14px 14px; border: 1px solid var(--color-card-nested-border); border-radius: 12px; background: var(--color-card-nested-bg); text-align: center; }
.location-pending__icon { display: grid; place-items: center; width: 40px; height: 40px; border-radius: 12px; background: var(--color-error-light); color: var(--color-error); }
.location-pending > strong { color: var(--color-error-700); font-size: 17px; }
.location-pending p { max-width: 290px; margin: 0 0 6px; color: var(--color-text-secondary); font-size: 13px; line-height: 1.45; }
.location-toolbar { display: flex; align-items: center; justify-content: space-between; gap: 10px; padding-bottom: 10px; margin-bottom: 10px; border-bottom: 1px solid var(--color-border); }
/* Sin lista de dispositivos debajo (0 sensores): la toolbar cierra el panel sin separador ni hueco. */
.location-toolbar:last-child { padding-bottom: 0; margin-bottom: 0; border-bottom: 0; }
/* Un solo grupo de acciones (p.ej. solo históricos): centrado en la fila. */
.location-toolbar--solo { justify-content: center; }
.location-toolbar__primary, .location-toolbar__secondary { display: flex; align-items: center; gap: 5px; flex-wrap: wrap; }
.location-toolbar a, .location-toolbar button { display: inline-flex; align-items: center; gap: 4px; min-height: 32px; padding: 5px 7px; border: 0; border-radius: 8px; background: transparent; color: var(--color-primary); font-size: 12px; font-weight: 600; text-decoration: none; cursor: pointer; }
.location-toolbar__secondary a, .location-toolbar__secondary button { color: var(--color-text-secondary); }
.location-devices { display: grid; gap: 8px; }
.location-empty, .dashboard-collection-empty, .dashboard-region-state { display: grid; justify-items: center; gap: 8px; padding: 20px; color: color-mix(in srgb, var(--color-text) 35%, var(--color-text-secondary)); text-align: center; }
.location-empty strong, .dashboard-collection-empty strong { color: var(--color-text); font-size: 14px; }
.location-empty p, .dashboard-collection-empty p, .dashboard-region-state p { margin: 0; color: color-mix(in srgb, var(--color-text) 35%, var(--color-text-secondary)); font-size: 12px; line-height: 1.45; }
.dashboard-region-state { border: 1px solid var(--color-border); border-radius: var(--radius-lg); background: var(--color-card-nested-bg); }
.dashboard-region-state--offline .dashboard-region-state__icon, .dashboard-region-state--error .dashboard-region-state__icon { color: var(--color-error); }
.location-modal > .dialog { width: min(100%, 430px); margin: 0 auto; }
.location-form { display: flex; flex-direction: column; max-height: calc(100dvh - 48px); }
.location-form__body { display: grid; gap: 13px; overflow-y: auto; min-height: 0; flex: 1 1 auto; }
.location-form__field { display: grid; gap: 6px; color: var(--color-text-secondary); font-size: 12px; font-weight: 600; }
.location-form__field .field { width: 100%; }
.location-form__picker { padding: 0; margin: 0; border: 0; }
.location-form__picker legend { margin-bottom: 8px; color: var(--color-text-secondary); font-size: 12px; font-weight: 600; }
.location-form__preview { display: flex; align-items: center; gap: 12px; padding: 12px; border-radius: 12px; margin-bottom: 10px; background: #fff; border: 1px solid var(--color-card-nested-border); }
html[data-theme="dark"] .location-form__preview { background: #1e293b; }
.location-form__preview > span:last-child { display: grid; min-width: 0; }
.location-form__preview strong { overflow: hidden; color: var(--color-text); font-size: 13px; font-weight: 600; text-overflow: ellipsis; white-space: nowrap; }
.location-form__preview small { color: var(--color-text-secondary); font-size: 11px; }
/* Filas del kit: colores 1×7 e iconos 2×5, repartidos a los bordes con ancho máx 280 centrado. */
.location-form__choices { display: grid; align-items: center; justify-content: space-between; row-gap: 8px; margin: 0 auto; max-width: 280px; }
/* 14px: el anillo de selección sobresale 4px por lado, así que con los 4px
 * previos la fila de colores y la de iconos parecían tocarse. */
.location-form__choices--colors { grid-template-columns: repeat(7, auto); margin-bottom: 14px; }
.location-form__choices--icons { grid-template-columns: repeat(5, auto); }
.location-form__choice { display: grid; padding: 0; border: 0; border-radius: 12px; cursor: pointer; opacity: .7; transform: scale(.92); transition: opacity .15s ease, transform .15s ease; }
.location-form__choice:has(input:checked) { opacity: 1; transform: scale(1); }
/* Ring de selección del kit: 2px de hueco (fondo del panel) + 4px de color. Iconos → primary. */
.location-form__choice:has(input:checked) .location-tile,
.location-form__choice--color:has(input:checked) .location-color { box-shadow: 0 0 0 2px #f8f8f8, 0 0 0 4px var(--color-primary); }
html[data-theme="dark"] .location-form__choice:has(input:checked) .location-tile,
html[data-theme="dark"] .location-form__choice--color:has(input:checked) .location-color { box-shadow: 0 0 0 2px #0f172a, 0 0 0 4px var(--color-primary); }
/* Swatches de color: el ring toma el propio color saturado. */
.location-form__choice--color:has(input:checked) .location-tile--blue { box-shadow: 0 0 0 2px #f8f8f8, 0 0 0 4px #3b82f6; }
.location-form__choice--color:has(input:checked) .location-tile--green { box-shadow: 0 0 0 2px #f8f8f8, 0 0 0 4px #22c55e; }
.location-form__choice--color:has(input:checked) .location-tile--amber { box-shadow: 0 0 0 2px #f8f8f8, 0 0 0 4px #f59e0b; }
.location-form__choice--color:has(input:checked) .location-tile--pink { box-shadow: 0 0 0 2px #f8f8f8, 0 0 0 4px #ec4899; }
.location-form__choice--color:has(input:checked) .location-tile--indigo { box-shadow: 0 0 0 2px #f8f8f8, 0 0 0 4px #6366f1; }
.location-form__choice--color:has(input:checked) .location-tile--teal { box-shadow: 0 0 0 2px #f8f8f8, 0 0 0 4px #14b8a6; }
.location-form__choice--color:has(input:checked) .location-tile--red { box-shadow: 0 0 0 2px #f8f8f8, 0 0 0 4px #ef4444; }
html[data-theme="dark"] .location-form__choice--color:has(input:checked) .location-tile--blue { box-shadow: 0 0 0 2px #0f172a, 0 0 0 4px #3b82f6; }
html[data-theme="dark"] .location-form__choice--color:has(input:checked) .location-tile--green { box-shadow: 0 0 0 2px #0f172a, 0 0 0 4px #22c55e; }
html[data-theme="dark"] .location-form__choice--color:has(input:checked) .location-tile--amber { box-shadow: 0 0 0 2px #0f172a, 0 0 0 4px #f59e0b; }
html[data-theme="dark"] .location-form__choice--color:has(input:checked) .location-tile--pink { box-shadow: 0 0 0 2px #0f172a, 0 0 0 4px #ec4899; }
html[data-theme="dark"] .location-form__choice--color:has(input:checked) .location-tile--indigo { box-shadow: 0 0 0 2px #0f172a, 0 0 0 4px #6366f1; }
html[data-theme="dark"] .location-form__choice--color:has(input:checked) .location-tile--teal { box-shadow: 0 0 0 2px #0f172a, 0 0 0 4px #14b8a6; }
html[data-theme="dark"] .location-form__choice--color:has(input:checked) .location-tile--red { box-shadow: 0 0 0 2px #0f172a, 0 0 0 4px #ef4444; }
.avatar-form__grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: 10px; }
.avatar-form__choice { display: grid; justify-items: center; gap: 4px; padding: 4px; border: 2px solid transparent; border-radius: 10px; cursor: pointer; font-size: 10px; color: var(--color-text-secondary); text-align: center; }
.avatar-form__choice:has(input:checked) { border-color: var(--color-primary); color: var(--color-primary-700); font-weight: 600; }
/* El picker de ESTILO muestra solo el personaje: ni fondo ni borde (esos los
 * eligen sus propios pickers y ya se ven en el preview fijo de arriba). */
.avatar-form__choice .avatar-tile { background: transparent; border-color: transparent; box-shadow: none; color: var(--color-text-secondary); }
.avatar-form__swatches { display: flex; gap: 12px; flex-wrap: wrap; }
.avatar-form__swatch-choice { display: inline-grid; padding: 3px; border-radius: 50%; cursor: pointer; }
.avatar-form__swatch-choice:has(input:checked) > .avatar-swatch { outline: 2.5px solid var(--color-primary); outline-offset: 2px; }
.avatar-swatch { display: grid; place-items: center; width: 38px; height: 38px; border: 1px solid var(--color-border); border-radius: 50%; }
.avatar-swatch--none { position: relative; overflow: hidden; }
.avatar-swatch--none::after { content: ""; width: 24px; height: 2px; border-radius: 1px; background: var(--color-error); transform: rotate(-45deg); }
.location-color { display: block; width: 36px; height: 36px; border-radius: 10px; }
.location-form__section { margin: 5px 0 0; }
.location-form__grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 12px; }
@media (max-width: 440px) { .location-form__grid { grid-template-columns: 1fr; } }
@media (max-width: 520px) { .location-panel__header { gap: 7px; padding: 9px 10px; } }
.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; }
/* NORMA: toda etiqueta-opción que esconda su input con .sr-only debe ser el
 * bloque contenedor de ese input (position: relative). Sin esto el input
 * absoluto se ancla al overlay del modal, y al pulsar la opción el navegador
 * hace scroll hasta ese punto fantasma — parecía una «redirección» del modal. */
:is(.avatar-form__choice, .avatar-form__swatch-choice, .location-form__choice, .location-form__choice--color) { position: relative; }
@media (min-width: 800px) { .presentation-main { padding-top: 28px; } .presentation-bottom-nav { left: 50%; width: 720px; transform: translateX(-50%); border: 1px solid var(--color-border); border-bottom: 0; border-radius: 18px 18px 0 0; } }
@media (prefers-reduced-motion: reduce) { *, *::before, *::after { scroll-behavior: auto !important; animation-duration: .01ms !important; animation-iteration-count: 1 !important; transition-duration: .01ms !important; } }

/* generated icon tones */

.ds-icon--tone-danger { color: var(--color-error); }
.ds-icon--tone-muted { color: var(--color-text-muted); }
.ds-icon--tone-primary { color: var(--color-primary); }
.ds-icon--tone-secondary { color: var(--color-text-secondary); }
.ds-icon--tone-success { color: var(--color-success); }
.ds-icon--tone-warning { color: var(--color-warning); }


/* generated persona-avatar palette */

.profile-avatar--bg-blue { background: #dbeafe; }
html[data-theme="dark"] .profile-avatar--bg-blue { background: #1e3a8a; }
.profile-avatar--bg-green { background: #dcfce7; }
html[data-theme="dark"] .profile-avatar--bg-green { background: #14532d; }
.profile-avatar--bg-amber { background: #fef3c7; }
html[data-theme="dark"] .profile-avatar--bg-amber { background: #78350f; }
.profile-avatar--bg-pink { background: #fce7f3; }
html[data-theme="dark"] .profile-avatar--bg-pink { background: #831843; }
.profile-avatar--bg-indigo { background: #e0e7ff; }
html[data-theme="dark"] .profile-avatar--bg-indigo { background: #312e81; }
.profile-avatar--bg-teal { background: #ccfbf1; }
html[data-theme="dark"] .profile-avatar--bg-teal { background: #134e4a; }
.profile-avatar--bg-red { background: #fee2e2; }
html[data-theme="dark"] .profile-avatar--bg-red { background: #7f1d1d; }
.profile-avatar--border-none { box-shadow: none; }
.profile-avatar--border-blue { box-shadow: 0 0 0 4px #3b82f6; }
.profile-avatar--border-green { box-shadow: 0 0 0 4px #22c55e; }
.profile-avatar--border-amber { box-shadow: 0 0 0 4px #f59e0b; }
.profile-avatar--border-pink { box-shadow: 0 0 0 4px #ec4899; }
.profile-avatar--border-purple { box-shadow: 0 0 0 4px #8b5cf6; }
.profile-avatar--border-red { box-shadow: 0 0 0 4px #ef4444; }
.avatar-tile { display: inline-flex; flex: 0 0 auto; align-items: center; justify-content: center; overflow: hidden; box-sizing: border-box; border-radius: 50%; font-weight: 700; }
.avatar-tile > img { display: block; width: 100%; height: 100%; }
.avatar-tile--20 { width: 20px; height: 20px; font-size: 7px; }
.avatar-tile--40 { width: 40px; height: 40px; font-size: 14px; }
.avatar-tile--56 { width: 56px; height: 56px; font-size: 19px; }
.avatar-tile--64 { width: 64px; height: 64px; font-size: 22px; }
.avatar-tile--80 { width: 80px; height: 80px; font-size: 27px; }
.avatar-tile--fg-0 { color: #1d4ed8; }
html[data-theme="dark"] .avatar-tile--fg-0 { color: #fff; }
.avatar-tile--fg-1 { color: #166534; }
html[data-theme="dark"] .avatar-tile--fg-1 { color: #fff; }
.avatar-tile--fg-2 { color: #92400e; }
html[data-theme="dark"] .avatar-tile--fg-2 { color: #fff; }
.avatar-tile--fg-3 { color: #3730a3; }
html[data-theme="dark"] .avatar-tile--fg-3 { color: #fff; }
.avatar-tile--fg-4 { color: #9d174d; }
html[data-theme="dark"] .avatar-tile--fg-4 { color: #fff; }
.avatar-tile--fg-5 { color: #0f766e; }
html[data-theme="dark"] .avatar-tile--fg-5 { color: #fff; }
.avatar-tile--fg-6 { color: #991b1b; }
html[data-theme="dark"] .avatar-tile--fg-6 { color: #fff; }

/* package: Alarmas/src/web/app/presentation/assets/packages/auth-system.css */

/* AUTH-SYSTEM presentation source. The aggregate asset pipeline owns publication. */

.auth-system-body {
  min-height: 100dvh;
  overflow-x: hidden;
}

.auth-system-shell {
  min-height: 100dvh;
  display: flex;
  flex-direction: column;
}

.auth-system-topbar {
  position: sticky;
  top: 0;
  z-index: var(--z-sticky);
  display: grid;
  grid-template-columns: 40px 1fr 40px;
  align-items: center;
  min-height: 56px;
  padding: var(--safe-top) max(12px, var(--safe-right)) 0 max(12px, var(--safe-left));
  background: var(--color-primary);
  color: #fff;
}

html[data-theme="dark"] .auth-system-topbar {
  background: var(--color-primary-300);
}

.auth-system-topbar__spacer {
  width: 40px;
  height: 40px;
}

.auth-system-topbar__title {
  overflow: hidden;
  font-size: 16px;
  font-weight: 600;
  text-align: center;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.auth-system-topbar__title > span { color: #0f172a; }
html[data-theme="dark"] .auth-system-topbar__title > span { color: #fff; }

/* Selector de idioma del login/registro — preset del kit (LangSelector,
 * screens.jsx): botón circular con banderita + desplegable con banderas,
 * divisor Europa/América y check en el activo. @kind other */
.flag { display: inline-flex; flex-shrink: 0; overflow: hidden; border-radius: 3px; box-shadow: 0 0 0 1px rgba(0, 0, 0, .12); }
.flag--circ { border-radius: 50%; }
.flag > img { display: block; width: 100%; height: 100%; object-fit: fill; }
.auth-lang { position: relative; flex-shrink: 0; }
.auth-lang__btn { display: inline-flex; align-items: center; justify-content: center; width: 36px; height: 36px; padding: 0; border: 1.5px solid rgba(255, 255, 255, .55); border-radius: 50%; background: transparent; cursor: pointer; }
.auth-lang__menu { position: absolute; top: calc(100% + 8px); right: 0; z-index: var(--z-modal); min-width: 200px; max-height: min(360px, calc(100dvh - 120px)); overflow-y: auto; padding: 6px; border: 1px solid var(--color-border); border-radius: 12px; background: #fff; box-shadow: 0 16px 40px -10px rgba(2, 6, 23, .45); }
[data-theme="dark"] .auth-lang__menu { background: #1e293b; }
.auth-lang__item { display: flex; align-items: center; gap: 10px; width: 100%; padding: 9px 10px; border: 0; border-radius: 8px; background: transparent; color: var(--color-text); font-family: inherit; font-size: 14px; font-weight: 500; text-align: left; cursor: pointer; }
.auth-lang__label { flex: 1; min-width: 0; }
.auth-lang__item .flag, .auth-lang__item .ds-icon { flex: 0 0 auto; }
.auth-lang__item.is-active { background: var(--color-primary-100); font-weight: 600; }
[data-theme="dark"] .auth-lang__item.is-active { background: rgba(59, 130, 246, .18); }
.auth-lang__divider { height: 1px; margin: 5px 8px; background: var(--color-border); }

.auth-system-main {
  min-height: 0;
  flex: 1;
}

.auth-stage {
  position: relative;
  min-height: calc(100dvh - 56px - var(--safe-top));
  display: grid;
  place-items: center;
  padding: 24px max(16px, var(--safe-right)) max(24px, calc(var(--safe-bottom) + var(--safe-gap))) max(16px, var(--safe-left));
  overflow: hidden;
}

.auth-stage--login {
  background: #020617;
}

.auth-stage--form {
  background:
    radial-gradient(circle at 50% 18%, color-mix(in srgb, var(--color-primary) 10%, transparent), transparent 52%),
    var(--color-bg);
}

.auth-login-backdrop {
  position: absolute;
  inset: 0;
  overflow: hidden;
  background:
    radial-gradient(circle at 12% 22%, rgba(147, 197, 253, .75) 0 2px, transparent 3px),
    radial-gradient(circle at 72% 18%, rgba(96, 165, 250, .7) 0 2px, transparent 3px),
    radial-gradient(circle at 84% 68%, rgba(147, 197, 253, .65) 0 2px, transparent 3px),
    radial-gradient(circle at 28% 78%, rgba(96, 165, 250, .6) 0 2px, transparent 3px),
    radial-gradient(ellipse at 50% 30%, #1e3a8a 0%, #0f172a 55%, #020617 100%);
}

.auth-login-backdrop::before,
.auth-login-backdrop::after {
  position: absolute;
  inset: -30%;
  border-radius: 50%;
  content: "";
}

.auth-login-backdrop::before {
  border: 1px solid rgba(147, 197, 253, .22);
  animation: auth-radar 9s linear infinite;
}

.auth-login-backdrop::after {
  background: conic-gradient(from 0deg, transparent 0 290deg, rgba(96, 165, 250, .18) 345deg, transparent 360deg);
  animation: auth-radar 12s linear infinite reverse;
}

.auth-signal {
  position: absolute;
  left: 50%;
  top: 34%;
  width: 130px;
  height: 130px;
  margin: -65px;
  border: 1px solid rgba(147, 197, 253, .6);
  border-radius: 50%;
  animation: auth-pulse 4.8s ease-out infinite;
}

.auth-signal--two { animation-delay: -1.6s; }
.auth-signal--three { animation-delay: -3.2s; }

.auth-card {
  position: relative;
  z-index: 1;
  width: min(100%, 360px);
  padding: 24px;
}

.auth-card--login {
  border-radius: 20px;
  box-shadow: 0 24px 48px -12px rgba(2, 6, 23, .55), 0 0 0 1px rgba(148, 163, 184, .15); /* kit: .55 claro */
}
html[data-theme="dark"] .auth-card--login {
  box-shadow: 0 24px 48px -12px rgba(2, 6, 23, .85), 0 0 0 1px rgba(148, 163, 184, .15); /* kit: .85 oscuro */
}

.auth-card--register {
  width: min(100%, 400px);
}

.auth-card--update {
  width: min(100%, 340px);
}

.auth-card__header {
  margin-bottom: 18px;
  text-align: center;
}

.auth-card__icon,
.auth-brand-mark,
.auth-state-icon {
  margin: 0 auto 12px;
}

.auth-brand-mark {
  display: grid;
  place-items: center;
  width: 60px;
  height: 60px;
  border-radius: var(--radius-xl);
  background: var(--color-primary);
  color: #fff;
  box-shadow: 0 8px 24px -6px rgba(59, 130, 246, .55);
}

/* Con el app-icon de marca dentro, la placa la aporta el propio SVG. */
.auth-brand-mark--brand { background: none; box-shadow: 0 8px 24px -6px rgba(59, 130, 246, .45); }
.auth-brand-mark--brand .brand-mark { width: 100%; height: 100%; }

.auth-card__title {
  margin: 0;
  color: var(--color-text);
  font-size: 22px;
  font-weight: 700;
  line-height: 1.25;
}

.auth-card__subtitle {
  margin: 4px 0 0;
  color: var(--color-text-secondary);
  font-size: 13px;
  line-height: 1.5;
}

.auth-card__body {
  display: grid;
  gap: 14px;
}

.auth-card__footer {
  display: flex;
  justify-content: center;
  gap: 5px;
  padding-top: 14px;
  margin-top: 18px;
  border-top: 1px solid var(--color-border);
  color: var(--color-text-secondary);
  font-size: 13px;
  text-align: center;
}

.auth-form,
.auth-field-group {
  display: grid;
  gap: 12px;
}

.auth-field-group {
  gap: 6px;
}

/* Recuperar contraseña: separa el bloque de email del aviso y pega la etiqueta
 * a su campo. */
[data-auth-recovery-form] .auth-field-group { margin-top: 14px; gap: 4px; }

.auth-form__between {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  font-size: 12px;
}

.auth-check {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  color: var(--color-text-secondary);
  font-size: 13px;
  line-height: 1.45;
  cursor: pointer;
}

.auth-check--legal {
  align-items: flex-start;
}

.auth-check--legal .tick {
  margin-top: 2px;
}

.auth-link {
  color: var(--color-primary);
  font-size: 13px;
  text-decoration: none;
}

.auth-link:hover { text-decoration: underline; }
.auth-link--strong { font-weight: 600; }

.auth-link--back {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  color: var(--color-text-secondary);
}

.auth-password-field {
  position: relative;
  display: flex;
  align-items: center;
}

.auth-password-field .field {
  width: 100%;
  padding-right: 44px;
}

.auth-password-toggle {
  position: absolute;
  right: 4px;
  display: grid;
  place-items: center;
  width: 36px;
  height: 36px;
  padding: 0;
  border: 0;
  border-radius: 8px;
  background: transparent;
  color: var(--color-text-muted);
  cursor: pointer;
}

.auth-password-toggle:hover,
.auth-password-toggle:focus-visible {
  background: var(--color-bg-alt);
  color: var(--color-text);
}

.auth-password-meter {
  margin-top: 2px;
}

.auth-field-hint,
.auth-info-box {
  display: flex;
  align-items: center;
  gap: 7px;
}

.auth-info-box {
  padding: 12px;
  border: 1px solid var(--color-border);
  border-radius: 12px;
  background: var(--color-bg-alt);
  color: var(--color-text-secondary);
  font-size: 13px;
  line-height: 1.45;
}

.auth-field-hint .ds-icon {
  margin-top: 2px;
  flex: 0 0 auto;
}

.auth-result {
  align-items: flex-start;
}

.auth-dialog-scrim {
  position: fixed;
  inset: 0;
  z-index: var(--z-modal);
  display: grid;
  place-items: center;
  padding: max(20px, calc(var(--safe-top) + var(--safe-gap))) max(16px, var(--safe-right)) max(20px, calc(var(--safe-bottom) + var(--safe-gap))) max(16px, var(--safe-left));
  overflow-y: auto;
}

.auth-dialog {
  width: min(100%, 400px);
  max-height: calc(100dvh - 40px);
  display: flex;
  flex-direction: column;
}

.auth-dialog--compact {
  width: min(100%, 380px);
}

.auth-dialog .dialog-body {
  min-height: 0;
  overflow-y: auto;
}

.auth-dialog[data-auth-resource="/auth/register"] {
  width: min(100%, 370px);
  max-height: calc(100dvh - 182px);
  box-sizing: border-box;
}

.auth-dialog[data-auth-resource="/auth/register"] .dialog-title {
  margin: 0;
  line-height: 1.4;
}

.auth-dialog[data-auth-resource="/auth/register"] .dialog-sub {
  margin: 3px 0 0;
  line-height: 1.4;
}

.auth-dialog[data-auth-resource="/auth/register"] .dialog-body {
  padding: 16px;
}

.auth-dialog[data-auth-resource="/auth/register"] .dialog-foot {
  padding: 12px 16px;
}

.auth-dialog[data-auth-resource="/auth/register"] .auth-field-group {
  gap: 0;
}

.auth-dialog[data-auth-resource="/auth/register"] .field-label {
  color: var(--color-text-secondary);
  font-size: 12px;
  font-weight: 600;
  letter-spacing: .02em;
  line-height: 1.5;
  text-transform: uppercase;
}

.auth-dialog[data-auth-resource="/auth/register"] .field {
  line-height: normal;
}

.auth-dialog[data-auth-resource="/auth/register"] .field-hint {
  margin-top: 6px;
  font-size: 11.5px;
  line-height: 1.4;
}

.auth-dialog[data-auth-resource="/auth/register"] .auth-password-meter {
  margin-top: 6px;
}

.auth-dialog[data-auth-resource="/auth/register"] .pwd-reqs {
  gap: 2px;
  margin-top: 0;
}

.auth-dialog[data-auth-resource="/auth/register"] .pwd-req {
  font-size: 11px;
  line-height: 1.5;
}

.auth-dialog[data-auth-resource="/auth/register"] .pwd-req-mark {
  width: 12px;
  height: 12px;
}

.auth-dialog[data-auth-resource="/auth/register"] [data-auth-register-optional-note] {
  margin: 0;
}

.auth-dialog[data-auth-resource="/auth/register"] [data-auth-register-optional],
.auth-dialog[data-auth-resource="/auth/register"] [data-auth-register-login-link] {
  margin: 0;
  color: var(--color-text-secondary);
  font-size: 13px;
  line-height: 1.5;
}

.auth-dialog[data-auth-resource="/auth/register"] [data-auth-register-login-link] {
  text-align: center;
}

.auth-dialog[data-auth-resource="/auth/register"] #register-result:empty {
  display: none;
}

.auth-created-state {
  display: grid;
  justify-items: center;
  gap: 12px;
  color: var(--color-text-secondary);
  font-size: 14px;
  line-height: 1.5;
  text-align: center;
}

.auth-created-state p {
  margin: 0;
}

/* El bloque de resultado recibe foco programático (tabindex=-1) para que los
 * lectores anuncien el mensaje; el anuncio ya lo hace role="status" +
 * aria-live, así que nunca se dibuja anillo (el usuario ve un recuadro raro
 * al enviar). */
.auth-forgot-result:focus,
.auth-forgot-result:focus-visible { outline: none; }

.auth-dialog-foot--submitted .auth-btn {
  flex: 1;
}

.auth-store-actions {
  width: 100%;
  display: grid;
  gap: 10px;
}

.auth-version-meta,
.auth-support-copy {
  margin: 2px 0 0;
  color: var(--color-text-secondary);
  font-size: 12px;
}

.public-home {
  position: relative;
  min-height: calc(100dvh - 130px);
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  padding: 32px 16px;
  text-align: center;
}

.public-home__glow {
  position: absolute;
  inset: 0;
  background: radial-gradient(circle at 50% 24%, color-mix(in srgb, var(--color-primary) 12%, transparent), transparent 60%);
}

.public-home__hero,
.public-home__features {
  position: relative;
  width: min(100%, 340px);
}

.public-home__hero h1 {
  margin: 0 0 14px;
  color: var(--color-text);
  font-size: 32px;
  font-weight: 700;
  letter-spacing: -.02em;
  line-height: 1.15;
}

.public-home__hero > p {
  margin: 0 0 22px;
  color: var(--color-text-secondary);
  font-size: 16px;
  line-height: 1.5;
}

.public-home__features {
  display: grid;
  gap: 12px;
  margin-top: 40px;
}

.public-feature {
  padding: 20px;
  text-align: center;
}

.public-feature .icon-tile { margin: 0 auto 10px; }

.public-feature h2 {
  margin: 0 0 6px;
  color: var(--color-text);
  font-size: 16px;
  font-weight: 600;
}

.public-feature p {
  margin: 0;
  color: var(--color-text-secondary);
  font-size: 13px;
  line-height: 1.5;
}

.platform-error-card {
  width: min(100%, 380px);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 10px;
  padding: 28px 20px;
  text-align: center;
}

.platform-error-card p {
  max-width: 280px;
  margin: 0 0 4px;
  color: var(--color-text-secondary);
  font-size: 13px;
  line-height: 1.5;
}

.platform-error-card form { margin: 0; }

.auth-shell-utilities {
  display: grid;
  gap: 18px;
}

.auth-connection-states {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
}

.auth-connection-states .chip {
  background: var(--st-bg);
  color: var(--st-fg);
}

.auth-connection-states .chip-dot { background: var(--st-dot); }

.auth-push-control {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 12px 14px;
}

.auth-push-control__copy {
  min-width: 0;
  display: grid;
  flex: 1;
  gap: 2px;
}

.auth-push-control__copy strong { font-size: 14px; }
.auth-push-control__copy small { color: var(--color-text-muted); font-size: 12px; }

.auth-pagination {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  color: var(--color-text-secondary);
  font-size: 12px;
}

.auth-toast-stack {
  display: grid;
  gap: 10px;
}
/* El toast es una fila flex; sin acotarla, un texto sin espacios (una URL) empuja
 * la línea más allá de la pila y se sale de pantalla. Se acota al ancho de la
 * pila, el texto puede partir por cualquier punto y se trunca a 3 líneas. */
.auth-toast { max-width: 100%; box-sizing: border-box; }
.auth-toast > span:not([class]) { display: -webkit-box; min-width: 0; overflow: hidden; overflow-wrap: anywhere; -webkit-box-orient: vertical; -webkit-line-clamp: 3; }

/* Pila de toasts — CENTRADA horizontalmente, como en el kit (los toasts del kit
 * usan left:50% + translateX(-50%) o left/right:16). Antes iba anclada a la
 * derecha, así que en móvil quedaba descentrada (340px con 16px a la derecha y
 * 34px a la izquierda). Afecta a TODAS las superficies: el mismo preset lo usan
 * el shell de app, el shell público y las páginas de auth. */
.presentation-toast-stack {
  position: fixed;
  top: max(16px, calc(var(--safe-top) + var(--safe-gap)));
  left: 50%;
  transform: translateX(-50%);
  z-index: var(--z-toast);
  width: min(340px, calc(100vw - 32px));
}

.auth-toast {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 12px 14px;
  border-radius: 14px;
}

.auth-toast > span:nth-child(2) {
  min-width: 0;
  flex: 1;
  color: var(--color-text);
  font-size: 13px;
  font-weight: 500;
}

.auth-shell-proof {
  display: grid;
  gap: 18px;
}

.auth-shell-proof__topbar {
  position: relative;
  border-radius: var(--radius-md);
}

.auth-shell-proof__nav {
  display: flex;
  overflow: hidden;
  border-radius: 0;
  box-shadow: none;
}

.auth-shell-proof__nav-item {
  min-width: 0;
  display: flex;
  align-items: center;
  flex: 1;
  flex-direction: column;
  gap: 3px;
  padding: 8px 2px 10px;
  color: var(--color-text-secondary);
  font-size: 10px;
  font-weight: 500;
  text-decoration: none;
}

.auth-shell-proof__nav-item[aria-current="page"] {
  color: var(--color-primary);
  font-weight: 600;
}

@keyframes auth-radar {
  to { transform: rotate(360deg); }
}

@keyframes auth-pulse {
  0% { opacity: .85; transform: scale(.2); }
  100% { opacity: 0; transform: scale(3.2); }
}

@media (min-width: 720px) {
  .public-home__features {
    width: min(100%, 720px);
    grid-template-columns: repeat(3, minmax(0, 1fr));
  }
}

@media (prefers-reduced-motion: reduce) {
  .auth-login-backdrop::before,
  .auth-login-backdrop::after,
  .auth-signal {
    animation: none;
  }
}

/* Kit auth state plates are circles (html_export/pages/verify_email.html, register.html). */
.auth-state-icon--round { border-radius: 50%; }


/* package: Alarmas/src/web/app/presentation/assets/packages/automations.css */

/* AUTOMATIONS presentation source. The aggregate asset pipeline owns publication. */

.automations-page,
.automations-list {
  display: grid;
  gap: 12px;
}

.automations-hero {
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 14px;
}

.automations-hero h1,
.automations-hero p {
  margin: 0;
}

.automations-hero h1 {
  font-size: clamp(1.35rem, 4vw, 1.75rem);
  letter-spacing: -.025em;
}

.automations-hero p {
  margin-top: 3px;
  color: var(--color-text-secondary);
  font-size: .82rem;
}

.automations-shared {
  overflow: hidden;
}

.automations-shared > .disclosure {
  padding: 12px 14px;
}

.automations-list--shared {
  padding: 0 12px 12px;
}

.automations-empty,
.automation-state {
  display: grid;
  min-height: 132px;
  place-items: center;
  align-content: center;
  gap: 8px;
  padding: 22px;
  color: var(--color-text-secondary);
  text-align: center;
}

.automations-empty--compact {
  min-height: 88px;
  padding: 14px;
}

.automations-empty h2,
.automations-empty p,
.automation-state p {
  margin: 0;
}

.automations-empty h2 {
  color: var(--color-text);
  font-size: 1rem;
}

.automation-card {
  position: relative;
  overflow: hidden;
  border: 1px solid var(--color-border);
  border-radius: 12px;              /* paridad kit trigger card */
  background: #fff;                 /* kit: blanco sólido en claro */
  padding: 12px;
  /* sombra: la aporta .elev-pop (la card ya lleva la clase) */
}
html[data-theme="dark"] .automation-card { background: var(--color-surface); }

.automation-card--inactive {
  background: var(--color-card-inactive-bg);
}

/* Kit TriggerCard (dark): inactiva = recesada BAJO el shell (#0a1020, más oscura
 * que el fondo #0f172a) con borde slate-800, sin atenuación por opacity. */
html[data-theme="dark"] .automation-card--inactive {
  opacity: 1;
  background: #0a1020;
  border-color: #1e293b;
}

.automation-card__head {
  position: relative;
  display: flex;
  min-height: 36px;
  align-items: center;
  justify-content: center;
}

.automation-card__handle {
  position: absolute;
  left: 0;
  padding: 8px 3px;
  color: var(--color-text-muted);
  font-size: 12px;
  letter-spacing: -2px;
  cursor: grab;
}

.automation-card__title {
  display: grid;
  width: min(60%, 320px);
  min-width: 0;
  gap: 2px;
  padding: 5px;
  border: 0;
  background: transparent;
  color: var(--color-text);
  font: inherit;
  font-size: .94rem;
  font-weight: 700;
  text-align: center;
  cursor: pointer;
}

.automation-card__title > span,
.automation-card__title > small {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.automation-card__title > small {
  color: var(--color-text-secondary);
  font-size: .68rem;
  font-weight: 500;
}

.automation-card__state {
  position: absolute;
  right: 0;
  display: flex;
  align-items: center;
}

.automation-card__error {
  margin: 6px 0 0;
  color: var(--color-error);
  font-size: .72rem;
}

.automation-card__details {
  margin-top: 12px;
}

.automation-card__schedule {
  display: flex;
  justify-content: center;
  padding: 0 0 10px;
}

/* Chip de programación — SCHEDULE_PRESET del kit (amber): bg/borde translúcidos,
 * texto #b45309 y valor reforzado #92400e (claro) / fbbf24-fde047 (oscuro). */
.automation-schedule-chip {
  padding: 3px 12px;
  border-color: rgb(180 83 9 / 50%);
  background: rgb(245 158 11 / 20%);
  color: #b45309;
}

.automation-schedule-chip strong { color: #92400e; }

html[data-theme="dark"] .automation-schedule-chip {
  border-color: rgb(245 158 11 / 40%);
  background: rgb(245 158 11 / 15%);
  color: #fbbf24;
}

html[data-theme="dark"] .automation-schedule-chip strong { color: #fde047; }

.automation-card__flow {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 8px;
  padding: 0;
}

/* Etiquetas CONDICIONES/ACCIONES — kit TriggerCard: 10px/500, centradas,
 * tracking .08em, azul info / verde success (los tonos *-text quedan para
 * el texto pequeño de cada pill). */
.automation-card__flow .eyebrow {
  display: block;
  margin: 0 0 4px;
  font-size: 10px;
  font-weight: 500;
  letter-spacing: .08em;
  text-align: center;
}

.automation-card__flow .eyebrow--cond { color: var(--color-info); }

.automation-card__flow .eyebrow--act { color: var(--color-success); }

.automation-card__flow > section {
  min-width: 0;
}

.automation-card__events {
  display: grid;
  gap: 4px;
  margin-top: 0;
}

.automation-card__events > p {
  margin: 0;
  color: var(--color-text-muted);
  font-size: .7rem;
}

.automation-event {
  display: grid;
  gap: 2px;
  padding: 6px 8px;
  border: 1px solid var(--color-card-nested-border);
  border-radius: 6px;
  background: var(--color-card-nested-bg);
  text-align: center;
}

/* Tintes translúcidos del kit (literales en ambos temas, como screens.jsx) */
.automation-card__events--conditions .automation-event {
  border-color: rgb(59 130 246 / 30%);
  background: rgb(59 130 246 / 15%);
}

.automation-card__events--actions .automation-event {
  border-color: rgb(34 197 94 / 30%);
  background: rgb(34 197 94 / 15%);
}

.automation-event strong,
.automation-event small {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.automation-event strong {
  color: var(--color-text);
  font-size: 13px;
  font-weight: 600;
}

.automation-event small {
  color: var(--color-text-secondary);
  font-size: 10px;
}

.automation-card__events--conditions .automation-event small { color: var(--color-primary-600); }

.automation-card__events--actions .automation-event small { color: var(--color-action-text); }

.automation-card__actions {
  display: flex;
  justify-content: center;
  gap: 16px;
  padding: 10px 0 0;
  margin-top: 12px;
  border-top: 1px solid var(--color-border);
  background: transparent;
}

.automation-delete-dialog__body p {
  margin: 0;
  color: var(--color-text-secondary);
  font-size: 13px;
  line-height: 1.5;
  text-align: center;
}

.automation-delete-dialog__body strong { color: var(--color-text); }

.automation-modal {
  position: fixed;
  inset: 0;
  z-index: var(--z-modal);
  display: grid;
  place-items: start center;
  padding: var(--modal-pad-top) 12px var(--modal-pad-bottom);
  background: rgba(2, 6, 23, .62);
  backdrop-filter: blur(5px);
}

.automation-modal > .dialog {
  width: min(100%, 620px);
  max-height: var(--modal-max-h);
  overflow: auto;
}

.automation-delete-dialog {
  width: min(100%, 340px) !important;
}

.automation-delete-dialog__body {
  text-align: center;
}

.automation-delete-dialog__body p {
  margin: 0;
}

.automation-delete-dialog__body p + p {
  margin-top: 7px;
  color: var(--color-text-secondary);
  font-size: .8rem;
}

.automation-form__grid {
  display: grid;
  gap: 13px;
}

.automation-form__field {
  display: grid;
  gap: 6px;
}

.automation-schedule {
  overflow: hidden;
  border: 1px solid var(--color-border); /* kit: tk.border, sin tinte */
  border-radius: 12px;
  background: var(--color-surface);
}

/* Builder (paridad kit trigger-form.jsx): sección PLANA — sin caja; la
 * cabecera es una pastilla tintada + botón "+" tintado, sobre el fondo del diálogo. */
.automation-builder { border: 0; background: transparent; overflow: visible; }

.automation-schedule__disclosure {
  display: flex;
  width: 100%;
  align-items: center;
  gap: 10px;
  padding: 10px 12px; /* kit */
  border: 0;
  background: var(--color-surface); /* kit: tk.surface — solo el icono lleva ámbar */
  color: var(--color-text);
  text-align: left;
  cursor: pointer;
}

.automation-schedule__icon {
  display: grid;
  width: 36px;
  height: 36px;
  flex: 0 0 auto;
  place-items: center;
  border-radius: 9px;
  background: rgb(245 158 11 / 20%); /* kit scheduleBg claro */
  color: #b45309;                    /* kit scheduleTxt claro */
}
[data-theme="dark"] .automation-schedule__icon {
  background: rgb(245 158 11 / 15%); /* kit scheduleBg oscuro */
  color: #fbbf24;                    /* kit scheduleTxt oscuro */
}

.automation-schedule__summary {
  display: grid;
  min-width: 0;
  flex: 1;
  gap: 2px;
}

.automation-schedule__summary small {
  color: var(--color-text-secondary);
  font-size: .68rem;
}

.automation-schedule__body {
  display: grid;
  gap: 12px;
  padding: 12px;
  border-top: 1px solid color-mix(in srgb, var(--color-warning) 30%, var(--color-border));
}

.automation-schedule__types {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 8px;
}

.automation-schedule__type {
  display: flex;
  min-width: 0;
  align-items: center;
  gap: 8px;
  padding: 10px;
  border: 1.5px solid var(--color-border); /* kit: 1.5px en ambos estados */
  border-radius: 10px;
  background: var(--color-surface);
  color: var(--color-text);
  text-align: left;
  cursor: pointer;
}

/* Seleccionada (kit): fondo/borde del preset ámbar, título en texto NORMAL,
 * solo el icono toma el tono del preset. */
.automation-schedule__type.is-selected {
  border-color: rgb(180 83 9 / 50%);   /* kit scheduleBd claro */
  background: rgb(245 158 11 / 20%);   /* kit scheduleBg claro */
  color: var(--color-text);
}
.automation-schedule__type.is-selected > .icon, .automation-schedule__type.is-selected > svg, .automation-schedule__type.is-selected > img { color: #b45309; }
[data-theme="dark"] .automation-schedule__type.is-selected {
  border-color: rgb(245 158 11 / 40%); /* kit scheduleBd oscuro */
  background: rgb(245 158 11 / 15%);   /* kit scheduleBg oscuro */
}
[data-theme="dark"] .automation-schedule__type.is-selected > .icon, [data-theme="dark"] .automation-schedule__type.is-selected > svg, [data-theme="dark"] .automation-schedule__type.is-selected > img { color: #fbbf24; }

.automation-schedule__type span {
  display: grid;
  min-width: 0;
}

.automation-schedule__type small {
  color: var(--color-text-secondary);
  font-size: .62rem;
  line-height: 1.3;
}

.automation-schedule__fixed,
.automation-ranges,
.automation-range {
  display: grid;
  gap: 10px;
}

.automation-range {
  padding: 10px;
  border: 1px solid var(--color-border);
  border-radius: 10px;
  background: var(--color-surface); /* kit */
}

.automation-time-fields {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 10px;
}

/* Columna caption + tp-card del preset TIMEPICKER (export trigger_form). */
.automation-time-field {
  display: grid;
  gap: 4px;
  justify-items: stretch;
  align-content: start;
}

.automation-time-field--single {
  justify-self: center;
  min-width: 140px;
}

.automation-time-field__caption {
  font-size: 10.5px;
  color: var(--color-text-secondary);
  text-align: center;
}

/* Rueda abierta en flujo: columnas scroll-snap (kit WheelNumber). */
.automation-tp {
  justify-self: center;
}

.automation-tp .tp-wheel ul {
  position: static;
  height: 100%;
  overflow-y: auto;
  scroll-snap-type: y mandatory;
  overscroll-behavior: contain;
  scrollbar-width: none;
  touch-action: pan-y;
}

.automation-tp .tp-wheel ul::-webkit-scrollbar {
  display: none;
  width: 0;
  height: 0;
}

/* Espaciadores (cellH * 2) para que el primer/último valor puedan centrarse. */
.automation-tp .tp-wheel ul::before,
.automation-tp .tp-wheel ul::after {
  content: "";
  display: block;
  height: 72px;
}

.automation-tp .tp-wheel li {
  scroll-snap-align: center;
  cursor: pointer;
  user-select: none;
}

.automation-tp .tp-wheel li.on {
  cursor: default;
}

.automation-weekdays,
.automation-day-shortcuts,
.automation-schedule__actions,
.automation-range__meta {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: 5px;
}

.automation-weekdays button {
  display: grid;
  min-width: 32px;
  min-height: 30px;
  place-items: center;
  padding: 4px 7px;
  border: 1px solid var(--color-border);
  border-radius: 8px;
  background: var(--color-surface);
  color: var(--color-text-secondary);
  font: inherit;
  font-size: .7rem;
  font-weight: 700;
  cursor: pointer;
}

.automation-weekdays button.is-selected {
  border-color: var(--color-warning);
  background: var(--color-warning);
  color: #fff;
}

.automation-day-shortcuts button,
.automation-range__meta button,
.automation-range__add {
  padding: 3px;
  border: 0;
  background: transparent;
  color: var(--color-primary);
  font: inherit;
  font-size: .67rem;
  font-weight: 650;
  cursor: pointer;
}

.automation-range__meta {
  justify-content: space-between;
}

.automation-range__meta button {
  color: var(--color-error);
}

.automation-midnight {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 3px 8px;
  border-radius: 999px;
  background: rgba(147, 51, 234, .15);
  color: #a78bfa;
  font-size: .65rem;
}

.automation-schedule__actions {
  justify-content: flex-end;
  padding-top: 10px;
  border-top: 1px solid var(--color-border);
}

.automation-builder > header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0;
  margin-bottom: 8px;
}

.automation-builder > header h3 {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  margin: 0;
  padding: 3px 8px;
  border-radius: 9999px;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: .04em;
  text-transform: uppercase;
}

.automation-builder > header button,
.automation-builder__row-actions button {
  display: grid;
  width: 28px;
  height: 28px;
  place-items: center;
  padding: 0;
  border: 0;
  border-radius: 8px;
  background: transparent;
  color: var(--color-primary);
  cursor: pointer;
}

.automation-builder--conditions > header h3,
.automation-builder--conditions > header button {
  background: rgba(59, 130, 246, .15);
  border: 1px solid rgba(59, 130, 246, .30);
  color: var(--color-primary-700);
}

.automation-builder--actions > header h3,
.automation-builder--actions > header button {
  background: rgba(34, 197, 94, .15);
  border: 1px solid rgba(34, 197, 94, .30);
  color: var(--color-success-700);
}

html[data-theme="dark"] .automation-builder--conditions > header h3,
html[data-theme="dark"] .automation-builder--conditions > header button { border-color: rgba(147, 197, 253, .35); color: #93c5fd; }
html[data-theme="dark"] .automation-builder--actions > header h3,
html[data-theme="dark"] .automation-builder--actions > header button { border-color: rgba(134, 239, 172, .35); color: #86efac; }

.automation-builder__rows {
  display: grid;
  gap: 8px;
  padding: 0;
}

.automation-builder__row:empty {
  display: none;
}

.automation-builder__editor {
  display: grid;
  grid-template-columns: minmax(120px, 1fr) minmax(0, 1.6fr) auto;
  align-items: center;
  gap: 7px;
  padding: 9px;
  border: 1px solid var(--color-card-nested-border);
  border-radius: 10px;
  background: var(--color-card-nested-bg);
}

.automation-builder__controls,
.automation-builder__row-actions {
  display: flex;
  min-width: 0;
  align-items: center;
  gap: 6px;
}

.automation-builder__operator {
  max-width: 68px;
}

/* TFSelect del kit (trigger-form.jsx:204-290): dropdown custom boton +
 * popover listbox — no un <select> nativo. Estado cerrado centrado sin
 * chevron ('center'); popover absoluto max-height 220 con la activa
 * resaltada. Tinte primary en condiciones, success en acciones. */
.automation-select {
  position: relative;
  min-width: 0;
  flex: 1;
}

.automation-select--fit {
  flex: 0 0 auto;
}

.automation-select__trigger {
  width: 100%;
  min-width: 0;
  padding: 8px 10px;
  border: 1px solid color-mix(in srgb, var(--color-primary) 55%, transparent);
  border-radius: 8px;
  background: var(--color-surface-sunken);
  color: var(--color-text);
  font-family: inherit;
  font-size: 13px;
  font-weight: 500;
  text-align: center;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  cursor: pointer;
}

.automation-select__list {
  position: absolute;
  top: calc(100% + 4px);
  left: 0;
  min-width: 100%;
  width: max-content;
  max-width: 260px;
  margin: 0;
  padding: 0;
  list-style: none;
  background: #ffffff;
  border: 1px solid var(--color-border);
  border-radius: 10px;
  box-shadow: 0 12px 24px rgb(0 0 0 / 18%);
  max-height: 220px;
  overflow-y: auto;
  z-index: 10;
}

html[data-theme="dark"] .automation-select__list {
  background: #1e293b;
}

.automation-select__option {
  width: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 8px 10px;
  border: none;
  background: transparent;
  color: var(--color-text);
  font-family: inherit;
  font-size: 13px;
  font-weight: 500;
  cursor: pointer;
  text-align: center;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.automation-select__option.is-active {
  background: #f1f5f9;
  font-weight: 600;
}

html[data-theme="dark"] .automation-select__option.is-active {
  background: rgb(148 163 184 / 10%);
}

.automation-builder--actions .automation-select__trigger {
  border-color: color-mix(in srgb, var(--color-success) 55%, transparent);
}

.automation-builder__row-actions button:last-child {
  color: var(--color-error);
}

.automation-builder__row-actions button:disabled {
  color: var(--color-text-muted);
  cursor: not-allowed;
}

.automation-builder__confirmed {
  display: grid;
  width: 100%;
  gap: 2px;
  padding: 9px 10px;
  border: 1px solid var(--color-card-nested-border);
  border-radius: 10px;
  background: var(--color-card-nested-bg);
  color: var(--color-text);
  text-align: left;
  cursor: pointer;
}

.automation-builder__confirmed small,
.automation-builder__empty {
  color: var(--color-text-secondary);
  font-size: .68rem;
}

.automation-builder__empty {
  margin: 2px;
  text-align: center;
}

.automation-options {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 7px;
  padding: 0;
  border: 0;
}

.automation-options label {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 9px 10px;
  border: 1px solid var(--color-border);
  border-radius: 10px;
  color: var(--color-text-secondary);
  font-size: .73rem;
}

.automation-emergency {
  display: grid;
  gap: 10px;
  padding: 11px;
  border: 1px solid color-mix(in srgb, var(--color-error) 35%, var(--color-border));
  border-radius: 11px;
  background: var(--color-error-light);
}

.automation-emergency > p {
  display: flex;
  align-items: center;
  gap: 7px;
  margin: 0;
  color: var(--color-error-700);
  font-size: .76rem;
}

.automation-form__error,
.automation-form__conflict {
  margin: 0;
  color: var(--color-error);
  font-size: .75rem;
  text-align: center;
}

.automation-log-filters {
  display: grid;
  gap: 0;
  padding-bottom: 12px;
}

.automation-log-filters fieldset {
  display: grid;
  gap: 6px; /* legacy: los filtros usan ahora .filter-row */
  padding: 0;
  border: 0;
}

.automation-log-list {
  display: grid;
  gap: 8px;
}

.automation-log {
  overflow: hidden;
  border: 1px solid var(--color-card-nested-border);
  border-radius: 12px;
  background: var(--color-card-nested-bg);
}

/* Fila única (kit TriggerLogCard compact): hora · pill resultado · stats a la derecha */
.automation-log summary {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px 12px;
  cursor: pointer;
  list-style: none;
}

.automation-log__result { flex-shrink: 0; }

.automation-log__stats svg { transition: transform .2s ease; }

.automation-log[open] .automation-log__stats svg { transform: rotate(180deg); }

.automation-log summary::-webkit-details-marker {
  display: none;
}

.automation-log time {
  overflow: hidden;
  color: var(--color-text-secondary);
  font-size: 12px;
  font-variant-numeric: tabular-nums;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.automation-log__result {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding: 3px 8px;
  border-radius: 9999px;
  font-size: 11px;
  font-weight: 600;
}

/* Punto de estado dentro de la pill (kit TriggerLogCard) */
.automation-log__result::before {
  content: "";
  width: 6px;
  height: 6px;
  border-radius: 3px;
  background: currentColor;
}

.automation-log__result--ok { background: var(--color-success-light); color: var(--color-success-700); }
.automation-log__result--warn { background: var(--color-warning-light); color: var(--color-warning-700); }
.automation-log__result--err { background: var(--color-error-light); color: var(--color-error-700); }

.automation-log__stats {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-left: auto;
  color: var(--color-text-secondary);
  font-size: 11px;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

.automation-log__stats > span {
  display: inline-flex;
  align-items: center;
  gap: 4px;
}

.automation-log__stats strong { color: var(--color-text); }

/* Mini-badges COND/ACC del kit: 9px/700, tinte azul info / verde success */
.automation-log__stats b {
  padding: 1px 5px;
  border-radius: 4px;
  font-size: 9px;
  font-weight: 700;
  letter-spacing: .04em;
  background: var(--color-info-light, var(--color-primary-100));
  color: var(--color-primary-700);
}

.automation-log__stats > span + span b {
  background: var(--color-success-light);
  color: var(--color-success-700);
}

/* Desglose kit: secciones Condiciones/Acciones con result-mark por fila */
.automation-log__detail {
  display: grid;
  gap: 12px;
  padding: 10px 12px 12px;
  border-top: 1px solid var(--color-card-nested-border);
}

.automation-log__group { display: grid; gap: 4px; }

.automation-log__group > .eyebrow { margin: 0; }

.automation-log__row {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 3px 0;
  font-size: 12px;
}

.automation-log__row .result-mark { flex-shrink: 0; }

.automation-log__row strong { flex-shrink: 0; color: var(--color-text); font-size: 12px; font-weight: 600; }

.automation-log__row > span:last-child { overflow: hidden; min-width: 0; color: var(--color-text-secondary); font-size: 12px; text-overflow: ellipsis; white-space: nowrap; }

.automation-location-history {
  display: grid;
  gap: 12px;
  padding: 14px;
}

.automation-location-history__list {
  display: grid;
  gap: 8px;
}

.automation-log-row {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto;
  align-items: center;
  gap: 10px;
  padding: 10px;
  border: 1px solid var(--color-border);
  border-radius: 10px;
  background: var(--color-surface);
}

.automation-log-row > div {
  display: grid;
  min-width: 0;
  gap: 2px;
}

.automation-log-row strong,
.automation-log-row small {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.automation-log-row small,
.automation-log-row__facts {
  color: var(--color-text-muted);
  font-size: 11px;
}

.automation-log-row__facts {
  justify-items: end;
  font-variant-numeric: tabular-nums;
}

@media (max-width: 560px) {
  .automation-options {
    grid-template-columns: 1fr;
  }

  .automation-builder__editor {
    grid-template-columns: 1fr;
  }

  .automation-builder__row-actions {
    justify-content: flex-end;
  }

  .automation-log-row {
    grid-template-columns: auto minmax(0, 1fr);
  }

  .automation-log-row__facts {
    grid-column: 2;
    justify-items: start;
  }
}

@media (prefers-reduced-motion: reduce) {
  .automation-card,
  .automation-delete-dialog__body p {
  margin: 0;
  color: var(--color-text-secondary);
  font-size: 13px;
  line-height: 1.5;
  text-align: center;
}

.automation-delete-dialog__body strong { color: var(--color-text); }

.automation-modal {
    scroll-behavior: auto;
  }
}


/* package: Alarmas/src/web/app/presentation/assets/packages/homehub-cloud.css */

.homehub-cloud-page, .locations-page { max-width: 760px; margin: 0 auto; }
.homehub-dialog-page { display: grid; justify-items: center; padding: 12px 0 24px; }
.homehub-dialog-page > .dialog, .homehub-wizard, .sensor-pairing { width: min(100%, 400px); max-height: none; overflow: visible; }
/* Overlay modal (mismo patrón que .profile-modal): flotante sobre la pantalla actual, con scrim. */
.homehub-modal { position: fixed; inset: 0; z-index: var(--z-modal); display: grid; justify-items: center; align-items: start; overflow: auto; padding: var(--modal-pad-top) 16px var(--modal-pad-bottom); background: rgba(2, 6, 23, .55); backdrop-filter: blur(2px); }
.homehub-location-create { width: min(100%, 430px); max-height: var(--modal-max-h); display: flex; flex-direction: column; }
.homehub-location-create__body { overflow-y: auto; min-height: 0; flex: 1 1 auto; }
.homehub-location-form { display: grid; gap: 13px; min-width: 0; }
.homehub-location-create .dialog-head, .homehub-wizard .dialog-head, .sensor-pairing .dialog-head { align-items: flex-start; }
.homehub-location-create .dialog-title, .homehub-location-create .dialog-sub,
.homehub-wizard .dialog-title, .homehub-wizard .dialog-sub,
.sensor-pairing .dialog-title, .sensor-pairing .dialog-sub { margin: 0; }
.homehub-location-create__body { overflow-y: auto; }

.homehub-hero { display: grid; grid-template-columns: auto minmax(0, 1fr) auto; align-items: center; gap: 14px; padding: 18px; }
.homehub-hero h1, .homehub-hero p { margin: 0; }
.homehub-hero p:last-child { margin-top: 3px; color: var(--color-text-secondary); font-size: 13px; }
.homehub-section-head { display: flex; align-items: center; justify-content: space-between; gap: 12px; margin-bottom: 12px; }
.homehub-section-head h2, .homehub-section-head p { margin: 0; }
.homehub-section-head h2 { font-size: 18px; }
.homehub-inventory, .homehub-actions, .locations-live-region { padding: 18px; border: 1px solid var(--color-border); border-radius: var(--radius-xl); background: var(--color-surface); }
.homehub-list, .homehub-location-list, .pairing-list { display: grid; gap: 10px; padding: 0; margin: 0; list-style: none; }
.homehub-card { display: grid; gap: 14px; padding: 15px; }
.homehub-card__identity { display: flex; align-items: center; gap: 12px; }
.homehub-card__identity > div { display: flex; min-width: 0; flex: 1; align-items: center; justify-content: space-between; gap: 8px; }
.homehub-card__identity strong { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.homehub-facts { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 12px; padding-top: 12px; margin: 0; border-top: 1px solid var(--color-border); }
.homehub-facts div { min-width: 0; }
.homehub-facts dt { color: var(--color-text-secondary); font-size: 11px; }
.homehub-facts dd { overflow: hidden; margin: 2px 0 0; color: var(--color-text); font-size: 13px; font-weight: 600; text-overflow: ellipsis; white-space: nowrap; }
.homehub-card__orphan { margin: 0; color: var(--color-text-muted); font-size: 12px; }
.homehub-empty, .homehub-state { display: grid; justify-items: center; gap: 10px; padding: 24px; text-align: center; }
.homehub-state > div { display: grid; justify-items: center; gap: 10px; }
.homehub-action-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px; }

.homehub-steps { display: flex; align-items: center; gap: 8px; padding: 11px 14px; margin: 0 0 18px; border: 1px solid var(--color-border); border-radius: 12px; background: var(--color-card-nested-bg); list-style: none; }
.homehub-step { display: flex; align-items: center; gap: 8px; color: var(--color-text-secondary); font-size: 12px; }
.homehub-step > span { display: grid; width: 26px; height: 26px; flex: 0 0 auto; place-items: center; border-radius: 50%; background: var(--color-border); font-weight: 700; }
.homehub-step.is-current { color: var(--color-text); }
.homehub-step.is-current > span { background: var(--color-primary); color: var(--color-on-primary, #fff); }
.homehub-step.is-done > span { background: var(--color-success); color: var(--color-on-success, #fff); }
.homehub-step__line { height: 2px; flex: 1; border-radius: 2px; background: var(--color-border); }
.homehub-step__line.is-done { background: var(--color-success); }
.homehub-location-form, .homehub-field, .homehub-identity { display: grid; gap: 7px; }
.homehub-location-form { gap: 13px; }
.homehub-field { color: var(--color-text-secondary); font-size: 12px; font-weight: 600; }
.homehub-field .field { width: 100%; }
.homehub-identity { padding: 0; margin: 0; border: 0; }
.homehub-identity legend { margin-bottom: 1px; color: var(--color-text-secondary); font-size: 12px; font-weight: 600; }
.homehub-identity__preview { display: flex; align-items: center; gap: 12px; padding: 12px; border: 1px solid var(--color-card-nested-border); border-radius: 12px; background: var(--color-card-nested-bg); }
.homehub-identity__preview > span:last-child { display: grid; min-width: 0; gap: 2px; }
.homehub-identity__preview strong { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.homehub-identity__preview small { color: var(--color-text-secondary); }
.homehub-colors, .homehub-icons { display: grid; justify-content: space-between; gap: 8px; }
.homehub-colors { grid-template-columns: repeat(7, auto); }
.homehub-icons { grid-template-columns: repeat(5, auto); }
.homehub-color, .homehub-icon { display: grid; padding: 3px; border: 2px solid transparent; border-radius: 13px; cursor: pointer; }
.homehub-color:has(input:checked), .homehub-icon:has(input:checked) { border-color: var(--color-primary); }
.homehub-color:focus-within, .homehub-icon:focus-within { outline: 2px solid var(--color-primary); outline-offset: 2px; }
.homehub-icon .location-tile { width: 42px; height: 42px; }
.homehub-color .location-color { display: block; width: 32px; height: 32px; border-radius: 10px; }
.location-color--blue, .location-tile--blue { background: var(--color-primary); }
.location-color--indigo, .location-tile--indigo { background: var(--color-indigo, #4f46e5); }
.location-color--teal, .location-tile--teal { background: var(--color-teal, #0d9488); }
.location-color--green, .location-tile--green { background: var(--color-success); }
.location-color--amber, .location-tile--amber { background: var(--color-warning); }
.location-color--red, .location-tile--red { background: var(--color-error); }
.location-color--slate, .location-tile--slate { background: var(--color-text-secondary); }
.homehub-address-title { margin: 5px 0 0; }
.homehub-address-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 12px; }

.homehub-wizard__prompt { margin: 0 0 12px; font-size: 15px; }
.homehub-location-option { display: grid; grid-template-columns: auto minmax(0, 1fr) auto; align-items: center; gap: 11px; color: var(--color-text); text-decoration: none; }
.homehub-location-option > span:nth-child(2) { display: grid; min-width: 0; gap: 2px; }
.homehub-location-option strong, .homehub-location-option small { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.homehub-location-option small { color: var(--color-text-secondary); }
.homehub-activation { display: grid; gap: 16px; }
.homehub-activation__alert:empty { display: none; }
.homehub-expire-form, .homehub-issue-form { margin-top: 12px; }
.homehub-activation-status > div { display: grid; min-width: 0; gap: 4px; }
.homehub-activation-status .btn { margin-top: 7px; }
.homehub-handoff-note { margin-top: 16px; }
.homehub-handoff-note > div { display: grid; gap: 3px; }
.homehub-handoff { margin-top: 10px; }
.homehub-provisioning { display: grid; gap: 13px; margin-top: 14px; }
.homehub-provisioning__identity { display: grid; gap: 10px; padding: 13px; border: 1px solid var(--color-border); border-radius: 12px; background: var(--color-card-nested-bg); }
.homehub-provisioning__identity code { overflow-wrap: anywhere; color: var(--color-text); font-family: var(--font-mono, monospace); font-size: 12px; line-height: 1.5; }
.homehub-provisioning__status { min-height: 1.4em; margin: 0; color: var(--color-text-secondary); font-size: 12px; line-height: 1.4; }
.homehub-provisioning__status[data-state="error"] { color: var(--color-error-700); }
.homehub-provisioning__status[data-state="completed"] { color: var(--color-success-700); font-weight: 600; }

.activation-code { padding: 20px; border: 1px solid var(--color-border); border-radius: 14px; background: var(--color-card-nested-bg); text-align: center; }
.activation-code__row { position: relative; display: flex; align-items: center; justify-content: center; }
.activation-code__code { color: var(--color-text); font-family: var(--font-mono, monospace); font-size: 32px; font-weight: 800; letter-spacing: .14em; }
.activation-code__copy { position: absolute; right: 0; display: grid; width: 38px; height: 38px; place-items: center; border: 1px solid var(--color-border); border-radius: 10px; background: var(--color-surface-sunken); color: var(--color-text-secondary); cursor: pointer; }
.activation-code__meta { display: inline-flex; align-items: center; gap: 6px; margin-top: 10px; color: var(--color-text-secondary); font-size: 12px; font-weight: 600; }
.activation-code__bar { height: 6px; margin-top: 12px; overflow: hidden; border-radius: 3px; background: var(--color-border); }
.activation-code__bar-fill { display: block; width: 100%; height: 100%; border-radius: inherit; background: var(--color-primary); }
.activation-code__regen { display: inline-flex; align-items: center; gap: 5px; padding: 6px; margin-top: 10px; border: 0; background: transparent; color: var(--color-primary); font-size: 12px; font-weight: 600; cursor: pointer; }
.activation-steps { padding: 14px; border: 1px solid color-mix(in srgb, var(--color-primary) 20%, var(--color-border)); border-radius: 14px; background: var(--color-primary-light); }
.activation-steps__title { display: block; margin-bottom: 12px; font-size: 12px; text-transform: uppercase; }
.activation-steps__list { display: grid; gap: 12px; padding: 0; margin: 0; list-style: none; }
.activation-steps__item { display: flex; align-items: flex-start; gap: 11px; }
.activation-steps__num { display: grid; width: 23px; height: 23px; flex: 0 0 auto; place-items: center; border-radius: 50%; background: var(--color-primary); color: var(--color-on-primary, #fff); font-size: 11px; font-weight: 700; }
.activation-steps__text { color: var(--color-text-secondary); font-size: 12px; line-height: 1.45; }

.pairing-control { display: flex; flex-direction: column; align-items: center; padding: 4px 0 6px; text-align: center; }
.pairing-control > p { max-width: 280px; margin: 8px 0 0; color: var(--color-text-secondary); font-size: 12px; line-height: 1.5; }
.pair-badge { display: inline-flex; align-items: center; gap: 8px; padding: 5px 14px; border-radius: 9999px; background: var(--color-surface-tonal); color: var(--color-text-secondary); font-size: 12px; font-weight: 600; }
.pair-badge__dot { width: 8px; height: 8px; border-radius: 50%; background: var(--color-text-muted); }
.pair-badge--searching { background: var(--color-success-light); color: var(--color-success-700); }
.pair-badge--searching .pair-badge__dot { background: var(--color-success); }
.pair-search { position: relative; display: flex; width: 148px; height: 148px; align-items: center; justify-content: center; margin: 20px 0 6px; }
.pair-search__btn { position: relative; z-index: 1; display: flex; width: 128px; height: 128px; flex-direction: column; align-items: center; justify-content: center; gap: 6px; border: 0; border-radius: 50%; background: var(--color-primary); box-shadow: var(--shadow-lg); color: var(--color-on-primary, #fff); cursor: pointer; }
.pair-search__label { max-width: 108px; font-size: 14px; font-weight: 700; line-height: 1.1; }
.pair-search--searching .pair-search__btn { background: var(--color-success); }
.pair-radar { position: absolute; inset: 4px; border: 2px solid var(--color-success); border-radius: 50%; pointer-events: none; animation: homehub-pair-radar 1.8s ease-out infinite; }
.pair-radar--delayed { animation-delay: .9s; }
.pairing-detected { padding-top: 14px; margin-top: 18px; border-top: 1px solid var(--color-border); }
.pairing-detected__head { display: flex; align-items: center; justify-content: space-between; gap: 8px; margin-bottom: 10px; }
.pairing-detected__head span { color: var(--color-text-muted); font-size: 11px; font-weight: 600; }
.pairing-list li { display: grid; grid-template-columns: auto minmax(0, 1fr) auto; align-items: center; gap: 11px; padding: 11px; border: 1px solid var(--color-border); border-radius: 14px; background: var(--color-card-nested-bg); animation: homehub-sensor-in 280ms cubic-bezier(.16,1,.3,1); }
.pairing-list li > span:nth-child(2) { display: grid; min-width: 0; gap: 2px; }
.pairing-list strong, .pairing-list small { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.pairing-list small { color: var(--color-text-secondary); font-size: 11px; }
.pairing-activity { display: inline-flex; align-items: center; gap: 5px; color: var(--color-success-700); font-size: 10px; font-style: normal; font-weight: 600; }
.pairing-activity i { width: 6px; height: 6px; border-radius: 50%; background: var(--color-success); animation: homehub-pair-pulse 1.3s ease-in-out infinite; }
.pairing-empty { display: grid; justify-items: center; gap: 5px; padding: 24px 18px; border: 1px dashed var(--color-border); border-radius: 14px; background: var(--color-surface-sunken); text-align: center; }
.pairing-empty p { margin: 0; color: var(--color-text-muted); font-size: 12px; }
.pairing-claim-card { padding: 14px; margin-bottom: 18px; border: 1px solid var(--color-border); border-radius: 14px; background: var(--color-card-nested-bg); }
.pairing-claim-card__head { display: flex; align-items: center; gap: 14px; margin-bottom: 12px; }
.pairing-claim-card__head > div { display: grid; gap: 3px; }
.pairing-claim-card dl { display: grid; gap: 7px; padding-top: 11px; margin: 0; border-top: 1px solid var(--color-border); }
.pairing-claim-card dl div { display: flex; align-items: baseline; justify-content: space-between; gap: 12px; }
.pairing-claim-card dt { color: var(--color-text-secondary); font-size: 12px; }
.pairing-claim-card dd { margin: 0; font-size: 12px; font-weight: 600; text-align: right; }
.pairing-claim-form { display: grid; gap: 14px; }
.pairing-type-warning { padding: 9px 11px; }
.pairing-action-result[data-state="error"]:not(:empty), .pairing-form-result[data-state="error"]:not(:empty) { width: 100%; padding: 9px 11px; border: 1px solid color-mix(in srgb, var(--color-error) 35%, var(--color-border)); border-radius: 10px; background: var(--color-error-light); color: var(--color-error-700); font-size: 12px; font-weight: 600; text-align: left; }

@keyframes homehub-pair-pulse { 50% { opacity: .3; } }
@keyframes homehub-pair-radar { 0% { opacity: .55; transform: scale(.75); } 80%, 100% { opacity: 0; transform: scale(1.35); } }
@keyframes homehub-sensor-in { from { opacity: 0; transform: translateY(8px); } to { opacity: 1; transform: translateY(0); } }
@media (max-width: 540px) {
  .homehub-hero { grid-template-columns: auto minmax(0, 1fr); }
  .homehub-hero > .btn { grid-column: 1 / -1; }
  .homehub-facts, .homehub-action-grid, .homehub-address-grid { grid-template-columns: 1fr; }
  .homehub-icons { grid-template-columns: repeat(5, minmax(0, 1fr)); }
  .homehub-icon { justify-items: center; }
}
@media (prefers-reduced-motion: reduce) {
  .pair-radar, .pairing-activity i, .pairing-list li { animation: none; }
}


/* package: Alarmas/src/web/app/presentation/assets/packages/locations-devices.css */

/* LOCATIONS-DEVICES package source. Linked only by the serial integrator. */
.device-card {
  position: relative;
  overflow: hidden;
  padding: 14px;
}

.device-card--warn,
.device-card--err,
.device-card--off {
  padding-top: 18px;
}

.device-card__accent {
  position: absolute;
  inset: 0 0 auto;
  height: 2px;
  background: var(--color-error);
}

.device-card--warn .device-card__accent {
  background: var(--color-warning);
}

.device-card__refresh {
  display: none;
}

.device-card__summary {
  display: flex;
  width: 100%;
  min-height: 32px;
  align-items: center;
  gap: 10px;
  padding: 0;
  border: 0;
  background: transparent;
  color: inherit;
  font: inherit;
  text-align: left;
  cursor: pointer;
}

.device-drag-handle {
  display: inline-flex;
  flex: 0 0 auto;
  color: var(--color-text-muted);
  cursor: grab;
  opacity: .6;
}

.device-card__name {
  min-width: 0;
  flex: 1;
  overflow: hidden;
  color: var(--color-text);
  font-size: 15px;
  font-weight: 600;
  letter-spacing: -.01em;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.device-card--off .device-card__name {
  color: var(--color-text-secondary);
}

.device-card__dot {
  width: 10px;
  height: 10px;
  flex: 0 0 auto;
  margin-right: 4px;
  border-radius: 50%;
  background: var(--color-success);
  box-shadow: 0 0 0 3px var(--pulse-soft);
  --pulse-strong: color-mix(in srgb, var(--color-success) 55%, transparent);
  --pulse-soft: color-mix(in srgb, var(--color-success) 22%, transparent);
}

.device-card--warn .device-card__dot {
  background: var(--color-warning);
  --pulse-strong: color-mix(in srgb, var(--color-warning) 55%, transparent);
  --pulse-soft: color-mix(in srgb, var(--color-warning) 22%, transparent);
}

.device-card--err .device-card__dot,
.device-card--off .device-card__dot {
  background: var(--color-error);
  --pulse-strong: color-mix(in srgb, var(--color-error) 55%, transparent);
  --pulse-soft: color-mix(in srgb, var(--color-error) 20%, transparent);
}

/* Sonar del kit (connPulse preset) en vez del throb de escala; off queda inerte. */
.device-card:not(.device-card--off) .device-card__dot {
  animation: connPulse 1.8s ease-out infinite;
}

.device-card__alert {
  margin-top: 10px;
  align-items: center;
  font-weight: 500;
}

.device-card__body {
  display: flex;
  flex-direction: column;
  gap: 10px;
  margin-top: 12px;
  padding-top: 10px;
  border-top: 1px solid var(--color-divider-inner);
}

.device-card__body[hidden] {
  display: none;
}

.device-card__actions {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  padding-bottom: 8px;
  border-bottom: 1px dashed var(--color-divider-inner);
}


.device-card__security {
  display: flex;
  justify-content: flex-end;
  margin-top: 10px;
}

.device-card__updated {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: 6px;
  margin-top: 10px;
  padding-top: 8px;
  border-top: 1px dashed var(--color-divider-inner);
  color: var(--color-text-secondary);
  font-size: 11px;
  font-weight: 500;
}

.device-card__updated > span {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--color-success);
}

.device-card__empty {
  display: grid;
  justify-items: center;
  gap: 6px;
  padding: 28px 12px;
  color: var(--color-text-secondary);
  font-size: 13px;
  text-align: center;
}

.sensor-fields {
  display: grid;
  gap: 14px;
}

.sensor-field {
  display: grid;
  gap: 8px;
}

.sensor-field > header {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 10px;
}

.sensor-field output {
  color: var(--color-text-secondary);
  font-size: 13px;
}

/* Campo de solo lectura (paridad kit ReadValue: valor 14px/600 con tono,
 * unidad 12px/500 muted en baseline). */
.sensor-field--read {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  padding: 4px 0;
}

.sensor-field__reading {
  display: inline-flex;
  align-items: baseline;
  gap: 2px;
  color: var(--color-text);
}

.sensor-field--read output {
  color: inherit;
  font-size: 14px;
  font-weight: 600;
  letter-spacing: -0.005em;
  line-height: 1.2;
  font-variant-numeric: tabular-nums;
}

.sensor-field__unit {
  margin-left: 1px;
  color: var(--color-text-secondary);
  font-size: 12px;
  font-weight: 500;
  letter-spacing: 0;
}

/* Booleanos en 2 columnas; los enums heredan la fila única del preset .segmented (flex). */
.sensor-field__choices--boolean {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 8px;
}

.sensor-field__choices form,
.arm-tiles form {
  display: contents;
}

.sensor-field__command {
  display: flex;
  gap: 8px;
}

.sensor-field__command .field {
  flex: 1;
}

.device-form__hardware,
.device-category-row {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 12px;
  border: 1px solid var(--color-border);
  border-radius: 12px;
  background: var(--color-surface);
}

.device-form__hardware > span:nth-child(2),
.device-category-row > span:nth-child(2) {
  display: grid;
  min-width: 0;
  flex: 1;
  gap: 2px;
}

.device-form__hardware small,
.device-category-row small {
  color: var(--color-text-secondary);
  font-size: 11px;
}

.device-form__hardware strong,
.device-category-row strong {
  overflow: hidden;
  color: var(--color-text);
  font-size: 14px;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.device-form__field {
  display: grid;
  gap: 6px;
  margin-top: 12px;
}

.device-form__field > span {
  color: var(--color-text);
  font-size: 12px;
  font-weight: 600;
}

.device-form__grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 12px;
}

.device-form__security {
  display: grid;
  gap: 8px;
  margin-top: 16px;
}

.sensor-history {
  padding: 14px;
}

.sensor-history__head {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto;
  align-items: center;
  gap: 8px;
  margin-bottom: 14px;
}

.sensor-history__head h3,
.sensor-history__head p {
  margin: 0;
}

.sensor-history__head h3 {
  overflow: hidden;
  color: var(--color-text);
  font-size: 14px;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.sensor-history__head p {
  color: var(--color-text-secondary);
  font-size: 11px;
}

.sensor-history__filters,
.sensor-history__list {
  display: grid;
  gap: 8px;
}

.sensor-history__filters {
  margin-bottom: 12px;
}

.sensor-history-item {
  padding: 10px;
  border: 1px solid var(--color-card-nested-border);
  border-radius: 12px;
  background: var(--color-card-nested-bg);
}

.sensor-history-item > header {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-bottom: 10px;
}

.sensor-history-item > header strong {
  min-width: 0;
  flex: 1;
  overflow: hidden;
  font-size: 13px;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.sensor-history-item > header time {
  color: var(--color-text-muted);
  font-size: 11px;
  white-space: nowrap;
}

.sensor-history-item__fields {
  display: grid;
  gap: 6px;
}

.sensor-history-item__fields--2 {
  grid-template-columns: repeat(2, minmax(0, 1fr));
}

.sensor-history-item__fields--3 {
  grid-template-columns: repeat(3, minmax(0, 1fr));
}

.sensor-history-item__fields > span {
  display: grid;
  min-width: 0;
  gap: 1px;
  padding: 6px 8px;
  border: 1px solid var(--color-surface-tonal-border);
  border-radius: 8px;
  background: var(--color-surface-tonal);
}

.sensor-history-item__fields small {
  overflow: hidden;
  color: var(--color-text-muted);
  font-size: 9.5px;
  font-weight: 600;
  letter-spacing: .03em;
  text-overflow: ellipsis;
  text-transform: uppercase;
  white-space: nowrap;
}

.camera-preview {
  position: relative;
  display: block;
  width: 100%;
  overflow: hidden;
  aspect-ratio: 16 / 9;
  padding: 0;
  border: 0;
  border-radius: 10px;
  background: linear-gradient(135deg, #1e293b 0%, #0f172a 60%, #020617 100%);
  cursor: pointer;
}

.camera-preview img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.camera-preview__overlay {
  position: absolute;
  inset: 0;
  display: grid;
  place-content: center;
  justify-items: center;
  gap: 6px;
  background: rgb(0 0 0 / 30%);
  color: #fff;
}

.camera-preview__overlay .ds-icon {
  --icon-size: 26px;
  padding: 12px;
  border-radius: 50%;
  background: rgb(255 255 255 / 20%);
  box-sizing: content-box;
  fill: currentcolor;
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
}

/* Offline: placeholder 16:9 no interactivo (kit screens.jsx:1347-1359). */
.camera-preview--offline {
  display: grid;
  place-content: center;
  justify-items: center;
  gap: 6px;
  background: linear-gradient(135deg, var(--color-bg-alt), var(--color-border));
  color: var(--color-text-secondary);
  font-size: 12px;
  cursor: default;
}

/* Directo in-card: mientras el host tiene contenido, el tap-to-play se oculta. */
.camera-live-host:not(:empty) + .camera-preview {
  display: none;
}

.camera-live-inline {
  display: block;
}

.camera-live-inline .camera-live-stage {
  border-radius: 10px;
}

.camera-live-inline__pill {
  position: absolute;
  top: 8px;
  left: 8px;
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding: 3px 8px;
  border-radius: 6px;
  background: rgb(0 0 0 / 50%);
  color: #fff;
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.04em;
}

.camera-live-inline__dot {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: #ef4444;
  animation: device-connection-pulse 1.2s ease-in-out infinite;
}

.camera-live-inline__top {
  position: absolute;
  top: 8px;
  right: 8px;
  display: flex;
  gap: 6px;
}

.camera-live-inline__topbtn {
  display: grid;
  place-items: center;
  width: 30px;
  height: 30px;
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: rgb(0 0 0 / 50%);
  color: #fff;
  cursor: pointer;
}

.camera-live-inline__ctrl {
  position: absolute;
  bottom: 10px;
  left: 50%;
  display: flex;
  gap: 10px;
  transform: translateX(-50%);
}

.camera-live-inline__ctrlbtn {
  display: grid;
  place-items: center;
  width: 40px;
  height: 40px;
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: rgb(255 255 255 / 18%);
  color: #fff;
  cursor: pointer;
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
}

.camera-live-inline__ctrlbtn[data-state="success"] {
  background: rgb(34 197 94 / 55%);
}

.camera-live-inline__ctrlbtn[data-state="error"] {
  background: rgb(239 68 68 / 55%);
}

.camera-wizard__summary {
  display: grid;
  gap: 8px;
  margin: 0;
  padding: 12px;
  border: 1px solid var(--color-border);
  border-radius: 12px;
  background: var(--color-surface);
}

.camera-wizard__summary > div {
  display: flex;
  justify-content: space-between;
  gap: 12px;
  font-size: 13px;
}

.camera-wizard__summary dt {
  color: var(--color-text-secondary);
}

.camera-wizard__summary dd {
  margin: 0;
  color: var(--color-text);
  font-weight: 600;
}

.camera-media-actions {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 8px;
  margin-top: 10px; /* respiro respecto al visor de la cámara */
}

.camera-wizard__steps {
  display: grid;
  grid-template-columns: 22px 36px 22px;
  align-items: center;
  justify-content: center;
  gap: 8px;
  margin: 0 0 16px;
  padding: 0;
  list-style: none;
}

.camera-wizard__steps::before {
  content: "";
  grid-column: 2;
  grid-row: 1;
  height: 2px;
  background: var(--color-border);
}

.camera-wizard__steps li {
  display: grid;
  grid-row: 1;
  width: 22px;
  height: 22px;
  place-content: center;
  border: 1px solid var(--color-border);
  border-radius: 50%;
  background: var(--color-bg-alt);
  color: var(--color-text-muted);
  font-size: 11px;
  font-weight: 700;
}

.camera-wizard__steps li:first-child {
  grid-column: 1;
}

.camera-wizard__steps li:last-child {
  grid-column: 3;
}

.camera-wizard__steps li.is-active {
  border-color: var(--color-primary);
  background: var(--color-primary);
  color: #fff;
}

.camera-wizard__rtsp {
  padding: 10px;
  border-radius: 8px;
  background: var(--color-bg-alt);
  color: var(--color-text-secondary);
  font-family: ui-monospace, monospace;
  font-size: 12px;
  overflow-wrap: anywhere;
}

.camera-wizard__test {
  display: grid;
  gap: 0;
  margin-top: 14px;
  overflow: hidden;
  border: 1px solid var(--color-border);
  border-radius: 12px;
}

.camera-wizard__test[hidden] {
  display: none;
}

.camera-wizard__test p {
  display: flex;
  align-items: center;
  gap: 6px;
  margin: 0;
  padding: 10px 12px;
  background: var(--color-success-light);
  color: var(--color-success-700);
  font-size: 12px;
}

[data-camera-wizard-result][data-state="error"]:not(:empty) {
  padding: 9px 11px;
  border: 1px solid color-mix(in srgb, var(--color-error) 35%, var(--color-border));
  border-radius: 10px;
  background: var(--color-error-light);
  color: var(--color-error-700);
  font-size: 12px;
  font-weight: 600;
}

.camera-preview__badge {
  position: absolute;
  top: 8px;
  left: 8px;
  padding: 3px 8px;
  border-radius: 9999px;
  background: rgb(34 197 94 / 85%);
  color: #fff;
  font-size: 10px;
  font-weight: 600;
}

.camera-media-list {
  display: grid;
  gap: 8px;
}

.camera-media-item {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 10px;
  border: 1px solid var(--color-border);
  border-radius: 12px;
  background: var(--color-surface);
}

.camera-media-item__identity {
  display: grid;
  min-width: 0;
  flex: 1;
  gap: 2px;
}

.camera-media-item__actions {
  display: flex;
  align-items: center;
  gap: 6px;
}

.camera-media-item time {
  color: var(--color-text-secondary);
  font-size: 12px;
}

.camera-live-modal {
  align-items: center;
  background: rgb(2 6 23 / 88%);
}

.camera-live-dialog {
  width: min(100%, 880px) !important;
  overflow: hidden;
  background: #090d16;
  color: #fff;
}

.camera-live-head {
  border-color: rgb(255 255 255 / 14%);
}

.camera-live-head .dialog-title {
  min-width: 0;
  overflow: hidden;
  color: #fff;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.camera-live-head__actions {
  display: flex;
  gap: 6px;
}

.camera-live-head .dialog-close {
  color: #fff;
}

.camera-live-body {
  display: grid;
  gap: 14px;
}

.camera-live-stage {
  position: relative;
  overflow: hidden;
  aspect-ratio: 16 / 9;
  border-radius: 12px;
  background: #000;
}

.camera-live-media,
.camera-live-video,
.camera-live-image {
  width: 100%;
  height: 100%;
}

.camera-live-video,
.camera-live-image {
  display: block;
  object-fit: contain;
}

.camera-live-loading,
.camera-live-error {
  position: absolute;
  inset: 0;
  display: grid;
  place-content: center;
  justify-items: center;
  gap: 12px;
  background: rgb(0 0 0 / 55%);
  text-align: center;
}

.camera-live-loading .ds-icon {
  animation: device-connection-pulse 1.2s ease-in-out infinite;
}

.camera-live-badge {
  position: absolute;
  top: 10px;
  left: 10px;
  padding: 4px 9px;
  border-radius: 999px;
  background: rgb(0 0 0 / 65%);
  color: #fff;
  font-size: 11px;
}

.camera-live-controls {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 8px;
}

.camera-live-controls .btn {
  color: #fff;
  background: rgb(255 255 255 / 10%);
  border-color: rgb(255 255 255 / 18%);
}

.camera-live-controls [data-state="error"] {
  color: #fecaca;
  border-color: rgb(239 68 68 / 55%);
}

.camera-live-controls [data-state="success"] {
  color: #bbf7d0;
  border-color: rgb(34 197 94 / 55%);
}

/* El kit pone margin-bottom:10px inline en el eyebrow del dialog-impact;
 * aquí el inline style está vetado por los tests de la superficie. */
.location-modal .dialog-impact > .eyebrow {
  margin: 0 0 10px;
}

.arm-tiles {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
}

.arm-tiles button {
  display: inline-flex;
  min-height: 52px;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 4px;
}

@keyframes device-connection-pulse {
  0%, 100% { transform: scale(1); }
  50% { transform: scale(1.18); }
}

@media (prefers-reduced-motion: reduce) {
  .device-card__dot { animation: none !important; }
}

@media (max-width: 480px) {
  /* paridad kit: Capturas/Vídeos mantienen la fila única también en móvil */
  .device-form__grid,
  .camera-live-controls { grid-template-columns: 1fr; }
  .sensor-history-item__fields--3 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

/* Camera live (inline mount): loader/error glyphs sit on the black stage — kit stage chrome is white. */
.camera-live-inline .camera-live-loading,
.camera-live-inline .camera-live-error { color: #fff; }
/* Kit record control: red disc with a white ring (screens.jsx streamChrome). */
.camera-live-inline__ctrlbtn[data-camera-record] > .ds-icon { fill: #ef4444; stroke: #fff; }
/* Pairing empty state: kit 44px r12 bg-alt plate with a muted glyph (location-modals.jsx). */
.pairing-empty__tile { width: 44px; height: 44px; border-radius: 12px; border-color: transparent; background: var(--color-bg-alt); color: var(--color-text-muted); opacity: .8; }


/* package: Alarmas/src/web/app/presentation/assets/packages/security-emergency.css */

.security-page { padding-bottom: 12px; }
.security-hero { display: flex; align-items: center; gap: 14px; padding: 14px; }
.security-hero h1, .security-hero p { margin: 0; }
.security-hero h1 { font-size: 18px; letter-spacing: -.015em; }
.security-hero p { margin-top: 2px; color: var(--color-text-secondary); font-size: 12px; line-height: 1.4; }
.security-collections { display: grid; gap: 18px; }
/* Cabecera portada del dashboard (entrada 149): mismo aire bajo el título que
 * dashboard-section/automatizaciones (grid gap 10). */
.security-collection { display: grid; gap: 10px; }
.security-section-heading { display: flex; align-items: baseline; justify-content: space-between; padding: 0 4px; margin-bottom: 8px; }
.security-section-heading h2 { margin: 0; color: var(--color-text-secondary); font-size: 11px; font-weight: 700; letter-spacing: .08em; text-transform: uppercase; }
.security-section-heading > span { color: var(--color-text-muted); font-size: 11px; font-weight: 600; font-variant-numeric: tabular-nums; }
.security-card-list { display: grid; gap: 10px; }
.security-card { position: relative; overflow: hidden; }
/* Barra de acento SOLO semántica de incidencia (decisión de producto): ámbar =
 * problema o transición en curso · rojo = emergencia/desconexión/fallo grave.
 * El estado de armado ya lo comunica el selector — sin barra en operación normal. */
.security-card::before { position: absolute; top: 0; right: 0; left: 0; z-index: 1; height: 3px; content: ""; background: transparent; }
.security-card--warning::before { background: var(--color-warning); }
.security-card--error { border-color: color-mix(in srgb, var(--color-error) 55%, var(--color-border)); box-shadow: 0 0 20px color-mix(in srgb, var(--color-error) 20%, transparent); }
.security-card--error::before { background: var(--color-error); }
.security-card__summary { display: grid; grid-template-columns: minmax(0, 1fr) auto; align-items: center; gap: 10px; padding: 12px 12px 12px 14px; }
.security-card__disclosure { display: flex; align-items: center; gap: 10px; min-width: 0; padding: 0; border: 0; background: transparent; color: var(--color-text); text-align: left; cursor: pointer; }
.security-card__identity { display: grid; min-width: 0; gap: 2px; }
.security-card__name { display: flex; align-items: center; gap: 5px; overflow: hidden; font-size: 14px; font-weight: 700; letter-spacing: -.015em; text-overflow: ellipsis; white-space: nowrap; }
.security-card__facts { display: flex; align-items: center; gap: 10px; color: var(--color-text-secondary); font-size: 11px; }
.security-card__facts > span { display: inline-flex; align-items: center; gap: 4px; }
.security-card__facts b { color: var(--color-text); }
.security-state-region { display: contents; }
/* Candado + selector SIEMPRE en una fila (el candado va a la izquierda). */
.security-arm-wrap { display: flex; align-items: center; gap: 6px; }
.security-arm-selector { display: grid; grid-template-columns: repeat(3, 58px); gap: 3px; padding: 4px; border-radius: 12px; }
.security-arm-selector form { margin: 0; }
.security-arm-selector button { display: inline-flex; flex-direction: column; align-items: center; justify-content: center; width: 100%; height: 46px; min-height: 0; gap: 3px; padding: 6px 3px 5px; border: 0; border-radius: 9px; background: transparent; color: var(--color-text-secondary); cursor: pointer; }
.security-arm-selector button span { font-size: 10px; font-weight: 500; line-height: 1; white-space: nowrap; }
/* Activo segActive3D del recipe (_segmented.css): replicado aqui porque el
 * <form> intermedio impide que `.segmented > button` matchee. Tokens --arm-*
 * de tone-presets resueltos desde el propio boton. */
.security-arm-selector button[data-arm-mode][aria-checked="true"] { color: var(--arm-deep); background: linear-gradient(180deg, rgba(255,255,255,0.45) 0, rgba(255,255,255,0) 48%), var(--arm-lt); transform: translateY(-0.5px); box-shadow: 0 1px 2px rgba(15,23,42,0.14), 0 2px 5px rgba(15,23,42,0.10), inset 0 0 0 1px color-mix(in srgb, var(--arm-ring) 50%, transparent); }
.security-arm-selector button[data-arm-mode="away"][aria-checked="true"] { box-shadow: 0 1px 3px rgba(15,23,42,0.14), 0 3px 10px color-mix(in srgb, var(--arm-ring) 22%, transparent), 0 0 0 2px color-mix(in srgb, var(--arm-ring) 25%, transparent), inset 0 0 0 2px color-mix(in srgb, var(--arm-ring) 67%, transparent); }
html[data-theme="dark"] .security-arm-selector button[data-arm-mode][aria-checked="true"] { background: linear-gradient(180deg, rgba(255,255,255,0.10) 0, rgba(255,255,255,0) 48%), var(--arm-lt); box-shadow: 0 1px 2px rgba(15,23,42,0.35), 0 2px 5px rgba(15,23,42,0.30), inset 0 0 0 1px color-mix(in srgb, var(--arm-ring) 33%, transparent); }
html[data-theme="dark"] .security-arm-selector button[data-arm-mode="away"][aria-checked="true"] { box-shadow: 0 1px 3px rgba(15,23,42,0.40), 0 3px 10px color-mix(in srgb, var(--arm-ring) 25%, transparent), 0 0 0 2px color-mix(in srgb, var(--arm-ring) 33%, transparent), inset 0 0 0 2px color-mix(in srgb, var(--arm-ring) 53%, transparent); }
.security-arm-selector button:disabled { opacity: .5; cursor: not-allowed; }
.security-arm-selector button[aria-busy="true"] { color: var(--color-warning-700); }
.security-alarm-link { white-space: nowrap; }
.security-state-feedback { grid-column: 1 / -1; margin-top: 2px; }
.security-not-ready { padding: 10px 12px; border: 1px solid color-mix(in srgb, var(--color-warning) 35%, transparent); border-radius: 12px; background: var(--color-warning-light); color: var(--color-warning-700); font-size: 12px; }
.security-not-ready ul { display: grid; gap: 4px; padding: 0; margin: 6px 0 0; list-style: none; }
.security-not-ready li { display: flex; justify-content: space-between; gap: 8px; }
.security-card__body { display: grid; gap: 14px; padding: 14px; border-top: 1px solid var(--color-border); }
/* Autocentrado: con menos de 3 tiles (permisos futuros) los restantes quedan
 * centrados manteniendo el ancho de tercio. */
.security-action-grid { display: flex; justify-content: center; gap: 8px; }
.security-action-tile { flex: 1 1 0; max-width: calc((100% - 16px) / 3); }
.security-action-tile { position: relative; display: flex; flex-direction: column; align-items: center; justify-content: center; min-height: 78px; gap: 8px; padding: 14px 6px; border: 1px solid var(--color-card-nested-border); border-radius: 12px; background: var(--color-card-nested-bg); color: var(--color-text); font-size: 11px; font-weight: 600; line-height: 1.3; text-align: center; text-decoration: none; cursor: pointer; }
.security-action-tile > .ds-icon { color: var(--color-text-secondary); }
.security-action-count { position: absolute; top: 6px; right: 6px; display: grid; place-items: center; min-width: 18px; height: 18px; padding: 0 5px; border-radius: 999px; background: var(--color-primary); color: #fff; font-size: 10px; box-shadow: 0 0 0 2px #fff; /* ring del kit: separa el badge del tile */ }
html[data-theme="dark"] .security-action-count { box-shadow: 0 0 0 2px #0f172a; }
.security-action-count--warning { background: var(--color-warning); }
/* Kit ArmLocationCard: mismo estándar que los action-tiles — elev-pop + innerSurface/innerBorder. */
.security-history-action { display: flex; align-items: center; justify-content: center; width: 100%; gap: 8px; padding: 11px 12px; border: 1px solid #e2e8f0; border-radius: 12px; background: #ffffff; color: var(--color-text-secondary); font-size: 11px; font-weight: 700; letter-spacing: .06em; text-transform: uppercase; text-decoration: none; cursor: pointer; }
html[data-theme="dark"] .security-history-action { border-color: rgb(71 85 105 / 35%); background: #0f172a; }
.security-empty { display: grid; justify-items: center; gap: 12px; padding: 24px; color: var(--color-text-secondary); text-align: center; }
.security-empty p { margin: 0; }
.presentation-modal { position: fixed; inset: 0; z-index: var(--z-modal); display: grid; align-items: start; overflow: auto; padding: var(--modal-pad-top) 16px var(--modal-pad-bottom); background: rgb(2 6 23 / 55%); backdrop-filter: blur(2px); }
.security-dialog { width: min(100%, 430px); max-height: var(--modal-max-h); margin: 0 auto; overflow: auto; }
.security-dialog .dialog-head { display: flex; align-items: flex-start; justify-content: center; gap: 12px; text-align: center; }
.security-dialog .dialog-title, .security-dialog .dialog-sub { margin: 0; }
.security-dialog .dialog-sub { margin-top: 3px; }
.security-dialog-state { padding: 24px 10px; margin: 0; color: var(--color-text-secondary); text-align: center; }
.security-event-list { display: grid; gap: 8px; }
/* Fila de evento (kit AlarmHistoryModal): tile 40 r11 teñido con el tono del
 * evento — fondo 14% sobre surface, borde 38%, glifo en el tono profundo. */
.security-event { --evt-tone: #64748b; --evt-fg: #1e293b; display: flex; align-items: center; gap: 12px; padding: 12px; border: 1px solid var(--color-border); border-radius: 12px; background: var(--color-surface); }
[data-event-tone="ok"] { --evt-tone: #22c55e; --evt-fg: #14532d; }
[data-event-tone="info"], [data-event-tone="primary"] { --evt-tone: #3b82f6; --evt-fg: #1e3a8a; }
[data-event-tone="warn"], [data-event-tone="warning"], [data-event-tone="sched"] { --evt-tone: #f59e0b; --evt-fg: #92400e; } /* sched = identidad ámbar de programación */
[data-event-tone="err"], [data-event-tone="error"] { --evt-tone: #ef4444; --evt-fg: #991b1b; }
html[data-theme="dark"] .security-event { --evt-fg: #f1f5f9; }
html[data-theme="dark"] [data-event-tone="ok"] { --evt-fg: #bbf7d0; }
html[data-theme="dark"] [data-event-tone="info"], html[data-theme="dark"] [data-event-tone="primary"] { --evt-fg: #93c5fd; }
html[data-theme="dark"] [data-event-tone="warn"], html[data-theme="dark"] [data-event-tone="warning"], html[data-theme="dark"] [data-event-tone="sched"] { --evt-fg: #fbbf24; }
html[data-theme="dark"] [data-event-tone="err"], html[data-theme="dark"] [data-event-tone="error"] { --evt-fg: #fca5a5; }
.security-event__icon { display: grid; flex: 0 0 auto; place-items: center; width: 40px; height: 40px; border-radius: 11px; box-sizing: border-box; background: color-mix(in srgb, var(--evt-tone) 14%, var(--color-surface)); border: 1px solid color-mix(in srgb, var(--evt-tone) 38%, transparent); color: var(--evt-fg); }
.security-event > div { display: grid; flex: 1; min-width: 0; gap: 2px; }
.security-event strong { font-size: 14px; }
.security-event small, .security-event time { color: var(--color-text-muted); font-size: 11.5px; }
.security-event time { flex: 0 0 auto; font-variant-numeric: tabular-nums; }
/* Tabs home/away (kit ProfileModeTabs): carril hundido segTrack3D + pastilla
 * activa con el color semántico del modo (tokens --arm-* de tone-presets). */
.security-profile-tabs { display: grid; grid-template-columns: 1fr 1fr; gap: 4px; padding: 4px; margin-bottom: 16px; border: 1px solid var(--color-border); border-radius: 12px; background: var(--color-surface-sunken); box-shadow: inset 0 1px 2px rgb(15 23 42 / 10%); }
html[data-theme="dark"] .security-profile-tabs { border-color: #334155; box-shadow: inset 0 1px 3px rgb(0 0 0 / 50%); }
.security-profile-tabs button { display: inline-flex; align-items: center; justify-content: center; gap: 7px; padding: 9px 10px; font-size: 13px; font-weight: 600; line-height: 1; letter-spacing: -.005em; border: 0; border-radius: 9px; background: transparent; color: var(--color-text-secondary); cursor: pointer; }
.security-profile-tabs button[data-arm-mode][aria-selected="true"] { color: var(--arm-deep); background: linear-gradient(180deg, rgba(255,255,255,0.45) 0, rgba(255,255,255,0) 48%), var(--arm-lt); transform: translateY(-0.5px); box-shadow: 0 1px 2px rgba(15,23,42,0.14), 0 2px 5px rgba(15,23,42,0.10), inset 0 0 0 1px color-mix(in srgb, var(--arm-ring) 50%, transparent); }
html[data-theme="dark"] .security-profile-tabs button[data-arm-mode][aria-selected="true"] { background: linear-gradient(180deg, rgba(255,255,255,0.10) 0, rgba(255,255,255,0) 48%), var(--arm-lt); box-shadow: 0 1px 2px rgba(15,23,42,0.35), 0 2px 5px rgba(15,23,42,0.30), inset 0 0 0 1px color-mix(in srgb, var(--arm-ring) 33%, transparent); }
.security-profile-form { display: grid; gap: 14px; }
.security-form-heading { margin: 0; color: var(--color-text-muted); font-size: 10px; font-weight: 700; letter-spacing: .08em; text-transform: uppercase; }
.security-category-list { display: grid; gap: 8px; }
/* CategoryRow del kit: fila clicable; con el toggle ON el borde de la fila y el
 * tile del icono toman el tono (--cat-tone); OFF = gris neutro. */
.security-category-row { --cat-tone: var(--color-primary); display: flex; align-items: center; gap: 12px; padding: 12px; border: 1px solid var(--color-border); border-radius: 12px; background: var(--color-surface); cursor: pointer; transition: border-color .15s ease; }
.security-category-row--warning { --cat-tone: var(--color-warning); }
.security-category-row--error { --cat-tone: var(--color-error); }
.security-category-row:has(input:checked) { border-color: color-mix(in srgb, var(--cat-tone) 33%, transparent); }
.security-category-row__icon { display: flex; flex: 0 0 auto; align-items: center; justify-content: center; width: 36px; height: 36px; border-radius: 10px; box-sizing: border-box; background: #e2e8f0; border: 1px solid #d3dbe5; color: var(--color-text-secondary); transition: background .15s ease, border-color .15s ease, color .15s ease; }
html[data-theme="dark"] .security-category-row__icon { background: rgb(148 163 184 / 10%); border-color: rgb(148 163 184 / 16%); }
.security-category-row:has(input:checked) .security-category-row__icon { background: color-mix(in srgb, var(--cat-tone) 13%, transparent); border-color: color-mix(in srgb, var(--cat-tone) 25%, transparent); color: var(--cat-tone); }
.security-empty-row { display: flex; align-items: center; gap: 12px; padding: 12px; border: 1px dashed var(--color-border); border-radius: 12px; background: #ffffff; }
html[data-theme="dark"] .security-empty-row { background: rgb(15 23 42 / 40%); border-color: #334155; }
.security-empty-row > span:nth-child(2) { display: grid; flex: 1; min-width: 0; gap: 2px; }
.security-empty-row strong { color: var(--color-text-secondary); font-size: 14px; }
.security-empty-row small { color: var(--color-text-muted); font-size: 12px; line-height: 1.4; }
/* Cabecera de sección con botón "?" (modal de información) a la derecha. */
.security-heading-row { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
.security-info-btn { display: grid; place-items: center; width: 20px; height: 20px; padding: 0; border: 1px solid var(--color-border); border-radius: 50%; background: var(--color-surface); color: var(--color-text-secondary); font-size: 11px; font-weight: 700; line-height: 1; cursor: pointer; }
.security-info-btn:hover { color: var(--color-text); border-color: var(--color-text-muted); }
.security-info-text { margin: 0; color: var(--color-text-secondary); font-size: 13px; line-height: 1.55; text-align: justify; }
/* Retardo de salida (kit ExitDelaySlider): valor grande + rango, slider accent primary,
 * presets = preset .segmented del sistema. */
.security-delay { display: grid; gap: 8px; }
.security-delay__head { display: flex; align-items: baseline; justify-content: space-between; }
.security-delay__head b { color: var(--color-text); font-size: 24px; font-weight: 700; letter-spacing: -.02em; font-variant-numeric: tabular-nums; }
.security-delay__head small { color: var(--color-text-muted); font-size: 11px; font-weight: 500; }
.security-delay__slider { width: 100%; margin: 4px 0; accent-color: var(--color-primary); }
.security-category-row > span:nth-child(2) { display: grid; flex: 1; min-width: 0; gap: 2px; }
.security-category-row strong { font-size: 14px; }
.security-category-row small { color: var(--color-text-secondary); font-size: 11px; }
.security-delay-field { display: grid; gap: 8px; color: var(--color-text-secondary); font-size: 12px; }
.security-delay-field > span:last-child { display: flex; align-items: baseline; gap: 8px; }
.security-delay-field .field { max-width: 110px; }
.security-delay-presets { display: grid; grid-template-columns: repeat(6, minmax(0, 1fr)); gap: 4px; }
.security-delay-presets button { min-height: 34px; padding: 5px 2px; border: 1px solid var(--color-border); border-radius: 8px; background: transparent; color: var(--color-text-secondary); font: inherit; font-size: 11px; font-weight: 650; cursor: pointer; }
.security-delay-presets button[aria-pressed="true"] { border-color: var(--color-primary); background: var(--color-primary-light); color: var(--color-primary-700); box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--color-primary) 20%, transparent); }
.security-schedules-body { display: grid; gap: 16px; }
.security-schedule-master { display: flex; align-items: center; gap: 12px; padding: 12px; border: 1px solid color-mix(in srgb, var(--color-success) 30%, var(--color-border)); border-radius: 12px; background: var(--color-success-light); }
.security-schedule-master > div { display: grid; flex: 1; gap: 2px; }
.security-schedule-master small { color: var(--color-text-secondary); font-size: 11px; }
.security-schedule-list { display: grid; gap: 10px; }
.security-schedule-card { padding: 12px; border: 1px solid var(--color-border); border-radius: 12px; background: var(--color-surface); box-shadow: var(--shadow-sm); }
.security-schedule-card summary { display: flex; align-items: center; justify-content: center; gap: 8px; min-height: 36px; list-style: none; cursor: pointer; }
.security-schedule-card summary > span:first-child { flex: 1; font-size: 14px; font-weight: 700; }
.security-schedule-card form { display: grid; gap: 10px; padding-top: 12px; margin-top: 12px; border-top: 1px solid var(--color-border); }
.security-schedule-card .security-schedule-order { display: flex; justify-content: flex-end; gap: 6px; }
.security-schedule-card .security-schedule-order form { display: block; padding: 0; margin: 0; border: 0; }
.security-schedule-card label { display: grid; gap: 5px; color: var(--color-text-secondary); font-size: 11px; }
.security-toggle-row { display: flex !important; align-items: center; justify-content: space-between; }
.security-schedule-create { display: grid; gap: 10px; padding: 12px; border: 1px dashed var(--color-border); border-radius: 12px; }
.security-schedule-create h3 { display: flex; align-items: center; gap: 6px; margin: 0; font-size: 13px; }
.location-sensors-page { display: grid; justify-items: center; padding: 12px 0 24px; }
.location-sensors-dialog { width: min(100%, 400px); max-height: none; overflow: visible; }
.location-sensors-dialog .dialog-head form { margin: 0; }
.location-sensors-hint { margin: 0 2px 12px; color: var(--color-text-secondary); font-size: 12px; line-height: 1.5; }
.location-sensor-list { display: grid; gap: 8px; }
.location-sensor-row { position: relative; display: grid; grid-template-columns: 36px minmax(0, 1fr) auto; align-items: center; gap: 12px; padding: 11px 12px; border: 1px solid var(--color-border); border-radius: 12px; background: var(--color-surface); }
.location-sensor-row.is-bypassed { border-color: color-mix(in srgb, var(--color-warning) 35%, transparent); opacity: .85; }
.location-sensor-row__icon { display: grid; place-items: center; width: 36px; height: 36px; border-radius: 10px; background: var(--color-primary-light); color: var(--color-primary-700); }
.location-sensor-row__icon.is-muted { background: var(--color-surface-sunken); color: var(--color-text-secondary); }
.location-sensor-row__identity { display: grid; min-width: 0; gap: 2px; }
.location-sensor-row__identity strong { overflow: hidden; color: var(--color-text); font-size: 14px; letter-spacing: -.01em; text-overflow: ellipsis; white-space: nowrap; }
.location-sensor-row__identity > span { display: flex; align-items: center; gap: 6px; color: var(--color-text-secondary); font-size: 12px; }
.location-sensor-row__identity small { color: var(--color-text-muted); font-size: 10px; }
.location-sensor-row__identity .chip { gap: 3px; padding: 1px 6px; font-size: 9px; letter-spacing: .04em; text-transform: uppercase; }
.location-sensor-toggle form { margin: 0; }
.location-sensor-toggle .toggle { display: block; border: 0; cursor: pointer; }
.location-sensor-row__result { position: absolute; top: calc(100% + 4px); right: 0; left: 0; z-index: 2; }
.location-sensors-empty { display: grid; justify-items: center; gap: 4px; padding: 20px; border: 1px dashed var(--color-border); border-radius: 12px; background: var(--color-surface-sunken); color: var(--color-text-muted); text-align: center; }
.location-sensors-empty strong { margin-top: 2px; color: var(--color-text-secondary); font-size: 14px; }
.location-sensors-empty p { margin: 0; font-size: 12px; line-height: 1.4; }
.alarm-page { min-height: 100dvh; overflow: hidden; background: #b91c1c; }
/* Emergencia (kit AlarmEmergencyScreen, screens.jsx:3862-4080): lienzo rojo
 * 135deg dc2626→b91c1c con capa pulsante, glow radial tras el icono, pill
 * «Alarma activa» glass, icono CIRCULAR 136 con anillo y pulso, título 30/700,
 * filas casa/sensor apiladas, ack blanco 17/700 y volver subrayado. */
.alarmx { position: relative; isolation: isolate; display: flex; flex-direction: column; min-height: 100dvh; overflow: hidden; color: #fff; text-align: center; background: linear-gradient(135deg, #dc2626 0%, #b91c1c 100%); }
.alarmx__bg { position: absolute; inset: 0; z-index: -2; background: linear-gradient(135deg, #dc2626 0%, #b91c1c 100%); animation: alarmx-pulse-bg 2s ease-in-out infinite; }
.alarmx__glow { position: absolute; inset: 0; z-index: -1; background: radial-gradient(ellipse at 50% 32%, rgb(255 255 255 / 20%) 0%, rgb(255 255 255 / 0%) 55%); pointer-events: none; }
.alarmx__status { position: relative; z-index: 2; display: flex; justify-content: center; padding: max(66px, calc(var(--safe-top) + 12px)) 0 8px; }
.alarmx__pill { display: inline-flex; align-items: center; gap: 7px; padding: 5px 12px 5px 10px; border: 1px solid rgb(255 255 255 / 28%); border-radius: 9999px; background: rgb(255 255 255 / 18%); -webkit-backdrop-filter: blur(8px); backdrop-filter: blur(8px); font-size: 11px; font-weight: 700; letter-spacing: .08em; text-transform: uppercase; }
.alarmx__dot { width: 7px; height: 7px; border-radius: 50%; background: #fff; box-shadow: 0 0 0 3px rgb(255 255 255 / 25%); animation: alarmx-dot 1.1s ease-in-out infinite; }
.alarmx__body { position: relative; z-index: 2; display: flex; flex: 1; flex-direction: column; align-items: center; justify-content: center; padding: 0 24px; }
.alarmx__icon { display: flex; align-items: center; justify-content: center; width: 136px; height: 136px; margin-bottom: 26px; border: 2px solid rgb(255 255 255 / 45%); border-radius: 50%; background: rgb(255 255 255 / 12%); box-shadow: 0 0 0 8px rgb(255 255 255 / 6%), 0 20px 40px -12px rgb(0 0 0 / 35%); animation: alarmx-pulse-icon 1.6s ease-in-out infinite; }
.alarmx__icon .ds-icon { width: 68px; height: 68px; }
.alarmx__source { display: grid; justify-items: center; }
.alarmx__source h1 { margin: 0; color: #fff; font-size: 30px; font-weight: 700; line-height: 1.15; letter-spacing: -.02em; text-wrap: pretty; }
/* El título recibe foco programático (tabindex=-1, para lectores): sin anillo visual. */
.alarmx__source h1:focus { outline: none; }
.alarmx__eyebrow { margin: 0 0 12px; color: rgb(255 255 255 / 90%); font-size: 12px; font-weight: 700; letter-spacing: .1em; text-transform: uppercase; }
.alarmx__facts { display: flex; flex-direction: column; align-items: center; gap: 9px; margin-top: 16px; }
.alarmx__facts p, .alarmx__message, .alarmx__time { margin: 0; }
.alarmx__facts p { display: inline-flex; align-items: center; gap: 7px; }
.alarmx__location { color: rgb(255 255 255 / 95%); font-size: 18px; font-weight: 600; letter-spacing: -.01em; }
.alarmx__sensor { color: rgb(255 255 255 / 82%); font-size: 14px; font-weight: 500; letter-spacing: -.01em; }
.alarmx__message { max-width: 290px; margin-top: 14px; color: rgb(255 255 255 / 85%); font-size: 15px; font-weight: 400; line-height: 1.45; }
.alarmx__time { display: inline-flex; align-items: center; gap: 5px; margin-top: 18px; color: rgb(255 255 255 / 70%); font-size: 12px; font-weight: 500; font-variant-numeric: tabular-nums; }
.alarmx__feedback { position: relative; z-index: 2; margin: 0 0 12px; }
.alarmx__actions { position: relative; z-index: 2; display: flex; flex-direction: column; gap: 10px; width: min(100%, 430px); margin: 0 auto; padding: 0 max(20px, var(--safe-right)) max(28px, calc(var(--safe-bottom) + var(--safe-gap))) max(20px, var(--safe-left)); box-sizing: border-box; }
.alarmx__ack-form { display: grid; }
.alarmx__ack { gap: 8px; padding: 16px 20px; border: 0; border-radius: 16px; background: #fff; color: #991b1b; font-size: 17px; font-weight: 700; box-shadow: 0 20px 25px -5px rgb(0 0 0 / 30%), 0 8px 10px -6px rgb(0 0 0 / 20%); transition: transform 150ms ease, box-shadow 150ms ease; }
.alarmx__ack:active { transform: scale(.97); }
.alarmx__back { padding: 8px 10px; color: rgb(255 255 255 / 78%); font-size: 13px; font-weight: 500; text-decoration: underline; text-underline-offset: 3px; }
@keyframes alarmx-pulse-bg { 0%, 100% { opacity: 1; } 50% { opacity: .86; } }
@keyframes alarmx-pulse-icon { 0%, 100% { transform: scale(1); } 50% { transform: scale(1.08); } }
@keyframes alarmx-dot { 0%, 100% { opacity: 1; transform: scale(1); } 50% { opacity: .5; transform: scale(.85); } }
@media (prefers-reduced-motion: reduce) { .alarmx__bg, .alarmx__icon, .alarmx__dot { animation: none; } }
.alarm-ack-error { display: grid; min-height: 100dvh; place-items: center; padding: 20px; }
.alarm-ack-error__card { display: grid; width: min(100%, 420px); justify-items: center; gap: 16px; padding: 24px; text-align: center; }
.alarm-ack-error__card h1 { margin: 0; font-size: 20px; }
@keyframes alarm-pulse { 50% { opacity: .55; transform: scale(.88); } }
@media (max-width: 520px) {
  .security-card__summary { grid-template-columns: minmax(82px, 1fr) auto; gap: 6px; padding-right: 8px; padding-left: 10px; }
  /* paridad kit: el selector de armado mantiene 58px + etiquetas también en móvil (ArmModeSegmented compact=false) */
  .security-action-grid { gap: 6px; }
  .security-dialog { max-height: calc(100dvh - 48px); }
  .presentation-modal { padding: var(--modal-pad-top) max(12px, var(--safe-right)) var(--modal-pad-bottom) max(12px, var(--safe-left)); }
}
@media (prefers-reduced-motion: reduce) { .alarmx__dot { animation: none; } }


/* package: Alarmas/src/web/app/presentation/assets/packages/sharing-subscription.css */

/* F5 · sharing and subscription presentation package. */
.sharing-proof,.sharing-tab-stack,.subscription-stack,.plan-picker{display:grid;gap:14px}.sharing-hero{display:flex;align-items:center;gap:14px;padding:18px}.sharing-hero h1,.sharing-hero p{margin:0}.sharing-hero h1{font-size:clamp(1.35rem,4vw,1.8rem)}.sharing-hero p{margin-top:3px;color:var(--color-text-secondary);font-size:.86rem}.sharing-tabs>button span{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.sharing-tabs>button[aria-selected="true"]{color:#fff;background:linear-gradient(180deg,rgba(255,255,255,0.26) 0,rgba(255,255,255,0) 48%),#3b82f6;box-shadow:0 1px 2px rgba(15,23,42,0.18),0 2px 5px rgba(37,99,235,0.24),inset 0 0 0 1px rgba(255,255,255,0.16);transform:translateY(-0.5px)}.sharing-card{overflow:hidden}.sharing-card>.disclosure,.sharing-card__head>.disclosure{padding:13px 14px}.sharing-card__head{display:flex;align-items:center}.sharing-card__head>.disclosure{min-width:0;flex:1}.sharing-card__head>.btn-help{margin-right:14px}.sharing-card__body{padding:0 14px 14px}.sharing-card__body:has(> .sharing-entity-list),.sharing-card__body:has(> .sharing-loading){padding:0}.sharing-loading,.subscription-loading{display:flex;align-items:center;justify-content:center;gap:8px;min-height:72px;color:var(--color-text-secondary)}.sharing-loading .ds-icon,.subscription-loading .ds-icon{animation:sharing-spin .9s linear infinite}@keyframes sharing-spin{to{transform:rotate(1turn)}}.sharing-status:empty{display:none}.sharing-code-form{display:grid;gap:10px}.sharing-code-form label{font-size:.78rem;font-weight:600;color:var(--color-text-secondary)}.sharing-code-input{text-transform:uppercase;letter-spacing:.18em;text-align:center}.sharing-entity-list{display:grid}.sharing-entity,.sharing-owner-row{overflow:hidden}.sharing-entity+.sharing-entity,.sharing-owner-row+.sharing-owner-row{border-top:1px solid rgba(148,163,184,0.18)}.sharing-entity__head,.sharing-owner-row{display:flex;align-items:center;gap:10px;padding:12px 14px}.sharing-entity__identity{display:grid;min-width:0;flex:1}.sharing-entity__identity strong,.sharing-entity__identity small{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.sharing-entity__identity small{margin-top:2px;color:var(--color-text-secondary);font-size:.72rem}.sharing-owner-badge{position:absolute;right:-4px;bottom:-4px;display:inline-flex;border-radius:50%;box-shadow:0 0 0 2px var(--color-bg)}.sharing-grant-list{display:grid;gap:8px;padding:4px 14px 14px}.sharing-guest-body{display:grid}.sharing-grant>.disclosure,.sharing-location>.disclosure{padding:10px 12px}.sharing-permissions{display:flex;flex-wrap:wrap;justify-content:center;gap:6px;padding:0 12px 12px}.sharing-toggle-row{display:flex;align-items:center;gap:8px;min-width:0;border-radius:9px}.sharing-toggle-row>span:nth-child(2){min-width:0;flex:1}.sharing-entity__revoke{padding:12px;border-top:1px solid var(--color-border)}.sharing-location__tile{position:relative}.sharing-location__body{display:grid;gap:10px;padding:0 12px 12px}.sharing-nested{display:grid;gap:7px;padding:10px 12px;border:1px solid var(--color-card-nested-border);border-radius:10px;background:var(--color-card-nested-bg)}.sharing-nested h3{margin:0}.sharing-pills{display:flex;flex-wrap:wrap;gap:6px}.sharing-pills .chip{display:inline-flex;align-items:center;gap:4px}.sharing-toggle-row{padding:6px 0;font-size:.79rem;cursor:pointer}.sharing-owner-row{flex-wrap:wrap}.sharing-owner-row__alerts{width:100%;padding-left:50px}.sharing-empty,.subscription-empty,.subscription-state,.paywall-card{display:flex;min-height:120px;flex-direction:column;align-items:center;justify-content:center;gap:8px;padding:20px;text-align:center;color:var(--color-text-secondary)}.sharing-code-result{display:flex;align-items:center;gap:10px;margin-top:10px;padding:10px 12px;border:1px solid var(--color-success);border-radius:10px;background:var(--color-success-light)}.sharing-code-result>div{display:grid;min-width:0;flex:1}.sharing-code-result small{color:var(--color-text-secondary);font-size:.7rem}.sharing-code-value{letter-spacing:.14em}.permissions-help-list{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:8px}.permissions-help-list>div{display:flex;align-items:center;gap:8px;padding:8px;border:1px solid var(--color-border);border-radius:9px;font-size:.78rem}.sharing-delete-dialog{max-width:430px}.sharing-delete-dialog .callout__body{display:grid;gap:5px}.sharing-delete-dialog .callout__body p{display:flex;justify-content:space-between;gap:12px;margin:0}
.subscription-stack{padding-top:4px}.subscription-block{display:grid;gap:6px}.subscription-inner{display:grid;gap:12px;padding:13px;border:1px solid var(--color-card-nested-border);border-radius:12px;background:var(--color-card-nested-bg)}.subscription-plan-head,.subscription-plan-head>div{display:flex;align-items:center;gap:8px}.subscription-plan-head{justify-content:space-between}.subscription-plan-head>div{min-width:0;flex-wrap:wrap}.subscription-plan-head strong{font-size:.96rem}.subscription-plan-head small{padding:2px 6px;border-radius:5px;background:var(--color-primary-100);color:var(--color-primary-700);font-size:.62rem;font-weight:700;letter-spacing:.06em}.subscription-period{display:flex;align-items:center;gap:12px}.subscription-period>div{display:grid;gap:2px}.subscription-period strong{font-size:1.05rem}.subscription-period small{color:var(--color-text-secondary);font-size:.72rem}.subscription-actions{display:flex;gap:8px;padding-top:10px;border-top:1px solid var(--color-border)}.subscription-actions>*{flex:1}.subscription-limit-list{gap:11px}.subscription-limit{display:grid;gap:4px}.subscription-limit>div{display:flex;justify-content:space-between;gap:12px;font-size:.76rem}.subscription-limit progress{width:100%;height:7px;overflow:hidden;border:0;border-radius:999px;background:var(--color-surface-tonal-hover);accent-color:var(--color-primary)}.subscription-limit[data-limit-tone=warning] progress{accent-color:var(--color-warning)}.subscription-limit[data-limit-tone=danger] progress{accent-color:var(--color-error)}.subscription-limit progress::-webkit-progress-bar{background:var(--color-surface-tonal-hover)}.subscription-limit progress::-webkit-progress-value{border-radius:999px;background:var(--color-primary)}.subscription-limit[data-limit-tone=warning] progress::-webkit-progress-value{background:var(--color-warning)}.subscription-limit[data-limit-tone=danger] progress::-webkit-progress-value{background:var(--color-error)}.subscription-transactions{gap:0;padding:0;overflow:hidden}.subscription-transaction{display:flex;align-items:center;gap:9px;padding:10px 12px}.subscription-transaction+.subscription-transaction{border-top:1px solid var(--color-border)}.subscription-transaction>div{display:grid;min-width:0;flex:1}.subscription-transaction small{color:var(--color-text-secondary);font-size:.7rem}.pricing-account{display:grid;gap:10px;padding:16px}.pricing-account h2,.pricing-account p{margin:0}.plan-picker{max-width:980px;margin-inline:auto}.plan-period{justify-self:center}.plan-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(100%,240px),1fr));gap:12px}.plan-card{display:flex;flex-direction:column;gap:14px;padding:18px 16px}.plan-card--featured{border:1.5px solid var(--color-primary)}.plan-card header{display:flex;align-items:center;justify-content:center;gap:8px}.plan-card h2{margin:0;text-align:center}.plan-price{display:flex;flex-wrap:wrap;align-items:baseline;justify-content:center;gap:5px;text-align:center}.plan-price strong{color:var(--color-primary);font-size:1.9rem;letter-spacing:-.03em}.plan-price span{color:var(--color-text-secondary);font-size:.78rem}.plan-price .chip{width:100%;justify-content:center}.plan-features{display:grid;gap:8px;margin:0;padding:0;list-style:none}.plan-features li{display:flex;align-items:center;gap:8px;font-size:.78rem}.plan-features .is-enabled .ds-icon{color:var(--color-success)}.plan-features .is-disabled{color:var(--color-text-muted)}.plan-promo{display:grid;grid-template-columns:minmax(0,1fr) auto;gap:8px;max-width:480px;margin-inline:auto}.plan-promo label{grid-column:1/-1;font-size:.76rem;font-weight:600}.paywall-card{min-height:250px}.paywall-card h2,.paywall-card p{margin:0}.paywall-card p{max-width:320px}.subscription-banner{display:flex;align-items:flex-start;justify-content:space-between;gap:10px;border-radius:0}.subscription-banner>span{display:flex;align-items:flex-start;gap:8px;min-width:0;flex:1}.subscription-banner a{flex:0 0 auto;color:inherit;font-size:.75rem;font-weight:700}.subscription-banner button{display:inline-flex;padding:2px;border:0;background:transparent;color:inherit;cursor:pointer}
.pricing-proof{padding-bottom:20px}.pricing-hero-proof{display:flex;align-items:center;gap:14px;padding:18px}.pricing-hero-proof h1,.pricing-hero-proof p{margin:0}.pricing-hero-proof h1{font-size:clamp(1.4rem,5vw,2rem)}.pricing-hero-proof p{margin-top:3px;color:var(--color-text-secondary);font-size:.86rem}.pricing-login-cta{text-align:center}
@media(min-width:640px){.sharing-code-form--inline{grid-template-columns:minmax(0,1fr) auto auto}}@media(max-width:480px){.permissions-help-list{grid-template-columns:1fr}.subscription-actions{flex-direction:column}.plan-promo{grid-template-columns:1fr}.subscription-banner{flex-wrap:wrap}.subscription-banner>span{flex-basis:100%}}
/* Hero del modal de borrado de cuenta (export account_delete_modal): el
 * preset dialog-danger-hero con copy neutra, no error-700. */
.profile-delete-hero .dialog-danger-hero__text{color:#475569;font-size:12px}
[data-theme="dark"] .profile-delete-hero .dialog-danger-hero__text{color:var(--color-text-secondary)}
.profile-delete-hero .dialog-danger-hero__text strong{display:block;color:var(--color-text);font-size:14px;letter-spacing:-.005em;margin-bottom:2px}
.subscription-block>.eyebrow--muted,.plan-promo-label{color:#475569}
[data-theme="dark"] :is(.subscription-block>.eyebrow--muted,.plan-promo-label){color:var(--color-text-secondary)}
.plan-features .is-disabled{color:var(--color-text-secondary)}


/* package: Alarmas/src/web/app/presentation/assets/packages/zz-parity-appendix.css */

/* Apendice de paridad del frontend real: componentes que el kit compone en
 * React y el port resuelve en CSS propio (historiales en modal, wizard de
 * camara, stepbar de vinculacion, builder de automatizaciones, tiles de tema).
 * Se mantiene como paquete separado y ultimo del orden para no alterar la
 * cascada de los seis paquetes por dominio. */

/* ── Historiales en modal (paridad kit TriggerLogCard / SensorHistoryItem) ── */
.hist-sticky { position: sticky; top: -18px; z-index: 5; margin: -18px -20px 12px; padding: 8px 20px 0; background: #f8f8f8; border-bottom: 1px solid var(--color-border); }
html[data-theme="dark"] .hist-sticky { background: #0f172a; }
.hist-sticky .filter-row { margin-bottom: 6px; }
.hist-sticky label.eyebrow { display: block; margin: 0 0 4px; line-height: 1.2; } /* elimina el hueco del line-box inline sobre el label del select */
.hist-sticky.sensor-history__filters { gap: 4px; margin-bottom: 12px; }
.hist-list { display: grid; gap: 8px; }
.hist-card { padding: 10px; border-radius: 12px; border: 1px solid var(--color-card-nested-border); background: #fff; }
html[data-theme="dark"] .hist-card { background: #1e293b; }
.hist-card__head { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
.hist-card__head > span:first-child { display: inline-flex; align-items: center; gap: 8px; min-width: 0; }
.hist-card__head strong { color: var(--color-text); font-size: 13px; font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.hist-card__head time { color: var(--color-text-muted); font-size: 11px; white-space: nowrap; }
.hist-card__meta { display: flex; align-items: center; gap: 6px; margin-top: 8px; flex-wrap: wrap; }
.hist-result { display: inline-flex; align-items: center; gap: 5px; padding: 3px 8px; border-radius: 9999px; font-size: 11px; font-weight: 600; background: var(--st-bg); color: var(--st-fg); }
.hist-result::before { content: ""; width: 6px; height: 6px; border-radius: 3px; background: var(--st-dot); }
.hist-srctag { padding: 3px 8px; border-radius: 6px; background: #f1f5f9; color: var(--color-text-secondary); font-size: 11px; }
html[data-theme="dark"] .hist-srctag { background: rgba(148, 163, 184, 0.12); }
.hist-stats { display: inline-flex; align-items: center; gap: 8px; margin-left: auto; color: var(--color-text-secondary); font-size: 11px; font-variant-numeric: tabular-nums; white-space: nowrap; }
.hist-stats > span { display: inline-flex; align-items: center; gap: 4px; }
.hist-stats strong { color: var(--color-text); }
.hist-minitag { padding: 1px 5px; border-radius: 4px; font-size: 9px; font-weight: 700; letter-spacing: .04em; }
.hist-minitag--cond { background: var(--color-primary-light); color: var(--color-primary-700); }
.hist-minitag--act { background: var(--color-success-light); color: var(--color-success-700); }
html[data-theme="dark"] .hist-minitag--cond { color: #93c5fd; }
html[data-theme="dark"] .hist-minitag--act { color: #86efac; }
.hist-fields { display: grid; gap: 6px; margin-top: 10px; }
.hist-fields[data-cols="1"] { grid-template-columns: 1fr; }
.hist-fields[data-cols="2"] { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.hist-fields[data-cols="3"] { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.hist-field { min-width: 0; padding: 6px 10px; border-radius: 10px; background: #f1f5f9; }
html[data-theme="dark"] .hist-field { background: #334155; }
.hist-field small { display: block; overflow: hidden; color: #475569; font-size: 10px; font-weight: 600; letter-spacing: .04em; text-overflow: ellipsis; text-transform: uppercase; white-space: nowrap; }
html[data-theme="dark"] .hist-field small { color: #cbd5e1; }
.hist-field strong { display: block; overflow: hidden; margin-top: 2px; color: var(--color-text); font-size: 13px; font-weight: 600; text-overflow: ellipsis; white-space: nowrap; }
.hist-field strong.is-on { color: var(--color-success); }
.hist-field strong.is-off { color: var(--color-text-muted); }
.hist-more { margin-top: 14px; padding: 2px 4px 5px; }
.hist-more__btn { border-radius: 9999px; }
/* Modales de historial: el section conserva su clase inline histórica (padding 14) — en modo dialog va a 0.
 * gap 0: el sticky de filtros queda pegado al divisor de la cabecera (el respiro lo da su padding-top). */
.dialog.automation-location-history, .dialog.sensor-history { padding: 0; gap: 0; }
/* Cabecera y pie FIJOS en los modales security-dialog (kit CenterDialog): solo scrollea el body.
 * automation-logs (historial de una automatización) comparte el preset: cabecera + filtros fijos. */
.security-dialog, .dialog.automation-logs, .camera-wizard, .camera-media-dialog { display: flex; flex-direction: column; overflow: hidden; }
.dialog.automation-logs { max-height: var(--modal-max-h); }
.security-dialog > .dialog-body, .dialog.automation-logs > .dialog-body, .camera-wizard > .dialog-body, .camera-media-dialog > .dialog-body { flex: 1 1 auto; min-height: 0; overflow-y: auto; }
/* Chips de filtro en fila única con scroll horizontal (kit FilterRow). */
.dialog-body .filter-row__chips { flex-wrap: nowrap; overflow-x: auto; scrollbar-width: none; }
.dialog-body .filter-row__chips::-webkit-scrollbar { display: none; }

/* ── Añadir cámara: stepbar + hints del select + snapshot (kit AddCameraModal) ── */
.camera-wizard__stepbar { display: flex; align-items: center; gap: 10px; padding: 11px 14px; border: 1px solid var(--color-border); border-radius: 12px; background: #fff; margin-bottom: 14px; }
html[data-theme="dark"] .camera-wizard__stepbar { background: rgba(30, 41, 59, .5); }
.step-dot { display: grid; place-items: center; width: 26px; height: 26px; border-radius: 50%; background: var(--color-bg-alt); color: var(--color-text-secondary); font-size: 12px; font-weight: 700; flex-shrink: 0; }
.step-dot.is-current { background: var(--color-primary); color: #fff; }
.step-dot.is-done { background: var(--color-success); color: #fff; }
.step-line { flex: 0 0 26px; height: 2px; border-radius: 1px; background: var(--color-border); }
.step-line.is-done { background: var(--color-success); }
.camera-wizard__stepinfo { display: grid; min-width: 0; margin-left: 4px; }
.camera-wizard__stepinfo strong { color: var(--color-text); font-size: 13px; }
/* OJO: esta regla era .ds-opt-hint global y pisaba el hint del preset de
 * dropdown (lo mandaba a la derecha, 11px y nowrap). Acotada al wizard. */
.camera-wizard .ds-opt-hint { margin-left: auto; padding-left: 10px; color: var(--color-text-muted); font-size: 11px; white-space: nowrap; }
.camera-snapshot { position: relative; overflow: hidden; aspect-ratio: 16 / 9; background: radial-gradient(ellipse at 30% 40%, rgba(99, 102, 241, .22) 0%, transparent 60%), radial-gradient(ellipse at 75% 70%, rgba(34, 197, 94, .14) 0%, transparent 50%), linear-gradient(135deg, #1e293b 0%, #0f172a 60%, #020617 100%); }
.camera-snapshot__obj1 { position: absolute; left: 22%; bottom: 18%; width: 36px; height: 70px; border-radius: 6px; background: rgba(148, 163, 184, .35); }
.camera-snapshot__obj2 { position: absolute; left: 46%; bottom: 14%; width: 60px; height: 40px; border-radius: 4px; background: rgba(245, 158, 11, .25); }
.camera-snapshot__badge { position: absolute; top: 8px; left: 8px; padding: 3px 8px; border-radius: 9999px; background: rgba(34, 197, 94, .85); color: #fff; font-size: 10px; font-weight: 600; letter-spacing: .08em; text-transform: uppercase; }
.camera-wizard__test { overflow: hidden; border: 1px solid var(--color-border); border-radius: 12px; margin-top: 14px; }
.camera-wizard__test-strip { display: flex; align-items: center; gap: 6px; margin: 0; padding: 10px 12px; background: var(--color-success-light); color: var(--color-success-700); font-size: 12px; }
/* ── Vincular sensor como modal (kit CreateSensorModal) ── */
.presentation-modal > .sensor-pairing, .sensor-pairing--modal { width: min(100%, 430px); max-height: var(--modal-max-h); margin: 0 auto; display: flex; flex-direction: column; }
.sensor-pairing--modal > .dialog-body { overflow-y: auto; min-height: 0; flex: 1 1 auto; }

/* Stepbar declarativo: los estados los pinta data-step (el JS solo cambia el atributo). */
.camera-wizard__stepbar[data-step="1"] .step-only-2, .camera-wizard__stepbar[data-step="2"] .step-only-1 { display: none; }
.camera-wizard__stepbar[data-step="1"] .step-dot__check { display: none; }
.camera-wizard__stepbar[data-step="2"] .step-dot__num { display: none; }
.camera-wizard__stepbar[data-step="1"] .step-dot--one { background: var(--color-primary); color: #fff; }
.camera-wizard__stepbar[data-step="2"] .step-dot--one { background: var(--color-success); color: #fff; }
.camera-wizard__stepbar[data-step="2"] .step-dot--two { background: var(--color-primary); color: #fff; }
.camera-wizard__stepbar[data-step="2"] .step-line { background: var(--color-success); }
.step-dot__check { display: grid; place-items: center; }

/* Campos de sensor: hint de límites, meta "actual:" y tono en lecturas (kit SensorField/FieldHead/ReadValue) */
.sensor-field__hint { margin-left: 4px; color: var(--color-text-secondary); font-size: 11px; font-weight: 500; letter-spacing: 0; text-transform: none; }
.sensor-field__meta { color: var(--color-text-secondary); font-size: 11px; font-weight: 500; white-space: nowrap; }
.sensor-field__meta output { color: inherit; }
.sensor-field__reading[data-tone="ok"] { color: var(--color-success-700); }
.sensor-field__reading[data-tone="warn"] { color: var(--color-warning-700); }
.sensor-field__reading[data-tone="err"] { color: var(--color-error-700); }

/* Ajustes de cámara (kit EditCameraModal): pill de conexión + card de info no editable */
.conn-pill { display: inline-flex; align-items: center; gap: 6px; flex-shrink: 0; margin-left: auto; padding: 5px 10px; border-radius: 9999px; font-size: 12px; font-weight: 600; }
.conn-pill i { width: 7px; height: 7px; border-radius: 50%; }
.conn-pill--online { background: var(--color-success-light); color: var(--color-success-700); }
.conn-pill--online i { background: var(--color-success); }
.conn-pill--offline { background: var(--color-error-light); color: var(--color-error-700); }
.conn-pill--offline i { background: var(--color-error); }
.device-info__title { margin: 0 0 8px; }
.device-info { padding: 4px; border: 1px solid var(--color-border); border-radius: 12px; background: var(--color-surface); }
.device-info__row { display: flex; align-items: center; justify-content: space-between; gap: 8px; padding: 10px; font-size: 13px; }
.device-info__row + .device-info__row { border-top: 1px solid var(--color-border); }
.device-info__row > span { display: inline-flex; align-items: center; gap: 8px; color: var(--color-text-secondary); }
.device-info__row strong { color: var(--color-text); font-weight: 600; }

/* Chrome del directo (kit streamChrome): sonido con doble icono, grabar con stop, activos kit */
.live-ico-muted, .live-ico-sound, .live-ico-rec { display: grid; place-items: center; }
[data-camera-mute][aria-pressed="true"] .live-ico-sound { display: none; }
[data-camera-mute][aria-pressed="false"] .live-ico-muted { display: none; }
[data-camera-mute][aria-pressed="false"] { background: rgba(255, 255, 255, 0.32); box-shadow: 0 0 0 3px rgba(255, 255, 255, 0.18); }
.live-rec-stop { display: none; width: 14px; height: 14px; border-radius: 4px; background: #fff; }
[data-camera-record][data-state="pending"] { background: #ef4444; box-shadow: 0 0 0 3px rgba(239, 68, 68, 0.30); }
[data-camera-record][data-state="pending"] .live-ico-rec { display: none; }
[data-camera-record][data-state="pending"] .live-rec-stop { display: block; }

/* Cinturón: un host de editar-sensor sin diálogo dentro nunca ocupa fila del grid. */
.location-devices > [data-sensor-edit-dialog]:not(:has([data-auth-dialog])) { display: none; }

/* ── Trigger form · alineación 1:1 con kit trigger-form.jsx (paste-back: fundir
 * estos valores en las reglas base del package automations) ── */
.automation-form__grid { gap: 20px; }
.automation-schedule { border-color: var(--color-border); border-radius: 10px; }
.automation-schedule__disclosure { padding: 10px 12px; background: var(--color-surface); }
.automation-schedule__icon { width: 36px; height: 36px; background: rgb(245 158 11 / 20%); color: #b45309; }
html[data-theme="dark"] .automation-schedule__icon { background: rgb(245 158 11 / 15%); color: #fbbf24; }
.automation-schedule__summary strong { font-size: 13.5px; font-weight: 600; }
.automation-schedule__summary small { font-size: 12px; }
.automation-schedule__body { gap: 14px; background: #f1f5f9; border-top-color: var(--color-border); } /* kit tk.bgAlt claro */
[data-theme="dark"] .automation-schedule__body { background: #0f172a; } /* kit tk.bgAlt oscuro = slate-900 (hundido bajo el surface) */
.automation-schedule__type strong { font-size: 12.5px; font-weight: 600; }
.automation-schedule__type small { font-size: 10.5px; }
.automation-schedule__type.is-selected { border: 1.5px solid rgb(180 83 9 / 50%); background: rgb(245 158 11 / 20%); color: var(--color-text); }
html[data-theme="dark"] .automation-schedule__type.is-selected { border-color: rgb(245 158 11 / 40%); background: rgb(245 158 11 / 15%); }
/* Días: chips 7-col, selección PRIMARY (kit WeekdayPicker) */
.automation-weekdays { display: grid; grid-template-columns: repeat(7, 1fr); gap: 4px; }
.automation-weekdays button { min-width: 0; min-height: 0; padding: 7px 0; font-size: 12px; letter-spacing: -.005em; color: var(--color-text); }
.automation-weekdays button.is-selected { border-color: var(--color-primary); background: var(--color-primary); color: #fff; }
/* Atajos de días: pills (kit preset chips) */
.automation-day-shortcuts { gap: 6px; }
.automation-day-shortcuts button { padding: 5px 10px; border: 1px solid var(--color-border); border-radius: 9999px; background: transparent; color: var(--color-text-secondary); font-size: 11px; font-weight: 600; letter-spacing: .01em; }
/* Añadir rango: card dashed (kit) */
.automation-range__add { padding: 10px; border: 1px dashed var(--color-border); border-radius: 10px; background: var(--color-surface); color: var(--color-primary-700); font-size: 12px; font-weight: 600; }
.automation-range__meta { justify-content: center; gap: 8px; }
.automation-range__meta button { color: var(--color-error-700); font-size: 11px; font-weight: 500; }
/* Guardar/Eliminar del horario: dos mitades sin divisor (kit) */
.automation-schedule__actions { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; padding-top: 4px; border-top: 0; }
/* Cabeceras de sección: pastilla UPPERCASE 11/700 (kit) */
.automation-builder > header h3 { font-size: 11px; font-weight: 700; letter-spacing: .04em; text-transform: uppercase; }
/* Editor de fila: tinte de sección (kit) y fila superior select+acciones */
/* Kit: fila 1 = select de dispositivo a todo el ancho; fila 2 = campo/op/valor + ✓ ✕ */
.automation-builder__editor { display: flex; flex-wrap: wrap; align-items: center; padding: 10px; gap: 8px; }
.automation-builder__editor > .automation-select { flex: 1 1 100%; }
.automation-builder__controls { display: flex; flex: 1 1 0; min-width: 0; align-items: center; gap: 6px; }
.automation-builder__row-actions { flex: 0 0 auto; margin-left: auto; }
/* Los triggers de select pueden encoger con ellipsis: la fila 2 nunca empuja los ✓/✕ a una 3ª fila */
.automation-builder__controls .automation-select__trigger { min-width: 0; }
.automation-builder--conditions .automation-builder__editor { border-color: rgb(59 130 246 / 25%); background: rgb(59 130 246 / 10%); }
.automation-builder--actions .automation-builder__editor { border-color: rgb(34 197 94 / 25%); background: rgb(34 197 94 / 10%); }
/* Confirmadas: centradas, tinte de sección, X a la derecha (kit) */
.automation-builder__confirmed-wrap { position: relative; }
.automation-builder__confirmed { padding: 10px 34px; text-align: center; }
.automation-builder__confirmed strong { font-size: 13px; font-weight: 600; }
.automation-builder__confirmed small { font-size: 12px; }
.automation-builder--conditions .automation-builder__confirmed { border-color: rgb(59 130 246 / 25%); background: rgb(59 130 246 / 10%); }
.automation-builder--conditions .automation-builder__confirmed small { color: var(--color-primary-600); }
.automation-builder--actions .automation-builder__confirmed { border-color: rgb(34 197 94 / 25%); background: rgb(34 197 94 / 10%); }
.automation-builder--actions .automation-builder__confirmed small { color: var(--color-action-text); }
.automation-builder__confirmed-remove { position: absolute; top: 50%; right: 8px; transform: translateY(-50%); display: grid; place-items: center; width: 24px; height: 24px; padding: 0; border: 0; border-radius: 6px; background: transparent; color: var(--color-error); cursor: pointer; }
/* Vacíos: hint dashed tintado italic (kit) */
.automation-builder__empty { margin: 0; padding: 10px 12px; border-radius: 10px; font-size: 12px; font-style: italic; line-height: 1.45; text-align: center; }
.automation-builder--conditions .automation-builder__empty { border: 1px dashed rgb(59 130 246 / 40%); background: rgb(59 130 246 / 8%); color: var(--color-primary-700); }
.automation-builder--actions .automation-builder__empty { border: 1px dashed rgb(34 197 94 / 40%); background: rgb(34 197 94 / 8%); color: var(--color-success-700); }
html[data-theme="dark"] .automation-builder--conditions .automation-builder__empty { color: #93c5fd; }
html[data-theme="dark"] .automation-builder--actions .automation-builder__empty { color: #86efac; }
/* 4 ticks: panel bg-alt de una columna (kit) */
.automation-options { grid-template-columns: 1fr; gap: 8px; padding: 12px 14px; border: 1px solid var(--color-border); border-radius: 10px; background: var(--color-bg-alt); }
.automation-options label { padding: 4px 0; border: 0; gap: 10px; color: var(--color-text); font-size: 13px; line-height: 1.35; }
.automation-options label:has(> .tick--danger) { color: var(--color-error); font-weight: 500; }
/* Emergencia: panel rojo suave del kit, hint arriba, contador a la derecha */
.automation-emergency { gap: 12px; padding: 14px; border: 1px solid rgb(239 68 68 / 30%); border-radius: 10px; background: rgb(239 68 68 / 5%); }
.automation-emergency > p { align-items: flex-start; gap: 8px; color: var(--color-text-secondary); font-size: 12px; line-height: 1.45; }
.automation-emergency textarea.field { border-color: rgb(239 68 68 / 30%); }
.automation-emergency .automation-form__field > small { color: var(--color-text-muted); font-size: 11px; text-align: right; }
@media (max-width: 560px) { .automation-options { grid-template-columns: 1fr; } }
/* Hora fija: mismo subcard que cada rango (kit: ambos comparten card surface/border r10 p10) */
.automation-schedule__fixed { padding: 10px; border: 1px solid var(--color-border); border-radius: 10px; background: var(--color-surface); } /* kit: tk.surface sobre el cuerpo bgAlt */

.automation-day-shortcuts button.is-active { border-color: var(--color-primary); background: rgb(59 130 246 / 6%); color: var(--color-primary); }
html[data-theme="dark"] .automation-day-shortcuts button.is-active { background: rgb(59 130 246 / 18%); }

/* Fila inferior del builder — tamaños kit: selects y valor a partes iguales, '=' e input al estilo TFSelect */
.automation-builder__controls .automation-select { flex: 1 1 0; min-width: 0; }
.automation-builder__controls .field {
  flex: 1 1 0; width: 0; min-width: 0; box-sizing: border-box;
  padding: 8px 10px; border: 1px solid color-mix(in srgb, var(--color-primary) 35%, transparent); border-radius: 8px;
  background: var(--color-surface-sunken); color: var(--color-text);
  font-size: 13px; font-weight: 500; text-align: center;
}
.automation-builder--actions .automation-builder__controls .field { border-color: color-mix(in srgb, var(--color-success) 35%, transparent); }
.automation-builder__equals {
  display: flex; flex-shrink: 0; align-items: center; justify-content: center;
  height: 33px; padding: 0 11px;
  border: 1px solid color-mix(in srgb, var(--color-success) 35%, transparent); border-radius: 8px;
  background: var(--color-surface-sunken); color: var(--color-text-secondary);
  font-size: 13px; font-weight: 500; opacity: .7;
}

/* Avatar del dueño en automatizaciones compartidas — mismo slot que el handle,
 * sin desplazar el título centrado. */
.automation-card__owner { position: absolute; left: 0; top: 50%; transform: translateY(-50%); display: inline-flex; }
.automation-card__owner .avatar-tile { font-size: 10px; }

/* Solo lectura (sin permiso de armar): pista rehundida plana con candado — el
 * estado activo se marca en gris neutro, sin el tono/relieve del selector real. */
.location-arm[data-arm-readonly="true"] {
  background: var(--color-surface-sunken);
  box-shadow: inset 0 0 0 1px rgb(15 23 42 / 14%), inset 0 1px 2px rgb(15 23 42 / 10%);
}
html[data-theme="dark"] .location-arm[data-arm-readonly="true"] {
  box-shadow: inset 0 0 0 1px rgb(0 0 0 / 45%), inset 0 1px 2px rgb(0 0 0 / 35%);
}
.location-arm[data-arm-readonly="true"] [data-arm-mode] { color: var(--color-text-muted); }
.location-arm[data-arm-readonly="true"] [data-arm-mode][aria-checked="true"] {
  color: var(--color-text-secondary);
  background: color-mix(in srgb, var(--color-text) 12%, transparent);
  box-shadow: none;
  transform: none;
}
/* Candado FUERA del selector (a su izquierda), en rojo */
.location-arm__lock {
  display: grid;
  place-items: center;
  align-self: center;
  flex: 0 0 auto;
  margin-right: 2px;
  color: var(--color-error);
}

/* Badge de dueño 16px (dashboard; Compartir usa 20). Ring -3px como el kit. */
.sharing-owner-badge--sm { right: -3px; bottom: -3px; }
.sharing-owner-badge--sm .avatar-tile { width: 16px; height: 16px; font-size: 6px; }

/* El modo de armado actual no se re-envía, pero sin disabled (opacity .5 del preset
 * de botones lavaba el color vivo del estado). */
.location-arm button[aria-current="true"] { pointer-events: none; }

/* ── x-collapse solo anima la altura: el espaciado vertical de los cuerpos
 * colapsables pasa a contenido interior (::before/::after), que sí se recorta
 * con la animación — sin esto el margen/padding salta en seco al final. ── */
.automation-card__details { margin-top: 0; }
.automation-card__details::before { content: ""; display: block; height: 12px; }
.automation-schedule__body { padding-top: 0; padding-bottom: 0; }
.automation-schedule__body::before, .automation-schedule__body::after { content: ""; height: 0; }
.automation-emergency { padding-top: 0; padding-bottom: 0; }
.automation-emergency::before, .automation-emergency::after { content: ""; height: 0; }

/* ── Modal Sensores del armado (kit LocationSensorsModal) ── */
.arm-sensors-hint { margin: 0 2px 12px; color: var(--color-text-secondary); font-size: 12px; line-height: 1.5; text-align: justify; }
.arm-sensor-list { display: grid; gap: 8px; }
.arm-sensor-row { display: flex; align-items: center; gap: 12px; padding: 11px 12px; border: 1px solid var(--color-border); border-radius: 12px; background: #ffffff; transition: border-color .15s ease, opacity .15s ease; }
html[data-theme="dark"] .arm-sensor-row { border-color: #334155; background: rgb(30 41 59 / 50%); }
.arm-sensor-row--bypass { border-color: rgb(245 158 11 / 35%); opacity: .85; }
html[data-theme="dark"] .arm-sensor-row--bypass { border-color: rgb(245 158 11 / 30%); }
.arm-sensor-row__icon { display: flex; flex: 0 0 auto; align-items: center; justify-content: center; width: 36px; height: 36px; border-radius: 10px; background: var(--color-primary-light); color: var(--color-primary); }
html[data-theme="dark"] .arm-sensor-row__icon { background: rgb(96 165 250 / 18%); }
.arm-sensor-row--bypass .arm-sensor-row__icon { background: #f1f5f9; color: var(--color-text-secondary); }
html[data-theme="dark"] .arm-sensor-row--bypass .arm-sensor-row__icon { background: rgb(148 163 184 / 10%); }
.arm-sensor-row__id { display: grid; flex: 1; min-width: 0; gap: 2px; }
.arm-sensor-row__id strong { overflow: hidden; color: var(--color-text); font-size: 14px; font-weight: 600; letter-spacing: -.01em; text-overflow: ellipsis; white-space: nowrap; }
.arm-sensor-row__id small { display: inline-flex; align-items: center; gap: 6px; color: var(--color-text-secondary); font-size: 12px; }
.arm-bypass-badge { display: inline-flex; align-items: center; gap: 4px; padding: 1px 6px; border-radius: 6px; background: var(--color-warning-light); color: var(--color-warning-700); font-size: 10px; font-weight: 700; letter-spacing: .04em; text-transform: uppercase; }
html[data-theme="dark"] .arm-bypass-badge { background: rgb(245 158 11 / 15%); }
.arm-sensors-empty { display: grid; justify-items: center; gap: 4px; padding: 20px; border: 1px dashed var(--color-border); border-radius: 12px; background: #f8fafc; text-align: center; }
html[data-theme="dark"] .arm-sensors-empty { background: rgb(15 23 42 / 40%); border-color: #334155; }
.arm-sensors-empty strong { margin-top: 4px; color: var(--color-text-secondary); font-size: 14px; }
.arm-sensors-empty span { color: var(--color-text-muted); font-size: 12px; line-height: 1.4; }
.arm-sensors-empty .ds-icon { color: var(--color-text-muted); }

/* ── Programación del armado (kit SchedulingModal + ScheduleRuleCard) ── */
.sched-master { display: flex; align-items: center; gap: 12px; padding: 12px; margin-bottom: 18px; border: 1px solid var(--color-border); border-radius: 12px; background: #f8fafc; cursor: pointer; outline: none; transition: background .15s ease, border-color .15s ease; }
html[data-theme="dark"] .sched-master { background: rgb(30 41 59 / 50%); border-color: #334155; }
.sched-master.is-on { background: var(--color-success-light); border-color: #bbf7d0; }
html[data-theme="dark"] .sched-master.is-on { background: rgb(34 197 94 / 10%); border-color: rgb(34 197 94 / 30%); }
.sched-master__icon { display: flex; flex: 0 0 auto; align-items: center; justify-content: center; width: 36px; height: 36px; border-radius: 10px; background: #f1f5f9; color: var(--color-text-secondary); }
/* Los spans x-show (calendar/pause) centran su svg — sin línea-base que lo suba. */
.sched-master__icon > span { display: flex; align-items: center; justify-content: center; }
html[data-theme="dark"] .sched-master__icon { background: rgb(148 163 184 / 10%); }
.sched-master.is-on .sched-master__icon { background: #dcfce7; color: var(--color-success); }
html[data-theme="dark"] .sched-master.is-on .sched-master__icon { background: rgb(34 197 94 / 20%); }
.sched-master__copy { display: grid; flex: 1; min-width: 0; gap: 2px; }
.sched-master__copy strong { color: var(--color-text); font-size: 14px; font-weight: 700; letter-spacing: -.01em; }
.sched-master__copy small { color: var(--color-text-secondary); font-size: 12px; line-height: 1.4; text-align: justify; }
.sched-body.is-paused { opacity: .55; pointer-events: none; }
.sched-rules-head { display: flex; align-items: center; justify-content: space-between; margin-bottom: 10px; }
.sched-rules-head .eyebrow b { margin-left: 6px; color: var(--color-text-muted); font-weight: 600; letter-spacing: 0; }
.sched-add { display: inline-flex; align-items: center; gap: 6px; padding: 6px 10px; border-radius: 999px; border: 1px solid color-mix(in srgb, var(--color-primary) 33%, transparent); background: color-mix(in srgb, var(--color-primary) 6%, transparent); color: var(--color-primary); font-size: 12px; font-weight: 600; letter-spacing: -.005em; cursor: pointer; }
html[data-theme="dark"] .sched-add { border-color: rgb(96 165 250 / 40%); background: rgb(59 130 246 / 18%); }
.sched-empty { display: flex; align-items: center; gap: 12px; padding: 12px; border: 1px dashed var(--color-border); border-radius: 12px; background: #ffffff; }
html[data-theme="dark"] .sched-empty { background: rgb(15 23 42 / 40%); border-color: #334155; }
.sched-empty > span:nth-child(2) { display: grid; gap: 2px; }
.sched-empty strong { color: var(--color-text-secondary); font-size: 14px; }
.sched-empty small { color: var(--color-text-muted); font-size: 12px; line-height: 1.4; }
.sched-list { display: grid; gap: 10px; }
.sched-rule { padding: 12px; border: 1px solid var(--glass-border); border-radius: 12px; background: var(--color-surface); cursor: pointer; transition: background 150ms ease, border-color 150ms ease, box-shadow 150ms ease; }
html[data-theme="dark"] .sched-rule { background: rgb(30 41 59 / 70%); }
.sched-rule.is-off { background: #f1f5f9; border-color: var(--color-border); }
html[data-theme="dark"] .sched-rule.is-off { background: #0a1020; border-color: #1e293b; }
.sched-rule.is-off .sched-rule__dim { opacity: .55; }
.sched-rule.is-open { border-color: var(--color-primary); box-shadow: 0 0 0 1px color-mix(in srgb, var(--color-primary) 20%, transparent); cursor: default; }
.sched-rule__head { position: relative; display: flex; align-items: center; justify-content: center; min-height: 36px; cursor: pointer; }
.sched-name-pill { display: inline-flex; align-items: center; max-width: 70%; padding: 6px 12px; border-radius: 9999px; background: var(--sched-bg); border: 1px solid var(--sched-border); color: var(--sched-text); font-size: 13px; font-weight: 700; letter-spacing: -.005em; white-space: nowrap; overflow: hidden; }
.sched-name-pill span { overflow: hidden; text-overflow: ellipsis; }
.sched-rule__toggle { position: absolute; right: 0; top: 50%; transform: translateY(-50%); }
.sched-dots { display: flex; justify-content: center; gap: 4px; margin-top: 12px; }
.sched-dots span { display: inline-flex; align-items: center; justify-content: center; width: 18px; height: 18px; border-radius: 5px; background: #e2e8f0; color: var(--color-text-muted); font-size: 10px; font-weight: 700; }
html[data-theme="dark"] .sched-dots span { background: rgb(148 163 184 / 12%); }
.sched-dots span.is-on { background: var(--color-primary); color: #fff; }
.sched-transitions { display: grid; grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr); align-items: center; justify-items: stretch; gap: 8px; margin-top: 10px; }
.sched-chip { display: flex; align-items: center; justify-content: center; gap: 6px; min-width: 0; overflow: hidden; box-sizing: border-box; padding: 4px 8px 4px 6px; border-radius: 9px; background: var(--arm-lt); border: 1px solid color-mix(in srgb, var(--arm-tone) 25%, transparent); color: var(--arm-deep); font-size: 12px; font-weight: 600; letter-spacing: -.005em; white-space: nowrap; }
.sched-chip b { font-variant-numeric: tabular-nums; font-weight: 700; flex-shrink: 0; }
.sched-chip small { opacity: .78; font-size: 12px; font-weight: 500; overflow: hidden; text-overflow: ellipsis; min-width: 0; }
.sched-editor { margin-top: 14px; padding-top: 14px; border-top: 1px solid var(--color-border); display: grid; gap: 8px; cursor: default; }
.sched-editor > .eyebrow { margin: 8px 0 -2px; }
.sched-editor > .eyebrow:first-child { margin-top: 0; }
.sched-part-head { display: flex; align-items: baseline; justify-content: center; gap: 8px; margin-top: 8px; }
.sched-part-head small { color: var(--color-text-muted); font-size: 11px; }
.sched-part { display: flex; align-items: center; gap: 8px; }
.sched-mode-picker { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 3px; flex: 1; min-width: 0; padding: 3px; border-radius: 10px; background: rgb(148 163 184 / 12%); }
html[data-theme="dark"] .sched-mode-picker { background: rgb(15 23 42 / 50%); }
.sched-mode-picker button { display: inline-flex; flex-direction: column; align-items: center; justify-content: center; gap: 3px; height: 40px; min-width: 0; padding: 4px 2px; border: 0; border-radius: 8px; background: transparent; color: var(--color-text-secondary); font-size: 10px; font-weight: 500; letter-spacing: -.01em; line-height: 1; white-space: nowrap; cursor: pointer; transition: background 200ms ease, color 200ms ease, box-shadow 200ms ease; }
.sched-mode-picker button span { max-width: 100%; overflow: hidden; text-overflow: ellipsis; }
.sched-mode-picker button[aria-checked="true"] { background: var(--arm-lt); color: var(--arm-deep); font-weight: 700; box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--arm-ring) 50%, transparent); }
html[data-theme="dark"] .sched-mode-picker button[aria-checked="true"] { box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--arm-ring) 33%, transparent); }
.sched-warn { display: inline-flex; align-items: center; gap: 6px; margin: 6px 2px 0; color: var(--color-warning-700); font-size: 12px; line-height: 1.5; }
.sched-editor__actions { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; margin-top: 8px; }

/* Historial del dashboard: registro desplegable (mismo detalle que trigger_logs). */
.hist-card--expandable > summary { list-style: none; cursor: pointer; }
.hist-card--expandable > summary::-webkit-details-marker { display: none; }
.hist-card__aside { display: inline-flex; align-items: center; gap: 6px; color: var(--color-text-muted); }
.hist-card__aside .ds-icon { transition: transform 160ms ease; }
.hist-card--expandable[open] > summary .hist-card__aside .ds-icon { transform: rotate(180deg); }
.hist-card--expandable > .automation-log__detail { margin-top: 10px; padding-top: 10px; border-top: 1px solid var(--color-border); }

/* Título y detalle en UNA sola línea (ellipsis); el div central puede encoger. */
.security-event > div { min-width: 0; }
.security-event > div strong { display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.security-event > div small { display: flex; align-items: center; gap: 5px; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.security-event > div small .ds-icon { flex: 0 0 auto; }
.security-event > div small .ds-icon { color: var(--color-text-muted); }

/* Selector de armado SOLO LECTURA (sin can_arm): pista hundida, estado en gris. */
.security-arm-selector--readonly { opacity: 1; background: var(--color-surface-sunken); box-shadow: inset 0 0 0 1px rgb(15 23 42 / 14%), inset 0 1px 2px rgb(15 23 42 / 10%); }
html[data-theme="dark"] .security-arm-selector--readonly { box-shadow: inset 0 0 0 1px rgb(0 0 0 / 45%), inset 0 1px 2px rgb(0 0 0 / 35%); }
.security-arm-selector--readonly > span[data-arm-mode] { display: inline-flex; flex-direction: column; align-items: center; justify-content: center; gap: 3px; padding: 6px 4px; border-radius: 8px; color: var(--color-text-muted); font-size: 10px; font-weight: 500; }
.security-arm-selector--readonly > span[data-arm-mode] span { white-space: nowrap; }
.security-arm-selector--readonly > span[data-arm-mode][aria-checked="true"] { color: var(--color-text-secondary); background: color-mix(in srgb, var(--color-text) 12%, transparent); }
span.toggle[aria-disabled="true"] { opacity: .55; cursor: default; display: inline-block; }
/* El candado del selector readonly vive junto al selector dentro del summary
 * (state-region es display:contents): se auto-alinea por el grid del summary. */
.security-card__summary .location-arm__lock { align-self: center; }

/* Card compartida sin permisos desplegables: aviso informativo con candado. */
.security-no-perms > .ds-icon { color: var(--color-text-muted); flex: 0 0 auto; }

/* Orden de armado en curso: loader girando sobre el modo destino. */
.arm-spin { display: inline-flex; animation: arm-spin 800ms linear infinite; }
@keyframes arm-spin { to { transform: rotate(360deg); } }
@media (prefers-reduced-motion: reduce) { .arm-spin { animation: none; } }

/* Hint del panel Invitar (kit SharingLinkedTab). */
.sharing-code-hint { margin: 0 0 2px; color: var(--color-text-secondary); font-size: 12px; line-height: 1.5; text-align: justify; }
/* Form de generar código: aire entre el hint y el CTA. */
.sharing-code-form { margin-top: 12px; }

/* Los tabs de Compartir nunca ensanchan la página: el item puede encoger y
 * las etiquetas caben completas (hasta 2 líneas por botón, como el kit). */
.sharing-tabs { min-width: 0; }
.sharing-tabs button { padding-inline: 6px; gap: 5px; }
.sharing-tabs button svg { width: 13px; height: 13px; }
.sharing-tabs button span { min-width: 0; white-space: normal; overflow-wrap: break-word; hyphens: auto; line-height: 1.15; text-align: left; }

/* Tab Compartido (kit SharingSharedTab): pills de permisos centradas y
 * equidistribuidas (PermPill: flex 1 1 80px, máx 120px) y filas de aviso
 * con hint (InlineToggleRow: label + hint + toggle). */
.sharing-pills { display: flex; flex-wrap: wrap; gap: 6px; justify-content: center; }
.sharing-pills .chip { flex: 1 1 80px; max-width: 120px; justify-content: center; }
/* PermPill del kit (Compartido conmigo · «Permisos concedidos»): pill azul
 * read-only 1:1 — primary100/primary700, 11/600, gap 4, pad 4·10, ellipsis;
 * equidistribución flex 1 1 80px, máx 120. Oscuro: rgba(96,165,250,.18). */
.sharing-perm-pill { display: flex; align-items: center; justify-content: center; gap: 4px; padding: 4px 10px; border-radius: 9999px; background: var(--color-primary-100); color: var(--color-primary-700); font-size: 11px; font-weight: 600; letter-spacing: .01em; flex: 1 1 80px; min-width: 0; max-width: 150px; box-sizing: border-box; white-space: nowrap; }
/* El recorte va en el TEXTO (inner span), no en el flex container: así el icono
 * nunca se pierde y la etiqueta larga («Automatizaciones») elipsa de verdad. */
.sharing-perm-pill__label { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0; }
.sharing-perm-pill svg { flex-shrink: 0; }
[data-theme="dark"] .sharing-perm-pill { background: rgba(96, 165, 250, 0.18); }
/* Variante FIT — pills de contenido largo (tipos de alerta): tamaño a contenido,
 * sin equidistribuir, para que el icono no quede fuera del pill. */
.sharing-pills--fit .chip { flex: 0 0 auto; max-width: none; }
.sharing-toggle-row { display: flex; align-items: center; gap: 10px; padding: 8px 0; }
.sharing-toggle-row + .sharing-toggle-row { border-top: 1px solid var(--color-card-nested-border); }
.sharing-toggle-row__main { flex: 1; min-width: 0; display: grid; gap: 1px; }
.sharing-toggle-row__main strong { font-size: 13px; font-weight: 600; color: var(--color-text); }
.sharing-toggle-row__main small { font-size: 11.5px; color: var(--color-text-secondary); line-height: 1.35; }

/* «Soy contacto de»: badges de tipo de alerta sangrados bajo la identidad (kit). */
.sharing-owner-row__alerts { display: flex; flex-wrap: wrap; gap: 5px; padding-left: 52px; }

/* Tab Mis invitados (kit GuestRow): cada ubicación es una inner card
 * (innerSurface + innerBorder + radio 12 + elev-pop) con tile 32,
 * nombre 13/600 y contador monoespaciado 11. */
.sharing-grant { background: var(--color-card-nested-bg); border: 1px solid var(--color-card-nested-border); border-radius: 12px; overflow: hidden; }
.sharing-grant > .disclosure { padding: 8px 10px; gap: 10px; }
.sharing-grant__name { flex: 1; min-width: 0; font-size: 13px; font-weight: 600; color: var(--color-text); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.sharing-grant__count { font-size: 11px; color: var(--color-text-secondary); font-family: ui-monospace, SFMono-Regular, Menlo, monospace; }
.sharing-permissions { border-top: 1px solid var(--color-card-nested-border); padding: 10px; margin: 0; }

/* Cabecera de lista de Compartir (kit): estática, icono + título 14/600 + badge (+ "?"). */
.sharing-card__hero { display: flex; align-items: center; gap: 8px; padding: 12px 14px; border-bottom: 1px solid var(--color-border); }
.sharing-card__hero strong { flex: 1; min-width: 0; font-size: 14px; font-weight: 600; color: var(--color-text); line-height: 1; }

/* Kit GuestRow: panel del invitado 4/14/14 con gap 8 (ubicaciones + revocar
 * dentro del mismo grid, sin separador propio). */
.sharing-guest-body { display: grid; gap: 8px; padding: 4px 14px 14px; }
.sharing-guest-body .sharing-grant-list { display: grid; gap: 8px; padding: 0; }
.sharing-guest-body .sharing-entity__revoke { padding: 0; border-top: 0; }
.sharing-location__body { padding: 0 14px 14px; }
.sharing-loading { min-height: 72px; }

/* Fila de invitado: disclosure (avatar+nombre) + papelera roja a la derecha (sin chevrón). */
.sharing-entity__row { display: flex; align-items: center; }
.sharing-entity__row > .disclosure { flex: 1; min-width: 0; }
.sharing-entity__row > .btn-icon { margin-right: 10px; flex-shrink: 0; }

/* Modal de datos de contacto del invitado (patrón info del DS). */
.contact-info-body { display: grid; gap: 14px; }
.contact-info-avatar { display: flex; justify-content: center; padding-top: 4px; }
.contact-info-list { display: grid; gap: 8px; }
.contact-info-row { display: flex; align-items: center; gap: 12px; padding: 10px 12px; border-radius: 12px; background: var(--color-card-nested-bg); border: 1px solid var(--color-card-nested-border); }
.contact-info-row__main { display: grid; gap: 1px; min-width: 0; }
.contact-info-row__main small { font-size: 11px; color: var(--color-text-secondary); }
.contact-info-row__main strong { font-size: 13.5px; font-weight: 600; color: var(--color-text); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.contact-info-row__main a { color: inherit; text-decoration: none; }
.contact-info-row__main a:hover { color: var(--color-primary-700); }

/* Papelera por ubicación en el grant (fila compacta): margen acorde al padding 8/10. */
.sharing-grant .sharing-entity__row > .btn-icon { margin-right: 6px; }

/* El resultado del código deja aire respecto al botón Generar (kit: gap 12 del panel). */
#sharing-access-code-result .code-block, #sharing-emergency-code-result .code-block { margin-top: 12px; }

/* Modal "?" de permisos (kit): una fila por permiso con descripción de una línea. */
.permissions-help-list { display: grid; gap: 8px; }
.permissions-help-row { display: flex; align-items: center; gap: 12px; padding: 10px 12px; border-radius: 12px; background: var(--color-card-nested-bg); border: 1px solid var(--color-card-nested-border); }
.permissions-help-row .icon-tile { width: 34px; height: 34px; border-radius: 9px; flex-shrink: 0; }
.permissions-help-row__main { display: grid; gap: 1px; min-width: 0; }
.permissions-help-row__main strong { font-size: 13.5px; font-weight: 600; color: var(--color-text); }
.permissions-help-row__main small { font-size: 12px; color: var(--color-text-secondary); line-height: 1.4; }

/* Modales de info de Compartir: cabecera y pie fijos, cuerpo con scroll (estándar security-dialog). */
.permissions-dialog, .contact-info-dialog { display: flex; flex-direction: column; overflow: hidden; max-height: var(--modal-max-h); }
.permissions-dialog > .dialog-body, .contact-info-dialog > .dialog-body { flex: 1 1 auto; min-height: 0; overflow-y: auto; }

/* Contacto de emergencia: bajo el nombre, solo los iconos de alertas habilitadas. */
.sharing-alert-icons { display: flex; align-items: center; gap: 6px; margin-top: 3px; min-height: 12px; }

/* ──────────────────────────────────────────────────────────────
 * MARCA — presets del DS (BRAND_PRESET: wordmark, tagline, accent,
 * launch=fundido/2300ms). El acento de marca es un token APARTE del
 * primario de UI, a propósito: re-marcar no debe mover la UI.
 * ────────────────────────────────────────────────────────────── */
:root { --brand-accent: #3b82f6; --brand-splash-duration: 2300ms; }
.brand-mark { display: block; flex-shrink: 0; }
.brand-mark--rounded { border-radius: 22%; }
.brand-lockup { display: inline-flex; align-items: center; gap: 16px; }
.brand-lockup__mark { display: block; flex-shrink: 0; }
.brand-lockup__mark--dark { display: none; }
[data-theme="dark"] .brand-lockup__mark--light { display: none; }
[data-theme="dark"] .brand-lockup__mark--dark { display: block; }
.brand-lockup__text { display: grid; gap: 3px; min-width: 0; }
.brand-lockup__name { font-size: 28px; font-weight: var(--weight-bold); line-height: 1; letter-spacing: -.02em; }
.brand-lockup__tag { font-size: 12px; opacity: .55; }
/* Marca en la topbar de auth: mark + título en el hueco central. */
.auth-system-topbar__title { display: inline-flex; align-items: center; gap: 8px; justify-content: center; min-width: 0; }
.brand-mark--on-color { border-radius: 0; }
/* Arranque — «fundido» del preset: mark con pop, wordmark y tagline en
 * cascada, y salida del overlay al 72% del ciclo. */
/* Oculto por defecto: el partial viaja en TODAS las cargas de página y, sin
 * este display:none, cada navegación mostraría un destello del arranque antes
 * de que runtime.js decida si toca reproducirlo (bug real). */
.brand-splash { display: none; }
.brand-splash.is-running { position: fixed; inset: 0; z-index: var(--z-toast); display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 14px; padding: var(--safe-top) 24px var(--safe-bottom); background: linear-gradient(160deg, var(--brand-accent), #0e1729); }
.brand-splash__mark { width: 104px; height: 104px; object-fit: contain; }
.brand-splash__wordmark { color: #fff; font-size: 27px; font-weight: var(--weight-bold); letter-spacing: -.02em; }
.brand-splash__tagline { margin-top: -9px; color: rgba(255, 255, 255, .72); font-size: 12.5px; }
@keyframes brand-splash-mark { 0% { opacity: 0; transform: scale(.9) } 22% { opacity: 1; transform: scale(1) } 48% { transform: scale(1.035) } 62% { transform: scale(1) } 100% { opacity: 1 } }
@keyframes brand-splash-wordmark { 0%, 22% { opacity: 0; transform: translateY(9px) } 48% { opacity: 1; transform: none } 100% { opacity: 1 } }
@keyframes brand-splash-tagline { 0%, 40% { opacity: 0; transform: translateY(6px) } 62% { opacity: 1; transform: none } 100% { opacity: 1 } }
@keyframes brand-splash-out { 0%, 72% { opacity: 1; transform: scale(1) } 100% { opacity: 0; transform: scale(1.06) } }
.brand-splash.is-running { animation: brand-splash-out var(--brand-splash-duration) ease forwards; }
@media (prefers-reduced-motion: reduce) { .brand-splash.is-running { display: none; } }
.brand-splash.is-running .brand-splash__mark { animation: brand-splash-mark var(--brand-splash-duration) ease both; }
.brand-splash.is-running .brand-splash__wordmark { animation: brand-splash-wordmark var(--brand-splash-duration) ease both; }
.brand-splash.is-running .brand-splash__tagline { animation: brand-splash-tagline var(--brand-splash-duration) ease both; }
html.is-booting { overflow: hidden; }
@media (prefers-reduced-motion: reduce) { .brand-splash { display: none; } }

/* ──────────────────────────────────────────────────────────────
 * SUSCRIPCIÓN (kit sharing-profile.jsx · SubscriptionBlock)
 * Dial de días restantes, bloque de renovación y filas de pago.
 * ────────────────────────────────────────────────────────────── */
.subscription-dial { position: relative; width: 96px; height: 96px; flex-shrink: 0; }
.subscription-dial svg { display: block; width: 100%; height: 100%; transform: rotate(-90deg); }
.subscription-dial__track { fill: none; stroke: #cbd5e1; stroke-width: 9; }
[data-theme="dark"] .subscription-dial__track { stroke: rgba(148, 163, 184, .22); }
.subscription-dial__fill { fill: none; stroke: var(--color-primary); stroke-width: 9; stroke-linecap: round; transition: stroke-dasharray .5s ease, stroke .15s ease; }
.subscription-dial[data-dial-tone="warning"] .subscription-dial__fill { stroke: var(--color-warning); }
.subscription-dial[data-dial-tone="danger"] .subscription-dial__fill { stroke: var(--color-error); }
.subscription-dial__value { position: absolute; inset: 0; display: flex; flex-direction: column; align-items: center; justify-content: center; color: var(--color-text); font-size: 22px; font-weight: var(--weight-bold); line-height: 1; letter-spacing: -.02em; font-variant-numeric: tabular-nums; }
.subscription-dial__value .eyebrow { margin-top: 2px; }
.subscription-renewal { flex: 1; min-width: 0; }
.subscription-renewal strong { display: block; margin-top: 2px; font-size: 18px; font-weight: var(--weight-bold); letter-spacing: -.01em; }
.subscription-price { margin: 4px 0 0; color: var(--color-text-secondary); font-size: 12px; }
.subscription-price b { color: var(--color-text); font-weight: 600; }
.subscription-price__code { display: inline-block; padding: 1px 6px; border-radius: 4px; background: var(--color-primary-100); color: var(--color-primary-700); font-size: 10px; font-weight: 600; letter-spacing: .06em; vertical-align: middle; }
/* Historial de pagos: filas a sangre con separador, como el kit. */
.subscription-inner.subscription-transactions { gap: 0; padding: 0; overflow: hidden; }
.subscription-transaction { display: flex; align-items: center; gap: 10px; padding: 10px 12px; }
.subscription-transaction + .subscription-transaction { border-top: 1px solid var(--color-border); }
.subscription-transaction > div { display: grid; flex: 1; min-width: 0; gap: 1px; }
.subscription-transaction strong { font-size: 14px; font-weight: 600; line-height: normal; font-variant-numeric: tabular-nums; }
.subscription-transaction small { color: var(--color-text-secondary); font-size: 11px; line-height: normal; }
.subscription-limit > div strong { font-variant-numeric: tabular-nums; }
.subscription-transactions .subscription-empty { padding: 18px; text-align: center; color: var(--color-text-secondary); font-size: 13px; }
.subscription-compare { justify-self: start; }
/* Aire por encima de «Plan actual» al abrir el panel. */
.subscription-stack > #current-plan { padding-top: 6px; }

/* Acciones del plan: SIEMPRE una fila (el kit no las apila en móvil). */
@media (max-width: 480px) { .subscription-actions { flex-direction: row; } }
.subscription-period { gap: 14px; }
.subscription-limit progress { height: 6px; }

/* Planes: el segmented mensual/anual ocupa la fila completa con mitades
 * iguales (era ancho-de-contenido, 159px sobre 358), y el código promocional
 * es una sola fila campo + botón. */
.plan-period { width: 100%; }
.plan-period > button { flex: 1 1 0; }
/* El #checkout-result vacío entre el slider y la rejilla suma otro hueco de la
 * rejilla .plan-picker (14+14): se colapsa mientras no tiene contenido. */
#checkout-result:empty { display: none; }
.plan-period { margin-bottom: -4px; }
/* margin-inline:auto (base F5) hace que el item de rejilla encoja al contenido
 * (271px sobre 358): se anula para que la fila ocupe el ancho completo. */
.plan-promo { grid-template-columns: minmax(0, 1fr) auto; align-items: center; margin-inline: 0; }
/* Los input[type=hidden] SÍ generan caja de rejilla y desplazaban el campo a la
 * fila siguiente: se sacan del flujo (el sr-only ya es absoluto). */
.plan-promo > input[type="hidden"] { display: none; }

/* Código promocional: título centrado y resultado compacto (título + una línea)
 * con el icono centrado en altura — .callout base alinea arriba (flex-start). */
/* El título pega con su fila: la rejilla .plan-picker separa 14px, aquí sobra. */
.plan-promo-label { text-align: center; margin-bottom: -8px; }
.promo-result-callout { align-items: center; padding: 10px 12px; }
.promo-result-callout .callout__body { display: grid; gap: 1px; min-width: 0; }
.promo-result-callout .callout__body strong { font-size: 13px; font-weight: 600; line-height: normal; }
.promo-result-callout .callout__body p { margin: 0; font-size: 12px; line-height: 1.35; }

/* Precio anterior cuando hay un código promocional aplicado. */
.plan-price__was { margin-right: 6px; color: var(--color-text-muted); font-size: .86rem; font-weight: 500; text-decoration: line-through; }

/* Opción de dropdown con hint (kit PickerList): etiqueta y hint en columna,
 * el check al final. El flex vive en el wrapper, no en la etiqueta. */
.ds-opt-main { display: grid; flex: 1; min-width: 0; }
.ds-opt-main .ds-opt-label { flex: none; }
.ds-opt[hidden] { display: none; }
/* Panel de selección dentro del perfil: la lista iba pegada arriba (4px) y con
 * demasiado aire abajo (14px), y parecía desplazada. */
.profile-panel.ds-panel { padding: 10px 14px 8px; }
/* El párrafo de estado vacío bajo la lista sumaba ~13px de aire fantasma. */
.profile-inline-result:empty { display: none; }

/* ──────────────────────────────────────────────────────────────
 * SELECTOR DE TEMA (kit sharing-profile.jsx · ThemePicker)
 * Tiles 3-en-fila con mini-maqueta del tema, check en el activo y
 * etiqueta con icono. Los colores de la maqueta son los REALES de
 * cada tema, nunca los del tema activo.
 * ────────────────────────────────────────────────────────────── */
.theme-picker { display: grid; grid-template-columns: repeat(3, 1fr); gap: 10px; }
.theme-tile { display: flex; flex-direction: column; gap: 8px; padding: 6px 6px 8px; border: 1.5px solid var(--color-card-nested-border); border-radius: 12px; background: var(--color-card-nested-bg); font-family: inherit; cursor: pointer; transition: border-color .15s ease, box-shadow .15s ease; }
.theme-tile.is-active { border-color: var(--color-primary); box-shadow: 0 0 0 3px rgba(59, 130, 246, .18); }
[data-theme="dark"] .theme-tile.is-active { box-shadow: 0 0 0 3px rgba(96, 165, 250, .25); }
.theme-tile__preview { position: relative; display: block; overflow: hidden; width: 100%; aspect-ratio: 16 / 11; border: 1px solid var(--color-card-nested-border); border-radius: 8px; }
.theme-tile__check { position: absolute; top: 4px; right: 4px; display: none; align-items: center; justify-content: center; width: 16px; height: 16px; border-radius: 50%; background: var(--color-primary); box-shadow: 0 1px 2px rgba(0, 0, 0, .3); }
.theme-tile__check svg { width: 9px; height: 9px; stroke: #fff; stroke-width: 3; }
.theme-tile.is-active .theme-tile__check { display: flex; }
.theme-tile__label { display: flex; align-items: center; justify-content: center; gap: 5px; color: var(--color-text-secondary); font-size: 12px; font-weight: 600; line-height: normal; }
.theme-tile__label svg { width: 13px; height: 13px; }
.theme-tile.is-active .theme-tile__label { color: var(--color-text); }
.theme-tile.is-active .theme-tile__label svg { stroke: var(--color-primary); }
/* Mini-maqueta: barra de 3 puntos + tarjeta con 3 líneas. */
.theme-mock { position: absolute; inset: 0; display: flex; flex-direction: column; gap: 4px; padding: 6px; }
.theme-mock__bar { display: flex; align-items: center; gap: 3px; }
.theme-mock__bar i { width: 5px; height: 5px; border-radius: 50%; }
.theme-mock__card { display: flex; flex: 1; flex-direction: column; justify-content: center; gap: 3px; padding: 5px; border-radius: 5px; border: 1px solid; }
.theme-mock__card i { height: 4px; border-radius: 2px; }
.theme-mock__card i:nth-child(1) { width: 70%; }
.theme-mock__card i:nth-child(2) { width: 92%; }
.theme-mock__card i:nth-child(3) { width: 55%; }
.theme-mock--light { background: #f1f5f9; }
.theme-mock--light .theme-mock__bar i:first-child, .theme-mock--light .theme-mock__card i:first-child { background: #3b82f6; }
.theme-mock--light .theme-mock__bar i, .theme-mock--light .theme-mock__card i { background: #cbd5e1; }
.theme-mock--light .theme-mock__bar i:first-child { background: #3b82f6; }
.theme-mock--light .theme-mock__card { background: #fff; border-color: #cbd5e1; }
.theme-mock--light .theme-mock__card i:first-child { background: #3b82f6; }
.theme-mock--dark { background: #0f172a; }
.theme-mock--dark .theme-mock__bar i, .theme-mock--dark .theme-mock__card i { background: #334155; }
.theme-mock--dark .theme-mock__bar i:first-child { background: #60a5fa; }
.theme-mock--dark .theme-mock__card { background: #1e293b; border-color: #334155; }
.theme-mock--dark .theme-mock__card i:first-child { background: #60a5fa; }
/* Tile «Sistema»: las dos maquetas partidas en diagonal + línea primaria. */
[data-theme-preview="system"] .theme-mock--light { clip-path: polygon(0 0, 56% 0, 44% 100%, 0 100%); }
[data-theme-preview="system"] .theme-mock--dark { clip-path: polygon(56% 0, 100% 0, 100% 100%, 44% 100%); }
[data-theme-preview="system"]::after { content: ""; position: absolute; top: -2px; bottom: -2px; left: 50%; width: 1.5px; transform: skewX(-14deg) translateX(-50%); background: var(--color-primary); opacity: .55; }

/* Campos del perfil — medidas del kit (ProfileField): control de 38px con
 * padding 10, texto 13px, radio 10; antes 42px de alto y 16px heredado. */
.profile-field { gap: 4px; }
.profile-field-control { min-height: 0; gap: 6px; padding: 0 10px; border-radius: 10px; }
.profile-field-control svg { width: 14px; height: 14px; }
.profile-field-control input { padding: 10px 0; font-size: 13px; line-height: normal; }
/* Solo lectura: superficie recesada + candado. El TEXTO se queda en
 * --color-text: atenuarlo además del fondo dejaba el valor en 3.86:1 en claro y
 * 2.96:1 en oscuro (mínimo AA a 13px: 4.5:1), y son justo los dos datos
 * identificativos del panel. El fondo es un velo del propio texto sobre la
 * superficie anidada, así recesa en ambos temas (--color-surface-tonal-hover en
 * oscuro es un tono medio de hover: subía el fondo en vez de recesarlo). */
.profile-field--readonly .profile-field-control { background: #f1f5f9; }
[data-theme="dark"] .profile-field--readonly .profile-field-control { background: #172033; }
.profile-field--readonly .profile-field-control input { color: var(--color-text); cursor: default; }
.profile-field-lock { display: flex; flex-shrink: 0; color: var(--color-text-muted); }
.profile-field-lock svg { width: 12px; height: 12px; }

/* Aviso de confirmación que no coincide (panel de contraseña). */
.pwd-mismatch { margin: 0; color: var(--color-error-700); font-size: 12px; }
[data-theme="dark"] .pwd-mismatch { color: var(--color-error); }

/* Nota de seguridad del panel de contraseña (cierre de sesiones). */
.pwd-sessions-note { display: flex; align-items: center; gap: 6px; margin: 0; color: var(--color-text-secondary); font-size: 12px; line-height: 1.4; }
.pwd-sessions-note svg { flex-shrink: 0; width: 13px; height: 13px; }

/* Estado de sesión en la fila de dispositivo (chip pequeño bajo la meta). */
.profile-device-metaline { display: flex; align-items: center; gap: 6px; min-width: 0; }
.profile-device-metaline small { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.profile-device-session { flex-shrink: 0; padding: 1px 7px; font-size: 10.5px; }

/* Las filas-acción son <button>: sin reset mostraban la chrome nativa del
 * navegador (fondo #efefef y borde outset), justo el «recuadro gris» alrededor
 * de «Dispositivos registrados» e «Historial de alarmas». */
button.profile-setting-row { width: 100%; border: 0; border-radius: 0; background: transparent; font-family: inherit; text-align: left; cursor: pointer; }
/* Fila de dispositivo — más compacta y con el icono centrado en su alto. */
.profile-device-row { align-items: center; gap: 9px; padding: 8px 10px; }
.profile-device-row .icon-tile { align-self: center; width: 30px; height: 30px; }
.profile-device-copy { gap: 1px; }
.profile-device-copy > strong { font-size: 13px; font-weight: 600; line-height: normal; }
.profile-device-copy > small { font-size: 11px; line-height: normal; }
.profile-device-actions { align-self: center; gap: 2px; }

/* Fila no operativa (backend pendiente): misma estética que los campos de solo
 * lectura del perfil (entrada 201) — superficie recesada literal por tema,
 * texto secundario en la copia y el icono/toggle atenuados. El texto principal
 * mantiene contraste suficiente para leerse. */
.profile-setting-row--readonly { margin: 0 -8px; padding: 10px 8px; border-radius: 10px; background: #f1f5f9; cursor: not-allowed; }
[data-theme="dark"] .profile-setting-row--readonly { background: #172033; }
/* El título se queda en --color-text: con --color-text-secondary sobre la
 * superficie recesada caía a 4.34:1, por debajo del mínimo AA a 14px (mismo
 * error que se corrigió en los campos de solo lectura). La superficie, el hint
 * «no disponible todavía» y el toggle atenuado ya comunican el estado. */
.profile-setting-row--readonly .profile-setting-copy strong { color: var(--color-text); }
/* El hint sube a texto secundario: --color-text-muted sobre la superficie
 * recesada daba 2.34:1 y ahí va la razón de que la fila esté deshabilitada. */
.profile-setting-row--readonly .profile-setting-copy small { color: #475569; }
[data-theme="dark"] .profile-setting-row--readonly .profile-setting-copy small { color: #cbd5e1; }
.profile-setting-row--readonly .icon-tile { opacity: .6; }
.profile-setting-row--readonly .toggle { opacity: .45; cursor: not-allowed; }
/* El párrafo de estado del panel de notificaciones solo ocupa sitio cuando
 * tiene mensaje; vacío dejaba ~20px de hueco tras «Historial de alarmas». */
#profile-notifications-panel > .profile-inline-result:empty { display: none; }
#profile-notifications-panel { padding-bottom: 4px; }

/* Paneles anidados del bloque de notificaciones (dispositivos e historial): el
 * mismo ritmo que el resto. .profile-alarm-history añadía 10px de padding-top
 * SOBRE los 4px del panel (15px arriba frente a 4 en dispositivos) y ambos
 * cerraban con 14px, más que los 8 de los paneles de preferencias. */
#profile-notifications-panel .profile-panel { padding-bottom: 8px; }
.profile-alarm-history { padding-top: 0; }

/* Lista de dispositivos: mismo aire arriba que abajo (8px). El panel aporta
 * 4px, así que la lista añade los 4 que faltan. */
#registered-devices .profile-device-list { padding-top: 3px; }

/* Historial de alarmas: mismo aire arriba que en la lista de dispositivos. */
#profile-alarm-history-panel .profile-history-list { padding-top: 3px; }

/* Cabecera de diálogo con más aire entre título y texto (confirmaciones sin
 * botón de cierre, donde el título manda). */
.dialog-head--roomy .dialog-title { margin-bottom: 6px; }

/* Modal de eliminar cuenta: el form envuelve cuerpo+pie, así que el scroll lo
 * aporta .dialog--scroll (preset de la entrada 169) sobre ese form. */
.profile-delete-dialog { max-width: 430px; }
/* 2 · Placa del hero como en el kit: cuadrado redondeado 44px con el rojo
 * pleno (no círculo con error-700) e icono blanco de 22px. */
.dialog--danger .dialog-danger-hero__icon { width: 44px; height: 44px; border-radius: 12px; background: var(--color-error); box-shadow: none; }
.dialog--danger .dialog-danger-hero__icon svg { width: 22px; height: 22px; }

/* Dirección (opcional) como bloque colapsable dentro del formulario. */
.location-form__collapsible { border-top: 1px solid var(--color-border); margin-top: 4px; padding-top: 10px; }
.location-form__collapsible > summary { display: flex; align-items: center; gap: 8px; list-style: none; cursor: pointer; }
.location-form__collapsible > summary::-webkit-details-marker { display: none; }
.location-form__collapsible > summary .disclosure-caret { margin-left: auto; color: var(--color-text-muted); transition: transform .2s ease; }
.location-form__collapsible[open] > summary .disclosure-caret { transform: rotate(180deg); }
.location-form__collapsible > .location-form__grid { margin-top: 12px; }

/* Instrucciones del HomeHub como colapsable (mismo patrón que «Dirección»). */
.activation-steps > .activation-steps__summary { display: flex; align-items: center; gap: 8px; list-style: none; cursor: pointer; }
.activation-steps > .activation-steps__summary::-webkit-details-marker { display: none; }
.activation-steps__summary .disclosure-caret { margin-left: auto; color: var(--color-text-muted); transition: transform .2s ease; }
.activation-steps[open] .activation-steps__summary .disclosure-caret { transform: rotate(180deg); }
.activation-steps[open] .activation-steps__list { margin-top: 10px; }

/* Estado de vinculación del HomeHub: dos líneas (rótulo + estado) con el icono
 * CENTRADO en la altura; los metadatos y la acción van en la segunda línea, no
 * apilados uno por línea. */
.homehub-activation-status { align-items: center; padding: 10px 12px; }
.homehub-activation-status > svg { align-self: center; }
/* NO grid: CSS Grid blockifica a sus hijos, así que los .meta se apilaban en
 * una línea cada uno pese al display:inline. Con block fluyen en la misma. */
.homehub-activation-status__main { display: block; min-width: 0; }
.homehub-activation-status__main > .eyebrow { display: block; }
.homehub-activation-status__main > strong { display: block; }
.homehub-activation-status__main > .eyebrow { font-size: 10.5px; }
.homehub-activation-status__main > strong { font-size: 13.5px; line-height: normal; }
.homehub-activation-status__main .meta { display: inline; margin-right: 8px; font-size: 11.5px; }
.homehub-activation-status__main .btn { display: inline-flex; margin-top: 6px; }

/* Código de activación: 32 → 27px para que el botón de copiar (38px, absoluto a
 * la derecha) no compita con las 8 cifras. */
.activation-code__code { font-size: 27px; letter-spacing: .1em; }
/* Emparejar sensores: acción del card, ancho completo bajo el estado. */
.homehub-activation__pair { display: grid; margin-top: 10px; }

/* Botones-enlace del pie de diálogo: el texto centrado como en los <button>
 * (un <a class="btn"> con icono se alineaba a la izquierda). */
.dialog-foot > a.btn { justify-content: center; text-align: center; }

/* Otra regla posterior seguía dejando __main en grid (y el grid blockifica los
 * .meta): se fija con selector descendiente, que gana por especificidad. */
.homehub-activation-status > .homehub-activation-status__main { display: block; }
.homehub-activation-status > .homehub-activation-status__main > .meta { display: inline; margin-right: 8px; }

/* «Esperando al HomeHub» + su cuenta atrás en la MISMA línea (el strong es
 * block por defecto y empujaba el TTL a una tercera). */
.homehub-activation-status > .homehub-activation-status__main > strong.is-inline { display: inline; margin-right: 8px; }

/* «Reintentar» a la derecha del estado, no bajo el texto. */
.homehub-activation-status__retry { flex-shrink: 0; margin-left: auto; }

/* El icono del estado nunca se encoge ni se desplaza, tampoco en la fila con
 * botón de reintentar. */
.homehub-activation-status > svg { flex: 0 0 auto; width: 18px; height: 18px; }

/* Sensores detectados: fila 1 = nombre a todo el ancho; fila 2 = icono (centrado
 * en su propia fila, sin contar el título) + datos + botón «+». */
.pairing-list li { grid-template-columns: auto minmax(0, 1fr) auto; grid-template-areas: "name name name" "icon meta add"; align-items: center; row-gap: 6px; }
.pairing-list__name { grid-area: name; overflow: hidden; font-size: 13.5px; font-weight: 600; text-overflow: ellipsis; white-space: nowrap; }
.pairing-list li > .icon-tile { grid-area: icon; align-self: center; }
.pairing-list__meta { grid-area: meta; display: grid; min-width: 0; gap: 2px; }
.pairing-list li { grid-template-areas: "name name add" "icon meta add"; }
.pairing-list__add { grid-area: add; align-self: center; display: grid; place-items: center; width: 36px; min-width: 36px; height: 36px; padding: 0; border-radius: 10px; box-shadow: none; }
.pairing-list__add svg { width: 16px; height: 16px; }

/* Etiqueta del botón de búsqueda: siempre dentro del círculo. */
.pair-search--searching .pair-search__label { max-width: 104px; font-size: 14px; font-family: inherit; line-height: 1.15; text-wrap: balance; }

/* Cards de listado de Compartir colapsables: la cabecera es el disparador y el
 * «?» queda fuera de él (un <button> no puede anidar otro). */
.sharing-card__hero--row { display: flex; align-items: center; gap: 8px; padding: 0; }
.sharing-card__toggle { display: flex; flex: 1; align-items: center; gap: 8px; min-width: 0; padding: 13px 4px 13px 14px; border: 0; background: transparent; color: inherit; font: inherit; text-align: left; cursor: pointer; }
.sharing-card__hero--row { gap: 4px; }
.sharing-card__hero--row .btn-help { flex-shrink: 0; margin-right: 12px; }
.sharing-card__toggle > strong { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.sharing-card__toggle > .chip { flex-shrink: 0; }

/* Toasts: superficie casi opaca. Heredaban la translucidez de .glass--strong y
 * el texto competía con el contenido de debajo (avisos que hay que leer de un
 * vistazo). Se mantiene el desenfoque del preset. */
.auth-toast { background-color: #ffffff; background-image: none; -webkit-backdrop-filter: none; backdrop-filter: none; }
[data-theme="dark"] .auth-toast { background-color: #1e293b; }


/* generated location-identity palette */

.location-tile { display: inline-flex; flex: 0 0 auto; align-items: center; justify-content: center; width: 40px; height: 40px; border-radius: 11.2px; color: #fff; }
.location-tile > img { display: block; width: 62%; height: 62%; }
.location-tile--lg { width: 48px; height: 48px; border-radius: 13.44px; }
.location-tile--blue { background: #3b82f6; }
.location-tile--green { background: #22c55e; }
.location-tile--amber { background: #f59e0b; }
.location-tile--pink { background: #ec4899; }
.location-tile--indigo { background: #6366f1; }
.location-tile--teal { background: #14b8a6; }
.location-tile--red { background: #ef4444; }

/* generated language-flag footprints */

.flag--22 { width: 22px; height: 16px; }
.flag--22.flag--circ { height: 22px; }
.flag--24 { width: 24px; height: 16px; }
.flag--24.flag--circ { height: 24px; }
