/* ============================================================
   RESET DEL MOLDE DE DEMOS — las líneas que ya nos costaron un run
   cada una. No se editan: se copian tal cual al arrancar una demo.
   Cada bloque cita el caso que lo puso acá.
   ============================================================ */

*, *::before, *::after { box-sizing: border-box; }

html {
  /* NUNCA overflow-x:hidden acá ni en body: convierte al elemento en
     contenedor de scroll y mata todo position:sticky (medido: nav con el CTA
     "Reservar" saliéndose de pantalla). clip recorta igual sin crear el
     contenedor. — berlin-barberia-demo */
  overflow-x: clip;
  -webkit-text-size-adjust: 100%;
}

body {
  margin: 0;
  overflow-x: clip;
  /* el fondo va acá o en body::before{position:fixed;z-index:-1} — jamás
     background-attachment:fixed con gradientes: repaint por frame de scroll
     en Windows/Chromium. — run crm-fluidez-motion */
}

/* ★ El atributo `hidden` pierde contra cualquier `display` de autor: un
   <button hidden class="btn"> con .btn{display:inline-flex} queda VISIBLE
   (misma especificidad 0,1,0 y el CSS de autor gana al UA). Reincidió TRES
   veces (tahia · berlin · hope: 4 carritos abiertos a la vez). Va fija.
   Y el assert correcto en los tests es getComputedStyle(el).display, nunca
   el.hidden ni la propiedad. */
[hidden] { display: none !important; }

/* El atributo height del <img> es un hint presentacional: si el CSS pisa sólo
   width, la altura QUEDA clavada en el atributo (foto 400×1163 con zoom-crop
   absurdo; aspect-ratio no aplica porque ninguna dimensión es auto).
   Con width/height en el HTML (anti-CLS), esto es obligatorio. — hope-burgers */
img, svg, video, canvas { display: block; max-width: 100%; }
img, video { height: auto; }

/* Los botones que son <a> salen subrayados y no se nota hasta el screenshot
   (pasó en los tres CTA del hero). — ockulta-demo */
a.btn, .btn { text-decoration: none; }

/* Toda columna de grid que contenga un riel con overflow-x lleva min-width:0.
   El default min-width:auto hace que el contenido del riel mande sobre la
   columna: 625px de overflow en 390. Reincidió tres veces (carnave · ockulta).
   Aplicalo también a los hijos directos de cualquier grid con carrusel. */
.grid > *, [data-riel] { min-width: 0; }

/* Clase base de un sistema de componentes SIN padding propio = deformación
   silenciosa en el uso N+1 (renderizó 103×17px). El default vive en la base;
   los contextos lo pisan. — carnave-v2-redesign */
.glass, .panel, .card { padding: clamp(1rem, 2.2vw, 1.75rem); }

/* Dos bandas del mismo color pegadas suman su padding: 8vw+8vw = 307px de
   vacío a 1920 que lee "sin terminar". El corte de color sí se gana su aire
   entero. — berlin-barberia-demo */
.banda + .banda[data-tono="mismo"] { padding-top: 0; }

button { font: inherit; color: inherit; background: none; border: 0; cursor: pointer; }
ul, ol { margin: 0; padding: 0; list-style: none; }
h1, h2, h3, h4, p, figure, blockquote { margin: 0; }

/* Keyframes con fill:both terminan en `transform: none`, jamás en
   translate*(0): un transform identidad persistente convierte al elemento en
   containing block de cualquier position:fixed descendiente (los modales
   anidados colapsan). — run crm-fluidez-motion */

/* Foco visible siempre — el gate de a11y del design-gate lo pide. */
:focus-visible { outline: 2px solid currentColor; outline-offset: 3px; }

/* El motion NO se apaga por prefers-reduced-motion en estas demos (preferencia
   explícita del user): por eso todo reveal usa gsap.from() — el estado final
   visible vive en el CSS y si el JS muere la página se lee igual. Lo único que
   respeta la preferencia son los autoplay (marquee, autociclo). */
@media (prefers-reduced-motion: reduce) {
  [data-marquee] > * { animation: none !important; }
}
