/* ============================================================
   PROTOTIPOS — el catálogo con pedido
   ------------------------------------------------------------
   Solo lo usa prototipos.html, pintado por js/prototipos.js.
   Va aparte de estilo.css para no engordar la hoja que cargan
   todas las páginas.

   Sigue las mismas reglas del resto del sitio: cero curvas,
   filete de 1px, y todos los colores por token para que el modo
   claro salga solo sin escribir una regla más.
   ============================================================ */

/* Aire a la mitad, igual que en estilo.css: se quejó del hueco
   entre la cabecera, el título y la lista. */
.pt-seccion { margin-top: clamp(1.3rem, 3vw, 2.2rem); }
.pt-cabeza { display: flex; align-items: baseline; gap: .9rem; flex-wrap: wrap; margin-bottom: .35rem; }
.pt-cabeza h2 { font-size: clamp(1.12rem, 2.4vw, 1.4rem); }
.pt-cuenta { color: var(--apagado); font-size: 0.875rem; }
.pt-bajada { color: var(--apagado); font-size: 1rem; max-width: 62ch; margin-bottom: .75rem; }

/* --- ficha del catálogo (va dentro de .rejilla, la pegada) --- */
.pt-ficha {
  background: var(--caja); display: flex; flex-direction: column;
  text-align: left; border: 0; padding: 0; color: inherit;
  cursor: pointer; font: inherit;
  transition: background .18s var(--curva-suave);
}
.pt-ficha:hover { background: var(--caja-alta); }
/* La tarjeta necesita ser el marco de referencia para que el
   ::after del botón se estire sobre ella. */
.pt-ficha { position: relative; }

/* EL BOTÓN QUE ABRE LA PIEZA (15/08/2026).
   Va dentro del <h3> y no se ve como botón: hereda la letra del
   título y no lleva ni fondo ni borde. Su ::after se estira sobre
   la tarjeta entera, así que sigue abriéndose pulsando donde sea
   —igual que cuando la tarjeta era un role="button"— pero ahora
   el nombre que anuncia un lector de pantalla es solo el de la
   pieza, y las flechas vuelven a ser botones de verdad.
   El foco se dibuja sobre TODA la tarjeta, no sobre las palabras
   del título, que es donde se espera verlo. */
.pt-ficha__abrir {
  font: inherit; color: inherit; text-align: left;
  background: none; border: 0; padding: 0; margin: 0;
  cursor: pointer;
}
.pt-ficha__abrir::after {
  content: ""; position: absolute; inset: 0;
  /* Por debajo de las flechas y del contador, que llevan z-index:2 */
  z-index: 1;
}
.pt-ficha__abrir:focus-visible { outline: none; }
.pt-ficha:has(.pt-ficha__abrir:focus-visible) {
  outline: 2px solid var(--realce); outline-offset: -2px;
}
/* Respaldo para navegadores sin :has() — ahí el foco se dibuja
   alrededor del título en vez de la tarjeta, que se ve peor pero
   NO deja a nadie sin saber dónde está. */
@supports not selector(:has(*)) {
  .pt-ficha__abrir:focus-visible { outline: 2px solid var(--realce); outline-offset: 2px; }
}
.pt-ficha__hueco {
  aspect-ratio: 4 / 3; border-bottom: 1px solid var(--linea);
  display: grid; place-items: center;
  color: var(--apagado);
  font-size: 0.75rem; letter-spacing: .16em; text-transform: uppercase;
  /* --rayado-hueco y no --rayado: el normal se hace de --papel y
     --caja, que en el tema claro son blanco y casi blanco, y el
     hueco quedaba lavado. Este lleva los grises de contraste. */
  background: var(--rayado-hueco);
  overflow: hidden;
}
/* OJO: el atenuado va SOLO en el recuadro vacío. Estuvo un rato en
   .pt-ficha__hueco a secas y, como opacity afecta a los hijos, la
   foto real salía al 50% de brillo.
   Subió de .5 a .85: con el rayado más oscuro, medio atenuado se
   volvía a perder justo lo que se quería ganar. */
.pt-ficha__hueco:not(.pt-ficha__hueco--foto) { opacity: .85; }
.pt-ficha__hueco--foto { padding: 0; }
.pt-ficha__hueco img {
  width: 100%; height: 100%; object-fit: cover; display: block;
  transition: transform .5s var(--curva);
}
/* Las piezas recortadas sin fondo se ven ENTERAS y sobre fondo
   LISO del color del tema — negro en oscuro, blanco en claro.
   Nada de rayado detrás: para eso se recortaron. Con `cover` se
   les cortarían las esquinas, que en un catálogo se lee como un
   descuido, así que van con `contain` y su aire alrededor. */
.pt-ficha__hueco--suelto { background: var(--papel); }
/* Mismo cuidado que en el panel: con width/height al 100% la
   imagen desborda una caja cuyo alto sale de `aspect-ratio`. */
/* Mismo criterio que en el panel: el aire lo pone el contenedor y
   la imagen se estira a él. Ver el comentario largo de
   .pt-visual__foto--suelto: ni `max-height:100%` ni `inset`
   funcionan aquí. */
