/* ==========================================================================
   ZYXORA — THE EXPERIENCE LAYER
   --------------------------------------------------------------------------
   The world canvas, the glass, the pinned scenes, the cursor and the loader.
   style.css is the site; this file is the journey through it.

   Layering, from back to front:
     0  the WebGL canvas
     1  vignette + grain (they sit on the canvas, under the content)
     2  document content
    60  header
   900  custom cursor
  1000  dialog
  1200  loader
  1300  page transition
   ========================================================================== */

/* --------------------------------------------------------------------------
   1. The world
   -------------------------------------------------------------------------- */
.world-canvas {
  position: fixed;
  inset: 0;
  width: 100%;
  height: 100%;
  z-index: var(--z-world);
  pointer-events: none;
  display: block;
}

/* Content must never be judged against a bright patch of world. The vignette
   is what keeps the type legible wherever the camera happens to be. */
.world-vignette {
  position: fixed;
  inset: 0;
  z-index: var(--z-vignette);
  pointer-events: none;
  background:
    radial-gradient(ellipse at 50% 42%, rgba(14, 15, 25, 0) 0%, rgba(14, 15, 25, 0.55) 62%, rgba(14, 15, 25, 0.88) 100%),
    linear-gradient(to bottom, rgba(14, 15, 25, 0.7) 0%, rgba(14, 15, 25, 0) 22%, rgba(14, 15, 25, 0) 78%, rgba(14, 15, 25, 0.75) 100%);
}

.world-grain {
  position: fixed;
  inset: 0;
  z-index: var(--z-vignette);
  pointer-events: none;
  opacity: 0.45;
  background-image: radial-gradient(rgba(255, 241, 208, 0.05) 1px, transparent 0);
  background-size: 34px 34px;
}

/* When there is no WebGL, the background still has to be a place. */
.no-world body {
  background:
    radial-gradient(ellipse at 50% -10%, rgba(120, 6, 6, 0.28) 0%, rgba(14, 15, 25, 0) 55%),
    radial-gradient(ellipse at 80% 110%, rgba(120, 6, 6, 0.14) 0%, rgba(14, 15, 25, 0) 50%),
    var(--color-bg);
  background-attachment: fixed;
}
.no-world .world-canvas { display: none; }

/* If the GPU drops the context mid-session, say so quietly rather than
   leaving a black rectangle. */
.webgl-lost .world-canvas { opacity: 0; transition: opacity 0.4s ease; }

main, .footer { position: relative; z-index: var(--z-content); }

/* --------------------------------------------------------------------------
   2. Loader
   -------------------------------------------------------------------------- */
.is-loading { overflow: hidden; }

.loader {
  position: fixed;
  inset: 0;
  z-index: var(--z-loader);
  background: var(--color-bg);
  display: grid;
  place-items: center;
  clip-path: inset(0% 0% 0% 0%);
}

.loader::after {
  content: '';
  position: absolute;
  inset: 0;
  background: radial-gradient(ellipse at 50% 50%, rgba(120, 6, 6, 0.22) 0%, rgba(14, 15, 25, 0) 62%);
  pointer-events: none;
}

.loader__inner {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 2.75rem;
  padding: 2rem;
}

.loader__mark {
  width: clamp(84px, 14vw, 128px);
  height: auto;
  animation: loader-pulse 2.8s var(--ease-out-expo) infinite;
}

@keyframes loader-pulse {
  0%, 100% { opacity: 0.62; transform: scale(1); }
  50%      { opacity: 1;    transform: scale(1.04); }
}

.loader__meta { width: min(320px, 70vw); }

.loader__bar {
  height: 1px;
  background: rgba(255, 241, 208, 0.16);
  overflow: hidden;
}

.loader__bar-fill {
  display: block;
  height: 100%;
  background: linear-gradient(90deg, var(--color-brand-accent), var(--color-heading));
  transform: scaleX(0);
  transform-origin: left center;
}

.loader__readout {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  margin-top: 0.9rem;
}

.loader__label {
  font-size: var(--text-micro);
  text-transform: uppercase;
  letter-spacing: var(--tracking-label);
  color: var(--color-secondary-text);
}

.loader__percent {
  font-size: var(--text-small);
  color: var(--color-heading);
  font-variant-numeric: tabular-nums;
}

/* --------------------------------------------------------------------------
   3. Page transition
   -------------------------------------------------------------------------- */
.page-transition {
  position: fixed;
  inset: 0;
  z-index: var(--z-transition);
  display: none;
  background: var(--color-bg);
  place-items: center;
  align-content: center;
  justify-items: center;
  gap: 1.75rem;
}

.page-transition__mark { width: 96px; height: auto; opacity: 0; }

.page-transition__line {
  display: block;
  width: min(280px, 50vw);
  height: 2px;
  background: var(--color-brand-accent);
  transform: scaleX(0);
  transform-origin: left center;
}

/* --------------------------------------------------------------------------
   4. Custom cursor
   -------------------------------------------------------------------------- */
.has-custom-cursor,
.has-custom-cursor a,
.has-custom-cursor button,
.has-custom-cursor [data-cursor] { cursor: none; }

.cursor {
  position: fixed;
  inset: 0;
  z-index: var(--z-cursor);
  pointer-events: none;
  opacity: 0;
}

.cursor__ring,
.cursor__dot {
  position: absolute;
  top: 0;
  left: 0;
  border-radius: 50%;
  will-change: transform;
}

.cursor__ring {
  width: 26px;
  height: 26px;
  margin: -13px 0 0 -13px;
  border: 1px solid rgba(255, 241, 208, 0.55);
  backdrop-filter: invert(2%);
}

.cursor__dot {
  width: 4px;
  height: 4px;
  margin: -2px 0 0 -2px;
  background: var(--color-heading);
}

