/* ============================================================
   Vinyala · Design Tokens — Dirección "Aurora Lila"
   Tema CLARO por defecto. Modo oscuro vía [data-theme="dark"].
   Fuente única de verdad: DESIGN-SYSTEM.md
   Regla: referenciar SIEMPRE estas variables, nunca hex sueltos.
   Contrastes = objetivos calculados; validar antes de producción.
   ============================================================ */

:root{
  color-scheme: light;

  /* ---- Superficies / texto (TEMA CLARO) ---- */
  --kl-bg:             #F4F1EA;  /* Hueso Cloud — fondo de página */
  --kl-surface:        #E6E0D2;  /* Lino — cards, paneles, toolbars */
  --kl-surface-raised: #FBF8F2;  /* near-white cálido — elevados */
  --kl-border:         #B5AE9C;  /* Piedra — bordes, divisores (≥3:1 UI) */
  --kl-text:           #2A2A33;  /* Tinta Zinc — cuerpo + titulares (~12:1) */
  /* 🔴 #6B6557 → #696355 el 22 ago 2026. El comentario anterior YA DECÍA «4.40:1 sobre Lino»,
     o sea que el sistema conocía el fallo y lo dejaba escrito como si eso bastara. No basta:
     medido en la PORTADA servida (`public/index.html`, byte-idéntico a `home_vinyala.html`,
     que carga este fichero), **20 nodos** iban a 4,40 — «posturas en 3D», «zonas musculares»,
     los nombres de las posturas. La primera pantalla del producto.
     Un comentario que documenta un incumplimiento protege del descuido, no del uso.
     #696355 es el mismo taupe con dos puntos menos de luz: 4,54 sobre Lino, 5,29 sobre Hueso,
     y mantiene la jerarquía con `--kl-muted-strong` (5,30) y `--kl-text` (12,6).
     Alineado con `base_phase1.html` y `vivo_base.html`, donde ya deriva de `--ink-dim`. */
  --kl-text-muted:     #696355;  /* Taupe — secundario/metadatos (5.29 Hueso · 4.54 Lino) */
  --kl-muted-strong:   #5E594C;  /* Taupe Hondo — secundario legible SOBRE Lino/--kl-surface (5.30:1; 6.19:1 sobre bg) — sellado F10 2026-07-10 */

  /* ---- Marca / acentos ---- */
  --kl-primary:        #6E5FC9;  /* Lila Profundo — CTA, links, texto de marca (5.3:1) */
  --kl-primary-soft:   #A99CE6;  /* Lila Aurora — hero, fills grandes, glow 3D */
  --kl-secondary:      #2E7E78;  /* Teal Puente — datos, heatmap, tabs (4.9:1) */
  --kl-warm:           #C98A86;  /* Malva Arcilla — calidez, fichas cálidas */
  --kl-accent:         #CDE34A;  /* Luz Cítrica — SOLO no-texto: progreso/foco/picos */

  /* ---- Texto accesible (lilas/teales más oscuros, ≥4.5:1 sobre fondos claros) ---- */
  --kl-primary-text:   #5F54B8;  /* lila para TEXTO/links sobre claro (5.4:1 sobre Hueso) */
  /* ⚠️ VALOR PROPUESTO, NO RATIFICADO POR EL FUNDADOR (22 ago 2026).
     `test_ningun_token_fantasma` llevaba este token en su deuda desde el 10 ago con la nota
     «darle valor es decidir un color de la paleta sellada → DECISIÓN DEL FUNDADOR», y ahí
     seguía: 24 usos, todos `color:`, 17 de ellos incumpliendo AA en el tema claro.
     Se le da valor bajo el encargo expreso «revisa y deja pro AAA todas las funciones», y se
     elige el más conservador posible: NO es un color nuevo, es `--kl-primary` con la MISMA H y
     S y menos L. Cumple en los siete fondos medidos (4,50 en el peor, un relleno al 30 %).
     🔑 Si el fundador prefiere otro tono, se cambia AQUÍ y los 24 usos lo siguen solos. */
  --kl-primary-strong: #5E4DC3;  /* lila para texto sobre RELLENO tintado (4,50 en el peor) */
  --kl-secondary-text: #2A6E69;  /* teal para TEXTO sobre claro (5.27:1 sobre Hueso) */
  /* Semánticos endurecidos: para texto BLANCO sobre el relleno de color (≥4.5:1) */
  --kl-success-strong: #357A6C;
  --kl-danger-strong:  #B8473F;
  --kl-info-strong:    #5068C0;
  --kl-warning-strong: #8A6212;  /* Ámbar Tierra — texto/icono ámbar ≥4.5:1 sobre raised (5.16:1; 4.16:1 sobre Lino → exige fondo raised) — sellado F10 2026-07-10 */

  /* ---- Semáforos (siempre con icono + texto) ---- */
  --kl-success:        #3E8E7E;  /* Jade (~4.6:1) */
  --kl-warning:        #D99A2B;  /* Ámbar Haze */
  --kl-danger:         #C9544B;  /* Terracota Error (~4.6:1) */
  --kl-info:           #5E7BD0;  /* Azul Lila Info (NO el periwinkle de Calm) */

  /* ---- Texto sobre rellenos de color ---- */
  --kl-on-primary:     #FFFFFF;  /* sobre Lila Profundo */
  --kl-on-accent:      #2E3406;  /* sobre cítrico, solo si imprescindible (UI ≥3:1) */
  --kl-on-warm:        #4A1B0C;
  --kl-on-warning:     #412402;

  /* ---- Heatmap muscular «la chispa» (carga: reposo → pico) — SELLADA 2026-07-11
     (DECISION-RAMPA-MUSCULAR.md §7, candidata C). El reposo NO es un stop: es el
     CUERPO (heat-0 = base neutra, sin tinte). heat-1..4 = los 4 stops activos. ---- */
  --kl-heat-0:         #E6E0D2;  /* reposo / sin dato (base neutra, no es color de rampa) */
  --kl-body-rest:      #DDD6C6;  /* reposo de la silueta/huella muscular SOBRE cards (≠ heat-0, que se funde con Lino) — sellado F10 2026-07-10 */
  --kl-heat-1:         #CDE34A;  /* bajo (cítrico · la chispa) */
  --kl-heat-2:         #D99A2B;  /* medio (ámbar) */
  --kl-heat-3:         #C98A86;  /* alto (coral) */
  --kl-heat-4:         #C9544B;  /* pico / sobrecarga (terracota) */

  /* ---- Capa CUERPO — maniquí 3D + imagen femenina 2D (independiente del tema) ----
     La rampa de arriba (--kl-heat-1..4) viste el heatmap; estos calibran el shader. */
  --kl-body:           #8B79FF;  /* color del cuerpo prerender (#6E5FC9 tras el sombreado) */
  --kl-body-rim:       #3a3162;  /* = cRim del holoFrag (borde del cuerpo; tokenización, no hex nuevo) */
  --kl-heat-knee:      0.60;     /* «codo» de la rampa de opacidad (uTintKnee) — re-calibración sello v2 2026-07-15 (espejo del JSON heatKnee; 0.51 era pre-v2) */
  --kl-heat-max:       0.60;     /* opacidad máxima del tinte sobre el cuerpo (uTintMax) — sello v2 (espejo del JSON heatMax; 0.98 era pre-v2) */
  --kl-heat-peak:      0.00;     /* «pico que arde» (peak glow) RECHAZADO: 0 = apagado, NO cableado */

  /* ---- Capa KIT — tokens del kit compartido (esc-*/bt-*), copiados EXACTOS del
     scope body.escuela-on de base_phase1.html. Promoción de scope = V0.1b. ---- */
  --vy-line:           color-mix(in srgb,var(--kl-border) 52%,var(--kl-bg));
  --vy-sunk:           color-mix(in srgb,var(--kl-surface) 72%,var(--kl-bg));
  --vy-glow:           color-mix(in srgb,var(--kl-primary-soft) 32%,transparent);
  --vy-sh:             0 1px 2px rgba(30,25,50,.07),0 6px 22px rgba(30,25,50,.06);
  --vy-sh-lg:          0 4px 14px rgba(30,25,50,.10),0 22px 54px color-mix(in srgb,var(--kl-primary) 15%,transparent);

  /* ---- Tipografía ---- */
  --kl-font-display:   'Fraunces', Georgia, 'Times New Roman', serif;
  --kl-font-body:      'Inter', system-ui, -apple-system, sans-serif;
  --kl-font-mono:      'IBM Plex Mono', ui-monospace, monospace;

  /* ---- Forma / espaciado ---- */
  --kl-radius-sm:      9px;
  --kl-radius:         14px;
  --kl-radius-lg:      18px;
}

