  /* =========================================================
     FONTS
     ========================================================= */
  @font-face{
    font-family:'Montserrat Variable';
    src:url('../fonts/MONTSERRAT-VARIABLEFONT_WGHT.woff2') format('woff2');
    font-weight:100 900;
    font-style:normal;
    font-display:swap;
  }
  @font-face{
    font-family:'Janna LT Regular';
    src:url('../fonts/JANNA%20LT%20REGULAR.woff2') format('woff2');
    font-weight:400;
    font-style:normal;
    font-display:swap;
  }
  /* used only for the "TÉCNICAMENTE ESPRESSO" wordmark treatment */
  @font-face{
    font-family:'Optima Normal';
    src:url('../fonts/OPTIMA_normal.woff2') format('woff2');
    font-weight:400;
    font-style:normal;
    font-display:swap;
  }
  @font-face{
    font-family:'Optima Bold';
    src:url('../fonts/OPTIMA_bold.woff2') format('woff2');
    font-weight:700;
    font-style:normal;
    font-display:swap;
  }
  /* =========================================================
     GLOBAL VARIABLES
     ========================================================= */
  :root{
    --dark:#1C1C1C;
    --cream:#E4D5B7;
    --font-title:'Montserrat Variable', Arial, sans-serif;
    --font-body:'Janna LT Regular', Georgia, serif;

    --accent-triangle:#D21D1B;
    --accent-larocca:#0091B3;
    --accent-markibar:#C31A4B;
    --accent-cunill:#C54039;
    --accent-remidag:#27A95B;
    --accent-eureka:#880000;

    --ease:cubic-bezier(.4,0,.2,1);

    /* =========================================================
       FROZEN VIEWPORT UNITS — the fixed-scale/anti-reflow mechanism.
       Every structural "Nvw" value in this stylesheet is written as
       calc(N * var(--frozen-vw)) instead of the native vw unit. The
       default below (1vw) makes this behave exactly like plain vw until
       the lock script in <head> overrides this custom property with a
       FIXED PX value — recomputed only on a genuine window resize, and
       deliberately left untouched when window.innerWidth only changed
       because of browser zoom (Ctrl +/-, pinch-zoom, etc. — detected via
       the devicePixelRatio heuristic, see the script tag near the top of
       <head>). Net effect: the HERO and every major section keep the
       exact same composition at any zoom level, but still adapt once to
       a genuinely different window/device size. See also the FIXED-SCALE
       script in <head>. (There is deliberately no --frozen-vh: the HERO
       now uses aspect-ratio instead of a viewport-height value — see
       .hero below — so it never depends on the device's own physical
       height, which is what made it balloon into a tall portrait box on
       real phones even with the width pinned to the desktop reference.) */
    --frozen-vw:1vw;

    /* Single shared inset for the locked composition. Both .site-frame
       and .floating-header read this SAME variable, so the fixed-position
       header can never drift a hair off from the frame's real edge —
       previously they were two separately-computed calc() expressions
       that could round a pixel apart, causing a hairline gap/strip.
       Flat 30px cap (not a vw-proportional value): gives the hero/frame
       the maximum available width at any screen size, per request. */
    --frame-inset: 30px;

    /* UNIFIED HEADER STACK sizing — the ticker strip + the header bar
       below it, both fixed to the viewport top at every screen size.
       Redefined smaller at the 680px tier for real phones; everything
       that depends on the total stack height (.hero's margin-top, the
       flyout menu's top) reads from these same two variables, so they
       never need to be recalculated by hand in more than one place. */
    --ticker-h: 22px;
    --header-bar-h: 74px;
  }

  *{margin:0;padding:0;box-sizing:border-box;}
  html{scroll-behavior:smooth;}
  /* Anclas del menú (¿Quiénes somos? / Servicio técnico): dejan espacio
     arriba igual a la cinta + el header fijo, para que la sección no quede
     tapada/mordida por el header al saltar. */
  #quienes-somos{
    scroll-margin-top:calc(var(--ticker-h) + var(--header-bar-h) + 24px);
  }
  /* Servicio técnico: que arranque justo en la foto (sin la franja crema
     de arriba). Se resta el margin-top propio del bloque .tec-espresso. */
  #tecnicamente-espresso{
    scroll-margin-top:calc(var(--ticker-h) + var(--header-bar-h));
  }
  html,body{overflow-x:hidden;}
  body{
    font-family:var(--font-body);
    background:var(--dark); /* #1C1C1C dead space — not pure black */
    color:var(--dark);
    line-height:1.5;
  }

  /* =========================================================
     SITE FRAME — locked-composition wrapper. The viewport meta stays
     "width=device-width, initial-scale=1.0" (a fixed "width=1280" meta
     previously made the site look artificially zoomed out — rejected).
     Instead the lock happens purely in CSS: symmetric left/right margins
     of --frame-inset produce the exact same ~90vw (capped at 1800px)
     composition as before, but expressed as the SAME shared variable
     that .floating-header also reads for its fixed-position left offset —
     guaranteeing the two can never render a pixel apart. Body's dark
     #1C1C1C fills any lateral dead space — never pure black.
     ========================================================= */
  .site-frame{
    position:relative;
    margin-left:var(--frame-inset);
    margin-right:var(--frame-inset);
    background:var(--cream);
    overflow-x:hidden;
  }
  img{display:block;max-width:100%;}
  h1,h2,h3{font-family:var(--font-title);}
  a{color:inherit;text-decoration:none;}
  button{font-family:var(--font-title);border:none;background:none;cursor:pointer;}

  .uppercase{text-transform:uppercase;}
  /* NOTE: the custom "9bares_offical-font.woff2" treatment was removed —
     the font file was corrupted/truncated on every upload attempt and
     never rendered correctly. Per the current rule, every visible
     brand-name mention ("9bares" / "9BARES" / "9 bares" / "9 BARES")
     is now just wrapped in <strong> instead, inheriting the existing
     font-family of its own section/context (no dedicated class needed —
     "strong" already carries its own default bold weight, and every
     section here already sets its own font-family upstream). */
  .sr-only{
    position:absolute;
    width:1px;height:1px;
    padding:0;margin:-1px;
    overflow:hidden;
    clip:rect(0,0,0,0);
    white-space:nowrap;
    border:0;
  }

  @media (prefers-reduced-motion:reduce){
    *{animation-duration:.001ms !important; transition-duration:.001ms !important;}
  }

  /* =========================================================
     FLOATING HEADER — left-edge tab/card, aligned with the exact left
     edge of the hero carousel/site-frame composition (not the raw
     browser edge). Uses the SAME --frame-inset variable as .site-frame
     (see GLOBAL VARIABLES), so the dark block always starts exactly
     where the frame starts — no independent formula that could drift
     a pixel apart and show a hairline gap/strip.
     The logo asset (icon/9bares_LOGO-flotante_Wh.svg) is alpha-only,
     so the dark #1C1C1C rectangular tab is built here in CSS instead of
     being baked into the SVG. The block is wide (generous horizontal
     padding) for proper breathing room around the logo; padding stays
     slightly biased right so the logo sits a little right of dead-center.
     Shares the same top + height as .hero-badge so both feel like one
     aligned header line (see HEADER ROW ALIGNMENT below).
     ========================================================= */
  .floating-header{
    position:fixed;
    top:var(--ticker-h);
    left:0;
    right:0;
    width:auto;
    height:var(--header-bar-h);
    z-index:300;
    display:flex;
    align-items:center;
    justify-content:flex-start;
    background:var(--dark);
    padding:0 28px 0 40px;
    /* full-width unified header bar: hamburger+logo stay left-aligned;
       the slogan+language badge (.hero-header-right, see below) docks to
       the right of this SAME row via its own fixed positioning — same
       top+height, so the two read as one continuous bar even though
       they're separate elements. */
  }
  .floating-logo{
    height:48px; /* enlarged from 38px, per request */
    width:auto;
    animation:headerLogoGlow 4s ease-in-out infinite;
  }
  /* subtle intermittent glow — mostly off, briefly rises to a soft
     cream glow once every 4s cycle, then fades back out. Elegant,
     not flashy: peak is a gentle drop-shadow, no scale/brightness change. */
  @keyframes headerLogoGlow{
    0%, 88%, 100%{ filter:drop-shadow(0 0 0 rgba(228,213,183,0)); }
    94%{ filter:drop-shadow(0 0 9px rgba(228,213,183,.6)); }
  }

  /* =========================================================
     MOBILE HEADER BRAND SWAP — solo en teléfonos. El logo 9bares
     queda centrado en el header y cada 5s hace un swipe-up con
     desvanecimiento que muestra el slogan, y vuelve al logo, en loop.
     En desktop está oculto: no cambia nada del diseño actual.
     ========================================================= */
  .mobile-brand-swap{ display:none; }
  /* Ciclo total 13s = logo 8s + slogan 5s. El swipe-up queda CONTENIDO
     dentro del header gracias a overflow:hidden en el contenedor. */
  @keyframes brandSwapLogo{
    0%     { opacity:1; transform:translateY(0); }       /* logo visible */
    61.54% { opacity:1; transform:translateY(0); }       /* ...hasta los 8s */
    63%    { opacity:0; transform:translateY(-100%); }   /* swipe up + fade out */
    63.1%  { opacity:0; transform:translateY(100%); }    /* reset abajo (invisible) */
    98.5%  { opacity:0; transform:translateY(100%); }
    100%   { opacity:1; transform:translateY(0); }       /* vuelve a entrar */
  }
  @keyframes brandSwapSlogan{
    0%     { opacity:0; transform:translateY(-100%); }
    0.1%   { opacity:0; transform:translateY(100%); }    /* esperando abajo */
    61.54% { opacity:0; transform:translateY(100%); }
    63%    { opacity:1; transform:translateY(0); }        /* swipe up + fade in (a los 8s) */
    98.5%  { opacity:1; transform:translateY(0); }        /* visible ~5s */
    100%   { opacity:0; transform:translateY(-100%); }    /* swipe up + fade out */
  }
  @media (max-width:680px){
    /* el logo de la izquierda y el slogan de la derecha se ocultan:
       ahora ese contenido vive en el swap centrado */
    .floating-header .floating-logo{ display:none; }
    .hero-badge p{ display:none; }

    .mobile-brand-swap{
      display:block;
      position:absolute;
      inset:0;
      z-index:2;
      overflow:hidden;                   /* el swipe no se sale del header */
      pointer-events:none;               /* los taps pasan al menú/idiomas */
    }
    .mobile-brand-swap .swap-item{
      position:absolute;
      inset:0;
      display:flex;
      align-items:center;
      justify-content:center;
      will-change:transform,opacity;
    }
    .swap-logo img{ height:32px; width:auto; display:block; }
    .swap-slogan{
      font-family:var(--font-body);
      font-weight:400;
      font-size:13px;
      letter-spacing:.3px;
      white-space:nowrap;
      color:var(--cream);
    }
    .swap-logo{   animation:brandSwapLogo   13s ease-in-out infinite; }
    .swap-slogan{ animation:brandSwapSlogan 13s ease-in-out infinite; }
  }
  /* accesibilidad: si el usuario pidió menos movimiento, sin animación
     (queda solo el logo fijo, centrado). */
  @media (max-width:680px) and (prefers-reduced-motion:reduce){
    .swap-logo{ animation:none; opacity:1; transform:none; }
    .swap-slogan{ display:none; }
  }

  /* =========================================================
     HEADER MENU ICON — three plain horizontal lines, sits to the
     left of the 9bares logo inside the same dark tab. Minimal,
     no circle/rounded button, no heavy hamburger UI.
     ========================================================= */
  .header-menu-toggle{
    display:flex;
    flex-direction:column;
    justify-content:center;
    gap:5px;
    width:22px;
    height:16px;
    margin-right:22px;
    flex-shrink:0;
    cursor:pointer;
  }
  .header-menu-toggle span{
    display:block;
    width:100%;
    height:2px;
    background:#787878;
    transition:background .3s var(--ease);
  }
  .header-menu-toggle:hover span{background:#9c9c9c;}

  /* sliding panel with the menu items — now shares the EXACT SAME left
     edge as the header tab (--frame-inset), not an offset formula: this
     is what keeps the button-container itself aligned to the logo's own
     container, per request. Each item's left PADDING (not the box) is
     what pushes the visible label text to start under the "9" — see
     .header-menu-item below. */
  .header-menu-panel{
    position:fixed;
    top:calc(var(--ticker-h) + var(--header-bar-h) + 10px);
    left:var(--frame-inset);
    z-index:290;
    display:flex;
    flex-direction:column;
    gap:2px;
    opacity:0;
    visibility:hidden;
    transform:translateY(-10px);
    transition:opacity .35s var(--ease), transform .35s var(--ease), visibility .35s var(--ease);
  }
  .header-menu-panel.open{
    opacity:1;
    visibility:visible;
    transform:translateY(0);
  }
  .header-menu-item{
    display:block;
    width:100%;
    background:rgba(28,28,28,0.70);
    color:var(--cream);
    font-family:var(--font-title);
    font-weight:700;
    font-size:12px;
    letter-spacing:1.5px;
    text-transform:uppercase;
    text-align:left; /* explicit: <button> defaults to centered text in
      some browsers, unlike <a> — without this, Showroom/Eventos/Tienda
      (buttons) drifted out of alignment with Servicio técnico (still an
      anchor). All four now render identically regardless of tag. */
    /* left padding = floating-header's own left padding (40px) + the
       hamburger icon width (22px) + its right margin (22px) = 84px from
       the shared left edge to where the logo/"9" itself starts, so every
       label text lines up under it. */
    padding:12px 24px 12px 84px;
    white-space:nowrap;
    border-radius:0;
    transition:background .3s var(--ease), color .3s var(--ease);
  }
  .header-menu-item:hover{background:rgba(28,28,28,0.92); color:#FFFFFF;}
  /* leading indicator — CSS-only, keeps the i18n string values clean/plain */
  .header-menu-item::before{
    content:'> ';
    opacity:.6;
  }

  /* =========================================================
     HERO — 5 slide carousel, full first screen. Brand divisions
     are only discovered by scrolling past this section.
     ========================================================= */
  .hero{
    position:relative;
    width:100%;
    /* aspect-ratio (not height:100vh) on purpose: the hero photos are
       native 16:9 (1920x1080). aspect-ratio derives the HERO's height
       purely from its own WIDTH, so it renders identically on mobile and
       desktop — both use the same fixed-canvas width (see the viewport
       meta + --frame-inset in <head>/<style>). height:100vh previously
       tied the hero's height to the device's own physical viewport
       height, which on a real phone (tall/portrait, even with the layout
       width pinned to the 1280 desktop reference) made the hero balloon
       into an oversized portrait box and crop the 16:9 photos down to a
       narrow 9:16 sliver. aspect-ratio removes that dependency entirely. */
    aspect-ratio:32/9; /* half the visual height of the previous 16/9, per request */
    min-height:360px; /* half of the previous 720px floor */
    overflow:hidden;
    background:var(--dark);
    /* pushes the hero photo down below the fixed ticker+header stack
       (see .floating-header / .hero-header-right below), so neither
       overlaps it — applies at every screen size now, not just mobile. */
    margin-top:calc(var(--ticker-h) + var(--header-bar-h));
  }
  .hero-slide{
    position:absolute;
    inset:0;
    opacity:0;
    transition:opacity .5s ease;
  }
  .hero-slide.active{opacity:1;}
  .hero-img{
    width:100%;
    height:100%;
    object-fit:cover;
    object-position:center 50%;
    /* scale(1.1) lives here permanently (not just on .active) — it used
       to be part of the active-only keyframe animation, so losing
       .active on slide change (outgoing slide) made the transform
       revert instantly to "none", i.e. a hard, visible snap/shrink back
       to 1:1 right as the crossfade started. Keeping it constant on
       every slide, active or not, means there's never a size jump —
       only the (much subtler) vertical drift below is active-only. */
    transform:scale(1.1);
  }
  /* subtle vertical pan/reveal — hero photos are now sourced taller than
     the hero's own wide/short 32:9 box (recommended upload size
     2820x1399), so object-fit:cover always has extra image above and
     below what's shown by default. Slowly drifting the image reveals
     that hidden top/bottom margin over time, Ken-Burns style, instead of
     it just sitting there unused. Only the ACTIVE slide animates (idle/
     background slides don't), and it restarts cleanly each time a slide
     becomes active since the .active class — and with it this animation
     — is freshly (re)applied by the carousel JS on every slide change.
     Animates transform (scale+translateY), NOT object-position: object-
     position changes force a repaint of the full-res image every frame,
     which is what caused the "tildado" stutter, especially right as a
     slide crosses over. transform runs on the compositor (GPU), so it
     stays smooth regardless of image size/decode cost. linear timing
     (not ease-in-out) removes the slow-start feel and the little hitch
     at each direction reversal — constant speed the whole way through,
     and the loop's start/end values match (both 35%-equivalent), so
     each restart on slide-change is seamless too, not a visible jump. */
  .hero-slide.active .hero-img{
    animation:heroImgPan 22s linear infinite;
    transform-origin:center center;
    will-change:transform;
  }
  @keyframes heroImgPan{
    0%{ transform:scale(1.1) translateY(-2.5%); }
    50%{ transform:scale(1.1) translateY(2.5%); }
    100%{ transform:scale(1.1) translateY(-2.5%); }
  }
  /* NOTE: scale(1.1) is repeated in every keyframe step on purpose — it's
     also the .hero-img base value now (see above), so losing .active
     mid-animation still lands exactly on scale(1.1), never a bare
     scale(1). Only translateY actually changes/animates. */
  /* accessibility: respect the OS-level "reduce motion" preference */
  @media (prefers-reduced-motion: reduce){
    .hero-slide.active .hero-img{ animation:none; }
  }
  /* NOTE: this used to have two hardcoded per-slide crop overrides tuned
     for the original fake_expo/cafe photos specifically. Removed on
     purpose — hero photos are now managed by uploading files (see
     images/hero/), so a crop tied to "slide #1" or "#4" would silently
     apply to whatever new, unrelated photo later lands in that slot.
     If a specific future photo needs a custom crop, compose/crop the
     source image itself before uploading it. */

  /* dark overlay for text readability over photography */
  .hero-overlay{
    position:absolute;
    inset:0;
    background:linear-gradient(180deg, rgba(28,28,28,0.3) 0%, rgba(28,28,28,0.18) 40%, rgba(28,28,28,0.7) 100%);
  }

  /* =========================================================
     UNIFIED HEADER — one fixed horizontal bar (#1C1C1C): logo+menu on
     the left (.floating-header), slogan+language switch on the right
     (.hero-header-right / .hero-badge). Both share the same top+height
     and dock to the SAME row; the badge has no background of its own
     (fully transparent) so the header tab's already-full-width dark
     fill reads as one continuous bar underneath it, logo left / slogan
     right — no separate cream box anymore. Applies at every screen
     size now (previously mobile-only; desktop used to have a separate
     "floating tab over the photo" look — retired in favor of this
     single unified design, per request). --ticker-h / --header-bar-h
     size the stack; --frame-inset stays for the flyout menu's left
     edge, redefined smaller for real phones further down. */
  .hero-header-right{
    position:fixed;
    top:var(--ticker-h);
    right:0;
    left:auto;
    width:auto;
    z-index:301;
  }
  /* the "closer to the logo" nudge only applies at real desktop widths.
     It was a flat -6px, which is fine against the desktop --ticker-h
     (22px) but is too aggressive at tablet/phone sizes where --ticker-h
     shrinks to 18px (or the marquee's own rendered height eats nearly
     all of it already) — applied everywhere, it made the badge overlap
     up into the ticker text on real phones. Scoped here so mobile keeps
     the safe, level (un-nudged) alignment it had before. */
  @media (min-width:1025px){
    .hero-header-right{ top:calc(var(--ticker-h) - 6px); }
  }
  .hero-badge{
    height:var(--header-bar-h);
    display:flex;
    align-items:center;
    justify-content:flex-end;
    gap:24px;
    background:transparent;
    color:var(--cream);
    padding:0 28px 0 20px;
  }
  .hero-badge p{
    font-family:var(--font-body);
    font-weight:400;
    font-size:14px;
    letter-spacing:.3px;
    line-height:1.4;
    text-align:left;
    white-space:nowrap;
    color:var(--cream); /* the removed cream BOX is now just cream TEXT, per request */
  }
  .hero-badge-langs{
    display:flex;
    align-items:center;
    gap:10px;
    flex-shrink:0;
  }
  .hero-badge-flag{
    height:16px;
    width:auto;
    display:block;
    opacity:.5;
    transition:opacity .3s var(--ease);
  }
  .hero-badge-lang:hover .hero-badge-flag,
  .hero-badge-lang.active .hero-badge-flag{opacity:1;}
  .hero-badge-lang-divider{
    width:1px;
    height:16px;
    background:rgba(228,213,183,0.35);
  }

  /* =========================================================
     HERO MARQUEE — now its own full-width strip ABOVE the header bar
     (ticker style), cream background (#E4D5B7) with dark (#1C1C1C)
     text, per request. position:fixed pulls it out of the DOM's normal
     flow regardless of where it's nested, so it can sit at the very
     top of the viewport independent of .hero-header-right below it.
     ========================================================= */
  .hero-marquee{
    position:fixed;
    top:0;
    left:0;
    right:0;
    width:auto;
    margin-top:0;
    z-index:302; /* above both the badge (301) and header tab (300) */
    background:var(--marquee-bg, var(--cream)); /* editable desde el panel */
    padding:4px 0; /* thinner strip, less visual weight — per request */
    overflow:hidden;
  }
  /* paused on hover so the user can read it without it slipping away */
  .hero-marquee:hover .hero-marquee-track{
    animation-play-state:paused;
  }
  .hero-marquee-track{
    display:flex;
    width:max-content;
    /* duration scaled up together with the 8x-per-half text repeat (see
       markup) — same px/s crawl speed as the original single-phrase
       version; 18s covered 1 copy, so 8 copies need ~8x the time to read
       at the same pace. Was 18s (way too fast once the content got 8x
       longer with the same duration), per request. */
    animation:heroMarqueeScroll 150s linear infinite;
  }
  .hero-marquee-track span{
    flex-shrink:0;
    white-space:nowrap;
    font-family:var(--font-body);
    font-weight:400;
    font-size:9px; /* shrunk from 11px, less protagonist — per request */
    letter-spacing:.4px;
    color:var(--marquee-color, var(--dark)); /* editable desde el panel */
    /* tightened from 14px — at that width the gap between repeats read
       as an oversized indent/tab, breaking the "///"-separator rhythm
       used WITHIN the phrase itself. This now roughly matches that same
       internal spacing, so the repeat boundary reads as just another
       "///" beat instead of a stray gap. */
    padding-right:4px;
  }
  @keyframes heroMarqueeScroll{
    from{ transform:translateX(0); }
    to{ transform:translateX(-50%); }
  }

  /* changing per-slide copy — now the main visual message of the hero.
     Pure white (not cream) so it reads as the dominant hero message;
     the .hero-badge phrase box keeps its cream treatment separately. */
  .hero-content{
    position:absolute;
    left:6%;
    right:6%;
    bottom:12%; /* lowered from 22% — was landing on top of important parts of the photos, per request */
    z-index:5;
    max-width:620px; /* narrowed from 900px so the headline actually wraps to ~2 lines instead of sitting on one, per request */
    color:#FFFFFF;
  }
  .hero-headline{
    font-family:var(--font-title);
    font-weight:700;
    font-size:clamp(18px, calc(2.6 * var(--frozen-vw)), 32px);
    line-height:1.25;
    letter-spacing:.2px;
    text-shadow:0 3px 20px rgba(0,0,0,.55);
    transition:opacity .4s ease; /* smooth cross-fade between slide texts */
    /* balances line lengths across the wrap instead of leaving a lone
       orphan word on the last line (e.g. 4 words / 2 words instead of
       6 words / 1 word) — exactly the "nunca una sola palabra debajo de
       una línea completa" rule, handled natively instead of hardcoding
       a <br> per headline/language. Falls back to normal wrapping on
       browsers that don't support it yet — never breaks anything. */
    text-wrap:balance;
  }
  .hero-headline.fading{opacity:0;}

  .hero-dots{
    position:absolute;
    right:6%;
    bottom:12%;
    z-index:6;
    display:flex;
    gap:10px;
  }
  .hero-dots button{
    width:9px;height:9px;border-radius:50%;
    background:rgba(228,213,183,0.4);
    padding:0;
    transition:background .3s, transform .3s;
  }
  .hero-dots button.active{
    background:var(--cream);
    transform:scale(1.25);
  }

  /* refined mosaic wipe used between hero slides */
  .mosaic-overlay{
    position:absolute;
    inset:0;
    z-index:4;
    display:grid;
    grid-template-columns:repeat(12,1fr);
    grid-template-rows:repeat(7,1fr);
    pointer-events:none;
  }
  .mosaic-tile{background:var(--dark); opacity:0;}
  .mosaic-tile.show{animation:tileFade .9s ease forwards;}
  @keyframes tileFade{
    0%{opacity:0;}
    40%{opacity:.88;}
    60%{opacity:.88;}
    100%{opacity:0;}
  }

  /* =========================================================
     CATALOG DIVIDER — thin #000000 band between the hero carousel and
     the brand divisions, per request. min-height (not a fixed height)
     so it never clips the label if it ever has to wrap on a very
     narrow phone.
     ========================================================= */
  .catalog-divider{
    background:#000000;
    color:#FFFFFF;
    font-family:var(--font-body); /* Janna LT Regular */
    font-weight:400;
    font-size:13px;
    letter-spacing:2px;
    text-transform:uppercase;
    text-align:center;
    min-height:40px;
    display:flex;
    align-items:center;
    justify-content:center;
    padding:8px 20px;
  }

  /* =========================================================
     BRAND DIVISIONS — row 1: 2 large, row 2: 4 small
     ========================================================= */
  .brands{
    display:flex;
    flex-direction:column;
    gap:0; /* cards sit flush against each other, no separators */
    padding:0;
    background:var(--dark);
  }
  /* flex (not grid) so the hovered division can actually grow while its
     neighbors compress — the row's total width always stays 100%, so
     there are never gaps or jumps. */
  .brands-row{display:flex;}
  .brand-card--large,
  .brand-card--small{
    flex:1 1 0%;
    min-width:0; /* allow smooth shrinking below intrinsic content size */
    transition:flex-grow .6s var(--ease);
  }
  /* 2-card row: kept more subtle than the 4-card row below —
     hovered card grows from 50% to ~54% share (+8%) */
  .brand-card--large:hover{flex-grow:1.17;}
  /* 4-card row: hovered card grows from 25% to ~28.75% share (+15%) */
  .brand-card--small:hover{flex-grow:1.21;}

  .brand-card{
    position:relative;
    overflow:hidden;
    border-radius:0; /* hard rectangular editorial block, no frame */
    border:none;
    outline:none;
    isolation:isolate;
    cursor:pointer;
  }
  .brand-card--large{height:clamp(360px, calc(38 * var(--frozen-vw)), 520px);}
  .brand-card--small{height:clamp(260px, calc(20 * var(--frozen-vw)), 360px);}

  /* the division itself is the main hover animation (flex-grow above).
     The image only gets a subtle brightness/contrast lift for polish. */
  .division-img{
    position:absolute;
    inset:0;
    width:100%;
    height:100%;
    object-fit:cover;
    filter:brightness(.78) saturate(.88) contrast(1.05);
    transition:filter .6s var(--ease), transform .6s var(--ease);
  }
  .brand-card:hover .division-img{
    filter:brightness(.98) saturate(1.05) contrast(1.08);
    transform:scale(1.03);
  }

  /* consistent darkening for logo/text contrast */
  .division-overlay{
    position:absolute;
    inset:0;
    background:rgba(28,28,28,0.48);
    transition:background .6s var(--ease);
  }
  .brand-card:hover .division-overlay{
    background:rgba(28,28,28,0.28);
  }

  /* single soft brand-color glow, ~10% opacity, blurred radial wash — upper-right only */
  .division-glow{
    position:absolute;
    top:-15%;
    right:-10%;
    width:65%;
    height:65%;
    background:radial-gradient(circle, var(--accent) 0%, transparent 70%);
    opacity:.5;
    filter:blur(50px);
    mix-blend-mode:screen;
    pointer-events:none;
  }

  .division-content{
    position:relative;
    z-index:2;
    height:100%;
    display:flex;
    flex-direction:column;
    align-items:center;
    justify-content:center;
    gap:14px;
    padding:20px;
    text-align:center;
  }
  .division-logo{
    max-width:64%;
    max-height:78px;
    width:auto;
    height:auto;
    filter:drop-shadow(0 3px 12px rgba(0,0,0,.55));
    transition:transform .4s var(--ease);
  }
  .brand-card--large .division-logo{max-height:96px;}
  .brand-card:hover .division-logo{transform:translateY(-2px) scale(1.03);}
  /* Eureka logo reads small next to the others — sized up specifically */
  .brand-card--eureka .division-logo{max-height:118px; max-width:82%;}

  .division-cta{
    font-family:var(--font-title);
    font-size:11px;
    font-weight:700;
    letter-spacing:2px;
    text-transform:uppercase;
    color:var(--cream);
    padding-bottom:3px;
    border-bottom:1px solid rgba(228,213,183,.6);
    opacity:0;
    transform:translateY(6px);
    transition:opacity .35s var(--ease), transform .35s var(--ease);
  }
  .brand-card:hover .division-cta{
    opacity:1;
    transform:translateY(0);
  }

  /* =========================================================
     ABOUT / COMPANY DESCRIPTION — editorial row: title | divider | text.
     No longer a single centered vertical block; kept compact, no
     excessive vertical padding.
     ========================================================= */
  .about{
    background:var(--cream);
    /* horizontal inset moved to .about-inner only, so .tec-espresso (a
       sibling) can span the FULL available width edge-to-edge instead of
       being boxed in by this section's own side padding. Bottom padding
       stays at 0 (not reintroduced): it was leaving a visible #E4D5B7
       cream strip between .tec-espresso's own bottom edge and whatever
       section follows it — .tec-espresso already carries its own
       margin-top for breathing room above, so this section can end
       flush right where the dark box ends. Top padding nudged down from
       48px to roughly match that same 28px margin-top on .tec-espresso,
       so the ¿Quiénes somos? block sits vertically centered in its band
       instead of pushed down. */
    padding:28px 0 0;
  }
  /* reverted to the previous asymmetric flex layout: fixed-width title
     column on the left, divider, description column taking the rest. */
  .about-inner{
    display:flex;
    align-items:center; /* title vertically centered against the description */
    gap:clamp(24px, calc(4 * var(--frozen-vw)), 56px);
    padding:0 8%; /* no max-width cap — spans the section's full width */
  }
  .about-title-col{
    flex-shrink:0;
  }
  .about-title{
    font-family:var(--font-title); /* Montserrat Bold */
    font-weight:800;
    font-size:clamp(18px, calc(1.8 * var(--frozen-vw)), 24px);
    letter-spacing:1.5px;
    text-transform:uppercase;
    white-space:nowrap;
    text-align:left;
  }
  .about-divider{
    width:1px;
    align-self:stretch;
    background:rgba(28,28,28,0.35);
    flex-shrink:0;
  }
  .about-desc-col{
    flex:1;
    min-width:0;
  }
  /* sentence case, 1 explicit line break splitting the text into the 2
     exact lines requested; full-width column (no cap), and the section's
     own 8% side padding keeps the outer margins symmetric on both sides. */
  .about-text{
    font-family:var(--font-body);
    font-size:clamp(15px, calc(1.4 * var(--frozen-vw)), 18px);
    line-height:1.7;
    color:var(--dark);
    text-align:left;
    /* reparte el texto en líneas parejas para que no queden palabras
       sueltas colgando al final (queda en ~3 líneas). */
    text-wrap:balance;
    max-width:62ch;
  }

  /* =========================================================
     TECNICAMENTE ESPRESSO — full redesign: dimmed division-style photo
     background (20% opacity image over a solid black base, matching the
     brand-card "division" treatment elsewhere on the site) with a
     centered gold-bordered black callout box holding the wordmark
     headline, a description line below it, and both brand logos
     underneath. A plain block in normal flow (same "no 100vw / no
     negative margins" approach as before) so it still spans the
     section's full width edge-to-edge within the site-frame.
     ========================================================= */
  .tec-espresso{
    position:relative;
    margin-top:28px;
    background:#000000; /* base behind the 20%-opacity photo */
    overflow:hidden;
  }
  .tec-espresso-bg{
    position:absolute;
    inset:0;
    width:100%;
    height:100%;
    object-fit:cover;
    opacity:.2;
  }
  .tec-espresso-content{
    position:relative;
    z-index:1;
    display:flex;
    flex-direction:column;
    align-items:center;
    text-align:center;
    gap:26px;
    padding:clamp(56px, calc(7 * var(--frozen-vw)), 88px) clamp(20px, calc(5 * var(--frozen-vw)), 56px);
  }
  /* gold-stroked black box — now a single horizontal row holding the
     headline text AND the garantía seal together, so the icon reads as
     part of the same bordered callout instead of sitting separately
     below it (per reference). */
  .tec-espresso-box{
    background:#000000;
    border:1.5px solid #F4CA54;
    padding:14px clamp(24px, calc(3.5 * var(--frozen-vw)), 44px);
    max-width:min(820px, 92%);
    display:flex;
    align-items:center;
    justify-content:center;
    gap:16px;
  }
  .tec-espresso-headline{
    font-family:var(--font-title);
    font-weight:700;
    font-size:clamp(15px, calc(1.5 * var(--frozen-vw)), 20px);
    letter-spacing:.3px;
    line-height:1.5;
    color:#FFFFFF;
    white-space:nowrap; /* stays one line so the seal fits at its end */
  }
  /* garantía seal now lives INSIDE the gold box, at the end of the
     headline row — fixed px so it never overpowers the text. */
  .tec-espresso-box .tec-espresso-seal{
    height:69px; /* +40% from the previous 49px */
    width:auto;
    flex-shrink:0;
    display:block;
  }
  /* Fixed, non-responsive size (plain px, not tied to --frozen-vw) so
     this description always renders as the same two lines, at the same
     size, regardless of viewport — per request. */
  .tec-espresso-desc{
    font-family:var(--font-body);
    font-weight:400;
    font-size:13px;
    line-height:1.6;
    letter-spacing:.2px;
    color:#FFFFFF;
    max-width:640px;
    text-transform:uppercase; /* texto de TE en mayúsculas */
  }
  .tec-espresso-logos{
    display:flex;
    align-items:center;
    justify-content:center;
    margin-top:6px;
  }
  /* Botón "SOLICITAR ASISTENCIA": va DEBAJO del logo de TE (que se mantiene),
     estilo crema a tono con el recuadro de arriba, abre WhatsApp de TE. */
  /* -20% de escala respecto al tamaño anterior (font 14->11.2, padding
     14/30 -> 11/24) y color #f4ca54. */
  .tec-espresso-cta{
    display:inline-block;
    margin-top:20px;
    font-family:var(--font-body);
    font-weight:700;
    font-size:11.2px;
    letter-spacing:1px;
    text-decoration:none;
    color:var(--dark);
    background:#f4ca54;
    border:1px solid #f4ca54;
    padding:11px 24px;
    border-radius:5px;
    transition:transform .25s ease, background .25s ease, color .25s ease, box-shadow .25s ease;
    box-shadow:0 8px 20px rgba(0,0,0,.35);
  }
  .tec-espresso-cta:hover{
    transform:translateY(-2px);
    background:transparent;
    color:#f4ca54;
    box-shadow:0 12px 28px rgba(0,0,0,.5);
  }

  /* WIDGET FLOTANTE DE WHATSAPP — botón + cartel de diálogo, abajo a la
     derecha, sobre todo. El SVG ya trae la burbuja verde: sin fondo extra. */
  .whatsapp-widget{
    position:fixed;
    right:22px;
    bottom:22px;
    z-index:900;
    display:flex;
    align-items:center;
    gap:12px;
  }
  .whatsapp-float{
    display:block;
    line-height:0;
    flex-shrink:0;
    filter:drop-shadow(0 6px 14px rgba(0,0,0,.4));
    transition:transform .25s ease, filter .25s ease;
  }
  .whatsapp-float img{ display:block; width:60px; height:60px; }
  /* Ocultar el WhatsApp flotante cuando hay un drawer de marca, un popup
     o un modal abierto, para que el ícono no pise esos botones/paneles. */
  body.drawer-open .whatsapp-widget,
  body.popup-open .whatsapp-widget,
  body.modal-open .whatsapp-widget{ display:none; }
  .whatsapp-float:hover{
    transform:scale(1.08);
    filter:drop-shadow(0 10px 22px rgba(0,0,0,.55));
  }
  /* Cartel de diálogo: aparece a los 10s (clase .show desde main.js).
     Contenedor negro 50% opacidad, letras blancas. */
  .whatsapp-bubble{
    position:relative;
    background:rgba(0,0,0,.5);
    color:#fff;
    font-family:var(--font-body);
    font-size:14px;
    line-height:1.2;
    white-space:nowrap;
    text-decoration:none;
    padding:11px 16px;
    border-radius:22px;
    box-shadow:0 4px 14px rgba(0,0,0,.3);
    opacity:0;
    transform:translateX(10px);
    pointer-events:none;
    transition:opacity .4s ease, transform .4s ease;
  }
  /* pico del cartel apuntando al ícono (a la derecha) */
  .whatsapp-bubble::after{
    content:"";
    position:absolute;
    top:50%;
    right:-6px;
    width:0;height:0;
    transform:translateY(-50%);
    border-top:6px solid transparent;
    border-bottom:6px solid transparent;
    border-left:7px solid rgba(0,0,0,.5);
  }
  .whatsapp-bubble.show{
    opacity:1;
    transform:none;
    pointer-events:auto;
  }
  @media (max-width:640px){
    .whatsapp-widget{ right:16px; bottom:16px; gap:9px; }
    .whatsapp-float img{ width:54px; height:54px; }
    .whatsapp-bubble{ font-size:12.5px; padding:9px 13px; }
  }
  .tec-espresso-logo{
    width:auto;
    display:block;
    filter:drop-shadow(0 8px 20px rgba(0,0,0,.45));
    transition:transform .3s ease, filter .3s ease;
  }
  /* standalone TE logo, centered below the description: scaled up
     another +20% from the previous 89px baseline (89 * 1.2 ≈ 107px)
     now that it's the only mark in this row. */
  .tec-espresso-logo{
    height:107px;
  }
  .tec-espresso-logos a:hover .tec-espresso-logo{
    transform:scale(1.06);
    filter:drop-shadow(0 12px 28px rgba(0,0,0,.55));
  }
  /* gold treatment for TÉCNICAMENTE ESPRESSO specifically inside this
     section — the About section used to keep the wordmark cream; now it
     matches the hero-slide gold treatment, since the box itself is black */
  .tec-espresso .brand-optima-normal,
  .tec-espresso .brand-optima-bold{
    color:#F4CA54;
  }
  /* brand treatment applied only to these two words */
  .brand-optima-normal{
    font-family:'Optima Normal', var(--font-title);
    font-weight:400;
    letter-spacing:.5px;
  }
  .brand-optima-bold{
    font-family:'Optima Bold', var(--font-title);
    font-weight:700;
    letter-spacing:.5px;
  }
  /* the "TECNICAMENTE ESPRESSO" hero slide only: brand wordmark reads in
     yellow against the dark hero photography (the About-section highlight
     box keeps its own cream color untouched, scoped separately here) */
  .hero-headline .brand-optima-normal,
  .hero-headline .brand-optima-bold{
    color:#F4CA54;
  }
  /* clickable wrapper around "TÉCNICAMENTE ESPRESSO" — inherits the
     cream text color (a{color:inherit} above), so it never looks like
     a default blue browser link */
  .brand-link{transition:opacity .3s var(--ease);}
  .brand-link:hover{opacity:.8;}

  /* =========================================================
     NEWSLETTER — dark #1C1C1C subscribe strip, now below Contacto and
     above the Footer, continuing the same dark run (per reference image
     — the whole tail of the site reads as one seamless dark block).
     ========================================================= */
  .newsletter{
    background:var(--dark);
    color:var(--cream);
    padding:24px clamp(24px, calc(5 * var(--frozen-vw)), 56px) 36px;
  }
  /* narrowed to match the email+button row's own width, so the CTA
     text wraps to sit inside that same block instead of stretching
     into one very long line above a much narrower form. */
  .newsletter-inner{
    max-width:440px;
    margin:0 auto;
    display:flex;
    flex-direction:column;
    align-items:center;
    text-align:center;
    gap:14px;
  }
  .newsletter-text{
    font-family:var(--font-title); /* Montserrat Variable */
    font-weight:400; /* regular, not bold — per request */
    font-size:clamp(11px, calc(1.05 * var(--frozen-vw)), 13px); /* shrunk further, per request */
    line-height:1.5;
    letter-spacing:.3px;
    text-transform:uppercase;
  }
  /* Caja de suscripción UNIFICADA: input + botón dentro de un mismo
     contenedor con borde común, sin separación. */
  .newsletter-form{
    display:flex;
    align-items:stretch;
    gap:0;
    width:100%;
    max-width:460px;
    border:1px solid rgba(228,213,183,.4);
    border-radius:6px;
    overflow:hidden;
  }
  .newsletter-input{
    flex:1 1 auto;
    min-width:0;
    background:transparent;
    border:none;
    color:var(--cream);
    padding:13px 18px;
    font-family:var(--font-body);
    font-size:14px;
    transition:border-color .3s var(--ease);
  }
  .newsletter-input::placeholder{color:rgba(228,213,183,.5);}
  .newsletter-input:focus{outline:none; border-color:var(--cream);}
  .newsletter-btn{
    flex-shrink:0;
    background:var(--cream);
    color:#111111;
    font-weight:700;
    font-size:12px;
    letter-spacing:1.5px;
    text-transform:uppercase;
    padding:13px 26px;
    border:none;
    cursor:pointer;
    transition:background .3s var(--ease), transform .3s var(--ease);
  }
  .newsletter-btn:hover{background:#FFFFFF; transform:translateY(-1px);}
  .newsletter-success{
    font-family:var(--font-body);
    font-size:14px;
    color:var(--cream);
    opacity:.9;
  }

  /* =========================================================
     CONTACT / SOCIAL — title removed (was oversized, added no real
     information); just the social buttons, centered in the section.
     ========================================================= */
  .contact{
    background:var(--dark);
    color:var(--cream);
    padding:32px 8% 20px;
  }
  .contact-inner{
    display:flex;
    flex-direction:column;
    align-items:center;
    justify-content:center;
    gap:16px;
    max-width:1040px;
    margin:0 auto;
  }
  /* "9" mark moved up above the social buttons (redes), per request */
  .contact-icon{
    height:28px;
    width:auto;
  }
  .social-grid{
    display:flex;
    flex-wrap:wrap; /* if it ever doesn't fit one line, wrap instead of overflow */
    justify-content:center;
    gap:10px;
  }
  /* social buttons follow the box system — Option A: cream bg, dark text.
     Slightly more compact than before so all 5 fit comfortably on one line. */
  .social-btn{
    font-family:var(--font-title);
    font-size:11px;
    font-weight:700;
    letter-spacing:1px;
    text-transform:uppercase;
    background:var(--cream);
    color:var(--dark);
    padding:11px 18px;
    white-space:nowrap;
    border-radius:0;
    transition:background .3s var(--ease), color .3s var(--ease), transform .3s var(--ease);
  }
  .social-btn:hover{
    background:transparent;
    color:var(--cream);
    box-shadow:inset 0 0 0 1px var(--cream);
    transform:translateY(-2px);
  }

  /* legal links — now live in the footer, between the logo and the
     copyright line, spaced via the footer's own flex gap (see below) */
  .legal-links{
    display:flex;
    flex-wrap:wrap;
    justify-content:center;
    gap:18px;
  }
  .legal-link{
    font-family:var(--font-body);
    font-size:12px;
    color:rgba(228,213,183,.7);
    text-decoration:underline;
    text-underline-offset:3px;
  }
  .legal-link:hover{color:var(--cream);}

  /* =========================================================
     MODALS — legal popups
     ========================================================= */
  .modal-overlay{
    position:fixed;
    inset:0;
    z-index:500;
    background:rgba(28,28,28,0.72);
    display:flex;
    align-items:center;
    justify-content:center;
    padding:24px;
    opacity:0;
    visibility:hidden;
    transition:opacity .3s var(--ease), visibility .3s var(--ease);
  }
  .modal-overlay.open{opacity:1; visibility:visible;}
  .modal-box{
    position:relative;
    background:var(--cream);
    color:var(--dark);
    max-width:640px;
    width:100%;
    max-height:80vh;
    overflow-y:auto;
    border-radius:0;
    padding:44px 36px 36px;
    transform:translateY(16px);
    transition:transform .3s var(--ease);
  }
  .modal-overlay.open .modal-box{transform:translateY(0);}
  .modal-box h3{
    font-size:20px;
    font-weight:800;
    text-transform:uppercase;
    letter-spacing:1px;
    margin-bottom:18px;
  }
  .modal-box p{
    font-family:var(--font-body);
    font-size:14px;
    line-height:1.7;
    margin-bottom:14px;
  }
  .modal-close{
    position:absolute;
    top:14px;
    right:16px;
    font-size:22px;
    line-height:1;
    color:var(--dark);
    width:34px;
    height:34px;
    border-radius:0;
    transition:background .3s;
  }
  .modal-close:hover{background:rgba(28,28,28,0.08);}
  body.modal-open{overflow:hidden;}

  /* =========================================================
     FOOTER — one clean compact block, in order: logo, legal links,
     copyright. A single flex column with a consistent gap replaces
     per-element margins, so spacing reads even and symmetrical.
     ========================================================= */
  .site-footer{
    /* pure black, distinct from the #1C1C1C used by Contacto/Suscripción
       right above it, so the legal links + copyright line don't visually
       blend into (or compete with) those sections. */
    background:#000000;
    color:var(--cream);
    text-align:center;
    padding:18px 8% 18px;
    font-size:12px;
    letter-spacing:.5px;
    display:flex;
    flex-direction:column;
    align-items:center;
    gap:8px;
  }
  /* transparent/alpha SVG — no box or frame needed behind it */
  .footer-logo{
    height:34px;
    width:auto;
  }

  /* =========================================================
     BRAND INFO DRAWER — slides in from the right, "data sheet" style
     Base structure prepared now; real per-brand copy pending.
     ========================================================= */
  .drawer-backdrop{
    position:fixed;
    inset:0;
    z-index:590;
    background:rgba(28,28,28,0.55);
    opacity:0;
    visibility:hidden;
    transition:opacity .35s var(--ease), visibility .35s var(--ease);
  }
  .drawer-backdrop.open{opacity:1; visibility:visible;}

  .brand-drawer{
    position:fixed;
    top:0;
    right:0;
    height:100%;
    width:min(440px, 92vw);
    background:var(--dark);
    color:var(--cream);
    z-index:600;
    overflow-y:auto;
    transform:translateX(100%);
    transition:transform .45s var(--ease);
  }
  .brand-drawer.open{transform:translateX(0);}

  .brand-drawer-inner{
    position:relative;
    padding:64px 32px 48px;
    display:flex;
    flex-direction:column;
    gap:22px;
  }
  .drawer-close{
    position:absolute;
    top:18px;
    right:20px;
    width:36px;
    height:36px;
    font-size:24px;
    line-height:1;
    color:var(--cream);
    border-radius:0;
    transition:background .3s;
  }
  .drawer-close:hover{background:rgba(228,213,183,0.12);}

  /* logo shown directly on the dark drawer background — no colored
     box/frame behind it, per the brand's own logo treatment */
  .drawer-logo-wrap{
    padding:8px 0 4px;
    display:flex;
    align-items:center;
    justify-content:center;
  }
  .drawer-logo{max-height:64px; width:auto;}

  /* model selectors — only rendered for brands with more than one model
     (La Rocca, Markibar, Cunill, Remidag); Triangle/Eureka are single-model
     so this stays empty for them. Clicking a name switches the gallery
     below to that model's own photos, in Janna LT (the body font). */
  .drawer-model-selectors{
    display:flex;
    flex-wrap:nowrap; /* reduced font/gap below keeps the longest list (4 Remidag names) on one row */
    justify-content:center;
    gap:5px 10px;
    padding:0 2px 4px;
  }
  .drawer-model-btn{
    font-family:var(--font-body);
    font-size:10px;
    letter-spacing:.3px;
    text-transform:uppercase;
    color:rgba(228,213,183,.55);
    padding:2px 1px;
    white-space:nowrap;
    border-bottom:1px solid transparent;
    transition:color .3s var(--ease), border-color .3s var(--ease);
  }
  .drawer-model-btn:hover{color:var(--cream);}
  .drawer-model-btn.active{color:var(--cream); border-bottom-color:var(--cream);}

  /* quick carousel — slide count varies per brand (see BRAND_MODELS in
     the script below); slides are rendered dynamically into
     #drawerSlides. Sits below the brand logo, minimal 3px rounded
     corners (per request), no colored box. The prev/next arrows are
     now OUTSIDE the image frame (flex siblings in .drawer-carousel-row),
     not overlapping the product photo. Clicking/tapping the image opens
     the lightbox (see IMAGE LIGHTBOX below). */
  .drawer-carousel-row{
    display:flex;
    align-items:center;
    gap:8px;
  }
  .drawer-carousel{
    position:relative;
    flex:1;
    min-width:0;
    aspect-ratio:4/3;
    overflow:hidden;
    background:#000;
    border-radius:3px;
    cursor:zoom-in;
  }
  .drawer-slides{position:absolute; inset:0;}
  .drawer-slide{
    position:absolute;
    inset:0;
    opacity:0;
    transition:opacity .4s var(--ease);
  }
  .drawer-slide.active{opacity:1;}
  .drawer-slide img{width:100%; height:100%; object-fit:cover;}
  /* single-model brands (Triangle, Eureka) don't need prev/next arrows —
     JS toggles 'single-slide' on the ROW (id="drawerCarousel"), which now
     hides these flex-sibling arrow buttons instead of absolute children */
  .drawer-carousel-row.single-slide .drawer-carousel-arrow{display:none;}

  .drawer-carousel-arrow{
    flex-shrink:0;
    width:32px;
    height:32px;
    display:flex;
    align-items:center;
    justify-content:center;
    background:rgba(28,28,28,0.6);
    color:var(--cream);
    font-size:18px;
    line-height:1;
    border-radius:0;
    transition:background .3s var(--ease);
  }
  .drawer-carousel-arrow:hover{background:rgba(28,28,28,0.85);}

  /* series label (e.g. "SERIE VENEZIA") — smaller, sits above the model
     title so the two are never on the same visual level. Empty/hidden
     for brands or slides without a series name. Centered (along with
     the name/text below it) so the whole model block reads centered
     directly under the selected model's photo. */
  .drawer-series{
    font-family:var(--font-title);
    font-weight:700;
    text-transform:uppercase;
    letter-spacing:2px;
    font-size:11px;
    opacity:.65;
    margin-bottom:-14px;
    text-align:center;
  }
  .drawer-name{
    font-family:var(--font-title);
    font-weight:800;
    text-transform:uppercase;
    letter-spacing:1px;
    font-size:20px;
    text-align:center;
  }
  .drawer-text{
    font-family:var(--font-body);
    text-align:center;
    font-size:14px;
    line-height:1.7;
    opacity:.9;
  }

  /* CTA — Option A box: cream bg, dark text, Montserrat Bold, rectangular */
  .drawer-cta{
    display:block;
    text-align:center;
    background:var(--cream);
    color:var(--dark);
    font-family:var(--font-title);
    font-weight:700;
    font-size:13px;
    letter-spacing:.3px;
    padding:14px 18px;
    border-radius:0;
    margin-top:auto;
    transition:opacity .3s var(--ease);
  }
  .drawer-cta:hover{opacity:.85;}

  body.drawer-open{overflow:hidden;}

  /* =========================================================
     IMAGE LIGHTBOX — opened from a click/tap on the drawer's product
     photo. Fixed, full-viewport overlay with the image centered and
     scaled to fit. On hover-capable pointers, mousemove over the stage
     scales the image up and shifts its transform-origin to the cursor
     position (magnifier effect); on touch, tapping just shows the
     enlarged photo and native pinch-zoom still works normally.
     ========================================================= */
  .image-lightbox{
    position:fixed;
    inset:0;
    z-index:700;
    background:rgba(28,28,28,0.92);
    display:flex;
    align-items:center;
    justify-content:center;
    padding:40px;
    opacity:0;
    visibility:hidden;
    transition:opacity .3s var(--ease), visibility .3s var(--ease);
  }
  .image-lightbox.open{opacity:1; visibility:visible;}
  .lightbox-stage{
    position:relative;
    max-width:90vw;
    max-height:85vh;
    overflow:hidden;
    border-radius:3px;
    cursor:zoom-in;
  }
  .lightbox-stage img{
    display:block;
    max-width:90vw;
    max-height:85vh;
    width:auto;
    height:auto;
    object-fit:contain;
    transform-origin:center center;
    transition:transform .15s ease-out;
  }
  .lightbox-close{
    position:fixed;
    top:20px;
    right:28px;
    z-index:710;
    width:44px;
    height:44px;
    font-size:28px;
    line-height:1;
    color:var(--cream);
    border-radius:0;
    transition:background .3s;
  }
  .lightbox-close:hover{background:rgba(228,213,183,0.12);}

  /* =========================================================
     MOBILE-ONLY DRAWER — kept from v4: (hover:none) and (pointer:coarse)
     key off the device's actual INPUT capability (true on touch-primary
     devices regardless of window width), so the brand drawer goes full
     screen on any real phone/tablet even if it happens to be in a wide
     landscape orientation, while desktop mice keep the narrow side panel.
     Works alongside the max-width breakpoints below, not instead of them. */
  @media (hover:none) and (pointer:coarse){
    .brand-drawer{
      width:100%;
    }
  }

  /* =========================================================
     MOBILE RESPONSIVE (v5) — real breakpoints, now that the viewport
     meta is width=device-width instead of a fixed 1280 (see <head>).
     Two tiers: (max-width:1024px) handles the structural restacking
     (every horizontal desktop row becomes a vertical mobile column —
     About, Técnicamente Espresso, the brand grid, the hero badge/
     marquee) and applies to tablets and phones alike since max-width
     queries cascade down; (max-width:680px) and (max-width:480px) layer
     on top with progressively tighter spacing/type sizing for real
     phones. Desktop (>1024px real window) is completely unaffected.
     ========================================================= */
  @media (max-width:1024px){
    /* HERO — aspect-ratio alone drives the height, but with NO floor at
       all (the old min-height:0) it collapsed to ~100-150px on real
       phones, well past "compact" into "broken". Restored a sensible
       floor, smaller than the desktop one (still much shorter than the
       pre-v8 design, per the original "halve it" request). */
    .hero{ min-height:220px; }

    /* the unified header/ticker/badge (see base rules above) applies at
       every screen size already — this tier just tightens type sizes
       for narrower windows. */
    .hero-marquee-track span{ font-size:9px; }
    .hero-badge p{ white-space:normal; font-size:12px; }
    .hero-content{ bottom:10%; max-width:520px; }
    .hero-headline{ font-size:clamp(16px, calc(3.2 * var(--frozen-vw)), 26px); }

    /* BRAND GRID — 2 columns instead of the desktop 2-large/4-small
       horizontal rows, which were far too squeezed under ~1024px. */
    .brands-row{ flex-wrap:wrap; }
    .brand-card--large,
    .brand-card--small{
      flex:1 1 50%;
    }
    .brand-card--large:hover,
    .brand-card--small:hover{ flex-grow:1; } /* no hover-driven width jump on touch */
    .brand-card--large{ height:clamp(280px, calc(46 * var(--frozen-vw)), 420px); }
    .brand-card--small{ height:clamp(220px, calc(38 * var(--frozen-vw)), 320px); }

    /* ABOUT — stack title above text instead of a fixed-width title
       column squeezing an ever-narrower text column. */
    .about-inner{
      flex-direction:column;
      align-items:flex-start;
      gap:16px;
    }
    .about-title{ white-space:normal; }
    .about-divider{
      width:100%;
      height:1px;
      align-self:auto;
    }

    /* TÉCNICAMENTE ESPRESSO — stack the headline text above the seal
       instead of forcing them onto one nowrap row (which overflowed on
       narrow screens), and let the headline itself wrap. */
    .tec-espresso-content{
      padding:clamp(36px, calc(8 * var(--frozen-vw)), 56px) 20px;
      gap:20px;
    }
    .tec-espresso-box{
      flex-direction:column;
      gap:14px;
    }
    .tec-espresso-headline{
      white-space:normal;
    }
  }

  @media (max-width:680px){
    /* BRAND GRID — single column on real phones; 2-up was still tight
       once card padding/logo sizing is factored in below ~680px. */
    .brands-row{ flex-wrap:wrap; }
    .brand-card--large,
    .brand-card--small{
      flex:1 1 100%;
    }
    .brand-card--large{ height:clamp(240px, calc(70 * var(--frozen-vw)), 320px); }
    .brand-card--small{ height:clamp(200px, calc(58 * var(--frozen-vw)), 260px); }

    /* overriding the shared variable (not .site-frame's margin directly)
       keeps .floating-header / .header-menu-panel's left:var(--frame-inset)
       perfectly aligned with the frame's own new margin on mobile — same
       guarantee the desktop version relies on. Same trick for the ticker
       and header-row heights: redefining them here automatically resizes
       everything that references them (header row, badge, hero's
       margin-top, the flyout menu's top) — no need to repeat those rules. */
    :root{
      --frame-inset:16px;
      --ticker-h:18px;
      --header-bar-h:60px;
    }
    .hero{ min-height:180px; }
    .floating-header{ padding:0 18px 0 16px; }
    .hero-badge{ padding:8px 20px 8px 12px; }
    .hero-badge-langs{ gap:6px; }
    .hero-badge-flag{ height:13px; }
    .hero-marquee{ padding:3px 0; }
    .floating-logo{ height:38px; }
    .header-menu-toggle{ margin-right:14px; }
    .header-menu-item{ font-size:11px; padding:11px 18px 11px 20px; }

    /* LOADING SCREEN — logo scaled to 60% of the desktop size; the bar/
       text composition scales down with it (same proportions) so it
       stays aligned under the smaller logo instead of floating off.
       Overlap/size/centering follow the same reworked proportions as
       the desktop version above (deeper logo overlap, contained width,
       centered percent), scaled down for the smaller logo. */
    /* IMPORTANTE: se usa el prefijo #site-loader para GANARLE en especificidad
       a la regla base .loader-logo (117px) que está más abajo en el archivo.
       Sin esto, la base pisaba el tamaño mobile y el logo salía enorme. */
    #site-loader .loader-logo{ height:42px; top:calc(50% - 38px); }
    #site-loader .loader-bar-wrap{ top:calc(50% + 6px); left:calc(50% - 64px); width:40px; height:20px; }
    #site-loader.loader-grow .loader-bar-wrap{ width:calc(50vw + 120px); }
    #site-loader .loader-bar-fill{ background:linear-gradient(to right, var(--cream) 0px, var(--cream) 170px, rgba(228,213,183,0) 100%); }
    #site-loader .loader-text{ left:11px; font-size:12px; }
    #site-loader .loader-percent{ top:calc(50% + 6px + 20px + 8px); left:50%; transform:translateX(-50%); font-size:10px; }

    .about{ padding:20px 0 0; }
    .about-inner{ padding:0 6%; }
    .about-title{ font-size:18px; }

    .tec-espresso{ margin-top:20px; }
    .tec-espresso-headline{ font-size:14px; }
    .tec-espresso-box .tec-espresso-seal{ height:44px; }
    .tec-espresso-desc{ font-size:12px; max-width:100%; }
    .tec-espresso-logo{ height:70px; }

    .contact{ padding:24px 6% 16px; }
    .newsletter{ padding:20px 6% 28px; }
    .site-footer{ padding:16px 6% 16px; }
    .legal-links{ gap:14px 20px; }

    .popup-page-header{ padding:16px 20px; gap:14px; }
    .popup-page-body{ padding:24px 20px 60px; }
    .showroom-mosaic img,
    .showroom-mosaic video{ height:200px; }
    .eventos-feed{ grid-template-columns:1fr; }

    .modal-box{ padding:32px 22px 26px; }

    .brand-drawer-inner{ padding:56px 22px 36px; }

    /* the model-name row (La Rocca, Markibar, Cunill, Remidag) was
       flex-wrap:nowrap, tuned to fit the longest list (4 Remidag names)
       on the DESKTOP drawer's 440px width. The mobile drawer goes full
       device width instead (see the hover:none/pointer:coarse rule
       above), which on real small phones (~375px or narrower) can
       actually be LESS available content width than the desktop drawer
       it was tuned for — risking clipped/overflowing names. Let it wrap
       to a second row instead of overflowing. */
    .drawer-model-selectors{ flex-wrap:wrap; }
  }

  @media (max-width:480px){
    /* single-column brand grid already applies from the 680px tier
       above; this tier is just further type/spacing tightening for the
       smallest phones. */
    .hero{ min-height:150px; }
    .hero-badge p{ font-size:11px; }
    .hero-marquee-track span{ font-size:8px; }
    .hero-headline{ font-size:clamp(15px, calc(3.8 * var(--frozen-vw)), 22px); }
    /* at this 150px floor, the desktop-inherited 10%/12% gap between
       .hero-content and .hero-dots shrinks to just a few px — widened
       here so a 2-line headline never crowds/touches the dots on the
       smallest phones. */
    .hero-content{ bottom:15%; }
    .hero-dots{ bottom:6%; }

    .header-menu-item{ font-size:10px; padding:10px 16px 10px 18px; }

    .tec-espresso-box{ padding:12px 18px; }
    .tec-espresso-headline{ font-size:13px; }
    .tec-espresso-box .tec-espresso-seal{ height:38px; }

    .social-btn{ font-size:10px; padding:9px 14px; }
    .newsletter-form{ flex-direction:column; }
    .newsletter-btn{ width:100%; }
    /* the base flex:1 1 220px sets a 220px flex-BASIS, which becomes a
       220px HEIGHT once the form stacks to flex-direction:column here —
       that's what was ballooning the email field far taller than the
       button below it. Cancel it so the input sizes like the button,
       to its own content height, then just stretch it to full width. */
    .newsletter-input{ flex:0 0 auto; width:100%; }
  }

  /* =========================================================
     PRELOADER — brief full-screen loader (icon/9bares_LOGO-flotante_Wh.svg).
     Logo sits closer to the vertical center (not pushed high up anymore).
     The cream bar is locked to the exact rendered width of "BARES" in the
     logo (measured from the SVG at the logo's own height/proportions), so
     it reads as visually attached to the wordmark rather than floating
     off to one side. Bar's left edge is fixed; only the width grows to
     the right (not a symmetric zoom) — same smooth, non-stepped easing
     as before. The bar sits on a higher z-index so it can slightly step
     over the bottom edge of the logo composition, matching the reference.
     Total visible time: ~1.2s bar + 1s fade-out.
     ========================================================= */
  #site-loader{
    position:fixed;
    inset:0;
    z-index:9999;
    background:var(--dark);
  }
  .loader-logo{
    position:absolute;
    top:calc(50% - 78.5px); /* logo top edge: center minus half its (reduced) height (58.5px) minus a 20px lift */
    left:50%;
    transform:translateX(-50%);
    height:117px; /* -20% from the previous 146px */
    width:auto;
    z-index:1;
    filter:drop-shadow(0 0 0 rgba(228,213,183,0));
    /* tied to the same duration as the loading bar (BAR_DURATION, see JS
       below): the glow rises together with the load progress rather than
       being a static always-on filter */
    transition:filter 2.4s cubic-bezier(.25,.05,.1,1);
  }
  /* JS adds this class in the same frame as .loader-grow, so the glow
     ramps up in sync with the bar's own 1.2s width animation. Kept quite
     restrained/soft this pass — smaller blur radius and lower opacity
     than before, so it barely reads as more than a faint lift. */
  #site-loader.loader-grow .loader-logo{
    filter:drop-shadow(0 0 8px rgba(228,213,183,.4));
  }
  /* left is locked under "BARES" (left edge under "B"). top overlaps
     noticeably deeper into the logo's own bottom edge (moved up from
     +35px to +18px, per request — "más encimado al logo"). Width grows
     wide again (restored, per request — "que la barra siga mucho más a
     la derecha como en el ejemplo"), exiting well past the right edge
     on most screens. */
  .loader-bar-wrap{
    position:absolute;
    top:calc(50% + 18px);
    left:calc(50% - 107px); /* left edge lines up with the start of the "B" in the logo above */
    width:60px;
    height:38px;
    overflow:hidden;
    z-index:3;
    transition:width 2.4s cubic-bezier(.25,.05,.1,1);
  }
  #site-loader.loader-grow .loader-bar-wrap{
    width:calc(50vw + 200px);
  }
  /* gradient tail (not a hard cutoff) — fixed-px stops (not %), so the
     fade zone always STARTS at a constant distance from the left edge
     (250px — safely past where "Hablamos el idioma del café." ends at
     this font-size), never sliding back over the phrase text at
     earlier/narrower points in the growth animation the way a
     percentage-based stop did (that's what looked "feo" before — the
     fade was cutting through the text itself while the bar was still
     short). From 250px it then fades out gradually all the way to
     whatever the CURRENT right edge is (100%), so a wider bar just
     means a longer, gentler taper — never a hard cutoff, and never a
     fade close enough to the text to bite into it. */
  .loader-bar-fill{
    position:absolute;
    inset:0;
    background:linear-gradient(to right, var(--cream) 0px, var(--cream) 250px, rgba(228,213,183,0) 100%);
  }
  /* left offset is fixed relative to the bar-wrap, so the phrase never
     moves — it just becomes visible as the cream fill grows past it
     (text color matches the loader background, so it only reads where
     it overlaps the cream bar) */
  .loader-text{
    position:absolute;
    top:0;
    left:18px;
    height:100%;
    display:flex;
    align-items:center;
    white-space:nowrap;
    font-family:var(--font-body);
    font-weight:400;
    font-size:15px; /* enlarged from 13px, per request */
    letter-spacing:.2px;
    color:var(--dark);
    z-index:2;
  }
  /* 0% → 100% readout, sits just below the bar (see JS: counts up in sync
     with BAR_DURATION). Small and subdued — a detail, not competing with
     the "Hablamos el idioma del café" phrase above it. Centered under
     the whole composition (like the logo), not left-aligned under the
     bar — per request ("porcentaje al medio"). */
  .loader-percent{
    position:absolute;
    top:calc(50% + 18px + 38px + 10px);
    left:50%;
    transform:translateX(-50%);
    text-align:center;
    z-index:3;
    font-family:var(--font-title);
    font-weight:600;
    font-size:11px;
    letter-spacing:1px;
    color:var(--cream);
    opacity:.55;
  }
  /* fade-out: opacity + visibility, no layout shift, no interaction while fading.
     Eased (not linear) so the fade itself feels smoother/slightly longer. */
  #site-loader.loader-hide{
    opacity:0;
    visibility:hidden;
    pointer-events:none;
    transition:opacity 1s ease, visibility 0s linear 1s;
  }

  /* =========================================================
     FULLSCREEN POPUPS — Showroom / Eventos / Tienda "fake pages",
     opened from the header menu. Unlike the small LEGAL MODALS above
     (centered box + × close), these cover the entire viewport and use
     a ← back control, so each reads as its own page rather than a
     dialog on top of the current one. Sits above the brand drawer
     (600) and legal modals (500) — only the image lightbox (700+)
     should ever appear on top of a popup, which never happens since
     the lightbox only opens from inside the drawer.
     ========================================================= */
  .popup-page{
    position:fixed;
    inset:0;
    z-index:650;
    background:var(--cream);
    color:var(--dark);
    opacity:0;
    visibility:hidden;
    transform:translateY(18px);
    transition:opacity .4s var(--ease), visibility .4s var(--ease), transform .4s var(--ease);
    overflow-y:auto;
  }
  .popup-page.open{
    opacity:1;
    visibility:visible;
    transform:translateY(0);
  }
  body.popup-open{overflow:hidden;}

  .popup-page-header{
    position:sticky;
    top:0;
    z-index:2;
    display:flex;
    align-items:center;
    gap:20px;
    background:var(--dark);
    color:var(--cream);
    padding:22px clamp(24px, calc(5 * var(--frozen-vw)), 56px);
  }
  .popup-back{
    flex-shrink:0;
    width:38px;
    height:38px;
    display:flex;
    align-items:center;
    justify-content:center;
    font-size:20px;
    line-height:1;
    color:var(--cream);
    border-radius:50%;
    transition:background .3s var(--ease), transform .3s var(--ease);
  }
  .popup-back:hover{
    background:rgba(228,213,183,.14);
    transform:translateX(-3px);
  }
  .popup-page-title{
    font-family:var(--font-title);
    font-weight:700;
    font-size:13px;
    letter-spacing:2px;
    text-transform:uppercase;
  }
  .popup-page-body{
    padding:clamp(28px, calc(5 * var(--frozen-vw)), 64px) clamp(24px, calc(5 * var(--frozen-vw)), 56px) 90px;
    max-width:1400px;
    margin:0 auto;
  }
  .popup-intro{
    font-family:var(--font-body);
    font-size:15px;
    line-height:1.7;
    color:rgba(28,28,28,.75);
    max-width:640px;
    margin-bottom:36px;
  }

  /* ---- SHOWROOM: section titles ("Showroom de café" / "Máquinas y
     Molinos") above each photo grid ---- */
  .popup-section-title{
    font-family:var(--font-title);
    font-weight:800;
    font-size:clamp(16px, calc(1.6 * var(--frozen-vw)), 20px);
    letter-spacing:1px;
    text-transform:uppercase;
    color:var(--dark);
    margin:0 0 18px;
  }
  .popup-section-title + .showroom-mosaic{
    margin-bottom:48px;
  }

  /* ---- SHOWROOM: photo mosaic. auto-fit (not auto-fill) is what makes
     this adapt to odd/even counts automatically: full rows read as a
     perfect grid, and a leftover odd row's items stretch (each track is
     minmax(240px,1fr)) to fill the row's full width instead of leaving
     empty trailing cells. ---- */
  /* FLEX con crecimiento: la última fila (par o impar) se estira para llenar
     el ancho completo, así nunca quedan celdas vacías y se adapta a cualquier
     ancho de pantalla. */
  .showroom-mosaic{
    display:flex;
    flex-wrap:wrap;
    gap:14px;
  }
  .showroom-mosaic figure{
    margin:0;
    overflow:hidden;
    background:var(--dark);
    flex:1 1 280px;   /* base ~280px; crece para completar la fila */
    min-width:200px;
  }

  /* ---- SHOWROOM POPUP override: dark #1C1C1C page (was the shared
     cream popup scheme), mosaics flush edge-to-edge with zero gap
     between images and no cream filler padding around them — the
     section titles keep their own inset so the label text stays
     readable, but the image grids themselves reach the full width. ---- */
  #popupShowroom.popup-page{
    background:#1C1C1C;
  }
  #popupShowroom .popup-page-body{
    padding:0 0 40px;
    max-width:none;
    margin:0;
  }
  #popupShowroom .popup-section-title{
    color:#FFFFFF;
    padding:28px clamp(20px, calc(4 * var(--frozen-vw)), 56px) 16px;
    margin:0;
  }
  #popupShowroom .popup-section-title + .showroom-mosaic{
    margin-bottom:0;
  }
  #popupShowroom .showroom-mosaic{
    gap:6px;
  }
  .showroom-mosaic img,
  .showroom-mosaic video{
    width:100%;
    height:260px;
    object-fit:cover;
    display:block;
    transition:transform .5s var(--ease);
  }
  .showroom-mosaic figure:hover img,
  .showroom-mosaic figure:hover video{
    transform:scale(1.05);
  }

  /* ---- EVENTOS: Instagram feed slot + interspersed noticias ---- */
  .eventos-feed{
    display:flex;
    flex-direction:column;
    gap:22px;
    max-width:1120px;           /* ocupa más pantalla */
    width:100%;
    margin:0 auto;
  }
  /* API de Instagram retirada de Eventos, per request */
  .ig-embed-slot{ display:none !important; }
  .noticia-card{
    background:var(--dark);
    color:var(--cream);
    display:flex;
    flex-direction:row;         /* imagen a la izquierda, texto a la derecha */
    align-items:stretch;
    overflow:hidden;
    border-radius:8px;
  }
  .noticia-card .noticia-media{
    flex:0 0 42%;
    overflow:hidden;
    background:#000;
  }
  .noticia-card .noticia-media img{
    width:100%;
    height:100%;
    min-height:240px;
    object-fit:cover;
    display:block;
  }
  .noticia-card .noticia-body{
    flex:1 1 auto;
    min-width:0;                /* CLAVE: permite que el texto se ajuste y NO se corte */
    display:flex;
    flex-direction:column;
    gap:10px;
    justify-content:center;
    padding:28px 30px;
  }
  /* el texto de la nota se lee COMPLETO (sin recortes ni "..."), porque la nota
     no se abre en otra pantalla: todo tiene que leerse acá. */
  .noticia-card .noticia-body p{ white-space:pre-wrap; }
  @media (max-width:680px){
    .noticia-card{ flex-direction:column; }
    .noticia-card .noticia-media{ flex-basis:auto; }
  }

  /* ---- aviso "Próximamente" reutilizable (Showroom / Eventos vacíos) ---- */
  .seccion-soon{
    text-align:center;
    padding:64px 24px;
    max-width:620px;
    margin:24px auto;
  }
  .seccion-soon h2{
    font-family:var(--font-title);
    font-weight:700;
    font-size:26px;
    margin:0 0 12px;
  }
  .seccion-soon p{
    font-family:var(--font-body);
    font-size:14px;
    line-height:1.6;
    opacity:.75;
    margin:0;
  }
  /* Showroom es página oscura: texto claro para el aviso */
  #popupShowroom .seccion-soon{ color:#fff; padding-top:80px; }

  /* ---- Showroom: mínimo 2 imágenes por fila en desktop (una sola imagen no
     debe estirarse a todo el ancho y pixelarse). En mobile queda 1 por fila
     como un listado, que se ve bien. ---- */
  @media (min-width:681px){
    #popupShowroom .showroom-mosaic{ justify-content:center; }
    .showroom-mosaic figure{ max-width:calc(50% - 4px); }
  }
  .noticia-card .noticia-tag{
    font-family:var(--font-title);
    font-size:10px;
    font-weight:700;
    letter-spacing:1.5px;
    text-transform:uppercase;
    opacity:.6;
  }
  .noticia-card h4{
    font-family:var(--font-title);
    font-size:15px;
    font-weight:700;
    line-height:1.4;
  }
  .noticia-card p{
    font-family:var(--font-body);
    font-size:13px;
    line-height:1.6;
    color:rgba(228,213,183,.85);
  }

  /* ---- TIENDA: "Próximamente" placeholder — full dark #1C1C1C page,
     white typography (distinct treatment from the cream Showroom/
     Eventos popups, per request). Overrides the shared .popup-page /
     .popup-page-header cream/dark scheme just for this popup. */
  #popupTienda.popup-page{
    background:#1C1C1C;
    color:#FFFFFF;
  }
  #popupTienda .popup-page-header{
    background:#111111;
    color:#FFFFFF;
  }
  #popupTienda .popup-back{color:#FFFFFF;}
  #popupTienda .popup-back:hover{background:rgba(255,255,255,.12);}
  .tienda-soon{
    min-height:46vh;
    display:flex;
    flex-direction:column;
    align-items:center;
    justify-content:center;
    text-align:center;
    gap:16px;
  }
  .tienda-soon h2{
    font-size:clamp(28px, calc(4 * var(--frozen-vw)), 46px);
    font-weight:800;
    letter-spacing:2px;
    text-transform:uppercase;
    color:#FFFFFF;
  }
  .tienda-soon p{
    max-width:420px;
    font-family:var(--font-body);
    font-size:15px;
    line-height:1.7;
    color:rgba(255,255,255,.75);
  }
