46 claves en el bloque `tree-view` de `recipes/base.ts` (fusionadas con el
forward de paleta). Censo 0 % → 92 %, cero globales. Global 46 %, sin contrato
47 → 46. Molde del hermano `tree-grid` allí donde el problema es el mismo.
LA PROPUESTA GENERADA FALLABA EN EL NOMBRE DE CASI TODO LO QUE IMPORTA: el
clasificador toma el PRIMER selector de cada regla como si fuera la parte
pintada, y aquí ese primero es el root o el branch-control cuando el nodo real
es otro.
1. `root-width: 1px` / `root-bg` NO son del root: son la GUÍA de indentación
(el `::before` del branch, una línea vertical). → `guide-width` + `guide-fg`,
literalmente los nombres de tree-grid. Un `root-bg` que tiñe una línea es la
clase de nombre que miente.
2. `branch-control-padding-inline-{k}` ⚠ fundía DOS ejes que se SUMAN en el
mismo calc: el ritmo de la fila y el PASO DE PROFUNDIDAD
(`--tree-depth × indent + padding`). Fundidos, tematizar la sangría habría
movido el padding. → `row-padding-inline-{k}` + `indent-{k}`.
3. El prefijo `branch-control-` es erróneo: la regla reza
`[data-tree-view-branch-control], [data-tree-view-item]` — las DOS filas. El
CSS ya llamaba `row` a sus privados. → `row-*`, como tree-grid y como la
lección de table. Y fuera el prefijo `root-` del chasis: el wrapper ES el
componente.
4. `row-padding-block` ⚠ no eran dos valores en pugna sino cinco por talla: xs
colapsa a `0`, las otras cuatro `--space-1`.
5. `branch-indicator-width` + `-height` son UN knob (`1em`) →
`branch-indicator-size`.
Bundle: la altura de fila casa 1:1; padding e indent llevan ritmo propio; la
tipografía un paso por debajo desde lg — verbatim, como table y tree-grid. Los
resueltos con `parts: ['root']` (el `data-size` va en `[data-tree-view-root]`,
wrapper de eidos, no parte del morfo). Los `transparent` de outline/ghost y el
`padding: 0` de ghost son identidad de variante y siguen literales.
`hover-row-bg` SÍ se acuña, al revés que en grid-list, y por medición: la misma
regla pinta dos nodos con arquetipo distinto, y `branch-control` NO lleva
archetype — ahí el plano de la receta es la única pintura (velo medido ausente)
y el token es toda la superficie de tema del hover. Tener un consumidor
legítimo es lo que lo distingue del caso grid-list.
EL DEFECTO QUE LA MEDICIÓN DESTAPÓ (preexistente, NO se toca aquí →
next-features §12.8): al pasar el ratón por la fila de una carpeta abierta se
tiñe LA CARPETA ENTERA, hijos incluidos. `archetype: 'item'` está declarado en
el `<li>` branch (`morfo/components/tree-view.ts:103`), que contiene el control
Y todo el `branch-content`, mientras la fila que el usuario señala es el
`branch-control` de dentro: el nodo velado mide 336 px frente a los 36 px de la
fila — medido y capturado. Un branch anidado acumula además el velo de sus
ancestros, así que sus filas se ven más oscuras que las hermanas. Mover el
arquetipo es morfo y mueve píxel en toda la demo. Es la TERCERA variante de la
misma familia: table lo tiene en fila Y celda, grid-list en fila Y celda sobre
el mismo nodo, y tree-view en un ANCESTRO del nodo señalado.
Artefactos y gates:
- Sonda antes/después = 0 diffs en 8.062 valores × 7 estados.
- R-5.4: 45/46; `disabled-row-fg` adjudicado en el ledger (la demo monta CERO
filas deshabilitadas, contadas; forzada alcanza oklch(0.61 0 0) → rgb(1,2,3)).
- censo --only 92 % · component:audit PASS · eidos-lint invalid 0, class-hooks 0
· suite eidos sin rojos nuevos (el conocido skin-media-player) · rtl:check 0
· docs:check 0 · check por fichero limpio (72 globales, ninguno mío).
- README con su «Talla y tema» y tab `Tokens` en la demo (46 claves, en vivo).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
| `--_tree-view-row-padding-inline` | 5 | `var(--space-2)`, `var(--space-1)`, `var(--space-3)`, `var(--space-4)` | global | no |
| `--_tree-view-indent` | 5 | `var(--space-4)`, `var(--space-3)`, `var(--space-5)`, `var(--space-6)` | global | no |
| `--_tree-view-font-size` | 5 | `var(--font-size-sm)`, `var(--font-size-xs)`, `var(--font-size-md)`, `var(--font-size-lg)` | global | no |
| `--_tree-view-guide` | 1 | `var(--color-border-default)` | global | no |
_La receta no declara privados propios en su CSS._
Consumidos y **no declarados en el CSS** (vienen de `base.ts` o de un estilo inline del wrapper): `--_tree-view-palette-element`.
## 4. Propuesta de corrección
- **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).
### 4.1 Tokens a declarar en `lib/recipes/base.ts` (30)
### 4.1 Tokens a declarar en `lib/recipes/base.ts` (0)
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
@ -90,54 +55,12 @@ no distingue lo que debería — se marca `⚠`.
- **⚠ decisión: `100%` 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** — 1: `inline-size`.
- **⚠ decisión: `border` es shorthand o eje físico — hay que partirlo en ejes lógicos antes de nombrarlo (recipe-contract §1, R-4.4)** — 3: `border`.
- **⚠ decisión: `padding` es shorthand o eje físico — hay que partirlo en ejes lógicos antes de nombrarlo (recipe-contract §1, R-4.4)** — 2: `padding`.
- **⚠ decisión: el privado que alimenta este knob no se declara en el CSS (viene de `base.ts` o de un estilo inline) — hay que resolverlo antes de nombrarlo** — 1: `background`.
### 4.3 Avisos sobre los tokens propuestos (7)
- **el privado `--_tree-view-radius` debe pasar a leer este público (o desaparecer)** — `--tree-view-root-radius`
- **el privado `--_tree-view-font-size` debe pasar a leer este público (o desaparecer)** — `--tree-view-root-font-size-md`, `--tree-view-root-font-size-xs`, `--tree-view-root-font-size-sm`, `--tree-view-root-font-size-lg`, `--tree-view-root-font-size-xl`
- **el privado `--_tree-view-row-block-size` debe pasar a leer este público (o desaparecer)** — `--tree-view-branch-control-height-md`, `--tree-view-branch-control-height-xs`, `--tree-view-branch-control-height-sm`, `--tree-view-branch-control-height-lg`, `--tree-view-branch-control-height-xl`
- **el privado `--_tree-view-row-padding-block` debe pasar a leer este público (o desaparecer)** — `--tree-view-branch-control-padding-block`
- **el privado `--_tree-view-row-padding-inline` debe pasar a leer este público (o desaparecer)** — `--tree-view-branch-control-padding-inline-md`, `--tree-view-branch-control-padding-inline-xs`, `--tree-view-branch-control-padding-inline-sm`, `--tree-view-branch-control-padding-inline-lg`, `--tree-view-branch-control-padding-inline-xl`
- **el privado `--_tree-view-indent` debe pasar a leer este público (o desaparecer)** — `--tree-view-branch-control-padding-inline-md`, `--tree-view-branch-control-padding-inline-xs`, `--tree-view-branch-control-padding-inline-sm`, `--tree-view-branch-control-padding-inline-lg`, `--tree-view-branch-control-padding-inline-xl`
- **el privado `--_tree-view-guide` debe pasar a leer este público (o desaparecer)** — `--tree-view-root-bg`
### 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.
@ -150,6 +73,69 @@ no distingue lo que debería — se marca `⚠`.
<!-- veredicto:start -->
_(pendiente — lo escribe el autor; se conserva al regenerar)_
**Medido 2026-08-21.** La §4 propone 30 tokens y **falla en el nombre de casi
todos los que importan**: el clasificador tomó el PRIMER selector de cada regla
como si fuera la parte pintada, y aquí ese primer selector es el root o el
branch-control cuando el nodo real es otro. Corregido queda en 46 claves, con
el molde del hermano `tree-grid` allí donde el problema es el mismo.
1. **`root-width: 1px` y `root-bg: var(--color-border-default)` NO son del
root: son la GUÍA de indentación.** El selector es
'no disabled row in the demo (0 mounted, counted); forced data-disabled → reaches (oklch(0.61 0 0) → rgb(1,2,3))'
},
textarea:{
'focus-input-border':
'consumed only under [data-focused], which the guard blurs away ON PURPOSE (the click-focus poisoning fix); focused by hand with the pointer parked → reaches (rgb(4,5,6))',