/* ============================================================================================
   GVenue — 🖼️ BANNER DE PIE de las pantallas que ve el público y el staff.
   Lo monta `gv-banner.js` dentro de cualquier `[data-gv-banner]`; lo inserta `gv_pie_banner()`.
   ============================================================================================

   Reemplaza al PNG estático de 970x90 que estaba al 50% de opacidad en la comandera y en la
   pantalla de listos. Es la misma pieza que mandó Design (`Upload/- GVenue-Banner/`), portada.

   🔴 QUÉ SE CAMBIÓ DEL KIT Y POR QUÉ — las dos cosas que lo hacían burdo en pantalla:

   1. El kit dibuja un lienzo FIJO de 1080x104 y lo achica entero con `transform:scale()`. En un
      celular de 375px eso da escala .35: **36px de alto y tipografía de 6px**. Estas pantallas
      SON celulares (el kiosco y la tienda las abre el cliente con su teléfono). Acá el layout es
      fluido de verdad: cuatro tamaños (`data-w`), cada uno con su altura y su tipografía, y en
      los chicos se caen las piezas que no entran (QR, CTA) en vez de encogerse hasta ser humo.

   2. El kit clava `#0B0B0D` de fondo y `#F4F4EF` de tinta. Estas pantallas tienen tres temas
      (oscuro / claro / blue-cut) y `/tienda` y `/rrpp` NO arrancan forzadas en oscuro. Va todo
      por token, con la misma receta de contraste que se midió para el pie de la home el 31-jul:
      el pastel del módulo PELADO da 1,64:1 en claro ⇒ `color-mix(var(--a) 62%, var(--ink))`.
      Ver [[feedback-contraste-fondo-clavado]] y [[project-footer-home-cinta-modulos]].

   Cada `color-mix()` va DESPUÉS de un color plano equivalente: un navegador viejo (WebView de
   tablet de barra) se queda con el plano y la pieza sigue legible, no queda sin color.
   ============================================================================================ */

.gv-pie-banner {
  /* El hueco alrededor. `contain` para que un repaint de la cinta no invalide la pantalla entera:
     esto convive con la comandera repintando pedidos cada 5 s toda la noche. */
  display: block;
  padding: 22px 14px 8px;
  contain: layout paint;
  /* 🔴 `width:100%` + `align-self:stretch` NO son de adorno. Varias de estas pantallas tienen el
     body en `display:flex; flex-direction:column; align-items:center` (salir.php, puesto.php, y
     cualquier pantalla-tarjeta que venga después). Ahí un hijo block deja de ocupar el ancho del
     padre y se encoge al de su contenido: medido en /ops/salir.php daban 122px de banner en una
     pantalla de 1280 — y como el tamaño lo decide el ancho del hueco, encima salía en su versión
     de celular. Con esto se comporta igual colgado de un body normal que de uno flex. */
  width: 100%;
  align-self: stretch;
}

/* ---- la pieza ---------------------------------------------------------------------------- */
.gvb {
  position: relative;
  display: flex;
  align-items: center;
  gap: 20px;
  width: 100%;
  max-width: 1080px;
  height: 104px;
  margin: 0 auto;
  padding: 0 18px 0 22px;
  overflow: hidden;
  isolation: isolate;
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  background: var(--surface);
  box-shadow: var(--shadow-1);
  color: var(--ink);
  font-family: var(--font-sans);
  text-decoration: none;
  -webkit-tap-highlight-color: transparent;
}
.gvb:hover  { border-color: var(--line-strong); }
.gvb:focus-visible { outline: 2px solid var(--signal); outline-offset: 3px; }

/* 🎨 LAS DOS PERILLAS DE CONTRASTE. Medido con canvas y las transiciones apagadas
   ([[feedback-medicion-contraste-computed-style]]) contra `--surface` en los tres temas:

     --gvb-sig  el teal de marca como TEXTO. Pelado sobre blanco da 3,43:1 — el token está
                pensado también como fondo de botón, no solo como texto de 12px. Mezclado al 78%
                con la tinta sube a 5,10:1 y sigue leyéndose como el teal de GVenue.
     --gvb-mix  cuánto del acento del módulo sobrevive en el nombre y el glifo de la cinta. En
                oscuro y en blue-cut el 62% del pie de la home da 8,0 y 7,1 y queda igual. En
                claro ese mismo 62% cae a 4,03 (el peor es GV Barra, #BED54E, un verde lima sobre
                blanco): al 55% da 4,85 y pasa. Es lo más de color que se puede dejar en claro.

   En oscuro y blue-cut no se toca nada: ahí los peores casos ya daban 4,49 y 5,40. */
