From 3bf7930baa3ae26ccb38e7f33d3fb488df73f06a Mon Sep 17 00:00:00 2001 From: dev Date: Tue, 25 Aug 2026 04:20:52 +0200 Subject: [PATCH] fix(theming): el velo del sistema no muere por un atajo - y el pin de chronos sobra Dos hechos de cascada, hermanos de la firma 55: 1. Las reglas del suelo de popover usaban el ATAJO `background:` - expande a `background-image: none` y MATA el velo de hover del sistema (archetypes) cuando el orden de carga cae del otro lado. La regla dura lo prohibe por escrito ("hover is the system's"). Partido a `background-color:`: 0 px sobre las 14 identidades del catalogo (68 lecturas reposo + 68 hover, todas a cero; `rules split=2` en las catorce como anti-vacio; control negativo 5/4), y el velo SOBREVIVE al orden invertido - verificado con experimento de cascada aislado. 2. El pin de `chronos.css:417` RETIRADO: sus cinco declaraciones eran copias textuales de `[data-button]` - 20 combinaciones variant x size identicas con y sin el (control negativo 0/20). La adjudicacion de 13 era FALSA: al `+N more` el velo se lo mata `button.css:69`/`:88`, con pin o sin el. `calendar-select.css:14` NO es pin (vivo en 3 de 4 tallas) - se queda. - Guarda extendida (active-eidos-config.test.ts): el suelo declara `background-color` y NUNCA el atajo - validada por 4 mutaciones (las dos ultimas prueban la mitad NEGATIVA, anadidas porque 1-2 solas la dejaban sin morder). - Sondas popover 0/448 y chronos 0/36.832 - eidos 443+1 ajeno - check identico byte a byte antes/despues - docs-check 0/0 x2 - lint 0 invalid. - Registro: changelog 56 (la prueba citable es el barrido de catalogo) - 13: `background-image` RESUELTO y `transition` como RESIDUO VIVO con su numero (suelo `background,border-color` vs arquetipo `opacity,background-color`: hoy el border-color del hover SALTA en vez de animarse) - fichas de chronos (7 filas stale corregidas, recuentos contados contra fichero: 202->198, 50->47), calendar (su HALLAZGO ya resuelto por 55, cerrado) y emoji-picker - 5 textos stale ANOTADOS sin reescribir (cada medida fue correcta con la cascada de su dia), con dos matices: en gradient-picker solo caduco la mitad base, y open-trigger-fg gana ahora por ESPECIFICIDAD, no por orden. - Fuera del registro del eje, por regla dura del autor: el material de sitio/demo (la inversion de imports de /alpha) - ademas desactivado por esta misma firma en la capa que importa. Co-Authored-By: Claude Fable 5 --- docs/audit/theming/calendar.md | 9 ++ docs/audit/theming/chronos.md | 29 +++++++ docs/audit/theming/emoji-picker.md | 9 ++ docs/next-features.md | 87 ++++++++++++++----- docs/process/CONTINUE-theming.md | 43 ++++++++- docs/theming/changelog.md | 81 ++++++++++++++++- src/uix/eidos/active-eidos-config.test.ts | 28 ++++++ src/uix/eidos/components/chronos/chronos.css | 20 ++--- .../components/emoji-picker/emoji-picker.css | 10 ++- .../gradient-picker/gradient-picker.css | 9 ++ src/uix/eidos/components/popover/popover.css | 14 ++- src/uix/eidos/lib/recipes/base.ts | 8 ++ 12 files changed, 309 insertions(+), 38 deletions(-) diff --git a/docs/audit/theming/calendar.md b/docs/audit/theming/calendar.md index b4113059b..aaef1fbf0 100644 --- a/docs/audit/theming/calendar.md +++ b/docs/audit/theming/calendar.md @@ -144,6 +144,15 @@ identidad, que es lo que son. `next-features` §13. **Regla que confirma**: ante un diff inesperado, corre la sonda dos veces sobre el mismo código ANTES de sospechar de tu cambio. + **CERRADO 2026-08-25 por la firma §55 «el sobre de trigger de popover es el + SUELO»** (changelog §55). El empate ya no existe: el sobre de `popover.css` + se emite desde `:where(...)`, (0,0,0), así que + `[data-calendar-month-select][data-button]` (0,2,0) le gana de forma + DETERMINISTA y la letra deja de depender de qué chunk inyecte Vite el último. + Medido después por talla con la regla desactivada en vivo: xs 12px, sm 14px, + md 16px, lg 20px con la regla, 16px en las cuatro sin ella — retirarla + rompería el tipo en 3 de 4 tallas, así que **no es un pin y no se toca**. Ya + no apunta a `next-features` §13. 4. **`select-min-width` no tiene nodo en NINGUNA página del repo**: su único consumidor es `[data-range-calendar-month-select]` / `-year-select`, y ninguna demo monta esas partes (la de range-calendar renderiza un heading de texto; el diff --git a/docs/audit/theming/chronos.md b/docs/audit/theming/chronos.md index 1f747d787..b52d11221 100644 --- a/docs/audit/theming/chronos.md +++ b/docs/audit/theming/chronos.md @@ -12,6 +12,22 @@ ## 1. Knobs fuera de alcance + + +> **NOTA 2026-08-25 — las filas 68-71 de §1.1 citan una regla RETIRADA.** El pin +> `[data-popover-trigger][data-chronos-more-link]:not(…)` (`chronos.css:417-423`, +> propiedades `padding-inline` · `border` · `border-radius` · `background`) se +> retiró con la firma «el velo del sistema no muere por un atajo». Existía sólo +> para ganarle al sobre de trigger de `popover.css` cuando estaba a (0,2,0); §55 +> bajó ese sobre al SUELO (0,0,0), donde `[data-button]` (0,1,0) ya le gana, y +> cuatro de las cinco declaraciones del pin eran copias literales de +> `[data-button]`. Medido con la regla desactivada en vivo: **0 diffs en 20 +> combinaciones `variant` × `size`**, reposo y hover. **El censo baja de 202 a +> 198** (verificado: `--only chronos` → knobs 240 · global 198); las cuatro filas +> desaparecen al regenerar la ficha. + + + ### 1.1 Directo a primitivo global (202) | # | fichero:línea | selector | propiedad | valor | @@ -302,6 +318,19 @@ Consumidos y **no declarados en el CSS** (vienen de `base.ts` o de un estilo inl ## 4. Propuesta de corrección + + +> **NOTA 2026-08-25 — `more-link-{padding-inline,radius,bg}` se quedan SIN +> CONSUMIDOR.** Los tres tokens propuestos en §4.1 tienen `usos: 1`, y ese uso +> era el pin de `chronos.css:417`, retirado por la firma «el velo del sistema no +> muere por un atajo». **La propuesta baja de 50 a 47.** Y no es sólo una +> limpieza: los tres proponían un token PÚBLICO de `chronos` cuyo valor es un +> PRIVADO de `button` (`--_button-*`), justo lo que el preámbulo de este §4 +> prohíbe — «un token prestado importa la semántica de su dueño: la corrección +> no es duplicarlo con prefijo propio». Retirar el pin las borra gratis. + + + - **Consume la capa compartida `picker-shell`.** Un eje que la capa posee se consume como `var(--_x, var(--x))`; el consumidor **no acuña** `--chronos-{eje}` para él — sería un vocabulario paralelo (README de `eidos/components`, «Capas compartidas» regla 2). - **Consume tokens públicos de `button`, `popover`.** Un token prestado importa la semántica de su dueño: la corrección no es duplicarlo con prefijo propio, sino la decisión de familia que la auditoría de fase 1 dejó registrada (`theming-audit.md` §B, familia calendar). - **Tiene eje `size`**: los tokens dimensionales van por talla (`{part}-{eje}-{k}`) apuntando al bundle `--size-{k}-*`, nunca al primitivo crudo (theming §5; el guard `recipe-css-contract` prohíbe el primitivo). diff --git a/docs/audit/theming/emoji-picker.md b/docs/audit/theming/emoji-picker.md index dad714665..de48efc2f 100644 --- a/docs/audit/theming/emoji-picker.md +++ b/docs/audit/theming/emoji-picker.md @@ -106,6 +106,15 @@ de que estaban muertas. Es el defecto que `gradient-picker` documentó (36 de su orden. **`trigger-fg` no llegó a existir**: se acuñó y se midió muerta en el mismo pase. +> **NOTA 2026-08-25 — la PREMISA de ese párrafo caducó; la retirada sigue +> siendo correcta.** El sobre de trigger ya no es **(0,2,0)**: la firma §55 «el +> sobre de trigger de popover es el SUELO» lo emite desde `:where(...)`, +> **(0,0,0)**, así que hoy PIERDE contra el (0,1,0) de esta receta. Las tres +> claves siguen retiradas y no hay defecto visual —la receta calla y el suelo +> pinta, que es su trabajo—, pero si volvieran **ganarían**: la razón por la que +> estaban muertas ya no es la que dice arriba. Se anota en vez de reescribirse +> porque la medida de entonces fue correcta con la cascada de entonces. + **Cinco adjudicaciones, todas medidas forzando sobre nodos reales**: las tres del marcador de tono (la demo monta **cero** celdas `data-tone-capable`; forzado el atributo sobre una celda real, el `::after` alcanza — 4px → 37px, 9999px → diff --git a/docs/next-features.md b/docs/next-features.md index 567288244..6c9f6cc8d 100644 --- a/docs/next-features.md +++ b/docs/next-features.md @@ -558,16 +558,30 @@ existiera. Se anotan porque el eje entero se apoya en esas mediciones. selector propio ENCIMA para recuperar su cromo. Con el sobre en el suelo, esos pines ya no defienden de nada — pero siguen pesando, y ahora ganan a reglas que quizá deberían ganarles: - - `chronos.css:417` — `[data-popover-trigger][data-chronos-more-link]:not(…)` - a **(0,3,0)**, con su comentario diciendo por qué existe. Medido hoy: su - `background: var(--_button-bg)` (shorthand) le gana al velo de hover de - `archetypes.css` (0,0,0), así que el `+N more` NO recibe la capa de estado - del sistema; su afordancia de hover es el `text-decoration: underline` de su - propia receta, que es correcta para un enlace pero NO es lo que el pin - pretendía. **Retirarlo es un cambio de píxel: firma aparte.** + - ~~`chronos.css:417`~~ — **RETIRADO 2026-08-25** (firma «el velo del sistema + no muere por un atajo»), y **§13 lo había adjudicado MAL**. Decía que su + `background: var(--_button-bg)` le ganaba al velo de hover de + `archetypes.css` y que retirarlo era un cambio de píxel. El HECHO es cierto + —el `+N more` no recibe el velo, su afordancia es el `underline` de su + receta— pero la ATRIBUCIÓN era falsa: al velo lo mata `button.css:69` + (`[data-button]`, (0,1,0)) y `button.css:88` (`:hover`, (0,2,0)), con el pin + puesto **o quitado**; medido, el único autor de `background-image` que casa + es `archetypes` y pierde en las dos pasadas. El pin era + **REDUNDANTE-TOTAL**: cuatro de sus cinco declaraciones eran copias + literales de `[data-button]` y la quinta (`height: auto`) es el gemelo + lógico de su `block-size: fit-content`. **0 diffs en 20 combinaciones + `variant` × `size`**, reposo y hover, con el sucesor NOMBRADO y control + negativo 20/20. No necesitó firma de producto: fue una limpieza. Ficha + `docs/audit/theming/chronos.md` anotada (censo 202→198, propuesta 50→47: + los tres `more-link-*` se quedaron sin consumidor, y proponían un público de + `chronos` con valor privado de `button` — lo que su propio §4 prohíbe). - `calendar` — sus selectores de mes/año NO llevan pin propio; el que empataba era `[data-calendar-month-select][data-button]` (0,2,0), que hoy gana solo. - Nada que revisar. + Nada que revisar. **Medido 2026-08-25** con la declaración desactivada en + vivo: retirarla rompería el tipo en **3 de 4 tallas** (xs 12→16, sm 14→16, + lg 20→16 px), así que ni es un pin ni se toca. El ⚠ HALLAZGO «no + determinista» de `docs/audit/theming/calendar.md` que apuntaba a este §13 + queda CERRADO allí con nota fechada. - `chat-message.css:462` — `[data-chat-message-actions] [data-chat-message-reaction-add]` (0,2,0) **era una trampa armada** (empataba con el sobre y ninguna superficie del repo monta ese anidamiento). Hoy gana de forma determinista: medido @@ -585,18 +599,38 @@ existiera. Se anotan porque el eje entero se apoya en esas mediciones. ninguna de las dos es una petición explícita por elemento como el `frost`, y `archetypes.css:19-21` ya declara que el anillo de foco «must lose to any component rule». **Decisión pendiente, con su número.** -- **El suelo de `popover.css` COMPARTE peldaño con `archetypes.css`** - (2026-08-25, medido, sin defecto observado). Al bajar a (0,0,0), las dos reglas - del sobre empatan con `:where([data-archetype='trigger'])` y su gemela de - hover, que declaran `transition` y el velo de estado. El orden lo decide el - documento. **Medido 16 cargas limpias en 4 rutas: archetypes SIEMPRE cae - después** (los índices de hoja varían de `sheet0` a `sheet19` y el resultado no - cambia), así que hoy el sistema gana su `transition` y su velo — que es lo que - la firma quería. Pero es un empate de verdad, y **no se ha verificado en - producción** (bundle de Vite en vez de dev), donde el orden de emisión es otro. - Si alguna vez se invierte, un trigger desnudo perdería el velo de hover. - El arreglo limpio sería que `popover.css` dejara de declarar hover propio y se - apoyara en la capa del sistema — otra firma. +- **El suelo de `popover.css` COMPARTE peldaño con `archetypes.css`** — y lo + único que queda del empate es `transition` (2026-08-25, medido). Al bajar a + (0,0,0), las dos reglas del sobre empatan con `:where([data-archetype='trigger'])` + y su gemela de hover: las CUATRO a (0,0,0), así que el orden de documento + decide. Se disputaban DOS propiedades y la firma «el velo del sistema no muere + por un atajo» sacó una del empate: + - **`background-image` — RESUELTO.** El suelo declaraba `background:`, un + ATAJO que expande a los ocho longhands y entre ellos `background-image: none` + — que es EXACTAMENTE donde `archetypes.css` pinta el velo de estado. Y no + era sólo la regla de hover: el `:where()` deja también la de REPOSO empatada + con la de hover del arquetipo, y ésa sola bastaba para matarlo. Partido en + `background-color:` (`popover.css:60` y `:75`), el velo **compone encima + gane quien gane el orden** — medido idéntico en los DOS órdenes, donde antes + daba `none`. Coste **0 px** sobre el barrido de **14 identidades del + catálogo, 68 lecturas × 2 estados**, con control negativo (diff 5 y 4). Es + lo que `feedback_hover_is_the_systems_never_a_per_component_invention` ya + mandaba: el acento de estado va en `background-color` para que la capa + COMPONGA encima. + - **`transition` — RESIDUO VIVO, con su número.** El suelo declara + `background, border-color`; el arquetipo, `opacity, background-color`. + Siguen empatados a (0,0,0) y sigue decidiéndolo el orden: hoy gana el del + arquetipo, así que **el cambio de `border-color` del hover de popover no se + anima — salta**. Defecto pequeño y sin efecto sobre el velo, pero es la + misma clase que §12.9 y §53 se firmaron para prohibir («no rung ties + another»): la doctrina no adjudica un ganador del empate, lo PROHÍBE. + - **Decisión de producto, aparte**: que `popover.css` deje de declarar hover + propio y se apoye entera en la capa del sistema — lo doctrinalmente puro, y + lo que §13 proponía. **NO es de coste cero**: hoy el hover de un trigger + desnudo mueve `background-color` 0.9821 → 0.931 **y además** recibe el velo; + sin la regla propia queda sólo el velo. Cambio visible en los triggers + desnudos del catálogo — firma aparte, con censo. Cerraría de paso el residuo + `transition`. - ~~**El centinela da falsos negativos sobre una propiedad transicionada.**~~ **CAUSA ENCONTRADA Y ARREGLADA 2026-08-21** (revisión adversarial): no era la @@ -667,6 +701,13 @@ existiera. Se anotan porque el eje entero se apoya en esas mediciones. Nació con la segunda ocurrencia de la clase: el `item-gap` de `carousel` contra un estilo INLINE de soma, invisible para todo análisis estático. Los ocho componentes de F2-A pasan con su adjudicación escrita. + > **NOTA 2026-08-25** — la premisa «(0,2,0 contra 0,1,0)» de este punto + > CADUCÓ: la firma §55 emite el sobre de trigger de `popover.css` desde + > `:where(...)`, **(0,0,0)**, así que hoy PIERDE contra la receta del huésped. + > El hallazgo sigue en pie como historia y la retirada sigue siendo correcta + > —la receta calla y el suelo pinta, que es su trabajo—, pero si aquellas + > declaraciones volvieran hoy **ganarían**. Se anota en vez de reescribirse: + > la medida de entonces fue correcta con la cascada de entonces. - **`--gp-current-gradient` es un nombre ABREVIADO en SOMA.** Lo estampa `gradient-picker-provider.svelte.ts` (no el wrapper de eidos, como decía la ficha), y viola theming §6 r5. No es knob de tema —es un canal de valor— pero @@ -722,6 +763,12 @@ Lo que la capa `calendar-surface` añadió (2026-08-21): Arreglarlo es subir el peso del pin de forma determinista — decisión, porque fija el píxel en un lado. Segunda ocurrencia de la clase §12.3 (empate por orden de carga) y segunda víctima de la misma regla de popover. + > **CERRADO 2026-08-25 por §55.** No hizo falta subir el peso del pin: bajó el + > del rival. El sobre de `popover.css` se emite desde `:where(...)`, (0,0,0), + > así que `[data-calendar-month-select][data-button]` (0,2,0) gana de forma + > DETERMINISTA y la letra deja de depender de qué chunk inyecte Vite el + > último. Re-medido 2026-08-25 por talla: 12 / 14 / 16 / 20 px con la regla, + > 16 px en las cuatro sin ella — **no es un pin y no se toca**. - **Los tres consumidores de la capa siguen leyendo 0 % de alcance**, ahora por los forwards de paleta THM-2 — ver el punto del censo más arriba. diff --git a/docs/process/CONTINUE-theming.md b/docs/process/CONTINUE-theming.md index 82f58123e..3d5656cad 100644 --- a/docs/process/CONTINUE-theming.md +++ b/docs/process/CONTINUE-theming.md @@ -1,4 +1,4 @@ -# CONTINUE — eje Theming «theme-reach» (handoff, act. 2026-08-24 noche) +# CONTINUE — eje Theming «theme-reach» (handoff, act. 2026-08-25) ## EMPIEZA AQUÍ @@ -10,6 +10,47 @@ pendientes. Global **68 %**, **45 componentes al 100 %**. Lo que queda NO es ejecución: son **cinco firmas** y una lista de deuda acotada. No abras nada nuevo sin leer §«Lo que espera TU FIRMA» de aquí abajo. +### FIRMA EJECUTADA (2026-08-25) — el velo del sistema no muere por un ATAJO + +**Qué se firmó** (changelog §56, reverso de §55 el mismo día): al bajar el sobre +de trigger de `popover.css` al suelo, §55 lo dejó a **(0,0,0) — el mismo peldaño +que `archetypes.css`**, que es quien pinta el velo de estado del sistema. Y el +suelo declaraba su superficie con el ATAJO `background:`, que expande a +`background-image: none` — **la propiedad exacta donde vive ese velo**. Resultado: +el velo de hover de todo trigger desnudo dependía de qué hoja cayera después. +No sólo por la regla de hover: el `:where()` deja también la de REPOSO empatada +con la de hover del arquetipo, y ésa sola bastaba. La corrección son DOS +PALABRAS — `background-color:` en `popover.css:60` y `:75`. + +**Los números**: **0 px** en el barrido de las **14 identidades del catálogo** +que montan un `[data-popover-trigger]` (68 lecturas en reposo → 0 movidas, 68 en +hover → 0 movidas, `rules split=2` en las 14) con control negativo diff 5 / 4; +las dos sondas del eje a **0 diffs** (`popover` 448 valores / 8 estados, `chronos` +36 832 / 7); y **el velo sobrevive al orden invertido**, donde con el atajo moría +(`linear-gradient(…8 %…)` → `none`). Cae con la firma el pin `chronos.css:417` +(cinco declaraciones a (0,3,0) que ya no defendían nada): **0 diffs en 20 +combinaciones `variant` × `size`**, control negativo 20/20 — §13 lo había +adjudicado mal, al velo del `+N more` lo mata `button.css:69`/`:88`. Guarda §55 +apartado **(f)** en `active-eidos-config.test.ts`, **4 mutaciones / 4 mordidas** +(las dos primeras muerden la mitad positiva, las dos segundas —el atajo AÑADIDO +junto al longhand— la negativa). + +**Lo que quedó fuera, con su número en `next-features.md` §13**: el residuo +`transition` del MISMO empate (suelo `background, border-color` vs arquetipo +`opacity, background-color`, las dos a (0,0,0) — hoy el `border-color` del hover +de popover salta en vez de animarse), la decisión de producto «popover deja de +declarar hover propio» (no es coste cero: 0.9821 → 0.931 **más** el velo hoy, +sólo el velo después) y `calendar-select.css:14`, que **no es un pin** — retirarlo +rompe el tipo en 3 de 4 tallas (12 / 14 / 20 → 16 px). + +**Fichas y prosa saneadas**: `chronos.md` (censo 202→198, propuesta 50→47, en +bloques `` para que sobrevivan a `--report`), `calendar.md` (su +⚠ HALLAZGO «no determinista» lo cerró §55 y ya no apunta a §13), `emoji-picker.md` +y los tres comentarios de código que seguían afirmando **(0,2,0)** del sobre +(`emoji-picker.css`, `gradient-picker.css` —sólo su mitad base, la de estados +sigue viva— y `lib/recipes/base.ts`). Se ANOTAN, no se reescriben: cada medida +fue correcta con la cascada de su día. + ### FIRMA B′ EJECUTADA (2026-08-24) — la cascada de paleta es una ESCALERA **Qué se firmó**: los tres escritores de `--{c}-palette-*` pasan a tres peldaños diff --git a/docs/theming/changelog.md b/docs/theming/changelog.md index b726e1d00..701b8f3dc 100644 --- a/docs/theming/changelog.md +++ b/docs/theming/changelog.md @@ -2307,8 +2307,83 @@ Guarda por **mutación** en `active-eidos-config.test.ts` (§55, 6 mutaciones, del `:where()` · suelo vaciado · una QUINTA regla de trigger fuera del suelo · y las dos reglas de estado bajadas en silencio. +## 56. El velo del sistema no muere por un ATAJO — `background-color`, nunca el shorthand `background` (2026-08-25) + +**FIRMA — el reverso de §55, el mismo día.** Al bajar el sobre de trigger al +suelo, §55 lo dejó a (0,0,0): **el mismo peldaño que ocupa `archetypes.css`**, +que es quien pinta el velo de estado del sistema. Empate nuevo. Y el suelo +declaraba su superficie con el ATAJO `background:`, que expande a los OCHO +longhands y entre ellos **`background-image: none`** — que es EXACTAMENTE la +propiedad donde ese velo se pinta. El empate no era cosmético: **el velo de hover +de todo trigger desnudo dependía de qué hoja cayera después**. + +**Y no era sólo la regla de hover.** El `:where()` anula la contribución de +especificidad de todo lo que lleva dentro, pseudo-clases incluidas, así que deja +la regla de **REPOSO** del suelo empatada también con la de **HOVER** del +arquetipo — y la de reposo ya declaraba `background-image: none` por el atajo. +Bastaba ella sola para matar el velo. + +**La corrección son dos palabras**: `background:` → `background-color:` en +`popover.css:60` (reposo) y `:75` (hover). Deja de declararse `background-image`, +así que **el velo SALE del empate**: el sistema pinta su capa y la superficie de +popover compone debajo, gane quien gane el orden. Es lo que +`feedback_hover_is_the_systems_never_a_per_component_invention` ya mandaba — +«nunca un `background:` a mano, nunca `background-image: none` para "limpiar" el +velo; el acento de estado va en `background-color` para que la capa COMPONGA +encima»—. La causa no era el empate: era un shorthand donde la doctrina exige un +longhand. + +**Los números** (transiciones congeladas en toda medida): + +- **0 px sobre el barrido de las 14 identidades del catálogo** que montan un + `[data-popover-trigger]` — `popover` · `chronos` · `calendar` · + `emoji-picker` · `natural-time-picker` · `chat-message` · `gradient-picker` · + `palabras` · `date-picker` · `time-picker` · `color-picker` · `field-langs` · + `toolbar` · `select`: **68 lecturas en reposo → 0 movidas, 68 en hover → + 0 movidas**, con las DOS reglas del suelo intervenidas en las catorce + (`rules split=2` en todas, que es el anti-vacío del barrido). **Control + negativo** con centinela: diff **5** y diff **4** — el arnés muerde. +- **Las dos sondas del eje, 0 diffs**: `popover` 448 valores computados en + 8 estados; `chronos` **36 832** en 7. +- **El velo sobrevive al ORDEN INVERTIDO.** Aislado el empate —las dos reglas del + suelo sacadas de su hoja y re-anexadas al final del ``, misma + especificidad, sólo cambia el orden de documento— el `background-image` del + hover leía `linear-gradient(…8 %…)` **→ `none`** con el atajo, y + `linear-gradient(…8 %…)` **en los DOS órdenes** con el longhand. + +**Y cae con ella un pin que ya no defendía nada**: `chronos.css:417`, cinco +declaraciones a (0,3,0) que existían sólo para ganarle al sobre viejo a (0,2,0). +Con el sobre en el suelo, `[data-button]` (0,1,0) le gana solo — y cuatro de las +cinco eran copias **literales** de `[data-button]`; la quinta, `height: auto`, es +el gemelo lógico de su `block-size: fit-content`. Retirado con **0 diffs en 20 +combinaciones `variant` × `size`**, reposo y hover, control negativo **20/20**. +`next-features.md` §13 lo había adjudicado como «cambio de píxel, firma aparte» +por una atribución FALSA: al velo del `+N more` lo mata `button.css:69` +(`[data-button]`, (0,1,0)) y `button.css:88` (`:hover`, (0,2,0)), con el pin +puesto **o quitado**. Corregido allí, y la ficha de `chronos` anotada +(censo **202→198**, propuesta **50→47**: los tres `more-link-*` se quedaron sin +consumidor, y proponían un público de `chronos` con valor privado de `button` — +lo que su propio §4 prohíbe). + +**Lo que NO se tocó, y es decisión**: `calendar-select.css:14`, que **no es un +pin** —retirarlo rompe el tipo en 3 de 4 tallas (12 / 14 / 20 → 16 px)—; el +**residuo `transition`** del mismo empate (el suelo declara `background, +border-color`, el arquetipo `opacity, background-color`, las dos a (0,0,0): hoy +gana el arquetipo, así que el cambio de `border-color` del hover de popover +SALTA en vez de animarse); y la decisión de producto de que `popover.css` deje de +declarar hover propio, que **no es de coste cero** (hoy el trigger desnudo mueve +`background-color` 0.9821 → 0.931 **y además** recibe el velo; sin ella, sólo el +velo). Los tres en `next-features.md` §13. + +Guarda por **mutación** en `active-eidos-config.test.ts` (§55, apartado **(f)**, +4 mutaciones, **4 mordidas**): el longhand devuelto al atajo en reposo y en hover +—que muerden la mitad POSITIVA, el anti-vacío— y el atajo **AÑADIDO junto** al +longhand en las dos, que muerden la mitad negativa, la que vigila el shorthand. +Control de falso positivo: el `transition: background …` de la misma regla sigue +ahí y el verde pasa. + --- -**Última revisión**: 2026-08-25 (§55 el sobre de trigger de popover es el -suelo). Si algo en este doc no coincide con el código, el código gana — pero -abre un issue para que actualicemos el doc. +**Última revisión**: 2026-08-25 (§56 el velo del sistema no muere por un atajo). +Si algo en este doc no coincide con el código, el código gana — pero abre un +issue para que actualicemos el doc. diff --git a/src/uix/eidos/active-eidos-config.test.ts b/src/uix/eidos/active-eidos-config.test.ts index 8739b63d3..8b9c84a50 100644 --- a/src/uix/eidos/active-eidos-config.test.ts +++ b/src/uix/eidos/active-eidos-config.test.ts @@ -670,6 +670,34 @@ describe('ActiveEidos config', () => { // A guard that inspected NOTHING passes green: the census is the other half // of the assertion. Four trigger rules — two on the floor, two above it. expect(triggerRules).toHaveLength(4); + + // (f) …and the floor paints its surface with the LONGHAND (signed + // 2026-08-25). `background:` is a SHORTHAND: it expands to all eight + // longhands, `background-image: none` among them — and `background-image` + // is exactly where `archetypes.css` paints the system's hover veil, at + // (0,0,0), i.e. TIED with this floor. While the shorthand was here the veil + // died on every bare trigger wherever popover.css happened to load LAST + // (measured live on the inverted order: `linear-gradient(…8 %…)` → `none`), + // a coin flip decided by two `import` lines of a layout. The longhand takes + // the surface out of the tie — 0 px over 68 triggers × 2 states — and is + // what `feedback: hover is the system's, never a per-component invention` + // already mandates. The positive half is the anti-void: a `not.toMatch` on + // an empty body passes green. + const SHORTHAND = /(?:^|[;\s])background\s*:/; + expect(rest!.body, 'the rest floor stopped painting a surface at all').toContain( + 'background-color: var(--popover-trigger-bg);' + ); + expect( + rest!.body, + 'the rest floor is back on the `background` SHORTHAND — it expands to `background-image: none` and kills the system hover veil it ties with' + ).not.toMatch(SHORTHAND); + expect(hover!.body, 'the hover floor stopped painting a surface at all').toContain( + 'background-color: var(--popover-hover-trigger-bg);' + ); + expect( + hover!.body, + 'the hover floor is back on the `background` SHORTHAND — it expands to `background-image: none` and kills the system hover veil it ties with' + ).not.toMatch(SHORTHAND); }); it('emits the Fase 4 frost atmosphere (opt-in [data-frost] + blur tokens)', () => { diff --git a/src/uix/eidos/components/chronos/chronos.css b/src/uix/eidos/components/chronos/chronos.css index 81513e374..8b532fbe4 100644 --- a/src/uix/eidos/components/chronos/chronos.css +++ b/src/uix/eidos/components/chronos/chronos.css @@ -410,17 +410,15 @@ align-self: start; justify-self: start; } -/* It's a composed