.cursor__label {
  position: absolute;
  top: 0;
  left: 0;
  transform: translate(-50%, -50%);
  font-size: var(--text-micro);
  font-weight: 700;
  letter-spacing: var(--tracking-nav);
  text-transform: uppercase;
  color: var(--color-heading);
  opacity: 0;
  white-space: nowrap;
}

/* Keep the label pinned to the ring */
.cursor__ring { display: grid; place-items: center; }

/* --------------------------------------------------------------------------
   5. Header
   -------------------------------------------------------------------------- */
.header {
  position: fixed;
  top: 0;
  inset-inline: 0;
  z-index: var(--z-header);
  padding-block: 1rem;
  transition: padding var(--transition-normal), background-color var(--transition-normal),
              border-color var(--transition-normal), backdrop-filter var(--transition-normal);
  border-bottom: 1px solid transparent;
}

.header.scrolled {
  padding-block: 0.7rem;
  background: rgba(14, 15, 25, 0.62);
  backdrop-filter: blur(var(--glass-blur)) saturate(140%);
  -webkit-backdrop-filter: blur(var(--glass-blur)) saturate(140%);
  border-bottom-color: var(--glass-border);
}

.nav-wrapper {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1.5rem;
}

.brand-logo {
  display: inline-flex;
  align-items: center;
  gap: 0.7rem;
  flex-shrink: 0;
}

.brand-logo img {
  width: clamp(30px, 3.4vw, 40px);
  height: auto;
  transition: transform var(--transition-normal);
}
.brand-logo:hover img { transform: rotate(24deg); }

.brand-logo__word {
  font-size: clamp(1.05rem, 0.9rem + 0.55vw, 1.4rem);
  letter-spacing: 0.08em;
  line-height: 1;
}

/* The drawer wrapper. On desktop it is nothing — a flex row that lets the
   list sit in the header. Everything that makes it a panel arrives in the
   ≤1024px block further down. */
.nav-panel {
  display: flex;
  align-items: center;
}

/* Head and foot exist only for the drawer */
.nav-panel__head,
.nav-panel__foot { display: none; }

.nav-menu {
  display: flex;
  align-items: center;
  gap: clamp(0.85rem, 1.6vw, 2rem);
}

/* Flex items shrink below their content width by default, which snapped
   "ABOUT US" onto two lines as soon as a seventh link was added. A menu bar
   either fits on one line or moves to the drawer — it never wraps. */
.nav-menu > li { flex: none; }
.nav-link { white-space: nowrap; }

.nav-scrim { display: none; }

/* Navigation.

   Bold, tightly-tracked uppercase is what dates a menu. Light weight with
   generous tracking reads as current, and at this size the extra letter
   spacing is what keeps it legible rather than what hurts it. */
.nav-link {
  position: relative;
  display: inline-block;
  padding-block: 0.4rem;
  font-size: var(--text-small);
  font-weight: 300;
  text-transform: uppercase;
  letter-spacing: 0.16em;
  color: var(--color-secondary-text);
  transition: color var(--transition-fast), letter-spacing var(--transition-normal);
}

.nav-link.active { font-weight: 400; }

.nav-link::after {
  content: '';
  position: absolute;
  left: 0;
  bottom: 0;
  width: 100%;
  height: 1px;
  background: var(--color-brand-accent);
  transform: scaleX(0);
  transform-origin: right center;
  transition: transform 0.4s var(--ease-out-expo);
}

.nav-link:hover,
.nav-link.active { color: var(--color-heading); }
.nav-link:hover::after,
.nav-link.active::after { transform: scaleX(1); transform-origin: left center; }

.header-actions { display: flex; align-items: center; gap: 1rem; }
.nav-cta-item { display: none; }

.mobile-toggle {
  display: none;
  width: 42px;
  height: 42px;
  position: relative;
  z-index: 2;
}
.mobile-toggle span {
  display: block;
  width: 22px;
  height: 1.5px;
  margin: 5px auto;
  background: var(--color-heading);
  transition: transform 0.35s var(--ease-out-expo), opacity 0.2s ease;
}
.menu-open .mobile-toggle span:nth-child(1) { transform: translateY(6.5px) rotate(45deg); }
.menu-open .mobile-toggle span:nth-child(2) { opacity: 0; }
.menu-open .mobile-toggle span:nth-child(3) { transform: translateY(-6.5px) rotate(-45deg); }

/* --------------------------------------------------------------------------
   6. Hero
   --------------------------------------------------------------------------
   Three columns, two rows:

       ┌───────────────────────────────────────────────┐
       │            ZYXORA PRIVATE LIMITED             │  row 1
       │                  ZYXORA                       │
       ├───────────┬───────────────────┬───────────────┤
       │  figures  │   the 3D mark     │    actions    │  row 2
       └───────────┴───────────────────┴───────────────┘

   Both rails are the same fixed width, so the centre column is exactly
   viewport-centred — which is where the WebGL mark sits at world x = 0.

   The whole block is centred with `align-content`, not stretched. That is
   what stops the composition drifting apart on a tall display: at 1080px the
   old layout left 216px of dead air above the eyebrow.
   -------------------------------------------------------------------------- */
.hero {
  position: relative;
  min-height: 100svh;
  display: flex;
  z-index: var(--z-content);
}

.hero-inner {
  --rail-width: clamp(200px, 19vw, 300px);
  --rail-gap: clamp(1.25rem, 3vw, 3rem);

  flex: 1;
  display: grid;
  grid-template-columns: var(--rail-width) minmax(0, 1fr) var(--rail-width);
  grid-template-rows: auto auto;
  column-gap: var(--rail-gap);
  row-gap: clamp(1.25rem, 3vh, 2.5rem);
  align-content: center;
  justify-items: center;
  min-height: 100svh;
  padding-top: calc(var(--header-height) + 1.5rem);
  padding-bottom: clamp(4rem, 8vh, 6rem);
  position: relative;
}