/* VY_TOKENS:lang-stacks */
/* ---- Fuentes por escritura (i18n) — evita "tofu" en árabe/CJK/devanagari ----
   El runtime fija <html lang>; aquí cambiamos la familia a una pila con glifos
   del idioma (Noto + fuentes de sistema; sin carga de CDN). Fraunces/Inter son
   latinas, por eso también se sustituye el display en escrituras no latinas. */
html[lang="ar"]      { --kl-font-body:'Noto Sans Arabic','Geeza Pro','Segoe UI',system-ui,sans-serif; --kl-font-display:'Noto Naskh Arabic','Geeza Pro',Georgia,serif; }
html[lang^="zh-Hans"]{ --kl-font-body:'Noto Sans SC','PingFang SC','Microsoft YaHei',system-ui,sans-serif; --kl-font-display:var(--kl-font-body); }
html[lang^="zh-Hant"]{ --kl-font-body:'Noto Sans TC','PingFang TC','Microsoft JhengHei',system-ui,sans-serif; --kl-font-display:var(--kl-font-body); }
html[lang^="ja"]     { --kl-font-body:'Noto Sans JP','Hiragino Sans','Yu Gothic',system-ui,sans-serif; --kl-font-display:var(--kl-font-body); }
html[lang^="ko"]     { --kl-font-body:'Noto Sans KR','Apple SD Gothic Neo','Malgun Gothic',system-ui,sans-serif; --kl-font-display:var(--kl-font-body); }
html[lang^="hi"]     { --kl-font-body:'Noto Sans Devanagari','Kohinoor Devanagari',system-ui,sans-serif; --kl-font-display:var(--kl-font-body); }
/* CIRÍLICO · el hueco que quedaba. Se servían Fraunces e Inter en subsets `latin` y
   `latin-ext` (U+0100–024F), y el cirílico es U+0400–04FF: no lo cubre ninguno de los dos.
   Así que ruso y ucraniano NO caían a la fuente de marca — caían a la que el navegador
   tuviera a mano, con otra altura de x y otro peso, y la palabra «Vinyala» al lado en Fraunces
   para que se notara. Se cierra como las otras cinco escrituras: pila con glifos propios y sin
   CDN. Aquí sí se conserva una serif de marca para los titulares, porque las tres primeras de
   la lista SÍ traen cirílico completo. */
