/* ============================================================
   ESTADOS E INTERACCIÓN
   Todo lo que le pasa a la interfaz cuando algo tarda, falla
   o responde: es la parte que más se nota cuando falta.
   ============================================================ */

/* ── Sin conexión ────────────────────────────────────────── */
.offline-banner {
  position: fixed;
  inset: 0 0 auto 0;
  z-index: calc(var(--z-nav) + 5);
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--s-2);
  padding: var(--s-2) var(--s-4);
  background: var(--c-amber);
  color: #241703;
  font-size: var(--fs-xs);
  font-weight: 800;
  text-align: center;
  transform: translateY(-100%);
  transition: transform var(--d-base) var(--e-out);
}

.offline-banner.is-visible { transform: none; }

/* Cuando el aviso está visible, todo lo fijo baja para no quedar tapado. */
body.is-offline .announce,
body.is-offline .nav { transform: translateY(var(--offline-h, 34px)); }

body.is-offline .mobile-menu {
  margin-top: var(--offline-h, 34px);
}

body.is-offline .hero {
  padding-top: calc(var(--h-announce) + var(--h-nav) + var(--s-16) + var(--offline-h, 34px));
}

@media (max-width: 720px) {
  .offline-banner { font-size: var(--fs-2xs); }
  body.is-offline { --offline-h: 44px; }
}

/* ── Imagen de producto: carga y fallback ────────────────── */
.pcard__media { isolation: isolate; }

/* Shimmer mientras la foto viaja. */
.pcard__media.is-loading::before {
  content: '';
  position: absolute;
  inset: 0;
  background: linear-gradient(
    90deg,
    var(--c-stage-2) 25%,
    var(--c-stage) 50%,
    var(--c-stage-2) 75%
  );
  background-size: 200% 100%;
  animation: shimmer 1.4s linear infinite;
  z-index: 1;
}

/* La imagen entra fundida: sin esto "aparece de golpe". */
.pcard__img {
  transition: opacity var(--d-slow) var(--e-out), transform var(--d-slow) var(--e-out);
}

/* Aviso de foto fallada. Sólo aparece si no quedó ninguna imagen. */
.pcard__fallback {
  position: absolute;
  inset: 0;
  z-index: 2;
  display: none;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--s-2);
  padding: var(--s-4);
  text-align: center;
  background: var(--c-stage-2);
  color: var(--c-ink-3);
  font-size: var(--fs-2xs);
  font-weight: 700;
}

.pcard__media.has-error .pcard__fallback { display: flex; }

.pcard__fallback button {
  padding: 3px var(--s-3);
  border: 1px solid var(--c-line-ink);
  border-radius: var(--r-full);
  font-size: var(--fs-2xs);
  font-weight: 800;
  color: var(--c-ink);
  transition: background var(--d-fast) var(--e-out);
}
.pcard__fallback button:hover { background: var(--c-stage-3); }

/* Marcador cuando la planilla no trae foto */
.pcard__media--empty {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--s-2);
  padding: var(--s-4);
  text-align: center;
  color: var(--c-ink-3);
}

