You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
svelte-kit-vice/docs/audit/theming/float-panel.md

178 lines
11 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

# float-panel — alcance de tema: análisis y propuesta
> Generado por `node --import tsx/esm scripts/theming-census.ts --report`.
> Lo **medido** y la **propuesta** se regeneran; el **Veredicto** (§5) se conserva.
> Vista de conjunto: [README](./README.md) · método y protocolo:
> [`PLAN-theming.md`](../../process/PLAN-theming.md) §1, §2, §7.
- **Medido**: 2026-08-23 · **Alcance**: **84%** — 41 de 49 knobs por token público
- **Knobs de apariencia**: 53 — público 41 · privado 3 · global 0 · literal 5 · sistema 4 · excepción 0 _(los dos últimos, fuera del ratio)_
- **Contrato hoy** (`lib/recipes/base.ts`): 40 pública(s) — `outline-bg`, `outline-border`, `ghost-bg`, `ghost-border`, `ghost-shadow`, `action-radius`, `action-fg`, `action-font-size`, `hover-action-bg`, `hover-action-fg`, `resize-grip-fg`, `resize-grip-radius`, `bg`, `border`, `border-width`, `radius`, `shadow`, `shadow-topmost`, `active-shadow`, `fg`, `font-family`, `font-size`, `line-height`, `header-bg`, `header-padding-inline`, `header-padding-block`, `header-gap`, `controls-gap`, `title-font-size`, `title-font-weight`, `title-fg`, `body-padding-inline`, `body-padding-block`, `resize-size`, `resize-edge`, `button-size`, `grip-size`, `accent`, `transition-duration`, `transition-ease` · 1 privada(s) forward — `_palette-border`
- **Eje `size`**: no · **ficheros**: `float-panel.css`
## 1. Knobs fuera de alcance
### 1.1 Directo a primitivo global (0)
_Ninguno._
### 1.2 A través de un privado (3)
| # | fichero:línea | selector | propiedad | valor |
| ---: | --- | --- | --- | --- |
| 1 | `float-panel.css:107` | `[data-float-panel-header]` | `border-block-end` | `var(--border-width-medium) solid var(--_float-panel-accent)` |
| 2 | `float-panel.css:184` | `[data-float-panel-action]:focus-visible, [data-float-panel-stage-trigger]:focus-visible` | `box-shadow` | `0 0 0 2px var(--_float-panel-accent)` |
| 3 | `float-panel.css:255` | `[data-float-panel-resize-grip]:hover, [data-float-panel-resize-grip][data-grabbed]` | `color` | `var(--_float-panel-accent)` |
### 1.3 Literales (5)
| # | fichero:línea | selector | propiedad | valor |
| ---: | --- | --- | --- | --- |
| 1 | `float-panel.css:173` | `[data-float-panel-action], [data-float-panel-stage-trigger]` | `line-height` | `1` |
| 2 | `float-panel.css:231` | `[data-float-panel-resize-grip]` | `background-image` | `repeating-linear-gradient( -45deg, transparent 0 3px, currentColor 3px 4.5px )` |
| 3 | `float-panel.css:248` | `[data-float-panel-resize-grip]:dir(rtl)` | `background-image` | `repeating-linear-gradient(45deg, transparent 0 3px, currentColor 3px 4.5px)` |
| 4 | `float-panel.css:254` | `[data-float-panel-resize-grip]:hover, [data-float-panel-resize-grip][data-grabbed]` | `opacity` | `1` |
| 5 | `float-panel.css:259` | `[data-float-panel-resize-grip]:focus-visible` | `opacity` | `1` |
### 1.4 Excepciones firmadas (0) — fuera del ratio
Literales que llevan su anotación `/* literal: <razón> */` en la propia
declaración: la válvula de recipe-contract §3, la misma que honra
`component-audit`. **Una desviación firmada no es deuda** — se listan para que la
razón se lea, no para acuñarlas.
_Ninguno._
## 2. Sistema transversal (4) — informativo, fuera del ratio
Un tema los alcanza **a nivel de sistema**, por diseño (recipe-contract §2).
| # | fichero:línea | selector | propiedad | valor |
| ---: | --- | --- | --- | --- |
| 1 | `float-panel.css:121` | `[data-float-panel-header]:focus-visible` | `box-shadow` | `inset 0 0 0 var(--ring-inset-width) var(--ring-inset-color, currentColor)` |
| 2 | `float-panel.css:125` | `[data-float-panel-header][data-grabbed]` | `box-shadow` | `inset 0 0 0 var(--ring-inset-width) var(--ring-inset-color, currentColor)` |
| 3 | `float-panel.css:239` | `[data-float-panel-resize-grip]` | `opacity` | `var(--opacity-muted)` |
| 4 | `float-panel.css:261` | `[data-float-panel-resize-grip]:focus-visible` | `box-shadow` | `inset 0 0 0 var(--ring-inset-width) var(--ring-inset-color, currentColor)` |
## 3. Privados de la receta — ¿de dónde sale su valor?
| privado | declaraciones | valor(es) | origen | ¿deriva de un público? |
| --- | ---: | --- | --- | :-: |
| `--_float-panel-accent` | 2 | `var(--float-panel-accent)`, `var(--_float-panel-palette-border)` | private, public | no |
Consumidos y **no declarados en el CSS** (vienen de `base.ts` o de un estilo inline del wrapper): `--_float-panel-palette-border`.
## 4. Propuesta de corrección
### 4.1 Tokens a declarar en `lib/recipes/base.ts` (3)
Valor **verbatim** del CSS de hoy: el default no se mueve, sólo cambia quién
puede moverlo. Nombres derivados de recipe-contract §1 (ejes lógicos, talla
al final) y theming §6.7 (slots de color, modificador delante). Un token con
DOS valores distintos es una colisión de nombre: son dos knobs, o el nombre
no distingue lo que debería — se marca `⚠`.
| token (`--float-panel-…`) | scope TSC | valor propuesto | usos |
| --- | --- | --- | ---: |
| `action-shadow` | `root` | ⚠ `var(--float-panel-accent)` / `var(--_float-panel-palette-border)` | 2 |
| `resize-grip-bg-image` | `root` | ⚠ `repeating-linear-gradient( -45deg, transparent 0 3px, currentColor 3px 4.5px )` / `repeating-linear-gradient(45deg, transparent 0 3px, currentColor 3px 4.5px)` | 2 |
| `hover-resize-grip-fg` | `root` | ⚠ `var(--float-panel-accent)` / `var(--_float-panel-palette-border)` | 2 |
### 4.2 Sin nombre mecánico (4)
- **⚠ decisión: `border-block-end` es shorthand o eje físico — hay que partirlo en ejes lógicos antes de nombrarlo (recipe-contract §1, R-4.4)** — 1: `border-block-end`.
- **⚠ decisión: `1` es un valor identidad o geometría de layout, no un knob de tema — el perímetro de «knob» es D-TH.2, sin firmar** — 3: `line-height`, `opacity`.
### 4.3 Avisos sobre los tokens propuestos (1)
- **el privado `--_float-panel-accent` debe pasar a leer este público (o desaparecer)** — `--float-panel-action-shadow`, `--float-panel-hover-resize-grip-fg`
### 4.4 Lo que hay que comprobar a mano (PLAN-theming §1.3 · §7.4)
- [ ] **Privado que no deriva de un público** — §3 lo marca; el privado debe leer el público o desaparecer.
- [ ] **Velo o acento en el nodo equivocado** (`archetype: 'item'` en un envoltorio, un `background` en shorthand que mata la capa de estado) — se mide desde el píxel hacia arriba.
- [ ] **Doble animación** al mover un sello a una superficie con animación propia — registro de `animationstart`/`animationend`.
- [ ] **Diff de computed = 0** en reposo · hover · abierto · disabled · foco, por talla, antes y después.
- [ ] **Centinela por token nuevo**: valor imposible en el root → el nodo lo sigue. Si no, el token miente.
## 5. Veredicto
<!-- veredicto:start -->
**EJECUTADO 2026-08-22 — 59 % → 84 %**, 12 claves. `global` a CERO.
Lo cosido: las dos VARIANTES que ajustan desde el default elevado
(`outline-*` / `ghost-*`) y los botones de su barra (`action-*` +
`hover-action-*`), más el asa de redimensionado.
**Y de paso muere uno de los nueve fantasmas del barrido**: el asa leía
`var(--color-content-tertiary, var(--color-content-secondary))` — ese primitivo
NO EXISTE, así que pintaba el respaldo. El contrato guarda lo que de verdad
pintaba (`--color-content-secondary`), con lo que la referencia muerta
desaparece sin mover un píxel.
**Once adjudicaciones medidas**: la demo monta la variante por DEFECTO (no
outline ni ghost) y no tiene botón de acción genérico —sólo el control de
cierre—, así que se forzaron el atributo de variante y se montó el botón donde
el CSS lo selecciona; el radio del asa sólo pinta bajo `:focus-visible`. Las
once alcanzan.
**La ANOMALÍA que registré aquí quedó RESUELTA el mismo día**, en la revisión
adversarial del bloque: `resize-grip-fg` movía aislado y leía muerto en una
corrida completa porque **la pasada de hover deja el puntero sobre el último
nodo que tocó**, y el asa re-apunta su color al acento bajo `:hover`. Con el
puntero aparcado tras esa pasada, el token vive y el guard delató su propia
excepción como STALE.
**Lo rojo que queda es ANTERIOR**: 12 tokens del bloque viejo, y seis de ellos
—`bg`, `border`, `border-width`, `shadow`, `font-family`,
`line-height`— son el mismo conjunto que en `popover`: el PLANO de profundidad
gana sobre el panel (§12.9, pendiente de firma).
Sonda antes/después: **0 diffs en 1.890 valores** (9 nodos × 7 estados).
---
**ADJUDICADO 2026-08-23 — los DOCE, uno a uno.** Quedaron escritos como «rojo
que queda» el 22 y nadie los midió: el guard R-5.4 **fallaba** en este
componente y el handoff daba por cerrado el bloque viejo. Ninguna regresión —la
bisección de las nueve versiones del guard desde `cd6a9f4e3` da siempre 17/40
con estos mismos doce—, sólo un rojo sin medir. Ahora el guard pasa: **17/40 con
23 adjudicaciones, cero STALE**.
**SEIS son el plano, y la predicción del 22 era exacta.** El contenido lleva
`data-depth='overlay'`, y `[data-depth='overlay']` declara `background`,
`border`, `box-shadow`, `font-family` y `line-height` a la MISMA especificidad
(0,1,0) y más tarde en la cascada. Verificado moviendo los tokens del propio
plano sobre este nodo (superficie, borde, fuente y leading lo repintan) y
enumerando las reglas que casan: la del plano está ahí, después de la de la
receta. `border-width` cae con `border` porque el plano escribe el shorthand.
Misma adjudicación que `tooltip`, misma decisión abierta.
⚠ **Y una corrección a mi propio diagnóstico**: primero atribuí la sombra a
`[data-topmost]` (el panel de la demo arranca frontal). Falso: quitando el
atributo, `--float-panel-shadow` sigue muerto. Es el plano también. Lo que sí
depende de `topmost` es su compañero **`shadow-topmost`, que SÍ alcanza**
(→ `rgb(4,5,6)`) porque su regla es (0,2,0) y le gana al plano — la prueba de
que la cascada es la explicación y no un token roto.
**Tres son estados o partes que la demo no monta**: `active-shadow` (forzado
`data-dragging` → alcanza), `resize-size` (lo consumen las asas de ESQUINA
`se/ne/sw/nw` y la demo monta sólo las de borde, `e` y `s`) y `button-size`
(lo consumen `[data-float-panel-action]` y `[data-float-panel-stage-trigger]`,
ninguno montado — el único control es el cierre, que es un `<Button>` compuesto
y se dimensiona solo: el mismo grupo que las tres `action-*` ya adjudicadas).
**Uno es el PUENTE DE PALETA** (§3.pre, no es deuda): el contenido lleva
`data-color`, así que `--_float-panel-accent` viene del forward THM-2
(`--_float-panel-palette-border` → `rgb(7,8,9)`); quitando `data-color`, la
clave alcanza (→ `rgb(1,2,3)`). Es la base sin color, no una clave muerta.
**Dos son la ley del congelado**: `transition-duration` / `-ease` no pueden
moverse bajo un guard que congela `transition` para hacer medible todo lo demás.
Pasada aparte sin congelar: `0.12s → 11.5s` y
`cubic-bezier(0.4,0,0.2,1) → steps(7)`.
Sin cambios de código: cero diffs por construcción.
<!-- veredicto:end -->

Powered by TurnKey Linux.