/* ---- row 1: the lockup ---- */
.hero-lockup {
  grid-column: 1 / -1;
  grid-row: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  width: 100%;
}

.hero-tag {
  display: inline-block;
  font-size: var(--text-micro);
  font-weight: 400;
  text-transform: uppercase;
  letter-spacing: var(--tracking-label);
  color: var(--color-secondary-text);
  padding: 0.5rem 1.15rem;
  border: 1px solid var(--glass-border);
  border-radius: 100px;
  background: var(--glass-bg);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  max-width: none;
  margin-bottom: clamp(1.1rem, 2.4vh, 1.9rem);
}

.hero-heading {
  font-size: var(--text-hero-size);
  font-weight: 900;
  line-height: 0.9;
  letter-spacing: var(--tracking-hero);
  margin: 0;
  word-break: normal;
  overflow-wrap: normal;
  max-width: 100%;
}

/* ---- row 2, centre: the band the 3D mark is aligned into ---- */
.hero-mark-space {
  grid-column: 2;
  grid-row: 2;
  width: 100%;
  height: clamp(180px, 30vh, 360px);
  pointer-events: none;
}

/* ---- the rails ---- */
.hero-rail {
  grid-row: 2;
  align-self: center;
  width: 100%;
  display: flex;
  flex-direction: column;
  border: 1px solid var(--glass-border);
  border-radius: var(--radius-lg);
  background: var(--glass-bg);
  backdrop-filter: blur(var(--glass-blur)) saturate(130%);
  -webkit-backdrop-filter: blur(var(--glass-blur)) saturate(130%);
  overflow: hidden;
}

.hero-rail--stats { grid-column: 1; justify-self: start; }
.hero-rail--actions { grid-column: 3; justify-self: end; }

/* Rows shared by both rails, so the two sides read as one system */
.hero-stat,
.hero-action {
  display: grid;
  align-items: center;
  gap: 0.85rem;
  padding: clamp(0.9rem, 1.7vh, 1.2rem) clamp(1rem, 1.4vw, 1.35rem);
  position: relative;
  isolation: isolate;
}

.hero-stat + .hero-stat,
.hero-action + .hero-action { border-top: 1px solid var(--glass-border); }

/* ---- figures ---- */
.hero-stat { grid-template-columns: minmax(3.1rem, auto) 1fr; }

.hero-stat__value {
  font-family: var(--font-astron);
  font-size: clamp(1.3rem, 1.05rem + 0.55vw, 1.65rem);
  font-weight: 700;
  line-height: 1;
  letter-spacing: 0.01em;
  color: var(--color-heading);
  font-variant-numeric: tabular-nums;
}

.hero-stat__label {
  font-family: var(--font-trade-gothic);
  font-size: var(--text-micro);
  font-weight: 400;
  text-transform: uppercase;
  letter-spacing: 0.11em;
  line-height: 1.35;
  color: var(--color-secondary-text);
}

/* ---- actions ---- */
.hero-action {
  grid-template-columns: auto 1fr auto;
  color: var(--color-heading);
  transition: color var(--transition-fast);
}

/* The fill wipes in from the left — the same gesture as the buttons and the
   display-type reveals, so the motion language stays consistent. */
.hero-action::before {
  content: '';
  position: absolute;
  inset: 0;
  z-index: -1;
  background: var(--color-brand-accent);
  transform: scaleX(0);
  transform-origin: left center;
  transition: transform 0.5s var(--ease-out-expo);
}
.hero-action:hover::before,
.hero-action:focus-visible::before { transform: scaleX(1); }

.hero-action__index {
  font-family: var(--font-trade-gothic);
  font-size: var(--text-micro);
  font-variant-numeric: tabular-nums;
  letter-spacing: 0.14em;
  color: var(--color-secondary-text);
  transition: color var(--transition-fast);
}
.hero-action:hover .hero-action__index { color: var(--color-heading); }

.hero-action__label {
  font-family: var(--font-trade-gothic);
  font-size: var(--text-small);
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: var(--tracking-button);
  line-height: 1.2;
  text-align: left;
}

/* Drawn rather than a glyph: it stays crisp at any size and it can move. */
.hero-action__arrow {
  position: relative;
  width: 22px;
  height: 1px;
  background: currentColor;
  opacity: 0.55;
  transition: transform 0.45s var(--ease-out-expo), opacity var(--transition-fast);
}
.hero-action__arrow::after {
  content: '';
  position: absolute;
  right: 0;
  top: 50%;
  width: 6px;
  height: 6px;
  border-top: 1px solid currentColor;
  border-right: 1px solid currentColor;
  transform: translateY(-50%) rotate(45deg);
}
.hero-action:hover .hero-action__arrow,
.hero-action:focus-visible .hero-action__arrow {
  transform: translateX(6px);
  opacity: 1;
}

/* ---- scroll cue ----
   Inside .hero-inner so it aligns to the container's content edge. As a child
   of .hero it was positioning against the viewport and landing out in the
   outer gutter on wide screens. */
.scroll-cue {
  position: absolute;
  right: var(--container-gutter);
  bottom: clamp(1rem, 3vh, 2rem);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.6rem;
  z-index: 3;
}
.scroll-cue__label {
  font-size: var(--text-micro);
  font-weight: 400;
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
  color: var(--color-secondary-text);
}
.scroll-cue__line {
  width: 1px;
  height: 40px;
  background: linear-gradient(to bottom, var(--color-heading), transparent);
  position: relative;
  overflow: hidden;
}
.scroll-cue__line::after {
  content: '';
  position: absolute;
  inset-inline: 0;
  height: 12px;
  background: var(--color-brand-accent);
  animation: cue-travel 2.2s var(--ease-out-expo) infinite;
}
@keyframes cue-travel {
  0%   { transform: translateY(-14px); opacity: 0; }
  40%  { opacity: 1; }
  100% { transform: translateY(40px); opacity: 0; }
}


