/* ============================================================
   NASTASI FOODS — product-sheet.css
   ------------------------------------------------------------
   La ficha de producto (product-sheet.js). Es la **scheda tecnica**: la hoja
   de especificaciones que viaja con el contenedor, no un lightbox de tienda.

     ┌─────────────────────────────────────────────────────────┐
     │ SPEC SHEET                        AST 00300         [×] │  cabecera impresa
     ├──────────────────────┬──────────────────────────────────┤
     │                      │  ASTURI                          │
     │   [ la placa ]       │  Asturi Classic VOO              │
     │   click to zoom      │  Cookies & Biscuits              │
     │                      │  ── DESCRIPTION ───────────      │
     │  [ Spec sheet PDF ]  │  ── INGREDIENTS ───────────      │
     │                      │  ── NUTRITION ─────────────      │
     │                      │  ── SPECIFICATIONS ────────      │
     │                      │  ── SHIPPING & STORAGE ────      │
     ├──────────────────────┴──────────────────────────────────┤
     │ CASE 12 × 4.23 OZ   $36.30   $3.03/unit   [− 0 +]  Ask  │  barra de compra
     └─────────────────────────────────────────────────────────┘

   DECISIONES QUE NO SON DE GUSTO
   ------------------------------
   · **El papel no scrollea; el docket sí.** La cabecera y la barra de compra
     quedan fijas y sólo la columna de texto se desplaza. El precio y el
     contador son la acción primaria de esta ventana y tienen que estar
     siempre a la vista (`primary-action` en las reglas de ui-ux-pro-max);
     si scrollease todo el papel, la única forma de comprar se iría de la
     pantalla justo cuando el comprador acaba de leer por qué comprar.
   · **La fotografía es una placa con reglas, no una imagen a sangre.** Es el
     mismo argumento que la tarjeta: el papel alrededor es lo que la convierte
     en una fotografía pegada a un documento.
   · **Nada de backdrop-filter.** shapes.css §7b: el cristal líquido es para
     paneles pequeños sobre imagen viva. Éste es un panel del tamaño de la
     página, y ya costó una ronda de depuración en Contact.
   · **Sin numerar las secciones.** Son categorías, no pasos.
   ============================================================ */

.psheet {
  position: fixed; inset: 0; z-index: var(--z-drawer, 90);
  display: grid; place-items: center;
  /* The explicit 1fr track is load-bearing. With the default auto row,
     `place-items: center` sizes the row to the paper's own content — so the
     paper's `height: 100%` resolved against a track that was itself waiting on
     the paper, i.e. against auto, and the panel came out 438px tall in a 900px
     window. A 1fr track fills the fixed box first, and 100% then means what it
     says. */
  grid-template: minmax(0, 1fr) / minmax(0, 1fr);
  padding: clamp(0.5rem, 2vw, 2rem);
}
.psheet[hidden] { display: none; }

.psheet__scrim {
  position: absolute; inset: 0;
  /* 40–60% es el rango en el que un scrim aísla de verdad el primer plano */
  background: rgba(22, 20, 15, 0.52);
  opacity: 0;
  transition: opacity var(--dur-mid) ease;
}
.psheet[data-open="true"] .psheet__scrim { opacity: 1; }

.psheet__paper {
  position: relative;
  width: min(1080px, 100%);
  /* HEIGHT, not max-height. With max-height the panel only grew to its content,
     and its shortest content is the square plate — so a document with five
     sections in it was rendering 438px tall inside a 900px window, with the
     docket scrolling four sections out of sight for no reason. A fixed height
     lets `minmax(0, 1fr)` on the body do its job: the docket gets every pixel
     the head and the buy bar do not need. */
  height: min(880px, 100%);
  display: grid; grid-template-rows: auto minmax(0, 1fr) auto;
  background: var(--bone-pure);
  border: 1px solid var(--line-strong);
  border-top: 4px solid var(--stamp);
  border-radius: 3px;
  box-shadow: 0 30px 70px rgba(22, 20, 15, 0.34), 0 8px 20px rgba(22, 20, 15, 0.16);
  overflow: hidden;
  /* Entra desde donde se pulsó, en espíritu: sube 12px y escala poco. Salir es
     más rápido que entrar (~65%), que es lo que hace que no se sienta pesada. */
  opacity: 0; transform: translateY(12px) scale(0.985);
  transition: opacity 180ms ease, transform 180ms var(--ease-out);
}
.psheet[data-open="true"] .psheet__paper {
  opacity: 1; transform: none;
  transition: opacity var(--dur-mid) ease, transform var(--dur-mid) var(--ease-out);
}

