/* ============================================================================
   hzn-ds.css — el sistema de diseño del CRM de HZN.

   QUÉ ES
   ------
   Una capa de tokens y componentes, servida desde /static con `asset_url()`
   para que herede el cache-busting por hash del contenido.

   POR QUÉ EXISTE
   --------------
   Los colores, los radios y las sombras estaban escritos a mano dentro de cada
   plantilla. `inicio.html` tenía su propio bloque de estilos con el rojo, el oro
   y el verde repetidos como literales, y `shell.html` tenía otro. Dos lugares
   que dicen lo mismo terminan diciendo cosas distintas, y no hay forma de
   agregar un modo oscuro cuando cada pantalla se inventó su propia paleta.

   Acá cada decisión visual vive UNA vez, como variable, con su gemela oscura al
   lado. Cambiar el gris de los bordes es cambiar una línea, no cazar 40.

   CÓMO CONVIVE CON LO QUE YA HAY
   ------------------------------
   Este archivo NO toca elementos desnudos (nada de `body {}` ni `h1 {}`). Solo
   define variables y clases con prefijo `ds-`. Por eso se puede cargar en las 25
   pantallas del hub sin mover ni un pixel de las que todavía están en Tailwind:
   lo que no usa una clase `ds-` no se entera de que este archivo existe.

   EL MODO OSCURO
   --------------
   Los tokens oscuros cuelgan de `[data-theme="dark"]`, un atributo EXPLÍCITO.
   No se usa `prefers-color-scheme` acá a propósito: si el modo oscuro dependiera
   de la preferencia del sistema, las 24 pantallas que todavía no convertimos se
   verían rotas en cualquier laptop configurada en oscuro, sin que nadie hubiera
   pedido nada. El script del shell resuelve la preferencia del sistema y la
   escribe como atributo, pero solo en las pantallas marcadas como listas.
   ========================================================================= */

/* ===========================================================================
   1. TOKENS — CLARO
   =========================================================================== */
:root {
  /* --- espaciado: escala de 4 --------------------------------------------- */
  --sp-1: 4px;
  --sp-2: 8px;
  --sp-3: 12px;
  --sp-4: 16px;
  --sp-5: 20px;
  --sp-6: 24px;
  --sp-7: 32px;
  --sp-8: 40px;
  --sp-9: 48px;
  --sp-10: 64px;

  /* --- un solo radio ------------------------------------------------------
     Una sola curva en todo el producto: tarjetas, botones, inputs y modales.
     `--r-full` no es una segunda decisión de radio, es una forma distinta (la
     píldora), y se usa solo donde el elemento ES una píldora. */
  --r: 12px;
  --r-full: 999px;

  /* --- sombras suaves -----------------------------------------------------
     Tres niveles y ninguno más. La luz cae siempre desde arriba, así que todas
     tienen desplazamiento vertical positivo y nada de blur exagerado: una
     sombra que se nota es una sombra mal puesta. */
  --sh-1: 0 1px 2px rgba(25, 25, 25, .05);
  --sh-2: 0 1px 2px rgba(25, 25, 25, .04), 0 8px 24px rgba(25, 25, 25, .06);
  --sh-3: 0 4px 12px rgba(25, 25, 25, .08), 0 20px 56px rgba(25, 25, 25, .14);

  /* --- superficies -------------------------------------------------------- */
  --bg: #F7F6F4;           /* el off-white del fondo */
  --surface: #FFFFFF;      /* tarjetas */
  --surface-2: #F2F0ED;    /* zonas hundidas: tracks, celdas, hover suave */
  --surface-3: #EAE7E3;    /* separadores gruesos, skeletons */
  --overlay: rgba(25, 25, 25, .48);

  /* --- texto -------------------------------------------------------------- */
  --tx: #191919;           /* tinta */
  --tx-2: #5C5A57;         /* secundario */
  --tx-3: #8E8B87;         /* terciario: etiquetas, ayudas */
  --tx-inv: #FFFFFF;

  /* --- líneas ------------------------------------------------------------- */
  --line: rgba(25, 25, 25, .09);
  --line-2: rgba(25, 25, 25, .16);

  /* --- color de marca -----------------------------------------------------
     El rojo es la acción principal y se usa POCO: un solo botón rojo por
     pantalla. Cuando todo grita, nada se escucha. */
  --red: #d10b0b;
  --red-h: #b50909;        /* hover */
  --red-soft: #FDF0EF;     /* fondo de aviso */
  --red-line: #F3C9C6;

  --gold: #8a5a00;         /* destacado, lo que merece mirarse sin ser urgente */
  --gold-h: #744c00;
  --gold-soft: #FDF5E6;
  --gold-line: #EBD9AE;

  --green: #1a7f37;        /* ganado */
  --green-h: #166b2e;
  --green-soft: #EDF7F0;
  --green-line: #BFE0C9;

  --wine: #7a0114;         /* perdido */
  --wine-h: #66010f;
  --wine-soft: #FBEFF1;
  --wine-line: #EFC9CF;

  /* PIZARRA. No es un color de marca: es el neutro frío del sistema, y existe
     para una sola cosa, que el «en curso» no le compita al oro de la racha.
     Desaturado a propósito: un azul más vivo se leería como un enlace, y un
     anillo no es algo en lo que se pueda hacer clic. */
  --slate: #41586E;
  --slate-soft: #EEF1F4;
  --slate-line: #CBD5DF;

  /* --- color de ESTADO ----------------------------------------------------
     Separado a propósito del color de MARCA. El rojo de marca es la acción
     principal (el botón de llamar); el rojo de estado es peligro. Antes eran el
     mismo literal y por eso un progreso a mitad de camino se pintaba de rojo:
     la pantalla le decía al agente que iba mal cuando simplemente iba a mitad
     de la mañana.

     La regla, y no tiene excepciones:
       sin empezar -> neutro
       en curso    -> PIZARRA
       cumplido    -> verde
       peligro     -> rojo, y NADA MÁS que peligro
       perdido     -> granate

     POR QUÉ EL «EN CURSO» NO ES ORO. Lo fue durante una versión y se cambió: el
     oro ya era el color de la racha, así que el bloque de la racha y los anillos
     quedaban de la misma familia y el ojo no podía separar «esto es un logro» de
     «esto es un dato». Ahora el oro es EXCLUSIVO de la gamificación y el avance
     usa un neutro frío. La regla de fondo: progreso y logro no comparten color.

     Son indirecciones, así que heredan solas la versión oscura de cada token. */
  --state-idle: var(--tx-3);
  --state-progress: var(--slate);
  --state-met: var(--green);
  --state-danger: var(--red);
  --state-lost: var(--wine);

  /* --- tipografía --------------------------------------------------------- */
  --ff-title: 'Cormorant Garamond', Georgia, serif;   /* títulos */
  --ff-ui: 'Manrope', system-ui, sans-serif;          /* interfaz y números */
  --ff-body: 'Inter', system-ui, sans-serif;          /* texto corrido */

  --fs-display: 38px;
  --fs-h1: 28px;
  --fs-h2: 19px;
  --fs-h3: 15px;
  --fs-body: 14px;
  --fs-sm: 13px;
  --fs-xs: 12px;
  --fs-micro: 10.5px;

  /* --- movimiento ---------------------------------------------------------
     Entre 150 y 200ms. Abajo de 150 el cambio no se lee como movimiento sino
     como un salto; arriba de 200 la interfaz se siente lenta. */
  --t-fast: 150ms cubic-bezier(.2, .8, .2, 1);
  --t: 180ms cubic-bezier(.2, .8, .2, 1);
  --t-slow: 200ms cubic-bezier(.2, .8, .2, 1);

  /* El anillo de foco es el mismo en todo el producto, y es visible: alguien
     navegando con teclado tiene que saber dónde está parado. */
  --focus: 0 0 0 2px var(--surface), 0 0 0 4px var(--red);
}