/* --------------------------------------------------------------------------
   7. Glass
   --------------------------------------------------------------------------
   Glass panels are spatial objects, not flat cards: they live inside a
   perspective, carry a z-position, and lift toward the viewer on hover.
   -------------------------------------------------------------------------- */
.glass,
.glass-panel,
.service-panel,
.product-panel,
.review-card {
  background: var(--glass-bg);
  border: 1px solid var(--glass-border);
  border-radius: var(--radius-lg);
  backdrop-filter: blur(var(--glass-blur)) saturate(130%);
  -webkit-backdrop-filter: blur(var(--glass-blur)) saturate(130%);
  position: relative;
  overflow: hidden;
}

/* A single sheen across the top edge — the light of the room catching glass */
.glass::before,
.glass-panel::before,
.service-panel::before,
.product-panel::before,
.review-card::before {
  content: '';
  position: absolute;
  inset: 0;
  background: linear-gradient(135deg, rgba(255, 241, 208, 0.09) 0%, rgba(255, 241, 208, 0) 34%);
  pointer-events: none;
}

/* --------------------------------------------------------------------------
   8. About
   -------------------------------------------------------------------------- */
.about-grid {
  display: grid;
  grid-template-columns: 1.05fr 0.95fr;
  gap: clamp(2rem, 5vw, 5rem);
  align-items: start;
  perspective: 1400px;
}

.statement-heading {
  font-size: var(--text-statement);
  margin-bottom: 1.75rem;
  line-height: 1.14;
}

/* Spacing between stacked paragraphs comes from the `p + p` flow rule in
   style.css, so this only needs to clear the block that follows. */
.about-text:last-child { margin-bottom: 0; }

.about-panels {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: clamp(1rem, 2vw, 1.5rem);
  transform-style: preserve-3d;
}

.glass-panel {
  padding: clamp(1.35rem, 2.4vw, 1.9rem);
  transition: transform var(--transition-normal), border-color var(--transition-normal),
              background-color var(--transition-normal);
  will-change: transform;
}

.glass-panel:hover {
  transform: translateY(-6px) translateZ(30px);
  border-color: var(--glass-border-active);
  background: var(--glass-bg-strong);
}

/* Small numerals sit at body size, so they follow the same contrast rule as
   the eyebrow labels: mauve text, red kept for the states that are drawn. */
.glass-panel__num {
  display: block;
  font-size: var(--text-small);
  color: var(--color-secondary-text);
  letter-spacing: var(--tracking-label);
  margin-bottom: 0.85rem;
  transition: color var(--transition-fast);
}
.glass-panel:hover .glass-panel__num { color: var(--color-heading); }

.glass-panel__title {
  font-size: 1.08rem;
  margin-bottom: 0.6rem;
  letter-spacing: 0.045em;
  line-height: 1.2;
}
.glass-panel__body {
  font-size: 0.93rem;
  line-height: 1.62;
  max-width: none;
}

/* --------------------------------------------------------------------------
   9. Services — pinned scene
   --------------------------------------------------------------------------
   All six panels occupy the same grid cell, so the container is as tall as
   the tallest of them and nothing is ever clipped. Only one is forward.
   -------------------------------------------------------------------------- */
/* The section's height IS the scroll budget for the sequence, and the scene
   sticks inside it. Sticky rather than a JS pin: no pin-spacer to mis-measure,
   nothing injected into the DOM, and it survives every resize for free. */
.services {
  padding-block: 0;
  height: 700vh;
}

.services-scene {
  position: sticky;
  top: 0;
  height: 100svh;
  display: flex;
  align-items: center;
  overflow: hidden;
}

.services-layout {
  display: grid;
  grid-template-rows: auto 1fr auto;
  gap: clamp(1.5rem, 4vh, 3rem);
  height: 100svh;
  padding-top: calc(var(--header-height) + clamp(1rem, 4vh, 3rem));
  padding-bottom: clamp(2rem, 5vh, 3.5rem);
}

.services-header { margin-bottom: 0; }

.services-stage {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 2rem;
  min-height: 0;
}

.service-panels {
  display: grid;
  width: min(620px, 100%);
  perspective: 1200px;
  transform-style: preserve-3d;
}

.service-panel {
  grid-area: 1 / 1;
  padding: clamp(1.6rem, 3.2vw, 2.6rem);
  opacity: 0;
  visibility: hidden;
  transform: translateZ(-260px) translateY(34px) rotateX(9deg);
  transition:
    opacity 0.65s var(--ease-out-expo),
    transform 0.75s var(--ease-out-expo),
    visibility 0s linear 0.75s,
    border-color 0.5s ease;
  pointer-events: none;
}

.service-panel.is-active {
  opacity: 1;
  visibility: visible;
  transform: translateZ(0) translateY(0) rotateX(0deg);
  border-color: var(--glass-border-active);
  transition-delay: 0s, 0s, 0s, 0s;
  pointer-events: auto;
}

/* Panels already passed recede upward instead of backward, so the stack has a
   sense of ahead and behind rather than simply appearing and disappearing. */
.service-panel.is-past:not(.is-active) {
  transform: translateZ(-180px) translateY(-30px) rotateX(-7deg);
}

.service-panel__num {
  display: flex;
  align-items: center;
  gap: 0.7rem;
  font-size: var(--text-small);
  color: var(--color-secondary-text);
  letter-spacing: var(--tracking-label);
  margin-bottom: 1.05rem;
}

/* The active station is the one being read, so its marker burns brand red */
.service-panel__num::before {
  content: '';
  flex: none;
  width: 20px;
  height: 2px;
  background: var(--color-border);
  transition: background-color var(--transition-normal), width var(--transition-normal);
}
.service-panel.is-active .service-panel__num { color: var(--color-heading); }
.service-panel.is-active .service-panel__num::before {
  background: var(--color-accent-light);
  width: 34px;
}