/* ---------- la cabecera impresa ---------- */
.psheet__head {
  display: flex; align-items: center; gap: 0.9rem;
  padding: 0.7rem clamp(0.9rem, 2vw, 1.5rem);
  border-bottom: 1px solid var(--line);
  background: var(--bone-deep);
  font-family: var(--font-mono); font-size: 0.6rem;
  letter-spacing: 0.18em; text-transform: uppercase;
}
.psheet__kicker { color: var(--stamp); font-weight: 500; }
.psheet__lot {
  color: var(--text-muted); font-variant-numeric: tabular-nums;
  margin-left: auto;
}
.psheet__x {
  width: 34px; height: 34px; flex: 0 0 auto;
  display: grid; place-items: center;
  background: none; border: 1px solid var(--line-strong); border-radius: 2px;
  color: var(--ink); cursor: pointer;
  transition: background var(--dur-fast) ease, border-color var(--dur-fast) ease;
}
.psheet__x svg { width: 16px; height: 16px; }
.psheet__x:hover { background: var(--bone); border-color: var(--ink); }
.psheet__x:focus-visible { outline: 2px solid var(--brass); outline-offset: 2px; }

/* ---------- el cuerpo ---------- */
.psheet__body {
  display: grid; grid-template-columns: minmax(0, 0.9fr) minmax(0, 1.1fr);
  min-height: 0;
}
/* The plate is MOUNTED on the sheet, so the slack goes above and below it as
   margins rather than collecting in one hole under the photograph — the same
   `space-between`/centring fix the visit ticket's stub needed in round 5. The
   PDF slot sits on the bottom edge because that is where a document carries
   its attachments. */
.psheet__plate {
  display: flex; flex-direction: column; gap: 0.75rem;
  padding: clamp(0.9rem, 2vw, 1.4rem);
  border-right: 1px solid var(--line);
  background: var(--bone);
  min-width: 0;
}
/* `margin-block: auto` on the figure and nothing on the foot: auto margins eat
   the free space BEFORE justify-content ever runs, so the plate centres itself
   in the room above the attachment and the attachment holds the bottom edge.
   (justify-content: center here would have lost to any auto margin.) */
.psheet__figure { margin-block: auto; }

/* LA PLACA. `overflow: hidden` es lo que hace que el zoom sea una lupa: la
   imagen crece dentro de un marco que no se mueve. */
.psheet__figure {
  position: relative;
  aspect-ratio: 1 / 1;
  background: var(--bone-pure);
  border: 1px solid var(--line-strong);
  border-radius: 2px;
  overflow: hidden;
  cursor: zoom-in;
}
.psheet__figure[data-zoom="on"] { cursor: zoom-out; }
.psheet__figure:focus-visible { outline: 2px solid var(--brass); outline-offset: 3px; }
.psheet__figure img {
  width: 100%; height: 100%; object-fit: cover; display: block;
  /* transform, nunca width/height: no reflowea y va en la GPU */
  transition: transform 260ms var(--ease-out);
  will-change: transform;
}
.psheet__zoomhint {
  position: absolute; left: 0.6rem; bottom: 0.6rem;
  font-family: var(--font-mono); font-size: 0.55rem;
  letter-spacing: 0.14em; text-transform: uppercase;
  color: var(--ink); background: rgba(244, 239, 226, 0.92);
  border: 1px solid var(--line-strong); border-radius: 2px;
  padding: 0.25em 0.5em;
  pointer-events: none;
}

/* el hueco del PDF: presente siempre, activo sólo cuando hay archivo */
.psheet__doc {
  display: flex; align-items: center; gap: 0.5rem;
  padding: 0.6rem 0.7rem;
  border: 1px solid var(--line-strong); border-radius: 2px;
  background: var(--bone-pure);
  font-size: 0.78rem; line-height: 1.35;
  color: var(--ink); text-decoration: none;
}
.psheet__doc svg { width: 16px; height: 16px; flex: 0 0 auto; color: var(--stamp); }
a.psheet__doc:hover { background: var(--bone-deep); border-color: var(--ink); }
a.psheet__doc:focus-visible { outline: 2px solid var(--brass); outline-offset: 2px; }
.psheet__doc--none { color: var(--text-muted); border-style: dashed; }
.psheet__doc--none a { color: var(--brass); text-decoration: underline; text-underline-offset: 3px; }

