/* ============================================================
   FUSION INFINITY — design system
   Dark, cinematic, premium, industrial-tech.
   Plain CSS. Built to drop into WordPress later.
============================================================ */

:root {
  /* Color */
  --bg-0: #0A0A0F;        /* near-black base */
  --bg-1: #0A1F3D;        /* deep blue */
  --steel: #11151F;       /* surface / cards */
  --steel-2: #141B29;     /* raised surface */
  --line: rgba(154, 174, 196, 0.14);
  --line-strong: rgba(154, 174, 196, 0.26);

  --accent: #4EA8FF;      /* used sparingly */
  --accent-deep: #1d6fd6;
  --accent-glow: rgba(78, 168, 255, 0.55);

  --text: #F5F7FA;        /* headings */
  --muted: #9AAEC4;       /* body */
  --muted-dim: #6b7d93;

  /* Type */
  --font-head: 'Poppins', system-ui, sans-serif;
  --font-body: 'Inter', system-ui, sans-serif;

  /* Rhythm */
  --maxw: 1200px;
  --gutter: clamp(1.25rem, 5vw, 4rem);
  --section-y: clamp(6rem, 14vh, 11rem);
  --radius: 18px;

  --ease: cubic-bezier(0.22, 1, 0.36, 1);
}

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

html { -webkit-text-size-adjust: 100%; }

body {
  font-family: var(--font-body);
  color: var(--text);
  background: var(--bg-0);
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
  /* Cinematic base: near-black settling into deep blue */
  background:
    radial-gradient(120% 80% at 50% -10%, rgba(10, 31, 61, 0.85) 0%, transparent 60%),
    linear-gradient(180deg, var(--bg-0) 0%, #080a13 40%, var(--bg-0) 100%);
  background-attachment: fixed;
}

img { display: block; max-width: 100%; }
a { color: inherit; text-decoration: none; }
::selection { background: var(--accent); color: #05080f; }

/* ============================================================
   AMBIENT BACKGROUND
   Drifting mesh gradient (CSS blobs) + canvas particles (JS).
   Deliberately faint — it must never compete with content.
============================================================ */
.bg-fx {
  position: fixed;
  inset: 0;
  z-index: -1;            /* above body's base gradient, below all content */
  overflow: hidden;
  pointer-events: none;
}
.bg-fx__mesh {
  position: absolute;
  inset: -25%;
  filter: blur(90px);
  opacity: 0.7;
}
.bg-fx__blob {
  position: absolute;
  display: block;
  border-radius: 50%;
  will-change: transform;
}
/* Deep-blue masses + one faint accent wash; all very soft */
.bg-fx__blob--a {
  width: 55vw; height: 55vw; left: -8vw; top: -12vh;
  background: radial-gradient(circle, rgba(10, 31, 61, 0.9), transparent 70%);
  animation: bg-drift-a 46s ease-in-out infinite;
}
.bg-fx__blob--b {
  width: 50vw; height: 50vw; right: -10vw; bottom: -10vh;
  background: radial-gradient(circle, rgba(16, 44, 84, 0.75), transparent 70%);
  animation: bg-drift-b 58s ease-in-out infinite;
}
.bg-fx__blob--c {
  width: 38vw; height: 38vw; left: 34vw; top: 28vh;
  background: radial-gradient(circle, rgba(78, 168, 255, 0.10), transparent 70%);
  animation: bg-drift-c 72s ease-in-out infinite;
}
@keyframes bg-drift-a {
  0%, 100% { transform: translate(0, 0) scale(1); }
  50%      { transform: translate(7vw, 6vh) scale(1.12); }
}
@keyframes bg-drift-b {
  0%, 100% { transform: translate(0, 0) scale(1); }
  50%      { transform: translate(-6vw, -5vh) scale(1.1); }
}
@keyframes bg-drift-c {
  0%, 100% { transform: translate(0, 0) scale(1); }
  50%      { transform: translate(-5vw, 7vh) scale(1.18); }
}
.bg-fx__canvas {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
}

:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 3px;
  border-radius: 4px;
}

/* ---- Shared type / structural devices ---- */
.eyebrow {
  font-size: 0.72rem;
  font-weight: 600;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--muted);
  display: inline-flex;
  align-items: center;
  gap: 0.7em;
}
.eyebrow--center { justify-content: center; }
.eyebrow__mark {
  color: var(--accent);
  font-size: 1.1em;
  text-shadow: 0 0 12px var(--accent-glow);
}

.section__title {
  font-family: var(--font-head);
  font-weight: 600;
  line-height: 1.08;
  letter-spacing: -0.02em;
  font-size: clamp(2rem, 5vw, 3.4rem);
  color: var(--text);
  margin-top: 1.1rem;
}

.section__lead {
  color: var(--muted);
  max-width: 46ch;
  margin-top: 1.4rem;
  font-size: 1.05rem;
}

/* ---- Buttons ---- */
.btn {
  --pad-y: 0.85rem;
  display: inline-flex;
  align-items: center;
  gap: 0.6em;
  font-family: var(--font-body);
  font-weight: 600;
  font-size: 0.95rem;
  padding: var(--pad-y) 1.5rem;
  border-radius: 999px;
  border: 1px solid transparent;
  cursor: pointer;
  transition: transform 0.4s var(--ease), background 0.3s var(--ease),
              border-color 0.3s var(--ease), box-shadow 0.3s var(--ease);
  will-change: transform;
}
.btn__arrow { transition: transform 0.4s var(--ease); }
.btn:hover .btn__arrow { transform: translateX(4px); }