.service-panel__title {
  font-size: var(--text-card-title);
  margin-bottom: 1.1rem;
  line-height: 1.06;
  letter-spacing: 0.005em;
}

.service-panel__body {
  font-size: var(--text-body);
  max-width: 46ch;
  line-height: 1.7;
}

.service-index {
  display: flex;
  align-items: center;
  gap: 0.85rem;
  flex-shrink: 0;
}
.service-index__current { font-size: clamp(2.5rem, 5vw, 4.5rem); line-height: 1; }
.service-index__total { font-size: 1.05rem; color: var(--color-secondary-text); }
.service-index__divider {
  width: 44px;
  height: 1px;
  background: var(--color-border);
}

.service-progress {
  height: 2px;
  background: rgba(154, 143, 151, 0.16);
  overflow: hidden;
}
.service-progress__fill {
  display: block;
  height: 100%;
  background: linear-gradient(90deg, var(--color-brand-accent), var(--color-heading));
  transform: scaleX(0);
  transform-origin: left center;
}

/* --------------------------------------------------------------------------
   10. Digital Products — pinned scene
   -------------------------------------------------------------------------- */
.products {
  padding-block: 0;
  height: 420vh;
}

.products-scene {
  position: sticky;
  top: 0;
  height: 100svh;
  display: flex;
  align-items: center;
  overflow: hidden;
}

.products-layout {
  display: grid;
  grid-template-rows: auto 1fr;
  gap: clamp(1.5rem, 4vh, 3rem);
  height: 100svh;
  padding-top: calc(var(--header-height) + clamp(1rem, 4vh, 3rem));
  padding-bottom: clamp(2rem, 6vh, 4rem);
}

.products-header { margin-bottom: 0; }

.product-panels {
  display: grid;
  align-content: center;
  justify-items: start;
  perspective: 1200px;
  transform-style: preserve-3d;
  min-height: 0;
}

.product-panel {
  grid-area: 1 / 1;
  width: min(520px, 100%);
  padding: clamp(1.6rem, 3.2vw, 2.6rem);
  opacity: 0;
  visibility: hidden;
  transform: translateZ(-240px) translateX(-40px);
  transition:
    opacity 0.7s var(--ease-out-expo),
    transform 0.8s var(--ease-out-expo),
    visibility 0s linear 0.8s;
  pointer-events: none;
}

.product-panel.is-active {
  opacity: 1;
  visibility: visible;
  transform: translateZ(0) translateX(0);
  border-color: var(--glass-border-active);
  transition-delay: 0s;
  pointer-events: auto;
}

.product-panel__index {
  display: block;
  font-size: var(--text-micro);
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
  color: var(--color-secondary-text);
  margin-bottom: 1rem;
}

.product-panel__title {
  font-size: var(--text-card-title);
  margin-bottom: 1.1rem;
  line-height: 1.06;
  letter-spacing: 0.005em;
}

.product-panel__body {
  font-size: var(--text-body);
  max-width: 42ch;
  margin-bottom: 1.85rem;
  line-height: 1.7;
}

/* Each product sits on a different side of the frame, matching the camera
   move that introduces it: head-on, from the side, then around. */
.products-scene .product-panel:nth-child(2) { justify-self: end; }
.products-scene .product-panel:nth-child(3) { justify-self: center; }

/* --------------------------------------------------------------------------
   11. Reviews — depth stack
   -------------------------------------------------------------------------- */
.reviews-stack {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(290px, 1fr));
  gap: clamp(1.25rem, 2.5vw, 2rem);
  perspective: 1500px;
  transform-style: preserve-3d;
}

.review-card {
  padding: clamp(1.6rem, 3vw, 2.25rem);
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  gap: 1.75rem;
  will-change: transform, opacity;
  transition: border-color var(--transition-normal), background-color var(--transition-normal);
}
.review-card:hover { border-color: var(--glass-border-active); background: var(--glass-bg-strong); }

.review-quote {
  font-size: var(--text-body);
  line-height: 1.72;
  letter-spacing: 0.004em;
  max-width: none;
  text-wrap: pretty;
}

.review-author { display: flex; align-items: center; gap: 0.9rem; }

.author-avatar {
  display: grid;
  place-items: center;
  width: 42px;
  height: 42px;
  border-radius: 50%;
  background: var(--color-brand-accent);
  color: var(--color-heading);
  font-size: 1rem;
  flex-shrink: 0;
}

.author-info { display: flex; flex-direction: column; line-height: 1.35; }
.author-name { color: var(--color-heading); font-weight: 700; font-size: 0.95rem; }
.author-role { font-size: 0.82rem; color: var(--color-secondary-text); }

/* --------------------------------------------------------------------------
   12. Final CTA
   -------------------------------------------------------------------------- */
.cta-section {
  text-align: center;
  padding-block: clamp(7rem, 16vh, 12rem);
}

.cta-title {
  font-size: clamp(2.4rem, 1.2rem + 5.4vw, 6.5rem);
  max-width: 15ch;
  margin-inline: auto;
  margin-bottom: 2rem;
}

.cta-desc {
  font-size: var(--text-lead);
  max-width: 54ch;
  margin-inline: auto;
  margin-bottom: 2.75rem;
}

.cta-actions { display: flex; justify-content: center; }

/* --------------------------------------------------------------------------
   13. Contact dialog
   -------------------------------------------------------------------------- */
.modal-overlay {
  position: fixed;
  inset: 0;
  z-index: var(--z-modal);
  display: grid;
  place-items: center;
  padding: 1.5rem;
  background: rgba(8, 9, 16, 0.72);
  backdrop-filter: blur(14px);
  -webkit-backdrop-filter: blur(14px);
  opacity: 0;
  visibility: hidden;
  transition: opacity 0.35s ease, visibility 0s linear 0.35s;
  perspective: 1200px;
}