/* ---------- el docket ---------- */
.psheet__docket {
  padding: clamp(0.9rem, 2vw, 1.5rem);
  /* Aire al final para que la última fila no muera pegada a la barra de compra.
     Sin él, "Ships from" tocaba el borde y la fila anterior parecía cortada. */
  padding-bottom: clamp(1.4rem, 2.5vw, 2rem);
  overflow-y: auto; min-height: 0;
  /* el scroll vive aquí y sólo aquí: la cabecera y la compra no se mueven */
  overscroll-behavior: contain;
  scrollbar-width: thin;
}

/* LA PISTA DE QUE ESTO SCROLLEA.
   Un hijo `sticky` del propio scroller: se queda pegado al borde inferior
   visible mientras quede algo por leer. `height: 0` + un ::before de 46px que
   cuelga hacia arriba, así que no ocupa sitio en el flujo y no puede empujar la
   última fila. `data-end` (lo escribe product-sheet.js) lo apaga al llegar
   abajo — si no, el propio degradado velaría la fila que se vino a leer. */
.psheet__fade {
  display: block; position: sticky; bottom: 0; height: 0;
  pointer-events: none;
}
.psheet__fade::before {
  content: ""; position: absolute; left: 0; right: 0; bottom: 0; height: 46px;
  background: linear-gradient(180deg, rgba(244, 239, 226, 0) 0%, var(--bone-pure) 82%);
  opacity: 1; transition: opacity var(--dur-fast) ease;
}
.psheet__docket[data-end] .psheet__fade::before { opacity: 0; }
.psheet__id { margin-bottom: 1.1rem; }
.psheet__brand {
  display: block;
  font-family: var(--font-mono); font-size: 0.6rem;
  letter-spacing: 0.18em; text-transform: uppercase; color: var(--stamp);
}
.psheet__docket h2 {
  font-family: var(--font-display); font-weight: 400;
  font-size: clamp(1.3rem, 1.1rem + 0.7vw, 1.75rem);
  line-height: 1.14; margin: 0.25rem 0 0;
}
.psheet__cat {
  margin: 0.35rem 0 0;
  font-size: 0.8rem; color: var(--text-muted);
}

/* las secciones: una regla y el nombre del campo en versalitas */
.psheet__sec { padding-top: 1rem; margin-top: 1rem; border-top: 1px solid var(--line); }
.psheet__sec:first-of-type { border-top: 0; margin-top: 0; padding-top: 0; }
.psheet__sech {
  font-family: var(--font-mono); font-size: 0.6rem;
  letter-spacing: 0.18em; text-transform: uppercase;
  color: var(--text-faint); font-weight: 500;
  margin: 0 0 0.55rem;
}
.psheet__sec p { margin: 0 0 0.5rem; font-size: 0.9rem; line-height: 1.62; }
.psheet__sec p:last-child { margin-bottom: 0; }
.psheet__lede { color: var(--text); }
.psheet__allerg { color: var(--stamp); }

/* EL ESTADO VACÍO ES UNA INVITACIÓN, NO UN HUECO. Dice qué falta y da la
   salida — pedirnos la ficha del fabricante. Ingredientes y nutrición llegan
   así a propósito: no se inventan datos de un alimento (build-product-details.js). */
.psheet__empty {
  padding: 0.7rem 0.8rem;
  background: color-mix(in srgb, var(--brass) 7%, transparent);
  border-left: 2px solid var(--brass);
  border-radius: 0 2px 2px 0;
  font-size: 0.84rem !important; color: var(--text-muted);
}
.psheet__empty b { color: var(--ink); font-weight: 500; }
.psheet__empty a { color: var(--brass); text-decoration: underline; text-underline-offset: 3px; }

/* la tabla de especificaciones: pares campo/valor, con regla punteada */
.psheet__specs { margin: 0; display: grid; gap: 0; }
.psheet__specs > div {
  display: grid; grid-template-columns: minmax(9rem, 0.8fr) minmax(0, 1.2fr);
  gap: 0.7rem;
  padding: 0.42rem 0;
  border-bottom: 1px dotted var(--line-strong);
}
.psheet__specs > div:last-child { border-bottom: 0; }
.psheet__specs dt {
  font-family: var(--font-mono); font-size: 0.58rem;
  letter-spacing: 0.13em; text-transform: uppercase; color: var(--text-faint);
  align-self: center;
}
.psheet__specs dd {
  margin: 0; font-size: 0.86rem; line-height: 1.45;
  font-variant-numeric: tabular-nums;
}

