/* ============================================
   Multichannel — design tokens 2026 (CSS plano)
   ============================================ */

* { -webkit-tap-highlight-color: transparent; }
/* Sin el retardo de 300 ms del doble toque; el zoom con pellizco sigue funcionando. */
a, button, summary, label, [role="button"], input, select, textarea { touch-action: manipulation; }
/* Títulos de varias líneas sin palabra suelta al final. */
h1, h2, h3, h4 { text-wrap: balance; }
html, body { height: 100%; }
body { overscroll-behavior: none; }

:root {
  /* Color de marca (acento). Los canales RGB permiten opacidades en Tailwind
     (bg-brand-500/20) y el acento por usuario los redefine (data-accent). */
  --brand-50-rgb:236 253 245; --brand-100-rgb:209 250 229; --brand-200-rgb:167 243 208; --brand-300-rgb:110 231 183; --brand-400-rgb:52 211 153; --brand-500-rgb:16 185 129; --brand-600-rgb:5 150 105; --brand-700-rgb:4 120 87; --brand-800-rgb:6 95 70; --brand-900-rgb:6 78 59;
  --brand-rgb: var(--brand-500-rgb);
  --brand-50:rgb(var(--brand-50-rgb)); --brand-100:rgb(var(--brand-100-rgb)); --brand-200:rgb(var(--brand-200-rgb)); --brand-300:rgb(var(--brand-300-rgb)); --brand-400:rgb(var(--brand-400-rgb)); --brand-500:rgb(var(--brand-500-rgb)); --brand-600:rgb(var(--brand-600-rgb)); --brand-700:rgb(var(--brand-700-rgb)); --brand-800:rgb(var(--brand-800-rgb)); --brand-900:rgb(var(--brand-900-rgb));
  --zinc-50:#fafafa; --zinc-100:#f4f4f5; --zinc-200:#e4e4e7; --zinc-300:#d4d4d8;
  --zinc-400:#a1a1aa; --zinc-500:#71717a; --zinc-600:#52525b; --zinc-700:#3f3f46;
  --zinc-800:#27272a; --zinc-900:#18181b;

  /* ----- Tokens semánticos (light theme por defecto) ----- */
  /* Estos son los que usan los componentes; cambian con el tema. Los
     colores "crudos" de arriba se mantienen como paleta de referencia. */
  --bg-app:        var(--zinc-100);   /* fondo general de la app */
  --bg-surface:    #ffffff;            /* tarjetas, paneles */
  --bg-elevated:   #ffffff;            /* modales, dropdowns, popovers */
  --bg-hover:      var(--zinc-100);   /* hover de filas/items */
  --border-soft:   var(--zinc-200);   /* divisores y bordes sutiles */
  --border-strong: var(--zinc-300);   /* bordes más visibles */
  --text-primary:  var(--zinc-900);
  --text-secondary:var(--zinc-600);
  --text-muted:    #67676f;           /* AA como texto (5,6:1); #a1a1aa daba 2,56:1 */
  --bubble-out-bg: #d1fae5;            /* burbuja propia (verde claro) */
  --bubble-in-bg:  #ffffff;            /* burbuja ajena */
  --bubble-out-fg: #064e3b;
  --bubble-in-fg:  var(--zinc-900);
  /* Fondo del área de mensajes — crema cálido tipo WhatsApp/Telegram para que
     el bocadillo blanco (inbound) destaque sobre el fondo en vez de mimetizarse. */
  --chat-bg: #efe6d8;
  /* Patrón sutil tipo "ruido" — 3 puntos diminutos por celda de 50x50 con opacidad
     muy baja. Lo justo para dar textura sin distraer del contenido. */
  --chat-pattern: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='50' height='50' viewBox='0 0 50 50'><circle cx='12' cy='12' r='1.2' fill='%23000' fill-opacity='0.04'/><circle cx='37' cy='28' r='1' fill='%23000' fill-opacity='0.03'/><circle cx='25' cy='42' r='0.8' fill='%23000' fill-opacity='0.035'/></svg>");
  color-scheme: light;
}

/* ----- Acento por usuario (Ajustes → Apariencia) ----- */
:root[data-accent="blue"] { --brand-50-rgb:239 246 255; --brand-100-rgb:219 234 254; --brand-200-rgb:191 219 254; --brand-300-rgb:147 197 253; --brand-400-rgb:96 165 250; --brand-500-rgb:59 130 246; --brand-600-rgb:37 99 235; --brand-700-rgb:29 78 216; --brand-800-rgb:30 64 175; --brand-900-rgb:30 58 138; }
:root[data-accent="violet"] { --brand-50-rgb:245 243 255; --brand-100-rgb:237 233 254; --brand-200-rgb:221 214 254; --brand-300-rgb:196 181 253; --brand-400-rgb:167 139 250; --brand-500-rgb:139 92 246; --brand-600-rgb:124 58 237; --brand-700-rgb:109 40 217; --brand-800-rgb:91 33 182; --brand-900-rgb:76 29 149; }
:root[data-accent="rose"] { --brand-50-rgb:255 241 242; --brand-100-rgb:255 228 230; --brand-200-rgb:254 205 211; --brand-300-rgb:253 164 175; --brand-400-rgb:251 113 133; --brand-500-rgb:244 63 94; --brand-600-rgb:225 29 72; --brand-700-rgb:190 18 60; --brand-800-rgb:159 18 57; --brand-900-rgb:136 19 55; }
:root[data-accent="amber"] { --brand-50-rgb:255 251 235; --brand-100-rgb:254 243 199; --brand-200-rgb:253 230 138; --brand-300-rgb:252 211 77; --brand-400-rgb:251 191 36; --brand-500-rgb:245 158 11; --brand-600-rgb:217 119 6; --brand-700-rgb:180 83 9; --brand-800-rgb:146 64 14; --brand-900-rgb:120 53 15; }
:root[data-accent="slate"] { --brand-50-rgb:248 250 252; --brand-100-rgb:241 245 249; --brand-200-rgb:226 232 240; --brand-300-rgb:203 213 225; --brand-400-rgb:148 163 184; --brand-500-rgb:100 116 139; --brand-600-rgb:71 85 105; --brand-700-rgb:51 65 85; --brand-800-rgb:30 41 59; --brand-900-rgb:15 23 42; }

/* Fondo del chat liso (Apariencia → fondo del chat) */
:root[data-chat-bg="plain"] { --chat-pattern: none; }

/* Tamaño de letra: Tailwind usa rem, así que escala casi todo el panel. */
:root[data-text-size="sm"] { font-size: 14px; }
:root[data-text-size="lg"] { font-size: 18px; }

/* ----- DARK MODE ----- */
:root[data-theme="dark"] {
  --bg-app:        #0a0a0a;
  --bg-surface:    #18181b;
  --bg-elevated:   #27272a;
  --bg-hover:      #27272a;
  --border-soft:   #27272a;
  --border-strong: #71717a;  /* AA: #3f3f46 era casi invisible (1.7:1); ahora bordes/inputs ≥3:1 */
  --text-primary:  #fafafa;
  --text-secondary:#a1a1aa;
  --text-muted:    #909099;  /* AA: #71717a fallaba (3.1-4.1:1) como texto en superficies oscuras */
  --bubble-out-bg: #064e3b;
  --bubble-in-bg:  #27272a;
  --bubble-out-fg: #d1fae5;
  --bubble-in-fg:  #fafafa;
  /* En dark mode, fondo cálido oscuro (no negro puro) — separa visualmente
     del header/composer y hace que las burbujas grises destaquen sin chillar. */
  --chat-bg: #0e1011;
  --chat-pattern: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='50' height='50' viewBox='0 0 50 50'><circle cx='12' cy='12' r='1.2' fill='%23fff' fill-opacity='0.04'/><circle cx='37' cy='28' r='1' fill='%23fff' fill-opacity='0.03'/><circle cx='25' cy='42' r='0.8' fill='%23fff' fill-opacity='0.035'/></svg>");
  color-scheme: dark;
}

/* ----- Aplicar tokens semánticos al body y a las clases Tailwind
   más usadas. Como Tailwind CDN no permite variantes `dark:`, las
   sobreescribimos a mano en este bloque. ----- */
body { background: var(--bg-app); color: var(--text-primary); }

:root[data-theme="dark"] .bg-white { background-color: var(--bg-surface) !important; }
:root[data-theme="dark"] .bg-zinc-50,
:root[data-theme="dark"] .bg-zinc-100 { background-color: var(--bg-hover) !important; }
:root[data-theme="dark"] .bg-zinc-200 { background-color: var(--border-soft) !important; }

:root[data-theme="dark"] .text-zinc-900 { color: var(--text-primary) !important; }
:root[data-theme="dark"] .text-zinc-800,
:root[data-theme="dark"] .text-zinc-700,
:root[data-theme="dark"] .text-zinc-600 { color: var(--text-primary) !important; }
:root[data-theme="dark"] .text-zinc-500 { color: var(--text-secondary) !important; }
:root[data-theme="dark"] .text-zinc-400 { color: var(--text-muted) !important; }

/* AA (tema claro): text-zinc-400 (#a1a1aa) como TEXTO daba 2.56:1 sobre blanco.
   #67676f pasa AA en blanco (5.6), fondo de app (5.1) y la crema del chat (4.5).
   `:root .text-zinc-400` gana a la utility base de Tailwind por especificidad, pero
   NO lleva !important, así que el `hover:` y el override dark de arriba siguen
   ganando. Oscurece un punto algún icono decorativo (inocuo) y arregla decenas de
   hints/labels/contadores. */