.pt-ficha__hueco--suelto { padding: .55rem; }
.pt-ficha__hueco--suelto img {
  width: 100%; height: 100%;
  object-fit: contain; padding: 0;
}
/* SIN ZOOM AL PASAR EL RATÓN (él, 06/09/2026). Iba a `scale(1.04)`
   y se notaba sobre todo en los isométricos, donde agrandar recorta
   las cotas de los bordes. Es la misma decisión que ya se tomó en
   Exhibición el 14/08/2026 — ver el comentario de .tarjeta__marco en
   estilo.css. La transición se deja puesta por si vuelve. */
.pt-ficha:hover .pt-ficha__hueco img { transform: none; }


/* --- flechas del carrusel de la ficha -----------------------
   Van dentro del recuadro de la imagen, pegadas a los lados.
   Aparecen al acercarse; en pantalla táctil (donde no hay hover)
   se quedan siempre visibles, si no serían inalcanzables. */
.pt-ficha__hueco { position: relative; }
.pt-flecha {
  position: absolute; top: 50%; transform: translateY(-50%);
  width: 30px; height: 44px; z-index: 2;
  display: grid; place-items: center;
  border: 0; padding: 0; cursor: pointer;
  font: inherit; font-size: 1.35rem; line-height: 1;
  background: color-mix(in srgb, var(--papel) 72%, transparent);
  color: var(--tinta);
  backdrop-filter: blur(4px);
  opacity: 0; transition: opacity .15s var(--curva-suave), background .15s;
}
.pt-flecha--izq { left: 0; }
.pt-flecha--der { right: 0; }
.pt-ficha:hover .pt-flecha,
.pt-flecha:focus-visible { opacity: 1; }
.pt-flecha:hover { background: var(--papel); }
@media (hover: none) { .pt-flecha { opacity: .85; } }
/* 2026-08-17 · En teléfono medían 30px de ancho y encima están
   pegadas al borde de la tarjeta, que es justo donde el pulgar
   llega peor. A 44 caben de sobra: la tarjeta mide 335. */
@media (max-width: 780px) { .pt-flecha { width: 44px; } }

/* ============================================================
   EL PISO DE LETRA CHICA EN TELÉFONO · 2026-08-17

   Medido a 375px: en esta página había 25 textos a 12px en 11
   papeles distintos. El nivel «letra chica» se había convertido
   en el cajón de sastre, y dentro estaba información con la que
   alguien decide una compra: la tasa del BCV, los datos de la
   cuenta, cuántas unidades quedan.

   Prototipos es la única página donde el visitante mueve dinero.
   Ahí el texto que informa la decisión sube a 14px; los 12px se
   quedan solo para lo accesorio (el contador de fotos, el
   «Desde» que antecede al precio, las versalitas de opción).
   ============================================================ */
@media (max-width: 780px) {
  /* El encabezado de sección («Listas ahora», «Por encargo») tenía
     su propia escala y caía en 17,9px, mientras los nombres de
     pieza que van DEBAJO son h3 de 17px en negrita: la sección se
     veía menos importante que sus propios artículos. Igualado al
     resto de encabezados de sección del sitio, 21,8px, que deja un
     salto limpio de 1,28 hasta los nombres. */
  .pt-cabeza h2 { font-size: 1.36rem; }

  /* Cuántas quedan y en cuánto tiempo llega: eso decide la compra. */
  .pt-estado { font-size: 0.8125rem; letter-spacing: .08em; }
  /* Los datos de la cuenta para pagar. */
  .pt-nota   { font-size: 0.875rem; }
  /* La tasa del día. Sube de tamaño y se le suelta la interlínea:
     iba en 1,3, que para dos renglones de cifras queda apretado. */
  .pt-tasa   { font-size: 0.8125rem; line-height: 1.45; }
  /* El equivalente en bolívares de cada línea del pedido. */
  .pt-gris   { font-size: 0.8125rem; }

  /* El total en bolívares se pintaba a 25,9px: era el texto más
     grande de la página, por encima del propio título de 28. Un
     subtotal no puede gritar más que el nombre de la página. */
  .pt-fila--grande .n { font-size: 1.35rem; }
}

/* El contador de fotos, abajo a la derecha del recuadro. */
.pt-cuenta-fotos {
  position: absolute; right: .4rem; bottom: .4rem; z-index: 2;
  font-size: 0.75rem; letter-spacing: .08em;
  padding: .12rem .34rem;
  background: color-mix(in srgb, var(--papel) 72%, transparent);
  color: var(--apagado);
  pointer-events: none;
}
/* Más compacto: relleno de 1rem a .8rem y el resumen más chico. */
.pt-ficha__cuerpo { padding: .8rem .8rem .9rem; display: flex; flex-direction: column; gap: .35rem; flex: 1; }
.pt-ficha h3 { font-size: 1.0625rem; }
.pt-ficha__res { font-size: 0.875rem; color: var(--apagado); line-height: 1.4; flex: 1; }
.pt-ficha__pie { display: flex; align-items: baseline; justify-content: space-between; gap: .6rem; margin-top: .25rem; }
.pt-precio { font-size: 1.25rem; font-weight: 700; white-space: nowrap; }
.pt-desde { font-size: 0.75rem; font-weight: 400; color: var(--apagado); margin-right: .3rem; }