.btn--primary {
  background: linear-gradient(180deg, var(--accent) 0%, var(--accent-deep) 100%);
  color: #05101f;
  box-shadow: 0 8px 30px -8px var(--accent-glow), inset 0 1px 0 rgba(255,255,255,0.4);
}
.btn--primary:hover {
  transform: translateY(-2px);
  box-shadow: 0 14px 44px -10px var(--accent-glow), inset 0 1px 0 rgba(255,255,255,0.5);
}

.btn--ghost {
  background: rgba(255, 255, 255, 0.03);
  border-color: var(--line-strong);
  color: var(--text);
  backdrop-filter: blur(6px);
}
.btn--ghost:hover {
  border-color: var(--accent);
  color: var(--accent);
  transform: translateY(-2px);
}

/* ---- Circle nav buttons (brands + categories) ---- */
.circle-btn {
  width: 52px;
  height: 52px;
  flex: 0 0 auto;
  border-radius: 50%;
  background: var(--steel-2);
  border: 1px solid var(--line-strong);
  color: var(--text);
  display: grid;
  place-items: center;
  cursor: pointer;
  transition: border-color 0.3s var(--ease), background 0.3s var(--ease),
              transform 0.3s var(--ease), box-shadow 0.3s var(--ease);
}
.circle-btn svg {
  width: 22px; height: 22px;
  fill: none; stroke: currentColor; stroke-width: 2;
  stroke-linecap: round; stroke-linejoin: round;
}
.circle-btn:hover {
  border-color: var(--accent);
  color: var(--accent);
  box-shadow: 0 0 0 1px var(--accent-glow), 0 0 24px -6px var(--accent-glow);
}
.circle-btn:active { transform: scale(0.94); }
.circle-btn:disabled { opacity: 0.35; cursor: not-allowed; box-shadow: none; border-color: var(--line); color: var(--muted-dim); }

/* ============================================================
   HEADER
============================================================ */
.site-header {
  position: fixed;
  top: 0; left: 0; right: 0;
  z-index: 50;
  display: flex;
  align-items: center;
  justify-content: space-between;
  /* 1.2rem, not 0.5rem: the logo file used to supply the header's breathing
     room as transparent padding baked into the image. That padding is now
     cancelled (see .brand__logo) so the space has to come from the header
     itself. Net header height is unchanged - the room simply moved from
     inside the PNG to real, symmetric padding. */
  padding: 1.2rem var(--gutter);
  transition: background 0.4s var(--ease), border-color 0.4s var(--ease), backdrop-filter 0.4s var(--ease);
  border-bottom: 1px solid transparent;
}
.site-header.is-scrolled {
  background: rgba(8, 10, 19, 0.72);
  backdrop-filter: blur(14px);
  border-bottom-color: var(--line);
}

.brand { display: inline-flex; align-items: center; gap: 0.6rem; font-family: var(--font-head); }
.brand__mark {
  font-size: 1.5rem;
  color: var(--accent);
  text-shadow: 0 0 16px var(--accent-glow);
  line-height: 1;
}
.brand__name { font-weight: 600; font-size: 1.15rem; letter-spacing: 0.01em; }
.brand__name-thin { font-weight: 500; color: var(--muted); }

.site-nav { display: flex; align-items: center; gap: 2rem; }
.site-nav a {
  font-size: 1rem;
  font-weight: 500;
  color: var(--muted);
  transition: color 0.3s var(--ease);
}
.site-nav a:hover { color: var(--text); }
.site-nav__cta {
  color: var(--text) !important;
  border: 1px solid var(--line-strong);
  font-size: 1rem;
  padding: 0.55rem 1.25rem;
  border-radius: 999px;
  transition: border-color 0.3s var(--ease), color 0.3s var(--ease);
}
.site-nav__cta:hover { border-color: var(--accent); color: var(--accent) !important; }

/* Hamburger toggle — desktop/tablet hidden; shown only on mobile (≤760px) */
.nav-toggle {
  display: none;
  width: 44px; height: 44px;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 5px;
  padding: 0;
  border: 1px solid var(--line-strong);
  border-radius: 10px;
  background: rgba(255, 255, 255, 0.03);
  cursor: pointer;
  z-index: 70;                 /* stays above the open overlay so it can close it */
  transition: border-color 0.3s var(--ease);
}
.nav-toggle:hover { border-color: var(--accent); }
.nav-toggle__bar {
  width: 20px; height: 2px;
  border-radius: 2px;
  background: var(--text);
  transition: transform 0.3s var(--ease), opacity 0.3s var(--ease);
}
/* Screen-reader-only text. Used for the brand name behind the categories
   logo, so replacing the heading with an image costs no accessibility or SEO. */