.modal-overlay.active {
  opacity: 1;
  visibility: visible;
  transition-delay: 0s;
}

.modal-card {
  width: 100%;
  max-width: 560px;
  max-height: 88vh;
  overflow-y: auto;
  padding: clamp(1.75rem, 4vw, 3rem);
  background: var(--glass-bg-strong);
  transform-style: preserve-3d;
}

.modal-close {
  position: absolute;
  top: 1.1rem;
  right: 1.25rem;
  width: 38px;
  height: 38px;
  display: grid;
  place-items: center;
  font-size: 1.6rem;
  line-height: 1;
  color: var(--color-secondary-text);
  border-radius: 50%;
  transition: color var(--transition-fast), background-color var(--transition-fast);
  z-index: 2;
}
.modal-close:hover { color: var(--color-heading); background: rgba(255, 241, 208, 0.08); }

.modal-title { font-size: clamp(1.6rem, 1.2rem + 1.6vw, 2.2rem); margin-bottom: 0.5rem; }
.modal-subtitle { font-size: 0.95rem; margin-bottom: 2rem; max-width: none; }

.modal-open { overflow: hidden; }

/* --------------------------------------------------------------------------
   14. Footer
   -------------------------------------------------------------------------- */
.footer {
  padding-block: clamp(3.5rem, 7vw, 6rem) clamp(2rem, 4vw, 3rem);
  background: linear-gradient(to bottom, rgba(14, 15, 25, 0) 0%, rgba(19, 21, 37, 0.9) 45%);
}

.footer-rule {
  display: block;
  height: 1px;
  background: linear-gradient(90deg, var(--color-border), rgba(154, 143, 151, 0.02));
  transform-origin: left center;
}

.footer-grid {
  display: grid;
  grid-template-columns: 1.6fr repeat(3, 1fr);
  gap: clamp(2rem, 4vw, 3.5rem);
  padding-block: clamp(2.5rem, 5vw, 4rem);
}

.footer-mark { display: inline-block; margin-bottom: 1.25rem; }
.footer-mark img {
  width: clamp(84px, 9vw, 120px);
  height: auto;
  transition: transform var(--transition-slow);
}
.footer-mark:hover img { transform: rotate(-20deg) scale(1.04); }

.footer-blurb { font-size: 0.92rem; max-width: 30ch; }

.footer-col__title {
  font-size: 0.92rem;
  letter-spacing: 0.07em;
  margin-bottom: 1.25rem;
}

.footer-links { display: flex; flex-direction: column; gap: 0.7rem; }
.footer-links a {
  font-size: 0.87rem;
  letter-spacing: 0.045em;
  color: var(--color-secondary-text);
  transition: color var(--transition-fast), transform var(--transition-fast);
  display: inline-block;
}
.footer-links a:hover { color: var(--color-heading); transform: translateX(4px); }

.footer-bottom {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  padding-top: clamp(1.5rem, 3vw, 2.25rem);
  font-size: var(--text-micro);
  letter-spacing: 0.08em;
  text-transform: uppercase;
}
.footer-bottom p { max-width: none; font-size: inherit; }

/* --------------------------------------------------------------------------
   15. Responsive
   --------------------------------------------------------------------------
   The type is already fluid, so these tiers reflow layout and shorten the
   choreography rather than resizing text.
   -------------------------------------------------------------------------- */

/* ---- Laptop ---- */
@media (max-width: 1400px) {
  /* Seven links plus the logo and the CTA is a lot for one row; close the
     gaps and the tracking before anything is forced to wrap. */
  .nav-menu { gap: 0.9rem; }
  .nav-link { letter-spacing: 0.1em; }
}

@media (max-width: 1200px) {
  .nav-menu { gap: 0.7rem; }
  .nav-link { font-size: var(--text-micro); letter-spacing: 0.08em; }
  .footer-grid { grid-template-columns: 1.4fr repeat(3, 1fr); gap: 2rem; }
}