.pt-estado {
  font-size: 0.75rem; letter-spacing: .13em; text-transform: uppercase;
  padding: .2rem .45rem; border: 1px solid var(--linea); color: var(--apagado);
  white-space: nowrap;
}
.pt-estado--hay    { color: var(--tinta);  border-color: var(--apagado); }
.pt-estado--poco   { color: var(--realce); border-color: var(--realce); }
.pt-estado--pedido { color: var(--madera-texto); border-color: var(--madera-texto); }

/* --- panel lateral de configuración ------------------------- */
.pt-velo { position: fixed; inset: 0; background: rgba(0,0,0,.75); display: none; z-index: 100; }
.pt-velo.abierto { display: block; }
:root[data-tema="claro"] .pt-velo { background: rgba(0,0,0,.42); }

/* 2026-08-11 · El panel se ensanchó de 460 a 880 para que quepa la
   visual a la izquierda de las opciones. Sigue siendo un panel
   lateral, no una página: él dijo expresamente que le gusta no
   tener que salir de la lista. */
.pt-panel {
  position: fixed; top: 0; right: 0; bottom: 0; width: min(880px, 100%);
  background: var(--papel); border-left: 1px solid var(--linea);
  z-index: 101; display: none; flex-direction: column;
  transform: translateX(100%); transition: transform .28s var(--curva);
}
.pt-panel.abierto { display: flex; transform: translateX(0); }
.pt-panel__cab { padding: 1.25rem 1.5rem; border-bottom: 1px solid var(--linea); display: flex; align-items: flex-start; gap: 1rem; }
.pt-panel__cab h3 { font-size: 1.25rem; flex: 1; }
.pt-cerrar { font: inherit; font-size: 1.5rem; line-height: 1; color: var(--apagado); background: none; border: 0; cursor: pointer; padding: 0 .1rem; }
.pt-cerrar:hover { color: var(--realce); }
/* Dos columnas: la visual manda a la izquierda, lo que se
   configura a la derecha. Por debajo de 760 se apilan y la visual
   queda arriba, que es el orden natural al leer. */
.pt-panel__cuerpo {
  padding: 1.5rem; overflow-y: auto; flex: 1;
  display: grid; grid-template-columns: 1fr 300px; gap: 1.5rem;
  align-items: start;
}
@media (max-width: 760px) {
  .pt-panel__cuerpo { grid-template-columns: 1fr; gap: 1.1rem; }
}
.pt-panel__visual { position: sticky; top: 0; }
/* 2026-08-17 · EN TELÉFONO NO SE PEGA, y esto es un fallo que se vio
   en uso: al deslizar, la imagen y las miniaturas se quedaban
   clavadas arriba y la descripción de la pieza les pasaba POR
   DEBAJO. Medido: 332 px de solape con el panel desplazado 350.

   En escritorio pegarla está bien —es la columna izquierda y la de
   opciones es mucho más larga, así que la pieza te acompaña mientras
   eliges—. Apiladas, en cambio, la imagen va ARRIBA de las opciones y
   pegarla solo sirve para tapar lo que vienes a leer.

   Va detrás de la regla de arriba y no dentro del @media de 760 que
   hay unas líneas antes: ese bloque está ANTES en el archivo y con la
   misma especificidad perdería. */
@media (max-width: 760px) {
  .pt-panel__visual { position: static; }
}

/* El recuadro de la visual. Cuando no hay modelo, se queda con el
   mismo rayado de las fichas para que el hueco no parezca un
   error de carga. */
/* El recuadro es CUADRADO siempre, mire lo que mire (él,
   08/09/2026): el panel dejaba de saltar de alto al pasar de una
   foto al plano o al 3D.

   HISTORIA, para no dar la vuelta otra vez. En agosto era 1:1 fijo
   y la foto iba con `cover`: al recortar para llenar el cuadrado se
   comía la base de la pieza, así que la foto pasó a 4:3. Volver a
   1:1 con `cover` repetiría ese fallo —y peor que antes, porque hoy
   hay fotos de 705×426 y de 562×870 en la misma tira—, así que el
   cuadrado viene acompañado de `contain` en .pt-visual__foto: la
   caja no se mueve Y la foto se ve entera. El aire que sobra es
   fondo liso, no recorte.

   Ya no hace falta ninguna excepción por tipo de medio: foto,
   vídeo, plano y 3D comparten el mismo cuadrado. `data-medio`
   sigue puesto por js/prototipos.js y sirve para el fondo. */
.pt-visual {
  aspect-ratio: 1 / 1; border: 1px solid var(--linea);
  background: var(--rayado);
  display: grid; place-items: center; position: relative;
  overflow: hidden;
  transition: aspect-ratio .25s var(--curva);
}
/* Detrás de una foto encajada, fondo LISO. Con el rayado asomando
   por las franjas de arriba y abajo parecía una imagen a medio
   cargar. Es el mismo criterio que ya seguían las piezas
   recortadas (data-suelto). El rayado se queda para el hueco
   vacío, que es lo que de verdad quiere decir "aquí no hay nada". */