/* ===========================================================================
   2. TOKENS — OSCURO

   No es el claro invertido. En oscuro los colores saturados se apagan y hay que
   levantarlos, o el rojo de marca sobre un fondo casi negro queda ilegible.
   Cada color de marca tiene acá su versión levantada, con el mismo significado.
   =========================================================================== */
:root[data-theme="dark"] {
  --sh-1: 0 1px 2px rgba(0, 0, 0, .40);
  --sh-2: 0 1px 2px rgba(0, 0, 0, .32), 0 8px 24px rgba(0, 0, 0, .44);
  --sh-3: 0 4px 12px rgba(0, 0, 0, .40), 0 20px 56px rgba(0, 0, 0, .60);

  --bg: #121211;
  --surface: #1B1B1A;
  --surface-2: #232322;
  --surface-3: #2C2C2A;
  --overlay: rgba(0, 0, 0, .66);

  --tx: #F2F0ED;
  --tx-2: #A8A5A0;
  --tx-3: #7A7773;
  --tx-inv: #121211;

  --line: rgba(255, 255, 255, .10);
  --line-2: rgba(255, 255, 255, .18);

  --red: #F0564F;
  --red-h: #F76E67;
  --red-soft: #2E1614;
  --red-line: #5A2622;

  --gold: #D9A441;
  --gold-h: #E7B75C;
  --gold-soft: #2A2114;
  --gold-line: #4E3D1D;

  --green: #4AC26B;
  --green-h: #62D081;
  --green-soft: #12251A;
  --green-line: #234A30;

  --wine: #E0576B;
  --wine-h: #EA7183;
  --wine-soft: #2B1418;
  --wine-line: #55232C;

  /* La pizarra también se levanta en oscuro: el #41586E del modo claro sobre un
     fondo casi negro sería una mancha sin forma. */
  --slate: #8AA6C4;
  --slate-soft: #1A2028;
  --slate-line: #33404F;

  --focus: 0 0 0 2px var(--surface), 0 0 0 4px var(--red);

  /* Le avisa al NAVEGADOR que esto es oscuro. Sin esto las barras de
     desplazamiento, los calendarios de los `input[type=date]` y las flechas de
     los `select` se siguen dibujando en claro: quedaba una barra blanca cruzando
     el tablero oscuro. Va en la raíz para no repetirlo pantalla por pantalla. */
  color-scheme: dark;
}

/* ===========================================================================
   PUENTE CON TAILWIND

   Las pantallas del hub todavía traen clases de Tailwind para el texto y los
   fondos (`text-hzn-gray`, `bg-white`...). Esos colores están escritos para
   fondo claro: un #504F50 sobre un fondo casi negro no se lee.

   Reescribir las cientos de apariciones no daría más valor que estas ocho
   líneas, y el marcado va a migrar a clases `ds-` a medida que cada pantalla
   pase por el facelift. Mientras tanto, esta capa las traduce a tokens.

   Vive acá y no dentro de una plantilla a propósito: empezó duplicada en la
   ficha y ya la necesitaban tres pantallas. Un puente por pantalla es la misma
   paleta desparramada que este archivo vino a terminar.

   Solo actúa bajo `[data-theme]`, o sea SOLO en las pantallas convertidas: en
   claro no cambia nada y las que siguen en Tailwind no se enteran.
   =========================================================================== */
