/* ==========================================================================
   KLACK — premium instrument brand system
   Black ground, one violet accent, one grotesk, one mono. Nothing decorative
   exists unless it carries information or depth.
   ========================================================================== */

:root {
  /* ground ------------------------------------------------------------- */
  --ink-000: #030304;
  --ink-050: #050505;
  --ink-100: #08080a;
  --ink-150: #0b0b0d;
  --ink-200: #101013;

  /* ink ---------------------------------------------------------------- */
  --fg:      #f5f5f5;
  --fg-mid:  #8a8a8a;
  --fg-low:  #555559;

  /* the single accent -------------------------------------------------- */
  --violet:     #7a3bff;
  --violet-hi:  #a37bff;

  --line:      rgba(255, 255, 255, 0.09);
  --line-soft: rgba(255, 255, 255, 0.05);

  /* rhythm ------------------------------------------------------------- */
  --gutter: clamp(20px, 4.6vw, 76px);
  --sec-y:  clamp(120px, 17vh, 220px);

  /* one easing for the entire site */
  --ease: cubic-bezier(0.16, 1, 0.3, 1);
}

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

html {
  background: var(--ink-050);
  scroll-behavior: smooth;
  -webkit-text-size-adjust: 100%;
}

body {
  margin: 0;
  background: var(--ink-050);
  color: var(--fg);
  font-family: "Archivo", "Helvetica Neue", Arial, sans-serif;
  font-synthesis-weight: none;
  font-size: 16px;
  line-height: 1.5;
  overflow-x: clip;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

img { display: block; max-width: 100%; height: auto; }
h1, h2, h3, h4, p, dl, dd, figure, ol, ul { margin: 0; }
ol, ul { padding: 0; list-style: none; }
a { color: inherit; text-decoration: none; }
button { font: inherit; color: inherit; background: none; border: 0; padding: 0; cursor: pointer; }

::selection { background: var(--violet); color: #fff; }

:focus-visible {
  outline: 1px solid var(--violet-hi);
  outline-offset: 4px;
}

.skip {
  position: absolute;
  left: -9999px;
  width: 1px;
  height: 1px;
  overflow: hidden;
}
.skip:focus {
  left: var(--gutter);
  top: 14px;
  z-index: 200;
  width: auto;
  height: auto;
  padding: 10px 16px;
  background: var(--ink-200);
  font-size: 11px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
}

/* ==========================================================================
   Type primitives
   ========================================================================== */

/* tiny editorial label — the site's connective tissue */
.eyebrow {
  font-family: "JetBrains Mono", ui-monospace, monospace;
  font-size: clamp(9px, 0.72vw, 11px);
  font-weight: 400;
  letter-spacing: 0.32em;
  text-transform: uppercase;
  color: var(--fg-mid);
}

/* section display type — wide, heavy, architectural */
.display {
  font-size: clamp(46px, 8.4vw, 148px);
  font-weight: 800;
  font-stretch: 108%;
  line-height: 0.9;
  letter-spacing: -0.035em;
  text-transform: uppercase;
}
.display span { display: block; }
.display--tight { font-size: clamp(40px, 6.4vw, 108px); }

.lede {
  max-width: 34ch;
  font-size: clamp(15px, 1.15vw, 19px);
  line-height: 1.55;
  color: #b6b6ba;
  text-wrap: pretty;
}

/* technical data pairs */
.spec {
  display: grid;
  gap: 1px;
  background: var(--line-soft);
  border-block: 1px solid var(--line-soft);
}
.spec > div {
  display: flex;
  justify-content: space-between;
  gap: 24px;
  padding: 13px 0;
  background: var(--ink-050);
  font-family: "JetBrains Mono", ui-monospace, monospace;
  font-size: 11px;
  letter-spacing: 0.08em;
}
.spec dt { color: var(--fg-low); text-transform: uppercase; letter-spacing: 0.2em; }
.spec dd { color: var(--fg); }

/* ==========================================================================
   Navigation — floats over the hero, no chrome of its own
   ========================================================================== */

.nav {
  position: fixed;
  inset: 0 0 auto;
  z-index: 100;
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: center;
  padding: clamp(18px, 2.4vh, 30px) var(--gutter);
  mix-blend-mode: normal;
  transition: transform 800ms var(--ease), opacity 800ms var(--ease);
}
.nav::before {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(to bottom, rgba(3, 3, 4, 0.72), transparent);
  opacity: 0;
  transition: opacity 700ms var(--ease);
  pointer-events: none;
}
.nav.is-stuck::before { opacity: 1; }
.nav.is-hidden { transform: translate3d(0, -110%, 0); }

.nav__mark { display: block; width: fit-content; }
.nav__mark img {
  height: clamp(26px, 2.5vw, 34px);
  width: auto;
  transition: filter 500ms var(--ease);
}
.nav__mark:hover img { filter: drop-shadow(0 0 14px rgba(122, 59, 255, 0.55)); }

.nav__links {
  display: flex;
  gap: clamp(26px, 3.4vw, 56px);
  justify-self: center;
}
.nav__links a,
.nav__cart {
  position: relative;
  font-size: 11px;
  font-weight: 500;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: rgba(245, 245, 245, 0.72);
  transition: color 460ms var(--ease);
  white-space: nowrap;
}
.nav__links a::after {
  content: "";
  position: absolute;
  left: 0;
  bottom: -7px;
  width: 100%;
  height: 1px;
  background: currentColor;
  transform: scaleX(0);
  transform-origin: left;
  transition: transform 620ms var(--ease);
}
.nav__links a:hover { color: var(--fg); }
.nav__links a:hover::after { transform: scaleX(1); }

.nav__side {
  display: flex;
  align-items: center;
  gap: clamp(16px, 1.6vw, 26px);
  justify-self: end;
}
.nav__cart:hover { color: var(--violet-hi); }
.nav__cart span { color: var(--fg-low); transition: color 460ms var(--ease); }
.nav__cart:hover span { color: var(--violet); }

/* the circular control — toggles keystroke sound */
.dial {
  position: relative;
  display: grid;
  place-items: center;
  width: 34px;
  height: 34px;
  border: 1px solid var(--line);
  border-radius: 50%;
  transition: border-color 500ms var(--ease);
}
.dial__dot {
  width: 4px;
  height: 4px;
  border-radius: 50%;
  background: var(--fg-mid);
  transition: background 500ms var(--ease), box-shadow 500ms var(--ease);
}
.dial__ring {
  position: absolute;
  inset: -1px;
  border: 1px solid var(--violet);
  border-radius: 50%;
  opacity: 0;
  transform: scale(0.7);
  transition: opacity 700ms var(--ease), transform 700ms var(--ease);
}
.dial:hover { border-color: rgba(255, 255, 255, 0.22); }
.dial[aria-pressed="true"] { border-color: rgba(122, 59, 255, 0.4); }
.dial[aria-pressed="true"] .dial__dot {
  background: var(--violet-hi);
  box-shadow: 0 0 10px 1px rgba(122, 59, 255, 0.8);
}
.dial[aria-pressed="true"] .dial__ring { opacity: 1; transform: scale(1); }

.nav__menu {
  display: none;
  font-size: 11px;
  font-weight: 500;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: rgba(245, 245, 245, 0.72);
}

.drawer {
  position: fixed;
  inset: 0;
  z-index: 99;
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 6px;
  padding: 0 var(--gutter);
  background: rgba(3, 3, 4, 0.96);
  opacity: 0;
  transition: opacity 620ms var(--ease);
}
.drawer[hidden] { display: none; }
.drawer.is-open { opacity: 1; }
.drawer a {
  font-size: clamp(34px, 11vw, 62px);
  font-weight: 800;
  font-stretch: 108%;
  letter-spacing: -0.03em;
  line-height: 1.14;
  text-transform: uppercase;
  opacity: 0;
  transform: translate3d(0, 22px, 0);
  transition: opacity 760ms var(--ease) var(--d, 0ms), transform 760ms var(--ease) var(--d, 0ms);
}
.drawer.is-open a { opacity: 1; transform: none; }

/* ==========================================================================
   HERO — six depth planes driven from one scroll value
   ========================================================================== */

.hero {
  position: relative;
  height: 100svh;
  min-height: 600px;
  overflow: hidden;
  isolation: isolate;
  background: var(--ink-050);
}

/* the stage owns the perspective so planes can be dollied, not just slid */
.hero__stage {
  position: absolute;
  inset: 0;
  perspective: 1400px;
  perspective-origin: 50% 62%;
  transform-style: preserve-3d;
}

.plane {
  position: absolute;
  inset: 0;
  will-change: transform;
  transform: translate3d(0, 0, 0);
  /* the loop writes rotateX/rotateY here — without this the rotation flattens
     against the stage's perspective and reads as a skew */
  transform-style: preserve-3d;
  backface-visibility: hidden;
}

/*
  Two planes only. The hero artwork is the supplied render, unaltered — no
  cutout, no feather, no vignette, no synthetic glow behind it. Everything you
  see in the frame other than the type is pixels from the file, so the plate
  keeps its own edges and its own light.
*/

/* --- z1 · the architectural wordmark -------------------------------------- */
/* Letters are distributed edge to edge rather than tracked by hand, so the
   word spans the frame at every viewport width without ever overflowing. */
.plane--type { z-index: 1; }
.wordmark {
  position: absolute;
  top: 15svh;
  left: 0;
  right: 0;
  display: flex;
  justify-content: space-between;
  margin: 0;
  padding-inline: clamp(6px, 1.4vw, 26px);
  /* Size and width axis are solved together: the five letters have to almost
     fill the measure on their own, so space-between is left distributing ~20px
     rather than a hundred. That is what makes KLACK read as one oversized word
     instead of five spaced letters. */
  font-size: min(25vw, 40svh);
  font-weight: 900;
  font-stretch: 95%;
  line-height: 0.74;
  letter-spacing: 0;
  color: #fff;
  white-space: nowrap;
  user-select: none;
}
.wordmark span { display: block; }

/* --- z2 · the product ------------------------------------------------------ */
.plane--product {
  z-index: 2;
  /* the dolly pivots at the foot of the frame so the scroll lift reads as the
     camera rising past the object, not as the object inflating */
  transform-origin: 50% 100%;
}
/*
  Width is capped against the viewport height as well as its width so the
  render's own bottom edge always lands on the foot of the frame — the plate is
  never scaled past its natural size and never cropped.
*/
.plane--product img {
  position: absolute;
  left: 50%;
  /*
    The supplied render carries its own alpha — the keyboard and plinth are cut
    out in the artwork — so the type is occluded by the chassis silhouette
    itself, not by a rectangle. Size and offset are therefore set from the
    subject: the chassis corner lands high in the letters and the plinth's foot
    lands just above the caption row.
  */
  top: 16.5svh;
  width: min(88vw, 126svh);
  max-width: none;
  transform: translateX(-50%);
}

/* --- hero interface -------------------------------------------------------- */
/* Grouped so the whole caption layer can fade out on one value as the scene
   lifts away, without fighting each element's own entrance animation. */
.hero__ui {
  position: absolute;
  inset: 0;
  z-index: 6;
  pointer-events: none;
}
.hero__ui > * { pointer-events: auto; }

.hero__label {
  position: absolute;
  left: var(--gutter);
  top: clamp(84px, 10.5svh, 128px);
  display: flex;
  align-items: center;
  gap: 20px;
  font-size: clamp(10px, 0.8vw, 12px);
  font-weight: 500;
  letter-spacing: 0.42em;
  text-transform: uppercase;
  color: #ededed;
}
.hero__label i {
  display: block;
  width: clamp(28px, 4vw, 58px);
  height: 1px;
  background: linear-gradient(to right, transparent, var(--violet));
}

.explore {
  position: absolute;
  left: var(--gutter);
  bottom: clamp(56px, 10svh, 108px);
  display: grid;
  grid-template-columns: auto auto;
  align-items: center;
  gap: 0 34px;
  padding-bottom: 16px;
}
.explore__text {
  font-size: clamp(11px, 0.9vw, 13px);
  font-weight: 500;
  letter-spacing: 0.34em;
  text-transform: uppercase;
  color: #e2e2e4;
  transition: color 560ms var(--ease);
}
.explore__arrow {
  color: var(--violet-hi);
  transition: transform 620ms var(--ease);
}
.explore__rule {
  grid-column: 1 / -1;
  height: 1px;
  margin-top: 16px;
  background: rgba(255, 255, 255, 0.22);
  transform-origin: left;
  transition: transform 700ms var(--ease), background 700ms var(--ease);
}
.explore:hover .explore__text { color: #fff; }
.explore:hover .explore__arrow { transform: translate3d(7px, 0, 0); }
.explore:hover .explore__rule { transform: scaleX(1.12); background: var(--violet); }

.scroll-cue {
  position: absolute;
  right: var(--gutter);
  bottom: clamp(40px, 7svh, 76px);
  display: grid;
  justify-items: center;
  gap: 18px;
  font-family: "JetBrains Mono", ui-monospace, monospace;
  font-size: 9px;
  letter-spacing: 0.34em;
  text-transform: uppercase;
  color: var(--fg-mid);
}
.scroll-cue i {
  display: block;
  width: 1px;
  height: clamp(34px, 6vh, 58px);
  background: linear-gradient(to bottom, transparent, rgba(255, 255, 255, 0.42));
  overflow: hidden;
}
.scroll-cue i::after {
  content: "";
  display: block;
  width: 1px;
  height: 40%;
  background: var(--violet-hi);
  animation: cue 2600ms var(--ease) infinite;
}
@keyframes cue {
  0%   { transform: translateY(-100%); }
  60%  { transform: translateY(250%); }
  100% { transform: translateY(250%); }
}

/* ==========================================================================
   Sections — asymmetric editorial grids, no cards
   ========================================================================== */

.sec {
  position: relative;
  padding: var(--sec-y) var(--gutter);
}

/* --- second hero: built to perform ------------------------------------------ */
/*
  The only motion here is the camera. The plate is wider than the frame that
  clips it and js/main.js slides it on scroll, so the view travels left to
  right across the product. The type column carries no transform at all — that
  is what keeps it fixed and sharp while the keyboard moves behind it.
*/
.sec--perform {
  display: grid;
  grid-template-columns: minmax(0, 1.06fr) minmax(0, 0.94fr);
  align-items: center;
  column-gap: clamp(24px, 3vw, 56px);
  /* no left padding: the product bleeds off the edge of the page */
  padding: clamp(90px, 13vh, 170px) var(--gutter) clamp(90px, 13vh, 170px) 0;
  overflow: hidden;
}

.perform__frame {
  position: relative;
  aspect-ratio: 1.1;
  overflow: hidden;
}
/*
  The plate fills the frame vertically and runs far wider than it, so the
  surplus width is the room the camera travels through and the pan can never
  expose an edge. Anchored so the plate's own right-hand edge — the anodised
  rail, with the artwork's transparent margin beyond it — stays inside the
  frame throughout, leaving the page's left edge as the only boundary the
  travel ever reaches.
*/
.perform__frame img {
  position: absolute;
  top: 50%;
  left: 14.5%;
  width: auto;
  height: 100%;
  max-width: none;
  transform: translate3d(-50%, -50%, 0);
  will-change: transform;
}

.perform__body {
  position: relative;
  z-index: 2;
  display: grid;
  justify-items: start;
}

.perform__title {
  font-size: clamp(40px, 5.6vw, 94px);
  font-weight: 900;
  font-stretch: 104%;
  line-height: 0.9;
  letter-spacing: -0.035em;
  text-transform: uppercase;
}
.perform__title i {
  display: inline-block;
  width: 0.17em;
  height: 0.17em;
  margin-left: 0.06em;
  background: var(--violet);
  vertical-align: baseline;
}

.perform__rule {
  width: 54px;
  height: 1px;
  margin: clamp(22px, 3vh, 34px) 0 0;
  background: var(--violet);
}

.perform__copy {
  max-width: 33ch;
  margin-top: clamp(20px, 2.6vh, 30px);
  font-size: clamp(14px, 1.02vw, 16px);
  line-height: 1.9;
  color: #9a9aa2;
  text-wrap: pretty;
}

.perform__specs {
  width: 100%;
  margin-top: clamp(34px, 5vh, 62px);
}

.pspec {
  position: relative;
  display: grid;
  grid-template-columns: clamp(30px, 2.6vw, 40px) minmax(0, 1fr);
  align-items: center;
  column-gap: clamp(16px, 1.6vw, 26px);
  row-gap: 5px;
  padding: clamp(15px, 2vh, 22px) 0;
  border-bottom: 1px solid rgba(255, 255, 255, 0.08);
}

/* the callout stroke: drawn from the marker outward toward the product */
.pspec__line {
  position: absolute;
  right: 100%;
  top: 50%;
  width: clamp(150px, 15vw, 240px);
  height: clamp(88px, 8.8vw, 140px);
  /* the path's origin sits at 20 of 140, so lift by a seventh to land it on
     the row axis at every scale */
  margin-top: calc(clamp(88px, 8.8vw, 140px) / -7);
  overflow: visible;
  pointer-events: none;
}
.pspec__line path {
  stroke: rgba(163, 123, 255, 0.5);
  stroke-width: 1;
  vector-effect: non-scaling-stroke;
  stroke-dasharray: 1;
  stroke-dashoffset: 1;
  transition: stroke-dashoffset 1800ms var(--ease) var(--d, 0ms);
}
.pspec.is-in .pspec__line path { stroke-dashoffset: 0; }

.pspec__dot {
  position: absolute;
  right: 100%;
  top: 50%;
  width: 7px;
  height: 7px;
  margin: -3.5px -3.5px 0 0;
  background: var(--violet);
  /* the permitted lighting drift: opacity only, never a brighter violet */
  animation: marker-breathe 9s ease-in-out infinite;
}
.pspec:nth-child(2) .pspec__dot { animation-delay: -2.2s; }
.pspec:nth-child(3) .pspec__dot { animation-delay: -4.5s; }
.pspec:nth-child(4) .pspec__dot { animation-delay: -6.7s; }
@keyframes marker-breathe {
  0%, 100% { opacity: 0.72; }
  50%      { opacity: 1; }
}

.pspec__icon {
  grid-row: 1 / span 2;
  width: 100%;
  height: auto;
  stroke: rgba(255, 255, 255, 0.55);
  stroke-width: 1.1;
  stroke-linecap: round;
  stroke-linejoin: round;
}
.pspec__label {
  font-family: "JetBrains Mono", ui-monospace, monospace;
  font-size: clamp(12px, 0.95vw, 14px);
  letter-spacing: 0.17em;
  text-transform: uppercase;
  color: var(--fg);
}
.pspec__sub {
  font-family: "JetBrains Mono", ui-monospace, monospace;
  font-size: clamp(10px, 0.76vw, 11px);
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: #6f6f78;
}

/* --- 04 keycaps ------------------------------------------------------------ */
/*
  This section is budgeted to land inside one screen: padding + heading + film
  + spec row all have to fit 100svh, so the shared .sec padding is trimmed here
  rather than globally.
*/
/* ==========================================================================
   04 · Keycaps — two-column editorial

   Type left, film right, spec row spanning the foot. The section carries no
   inline padding so column 2 runs clean to the viewport edge; the left column
   pays for its own gutter.
   ========================================================================== */

.sec--caps {
  display: grid;
  grid-template-columns: minmax(0, 0.82fr) minmax(0, 1.18fr);
  align-items: center;
  column-gap: clamp(20px, 3.5vw, 64px);
  padding-inline: 0;
  padding-block: clamp(48px, 8vh, 104px);
}

.caps__head {
  grid-column: 1;
  display: grid;
  gap: clamp(14px, 2vh, 26px);
  padding-left: var(--gutter);
  align-content: center;
}

.caps__title {
  /* capped on height too, so a 720px laptop does not lose the spec row */
  font-size: min(clamp(40px, 6.4vw, 108px), 10svh);
}

.caps__lede {
  max-width: 38ch;
  font-size: clamp(14px, 1.05vw, 17px);
  line-height: 1.6;
  color: var(--fg-mid);
  text-wrap: pretty;
}

/*
  The film fills its column and reaches the right edge of the viewport. No
  card, radius, border, shadow, glow or overlay — and height:auto keeps the
  source proportions, so it is never cropped.
*/
.caps__film {
  grid-column: 2;
  width: 100%;
}
.caps__film video {
  display: block;
  width: 100%;
  height: auto;
  aspect-ratio: 1600 / 836;
  border: 0;
  outline: 0;
  background: transparent;
}

.spec--row {
  grid-column: 1 / -1;
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 0 1px;
  margin: clamp(30px, 5vh, 64px) var(--gutter) 0;
}
.spec--row > div {
  flex-direction: column;
  justify-content: flex-start;
  gap: 10px;
  padding: 18px 0;
}

/* --------------------------------------------------------------------------
   Entrance

   Opt-in and self-cancelling. The default styles below are the VISIBLE ones —
   nothing in this section is ever declared opacity:0 at rest. main.js adds
   .caps-anim on load and removes it once the longest animation has finished,
   so if the animation never runs at all (blocked, throttled, background tab,
   JS off) the content is simply there. There is no state in which the headline
   can be left invisible, and nothing waits for a scroll.
   -------------------------------------------------------------------------- */

@keyframes caps-rise {
  from { opacity: 0; transform: translate3d(0, 22px, 0); }
  to   { opacity: 1; transform: none; }
}

@keyframes caps-rule {
  from { background-size: 0% 100%; }
  to   { background-size: 100% 100%; }
}

/* two lines, one gesture — never per letter */
.caps-anim .caps__title span { animation: caps-rise 1100ms var(--ease) both; }
.caps-anim .caps__title span:nth-child(1) { animation-delay: 120ms; }
.caps-anim .caps__title span:nth-child(2) { animation-delay: 290ms; }

.caps-anim .caps__lede { animation: caps-rise 1100ms var(--ease) 620ms both; }

/* the film lifts with the headline rather than behind it */
.caps-anim .caps__film { animation: caps-rise 1300ms var(--ease) 220ms both; }

/*
  Cells never fade — each one paints the page background, and that is what
  masks the divider colour behind it. Only their contents animate.
*/
.caps-anim .spec--row dt,
.caps-anim .spec--row dd { animation: caps-rise 900ms var(--ease) both; }
.caps-anim .spec--row > div:nth-child(1) dt { animation-delay: 800ms; }
.caps-anim .spec--row > div:nth-child(1) dd { animation-delay: 890ms; }
.caps-anim .spec--row > div:nth-child(2) dt { animation-delay: 940ms; }
.caps-anim .spec--row > div:nth-child(2) dd { animation-delay: 1030ms; }
.caps-anim .spec--row > div:nth-child(3) dt { animation-delay: 1080ms; }
.caps-anim .spec--row > div:nth-child(3) dd { animation-delay: 1170ms; }
.caps-anim .spec--row > div:nth-child(4) dt { animation-delay: 1220ms; }
.caps-anim .spec--row > div:nth-child(4) dd { animation-delay: 1310ms; }

/*
  Every rule in this row — both borders and the three column gaps — is one
  background on the <dl> showing through the opaque cells, so animating that
  single background's width wipes all of them left to right together. At rest
  background-size is auto, i.e. the rules are fully drawn.
*/
.sec--caps .spec--row {
  background-color: transparent;
  border-block-color: transparent;
  background-image: linear-gradient(var(--line-soft), var(--line-soft));
  background-origin: border-box;
  background-repeat: no-repeat;
}
.caps-anim .sec--caps .spec--row { animation: caps-rule 1400ms var(--ease) 760ms both; }

/* --- 05 material ----------------------------------------------------------- */
.sec--material {
  position: relative;
  min-height: clamp(560px, 82vh, 880px);
  display: flex;
  align-items: flex-end;
  padding-block: clamp(90px, 12vh, 150px);
  overflow: hidden;
}
.material__bg {
  position: absolute;
  inset: -12% 0;
  z-index: 0;
}
.material__bg img {
  width: 118%;
  height: 100%;
  max-width: none;
  margin-left: -9%;
  object-fit: cover;
  object-position: 50% 40%;
  opacity: 0.8;
  will-change: transform;
}
.material__bg::after {
  content: "";
  position: absolute;
  inset: 0;
  background:
    linear-gradient(to top, var(--ink-050) 4%, rgba(5, 5, 5, 0.35) 46%, var(--ink-050) 98%),
    linear-gradient(to right, rgba(5, 5, 5, 0.88), rgba(5, 5, 5, 0.1) 62%);
}
.ghost {
  position: absolute;
  z-index: 1;
  left: var(--gutter);
  top: clamp(60px, 9vh, 120px);
  margin: 0;
  font-size: clamp(64px, 15vw, 240px);
  font-weight: 900;
  font-stretch: 112%;
  line-height: 0.8;
  letter-spacing: -0.04em;
  text-transform: uppercase;
  color: transparent;
  -webkit-text-stroke: 1px rgba(255, 255, 255, 0.13);
  pointer-events: none;
}
.material__body {
  position: relative;
  z-index: 2;
  display: grid;
  gap: clamp(24px, 3vh, 40px);
  max-width: 640px;
}

/* --- 06 accessories -------------------------------------------------------- */
/*
  Two halves and nothing else: the list is the control on the left, one plate
  floats free on the right. No frame, no card, no border — the artwork carries
  its own alpha and sits straight on the page ground.
*/
.sec--acc {
  display: grid;
  grid-template-columns: minmax(0, 0.9fr) minmax(0, 1.1fr);
  align-items: center;
  align-content: center;
  column-gap: clamp(28px, 4.5vw, 86px);
  min-height: 100svh;
  padding-block: clamp(90px, 12vh, 150px);
}

.acc__body { max-width: 820px; }

.acc__title {
  font-size: clamp(44px, 6.4vw, 132px);
  font-weight: 900;
  font-stretch: 104%;
  line-height: 0.88;
  letter-spacing: -0.038em;
  text-transform: uppercase;
}
.acc__title span { display: block; }

.acc__copy {
  margin-top: clamp(28px, 4vh, 48px);
  font-size: clamp(14px, 1.02vw, 16px);
  line-height: 1.65;
  color: #9a9aa2;
  text-wrap: pretty;
}

.acc__list { margin-top: clamp(52px, 8vh, 96px); }

.acc-row {
  position: relative;
  border-bottom: 1px solid rgba(255, 255, 255, 0.09);
  transition: border-color 600ms var(--ease);
}
/* the active marker: a hairline on the leading edge, wiped in from the top */
.acc-row::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0;
  bottom: 0;
  width: 1px;
  background: var(--violet);
  transform: scaleY(0);
  transform-origin: top;
  transition: transform 620ms var(--ease);
}
.acc-row.is-active::before { transform: scaleY(1); }
.acc-row.is-active { border-bottom-color: rgba(122, 59, 255, 0.6); }

.acc-row button {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto auto;
  align-items: center;
  gap: 0 clamp(14px, 1.6vw, 26px);
  width: 100%;
  padding: clamp(16px, 2.2vh, 24px) 0 clamp(16px, 2.2vh, 24px) clamp(18px, 1.6vw, 26px);
  text-align: left;
  transition: padding-left 700ms var(--ease);
}
.acc-row.is-active button { padding-left: clamp(24px, 2.2vw, 34px); }

.acc-row__dot {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: #4b4b54;
  transition: background 600ms var(--ease), box-shadow 600ms var(--ease);
}
.acc-row.is-active .acc-row__dot {
  background: var(--violet);
  box-shadow: 0 0 12px 1px rgba(122, 59, 255, 0.55);
}

.acc-row__name {
  font-size: clamp(16px, 1.5vw, 22px);
  font-weight: 500;
  letter-spacing: -0.005em;
  color: #c6c6cc;
  transition: color 500ms var(--ease);
}
.acc-row.is-active .acc-row__name { color: var(--fg); }

.acc-row__price {
  font-family: "JetBrains Mono", ui-monospace, monospace;
  font-size: clamp(12px, 1vw, 14px);
  letter-spacing: 0.04em;
  color: #8e8e97;
  transition: color 500ms var(--ease);
}
.acc-row.is-active .acc-row__price { color: var(--fg); }

.acc-row__arrow {
  color: #5c5c66;
  transition: color 500ms var(--ease), transform 620ms var(--ease);
}
.acc-row.is-active .acc-row__arrow {
  color: var(--violet-hi);
  transform: translate3d(6px, 0, 0);
}

/* --- the floating plate ---------------------------------------------------- */
.acc__stage {
  position: relative;
  aspect-ratio: 1536 / 1024;
  width: 100%;
}
.acc__shot {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: contain;
  opacity: 0;
  transform: scale(0.96);
  transition: opacity 700ms var(--ease), transform 700ms var(--ease);
  pointer-events: none;
}
.acc__shot.is-on {
  opacity: 1;
  transform: none;
}

/* --- 07 statement ---------------------------------------------------------- */
.sec--say {
  display: grid;
  gap: clamp(48px, 8vh, 96px);
  padding-block: clamp(180px, 28vh, 340px);
  text-align: center;
  justify-items: center;
}
.say {
  position: relative;
  font-size: clamp(32px, 5.4vw, 92px);
  font-weight: 700;
  font-stretch: 104%;
  line-height: 1.06;
  letter-spacing: -0.038em;
  text-transform: uppercase;
  max-width: 16ch;
}
.say i {
  display: inline-block;
  width: 0.14em;
  height: 0.14em;
  margin-left: 0.16em;
  border-radius: 50%;
  background: var(--violet);
  vertical-align: baseline;
  box-shadow: 0 0 26px 4px rgba(122, 59, 255, 0.6);
}
.say__foot {
  font-family: "JetBrains Mono", ui-monospace, monospace;
  font-size: 10px;
  letter-spacing: 0.34em;
  text-transform: uppercase;
  color: var(--fg-low);
}

/* ==========================================================================
   Footer
   ========================================================================== */

.foot {
  position: relative;
  padding: clamp(70px, 10vh, 120px) var(--gutter) 0;
  border-top: 1px solid var(--line-soft);
  overflow: hidden;
}
.foot__top {
  display: grid;
  gap: 26px;
  max-width: 520px;
  margin-bottom: clamp(70px, 10vh, 120px);
}
.join {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  align-items: center;
  gap: 20px;
  border-bottom: 1px solid var(--line);
  transition: border-color 600ms var(--ease);
}
.join:focus-within { border-color: rgba(122, 59, 255, 0.75); }
.join input {
  padding: 14px 0;
  background: none;
  border: 0;
  color: var(--fg);
  font-family: inherit;
  font-size: 15px;
  letter-spacing: 0.01em;
}
.join input::placeholder { color: var(--fg-low); }
.join input:focus { outline: none; }
.join button {
  display: flex;
  align-items: center;
  gap: 12px;
  font-size: 11px;
  font-weight: 500;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--fg-mid);
  transition: color 500ms var(--ease);
}
.join button svg { transition: transform 620ms var(--ease); }
.join button:hover { color: var(--fg); }
.join button:hover svg { transform: translate3d(6px, 0, 0); }
.join__status {
  min-height: 16px;
  font-family: "JetBrains Mono", ui-monospace, monospace;
  font-size: 10px;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--violet-hi);
  opacity: 0;
  transform: translate3d(0, 6px, 0);
  transition: opacity 700ms var(--ease), transform 700ms var(--ease);
}
.join__status.is-on { opacity: 1; transform: none; }