.pt-visual[data-medio="foto"] { background: var(--papel); }
/* Aquí había tres reglas más —video, 3d y plano-img— que repetían
   `aspect-ratio: 1 / 1`. Desde que el cuadrado es la base y no la
   excepción, sobran. Lo que decían y sigue valiendo:
   · los vídeos del taller se graban con el teléfono y salen
     VERTICALES; en un recuadro apaisado un vídeo de 608×1081 se
     salía por abajo, y recortarlo dejaba una franja del centro.
   · el plano es una imagen muy alta: darle su proporción estiraría
     el panel entero. */
.pt-visual__lienzo { position: absolute; inset: 0; display: grid; place-items: center; }
.pt-visual .visor3d { width: 100%; height: 100%; border: 0; background: transparent; }
/* `contain` y no `cover`: en un recuadro cuadrado, `cover` recorta
   —los lados de una foto apaisada, y la cabeza y la BASE de una
   vertical—. Ver el comentario de .pt-visual arriba. La foto entra
   entera y lo que sobra es fondo.

   `position:absolute; inset:0` NO es adorno, y quitarlo rompe esto
   en silencio. Con `width/height:100%` a secas el alto no resuelve
   —el del padre sale de `aspect-ratio` y para un porcentaje eso
   cuenta como indefinido, la misma trampa de .pt-visual__foto--suelto
   unas líneas más abajo—, así que la imagen se dimensionaba solo por
   el ancho: tumbona-6 (1400×1860) salía de 490×651 dentro de una caja
   de 492×492 y se comía 159 px POR ABAJO, escondidos por el
   `overflow:hidden` del recuadro. Y `object-fit` no lo salvaba: si la
   caja del <img> ya tiene la proporción de la foto, no hay nada que
   encajar. Con los insets el elemento mide 492×492 de verdad y ahí
   sí `contain` hace su trabajo.
   Es la misma receta que ya usaba video.pt-visual__foto aquí debajo. */
.pt-visual__foto {
  position: absolute; inset: 0;
  width: 100%; height: 100%; object-fit: contain; display: block;
}

/* El vídeo, ENTERO y encajado en el recuadro. `position:absolute`
   porque con `height: 100%` a secas dentro del lienzo en grid no
   resolvía y tomaba su alto natural; y `contain` en vez de
   `cover` porque recortar un vídeo vertical deja solo una franja
   del centro. */
video.pt-visual__foto {
  position: absolute; inset: 0;
  object-fit: contain;
  background: #000;
}
/* El plano va sobre fondo liso, como las piezas recortadas: un
   dibujo de cotas sobre rayado no se lee. */
.pt-plano { width: 100%; padding: 1rem; box-sizing: border-box; }

/* --- plano hecho aparte, como imagen -------------------------
   Viene en NEGRO sobre fondo transparente, que es lo que sirve
   para el modo claro. En oscuro se invierte y queda blanco.

   Se invierte por CSS en vez de tener dos archivos a proposito:
   asi solo hay UN plano que mantener. Con dos imagenes, el dia
   que se regenera una y se olvida la otra, los dos modos dejan
   de coincidir y nadie se entera hasta que un cliente lo ve.

   `invert(1)` no toca el canal alfa, asi que el fondo sigue
   transparente en los dos modos. Y como el plano es negro puro
   sobre transparente, el invertido es EXACTAMENTE la version en
   blanco. */
/* El plano es MUY alto (976x1300) y el recuadro es cuadrado. Se
   encoge hasta caber ENTERO, dejando aire a los lados — que es lo
   que él pidió: no estirar el recuadro hacia abajo, sino meter el
   dibujo dentro del que ya hay.

   `position:absolute; inset:0` y no `width/height:100%` a secas:
   dentro del grid centrado, la imagen se quedaba en su tamaño
   natural y el `overflow:hidden` del recuadro le cortaba la parte
   de abajo, justo donde van las cotas de 24 cm. */
/* El plano necesita el lienzo OCUPANDO TODO el recuadro. Va
   marcado como "suelto" —para ir sobre fondo liso y no sobre el
   rayado, que se come un dibujo de cotas—, y esa marca vuelve el
   lienzo `position: relative`, pensada para fotos recortadas que
   se muestran a su tamaño. Con el lienzo en relative colapsaba a
   la altura del contenido (35 px) y la imagen, que va absoluta,
   se encogía con él: el plano no se veía. */
.pt-visual[data-suelto="1"][data-medio="plano-img"] .pt-visual__lienzo {
  position: absolute; inset: 0; padding: 0;
}
.pt-visual__plano {
  position: absolute; inset: 0;
  display: block;
  width: 100%; height: 100%;
  object-fit: contain;
  /* holgura para que las cifras no toquen el borde */
  padding: .9rem 1rem; box-sizing: border-box;
}
/* 06/09/2026 · La inversión vale SOLO PARA EL SVG. Desde hoy este
   mismo hueco sirve también para la imagen isométrica con cotas, que
   es un render en color sobre fondo negro: invertirla la dejaba con
   la madera azul y el fondo blanco. El plano de líneas sí la
   necesita, porque va dibujado en negro sobre transparente.
   El selector mira la extensión del `src`; cuando el SVG ya está
   incrustado en línea es un <svg>, no un <img>, y entra por la
   segunda mitad. */
