fix(theming)!: file-upload pinta lo SUYO - muere el barrido de descendientes

`[data-file-upload] [data-disabled]` (0,2,0) vestia todo nodo disabled bajo el
provider, HUESPEDES incluidos, y ganaba el empate por orden de import - el
accidente que B' condena. Medido en la composicion documentada del composer:
el textarea huesped recibia la atenuacion TRES veces (0.4^3 = 0.064, el
placeholder casi ilegible) con el file-upload NI SIQUIERA disabled, y
`--chat-composer-disabled-opacity` no alcanzaba nunca.

- La mitad descendiente se sustituye por los CINCO selectores por parte
  (label, dropzone, trigger, item-remove, clear-trigger; el provider ya
  estaba). El morfo declara `data-disabled` exactamente en esas partes y soma
  lo estampa siempre junto al atributo de parte: el barrido era 100 %
  redundante hacia dentro - solo anadia alcance hacia fuera.
- Unicidad re-censada HOY: 171 recetas, unica ocurrencia con `data-disabled`.
- Medido: file-upload CERO ESTRICTO (4.608 valores x 8 estados + pase
  disabled propio 0/35); composer recupera EXACTAMENTE 6 valores (opacity y
  alpha de textarea/input, cursor x2) y nada mas - la excepcion a D-TH.5
  firmada, con capturas antes/despues.
- Centinela: composer 29 -> 30/33 (revive `disabled-opacity`; su excepcion
  EXACTA salio STALE por si sola - el reverso de la ceguera a patrones);
  file-upload 61/98, exit 0 ambos.
- README del composer corregido: su adjudicacion "no se ve hasta que un tema
  mueva" era FALSA para el textarea (triple atenuacion en el tema default).
- Registro: PLAN 8 entrada fechada - CONTINUE item 3 EJECUTADA - notas en
  las fichas de ambos.

Aviso de instrumento (en el registro): la sonda sancionada es CIEGA a esta
firma (sin paso disabled; su filtro del composer no ve [data-textarea]) - su
cero vale como regresion, no como testigo; el gate se cumplio con instrumento
dedicado, exacto y sin extras.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
alpha-0.1-background
dev 2 months ago
parent ffa45726fd
commit 2daa683fa4

@ -147,4 +147,30 @@ del servidor de desarrollo. Los 2.204 valores restantes, idénticos.
**Lo que queda fuera y por qué**: una identidad firmada (§1.4) y cinco knobs de
sistema transversal (§2). El componente está CERRADO en su número.
**Nota 2026-08-24 — la adjudicación de `disabled-opacity` de aquí arriba era
FALSA, y la firma la retira.** `file-upload` acotó su barrido a sus cinco partes
propias, así que la colisión ya no existe. Pero además la cuenta que la
justificaba estaba incompleta: «invisible hasta que un tema mueva uno» es cierto
para las dos reglas PROPIAS del composer —`[data-chat-composer][data-disabled]`
y `[data-chat-composer-send][data-disabled]` empataban a 0.4 y ahí se quedaban—
y **falso para el textarea**, que esa lectura no miró. `[data-textarea]` y
`[data-textarea-input]` **no declaran atenuación propia** (y esta ficha ya
declara el wrapper «celda neutra»), así que el barrido les imponía 0.4 **dos
veces más** sobre el 0.4 legítimo del provider. La opacidad multiplica:
**0.4³ = 0.064 de alpha efectiva en el TEMA POR DEFECTO**, seis veces más
apagado de lo diseñado, con el placeholder casi ilegible — **925 de 25.568 px,
3,6 % de la superficie**, sin tocar un tema.
**Recuperado, medido**: exactamente **6 de 25** valores del estado `disabled`
—`[data-textarea]` opacity 0.4 → 1, alpha 0.16 → 0.4 y cursor `default` → `auto`;
`[data-textarea-input]` opacity 0.4 → 1 y alpha **0.064 → 0.4**; y el cursor
`default` → `auto` del provider del composer—. Nada más: `send` y el provider
siguen en 0.4 porque ambos defaults son `--opacity-disabled`; lo que recuperan es
que su `--chat-composer-disabled-opacity` **vuelve a alcanzar**. Centinela
**29 → 30/33** y la entrada del ledger sale como STALE (retirada de
`theming-sentinel-exceptions.ts`). La sonda estándar da 0 diffs reales — es
CIEGA a esto: no tiene paso `disabled` y su filtro de nodos no incluye
`[data-textarea]`; los 4 crudos son otra vez el `blockSize` flotante del
`attach` ya documentado arriba, reproducido sobre código idéntico.
<!-- veredicto:end -->

