/* ==========================================================================
   GAAB Website — Components
   Navbar, buttons, hero, cinematic section, category cards, footer.
   ========================================================================== */


/* --------------------------------------------------------------------------
   LAYOUT — container utility for max-width + horizontal padding
   -------------------------------------------------------------------------- */

.container {
  width: 100%;
  max-width: var(--container-max);
  margin-inline: auto;
  padding-inline: var(--container-padding);
}


/* ==========================================================================
   NAVBAR — Floating glass pill, centered, dynamic states
   ========================================================================== */

/* Clean linear navbar — subtle glassmorphism; compacts on scroll (.is-scrolled). */
:root { --announce-h: 37px; }

/* ==========================================================================
   ANNOUNCEMENT BAR — thin blue strip above the navbar (all pages). Two rotating
   messages (fade + vertical slide). Hides on scroll; reappears at the top.
   ========================================================================== */
.announce-bar {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: var(--announce-h);
  background: var(--color-blue-gaab);
  z-index: 101;                        /* above the navbar */
  overflow: hidden;
  transition: transform 0.4s cubic-bezier(0.22, 1, 0.3, 1);
}
.announce-bar__track { position: relative; width: 100%; height: 100%; }
.announce-bar__msg {
  position: absolute;
  left: 50%;
  top: 50%;
  transform: translate(-50%, calc(-50% + 8px));   /* waiting below */
  opacity: 0;
  font-family: var(--font-sans);
  font-size: 12.5px;
  font-weight: var(--weight-medium);
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: #FFFFFF;
  white-space: nowrap;
  pointer-events: none;
  transition: opacity 0.5s ease, transform 0.5s cubic-bezier(0.22, 1, 0.3, 1);
}
.announce-bar__msg.is-current { opacity: 1; transform: translate(-50%, -50%); }
.announce-bar__msg.is-out { opacity: 0; transform: translate(-50%, calc(-50% - 8px)); } /* exits up */

body.announce-hidden .announce-bar { transform: translateY(-100%); }
body.announce-hidden { --announce-h: 0px; }

@media (max-width: 640px) {
  :root { --announce-h: 34px; }
  .announce-bar__msg { font-size: 11px; letter-spacing: 0.04em; }
}

.navbar {
  position: fixed;
  top: var(--announce-h);                            /* sits below the blue bar */
  left: 0;
  width: 100%;
  padding: clamp(19px, 2.2vh, 26px) clamp(24px, 4vw, 48px);  /* a touch taller */
  background: rgba(10, 10, 12, 0.7);                 /* dark glass premium */
  backdrop-filter: blur(20px) saturate(180%);
  -webkit-backdrop-filter: blur(20px) saturate(180%);
  border-bottom: 1px solid rgba(255, 255, 255, 0.06);
  z-index: 100;
  transition: top 0.4s cubic-bezier(0.22, 1, 0.3, 1),
              padding 250ms ease-out, background 250ms ease-out, box-shadow 250ms ease-out;
}

.navbar.is-scrolled {
  /* No size change on scroll — the navbar keeps its height; it only gains a
     touch of solidity (slightly more opaque + a soft shadow) for legibility. */
  background: rgba(10, 10, 12, 0.85);
  box-shadow: 0 4px 24px rgba(0, 0, 0, 0.25);
}

.navbar-inner {
  max-width: 1440px;
  margin: 0 auto;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-xl);
  /* Locks the bar height so every page's navbar is identical, even pages
     without the "Get a Quote" button (e.g. contact). */
  min-height: 40px;
}

.navbar-logo {
  display: flex;
  align-items: center;
  line-height: 0;
}

.navbar-logo-img {
  height: 28px;
  width: auto;
  display: block;
}

.navbar-right {
  display: flex;
  align-items: center;
  gap: clamp(20px, 2.5vw, 36px);
}

.navbar-menu {
  display: flex;
  gap: clamp(16px, 2vw, 28px);
  list-style: none;
  padding: 0;
  margin: 0;
}

.navbar-menu a {
  font-size: 14px;
  font-weight: 400;
  color: rgba(255, 255, 255, 0.65);   /* tenue on the dark glass */
  text-decoration: none;
  letter-spacing: -0.005em;
  transition: color 180ms ease-out;
  padding: 6px 2px;
}

.navbar-menu a:hover { color: #FFFFFF; }

.navbar-cta {
  padding: 10px 20px;
  border-radius: 14px;                  /* well rounded, not a full pill */
  background: var(--color-blue-gaab);
  color: #FFFFFF;
  font-size: 13px;
  font-weight: 500;
  text-decoration: none;
  box-shadow: 0 0 0 1px rgba(255, 255, 255, 0.06);
  transition: background 180ms ease-out, transform 180ms ease-out;
  white-space: nowrap;
}

.navbar-cta:hover {
  background: #152D52;
  transform: translateX(2px);
}

/* --------------------------------------------------------------------------
   MEGA-MENU — desktop dropdown under "Products" (injected by megamenu.js).
   Full-width panel anchored to the navbar; opens on hover with fade + slide.
   -------------------------------------------------------------------------- */
.navbar-menu li.has-mega,
.navbar__menu li.has-mega { position: static; }   /* panel spans full width */

.mega-menu {
  position: absolute;
  top: 100%;
  left: 0;
  width: 100vw;
  background: #FDFDFD;
  border-top: 1px solid rgba(10, 10, 12, 0.06);
  box-shadow: 0 26px 50px -18px rgba(16, 24, 40, 0.20);
  opacity: 0;
  visibility: hidden;
  transform: translateY(-6px);
  transition: opacity 0.28s ease, transform 0.28s cubic-bezier(0.22, 1, 0.3, 1),
              visibility 0.28s;
  pointer-events: none;
}
.mega-menu.is-open {
  opacity: 1;
  visibility: visible;
  transform: translateY(0);
  pointer-events: auto;
}

.mega-menu__inner {
  max-width: var(--container-max);           /* 1280 — coherent side margins */
  margin: 0 auto;
  display: grid;
  /* fr (not %) so the gap is subtracted before splitting — otherwise 38%+62%+gap
     overflows and the right column (doors) gets clipped off the right edge. */
  grid-template-columns: 38fr 62fr;
  gap: clamp(32px, 5vw, 72px);
  padding: clamp(32px, 4vh, 52px) clamp(24px, 4vw, 48px);
}
.mega-menu__left,
.mega-menu__right { min-width: 0; }           /* let columns shrink, no overflow */

.mega-menu__eyebrow {
  display: block;
  font-family: ui-monospace, 'JetBrains Mono', monospace;
  font-size: 12px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--color-medium-gray);
  margin-bottom: 20px;
}

.mega-menu__left {
  border-right: 1px solid rgba(10, 10, 12, 0.07);
  padding-right: clamp(24px, 3vw, 48px);
}

.mega-menu__all {
  display: inline-block;
  font-family: var(--font-sans);
  font-size: 1.05rem;
  font-weight: var(--weight-medium);
  color: var(--color-text-primary);
  text-decoration: none;
  margin-bottom: 22px;
  transition: color 0.2s ease;
}
.mega-menu__all:hover { color: var(--color-blue-gaab); }

.mega-menu__cats {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 3px 28px;
}
.mega-cat {
  font-family: var(--font-sans);
  font-size: 0.95rem;
  color: #3F3F3F;               /* darker than secondary — reads clearly */
  text-decoration: none;
  padding: 2px 0;
  transition: color 0.2s ease;
}
.mega-cat:hover { color: var(--color-blue-gaab); }

.mega-menu__doors {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));   /* shrink to fit all four */
  gap: clamp(14px, 1.6vw, 24px);
}
.mega-door {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 12px;
  min-width: 0;               /* let long names wrap instead of overflowing */
  text-decoration: none;
}
.mega-door__frame {
  width: 100%;
  aspect-ratio: 3 / 4;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 14px 18px 0;
  background: #FDFDFD;
  border-radius: 16px;
}
.mega-door__frame img {
  max-width: 100%;
  max-height: 100%;
  object-fit: contain;
  opacity: 0.85;
  mix-blend-mode: multiply;             /* white photo bg melts into the panel */
  transition: opacity 0.3s ease, transform 0.3s ease;
}
.mega-door__name {
  font-family: var(--font-sans);
  font-size: 0.85rem;
  line-height: 1.3;
  font-weight: var(--weight-medium);
  color: var(--color-text-secondary);
  text-align: center;
  max-width: 100%;
  transition: color 0.2s ease;
}
.mega-door:hover .mega-door__frame img { opacity: 1; transform: scale(1.02); }
.mega-door:hover .mega-door__name { color: var(--color-text-primary); }

/* Touch / mobile: no mega-menu (the script also no-ops there). */
@media (max-width: 1024px) {
  .mega-menu { display: none; }
}

/* --------------------------------------------------------------------------
   MOBILE NAV — hamburger + slide-down panel (injected by nav-mobile.js).
   The bar keeps logo + "Get a Quote" + burger; the links move into the panel.
   -------------------------------------------------------------------------- */

/* Desktop: the injected button and panel simply don't exist visually. */
.nav-burger { display: none; }
.nav-panel  { display: none; }

@media (max-width: 768px) {
  .navbar { padding: 14px 20px; }
  .navbar-menu, .navbar__menu { display: none; }

  /* Burger — 44x44 touch target, two bars that cross into an X when open. */
  .nav-burger {
    display: flex;
    flex-direction: column;
    justify-content: center;
    align-items: center;
    gap: 5px;
    width: 44px;
    height: 44px;
    margin-right: -10px;      /* optical: pulls the glyph flush with the edge */
    padding: 0;
    border: 0;
    background: none;
    cursor: pointer;
    -webkit-tap-highlight-color: transparent;
  }
  .nav-burger__bar {
    display: block;
    width: 20px;
    height: 1.5px;
    border-radius: 2px;
    background: rgba(255, 255, 255, 0.85);
    transition: transform 260ms cubic-bezier(0.22, 1, 0.3, 1),
                opacity 160ms ease-out;
  }
  .navbar.nav-is-open .nav-burger__bar:nth-child(1) { transform: translateY(3.25px) rotate(45deg); }
  .navbar.nav-is-open .nav-burger__bar:nth-child(2) { transform: translateY(-3.25px) rotate(-45deg); }

  /* Panel — drops out of the bar, same dark glass so it reads as one surface. */
  .nav-panel {
    display: block;
    position: absolute;
    top: 100%;
    left: 0;
    width: 100%;
    background: rgba(10, 10, 12, 0.92);
    backdrop-filter: blur(20px) saturate(180%);
    -webkit-backdrop-filter: blur(20px) saturate(180%);
    border-bottom: 1px solid rgba(255, 255, 255, 0.06);
    padding: 8px 20px 20px;
    opacity: 0;
    transform: translateY(-8px);
    pointer-events: none;
    transition: opacity 240ms ease-out,
                transform 240ms cubic-bezier(0.22, 1, 0.3, 1);
  }
  .navbar.nav-is-open .nav-panel {
    opacity: 1;
    transform: translateY(0);
    pointer-events: auto;
  }
  .nav-panel__list {
    list-style: none;
    margin: 0;
    padding: 0;
  }
  .nav-panel__list a {
    display: block;
    padding: 14px 0;                                    /* ≥44px touch target */
    font-family: var(--font-sans);
    font-size: 17px;
    font-weight: 400;
    letter-spacing: -0.01em;
    color: rgba(255, 255, 255, 0.72);
    text-decoration: none;
    border-bottom: 1px solid rgba(255, 255, 255, 0.06);
    transition: color 180ms ease-out;
  }
  .nav-panel__list li:last-child a { border-bottom: 0; }
  .nav-panel__list a:active,
  .nav-panel__list a[aria-current="page"] { color: #FFFFFF; }
}

/* Very narrow — keep logo + CTA + burger on one line without wrapping. */
@media (max-width: 400px) {
  .navbar-logo-img { height: 22px; }
  .navbar-cta { padding: 9px 14px; font-size: 12px; }
  .navbar-right { gap: 10px; }
}

@media (prefers-reduced-motion: reduce) {
  .nav-panel, .nav-burger__bar { transition: none; }
}


/* ==========================================================================
   BUTTONS
   ========================================================================== */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;

  padding: 14px 28px;
  border-radius: var(--radius-pill);

  font-family: var(--font-sans);
  font-size: var(--text-small);
  font-weight: var(--weight-medium);
  letter-spacing: var(--tracking-loose);
  line-height: var(--leading-button);
  white-space: nowrap;

  border: 1px solid transparent;
  cursor: pointer;
  user-select: none;

  transition:
    background-color var(--duration-fast) ease-out,
    color var(--duration-fast) ease-out,
    border-color var(--duration-fast) ease-out,
    transform var(--duration-fast) ease-out,
    box-shadow var(--duration-fast) ease-out;
}

/* Primary — GAAB blue */
.btn--primary {
  background: var(--color-blue-gaab);
  color: var(--color-white);
}

.btn--primary:hover {
  background: var(--color-blue-gaab-dark);
  transform: translateY(-1px);
  box-shadow: 0 8px 24px rgba(27, 58, 107, 0.18);
}

/* Dark — black with a minimal vertical gradient (reserves GAAB blue for the
   main CTAs). Keeps the .btn base sizing/padding; only colour + radius change. */
