Se commitea PARA CONSERVARLA: esta versión se borra y se rehace. El autor la
valoró como duplicación, y la medición le da la razón. Queda aquí para que la
segunda no repita sus errores.
Qué hay:
- `eidos/components/skin-media-player/` — cuatro objetos dibujados (disco,
giradiscos, casete, pletina) sobre el morfo `media-player`. El aparato anida
su soporte como `<svg>` interior, así que la pintura del soporte se reutiliza.
- La afordancia es un `<button>` HTML superpuesto, colocado en % del viewBox, y
NO un `role="button"` sobre un `<g>` como en los bocetos. Precedente:
`onion-menu` («a real HTML button overlaid at the SVG centre… which an SVG
element can't do») y el knob de `natural-time-picker`.
- Transporte compuesto sobre las partes reales: MARCHA/REPROD sólo arrancan y
PAUSA sólo pausa, anulando el toggle de soma con `preventDefault()` en la
costura (patrón de `RateFloat`). PARO/STOP no existe en el contrato y se
compone `togglePlay()` + `seek(0)`.
- `engaged()` — `started` se enciende con la primera reproducción y no se apaga
nunca, así que por sí solo dejaba el brazo apoyado sobre un disco parado. Con
`started && !ended && (currentTime > 0 || !paused)` salen los tres estados de
una máquina: parada, sonando, en pausa.
- Geometría portada del boceto: brazo por cinemática inversa de forma cerrada
(r² = K + A·cosθ + B·senθ) y bobinas por conservación de área
(R_izq² + R_der² constante), de donde sale sola la velocidad correcta de cada
bobina. El contador de cinta lee el medio en vez de un `setInterval` propio.
- Los 83 colores del autor se conservan intactos: `skin-media-player` entra en
`FIXED_TONE_COMPONENTS` — la excepción que el guard ya reserva para los
componentes que DIBUJAN un objeto físico (`natural-time-picker`,
`color-picker`, `proof-of-human`). Acotada a esta carpeta a propósito: dentro
de `media-player/` habría eximido al recipe del player real.
- `web/routes/otros/players/` — los cuatro bocetos originales del autor (estado
simulado, sin audio) y el banco de verificación.
Por qué se rehace, medido:
1. DUPLICACIÓN. `fit()` idéntico en record y cassette; `hold()` y `stop()`
idénticos en turntable y deck; `MediaPlayerProvider.require()` + `engaged()`
en los cuatro. Son cuatro componentes que comparten carpeta, no un skin: cada
cuerpo se agarra al provider por su cuenta y recablea las mismas costuras. Lo
correcto es al revés — un componente que recibe el player y resuelve las
acciones, y a cada aparato sólo su pintura y su mapa de mandos.
2. MOTION A MANO. Tres `@keyframes` locales y siete transiciones con números
crudos, existiendo el motor: `smp-turn` ES el preset `spin` (`loop-spin`,
periodo por `--motion-loop-spin`) y `smp-tape-pulse` ES `pulse`; las
transiciones debían salir de `--duration-*` / `--ease-*`. Y un defecto
funcional: el generador apaga los loops por `[data-motion='reduce']` Y por la
media query; mi bloque a mano sólo tenía la segunda, así que la preferencia
UIX en `reduce` sin ajuste del SO no paraba el plato.
3. La raíz `skin-media-player.svelte` empaqueta `Media + Skin + barra` por
dentro, así que la forma del reproductor (inline/bar/row/card, que es el eje
de `AudioPlayer`) no se podía elegir y el MediaPlayer no se veía por ningún
lado en la demo.
Verificado antes de commitear: `npm run check` sin errores nuevos (la base del
repo, 72, no se mueve) · guards de eidos 49/49 · `rtl:check` 0/179 · en
navegador con audio real, transporte, brazo siguiendo el surco, bobinas por
área y contador de cinta.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>