@ -157,4 +157,24 @@ control (gana por orden a igual especificidad): 0 diffs sobre 6.840 valores. El
instrumento pasó su muta-prueba: alterando el CSS de control acusa 19 diffs, y 1
si sólo se altera el borde inválido.
**Nota 2026-08-24 — FIRMA: la receta deja de BARRER DESCENDIENTES.** La regla de
disabled (`file-upload.css:200-218`) escribía
`[data-file-upload][data-disabled], [data-file-upload] [data-disabled]`. La
segunda mitad, (0,2,0), vestía TODO nodo deshabilitado bajo el provider —los
ajenos incluidos— y ganaba el empate por orden de emisión. **Única ocurrencia de
ese patrón en las 171 recetas del árbol.** Pasa a cinco selectores por parte
propia (`label`, `dropzone`, `trigger`, `item-remove`, `clear-trigger`), con la
mitad del provider intacta y la misma especificidad.
Se pudo retirar entera porque el morfo declara `data-disabled` en 6 partes y
soma lo escribe en esos 6 nodos exactos, **siempre junto a su
`data-file-upload-{parte}`**: el barrido no alcanzaba ni un nodo propio que un
selector por parte no alcance. Verificado en runtime — las 6 partes conservan
`opacity: 0.4` y `cursor: default`. **Este componente NO se mueve**: sonda
estándar 0 diffs (4.608 valores · 8 estados) y **0 de 35** valores en el estado
`disabled` medido aparte (la sonda compartida no tiene paso `disabled`).
`image-picker`, el otro consumidor de sus partes, **0 de 15**. Lo que se movió
es el huésped: ver `chat-composer.md`. Centinela 61/98, exit 0. Detalle en §8 de
`PLAN-theming.md`.
<!-- veredicto:end -->