/* ---- Tablet: the desktop nav no longer fits beside the CTA ---- */
@media (max-width: 1024px) {
  :root { --header-height: 72px; }

  /* Shorter pinned sequences on smaller screens: the same choreography, far
     less scrolling to get through it. */
  .services { height: 500vh; }
  .products { height: 320vh; }

  .about-grid { grid-template-columns: 1fr; }
  .about-panels { grid-template-columns: repeat(2, 1fr); }
  .footer-grid { grid-template-columns: 1fr 1fr; }

  /* ---- The drawer -------------------------------------------------------
     A full-height panel rather than a floating list: a head so it is clearly
     a menu and not a misplaced overlay, the links, then a foot carrying the
     action that the header's own CTA had to give up at this width.

     100dvh, not 100vh — on iOS Safari the address bar makes vh taller than
     the visible viewport, which would put the foot underneath it. */
  .nav-panel {
    position: fixed;
    inset: 0 0 0 auto;
    z-index: 1;
    display: flex;
    flex-direction: column;
    /* Not inherited: the desktop rule above is align-items:center, which in a
       column makes every row shrink to its content and centre itself. */
    align-items: stretch;
    width: min(88vw, 400px);
    height: 100vh;
    height: 100dvh;
    padding: 1.35rem 1.6rem calc(1.6rem + env(safe-area-inset-bottom));
    background: linear-gradient(200deg, rgba(28, 12, 16, 0.97), rgba(14, 15, 25, 0.98) 55%);
    backdrop-filter: blur(26px) saturate(150%);
    -webkit-backdrop-filter: blur(26px) saturate(150%);
    border-left: 1px solid var(--glass-border);
    box-shadow: -30px 0 80px -30px rgba(0, 0, 0, 0.9);
    transform: translateX(101%);
    /* 101% rather than 100%: a subpixel viewport width can otherwise leave a
       hairline of the panel visible against the right edge. */
    transition: transform 0.5s var(--ease-out-expo);
    overflow-y: auto;
    overscroll-behavior: contain;
    -webkit-overflow-scrolling: touch;
    visibility: hidden;
  }

  .nav-panel.open {
    transform: translateX(0);
    visibility: visible;
  }

  /* ---- Head ---- */
  .nav-panel__head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    /* Matches the header row, so MENU and the close button land level with
       the logo still showing to the left of the panel. */
    min-height: calc(var(--header-height) - 1.35rem);
    padding-bottom: 1rem;
    margin-bottom: 0.5rem;
    border-bottom: 1px solid var(--glass-border);
  }

  .nav-panel__eyebrow {
    font-family: var(--font-trade-gothic);
    font-size: var(--text-micro);
    font-weight: 400;
    letter-spacing: var(--tracking-label);
    text-transform: uppercase;
    color: var(--color-secondary-text);
  }

  .nav-close {
    position: relative;
    width: 42px;
    height: 42px;
    flex: none;
    border-radius: 50%;
    border: 1px solid var(--glass-border);
    background: transparent;
    cursor: pointer;
    transition: border-color var(--transition-fast), background var(--transition-fast);
  }
  .nav-close:hover { border-color: var(--glass-border-active); background: rgba(255, 241, 208, 0.06); }

  .nav-close span {
    position: absolute;
    left: 50%;
    top: 50%;
    width: 15px;
    height: 1.5px;
    background: var(--color-heading);
  }
  .nav-close span:nth-child(1) { transform: translate(-50%, -50%) rotate(45deg); }
  .nav-close span:nth-child(2) { transform: translate(-50%, -50%) rotate(-45deg); }

  /* ---- Links ----
     Numbered by a counter, so the markup stays a plain list and the numbering
     follows whatever order the admin panel put the links in. */
  .nav-menu {
    counter-reset: navitem;
    flex-direction: column;
    align-items: stretch;
    gap: 0;
    flex: 1 1 auto;
    padding: 0.75rem 0;
    margin: 0;
    list-style: none;
  }

  .nav-menu li { border-bottom: 1px solid rgba(255, 241, 208, 0.07); }
  .nav-menu li:last-child { border-bottom: 0; }

  .nav-menu .nav-link {
    display: flex;
    align-items: baseline;
    gap: 0.9rem;
    /* Undo the desktop tightening: in the drawer each link has a row to
       itself and should read at full size. */
    white-space: normal;
    /* A full-width row, so the whole line is the tap target rather than the
       few characters of the label. */
    padding: 1rem 0.25rem;
    font-size: var(--text-subhead);
    font-weight: 400;
    letter-spacing: 0.09em;
  }

  .nav-menu .nav-link::before {
    counter-increment: navitem;
    content: counter(navitem, decimal-leading-zero);
    font-size: var(--text-micro);
    font-weight: 400;
    letter-spacing: 0.14em;
    color: var(--color-secondary-text);
    transition: color var(--transition-fast);
    min-width: 1.6rem;
  }

  .nav-menu .nav-link.active::before { color: var(--color-accent-light); }

  /* The desktop underline sweep would run the full width of the row here,
     which reads as a mistake rather than a hover state. */
  .nav-menu .nav-link::after { display: none; }

  .nav-menu .nav-link.active,
  .nav-menu .nav-link:hover { color: var(--color-heading); }

  /* ---- Entrance ----------------------------------------------------------
     Deliberately CSS and not GSAP. The previous version tweened autoAlpha,
     which writes visibility:hidden onto every row as its start state — so a
     throttled or failed tween left the drawer open and empty, which is a far
     worse failure than a missing stagger. Here the resting state is the
     visible one; the transform only exists while the panel is closed. */
  .nav-menu li,
  .nav-panel__foot > * {
    opacity: 0;
    transform: translateX(20px);
    transition: opacity 0.45s var(--ease-out-expo),
                transform 0.45s var(--ease-out-expo);
  }

  .nav-panel.open .nav-menu li,
  .nav-panel.open .nav-panel__foot > * {
    opacity: 1;
    transform: none;
  }

  /* The stagger. Nth-child rather than a custom property per row, so the
     markup stays a plain list the admin panel can reorder freely. */
  .nav-panel.open .nav-menu li:nth-child(1) { transition-delay: 0.10s; }
  .nav-panel.open .nav-menu li:nth-child(2) { transition-delay: 0.15s; }
  .nav-panel.open .nav-menu li:nth-child(3) { transition-delay: 0.20s; }
  .nav-panel.open .nav-menu li:nth-child(4) { transition-delay: 0.25s; }
  .nav-panel.open .nav-menu li:nth-child(5) { transition-delay: 0.30s; }
  .nav-panel.open .nav-menu li:nth-child(6) { transition-delay: 0.35s; }
  .nav-panel.open .nav-menu li:nth-child(7) { transition-delay: 0.40s; }
  .nav-panel.open .nav-menu li:nth-child(n+8) { transition-delay: 0.45s; }

  .nav-panel.open .nav-panel__foot > *:nth-child(1) { transition-delay: 0.40s; }
  .nav-panel.open .nav-panel__foot > *:nth-child(2) { transition-delay: 0.46s; }
  .nav-panel.open .nav-panel__foot > *:nth-child(3) { transition-delay: 0.52s; }

  /* ---- Foot ---- */
  .nav-panel__foot {
    display: flex;
    flex-direction: column;
    gap: 1rem;
    padding-top: 1.35rem;
    border-top: 1px solid var(--glass-border);
  }

  .nav-panel__cta { width: 100%; justify-content: center; }

  .nav-panel__mail {
    font-size: var(--text-small);
    letter-spacing: 0.04em;
    color: var(--color-secondary-text);
    transition: color var(--transition-fast);
  }
  .nav-panel__mail:hover { color: var(--color-heading); }

  .nav-panel__social {
    display: flex;
    flex-wrap: wrap;
    gap: 0.4rem 1.1rem;
    margin: 0;
    padding: 0;
    list-style: none;
  }

  .nav-panel__social a {
    font-size: var(--text-micro);
    letter-spacing: var(--tracking-label);
    color: var(--color-secondary-text);
    transition: color var(--transition-fast);
  }
  .nav-panel__social a:hover { color: var(--color-heading); }

  /* ---- Scrim ----
     Sits below the header, so the logo and the toggle stay lit and tappable
     while everything else behind the drawer is dimmed. */
  .nav-scrim {
    display: block;
    position: fixed;
    inset: 0;
    z-index: calc(var(--z-header) - 5);
    border: 0;
    padding: 0;
    background: rgba(6, 7, 12, 0.68);
    backdrop-filter: blur(3px);
    -webkit-backdrop-filter: blur(3px);
    opacity: 0;
    pointer-events: none;
    cursor: pointer;
    transition: opacity 0.45s var(--ease-out-expo);
  }

  .menu-open .nav-scrim { opacity: 1; pointer-events: auto; }

  .mobile-toggle { display: block; }
  .header-actions .btn { display: none; }

  /* While the drawer is open its own close button takes over. Two X controls
     a few pixels apart is confusing, and this one is outside the focus trap,
     so a keyboard user could never reach it anyway. */
  .menu-open .mobile-toggle {
    opacity: 0;
    pointer-events: none;
    transition: opacity 0.2s ease;
  }

  /* Below this width the rails no longer fit beside the mark. They drop
     underneath it and sit side by side, which keeps the composition
     symmetrical rather than turning into a single long column. */
  .hero-inner {
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    grid-template-rows: auto auto auto;
    column-gap: clamp(1rem, 2.5vw, 1.75rem);
  }
  .hero-lockup { grid-column: 1 / -1; grid-row: 1; }
  .hero-mark-space {
    grid-column: 1 / -1;
    grid-row: 2;
    height: clamp(170px, 26vh, 300px);
  }
  .hero-rail--stats { grid-column: 1; grid-row: 3; justify-self: stretch; }
  .hero-rail--actions { grid-column: 2; grid-row: 3; justify-self: stretch; }

  .services-stage { flex-direction: column; align-items: flex-start; justify-content: center; gap: 1.5rem; }
  .service-index { order: -1; }
  .service-panels { width: 100%; }
  .products-scene .product-panel:nth-child(2),
  .products-scene .product-panel:nth-child(3) { justify-self: start; }
}