.foot__cols {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 40px;
  max-width: 720px;
  margin-bottom: clamp(60px, 9vh, 110px);
}
.foot__cols div { display: grid; gap: 12px; align-content: start; }
.foot__cols h4 {
  margin-bottom: 6px;
  font-family: "JetBrains Mono", ui-monospace, monospace;
  font-size: 9px;
  font-weight: 400;
  letter-spacing: 0.3em;
  text-transform: uppercase;
  color: var(--fg-low);
}
.foot__cols a {
  width: fit-content;
  font-size: 13px;
  color: var(--fg-mid);
  transition: color 500ms var(--ease);
}
.foot__cols a:hover { color: var(--fg); }

/* the wordmark returns at the very bottom, cropped by the page edge */
.foot__mark {
  margin: 0 calc(var(--gutter) * -1) -0.22em;
  font-size: 25vw;
  font-weight: 900;
  font-stretch: 112%;
  line-height: 0.74;
  letter-spacing: 0.01em;
  text-align: center;
  color: transparent;
  background: linear-gradient(to bottom, rgba(255, 255, 255, 0.115), rgba(255, 255, 255, 0.008) 78%);
  -webkit-background-clip: text;
  background-clip: text;
  pointer-events: none;
  user-select: none;
}
.foot__legal {
  display: flex;
  justify-content: space-between;
  gap: 20px;
  padding: 26px 0;
  border-top: 1px solid var(--line-soft);
  font-family: "JetBrains Mono", ui-monospace, monospace;
  font-size: 10px;
  letter-spacing: 0.14em;
  color: var(--fg-low);
}