@ -119,8 +119,14 @@ guarda `active-eidos-config.test.ts` · ledger `scripts/theming-sentinel-excepti
y que reaparece por tercera vez en `prose.code-bg` / `code-radius` /
`code-font-family` (`:862-865`). Lo que cambia es el ALCANCE de la firma:
de radio / padding / tipografía **a incluir también la tinta**.
3. **`file-upload` barre DESCENDIENTES** (`[data-file-upload] [data-disabled]`)
y se come el token de sus huéspedes. Única ocurrencia en 162 recetas.
3. ~~**`file-upload` barre DESCENDIENTES**~~ — **✅ FIRMADA Y EJECUTADA
2026-08-24**: la mitad descendiente pasa a cinco selectores por parte propia
(el morfo declara `data-disabled` en 6 nodos y los 6 llevan su attr de
parte, así que el barrido era redundante hacia dentro). Única ocurrencia en
**171** recetas, no 162. `file-upload` e `image-picker` con diff CERO;
`chat-composer` recupera 6 valores —el textarea salía a **0.4³ = 0.064** de
alpha en el tema POR DEFECTO, 925 px— y su entrada del ledger se RETIRA.
Detalle en §8 del PLAN.
4. **Las cuatro claves de `avatar` fuera de gramática** (`*-color-custom*`,
la ranura de tinta es `fg`). Son contrato público: renombrar es romper.
5. **`tags-input`** sella `aria-selected='true'` como LITERAL en cada etiqueta,

@ -521,6 +521,49 @@ excepción abre la mano para MEDIR, no para contabilizar.
## 8. Registro
- 2026-08-24 — **FIRMA: `file-upload` deja de BARRER DESCENDIENTES.** Su receta
escribía `[data-file-upload] [data-disabled]` (0,2,0) —única ocurrencia de
«combinador descendiente hacia un atributo de estado desnudo» en las **171**
recetas del árbol (el claim decía 162; el censo creció)— y vestía TODO nodo
deshabilitado bajo el provider, huéspedes incluidos. Pasa a **cinco selectores
por parte propia** (`label`, `dropzone`, `trigger`, `item-remove`,
`clear-trigger`), conservando la mitad del provider. Misma especificidad, así
que ninguna otra regla se mueve.
**Por qué se podía retirar entero**: el morfo declara `data-disabled` en 6
partes y soma lo escribe en esos 6 nodos exactos
(`file-upload-provider.svelte.ts:265, 300, 399, 450, 751, 838`), **siempre
junto a su propio `data-file-upload-{parte}`**. El barrido era 100 %
redundante hacia dentro y sólo añadía alcance hacia fuera. Censo por demo:
`/file-upload` 6 propios / 0 ajenos · `/image-picker` 2 / 0 ·
**`/chat-composer` 0 propios / 4 AJENOS** — allí no pintaba ni un nodo suyo, y
`[data-file-upload]` ni siquiera estaba deshabilitado.
**Los números**: `file-upload` diff **CERO ESTRICTO** (4.608 valores × 8
estados) y **0/35** en el estado disabled; `image-picker` **0/15**;
`chat-composer` exactamente **6 de 25** valores, todos recuperación —
`[data-textarea]` opacity 0.4 → 1 y alpha efectiva 0.16 → 0.4,
`[data-textarea-input]` opacity 0.4 → 1 y alpha **0.064 → 0.4**, y el `cursor`
`default` → `auto` del provider del composer y del wrapper del textarea. Nada
extra. **925 de 25.568 px (3,6 %)** en el TEMA POR DEFECTO. Centinela
`file-upload` 61/98 y `chat-composer` **29 → 30/33**, los dos exit 0.
**Lo que enseñó**: (1) **una adjudicación puede ser falsa por no mirar al
huésped ENTERO.** El ledger daba `chat-composer.disabled-opacity` por
invisible «hasta que un tema mueva uno» — cierto para las dos reglas propias
del composer, que empataban a 0.4, y **falso para el textarea**, que no
declara atenuación y recibía el 0.4 dos veces más sobre el legítimo del
provider: la opacidad MULTIPLICA y 0.4³ = 0.064 se ve sin tocar el tema. La
entrada se RETIRA (`theming-sentinel-exceptions.ts`), y esta vez **el guard sí
la cazó** —era clave EXACTA, no patrón—, que es justo el reverso de la ley 1
de B′. (2) **La sonda compartida no tiene paso `disabled`** (rest / size /
open / hover / focus) y su filtro de nodos para `chat-composer` no incluye
`[data-textarea]`: era CIEGA a esta firma, y su cero no es prueba. La
recuperación se midió con instrumento propio; el cero de la sonda vale como
regresión, no como testigo. (3) **Un empate resuelto por orden de emisión no
es una decisión, es una que aún no se ha tomado** — ley hermana de B′, tercera
aplicación de la misma doctrina tras §12.9.
- 2026-08-24 — **`toast` 98 % → 100 %** (`b8eccc1c4`), contrato 85 → **85**
claves —ninguna acuñada—, centinela **51/85** con 34 adjudicadas. Llegaba con
`global`, `private` y `sistema` a CERO y **un** knob fuera de alcance: el

@ -159,17 +159,20 @@ export const SENTINEL_EXCEPTIONS: Record<string, Record<string, string>> = {
'pause-z': 'the pause control is not mounted in the demo (0 nodes on the page)'
},
'chat-composer': {
// 2026-08-23. Four, and three of them are the guard's own two habits.
// 2026-08-23, narrowed 2026-08-24. Three, and ALL of them are the guard's
// own two habits. `disabled-opacity` was the fourth and is RETIRED: it was
// adjudicated on file-upload's descendant sweep `[data-file-upload]
// [data-disabled]`, which the firma of 2026-08-24 narrowed to its five own
// parts. The entry's own premise ("invisible until a theme moves one") was
// false: the sweep also hit `[data-textarea]` and `[data-textarea-input]`,
// which declare no dim, stacking 0.4 three deep (0.064 effective) in the
// DEFAULT theme. The token moves again — the guard reads it STALE.
'focus-border':
'only paints under :focus-within, and the guard blurs the active element after opening; focused the REAL textarea with transitions frozen -> reaches (color(srgb 0.745 0.577 0.894 / 0.48) -> rgb(1, 2, 3) on the shell border)',
'transition-duration':
'the guard freezes transitions and this token IS the transition; measured unfrozen -> reaches (0.12s -> 4.321s on the shell AND on the send)',
'transition-ease':
'same freeze; measured unfrozen -> reaches (cubic-bezier(0.4, 0, 0.2, 1) -> steps(3))',
// NOT the guard: a cross-recipe collision, and the composer is on the losing
// side of it BY DESIGN — its documented composition puts it inside FileUpload.
'disabled-opacity':
'file-upload sweeps DESCENDANTS: `[data-file-upload] [data-disabled]` is (0,2,0), the same weight as `[data-chat-composer-send][data-disabled]`, and its recipe is emitted LATER, so it wins over every disabled node inside a FileUpload — which is where the demo (and the documented composition) puts the composer; measured on the REAL nodes with the ancestor attr removed -> reaches (0.4 -> 0.123 on the send AND on the shell). Both defaults are --opacity-disabled, so the collision is invisible until a theme moves one'
'same freeze; measured unfrozen -> reaches (cubic-bezier(0.4, 0, 0.2, 1) -> steps(3))'
},
'chat-message': {
// 2026-08-24. Four, and every one of them is a limit of the INSTRUMENT —

@ -61,17 +61,28 @@ no tema.
**Identidad firmada** (fuera del ratio): el `inline-size: 100%` del textarea,
que ocupa su celda de la rejilla.
**Lo que el guard da por silencioso** (4, todas medidas):
**Lo que el guard da por silencioso** (3, todas medidas):
`focus-border` (sólo bajo `:focus-within`, y el centinela hace blur tras
abrir) · `transition-duration` / `transition-ease` (el centinela CONGELA la
transición para poder medir lo demás; sin congelar, 0,12 s → 4,321 s) ·
`disabled-opacity`, que es lo único que no es una limitación del instrumento:
`file-upload` barre DESCENDIENTES (`[data-file-upload] [data-disabled]`, (0,2,0),
el mismo peso que `[data-chat-composer-send][data-disabled]`) y su receta se
emite MÁS TARDE, así que gana sobre cualquier nodo deshabilitado dentro de un
FileUpload — que es justo donde vive el composer en su composición documentada.
Fuera de ese envoltorio alcanza (0.4 → 0.123). Los dos defaults son
`--opacity-disabled`, así que la colisión no se ve hasta que un tema mueve uno.
transición para poder medir lo demás; sin congelar, 0,12 s → 4,321 s).
**`disabled-opacity` ya NO está en esa lista — firma 2026-08-24.** Lo que
había escrito aquí («los dos defaults son `--opacity-disabled`, así que la
colisión no se ve hasta que un tema mueva uno») era una **adjudicación falsa**,
y la re-medida la retiró. Cierto para las dos reglas PROPIAS del composer —
`[data-chat-composer][data-disabled]` y `[data-chat-composer-send][data-disabled]`
empataban a (0,2,0) con el barrido y quedaban en 0.4 de todas formas—; **falso
para el textarea**, que esa cuenta no miró: `[data-textarea]` y
`[data-textarea-input]` **no declaran atenuación propia en esta página**, así
que el barrido de `file-upload` les imponía 0.4 **dos veces más** sobre el 0.4
legítimo del provider. La opacidad multiplica: **0.4³ = 0.064 de alpha efectiva
en el TEMA POR DEFECTO**, seis veces más apagado de lo diseñado, con el
placeholder casi ilegible. **925 de 25 568 px (3,6 % del composer).**
Desde la firma el barrido no existe: `file-upload` acota su regla a sus cinco
partes propias (`file-upload.css:200-218`), el composer recupera su
`--chat-composer-disabled-opacity` y el textarea vuelve a 0.4 de alpha. Fuera
de cualquier envoltorio la clave siempre alcanzó (0.4 → 0.123).
## Tokens (`--chat-composer-*`)