.gvb { --gvb-sig: var(--signal); --gvb-mix: 62%; }
/* 20-ago-2026: blue-cut dejó de ser oscuro. La medición de abajo decía "en
   oscuro y en blue-cut el 62% da 8,0 y 7,1" — eso valía cuando blue era
   navy. Ahora es papel cálido, así que le corresponde el mismo tratamiento
   que a claro: el acento del módulo pelado se lava sobre fondo claro. */
:root[data-theme="light"] .gvb,
:root[data-theme="blue"] .gvb {
  --gvb-sig: color-mix(in oklab, var(--signal) 78%, var(--ink));
  --gvb-mix: 55%;
}

/* Trama de puntos del kit. Por token: en claro son puntos oscuros sobre blanco, no desaparecen. */
.gvb::before {
  content: "";
  position: absolute;
  inset: 0;
  background-image: radial-gradient(circle at 1px 1px, rgba(128,128,128,.14) 1px, transparent 0);
  background-image: radial-gradient(circle at 1px 1px, color-mix(in oklab, var(--ink) 9%, transparent) 1px, transparent 0);
  background-size: 14px 14px;
  pointer-events: none;
}

/* Halo que va tomando el color del módulo que está pasando. En claro pesa la mitad: sobre blanco
   un lavado de color al 13% se lee como una mancha, no como un halo. */
.gvb-aura {
  position: absolute;
  inset: -40% -10%;
  background: var(--gvb-aura-bg, radial-gradient(ellipse 34% 120% at 22% 50%, rgba(92,242,217,.13), transparent 62%));
  opacity: var(--gvb-aura-op, 1);
  transition: background 1.4s ease;
  pointer-events: none;
}
:root[data-theme="light"] .gvb-aura,
:root[data-theme="blue"] .gvb-aura { --gvb-aura-op: .5; }

/* Barrido de luz. 🔴 Apagado en claro a propósito: un destello claro sobre blanco no se ve, y la
   versión oscura del mismo barrido sobre blanco se lee como suciedad en la pantalla. */
.gvb-sweep {
  position: absolute;
  top: 0;
  bottom: 0;
  width: 190px;
  background: linear-gradient(100deg, transparent, var(--signal-soft) 42%, rgba(128,128,128,.06) 52%, transparent);
  filter: blur(1px);
  animation: gvb-sweep 9s cubic-bezier(.45,0,.2,1) infinite;
  pointer-events: none;
}
@keyframes gvb-sweep { 0% { left: -24%; } 55%, 100% { left: 112%; } }
:root[data-theme="light"] .gvb-sweep,
:root[data-theme="blue"] .gvb-sweep { display: none; }

/* Esquinas de encuadre (el «corchete» de la marca). */
.gvb-c {
  position: absolute;
  width: 9px;
  height: 9px;
  border-color: var(--signal);
  opacity: .55;
  pointer-events: none;
}
.gvb-c.tl { top: 7px;    left: 7px;  border-top: 1.4px solid;    border-left: 1.4px solid; }
.gvb-c.tr { top: 7px;    right: 7px; border-top: 1.4px solid;    border-right: 1.4px solid; }
.gvb-c.bl { bottom: 7px; left: 7px;  border-bottom: 1.4px solid; border-left: 1.4px solid; }
.gvb-c.br { bottom: 7px; right: 7px; border-bottom: 1.4px solid; border-right: 1.4px solid; }

/* ---- marca ------------------------------------------------------------------------------- */
.gvb-brand { display: flex; align-items: center; gap: 13px; flex-shrink: 0; position: relative; }
.gvb-mk    { width: 26px; height: 26px; display: block; overflow: visible; }
.gvb-wm    { font-size: 22px; font-weight: 600; letter-spacing: -.024em; line-height: 1; white-space: nowrap; }

.gvb-rule {
  flex-shrink: 0;
  width: 1px;
  height: 54px;
  background: linear-gradient(180deg, transparent, var(--line) 22%, var(--line) 78%, transparent);
}

/* ---- centro ------------------------------------------------------------------------------ */
.gvb-mid {
  flex: 1;
  min-width: 0;              /* sin esto el flex no deja que la cinta se recorte y desborda */
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 9px;
  position: relative;
}

/* Los claims van apilados en la misma caja (position:absolute) para que el fundido cruce sin
   empujar nada. La altura la fija el contenedor, no el texto. */
.gvb-claims { position: relative; height: 22px; }
.gvb-claim {
  position: absolute;
  left: 0; top: 0; right: 0;
  line-height: 22px;
  font-size: 17.5px;
  font-weight: 500;
  letter-spacing: -.018em;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  opacity: 0;
  transform: translateY(6px);
  filter: blur(3px);
  transition: opacity .62s ease, transform .62s cubic-bezier(.22,1,.36,1), filter .62s ease;
}
.gvb-claim.on { opacity: 1; transform: none; filter: none; }
.gvb-claim em { font-style: normal; color: var(--signal); color: var(--gvb-sig); }