/* el panel de Nutrition Facts, en el formato de la FDA */
.nutri {
  border: 1px solid var(--ink); border-radius: 2px;
  padding: 0.6rem 0.7rem; background: #fff;
}
.nutri__head {
  display: flex; flex-direction: column; gap: 0.1rem;
  font-size: 0.78rem; padding-bottom: 0.4rem;
  border-bottom: 6px solid var(--ink);
}
.nutri__table { width: 100%; border-collapse: collapse; font-size: 0.8rem; }
.nutri__table th, .nutri__table td {
  text-align: left; padding: 0.26rem 0;
  border-bottom: 1px solid var(--line-strong);
  font-weight: 400;
}
.nutri__table tr.is-sub th { padding-left: 1rem; }
.nutri__dv { text-align: right; font-variant-numeric: tabular-nums; }
.nutri__foot {
  margin: 0.5rem 0 0 !important;
  font-size: 0.62rem !important; line-height: 1.4 !important;
  color: var(--text-muted); border-top: 3px solid var(--ink); padding-top: 0.4rem;
}

/* ---------- la barra de compra ---------- */
.psheet__buy {
  border-top: 1px solid var(--line-strong);
  background: var(--bone-deep);
  padding: 0.7rem clamp(0.9rem, 2vw, 1.5rem);
}
.psheet__buyin { display: flex; align-items: center; gap: clamp(0.6rem, 1.6vw, 1.2rem); flex-wrap: wrap; }
.psheet__money { display: grid; gap: 0.1rem; min-width: 0; }
.psheet__pack {
  font-family: var(--font-mono); font-size: 0.56rem;
  letter-spacing: 0.13em; text-transform: uppercase; color: var(--text-faint);
}
.psheet__price {
  font-family: var(--font-display); font-size: 1.6rem; line-height: 1.05;
  font-variant-numeric: tabular-nums;
}
.psheet__ref {
  font-family: var(--font-mono); font-size: 0.56rem;
  letter-spacing: 0.12em; text-transform: uppercase; color: var(--text-muted);
}
.psheet__ask { margin-left: auto; }
.psheet__oos {
  font-family: var(--font-mono); font-size: 0.66rem;
  letter-spacing: 0.16em; text-transform: uppercase; color: var(--stamp);
  border: 1.5px solid var(--stamp); border-radius: 2px; padding: 0.3em 0.6em;
}

/* el contador de la ficha: 40px en puntero fino, 44 en táctil */
.qty--sheet {
  height: 40px;
  background: var(--bone-pure);
  border: 1px solid var(--line-strong); border-radius: 2px;
}
.qty--sheet button { width: 38px; height: 38px; font-size: 1.05rem; }
.qty--sheet button:disabled { opacity: 0.35; cursor: default; }
.qty--sheet button:disabled:hover { background: none; }
.qty--sheet span { min-width: 30px; font-size: 0.9rem; font-variant-numeric: tabular-nums; }
.qty--sheet button:focus-visible { outline: 2px solid var(--brass); outline-offset: -2px; }
@media (hover: none), (pointer: coarse) {
  .qty--sheet { height: 46px; }
  .qty--sheet button { width: 44px; height: 44px; }
}

/* ---------- estrecho ----------
   Una columna. La placa se limita en ALTO (no en ancho) porque en un teléfono
   una foto 1:1 a ancho completo se come la pantalla entera y el texto — que es
   lo que se vino a leer — queda por debajo del pliegue. */
@media (max-width: 860px) {
  .psheet { padding: 0; }
  .psheet__paper {
    width: 100%; max-height: 100%; height: 100%;
    border-radius: 0; border-left: 0; border-right: 0;
  }
  .psheet__body { grid-template-columns: minmax(0, 1fr); overflow-y: auto; }
  .psheet__plate {
    border-right: 0; border-bottom: 1px solid var(--line);
    flex-direction: row; align-items: flex-start; gap: 0.7rem;
  }
  .psheet__figure { aspect-ratio: 1 / 1; width: 42%; max-width: 210px; flex: 0 0 auto; }
  .psheet__doc { flex: 1; }
  .psheet__docket { overflow: visible; }
  .psheet__ask { margin-left: 0; width: 100%; text-align: center; }
}
@media (max-width: 560px) {
  .psheet__plate { flex-direction: column; }
  .psheet__figure { width: 100%; max-width: none; }
  .psheet__specs > div { grid-template-columns: minmax(0, 1fr); gap: 0.1rem; }
}

@media (prefers-reduced-motion: reduce) {
  .psheet__paper, .psheet__scrim, .psheet__figure img { transition: none; }
  .psheet__paper { transform: none; }
}
