| `8086f21d6`…`01b891b64` | **Las gráficas** (§7): 6 defectos de RTL en el chart + funnel, calendar-heatmap, heatmap matriz, radar, y los bloques de código |
| `8086f21d6`…`01b891b64` | **Las gráficas** (§7): 6 defectos de RTL en el chart + funnel, calendar-heatmap, heatmap matriz, radar, y los bloques de código |
Empezó como «el slider no responde al RTL» y eran **dos defectos independientes**:
@ -97,17 +97,17 @@ ahí pasaría hiciera lo que hiciera el código.
### 2.2 · Geometría lógica en los cinco que calculan píxeles desde JS
| componente | sitios |
| --- | --- |
| `slider` | 6 |
| `carousel` | 2 (signo del `translate3d` + signo del swipe) |
- **`dir="auto"` es la herramienta equivocada** cuando SÍ se sabe la dirección: mira
sólo el primer carácter fuerte, la spec llama a la heurística *"very crude"* y el
sólo el primer carácter fuerte, la spec llama a la heurística _"very crude"_ y el
W3C documenta que falla justo en esta clase de texto.
Excepción correcta que se queda: `chat-message.css:156` usa `unicode-bidi: plaintext`
@ -248,6 +248,7 @@ arreglo que se commiteó sale verde, y el eje de bloque (`inset-block-start` +
`translateY`) no se marca.
**Dos desviaciones del enunciado de §2.1, deliberadas:**
- **Amplía** a la propiedad independiente `translate:`, que se usa MÁS que
`transform: translate*` (87 apariciones frente a 36) y tiene el mismo defecto.
Ocho de los 24 hallazgos eran de esa forma.
@ -263,11 +264,11 @@ guard no puede ver esa compensación.
El único que queda es `palabras-chrome.css:446`, **auditado y no tocado** por la
regla de no escribir en palabras. Los 23 restantes cayeron en tres familias:
| Familia | Cuántos | Arreglo |
| --- | --- | --- |
| **Centrado** | 10 | `margin-inline-start: calc(<size> / -2)` si el tamaño se conoce (idioma del slider); `inset-inline: 0` + `margin-inline: auto` si lo fija el contenido |
| **Direccional** | 6 | El signo se invierte con `:dir(rtl)`; el par queda marcado `rtl-physical` |
| **Físico** | 7 | `left`/`right` — geometría de brújula (`cropper`) y polar (`menu-dial` arco) |
| **Centrado**| 10 | `margin-inline-start: calc(<size> / -2)` si el tamaño se conoce (idioma del slider); `inset-inline: 0` + `margin-inline: auto` si lo fija el contenido |
| **Direccional** | 6 | El signo se invierte con `:dir(rtl)`; el par queda marcado `rtl-physical` |
| **Físico**| 7 | `left`/`right` — geometría de brújula (`cropper`) y polar (`menu-dial` arco) |
⚠️ **NO añadas `inline-size: fit-content` a ciegas** en el centrado por márgenes
automáticos: al trigger del `carousel` le comió el ancho de 36px a 17px porque su
@ -293,10 +294,10 @@ llega a esa media query:
Los 12 selectores `[dir='rtl']` que había en eidos estaban **todos rotos**, en los
dos sentidos opuestos del mismo error. Medido en Chrome:
| Forma | Cuántos | Fallo | Medición |
| --- | --- | --- | --- |
| `[dir='rtl'] <desc>` | 5 | **Se aplica de más** — capta un ancestro RTL e ignora un `dir` más cercano que redeclare | `sidebar`: `direction: ltr` y aun así matchea |
| `[data-x][dir='rtl']` | 7 | **No se aplica nunca** — el atributo ya no se estampa por defecto (`013ceac57`) | `tree-view`: `direction: rtl` de verdad y NO matchea |
| `[dir='rtl'] <desc>`| 5 | **Se aplica de más** — capta un ancestro RTL e ignora un `dir` más cercano que redeclare | `sidebar`: `direction: ltr` y aun así matchea |
| `[data-x][dir='rtl']` | 7 | **No se aplica nunca** — el atributo ya no se estampa por defecto (`013ceac57`) | `tree-view`: `direction: rtl` de verdad y NO matchea |
Migrados los 12 a `:dir()`, que acierta los tres casos (atributo propio, heredado,
y redeclarado por un ancestro intermedio). Verificado en `sidebar` y `tree-view`.
@ -391,13 +392,13 @@ indicador del `radio-group`, que tampoco lo lista.
Pasados por navegador, con la dirección movida por el camino real (toggle del
topbar → prefs), nunca por `setAttribute`:
| | Resultado |
| --- | --- |
| **slider** | ✓ Click al 25% del ancho FÍSICO da 75 en RTL; arrastrar +120px a la derecha sube en LTR y baja en RTL; `ArrowRight` igual. Los seis sitios responden |
| **number-field** | ✓ El mismo arrastre físico sube en LTR y baja en RTL |
| **css-field** | ✓ Idéntico (`16px → 40px` en LTR, `40px → 16px` en RTL) |
| **dropdown-menu** | ✓ El panel raíz se alinea al inline-start (izquierda en LTR, derecha en RTL) y el submenú abre a la derecha en LTR, a la izquierda en RTL |
| **carousel** | Track ✓ (Next mueve −622px en LTR y +622px en RTL). **Swipe SIN MEDIR** |
| **slider**| ✓ Click al 25% del ancho FÍSICO da 75 en RTL; arrastrar +120px a la derecha sube en LTR y baja en RTL; `ArrowRight` igual. Los seis sitios responden |
| **number-field**| ✓ El mismo arrastre físico sube en LTR y baja en RTL |
| **css-field**| ✓ Idéntico (`16px → 40px` en LTR, `40px → 16px` en RTL) |
| **dropdown-menu** | ✓ El panel raíz se alinea al inline-start (izquierda en LTR, derecha en RTL) y el submenú abre a la derecha en LTR, a la izquierda en RTL |
| **carousel**| Track ✓ (Next mueve −622px en LTR y +622px en RTL). **Swipe SIN MEDIR** |
⚠️ **El swipe del carousel se me resistió a cinco intentos** de simulación de
puntero: la capa de gesto tiene umbral de distancia y de velocidad, y con
@ -459,7 +460,7 @@ resolvía `align: 'start'` a `r.left` SIEMPRE — una alineación LÓGICA clavad
un borde FÍSICO, que nunca voltea. `$ethereal` ya exporta la matemática buena:
```ts
computeCoordsFromPlacement(rects, placement, rtl) // pura, síncrona, sin ciclo de vida
computeCoordsFromPlacement(rects, placement, rtl); // pura, síncrona, sin ciclo de vida
```
Es la misma que usa el motor compartido, y toma la dirección como argumento.
@ -467,6 +468,7 @@ Migrado: se comparte la SEMILLA, no `useFloating`.
Verificado con `anchored-seed.test.ts` (4 casos), porque **la demo no ancla
ningún panel** y el defecto no era observable ahí:
- LTR: idéntico al algoritmo anterior en las 12 combinaciones side × align —
cero regresión.
- RTL con side vertical: `start` y `end` se espejan (lo que el viejo no podía).
@ -572,8 +574,8 @@ defecto no estaba en la decisión de `finishDrag` (que sí voltea con
`isRtlHorizontal`) sino en el pintado durante el arrastre:
```ts
translate = base + dragOffset // base = índice, dragOffset = dedo
itemGroupTransform = translate * flip // el flip caía sobre LOS DOS
translate = base + dragOffset; // base = índice, dragOffset = dedo
itemGroupTransform = translate * flip; // el flip caía sobre LOS DOS
```
El recorrido por índice es LÓGICO y debe voltear; `dragOffset` es el
@ -653,16 +655,16 @@ gráfico.
### 7.2 · Estado del catálogo — TODAS revisadas
| | Estado |
| --- | --- |
| `chart` + presets (line/area/bar/bubble/scatter) | Arreglado: eje X espeja · tooltip hereda `formatY` · canalón adaptativo · etiquetas a 9.4px del tick · anchor físico |
| `chart-legend` | **Correcto.** No renderiza nada — es un config child; el marcado lo pinta el frame con flex lógico, y §6.14 ya midió que `legendDir` voltea |
| `metrics` | **CSS correcto**: `icon-start` va al borde derecho en RTL y la sparkline espeja (`M0,31` → `M304,31`). Problema de VOCABULARIO |
| `bar-segment` | Layout, leyenda y tooltip correctos. **Defecto real en la animación de entrada** |
| `metrics`| **CSS correcto**: `icon-start` va al borde derecho en RTL y la sparkline espeja (`M0,31` → `M304,31`). Problema de VOCABULARIO |
| `bar-segment`| Layout, leyenda y tooltip correctos. **Defecto real en la animación de entrada** |
**El defecto no era de `bar-segment`, era del preset `grow-x`**, que clavaba
`transform-origin: 0% 50%` — el borde FÍSICO izquierdo. En RTL la barra se
@ -977,13 +980,13 @@ eidos, y sólo había corrido los tests del ámbito. La pasada COMPLETA da
`eidos/lint`, `orca`. Verificado que **ninguno es mío**, cruzando los ficheros
que señalan contra `git diff --name-only 40db0b981..HEAD`:
| guard | señala | dueño |
| --- | --- | --- |
| `eidos/lint` | `audio-player: no morfo` | hilo del sonido (ya en §6.5) |