/* ---- cinta de módulos -------------------------------------------------------------------- */
.gvb-track {
  position: relative;
  height: 19px;
  overflow: hidden;
  -webkit-mask-image: linear-gradient(90deg, transparent, #000 34px, #000 calc(100% - 46px), transparent);
          mask-image: linear-gradient(90deg, transparent, #000 34px, #000 calc(100% - 46px), transparent);
}
.gvb-lane {
  position: absolute;
  top: 0; left: 0;
  display: flex;
  align-items: center;
  gap: 22px;
  white-space: nowrap;
  will-change: transform;
  animation: gvb-slide var(--gvb-dur, 42s) linear infinite;
}
@keyframes gvb-slide { to { transform: translateX(-50%); } }
.gvb:hover .gvb-lane { animation-play-state: paused; }

/* 🔋 Pantalla en segundo plano (pestaña oculta / TV con otra app encima): se congela TODO. Estas
   pantallas quedan prendidas ocho horas seguidas; una cinta animando sin que nadie la mire es
   batería de la tablet y ventilador del mini-PC de la comandera, gratis. Lo pone el JS. */
.gvb-quieto .gvb-lane,
.gvb-quieto .gvb-sweep,
.gvb-quieto .gvb-live i { animation-play-state: paused; }

.gvb-mod {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: .11em;
  text-transform: uppercase;
  color: var(--ink-mute);
  color: color-mix(in oklab, var(--ink-mute) 80%, var(--ink));
}
/* 🔴 El acento del módulo NUNCA pelado: sobre fondo claro los pasteles del kit caen a 1,64:1.
   Misma mezcla que la cinta del pie de la home (31-jul), así el módulo tiene el MISMO color en
   los dos lados. */
.gvb-mod .ic {
  display: grid;
  place-items: center;
  width: 17px;
  height: 17px;
  border-radius: 4px;
  background: color-mix(in oklab, var(--a) 16%, transparent);
  box-shadow: inset 0 0 0 1px color-mix(in oklab, var(--a) 34%, transparent);
}
.gvb-mod .ic svg {
  width: 11px;
  height: 11px;
  fill: none;
  stroke: var(--a);
  stroke: color-mix(in oklab, var(--a) var(--gvb-mix), var(--ink));
  stroke-width: 2.1;
  stroke-linecap: round;
  stroke-linejoin: round;
}
.gvb-mod b {
  font-weight: 500;
  color: var(--a);
  color: color-mix(in oklab, var(--a) var(--gvb-mix), var(--ink));
}
.gvb-mod .n {
  font-size: 9.5px;
  letter-spacing: .16em;
  color: var(--ink-fade);
  color: color-mix(in oklab, var(--ink-fade) 55%, var(--ink));
}
.gvb-mod .f { opacity: .62; }
.gvb-sep { flex: none; width: 3px; height: 3px; border-radius: 50%; background: var(--ink-fade); }

/* ---- derecha: QR + llamada --------------------------------------------------------------- */
.gvb-right { display: flex; align-items: center; gap: 13px; flex-shrink: 0; }
/* La plaquita del QR es blanca SIEMPRE (en los tres temas): un QR necesita su quiet zone clara o
   el lector no engancha. Acá el fondo clavado es correcto — es requisito del formato, no estilo. */
.gvb-qr {
  width: 62px;
  height: 62px;
  padding: 3px;
  border-radius: 3px;
  background: #fff;
  box-shadow: 0 0 0 1px var(--line-strong);
  line-height: 0;
}
.gvb-qr svg { width: 100%; height: 100%; display: block; }
.gvb-cta { text-align: right; line-height: 1.5; }
/* 🔴 display:block obligatorio. Toda la pieza vive adentro de un <a>, así que los renglones son
   <span> y no <div> (un <div> ahí es HTML inválido). Un <span> es inline: sin esto «ESCANEÁ», la
   URL y el contador se apilan en UN renglón, se pisan y la URL se sale del banner. */
.gvb-cta .k,
.gvb-cta .u { display: block; }
.gvb-cta .k {
  font-family: var(--font-mono);
  font-size: 8.5px;
  letter-spacing: .24em;
  text-transform: uppercase;
  /* `--ink-mute` pelado sobre `--surface` da 4,49 en oscuro — el mismo 4,49 que apareció en la
     cinta del pie de la home el 31-jul, y por el mismo motivo: estos rótulos van sobre panel, no
     sobre el fondo de la página. Misma corrección de allá. */
  color: var(--ink-mute);
  color: color-mix(in oklab, var(--ink-mute) 80%, var(--ink));
}
.gvb-cta .u {
  font-family: var(--font-mono);
  font-size: 12.5px;
  font-weight: 500;
  letter-spacing: .01em;
  color: var(--signal);
  color: var(--gvb-sig);
}
.gvb-live {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: 5px;
  margin-top: 1px;
  font-family: var(--font-mono);
  font-size: 8.5px;
  letter-spacing: .2em;
  text-transform: uppercase;
  color: var(--ink-mute);                                    /* mismo 4,49 que .gvb-cta .k */
  color: color-mix(in oklab, var(--ink-mute) 80%, var(--ink));
}
.gvb-live i {
  width: 4px;
  height: 4px;
  border-radius: 50%;
  background: var(--signal);
  animation: gvb-blip 2.2s ease-in-out infinite;
}
@keyframes gvb-blip {
  0%, 100% { opacity: .35; box-shadow: 0 0 0 0 var(--signal-line); }
  50%      { opacity: 1;   box-shadow: 0 0 0 4px transparent; }
}

/* ============================================================================================
   TAMAÑOS — los pone el JS midiendo el ANCHO REAL del hueco (ResizeObserver), no el viewport.
   Va por ancho del contenedor y no por media query porque el mismo banner entra en una TV de la
   comandera y en una columna angosta del panel: el viewport miente.
   ============================================================================================ */

/* md · tablet apaisada — se va la llamada escrita, el QR queda (a esa distancia se escanea). */
.gvb[data-w="md"] { height: 96px; gap: 17px; }
.gvb[data-w="md"] .gvb-wm     { font-size: 20px; }
.gvb[data-w="md"] .gvb-claim  { font-size: 16px; }
.gvb[data-w="md"] .gvb-qr     { width: 56px; height: 56px; }
.gvb[data-w="md"] .gvb-cta    { display: none; }

/* sm · tablet parada y celular apaisado — se va el QR entero. Nadie escanea un QR que tiene a
   diez centímetros de la cara: a esa distancia el banner se TOCA, y todo él es un link. */
.gvb[data-w="sm"] { height: 88px; gap: 14px; padding: 0 15px; }
.gvb[data-w="sm"] .gvb-mk    { width: 23px; height: 23px; }
.gvb[data-w="sm"] .gvb-wm    { font-size: 18px; }
.gvb[data-w="sm"] .gvb-claim { font-size: 14.5px; }
.gvb[data-w="sm"] .gvb-right,
.gvb[data-w="sm"] .gvb-rule  { display: none; }
.gvb[data-w="sm"] .gvb-brand { gap: 10px; }

/* xs · celular parado. Es el caso del kiosco y de la tienda: el cliente con su teléfono.
   El claim pasa a su versión corta (lo elige el JS) — recortar el largo con puntos suspensivos
   sería justamente lo burdo. */
.gvb[data-w="xs"] { height: 78px; gap: 11px; padding: 0 12px; border-radius: var(--r-sm); }
.gvb[data-w="xs"] .gvb-mk     { width: 20px; height: 20px; }
.gvb[data-w="xs"] .gvb-wm     { font-size: 16px; }
.gvb[data-w="xs"] .gvb-brand  { gap: 8px; }
.gvb[data-w="xs"] .gvb-mid    { gap: 7px; }
.gvb[data-w="xs"] .gvb-claims { height: 19px; }
.gvb[data-w="xs"] .gvb-claim  { font-size: 13px; line-height: 19px; }
.gvb[data-w="xs"] .gvb-track  { height: 17px; }
.gvb[data-w="xs"] .gvb-lane   { gap: 16px; }
.gvb[data-w="xs"] .gvb-mod    { font-size: 10px; gap: 6px; }
.gvb[data-w="xs"] .gvb-mod .n { display: none; }   /* el 01/02/03 es lo primero que sobra */
.gvb[data-w="xs"] .gvb-mod .f { display: none; }   /* y después el descriptor: queda el nombre */
.gvb[data-w="xs"] .gvb-right,
.gvb[data-w="xs"] .gvb-rule   { display: none; }
.gvb[data-w="xs"] .gvb-c      { display: none; }   /* 9px de corchete en 78px de alto es ruido */

/* ============================================================================================
   ♿ Movimiento reducido: la pieza queda ENTERA y quieta. No se esconde nada — quien lo configuró
   así quiere leer lo mismo, sin que se le mueva. La cinta se centra y el claim que se ve es el
   primero (el JS no rota).
   ============================================================================================ */
@media (prefers-reduced-motion: reduce) {
  .gvb-lane   { animation: none; transform: none; }
  .gvb-sweep  { display: none; }
  .gvb-live i { animation: none; opacity: 1; }
  .gvb-aura   { transition: none; }
  .gvb-claim  { transition: opacity .2s ease; transform: none; filter: none; }
}

/* Impresión: el banner no se imprime (los tickets y los cierres de caja salen por estas mismas
   pantallas y la tinta del boliche no es nuestra). */
@media print { .gv-pie-banner { display: none !important; } }
