/* ============================================================================
   Juicy — Dashboard Design System · TONOS
   ----------------------------------------------------------------------------
   Un solo juego de tonos para TODOS los componentes. Button, Icon Button,
   Badge, Chip, Alert… todos consumen el mismo contrato de seis variables:

     --tone-fill     fondo cuando el componente es sólido
     --tone-fg       contenido sobre ese fondo
     --tone-hover    ese fondo al pasar el cursor
     --tone-line     trazo y contenido cuando es outline / ghost
     --tone-soft     fondo tintado
     --tone-on-soft  contenido sobre el tinte

   En Figma cada componente redeclara sus tonos por dentro, y por eso se
   desincronizaron (el Button tiene 9 tonos, el Icon Chip 10, el Badge 5; uno los
   llama "Neutral LVL1" y el otro "Neutral LV1"). Aquí el tono se declara UNA vez
   y lo heredan todos. Componente nuevo = cero tonos que escribir.

   `--tone-soft` sale de DOS familias distintas de la semántica, y no es un
   descuido: `feed/…/soft` usa la rampa 200 y `action/…/soft` la 300. Los tonos
   de feedback (success/error/warning/information) toman el 200 porque es lo que
   consume el Badge; el resto toma su 300. Ojo: los `action/…/soft` (300) hoy no
   los usa NINGÚN componente — y en primary/secondary son idénticos al default,
   o sea que ahí no hay variante soft de verdad.

   `--tone-on-soft` DIVERGE DE FIGMA a propósito (aprobado por el dueño
   2026-07-16). Figma usa el fill (la rampa 500) como texto sobre el tinte, y eso
   reprueba AA en las 4: 2.06–3.31 medido. Los tonos de feedback usan la rampa
   700 vía `feed/…/text-on-soft` (ver el bloque AÑADIDOS de semantics.css): da
   6.86–11.10. Es la única divergencia deliberada del sistema; falta crear esos
   4 tokens en Figma para volver a alinear las dos superficies.

   Los tonos NO-feedback (primary, secondary, neutral-lv*) siguen con on-soft =
   fill, porque la rampa `ui` no es una rampa de un tono: `ui/700` es NARANJA, no
   un cyan oscuro. No hay 700 al cual apuntar. Da igual hoy: ningún componente
   usa el soft de esos tonos.
   ============================================================================ */

.tone-primary {
  --tone-fill: var(--action-primary-default);
  --tone-fg:   var(--action-primary-text);
  --tone-line: var(--tone-fill);
  --tone-soft: var(--action-primary-soft);
  --tone-on-soft: var(--tone-fill);
}

.tone-secondary {
  --tone-fill: var(--action-secondary-default);
  --tone-fg:   var(--action-secondary-text);
  --tone-line: var(--tone-fill);
  --tone-soft: var(--action-secondary-soft);
  --tone-on-soft: var(--tone-fill);
}

.tone-neutral-lv1 {
  --tone-fill: var(--action-neutral-lv1-default);
  --tone-fg:   var(--action-neutral-lv1-text);
  --tone-line: var(--tone-fill);
  --tone-soft: var(--action-neutral-lv1-soft);
  --tone-on-soft: var(--tone-fill);
}

.tone-neutral-lv2 {
  --tone-fill: var(--action-neutral-lv2-default);
  --tone-fg:   var(--action-neutral-lv2-text);
  --tone-line: var(--tone-fill);
  --tone-soft: var(--action-neutral-lv2-soft);
  --tone-on-soft: var(--tone-fill);
}

.tone-neutral-lv3 {
  --tone-fill: var(--action-neutral-lv3-default);
  --tone-fg:   var(--action-neutral-lv3-text);
  --tone-line: var(--tone-fill);
  --tone-soft: var(--action-neutral-lv3-soft);
  --tone-on-soft: var(--tone-fill);
}