@ -197,8 +197,22 @@
transition: inline-size var(--file-upload-transition-duration) var(--file-upload-transition-ease);
}
/* A component paints what is ITS OWN. The second half used to read
`[data-file-upload] [data-disabled]` — a descendant sweep that dressed every
disabled node under the provider, HOSTS included, and won the (0,2,0) tie by
emission order alone. Measured 2026-08-24 on the documented `chat-composer`
composition: the composer's textarea took this 0.4 twice on top of the
composer's own (0.4³ = 0.064 effective) in the DEFAULT theme, and
`--chat-composer-disabled-opacity` never painted. The five parts below are
exactly the ones the morfo declares with `data-disabled` — the sweep never
reached an own node they do not. Sibling law of firma B′: precedence belongs
in the artefact, not in the emission order. Firma 2026-08-24. */
[data-file-upload][data-disabled],
[data-file-upload] [data-disabled] {
[data-file-upload-label][data-disabled],
[data-file-upload-dropzone][data-disabled],
[data-file-upload-trigger][data-disabled],
[data-file-upload-item-remove][data-disabled],
[data-file-upload-clear-trigger][data-disabled] {
cursor: default;
opacity: var(--file-upload-disabled-opacity);
}

Loading…
Cancel
Save

Powered by TurnKey Linux.