:root[data-theme="dark"] .text-hzn-gray  { color: var(--tx-2); }
:root[data-theme="dark"] .text-hzn-black { color: var(--tx); }
:root[data-theme="dark"] .text-hzn-red   { color: var(--red); }
:root[data-theme="dark"] .text-white     { color: #fff; }
:root[data-theme="dark"] .bg-white       { background: var(--surface); }
:root[data-theme="dark"] .bg-hzn-bg      { background: var(--bg); }
:root[data-theme="dark"] .bg-hzn-bg-soft { background: var(--surface-2); }
:root[data-theme="dark"] .bg-hzn-black   { background: var(--surface-3); }
/* `shadow-card` es la sombra de Tailwind calculada con tinta sobre blanco: en
   oscuro no se ve nada. Se cambia por la sombra de tarjeta del sistema, que ya
   viene con su versión oscura. Y a una tarjeta blanca convertida se le agrega
   el borde: sin él, una superficie clara sobre un fondo oscuro flota sin canto. */
:root[data-theme="dark"] .shadow-card { box-shadow: var(--sh-2); }
:root[data-theme="dark"] .shadow-lg   { box-shadow: var(--sh-3); }
:root[data-theme="dark"] .bg-white.shadow-card { border: 1px solid var(--line); }

/* LOS BORDES DE TINTA. `border-black/5` y `border-black/10` son negro con cinco
   o diez por ciento de opacidad: sobre un fondo claro son una línea tenue y
   sobre uno oscuro NO SON NADA. Es la clase de detalle que no se ve en una
   captura y se nota al usar la pantalla: las tarjetas pierden el canto y las
   secciones de un formulario se funden en una sola pared.
   `--line` y `--line-2` son las mismas líneas pero declaradas al revés en
   oscuro (blanco con poca opacidad), así que acá se traducen y listo. */
:root[data-theme="dark"] .border-black\/5  { border-color: var(--line); }
:root[data-theme="dark"] .border-black\/10 { border-color: var(--line); }
:root[data-theme="dark"] .border-black\/20 { border-color: var(--line-2); }
:root[data-theme="dark"] .divide-black\/5  > * + * { border-color: var(--line); }
:root[data-theme="dark"] .divide-black\/10 > * + * { border-color: var(--line); }

/* Los blancos TRASLÚCIDOS. Una barra pegajosa con `bg-white/85` deja ver lo que
   pasa por debajo, y eso está bien; lo que no puede es seguir siendo BLANCA en
   oscuro. Se cambia por la superficie del tema con la misma transparencia, que
   conserva el efecto y cambia el color. */
:root[data-theme="dark"] .bg-white\/85 { background-color: color-mix(in srgb, var(--surface) 85%, transparent); }
:root[data-theme="dark"] .bg-white\/95 { background-color: color-mix(in srgb, var(--surface) 95%, transparent); }
:root[data-theme="dark"] .bg-white\/25 { background-color: color-mix(in srgb, var(--surface) 25%, transparent); }

/* Los grises con opacidad. `text-hzn-gray/70` es el gris medio del tema claro
   rebajado: en oscuro el original ya es casi el fondo, así que rebajarlo lo
   borra. Se parte del texto terciario, que en oscuro sí se aclara. */
:root[data-theme="dark"] .text-hzn-gray\/80 { color: var(--tx-2); }
:root[data-theme="dark"] .text-hzn-gray\/70 { color: var(--tx-3); }
:root[data-theme="dark"] .text-hzn-gray\/50 { color: var(--tx-3); }
:root[data-theme="dark"] .text-hzn-gray\/40 { color: var(--tx-3); }

/* Nadie tiene que ver una animación si pidió no verlas. */
@media (prefers-reduced-motion: reduce) {
  :root {
    --t-fast: 1ms;
    --t: 1ms;
    --t-slow: 1ms;
  }
}

/* ===========================================================================
   3. BASE de las pantallas convertidas

   Solo se aplica donde el shell puso `data-theme`, es decir donde la pantalla
   se declaró lista. En las demás este bloque no existe.
   =========================================================================== */
:root[data-theme] body {
  background: var(--bg);
  color: var(--tx);
  font-family: var(--ff-body);
  transition: background var(--t), color var(--t);
}

/* ===========================================================================
   4. TIPOGRAFÍA

   Sin itálicas en ningún nivel: la Cormorant en itálica se lee bonita en una
   invitación y mal en una pantalla de trabajo.
   =========================================================================== */
.ds-display {
  font-family: var(--ff-title);
  font-size: var(--fs-display);
  font-weight: 500;
  font-style: normal;
  line-height: 1.08;
  letter-spacing: -.01em;
  color: var(--tx);
}

.ds-h1 {
  font-family: var(--ff-title);
  font-size: var(--fs-h1);
  font-weight: 600;
  font-style: normal;
  line-height: 1.15;
  color: var(--tx);
}

.ds-h2 {
  font-family: var(--ff-ui);
  font-size: var(--fs-h2);
  font-weight: 800;
  letter-spacing: -.02em;
  line-height: 1.25;
  color: var(--tx);
}

.ds-h3 {
  font-family: var(--ff-ui);
  font-size: var(--fs-h3);
  font-weight: 700;
  letter-spacing: -.01em;
  color: var(--tx);
}

.ds-body { font-size: var(--fs-body); line-height: 1.5; color: var(--tx); }
.ds-sub  { font-size: var(--fs-sm); line-height: 1.45; color: var(--tx-2); }
.ds-help { font-size: var(--fs-xs); line-height: 1.4; color: var(--tx-3); }

/* La etiqueta chica en versalitas: para rotular una zona sin competir con su
   contenido. */
.ds-eyebrow {
  font-family: var(--ff-ui);
  font-size: var(--fs-micro);
  font-weight: 800;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--tx-3);
}

