/* ============================================================
  Titan JS App — Design Tokens (CSS Variables)
   Paleta verde WhatsApp
   ============================================================ */
/* `[data-theme="light"]`: el tema claro también se puede forzar en UN elemento
   dentro de la app oscura (el widget del chatbot con tema fijo en su vista previa),
   igual que `[data-theme="dark"]`. Solo cambia el selector, no hay reglas de componente. */
:root,
[data-theme="light"] {
    /* ── Brand (verde WhatsApp) ──────────────────────────────── */
    --brand-50: #e8f6f2;
    --brand-100: #cdeee4;
    --brand-200: #9fdcc9;
    --brand-300: #66c4a8;
    --brand-400: #2bb08f;
    --brand-500: #0f7d70;
    --brand-600: #0b6a5f;
    --brand-700: #075e54;
    --brand-800: #054a42;
    --brand-900: #033630;
    --brand: #0f7d70;
    --brand-contrast: #ffffff;

    /* ── Accent ────────────────────────────────────────────────── */
    /* --accent-50 se declara aquí aunque nadie lo pinte todavía: sin él, el
       `var(--accent-50, #e9fbef)` de --color-secondary-light dependía de un
       fallback, y ese fallback es un verde claro que en tema oscuro no se
       podría corregir desde ningún sitio. */
    --accent-50: #e9fbef;
    --accent-500: #25d366;
    --accent: #25d366;
    --accent-contrast: #052e1a;

    /* ── Neutrales ─────────────────────────────────────────────── */
    --neutral-50: #f7f9fc;
    --neutral-100: #f1f4f9;
    --neutral-200: #e5e9f0;
    --neutral-300: #d4d9e2;
    --neutral-400: #b9c2cf;
    --neutral-500: #99a5b6;
    --neutral-600: #738196;
    --neutral-700: #5b677a;
    --neutral-800: #434d5b;
    --neutral-900: #2c323c;

    /* ── Surfaces ──────────────────────────────────────────────── */
    --surface-0: #f3f6f5;
    --surface-1: #ffffff;
    --surface-2: #edf2f0;
    --surface-inverse: #0b141a;

    /* ── Texto ─────────────────────────────────────────────────── */
    --text-1: #1f2937;
    --text-2: #4b5563;
    --text-3: #6b7280;
    --text-inverse: #ffffff;

    /* ── Bordes ────────────────────────────────────────────────── */
    --border-subtle: #e5e7eb;
    --border: #d1d5db;
    --border-strong: #9aa3af;

    /* ── States ────────────────────────────────────────────────── */
    --state-hover: rgba(15, 125, 112, .08);
    --state-active: rgba(15, 125, 112, .16);

    /* ── Focus ─────────────────────────────────────────────────── */
    --focus-ring-color: rgba(15, 125, 112, .35);
    --focus-ring: 0 0 0 3px rgba(15, 125, 112, .35);

    /* ── Semánticos ────────────────────────────────────────────── */
    --success: #16a34a;
    --success-on: #ffffff;
    --success-soft: #e9f7ef;
    --success-border: #b7e3c8;

    --warning: #f59e0b;
    --warning-on: #1f1300;
    --warning-soft: #fff7e6;
    --warning-border: #fad7a0;

    --danger: #dc2626;
    --danger-on: #ffffff;
    --danger-soft: #ffecec;
    --danger-border: #f7b4b4;
    /* Hover del botón sólido de peligro. Existe como token porque la
       dirección del hover NO es la misma en los dos temas: sobre fondo
       claro se oscurece, sobre fondo oscuro se aclara. Un filter:
       brightness() fijo acertaría en uno y en el otro se leería como
       "desactivado". */
    --danger-hover: #b91c1c;

    --info: #0284c7;
    --info-on: #ffffff;
    --info-soft: #e6f4ff;
    --info-border: #a6d8ff;

    /* Ayuda («?» que abre un tutorial): bolita azul con blanco, IGUAL en los dos
       temas para que se reconozca en toda la app (el --info del oscuro es claro
       con texto oscuro y el blanco no se leería encima). */
    --help: #0284c7;
    --help-hover: #0369a1;
    --help-on: #ffffff;

    /* ── Sombras ───────────────────────────────────────────────── */
    --shadow-sm: 0 1px 2px rgba(15, 23, 42, .06);
    --shadow-md: 0 2px 4px rgba(15, 23, 42, .08), 0 1px 2px rgba(15, 23, 42, .06);
    --shadow-lg: 0 8px 24px rgba(15, 23, 42, .14);
    --backdrop: rgba(16, 24, 40, .55);
    /* Velo del loader global. Separado de --backdrop porque hace lo
       contrario: --backdrop OSCURECE para destacar un modal encima; este
       ACLARA para dejar ver la página que sigue detrás mientras carga.
       En oscuro, "aclarar" es oscurecer un poco más. */
    --loader-veil: rgba(255, 255, 255, .65);

    /* ── Botones ───────────────────────────────────────────────── */
    --btn-primary-bg: #0f7d70;
    --btn-primary-text: #ffffff;
    --btn-primary-hover: #0b6a5f;

    /* ── Panel de marca del área pública ───────────────────────
     La mitad izquierda de login / forgot / reset. Tiene tokens PROPIOS y no
     reusa --brand-600/800/900 aunque en tema claro valgan lo mismo, porque
     los dos usos divergen en oscuro:

       · La sub-barra del appbar tiene que seguir siendo verde de marca:
         es chrome, y su trabajo es identificar la app.
       · Este panel comparte pantalla con el formulario, que es --surface-1.
         Si conserva la saturación de la marca (64% frente al 29% de la
         superficie) los dos lados chocan: en claro el salto se justifica
         porque el formulario es blanco, pero en oscuro los dos lados son
         oscuros y sin diferencia de luminosidad el salto solo se lee como
         dos verdes que no combinan.

     En claro los valores son exactamente los de --brand-800/600/900, así que
     el aspecto no cambia. En oscuro la base baja a la familia de las
     superficies y el brillo pasa a ser un TINTE translúcido. */
    --hero-base: #075e54;
    --hero-end: #033630;
    --hero-glow: #128c7e;
    /* Sombra al pie del panel, para que el texto blanco se lea sobre el
       degradado. Cuánta hace falta depende de lo claro que sea el degradado
       debajo, así que también cambia con el tema. */
    --hero-shade: rgba(0, 0, 0, .40);

    /* ── Nodo «Consultar API» del editor de chatbots ────────────
     Su propio tono (magenta) para distinguirse de los demás tipos, que ya
     usan brand, accent, info, success, warning y danger. */
    --node-api: #a21caf;
    --node-api-on: #ffffff;

    /* ── Aliases Bootstrap ─────────────────────────────────────── */
    --bs-primary: #0f7d70;
    --bs-success: #16a34a;
    --bs-warning: #f59e0b;
    --bs-danger: #dc2626;
    --bs-body-bg: var(--surface-0);
    --bs-body-color: var(--text-1);
    --bs-border-color: var(--border);

    /* ── Aliases semánticos (compatibilidad con módulos) ────────── */
    --color-primary: var(--brand);
    --color-primary-dark: var(--brand-800);
    --color-primary-light: var(--brand-50);
    --color-secondary: var(--accent);
    --color-secondary-light: var(--accent-50, #e9fbef);
    --color-surface: var(--surface-1);
    --color-background: var(--surface-0);
    --color-text-primary: var(--text-1);
    --color-text-secondary: var(--text-2);
    --color-text-tertiary: var(--text-3);
    --color-border: var(--border);
    --color-error: var(--danger);
    --color-success: var(--success);
    --color-primary-rgb: 15, 125, 112;
    --color-error-rgb: 220, 38, 38;

    /* ── Landing Page ──────────────────────────────────────────── */
    /* Nombres se conservan por compatibilidad; los valores son la paleta verde. */
    --lp-ink: #0b141a;
    --lp-ink2: #111b21;
    --lp-ink3: #202c33;
    --lp-teal: #0f7d70;
    --lp-teal2: #0b6a5f;
    --lp-teal-glow: rgba(15, 125, 112, 0.18);
    --lp-muted: #9fbcb4;
    --lp-border: rgba(255, 255, 255, 0.08);
    --lp-white: #FFFFFF;
    --lp-card: rgba(255, 255, 255, 0.04);

    /* ── Escala de accesibilidad ───────────────────────────────
     Multiplicador global del tamaño de fuente. Es el único punto
     de control: `html` deriva su font-size de aquí y TODO lo demás
     está en `rem`, así que un solo valor mueve la interfaz entera.

     El usuario lo elige en Configuración del sistema → Accesibilidad
     (pensado para quien necesita letra más grande). El valor viaja
     como atributo `data-font-scale` en `<html>`, que index.php
     escribe desde el SERVIDOR con la preferencia de la cuenta
     (tabla user_preference) — sin eso habría un salto de tamaño
     visible al arrancar. Lo cambia el usuario en Mi perfil.

     NO tocar este valor desde CSS de contenedores: es global. */
    --font-scale: 1;

    /* ── Tipografía base ───────────────────────────────────────
     En `rem` a propósito: así siguen la escala de accesibilidad.
     Los comentarios muestran el equivalente en px a escala 1
     (root = 16px). */
    --text-xs: 0.75rem;
    /* 12px */
    --text-sm: 0.8125rem;
    /* 13px */
    --text-body: 0.9375rem;
    /* 15px */
    --text-md: 1rem;
    /* 16px */
    --text-lg: 1.125rem;
    /* 18px */
    --text-h1: 1.25rem;
    /* 20px */
    --text-h2: 1.0625rem;
    /* 17px */
    --line-tight: 1.25;
    --line-normal: 1.5;

    /* Grosor del trazo de los iconos (Material Symbols, 100–700). */
    --icon-weight: 300;
}

/* ── Niveles de la escala ───────────────────────────────────
   `:root[...]` (0,2,0) para ganarle siempre al `:root` de arriba
   sin depender del orden de las reglas.

   Los saltos son de ~15% porque por debajo de eso el cambio no se
   percibe y el usuario cree que el control no hizo nada. */
:root[data-font-scale="sm"] {
    --font-scale: 0.90;
}

/* Pequeña   */
:root[data-font-scale="md"] {
    --font-scale: 1.00;
}

/* Normal    */
:root[data-font-scale="lg"] {
    --font-scale: 1.15;
}

/* Grande    */
:root[data-font-scale="xl"] {
    --font-scale: 1.30;
}

/* Muy grande*/
:root[data-font-scale="xxl"] {
    --font-scale: 1.50;
}

/* Máxima    */

/* Raíz de la escala. Se usa `100%` en vez de `16px` para NO pisar el
   tamaño de fuente que el usuario haya configurado en su navegador o
   en Android/iOS: nuestro multiplicador se aplica encima del suyo. */
html {
    font-size: calc(100% * var(--font-scale));
}

/* ── Tipografía móvil ─────────────────────────────────────
   Sube el body y los títulos en pantallas chicas. */
@media (max-width: 720px) {
    :root {
        --text-body: 1rem;
        /* 16px */
        --text-h1: 1.375rem;
        /* 22px */
        --text-h2: 1.125rem;
        /* 18px */
    }

    /* Piso de 16px REALES en campos de formulario.
     Safari iOS hace zoom automático al enfocar un input cuya letra
     mide menos de 16px, y deja la vista descuadrada al salir. Con la
     escala en "Pequeña" (0.9) el body caería a 14.4px y volvería a
     dispararse ese zoom, así que el piso se fija en px absolutos:
     `max()` toma 16px cuando la escala encoge y deja crecer el rem
     cuando la escala agranda. */
    input,
    select,
    textarea {
        font-size: max(16px, 1rem);
    }
}

/* ============================================================
   TEMA OSCURO
   ============================================================

   Se activa con `data-theme="dark"` en <html>. Lo estampa el bootstrap
   inline de index.php ANTES de que pinte el CSS — si se hiciera desde
   js/main.js habría un destello de tema claro en cada carga.

   Regla del bloque: aquí solo se REDEFINEN tokens, nunca se escriben
   reglas de componente. Si una vista se ve mal en oscuro, el arreglo es
   que use un token, no que este archivo aprenda su selector.
   ============================================================ */
[data-theme="dark"] {

    /* ── Marca ─────────────────────────────────────────────────────
     *
     * La rampa NO se invierte entera, porque sus dos extremos se usan para
     * cosas distintas y opuestas:
     *
     *   50-200  son FONDOS detrás de texto de marca (item activo del nav).
     *           En claro eran pasteles casi blancos; sobre superficie oscura
     *           pasan a ser tintes TRANSLÚCIDOS del acento, que es lo único
     *           que se comporta igual sobre --surface-1 y sobre --surface-2.
     *
     *   300-400 ya eran claros en el tema claro y se quedan como están: son
     *           los que se leen encima del fondo oscuro.
     *
     *   600-900 son CHROME sólido bajo texto blanco (la sub-barra del appbar,
     *           el panel del login). Siguen siendo verdes, pero TODOS bajan.
     *           El #0b6a5f del tema claro, medido contra una página #0b141a,
     *           era el único elemento brillante de la pantalla y se comía la
     *           atención que le tocaba al contenido. Con #0a4d43 la barra
     *           sigue leyéndose como marca (blanco encima > 9:1) y la
     *           píldora de la app activa —que es --surface-1, oscura— sigue
     *           separándose del fondo de la barra.
     *
     * --brand pasa de #0f7d70 a #00a884: el verde de marca es demasiado oscuro sobre
     * #0b141a y es ilegible como texto o como borde. #00a884 da ~6:1 sobre
     * la página y 6,2:1 sobre una tarjeta.
     *
     * Y como --brand también se usa de FONDO (avatar, botón primario),
     * --brand-contrast se voltea a oscuro: el blanco de antes caería a
     * 2,5:1. Es el mismo volteo que ya hacían los --*-on de abajo.
     */
    --brand-50: rgba(0, 168, 132, 0.12);
    --brand-100: rgba(0, 168, 132, 0.18);
    --brand-200: rgba(0, 168, 132, 0.26);
    --brand-300: #6fdcbf;
    --brand-400: #00a884;
    --brand-500: #06b98f;
    --brand-600: #0a4d43;
    --brand-700: #08403a;
    --brand-800: #102a2c;
    --brand-900: #0a1a1d;
    --brand: #00a884;
    --brand-contrast: #0b141a;

    --accent-50: rgba(37, 211, 102, 0.12);
    --accent-500: #25d366;
    --accent: #25d366;
    --accent-contrast: #052e1a;

    /* ── Neutrales ─────────────────────────────────────────────────
     * Rampa invertida: en claro 50 es casi blanco y 900 casi negro, así que
     * leídos en oscuro significan lo contrario de lo que el componente pidió.
     * Invirtiéndola, quien pedía "gris apagado" (--neutral-500 para iconos de
     * placeholder) sigue pidiendo lo mismo y lo sigue recibiendo, sin tocar
     * el componente.
     *
     * --neutral-500 se ajusta a 5,2:1 sobre tarjeta: donde se usa es texto
     * secundario de verdad, no decoración.
     */
    --neutral-50: #151b28;
    --neutral-100: #1b2231;
    --neutral-200: #232c3e;
    --neutral-300: #2f394d;
    --neutral-400: #5a6883;
    --neutral-500: #8b98b2;
    --neutral-600: #a0adc4;
    --neutral-700: #b8c2d6;
    --neutral-800: #d0d8e6;
    --neutral-900: #e5eaf3;

    /* ── Superficies ───────────────────────────────────────────── */
    --surface-0: #0b141a;
    --surface-1: #111b21;
    --surface-2: #202c33;
    --surface-inverse: #f0f2f5;

    /* ── Texto ─────────────────────────────────────────────────────
     * --text-inverse NO se voltea: nombra el texto que va sobre chrome de
     * marca (la sub-barra verde, el panel del login), y ese chrome sigue
     * siendo oscuro en este tema. Voltearlo lo dejaría verde sobre verde.
     */
    --text-1: #e9edef;
    --text-2: #b9c5cb;
    --text-3: #8696a0;
    --text-inverse: #ffffff;

    /* ── Bordes ────────────────────────────────────────────────────
     * Translúcidos a propósito: un borde en hex fijo se ve como una costura
     * cuando la tarjeta está sobre --surface-0 y desaparece cuando está
     * sobre --surface-2. El alfa se adapta solo a las dos.
     */
    --border-subtle: rgba(255, 255, 255, 0.06);
    --border: rgba(255, 255, 255, 0.12);
    --border-strong: rgba(255, 255, 255, 0.22);

    /* ── Estados ───────────────────────────────────────────────────
     * En claro el hover era un tinte de marca sobre blanco. En oscuro el
     * recurso equivalente es ACLARAR: un tinte verde sobre #0D1117 casi no se
     * distingue, un velo blanco sí.
     */
    --state-hover: rgba(255, 255, 255, 0.06);
    --state-active: rgba(255, 255, 255, 0.12);

    /* ── Foco ──────────────────────────────────────────────────────
     * Sube de .35 a .45 de alfa y usa el verde claro: el anillo tiene que
     * verse sobre el fondo oscuro, no fundirse con él.
     */
    --focus-ring-color: rgba(0, 168, 132, 0.45);
    --focus-ring: 0 0 0 3px rgba(0, 168, 132, 0.45);

    /* ── Semánticos en oscuro ──────────────────────────────────────
     *
     * Faltaban. El tema oscuro redefinía superficies, texto y bordes,
     * pero dejaba los semánticos con sus valores de tema claro: los
     * `-soft` seguían siendo pasteles casi blancos (#ffecec, #e9f7ef…).
     * Como `--text-1` en oscuro es casi blanco, cualquier banner que
     * heredara el color del texto quedaba en 1,06:1 de contraste —
     * literalmente ilegible.
     *
     * Y no era solo lo heredado: los componentes que sí fijaban
     * `color: var(--danger)` sobre el pastel daban 4,25:1, y
     * `var(--success)` daba 2,98:1 — tampoco cumplían.
     *
     * Arreglo: `-soft` pasa a ser un TINTE TRANSLÚCIDO del propio tono
     * sobre la superficie oscura, y el tono se aclara para leerse encima.
     * Medido: texto heredado ≥ 12:1, tono sobre su propio soft ≥ 5,7:1.
     *
     * `--*-on` (texto sobre el color sólido) se voltea a oscuro: con el
     * tono aclarado, el blanco de antes caía a 1,74:1 en los botones.
     */
    --success: #4ade80;
    --success-on: #052e16;
    --success-soft: rgba(74, 222, 128, 0.14);
    --success-border: rgba(74, 222, 128, 0.32);

    --warning: #fbbf24;
    /* Oscuro como sus hermanos (-on = tinta SOBRE el color sólido, dice el
     * comentario de arriba). Estuvo en #fde68a —amarillo pálido sobre el
     * ámbar, 1,4:1, ilegible— porque dos vistas lo usaban como "texto
     * ámbar sobre fondo -soft"; esas ya usan --text-1, como .set-note-info.
     * Medido: #451a03 sobre #fbbf24 ≈ 8,8:1. */
    --warning-on: #451a03;
    --warning-soft: rgba(251, 191, 36, 0.14);
    --warning-border: rgba(251, 191, 36, 0.32);

    --danger: #f87171;
    --danger-on: #450a0a;
    --danger-soft: rgba(248, 113, 113, 0.14);
    --danger-border: rgba(248, 113, 113, 0.32);
    --danger-hover: #fca5a5;

    --info: #38bdf8;
    --info-on: #082f49;
    --info-soft: rgba(56, 189, 248, 0.14);
    --info-border: rgba(56, 189, 248, 0.32);

    /* ── Sombras ───────────────────────────────────────────────────
     * En claro la sombra es gris verdeado a poca opacidad, porque su trabajo
     * es separar del blanco. Sobre #0D1117 eso no se ve: pasa a negro casi
     * puro y sube de alfa. Es lo único que despega un modal del fondo
     * cuando los dos son oscuros.
     */
    --shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.40);
    --shadow-md: 0 2px 4px rgba(0, 0, 0, 0.45), 0 1px 2px rgba(0, 0, 0, 0.35);
    --shadow-lg: 0 8px 24px rgba(0, 0, 0, 0.60);
    --backdrop: rgba(0, 0, 0, 0.68);
    --loader-veil: rgba(11, 20, 26, 0.72);

    /* ── Botones ───────────────────────────────────────────────────
     * Mismo volteo que --brand/--brand-contrast, y por el mismo motivo: el
     * botón primario es un bloque de color CLARO con texto oscuro. Es la
     * convención del tema oscuro (Material 3: primary claro, on-primary
     * oscuro) y es lo que mantiene UN solo aspecto de botón en toda la app,
     * porque .set-btn usa --brand y .titan3-btn-primary usa --btn-primary-bg.
     *
     * El hover ACLARA en vez de oscurecer: sobre fondo oscuro, oscurecer se
     * lee como "desactivado", no como "estás encima".
     */
    --btn-primary-bg: #00a884;
    --btn-primary-text: #0b141a;
    --btn-primary-hover: #33c19f;

    /* ── Panel de marca del área pública ───────────────────────────
     * La base se muda a la familia de las superficies: mismo tono (~220°)
     * y saturación ~30%, la de --surface-1, en vez del 48% que tenía
     * heredando --brand-800. Queda entre --surface-0 y --surface-1, así que
     * junto al formulario se lee como una división de paneles y no como un
     * bloque de otro color.
     *
     * El brillo pasa de verde SÓLIDO a tinte TRANSLÚCIDO del acento: sobre
     * una base oscura, un #128c7e opaco es una mancha con borde propio;
     * un 18% del mismo verde tiñe la base y conserva su tono. Es el mismo
     * recurso que usan los --*-soft y los --brand-50/100/200 de arriba.
     */
    --hero-base: #0f1d24;
    --hero-end: #0b141a;
    --hero-glow: rgba(0, 168, 132, 0.18);

    /* Baja de .40 a .15. El .40 del tema claro tenía que oscurecer un verde
       medio para que el texto blanco se leyera; sobre esta base, que ya es
       oscura, solo aplasta el pie del panel a negro plano y se lleva por
       delante la forma del degradado. Con .15 el texto sigue por encima de
       12:1 y el panel conserva profundidad. */
    --hero-shade: rgba(0, 0, 0, .15);

    /* Nodo «Consultar API»: magenta claro con tinta oscura (como los botones). */
    --node-api: #e879f9;
    --node-api-on: #2e0533;

    /* ── Aliases Bootstrap ─────────────────────────────────────────
     * --bs-body-bg / --bs-body-color / --bs-border-color no se repiten: ya
     * apuntan a var(--surface-0) / var(--text-1) / var(--border), y esos se
     * resuelven contra los valores de ESTE bloque. Los que sí van aquí son
     * los que en :root están en hex fijo.
     *
     * Aquí NO hay --bs-secondary-bg, --bs-emphasis-color ni --bs-link-color:
     * son tokens de Bootstrap 5.3 y el que carga index.php es 5.1.3, que aún
     * compila esos colores a literales. Declararlos no pintaría nada y haría
     * creer que el tema cubre más de lo que cubre. Lo que salva a la app es
     * que de bootstrap solo se usan la rejilla y las utilidades — ninguna
     * vista de containers/ usa una clase de componente suyo.
     */
    --bs-primary: #00a884;
    --bs-success: #4ade80;
    --bs-warning: #fbbf24;
    --bs-danger: #f87171;

    /* ── Aliases semánticos ────────────────────────────────────────
     * Los --color-* apuntan a var(...) y siguen solos. Los *-rgb están en
     * tripleta cruda (los consume rgba(var(--x), .5)) y hay que reescribirlos
     * a mano.
     */
    --color-primary-rgb: 0, 168, 132;
    --color-error-rgb: 248, 113, 113;

    /* ── Landing Page ──────────────────────────────────────────────
     * Nacieron oscuros, así que casi todo se queda. --lp-teal sube al verde
     * claro por el mismo motivo que --brand: era ilegible como texto.
     */
    --lp-teal: #00a884;
    --lp-teal2: #33c19f;
    --lp-teal-glow: rgba(0, 168, 132, 0.22);
    --lp-border: rgba(255, 255, 255, 0.10);
    --lp-card: rgba(255, 255, 255, 0.05);
}

/* Pinta en su variante oscura la barra de scroll y los controles NATIVOS
   (checkbox, radio, select, date picker), que no se pueden alcanzar con
   CSS propio. Sin esto se quedan blancos y son lo único de la pantalla que
   delata que el tema oscuro es un añadido. */
:root,
[data-theme="light"] {
    color-scheme: light;
}

[data-theme="dark"] {
    color-scheme: dark;
}