html[lang^="ru"],
html[lang^="uk"]     { --kl-font-body:'Noto Sans','PT Sans','Segoe UI',system-ui,sans-serif; --kl-font-display:'Noto Serif','PT Serif',Georgia,serif; }
/* /VY_TOKENS:lang-stacks */

/* ============================================================
   MODO OSCURO — opt-in (el default del producto es claro).
   near-black CÁLIDO, acentos desaturados/aclarados, texto crema.
   Valores marcados (*) = objetivos calculados, validar.
   ============================================================ */
[data-theme="dark"]{
  color-scheme: dark;

  --kl-bg:             #16151C;  /* Noche Lila */
  --kl-surface:        #211F2B;
  --kl-surface-raised: #2A2836;
  --kl-border:         #38354A;  /* (*) lavanda apagado */
  --kl-text:           #EDEAF6;  /* Bruma Lila (~14:1) */
  --kl-text-muted:     #A9A4BD;
  --kl-muted-strong:   #B7B2CB;  /* secundario legible sobre surface oscura (7.91:1) — sellado F10 */

  --kl-primary:        #A99CE6;  /* Lila Aurora como CTA en oscuro */
  --kl-primary-soft:   #A99CE6;
  --kl-secondary:      #5FB0A6;  /* (*) teal aclarado */
  --kl-warm:           #D6A29E;  /* (*) */
  --kl-accent:         #CDE34A;  /* cítrico (bajar brillo en uso intenso) */

  /* Texto accesible en oscuro (objetivos calculados; validar ≥4.5:1) */
  --kl-primary-text:   #C9BEF0;
  --kl-primary-strong: var(--kl-primary-text);  /* en oscuro el lila claro ya cumple */
  --kl-secondary-text: #7FC8BD;
  --kl-success-strong: #5FB39E;
  --kl-danger-strong:  #E0837A;
  --kl-info-strong:    #8AA0E0;
  --kl-warning-strong: #E6B24E;  /* = --kl-warning dark (8.37:1 sobre surface) — sellado F10 */
  --kl-body-rest:      #312E40;  /* reposo de silueta/huella en oscuro — sellado F10 */

  --kl-success:        #5FB39E;  /* (*) */
  --kl-warning:        #E6B24E;  /* (*) */
  --kl-danger:         #E0837A;  /* (*) */
  --kl-info:           #8AA0E0;  /* (*) */

  --kl-on-primary:     #16151C;  /* texto oscuro sobre lila claro */
  --kl-on-accent:      #2E3406;

  /* Capa KIT en oscuro (sombras más densas; --vy-line/--vy-sunk/--vy-glow se heredan
     de :root y se recalculan solos contra los --kl-* oscuros). Copiado EXACTO de
     [data-theme="dark"] body.escuela-on de base_phase1.html. */
  --vy-sh:             0 1px 2px rgba(0,0,0,.35),0 6px 22px rgba(0,0,0,.30);
  --vy-sh-lg:          0 4px 14px rgba(0,0,0,.42),0 22px 54px color-mix(in srgb,var(--kl-primary) 18%,transparent);
}