/* Los números que cambian solos (contadores, metas) van tabulares o bailan. */
.ds-num { font-family: var(--ff-ui); font-weight: 800; font-variant-numeric: tabular-nums; }

/* ===========================================================================
   5. BOTÓN
   =========================================================================== */
.ds-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--sp-2);
  font-family: var(--ff-ui);
  font-size: var(--fs-sm);
  font-weight: 700;
  line-height: 1;
  padding: 11px 16px;
  min-height: 42px;             /* zona de toque cómoda en móvil */
  border-radius: var(--r);
  border: 1px solid var(--line-2);
  background: var(--surface);
  color: var(--tx);
  cursor: pointer;
  white-space: nowrap;
  text-align: center;
  transition: background var(--t-fast), border-color var(--t-fast),
              color var(--t-fast), transform var(--t-fast), box-shadow var(--t-fast);
}

.ds-btn:hover { background: var(--surface-2); border-color: var(--line-2); }
.ds-btn:active { transform: scale(.975); }
.ds-btn:focus-visible { outline: none; box-shadow: var(--focus); }
.ds-btn[disabled], .ds-btn.is-disabled { opacity: .5; cursor: not-allowed; transform: none; }
.ds-btn svg { width: 16px; height: 16px; flex: none; }

/* LA REGLA DE LOS RELLENOS DE COLOR
   ---------------------------------
   Todo lo que se pinta con un color de marca DE FONDO (el botón rojo, el verde
   de WhatsApp) lleva su texto en `--tx-inv`, nunca en blanco fijo.

   Por qué. En oscuro los colores de marca se ACLARAN para poder verse sobre un
   fondo casi negro: el rojo pasa de #d10b0b a #F0564F y el verde de #1a7f37 a
   #4AC26B. Encima de esos tonos claros el blanco se apaga. Medido en el
   navegador sobre /hub en oscuro, el botón «Llamar ahora» daba 3.42:1 entre su
   texto blanco y su fondo: por debajo del 4.5:1 que pide WCAG AA para texto
   normal (13px en negrita NO cuenta como texto grande, que empieza en 18.66px).
   `--tx-inv` sube ese mismo botón a 5.5:1.

   `--tx-inv` es BLANCO en claro, así que en el tema claro no se mueve un pixel:
   el rojo #d10b0b con texto blanco ya daba 5.58:1 y sigue dando lo mismo.

   POR QUÉ NO SE OSCURECE EL ROJO EN VEZ DE CAMBIAR LA TINTA. Porque `--red` no
   es solo un fondo: también es color de TEXTO sobre fondos oscuros (`.ds-req`,
   `.ds-chip--red`, `.text-hzn-red`). Un rojo lo bastante oscuro como para
   aguantar el blanco encima (luminancia ≤ 0.18) baja a 3.8:1 como texto sobre
   `--surface`, o sea arregla el botón y rompe todo lo demás. Los dos usos piden
   cosas opuestas del mismo color, y por eso lo que cambia es la TINTA de encima
   y no el color de abajo.

   Este comentario antes decía que «el verde no es como el rojo». Sí lo es: el
   rojo también se aclara en oscuro. Era el único caso que faltaba. */

/* La acción principal. Una por pantalla. */
.ds-btn--primary {
  background: var(--red);
  border-color: var(--red);
  color: var(--tx-inv);
}
.ds-btn--primary:hover { background: var(--red-h); border-color: var(--red-h); }

/* WhatsApp comparte jerarquía con Llamar: en Perú son los dos canales reales y
   elegir uno por el agente sería inventarle una preferencia. */
.ds-btn--wa {
  background: var(--green);
  border-color: var(--green);
  color: var(--tx-inv);
}
.ds-btn--wa:hover { background: var(--green-h); border-color: var(--green-h); }

.ds-btn--wine { background: transparent; border-color: var(--wine); color: var(--wine); }
.ds-btn--wine:hover { background: var(--wine-soft); }

/* Sin marco: para lo terciario, que tiene que estar pero no pesar. */
.ds-btn--quiet { background: transparent; border-color: transparent; color: var(--tx-2); }
.ds-btn--quiet:hover { background: var(--surface-2); color: var(--tx); }

.ds-btn--sm { min-height: 34px; padding: 8px 12px; font-size: var(--fs-xs); }
.ds-btn--block { width: 100%; }

/* Botón de solo ícono, cuadrado. */
.ds-icon-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 38px;
  height: 38px;
  flex: none;
  border-radius: var(--r);
  border: 1px solid transparent;
  background: transparent;
  color: var(--tx-2);
  cursor: pointer;
  transition: background var(--t-fast), color var(--t-fast);
}
.ds-icon-btn:hover { background: var(--surface-2); color: var(--tx); }
.ds-icon-btn:focus-visible { outline: none; box-shadow: var(--focus); }
.ds-icon-btn svg { width: 18px; height: 18px; }

/* ===========================================================================
   6. TARJETA
   =========================================================================== */
.ds-card {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r);
  box-shadow: var(--sh-2);
  padding: var(--sp-5);
  transition: background var(--t), border-color var(--t), box-shadow var(--t);
}

.ds-card--flat { box-shadow: var(--sh-1); }
.ds-card--quiet { background: var(--surface-2); box-shadow: none; }