:root .text-zinc-400 { color: #67676f; }

:root[data-theme="dark"] .border-zinc-100,
:root[data-theme="dark"] .border-zinc-200 { border-color: var(--border-soft) !important; }
:root[data-theme="dark"] .border-zinc-300 { border-color: var(--border-strong) !important; }

/* Inputs en dark mode */
:root[data-theme="dark"] .input { background: var(--bg-elevated); color: var(--text-primary); border-color: var(--border-strong); }
:root[data-theme="dark"] .input::placeholder { color: var(--text-secondary); }  /* AA: text-muted fallaba a 3.1:1 */

/* Chips: en dark mode el fondo claro se ve mal. Los oscurecemos. */
:root[data-theme="dark"] .chip-zinc { background: var(--border-soft); color: var(--text-secondary); }
:root[data-theme="dark"] .chip-emerald { background: rgba(16, 185, 129, 0.15); color: #6ee7b7; }
:root[data-theme="dark"] .chip-amber { background: rgba(245, 158, 11, 0.15); color: #fbbf24; }
:root[data-theme="dark"] .chip-red { background: rgba(239, 68, 68, 0.15); color: #fca5a5; }
:root[data-theme="dark"] .chip-blue { background: rgba(59, 130, 246, 0.15); color: #93c5fd; }
:root[data-theme="dark"] .chip-purple { background: rgba(168, 85, 247, 0.15); color: #d8b4fe; }

/* Sombras suaves dejan de ser visibles en negro — usamos borde sutil en su lugar */
:root[data-theme="dark"] .shadow-soft { box-shadow: 0 0 0 1px var(--border-soft); }

/* ============================================
   DARK MODE — overrides comprehensivos
   Tailwind CDN no soporta variantes dark:, así que cubrimos a mano todas
   las clases de color usadas en el HTML/JS. Patrón: para cada familia
   (amber/red/blue/emerald/brand/purple/pink) los bg-*-50/100/200 pasan a
   tintes RGBA del color semilla sobre el fondo oscuro (lo justo para que
   se note la familia sin "chillar"), borders se hacen más visibles, y
   text-*-600+ se aclaran a la variante -300/-400 para contraste WCAG AA.
   ============================================ */

/* Labels y elementos con var(--zinc-*) hardcodeados en CSS base */
:root[data-theme="dark"] .label { color: var(--text-secondary); }
:root[data-theme="dark"] .btn-secondary { background: var(--bg-elevated); color: var(--text-primary); }
:root[data-theme="dark"] .btn-secondary:hover { background: var(--bg-hover); }
:root[data-theme="dark"] .nav-item { color: var(--text-secondary); }
:root[data-theme="dark"] .nav-item:hover { background: var(--bg-hover); color: var(--text-primary); }
:root[data-theme="dark"] .bottom-nav-item { color: var(--text-secondary); }
:root[data-theme="dark"] .bottom-nav-item:hover { color: var(--text-primary); }
:root[data-theme="dark"] .contact-action:hover { background: var(--bg-hover); color: var(--text-primary); }
:root[data-theme="dark"] .composer-plus-btn:hover { background: var(--bg-hover); }
:root[data-theme="dark"] .composer-plus-item { color: var(--text-primary); }
:root[data-theme="dark"] .composer-plus-item:hover { background: var(--bg-hover); }
:root[data-theme="dark"] .composer-plus-menu { border-color: var(--border-soft); }
:root[data-theme="dark"] .thread-overflow-menu { border-color: var(--border-soft); }
:root[data-theme="dark"] .thread-overflow-menu button { color: var(--text-primary); }
:root[data-theme="dark"] .thread-overflow-menu button:hover { background: var(--bg-hover); }
:root[data-theme="dark"] .thread-overflow-menu button.danger { color: #fca5a5; }
:root[data-theme="dark"] .sheet-handle { background: var(--border-strong); }

/* ---- AMBER (warnings, fuera de ventana 24h) ---- */
:root[data-theme="dark"] .bg-amber-50  { background-color: rgba(245, 158, 11, 0.12) !important; }
:root[data-theme="dark"] .bg-amber-100 { background-color: rgba(245, 158, 11, 0.18) !important; }
:root[data-theme="dark"] .bg-amber-200 { background-color: rgba(245, 158, 11, 0.25) !important; }
:root[data-theme="dark"] .border-amber-200 { border-color: rgba(245, 158, 11, 0.35) !important; }
:root[data-theme="dark"] .border-amber-300 { border-color: rgba(245, 158, 11, 0.45) !important; }
:root[data-theme="dark"] .border-amber-400 { border-color: rgba(245, 158, 11, 0.55) !important; }
:root[data-theme="dark"] .text-amber-600 { color: #fcd34d !important; }
:root[data-theme="dark"] .text-amber-700,
:root[data-theme="dark"] .text-amber-800,
:root[data-theme="dark"] .text-amber-900 { color: #fbbf24 !important; }
:root[data-theme="dark"] .hover\:bg-amber-200:hover { background-color: rgba(245, 158, 11, 0.30) !important; }
:root[data-theme="dark"] .hover\:bg-amber-700:hover { background-color: #b45309 !important; }

/* ---- RED (errores, danger) ---- */
:root[data-theme="dark"] .bg-red-50 { background-color: rgba(239, 68, 68, 0.12) !important; }
:root[data-theme="dark"] .border-red-200 { border-color: rgba(239, 68, 68, 0.35) !important; }
:root[data-theme="dark"] .border-red-400 { border-color: rgba(239, 68, 68, 0.55) !important; }
:root[data-theme="dark"] .text-red-500,
:root[data-theme="dark"] .text-red-600,
:root[data-theme="dark"] .text-red-700,
:root[data-theme="dark"] .text-red-800,
:root[data-theme="dark"] .text-red-900 { color: #fca5a5 !important; }
:root[data-theme="dark"] .hover\:bg-red-50:hover { background-color: rgba(239, 68, 68, 0.15) !important; }
/* bg-red-500/600/700 son saturados — se ven bien en dark sin tocar */

/* ---- BLUE (info) ---- */
:root[data-theme="dark"] .bg-blue-50  { background-color: rgba(59, 130, 246, 0.12) !important; }
:root[data-theme="dark"] .bg-blue-100 { background-color: rgba(59, 130, 246, 0.18) !important; }
:root[data-theme="dark"] .border-blue-200 { border-color: rgba(59, 130, 246, 0.35) !important; }
:root[data-theme="dark"] .text-blue-600,
:root[data-theme="dark"] .text-blue-700,
:root[data-theme="dark"] .text-blue-800,
:root[data-theme="dark"] .text-blue-900 { color: #93c5fd !important; }

/* ---- EMERALD + BRAND (mismo tono — el brand de la app es emerald-500) ---- */
:root[data-theme="dark"] .bg-emerald-50  { background-color: rgba(16, 185, 129, 0.12) !important; }
:root[data-theme="dark"] .bg-emerald-100 { background-color: rgba(16, 185, 129, 0.18) !important; }
:root[data-theme="dark"] .bg-brand-50    { background-color: rgb(var(--brand-rgb) / 0.12) !important; }
:root[data-theme="dark"] .bg-brand-100   { background-color: rgb(var(--brand-rgb) / 0.18) !important; }
:root[data-theme="dark"] .border-emerald-200 { border-color: rgba(16, 185, 129, 0.35) !important; }
:root[data-theme="dark"] .border-brand-500 { border-color: var(--brand-500) !important; }
:root[data-theme="dark"] .text-emerald-600,
:root[data-theme="dark"] .text-emerald-700,
:root[data-theme="dark"] .text-emerald-800,
:root[data-theme="dark"] .text-emerald-900,
:root[data-theme="dark"] .text-brand-600,
:root[data-theme="dark"] .text-brand-700 { color: var(--brand-300) !important; }
:root[data-theme="dark"] .hover\:bg-brand-50:hover { background-color: rgb(var(--brand-rgb) / 0.12) !important; }
:root[data-theme="dark"] .hover\:bg-brand-100:hover { background-color: rgb(var(--brand-rgb) / 0.22) !important; }

/* ---- PURPLE ---- */
:root[data-theme="dark"] .bg-purple-50 { background-color: rgba(168, 85, 247, 0.12) !important; }
:root[data-theme="dark"] .text-purple-700,
:root[data-theme="dark"] .text-purple-800 { color: #d8b4fe !important; }

/* ---- PINK ---- */
:root[data-theme="dark"] .bg-pink-100 { background-color: rgba(236, 72, 153, 0.18) !important; }

/* ---- Hover sobre fondos zinc (Tailwind: hover:bg-zinc-N) ---- */
:root[data-theme="dark"] .hover\:bg-zinc-50:hover,
:root[data-theme="dark"] .hover\:bg-zinc-100:hover,
:root[data-theme="dark"] .hover\:bg-zinc-200:hover { background-color: var(--bg-hover) !important; }

/* ---- bg-zinc-900: NO lo flipamos globalmente. Lo usan paneles de código
   (#setup-output, #apikey-plain, #listen-raw) que quieren conservar el
   look "terminal oscuro" incluso en dark mode. Sólo se trata aparte el
   toast (más abajo). ---- */
:root[data-theme="dark"] .bg-zinc-400 { background-color: var(--zinc-600) !important; }

/* ---- text-zinc-100 (era texto claro sobre oscuro) → mantener claro ---- */
:root[data-theme="dark"] .text-zinc-100 { color: var(--text-primary) !important; }

/* ---- text-emerald-300 ya es claro, no cambia. Lo dejamos explícito por claridad. ---- */
:root[data-theme="dark"] .text-emerald-300 { color: #6ee7b7 !important; }

/* ============================================
   DARK MODE — pasada 3 (gaps post v2.21)
   Selectores componentes nuevos (listas/tags, bubble template, picker,
   cards de media) + sombras de palette tokens hardcodeados que pasaron
   por alto las pasadas 1 y 2.
   ============================================ */

/* border-brand-200 (toolbar bulk, chip-brand) — faltaba */
:root[data-theme="dark"] .border-brand-200 { border-color: rgb(var(--brand-rgb) / 0.35) !important; }
:root[data-theme="dark"] .border-brand-100 { border-color: rgb(var(--brand-rgb) / 0.25) !important; }

/* .btn-chip — botones interactivos dentro de bubbles + en plantillas */
:root[data-theme="dark"] .btn-chip {
  background: var(--bg-elevated);
  border-color: var(--border-strong);
  color: var(--text-primary);
}
:root[data-theme="dark"] .btn-chip.selected {
  background: rgb(var(--brand-rgb) / 0.20);
  border-color: var(--brand-500);
  color: var(--brand-300);
  box-shadow: 0 0 0 2px rgb(var(--brand-rgb) / 0.25);
}

/* .reaction-chip — borde palette + sombra inútil en dark */
:root[data-theme="dark"] .reaction-chip {
  background: var(--bg-elevated);
  border-color: var(--border-strong);
  color: var(--text-primary);
  box-shadow: 0 2px 5px rgb(0 0 0 / 0.4);
}

/* .read-ind y .cm-card-date — colores zinc-500 sobre superficies oscuras
   no llegan al contraste WCAG AA. */
:root[data-theme="dark"] .read-ind,
:root[data-theme="dark"] .cm-card-date,
:root[data-theme="dark"] .bubble-meta {
  color: var(--text-secondary);  /* #a1a1aa = zinc-400 — más legible en dark */
}

/* .chip-brand (gallery) — palette tokens hardcodeados */
:root[data-theme="dark"] .chip-brand {
  background: rgb(var(--brand-rgb) / 0.15) !important;
  color: var(--brand-300) !important;
  border-color: rgb(var(--brand-rgb) / 0.30) !important;
}

/* .cm-card (gallery card de /multi) y descendientes */
:root[data-theme="dark"] .cm-card {
  background: var(--bg-elevated);
  border-color: var(--border-soft);
}
:root[data-theme="dark"] .cm-card:hover {
  border-color: var(--border-strong);
  box-shadow: 0 4px 12px rgb(0 0 0 / 0.35);
}
:root[data-theme="dark"] .cm-thumb-img,
:root[data-theme="dark"] .cm-thumb-icon {
  background: var(--bg-hover);
}
:root[data-theme="dark"] .cm-card-name {
  color: var(--text-primary);
}

/* ---- Componentes internos con var(--zinc-*) hardcodeado en su CSS ---- */
/* var(--zinc-100) es #f4f4f5 (gris muy claro) — bien para hover en light,
   pero en dark se ve como un destello blanco. Lo mapeamos a --bg-hover. */
:root[data-theme="dark"] .bubble-actions button { background: var(--bg-surface); border-color: var(--border-soft); }
:root[data-theme="dark"] .bubble-actions button:hover { background: var(--bg-hover); }
:root[data-theme="dark"] .ctx-item { color: var(--text-primary); }
:root[data-theme="dark"] .ctx-item:hover { background: var(--bg-hover); }
:root[data-theme="dark"] .drawer-item { color: var(--text-primary); }
:root[data-theme="dark"] .drawer-item:hover { background: var(--bg-hover); }

/* ---- .danger variants (rojo oscuro sobre claro → rojo claro sobre oscuro) ---- */
:root[data-theme="dark"] .contact-action.danger,
:root[data-theme="dark"] .ctx-item.danger,
:root[data-theme="dark"] .channel-action.danger,
:root[data-theme="dark"] .drawer-item.danger { color: #fca5a5; }
:root[data-theme="dark"] .contact-action.danger:hover,
:root[data-theme="dark"] .ctx-item.danger:hover,
:root[data-theme="dark"] .channel-action.danger:hover { background: rgba(239, 68, 68, 0.15); color: #fca5a5; }

/* ---- Status badges de plantillas (rojo/ámbar tintados) ---- */
:root[data-theme="dark"] .tpl-status-REJECTED { background: rgba(239, 68, 68, 0.15) !important; color: #fca5a5 !important; }
:root[data-theme="dark"] .tpl-status-PENDING  { background: rgba(245, 158, 11, 0.15) !important; color: #fbbf24 !important; }

/* ---- Chips en su forma light-mode (líneas 1017+) — ya cubiertos arriba
   por chip-amber/red/blue/purple. La variante zinc no listada explícitamente: ---- */

/* ---- Snippet language remove button ---- */
:root[data-theme="dark"] .snip-lang-x:hover { background: rgba(255, 255, 255, 0.08); color: #fca5a5; }

/* ---- Status icons readables sobre cualquier fondo (ya eran colores
   saturados, los dejamos como están). Sólo .status-PENDING/SENT/DELIVERED
   que usaban zinc-500: ---- */
:root[data-theme="dark"] .status-PENDING,
:root[data-theme="dark"] .status-SENT,
:root[data-theme="dark"] .status-DELIVERED { color: var(--text-secondary); }

/* ============================================
   DARK MODE — pasada 2 (hallazgos del audit)
   ============================================ */

/* text-amber-900 / text-blue-700-800 / text-purple-700-800 — explícitos
   (estaban via selectores múltiples pero rematamos por claridad). */
:root[data-theme="dark"] .text-amber-900 { color: #fbbf24 !important; }
:root[data-theme="dark"] .text-blue-700,
:root[data-theme="dark"] .text-blue-800 { color: #93c5fd !important; }

/* Modales: descripciones/help text en zinc-500 sobre superficie oscura
   pasan a text-muted para mejor legibilidad sin perder la jerarquía. */
:root[data-theme="dark"] .sheet-content .text-zinc-500 { color: var(--text-secondary); }

/* Border en placeholders/info boxes que usan border-zinc-200 + bg-zinc-50
   (e.g. #tpl-params-preview): borde algo más visible en dark. */
:root[data-theme="dark"] #tpl-params-preview { border-color: var(--border-strong) !important; }

/* Composer text placeholder — el text-muted era demasiado oscuro
   para distinguirlo del bg del input en dark. */
:root[data-theme="dark"] #composer-text::placeholder,
:root[data-theme="dark"] textarea::placeholder { color: #a1a1aa !important; }

/* Toast (#toast con bg-zinc-900 + text-white): en dark, el zinc-900 se
   mimetiza con el fondo de la app. Le damos surface elevado + borde
   para que destaque sin perder la legibilidad del texto blanco. */
:root[data-theme="dark"] #toast { background-color: var(--bg-elevated) !important; border: 1px solid var(--border-strong); }

/* Avatar placeholder (gris inline en el JS,
   line 5690 de app.js). En dark el degradado se camuflaba con el fondo.
   Subimos los tonos vía sobrecarga del style inline con CSS variable
   en el componente .contact-avatar. */
:root[data-theme="dark"] .contact-avatar[style*="71717a"] {
  background: #71717a !important;
}

/* ---- Estilos inline hardcodeados con hex en app.js ----
   Patrón: hex de luz (success/error/warning bgs y colores) en JS via
   `el.style.background = '#xxx'`. CSS no llega ahí por especificidad
   sin !important, así que usamos selectores de atributo. */

/* Success boxes: #ecfdf5 (emerald-50 bg) + #065f46 (emerald-900 fg) */
:root[data-theme="dark"] [style*="background: #ecfdf5"],
:root[data-theme="dark"] [style*="background:#ecfdf5"] { background: rgba(16, 185, 129, 0.15) !important; }
:root[data-theme="dark"] [style*="color: #065f46"],
:root[data-theme="dark"] [style*="color:#065f46"],
:root[data-theme="dark"] [style*="color: #047857"],
:root[data-theme="dark"] [style*="color:#047857"] { color: #6ee7b7 !important; }

/* Error boxes: #fef2f2 (red-50 bg) + #991b1b (red-900 fg) */
:root[data-theme="dark"] [style*="background: #fef2f2"],
:root[data-theme="dark"] [style*="background:#fef2f2"] { background: rgba(239, 68, 68, 0.15) !important; }
:root[data-theme="dark"] [style*="color: #991b1b"],
:root[data-theme="dark"] [style*="color:#991b1b"],
:root[data-theme="dark"] [style*="color: #dc2626"],
:root[data-theme="dark"] [style*="color:#dc2626"],
:root[data-theme="dark"] [style*="color: #b91c1c"],
:root[data-theme="dark"] [style*="color:#b91c1c"] { color: #fca5a5 !important; }

/* Warning text: #a16207 (amber-700) y #92400e (amber-900) */
:root[data-theme="dark"] [style*="color: #a16207"],
:root[data-theme="dark"] [style*="color:#a16207"],
:root[data-theme="dark"] [style*="color: #92400e"],
:root[data-theme="dark"] [style*="color:#92400e"] { color: #fbbf24 !important; }

/* Plugin status badge: pequeños puntos con #16a34a (loaded) / #dc2626 (error) /
   #71717a (idle) usados como bg con alpha .1a y color sólido. */
:root[data-theme="dark"] [style*="color: #16a34a"],
:root[data-theme="dark"] [style*="color:#16a34a"] { color: #6ee7b7 !important; }
:root[data-theme="dark"] [style*="color: #71717a"],
:root[data-theme="dark"] [style*="color:#71717a"] { color: #a1a1aa !important; }

/* ============================================
   Clases reutilizables para resultados / contadores
   (sustituyen los inline `el.style.background = '#xxx'` del JS, que el
   navegador normaliza a rgb() rompiendo cualquier selector [style*="#hex"])
   ============================================ */

/* Cajas de resultado (channel test, rule test) — bg/fg auto-flipan con el tema. */
.result-ok      { background: #ecfdf5; color: #065f46; }
.result-error   { background: #fef2f2; color: #991b1b; }
.result-neutral { background: var(--zinc-100); color: var(--zinc-700); }

:root[data-theme="dark"] .result-ok      { background: rgba(16, 185, 129, 0.15); color: #6ee7b7; }
:root[data-theme="dark"] .result-error   { background: rgba(239, 68, 68, 0.15); color: #fca5a5; }
:root[data-theme="dark"] .result-neutral { background: var(--bg-elevated); color: var(--text-primary); }

/* Composer counter — color rojo (over), ámbar (near), emerald (markdown). */
.counter-over { color: #dc2626; }
.counter-near { color: #a16207; }
.counter-md   { color: #047857; }

:root[data-theme="dark"] .counter-over { color: #fca5a5; }
:root[data-theme="dark"] .counter-near { color: #fbbf24; }
:root[data-theme="dark"] .counter-md   { color: #6ee7b7; }

/* ---------- Accesibilidad: foco de teclado, sr-only, motion reducido ---------- */

/* Foco de teclado visible y consistente en todo control interactivo.
   Solo :focus-visible para no molestar al ratón. Los .input/select.input ya
   tienen su propio halo (línea ~413); aquí cubrimos botones, enlaces, summary,
   elementos con tabindex y los checkbox/radio nativos, que es donde faltaba. */
button:focus-visible,
a:focus-visible,
summary:focus-visible,
[tabindex]:focus-visible,
input[type="checkbox"]:focus-visible,
input[type="radio"]:focus-visible {
  /* brand-500 sobre blanco daba 2,54:1 (por debajo del 3:1 de WCAG 1.4.11 para un
     indicador de foco); brand-700 sube a 5,25:1. */
  outline: 2px solid var(--brand-700);
  outline-offset: 2px;
}
:root[data-theme="dark"] button:focus-visible,
:root[data-theme="dark"] a:focus-visible,
:root[data-theme="dark"] summary:focus-visible,
:root[data-theme="dark"] [tabindex]:focus-visible,
:root[data-theme="dark"] input[type="checkbox"]:focus-visible,
:root[data-theme="dark"] input[type="radio"]:focus-visible {
  outline-color: #6ee7b7;
}

/* Texto solo para lectores de pantalla (etiquetas de estado, contexto). */
.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;
}

/* Estado de entrega del mensaje: el glyph es decorativo (role=img lo nombra). */
.msg-status { cursor: default; }

/* Respeto a prefers-reduced-motion: anula entradas de sheets/modales, pulse de
   grabación, rotación de chevrons, etc. dejando transiciones casi instantáneas. */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
}

/* ---------- Inputs/labels/botones ---------- */

.input {
  width: 100%;
  padding: 8px 12px;
  font-size: 14px;
  background: var(--bg-surface);
  border: 1px solid var(--zinc-200);
  border-radius: 8px;
  outline: none;
  transition: border-color 0.15s, box-shadow 0.15s;
  font-family: inherit;
}
.input::placeholder { color: var(--zinc-500); }  /* AA: zinc-400 (#a1a1aa) fallaba a 2.6:1 */
.input:focus { border-color: var(--brand-500); box-shadow: 0 0 0 3px rgb(var(--brand-rgb) / 0.15); }
.input.text-xs { font-size: 12px; padding: 6px 10px; }

.label {
  display: block;
  font-size: 12px;
  font-weight: 500;
  color: var(--zinc-600);
  margin-bottom: 6px;
}

.btn-primary, .btn-secondary, .btn-ghost {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  padding: 8px 16px;
  font-size: 14px;
  font-weight: 500;
  border-radius: 8px;
  cursor: pointer;
  transition: background 0.15s, color 0.15s, border-color 0.15s, opacity 0.15s;
  border: none;
  font-family: inherit;
}
.btn-primary { background: var(--brand-700); color: white; }  /* AA: blanco sobre 600 daba 3,77:1 */
.btn-primary:hover { background: var(--brand-800); }
.btn-primary:active { background: var(--brand-900); }
.btn-primary:disabled { opacity: 0.5; cursor: not-allowed; }
.btn-secondary { background: var(--zinc-100); color: var(--zinc-900); }
.btn-secondary:hover { background: var(--zinc-200); }
.btn-ghost { background: var(--bg-surface); color: var(--text-primary); border: 1px solid var(--border-soft); }
.btn-ghost:hover { background: var(--bg-hover); }

/* Botón de solo icono. No tenía estilo base: en escritorio medía lo que el icono
   (12-16 px), p. ej. los de copiar URL en Canales. 28 px de diana y un fondo al
   pasar por encima; en táctil sube a 44 px (regla de móvil más abajo). */
.btn-icon {
  display: inline-flex; align-items: center; justify-content: center;
  min-width: 28px; min-height: 28px; padding: 4px;
  border-radius: 6px; background: transparent; border: none; cursor: pointer;
  transition: background 0.15s;
}
.btn-icon:hover { background: var(--bg-hover); }

/* ---------- Sidebar nav ---------- */

.nav-item {
  width: 100%;
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 8px 12px;
  border-radius: 8px;
  font-size: 14px;
  font-weight: 500;
  color: var(--zinc-600);
  background: transparent;
  border: none;
  cursor: pointer;
  text-align: left;
  transition: background 0.15s, color 0.15s;
  font-family: inherit;
}
.nav-item:hover { background: var(--zinc-100); color: var(--zinc-900); }
.nav-active { background: var(--brand-50); color: var(--brand-700); }
.nav-active:hover { background: var(--brand-100); color: var(--brand-700); }

/* Grupo desplegable en el sidebar */
.nav-group { margin: 0; }
.nav-group summary { list-style: none; cursor: pointer; }
.nav-group summary::-webkit-details-marker { display: none; }
.nav-summary {
  /* Hereda .nav-item pero como summary debe gestionar bien el chevron */
  width: 100%;
}
.nav-chevron { transition: transform 0.15s; }
.nav-group[open] .nav-chevron { transform: rotate(180deg); }
.nav-sub {
  padding-left: 16px;
  display: flex;
  flex-direction: column;
  gap: 1px;
}
.nav-sub-item {
  font-size: 13px;
  padding-left: 12px;
}

/* ---------- Bottom nav ---------- */

.bottom-nav-item {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 2px;
  padding: 8px 0;
  font-size: 10px;
  font-weight: 500;
  color: var(--zinc-500);
  background: transparent;
  border: none;
  cursor: pointer;
  font-family: inherit;
  transition: color 0.15s;
}
.bottom-nav-item:hover { color: var(--zinc-900); }
.bottom-nav-active { color: var(--brand-700); }

/* ---------- Sheets / Modales ---------- */

.sheet {
  position: fixed; inset: 0; z-index: 50;
  display: flex; align-items: flex-end; justify-content: center;
}
@media (min-width: 768px) {
  .sheet { align-items: center; }
}
.sheet-backdrop {
  position: absolute; inset: 0;
  background: rgb(0 0 0 / 0.45);
  backdrop-filter: blur(2px);
  animation: fade-in 0.15s ease-out;
}
.sheet-content {
  position: relative;
  width: 100%;
  background: var(--bg-surface);
  border-top-left-radius: 20px; border-top-right-radius: 20px;
  box-shadow: 0 -8px 32px rgb(0 0 0 / 0.12);
  animation: slide-up 0.2s ease-out;
}
@media (min-width: 768px) {
  .sheet-content {
    border-radius: 16px;
    box-shadow: 0 20px 60px rgb(0 0 0 / 0.2);
    animation: pop-in 0.18s ease-out;
    margin: 1rem;
  }
}
.sheet-handle {
  width: 40px; height: 4px;
  background: var(--zinc-300);
  border-radius: 2px;
  margin: 8px auto 0;
}
@keyframes fade-in { from { opacity: 0; } to { opacity: 1; } }
@keyframes slide-up { from { transform: translateY(100%); } to { transform: translateY(0); } }
@keyframes pop-in {
  from { opacity: 0; transform: scale(0.96); }
  to { opacity: 1; transform: scale(1); }
}

/* ---------- Lista de contactos ---------- */

.contact-item {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 10px 12px;
  cursor: pointer;
  border-bottom: 1px solid var(--zinc-100);
  transition: background 0.15s;
}
/* Filas que son <button> (búsqueda, personas, grupos): sin el aspecto nativo del botón. */
button.contact-item { width: 100%; text-align: left; font: inherit; color: inherit; background: transparent; border: 0; border-bottom: 1px solid var(--zinc-100); }
.contact-item:hover { background: var(--bg-hover); }  /* token: con --zinc-50 fijo, en oscuro el nombre desaparecía */
.contact-item.active { background: var(--brand-50); }
.contact-item.active:hover { background: var(--brand-50); }

/* providerStatus = 'undeliverable' (Meta errorCode 131026: el número no tiene
   WhatsApp). Marcamos con borde izquierdo rojo + ligera atenuación para que
   el operador lo distinga de un vistazo en el listado lateral. */
.contact-item.contact-undeliverable {
  /* Sin franja lateral de color (DESIGN.md): el estado lo dice la insignia de texto
     de la fila; la fila solo se atenúa. */
  opacity: 0.78;
}
.contact-item.contact-undeliverable:hover { opacity: 0.95; }
.contact-item.contact-undeliverable.active { opacity: 1; }
/* El chip "⚠ Sin WA" es clickable (reset manual) → cursor pointer. */
.contact-item [data-clear-provider] { cursor: pointer; }
.contact-item [data-clear-provider]:hover { filter: brightness(1.1); }

/* ---------- Tabs de listas (tags) sobre el listado de contactos ---------- */
.tag-tab {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 4px 10px;
  font-size: 12px;
  font-weight: 500;
  color: var(--zinc-700);
  background: transparent;
  border: 1px solid transparent;
  border-radius: 999px;
  cursor: pointer;
  transition: background 0.15s, color 0.15s, border-color 0.15s;
  flex-shrink: 0;
}
.tag-tab:hover { background: var(--zinc-100); color: var(--zinc-900); }
.tag-tab.tag-tab-active {
  background: var(--brand-50);
  color: var(--brand-700);
  border-color: var(--brand-200, #a7f3d0);
}
.tag-tab-count {
  display: inline-block;
  min-width: 18px;
  padding: 0 5px;
  font-size: 10px;
  background: var(--zinc-200);
  color: var(--zinc-700);
  border-radius: 999px;
  font-weight: 600;
}
.tag-tab-active .tag-tab-count { background: var(--brand-700); color: white; }
/* Hint discreto cuando aún no hay ninguna lista creada en el canal. */
.tag-tab-hint {
  display: inline-flex;
  align-items: center;
  padding: 4px 8px;
  font-size: 11px;
  color: var(--zinc-400);
  font-style: italic;
  cursor: help;
  flex-shrink: 0;
}
:root[data-theme="dark"] .tag-tab-hint { color: var(--text-muted); }
:root[data-theme="dark"] .tag-tab { color: var(--text-secondary); }
:root[data-theme="dark"] .tag-tab:hover { background: var(--bg-hover); color: var(--text-primary); }
:root[data-theme="dark"] .tag-tab.tag-tab-active {
  background: rgb(var(--brand-rgb) / 0.15);
  color: var(--brand-300);
  border-color: rgb(var(--brand-rgb) / 0.35);
}
:root[data-theme="dark"] .tag-tab-count { background: var(--bg-elevated); color: var(--text-secondary); }

/* ---------- Checkbox de selección bulk en cada contact-item ---------- */
.contact-checkbox {
  flex-shrink: 0;
  width: 16px;
  height: 16px;
  margin-right: 2px;
  cursor: pointer;
  accent-color: var(--brand-600);
  /* Por defecto sólo se ve al hover sobre el contact-item, para no saturar
     visualmente cuando no se está usando la función bulk. */
  opacity: 0;
  transition: opacity 0.15s;
}
.contact-item:hover .contact-checkbox,
.contact-item.contact-selected .contact-checkbox,
.contact-checkbox:checked,
.contact-checkbox:focus-visible { opacity: 1; }
/* Si hay AL MENOS uno seleccionado, mostrar todos los checkboxes para que
   el modo "selección" sea evidente. La clase .has-selection se aplica al
   contacts-list desde JS. */
#contacts-list.has-selection .contact-checkbox { opacity: 1; }

.contact-item.contact-selected {
  background: var(--brand-50);
}
.contact-item.contact-selected:hover { background: var(--brand-100); }
:root[data-theme="dark"] .contact-item.contact-selected { background: rgb(var(--brand-rgb) / 0.12); }
:root[data-theme="dark"] .contact-item.contact-selected:hover { background: rgb(var(--brand-rgb) / 0.20); }

.contact-avatar {
  width: 40px; height: 40px;
  border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  color: white; font-weight: 600; font-size: 14px;
  flex-shrink: 0;
  background: var(--brand-700);
  object-fit: cover;  /* importante cuando es <img> */
  overflow: hidden;
}
/* Cuando .contact-avatar es una <img>, el contenido es la imagen — quitamos
   el fondo para que no se vea borde. */
img.contact-avatar { background: transparent; }
.contact-item { align-items: flex-start; }
.contact-meta { flex: 1; min-width: 0; }
.contact-name {
  font-size: 14px; font-weight: 500; color: var(--zinc-900);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.contact-waid {
  font-size: 12px; color: var(--text-secondary);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
/* Hora del último mensaje y «Tú:»/«Bot:» delante de la vista previa. */
.contact-when { flex: none; font-size: 11px; font-weight: 500; color: var(--text-secondary); font-variant-numeric: tabular-nums; }
.contact-item.has-unread .contact-when { color: var(--brand-700); font-weight: 600; }
.contact-when.is-waiting, .contact-item.has-unread .contact-when.is-waiting { color: #92400e; font-weight: 600; }
:root[data-theme="dark"] .contact-when.is-waiting { color: #fcd34d; }
:root[data-theme="dark"] .contact-item.has-unread .contact-when { color: var(--brand-300); }
:root[data-theme="dark"] #contact-unread-badge { color: var(--brand-100); }
.contact-who { color: var(--text-secondary); font-weight: 500; }
/* Filtros rápidos y botón «Filtros» de la cabecera de la lista. */
.contact-quick { display: inline-flex; align-items: center; gap: 6px; font-size: 12px; color: var(--text-primary); cursor: pointer; white-space: nowrap; }
.contact-filters-btn {
  display: inline-flex; align-items: center; gap: 6px; padding: 4px 10px; font-size: 12px; font-weight: 500;
  color: var(--text-secondary); border: 1px solid var(--border-strong); border-radius: 9999px; background: var(--bg-surface); cursor: pointer;
}
.contact-filters-btn:hover { background: var(--bg-hover); color: var(--text-primary); }
.contact-filters-btn[aria-expanded="true"] { background: var(--brand-50); border-color: var(--brand-200); color: var(--brand-800); }
.contact-filters-count { min-width: 18px; height: 18px; padding: 0 5px; border-radius: 9999px; background: var(--brand-700); color: #fff; font-size: 11px; font-weight: 600; display: inline-flex; align-items: center; justify-content: center; }
.contact-filters-count.hidden { display: none; }
@media (pointer: coarse) { .contact-quick, .contact-filters-btn { min-height: 44px; } }

/* Acciones por contacto: iconos pequeños en fila inferior izquierda */
.contact-actions {
  display: flex; align-items: center; gap: 4px;
  margin-top: 6px;
}
.contact-action {
  display: inline-flex; align-items: center; justify-content: center;
  width: 28px; height: 28px;
  border-radius: 7px;
  background: transparent;
  color: var(--zinc-500);
  border: none;
  cursor: pointer;
  transition: background 0.12s, color 0.12s, transform 0.1s;
}
.contact-action:hover { background: var(--zinc-100); color: var(--zinc-800); }
.contact-action:active { transform: scale(0.92); }
.contact-action.primary { color: var(--brand-700); }
.contact-action.primary:hover { background: var(--brand-100); color: var(--brand-800); }
.contact-action.danger { color: #b91c1c; }
.contact-action.danger:hover { background: #fee2e2; color: #991b1b; }
/* En desktop, sólo se ven al pasar el ratón sobre el contact-item — UI más limpia.
   En móvil siempre visibles porque no hay hover. */
/* Pie de la fila: etiquetas (máx. 2 + «+N») y acciones en la misma línea. */
.contact-item { position: relative; }
.contact-foot { display: flex; align-items: center; gap: 8px; margin-top: 4px; min-height: 0; }
.contact-tags { flex: 1 1 auto; min-width: 0; display: flex; gap: 4px; overflow: hidden; }
.contact-tags:empty { display: none; }
.contact-foot .contact-actions { margin-top: 0; margin-left: auto; flex: none; }
/* Escritorio: las acciones flotan sobre la fila al pasar el ratón o con el foco del
   teclado, sin reservar una línea; antes estaban invisibles ocupando 28 px y se
   podían pulsar sin verse. */
@media (min-width: 768px) {
  .contact-foot .contact-actions {
    position: absolute; right: 8px; bottom: 6px;
    background: var(--bg-surface); border: 1px solid var(--border-soft); border-radius: 8px; padding: 2px;
    box-shadow: 0 2px 8px rgb(0 0 0 / .08);
    opacity: 0; pointer-events: none; transition: opacity 0.15s;
  }
  .contact-item:hover .contact-actions,
  .contact-item:focus-within .contact-actions { opacity: 1; pointer-events: auto; }
  /* Sin etiquetas el pie no ocupa alto, pero sigue ahí: sus acciones flotan igual. */
  .contact-foot:has(.contact-tags:empty) { margin-top: 0; height: 0; }
}
@media (prefers-reduced-motion: reduce) { .contact-foot .contact-actions { transition: none; } }

/* ---------- Fondo del área de mensajes ---------- */

/* Sobreescribimos el bg-zinc-50 que pone Tailwind en #thread-pane: queremos
   crema con patrón para que las burbujas destaquen, no casi-blanco que se
   confunde con el bocadillo del inbound. */
#thread-pane { background-color: var(--chat-bg) !important; }
#thread-messages {
  background-color: var(--chat-bg);
  background-image: var(--chat-pattern);
  background-repeat: repeat;
  /* `scroll` (default) hace que el patrón quede anclado al viewport del
     contenedor scrolleable y los mensajes se muevan por encima — efecto
     idéntico al wallpaper de WhatsApp. */
}

/* Separador de día centrado (globito) — estilo WhatsApp */
.chat-day-divider {
  display: flex;
  justify-content: center;
  align-items: center;
  margin: 14px 0 10px;
  width: 100%;
  clear: both;
  pointer-events: none;
}
.chat-day-divider span {
  display: inline-block;
  padding: 5px 14px;
  border-radius: 999px;
  font-size: 12px;
  font-weight: 500;
  line-height: 1.3;
  color: var(--text-secondary);
  background: rgb(255 255 255 / 0.92);
  box-shadow: 0 1px 2px rgb(0 0 0 / 0.12);
}
:root[data-theme="dark"] .chat-day-divider span {
  background: rgb(32 35 38 / 0.95);
  color: var(--text-secondary);
  box-shadow: 0 1px 3px rgb(0 0 0 / 0.35);
}

/* ---------- Burbujas de chat ---------- */

.bubble {
  position: relative;
  width: fit-content;          /* el globo se adapta al ancho del texto */
  max-width: min(75%, 480px);  /* tope para textos largos */
  padding: 8px 12px;
  border-radius: 14px;
  word-wrap: break-word;
  overflow-wrap: anywhere;
  font-size: 14px;
  line-height: 1.4;
  /* Sombra ligeramente más marcada que antes (0.08 → 0.12) — sobre fondo crema
     necesitamos un poco más de "levantamiento" para que el inbound blanco no
     se camufle con la lámina del fondo. */
  box-shadow: 0 1px 1.5px rgb(0 0 0 / 0.12);
  /* iOS PWA: deshabilita el callout nativo (Copy/Look up/Share) en long-press. */
  -webkit-touch-callout: none;
}

/* Desktop / dispositivos con puntero fino (ratón, trackpad): mantener
   selección de texto normal para que el usuario pueda arrastrar y copiar. */
@media (hover: hover) and (pointer: fine) {
  .bubble, .bubble * {
    -webkit-user-select: text;
    user-select: text;
  }
}

/* Móvil / dispositivos táctiles (PWA): bloquear selección de texto en el globo
   para que el long-press dispare NUESTRO menú contextual (con "Copiar texto"
   incluido) en lugar de iniciar la selección nativa. */
@media (hover: none) and (pointer: coarse) {
  .bubble, .bubble * {
    -webkit-user-select: none;
    user-select: none;
  }
  /* Excepción: inputs y áreas editables siguen siendo seleccionables. */
  .bubble input, .bubble textarea, .bubble [contenteditable] {
    -webkit-user-select: text;
    user-select: text;
  }
}
/* Más espacio superior si la burbuja tiene reacciones flotantes para no solapar el anterior */
.bubble:has(.reactions-row) { margin-top: 10px; }
.bubble-out {
  background: var(--bubble-out-bg);
  margin-left: auto;     /* alineado a la derecha */
  border-bottom-right-radius: 4px;
  color: var(--bubble-out-fg);
}
.bubble-in {
  background: var(--bubble-in-bg);
  margin-right: auto;    /* alineado a la izquierda */
  border-bottom-left-radius: 4px;
  color: var(--bubble-in-fg);
}
.bubble-meta {
  display: flex; gap: 6px; align-items: center;
  font-size: 10px;
  color: var(--zinc-500);
  margin-top: 3px;
  justify-content: flex-end;
}

/* ---- Estado de entrega (ticks) y legibilidad de la meta ----
   Los ticks solo aparecen en mensajes SALIENTES, así que siempre van sobre la
   burbuja verde; afinamos el contraste sobre ese fondo. READ se distingue de
   DELIVERED por color (azul vs verde apagado) Y por su etiqueta accesible
   (statusIcon en app.js) — nunca solo por color. Contrastes verificados AA. */
.bubble-out .bubble-meta { color: #2f6b54; }            /* hora + SENT/DELIVERED/PENDING (5.5:1) */
.msg-status-read   { color: #1d4ed8; }                  /* tic azul "leído" (5.9:1) */
.msg-status-failed { color: #b91c1c; }                  /* fallo en rojo (5.7:1) */

:root[data-theme="dark"] .bubble-meta { color: var(--text-secondary); }   /* bubble-in oscuro (5.8:1) */
:root[data-theme="dark"] .bubble-out .bubble-meta { color: #a7f3d0; }     /* sobre #064e3b (7.6:1) */
:root[data-theme="dark"] .msg-status-read   { color: #93c5fd; }           /* (5.4:1) */
:root[data-theme="dark"] .msg-status-failed { color: #fca5a5; }           /* (5.1:1) */

/* Texto del error y del hint dentro de una burbuja FALLIDA (saliente = verde):
   en gris/rojo claros caían por debajo de AA sobre el fondo verde. Mismo patrón
   de override por descendencia que usa el bloque dark. */
.bubble-out .text-red-600 { color: #991b1b; }     /* error: 4.26→7.33 */
.bubble-out .text-zinc-500 { color: #2f6b54; }    /* hint:  4.26→5.52 */
:root[data-theme="dark"] .bubble-out .text-zinc-500 { color: #a7f3d0 !important; }  /* 3.79→7.6 */

/* Botón "Reenviar" dentro de una burbuja fallida: píldora roja sutil. */
.msg-resend-btn {
  display: inline-flex; align-items: center; gap: 4px;
  margin-top: 6px;
  padding: 3px 10px;
  font-size: 12px; font-weight: 500;
  color: #991b1b;
  background: #fee2e2;
  border: none; border-radius: 9999px;
  cursor: pointer;
}
.msg-resend-btn:hover { background: #fecaca; }
:root[data-theme="dark"] .msg-resend-btn { color: #fca5a5; background: rgba(239, 68, 68, 0.18); }
:root[data-theme="dark"] .msg-resend-btn:hover { background: rgba(239, 68, 68, 0.28); }
.bubble-actions {
  position: absolute;
  top: -10px; right: -8px;
  /* Transparente y no display:none: así los botones siguen en el orden de Tab y
     aparecen también al recibir el foco del teclado, no solo con el ratón. */
  display: flex; gap: 4px; opacity: 0; pointer-events: none; transition: opacity 120ms;
}
.bubble:hover .bubble-actions, .bubble:active .bubble-actions, .bubble:focus-within .bubble-actions { opacity: 1; pointer-events: auto; }
@media (prefers-reduced-motion: reduce) { .bubble-actions { transition: none; } }
.bubble-actions button {
  width: 26px; height: 26px;
  background: var(--bg-surface);
  border: 1px solid var(--zinc-200);
  border-radius: 999px;
  color: var(--text-secondary);
  cursor: pointer;
  box-shadow: 0 1px 3px rgb(0 0 0 / 0.1);
  display: flex; align-items: center; justify-content: center;
  transition: background 0.15s;
}
.bubble-actions button:hover { background: var(--zinc-100); }

/* ---------- Reply quote y reacciones ---------- */
.reply-quote {
  background: rgb(0 0 0 / 0.04);
  border-radius: 6px;
  padding: 4px 6px;
  max-width: 100%;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
/* Reacciones: globo flotante en la esquina superior derecha del mensaje */
.reactions-row {
  position: absolute;
  top: -10px; right: -4px;
  display: flex; flex-wrap: wrap; gap: 2px;
  z-index: 5;
  pointer-events: none;
}
.reaction-chip {
  display: inline-flex; align-items: center; gap: 2px;
  background: var(--bg-surface);
  border: 1px solid var(--zinc-200);
  border-radius: 999px;
  padding: 2px 7px;
  font-size: 12px;
  line-height: 1.1;
  box-shadow: 0 2px 5px rgb(0 0 0 / 0.12);
  pointer-events: auto;
}
.star-ind {
  font-size: 11px;
  margin-right: 4px;
}
.read-ind {
  font-size: 10px;
  color: var(--zinc-500);
  margin-right: 4px;
}
/* Botones de mensajes interactivos (van DENTRO de la burbuja, no flotantes) */
.buttons-row {
  display: flex; flex-wrap: wrap; gap: 4px;
  margin-top: 6px;
}
.btn-chip {
  display: inline-flex; align-items: center; gap: 2px;
  background: var(--bg-surface);
  border: 1px solid var(--zinc-300);
  border-radius: 8px;
  padding: 4px 10px;
  font-size: 13px;
  line-height: 1;
  font-weight: 500;
  color: var(--zinc-700);
}
.btn-chip.selected {
  background: var(--brand-100, #dbeafe);
  border-color: var(--brand-500, #0ea5e9);
  color: var(--brand-700, #1d4ed8);
  font-weight: 600;
  box-shadow: 0 0 0 2px rgb(14 165 233 / 0.2);
}
.reaction-chip.selected {
  background: var(--brand-100, #dbeafe);
  border-color: var(--brand-500, #0ea5e9);
  color: var(--brand-700, #1d4ed8);
  font-weight: 600;
  box-shadow: 0 0 0 2px rgb(14 165 233 / 0.2);
}

/* ---------- Emoji picker ---------- */
.emoji-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(40px, 1fr));
  gap: 4px;
  max-height: 280px;
  overflow-y: auto;
  padding: 4px;
  border: 1px solid var(--zinc-200);
  border-radius: 8px;
  background: var(--zinc-50, #fafafa);
}
.emoji-pick {
  display: flex; align-items: center; justify-content: center;
  width: 40px; height: 40px;
  font-size: 22px;
  background: var(--bg-surface);
  border: 1px solid transparent;
  border-radius: 6px;
  cursor: pointer;
  transition: background 0.1s, border-color 0.1s, transform 0.1s;
}
.emoji-pick:hover {
  background: var(--zinc-100);
  border-color: var(--zinc-300);
  transform: scale(1.1);
}

/* ---------- Menú contextual de mensaje ---------- */
#msg-context-menu {
  background: var(--bg-surface);
  border: 1px solid var(--zinc-200);
  border-radius: 10px;
  box-shadow: 0 8px 24px rgb(0 0 0 / 0.15);
  padding: 4px;
  min-width: 200px;
  font-size: 14px;
  user-select: none;
}
.ctx-item {
  display: flex;
  align-items: center;
  gap: 10px;
  width: 100%;
  padding: 8px 10px;
  border: none;
  background: transparent;
  text-align: left;
  cursor: pointer;
  border-radius: 6px;
  color: var(--zinc-800);
  font-size: 13px;
  transition: background 0.1s;
}
.ctx-item:hover { background: var(--zinc-100); }
.ctx-item.danger { color: #dc2626; }
.ctx-item.danger:hover { background: #fee2e2; }
.ctx-item.disabled {
  opacity: 0.4;
  cursor: not-allowed;
  pointer-events: auto; /* permitir hover para tooltip */
}
.ctx-item.disabled:hover { background: transparent; }
.ctx-item .ctx-icon {
  width: 16px; height: 16px;
  display: flex; align-items: center; justify-content: center;
  flex-shrink: 0;
}
.ctx-divider {
  height: 1px;
  background: var(--zinc-200);
  margin: 4px 0;
}

/* Item activo en listas navegadas con teclado */
.list-nav-active {
  outline: 2px solid var(--brand-500, #0ea5e9);
  outline-offset: -2px;
  background: rgb(14 165 233 / 0.06);
  border-radius: 8px;
}

/* ---------- Galería /multi (archivos de la conversación) ---------- */
.cm-card {
  display: flex; flex-direction: column;
  background: var(--zinc-50);
  border: 1px solid var(--zinc-200);
  border-radius: 10px;
  overflow: hidden;
  cursor: pointer;
  transition: transform 0.1s, box-shadow 0.1s, border-color 0.1s;
  min-width: 0;
}
.cm-card:hover {
  transform: translateY(-1px);
  box-shadow: 0 4px 12px rgb(0 0 0 / 0.08);
  border-color: var(--zinc-300);
}
.cm-thumb-img {
  width: 100%; height: 100px;
  object-fit: cover;
  display: block;
  background: var(--zinc-100);
}
.cm-thumb-icon {
  width: 100%; height: 100px;
  display: flex; align-items: center; justify-content: center;
  font-size: 36px;
  background: var(--zinc-100);
}
.cm-card-meta {
  padding: 6px 8px;
  text-align: left;
  display: flex; flex-direction: column; gap: 2px;
  min-width: 0;
}
.cm-card-name {
  font-size: 12px;
  font-weight: 500;
  color: var(--zinc-800);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.cm-card-date {
  font-size: 10px;
  color: var(--zinc-500);
  font-variant-numeric: tabular-nums;
}
.chip-brand {
  background: var(--brand-100, #dbeafe);
  color: var(--brand-700, #1d4ed8);
  border-color: var(--brand-200, #bfdbfe);
}

/* Sección plegable de capacidades (canales) */
.caps-details summary {
  list-style: none;
}
.caps-details summary::-webkit-details-marker { display: none; }
.caps-summary {
  display: inline-flex; align-items: center; gap: 4px;
  padding: 3px 8px;
  font-size: 11px;
  color: var(--zinc-600);
  background: var(--zinc-100);
  border-radius: 999px;
  cursor: pointer;
  user-select: none;
  transition: background 0.15s, color 0.15s;
}
.caps-summary:hover {
  background: var(--zinc-200);
  color: var(--zinc-700);
}
.caps-details[open] .caps-summary {
  color: var(--zinc-700);
  background: var(--zinc-200);
}

.status-icon { font-size: 12px; }
.status-PENDING, .status-SENT, .status-DELIVERED { color: var(--zinc-500); }
.status-READ { color: #34b7f1; }
.status-FAILED, .status-DELETED { color: #ef4444; }

/* ---------- Multimedia en burbuja ---------- */

img.media-img {
  max-width: 280px; max-height: 280px;
  border-radius: 12px;
  display: block;
}
.media-thumb {
  display: flex; align-items: center; gap: 10px;
  background: var(--zinc-100);
  padding: 10px 12px;
  border-radius: 10px;
  font-size: 13px;
  border: none;
  cursor: pointer;
  text-decoration: none;
  color: inherit;
  min-width: 200px;
  max-width: 320px;
}
.media-thumb:hover { background: var(--zinc-200); }
.media-thumb a { color: var(--brand-700); text-decoration: none; font-weight: 500; }
.media-thumb a:hover { text-decoration: underline; }
.cursor-zoom-in { cursor: zoom-in; }

/* Botón de descarga flotante sobre imagen/vídeo */
.media-wrap { position: relative; display: inline-block; }
.media-download-btn {
  position: absolute;
  top: 6px; right: 6px;
  display: inline-flex; align-items: center; justify-content: center;
  width: 30px; height: 30px;
  border-radius: 999px;
  background: rgb(0 0 0 / 0.55);
  color: #fff;
  border: none;
  cursor: pointer;
  opacity: 0;
  transition: opacity 0.12s, background 0.12s;
}
.media-wrap:hover .media-download-btn,
.media-download-btn:focus-visible { opacity: 1; }
.media-download-btn:hover { background: rgb(0 0 0 / 0.75); }
/* En táctil (sin hover) el botón siempre visible */
@media (hover: none) {
  .media-download-btn { opacity: 1; }
}

/* Pastilla de IA flotante sobre la foto/vídeo (Describir / Descripción /
   Leyendo…): abajo a la izquierda, sin ensanchar el globo. Siempre visible:
   dice si la foto está leída. En vídeo va arriba para no tapar los controles. */
.media-ai-chip {
  position: absolute;
  left: 6px; bottom: 6px;
  display: inline-flex; align-items: center; gap: 4px;
  max-width: calc(100% - 12px);
  padding: 3px 9px;
  font-size: 11px; font-weight: 500; line-height: 16px;
  white-space: nowrap;
  border-radius: 999px;
  background: rgb(0 0 0 / 0.55);
  color: #fff;
  border: none;
  cursor: pointer;
  backdrop-filter: blur(4px);
  -webkit-backdrop-filter: blur(4px);
  transition: background 0.12s;
}
.media-ai-chip:hover { background: rgb(0 0 0 / 0.75); }
.media-ai-chip svg { flex-shrink: 0; }
.media-ai-chip span { overflow: hidden; text-overflow: ellipsis; }
.media-ai-chip:disabled, .media-ai-chip.is-busy { cursor: default; }
.media-ai-chip:focus-visible { outline: 2px solid #fff; outline-offset: 1px; }
.media-wrap.is-video .media-ai-chip { top: 6px; bottom: auto; }
@media (prefers-reduced-motion: reduce) {
  .media-ai-chip .animate-spin { animation: none; }
}

/* ---------- Barra de grabación de micro ---------- */
#composer-rec.flex { display: flex; }
.rec-pulse {
  width: 12px; height: 12px;
  background: #dc2626;
  border-radius: 999px;
  display: inline-block;
  animation: rec-pulse 1.2s ease-in-out infinite;
  flex-shrink: 0;
}
@keyframes rec-pulse {
  0%, 100% { opacity: 1; transform: scale(1); }
  50% { opacity: 0.4; transform: scale(0.85); }
}

/* ---------- Audio bubble (estilo WhatsApp) ---------- */
.audio-bubble {
  display: flex; align-items: center; gap: 10px;
  background: rgb(0 0 0 / 0.04);
  padding: 8px 10px;
  border-radius: 12px;
  min-width: 240px;
  max-width: 320px;
}
.audio-play {
  width: 38px; height: 38px;
  border-radius: 999px;
  background: var(--brand-600, #0ea5e9);
  color: white;
  border: none;
  cursor: pointer;
  display: flex; align-items: center; justify-content: center;
  flex-shrink: 0;
  transition: background 0.15s, transform 0.1s;
}
.audio-play:hover { background: var(--brand-700, #0284c7); transform: scale(1.05); }
.audio-body { flex: 1; min-width: 0; }
.audio-waveform {
  display: flex; align-items: center; gap: 2px;
  height: 28px;
  cursor: pointer;
}
.wf-bar {
  flex: 1;
  background: var(--zinc-300, #d4d4d8);
  border-radius: 1px;
  min-width: 2px;
  transition: background 0.15s;
}
.wf-bar.active { background: var(--brand-600, #0ea5e9); }
.audio-meta {
  display: flex; justify-content: space-between; align-items: center;
  font-size: 11px;
  color: var(--zinc-500, #71717a);
  margin-top: 2px;
}
.audio-time { font-variant-numeric: tabular-nums; }
.audio-speed {
  border: 1px solid var(--zinc-300);
  background: var(--bg-surface);
  border-radius: 999px;
  padding: 1px 8px;
  font-size: 10px;
  font-weight: 600;
  cursor: pointer;
  color: var(--zinc-700);
  transition: background 0.15s;
}
.audio-speed:hover { background: var(--zinc-100); }

/* ---------- Lightbox (modal para imágenes/PDF) ---------- */
#lightbox {
  position: fixed; inset: 0;
  z-index: 1000;
  display: none;
  align-items: center; justify-content: center;
}
#lightbox.open { display: flex; }
.lb-backdrop {
  position: absolute; inset: 0;
  background: rgb(0 0 0 / 0.85);
  cursor: zoom-out;
}
.lb-content {
  position: relative;
  max-width: 95vw;
  max-height: 95vh; max-height: 95dvh;
  display: flex; flex-direction: column;
  background: var(--zinc-900, #18181b);
  border-radius: 8px;
  overflow: hidden;
  box-shadow: 0 20px 60px rgb(0 0 0 / 0.5);
}
.lb-header {
  display: flex; align-items: center; gap: 12px;
  padding: 8px 12px;
  background: rgb(0 0 0 / 0.6);
  color: white;
  font-size: 13px;
}
.lb-title { flex: 1; min-width: 0; text-overflow: ellipsis; overflow: hidden; white-space: nowrap; }
.lb-download, .lb-close {
  width: 30px; height: 30px;
  display: flex; align-items: center; justify-content: center;
  background: rgb(255 255 255 / 0.1);
  border: none; border-radius: 6px;
  color: white; text-decoration: none;
  cursor: pointer;
  font-size: 16px;
}
.lb-download:hover, .lb-close:hover { background: rgb(255 255 255 / 0.2); }
.lb-body {
  background: black;
  display: flex; align-items: center; justify-content: center;
  min-width: 60vw; min-height: 60vh; min-height: 60dvh;
  max-width: 95vw; max-height: 90vh; max-height: 90dvh;
  overflow: auto;
}
.lb-body img {
  max-width: 95vw;
  max-height: 85vh; max-height: 85dvh;
  display: block;
  object-fit: contain;
}
.lb-body embed {
  width: 90vw; height: 85vh; height: 85dvh;
  border: none;
}

/* ---------- Eventos ---------- */

.event-row { padding: 12px 16px; }
.event-row pre {
  font-size: 11px; line-height: 1.5;
  background: var(--zinc-50);
  padding: 8px;
  margin-top: 8px;
  border-radius: 8px;
  max-height: 192px;
  overflow: auto;
}

/* ---------- Plantillas ---------- */

.tpl-item {
  padding: 12px 16px;
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
}
.tpl-name { font-weight: 500; font-size: 14px; }
.tpl-tags { display: flex; gap: 6px; flex-wrap: wrap; margin-top: 4px; }
.tpl-tag {
  font-size: 10px; padding: 2px 8px; border-radius: 6px;
  font-weight: 500; text-transform: uppercase; letter-spacing: 0.04em;
  background: var(--zinc-100); color: var(--zinc-700);
}
.tpl-status-APPROVED { background: var(--brand-100); color: var(--brand-800); }
.tpl-status-REJECTED { background: #fee2e2; color: #991b1b; }
.tpl-status-PENDING  { background: #fef3c7; color: #92400e; }

/* ---------- Tarjetas de exposición (radio) ---------- */

.exposure-card {
  display: flex; align-items: flex-start; gap: 12px;
  padding: 12px;
  border-radius: 12px;
  cursor: pointer;
  border: 1px solid var(--zinc-200);
  background: var(--bg-surface);
  transition: border-color 0.15s, background 0.15s, box-shadow 0.15s;
}
.exposure-card:hover { border-color: var(--zinc-300); background: var(--zinc-50); }
.exposure-card input[type=radio] {
  margin-top: 2px;
  width: 16px; height: 16px;
  accent-color: var(--brand-600);
}
.exposure-card:has(input[type=radio]:checked) {
  border-color: var(--brand-500);
  background: rgb(var(--brand-rgb) / 0.04); /* sigue el color de acento */
  box-shadow: 0 0 0 1px var(--brand-500);
}

/* ---------- Tarjetas de canal ---------- */

.channel-card {
  background: var(--bg-surface);
  border-radius: 14px;
  padding: 12px;
  box-shadow: 0 1px 2px rgb(0 0 0 / 0.04), 0 4px 12px rgb(0 0 0 / 0.04);
  transition: box-shadow 0.15s;
}
.channel-card:hover { box-shadow: 0 2px 4px rgb(0 0 0 / 0.06), 0 8px 20px rgb(0 0 0 / 0.06); }
@media (min-width: 768px) { .channel-card { padding: 14px; } }

/* Acciones compactas (iconos en fila) abajo del card */
.channel-card-actions {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 4px;
  margin-top: 10px;
  padding-top: 8px;
  border-top: 1px solid var(--zinc-100);
}
.channel-action {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 32px; height: 32px;
  border-radius: 8px;
  background: var(--zinc-100);
  color: var(--zinc-700);
  border: none;
  cursor: pointer;
  transition: background 0.12s, color 0.12s, transform 0.1s;
}
.channel-action:hover { background: var(--zinc-200); color: var(--zinc-900); }
.channel-action:active { transform: scale(0.95); }
.channel-action.danger { color: #dc2626; }
.channel-action.danger:hover { background: #fee2e2; color: #991b1b; }
.channel-action.primary { background: var(--brand-100); color: var(--brand-800); }
.channel-action.primary:hover { background: var(--brand-700); color: white; }
.channel-action.spacer { flex: 1; pointer-events: none; background: transparent; }

.chip {
  display: inline-flex; align-items: center; gap: 4px;
  padding: 2px 8px;
  border-radius: 6px;
  font-size: 11px; font-weight: 500;
  white-space: nowrap;
}
.chip-emerald { background: var(--brand-100); color: var(--brand-800); }
.chip-zinc    { background: var(--zinc-100); color: var(--zinc-700); }
.chip-amber   { background: #fef3c7; color: #92400e; }
.chip-purple  { background: #f3e8ff; color: #6b21a8; }
.chip-blue    { background: #dbeafe; color: #1e40af; }
.chip-red     { background: #fee2e2; color: #991b1b; }

.code-pill {
  display: inline-block;
  background: var(--zinc-100);
  color: var(--zinc-800);
  padding: 2px 6px;
  border-radius: 4px;
  font-size: 11px;
  font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;
  user-select: all;
}

/* ---------- Scrollbars discretos ---------- */

/* Propiedades estándar (Firefox, Chrome 121+, Safari 26): siguen el tema. Antes
   solo había ::-webkit-scrollbar con zinc-300 fijo: en oscuro, píldoras casi blancas. */
:root { --sb-thumb: var(--zinc-300); }
:root[data-theme="dark"] { --sb-thumb: #52525b; }
* { scrollbar-color: var(--sb-thumb) transparent; scrollbar-width: thin; }
@supports not (scrollbar-color: auto) {
  *::-webkit-scrollbar { width: 8px; height: 8px; }
  *::-webkit-scrollbar-track { background: transparent; }
  *::-webkit-scrollbar-thumb { background: var(--sb-thumb); border-radius: 999px; }
  *::-webkit-scrollbar-thumb:hover { background: var(--zinc-400); }
}

/* ---------- Empty states ---------- */

.empty-state {
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  /* Token semántico: con zinc-500 fijo, en oscuro daba 3,1:1. */
  text-align: center; padding: 48px 24px; color: var(--text-secondary);
}
.empty-state .icon-wrap {
  width: 56px; height: 56px;
  border-radius: 16px;
  background: var(--zinc-100);
  color: var(--zinc-400);
  display: flex; align-items: center; justify-content: center;
  margin-bottom: 12px;
}

/* ---------- Lucide icon wrapper sizes ---------- */
.w-4\.5 { width: 1.125rem; }
.h-4\.5 { height: 1.125rem; }

/* ============================================
   MOBILE NATIVE LOOK (iOS/Android)
   ============================================ */

:root {
  --safe-top: env(safe-area-inset-top, 0px);
  --safe-bottom: env(safe-area-inset-bottom, 0px);
  --safe-left: env(safe-area-inset-left, 0px);
  --safe-right: env(safe-area-inset-right, 0px);
}

@media (max-width: 767px) {
  body { font-size: 15px; }
  /* App container — sin scroll horizontal por safe-areas */
  body, #root, main { overflow-x: hidden; }

  /* Touch-targets más grandes */
  .btn-icon, .nav-item, .bottom-nav-item { min-height: 44px; }
}

/* ---------- Top bar móvil sticky con safe-area ---------- */
.mobile-top-bar {
  padding-top: calc(8px + var(--safe-top));
  padding-left: calc(12px + var(--safe-left));
  padding-right: calc(12px + var(--safe-right));
}

/* ---------- Desplegable de canal (cabecera de la lista) ---------- */
.channel-switcher { position: relative; margin: 10px 12px 0; }
.channel-switcher-select {
  width: 100%; appearance: none; -webkit-appearance: none;
  padding: 8px 34px 8px 30px; font: 600 14px/1.3 inherit; color: var(--text-primary);
  background: var(--bg-surface); border: 1px solid var(--border-strong); border-radius: 8px;
  cursor: pointer; transition: background 150ms, border-color 150ms;
  text-overflow: ellipsis; white-space: nowrap; overflow: hidden;
}
.channel-switcher-select:hover { background: var(--bg-hover); }
.channel-switcher-select:focus-visible { outline: none; border-color: var(--brand-500); box-shadow: 0 0 0 3px rgb(var(--brand-rgb) / .15); }
#channel-switcher-dot { position: absolute; left: 12px; top: 50%; transform: translateY(-50%); width: 10px; height: 10px; pointer-events: none; }
.channel-switcher-chevron { position: absolute; right: 10px; top: 50%; transform: translateY(-50%); pointer-events: none; color: var(--text-secondary); }
.channel-switcher-empty {
  margin: 10px 12px 0; display: flex; align-items: center; justify-content: center; gap: 6px;
  padding: 8px 12px; font-size: 14px; font-weight: 500; color: var(--text-secondary);
  border: 1px dashed var(--border-strong); border-radius: 8px; background: transparent; cursor: pointer;
}
.channel-switcher-empty:hover { background: var(--bg-hover); color: var(--text-primary); }
@media (pointer: coarse) { .channel-switcher-select { min-height: 44px; font-size: 16px; } }
/* Pendientes en otros canales: texto visible bajo el desplegable, que lleva al canal. */
.channel-elsewhere {
  margin: 6px 12px 0; width: calc(100% - 24px); display: flex; align-items: center; gap: 6px;
  padding: 6px 10px; font-size: 12px; font-weight: 500; text-align: left;
  color: var(--brand-800); background: var(--brand-50); border: 1px solid var(--brand-200); border-radius: 8px; cursor: pointer;
}
.channel-elsewhere:hover { background: var(--brand-100); }
.channel-elsewhere-go { margin-left: auto; font-weight: 600; white-space: nowrap; text-decoration: underline; text-underline-offset: 2px; }
:root[data-theme="dark"] .channel-elsewhere { background: rgb(6 78 59 / .35); border-color: var(--brand-700); color: var(--brand-100); }
@media (pointer: coarse) { .channel-elsewhere { min-height: 44px; } }

/* ---------- Compositor «solo plantillas» (WhatsApp fuera de 24 h) ---------- */
#composer.templates-only #composer-mic,
#composer.templates-only #composer-send { display: none !important; }
#composer.templates-only #composer-tpl-cta { display: inline-flex !important; }
#composer.templates-only #composer-text { cursor: not-allowed; }

/* ---------- Pasos del formulario de campaña ---------- */
.camp-steps { display: flex; gap: 6px; margin: 0 0 16px; padding: 0; list-style: none; counter-reset: none; }
.camp-steps li { flex: 1 1 0; min-width: 0; }
.camp-steps button {
  width: 100%; display: flex; align-items: center; gap: 8px; padding: 8px 10px;
  font-size: 13px; font-weight: 500; color: var(--text-secondary); text-align: left;
  background: transparent; border: 0; border-bottom: 2px solid var(--border-soft); cursor: pointer;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; transition: color 150ms, border-color 150ms;
}
.camp-steps button:disabled { cursor: default; opacity: 0.6; }
.camp-steps button:not(:disabled):hover { color: var(--text-primary); }
.camp-step-n {
  flex: none; width: 22px; height: 22px; border-radius: 9999px; display: inline-flex; align-items: center; justify-content: center;
  font-size: 12px; font-weight: 600; border: 1px solid var(--border-strong); color: var(--text-secondary);
}
.camp-steps button.is-current { color: var(--text-primary); font-weight: 600; border-bottom-color: var(--brand-700); }
.camp-steps button.is-current .camp-step-n { background: var(--brand-700); border-color: var(--brand-700); color: #fff; }
.camp-steps button.is-done .camp-step-n { background: var(--brand-50); border-color: var(--brand-200); color: var(--brand-800); }
:root[data-theme="dark"] .camp-steps button.is-done .camp-step-n { background: var(--brand-900); border-color: var(--brand-700); color: var(--brand-100); }
@media (pointer: coarse) { .camp-steps button { min-height: 44px; } }

/* ---------- Dianas y tamaños de controles ---------- */
/* Pestañas de Bots IA: eran chips de 20 px de alto, poca diana para un control que
   se usa a cada rato. 32 px con puntero fino, 44 px en táctil. */
.bot-tab, .bots-subtab { min-height: 32px; padding: 6px 12px; font-size: 13px; }
@media (pointer: coarse) { .bot-tab, .bots-subtab { min-height: 44px; } }
/* Táctil: dianas del chat que se quedaban en 16-32 px. Borrar conversación, además,
   se separa de Etiquetas para que un dedo no acierte en la equivocada. */
@media (pointer: coarse) {
  .contact-actions { gap: 8px; }
  .contact-action { width: 40px; height: 40px; }
  .contact-action.danger { margin-left: 12px; }
  /* Sin `display`: le ganaría a `md:hidden` del botón de menú en tabletas táctiles. */
  #mobile-drawer-btn, #contacts-refresh, #new-conv-btn, #contact-tag-adv-btn,
  #thread-back, #thread-refresh, #thread-overflow-btn, #thread-mark-read, #dossier-tags-edit, #window-banner-action {
    min-width: 44px; min-height: 44px;
  }
  .dossier-bot { min-height: 44px; }
  #thread-overflow-menu button { min-height: 44px; }
}

/* Campo con error (validación junto al campo). */
.input[aria-invalid="true"] { border-color: #b91c1c; box-shadow: 0 0 0 3px rgb(185 28 28 / .12); }

/* ---------- Bloques del rail ---------- */
.nav-section + .nav-section { margin-top: 10px; }
.nav-section-title { padding: 4px 12px 2px; font-size: 12px; font-weight: 600; color: var(--text-secondary); }
/* Bloque sin ningún destino visible para este usuario (permisos): fuera, título incluido. */
.nav-section:not(:has(> .nav-item:not(.hidden), > details.nav-group:not(.hidden))) { display: none; }
/* Rail en iconos: el título se queda en una raya fina entre bloques. */
#nav-rail.rail-collapsed .nav-section-title { padding: 0; margin: 6px 10px; height: 1px; background: var(--border-soft); }
#nav-rail.rail-collapsed .nav-section:has(> .nav-item:not(.hidden), > details.nav-group:not(.hidden)) {
  display: flex; flex-direction: column; align-items: center; width: 100%;
}
#nav-rail.rail-collapsed .nav-section-title { align-self: stretch; }

/* ---------- Modo desarrollador ---------- */
/* Lo marcado .dev-only solo se ve con el modo desarrollador (Apariencia). La fila de
   salud se ve siempre que la BD falle: ese aviso no puede depender de una preferencia. */
:root:not([data-dev]) .dev-only { display: none !important; }
:root:not([data-dev]) #health-row:has(#health-dot.bg-red-500) { display: flex !important; }


/* ---------- Bottom nav móvil con safe-area ---------- */
@media (max-width: 767px) {
  .bottom-nav {
    padding-bottom: calc(2px + var(--safe-bottom));
    padding-left: var(--safe-left);
    padding-right: var(--safe-right);
    box-shadow: 0 -1px 0 rgb(0 0 0 / 0.04);
  }
  .bottom-nav-item {
    padding: 10px 0 8px;
    font-size: 10px;
  }
  .bottom-nav-item i { width: 22px; height: 22px; }
  .bottom-nav-item.bottom-nav-active i { transform: scale(1.05); }
  .bottom-nav-item { transition: color 0.15s, transform 0.15s; }
}

/* ---------- Drawer / sheet lateral (móvil) ---------- */
.drawer {
  position: fixed; inset: 0; z-index: 60;
  display: none;
}
.drawer.open { display: block; }
.drawer-backdrop {
  position: absolute; inset: 0;
  background: rgb(0 0 0 / 0.45);
  backdrop-filter: blur(2px);
  animation: fade-in 0.18s ease-out;
}
.drawer-panel {
  position: absolute;
  left: 0; right: 0; bottom: 0;
  max-height: 88vh; max-height: 88dvh;
  background: var(--bg-surface);
  display: flex;
  flex-direction: column;
  border-top-left-radius: 18px;
  border-top-right-radius: 18px;
  padding-bottom: var(--safe-bottom);
  box-shadow: 0 -8px 32px rgb(0 0 0 / 0.18);
  animation: slide-up-sheet 0.22s cubic-bezier(0.2, 0.8, 0.2, 1);
}
@keyframes slide-up-sheet {
  from { transform: translateY(100%); }
  to   { transform: translateY(0); }
}
.drawer-grabber {
  width: 38px; height: 4px;
  background: var(--zinc-300);
  border-radius: 2px;
  margin: 8px auto 0;
  flex-shrink: 0;
}
.drawer-section {
  padding: 4px 8px;
}
.drawer-section + .drawer-section {
  border-top: 1px solid var(--zinc-100);
}
.drawer-item {
  width: 100%;
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 12px 14px;
  border-radius: 10px;
  font-size: 14px;
  font-weight: 500;
  color: var(--zinc-800);
  background: transparent;
  border: none;
  cursor: pointer;
  text-align: left;
  transition: background 0.12s;
}
.drawer-item:hover, .drawer-item:active { background: var(--zinc-100); }
.drawer-item.danger { color: #b91c1c; }
.drawer-header {
  display: flex; align-items: center; gap: 12px;
  padding: 16px 14px 12px;
  border-bottom: 1px solid var(--zinc-100);
}
.drawer-header .avatar {
  width: 44px; height: 44px;
  border-radius: 999px;
  background: var(--brand-700);
  color: white; font-weight: 600; font-size: 16px;
  display: flex; align-items: center; justify-content: center;
}

/* ---------- Thread overflow menu (todos los tamaños) ---------- */
.thread-overflow-menu {
  position: absolute;
  top: 100%; right: 8px;
  margin-top: 4px;
  background: var(--bg-surface);
  border: 1px solid var(--zinc-200);
  border-radius: 12px;
  box-shadow: 0 12px 32px rgb(0 0 0 / 0.12);
  padding: 4px;
  z-index: 30;
  min-width: 200px;
  animation: pop-in 0.14s ease-out;
}
.thread-overflow-menu button {
  width: 100%;
  display: flex; align-items: center; gap: 10px;
  padding: 10px 12px;
  font-size: 14px;
  background: transparent;
  border: none;
  border-radius: 8px;
  cursor: pointer;
  text-align: left;
  color: var(--zinc-800);
}
.thread-overflow-menu button:hover { background: var(--zinc-100); }
.thread-overflow-menu button.danger { color: #b91c1c; }

/* Los botones extra del thread (ajustes de reglas, enlace, debug JSON/HTML y el
   destructivo "vaciar") viven SIEMPRE tras el "...", en todos los tamaños, para
   no saturar la cabecera. Inline quedan solo las acciones de uso diario:
   marcar-leído y recargar. Siguen en el DOM (ocultos) porque el menú "..." los
   usa como proxy de click; no hace falta duplicar lógica. */
#thread-copy-json,
#thread-copy-html,
#thread-clear,
#thread-rules-toggle,
#thread-copy-link {
  display: none !important;
}

/* ---------- Lista de contactos (touch) ---------- */
@media (max-width: 767px) {
  .contact-item { padding: 12px 14px; min-height: 64px; }
  .contact-avatar { width: 48px; height: 48px; font-size: 16px; }
  .contact-name { font-size: 15px; }
  .contact-waid { font-size: 12px; }
}

/* ---------- Slide entre panes (móvil) ---------- */
@media (max-width: 767px) {
  #contacts-pane, #thread-pane {
    /* Como flex items, su min-width por defecto es `auto`: el min-content del
       composer puede forzar más ancho que el viewport y cortar el micro y el
       botón de enviar por la derecha. */
    min-width: 0;
    transition: transform 0.22s cubic-bezier(0.2, 0.8, 0.2, 1);
    will-change: transform;
  }
}

/* ---------- Inputs estilo iOS ---------- */
@media (max-width: 767px) {
  .input { font-size: 16px; /* evita zoom en iOS */ padding: 10px 14px; border-radius: 10px; }
  textarea.input { padding: 10px 14px; }
  /* El composer también a 16px para que el textarea no haga zoom */
  #composer-text { font-size: 16px; }
}

/* ---------- Burbujas de chat en móvil: más respiración a los lados ---------- */
@media (max-width: 767px) {
  /* Burbujas no llegan al borde — siempre dejan ~10% de hueco al lado contrario */
  .bubble { max-width: 82%; }
  .bubble-out { margin-right: 4px; }
  .bubble-in  { margin-left: 4px; }
  /* Más espacio entre burbujas para que no se vean apelmazadas */
  #thread-messages { padding-left: 14px; padding-right: 14px; }
}

/* ---------- Placeholder autocomplete (truco "/" para insertar {{var}}) ---------- */
.placeholder-ac {
  position: absolute;
  left: 0; right: 0;
  bottom: calc(100% + 4px);
  background: var(--bg-surface);
  border: 1px solid var(--zinc-200);
  border-radius: 12px;
  box-shadow: 0 12px 32px rgb(0 0 0 / 0.14);
  z-index: 40;
  max-height: 280px;
  overflow: hidden;
  animation: pop-in 0.12s ease-out;
}
.placeholder-ac-list {
  max-height: 280px;
  overflow-y: auto;
  padding: 4px;
}
.placeholder-ac-item {
  width: 100%;
  display: flex; align-items: center; gap: 10px;
  padding: 8px 10px;
  border-radius: 8px;
  background: transparent;
  border: none;
  cursor: pointer;
  text-align: left;
  transition: background 0.1s;
}
.placeholder-ac-item:hover, .placeholder-ac-item.selected { background: var(--zinc-100); }
.placeholder-ac-item.selected { background: var(--brand-50); }
.placeholder-ac-key {
  font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;
  font-size: 13px; font-weight: 600;
  color: var(--brand-700);
}
.placeholder-ac-desc {
  font-size: 11px; color: var(--zinc-600);
  margin-top: 2px;
}
.placeholder-ac-sample {
  background: var(--zinc-100);
  color: var(--zinc-600);
  padding: 2px 6px;
  border-radius: 4px;
  font-size: 11px;
  font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;
  white-space: nowrap;
}
.placeholder-ac-empty {
  padding: 12px; text-align: center;
  font-size: 12px; color: var(--zinc-400);
}

/* ---------- Tooltip flotante de preview (snippets / plantillas WA) ---------- */
.hover-preview {
  position: fixed;
  z-index: 100;
  max-width: 360px;
  max-height: 60vh; max-height: 60dvh;
  overflow-y: auto;
  padding: 10px 12px;
  background: var(--bg-surface);
  border: 1px solid var(--zinc-200);
  border-radius: 12px;
  box-shadow: 0 12px 32px rgb(0 0 0 / 0.16);
  font-size: 12px;
  line-height: 1.45;
  color: var(--zinc-800);
  pointer-events: none; /* no roba foco/click */
  animation: pop-in 0.12s ease-out;
}
.hover-preview .hp-title {
  font-size: 11px;
  font-weight: 600;
  color: var(--zinc-500);
  text-transform: uppercase;
  letter-spacing: 0.04em;
  margin-bottom: 4px;
}
.hover-preview .hp-section { margin-top: 6px; }
.hover-preview .hp-section + .hp-section { padding-top: 6px; border-top: 1px solid var(--zinc-100); }
.hover-preview code { background: var(--zinc-100); padding: 1px 4px; border-radius: 3px; font-size: 11px; }
.hover-preview .hp-btn {
  display: inline-block;
  margin: 2px 4px 0 0;
  padding: 2px 8px;
  border: 1px solid var(--zinc-300);
  border-radius: 999px;
  font-size: 11px;
  color: var(--zinc-700);
}
.hover-preview .hp-empty { color: var(--zinc-400); font-style: italic; }
@media (max-width: 767px) { .hover-preview { display: none !important; } } /* móvil: no hay hover */

/* ---------- Pestañas de idioma del editor de snippet ---------- */
.snip-lang-tab {
  display: inline-flex; align-items: center; gap: 4px;
  padding: 2px 8px;
  font-size: 11px;
  font-weight: 500;
  border-radius: 999px;
  background: var(--zinc-100);
  color: var(--zinc-600);
  border: 1px solid transparent;
  cursor: pointer;
  transition: background 0.12s, color 0.12s, border-color 0.12s;
}
.snip-lang-tab:hover { background: var(--zinc-200); }
.snip-lang-tab.active {
  background: var(--brand-50);
  color: var(--brand-800);
  border-color: var(--brand-200);
}
.snip-lang-tab.dashed {
  background: transparent;
  border: 1px dashed var(--zinc-300);
  color: var(--zinc-500);
}
.snip-lang-x {
  display: inline-flex; align-items: center; justify-content: center;
  width: 14px; height: 14px;
  border-radius: 50%;
  font-size: 11px;
  line-height: 1;
  color: var(--zinc-500);
}
.snip-lang-x:hover { background: rgb(0 0 0 / 0.08); color: #b91c1c; }

/* ---------- Unread badge en lista de chats ---------- */
.unread-badge {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 20px;
  height: 20px;
  padding: 0 6px;
  border-radius: 999px;
  font-size: 11px;
  font-weight: 600;
  color: white;
  background: var(--brand-700);
  flex-shrink: 0;
}
.contact-item.has-unread .contact-name { font-weight: 600; color: var(--zinc-900); }
.contact-item.has-unread .contact-waid { color: var(--zinc-700); }

/* ---------- Botón "Ver transcripción/descripción" en mensajes ---------- */
.media-info-btn {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  margin-top: 4px;
  padding: 3px 9px;
  font-size: 11px;
  font-weight: 500;
  border-radius: 999px;
  background: rgb(255 255 255 / 0.85);
  color: var(--brand-700);
  border: 1px solid var(--brand-200);
  cursor: pointer;
  transition: background 0.12s, color 0.12s;
}
.media-info-btn:hover { background: var(--brand-50); color: var(--brand-800); }
.bubble-out .media-info-btn { background: rgb(255 255 255 / 0.75); }

/* ---------- Composer "+": acciones secundarias agrupadas ---------- */
.composer-plus-btn {
  display: flex; align-items: center; justify-content: center;
  width: 38px; height: 38px;
  border-radius: 50%;
  background: var(--bg-hover);
  color: var(--zinc-700);
  border: none;
  cursor: pointer;
  transition: background 0.15s, transform 0.15s, color 0.15s;
}
.composer-plus-btn:hover { background: var(--zinc-200); }
.composer-plus-btn.open { background: var(--brand-700); color: white; transform: rotate(45deg); }

.composer-plus-menu {
  position: absolute;
  bottom: calc(100% + 8px);
  left: 0;
  background: var(--bg-surface);
  border: 1px solid var(--zinc-200);
  border-radius: 14px;
  box-shadow: 0 12px 32px rgb(0 0 0 / 0.14);
  padding: 6px;
  min-width: 230px;
  z-index: 30;
  animation: pop-in 0.14s ease-out;
}
.composer-plus-item {
  width: 100%;
  display: flex; align-items: center; gap: 10px;
  padding: 10px 12px;
  border-radius: 8px;
  font-size: 14px;
  color: var(--zinc-800);
  background: transparent;
  border: none;
  cursor: pointer;
  text-align: left;
  transition: background 0.12s;
}
.composer-plus-item:hover { background: var(--zinc-100); }

/* ---------- Picker de emojis (comando /emo) ---------- */
.emoji-cat {
  flex-shrink: 0;
  width: 36px; height: 36px;
  font-size: 18px;
  border: 1px solid transparent;
  border-radius: 8px;
  background: transparent;
  cursor: pointer;
  transition: background 0.12s, border-color 0.12s;
}
.emoji-cat:hover { background: var(--zinc-100); }
.emoji-cat.emoji-cat-active {
  background: var(--brand-50);
  border-color: var(--brand-200, #a7f3d0);
}
:root[data-theme="dark"] .emoji-cat:hover { background: var(--bg-hover); }
:root[data-theme="dark"] .emoji-cat.emoji-cat-active {
  background: rgba(16, 185, 129, 0.15);
  border-color: rgba(16, 185, 129, 0.35);
}
.emoji-btn {
  width: 100%; aspect-ratio: 1;
  display: flex; align-items: center; justify-content: center;
  font-size: 22px; line-height: 1;
  background: transparent;
  border: 1px solid transparent;
  border-radius: 6px;
  cursor: pointer;
  transition: background 0.1s, transform 0.1s;
  padding: 0;
}
.emoji-btn:hover { background: var(--zinc-100); transform: scale(1.15); }
.emoji-btn:active { transform: scale(0.92); }
:root[data-theme="dark"] .emoji-btn:hover { background: var(--bg-hover); }

/* Teclas en el panel de atajos. Sobrias, coherentes con el chrome (sin color). */
kbd {
  display: inline-block;
  min-width: 1.5em;
  padding: 1px 6px;
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 0.78em;
  line-height: 1.5;
  text-align: center;
  color: var(--text-secondary, #52525b);
  background: var(--zinc-100, #f4f4f5);
  border: 1px solid var(--border-strong, #d4d4d8);
  border-bottom-width: 2px;
  border-radius: 5px;
}
:root[data-theme="dark"] kbd {
  color: var(--text-secondary);
  background: var(--bg-elevated, #27272a);
  border-color: var(--border-strong);
}

/* Flash al navegar a un mensaje citado (clic en la cita del reply). */
@keyframes bubble-flash {
  0%, 60% { box-shadow: 0 0 0 3px rgba(16, 185, 129, 0.55); }
  100% { box-shadow: 0 0 0 3px transparent; }
}
.bubble-flash { animation: bubble-flash 1.5s ease-out; }
@media (prefers-reduced-motion: reduce) {
  .bubble-flash { animation: none; box-shadow: 0 0 0 3px rgba(16, 185, 129, 0.55); }
}

/* ---------- Drawer lateral (variante de sheet) ----------
   Panel que se despliega desde la DERECHA, por encima de otro modal abierto
   (z-index 60 > 50 del sheet normal). Se usa para los destinatarios del wizard
   de campañas: el wizard sigue visible a la izquierda mientras editas la lista. */
.sheet.sheet-side { z-index: 60; align-items: stretch; justify-content: flex-end; }
.sheet.sheet-side .sheet-content {
  height: 100%;
  width: min(560px, 100vw);
  margin: 0;
  border-radius: 0;
  box-shadow: -12px 0 40px rgb(0 0 0 / 0.18);
  animation: slide-in-right 0.2s ease-out;
  display: flex;
  flex-direction: column;
}
@media (min-width: 768px) {
  .sheet.sheet-side .sheet-content {
    border-top-left-radius: 16px;
    border-bottom-left-radius: 16px;
  }
}
@keyframes slide-in-right { from { transform: translateX(100%); } to { transform: translateX(0); } }
@media (prefers-reduced-motion: reduce) {
  .sheet.sheet-side .sheet-content { animation: fade-in 0.01s linear; }
}
/* Backdrop más suave en el drawer: el modal de debajo (wizard) debe seguir
   siendo legible — la gracia es ver ambos a la vez. */
.sheet.sheet-side .sheet-backdrop { background: rgb(0 0 0 / 0.22); backdrop-filter: none; }

/* ==========================================================================
   EXPEDIENTE DE LA PERSONA — rediseño del chat + shell
   Composición: rail de iconos · lista de personas · banda de expediente ·
   hilo con canal rotulado · rail de contexto.
   Todos los colores salen de los tokens semánticos, así que claro/oscuro van
   solos. El estado nunca se comunica sólo por color: cada punto de canal va
   acompañado de su etiqueta de texto.
   ========================================================================== */

/* ---------- Rail de navegación minimizable ---------- */
#nav-rail { transition: width 180ms cubic-bezier(0.2, 0.7, 0.2, 1); }
#nav-rail.rail-collapsed { width: 64px; }
#nav-rail.rail-collapsed .nav-label { display: none; }
#nav-rail.rail-collapsed > div:first-child { justify-content: center; padding-inline: 6px; gap: 0; }
#nav-rail.rail-collapsed #brand-logo { display: none; }
#nav-rail.rail-collapsed nav { padding-inline: 0; align-items: center; }
#nav-rail.rail-collapsed .nav-item { justify-content: center; width: 44px; padding: 9px 0; }
#nav-rail.rail-collapsed .nav-item span,
#nav-rail.rail-collapsed .nav-chevron { display: none; }
#nav-rail.rail-collapsed .nav-sub { display: none; }
#nav-rail.rail-collapsed .nav-group { width: auto; }
#nav-rail.rail-collapsed > div:last-child { display: flex; flex-direction: column; align-items: center; gap: 8px; }
#nav-rail.rail-collapsed #version-btn { display: none; }
/* Contraída: el usuario queda en su avatar. */
#nav-rail.rail-collapsed #user-menu-btn { width: auto; justify-content: center; }
#nav-rail.rail-collapsed #user-menu { width: 14rem; }
#nav-rail.rail-collapsed #tunnel-state-mini { display: none; }
/* Con el rail en iconos, el estado de la base deja de tener texto: el punto no
   puede ser la única señal. Cuando falla, el punto crece y lleva un signo. */
#nav-rail.rail-collapsed #health-dot { width: 14px; height: 14px; }
#nav-rail.rail-collapsed #health-dot.bg-red-500,
#nav-rail.rail-collapsed #health-dot.bg-zinc-400 {
  display: inline-flex; align-items: center; justify-content: center;
  font-size: 10px; font-weight: 700; line-height: 1;
}
#nav-rail.rail-collapsed #health-dot.bg-zinc-400::after { content: "?"; color: #18181b; }
#nav-rail.rail-collapsed #health-dot.bg-red-500::after { content: "!"; color: #18181b; }
#nav-rail.rail-collapsed #health-dot.bg-emerald-500 { background: #6ee7b7; }
#nav-rail.rail-collapsed #health-dot.bg-emerald-500::after { content: "✓"; color: #064e3b; }
/* El signo va en tinta oscura sobre el punto claro: blanco sobre #ef4444 daba 3,76:1 y
   sobre #a1a1aa 2,56:1; con tinta oscura, 4,7:1 y 6,8:1. La regla de «!» va después
   de la de «?» para que un fallo nunca se lea como duda si ambas clases coinciden. */
@media (prefers-reduced-motion: reduce) {
  #nav-rail { transition: none; }
}

/* ---------- Banda del expediente (cabecera del hilo) ---------- */
/* La cabecera envuelve: antes de recortar una acción (recargar, desbordamiento),
   baja de línea. En móvil los chips de canal van a su propia línea para que las
   acciones sigan enteras. */
.dossier-top { display: flex; align-items: center; gap: 12px; padding: 10px 16px 8px; flex-wrap: wrap; row-gap: 8px; }
/* El nombre es el dato que la banda existe para dar: es él quien tiene prioridad
   de ancho, y los chips ceden antes que el nombre (medido: con 5 canales el
   nombre quedaba en 21 px mientras los chips conservaban su ancho). */
.dossier-top > .flex-1 { flex: 1 1 200px; min-width: 9rem; }
.dossier-channels { display: flex; align-items: center; gap: 6px; flex-shrink: 1; flex-wrap: wrap; max-width: 100%; }
@media (max-width: 767px) {
  /* Sin `order`: el orden visual tiene que seguir siendo el del DOM o el foco por
     teclado salta (WCAG 2.4.3). Los chips ya caen a su línea con width:100%. */
  .dossier-channels { width: 100%; flex-shrink: 1; }
}
.dossier-band {
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  padding: 0 16px 10px;
}
.dossier-window {
  display: inline-flex; align-items: center; gap: 0.3em;
  font-size: 12px; font-weight: 600; color: var(--text-secondary);
}
.dossier-window.ok { color: #047857; }
.dossier-window.warn { color: #92400e; }
.dossier-window.gone { color: #991b1b; }
:root[data-theme="dark"] .dossier-window.ok { color: #6ee7b7; }
:root[data-theme="dark"] .dossier-window.warn { color: #fcd34d; }
:root[data-theme="dark"] .dossier-window.gone { color: #fca5a5; }
.dossier-tags { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }
/* ---------- Una sola receta de píldora para toda la superficie ----------
   Antes había tres (persona 11/500 radio 6, etiquetas 12/500 radio 6, canal 12/600
   radio 9999) en la MISMA fila. Ahora la forma vive en un sitio y cada variante sólo
   cambia color o peso. */
.dossier-pill, .chan-chip, .dossier-scope {
  display: inline-flex; align-items: center; gap: 6px;
  font-size: 12px; font-weight: 600; line-height: 1.5; white-space: nowrap;
  border-radius: 9999px; padding: 3px 10px;
  border: 1px solid var(--border-strong);
  background: var(--bg-surface); color: var(--text-secondary);
}
.dossier-scope { margin-left: auto; transition: background 150ms, color 150ms, border-color 150ms; }
.dossier-scope:hover { background: var(--bg-hover); }

/* ---------- Puntos de canal (compartidos) ---------- */
.chan-dot { width: 8px; height: 8px; border-radius: 9999px; background: var(--zinc-400); flex-shrink: 0; }
.chan-dot[data-type="WHATSAPP"] { background: #25d366; }
.chan-dot[data-type="TELEGRAM"] { background: #2aabee; }
.chan-dot[data-type="FACEBOOK"] { background: #0084ff; }
.chan-dot[data-type="INSTAGRAM"] { background: #e1306c; }
.chan-dot[data-type="APP_CHAT"] { background: var(--zinc-500); }
.contact-channels { display: flex; align-items: center; gap: 3px; margin-top: 3px; }
/* Abreviatura del canal junto a su punto: sin ella el punto sería el único portador
   visual del dato y dos de los cuatro colores no llegan al 3:1 de WCAG 1.4.11. */
.chan-abbr { font-size: 10px; font-weight: 600; color: var(--text-secondary); margin-right: 3px; }

/* Chip de canal con su punto de color (la forma la pone la receta de píldora) */
.chan-chip.is-active { background: var(--brand-50); border-color: #a7f3d0; color: var(--brand-700); }
:root[data-theme="dark"] .chan-chip.is-active { background: var(--brand-800); border-color: var(--brand-700); color: var(--brand-100); }
button.chan-chip { transition: background 150ms, color 150ms, border-color 150ms; }
button.chan-chip:hover { background: var(--bg-hover); }
button.chan-chip.is-active:hover { background: var(--brand-100); }
/* El chip activo no puede distinguirse solo por croma (1,4:1 en claro): pesa más y su
   punto lleva anillo, dos señales que sobreviven a cualquier daltonismo. */
.chan-chip.is-active { font-weight: 700; }
.chan-chip.is-active .chan-dot { box-shadow: 0 0 0 2px var(--bg-surface), 0 0 0 3px currentColor; }
/* Canal deshabilitado: borde discontinuo (forma, no color) + la palabra en el chip. */
.chan-chip.is-off { border-style: dashed; color: var(--text-secondary); }
.chan-chip.is-off .chan-dot { background: var(--zinc-400); }

/* Etiquetas de la barra inferior del móvil: suben del escalón 10 al 12 (`label`).
   Texto funcional por debajo de 11 px es un fallo de legibilidad, no una decisión de
   estilo (el detector de Impeccable lo marca y tiene razón). */
.bottom-nav-item span { font-size: 12px; }

/* En móvil la banda se queda en UNA línea: el chrome se llevaba 202 px de 844 (24 %)
   por una segunda línea de píldoras. La ventana trunca (el texto completo va en el
   `title`) y las etiquetas se callan, porque ya están en la fila de la lista. */
@media (max-width: 767px) {
  .dossier-top { padding: 8px 12px 6px; gap: 8px; }
  .dossier-band { flex-wrap: nowrap; gap: 8px; padding-bottom: 6px; }
  .dossier-window { flex: 1 1 auto; min-width: 0; overflow: hidden; white-space: nowrap; }
  /* Cede primero el nombre del canal (se lee en la línea de arriba) y solo después
     el estado: antes el recorte se comía justo «sin límite» o «quedan 3 h». */
  .dossier-window .dw-chan { flex: 0 1000 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; }
  .dossier-window .dw-state { flex: 0 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; }
  /* El nombre no reserva 200 px de base: con esa base las acciones (recargar, ···)
     caían solas a una segunda línea a 375 px. Sigue teniendo su mínimo de 9rem. */
  .dossier-top > .flex-1 { flex-basis: 0; }
  .dossier-tags { display: none; }
}

/* En móvil el botón de etiquetas se queda en icono (la palabra no cabe sin empujar
   la banda a una línea más, y el nombre accesible la lleva igual). */
@media (max-width: 480px) {
  #dossier-tags-edit span { display: none; }
}

/* ---------- Canal rotulado en cada burbuja ----------
   Sin el traje de eyebrow (mayúsculas + tracking 0,05em) que DESIGN.md §7 prohíbe:
   el dato es el canal, el adorno era de otra casa. 12px/600 en caja normal y color
   de rampa, con su punto delante. */
.bubble-chan {
  display: flex; align-items: center; gap: 5px;
  font-size: 12px; font-weight: 600; letter-spacing: 0;
  color: var(--text-secondary); margin-bottom: 4px;
}
.bubble-chan .chan-dot { width: 8px; height: 8px; }
.bubble-out .bubble-chan { color: var(--brand-800); }
:root[data-theme="dark"] .bubble-out .bubble-chan { color: var(--brand-100); }

/* ---------- Bot en la conversación ----------
   Misma receta de píldora que el resto de la banda. Estado por texto y por
   forma (activo = relleno de marca; en pausa = borde discontinuo), no sólo color. */
.dossier-bot {
  display: inline-flex; align-items: center; gap: 6px;
  font-size: 12px; font-weight: 600; line-height: 1.5; white-space: nowrap;
  border-radius: 9999px; padding: 3px 10px; cursor: pointer;
  border: 1px solid var(--border-strong);
  background: var(--bg-surface); color: var(--text-secondary);
  transition: background 150ms, color 150ms, border-color 150ms;
}
.dossier-bot.is-active { background: var(--brand-50); border-color: var(--brand-200); color: var(--brand-700); }
.dossier-bot.is-paused { border-style: dashed; color: #92400e; }
.dossier-bot:hover { background: var(--bg-hover); }
:root[data-theme="dark"] .dossier-bot.is-active { background: var(--brand-800); border-color: var(--brand-700); color: var(--brand-100); }
:root[data-theme="dark"] .dossier-bot.is-paused { color: #fcd34d; }
/* Burbuja generada por un bot: rotulada como el canal, para que el operador lo sepa. */
.bubble-bot {
  display: flex; align-items: center; gap: 5px;
  font-size: 12px; font-weight: 600; letter-spacing: 0;
  color: var(--brand-800); margin-bottom: 4px;
}
:root[data-theme="dark"] .bubble-bot { color: var(--brand-100); }

/* ---------- Signo del túnel con el rail en iconos ----------
   Forma, no color: relleno = escuchando, anillo = caído, apagado = sin datos. */
.tunnel-mini-dot {
  display: none; width: 10px; height: 10px; border-radius: 9999px;
  border: 2px solid var(--zinc-400); background: transparent; flex-shrink: 0;
}
#nav-rail.rail-collapsed .tunnel-mini-dot { display: inline-block; }
.tunnel-mini-dot[data-state="up"] { background: var(--brand-600); border-color: var(--brand-600); }
.tunnel-mini-dot[data-state="down"] { border-color: #dc2626; background: transparent; }

/* ---------- Rail de contexto ---------- */
.ctx-section + .ctx-section { margin-top: 16px; }
.ctx-title {
  font-size: 12px; font-weight: 600; color: var(--text-secondary); margin-bottom: 7px;
}
/* El tema oscuro del rail de navegación: el item activo no puede ser un bloque
   casi blanco sobre negro. */
:root[data-theme="dark"] .nav-active { background: var(--brand-800); color: var(--brand-100); }
:root[data-theme="dark"] .nav-active:hover { background: #065f46; color: var(--brand-100); }
.ctx-box {
  background: var(--bg-surface); border: 1px solid var(--border-soft);
  border-radius: 10px; padding: 9px 11px; font-size: 12px;
  color: var(--text-secondary); line-height: 1.45;
}
.ctx-link { margin-top: 6px; font-size: 12px; font-weight: 600; color: var(--brand-700); }
.ctx-link:hover { text-decoration: underline; }
.ctx-row { display: flex; justify-content: space-between; gap: 8px; padding: 4px 0; }
.ctx-row + .ctx-row { border-top: 1px solid var(--border-soft); }
.ctx-row b { font-weight: 600; color: var(--text-primary); }

/* ---------- Cierres de accesibilidad exigidos por el panel (veto AA) ---------- */
/* En oscuro el nombre de cada contacto quedaba #18181b sobre #18181b (1,0:1): la lista
   se veía sin nombres. El número tampoco llegaba a AA sobre la fila activa. */
:root[data-theme="dark"] .contact-name { color: var(--text-primary); }
:root[data-theme="dark"] .contact-waid { color: var(--text-secondary); }
:root[data-theme="dark"] .contact-item { border-bottom-color: var(--border-soft); }
:root[data-theme="dark"] .contact-item.active,
:root[data-theme="dark"] .contact-item.active:hover { background: rgba(16, 185, 129, 0.12); }
/* Los enlaces del rail de contexto usaban brand-700 (#047857) también en oscuro: 2,72:1. */
:root[data-theme="dark"] .ctx-link { color: var(--brand-100); }
/* El contador de no leídos (#059669 con texto blanco a 11 px) daba 3,77:1: no llega a AA. */
.unread-badge { background: var(--brand-700); }


/* Oculto por permisos de perfil (applyPermissionGating en app.js). */
.perm-hidden { display: none !important; }

/* Ajustes: apartados (settings-nav en app.js). Clase propia para no pisar
   los `hidden` que ya gestionan algunas tarjetas (p. ej. sesiones ngrok). */
.settings-off { display: none !important; }
.settings-nav-item {
  display: flex; align-items: center; gap: .5rem; white-space: nowrap;
  padding: .5rem .75rem; border-radius: .6rem; font-size: .875rem;
  color: var(--text-secondary); text-align: left;
}
.settings-nav-item:not(.nav-active):hover { background: var(--bg-hover); }
.settings-nav-item.nav-active { font-weight: 600; }
#settings-nav { scrollbar-width: none; }
#settings-nav::-webkit-scrollbar { display: none; }


/* ============================================
   Asistente del panel (botón flotante + chat)
   ============================================ */
.assistant-fab {
  position: fixed; right: 1.25rem; bottom: 1.25rem; z-index: 90;
  width: 3.25rem; height: 3.25rem; border-radius: 9999px;
  display: flex; align-items: center; justify-content: center;
  background: var(--brand-600); color: white;
  box-shadow: 0 6px 20px rgb(0 0 0 / 0.18);
  transition: transform .15s ease, background-color .15s ease;
}
.assistant-fab:hover { background: var(--brand-700); transform: translateY(-1px); }
.assistant-fab:focus-visible { outline: 2px solid var(--brand-300); outline-offset: 3px; }
.assistant-panel {
  position: fixed; right: 1.25rem; bottom: 5.25rem; z-index: 91;
  width: min(400px, calc(100vw - 2.5rem)); height: min(620px, calc(100vh - 7rem)); height: min(620px, calc(100dvh - 7rem));
  display: flex; flex-direction: column;
  background: var(--bg-elevated); color: var(--text-primary);
  border: 1px solid var(--border-soft); border-radius: 1rem;
  box-shadow: 0 16px 48px rgb(0 0 0 / 0.18); overflow: hidden;
}
.assistant-panel.hidden, .assistant-fab.hidden { display: none; }
.assistant-head { display: flex; align-items: center; justify-content: space-between; gap: .5rem; padding: .75rem .9rem; border-bottom: 1px solid var(--border-soft); }
.assistant-messages { flex: 1; overflow-y: auto; padding: .9rem; display: flex; flex-direction: column; gap: .6rem; }
.assistant-composer { display: flex; gap: .5rem; align-items: flex-end; padding: .7rem; border-top: 1px solid var(--border-soft); }
.assistant-composer textarea { resize: none; max-height: 8rem; }
.assistant-msg { max-width: 88%; padding: .55rem .75rem; border-radius: .9rem; font-size: .875rem; line-height: 1.45; white-space: pre-wrap; overflow-wrap: anywhere; }
.assistant-msg.user { align-self: flex-end; background: var(--brand-700); color: white; border-bottom-right-radius: .3rem; }
.assistant-msg.bot { align-self: flex-start; background: var(--bg-hover); border-bottom-left-radius: .3rem; }
.assistant-msg.bot code { font-size: .8em; padding: 0 .25em; border-radius: .25rem; background: rgb(0 0 0 / 0.06); }
.assistant-msg.error { align-self: flex-start; background: #fef2f2; color: #991b1b; }
.assistant-action { align-self: stretch; border: 1px solid var(--border-strong); border-radius: .8rem; padding: .6rem .7rem; font-size: .8rem; }
.assistant-action .assistant-action-summary { font-weight: 500; }
.assistant-action.done { border-color: var(--brand-500); }
.assistant-action.discarded { opacity: .6; }
.assistant-action.danger { border-color: #dc2626; }
.assistant-chip { font-size: .75rem; padding: .35rem .6rem; border-radius: 9999px; border: 1px solid var(--border-strong); text-align: left; }
.assistant-chip:hover { background: var(--bg-hover); }
.assistant-typing { align-self: flex-start; font-size: .8rem; color: var(--text-muted); }
:root[data-theme="dark"] .assistant-msg.bot code { background: rgb(255 255 255 / 0.08); }
:root[data-theme="dark"] .assistant-msg.error { background: rgb(220 38 38 / 0.15); color: #fca5a5; }
/* Con una conversación abierta, por encima del compositor: si no, tapaba el
   botón de enviar, que está en esa misma esquina. */
/* --composer-clearance la mide app.js (trackComposerClearance): lo que ocupa el
   compositor desde el borde inferior, barra inferior y área segura incluidas. */
body:has(#composer:not(.hidden)) .assistant-fab { bottom: calc(var(--composer-clearance, 5rem) + 0.75rem); }
body:has(#composer:not(.hidden)) .assistant-panel { bottom: calc(var(--composer-clearance, 5rem) + 4.75rem); height: min(620px, calc(100vh - var(--composer-clearance, 5rem) - 6.5rem)); height: min(620px, calc(100dvh - var(--composer-clearance, 5rem) - 6.5rem)); }
/* Móvil: por encima de la barra inferior; el chat ocupa la pantalla. */
@media (max-width: 767px) {
  .assistant-fab { bottom: calc(4.75rem + env(safe-area-inset-bottom)); right: 1rem; }
  body:has(#composer:not(.hidden)) .assistant-fab { bottom: calc(var(--composer-clearance, calc(9.5rem + env(safe-area-inset-bottom))) + 0.75rem); }
  .assistant-panel, body:has(#composer:not(.hidden)) .assistant-panel { inset: 0; width: 100%; height: 100%; border-radius: 0; border: 0; }
}
@media (prefers-reduced-motion: reduce) { .assistant-fab { transition: none; } }

/* Selector de acento (Apariencia) */
.accent-swatch { width: 2rem; height: 2rem; border-radius: 9999px; border: 2px solid transparent; }
.accent-swatch[aria-pressed="true"] { border-color: var(--text-primary); box-shadow: 0 0 0 2px var(--bg-surface) inset; }


/* ============================================
   Móvil: sin zoom al tocar un campo
   ============================================
   iOS Safari amplía la página al enfocar un campo con letra de menos de 16 px
   (y a veces no vuelve a su tamaño, así que todo parece más ancho que la
   pantalla). En pantallas táctiles y estrechas los campos van a 16 px. No se
   usa maximum-scale=1 en el viewport: impediría hacer zoom con los dedos. */
@media (pointer: coarse), (max-width: 767px) {
  input:not([type="checkbox"]):not([type="radio"]):not([type="range"]):not([type="color"]):not([type="file"]),
  textarea,
  select {
    font-size: 16px !important;
  }
}

/* =====================================================================
   Calendario (/ui/calendar.js)
   Chrome neutro como el resto; el color de cada calendario solo marca a
   qué calendario pertenece un evento (fondo tintado + filete). Todo con
   tokens semánticos, así que el modo oscuro sale solo.
   ===================================================================== */
.cal-shell { display: flex; height: 100%; min-height: 0; background: var(--bg-surface); position: relative; }
.cal-side {
  width: 264px; flex-shrink: 0; border-right: 1px solid var(--border-soft);
  padding: 16px 12px; overflow-y: auto; display: flex; flex-direction: column; gap: 16px;
  background: var(--bg-surface);
}
.cal-side-backdrop { display: none; }
.cal-only-narrow { display: none; }
@media (max-width: 1023px) {
  .cal-side {
    position: absolute; inset: 0 auto 0 0; z-index: 30; transform: translateX(-100%);
    transition: transform .2s ease;
  }
  .cal-shell.side-open .cal-side { transform: none; box-shadow: 8px 0 32px rgb(0 0 0 / .12); }
  .cal-shell.side-open .cal-side-backdrop { display: block; position: absolute; inset: 0; z-index: 29; background: rgb(0 0 0 / .3); }
  .cal-only-narrow { display: inline-flex; }
}
.cal-new-btn { display: inline-flex; align-items: center; justify-content: center; gap: 6px; width: 100%; padding: 10px 16px; border-radius: 12px; }
.cal-side-head { display: flex; align-items: center; justify-content: space-between; font-size: 12px; font-weight: 600; color: var(--text-secondary); padding: 0 4px; }
.cal-icon-btn {
  display: inline-flex; align-items: center; justify-content: center; width: 34px; height: 34px;
  border-radius: 9999px; color: var(--text-secondary); transition: background .12s, color .12s;
}
.cal-icon-btn:hover { background: var(--bg-hover); color: var(--text-primary); }
.cal-icon-btn:focus-visible, .cal-views button:focus-visible, .cal-chip:focus-visible, .cal-block:focus-visible { outline: 2px solid var(--brand-500); outline-offset: 2px; }

/* Mini mes */
.cal-mini { font-size: 12px; user-select: none; }
.cal-mini-head { display: flex; align-items: center; justify-content: space-between; padding: 0 2px 6px; font-weight: 600; font-size: 13px; }
.cal-mini-head .cal-icon-btn { width: 26px; height: 26px; }
.cal-mini-grid { display: grid; grid-template-columns: repeat(7, 1fr); text-align: center; row-gap: 2px; }
.cal-mini-grid .dow { color: var(--text-muted); font-size: 10px; font-weight: 600; padding-bottom: 4px; }
.cal-mini-grid button { width: 28px; height: 28px; margin: 0 auto; border-radius: 9999px; font-variant-numeric: tabular-nums; color: var(--text-primary); }
.cal-mini-grid button:hover { background: var(--bg-hover); }
.cal-mini-grid button.out { color: var(--text-muted); }
.cal-mini-grid button.in-range { background: rgb(var(--brand-rgb) / .1); }
.cal-mini-grid button.today { background: var(--brand-700); color: #fff; font-weight: 600; }

/* Lista de calendarios */
.cal-list { display: flex; flex-direction: column; gap: 2px; }
.cal-list-label { font-size: 11px; color: var(--text-muted); padding: 8px 6px 2px; }
.cal-item { display: flex; align-items: center; gap: 8px; padding: 5px 6px; border-radius: 8px; font-size: 13px; }
.cal-item:hover { background: var(--bg-hover); }
.cal-item label { display: flex; align-items: center; gap: 10px; flex: 1; min-width: 0; cursor: pointer; }
.cal-item .name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.cal-check { appearance: none; width: 16px; height: 16px; border-radius: 4px; border: 2px solid var(--c); flex-shrink: 0; cursor: pointer; display: grid; place-content: center; }
.cal-check:checked { background: var(--c); }
.cal-check:checked::after { content: ''; width: 8px; height: 5px; border: 2px solid #fff; border-top: 0; border-right: 0; transform: rotate(-45deg) translate(1px, -1px); }
.cal-item .meta { color: var(--text-muted); display: inline-flex; gap: 2px; }
.cal-item .cal-icon-btn { width: 26px; height: 26px; opacity: 0; }
.cal-item:hover .cal-icon-btn, .cal-item .cal-icon-btn:focus-visible { opacity: 1; }
@media (hover: none) { .cal-item .cal-icon-btn { opacity: 1; } }
.cal-empty-side { font-size: 12px; color: var(--text-secondary); padding: 8px 6px; line-height: 1.45; }

/* Barra superior */
.cal-main { flex: 1; min-width: 0; display: flex; flex-direction: column; position: relative; }
.cal-toolbar { display: flex; align-items: center; gap: 8px; padding: 10px 16px; border-bottom: 1px solid var(--border-soft); flex-wrap: wrap; }
.cal-today { padding: 6px 14px; border-radius: 9999px; font-size: 13px; }
.cal-nav { display: flex; }
.cal-title { font-size: 20px; font-weight: 600; letter-spacing: -0.01em; margin-right: auto; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; min-width: 0; }
.cal-toolbar-end { display: flex; align-items: center; gap: 8px; }
.cal-search { display: flex; align-items: center; gap: 6px; padding: 0 10px; height: 34px; border-radius: 9999px; background: var(--bg-hover); color: var(--text-muted); }
.cal-search input { background: transparent; border: 0; outline: 0; width: 140px; font-size: 13px; color: var(--text-primary); }
/* El input no pinta foco propio: el halo va en la píldora (mismo estilo que el foco global). */
.cal-search:focus-within { outline: 2px solid var(--brand-700); outline-offset: 2px; }
:root[data-theme="dark"] .cal-search:focus-within { outline-color: #6ee7b7; }
.cal-views { display: inline-flex; padding: 3px; border-radius: 9999px; background: var(--bg-hover); }
.cal-views button { padding: 5px 12px; border-radius: 9999px; font-size: 13px; font-weight: 500; color: var(--text-secondary); transition: background .12s, color .12s; }
.cal-views button[aria-selected="true"] { background: var(--bg-surface); color: var(--text-primary); box-shadow: 0 1px 3px rgb(0 0 0 / .12); }
@media (max-width: 767px) {
  .cal-toolbar { padding: 8px 12px; gap: 6px; }
  .cal-title { font-size: 17px; }
  .cal-toolbar-end { width: 100%; }
  .cal-search { flex: 1; min-width: 0; } .cal-search input { width: 100%; min-width: 0; }
  .cal-views button { padding: 5px 9px; font-size: 12px; }
}
.cal-view { flex: 1; min-height: 0; overflow: hidden; display: flex; flex-direction: column; }
.cal-fab { display: none; }
@media (max-width: 767px) {
  .cal-fab {
    /* Por encima del botón del asistente, que ocupa la esquina. */
    display: flex; align-items: center; justify-content: center; position: absolute; right: 16px; bottom: 84px; z-index: 20;
    width: 56px; height: 56px; border-radius: 18px; background: var(--brand-600); color: #fff; box-shadow: 0 8px 24px rgb(0 0 0 / .22);
  }
}

/* Eventos: color del calendario en --ev */
.cal-chip, .cal-block, .cal-agenda-item {
  --ev-bg: color-mix(in srgb, var(--ev) 16%, var(--bg-surface));
  --ev-fg: color-mix(in srgb, var(--ev) 55%, var(--text-primary));
}
.cal-chip {
  display: flex; align-items: center; gap: 5px; width: 100%; min-width: 0; text-align: left;
  font-size: 12px; line-height: 1.35; padding: 1px 6px; border-radius: 6px; color: var(--text-primary);
  white-space: nowrap; overflow: hidden; cursor: pointer;
}
.cal-chip:hover { background: var(--bg-hover); }
.cal-chip .dot { width: 8px; height: 8px; border-radius: 9999px; background: var(--ev); flex-shrink: 0; }
.cal-chip .t { color: var(--text-secondary); font-variant-numeric: tabular-nums; flex-shrink: 0; }
.cal-chip .n { overflow: hidden; text-overflow: ellipsis; }
.cal-chip.allday { background: var(--ev-bg); color: var(--ev-fg); font-weight: 500; box-shadow: inset 3px 0 0 var(--ev); }
.cal-chip.allday:hover { background: color-mix(in srgb, var(--ev) 24%, var(--bg-surface)); }
.cal-chip.cancelled .n, .cal-block.cancelled .n { text-decoration: line-through; opacity: .7; }
.cal-chip.tentative, .cal-block.tentative { background-image: repeating-linear-gradient(135deg, transparent 0 6px, rgb(127 127 127 / .08) 6px 12px); }

/* Mes */
.cal-month { flex: 1; display: grid; grid-template-rows: auto 1fr; min-height: 0; }
.cal-month-dow { display: grid; grid-template-columns: repeat(7, minmax(0, 1fr)); border-bottom: 1px solid var(--border-soft); }
.cal-month-dow div { font-size: 11px; font-weight: 600; color: var(--text-secondary); text-align: center; padding: 8px 0 6px; text-transform: uppercase; letter-spacing: .02em; }
.cal-month-grid { display: grid; grid-template-columns: repeat(7, minmax(0, 1fr)); grid-auto-rows: minmax(0, 1fr); min-height: 0; overflow: hidden; }
.cal-day { border-right: 1px solid var(--border-soft); border-bottom: 1px solid var(--border-soft); padding: 4px 4px 2px; min-height: 0; display: flex; flex-direction: column; gap: 1px; overflow: hidden; cursor: default; }
.cal-day:nth-child(7n) { border-right: 0; }
.cal-day.out { background: color-mix(in srgb, var(--bg-hover) 45%, transparent); }
.cal-day.out .num { color: var(--text-muted); }
.cal-day.weekend:not(.out) { background: color-mix(in srgb, var(--bg-hover) 25%, transparent); }
.cal-day .num { align-self: center; font-size: 12px; font-weight: 500; width: 24px; height: 24px; border-radius: 9999px; display: grid; place-content: center; font-variant-numeric: tabular-nums; cursor: pointer; flex-shrink: 0; }
.cal-day .num:hover { background: var(--bg-hover); }
.cal-day.today .num { background: var(--brand-700); color: #fff; }
.cal-day .more { font-size: 11px; font-weight: 600; color: var(--text-secondary); text-align: left; padding: 0 6px; border-radius: 6px; }
.cal-day .more:hover { background: var(--bg-hover); color: var(--text-primary); }
@media (max-width: 767px) {
  .cal-day { padding: 2px 1px; }
  .cal-chip { font-size: 10px; padding: 0 3px; gap: 3px; }
  .cal-chip .t { display: none; }
}

/* Semana / día */
.cal-week { flex: 1; display: flex; flex-direction: column; min-height: 0; }
.cal-week-head { display: grid; border-bottom: 1px solid var(--border-soft); padding-right: var(--sbw, 0px); }
.cal-week-head .dh { text-align: center; padding: 8px 0 6px; cursor: pointer; }
.cal-week-head .dh .dow { font-size: 11px; font-weight: 600; color: var(--text-secondary); text-transform: uppercase; letter-spacing: .02em; }
.cal-week-head .dh .dn { font-size: 22px; font-weight: 500; width: 40px; height: 40px; margin: 2px auto 0; border-radius: 9999px; display: grid; place-content: center; font-variant-numeric: tabular-nums; }
.cal-week-head .dh:hover .dn { background: var(--bg-hover); }
.cal-week-head .dh.today .dow { color: var(--brand-700); }
:root[data-theme="dark"] .cal-week-head .dh.today .dow { color: var(--brand-300); }
.cal-week-head .dh.today .dn { background: var(--brand-700); color: #fff; }
.cal-allday { display: grid; border-bottom: 1px solid var(--border-soft); padding-right: var(--sbw, 0px); max-height: 96px; overflow-y: auto; }
.cal-allday .gutter { font-size: 10px; color: var(--text-muted); text-align: right; padding: 4px 8px 0 0; }
.cal-allday .col { border-left: 1px solid var(--border-soft); padding: 2px; display: flex; flex-direction: column; gap: 2px; min-height: 26px; min-width: 0; }
.cal-scroll { flex: 1; overflow-y: auto; min-height: 0; position: relative; }
.cal-grid { display: grid; position: relative; }
.cal-hours { position: relative; }
.cal-hours span { position: absolute; right: 8px; transform: translateY(-50%); font-size: 10px; color: var(--text-muted); font-variant-numeric: tabular-nums; }
.cal-col { position: relative; border-left: 1px solid var(--border-soft); touch-action: pan-y; }
.cal-col.weekend { background: color-mix(in srgb, var(--bg-hover) 25%, transparent); }
.cal-col .hl { position: absolute; left: 0; right: 0; border-top: 1px solid var(--border-soft); pointer-events: none; }
.cal-col .hl.half { border-top-style: dashed; opacity: .5; }
.cal-now { position: absolute; left: -1px; right: 0; height: 2px; background: #ef4444; z-index: 8; pointer-events: none; }
.cal-now::before { content: ''; position: absolute; left: -5px; top: -4px; width: 10px; height: 10px; border-radius: 9999px; background: #ef4444; }
.cal-block {
  position: absolute; z-index: 2; border-radius: 8px; padding: 3px 7px; overflow: hidden; cursor: pointer;
  background: var(--ev-bg); color: var(--ev-fg); box-shadow: inset 3px 0 0 var(--ev), 0 0 0 1.5px var(--bg-surface);
  font-size: 12px; line-height: 1.3; text-align: left; user-select: none;
}
.cal-block:hover { background: color-mix(in srgb, var(--ev) 24%, var(--bg-surface)); z-index: 9 !important; }
.cal-block .n { font-weight: 600; overflow: hidden; text-overflow: ellipsis; display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; }
.cal-block .t { font-size: 11px; opacity: .85; font-variant-numeric: tabular-nums; }
.cal-block.short { display: flex; align-items: baseline; gap: 5px; white-space: nowrap; padding-top: 2px; padding-bottom: 0; }
.cal-block.short .n { display: block; min-width: 0; overflow: hidden; text-overflow: ellipsis; }
.cal-block.short .t { flex-shrink: 0; }
.cal-block .grip { position: absolute; left: 0; right: 0; bottom: 0; height: 7px; cursor: ns-resize; }
.cal-block.dragging { opacity: .9; box-shadow: inset 3px 0 0 var(--ev), 0 10px 24px rgb(0 0 0 / .2); z-index: 10 !important; cursor: grabbing; }
.cal-block.readonly { cursor: pointer; }
.cal-select { position: absolute; left: 2px; right: 4px; z-index: 3; border-radius: 8px; background: rgb(var(--brand-rgb) / .18); border: 1px solid rgb(var(--brand-rgb) / .5); font-size: 11px; font-weight: 600; color: var(--brand-800); padding: 2px 6px; pointer-events: none; }
:root[data-theme="dark"] .cal-select { color: var(--brand-200); }

/* Agenda */
.cal-agenda { flex: 1; overflow-y: auto; padding: 8px 16px 96px; }
.cal-agenda-day { display: grid; grid-template-columns: 96px 1fr; gap: 12px; padding: 10px 0; border-bottom: 1px solid var(--border-soft); }
.cal-agenda-date { display: flex; align-items: baseline; gap: 6px; cursor: pointer; }
.cal-agenda-date .dn { font-size: 22px; font-weight: 500; font-variant-numeric: tabular-nums; }
.cal-agenda-date .dw { font-size: 11px; font-weight: 600; color: var(--text-secondary); text-transform: uppercase; }
.cal-agenda-day.today .dn { color: var(--brand-700); }
.cal-agenda-item { display: grid; grid-template-columns: 112px 1fr; gap: 12px; width: 100%; text-align: left; padding: 6px 8px; border-radius: 8px; align-items: start; }
.cal-agenda-item:hover { background: var(--bg-hover); }
.cal-agenda-item .t { font-size: 13px; color: var(--text-secondary); font-variant-numeric: tabular-nums; display: flex; align-items: center; gap: 8px; }
.cal-agenda-item .t::before { content: ''; width: 10px; height: 10px; border-radius: 9999px; background: var(--ev); flex-shrink: 0; }
.cal-agenda-item .n { font-size: 14px; font-weight: 500; }
.cal-agenda-item .s { font-size: 12px; color: var(--text-secondary); }
.cal-agenda-empty, .cal-onboard { margin: 48px auto; max-width: 380px; text-align: center; color: var(--text-secondary); font-size: 14px; line-height: 1.5; padding: 0 16px; }
.cal-onboard h3 { color: var(--text-primary); font-size: 16px; font-weight: 600; margin: 12px 0 4px; }
.cal-onboard .ic { width: 48px; height: 48px; border-radius: 14px; margin: 0 auto; display: grid; place-content: center; background: var(--bg-hover); color: var(--text-secondary); }
@media (max-width: 767px) {
  .cal-agenda { padding: 4px 12px 96px; }
  .cal-agenda-day { grid-template-columns: 1fr; gap: 4px; }
  .cal-agenda-item { grid-template-columns: 92px 1fr; gap: 8px; }
}

/* Detalle del evento (popover en escritorio, hoja en móvil) */
.cal-pop {
  /* Por encima del botón del asistente (z 90). */
  position: fixed; z-index: 95; width: 360px; max-width: calc(100vw - 24px); background: var(--bg-elevated);
  border: 1px solid var(--border-soft); border-radius: 16px; box-shadow: 0 20px 60px rgb(0 0 0 / .22);
  animation: pop-in .14s ease-out; overflow: hidden;
}
.cal-pop .bar { height: 6px; background: var(--ev); }
.cal-pop .body { padding: 12px 16px 16px; display: flex; flex-direction: column; gap: 10px; max-height: 70vh; max-height: 70dvh; overflow-y: auto; }
.cal-pop .acts { display: flex; justify-content: flex-end; gap: 2px; margin: 0 -8px -2px 0; }
.cal-pop h4 { font-size: 18px; font-weight: 600; line-height: 1.3; word-break: break-word; }
.cal-pop .row { display: flex; gap: 12px; font-size: 13px; color: var(--text-primary); align-items: flex-start; }
.cal-pop .row > svg, .cal-pop .row > i { flex-shrink: 0; margin-top: 2px; color: var(--text-muted); width: 16px; height: 16px; }
.cal-pop .row .sub { color: var(--text-secondary); font-size: 12px; }
.cal-pop .desc { white-space: pre-wrap; word-break: break-word; }
.cal-pop a { color: var(--brand-700); text-decoration: underline; text-underline-offset: 2px; word-break: break-all; }
@media (max-width: 767px) {
  .cal-pop { left: 0 !important; right: 0; bottom: 0; top: auto !important; width: 100%; max-width: none; border-radius: 20px 20px 0 0; animation: slide-up .2s ease-out; padding-bottom: env(safe-area-inset-bottom); }
}
.cal-pop-backdrop { position: fixed; inset: 0; z-index: 94; }
@media (max-width: 767px) { .cal-pop-backdrop { background: rgb(0 0 0 / .35); } }

/* Formularios del calendario */
.cal-title-input { flex: 1; font-size: 22px; font-weight: 600; background: transparent; border: 0; border-bottom: 2px solid var(--border-soft); padding: 4px 2px 6px; outline: 0; color: var(--text-primary); min-width: 0; }
.cal-title-input:focus { border-bottom-color: var(--brand-500); }
.cal-field { display: flex; align-items: center; gap: 12px; }
.cal-field > svg, .cal-field > i { color: var(--text-muted); flex-shrink: 0; }
.cal-when { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; }
.cal-when .input { width: auto; }
.cal-when .cal-time { width: 110px; }
.cal-when .lbl { width: 58px; font-size: 12px; color: var(--text-secondary); }
.cal-when input[type=date] { flex: 1; min-width: 0; max-width: 180px; }
.cal-inline-select { width: auto; padding-top: 6px; padding-bottom: 6px; }
.cal-switch { display: inline-flex; align-items: center; gap: 8px; font-size: 13px; cursor: pointer; user-select: none; }
.cal-switch input { position: absolute; opacity: 0; width: 1px; height: 1px; }
.cal-switch span { width: 34px; height: 20px; border-radius: 9999px; background: var(--border-strong); position: relative; transition: background .15s; flex-shrink: 0; }
.cal-switch span::after { content: ''; position: absolute; top: 2px; left: 2px; width: 16px; height: 16px; border-radius: 9999px; background: #fff; transition: transform .15s; box-shadow: 0 1px 2px rgb(0 0 0 / .2); }
.cal-switch input:checked + span { background: var(--brand-600); }
.cal-switch input:checked + span::after { transform: translateX(14px); }
.cal-switch input:focus-visible + span { outline: 2px solid var(--brand-500); outline-offset: 2px; }
.cal-swatches { display: flex; flex-wrap: wrap; gap: 8px; }
.cal-swatches button { width: 26px; height: 26px; border-radius: 9999px; background: var(--c); display: grid; place-content: center; color: #fff; box-shadow: 0 0 0 1px rgb(0 0 0 / .08) inset; }
.cal-swatches button[aria-checked="true"] { box-shadow: 0 0 0 2px var(--bg-surface), 0 0 0 4px var(--c); }
.cal-swatches button.none { background: var(--bg-hover); color: var(--text-secondary); font-size: 10px; width: auto; padding: 0 10px; border-radius: 9999px; }
.cal-swatches button.none[aria-checked="true"] { box-shadow: 0 0 0 2px var(--brand-500); }
.cal-more summary { font-size: 13px; color: var(--text-secondary); cursor: pointer; padding-left: 28px; }
.cal-suggest { position: absolute; left: 0; right: 0; top: calc(100% + 4px); z-index: 10; background: var(--bg-elevated); border: 1px solid var(--border-soft); border-radius: 12px; box-shadow: 0 12px 32px rgb(0 0 0 / .14); max-height: 220px; overflow-y: auto; padding: 4px; }
.cal-suggest button { display: block; width: 100%; text-align: left; padding: 7px 10px; border-radius: 8px; font-size: 13px; }
.cal-suggest button:hover, .cal-suggest button[aria-selected="true"] { background: var(--bg-hover); }
.cal-providers { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; }
.cal-providers label { display: flex; gap: 10px; align-items: flex-start; padding: 10px 12px; border: 1px solid var(--border-soft); border-radius: 12px; cursor: pointer; font-size: 13px; }
.cal-providers label:has(input:checked) { border-color: var(--brand-500); box-shadow: 0 0 0 1px var(--brand-500); }
.cal-providers label.disabled { opacity: .55; cursor: not-allowed; }
.cal-providers .sub { display: block; font-size: 11px; color: var(--text-secondary); }
@media (max-width: 767px) { .cal-providers { grid-template-columns: 1fr; } }
.cal-shares { max-height: 240px; overflow-y: auto; border: 1px solid var(--border-soft); border-radius: 12px; }
.cal-share { display: flex; align-items: center; gap: 8px; padding: 7px 10px; border-bottom: 1px solid var(--border-soft); font-size: 13px; }
.cal-share:last-child { border-bottom: 0; }
.cal-share .gname { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; display: flex; align-items: center; gap: 8px; cursor: pointer; }
.cal-share .opts { display: flex; align-items: center; gap: 8px; }
.cal-share .opts select { padding: 3px 8px; font-size: 12px; width: auto; }
.cal-share .opts label { display: inline-flex; gap: 4px; align-items: center; font-size: 12px; color: var(--text-secondary); white-space: nowrap; }
.cal-tool { display: flex; gap: 12px; align-items: flex-start; padding: 12px; border: 1px solid var(--border-soft); border-radius: 12px; }
.cal-scope { display: flex; flex-direction: column; gap: 8px; }
.cal-scope button { text-align: left; padding: 10px 12px; border-radius: 10px; border: 1px solid var(--border-soft); font-size: 14px; }
.cal-scope button:hover { background: var(--bg-hover); }
@media (prefers-reduced-motion: reduce) { .cal-side, .cal-pop { transition: none; animation: none; } }

/* ---------- Modo oscuro: componentes con zinc claro fijo ----------
   Con --zinc-50/100/200 el fondo seguía claro en oscuro: al pasar el ratón por
   una tarjeta de exposición el texto (#fafafa) quedaba blanco sobre blanco. En
   claro no cambia nada. */
:root[data-theme="dark"] .exposure-card { border-color: var(--border-soft); }
:root[data-theme="dark"] .exposure-card:hover { border-color: var(--border-strong); background: var(--bg-hover); }
:root[data-theme="dark"] .placeholder-ac-item:hover { background: var(--bg-hover); }
:root[data-theme="dark"] .placeholder-ac-item.selected { background: rgb(var(--brand-rgb) / 0.12); }
:root[data-theme="dark"] .media-thumb { background: var(--bg-elevated); }
:root[data-theme="dark"] .media-thumb:hover { background: #3f3f46; }
:root[data-theme="dark"] .audio-speed { border-color: var(--border-strong); }
:root[data-theme="dark"] .audio-speed:hover { background: var(--bg-hover); }
:root[data-theme="dark"] .hover-preview { border-color: var(--border-soft); }
:root[data-theme="dark"] .hover-preview code { background: var(--bg-hover); }
:root[data-theme="dark"] .snip-lang-tab { background: var(--bg-hover); color: var(--text-secondary); }
:root[data-theme="dark"] .snip-lang-tab:hover { background: #3f3f46; }
:root[data-theme="dark"] .snip-lang-tab.active { background: rgb(var(--brand-rgb) / 0.12); color: var(--brand-300); border-color: rgb(var(--brand-rgb) / 0.35); }
:root[data-theme="dark"] .snip-lang-tab.dashed { background: transparent; border-color: var(--border-strong); color: var(--text-muted); }