:root:not([data-tema="claro"]) img.pt-visual__plano[src$=".svg"],
:root:not([data-tema="claro"]) svg.pt-visual__plano { filter: invert(1); }
/* El plano entero se invierte en oscuro, y eso volvería AZUL el naranja
   quemado que señala el agujero en uso. Invertirlo otra vez a él lo deja
   igual en los dos temas: dos inversiones se anulan.
   Solo funciona con el SVG metido en la página; por <img> el CSS no entra
   ahí y en oscuro sí saldría azul — pero ese camino es solo para abrir el
   HTML con doble clic. Ver incrustarPlano() en js/prototipos.js. */
:root:not([data-tema="claro"]) .pt-visual__plano .pt-plano__acento { filter: invert(1); }

/* La pieza recortada se ve ENTERA, sin que le falte nada.
   OJO CON EL TAMAÑO: aquí había `width:100%; height:100%` y la
   imagen salía de 518 px de alto dentro de una caja de 369, o sea
   recortada 150 px por abajo. El motivo es que el alto de
   .pt-visual viene de `aspect-ratio`, y contra eso un `height:100%`
   no resuelve: la imagen se dimensionaba solo por el ancho.
   Con max-width/max-height sí encaja siempre. */
/* El aire va en el CONTENEDOR, no en la imagen, y la imagen se
   estira a ese contenedor con object-fit haciendo el encaje.

   Se probaron dos caminos que NO funcionan y conviene no repetir:
   · `max-height: 100%` — no resuelve, porque el alto de
     .pt-visual sale de `aspect-ratio` y para los porcentajes eso
     cuenta como indefinido. La imagen salía 518 px en una caja de
     369 y se recortaban 150 px por abajo.
   · `position:absolute; inset:1.1rem` sobre la propia imagen —
     una imagen es un elemento REEMPLAZADO: con `width:auto` usa
     su tamaño intrínseco y se salta los insets. */
/* Aquí manda la IMAGEN y la caja se adapta a ella, al revés que
   en el resto del panel. Es la única forma que funciona: mientras
   .pt-visual tenga altura de `aspect-ratio`, ningún `height:100%`
   ni `max-height:100%` del hijo resuelve contra ella, y la imagen
   se dimensiona solo por el ancho y desborda por abajo. Se probó
   también `inset` sobre la imagen: no vale, un <img> es elemento
   reemplazado y con `width:auto` usa su tamaño intrínseco.
   Quitando el aspect-ratio y sacando el lienzo del posicionamiento
   absoluto, el alto lo pone el contenido y se ve entera. */
.pt-visual[data-suelto="1"] { aspect-ratio: auto; }
.pt-visual[data-suelto="1"] .pt-visual__lienzo {
  position: relative; inset: auto;
  width: 100%; padding: 1.1rem;
}
.pt-visual__foto--suelto {
  width: 100%; height: auto;
  /* Tope para que una foto muy vertical no empuje el panel entero. */
  max-height: 58vh;
  object-fit: contain; padding: 0;
}
/* Y la caja se hace cuadrada: las piezas recortadas vienen unas
   apaisadas y otras verticales, y el cuadrado le da sitio a las
   dos sin dejar un hueco enorme. */
.pt-visual[data-suelto="1"] { aspect-ratio: 1 / 1; }
/* Mismo criterio que en la cuadrícula: si la pieza viene
   recortada, detrás va el color del tema y no el rayado. Lo pone
   js/prototipos.js en data-suelto al montar el medio. */
.pt-visual[data-suelto="1"] { background: var(--papel); }
.pt-visual__vacio {
  color: var(--apagado); opacity: .5;
  font-size: 0.75rem; letter-spacing: .16em; text-transform: uppercase;
}

/* --- riel de miniaturas ------------------------------------
   2026-08-17 · CAMBIO SUYO. Antes flotaban ARRIBA A LA IZQUIERDA
   ENCIMA del lienzo, en columna y de 42px: tapaban justo la esquina
   de la pieza y eran demasiado chicas para ver qué había dentro.

   Ahora van DEBAJO del recuadro, en cuadrícula horizontal y más
   grandes. El cambio de sitio no es solo CSS: en index.html el
   bloque tuvo que salir de dentro de .pt-visual, que lleva
   aspect-ratio y position:relative y no deja colocar nada debajo.

   `auto-fill` con mínimo de 76px y no un número fijo de columnas:
   una pieza puede tener dos medios o siete, y así la fila se llena
   sola y las que sobran bajan al renglón siguiente. */
.pt-medios {
  display: grid; gap: .4rem; margin-top: .5rem;
  grid-template-columns: repeat(auto-fill, minmax(76px, 1fr));
}
.pt-medio {
  width: auto; aspect-ratio: 1; padding: 0; cursor: pointer;
  border: 1px solid var(--linea);
  /* Ya no van encima de la foto, así que no hace falta el cristal
     esmerilado que las despegaba del fondo: color liso y basta. */
  background-color: var(--caja);
  display: grid; place-items: center; overflow: hidden;
  transition: border-color .15s, opacity .15s;
  opacity: .72;
}
.pt-medio:hover { opacity: 1; border-color: var(--apagado); }
.pt-medio.sel  { opacity: 1; border-color: var(--tinta); }
.pt-medio img { width: 100%; height: 100%; object-fit: cover; display: block; }