.pcard__media-name {
  font-family: var(--font-display);
  font-size: var(--fs-base);
  font-weight: 800;
  color: var(--c-ink-2);
  line-height: 1.2;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

.pcard__media-note {
  font-size: var(--fs-2xs);
  font-weight: 800;
  letter-spacing: var(--ls-wide);
  text-transform: uppercase;
  color: var(--c-ink-3);
}

/* ── Esqueletos con la forma real de la tarjeta ──────────── */
.pcard--skeleton { pointer-events: none; }
.pcard--skeleton:hover { transform: none; box-shadow: none; border-color: var(--c-line-ink); }

.sk-line {
  display: block;
  height: 11px;
  border-radius: var(--r-xs);
}

.sk-line--title { height: 20px; }

/* Los esqueletos del final entran con un pulso suave. */
.pcard--tail { animation: tailIn var(--d-slow) var(--e-out) both; }

@keyframes tailIn {
  from { opacity: 0; transform: translateY(8px); }
  to   { opacity: 1; transform: none; }
}

/* ── Micro-interacciones ─────────────────────────────────── */

/* Confirmación al agregar: un destello verde en el borde. */
@keyframes cardAdded {
  0%   { box-shadow: 0 0 0 0 rgba(122, 204, 0, 0.55); }
  100% { box-shadow: 0 0 0 14px rgba(122, 204, 0, 0); }
}

.pcard.is-added { animation: cardAdded 620ms var(--e-out); }

/* La cantidad cambia de tamaño: se nota que se registró. */
@keyframes qtyPop {
  0%   { transform: scale(1); }
  45%  { transform: scale(1.28); color: var(--c-brand-ink); }
  100% { transform: scale(1); }
}

.qty__value.is-bumped { animation: qtyPop 380ms var(--e-spring); }

/* El total del pedido se resalta cuando cambia. */
@keyframes totalFlash {
  0%   { color: var(--c-brand); }
  100% { color: inherit; }
}

.totals__value.is-bumped,
.mobile-bar__value.is-bumped {
  animation: totalFlash 700ms var(--e-out);
}

/* Punto de estado del catálogo */
.nav__status[data-state='ready'] .nav__status-dot {
  box-shadow: 0 0 0 3px var(--c-brand-dim);
}

/* ── Volver arriba ───────────────────────────────────────── */
.to-top {
  position: fixed;
  right: var(--s-5);
  bottom: calc(var(--s-5) + 68px + env(safe-area-inset-bottom, 0px));
  z-index: var(--z-sticky);
  display: grid;
  place-items: center;
  width: 44px; height: 44px;
  border-radius: var(--r-full);
  background: var(--c-surface-3);
  border: 1px solid var(--c-line-strong);
  color: var(--c-text);
  box-shadow: var(--sh-md);
  opacity: 0;
  visibility: hidden;
  transform: translateY(10px);
  transition:
    opacity var(--d-base) var(--e-out),
    transform var(--d-base) var(--e-out),
    visibility var(--d-base),
    background var(--d-fast) var(--e-out);
}

.to-top.is-visible {
  opacity: 1;
  visibility: visible;
  transform: none;
}

.to-top:hover { background: var(--c-surface-hover); }

/* Anillo de progreso del scroll, dibujado con conic-gradient. */
.to-top__ring {
  position: absolute;
  inset: -3px;
  border-radius: var(--r-full);
  background: conic-gradient(var(--c-brand) calc(var(--scroll-pct, 0) * 1%), transparent 0);
  mask: radial-gradient(farthest-side, transparent calc(100% - 2px), #000 calc(100% - 2px));
  -webkit-mask: radial-gradient(farthest-side, transparent calc(100% - 2px), #000 calc(100% - 2px));
  pointer-events: none;
}

/* En mobile hay barra inferior: el botón sube un poco más. */
@media (max-width: 720px) {
  .to-top { bottom: calc(var(--s-5) + 76px + env(safe-area-inset-bottom, 0px)); }
}

/* ── Tarjeta recién agregada al pedido ───────────────────── */
.pcard.is-in-cart .pcard__actions { opacity: 1; transform: none; }

/* ── Foco visible sobre superficies claras ───────────────── */
.catalog :focus-visible,
.toolbar :focus-visible {
  outline-color: var(--c-brand-ink);
}

/* ── Menos movimiento: sin destellos ni pulsos ───────────── */
@media (prefers-reduced-motion: reduce) {
  .pcard.is-added,
  .qty__value.is-bumped,
  .totals__value.is-bumped,
  .mobile-bar__value.is-bumped,
  .pcard--tail { animation: none; }

  .pcard__media.is-loading::before { animation: none; }

  .pcard__img { transition: none; }
  .to-top { transition: none; }
}

/* ── El atributo hidden siempre gana ──────────────────────
   Sin esto, un `display: flex` de otra regla puede anularlo y la
   sección vacía vuelve a aparecer. */
[hidden] { display: none !important; }

/* ── El menú mobile ocupa su columna correctamente ───────── */
.mobile-menu { left: 0; right: 0; }

