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/prose.md

158 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.

# prose — 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**: **83%** — 44 de 53 knobs por token público
- **Knobs de apariencia**: 53 — público 44 · privado 0 · global 0 · literal 9 · sistema 0 · excepción 21 _(los dos últimos, fuera del ratio)_
- **Contrato hoy** (`lib/recipes/base.ts`): 37 pública(s) — `font-size-sm`, `font-size-md`, `font-size-lg`, `fg`, `fg-muted`, `heading-fg`, `heading-font-weight`, `h1-font-weight`, `link-fg`, `link-font-weight`, `strong-font-weight`, `dt-font-weight`, `th-font-weight`, `mark-bg`, `mark-radius`, `blockquote-border`, `blockquote-border-width`, `blockquote-fg`, `code-font-family`, `code-bg`, `code-radius`, `pre-bg`, `pre-radius`, `kbd-font-family`, `kbd-bg`, `kbd-border`, `kbd-border-width`, `kbd-radius`, `kbd-shadow`, `media-radius`, `hr-border`, `hr-border-width`, `table-header-border`, `table-cell-border`, `table-border-width`, `measure`, `line-height`
- **Eje `size`**: sí · **ficheros**: `prose.css`
## 1. Knobs fuera de alcance
### 1.1 Directo a primitivo global (0)
_Ninguno._
### 1.2 A través de un privado (0)
_Ninguno._
### 1.3 Literales (9)
| # | fichero:línea | selector | propiedad | valor |
| ---: | --- | --- | --- | --- |
| 1 | `prose.css:139` | `:where([data-prose] mark):not(:where([data-prose-ignore], [data-prose-ignore] *))` | `padding` | `0.05em 0.15em` |
| 2 | `prose.css:154` | `:where([data-prose] blockquote):not(:where([data-prose-ignore], [data-prose-ignore] *))` | `padding-inline-start` | `1em` |
| 3 | `prose.css:164` | `:where([data-prose] :is(ul, ol)):not(:where([data-prose-ignore], [data-prose-ignore] *))` | `padding-inline-start` | `1.6em` |
| 4 | `prose.css:202` | `:where([data-prose] code):not(:where([data-prose-ignore], [data-prose-ignore] *))` | `padding` | `0.15em 0.35em` |
| 5 | `prose.css:209` | `:where([data-prose] pre):not(:where([data-prose-ignore], [data-prose-ignore] *))` | `padding` | `1em 1.15em` |
| 6 | `prose.css:226` | `:where([data-prose] kbd):not(:where([data-prose-ignore], [data-prose-ignore] *))` | `padding` | `0.15em 0.4em` |
| 7 | `prose.css:272` | `:where([data-prose] table):not(:where([data-prose-ignore], [data-prose-ignore] *))` | `inline-size` | `max-content` |
| 8 | `prose.css:284` | `:where([data-prose] th):not(:where([data-prose-ignore], [data-prose-ignore] *))` | `padding` | `0.5em 0.75em` |
| 9 | `prose.css:290` | `:where([data-prose] td):not(:where([data-prose-ignore], [data-prose-ignore] *))` | `padding` | `0.5em 0.75em` |
### 1.4 Excepciones firmadas (21) — 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.
| # | fichero:línea | selector | propiedad | valor |
| ---: | --- | --- | --- | --- |
| 1 | `prose.css:57` | `:where([data-prose] h1):not(:where([data-prose-ignore], [data-prose-ignore] *))` | `font-size` | `2.25em` |
| 2 | `prose.css:59` | `:where([data-prose] h1):not(:where([data-prose-ignore], [data-prose-ignore] *))` | `line-height` | `1.1` |
| 3 | `prose.css:60` | `:where([data-prose] h1):not(:where([data-prose-ignore], [data-prose-ignore] *))` | `letter-spacing` | `-0.01em` |
| 4 | `prose.css:66` | `:where([data-prose] h2):not(:where([data-prose-ignore], [data-prose-ignore] *))` | `font-size` | `1.5em` |
| 5 | `prose.css:68` | `:where([data-prose] h2):not(:where([data-prose-ignore], [data-prose-ignore] *))` | `line-height` | `1.3` |
| 6 | `prose.css:69` | `:where([data-prose] h2):not(:where([data-prose-ignore], [data-prose-ignore] *))` | `letter-spacing` | `-0.008em` |
| 7 | `prose.css:75` | `:where([data-prose] h3):not(:where([data-prose-ignore], [data-prose-ignore] *))` | `font-size` | `1.25em` |
| 8 | `prose.css:77` | `:where([data-prose] h3):not(:where([data-prose-ignore], [data-prose-ignore] *))` | `line-height` | `1.4` |
| 9 | `prose.css:83` | `:where([data-prose] h4):not(:where([data-prose-ignore], [data-prose-ignore] *))` | `font-size` | `1em` |
| 10 | `prose.css:90` | `:where([data-prose] h5):not(:where([data-prose-ignore], [data-prose-ignore] *))` | `font-size` | `0.9em` |
| 11 | `prose.css:97` | `:where([data-prose] h6):not(:where([data-prose-ignore], [data-prose-ignore] *))` | `font-size` | `0.85em` |
| 12 | `prose.css:99` | `:where([data-prose] h6):not(:where([data-prose-ignore], [data-prose-ignore] *))` | `letter-spacing` | `0.02em` |
| 13 | `prose.css:107` | `:where([data-prose] :is(h1, h2, h3, h4, h5, h6) code):not( :where([data-prose-ignore], [data-prose-ignore] *) )` | `font-size` | `0.9em` |
| 14 | `prose.css:147` | `:where([data-prose] :is(sub, sup)):not(:where([data-prose-ignore], [data-prose-ignore] *))` | `font-size` | `0.75em` |
| 15 | `prose.css:201` | `:where([data-prose] code):not(:where([data-prose-ignore], [data-prose-ignore] *))` | `font-size` | `0.875em` |
| 16 | `prose.css:213` | `:where([data-prose] pre):not(:where([data-prose-ignore], [data-prose-ignore] *))` | `font-size` | `0.875em` |
| 17 | `prose.css:214` | `:where([data-prose] pre):not(:where([data-prose-ignore], [data-prose-ignore] *))` | `line-height` | `1.6` |
| 18 | `prose.css:225` | `:where([data-prose] kbd):not(:where([data-prose-ignore], [data-prose-ignore] *))` | `font-size` | `0.8em` |
| 19 | `prose.css:252` | `:where([data-prose] figcaption):not(:where([data-prose-ignore], [data-prose-ignore] *))` | `font-size` | `0.85em` |
| 20 | `prose.css:277` | `:where([data-prose] table):not(:where([data-prose-ignore], [data-prose-ignore] *))` | `font-size` | `0.9em` |
| 21 | `prose.css:278` | `:where([data-prose] table):not(:where([data-prose-ignore], [data-prose-ignore] *))` | `line-height` | `1.5` |
## 2. Sistema transversal (0) — informativo, fuera del ratio
Un tema los alcanza **a nivel de sistema**, por diseño (recipe-contract §2).
_Ninguno._
## 3. Privados de la receta — ¿de dónde sale su valor?
_La receta no declara privados propios en su CSS._
## 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` (5)
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 (`--prose-…`) | scope TSC | valor propuesto | usos |
| --- | --- | --- | ---: |
| `font-size` | `root` | ⚠ `2.25em` / `1.5em` / `1.25em` / `1em` / `0.9em` / `0.85em` / `0.75em` / `0.875em` / `0.8em` | 13 |
| `line-height` _(ya existe)_ | `root` | ⚠ `1.1` / `1.3` / `1.4` / `1.6` / `1.5` | 5 |
| `letter-spacing` | `root` | ⚠ `-0.01em` / `-0.008em` / `0.02em` | 3 |
| `padding-inline` | `root` | ⚠ `1em` / `1.6em` | 2 |
| `width` | `root` | `max-content` | 1 |
### 4.2 Sin nombre mecánico (6)
- **⚠ 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)** — 6: `padding`.
### 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 — 1 % → 83 %**, 35 claves de COSTURA. `global` a CERO.
Prose estiliza **HTML crudo** (`h1`, `code`, `table`…) a través de
`:where([data-prose] el)`, así que sus «partes» son elementos y la costura va
**por parte**, como en `result`. Los valores siguen siendo los del canon
—bundle de talla, ranuras de contenido, escalas de peso y radio, familia mono—
y ahora tienen su knob, que es lo que PLAN §2-A pide.
**Su escala editorial NO entra en el contrato, y es doctrina firmada**: los
`2.25em`, `1.5em`, `0.9em`, sus `line-height` y su tracking son
`em`-relativos a propósito —un `font-size` raíz re-deriva encabezados y
márgenes, por eso NO hay una escala duplicada por talla como en
tailwind-typography (README, «No 5× duplicated scale»)— y van anotados
`/* literal: */`, la válvula de recipe-contract §3. Son las **21 excepciones**
firmadas de §1.4; el censo las saca del ratio desde hoy.
Dos literales se cambiaron por su paso de escala, con el mismo valor: el
`3px` del borde-acento del blockquote es `--border-width-thick`, y los `1px`
de kbd, `hr` y la tabla son `--border-width`.
**El instrumento estaba ciego de dos maneras y las dos se arreglaron antes de
medir:**
1. **Sonda y centinela filtran por `data-{c}-*`**, y aquí NINGUNA parte lo
lleva: la sonda medía **1 nodo** y el guard daba 27 de 37 tokens por
muertos. Ambos ganan un selector de nodos extra
(`EXTRA_NODES` / `extraNodes`) — con él, **63 nodos** y el gate empieza a
significar algo.
2. **El centinela no leía el color de un borde que no fuera el de arriba.**
El blockquote tiñe su `border-inline-start` y la tabla sus bordes de
bloque: tres tokens vivos leían muertos. Añadidos los cuatro lados lógicos
(+ `borderBottomColor`).
**Ocho adjudicaciones, todas medidas**: cinco son el harness de la
documentación —`[data-uix-docs] code|pre` (0,2,0) gana a `:where(…)` (0,0,0),
que es la incidencia ya escrita para `code-block` un piso más arriba— y tres
son elementos que el HTML de ejemplo no usa (`<mark>`, `<dl>`), montados
DENTRO del contenedor real: un `<mark>` a pelo es exactamente lo que esta
receta estiliza, así que el nodo es fiel.
Gates: sonda **0 diffs en 11.910 valores** (63 nodos × 7 estados) · centinela
**29/37** con las ocho adjudicadas · censo 83 % · `--names` 37/37 conformes ·
audit PASS · eidos-lint 0 invalid.
<!-- veredicto:end -->

Powered by TurnKey Linux.