/* La miniatura del PLANO enseña el dibujo, no la palabra (él,
   14/08/2026). Va con `contain` y no `cover` —recortado no se
   entendería— y se invierte en oscuro igual que el grande, o
   sería una mancha negra sobre negro.

   07/09/2026 · La inversión vale SOLO PARA EL SVG, igual que arriba
   en .pt-visual__plano. Cuando el hueco del plano lo ocupa el
   isométrico —un render en color sobre fondo negro, `algo-iso.webp`—
   invertirlo lo dejaba con fondo blanco y la madera azul dentro del
   modo oscuro (comedero pequeño, gancho de pared). El SVG sí la
   necesita: va dibujado en negro sobre transparente. */
.pt-medio--plano img { object-fit: contain; padding: 3px; box-sizing: border-box; }
:root:not([data-tema="claro"]) .pt-medio--plano img[src$=".svg"] { filter: invert(1); }

/* El VÍDEO lleva el triángulo de reproducir, no la palabra. */
.pt-medio__play { font-size: 0.75rem; color: var(--tinta); line-height: 1; }

/* Solo queda con letras el 3D: un .glb no tiene nada que enseñar
   hasta que se carga. */
.pt-medio__glifo {
  font-size: 0.75rem; font-weight: 700; letter-spacing: .06em;
  color: var(--tinta); line-height: 1;
}
.pt-panel__pie { padding: 1.15rem 1.5rem; border-top: 1px solid var(--linea); }
.pt-panel__resumen { font-size: 0.875rem; color: var(--apagado); line-height: 1.55; margin-bottom: 1.6rem; }

/* Aviso de personalización, en todas las fichas. Va más apagado que el
   resumen —es una nota, no argumento de venta— pero el enlace sí destaca. */
.pt-personalizar {
  font-size: 0.8125rem; color: var(--apagado); line-height: 1.5;
  margin: -1rem 0 1.6rem; padding-top: .8rem;
  border-top: 1px solid var(--linea);
}
.pt-personalizar a { color: var(--realce); text-decoration: underline; }

.pt-grupo { margin-bottom: 1.6rem; }
.pt-etiqueta {
  display: block; font-size: 0.75rem; letter-spacing: .13em; text-transform: uppercase;
  color: var(--apagado); margin-bottom: .6rem;
}
.pt-ops { display: flex; flex-wrap: wrap; gap: .5rem; }
.pt-op {
  border: 1px solid var(--linea); background: none; padding: .55rem .85rem;
  font: inherit; font-size: 0.875rem; color: var(--apagado); cursor: pointer;
  transition: border-color .15s, color .15s, background .15s;
}
.pt-op:hover { border-color: var(--apagado); color: var(--tinta); }
.pt-op.sel { border-color: var(--tinta); color: var(--tinta); background: var(--caja-alta); }
.pt-d { font-size: 0.75rem; color: var(--apagado); margin-left: .35rem; }
.pt-op.sel .pt-d { color: var(--madera-texto); }
.pt-op:disabled { opacity: .32; cursor: not-allowed; text-decoration: line-through; }

/* SIN EXISTENCIAS PERO SE PUEDE PEDIR (06/09/2026).
   Ni tachado ni bloqueado: eso dice «no se puede», y sí se puede
   — se encarga. Solo se apaga un punto y lleva un círculo hueco en
   la esquina de arriba, que es la señal de «hay que fabricarla».
   El punto va en el borde, no dentro, para no empujar el texto. */
.pt-op--agotado { opacity: .62; position: relative; }
.pt-op--agotado::after {
  content: ""; position: absolute; top: -4px; right: -4px;
  width: 7px; height: 7px; border-radius: 50%;
  border: 1px solid var(--acento-texto); background: var(--papel);
}
.pt-op--agotado.sel { opacity: 1; }
.pt-op--agotado.sel::after { background: var(--acento-texto); }

.pt-contador { display: flex; align-items: center; border: 1px solid var(--linea); width: max-content; }
.pt-contador button {
  width: 38px; height: 38px; font: inherit; font-size: 1rem;
  background: none; border: 0; color: var(--apagado); cursor: pointer;
}
.pt-contador button:hover { color: var(--tinta); background: var(--caja-alta); }
.pt-contador span { width: 52px; text-align: center; font-size: 1rem; font-weight: 700; }
.pt-nota-pack { font-size: 0.875rem; color: var(--madera-texto); margin-top: .5rem; }
.pt-nota-stock { font-size: 0.875rem; color: var(--apagado); margin-top: .5rem; line-height: 1.45; }
/* Cuando se pide más de lo que hay hecho: el número y la nota
   pasan al acento. No es un error, es un aviso — por eso se usa el
   acento de marca y no el rojo de fallo. */
.pt-cant--sobre { color: var(--acento-texto); }
.pt-nota-sobre  { color: var(--acento-texto) !important; }

.pt-precio-panel { display: flex; align-items: baseline; justify-content: space-between; gap: .8rem; margin-bottom: .9rem; }
.pt-precio-panel .n { font-size: 1.25rem; font-weight: 700; }
.pt-precio-panel .bs { font-size: 1.25rem; color: var(--apagado); }

