- Imagen principal del producto pasa de object-cover a object-contain
(mismo motivo que las miniaturas del commit anterior): la foto
vertical de Buzz Lightyear (933x1500) aparecía sin cabeza al
seleccionarla, reportado en vivo con captura real.
- Descripción del producto baja de 16px a 14px (text-sm leading-6,
mismo tamaño que los párrafos secundarios de /envios y /cambios) --
seguía viéndose grande al lado del resto de la columna.
- El buy-box mostraba los mismos 2 productos que ya aparecían en el
carrusel "También te puede gustar" de abajo (ambos usaban el mismo
cálculo de categoría/colección). Ahora el buy-box sugiere 1 producto
de una categoría DISTINTA -- cross-sell real en vez de duplicado.
Co-Authored-By: Claude Sonnet 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_012Y4df3Z7odr9Cg8F2nw6uV
- Miniaturas pasan de object-cover a object-contain: fotos con
relación de aspecto muy vertical (confirmado en vivo: 933x1500 en
este catálogo) perdían cabeza o pies al forzar el recorte cuadrado.
Reportado por el usuario viendo las miniaturas de un producto real.
- La descripción del producto bajaba de 18px (text-lg, mismo tamaño
que un párrafo de apertura de página completa como /envios) a 16px
(text-base) -- se veía desproporcionada al lado del resto de la
columna de compra en el layout de 3 columnas.
Co-Authored-By: Claude Sonnet 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_012Y4df3Z7odr9Cg8F2nw6uV
Root cause real del bug reportado por el usuario (imagen de producto
viéndose gigante/cortada en Chrome y Edge Android) -- no era la imagen:
al mover "También te puede gustar" DENTRO del grid de la página (para
el layout de 2 filas del commit anterior), su carrusel horizontal
(overflow-x-auto interno, sin flex-wrap) empezó a contar como item de
ese grid. Sin min-w-0, el ancho mínimo intrínseco de TODAS las cards
del carrusel sin wrappear se usa para dimensionar la columna
compartida del grid -- en mobile (grid de una sola columna), eso
empujaba TODO (imagen, título, specs) a ~800px de ancho en un viewport
real de ~380px. El navegador termina "zoomeando" el layout para que
entre, dando la sensación de que todo se ve a tamaño real / cortado.
Confirmado en vivo con bisección real: sin el fix, el grid medía 783px
en un viewport de 380px; agregando min-w-0 al contenedor del carrusel
vuelve a 380px. Se agrega min-w-0 también a los otros 3 contenedores
del grid (galería, info, buy-box) y a la tira de miniaturas dentro de
ProductGallery (mismo patrón de overflow-x-auto) como defensa
preventiva -- práctica estándar para items de grid/flex con scroll
horizontal interno.
Co-Authored-By: Claude Sonnet 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_012Y4df3Z7odr9Cg8F2nw6uV
Reportado en vivo por el usuario: la foto principal (y el modal de
zoom interactivo) se ven borrosas en mobile, especificamente en
Chrome y Edge de Android.
Investigado a fondo antes de tocar nada: no es un archivo corrupto ni
un problema de nuestro cache/backend -- confirmado con
fetch()+createImageBitmap() (que evita <img>/srcset por completo) que
el archivo real decodifica perfecto a resolución completa (1200x1200).
El bug está en cómo Chromium elige el candidato del srcset con
sizes="100vw" + fill a DPR alto (2.6+, cualquier Android real):
currentSrc reporta la URL de un candidato grande, pero
naturalWidth/Height terminan reflejando un candidato mucho más chico
-- reproducido igual en Chromium headless, y consistente con lo
reportado en Chrome y Edge Android reales (mismo motor).
No hay forma de arreglar el algoritmo de selección de Chromium desde
acá. La foto principal y el modal de zoom pasan a unoptimized: al
quedar un solo recurso real por foto (sin candidatos de por medio),
no hay entre qué elegir mal. Costo: la foto pesa el archivo completo
en vez de una versión redimensionada -- aceptable para dos imágenes
puntuales donde la nitidez importa.
Co-Authored-By: Claude Sonnet 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_012Y4df3Z7odr9Cg8F2nw6uV
- El panel de zoom lateral ahora calcula tamaño/posición contra el
viewport real (window.innerWidth/innerHeight) en cada mousemove, en
vez de un breakpoint fijo (lg:block) con ancho fijo -- a resoluciones
altas con poco espacio a la derecha de la imagen terminaba
saliéndose de la pantalla. Si no entra un panel de al menos
PANEL_MIN_SIZE, se cae automáticamente al overlay in-place (antes
atado a "por debajo de lg", ahora a "no hay espacio real").
- La barra fija de "Añadir al carrito" en mobile quedaba fija desde el
primer render, tapando permanentemente parte de la imagen del
producto. Ahora el botón real (ProductPurchase) también se muestra
en mobile, y la barra sticky solo aparece cuando ese botón sale del
viewport (IntersectionObserver) -- mismo patrón que el "Buy Now"
sticky de Amazon.
Co-Authored-By: Claude Sonnet 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_012Y4df3Z7odr9Cg8F2nw6uV
Sin cambio de comportamiento -- solo hooks estables para la suite de
Playwright en .browser-scratch/checks.mjs (el selector genérico
div[aria-hidden] dejó de alcanzar para distinguir la lupa, el overlay
in-place y el panel lateral, que ahora coexisten en el DOM).
Co-Authored-By: Claude Sonnet 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_012Y4df3Z7odr9Cg8F2nw6uV
El zoom in-place anterior (overlay de fondo dentro de la misma caja)
seguía sintiéndose confuso: el usuario esperaba el patrón clásico de
e-commerce (Amazon) -- un recuadro semitransparente ("lupa") que marca
qué región de la foto se está mirando, y un panel aparte, más grande,
que muestra esa región ampliada. Sin scroll ni superposición dentro de
la misma caja.
- Lupa: recuadro que sigue al cursor sobre la imagen principal,
clampeado para no salirse de los bordes (visible en lg+).
- bgX/bgY ahora se calculan por fracción de recorrido de la lupa
(posición del borde de la lupa entre 0 y el ancho disponible), no por
posición cruda del cursor -- mapeo correcto incluso cuando la lupa
queda pegada a un borde.
- Panel: a la derecha de la imagen (position absolute, se superpone al
contenido de al lado igual que en Amazon), mismo mecanismo de
background-image con la foto completa que ya evitaba el problema de
object-cover recortando partes de la imagen.
- Por debajo de lg (sin espacio para un panel aparte) se conserva el
overlay in-place como fallback.
Co-Authored-By: Claude Sonnet 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_012Y4df3Z7odr9Cg8F2nw6uV
El hover-zoom escalaba (transform:scale) la misma <Image> ya recortada
por object-cover -- para fotos verticales (ej. figura de acción de pie)
eso dejaba partes del producto (la cabeza) fuera del recorte desde el
propio render, así que ningún nivel de zoom las mostraba. Se reemplaza
por un overlay con background-image usando la foto completa
(background-size en un solo valor preserva el aspect ratio real) y
background-position siguiendo el cursor, que sí permite recorrer toda
la imagen.
De paso: las miniaturas ahora cambian la imagen principal también con
hover (onMouseEnter), no solo con click.
Co-Authored-By: Claude Sonnet 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_012Y4df3Z7odr9Cg8F2nw6uV
Antes el único zoom era el modal interactivo (click -> Dialog con scale/
drag). Ahora la imagen principal también hace zoom estilo lupa (2.2x)
que sigue la posición del cursor con mousemove/transform-origin, sin
tocar el modal existente (sigue abriéndose igual con el click).
Solo mouse -- mousemove no dispara de forma continua en touch, así que
en mobile simplemente no aparece el efecto, sin romper nada ahí.
Verificado: tsc --noEmit limpio, página de producto renderiza 200 con
datos mock y el nuevo markup presente. No se pudo verificar visualmente
el hover en un navegador real (sin chromium-cli ni claude-in-chrome
disponibles en este shell headless).
Co-Authored-By: Claude Sonnet 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01THZFwPzrwv6VAbuwmaf5vR