/* ✅ ESTOS TRES YA ESTÁN EN 500 (F5, HECHO 2026-07-19) — decisión del dueño, 2026-07-17.
   ────────────────────────────────────────────────────────────────────────────
   Los quiere en 500: "los colores opacos que pusimos en 600 por visibilidad no me
   gustan, están muy opacos, apagados, grises, fuera de la vibra de la marca.
   Quiero que los colores para botones, chips, badges, etc. sean los tonos 500.
   También estoy consciente de la baja visibilidad, pero prefiero agregar un modo
   alto contraste que el cliente decida, a dañar la imagen de la marca de primera
   mano."

   Es una decisión de PRODUCTO, no un descuido, y gana: el contraste se puede
   ofrecer como opción; la identidad de marca no. Un DS que apaga la marca para
   pasar una métrica está optimizando lo que se mide en vez de lo que importa.

   EL ALCANCE SON EXACTAMENTE ESTAS TRES LÍNEAS (green-600, red-600, blue-600).
   Medido: los `--action-*-default` y `--feed-*-default` de semantics.css YA son
   500, y el naranja ya es 500 por otra razón (ver su nota). O sea que el DS se
   estaba saltando su propia semántica en tres sitios, y volver es dejar que la
   semántica mande:  --tone-fill: var(--action-success-default);  (y error, e
   information). Con eso vuelven al 500 y de paso dejan de duplicar el dato.

   Lo que va incluido y NO es gratis: el texto blanco encima baja a 2.62 (verde),
   3.76 (rojo) y 3.24 (azul) — reprueban AA. Por eso el paquete es 500 **+ un modo
   de alto contraste opcional**, que es donde reviven los 600. El modo tiene sitio
   natural: como los tonos ya son un contrato, es un scope que redefine
   `--tone-fill` y nada más — la misma mecánica que el volteo de tinta del login,
   sin tocar un solo componente. Eso lo hace barato, y es exactamente para lo que
   se construyó el contrato así.

   HECHO en F5 (movía TODOS los botones, chips y badges a la vez, por eso fue al
   final con su verificación pixel POS+Hub). El AA que pierden lo devuelve el modo
   alto contraste opt-in (bloque abajo).
   NO lo "arregles" de vuelta al ver que reprueban: ya se sabe, y está decidido.
   ────────────────────────────────────────────────────────────────────────────

   Los cuatro tonos de feedback DIVERGEN de Figma en su `fill` — ver la nota
   RELLENOS al final. El `default` de la semántica sigue siendo el 500 y no se
   toca: sirve para barras, iconos y bordes, donde el requisito es 3:1, no 4.5. */

.tone-success {
  --tone-fill: var(--action-success-default);   /* 500 (F5): la marca manda; AA (2.62) la da el modo alto contraste */
  --tone-fg:   var(--action-success-text);
  --tone-line: var(--action-success-default);
  --tone-soft: var(--feed-success-soft);
  --tone-on-soft: var(--feed-success-text-on-soft);
}

.tone-error {
  --tone-fill: var(--action-error-default);     /* 500 (F5): la marca manda; AA (3.76) la da el modo alto contraste */
  --tone-fg:   var(--action-error-text);
  --tone-line: var(--action-error-default);
  --tone-soft: var(--feed-error-soft);
  --tone-on-soft: var(--feed-error-text-on-soft);
}

/* El naranja es un color CLARO: blanco sobre el 500 da 2.26 (reprueba AA), por eso
   el texto sobre el fill sólido ERA neutral/700 (6.98, como un señalamiento vial).
   DECISIÓN DEL DUEÑO (2026-07-20): el fill sólido va con texto/icono BLANCO como el
   resto de tonos — prioriza la coherencia visual sobre el contraste (misma línea
   que "el contraste no es prioritario al 100%"). Solo cambia `--tone-fg` (contenido
   sobre el fill); `--tone-line` (outline) y `--tone-on-soft` (soft) siguen oscuros
   porque el blanco sobre naranja claro / tinte sería invisible. */
.tone-warning {
  --tone-fill: var(--action-warning-default);
  --tone-fg:   var(--action-warning-text);   /* blanco (decisión del dueño; AA 2.26) */
  --tone-line: var(--action-warning-default);
  --tone-soft: var(--feed-warning-soft);
  --tone-on-soft: var(--feed-warning-text-on-soft);
}

.tone-information {
  --tone-fill: var(--action-information-default); /* 500 (F5): la marca manda; AA (3.24) la da el modo alto contraste */
  --tone-fg:   var(--action-information-text);
  --tone-line: var(--action-information-default);
  --tone-soft: var(--feed-information-soft);
  --tone-on-soft: var(--feed-information-text-on-soft);
}

/* ---- Modo alto contraste (opt-in) ------------------------------------------
   La contraparte de bajar los 3 fills al 500 (F5): revive los 600 para el
   cliente que prefiere legibilidad sobre la vibra de marca. Es la razón por la
   que el 500 fue una decisión segura y no un descuido — el contraste se ofrece,
   la identidad no se sacrifica.

   Mecánica del CONTRATO: redefine `--tone-fill` y nada más — cero componentes
   tocados, igual que el volteo de tinta del login. `--tone-hover` lo sigue solo
   (se deriva del fill). Solo los tres que F5 movió; warning (naranja, texto
   oscuro) y los neutrales ya pasan AA y no cambian.

   AA con blanco encima (medido, ver nota RELLENOS): green-600 5.41, red-600
   5.52, blue-600 4.57 — los tres pasan.

   EL TOGGLE es PRODUCTO, pendiente aparte: un ajuste del cliente que pone la
   clase `.high-contrast` en el <body> o el wrapper del dashboard. Aquí solo vive
   el modo, listo para que ese ajuste lo encienda. */
.high-contrast .tone-success    { --tone-fill: var(--green-600); }
.high-contrast .tone-error      { --tone-fill: var(--red-600); }
.high-contrast .tone-information { --tone-fill: var(--blue-600); }