/* ==========================================================================
   Reveal choreography — one easing, 900–1300ms, never bouncy
   ========================================================================== */

.reveal {
  opacity: 0;
  transform: translate3d(0, 30px, 0) scale(0.988);
  filter: blur(6px);
  transition:
    opacity 1150ms var(--ease) var(--d, 0ms),
    transform 1400ms var(--ease) var(--d, 0ms),
    filter 1000ms var(--ease) var(--d, 0ms);
}
/* filter is dropped to `none`, not blur(0), so the compositing layer is
   released once the element has landed */
.reveal.is-in {
  opacity: 1;
  transform: none;
  filter: none;
}

.reveal-film {
  opacity: 0;
  transform: translate3d(0, 54px, 0);
  transition:
    opacity 1250ms var(--ease) var(--d, 0ms),
    transform 1550ms var(--ease) var(--d, 0ms);
}
.reveal-film.is-in { opacity: 1; transform: none; }

/* the wipe lives on the frame, never on the image — the image's transform
   belongs to the parallax loop and the two must not fight over it */
.reveal-img {
  clip-path: inset(0 0 100% 0);
  transform: scale(1.02);
  transition: clip-path 1400ms var(--ease), transform 1600ms var(--ease);
}
.reveal-img.is-in { clip-path: inset(0 0 0 0); transform: none; }