/* ---- Phone ---- */
@media (max-width: 768px) {
  /* One column: mark, then figures, then actions. */
  .hero-inner {
    grid-template-columns: minmax(0, 1fr);
    padding-top: calc(var(--header-height) + 0.75rem);
    row-gap: clamp(1rem, 2.5vh, 1.75rem);
  }
  .hero-lockup,
  .hero-mark-space,
  .hero-rail--stats,
  .hero-rail--actions { grid-column: 1; }
  .hero-lockup { grid-row: 1; }
  .hero-mark-space { grid-row: 2; height: clamp(150px, 23vh, 250px); }
  .hero-rail--stats { grid-row: 3; }
  .hero-rail--actions { grid-row: 4; }
  .hero-stat, .hero-action { padding: 0.95rem 1.1rem; }

  .about-panels { grid-template-columns: 1fr; }
  .footer-grid { grid-template-columns: 1fr; }
  .footer-bottom { flex-direction: column; text-align: center; }

  .reviews-stack { grid-template-columns: 1fr; }

  p, .cta-desc, .footer-blurb,
  .service-panel__body, .product-panel__body { max-width: 100%; }

  .scroll-cue { display: none; }
}

/* ---- Small phone ---- */
@media (max-width: 560px) {
  .brand-logo__word { display: none; }
  .hero-stat, .hero-action { gap: 0.7rem; padding: 0.85rem 1rem; }
  .hero-stat { grid-template-columns: minmax(2.8rem, auto) 1fr; }

  .services-layout,
  .products-layout { padding-top: calc(var(--header-height) + 1.5rem); }

  .service-panel,
  .product-panel,
  .review-card,
  .glass-panel { padding: 1.35rem; }

  .service-index__current { font-size: 2.2rem; }
}

/* ---- Short landscape ---- */
@media (max-height: 560px) and (orientation: landscape) {
  .hero { min-height: auto; padding-top: calc(var(--header-height) + 2rem); }
  .services-scene, .products-scene { height: 100svh; }
  .services-layout, .products-layout { height: 100svh; overflow-y: auto; }
  .scroll-cue { display: none; }
}

/* --------------------------------------------------------------------------
   16. Reduced motion & no-world fallbacks
   --------------------------------------------------------------------------
   Without the pinned choreography, the stacked panels have to become an
   ordinary readable list — otherwise five of six services would be invisible.
   -------------------------------------------------------------------------- */
@media (prefers-reduced-motion: reduce) {
  /* The drawer still opens — it just arrives rather than slides. */
  .nav-panel { transition: none; }
  .nav-menu li,
  .nav-panel__foot > * {
    opacity: 1;
    transform: none;
    transition: none;
    transition-delay: 0s !important;
  }
  .nav-scrim { transition: none; }

  .services-scene,
  .products-scene,
  .services-layout,
  .products-layout {
    position: static;
    height: auto;
    display: block;
    overflow: visible;
  }

  .services, .products {
    height: auto;
    padding-block: var(--section-padding-y);
  }

  .service-panels,
  .product-panels {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
    gap: 1.5rem;
    perspective: none;
  }

  .service-panel,
  .product-panel {
    grid-area: auto;
    width: auto;
    opacity: 1;
    visibility: visible;
    transform: none;
    pointer-events: auto;
  }

  .service-index,
  .service-progress,
  .scroll-cue,
  .cursor { display: none; }

  .loader { display: none; }

  .loader__mark,
  .scroll-cue__line::after { animation: none; }
}