/* ---- Hover -----------------------------------------------------------------
   El Figma NO tiene hover: ni una variante, ni un token `action/…/hover`. Un
   botón sin hover no es un botón.

   El producto SÍ tiene hovers, pero NO tiene una convención. Son tres valores
   a mano con tres criterios distintos (medido 2026-07-16):
     cyan    #00B4BD → #009aa3   ΔE  9.9
     morado  #9366DD → #7d52c9   ΔE  7.9
     rojo    #D62A49 → #8a2c2c   ΔE 30.0  ← el triple de salto que los otros,
                                            y además desatura: no es un crimson
                                            oscuro, es otro color
   O sea: aquí el DS no está poniéndole nombre a una regla que ya existía. Está
   INVENTANDO la regla que faltaba, y unificando tres intuiciones que no
   coincidían entre sí. (Nota honesta: la primera versión de este comentario
   afirmaba que la fórmula "reproduce lo que el dueño ya hacía a ojo". Falso:
   lo reproduce en 1 de los 3. Se generalizó desde el caso que coincidió.)

   Aun así la fórmula es la decisión correcta, por tres razones medidas:
     · Da un salto PAREJO (ΔE 8–13) en los 10 tonos. Los valores a mano iban
       de 7.9 a 30.0 — el mismo gesto se sentía distinto según el botón.
     · La rampa NO sirve de hover: error #C0362D → red/700 #601B16 es ΔE 36.8.
       Eso no es un hover, es otro color.
     · `ui` y `brand` NO son rampas de un tono (ui/700 es NARANJA), así que
       primary y secondary no tienen a dónde bajarse. La fórmula sí funciona.
   Y se DERIVA de `--tone-fill`: si el fill cambia, el hover lo sigue solo.
   De propina clava el cyan (#009BA3 vs #009aa3, ΔE 0.7).

   Va en `:where()` para que un tono o un componente pueda pisarlo sin pelear
   por especificidad — y hay uno que lo hace: el botón del login conserva su
   #8a2c2c explícito (main.css:1948). */
:where([class*="tone-"], .button, .btn, .icon-chip) {
  --tone-hover: color-mix(in srgb, var(--tone-fill) 86%, black);
}

/* Dos cosas propias del tono inerte:
   - No reacciona al cursor: su hover ES su fill.
   - Su trazo NO sale del fill (en Figma el Outline de Disabled usa
     `action/inactive/text` para borde y contenido, no `default`).
   Y su `fill` es neutral/150 — casi blanco — así que el 600 de los otros no
   aplica: no hay nada que oscurecer, el fondo YA es el claro. Lo que estaba
   mal era el TEXTO (neutral/250 sobre neutral/150 = 1.11:1, literalmente
   invisible). Con `text/secondary` da 5.72. "Deshabilitado" no significa
   "ilegible": WCAG exime a los controles inertes, pero un BADGE disabled no es
   un control, es una etiqueta de estado que hay que poder leer. */
.tone-disabled {
  --tone-fill: var(--action-inactive-default);
  --tone-fg:   var(--text-secondary);       /* Figma: neutral/250 -> 1.11, invisible */
  --tone-hover: var(--tone-fill);
  --tone-line: var(--action-inactive-text);
  --tone-soft: var(--action-inactive-default);
  --tone-on-soft: var(--text-secondary);
}

/* ============================================================================
   RELLENOS — segunda divergencia estructural con Figma (2026-07-16)

   Igual que `on-soft`, el `fill` de Figma no se puede usar: pinta texto blanco
   sobre la rampa 500 y reprueba AA en 5 de 6. Medido sobre el render:

                 Figma (blanco/500)      aquí                      resultado
     success          2.62               blanco / green-600          5.41 ✓
     error            3.76               blanco / red-600            5.52 ✓
     information      3.24               blanco / blue-600           4.57 ✓
     warning          2.26               neutral-700 / orange-500    6.98 ✓
     inactive         1.11               text-secondary / neutral-150 5.72 ✓
     neutral          9.98               (ya pasaba, sin tocar)      9.98 ✓

   OJO CON EL ATAJO: yo mismo escribí en badge.css que "el 600 de cada rampa lo
   arregla". Es FALSO en 2 de 5 — warning se queda en 3.49 con el 600, y
   inactive no tiene 600 al cual bajar. No hay una regla única; hay que medir
   cada tono. El color no se negocia con una regla mnemotécnica.

   `--tone-line` se queda en el 500 A PROPÓSITO: un borde o un icono piden 3:1
   (WCAG 1.4.11), no 4.5. Pero OJO — `line` también es el color del CONTENIDO en
   las variantes outline/ghost, y ahí sí es texto: red/500 sobre blanco da 3.76.
   Cuando aterrice button.css hay que separar `--tone-line` (borde) de
   `--tone-ink` (texto sobre blanco), o mandar los dos al 600.

   La semántica `action/…/default` NO se toca: sigue siendo el 500 y es correcta
   para lo que no es texto (barras de la gráfica, iconos, trazos).
   ============================================================================ */