.u-visually-hidden {
  position: absolute;
  width: 1px; height: 1px;
  margin: -1px; padding: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

/* Categories heading in logo mode: the <h2> holds an <img> instead of text,
   so it must not keep the text line-height/margins that would leave a gap. */
.section__title--logo {
  display: flex;
  align-items: center;
  line-height: 1;
}

/* EQUAL HEIGHTS across brands, widths free.
   --logo-h is the shared target height for every mark, set to the height
   Tefal renders at. fitLogo() in main.js scales each logo's actual ink - not
   its file, which may carry 40%+ transparent margin - to this height, so a
   wordmark and a monogram read as the same size no matter how differently
   they were exported.
   --logo-scale is a per-brand optical nudge. An upright monogram looks
   smaller than a wide wordmark at identical height, so WMF gets 1.3.
   The box is full width and reserves the tallest case, so switching brands
   never shifts the layout while the next logo decodes. */
.cat__logo-box {
  --logo-h: 52px;
  --logo-scale: 1;
  display: block;
  /* Wide enough for the widest mark at the shared height: Rowenta's wordmark
     is 10.7:1, so 52px tall needs ~556px. Inheriting the heading's own width
     is not enough - that column is only ~286px - which would clamp Rowenta to
     half height and break the equal-height rule. Capped at 92vw so narrow
     screens still fall back to the width guard in fitLogo() instead of
     scrolling sideways. */
  width: min(580px, 92vw);
  margin-inline: auto;
  height: calc(var(--logo-h) * 1.3);
  position: relative;      /* positioning context for the absolutely placed logo */
}
/* Per-brand optical nudges. Equal height works for marks of roughly similar
   proportion, but breaks at the extremes, so these two are corrected by eye
   against Tefal (52px tall, 219px wide, the reference):
     WMF     - upright monogram, 0.8:1. At an equal height it reads smaller
               than a wordmark because it occupies far less area, so it goes up.
     ROWENTA - 10.7:1, the opposite problem. At the shared 52px it stretched to
               539px, ~2.5x Tefal's width and visually dominant; clamped to the
               heading column it collapsed to 28px and vanished. 0.75 lands
               between the two at ~39px tall / ~404px wide, which carries about
               the same optical weight as the reference without dominating. */
.cat__logo-box[data-brand="WMF" i]     { --logo-scale: 1.3; }
.cat__logo-box[data-brand="ROWENTA" i] { --logo-scale: 0.75; }
.cat__logo {
  /* Absolutely placed and explicitly sized by fitLogo(), which rasterises the
     artwork at its final size rather than scaling a smaller bitmap up.
     max-width:none overrides the global `img { max-width: 100% }`, which would
     otherwise clamp a wide wordmark back to the box. The contain fit below is
     only the pre-JS fallback. */
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  max-width: none;
  object-fit: contain;
  pointer-events: none;
}

/* Page behind the open menu must not scroll. initNav() adds this to <body>
   and also stops Lenis, which does not respect overflow:hidden on its own. */
body.nav-locked {
  overflow: hidden;
  /* iOS Safari leaks touch scrolling through overflow:hidden; these stop the
     gesture reaching the page behind the overlay. Taps are unaffected. */
  touch-action: none;
  overscroll-behavior: none;
}

/* Bars morph into an X when the menu is open */
.site-header.nav-open .nav-toggle__bar:nth-child(1) { transform: translateY(7px) rotate(45deg); }
.site-header.nav-open .nav-toggle__bar:nth-child(2) { opacity: 0; }
.site-header.nav-open .nav-toggle__bar:nth-child(3) { transform: translateY(-7px) rotate(-45deg); }

/* ============================================================
   1 · HERO — zoom parallax
============================================================ */
.hero {
  position: relative;
  height: 320vh;            /* scroll distance for the zoom */
}
.hero__sticky {
  position: sticky;
  top: 0;
  height: 100vh;
  overflow: hidden;
  display: flex;
  align-items: center;
  justify-content: center;
}

.hero__grid { position: absolute; inset: 0; }

/* Full-screen centering wrapper — GSAP scales THIS around screen centre,
   so its tile grows in place (centre) or rushes outward (offset tiles).
   pointer-events: none because this wrapper's box covers the ENTIRE hero
   for all 7 tiles (only its child .zoom-img__tile is visually the small
   framed image) — without this, whichever wrapper is last in DOM order
   would swallow every click across the whole hero, no matter which tile
   is actually visible under the pointer. The real hit target is re-enabled
   below on .zoom-img__tile, which is correctly sized/positioned per tile. */
/* SHARPNESS + MEMORY: how the hero zoom is built.

   GSAP animates .zoom-img's `transform: scale()`. A transform composites by
   STRETCHING an already-rasterized GPU layer - it does not repaint at the
   larger size, and `will-change: transform` locks the raster scale. So the
   pixel size the layer is painted at IS the real resolution of the image for
   the whole animation, however high-res the source photo is.

   An early attempt pre-sized the tile box to its max-zoom footprint and
   counter-scaled it with `transform: scale(1/f)` on .zoom-img__tile. That
   does NOT work: the counter-scale lives INSIDE the composited layer, so it
   is baked into the raster - the image is still rasterized small, then
   stretched.

   Fix part 1 (sharpness): the counter-scale lives on the LAYER ITSELF
   (.zoom-img) and GSAP animates that layer UP to its final scale, so the
   tile box is laid out at real pixel size and the raster is taken from it.

   Fix part 2 (memory): painting every tile at its FULL max-zoom footprint
   costs ~30 megapixels of GPU texture (~122 MB at DPR 1, ~200 MB on a DPR-3
   phone) and crashes mobile Safari. But no tile needs more pixels than the
   screen can show - at max zoom the outer tiles have already rushed past the
   viewport, so that resolution is painted off-screen and wasted. So the
   PAINT factor --pf is decoupled from the ZOOM factor --f:
     . the tile box is laid out at `rest x --pf`, capped near one viewport;
     . the layer animates scale from 1/--pf up to --f / --pf.
   Residual stretch at max zoom is --f / --pf. For the centre tile (0) --pf
   equals --f, so it lands on exactly 1.0 - pixel perfect, which is the tile
   that matters because it ends up filling the screen. Outer tiles accept
   1.25x-2.7x, invisible at the speed they cross the viewport.

   Every per-tile length that must look unchanged on screen (box size,
   top/left offset, radius, shadow) is therefore multiplied by --pf below.
   --f must match `scales` in main.js; --pf must match `paint`. */
.zoom-img {
  --f: 4;                     /* zoom factor  - MUST match scales[] in main.js */
  --pf: 4;                    /* paint factor - MUST match paint[]  in main.js */
  position: absolute;
  top: 0; left: 0;
  width: 100%; height: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
  transform: scale(calc(1 / var(--pf)));
  will-change: transform;
  pointer-events: none;       /* see note below: this wrapper covers the whole hero */
}
/* The framed tile - each has its own rest size + position, written as
   `rest value x var(--pf)` so the intended on-screen geometry stays readable.
   pointer-events is re-enabled here because .zoom-img's box spans the entire
   hero for all 7 tiles; without that, the last wrapper in DOM order would
   swallow every click across the hero regardless of which tile is visible. */
.zoom-img__tile {
  position: relative;
  width:  calc(25vw * var(--pf));
  height: calc(25vh * var(--pf));
  overflow: hidden;
  border-radius: calc(8px * var(--pf));
  box-shadow: 0 calc(30px * var(--pf)) calc(80px * var(--pf)) calc(-30px * var(--pf)) rgba(0,0,0,0.8);
  cursor: pointer;            /* clicking scrolls to this tile's brand (see main.js initHeroImageScroll) */
  pointer-events: auto;
  flex-shrink: 0;             /* the box is larger than the hero; without this,
                                 flexbox shrink-to-fit would squash the width down */
}
.zoom-img__tile picture { display: block; width: 100%; height: 100%; }
.zoom-img__tile img {
  width: 100%; height: 100%;
  object-fit: cover;
  display: block;
}

/* Scattered grid placement - mirrors the reference layout.
   --f  = this tile's entry in `scales` in main.js (indexed by data-zoom, 0-6)
   --pf = its entry in `paint`; box/offsets below are `rest value x var(--pf)`,
          keeping the rest layout identical to the original design. */
.zoom-img[data-zoom="1"] { --f: 5; --pf: 3; }
.zoom-img[data-zoom="2"] { --f: 6; --pf: 3; }
.zoom-img[data-zoom="3"] { --f: 5; --pf: 4; }
.zoom-img[data-zoom="4"] { --f: 6; --pf: 4; }
.zoom-img[data-zoom="5"] { --f: 8; --pf: 3; }
.zoom-img[data-zoom="6"] { --f: 9; --pf: 6; }

.zoom-img[data-zoom="1"] .zoom-img__tile { top: calc(-30vh * var(--pf));  left: calc(5vw * var(--pf));     width: calc(35vw * var(--pf)); height: calc(30vh * var(--pf)); }
.zoom-img[data-zoom="2"] .zoom-img__tile { top: calc(-10vh * var(--pf));  left: calc(-25vw * var(--pf));   width: calc(20vw * var(--pf)); height: calc(45vh * var(--pf)); }
.zoom-img[data-zoom="3"] .zoom-img__tile {                                left: calc(27.5vw * var(--pf));  width: calc(25vw * var(--pf)); height: calc(25vh * var(--pf)); }
.zoom-img[data-zoom="4"] .zoom-img__tile { top: calc(27.5vh * var(--pf)); left: calc(5vw * var(--pf));     width: calc(20vw * var(--pf)); height: calc(25vh * var(--pf)); }
.zoom-img[data-zoom="5"] .zoom-img__tile { top: calc(27.5vh * var(--pf)); left: calc(-22.5vw * var(--pf)); width: calc(30vw * var(--pf)); height: calc(25vh * var(--pf)); }
.zoom-img[data-zoom="6"] .zoom-img__tile { top: calc(22.5vh * var(--pf)); left: calc(25vw * var(--pf));    width: calc(15vw * var(--pf)); height: calc(15vh * var(--pf)); }

.hero__overlay {
  position: relative;
  z-index: 4;
  text-align: center;
  max-width: 720px;
  padding: 0 var(--gutter);
  pointer-events: none; /* purely decorative text — let clicks pass through to hero tiles behind it */
}
/* Soft scrim so the headline reads over the imagery; fades with overlay */
.hero__overlay::before {
  content: '';
  position: absolute;
  left: 50%; top: 50%;
  width: 150%; height: 150%;
  transform: translate(-50%, -50%);
  background: radial-gradient(ellipse at center, rgba(5,8,16,0.78) 0%, rgba(5,8,16,0.45) 42%, transparent 70%);
  z-index: -1;
  pointer-events: none;
}
.hero__title {
  font-family: var(--font-head);
  font-weight: 700;
  font-size: clamp(3rem, 11vw, 8rem);
  line-height: 0.95;
  letter-spacing: -0.03em;
  margin: 1rem 0 1.4rem;
  text-shadow: 0 4px 40px rgba(0,0,0,0.6);
}
.hero__title-thin { font-weight: 500; color: var(--accent); }

.hero__tagline {
  color: var(--muted);
  font-size: clamp(1rem, 2vw, 1.25rem);
  max-width: 46ch;
  margin: 0 auto 2rem;
}

.hero__scroll-hint {
  position: absolute;
  bottom: 2rem; left: 50%;
  transform: translateX(-50%);
  z-index: 4;
  font-size: 0.7rem;
  letter-spacing: 0.3em;
  text-transform: uppercase;
  color: var(--muted);
  animation: float-hint 2.4s var(--ease) infinite;
}
@keyframes float-hint {
  0%, 100% { transform: translate(-50%, 0); opacity: 0.6; }
  50%      { transform: translate(-50%, 6px); opacity: 1; }
}
/* While the hero zoom is scrolled, main.js adds .is-fading and drives opacity
   itself. The keyframe must be off then: a running CSS animation overrides
   inline styles, so with it on, GSAP's fade never showed and the hint kept
   pulsing over the whole zoom. */
.hero__scroll-hint.is-fading { animation: none; }

/* ============================================================
   SECTION SCAFFOLD
============================================================ */
.section {
  position: relative;
  max-width: var(--maxw);
  margin: 0 auto;
  padding: var(--section-y) var(--gutter);
}
.section__head { max-width: 640px; margin-bottom: clamp(2.5rem, 6vw, 4rem); }
.section__head--row {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: 2rem;
  max-width: 100%;
}

/* ============================================================
   2 · BRANDS — coverflow
============================================================ */
.section--brands { text-align: left; padding-bottom: clamp(2rem, 5vw, 3.5rem); }
.section--brands .section__head { margin-inline: auto; text-align: center; max-width: 720px; }
.section--brands .eyebrow { justify-content: center; }
.section--brands .section__lead { margin-inline: auto; }

.brands { position: relative; }
.brands .swiper { padding: 2rem 0 1rem; overflow: visible; }
/* Coverflow gives side slides a negative z-index, which drops them behind
   the wrapper for hit-testing and swallows their clicks. Let pointer events
   pass through the wrapper to the slides (drag is disabled, so the wrapper
   doesn't need to be a hit target). */
.brands .swiper-wrapper { pointer-events: none; }
.brands .swiper-slide { pointer-events: auto; }
.brands .swiper-slide {
  width: 300px;
  height: 380px;
}

.brand-card {
  width: 100%; height: 100%;
  cursor: pointer;
  border-radius: var(--radius);
  overflow: hidden;                 /* clip the image to the rounded corners */
  background: var(--steel);         /* fallback while the image loads */
  border: 1px solid var(--line);
  transition: border-color 0.5s var(--ease), box-shadow 0.5s var(--ease);
}
/* Full-bleed image — swap the src per brand later */
.brand-card__img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

/* Focused (center) slide */
.swiper-slide-active .brand-card {
  border-color: var(--accent);
  box-shadow: 0 0 0 1px var(--accent-glow), 0 30px 70px -30px var(--accent-glow);
}

.brands__controls {
  display: flex;
  justify-content: center;
  gap: 1rem;
  margin-top: 2.5rem;
}

/* ============================================================
   3 · CATEGORIES — scroll-snap rail
============================================================ */
.section--categories { max-width: 100%; padding-inline: 0; padding-top: clamp(2rem, 5vw, 3.5rem); }
.section--categories .section__head--row {
  max-width: var(--maxw);
  margin: 0 auto clamp(2.5rem, 6vw, 4rem);
  padding-inline: var(--gutter);
  flex-direction: column;
  align-items: center;
  justify-content: center;
  text-align: center;
  gap: 1.4rem;
}
/* Centered heading block (eyebrow, brand name, tagline) */
.cat__intro {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
}
.cat__controls { display: flex; gap: 0.8rem; flex: 0 0 auto; }

.cat__track {
  display: flex;
  gap: 1.5rem;
  overflow-x: auto;
  scroll-behavior: smooth;          /* no snap so the centred rest holds exactly */
  padding: 0.5rem var(--gutter) 2rem;
  scrollbar-width: none;
}
.cat__track::-webkit-scrollbar { display: none; }
/* JS sets justify-content: 'center' when the row fits (centres the group,
   no scrolling) or 'flex-start' when it overflows (fully scrollable; JS also
   starts it scrolled to the middle so many cards still read as centred). */

.cat-card {
  flex: 0 0 auto;
  width: clamp(260px, 78vw, 340px);
  border-radius: var(--radius);
  overflow: hidden;
  background: linear-gradient(180deg, var(--steel-2), var(--steel));
  border: 1px solid var(--line);
  transition: border-color 0.4s var(--ease), transform 0.4s var(--ease), box-shadow 0.4s var(--ease);
}
.cat-card:hover {
  transform: translateY(-6px);
  border-color: var(--line-strong);
  box-shadow: 0 30px 60px -30px rgba(0,0,0,0.8);
}
.cat-card__media { aspect-ratio: 4 / 3; overflow: hidden; }
.cat-card__media img {
  width: 100%; height: 100%; object-fit: cover;
  transition: transform 0.6s var(--ease);
}
.cat-card:hover .cat-card__media img { transform: scale(1.06); }
.cat-card__body { padding: 1.4rem 1.5rem 1.7rem; }
.cat-card__title {
  font-family: var(--font-head);
  font-weight: 600;
  font-size: 1.25rem;
  letter-spacing: -0.01em;
}
.cat-card__text { color: var(--muted); font-size: 0.95rem; margin-top: 0.5rem; }

/* ============================================================
   4 · CTA
============================================================ */
.section--cta { text-align: center; }
.cta {
  position: relative;
  border: 1px solid var(--line);
  border-radius: clamp(20px, 4vw, 32px);
  padding: clamp(3rem, 9vw, 6rem) var(--gutter);
  overflow: hidden;
  background:
    radial-gradient(120% 140% at 50% -20%, rgba(10,31,61,0.9), transparent 55%),
    linear-gradient(180deg, var(--steel-2), var(--steel));
}
.cta__title {
  position: relative;
  font-family: var(--font-head);
  font-weight: 600;
  font-size: clamp(2.2rem, 6vw, 4rem);
  line-height: 1.05;
  letter-spacing: -0.02em;
  margin: 1.2rem 0 1.4rem;
}
.cta__lead {
  position: relative;
  color: var(--muted);
  max-width: 48ch;
  margin: 0 auto 2.4rem;
  font-size: 1.05rem;
}
.cta__actions {
  position: relative;
  display: flex;
  gap: 1rem;
  justify-content: center;
  flex-wrap: wrap;
}

/* ============================================================
   FOOTER
============================================================ */
.site-footer {
  max-width: var(--maxw);
  margin: 0 auto;
  padding: 3rem var(--gutter) 4rem;
  border-top: 1px solid var(--line);
  display: flex;
  flex-direction: column;
  gap: 0.7rem;
  align-items: center;
  text-align: center;
}
.site-footer__brand { display: inline-flex; align-items: center; gap: 0.6rem; font-family: var(--font-head); }
.site-footer__note { color: var(--muted); font-size: 0.9rem; }
.site-footer__copy { color: var(--muted-dim); font-size: 0.8rem; }

/* ============================================================
   SCROLL-REVEAL (set by JS)
============================================================ */
.reveal { opacity: 0; transform: translateY(28px); }
.reveal.is-in { opacity: 1; transform: none; transition: opacity 0.8s var(--ease), transform 0.8s var(--ease); }

/* ============================================================
   RESPONSIVE
============================================================ */
@media (max-width: 760px) {
  /* Mobile nav: hamburger + full-screen overlay menu (all four items) */
  .nav-toggle { display: flex; }
  .site-nav {
    position: fixed;
    inset: 0;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 2.25rem;
    background: rgba(8, 10, 19, 0.96);
    backdrop-filter: blur(16px);
    z-index: 60;                 /* above page content, below .nav-toggle (70) */
    opacity: 0;
    visibility: hidden;
    transform: translateY(-10px);
    transition: opacity 0.4s var(--ease), transform 0.4s var(--ease), visibility 0.4s;
  }
  .site-header.nav-open .site-nav { opacity: 1; visibility: visible; transform: none; }
  .site-nav a { font-size: 1.5rem; color: var(--text); }
  .site-nav a:hover { color: var(--accent); }
  .site-nav__cta {
    margin-top: 0.5rem;
    padding: 0.85rem 2rem;
    font-size: 1.05rem;
  }

  /* Compact header on phones - same cancellation, smaller target mark. */
  .site-header { padding: 0.75rem var(--gutter); }
  .brand__logo {
    height: 88px;
    margin-top: calc(88px * -0.03);
    margin-bottom: calc(88px * -0.38);
  }

  .section__head--row { flex-direction: column; align-items: flex-start; }
  /* Keep the category pager visible on mobile (slightly smaller to fit) */
  .cat__controls { gap: 0.6rem; }
  .cat__controls .circle-btn { width: 44px; height: 44px; }
  .cat__controls .circle-btn svg { width: 20px; height: 20px; }
  /* ---- HERO ----
     The desktop hero is a 320vh scroll-driven zoom across seven composited
     tiles. At 390px that reads as a 97x210 sliver behind the title and costs
     three screens of scrolling to get past, while seven layers at DPR 3 is
     ~70 MB of GPU texture - what crashed mobile Safari.
     Phones get a plain full-bleed hero instead: one image, one screen, no
     GSAP. initZoom() bails out under this breakpoint (see main.js), so the
     tile keeps the static size set here. */
  .hero { height: 100vh; }
  .hero__sticky { position: relative; height: 100vh; }

  .zoom-img:not([data-zoom="0"]) { display: none; }
  .zoom-img { transform: none; }
  .zoom-img[data-zoom="0"] .zoom-img__tile {
    top: 0; left: 0;
    width: 100vw; height: 100vh;
    border-radius: 0;
    box-shadow: none;
  }
  /* The photo is now directly behind the headline rather than a small framed
     tile, so the desktop radial scrim no longer carries it. This gradient
     keeps the title and eyebrow legible over a bright image. z-index sits
     under .hero__overlay (4) and over the tile. */
  .hero__sticky::after {
    content: '';
    position: absolute;
    inset: 0;
    z-index: 3;
    pointer-events: none;
    background: linear-gradient(180deg,
      rgba(5, 8, 16, 0.60) 0%,
      rgba(5, 8, 16, 0.28) 38%,
      rgba(5, 8, 16, 0.80) 100%);
  }

  /* ---- HAMBURGER MENU ----
     .site-header gets backdrop-filter once scrolled, and a non-none
     backdrop-filter makes an element a containing block for its
     position:fixed descendants. The menu is a fixed inset:0 child of the
     header, so after any scroll it collapsed from 371x840 into the 371x106
     header strip - the "menu misbehaves in the middle of the page" bug.
     Dropping the filter while the menu is open hands the viewport back as
     the containing block; the blur is invisible anyway behind an opaque
     full-screen overlay. */
  .site-header.nav-open,
  .site-header.nav-open.is-scrolled {
    backdrop-filter: none;
    -webkit-backdrop-filter: none;
    background: transparent;
    border-bottom-color: transparent;
  }

  /* ---- HORIZONTAL SCROLL ----
     The coverflow carousel runs overflow:visible on purpose so neighbouring
     cards peek on desktop. At 390px those slides pushed the document to
     786px wide and the whole page scrolled sideways. */
  .brands .swiper { overflow: hidden; }

  .brands .swiper-slide { width: 240px; height: 320px; }

  /* Smaller shared height on phones; fitLogo() re-fits on resize. Its width
     guard also clamps Rowenta's very wide wordmark to the viewport here. */
  .cat__logo-box { --logo-h: 34px; }
}

/* ============================================================
   REDUCED MOTION
============================================================ */
@media (prefers-reduced-motion: reduce) {
  * { animation: none !important; scroll-behavior: auto !important; }
  .hero { height: auto; }
  .hero__sticky { position: relative; height: auto; padding: 8rem 0; }
  .hero__grid { display: none; }
  .reveal { opacity: 1; transform: none; }
}

/* ============================================================
   CONTACT PAGE
   Reuses .section, .eyebrow, .section__title/__lead, .btn, .reveal
   etc. from above; only the page-specific pieces are added here.
============================================================ */
.section--intro { padding-top: calc(var(--section-y) + 2.5rem); padding-bottom: clamp(2rem, 5vw, 3.5rem); }

.contact { display: grid; grid-template-columns: 0.9fr 1.1fr; gap: clamp(1.5rem, 4vw, 3.5rem); align-items: start; }

/* Details column */
.contact__info { display: flex; flex-direction: column; gap: 1.5rem; }
.contact-card {
  display: flex; gap: 1rem; align-items: flex-start;
  padding: 1.35rem 1.4rem; background: var(--steel); border: 1px solid var(--line); border-radius: var(--radius);
  transition: transform 0.4s var(--ease), border-color 0.4s var(--ease), box-shadow 0.4s var(--ease);
}
.contact-card:hover { transform: translateY(-3px); border-color: var(--line-strong); box-shadow: 0 20px 50px -30px rgba(0,0,0,0.9); }
.contact-card__icon {
  flex: none; width: 46px; height: 46px; display: grid; place-items: center; border-radius: 12px;
  color: var(--accent); background: rgba(78,168,255,0.08); border: 1px solid var(--line-strong);
}
.contact-card__icon svg { width: 21px; height: 21px; }
.contact-card__label { font-size: 0.7rem; font-weight: 600; letter-spacing: 0.16em; text-transform: uppercase; color: var(--muted-dim); margin-bottom: 0.3rem; }
.contact-card__value { color: var(--text); font-size: 1rem; line-height: 1.5; }
a.contact-card__value { transition: color 0.25s var(--ease); }
a.contact-card__value:hover { color: var(--accent); }

/* Form column */
.contact__form-wrap {
  position: relative; padding: clamp(1.6rem, 3vw, 2.6rem);
  background: var(--steel-2); border: 1px solid var(--line); border-radius: var(--radius);
  box-shadow: 0 30px 80px -50px rgba(0,0,0,0.9);
}
.contact-form { display: flex; flex-direction: column; gap: 1.25rem; }
.contact-form__error {
  margin-bottom: 1rem; padding: 0.85rem 1rem; border-radius: 12px;
  background: rgba(255,120,120,0.08); border: 1px solid rgba(255,120,120,0.35); color: var(--text); font-size: 0.9rem;
}
.field-row { display: grid; grid-template-columns: 1fr 1fr; gap: 1.25rem; }
.field { display: flex; flex-direction: column; gap: 0.5rem; }
.field label { font-size: 0.8rem; font-weight: 600; letter-spacing: 0.04em; color: var(--muted); }
.field input, .field textarea {
  font-family: var(--font-body); font-size: 0.98rem; color: var(--text);
  background: rgba(255,255,255,0.03); border: 1px solid var(--line-strong); border-radius: 12px; padding: 0.85rem 1rem;
  transition: border-color 0.25s var(--ease), box-shadow 0.25s var(--ease), background 0.25s var(--ease);
}
.field textarea { resize: vertical; min-height: 130px; }
.field input::placeholder, .field textarea::placeholder { color: var(--muted-dim); }
.field input:focus, .field textarea:focus {
  outline: none; border-color: var(--accent); background: rgba(78,168,255,0.05); box-shadow: 0 0 0 3px rgba(78,168,255,0.14);
}
.field.is-invalid input, .field.is-invalid textarea { border-color: rgba(255,120,120,0.6); }
.contact-form__actions { display: flex; align-items: center; gap: 1.25rem; flex-wrap: wrap; margin-top: 0.5rem; }
.contact-form__fineprint { color: var(--muted-dim); font-size: 0.85rem; }

/* Success panel — shown when the server redirects back with ?sent=1 */
.form-success {
  position: absolute; inset: 0; display: none; flex-direction: column; align-items: center; justify-content: center; text-align: center;
  gap: 0.75rem; padding: 2rem; border-radius: var(--radius);
  background: linear-gradient(180deg, rgba(20,27,41,0.96), rgba(17,21,31,0.98)); backdrop-filter: blur(4px);
}
.form-success.is-shown { display: flex; }
.form-success__ring { width: 64px; height: 64px; display: grid; place-items: center; border-radius: 50%; color: var(--accent); border: 2px solid var(--accent); box-shadow: 0 0 30px -6px var(--accent-glow); }
.form-success h3 { font-family: var(--font-head); font-weight: 600; font-size: 1.4rem; }
.form-success p { color: var(--muted); max-width: 34ch; }

/* Trust strip */
.trust { display: grid; grid-template-columns: repeat(3, 1fr); gap: clamp(1rem,3vw,2.5rem); margin-top: clamp(3rem,7vw,5rem); padding-top: clamp(2rem,5vw,3rem); border-top: 1px solid var(--line); }
.trust__num { font-family: var(--font-head); font-weight: 700; font-size: clamp(1.8rem,4vw,2.6rem); color: var(--text); }
.trust__label { color: var(--muted); font-size: 0.9rem; margin-top: 0.35rem; }

@media (max-width: 860px) { .contact { grid-template-columns: 1fr; } }
@media (max-width: 560px) { .field-row { grid-template-columns: 1fr; } .trust { grid-template-columns: 1fr; text-align: center; } }

/* ============================================================
   ABOUT PAGE (additive — scoped to page-about.php markup only)
   Reuses the shared .section/.eyebrow/.trust/.cta/.btn system; these
   classes only cover the story column width and the 3-pillar grid.
============================================================ */
/* Feature image — a large framed band with the same steel/glow treatment as
   the CTA, giving the About page a distinct visual moment. */
.about-figure {
  position: relative; margin: 0; overflow: hidden;
  border: 1px solid var(--line); border-radius: clamp(20px, 4vw, 32px);
  box-shadow: 0 40px 90px -50px rgba(0,0,0,0.9);
}
.about-figure::after {
  content: ""; position: absolute; inset: 0; pointer-events: none;
  background: radial-gradient(120% 140% at 50% -25%, rgba(10,31,61,0.4), transparent 55%);
}
.about-figure__img { display: block; width: 100%; height: clamp(260px, 46vw, 560px); object-fit: cover; }

/* Story — two-column editorial layout (heading | body) so it reads
   differently from the single-column home / partner pages. */
.about-story-grid { display: grid; grid-template-columns: 0.8fr 1.2fr; gap: clamp(1.5rem, 4vw, 3.5rem); align-items: start; }
.about-story-grid__head { position: sticky; top: 6rem; }
.about-story { max-width: 64ch; }
.about-story p { color: var(--muted); font-size: 1.05rem; }
.about-story p + p { margin-top: 1.2rem; }
@media (max-width: 860px) { .about-story-grid { grid-template-columns: 1fr; } .about-story-grid__head { position: static; } }

/* Three pillars — same card language as .contact-card (steel + line + radius). */
.about-values { display: grid; grid-template-columns: repeat(3, 1fr); gap: clamp(1rem, 3vw, 2rem); margin-top: clamp(2.5rem, 6vw, 4rem); }
.about-value {
  padding: 1.6rem 1.5rem; background: var(--steel); border: 1px solid var(--line); border-radius: var(--radius);
  transition: transform 0.4s var(--ease), border-color 0.4s var(--ease), box-shadow 0.4s var(--ease);
}
.about-value:hover { transform: translateY(-3px); border-color: var(--line-strong); box-shadow: 0 20px 50px -30px rgba(0,0,0,0.9); }
.about-value__title { font-family: var(--font-head); font-weight: 600; font-size: 1.1rem; color: var(--text); margin-bottom: 0.5rem; }
.about-value__text { color: var(--muted); font-size: 0.95rem; line-height: 1.6; }
@media (max-width: 760px) { .about-values { grid-template-columns: 1fr; } }

/* ============================================================
   WORDPRESS/ACF PLUMBING
   Non-visual helpers so ACF-driven links and the image logo slot
   into the existing design without changing any layout or styling.
============================================================ */
/* Image logo replaces the text wordmark (header + footer). */
/* The logo PNG carries dead space: the artwork fills 80% of its width and
   only 59% of its height, with 38% empty at the bottom. Sizing the FILE
   therefore sized mostly nothing - a 90px-tall box showing a 53px mark, while
   still forcing the header to 107px.
   Fix: render the file large enough that the artwork itself hits the target
   height, then pull the transparent margins back out of the layout with
   negative margins. The element's effective footprint becomes the artwork
   alone, so the header is driven by what you can actually see.
     height 115px x 59% ink  = ~68px of visible mark (was 53px)
     margins cancel 3% top / 38% bottom of that 115px
   Net: the mark is ~28% larger, the header box is the same height. */
.brand__logo {
  display: block;
  height: 115px;
  width: auto;
  margin-top: calc(115px * -0.03);
  margin-bottom: calc(115px * -0.38);
}
.site-footer__brand .brand__logo {
  height: 107px;
  margin-top: calc(107px * -0.03);
  margin-bottom: calc(107px * -0.38);
}

/* Brand card may render as <a>; keep it identical to the <article> version. */
.brand-card { display: block; color: inherit; text-decoration: none; }

/* Category card may wrap its contents in a link; a block anchor fills the
   card with no visual change (same stacking as the un-linked version). */
.cat-card__link { display: block; color: inherit; text-decoration: none; }

/* Contact-form honeypot: moved off-screen rather than display:none, because
   the dumb bots this catches skip fields the browser reports as hidden. */
.fi-hp {
  position: absolute !important;
  left: -9999px !important;
  width: 1px; height: 1px;
  overflow: hidden;
}