/* Tarjeta que además es un enlace: se levanta apenas al pasar por encima. */
.ds-card--link {
  display: block;
  transition: box-shadow var(--t), transform var(--t), background var(--t), border-color var(--t);
}
.ds-card--link:hover { box-shadow: var(--sh-3); transform: translateY(-2px); }

.ds-card__head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--sp-3);
  flex-wrap: wrap;
  margin-bottom: var(--sp-4);
}

/* ===========================================================================
   7. CHIP
   =========================================================================== */
.ds-chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-family: var(--ff-ui);
  font-size: var(--fs-micro);
  font-weight: 700;
  line-height: 1;
  padding: 5px 10px;
  border-radius: var(--r-full);
  border: 1px solid var(--line-2);
  background: var(--surface);
  color: var(--tx-2);
  white-space: nowrap;
}

.ds-chip__dot { width: 6px; height: 6px; border-radius: 50%; flex: none; background: currentColor; }

/* La equis de un chip que se puede QUITAR. Vive en el sistema de diseño y no en
   la pantalla que la estrenó (el selector de distritos del buscador) porque un
   chip removible es un patrón, no un caso: el próximo que lo necesite no tiene
   que volver a decidir de qué tamaño es la equis.

   Hereda el color del chip a propósito: un chip rojo lleva su equis roja sin que
   nadie escriba una segunda regla. Y arranca atenuada — la equis está para
   cuando la buscás, no para competir con el nombre que el chip dice. */
.ds-chip__x {
  border: 0;
  background: none;
  color: inherit;
  font: inherit;
  font-size: 15px;
  line-height: 1;
  padding: 0 0 0 2px;
  margin-left: 2px;
  cursor: pointer;
  opacity: .55;
}
.ds-chip__x:hover,
.ds-chip__x:focus-visible { opacity: 1; }

/* ---------------------------------------------------------------------------
   CHIP DE ETAPA. La etapa de un contacto no es color de marca ni color de
   estado: es una FAMILIA propia (bandeja, trabajando, calificado, cita, ganado,
   activo) y tiene que leerse igual en todas las oficinas, con cualquier acento.

   Las familias y sus colores claros son los mismos que `contacts_store` ya venía
   sirviendo como hex en línea; lo que se agrega acá es la versión OSCURA, que
   con un estilo en línea era imposible: un atributo `style` le gana a cualquier
   clase, así que mientras el color viajara en el HTML no había forma de que
   cambiara con el tema.

   `oscuro` se INVIERTE en modo oscuro a propósito. Significa «lo más avanzado»
   y lo decía siendo casi negro sobre blanco; sobre un fondo oscuro eso
   desaparece, así que pasa a ser claro sobre oscuro y conserva su significado,
   que es ser el más fuerte de la escala.
   --------------------------------------------------------------------------- */
.ds-stage {
  display: inline-flex;
  align-items: center;
  font-family: var(--ff-ui);
  font-size: var(--fs-micro);
  font-weight: 700;
  line-height: 1;
  padding: 5px 10px;
  border-radius: var(--r-full);
  border: 1px solid transparent;
  white-space: nowrap;
}