.btn--dark {
  background: linear-gradient(180deg, #1A1A1E 0%, #0A0A0C 100%);
  color: var(--color-white);
  border-color: rgba(255, 255, 255, 0.08);
  border-radius: 12px;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
}

.btn--dark:hover {
  background: linear-gradient(180deg, #25252A 0%, #15151A 100%);
  transform: translateY(-1px);
}

/* Secondary — outline on light */
.btn--secondary {
  background: transparent;
  color: var(--color-black);
  border-color: var(--color-black);
}

.btn--secondary:hover {
  background: var(--color-black);
  color: var(--color-white);
  transform: translateY(-1px);
}

/* Secondary on dark — inverted */
.btn--on-dark.btn--secondary {
  color: var(--color-white);
  border-color: var(--color-white);
}

.btn--on-dark.btn--secondary:hover {
  background: var(--color-white);
  color: var(--color-black);
}


/* ==========================================================================
   HERO SECTION — White, full viewport, video peek at bottom
   ========================================================================== */

.hero-section {
  position: relative;
  min-height: 100vh;
  padding-top: clamp(140px, 19vh, 220px);  /* generous air under the navbar */
  padding-bottom: clamp(80px, 10vh, 140px); /* air before the video preview */
  /* subtle radial depth instead of a flat white field */
  background: radial-gradient(ellipse 80% 70% at 50% 35%, #FAFAF7 0%, #FFFFFF 65%);
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  /* overflow visible so the fixed traveling video is never clipped */
}

/* Textual content sits centered above the video preview below */
.hero-section__container {
  position: relative;
  z-index: 2;
  width: 100%;
  max-width: 1400px;   /* widened so the 3-image row fits; text stays centred */
  margin: 0 auto;
  padding: 0 var(--space-xl);
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  gap: 0; /* spacing handled by per-element margins below */
}

/* Mono eyebrow above the title */
.hero-eyebrow {
  font-family: ui-monospace, 'JetBrains Mono', 'SFMono-Regular', monospace;
  font-size: 11px;
  font-weight: 500;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--color-medium-gray);
  opacity: 0.65;
  margin: 0 0 clamp(28px, 3vh, 40px) 0;
}

/* Central placeholder = the SAME box as the side images (4/3). video-travel.js
   reads its live rect, so the growing animation just starts from this size and
   shape — nothing in its travel logic changes. */
.hero-video-mini {
  width: clamp(320px, 30vw, 480px);   /* same box as the sides now — all three equal */
  aspect-ratio: 4 / 3;
  margin: 0;
}

/* --------------------------------------------------------------------------
   HERO IMAGES ROW — three identical 4/3 boxes side by side on one line:
   side · central traveling-video placeholder · side. Same width, same height,
   same 20px radius.
   -------------------------------------------------------------------------- */
.hero-images-row {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: clamp(16px, 2vw, 32px);
  width: 100%;
  margin: var(--space-3xl) auto 0;
}

/* Just a wrapper — sizes to the placeholder, never resizes it */
.hero-image-center {
  flex-shrink: 0;
  z-index: 2;            /* protagonist sits above the sides */
  position: relative;
}

.hero-image-side {
  position: relative;
  z-index: 1;
  width: clamp(320px, 30vw, 480px);    /* SAME box as the central — all three equal */
  aspect-ratio: 4 / 3;                 /* SAME aspect as the central (no distortion) */
  flex-shrink: 0;
  border-radius: 20px;
  overflow: hidden;
  /* Cinematic look: the sides stay sharp + full colour. Their OUTER edge fades
     out toward the viewport edge via mask-image (set per-side below). No blur,
     no dimming, no scale — that resting state was removed from main.js too. */
}

.hero-image-side img {
  width: 100%;
  height: 100%;
  object-fit: cover;                   /* fill without distortion */
  display: block;
}

/* Left side: fades toward the LEFT (outer) edge — inner edge by the centre stays sharp */
.hero-image-left {
  transform: none;
  -webkit-mask-image: linear-gradient(to right,
                        transparent 0%, rgba(0,0,0,0.4) 22%, #000 62%, #000 100%);
          mask-image: linear-gradient(to right,
                        transparent 0%, rgba(0,0,0,0.4) 22%, #000 62%, #000 100%);
}

/* Right side: fades toward the RIGHT (outer) edge */
.hero-image-right {
  transform: none;
  -webkit-mask-image: linear-gradient(to left,
                        transparent 0%, rgba(0,0,0,0.4) 22%, #000 62%, #000 100%);
          mask-image: linear-gradient(to left,
                        transparent 0%, rgba(0,0,0,0.4) 22%, #000 62%, #000 100%);
}

@media (max-width: 900px) {
  .hero-image-side { display: none; }   /* mobile: only the central video */
  .hero-video-mini { width: clamp(280px, 80vw, 440px); }
}

/* The single traveling video — lives in a fixed layer and interpolates its
   rect between the hero mini placeholder and the cinematic target on scroll. */
.hero-video {
  position: fixed;
  top: 0;
  left: 0;
  border-radius: 20px;
  overflow: hidden;
  object-fit: cover;
  z-index: 5;
  will-change: transform, width, height, top, left;
  pointer-events: none;
  box-shadow: 0 30px 60px rgba(0, 0, 0, 0.16), 0 12px 28px rgba(0, 0, 0, 0.12);  /* lift */
}


/* --------------------------------------------------------------------------
   HERO TRUST SIGNAL — avatar cluster + caption
   -------------------------------------------------------------------------- */

.hero-trust {
  display: inline-flex;
  align-items: center;
  margin-bottom: var(--space-xl);
  /* Visible by default — GSAP uses .from() to fade it in. Failsafe: if JS
     breaks, the trust signal still reads. */
}

.hero-trust__cluster {
  display: inline-flex;
}

.hero-trust__avatar {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 32px;
  height: 32px;
  border-radius: 50%;
  background: var(--color-light-gray);
  border: 2px solid var(--color-white);
  margin-left: -8px;
  box-sizing: border-box;
  overflow: hidden;

  font-size: 13px;
  font-weight: var(--weight-medium);
  color: var(--color-medium-gray);
  line-height: 1;
}

.hero-trust__avatar:first-child { margin-left: 0; }

.hero-trust__avatar img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

/* Plus tile — keeps the placeholder grey + border, sits on top of stack */
/* Plus circle — same 32×32 box and 2px white border as the photo avatars.
   Glassmorphism background. The "+" is drawn with two pseudo-elements so
   the line caps are perfectly square (no border-radius / no font baseline). */
.hero-trust__avatar--plus {
  position: relative;
  /* Same border thickness as the photo avatars so the inner size matches */
  border: 2px solid var(--color-white);
  background: rgba(255, 255, 255, 0.5);
  -webkit-backdrop-filter: blur(12px) saturate(150%);
          backdrop-filter: blur(12px) saturate(150%);
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06);
  /* No text content — pseudo-elements draw the cross */
  font-size: 0;
  color: transparent;
}

.hero-trust__avatar--plus::before,
.hero-trust__avatar--plus::after {
  content: "";
  position: absolute;
  top: 50%;
  left: 50%;
  background: #888888;
  border-radius: 0;      /* square caps — no rounded ends */
}

/* Horizontal bar */
.hero-trust__avatar--plus::before {
  width: 12px;
  height: 1.5px;
  transform: translate(-50%, -50%);
}

/* Vertical bar */
.hero-trust__avatar--plus::after {
  width: 1.5px;
  height: 12px;
  transform: translate(-50%, -50%);
}

.hero-trust__caption {
  margin-left: 12px;
  font-size: var(--text-small);
  font-weight: var(--weight-regular);
  color: var(--color-medium-gray);
}


/* --------------------------------------------------------------------------
   HERO HEADLINE — bigger, denser
   -------------------------------------------------------------------------- */

.hero-headline {
  font-size: clamp(40px, 5vw, 68px); /* notably smaller than before (~96px) */
  font-weight: var(--weight-medium);
  line-height: 1.08;
  letter-spacing: -0.02em;
  color: var(--color-text-primary);
  margin: 0 0 clamp(36px, 4.5vh, 56px) 0; /* big air before the CTAs */
  max-width: 16ch;
}

@media (max-width: 768px) {
  .hero-headline {
    font-size: clamp(32px, 9vw, 48px);
    margin-bottom: clamp(28px, 4vh, 40px);
  }
  .hero-eyebrow {
    font-size: 10px;
    margin-bottom: clamp(20px, 2.5vh, 32px);
  }
}

/* Word wrappers for the hero headline.
   IMPORTANT: words are VISIBLE by default — GSAP uses .from() to animate
   them in. If JS fails, every word still reads. */
.hero-headline .line {
  display: block;
  line-height: 1.05;
}

.hero-headline .word-wrap {
  display: inline-block;
  overflow: hidden;             /* hides the word while it sits below baseline */
  vertical-align: bottom;
  line-height: 1.05;
  padding-bottom: 0.08em;        /* keep descenders safe */
}

.hero-headline .word {
  display: inline-block;
  will-change: transform, opacity;
  /* No translateY/opacity defaults — visible. GSAP.from() animates them in. */
}

/* Premium animated shimmer on the leading word ("Hardware") —
   horizontal gradient + background-size 200% so GSAP can yoyo it in a slow loop */
.hero-gradient-text {
  background: linear-gradient(
    90deg,
    #0A0A0A  0%,
    #1B3A6B 33%,
    #3A5A9F 50%,
    #1B3A6B 66%,
    #0A0A0A 100%
  );
  background-size: 200% 100%;
  background-position: 0% 0%;
  background-repeat: no-repeat;
  -webkit-background-clip: text;
          background-clip: text;
  color: transparent;
  -webkit-text-fill-color: transparent;
  display: inline-block;
  will-change: background-position;
}

.hero-headline .line {
  display: block;
  overflow: hidden;
}

/* (hero subtitle removed — title goes straight to the CTAs) */

/* Bulletproof CTA row — fixed gap, content-width, no growth, no margin
   anywhere on children. flex-wrap: nowrap so buttons NEVER wrap mid-row. */
.hero-buttons {
  display: flex;
  flex-direction: row;
  align-items: center;
  justify-content: center;
  gap: 16px;
  flex-wrap: nowrap;
  width: max-content;
  max-width: 100%;
  margin: 0 auto;
  padding: 0;
}

.hero-buttons .btn {
  padding: 14px 20px;
  border-radius: 8px;
  flex: 0 0 auto;
  /* Defensive: kill any inherited margin that might add ghost gap */
  margin: 0 !important;
}


/* Hero ends at the buttons. The black .cinematic-section below contrasts
   against the white hero — that contrast alone signals "scroll for more".
   No static image, no video peek between hero and cinematic. */



@media (max-width: 640px) {
  .hero-section__container {
    padding: 140px var(--container-padding) var(--space-2xl);
  }
  .hero-buttons { gap: 8px; }
  .hero-buttons .btn { min-width: 140px; padding: 12px 24px; }
}


/* ==========================================================================
   CINEMATIC SECTION — Black, pinned, three videos scrubbed to scroll
   ========================================================================== */

.cinematic-section {
  position: relative;
  width: 100%;
  height: 100vh; /* explicit height so ScrollTrigger pin spacer is correct */
  background: var(--color-white);
  overflow: hidden;
}

.cinematic-section__viewport {
  position: relative;
  width: 100%;
  height: 100%;
  overflow: hidden;
  background: var(--color-white);
}

/* Landing target for the fixed traveling video. Empty box used to measure
   where/what size the video should be when "in" the cinematic. The video is a
   fixed sibling (z-index 5); overlay + text sit above it (z-index 6 / 7). */
.cinematic-video-target {
  position: absolute;
  inset: 40px;
  border-radius: 20px;
  overflow: hidden;
}

/* Dark gradient overlay for text legibility — sits exactly over the video
   (inset 40px, rounded) so it never darkens the white frame around it. */
.cinematic-section__overlay {
  position: absolute;
  inset: 40px;
  border-radius: 20px;
  background: linear-gradient(
    180deg,
    rgba(0, 0, 0, 0.15) 0%,
    rgba(0, 0, 0, 0.45) 100%
  );
  pointer-events: none;
  z-index: 6;
}

/* Fixed layer ABOVE the traveling image (z-index 6 > image's 5), centred in
   the viewport so it sits over the image once it has landed. JS controls its
   opacity (hidden outside the cinematic). */
.cinematic-text {
  position: fixed;
  inset: 0;
  z-index: 6;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0 clamp(40px, 8vw, 120px);
  pointer-events: none;
  opacity: 0; /* JS fades it in once the image lands */
  will-change: opacity, clip-path;
}

/* Editorial headline over the image — two lines, each revealed on its own
   left→right wipe (JS clips each line independently). Both are white. */
.cinematic-title {
  width: 100%;
  max-width: 24ch;
  margin: 0;
  text-align: center;
  font-family: var(--font-sans);
  font-weight: var(--weight-medium);
  font-size: clamp(28px, 3.2vw, 48px); /* smaller than before */
  line-height: 1.12;
  letter-spacing: -0.02em;
  color: #FFFFFF;
  text-shadow: 0 2px 24px rgba(0, 0, 0, 0.45);
}

/* Each line is its own block so JS can wipe them in sequence (line 1, then
   line 2). Start fully clipped from the right; JS sweeps clip + opacity. */
.cine-line {
  display: block;
  clip-path: inset(0 100% 0 0);
  opacity: 0;
  will-change: clip-path, opacity;
}
.cine-line-2 { margin-top: 0.12em; }

@media (max-width: 640px) {
  .cinematic-title { font-size: clamp(24px, 7vw, 34px); }
}


/* ==========================================================================
   PRODUCTS SECTION — Off-white, pinned header + fan/poker-hand showcase
   ========================================================================== */

.products-section {
  background: var(--color-off-white);
  position: relative;
  overflow: hidden;
}

/* NEW LAYOUT — Apple-style horizontal scroll. products-fan.js pins the section
   and slides .products-cards-wrapper on X. Cards (z2) pass over the title (z1). */
.products-stage {
  position: relative;
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  justify-content: center;
  padding: 0 clamp(24px, 5vw, 100px);
}
.products-stage .products-header {
  position: relative;
  z-index: 1;
  display: block;
  width: auto;
  max-width: 820px;
  margin: 0;
  transform: translateY(-6vh);
}
.products-track {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  z-index: 2;
  pointer-events: none;
  overflow: visible;
}
.products-cards-wrapper {
  display: flex;
  gap: 16px;
  align-items: stretch;
  padding-left: clamp(440px, 48vw, 820px);
  padding-right: 80px;
  pointer-events: auto;
  will-change: transform;
}

/* Card 4 — CTA (the only #1B3A6B surface on the page) */
.product-card.product-card--cta {
  background:
    radial-gradient(125% 90% at 22% 12%, rgba(58, 90, 159, 0.55) 0%, rgba(58, 90, 159, 0) 55%),
    linear-gradient(158deg, #1F4178 0%, #152D52 48%, #0E1B38 100%);
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  text-align: center;
  padding: 40px;
  cursor: pointer;
}
.product-card__cta-eyebrow {
  font-family: var(--font-sans);
  font-size: 13px;
  font-weight: var(--weight-regular);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.6);
}
.product-card__cta-title {
  font-family: var(--font-sans);
  font-size: 28px;
  font-weight: var(--weight-medium);
  line-height: 1.1;
  color: #FFFFFF;
  margin-top: 12px;
}
.product-card__cta-link {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  margin-top: 28px;
  padding: 12px 22px;
  border-radius: 100px;
  font-family: var(--font-sans);
  font-size: 13px;
  font-weight: var(--weight-regular);
  color: rgba(255, 255, 255, 0.92);
  background: rgba(255, 255, 255, 0.10);
  border: 1px solid rgba(255, 255, 255, 0.22);
  -webkit-backdrop-filter: blur(10px) saturate(160%);
          backdrop-filter: blur(10px) saturate(160%);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.12);
  transition: background 0.3s ease, transform 0.3s ease, border-color 0.3s ease;
}
.product-card--cta:hover .product-card__cta-link {
  background: rgba(255, 255, 255, 0.18);
  border-color: rgba(255, 255, 255, 0.35);
}

/* The whole viewport stays pinned: header sticks up top, fan in the middle */
.products-section__viewport {
  position: relative;
  width: 100%;
  height: 100vh;
  display: flex;
  flex-direction: column;
  align-items: stretch;
  /* More top air so the title clears the fixed navbar; 56 bottom, 100 sides */
  padding: clamp(100px, 14vh, 140px) 100px 56px;
}

/* Header — left lead + right CTA on same baseline. Eyebrow gets a tiny
   top margin so the cap-line doesn't get clipped by any ancestor. */
.products-header {
  position: relative;
  z-index: 4;
  width: 100%;
  max-width: 1240px;
  margin: 0 auto;
  display: flex;
  justify-content: space-between;
  align-items: flex-end;
  gap: 48px;
}

.products-header__lead {
  flex: 1 1 auto;
  min-width: 0;
  max-width: 760px;
  text-align: left;
}

.products-header__eyebrow {
  display: inline-block;
  margin-top: 2px;
  margin-bottom: 16px;
  font-family: ui-monospace, 'JetBrains Mono', monospace;
  font-size: 13px;
  font-weight: 500;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: #888888;
}

.products-header__title {
  font-size: clamp(42px, 4.6vw, 56px);
  font-weight: var(--weight-medium);
  line-height: 1.08;
  letter-spacing: -0.02em;
  color: var(--color-text-primary);
}

/* Gradient fragment inside the H2 ("commercial door.") */
.products-header__title .grad-text {
  color: #0A0A0A;
  opacity: 0.25;
}

@media (max-width: 1024px) { .products-header__title { font-size: 32px; } }
@media (max-width: 640px)  { .products-header__title { font-size: 26px; } }

.products-header__subtitle {
  margin-top: 12px;
  font-size: 17px;
  font-weight: var(--weight-regular);
  color: #888888;
  line-height: 1.5;
}

/* CTA "View all" — solid GAAB blue with blue-shadow */
.products-header__cta--solid {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 16px 28px;
  border-radius: 8px;
  background: var(--color-blue-gaab);
  color: var(--color-white);
  font-size: 15px;
  font-weight: var(--weight-medium);
  white-space: nowrap;
  border: 0;
  box-shadow: 0 6px 20px rgba(27, 58, 107, 0.28);

  transition: background 200ms ease-out,
              transform 200ms ease-out,
              box-shadow 200ms ease-out;
}

.products-header__cta--solid:hover {
  background: #152D52;
  transform: translateY(-2px);
  box-shadow: 0 10px 28px rgba(27, 58, 107, 0.35);
}

.products-header__cta--solid .arrow {
  display: inline-block;
  transition: transform 200ms ease-out;
}

.products-header__cta--solid:hover .arrow { transform: translateX(4px); }

@media (max-width: 768px) {
  .products-header {
    flex-direction: column;
    align-items: flex-start;
    gap: var(--space-md);
  }
}

.eyebrow {
  display: inline-block;
  font-size: var(--text-micro);
  font-weight: var(--weight-medium);
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
  color: var(--color-blue-gaab);
  margin-bottom: var(--space-md);
}

.products-title {
  font-size: var(--text-h2);
  font-weight: var(--weight-medium);
  line-height: var(--leading-tight);
  letter-spacing: var(--tracking-tight);
  color: var(--color-text-primary);
}

.products-subtitle {
  margin-top: var(--space-md);
  font-size: var(--text-body-lg);
  font-weight: var(--weight-regular);
  color: var(--color-medium-gray);
  line-height: var(--leading-normal);
}

/* --------------------------------------------------------------------------
   PRODUCTS FAN — 3 cards stacked straight (no rotation), arrows on the sides
   -------------------------------------------------------------------------- */

.products-fan {
  position: relative;
  flex: 1;
  width: 100%;
  max-width: 1240px;
  min-height: 540px;
  margin: 0 auto;
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: visible; /* .products-section parent handles clipping */
}

/* Big decorative number — centered on the FAN behind the cards (z 0). */
.products-fan__bignum {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  z-index: 0;

  font-family: var(--font-sans);
  font-size: 280px;
  font-weight: var(--weight-medium);
  line-height: 1;
  letter-spacing: -0.04em;
  color: var(--color-text-primary);
  opacity: 0.025;

  pointer-events: none;
  user-select: none;
  will-change: opacity, transform;
}

@media (max-width: 1024px) { .products-fan__bignum { font-size: 200px; } }
@media (max-width: 640px)  { .products-fan__bignum { font-size: 140px; opacity: 0.02; } }

/* CARDS — premium static fan. The three categories are visible at once,
   fanned in a gentle diagonal with a peak in the middle (matches the
   reference). Same glass card design; the title stays bottom-left and slides
   to the centre on hover. Image fills the card; glass panel overlays the
   bottom. Each card carries a corner action button (top-right).
   Per-card offsets live in --tx / --ty; --enter is animated in by JS. */
.product-card {
  position: relative;
  flex: 0 0 380px;
  width: 380px;
  height: 520px;
  border-radius: 20px;
  overflow: hidden;
  background: var(--color-light-gray);

  /* Layered, low-opacity depth — soft and expensive, not a hard drop. */
  box-shadow:
    0 1px 2px rgba(16, 24, 40, 0.06),
    0 14px 28px -10px rgba(16, 24, 40, 0.18),
    0 36px 60px -24px rgba(16, 24, 40, 0.22);

  cursor: pointer;
  transition: transform 650ms cubic-bezier(0.16, 1, 0.3, 1),
              box-shadow 650ms cubic-bezier(0.16, 1, 0.3, 1);
  will-change: transform;
}

/* Fan positions — three separated cards in a gentle peak (no overlap; a clear
   gap between each). Sides sit a touch lower, middle rises slightly. */
/* (fan offsets removed — cards now flow in a horizontal flex row) */

/* Hover — the card lifts, grows a touch and jumps to the front. */
.product-card:hover {
  /* no lift/scale on hover — it broke the horizontal carousel */
  z-index: 5;
}

/* Tablet / mobile: SAME pinned horizontal sweep as desktop. This used to be a
   native swipe row (`overflow-x: auto`, no pin), which meant the scroll never
   drove the cards and the run ended wherever the finger stopped — the blue CTA
   card was easy to never reach. products-fan.js now pins here too and
   translates the wrapper, so one vertical scroll walks every category and lands
   on the blue card, exactly like desktop.
   The only mobile-specific bit is where the cards START: desktop parks them
   440-820px in, to the right of a half-width title, but on a phone the title
   spans the screen, so they begin just off the right edge instead. */
/* Tablet / mobile — deliberate DIVERGENCE from desktop.
   On desktop the cards sweep left ACROSS the title, which fades out as the first
   card covers it. On a phone that reads as a collision: there is no room for the
   cards to pass beside the headline. So here the title parks at the TOP and
   stays put, and the cards run as a band BELOW it — same pinned, scroll-driven
   sweep, no overlap. products-fan.js skips the header fade at this width and
   adds the back/forward arrows. */
@media (max-width: 1024px) {
  .products-stage {
    justify-content: flex-start;
    padding: 0 clamp(20px, 5vw, 48px);
  }
  .products-stage .products-header {
    transform: none;
    margin-top: 15vh;      /* clears the fixed navbar */
    opacity: 1 !important;  /* never faded on mobile — JS owns it on desktop */
  }
  /* The card band occupies the lower half instead of the whole section. */
  .products-track {
    top: auto;
    bottom: 15vh;
    height: 50vh;
    /* stretch, not center: the wrapper must inherit the band's height or the
       cards' `height: 100%` has nothing to resolve against (see below). */
    align-items: stretch;
  }
  /* The track has an explicit height (50vh); this passes it down so the cards
     can fill it. Without it the wrapper is auto-height and every `height: 100%`
     card collapsed to ZERO — only the blue CTA card survived, because its height
     comes from its own content. That is why the section looked empty until the
     very end of the sweep. */
  .products-cards-wrapper { height: 100%; }
  .products-cards-wrapper {
    /* Card 1 sits CENTRED and already on screen the moment the title lands —
       a first pass parked the whole row off the right edge (90vw), which meant
       the section opened with the headline alone and no cards at all until you
       scrolled. Its slide-in from the right is the entrance tween (x:60 → 0),
       not this offset. */
    padding-left: calc((100vw - min(72vw, 300px)) / 2);
    padding-right: 24px;
  }
}

@media (max-width: 768px) {
  .product-card { flex: 0 0 72vw; width: 72vw; max-width: 300px; height: 100%; }
  .product-card:hover { transform: none !important; }
  .product-card__cta-title { font-size: 24px; }
}

/* Carousel arrows — mobile only. The sweep is scroll-driven, so these nudge the
   PAGE scroll by exactly one card; going back is otherwise impossible without
   scrolling up blind. */
.products-arrows { display: none; }

@media (max-width: 1024px) {
  .products-arrows {
    position: absolute;
    left: 50%;
    transform: translateX(-50%);
    /* Tucked right under the card band (.products-track ends at 15vh) rather
       than pinned to the bottom of the section. */
    bottom: 6vh;
    z-index: 6;
    display: flex;
    gap: 12px;
    pointer-events: auto;
  }
  .products-arrow {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 44px;
    height: 44px;
    padding: 0;
    border: 1px solid rgba(10, 10, 10, 0.14);
    border-radius: 50%;
    background: rgba(255, 255, 255, 0.7);
    -webkit-backdrop-filter: blur(8px);
    backdrop-filter: blur(8px);
    color: var(--color-text-primary);
    cursor: pointer;
    transition: opacity 180ms ease-out, border-color 180ms ease-out;
    -webkit-tap-highlight-color: transparent;
  }
  .products-arrow:disabled { opacity: 0.3; }
}


/* Image fills the entire card. A wrapping span is added by JS so we can
   animate scale (1.05→1) on the new active card without fighting object-fit. */
.product-card__image {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center 35%;
  display: block;
  will-change: transform;
}

/* Door Closers (home): el cierrapuertas queda en el centro de la foto, justo
   donde el panel inferior con blur lo tapaba. Acercamos la imagen y subimos el
   encuadre para que el producto quede por encima del scrim. No toca el tamaño
   de la card — solo reencuadra el contenido dentro del recorte existente. */
.product-card[data-index="0"] .product-card__image {
  object-position: 50% 42%;
  transform-origin: 50% 42%;
  transform: scale(1.62) translateY(-17%);
}

/* El panel con blur arranca un poco más abajo en esta card para descubrir por
   completo el cuerpo del cierrapuertas, sin perder legibilidad del texto. */
.product-card[data-index="0"] .product-card__body {
  height: 46%;
}


/* Corner action button — circular glass (matches the site's glass arrows).
   Sits glassy over the photo at rest, then turns solid white on hover. */
.product-card__cta {
  position: absolute;
  top: 16px;
  right: 16px;
  z-index: 4;

  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 40px;
  height: 40px;
  border-radius: 50%;

  background: rgba(255, 255, 255, 0.16);
  border: 1px solid rgba(255, 255, 255, 0.55);
  color: #FFFFFF;
  box-shadow: 0 4px 16px rgba(0, 0, 0, 0.18);
  -webkit-backdrop-filter: blur(10px) saturate(160%);
          backdrop-filter: blur(10px) saturate(160%);

  transition: background 280ms ease,
              color 280ms ease,
              border-color 280ms ease,
              transform 350ms cubic-bezier(0.16, 1, 0.3, 1);
}

.product-card__cta svg {
  width: 17px;
  height: 17px;
  transition: transform 350ms cubic-bezier(0.16, 1, 0.3, 1);
}

.product-card:hover .product-card__cta {
  background: #FFFFFF;
  border-color: #FFFFFF;
  color: #0A0E14;
  transform: scale(1.08);
}

.product-card:hover .product-card__cta svg {
  transform: translateX(3px);
}


/* (legacy fan mobile block removed — handled by the horizontal-row rules) */


/* Glass panel — dark gradient covering the bottom 55%, blur fades with mask */
.product-card__body {
  position: absolute;
  inset: auto 0 0 0;
  height: 55%;
  padding: 0 26px 26px;
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  gap: 8px;

  background: linear-gradient(
    to top,
    rgba(0, 0, 0, 0.85) 0%,
    rgba(0, 0, 0, 0.40) 40%,
    rgba(0, 0, 0, 0)    65%
  );

  -webkit-backdrop-filter: blur(12px);
          backdrop-filter: blur(12px);
  -webkit-mask-image: linear-gradient(to top, #000 60%, transparent 100%);
          mask-image: linear-gradient(to top, #000 60%, transparent 100%);

  border-top: 0;
}

.product-card__title {
  font-size: 21px;
  font-weight: var(--weight-medium);
  line-height: 1.15;
  letter-spacing: var(--tracking-tight);
  color: #FFFFFF;
  /* Keep the title crisp now that the gradient lets more image through. */
  text-shadow: 0 2px 10px rgba(0, 0, 0, 0.5);
}

.product-card__caption {
  font-size: 14px;
  font-weight: var(--weight-regular);
  color: rgba(255, 255, 255, 0.8);
  line-height: 1.4;
}

.product-card__meta {
  margin-top: 2px;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: 13px;
  font-weight: var(--weight-regular);
  color: rgba(255, 255, 255, 0.65);
}

.product-card__meta::before {
  content: "·";
  display: inline-block;
  font-size: 14px;
  line-height: 1;
  color: rgba(255, 255, 255, 0.65);
}


/* --------------------------------------------------------------------------
   HOVER TAKEOVER (mouse only, active card only) — the existing glass panel
   grows to fill the card, the title centres + enlarges, caption + meta fade.
   Does NOT touch the carousel's is-active/is-prev/is-next transforms.
   -------------------------------------------------------------------------- */
@media (hover: hover) {
  .product-card__body {
    transition:
      height 450ms cubic-bezier(0.4, 0, 0.2, 1),
      background 350ms ease,
      backdrop-filter 350ms ease,
      -webkit-backdrop-filter 350ms ease;
  }
  .product-card__title {
    position: relative;   /* anchor for the underline pseudo */
    transition: font-size 450ms cubic-bezier(0.4, 0, 0.2, 1);
  }
  .product-card__caption,
  .product-card__meta {
    transition: opacity 300ms ease;
  }

  /* Underline — ABSOLUTE to the title, OUT of the flex flow so it never offsets
     the text centring. Sits 24px below the card centre. Drawn after the title
     settles (350ms delay). Hidden at rest. */
  .product-card__title::after {
    content: '';
    position: absolute;
    top: calc(50% + 24px);
    left: 50%;
    transform: translateX(-50%);
    width: 0;
    height: 1px;
    background: rgba(255, 255, 255, 0.7);
    opacity: 0;
    transition:
      width 500ms cubic-bezier(0.4, 0, 0.2, 1) 350ms,
      opacity 300ms ease 350ms;
    pointer-events: none;
  }

  /* Glass panel grows to fill the card (the working glassmorphism — kept) */
  .product-card:hover .product-card__body {
    height: 100%;
    background: linear-gradient(to top, rgba(0, 0, 0, 0.60), rgba(0, 0, 0, 0.45));
    -webkit-backdrop-filter: blur(22px) saturate(160%);
            backdrop-filter: blur(22px) saturate(160%);
    -webkit-mask-image: none;
            mask-image: none;
  }

  /* Title — EXACT centre of the card (only the text; the ::after is absolute and
     does not enter the flex). Smaller than before. */
  .product-card:hover .product-card__title {
    position: absolute;
    inset: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: clamp(20px, 2.2vw, 32px);
    line-height: 1.1;
    letter-spacing: -0.015em;
    text-align: center;
    color: #FFFFFF;
    z-index: 2;
    padding: var(--space-xl);
  }

  /* Underline reveals once the title is centred */
  .product-card:hover .product-card__title::after {
    width: 56px;
    opacity: 1;
  }

  /* Supporting copy fades out and leaves the flow */
  .product-card:hover .product-card__caption,
  .product-card:hover .product-card__meta {
    opacity: 0;
    position: absolute;
  }
}


/* --------------------------------------------------------------------------
   FAN ARROWS — circular glass, flanking the cards
   -------------------------------------------------------------------------- */

/* Perfect circle, real glass, locked to 52×52 (no stretching) */
.products-fan__arrow {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  z-index: 4;

  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  width: 52px;
  height: 52px;
  min-width: 52px;
  min-height: 52px;
  border-radius: 50%;
  padding: 0;
  box-sizing: border-box;

  background: rgba(255, 255, 255, 0.60);
  -webkit-backdrop-filter: blur(24px) saturate(180%);
          backdrop-filter: blur(24px) saturate(180%);
  border: 1px solid rgba(255, 255, 255, 0.80);
  box-shadow: 0 6px 18px rgba(0, 0, 0, 0.12);

  color: rgba(10, 10, 10, 0.75);
  cursor: pointer;

  transition: background 300ms ease-out,
              box-shadow 300ms ease-out,
              transform 300ms cubic-bezier(0.16, 1, 0.3, 1);
}

/* Inside the carousel area, ~24px from the fan edge */
.products-fan__arrow--prev { left:  24px; }
.products-fan__arrow--next { right: 24px; }

.products-fan__arrow:hover {
  background: rgba(255, 255, 255, 0.95);
  transform: translateY(-50%) scale(1.08);
  box-shadow: 0 10px 24px rgba(0, 0, 0, 0.16);
}

.products-fan__arrow svg {
  width: 20px;
  height: 20px;
  transition: transform 300ms cubic-bezier(0.16, 1, 0.3, 1);
}

.products-fan__arrow--prev:hover svg { transform: translateX(-2px); }
.products-fan__arrow--next:hover svg { transform: translateX(2px); }

.products-fan__arrow:disabled,
.products-fan__arrow.is-disabled {
  opacity: 0.35;
  pointer-events: none;
}

@media (max-width: 640px) {
  .products-fan__arrow { width: 44px; height: 44px; min-width: 44px; min-height: 44px; }
  .products-fan__arrow--prev { left:  16px; }
  .products-fan__arrow--next { right: 16px; }
}


/* --------------------------------------------------------------------------
   PROGRESS BARS — 3 thin horizontal indicators below the fan
   -------------------------------------------------------------------------- */

.products-fan__progress {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  margin-top: 48px;
}

.products-fan__progress .bar {
  width: 32px;
  height: 3px;
  border-radius: 2px;
  background: rgba(10, 10, 10, 0.15);
  border: 0;
  padding: 0;
  cursor: pointer;
  transition: width 400ms ease-out, background 400ms ease-out;
}

.products-fan__progress .bar:hover {
  background: rgba(10, 10, 10, 0.35);
}

.products-fan__progress .bar.is-active {
  width: 48px;
  background: var(--color-blue-gaab);
}


/* --------------------------------------------------------------------------
   HEADER CTA — "View all", under the title (replaces the old subtitle).
   Left-aligned, where the subtitle used to sit.
   -------------------------------------------------------------------------- */
.products-header-cta {
  margin-top: clamp(20px, 2.5vh, 32px);
  display: flex;
  justify-content: flex-start;
}

.products-view-all {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 11px 18px;                 /* smaller */
  background: var(--color-blue-gaab);
  color: #FFFFFF;
  border-radius: 12px;                /* was 999px — rounded rectangle, sober */
  font-family: var(--font-sans);
  font-size: 13px;                    /* was ~16px */
  font-weight: 500;
  letter-spacing: -0.005em;
  text-decoration: none;
  box-shadow: none;                   /* shadow removed */
  transition: background 200ms, transform 200ms;
}

.products-view-all:hover {
  background: #152D52;
  transform: translateX(2px);
  box-shadow: none;
}

.products-view-all span[aria-hidden] {
  font-size: 14px;
  margin-left: 2px;
  transition: transform 200ms ease-out;
}
.products-view-all:hover span[aria-hidden] { transform: translateX(2px); }


/* --------------------------------------------------------------------------
   BOOM LETTERS — used by both .products-header__title and .product-card__title
   Each character is wrapped in .char-wrapper; .char rises from y=100% to 0.
   -------------------------------------------------------------------------- */

.char-wrapper {
  display: inline-block;
  overflow: hidden;
  vertical-align: bottom;
  line-height: 1.05;
}

.char-wrapper--space {
  width: 0.28em;
}

.char {
  display: inline-block;
  transform: translateY(100%);
  transition: transform 600ms cubic-bezier(0.16, 1, 0.3, 1);
  will-change: transform;
}

.char.is-visible {
  transform: translateY(0);
}


/* ==========================================================================
   DOOR CLOSER — Apple AirPods-style exploded reveal. The 4 components are
   sprite-cropped from one image (part2gaab-sprite.png) into 4 divs that start
   assembled and physically separate as you scroll; the features then reveal in
   sequence. Pinned + scrubbed by anatomy.js. mix-blend multiply melts each
   sprite's white backdrop into the cream page (and lets sprites overlap clean).
   ========================================================================== */

.closer-section {
  position: relative;
  width: 100%;
  min-height: 100vh;
  /* Exact backdrop of anatomy_frame0.png / anatomy_optimized.mp4 (#FDFDFD), so
     the video/image rectangle is invisible — the product reads as floating. */
  background: #FDFDFD;
  overflow: hidden;
}

/* Header — centred near the top; anatomy.js fades it out as the product rises. */
.closer-header {
  position: absolute;
  top: 12vh;
  left: 50%;
  transform: translateX(-50%);
  width: 100%;
  max-width: 820px;
  padding: 0 24px;
  text-align: center;
  z-index: 10;
}

.closer-eyebrow {
  display: block;
  font-family: ui-monospace, 'JetBrains Mono', monospace;
  font-size: 13px;
  font-weight: 500;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: #888888;
  margin-bottom: 24px;
}

.closer-title {
  font-family: var(--font-sans);
  font-weight: 600;
  font-size: clamp(2.8rem, 6vw, 4.5rem);
  line-height: 1.05;
  letter-spacing: -0.02em;
  color: #0A0A0A;
  margin: 0 0 20px;
}

.closer-subtitle {
  font-family: var(--font-sans);
  font-weight: 400;
  font-size: 1.2rem;
  line-height: 1.5;
  color: #666666;
  margin: 0;
}

/* Product — one COMPLETE unit, centred. anatomy.js owns its transform
   (xPercent/yPercent centring + animated y / scale / opacity). */
.closer-product {
  position: absolute;
  top: 50%;
  left: 50%;
  z-index: 5;
  will-change: transform, opacity;
}

/* Glow behind the product — lights up during phase 1. */
.product-glow {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  width: 130%;
  height: 130%;
  background: radial-gradient(
    circle,
    rgba(255, 255, 255, 0.85) 0%,
    rgba(255, 255, 255, 0.40) 30%,
    transparent 70%
  );
  opacity: 0;
  z-index: 0;
  pointer-events: none;
  filter: blur(50px);
}

.closer-img {
  position: relative;
  z-index: 1;
  display: block;
  /* Same footprint as the video (they are the same frame). height:auto keeps the
     true aspect ratio. No brightness/drop-shadow filter — the image is opaque
     (white backdrop), so those would darken the rectangle / cast a boxy shadow.
     anatomy.js fades it in (opacity) instead, over the invisible #FDFDFD field. */
  width: min(700px, 48vw);
  height: auto;
  /* Rule A — feather the frame's rectangle into the page so no box edge shows.
     Gentle (outer ~20% only) so the product itself is never clipped. */
  -webkit-mask-image: radial-gradient(ellipse closest-side at center, #000 68%, transparent 100%);
          mask-image: radial-gradient(ellipse closest-side at center, #000 68%, transparent 100%);
}

/* Narrative video — overlays the product, same footprint. Starts invisible;
   anatomy.js cross-fades the photo into it (and scrubs its currentTime) only
   from 25% of the pin onward, so it never interferes with the entrance. */
.closer-video {
  position: absolute;
  top: 50%;
  left: 50%;
  /* Natural scale — the video IS the frame-0 image at the same size, so it lands
     exactly where the entrance image is. No scale/offset/chroma key. */
  transform: translate(-50%, -50%);
  width: min(700px, 48vw);
  height: auto;
  object-fit: contain;
  z-index: 3;                /* above the entrance image */
  opacity: 0;                /* anatomy.js fades it in once the product lands */
  pointer-events: none;
  /* Rule A — same feather as .closer-img so the cross-faded video shares the
     exact silhouette and never reveals its own rectangle. */
  -webkit-mask-image: radial-gradient(ellipse closest-side at center, #000 68%, transparent 100%);
          mask-image: radial-gradient(ellipse closest-side at center, #000 68%, transparent 100%);
}

/* Top shadow — MASKED to the product silhouette (so it darkens the product,
   not a rectangle of the cream page). Lifts away as the product ignites. */
.product-shadow-overlay {
  position: absolute;
  inset: 0;
  z-index: 2;
  pointer-events: none;
  background: linear-gradient(
    to bottom,
    rgba(0, 0, 0, 0.80) 0%,
    rgba(0, 0, 0, 0.46) 35%,
    transparent 68%
  );
  -webkit-mask: url('../assets/images/part1gaabtransp.png') center / min(680px, 48vw) auto no-repeat;
          mask: url('../assets/images/part1gaabtransp.png') center / min(680px, 48vw) auto no-repeat;
  opacity: 1;
}

/* Descriptions — flank the product; revealed in pairs by anatomy.js.
   anatomy.js owns the transform (yPercent centring + animated x). */
.desc {
  position: absolute;
  top: 50%;
  max-width: min(260px, 20vw);
  opacity: 0;
  z-index: 8;
}
/* Vertical centring + horizontal slide are owned by anatomy.js (yPercent / x),
   so no transform here — it would clobber the gsap-driven slide. */
/* Left block sits at mid-height; right block lower — matching the Apple refs. */
.desc--left  { left: 4%;  top: 50%; }
.desc--right { right: 4%; top: 63%; }

.desc h4 {
  font-family: var(--font-sans);
  font-weight: 700;
  font-size: 1.5rem;
  color: #0A0A0A;
  margin: 0 0 12px;
  line-height: 1.2;
}
.desc p {
  font-family: var(--font-sans);
  font-weight: 400;
  font-size: 1rem;
  line-height: 1.5;
  color: #666666;
  margin: 0;
}

/* Tablet / mobile — no pin: header, product (lit) and all descriptions just
   stack in normal flow. anatomy.js shortcuts to this state below 1024px. */
/* Tablet / mobile — the section KEEPS its pinned, absolutely-positioned layout
   (it used to collapse to static flow, which is why all three products showed at
   once as a flat block). Only the composition changes: the product sits in the
   upper half instead of dead centre, and the captions move from the left/right
   edges to a single centred column in the lower half, so they rise from BELOW
   the product. anatomy.js still owns opacity + the y drift, so the entrance and
   the upward travel are the same animation as desktop. */
@media (max-width: 1024px) {
  .closer-section { min-height: 100vh; }
  /* Nudged down from the shared 12vh — mobile only. It still fades out on the
     product's arrival: anatomy.js drives its opacity as `1 - f1`, which reaches
     0 exactly when the rise finishes at 25% of the pin, so the product never
     lands on top of live text. */
  .closer-header { top: 17vh; }
  .closer-title { font-size: clamp(1.6rem, 5.6vw, 2.2rem); }
  .closer-subtitle { font-size: 0.95rem; }

  /* Product lifts into the top half to clear the caption column below it.
     The explicit width matters: .closer-product is absolute at left:50% with no
     width, so it shrink-to-fits against the space left of the right edge — just
     195px on a 390px screen. The global `img { max-width: 100% }` then clamped
     the artwork to that, which is why the product looked tiny no matter what
     width the image itself asked for. Desktop never hit this because half of a
     1440px viewport is plenty. */
  .closer-product { top: 38%; width: min(96vw, 520px); }
  .closer-img,
  .closer-video { width: 100%; }
  .product-shadow-overlay { display: none; }

  /* Both captions share one centred column low on the screen. anatomy.js sets
     yPercent:-50 on them, so `top` is their centre line. */
  .desc,
  .desc--left,
  .desc--right {
    left: 50%;
    right: auto;
    top: 76%;
    width: min(84vw, 380px);
    max-width: none;
    margin-left: calc(min(84vw, 380px) / -2);
    text-align: center;
  }
  /* Smaller copy on a phone — the desktop sizes crowd a 390px column.
     The two captions are sequential (the left one fades out at 56% exactly as
     the right one fades in), so sharing one spot reads as a single caption area
     handing over, not as two blocks colliding. */
  .desc h4 { font-size: 1.02rem; margin-bottom: 6px; }
  .desc p  { font-size: 0.85rem; line-height: 1.5; }
}

/* ==========================================================================
   ABOUT SECTION — Off-white, 2 cols (text + image), parallax on image
   ========================================================================== */

.about-section {
  background: var(--color-off-white);
  padding-block: var(--space-4xl);
  overflow: hidden;
}

.about-container {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 96px;
  align-items: center;
  max-width: var(--container-max);
  margin-inline: auto;
  padding-inline: var(--container-padding);
}

.about-text {
  display: flex;
  flex-direction: column;
  gap: var(--space-md);
  max-width: 560px;
}

.about-text .eyebrow {
  margin-bottom: 0;
}

.about-title {
  font-size: var(--text-h2);
  font-weight: var(--weight-medium);
  line-height: var(--leading-tight);
  letter-spacing: var(--tracking-tight);
  color: var(--color-text-primary);
  margin-bottom: var(--space-md);
}

.about-paragraph {
  font-size: var(--text-body);
  font-weight: var(--weight-regular);
  line-height: var(--leading-normal);
  color: var(--color-medium-gray);
}

.about-cta {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  width: fit-content;
  margin-top: var(--space-md);
  font-size: var(--text-small);
  font-weight: var(--weight-medium);
  letter-spacing: var(--tracking-loose);
  color: var(--color-blue-gaab);
}

.about-cta .arrow {
  display: inline-block;
  transition: transform var(--duration-slow) var(--ease-out);
}

.about-cta:hover .arrow { transform: translateX(4px); }

/* Image side — parallax handled by GSAP */
.about-media {
  position: relative;
  width: 100%;
  aspect-ratio: 4 / 5;
  overflow: hidden;
  border-radius: 24px;
  background: var(--color-light-gray);
}

.about-media__image {
  width: 100%;
  height: 110%; /* extra height so the parallax has room to move */
  object-fit: cover;
  display: block;
  will-change: transform;
}

@media (max-width: 1024px) {
  .about-container { gap: 48px; }
}

@media (max-width: 768px) {
  .about-container {
    grid-template-columns: 1fr;
    gap: var(--space-xl);
  }
  .about-media { aspect-ratio: 4 / 3; }
  .about-media__image { height: 100%; }
}


/* ==========================================================================
   FOOTER — Black background, three columns
   ========================================================================== */

.footer {
  position: relative;
  z-index: 1;            /* sits cleanly after the pinned Trust section */
  background: var(--color-black);
  color: var(--color-white);
  padding-block: var(--space-3xl) var(--space-xl);
}

.footer__container {
  width: 100%;
  max-width: var(--container-max);
  margin-inline: auto;
  padding-inline: var(--container-padding);
  display: grid;
  grid-template-columns: 1fr 2fr;
  gap: var(--space-3xl);
}

.footer__logo {
  display: block;
  height: 32px;
  width: auto;
  margin-bottom: var(--space-md);
}

.footer__tagline {
  font-size: var(--text-small);
  color: rgba(255, 255, 255, 0.6);
  line-height: var(--leading-normal);
}

.footer__nav {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: var(--space-xl);
}

.footer__nav-title {
  font-size: var(--text-micro);
  font-weight: var(--weight-medium);
  text-transform: uppercase;
  letter-spacing: var(--tracking-label);
  color: rgba(255, 255, 255, 0.5);
  margin-bottom: var(--space-md);
}

.footer__nav-group ul {
  list-style: none;
  display: flex;
  flex-direction: column;
  gap: var(--space-sm);
}

.footer__nav-group a,
.footer__nav-group address a {
  font-size: var(--text-small);
  color: rgba(255, 255, 255, 0.85);
  transition: color var(--duration-fast) ease-out;
}

.footer__nav-group a:hover,
.footer__nav-group address a:hover {
  color: var(--color-white);
}

.footer__nav-group address {
  font-style: normal;
  font-size: var(--text-small);
  color: rgba(255, 255, 255, 0.85);
  line-height: 1.8;
}

/* Contact items con iconito a la izquierda. Se aplica en mobile y desktop. */
.footer__contact {
  display: flex;
  flex-direction: column;
  gap: 12px;
  line-height: 1.5;
}
.footer__contact-item {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  color: rgba(255, 255, 255, 0.85);
  text-decoration: none;
  transition: color var(--duration-fast) ease-out;
}
.footer__contact-item:hover { color: var(--color-white); }
.footer__contact-icon {
  flex-shrink: 0;
  margin-top: 2px;
  color: rgba(255, 255, 255, 0.55);
  transition: color var(--duration-fast) ease-out;
}
.footer__contact-item:hover .footer__contact-icon { color: var(--color-gaab-sky); }

.footer__bottom {
  grid-column: 1 / -1;
  margin-top: var(--space-2xl);
  padding-top: var(--space-lg);
  border-top: 0.5px solid rgba(255, 255, 255, 0.08);
  font-size: var(--text-micro);
  color: rgba(255, 255, 255, 0.5);
  display: flex;
  flex-wrap: wrap;
  gap: 10px 18px;
  align-items: baseline;
  justify-content: space-between;
}
.footer__bottom p { margin: 0; }
.footer__terms {
  color: rgba(255, 255, 255, 0.65);
  text-decoration: none;
  letter-spacing: 0.02em;
  transition: color var(--duration-fast) ease-out;
}
.footer__terms:hover { color: var(--color-gaab-sky); }

@media (max-width: 1024px) {
  .footer__container { grid-template-columns: 1fr; gap: var(--space-2xl); }
  .footer__nav { gap: var(--space-lg); }
}

@media (max-width: 640px) {
  .footer__nav { grid-template-columns: 1fr 1fr; gap: 28px 20px; }
  /* Ocultar tagline en mobile (pedido del cliente — solo mobile, no tocar el
     resto). */
  .footer__tagline { display: none; }
  /* Agrandar links y headers para leer mejor y respirar más. */
  .footer__nav-title { font-size: 13px; margin-bottom: 14px; }
  .footer__nav-group a,
  .footer__nav-group address a { font-size: 16px; line-height: 1.35; }
  .footer__nav-group ul { gap: 10px; }
  .footer__nav-group address { font-size: 16px; line-height: 1.55; }
  .footer__brand { margin-bottom: 8px; }
}


/* ==========================================================================
   TRUST / SHIPPING — compact off-white band (title, then stat + CTA below) and
   a black visual where the van sits in a dark "folder" frame that rises on
   scroll. The black block merges into the black footer (no seam).
   ========================================================================== */
.trust-section {
  position: relative;
  width: 100%;
  /* No overflow:hidden here — it breaks GSAP pin-spacing and lets the footer
     overlap the pinned section. The rising image is already clipped by
     .trust-visual's own overflow:hidden. */
}

/* === BLOCK 1: textual content — on-brand off-white (NOT beige) === */
.trust-content {
  background: var(--color-off-white);
  padding: clamp(100px, 13vh, 150px) var(--space-2xl) clamp(48px, 7vh, 80px);
}

.trust-content-inner {
  max-width: 1080px;
  margin: 0 auto;
  display: flex;
  flex-direction: column;
  gap: clamp(28px, 4vh, 44px);
}

.trust-header { display: flex; flex-direction: column; gap: var(--space-md); }

.trust-eyebrow {
  font-family: ui-monospace, 'JetBrains Mono', monospace;
  font-size: 11px;
  font-weight: 500;
  letter-spacing: 0.18em;
  color: var(--color-blue-gaab);
  opacity: 0.85;
  text-transform: uppercase;
}

.trust-title {
  font-family: var(--font-sans);
  font-weight: 500;
  font-size: clamp(34px, 4.2vw, 58px);  /* dialed down from 92px */
  line-height: 1.08;
  letter-spacing: -0.025em;
  color: #0A0A0A;
  margin: 0;
}
/* "to your job site." — fills grey → black, left-to-right, on scroll (trust.js
   animates background-position). Hard-stop gradient over 200% width = a wipe. */
.trust-title-em {
  background-image: linear-gradient(to right, #0A0A0A 50%, rgba(0, 0, 0, 0.45) 50%);
  background-size: 200% 100%;
  background-position: 100% 0;            /* start: grey (unfilled) */
  -webkit-background-clip: text;
  background-clip: text;
  -webkit-text-fill-color: transparent;
  color: transparent;
}

/* Stat + CTA sit in a row BELOW the title, split by a hairline rule */
.trust-side {
  display: flex;
  flex-direction: row;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: var(--space-lg);
  width: 100%;
  border-top: 1px solid rgba(0, 0, 0, 0.10);
  padding-top: clamp(20px, 3vh, 32px);
}

.trust-stat {
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.stat-num {
  font-family: var(--font-sans);
  font-weight: 500;
  font-size: clamp(26px, 2.4vw, 36px);  /* smaller, secondary to the title */
  letter-spacing: -0.02em;
  color: #0A0A0A;
  line-height: 1;
}

.stat-label { font-size: 13px; line-height: 1.4; color: rgba(0, 0, 0, 0.55); margin-top: 2px; }

.trust-cta {
  display: inline-flex;
  align-items: center;
  gap: var(--space-sm);
  padding: clamp(13px, 1.6vw, 16px) clamp(20px, 2.5vw, 26px);
  background: var(--color-blue-gaab);
  color: #FFFFFF;
  border-radius: 999px;
  font-family: var(--font-sans);
  font-size: clamp(14px, 1.1vw, 15px);
  font-weight: 500;
  text-decoration: none;
  transition: background 200ms, transform 200ms;
}
.trust-cta:hover { background: #152D52; transform: translateX(2px); }

/* === BLOCK 2: black visual; van inside a dark folder that merges w/ footer === */
.trust-visual {
  position: relative;
  width: 100%;
  background: #000000;   /* same as footer — continuous black, no seam */
  padding: clamp(40px, 6vh, 80px) var(--space-2xl) clamp(60px, 8vh, 100px);
  /* the larger padding-bottom gives breathing room before the footer */
  overflow: hidden;       /* clips the rising frame */
}

/* The device frame — dark card that reads as a contained unit on the black,
   distinguished from the footer by a brighter edge + dramatic shadow. */
.trust-image-wrapper {
  position: relative;
  width: 100%;
  max-width: 1320px;
  margin: 0 auto;
  background: #0A0A0A;
  border: 1px solid rgba(255, 255, 255, 0.1);   /* brighter than 0.06 — visible */
  border-radius: 16px;
  overflow: hidden;
  box-shadow:
    0 40px 100px rgba(0, 0, 0, 0.6),
    0 16px 40px rgba(0, 0, 0, 0.4),
    inset 0 1px 0 rgba(255, 255, 255, 0.04);    /* subtle top glow */
  will-change: transform;
}

.trust-image {
  width: 100%;
  height: auto;
  display: block;
  max-height: clamp(400px, 55vh, 640px);
  object-fit: cover;
  object-position: center;
}

/* Frame tab — sticks up from the top-left, fused with the frame body */
.trust-image-tab {
  position: absolute;
  top: -33px;
  left: -1px;   /* compensate the frame's 1px border so edges line up */
  height: 33px;
  padding: 0 18px;
  display: flex;
  align-items: center;
  background: #0A0A0A;
  border: 1px solid rgba(255, 255, 255, 0.1);
  border-bottom: 1px solid #0A0A0A;   /* same as bg — erases the seam */
  border-radius: 14px 14px 0 0;
  z-index: 2;
}

.image-tab-label {
  font-family: ui-monospace, 'JetBrains Mono', monospace;
  font-size: 10px;
  font-weight: 500;
  letter-spacing: 0.14em;
  color: rgba(255, 255, 255, 0.5);
  text-transform: uppercase;
}

@media (max-width: 900px) {
  .trust-title { font-size: clamp(30px, 8vw, 44px); }
  .stat-num { font-size: clamp(24px, 6vw, 32px); }
  .trust-side { flex-direction: column; align-items: flex-start; gap: var(--space-lg); }
  .trust-image { max-height: clamp(240px, 38vh, 360px); }
}


/* ==========================================================================
   SCROLL HERO — scroll-scrubbed product film + two golden-lit text beats
   The section is pinned by scroll-hero.js; the video fills it (object-fit
   cover) and currentTime is driven by scroll. Beats fade in over it.
   ========================================================================== */

.scroll-hero {
  position: relative;
  width: 100%;
  height: 100vh;
  overflow: hidden;
  background: var(--color-white);
}

.scroll-hero__video {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center;
  /* video frame 0 is near-white; this keeps a clean canvas before scroll */
}

/* Dark cinematic overlay — the film background is bright (pale stone), so the
   white headline needs this to stay legible. Strongest behind the centred
   text, softer at the edges so the video still reads. Opacity is fixed (the
   JS no longer drives it). */
.scroll-hero__scrim {
  position: absolute;
  inset: 0;
  pointer-events: none;
  opacity: 1;
  background:
    radial-gradient(110% 85% at 50% 48%, rgba(8, 10, 14, 0.58) 0%, rgba(8, 10, 14, 0.30) 60%, rgba(8, 10, 14, 0.20) 100%),
    linear-gradient(180deg, rgba(8, 10, 14, 0.30) 0%, rgba(8, 10, 14, 0.12) 45%, rgba(8, 10, 14, 0.34) 100%);
}

/* Portal cream layer — the film's last frame is a warm, vignetted beige, NOT
   flat cream. In the final scroll segment scroll-hero.js fades this flat
   #FAFAF7 layer in over the canvas so the hero dissolves seamlessly into the
   products section (same #FAFAF7 background) with no visible colour seam.
   Sits above the film + scrim (z2) but below the copy (z3), which fades out. */
.scroll-hero__cream {
  position: absolute;
  inset: 0;
  z-index: 2;
  pointer-events: none;
  opacity: 0;
  background: var(--color-off-white); /* #FAFAF7 — exact match to products bg */
}

/* --- Hero content: terminal-style letter ignition ------------------------
   Two titles + a CTA, stacked dead-centre over the film. Each title's letters
   are split into .char spans (in scroll-hero.js) that enter dim grey, flash a
   cool sky blue, and settle to white — a wave of light sweeping left → right.
   The video autoplays; a GSAP timeline drives the whole choreography. */
.hero-content {
  position: absolute;
  inset: 0;
  z-index: 3;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: clamp(14px, 2.2vh, 22px);
  padding: 0 var(--container-padding);
  text-align: center;
  pointer-events: none;
}

.hero-origin {
  font-family: var(--font-sans);
  font-size: clamp(0.68rem, 0.78vw, 0.82rem);
  font-weight: 500;
  letter-spacing: 0.28em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.88);
  text-shadow: 0 1px 8px rgba(0, 0, 0, 0.35);
}
@media (max-width: 700px) {
  .hero-origin { font-size: 0.62rem; letter-spacing: 0.22em; }
}

.hero-title {
  grid-area: 1 / 1;
  width: min(94vw, 980px);
  margin: 0;
  font-family: var(--font-sans);
  font-weight: 600;
  letter-spacing: -0.02em;
  line-height: 1.15;
  color: #FFFFFF;
  text-shadow: 0 2px 20px rgba(0, 0, 0, 0.30);
}

/* Same size as title 2 so every rotating headline matches (no oversized/clipped
   first line). Weight/line-height/colour come from .hero-title. */
.hero-title--1 { font-size: clamp(1.65rem, 3.4vw, 2.7rem); }
/* Title 2 is a full sentence, so it rides a notch smaller than title 1 to
   avoid a giant multi-line wrap — same weight, same family. */
.hero-title--2 { font-size: clamp(1.65rem, 3.4vw, 2.7rem); }

/* Line-break control por viewport para .hero-title--1:
   desktop → break después de "Hardware" (2 líneas)
   mobile  → breaks después de "Residential" y "for all" (3 líneas)
   Default (desktop): desktop BR visible, mobile BRs ocultos. */
.hero-br-mobile { display: none; }
.hero-br-desktop { display: inline; }
@media (max-width: 700px) {
  .hero-br-mobile { display: inline; }
  .hero-br-desktop { display: none; }
}

/* Title 2 + CTA share the centre cell and stack vertically. */
.hero-group--2 {
  grid-area: 1 / 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: clamp(24px, 3vw, 36px);
  pointer-events: auto;
}

/* Split letters — GSAP owns the entry; these are the resting styles. The
   starting colour/opacity are set in JS so a no-JS load still shows text. */
.hero-title .char {
  display: inline-block;
}

/* Keeps a word's letters together. Each .char is an inline-block, and a line can
   break between any two inline-blocks — so without this wrapper "Hardware" broke
   mid-word. Breaks now only happen at the real spaces between words. */
.hero-title .word {
  display: inline-block;
  white-space: nowrap;
}

/* CTA — black pill, fades + lifts in as a block (no letter effect). */
/* Animatable angle for the shine border (so we rotate the gradient, not the
   masked frame — that's what makes the light actually trace the perimeter). */
@property --cta-shine-angle {
  syntax: '<angle>';
  initial-value: 0deg;
  inherits: false;
}

.hero-cta {
  position: relative;            /* anchor for the shine ring */
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 14px 32px;
  background: #000000;
  color: #FFFFFF;
  font-weight: var(--weight-medium);
  font-size: var(--text-body);
  line-height: 1;
  border-radius: 100px;
  pointer-events: auto;
  transition: transform 0.25s var(--ease-out), background 0.25s var(--ease-out);
}

/* Shine border — a thin pale-sky light slides around the perimeter on a slow,
   continuous loop. A 1px ring is carved out with a mask so only the edge glows;
   the text stays untouched. */
.hero-cta::before {
  content: '';
  position: absolute;
  inset: -1px;
  border-radius: inherit;
  padding: 1px;
  background: conic-gradient(
    from var(--cta-shine-angle),
    transparent 0deg,
    transparent 270deg,
    #D6EBF7 320deg,
    #FFFFFF 340deg,
    #D6EBF7 360deg
  );
  -webkit-mask:
    linear-gradient(#000 0 0) content-box,
    linear-gradient(#000 0 0);
          mask:
    linear-gradient(#000 0 0) content-box,
    linear-gradient(#000 0 0);
  -webkit-mask-composite: xor;
          mask-composite: exclude;
  opacity: 0.5;
  pointer-events: none;
  animation: hero-cta-shine 3.5s linear infinite;
}

.hero-cta:hover {
  transform: scale(1.03);
  background: #14181F;
  will-change: transform;        /* only promote on hover, idle stays cheap */
}
/* Hover — the light gets a touch brighter and circles faster. */
.hero-cta:hover::before {
  opacity: 0.9;
  animation-duration: 2s;
}

@keyframes hero-cta-shine {
  to { --cta-shine-angle: 360deg; }
}

@media (prefers-reduced-motion: reduce) {
  .hero-cta::before { animation: none; }
}

/* Static fallback (mobile / reduced-motion): no scrub, so the two titles
   can't share a cell — stack them in a column and show everything. */
.scroll-hero--static .hero-content {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: clamp(20px, 4vh, 36px);
}
.scroll-hero--static .hero-title,
.scroll-hero--static .hero-group--2 {
  grid-area: auto;
}

@media (max-width: 768px) {
  /* Generous side padding so the headline never kisses the edges — it is split
     into per-letter spans, so a tight box makes the wave look ragged. */
  .hero-content { padding: 0 32px; }
  /* ~28px at 390px. The original 4.6vw ceiling resolved to ~18px (subtitle
     size); a first pass at 10.5vw overshot to ~41px and crowded the frame.
     This sits between: clearly an H1, still airy against the film. */
  .hero-title--1,
  .hero-title--2 {
    /* Ceiling: "Commercial & Residential" has to stay on ONE line inside the
       326px the padded grid leaves, so "Hardware" drops to line 2 by itself and
       the <br> gives line 3. Measured — 6.9vw still fits; much past that and the
       first line breaks and the 3-line shape is gone. No text-wrap:balance:
       balancing evens the lines out and pulls "Hardware" back up. */
    font-size: clamp(1.4rem, 6.9vw, 2rem);
    line-height: 1.28;
    /* .hero-title carries `width: min(94vw, 980px)` for desktop. On a phone 94vw
       is 367px — wider than the 326px the padded grid actually leaves — so the
       headline hung 9px past the right edge no matter the font size. Fill the
       grid area instead and let it wrap inside the padding. */
    width: 100%;
    max-width: 100%;
  }
}


/* ==========================================================================
   SHIPPING — headline on a black field, with a short, cropped band of the
   delivery-van photo below it. Image-only (no video / no scroll-scrub).
   ========================================================================== */

.van-section {
  position: relative;
  width: 100%;
  background: var(--color-black);
  overflow: hidden;
}

/* Black band on top — eyebrow + left-aligned title. The generous bottom
   padding is the breathing room (a band of black air) before the film. */
.van-content {
  width: 100%;
  max-width: var(--container-max);
  margin-inline: auto;
  padding: clamp(104px, 16vh, 184px) clamp(24px, 5vw, 80px) clamp(52px, 9vh, 104px);
  text-align: left;
}

.van-eyebrow {
  display: inline-block;
  font-family: ui-monospace, 'JetBrains Mono', monospace;
  font-size: 13px;
  font-weight: 500;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: #888888;
  padding: 5px 13px;
  border: 1px solid #333333;
  border-radius: 4px;
  margin-bottom: clamp(20px, 3vh, 32px);
}

.van-title {
  display: flex;
  flex-direction: column;
  margin: 0;
  font-family: var(--font-sans);
  font-weight: 600;
  /* smaller / more minimal than before */
  font-size: clamp(2.1rem, 4.2vw, 3.8rem);
  line-height: 1.08;
  letter-spacing: -0.02em;
  color: #FFFFFF;
}

.van-line { display: block; }
.van-title .char { display: inline-block; }

/* Delivery film — contained (NOT full-bleed): side gutters, rounded corners
   and bottom breathing room, like an Apple product card. Still scrubbed by
   ship.js. No overlay. */
.van-video {
  display: block;
  width: calc(100% - clamp(48px, 8vw, 140px));   /* side gutters → not edge-to-edge */
  max-width: var(--container-max);
  height: 60vh;
  margin-inline: auto;
  margin-bottom: clamp(48px, 8vh, 100px);        /* air before the footer */
  border-radius: clamp(20px, 2vw, 32px);
  object-fit: cover;
  object-position: center;
}

@media (max-width: 768px) {
  .van-content {
    padding-left: 24px;
    padding-right: 24px;
    padding-bottom: clamp(40px, 7vh, 72px);
  }
  .van-title { font-size: clamp(1.7rem, 6vw, 2.4rem); }
  .van-video {
    width: calc(100% - 32px);
    height: 52vh;
    border-radius: 18px;
    margin-bottom: clamp(36px, 6vh, 64px);
  }
}


/* ==========================================================================
   FOOTER WORDMARK — oversized "GAAB" bleeding to the edges at the very bottom
   (mirrors the reference's giant brand lettering).
   ========================================================================== */
.footer { overflow: hidden; }   /* clip the wordmark's edge bleed */

.footer__wordmark {
  pointer-events: none; /* decorative — must not swallow clicks on the footer links above */
  margin-top: clamp(20px, 3vh, 44px);
  /* Bleed the type off the bottom edge so only the top portion of the word
     shows (em-based, so the crop stays consistent on any screen size). A larger
     negative margin pushes it DOWN and hides MORE of the lettering. */
  margin-bottom: -0.46em;
  width: 100%;
  text-align: center;
  font-family: var(--font-sans);
  font-weight: 500;
  /* Big brand sign-off, mostly cropped by the bottom edge. */
  font-size: clamp(120px, 25vw, 440px);
  line-height: 0.80;
  letter-spacing: -0.03em;
  color: var(--color-white);
  opacity: 0.14;
  white-space: nowrap;
  user-select: none;
}


/* ==========================================================================
   PRODUCTS GRID — Apple-style minimal, filterable catalogue
   Off-white section, 2 rows of 3 cards, category pills, in-page detail modal.
   ========================================================================== */

.products-grid-section {
  background: var(--color-off-white);
  position: relative;
  padding: clamp(80px, 12vh, 140px) 0 clamp(80px, 12vh, 140px);
}

.products-grid-section__inner {
  width: 100%;
  max-width: var(--container-max);
  margin: 0 auto;
  padding: 0 var(--container-padding);
}

/* ----- Header ----- */
.pg-header {
  max-width: 720px;
  margin: 0 auto clamp(32px, 5vh, 56px);
  text-align: center;
}

.pg-header__eyebrow {
  margin-bottom: 14px;
}

.pg-header__title {
  font-size: var(--text-h2);
  font-weight: var(--weight-medium);
  line-height: 1.08;
  letter-spacing: var(--tracking-tight);
  color: var(--color-text-primary);
}

.pg-header__title .grad-text {
  background: linear-gradient(90deg, #1B3A6B 0%, #3A5A9F 100%);
  -webkit-background-clip: text;
          background-clip: text;
  color: transparent;
  -webkit-text-fill-color: transparent;
}

.pg-header__subtitle {
  margin-top: 16px;
  font-size: var(--text-body-lg);
  font-weight: var(--weight-regular);
  line-height: 1.5;
  color: var(--color-text-secondary);
}

/* ----- Filter pills ----- */
.pg-filters {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 10px;
  margin-bottom: clamp(32px, 5vh, 56px);
}

.pg-pill {
  padding: 10px 20px;
  border-radius: var(--radius-pill);
  border: 1px solid var(--color-border-light);
  background: transparent;
  color: var(--color-text-secondary);
  font-size: var(--text-small);
  font-weight: var(--weight-medium);
  letter-spacing: 0.01em;
  white-space: nowrap;
  transition: background var(--duration-fast) var(--ease-out),
              color var(--duration-fast) var(--ease-out),
              border-color var(--duration-fast) var(--ease-out),
              transform var(--duration-fast) var(--ease-out);
}

.pg-pill:hover {
  color: var(--color-text-primary);
  border-color: rgba(10, 10, 10, 0.18);
}

.pg-pill.is-active {
  background: var(--color-blue-gaab);
  border-color: var(--color-blue-gaab);
  color: var(--color-white);
  box-shadow: 0 6px 18px rgba(27, 58, 107, 0.22);
}

/* ----- Grid ----- */
.pg-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: clamp(16px, 2vw, 28px);
}

/* ----- Card ----- */
.pg-card {
  position: relative;
  display: flex;
  flex-direction: column;
  background: var(--color-white);
  border: 1px solid var(--color-border-light);
  border-radius: var(--radius-lg);
  overflow: hidden;
  cursor: pointer;
  text-align: left;
  /* Reveal-on-scroll start state */
  opacity: 0;
  transform: translateY(22px);
  transition: opacity 600ms var(--ease-out),
              transform 600ms var(--ease-out),
              box-shadow var(--duration-base) var(--ease-out),
              border-color var(--duration-base) var(--ease-out);
}

.pg-grid.is-revealed .pg-card {
  opacity: 1;
  transform: translateY(0);
  transition-delay: calc(var(--i, 0) * 70ms);
}

.pg-card:hover {
  border-color: rgba(10, 10, 10, 0.14);
  box-shadow: 0 18px 44px rgba(10, 10, 10, 0.10);
}

.pg-card.is-hidden {
  display: none;
}

/* Image area — light tray so the product floats, Apple-style */
.pg-card__media {
  position: relative;
  aspect-ratio: 4 / 3;
  background: var(--color-light-gray);
  overflow: hidden;
}

.pg-card__img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: transform 600ms var(--ease-out);
}

.pg-card:hover .pg-card__img {
  transform: scale(1.04);
}

/* Round "view" affordance, hidden until hover */
.pg-card__view {
  position: absolute;
  top: 14px;
  right: 14px;
  width: 38px;
  height: 38px;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: var(--radius-pill);
  background: rgba(255, 255, 255, 0.92);
  color: var(--color-blue-gaab);
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
  opacity: 0;
  transform: translateY(-4px);
  transition: opacity var(--duration-base) var(--ease-out),
              transform var(--duration-base) var(--ease-out);
}

.pg-card:hover .pg-card__view,
.pg-card:focus-visible .pg-card__view {
  opacity: 1;
  transform: translateY(0);
}

.pg-card__body {
  padding: 22px 24px 26px;
}

.pg-card__tag {
  display: inline-block;
  margin-bottom: 10px;
  font-size: var(--text-micro);
  font-weight: var(--weight-medium);
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
  color: var(--color-blue-gaab);
}

.pg-card__title {
  font-size: var(--text-h3);
  font-weight: var(--weight-medium);
  line-height: 1.15;
  letter-spacing: var(--tracking-tight);
  color: var(--color-text-primary);
}

.pg-card__caption {
  margin-top: 6px;
  font-size: var(--text-body);
  color: var(--color-text-secondary);
}

/* ----- Responsive ----- */
@media (max-width: 900px) {
  .pg-grid { grid-template-columns: repeat(2, 1fr); }
}

@media (max-width: 560px) {
  .pg-grid { grid-template-columns: 1fr; }
  .pg-card__title { font-size: 22px; }
}


/* ==========================================================================
   PRODUCT DETAIL MODAL
   ========================================================================== */

.pg-modal {
  position: fixed;
  inset: 0;
  z-index: var(--z-modal);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 24px;
  opacity: 0;
  visibility: hidden;
  transition: opacity var(--duration-base) var(--ease-out),
              visibility var(--duration-base) var(--ease-out);
}

.pg-modal.is-open {
  opacity: 1;
  visibility: visible;
}

.pg-modal__backdrop {
  position: absolute;
  inset: 0;
  background: rgba(10, 10, 10, 0.55);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
}

.pg-modal__dialog {
  position: relative;
  z-index: 1;
  display: grid;
  grid-template-columns: 1.05fr 1fr;
  width: 100%;
  max-width: 920px;
  max-height: 88vh;
  background: var(--color-white);
  border-radius: var(--radius-xl);
  overflow: hidden;
  box-shadow: 0 40px 100px rgba(10, 10, 10, 0.30);
  transform: scale(0.96) translateY(12px);
  opacity: 0;
  transition: transform var(--duration-slow) var(--ease-out),
              opacity var(--duration-slow) var(--ease-out);
}

.pg-modal.is-open .pg-modal__dialog {
  transform: scale(1) translateY(0);
  opacity: 1;
}

.pg-modal__close {
  position: absolute;
  top: 16px;
  right: 16px;
  z-index: 2;
  width: 40px;
  height: 40px;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: var(--radius-pill);
  background: rgba(255, 255, 255, 0.9);
  color: var(--color-dark-gray);
  box-shadow: 0 2px 10px rgba(10, 10, 10, 0.12);
  transition: background var(--duration-fast) var(--ease-out),
              transform var(--duration-fast) var(--ease-out);
}

.pg-modal__close:hover {
  background: var(--color-white);
  transform: rotate(90deg);
}

.pg-modal__media {
  background: var(--color-light-gray);
}

.pg-modal__img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.pg-modal__body {
  padding: clamp(28px, 4vw, 48px);
  overflow-y: auto;
}

.pg-modal__tag {
  display: inline-block;
  margin-bottom: 12px;
  font-size: var(--text-micro);
  font-weight: var(--weight-medium);
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
  color: var(--color-blue-gaab);
}

.pg-modal__title {
  font-size: var(--text-h3);
  font-weight: var(--weight-medium);
  line-height: 1.12;
  letter-spacing: var(--tracking-tight);
  color: var(--color-text-primary);
}

.pg-modal__desc {
  margin-top: 14px;
  font-size: var(--text-body);
  line-height: 1.6;
  color: var(--color-text-secondary);
}

.pg-modal__specs {
  margin-top: 26px;
  border-top: 1px solid var(--color-border-light);
}

.pg-modal__spec {
  display: flex;
  justify-content: space-between;
  gap: 16px;
  padding: 13px 0;
  border-bottom: 1px solid var(--color-border-light);
}

.pg-modal__spec dt {
  font-size: var(--text-small);
  color: var(--color-text-secondary);
}

.pg-modal__spec dd {
  font-size: var(--text-small);
  font-weight: var(--weight-medium);
  color: var(--color-text-primary);
  text-align: right;
}

.pg-modal__cta {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  margin-top: 28px;
  padding: 14px 26px;
  border-radius: var(--radius-md);
  background: var(--color-blue-gaab);
  color: var(--color-white);
  font-size: var(--text-small);
  font-weight: var(--weight-medium);
  box-shadow: 0 6px 20px rgba(27, 58, 107, 0.28);
  transition: background var(--duration-fast) var(--ease-out),
              transform var(--duration-fast) var(--ease-out),
              box-shadow var(--duration-fast) var(--ease-out);
}

.pg-modal__cta:hover {
  background: var(--color-blue-gaab-dark);
  transform: translateY(-2px);
  box-shadow: 0 10px 28px rgba(27, 58, 107, 0.35);
}

.pg-modal__cta span[aria-hidden] {
  transition: transform var(--duration-fast) var(--ease-out);
}

.pg-modal__cta:hover span[aria-hidden] {
  transform: translateX(4px);
}

body.pg-modal-open {
  overflow: hidden;
}

/* Modal responsive — stack image over content */
@media (max-width: 700px) {
  .pg-modal__dialog {
    grid-template-columns: 1fr;
    max-height: 90vh;
  }
  .pg-modal__media {
    aspect-ratio: 16 / 10;
  }
}

@media (prefers-reduced-motion: reduce) {
  .pg-card,
  .pg-modal,
  .pg-modal__dialog { transition-duration: 1ms; }
}


/* ==========================================================================
   PRODUCTS CAROUSEL — hover takeover disabled (per request). Cards stay in
   their resting state on mouse-over: title bottom-left, caption/meta visible,
   glass panel at 55%, arrow glass (no fill). Appended last so it wins.
   ========================================================================== */
@media (hover: hover) {
  .products-section .product-card:hover .product-card__body {
    height: 55%;
    background: linear-gradient(to top, rgba(0,0,0,0.85) 0%, rgba(0,0,0,0.40) 40%, rgba(0,0,0,0) 65%);
    -webkit-backdrop-filter: blur(12px);
            backdrop-filter: blur(12px);
    -webkit-mask-image: linear-gradient(to top, #000 60%, transparent 100%);
            mask-image: linear-gradient(to top, #000 60%, transparent 100%);
  }
  .products-section .product-card:hover .product-card__title {
    position: static;
    inset: auto;
    display: block;
    font-size: 21px;
    text-align: left;
    padding: 0;
  }
  .products-section .product-card:hover .product-card__title::after {
    width: 0;
    opacity: 0;
  }
  .products-section .product-card:hover .product-card__caption,
  .products-section .product-card:hover .product-card__meta {
    opacity: 1;
    position: static;
  }
  .products-section .product-card:hover .product-card__cta {
    background: rgba(255, 255, 255, 0.16);
    border-color: rgba(255, 255, 255, 0.55);
    color: #FFFFFF;
    transform: none;
  }
  .products-section .product-card:hover .product-card__cta svg {
    transform: none;
  }
}


/* ==========================================================================
   NEWSLETTER MODAL — Home-only split popup (image left, cream form right).
   Injected by scripts/newsletter.js, 10s into the visit. GAAB quiet-luxury:
   blue + cream, system type, generous air. Reuses the video-modal open pattern.
   ========================================================================== */
.nl-modal {
  position: fixed;
  inset: 0;
  z-index: 200;                       /* above navbar (100) + announce bar (101) */
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 24px;
  opacity: 0;
  transition: opacity 0.4s ease;
}
.nl-modal[hidden] { display: none; }
.nl-modal.is-open { opacity: 1; }
/* Explicit display rules would otherwise override the [hidden] attribute. */
.nl-modal__body[hidden],
.nl-modal__success[hidden] { display: none; }

.nl-modal__backdrop {
  position: absolute;
  inset: 0;
  background: rgba(0, 0, 0, 0.6);
  cursor: pointer;
}

.nl-modal__dialog {
  position: relative;
  z-index: 1;
  display: flex;
  width: min(860px, 100%);
  max-height: min(540px, 88vh);
  background: #F7F6F2;                /* cream */
  border-radius: var(--radius-xl);
  overflow: hidden;
  box-shadow: 0 30px 90px -20px rgba(10, 14, 20, 0.5);
  transform: scale(0.96);
  transition: transform 0.4s cubic-bezier(0.22, 1, 0.3, 1);
}
.nl-modal.is-open .nl-modal__dialog { transform: scale(1); }

/* Close — circular, subtle, over the cream panel. */
.nl-modal__close {
  position: absolute;
  top: 16px;
  right: 16px;
  z-index: 2;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 36px;
  height: 36px;
  border-radius: 50%;
  border: none;
  background: rgba(10, 14, 20, 0.06);
  color: #0A0E14;
  cursor: pointer;
  transition: background 0.2s ease;
}
.nl-modal__close:hover { background: rgba(10, 14, 20, 0.12); }

/* Left media — random product photo, full height. */
.nl-modal__media {
  flex: 0 0 46%;
  overflow: hidden;
  background: var(--color-off-white);
}
.nl-modal__media img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

/* Right panel — cream, the form. */
.nl-modal__panel {
  flex: 1 1 54%;
  display: flex;
  align-items: center;
  padding: clamp(32px, 5vw, 52px);
}
.nl-modal__body { width: 100%; }

.nl-modal__title {
  font-family: var(--font-sans);
  font-weight: 600;
  font-size: clamp(1.9rem, 3vw, 2.5rem);
  line-height: 1.05;
  letter-spacing: -0.02em;
  color: var(--color-blue-gaab);
  margin: 0 0 14px;
}
.nl-modal__sub {
  font-family: var(--font-sans);
  font-size: 14.5px;
  line-height: 1.5;
  color: #6B6B6B;
  margin: 0 0 26px;
  max-width: 34ch;
}

.nl-modal__form { display: flex; flex-direction: column; gap: 12px; }
.nl-modal__input {
  width: 100%;
  padding: 14px 20px;
  font-family: var(--font-sans);
  font-size: 15px;
  color: #0A0E14;
  background: #FFFFFF;
  border: 1px solid rgba(10, 14, 20, 0.16);
  border-radius: var(--radius-pill);
  outline: none;
  transition: border-color 0.2s ease, box-shadow 0.2s ease;
}
.nl-modal__input::placeholder { color: #9A9A9A; }
.nl-modal__input:focus {
  border-color: var(--color-blue-gaab);
  box-shadow: 0 0 0 3px rgba(27, 58, 107, 0.12);
}
.nl-modal__submit {
  width: 100%;
  padding: 14px 20px;
  font-family: var(--font-sans);
  font-size: 15px;
  font-weight: 600;
  color: #FFFFFF;
  background: var(--color-blue-gaab);
  border: none;
  border-radius: var(--radius-pill);
  cursor: pointer;
  transition: filter 0.2s ease, transform 0.2s ease;
}
.nl-modal__submit:hover { filter: brightness(1.12); }
.nl-modal__submit:active { transform: translateY(1px); }

.nl-modal__legal {
  font-family: var(--font-sans);
  font-size: 12px;
  color: #9A9A9A;
  margin: 16px 0 0;
}

/* Success state — replaces the form after submit. */
.nl-modal__success {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 14px;
}
.nl-modal__success-check {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 52px;
  height: 52px;
  border-radius: 50%;
  background: rgba(27, 58, 107, 0.1);
  color: var(--color-blue-gaab);
}
.nl-modal__success-msg {
  font-family: var(--font-sans);
  font-size: clamp(1.3rem, 2.4vw, 1.7rem);
  font-weight: 600;
  color: var(--color-blue-gaab);
  margin: 0;
}

/* Mobile — image becomes a top banner, form below; modal near full width. */
@media (max-width: 640px) {
  .nl-modal { padding: 16px; }
  .nl-modal__dialog {
    flex-direction: column;
    width: 100%;
    max-height: 90vh;
  }
  .nl-modal__media {
    flex: 0 0 130px;
    width: 100%;
  }
  .nl-modal__panel { padding: 28px 24px 32px; }
  .nl-modal__sub { margin-bottom: 22px; }
}


/* ==========================================================================
   HELP CTA — home closing section ("Can't find what you're looking for?")
   Light, Apple-like (echoes the About .close-card language). Sits between the
   van section and the footer. Button opens the quote modal.
   ========================================================================== */
.help-cta {
  background: var(--color-off-white);
  /* More vertical air, top and bottom, so the section breathes instead of
     butting up against the van film above and the footer below. The clamp
     scales, so both desktop and mobile gain the room. */
  padding: clamp(100px, 16vh, 180px) var(--container-padding);
  text-align: center;
  border-top: 1px solid var(--color-border-light);
}
.help-cta__inner {
  max-width: 720px;
  margin: 0 auto;
  display: flex;
  flex-direction: column;
  align-items: center;
}
.help-cta__title {
  font-size: clamp(2rem, 5vw, 3.4rem);
  font-weight: 600;
  line-height: 1.06;
  letter-spacing: -0.02em;
  color: var(--color-black);
  margin: 0 0 20px;
}
.help-cta__subtitle {
  font-size: clamp(1rem, 1.6vw, 1.2rem);
  color: var(--color-medium-gray);
  line-height: 1.5;
  max-width: 520px;
  margin: 0 0 40px;
}
.help-cta__btn {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 16px 34px;
  border-radius: 14px;
  background: var(--color-blue-gaab);
  color: #FFFFFF;
  font-size: 16px;
  font-weight: var(--weight-medium);
  box-shadow: 0 10px 30px -12px rgba(27, 58, 107, 0.5);
  transition: background 200ms var(--ease-out), transform 200ms var(--ease-out),
              box-shadow 200ms var(--ease-out);
}
.help-cta__btn:hover {
  background: var(--color-blue-gaab-dark);
  transform: translateY(-2px);
  box-shadow: 0 16px 40px -12px rgba(27, 58, 107, 0.55);
}
.help-cta__arrow { transition: transform 200ms var(--ease-out); }
.help-cta__btn:hover .help-cta__arrow { transform: translateX(4px); }

/* Mobile: a touch smaller — the desktop pill reads oversized on a phone.
   Still a 44px-tall target. */
@media (max-width: 640px) {
  .help-cta__btn { padding: 12px 26px; font-size: 14px; border-radius: 12px; }
}


/* ==========================================================================
   QUOTE MODAL — premium "Request a quote" popup (injected by quote-modal.js).
   Reuses the About video-modal open/close pattern (hidden + .is-open).
   ========================================================================== */
.quote-modal {
  position: fixed;
  inset: 0;
  z-index: var(--z-modal);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 14px;
  opacity: 0;
  transition: opacity var(--duration-slow) var(--ease-out);
}
.quote-modal[hidden] { display: none; }
.quote-modal.is-open { opacity: 1; }

.quote-modal__backdrop {
  position: absolute;
  inset: 0;
  background: rgba(6, 8, 12, 0.6);
  -webkit-backdrop-filter: blur(6px);
          backdrop-filter: blur(6px);
}
.quote-modal__dialog {
  position: relative;
  width: min(600px, 100%);
  max-height: calc(100vh - 28px);
  display: flex;
  flex-direction: column;
  background: #FFFFFF;
  border-radius: var(--radius-xl);
  box-shadow: 0 40px 100px -24px rgba(10, 16, 32, 0.45);
  overflow: hidden;
  opacity: 0;
  transform: scale(0.96);
  transition: transform var(--duration-slow) var(--ease-out),
              opacity var(--duration-slow) var(--ease-out);
}
.quote-modal.is-open .quote-modal__dialog { opacity: 1; transform: scale(1); }

.quote-modal__close {
  position: absolute;
  top: 16px;
  right: 16px;
  z-index: 3;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 38px;
  height: 38px;
  border-radius: 50%;
  color: var(--color-medium-gray);
  background: rgba(10, 10, 10, 0.04);
  transition: background 180ms ease, color 180ms ease;
}
.quote-modal__close:hover { background: rgba(10, 10, 10, 0.09); color: var(--color-black); }

.quote-modal__scroll {
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
  padding: clamp(24px, 3.4vw, 34px) clamp(24px, 4vw, 44px) clamp(20px, 3vw, 30px);
}
.quote-modal__intro { text-align: center; margin-bottom: 18px; }
.quote-modal__eyebrow {
  display: inline-block;
  font-size: var(--text-micro);
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
  color: var(--color-blue-gaab);
  margin-bottom: 7px;
}
.quote-modal__title {
  font-size: clamp(1.4rem, 2.4vw, 1.75rem);
  font-weight: 600;
  letter-spacing: -0.02em;
  line-height: 1.12;
  color: var(--color-black);
  margin: 0 0 6px;
}
.quote-modal__subtitle {
  font-size: 14px;
  color: var(--color-medium-gray);
  line-height: 1.45;
  max-width: 400px;
  margin: 0 auto;
}

/* ---- form ---- */
.quote-form { display: flex; flex-direction: column; gap: 9px; }
.quote-form__row { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; }
.quote-field { display: flex; flex-direction: column; gap: 5px; }
.quote-field label { font-size: 12.5px; font-weight: var(--weight-medium); color: var(--color-dark-gray); }
.quote-field label span { color: var(--color-blue-gaab); }
.quote-field input,
.quote-field textarea {
  width: 100%;
  padding: 9px 12px;
  border: 1px solid var(--color-border-light);
  border-radius: var(--radius-md);
  background: var(--color-off-white);
  font-size: 14.5px;
  color: var(--color-black);
  transition: border-color 180ms ease, box-shadow 180ms ease, background 180ms ease;
}
.quote-field input::placeholder,
.quote-field textarea::placeholder { color: #B0B0B0; }
.quote-field input:focus,
.quote-field textarea:focus {
  outline: none;
  border-color: var(--color-blue-gaab);
  background: #FFFFFF;
  box-shadow: 0 0 0 3px rgba(27, 58, 107, 0.10);
}
.quote-field textarea { resize: vertical; min-height: 62px; }
.quote-field input.is-invalid,
.quote-field textarea.is-invalid {
  border-color: #C0392B;
  box-shadow: 0 0 0 3px rgba(192, 57, 43, 0.08);
}

.quote-chips { display: flex; flex-wrap: wrap; gap: 6px; }
.quote-chip {
  min-height: 34px;
  padding: 6px 13px;
  border: 1px solid var(--color-border-light);
  border-radius: var(--radius-pill);
  background: #FFFFFF;
  font-size: 13.5px;
  color: var(--color-dark-gray);
  transition: background 160ms ease, color 160ms ease, border-color 160ms ease;
}
.quote-chip:hover { border-color: var(--color-blue-gaab-light); }
.quote-chip.is-active {
  background: var(--color-blue-gaab);
  color: #FFFFFF;
  border-color: var(--color-blue-gaab);
}

.quote-form__error { font-size: 13.5px; color: #C0392B; margin: -4px 0 0; }

.quote-submit {
  margin-top: 3px;
  padding: 12px 24px;
  border-radius: 12px;
  background: var(--color-blue-gaab);
  color: #FFFFFF;
  font-size: 15px;
  font-weight: var(--weight-medium);
  transition: background 200ms var(--ease-out), transform 200ms var(--ease-out);
}
.quote-submit:hover { background: var(--color-blue-gaab-dark); transform: translateY(-1px); }
.quote-submit:disabled { opacity: 0.7; cursor: default; transform: none; }

.quote-or {
  display: flex;
  align-items: center;
  margin: 11px 0 8px;
  color: var(--color-medium-gray);
  font-size: 13px;
}
.quote-or::before,
.quote-or::after { content: ''; flex: 1; height: 1px; background: var(--color-border-light); }
.quote-or span { padding: 0 14px; }

.quote-mail { text-align: center; font-size: 14px; color: var(--color-medium-gray); line-height: 1.6; }
.quote-mail a { color: var(--color-blue-gaab); font-weight: var(--weight-medium); }
.quote-mail a:hover { text-decoration: underline; }

.quote-success {
  padding: clamp(52px, 9vw, 88px) clamp(24px, 4vw, 48px);
  text-align: center;
  display: flex;
  flex-direction: column;
  align-items: center;
}
.quote-success[hidden] { display: none; }
.quote-modal__scroll[hidden] { display: none; }
.quote-success__icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 60px;
  height: 60px;
  border-radius: 50%;
  background: rgba(27, 58, 107, 0.08);
  color: var(--color-blue-gaab);
  margin-bottom: 20px;
}
.quote-success__title {
  font-size: clamp(1.4rem, 2.6vw, 1.9rem);
  font-weight: 600;
  letter-spacing: -0.02em;
  color: var(--color-black);
  margin: 0 0 10px;
}
.quote-success__text { font-size: 15px; color: var(--color-medium-gray); max-width: 360px; line-height: 1.55; }

/* ---- mobile: near-fullscreen, single column ---- */
/* Mobile — a floating card, NOT a takeover. This block used to force the dialog
   fullscreen (100% × 100%, no radius, zero padding on the overlay), so the quote
   form swallowed the whole phone and stopped reading as a modal at all. Now it
   matches the product popup's language — centred card, blurred backdrop visible
   all the way round — and sits slightly SMALLER than it (72vh vs the product
   modal's 78vh), per the brief. The inner scroll already exists on
   .quote-modal__scroll (flex: 1 + overflow-y: auto). */
/* Mobile — a floating card, NOT a takeover, and compact enough that the whole
   form (Submit included) fits on most phones without scrolling.

   Two earlier states this replaces: it was fullscreen (100% × 100%, no radius),
   and then capped at 72vh — which cut the form off with the Submit button below
   the fold. Now: 90vh so there is room, everything inside tightened, and the
   Submit pinned as a sticky footer so it is visible even when the content does
   need to scroll (small phones, keyboard open). */
@media (max-width: 560px) {
  .quote-modal { padding: 18px 16px; }
  .quote-modal__dialog {
    width: 100%;
    height: auto;
    max-height: 90vh;
    border-radius: var(--radius-xl);
  }
  .quote-modal__backdrop {
    background: rgba(6, 8, 12, 0.62);
    -webkit-backdrop-filter: blur(14px);
            backdrop-filter: blur(14px);
  }

  /* Padding-bottom moves onto the sticky footer so it can sit flush. */
  .quote-modal__scroll {
    padding: 20px 18px 0;
    overscroll-behavior: contain;   /* don't chain the scroll to the page behind */
    -webkit-overflow-scrolling: touch;
  }

  /* ---- Compact, not cramped ---- */
  .quote-modal__intro { margin-bottom: 12px; }
  .quote-modal__eyebrow { margin-bottom: 4px; }
  .quote-modal__title { font-size: 1.22rem; margin-bottom: 3px; }
  .quote-modal__subtitle { font-size: 12.5px; line-height: 1.35; }

  .quote-form { gap: 7px; }
  .quote-form__row { grid-template-columns: 1fr 1fr; gap: 8px; }  /* keep pairs side by side — halves the height */
  .quote-field { gap: 3px; }
  .quote-field label { font-size: 11.5px; }
  .quote-field input,
  .quote-field textarea { padding: 7px 10px; font-size: 14px; border-radius: 9px; }
  .quote-field textarea { min-height: 58px; }

  .quote-chips { gap: 5px; }
  .quote-chip { min-height: 28px; padding: 4px 10px; font-size: 12px; }

  /* ---- Sticky Submit ----
     Sticks to the bottom of the SCROLL container (its nearest scrolling
     ancestor), so it stays put while the fields scroll under it. The negative
     inline margin bleeds the white band out to the container's padding, or the
     fields would show through at the sides as they pass behind. */
  .quote-form__footer {
    position: sticky;
    bottom: 0;
    z-index: 2;
    margin: 4px -18px 0;
    padding: 10px 18px 14px;
    background: #FFFFFF;
    box-shadow: 0 -10px 18px -10px rgba(10, 16, 32, 0.14);
  }
  .quote-submit { margin-top: 0; width: 100%; padding: 11px 24px; }
}


/* ==========================================================================
   NARROW STILE EXIT DEVICE — pinned product section (narrow-stile.js).
   Vertical video on the left, text block on the right. White throughout;
   GAAB blue only on the eyebrow. Same typographic language as the anatomy
   overlays, ~15–20% larger.
   ========================================================================== */
.nse-section {
  position: relative;
  width: 100%;
  min-height: 100vh;
  background: var(--color-white);
  overflow: hidden;
}

/* Video — anchored to the RIGHT edge, vertically centred, enlarged so the
   product reads well and the final detail frame touches the viewport edge.
   narrow-stile.js owns only its opacity (fade-in); centring stays in CSS. */
.nse-media {
  position: absolute;
  top: 50%;
  right: 0;
  transform: translateY(-50%);
  display: flex;
  align-items: center;
  justify-content: flex-end;
  z-index: 2;
  will-change: opacity;
}
.nse-video {
  height: min(97vh, 980px);   /* enlarged — reads bigger on screen */
  width: auto;
  max-width: 64vw;
  object-fit: contain;
  display: block;
  /* Rule A — the exit-device bar runs nearly edge-to-edge, so an edge-feather
     mask would wash out its ends (esp. the right). multiply instead: the near-
     white video field blends into the white page (box gone) while the product
     only ever darkens → the whole bar stays crisp, tip to tip.
     El filter empuja el fondo beige claro del video a blanco puro (brightness
     lleva los highlights a 255; contrast separa la barra plateada del fondo). */
  mix-blend-mode: multiply;
  filter: brightness(1.08) contrast(1.08);
}

/* Text — LEFT, vertically centred. narrow-stile.js owns the yPercent centring +
   animated y drift + opacity (same treatment as the anatomy overlays). */
.nse-text {
  position: absolute;
  top: 50%;
  left: clamp(28px, 8vw, 120px);
  max-width: min(440px, 40vw);
  z-index: 5;
  will-change: transform, opacity;
}
.nse-title {
  font-family: var(--font-sans);
  font-weight: var(--weight-medium);
  font-size: clamp(1.75rem, 2.6vw, 2.2rem);
  line-height: 1.1;
  letter-spacing: -0.015em;
  color: var(--color-black);
  margin: 0 0 18px;
}
.nse-copy {
  font-family: var(--font-sans);
  font-weight: var(--weight-regular);
  font-size: clamp(1.08rem, 1.35vw, 1.24rem);
  line-height: 1.5;
  color: var(--color-text-secondary);
  margin: 0;
}

/* Tablet / mobile — KEEPS the pinned layout (it used to collapse to static flow
   with a looping video). Same recipe as the Door Closer: media in the upper
   half, caption centred in the lower half so it rises from below the product.
   narrow-stile.js owns the opacity + y drift, so the entrance matches desktop. */
@media (max-width: 1024px) {
  /* Flush RIGHT, matching desktop's anchoring. Centring it left a white gutter
     down the right-hand side at the end of the scrub, which read as the product
     being cut off. */
  .nse-media {
    left: auto;
    right: 0;
    transform: none;
    /* Nudged down from 4vh: it left an 81px hole between the product and the
       caption. 8vh keeps ~46px of clearance above .nse-text (which centres at
       74%), so it closes the gap without ever crowding the copy. Size unchanged. */
    top: 8vh;
    bottom: auto;
    justify-content: flex-end;
  }
  .nse-video { height: 54vh; width: auto; max-width: 92vw; }
  .nse-text {
    left: 50%;
    top: 74%;
    width: min(84vw, 400px);
    max-width: none;
    margin-left: calc(min(84vw, 400px) / -2);
    text-align: center;
  }
  .nse-title { font-size: clamp(1.5rem, 5.4vw, 2rem); margin-bottom: 14px; }
  .nse-copy { font-size: 0.88rem; line-height: 1.5; }
}


/* ==========================================================================
   G2000 CYLINDRICAL LEVERSET — pinned product section (leverset.js). Mirror
   of the narrow-stile section, ALTERNATED: video on the LEFT, text block on
   the RIGHT. White throughout; GAAB blue only as an accent. Same typographic
   language and sizing as the narrow-stile overlay — reuses its scale.
   ========================================================================== */
.lvs-section {
  position: relative;
  width: 100%;
  min-height: 100vh;
  background: var(--color-white);
  overflow: hidden;
}

/* Video — anchored to the LEFT edge, vertically centred, enlarged so the
   product reads well. leverset.js owns only its opacity (fade-in); centring
   stays in CSS. */
.lvs-media {
  position: absolute;
  top: 50%;
  left: 0;
  transform: translateY(-50%);
  display: flex;
  align-items: center;
  justify-content: flex-start;
  z-index: 2;
  will-change: opacity;
}
/* Canvas image-sequence (square). leverset.js draws a cover-fit frame per scroll
   and owns only the opacity (fade-in); size/centring stay here. */
.lvs-video {
  height: min(78vh, 680px);   /* smaller — it was reading too large */
  width: min(78vh, 680px);    /* square — the frames are 1:1 */
  max-width: 46vw;
  aspect-ratio: 1 / 1;
  display: block;
  /* Rule A — feather the frame's rectangle into the white page so no box shows. */
  -webkit-mask-image: radial-gradient(ellipse closest-side at center, #000 60%, transparent 100%);
          mask-image: radial-gradient(ellipse closest-side at center, #000 60%, transparent 100%);
}

/* Text — RIGHT, block vertically centred in CSS. leverset.js animates each
   CHILD (title, item 1, item 2) separately: they rise in staggered and stay
   visible while the product is on screen (rule B), fading out only at the end. */
.lvs-text {
  position: absolute;
  top: 50%;
  right: clamp(28px, 8vw, 120px);
  transform: translateY(calc(-50% - 34px));   /* parked a little above centre */
  max-width: min(460px, 42vw);
  z-index: 5;
}
.lvs-title {
  font-family: var(--font-sans);
  font-weight: var(--weight-medium);
  font-size: clamp(1.75rem, 2.6vw, 2.2rem);   /* matches .nse-title exactly */
  line-height: 1.15;
  letter-spacing: -0.02em;         /* tighter, cleaner headline */
  color: var(--color-black);
  margin: 0 0 34px;
  will-change: transform, opacity;
}
.lvs-item {
  font-family: var(--font-sans);
  font-weight: var(--weight-regular);
  font-size: clamp(1.08rem, 1.35vw, 1.24rem); /* matches .nse-copy exactly */
  line-height: 1.7;                          /* more air between lines */
  letter-spacing: 0.005em;
  color: var(--color-text-secondary);
  margin: 0;
  will-change: transform, opacity;
}
.lvs-item--2 { margin-top: 40px; }   /* more breathing room between the two items */

/* Tablet / mobile — KEEPS the pinned layout, mirroring the Narrow Stile exactly
   so products 2 and 3 are a matched pair. The canvas was capped at 340px here
   and looked tiny next to the other two; it now gets the same 46vh/78vw frame
   as the Exit Device. leverset.js owns the per-item rise, so the staggered
   entrance is the desktop one. */
@media (max-width: 1024px) {
  .lvs-media {
    left: 50%;
    right: auto;
    transform: translateX(-50%);
    top: 12vh;              /* nudged down — size is approved, position was high */
    bottom: auto;
    justify-content: center;
  }
  .lvs-video { height: 46vh; width: 86vw; max-width: none; }
  .lvs-text {
    left: 50%;
    right: auto;
    top: 74%;
    transform: translateY(-50%);
    width: min(84vw, 400px);
    max-width: none;
    margin-left: calc(min(84vw, 400px) / -2);
    text-align: center;
  }
  .lvs-title { font-size: clamp(1.5rem, 5.4vw, 2rem); margin-bottom: 14px; }
  .lvs-item { font-size: 0.88rem; line-height: 1.5; }
  .lvs-item--2 { margin-top: 16px; }
}


/* ==========================================================================
   HEADLINE FONT — titles use --font-display (Archivo). Everything else (body,
   navbar, buttons, eyebrows, captions, specs) stays on Inter (--font-sans).
   Placed last so it overrides each title's font-family above WITHOUT touching
   its size / weight / line-height. To revert: set --font-display back to
   var(--font-sans) in variables.css.
   ========================================================================== */
.hero-title,
.products-header__title,
.closer-title,
.desc h4,
.product-card__title,
.help-cta__title,
.quote-modal__title,
.quote-success__title,
.nse-title,
.lvs-title {
  font-family: var(--font-display);
  /* Global headline tracking — tightened for a cleaner, more premium set. */
  letter-spacing: -0.035em;
}