/* ---- first paint: the hero assembles itself back to front ---------------- */
/* Animations are gated behind .is-loading so the scene starts when the
   product render is decoded, not when the stylesheet parses. */
.is-loading .wordmark span,
.is-loading .plane--product img,
.is-loading .plane--atmos,
.is-loading .plane--floor,
.is-loading .hero__label,
.is-loading .explore,
.is-loading .scroll-cue,
.is-loading .nav { opacity: 0; }

body:not(.is-loading) .hero__label,
body:not(.is-loading) .explore,
body:not(.is-loading) .scroll-cue { animation: fade-up 1200ms var(--ease) both; }
body:not(.is-loading) .hero__label { animation-delay: 900ms; }
body:not(.is-loading) .explore     { animation-delay: 1050ms; }
body:not(.is-loading) .scroll-cue  { animation-delay: 1150ms; }

/* opacity only — the bar's transform is owned by the retract-on-scroll state */
body:not(.is-loading) .nav { animation: fade-in 1000ms var(--ease) 250ms both; }

@keyframes fade-up {
  from { opacity: 0; transform: translate3d(0, 14px, 0); }
  to   { opacity: 1; transform: none; }
}

body:not(.is-loading) .wordmark span { animation: letter-in 1400ms var(--ease) both; }
.wordmark span:nth-child(1) { animation-delay: 260ms; }
.wordmark span:nth-child(2) { animation-delay: 340ms; }
.wordmark span:nth-child(3) { animation-delay: 420ms; }
.wordmark span:nth-child(4) { animation-delay: 500ms; }
.wordmark span:nth-child(5) { animation-delay: 580ms; }
@keyframes letter-in {
  from { opacity: 0; transform: translate3d(0, 0.14em, 0); }
  to   { opacity: 1; transform: none; }
}