.ds-stage--gris   { background: #F0EFEF; color: #504F50; border-color: #E2E0E0; }
.ds-stage--ambar  { background: #FEF3E2; color: #B45309; border-color: #FBE2BC; }
.ds-stage--azul   { background: #E7F0FB; color: #1D4ED8; border-color: #C9DCF6; }
.ds-stage--morado { background: #F1E9FB; color: #6D28D9; border-color: #E0CDF6; }
.ds-stage--verde  { background: #E7F6EC; color: #1A7F37; border-color: #C6E8D1; }
.ds-stage--oscuro { background: #1F1D1D; color: #FFFFFF; border-color: #1F1D1D; }

:root[data-theme="dark"] .ds-stage--gris   { background: #262625; color: #A8A5A0; border-color: #3A3A38; }
:root[data-theme="dark"] .ds-stage--ambar  { background: #2A2114; color: #E0A85C; border-color: #4E3D1D; }
:root[data-theme="dark"] .ds-stage--azul   { background: #16202B; color: #8AB4F8; border-color: #2A3B50; }
:root[data-theme="dark"] .ds-stage--morado { background: #221A2E; color: #C4A2F5; border-color: #3B2D50; }
:root[data-theme="dark"] .ds-stage--verde  { background: #12251A; color: #4AC26B; border-color: #234A30; }
:root[data-theme="dark"] .ds-stage--oscuro { background: #F2F0ED; color: #121211; border-color: #F2F0ED; }

/* El puntito de color que encabeza una columna del tablero: el mismo mapa de
   familias, pero como relleno sólido. */
.ds-stage-dot--gris   { background: #504F50; }
.ds-stage-dot--ambar  { background: #B45309; }
.ds-stage-dot--azul   { background: #1D4ED8; }
.ds-stage-dot--morado { background: #6D28D9; }
.ds-stage-dot--verde  { background: #1A7F37; }
.ds-stage-dot--oscuro { background: #1F1D1D; }

:root[data-theme="dark"] .ds-stage-dot--gris   { background: #A8A5A0; }
:root[data-theme="dark"] .ds-stage-dot--ambar  { background: #E0A85C; }
:root[data-theme="dark"] .ds-stage-dot--azul   { background: #8AB4F8; }
:root[data-theme="dark"] .ds-stage-dot--morado { background: #C4A2F5; }
:root[data-theme="dark"] .ds-stage-dot--verde  { background: #4AC26B; }
:root[data-theme="dark"] .ds-stage-dot--oscuro { background: #F2F0ED; }

.ds-chip--red   { color: var(--red);   border-color: var(--red-line);   background: var(--red-soft); }
.ds-chip--gold  { color: var(--gold);  border-color: var(--gold-line);  background: var(--gold-soft); }
.ds-chip--green { color: var(--green); border-color: var(--green-line); background: var(--green-soft); }
.ds-chip--wine  { color: var(--wine);  border-color: var(--wine-line);  background: var(--wine-soft); }
.ds-chip--solid { background: var(--tx); border-color: var(--tx); color: var(--surface); }

/* ===========================================================================
   8. INPUT
   =========================================================================== */
.ds-label {
  display: block;
  font-family: var(--ff-ui);
  font-size: var(--fs-xs);
  font-weight: 700;
  color: var(--tx);
  margin-bottom: 6px;
}

/* Marca lo obligatorio con palabra, no con un asterisco que hay que descifrar. */
.ds-req {
  font-size: var(--fs-micro);
  font-weight: 800;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--red);
  margin-left: 6px;
}

.ds-input {
  width: 100%;
  font-family: var(--ff-body);
  font-size: var(--fs-body);
  color: var(--tx);
  background: var(--surface);
  border: 1px solid var(--line-2);
  border-radius: var(--r);
  padding: 11px 13px;
  min-height: 44px;
  transition: border-color var(--t-fast), box-shadow var(--t-fast), background var(--t-fast);
}

.ds-input::placeholder { color: var(--tx-3); }
.ds-input:hover { border-color: var(--line-2); }
.ds-input:focus { outline: none; border-color: var(--red); box-shadow: 0 0 0 3px var(--red-soft); }
.ds-input:disabled { background: var(--surface-2); color: var(--tx-3); cursor: not-allowed; }


/* Grupo de opciones excluyentes, tipo segmentos. */
.ds-seg { display: flex; flex-wrap: wrap; gap: 6px; }
.ds-seg__b {
  font-family: var(--ff-ui);
  font-size: var(--fs-xs);
  font-weight: 700;
  padding: 9px 13px;
  min-height: 38px;
  border-radius: var(--r);
  border: 1px solid var(--line-2);
  background: var(--surface);
  color: var(--tx-2);
  cursor: pointer;
  transition: background var(--t-fast), color var(--t-fast), border-color var(--t-fast);
}
.ds-seg__b:hover { background: var(--surface-2); color: var(--tx); }
.ds-seg__b.is-on { background: var(--tx); border-color: var(--tx); color: var(--surface); }
.ds-seg__b:focus-visible { outline: none; box-shadow: var(--focus); }

/* ===========================================================================
   9. MODAL

   En móvil sube desde abajo y ocupa el ancho (el pulgar llega); de 640px para
   arriba se centra como diálogo.
   =========================================================================== */
.ds-modal {
  position: fixed;
  inset: 0;
  z-index: 140;
  background: var(--overlay);
  display: flex;
  align-items: flex-end;
  justify-content: center;
  padding: 0;
  animation: ds-fade var(--t) ease;
}

.ds-modal[hidden] { display: none; }

.ds-modal__card {
  background: var(--surface);
  color: var(--tx);
  border-radius: var(--r) var(--r) 0 0;
  box-shadow: var(--sh-3);
  padding: var(--sp-5) var(--sp-5) var(--sp-6);
  width: 100%;
  max-width: 540px;
  max-height: 92vh;
  overflow-y: auto;
  animation: ds-rise var(--t-slow) cubic-bezier(.2, .8, .2, 1);
}

.ds-modal__actions {
  display: flex;
  gap: var(--sp-2);
  justify-content: flex-end;
  margin-top: var(--sp-5);
}

@keyframes ds-fade { from { opacity: 0 } to { opacity: 1 } }
@keyframes ds-rise { from { transform: translateY(14px); opacity: .6 } to { transform: none; opacity: 1 } }

/* ===========================================================================
   10. AVATAR
   =========================================================================== */
.ds-avatar {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex: none;
  width: 40px;
  height: 40px;
  border-radius: var(--r-full);
  object-fit: cover;
  background: var(--surface-3);
  color: var(--tx);
  font-family: var(--ff-ui);
  font-size: var(--fs-sm);
  font-weight: 800;
  letter-spacing: .02em;
  overflow: hidden;
}

.ds-avatar--sm { width: 30px; height: 30px; font-size: var(--fs-xs); }
.ds-avatar--lg { width: 52px; height: 52px; font-size: var(--fs-h3); }

/* ===========================================================================
   11. ÍTEM DE TIMELINE

   Una columna con la línea y el punto, y el contenido al lado. El último ítem
   corta la línea para que no quede colgando en el vacío.
   =========================================================================== */
.ds-tl { list-style: none; margin: 0; padding: 0; }

.ds-tl__item {
  position: relative;
  display: grid;
  grid-template-columns: 22px 1fr;
  gap: var(--sp-3);
  padding-bottom: var(--sp-5);
}

.ds-tl__item:last-child { padding-bottom: 0; }

.ds-tl__rail { position: relative; display: flex; justify-content: center; }

.ds-tl__dot {
  width: 10px;
  height: 10px;
  margin-top: 4px;
  border-radius: 50%;
  background: var(--tx-3);
  border: 2px solid var(--surface);
  box-shadow: 0 0 0 1px var(--line-2);
  flex: none;
  z-index: 1;
}

.ds-tl__dot--red   { background: var(--red); }
.ds-tl__dot--gold  { background: var(--gold); }
.ds-tl__dot--green { background: var(--green); }
.ds-tl__dot--wine  { background: var(--wine); }

.ds-tl__item:not(:last-child) .ds-tl__rail::after {
  content: '';
  position: absolute;
  top: 16px;
  bottom: calc(var(--sp-5) * -1);
  width: 1px;
  background: var(--line);
}

.ds-tl__when { font-size: var(--fs-micro); font-weight: 700; letter-spacing: .06em;
               text-transform: uppercase; color: var(--tx-3); }
.ds-tl__what { font-size: var(--fs-sm); color: var(--tx); margin-top: 2px; line-height: 1.45; }

/* ===========================================================================
   12. ANILLO DE PROGRESO

   El arco se dibuja con stroke-dasharray sobre r=52, o sea 326,7 de
   circunferencia: 1% = 3,2673. El SVG va rotado -90 grados para que empiece
   arriba y no a las tres en punto.
   =========================================================================== */
/* El disco es un cuadrado propio con el SVG adentro, y el centro se posiciona
   contra ÉL y no contra una altura escrita a mano. Antes `--mid` tenía
   `height:108px` fijo, así que cualquier anillo de otro tamaño dejaba el número
   descentrado. Ahora el tamaño se cambia en un solo lugar, `--ring-d`. */
.ds-ring { text-align: center; --ring-d: 132px; }

.ds-ring__d { position: relative; width: var(--ring-d); max-width: 100%; margin: 0 auto; }
.ds-ring__svg { width: 100%; height: auto; display: block; transform: rotate(-90deg); }
.ds-ring__bg { fill: none; stroke: var(--surface-3); stroke-width: 12; }
.ds-ring__fg {
  fill: none;
  stroke-width: 12;
  stroke-linecap: round;
  transition: stroke-dasharray 700ms cubic-bezier(.2, .8, .2, 1), stroke var(--t);
}

/* Los tres estados del arco, y ninguno más. Ver «color de ESTADO» arriba. */
.ds-ring__fg--progress { stroke: var(--state-progress); }
.ds-ring__fg--met      { stroke: var(--state-met); }
.ds-ring__fg--idle     { stroke: var(--state-idle); }

/* El anillo grande: el número principal de la pantalla. */
.ds-ring--lg { --ring-d: 196px; }
.ds-ring--lg .ds-ring__done { font-size: 46px; }
.ds-ring--lg .ds-ring__goal { font-size: var(--fs-h3); }

.ds-ring__mid {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 3px;
  pointer-events: none;
}

.ds-ring__done { font-family: var(--ff-ui); font-size: 30px; font-weight: 800;
                 color: var(--tx); font-variant-numeric: tabular-nums; line-height: 1; }
.ds-ring__goal { font-size: var(--fs-sm); color: var(--tx-3); font-variant-numeric: tabular-nums; }
.ds-ring__label { font-family: var(--ff-ui); font-size: var(--fs-sm); font-weight: 700;
                  color: var(--tx); margin-top: 10px; line-height: 1.25; }
.ds-ring__src { font-size: var(--fs-micro); color: var(--tx-3); margin-top: 2px; line-height: 1.3; }

/* ===========================================================================
   13. ESTADO VACÍO

   Un vacío nunca es una pantalla en blanco: dice qué significa, qué hacer y
   deja el botón para hacerlo. Es la primera pantalla que ve alguien que recién
   entra, y tiene que enseñar sola.
   =========================================================================== */
.ds-empty {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  padding: var(--sp-8) var(--sp-5);
  gap: var(--sp-3);
}

.ds-empty__ico {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 52px;
  height: 52px;
  border-radius: var(--r-full);
  background: var(--surface-2);
  color: var(--tx-3);
  margin-bottom: var(--sp-1);
}
.ds-empty__ico svg { width: 24px; height: 24px; }
.ds-empty__ico--green { background: var(--green-soft); color: var(--green); }

.ds-empty__t { font-family: var(--ff-ui); font-size: var(--fs-h3); font-weight: 800; color: var(--tx); }
.ds-empty__d { font-size: var(--fs-sm); color: var(--tx-2); max-width: 42ch; line-height: 1.5; }

/* ===========================================================================
   14. SKELETON

   Gris que respira, sin brillo que cruza: el barrido diagonal se nota más que
   el contenido que está esperando.
   =========================================================================== */
.ds-skel {
  background: var(--surface-3);
  border-radius: var(--r);
  animation: ds-pulse 1.5s ease-in-out infinite;
}

.ds-skel--text { height: 12px; border-radius: var(--r-full); }
.ds-skel--title { height: 20px; width: 45%; border-radius: var(--r-full); }
.ds-skel--circle { border-radius: 50%; }

@keyframes ds-pulse { 0%, 100% { opacity: 1 } 50% { opacity: .45 } }

/* ===========================================================================
   15. PISTA (tooltip)

   Para explicar un número sin poner un párrafo al lado. Aparece con el mouse y
   con el foco de teclado, y el botón que la dispara tiene su propio
   `aria-label`, así que el lector de pantalla no depende de este texto.
   =========================================================================== */
.ds-hint { position: relative; display: inline-flex; }

.ds-hint__q {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 16px;
  height: 16px;
  border-radius: 50%;
  border: 1px solid var(--line-2);
  background: transparent;
  color: var(--tx-3);
  font-family: var(--ff-ui);
  font-size: 10px;
  font-weight: 800;
  line-height: 1;
  cursor: help;
  padding: 0;
  transition: color var(--t-fast), border-color var(--t-fast);
}
.ds-hint__q:hover { color: var(--tx); border-color: var(--tx-3); }
.ds-hint__q:focus-visible { outline: none; box-shadow: var(--focus); }

/* `display:none` y no `opacity:0`: un elemento absoluto invisible SIGUE contando
   para el ancho desplazable de la página. Medido en un teléfono de 390px, las
   pistas de los anillos estiraban el documento a 440px y aparecía una barra de
   desplazamiento horizontal en toda la pantalla. Con `display:none` no existe
   hasta que se la pide, y la aparición se anima con un keyframe, que sí funciona
   sobre un elemento que acaba de entrar. */
.ds-hint__body {
  display: none;
  position: absolute;
  bottom: calc(100% + 8px);
  left: 50%;
  transform: translateX(-50%);
  width: max-content;
  /* Nunca más ancha que la pantalla del teléfono. */
  max-width: min(230px, 70vw);
  background: var(--tx);
  color: var(--surface);
  font-family: var(--ff-body);
  font-size: var(--fs-xs);
  font-weight: 500;
  line-height: 1.4;
  text-align: left;
  padding: 8px 11px;
  border-radius: var(--r);
  box-shadow: var(--sh-3);
  pointer-events: none;
  z-index: 70;
}

.ds-hint__q:hover + .ds-hint__body,
.ds-hint__q:focus-visible + .ds-hint__body {
  display: block;
  animation: ds-hint-in var(--t-fast) ease-out;
}

@keyframes ds-hint-in {
  from { opacity: 0; transform: translateX(-50%) translateY(3px) }
  to   { opacity: 1; transform: translateX(-50%) translateY(0) }
}

/* Pegada al borde derecho, la pista se saldría de la pantalla. Estas dos
   variantes la anclan al lado que corresponda en vez de centrarla. */
.ds-hint--end .ds-hint__body { left: auto; right: 0; transform: none; }
.ds-hint--end .ds-hint__q:hover + .ds-hint__body,
.ds-hint--end .ds-hint__q:focus-visible + .ds-hint__body { animation-name: ds-hint-in-end; }
.ds-hint--start .ds-hint__body { left: 0; right: auto; transform: none; }
.ds-hint--start .ds-hint__q:hover + .ds-hint__body,
.ds-hint--start .ds-hint__q:focus-visible + .ds-hint__body { animation-name: ds-hint-in-end; }

@keyframes ds-hint-in-end {
  from { opacity: 0; transform: translateY(3px) }
  to   { opacity: 1; transform: translateY(0) }
}

/* ===========================================================================
   16. (sin barra de progreso)

   Existía una `.ds-bar` y se quitó. El progreso en este producto se muestra
   SIEMPRE con `.ds-ring`. Dejar las dos formas en el sistema no era ofrecer
   opciones: era garantizar que dos pantallas mostraran el mismo dato de dos
   maneras distintas, que es exactamente el desorden que este archivo vino a
   terminar. Si hace falta progreso en una fila muy angosta, la respuesta es un
   anillo chico, no volver a traer la barra.
   =========================================================================== */

/* ===========================================================================
   17. AYUDANTES
   =========================================================================== */
.ds-stack   { display: flex; flex-direction: column; }
.ds-row     { display: flex; align-items: center; }
.ds-wrap    { flex-wrap: wrap; }
.ds-gap-1 { gap: var(--sp-1) } .ds-gap-2 { gap: var(--sp-2) }
.ds-gap-3 { gap: var(--sp-3) } .ds-gap-4 { gap: var(--sp-4) }
.ds-gap-5 { gap: var(--sp-5) } .ds-gap-6 { gap: var(--sp-6) }
.ds-grow    { flex: 1 1 auto; min-width: 0; }
.ds-none    { flex: none; }
.ds-between { justify-content: space-between; }
.ds-mt-1 { margin-top: var(--sp-1) } .ds-mt-2 { margin-top: var(--sp-2) }
.ds-mt-3 { margin-top: var(--sp-3) } .ds-mt-4 { margin-top: var(--sp-4) }
.ds-mt-5 { margin-top: var(--sp-5) } .ds-mt-6 { margin-top: var(--sp-6) }
.ds-mb-2 { margin-bottom: var(--sp-2) } .ds-mb-3 { margin-bottom: var(--sp-3) }
.ds-mb-4 { margin-bottom: var(--sp-4) } .ds-mb-5 { margin-bottom: var(--sp-5) }
.ds-mb-6 { margin-bottom: var(--sp-6) } .ds-mb-7 { margin-bottom: var(--sp-7) }

/* Visible solo para lectores de pantalla. */
.ds-sr {
  position: absolute;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
  border: 0;
}


/* --- selector de contacto (hzn-contacto-picker.js) ------------------------
   Vive en el design system y no en una pantalla porque lo usan DOS: Correo y el
   modal de Mi Calendario. Si el estilo viviera en una de las dos, la otra seria
   una copia, y una copia es una divergencia con fecha. */
.hzn-cp { position:relative; }
.hzn-cp-lista { position:absolute; z-index:30; left:0; right:0; top:calc(100% + 4px);
                max-height:260px; overflow-y:auto; background:var(--surface);
                border:1px solid var(--line-2); border-radius:10px;
                box-shadow:0 10px 26px rgba(0,0,0,.14); padding:4px; }
.hzn-cp-lista[hidden] { display:none; }
.hzn-cp-op { display:flex; flex-direction:column; gap:1px; padding:8px 10px;
             border-radius:7px; cursor:pointer; }
.hzn-cp-op:hover, .hzn-cp-op.es-marcada { background:var(--surface-2); }
.hzn-cp-n { font-family:'Manrope',sans-serif; font-size:13px; font-weight:700;
            color:var(--tx); }
.hzn-cp-e { font-size:11.5px; color:var(--tx-3); }