/* --- botones ------------------------------------------------ */
/* Sin rayado: sobre un botón el patrón se lee como "no funciona". */
.pt-btn {
  display: block; width: 100%; padding: .95rem; text-align: center;
  background-color: var(--tinta);
  color: var(--papel); font: inherit;
  font-weight: 700; font-size: 0.875rem; letter-spacing: .02em;
  border: 0; border-radius: 0; cursor: pointer;
  transition: background-color .15s, color .15s;
}
.pt-btn:hover { background-color: var(--madera); color: #000; }
.pt-btn:disabled { background-color: var(--linea); color: var(--apagado); cursor: not-allowed; }

/* Los dos botones de agregar, uno al lado del otro. El de seguir
   viendo va en versión de línea: hace lo mismo pero no es el
   camino principal, y dos botones macizos iguales no dicen cuál
   pulsar. En móvil se apilan, que a media pantalla no caben dos
   textos de este largo. */
.pt-acciones { display: grid; grid-template-columns: 1fr 1fr; gap: .5rem; }
@media (max-width: 520px) { .pt-acciones { grid-template-columns: 1fr; } }
.pt-btn--linea {
  background-color: transparent;
  color: var(--tinta);
  box-shadow: inset 0 0 0 1px var(--tinta);
}
.pt-btn--linea:hover { background-color: var(--tinta); color: var(--papel); }
.pt-btn--linea:disabled {
  background-color: transparent; color: var(--apagado);
  box-shadow: inset 0 0 0 1px var(--linea);
}
/* El botón de pedido va en el verde de WhatsApp, no en el acento
   del sitio: aquí el color es una señal de a dónde lleva.
   Los tres son de la paleta de WhatsApp. En reposo va #075E54,
   el verde oscuro: con texto blanco da 7,67:1. Se probó antes
   #128C7E y se queda en 4,14:1, por debajo del mínimo para texto
   normal — el botón lleva letra de 14px, que no cuenta como
   texto grande. El vivo #25D366 se reserva para el hover, con
   texto oscuro encima (8,54:1). */
.pt-btn--wa {
  background-color: #075E54; color: #fff;
  display: flex; align-items: center; justify-content: center; gap: .55rem;
}
.pt-btn--wa:hover { background-color: #25D366; color: #06281F; }
.pt-pedir__wa  { width: 19px; height: 19px; fill: currentColor; flex: none; }
.pt-pedir__ext {
  width: 13px; height: 13px; flex: none;
  fill: none; stroke: currentColor; stroke-width: 2.2;
  stroke-linecap: round; stroke-linejoin: round;
  opacity: .75;
}
.pt-btn--wa:disabled { background-color: var(--linea); color: var(--apagado); }

/* --- el pedido ---------------------------------------------- */
.pt-cols {
  display: grid; grid-template-columns: 1fr 375px; gap: 1px;
  background: var(--linea); border: 1px solid var(--linea);
}
@media (max-width: 900px) { .pt-cols { grid-template-columns: 1fr; } }
/* Sin rayado: lo tuvo un rato en las dos columnas del pedido y lo
   quitó. La textura vive ahora SOLO en las casillas de opción que
   no están escogidas — ver .pt-radio más abajo. */
.pt-col { background: var(--caja); padding: 1.6rem; }

/* Cada pieza del pedido en su propio recuadro. Antes solo las
   separaba una línea fina y con dos o tres renglones —nombre,
   opciones, packs, cantidad— costaba ver dónde acababa uno y
   empezaba el siguiente. */
.pt-linea {
  display: flex; gap: .9rem; align-items: flex-start;
  padding: .8rem .9rem;
  border: 1px solid var(--linea);
  background-color: color-mix(in srgb, var(--tinta) 3%, transparent);
}
.pt-linea + .pt-linea { margin-top: .5rem; }
.pt-linea__desc { flex: 1; min-width: 0; }
.pt-linea__desc b { font-size: 1rem; display: block; }
.pt-linea__desc small { font-size: 0.875rem; color: var(--apagado); display: block; margin-top: .15rem; }
.pt-linea__packs { font-size: 0.875rem; color: var(--madera-texto); display: block; margin-top: .15rem; }
.pt-linea__mon { font-size: 1rem; font-weight: 700; white-space: nowrap; }

/* La cantidad se edita en la propia línea, con los mismos − y +
   del panel de producto. `align-items: center` en la línea para
   que los tres bloques queden a la misma altura. */
.pt-linea { align-items: center; }
.pt-linea__cant {
  display: flex; align-items: center; gap: .1rem;
  border: 1px solid var(--linea); flex: none;
}
.pt-linea__cant .pt-pasos__b { width: 26px; height: 26px; font-size: 1rem; }
.pt-linea__n {
  min-width: 1.6rem; text-align: center;
  font-size: 0.875rem; font-weight: 700; font-variant-numeric: tabular-nums;
}

/* Quitar: cuadradito con un signo menos, a la derecha del
   subtotal. Va en ROJO desde el principio —lo pidió resaltado—,
   y al pasar por encima se rellena. El `title` dice qué hace: un
   − suelto no se explica solo, y al lado de los otros − y + de
   la cantidad hace falta distinguirlo. */
.pt-quitar {
  flex: none; width: 26px; height: 26px; padding: 0;
  display: grid; place-items: center;
  font: inherit; font-size: 1rem; line-height: 1;
  color: var(--de); background: none;
  border: 1px solid var(--de); border-radius: 0;
  cursor: pointer;
  transition: color .15s, border-color .15s, background-color .15s;
}
.pt-quitar:hover, .pt-quitar:focus-visible {
  color: #fff; background-color: var(--de); border-color: var(--de);
}
.pt-vacio { color: var(--apagado); font-size: 0.875rem; padding: 1.6rem 0; text-align: center; }

.pt-campo { margin-bottom: 1.4rem; }
.pt-radios { display: flex; flex-direction: column; gap: 1px; background: var(--linea); border: 1px solid var(--linea); }
.pt-radio {
  display: flex; align-items: center; gap: .7rem; padding: .75rem .85rem;
  background-color: var(--caja); font: inherit; font-size: 0.875rem; text-align: left;
  width: 100%; border: 0; color: inherit; cursor: pointer;
}
/* Sin rayado aquí tampoco: lo tuvo un rato en las casillas no
   escogidas y salió. Lo que marca la elección es el cuadradito,
   que se llena con el acento. */
.pt-radio:hover { background-color: var(--caja-alta); }
.pt-radio.sel { background-color: var(--caja-alta); }
/* El cuadradito es lo único que dice qué está escogido, así que se
   llena con el acento claro de la paleta (Burnt Sugar). Es el
   único punto de color de todo el pedido. */
.pt-radio__punto {
  width: 11px; height: 11px; border: 1px solid var(--apagado); flex: none;
  transition: background-color .15s, border-color .15s;
}
.pt-radio.sel .pt-radio__punto {
  border-color: var(--acento-claro);
  background-color: var(--acento-claro);
}
.pt-radio__et { flex: 1; }
.pt-radio__et small { display: block; font-size: 0.875rem; color: var(--apagado); margin-top: .1rem; }
.pt-radio__val { font-size: 0.875rem; color: var(--apagado); white-space: nowrap; }
.pt-radio:disabled { opacity: .35; cursor: not-allowed; }

.pt-select {
  width: 100%; background: var(--caja); border: 1px solid var(--linea);
  padding: .7rem .8rem; font: inherit; font-size: 0.875rem; color: inherit;
  border-radius: 0; appearance: none;
  background-image:
    linear-gradient(45deg, transparent 50%, var(--apagado) 50%),
    linear-gradient(135deg, var(--apagado) 50%, transparent 50%);
  background-position: calc(100% - 18px) 50%, calc(100% - 13px) 50%;
  background-size: 5px 5px, 5px 5px; background-repeat: no-repeat;
}
.pt-select:focus { outline: 1px solid var(--tinta); outline-offset: -1px; }

.pt-fila { display: flex; justify-content: space-between; align-items: baseline; gap: .8rem; margin-bottom: .55rem; font-size: 0.875rem; }
.pt-fila .et { color: var(--apagado); }
.pt-fila--grande { font-size: 1rem; margin-top: .9rem; padding-top: .9rem; border-top: 1px solid var(--linea); }
.pt-fila--grande .et { color: var(--tinta); font-weight: 700; }
.pt-fila--grande .n { font-size: 1.62rem; font-weight: 700; }
.pt-gris { color: var(--apagado); font-size: 0.75rem; display: block; margin-top: .1rem; text-align: right; }

/* El envío va en su propia caja y NO suma al total: es cobro
   destino, lo cobra la agencia al entregarlo. */
.pt-aparte { border: 1px solid var(--linea); padding: .8rem .85rem; margin-top: 1rem; font-size: 0.875rem; }
.pt-aparte__top { display: flex; justify-content: space-between; gap: .6rem; margin-bottom: .2rem; }
.pt-aparte small { color: var(--apagado); font-size: 0.75rem; line-height: 1.4; display: block; }

.pt-previa {
  margin-top: .9rem; border: 1px solid var(--linea); background: var(--papel);
  padding: .95rem; font-size: 0.875rem; line-height: 1.6; white-space: pre-wrap;
  color: var(--apagado); max-height: 290px; overflow-y: auto;
}
.pt-nota { display: block; color: var(--apagado); font-size: 0.75rem; margin-top: .6rem; line-height: 1.45; }

/* ============================================================
   TRANSICION GLITCH ENTRE MEDIOS
   ------------------------------------------------------------
   2026-08-15 - El bloque se mudo a css/estilo.css, tal cual,
   sin tocar una linea. Motivo: la ficha de Exhibicion usa el
   mismo corte y esa pagina (trabajo.html) NO carga esta hoja.
   Las clases siguen llamandose .pt-glitch, .pt-saliendo y
   .pt-entrando; se buscan alli.
   ============================================================ */

/* La tasa del día, arriba a la derecha del recuadro del pedido.
   Va absoluta para que no empuje las filas de totales hacia abajo. */
.pt-tasa {
  position: absolute; top: .7rem; right: 1.6rem;
  font-size: 0.75rem; color: var(--apagado); letter-spacing: .02em;
  text-align: right; line-height: 1.3; max-width: 60%;
}
/* La columna necesita ser el ancla de esa posición absoluta. */
.pt-col { position: relative; }