body:not(.is-loading) .plane--product img { animation: product-in 1700ms var(--ease) 380ms both; }
@keyframes product-in {
  from { opacity: 0; transform: translate3d(-50%, 5.5svh, 0) scale(1.05); }
  to   { opacity: 1; transform: translateX(-50%); }
}

body:not(.is-loading) .plane--atmos,
body:not(.is-loading) .plane--floor { animation: fade-in 1800ms var(--ease) both; }
@keyframes fade-in { from { opacity: 0; } to { opacity: 1; } }

/* ==========================================================================
   Responsive — tablet keeps the drama, mobile gets its own composition
   ========================================================================== */

@media (max-width: 1080px) {
  .sec--acc { grid-template-columns: minmax(0, 1fr); }

  .sec--caps {
    grid-template-columns: minmax(0, 1fr);
    row-gap: clamp(26px, 4.5vh, 52px);
  }
  /* the explicit column placements must be dropped too — leaving the film on
     column 2 conjures an implicit second track, which also makes the spec
     row's 1 / -1 span collapse to a single narrow column */
  .caps__head,
  .caps__film,
  .sec--caps .spec--row { grid-column: 1; }
  .caps__head { padding-inline: var(--gutter); }

  /* stacked: the product takes the full width, the callout strokes have
     nowhere left to travel so they come out entirely */
  .sec--perform {
    grid-template-columns: minmax(0, 1fr);
    row-gap: clamp(36px, 6vh, 64px);
    padding-right: 0;
  }
  .perform__frame { aspect-ratio: 1.45; }
  .perform__frame img { left: 50%; }
  .perform__body { padding-inline: var(--gutter); }
  .pspec__line,
  .pspec__dot { display: none; }


  /* stacked, same hierarchy: plate first, then the heading and the list */
  .sec--acc {
    grid-template-columns: minmax(0, 1fr);
    row-gap: clamp(30px, 5vh, 56px);
    min-height: 0;
  }
  .acc__body { order: 2; max-width: none; }
  .acc__stage { order: 1; margin-inline: calc(var(--gutter) * -0.5); }

}