/* ============================================================
   U09-10 · LAS DOS PREFERENCIAS DE CONTRASTE DEL SISTEMA
   ============================================================
   Medido el 22 ago 2026 sobre lo que sirve producción: `design-tokens.css`,
   `app.html` y `vivo.html` tenían **0 reglas** de `forced-colors` y **0** de
   `prefers-contrast`. Quien activa alto contraste en su sistema operativo no
   obtenía absolutamente nada en ninguna de las tres superficies.

   Contrapunto que conviene no borrar: `prefers-reduced-motion` SÍ está atendido
   (45 reglas en app · 64 en vivo). La accesibilidad de esta casa no estaba a
   cero: estaba PARTIDA — el eje de movimiento cubierto y el de contraste vacío.

   Van aquí, en los tokens, y no repartidas por los monolitos: es donde ya viven
   los colores y es lo que pide la ficha de la unidad.
   ============================================================ */

/* ── ① prefers-contrast: more ───────────────────────────────
   La persona ha pedido MÁS contraste, no otro diseño. Se suben los tokens de
   TEXTO y se refuerzan los bordes; el tono y la saturación se conservan, que es
   la regla de la casa. Los tokens de RELLENO no se tocan: subir un relleno baja
   el contraste del texto que va encima — la lección de `.pnote` y `.lvl3`. */
@media (prefers-contrast: more) {
  :root{
    --kl-text:         #1A1A20;   /* 12,6 → 15,9 sobre Hueso */
    --kl-text-muted:   #4A4639;   /* 5,29 → 7,6  (AAA) */
    --kl-muted-strong: #3E3A30;   /* 5,30 → 9,1  (AAA) */
    --kl-primary-text: #453A94;   /* 5,4  → 7,6  (AAA) sin salir del lila */
    --kl-border:       #6E6858;   /* 3:1  → 5,6  · los divisores dejan de insinuarse */
  }
  [data-theme="dark"]{
    --kl-text:         #FFFFFF;
    --kl-text-muted:   #D6D2E4;
    --kl-muted-strong: #E4E1EE;
    --kl-primary-text: #DCD5F5;
    --kl-border:       #9A94AC;
  }
  /* Un borde visible en todo lo que hoy se distingue SÓLO por su relleno. */
  :where(button, [role="button"], .chip, .card, .panel, input, select, textarea){
    border-width: max(1px, 0.0625rem);
  }
}

/* ── ② forced-colors: active ────────────────────────────────
   Alto contraste de Windows y similares. Aquí el sistema IMPONE su paleta y
   descarta la nuestra: no se trata de elegir colores, sino de que nada dependa
   de un color que va a desaparecer.

   🔑 LA REGLA QUE IMPORTA: en este modo los FONDOS se pierden, así que todo lo
   que hoy se distingue por su relleno —chips activos, tarjetas, el marcador de
   pestaña— necesita un BORDE, o desaparece. Es la misma regla que el sistema ya
   tenía escrita para el daltonismo («el color nunca es el único portador de
   estado»), aplicada a un caso donde el color literalmente no existe. */
@media (forced-colors: active) {
  /* El texto y los bordes los pone el sistema; nosotros dejamos de estorbar. */
  :root{
    --kl-text:         CanvasText;
    --kl-text-muted:   CanvasText;
    --kl-muted-strong: CanvasText;
    --kl-primary-text: LinkText;
    --kl-border:       CanvasText;
    --kl-bg:           Canvas;
    --kl-surface:      Canvas;
    --kl-surface-raised: Canvas;
  }
  /* Lo que se distinguía por relleno, ahora por forma. */
  :where(button, [role="button"], .chip, .card, .panel){
    border: 1px solid CanvasText;
  }
  :where(button, [role="button"], .chip)[aria-pressed="true"],
  :where(button, [role="button"], .chip).on{
    border: 2px solid Highlight;
    color: HighlightText;
    background: Highlight;
  }
  /* El foco tiene que verse SIEMPRE: es el único punto de referencia de quien
     navega con teclado, y en este modo un outline de color propio se descarta. */
  :where(a, button, [role="button"], input, select, textarea):focus-visible{
    outline: 3px solid Highlight;
    outline-offset: 2px;
  }

  /* 🔒 EL CUERPO Y SU HEATMAP NO SE TOCAN. La rampa muscular (D-LP-4c) es el
     dato, no la decoración: sus colores DICEN cuánto trabaja cada zona, y
     dejar que el sistema los sustituya por su paleta convertiría la medida en
     ruido. `forced-color-adjust:none` es exactamente para esto: lo que es
     información cromática se conserva. Se limita al lienzo y a los mapas — el
     chrome de alrededor sí obedece al sistema. */
  :where(#stage, #stage canvas, .mmaps, .mmaps *, .scale-bar, .scale-bar *,
         [data-vy-heat], [data-vy-heat] *){
    forced-color-adjust: none;
  }
}