@media (max-width: 860px) {
  .nav__links { display: none; }
  .nav__menu { display: block; }
  .nav { grid-template-columns: auto 1fr; }
  .nav__side { grid-column: 2; }

  /* The mobile hero is recomposed, not shrunk. The wordmark is set larger
     than the frame and centred, so it crops symmetrically off both edges,
     and the plinth bleeds past the sides with the keyboard still dominant. */
  .hero { height: 100svh; min-height: 560px; }
  .wordmark {
    top: 21svh;
    padding-inline: 0;
    /* narrower axis on a narrow frame, so all five letters still span the
       measure edge to edge instead of overflowing it */
    font-stretch: 80%;
    font-size: min(30vw, 21svh);
    letter-spacing: -0.005em;
  }
  /* On a portrait frame the plate runs wider than the viewport, so its own left
     and right borders fall outside the frame and the plinth reads full bleed. */
  .plane--product img {
    top: 27svh;
    width: min(148vw, 96svh);
  }

  .hero__label {
    top: 15svh;
    letter-spacing: 0.28em;
    gap: 14px;
    font-size: 10px;
  }
  .explore { bottom: 74px; }
  .explore__rule { margin-top: 12px; }
  .scroll-cue { bottom: 74px; gap: 12px; }
  .scroll-cue i { height: 30px; }

  .spec--row { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 0; }
  .spec--row > div { border-bottom: 1px solid var(--line-soft); }
  .foot__cols { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

@media (max-width: 560px) {
  .display { font-size: clamp(40px, 13vw, 68px); }
  .display--tight { font-size: clamp(36px, 11.5vw, 60px); }
  .stack li { grid-template-columns: 42px minmax(0, 1fr); }
  .foot__legal { flex-direction: column; gap: 8px; }
}

/* pointer-only affordances */
@media (hover: none) {
}

/* ==========================================================================
   Reduced motion — the composition stays, the movement goes
   ========================================================================== */

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }

  *,
  *::before,
  *::after {
    animation-duration: 1ms !important;
    animation-delay: 0ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 1ms !important;
    transition-delay: 0ms !important;
  }

  /* filter must be cleared too, or the new soft-focus reveal never resolves
     and the text stays permanently blurred */
  .reveal { opacity: 1; transform: none; filter: none; }
  .reveal-film { opacity: 1; transform: none; }
  /* the keycaps entrance is animation-driven; pin it to its finished state */
  .caps__title span,
  .sec--caps .spec--row dt,
  .sec--caps .spec--row dd,
  .caps__lede,
  .caps__film { animation: none; opacity: 1; transform: none; }
  .sec--caps .spec--row { animation: none; background-size: 100% 100%; }
  .reveal-img { clip-path: none; }
  .reveal-img img { transform: none; }
  .plane { transform: none !important; }
  .scroll-cue i::after { display: none; }
}
