/* ═══════════════════════════════════════════════════════════════════════
   PEBB — STYLE
   Tokens from Figma (Flect-Visuals '26 / Final, 1728 grid). Fluid scale:
   every size is clamp(min, px/17.28 vw, design-px) so desktop widths
   below 1728 keep the exact composition.
   ═══════════════════════════════════════════════════════════════════════ */

:root {
  /* ── color: constants (hero / photo / footer never re-theme) ── */
  --ink:   #111111;
  --paper: #ffffff;
  --mut:   #737373;

  /* ── color: theme layer (day) ── */
  --bg:        #ffffff;
  --fg:        #111111;
  --fg-muted:  #737373;
  --sec1-bg:   #f5f5f5;
  --how-bg:    #565656;
  --how-ctl:   #676767;
  --why-bg:    #ffffff;
  --badge-bg:  #ececec;
  --hairline:  rgba(17, 17, 17, 0.1);
  --toggle-bg:       rgba(255, 255, 255, 0.1);

  /* ── type ── */
  --font-sans:  'PP Neue Montreal', 'Helvetica Neue', Arial, sans-serif;
  --font-serif: 'PP Editorial New', Georgia, serif;

  --fs-display:   clamp(42px, 4.398vw, 76px);
  --fs-display-2: clamp(44px, 5.556vw, 96px);
  --fs-h2:        clamp(34px, 3.704vw, 64px);
  --fs-h3:        clamp(26px, 2.546vw, 44px);
  --fs-h4:        clamp(21px, 1.736vw, 30px);
  --fs-body-lg:   clamp(18px, 1.505vw, 26px);
  --fs-body:      clamp(16px, 1.157vw, 20px);
  --fs-caption:   clamp(13px, 0.926vw, 16px);
  --fs-num:       clamp(24px, 1.852vw, 32px);
  --fs-spec:      clamp(38px, 3.704vw, 64px);
  --fs-btn:       clamp(17px, 1.331vw, 23px);

  /* ── space ── */
  --pad-x:      clamp(24px, 6.944vw, 120px);
  --sec-py:     clamp(72px, 9.259vw, 160px);
  --gap-head:   clamp(44px, 5.556vw, 96px);
  --header-px:  16px;
  --header-py:  16px;

  /* ── controls ── */
  --ctl-h:      clamp(56px, 4.167vw, 72px);
  --toggle-h:   clamp(48px, 3.241vw, 56px);   /* shared by the day/night switch and header CTA */
  --ctl-px:     clamp(24px, 2.083vw, 36px);
  --input-px:   clamp(18px, 1.62vw, 28px);
  --radius-ctl: 12px;

  /* ── motion ── */
  --ease:      cubic-bezier(0.22, 1, 0.36, 1);
  --ease-luxe: cubic-bezier(0.16, 1, 0.22, 1);
  --ease-snap: cubic-bezier(0.32, 0.72, 0, 1);

  --theme-fade: 450ms;
  --muted-opacity: 0.6;
}

:root[data-theme='night'] {
  --bg:        #111111;
  --fg:        #f5f5f5;
  --fg-muted:  #919191;
  --sec1-bg:   #1c1c1c;
  --how-bg:    #232323;
  --how-ctl:   #343434;
  --why-bg:    #111111;
  --badge-bg:  #232323;
  --hairline:  rgba(255, 255, 255, 0.14);
  --toggle-bg:       rgba(255, 255, 255, 0.1);
}

/* ═══════════ FONTS ═══════════ */
@font-face {
  font-family: 'PP Neue Montreal';
  src: url('../assets/fonts/PPNeueMontreal-Regular.woff') format('woff');
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: 'PP Neue Montreal';
  src: url('../assets/fonts/PPNeueMontreal-Medium.woff') format('woff');
  font-weight: 500;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: 'PP Editorial New';
  src: url('../assets/fonts/PPEditorialNew-Regular.woff') format('woff');
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: 'PP Editorial New';
  src: url('../assets/fonts/PPEditorialNew-Ultralight.woff') format('woff');
  font-weight: 200;
  font-style: normal;
  font-display: swap;
}

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

html {
  -webkit-text-size-adjust: 100%;
  overscroll-behavior-y: none;
  /* html carries the page tint so Safari paints its bars to match the theme
     instead of clipping the page with a system-grey toolbar */
  background: var(--bg);
  transition: background-color var(--theme-fade) var(--ease);
  scrollbar-width: none;
}
html::-webkit-scrollbar { width: 0; height: 0; display: none; }


body {
  font-family: var(--font-sans);
  font-weight: 400;
  background: var(--bg);
  color: var(--fg);
  line-height: 1.4;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  overflow-x: clip;
  transition: background-color var(--theme-fade) var(--ease), color var(--theme-fade) var(--ease);
}

a { color: inherit; text-decoration: none; }
img, svg { display: block; max-width: 100%; }
img { height: auto; }
button { font-family: inherit; cursor: pointer; background: none; border: none; color: inherit; }
ul, ol { list-style: none; }
figure { margin: 0; }
/* selection: pure black backing in day, pure white in night */
::selection { background: #111111; color: #ffffff; }
:root[data-theme='night'] ::selection { background: #ffffff; color: #111111; }

:focus-visible {
  outline: 2px solid currentColor;
  outline-offset: 3px;
  border-radius: 4px;
}
/* the button's currentColor is its label (white on ink) — invisible as an
   outline against the page, so ring it with the page ink instead */
.btn:focus-visible, .rail-btn:focus-visible { outline-color: var(--fg); }

.sr-only {
  position: absolute;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
  border: 0;
}

/* ═══════════ TYPE ROLES ═══════════ */
.serif {
  font-family: var(--font-serif);
  font-weight: 400;
  font-style: normal;
}

.display {
  font-size: var(--fs-display);
  font-weight: 500;
  line-height: 1.04;
  letter-spacing: -0.03em;
}
.display-2 {
  font-size: var(--fs-display-2);
  font-weight: 500;
  line-height: 1.04;
  letter-spacing: -0.03em;
}
.h2 {
  font-size: var(--fs-h2);
  font-weight: 500;
  line-height: 1.04;
  letter-spacing: -0.03em;
}
.h3 {
  font-size: var(--fs-h3);
  font-weight: 500;
  line-height: 1.2;
  letter-spacing: -0.025em;
}
.h4 {
  font-size: var(--fs-h4);
  font-weight: 500;
  line-height: 1.2;
  letter-spacing: -0.03em;
}
.body-lg {
  font-size: var(--fs-body-lg);
  font-weight: 500;
  line-height: 1.4;
  letter-spacing: -0.02em;
}
.body {
  font-size: var(--fs-body);
  font-weight: 400;
  line-height: 1.45;
  letter-spacing: -0.01em;
}
/* rests at 60% ink even when combined with .reveal-up (whose .visible state
   would otherwise win the opacity war and push it to 100%) */
.muted-block {
  opacity: var(--muted-opacity);
  --reveal-opacity: var(--muted-opacity);
}

/* ═══════════ HEADINGS ═══════════
   Plain solid ink — no gradient sweep. --sweep-ink lets the dark sections
   (e.g. How) flip the heading to white. */
.sweep { color: var(--sweep-ink, var(--fg)); }

/* ═══════════ BUTTON + LETTER ROLL ═══════════ */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  height: var(--ctl-h);
  padding: 0 var(--ctl-px);
  border-radius: var(--radius-ctl);
  background: var(--ink);
  color: var(--paper);
  font-size: var(--fs-btn);
  font-weight: 500;
  letter-spacing: -0.02em;
  line-height: 1;
  white-space: nowrap;
  flex: 0 0 auto;
  -webkit-tap-highlight-color: transparent;
  transition: background-color var(--theme-fade) var(--ease), color var(--theme-fade) var(--ease);
}
.btn-label { display: inline-flex; line-height: 1; }
.roll-space { display: inline-block; }
.roll-char {
  position: relative;
  display: inline-block;
  overflow: hidden;
  line-height: 1;
  /* room for descenders inside the clip without changing layout height */
  padding-bottom: 0.14em;
  margin-bottom: -0.14em;
}
.roll-char > span {
  display: block;
  transition: transform 0.55s var(--ease-luxe);
  transition-delay: var(--cd, 0ms);
}
.roll-char .r-bot {
  position: absolute;
  inset: 0;
  transform: translateY(110%);
}
.btn:hover .roll-char .r-top,
.rail-btn:hover .roll-char .r-top { transform: translateY(-110%); }
.btn:hover .roll-char .r-bot,
.rail-btn:hover .roll-char .r-bot { transform: translateY(0); }

/* ═══════════ FORM (input ⌇ button, joined by the connector) ═══════════ */
.access-form { display: flex; flex-direction: column; gap: 16px; }
.form-row {
  display: flex;
  align-items: center;
}
.input {
  height: var(--ctl-h);
  width: clamp(240px, 19.676vw, 340px);
  padding: 0 var(--input-px);
  border: 1px solid var(--ink);
  border-radius: var(--radius-ctl);
  background: transparent;
  font-family: inherit;
  font-size: var(--fs-body);
  letter-spacing: -0.02em;
  color: var(--ink);
  transition: box-shadow 0.25s var(--ease), border-color 0.25s var(--ease);
}
.input::placeholder { color: var(--mut); }
.input:focus { outline: none; box-shadow: inset 0 0 0 1px var(--ink); }
.input.is-error { border-color: #c34434; box-shadow: inset 0 0 0 1px #c34434; }
.form-row--fluid .input { flex: 1 1 auto; min-width: 0; width: auto; }
/* hard CSS box — Safari ignores the svg width/height attributes in a flex
   row and stretches the bridge to the control height otherwise */
.form-row .connector {
  flex: 0 0 auto;
  color: var(--ink);
  width: 4px;
  height: 41px;
}
.form-row .connector--mob { display: none; width: 4px; height: 26px; }
.form-note {
  font-size: var(--fs-caption);
  letter-spacing: -0.01em;
  line-height: 1;
  color: var(--mut);
}
.access-form .form-success {
  display: flex;
  align-items: center;
  height: var(--ctl-h);
  font-size: var(--fs-body-lg);
  font-weight: 500;
  letter-spacing: -0.02em;
  color: var(--ink);
}

/* ═══════════ HEADER ═══════════ */
.site-header {
  position: fixed;
  top: 0; left: 0; right: 0;
  z-index: 100;
  display: flex;
  align-items: center;
  justify-content: space-between;
  /* 16 on top and sides, nothing below — logo and CTA hug the corners */
  padding: var(--header-py) var(--header-px) 0;
  pointer-events: none;
  --header-fg: var(--ink);
  /* light section behind the toggle → light hover fill (dark icons show) */
  --toggle-hover: #ffffff;
}
.site-header > * { pointer-events: auto; }
/* dark section behind → white icons, so the hover fill goes dark to match */
.site-header.on-dark { --header-fg: #ffffff; --toggle-hover: #1e1e1e; }

/* The tone tracker re-inks the fixed logo per section. Keeping the mask on a
   flat color avoids repainting a fixed backdrop-filter on every scroll frame. */
.logo { display: inline-flex; align-items: center; height: var(--ctl-h); }
.logo-mark {
  display: block;
  width: clamp(72px, 5.613vw, 97px);
  aspect-ratio: 97 / 31;
  background: var(--header-fg);
  transition: background-color 0.25s var(--ease);
  -webkit-mask: url('../assets/logo.svg') center / contain no-repeat;
  mask: url('../assets/logo.svg') center / contain no-repeat;
}

/* ── theme toggle (Labe-style round carousel) ──
   One round button, icons clipped by the circle: the current mode's icon
   sits centred (semi-transparent, opaque on hover), the other is parked off
   to one side. A click slides the outgoing icon out one edge while the
   incoming rides in from the far side. Only the disc + icon — no inner
   thumb. Icon and hover fill both re-ink against the section behind. */
.theme-toggle {
  position: absolute;
  left: 50%;
  /* header pads top-only, so the content band is offset by half the pad */
  top: calc(50% + var(--header-py) / 2);
  transform: translate(-50%, -50%);
  width: var(--toggle-h);
  height: var(--toggle-h);
  border-radius: 999px;
  overflow: hidden;
  /* no backdrop-filter: a fixed blur re-samples & re-blurs the scrolling
     content beneath it every frame — a pure scroll-time composite cost */
  background: var(--toggle-bg);
  color: var(--header-fg);
  transition: background-color 0.3s var(--ease);
  --toggle-slide: 26px;
}
/* hover fill contrasts the SECTION behind the disc (same driver as the
   icon), not the theme — otherwise a day icon could land on a dark hover
   fill over a dark section and vanish */
.theme-toggle:hover { background: var(--toggle-hover); }
.toggle-icon {
  position: absolute;
  top: 50%;
  left: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--header-fg);
  transition:
    transform 0.46s var(--ease-snap),
    opacity 0.3s var(--ease),
    color 0.3s var(--ease);
}
.toggle-icon svg { display: block; width: 20px; height: 20px; }
/* day: sun centred (dimmed), moon parked off the right */
.toggle-sun  { transform: translate(-50%, -50%); opacity: 0.55; }
.toggle-moon { transform: translate(calc(-50% + var(--toggle-slide)), -50%); opacity: 0; }
/* night: sun exits left, moon slides to centre */
:root[data-theme='night'] .toggle-sun  { transform: translate(calc(-50% - var(--toggle-slide)), -50%); opacity: 0; }
:root[data-theme='night'] .toggle-moon { transform: translate(-50%, -50%); opacity: 0.55; }
/* hover: the centred icon goes fully opaque */
:root:not([data-theme='night']) .theme-toggle:hover .toggle-sun,
:root[data-theme='night'] .theme-toggle:hover .toggle-moon { opacity: 1; }

/* ── header CTA: hidden until the hero form scrolls away ── */
.header-cta {
  /* matches the day/night switch height, a touch smaller label */
  height: var(--toggle-h);
  padding: 0 clamp(20px, 1.736vw, 30px);
  font-size: clamp(15px, 1.088vw, 18px);
  opacity: 0;
  visibility: hidden;
  pointer-events: none !important;
  transform: translate3d(12px, 0, 0);
  transition:
    opacity 0.5s var(--ease-luxe),
    transform 0.6s var(--ease-luxe),
    background-color 0.7s var(--ease),
    color 0.7s var(--ease),
    visibility 0s linear 0.5s;
}
body.cta-active .header-cta {
  opacity: 1;
  visibility: visible;
  pointer-events: auto !important;
  transform: none;
  transition:
    opacity 0.5s var(--ease-luxe),
    transform 0.6s var(--ease-luxe),
    background-color 0.7s var(--ease),
    color 0.7s var(--ease);
}
/* headers's CTA re-inks itself against the section underneath */
.site-header.on-dark .header-cta { background: #ffffff; color: #111111; }
/* footer owns the real form — the shortcut steps aside */
body.cta-docked .header-cta {
  opacity: 0;
  visibility: hidden;
  pointer-events: none !important;
}

/* ═══════════ MOBILE FLOATING CTA ═══════════ */
.mobile-cta { display: none; }

/* ═══════════ HERO ═══════════ */
.hero {
  position: relative;
  height: 100svh;
  min-height: 560px;
  background: #ffffff;
  color: var(--ink);
  overflow: hidden;
}
.hero-media, .hero-media img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
}
.hero-media img {
  object-fit: cover;
  object-position: 62% 20%;
  transform-origin: 62% 20%;
  animation: hero-bg-scale 1.7s var(--ease-luxe) both;
}
@keyframes hero-bg-scale {
  from { transform: scale(1.035); }
  to { transform: none; }
}
.hero-copy {
  position: absolute;
  left: 0;
  bottom: 0;
  width: 100%;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: clamp(24px, 2.083vw, 36px);
  padding: 0 var(--pad-x) clamp(48px, 6.944vw, 120px);
}
.hero-sub {
  font-size: var(--fs-body-lg);
  font-weight: 400;
  line-height: 1.4;
  letter-spacing: -0.02em;
  opacity: var(--muted-opacity);
  max-width: clamp(300px, 30.093vw, 520px);
  animation: hero-rise 0.85s var(--ease-luxe) 240ms both;
}
/* the whole form (input + button + note) rises as one block, last in line */
.hero .access-form {
  animation: hero-rise 0.85s var(--ease-luxe) 360ms both;
}
/* Hero entrance, staggered so the hierarchy reads heading → subheading →
   input. Pure CSS animations that play on load and are backwards-filled
   (`both`), so the hidden start shows before the delay and there is no
   flash of the final state on reload. Each authored .hero-line rises as a
   whole through its own clip — the two fonts inside a line stay on that
   line, never split apart. */
.hero-line {
  display: block;
  overflow: hidden;
  /* room for descenders inside the clip without shifting layout */
  padding-bottom: 0.08em;
  margin-bottom: -0.08em;
}
.hero-line-in {
  display: block;
  animation: hero-line-rise 0.95s var(--ease-luxe) var(--hd, 0ms) both;
}
.hero-line:nth-of-type(2) .hero-line-in { --hd: 90ms; }
@keyframes hero-line-rise { from { transform: translateY(112%); } }
@keyframes hero-rise { from { opacity: 0; transform: translateY(26px); } }

/* ═══════════ SECTION SHARED ═══════════ */
.section {
  padding: var(--sec-py) var(--pad-x);
  transition: background-color var(--theme-fade) var(--ease), color var(--theme-fade) var(--ease);
}
.section > .h2 { margin-bottom: var(--gap-head); }

/* ═══════════ JEWELRY ═══════════ */
.jewelry {
  background: var(--sec1-bg);
  color: var(--fg);
}
.tech-grid {
  display: flex;
  gap: 8px;
}
.tech-cell { flex: 1 1 0; min-width: 0; }
.tech-img {
  aspect-ratio: 485 / 560;
  overflow: hidden;
}
.tech-img img { width: 100%; height: 100%; object-fit: cover; }
.tech-desc {
  margin-top: clamp(16px, 1.389vw, 24px);
  padding-right: clamp(16px, 1.389vw, 24px);
  font-size: var(--fs-body-lg);
  font-weight: 500;
  line-height: 1.4;
  letter-spacing: -0.02em;
  opacity: var(--muted-opacity);
  --reveal-opacity: var(--muted-opacity);
}

/* ═══════════ HOW IT WORKS ═══════════ */
.how {
  background: var(--how-bg);
  color: #ffffff;
  --sweep-ink: #ffffff;
}
.how-head {
  margin-bottom: var(--gap-head);
}
.rail-nav {
  display: flex;
  align-items: center;
  margin-top: clamp(28px, 2.778vw, 48px);
}
.rail-nav .connector--small { color: var(--how-ctl); transition: color var(--theme-fade) var(--ease); }
.rail-btn {
  width: clamp(96px, 7.407vw, 128px);
  height: 44px;
  border-radius: var(--radius-ctl);
  background: var(--how-ctl);
  color: #ffffff;
  display: flex;
  align-items: center;
  justify-content: center;
  transition: background-color 0.3s var(--ease), opacity 0.3s var(--ease);
}
.rail-btn:hover:not(:disabled) { background: color-mix(in srgb, var(--how-ctl) 84%, #ffffff); }
.rail-btn:active:not(:disabled) svg { transform: scale(0.9); }
.rail-btn svg { transition: transform 0.2s var(--ease); }
.rail-btn:disabled { opacity: 0.4; cursor: default; }

.rail {
  /* full-bleed scroller: cancel the section gutter, restore it as inline pad */
  margin-inline: calc(var(--pad-x) * -1);
  padding-inline: var(--pad-x);
  overflow-x: auto;
  overflow-y: hidden;
  overscroll-behavior-x: contain;
  scroll-snap-type: x proximity;
  scroll-padding-inline-start: var(--pad-x);
  scrollbar-width: none;
  cursor: grab;
}
.rail::-webkit-scrollbar { display: none; }
.rail.is-dragging { cursor: grabbing; scroll-snap-type: none; }
.rail.is-dragging .step { pointer-events: none; }
.steps {
  display: flex;
  gap: clamp(32px, 5.556vw, 96px);
  width: max-content;
  border-top: 1px solid rgba(255, 255, 255, 0.2);
}
.step {
  width: clamp(300px, 21.991vw, 380px);
  border-left: 1px solid rgba(255, 255, 255, 0.2);
  display: flex;
  flex-direction: column;
  gap: 16px;
  scroll-snap-align: start;
}
.step-head {
  padding: 16px;
  min-height: clamp(170px, 11.574vw, 200px);
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  gap: 32px;
}
.step-desc { display: flex; flex-direction: column; gap: 16px; }
.step-desc .body {
  opacity: var(--muted-opacity);
  --reveal-opacity: var(--muted-opacity);
}
.step-num {
  font-family: var(--font-serif);
  font-weight: 200;
  font-size: var(--fs-num);
  line-height: 1;
  opacity: 0.4;
  white-space: nowrap;
  text-box-trim: trim-both;
  text-box-edge: cap alphabetic;
}
.step-img {
  width: clamp(280px, 19.676vw, 340px);
  height: clamp(360px, 25.463vw, 440px);
  overflow: hidden;
}
.step-img img { width: 100%; height: 100%; object-fit: cover; }
.steps .step:nth-child(2) { --step-reveal-delay: 110ms; }
.steps .step:nth-child(3) { --step-reveal-delay: 220ms; }
.steps .step:nth-child(4) { --step-reveal-delay: 330ms; }
.steps .step:nth-child(5) { --step-reveal-delay: 440ms; }

/* ═══════════ PHOTO (rounds itself off as you scroll) ═══════════ */
.photo-block {
  position: relative;
  background: var(--why-bg);
  transition: background-color var(--theme-fade) var(--ease);
}
/* one-shot rounding: the corners were animated per scroll frame via
   border-radius (a paint property) on a full-width layer — the #1 scroll-jank
   source. Now a single composited clip-path wipe fired by JS once the photo is
   properly in view (.photo-rounded), so nothing repaints while scrolling. */
.photo-clip {
  overflow: hidden;
  border-radius: 0;
  /* border-radius (not clip-path) — Chrome interpolates clip-path round poorly
     and snaps; border-radius transitions smoothly. One-shot, so no per-frame
     paint cost. Long, unhurried settle. */
  transition: border-radius 2.3s var(--ease-luxe);
  transform: translateZ(0);
}
.photo-clip img {
  width: 100%;
  aspect-ratio: 1728 / 942;
  object-fit: cover;
  transform: scale(1.09);
  transition: transform 2.6s var(--ease-luxe);
  will-change: transform;
}
.photo-block.photo-rounded .photo-clip {
  border-radius: 0 0 58vw 58vw;
}
.photo-block.photo-rounded .photo-clip img {
  transform: none;
  will-change: auto;
}

/* ═══════════ WHY IT WORKS ═══════════ */
.why {
  position: relative;
  background: var(--why-bg);
  color: var(--fg);
  padding-inline: 12px;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--gap-head);
  overflow: clip;
}
.why-copy {
  position: relative;
  z-index: 1;
  width: min(670px, 100%);
  display: flex;
  flex-direction: column;
  gap: clamp(40px, 3.704vw, 64px);
}
.why-main-img {
  position: relative;
  width: 100%;
  aspect-ratio: 1 / 1;
  overflow: hidden;
}
/* oversized like the collage shots so its own parallax never bares an edge */
.why-main-img img {
  position: absolute;
  left: 0;
  top: -9%;
  width: 100%;
  height: 118%;
  object-fit: cover;
  will-change: transform;
}

/* floating collage: each shot glides into place once it enters the viewport
   (inner layer, one-shot). The frame then stays put while the photo drifts
   inside it — the image is oversized and JS slides it as you scroll. */
.why-float {
  position: absolute;
  z-index: 2;
  width: 18.171vw;
  aspect-ratio: 314 / 418;
}
.why-float-inner {
  position: relative;
  width: 100%;
  height: 100%;
  overflow: hidden;
  opacity: 0;
  transform: translate3d(var(--cx, 0vw), var(--cy, 0vw), 0) scale(0.96);
  transition:
    transform 1.3s var(--ease-luxe),
    opacity 0.9s var(--ease-luxe);
}
.why-float.placed .why-float-inner {
  opacity: 1;
  transform: none;
}
.why-float img {
  position: absolute;
  left: 0;
  top: -12%;
  width: 100%;
  height: 124%;
  object-fit: cover;
  will-change: transform;
}
.why-float--02 { left: 0.463vw;  top: 32.84vw;  --cx: 11vw;  --cy: -2.5vw; }
.why-float--03 { right: 0.463vw; top: 9.284vw;  --cx: -10vw; --cy: 2vw; }
.why-float--04 { left: 69.85vw; top: 66.634vw; }
/* why04 is fully static: no data-float (no scroll parallax) and no entrance
   glide — it just sits in its native 628x836 ratio, image filling the box
   1:1 with zero transforms */
.why-float--04 { aspect-ratio: 628 / 836; }
.why-float--04 .why-float-inner {
  opacity: 1;
  transform: none;
  transition: none;
}
.why-float--04 img {
  top: 0;
  height: 100%;
  transform: none;
  will-change: auto;
}

.privacy {
  position: relative;
  z-index: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: clamp(28px, 2.778vw, 48px);
  text-align: center;
  width: min(958px, 100%);
  margin-top: var(--gap-head);
}
.privacy-badge {
  width: clamp(88px, 6.944vw, 120px);
  height: clamp(88px, 6.944vw, 120px);
  border-radius: 50%;
  background: var(--badge-bg);
  color: var(--fg);
  display: flex;
  align-items: center;
  justify-content: center;
  transition: background-color var(--theme-fade) var(--ease);
}
.privacy-badge svg {
  width: clamp(44px, 3.472vw, 60px);
  height: clamp(44px, 3.472vw, 60px);
  overflow: visible;
}
/* padlock physics: raised, the short left leg shows an 8px gap while the
   long right leg stays sunk in the case. On reveal the shackle glides down
   and the gap closes; the case settles a hair as it seats. */
.lock-shackle {
  transform: translateY(-8px);
  transition: transform 0.85s cubic-bezier(0.5, 0, 0.15, 1.06) 0.6s;
}
.privacy.visible .lock-shackle { transform: none; }
.privacy-title { max-width: clamp(300px, 24.769vw, 428px); }
.privacy-text { max-width: min(598px, 100%); }

/* ═══════════ FOOTER / RESERVE ═══════════ */
.footer {
  position: relative;
  overflow: hidden;
  color: var(--ink);
}
.footer-media, .footer-media img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
}
.footer-media img { object-fit: cover; object-position: 50% 50%; }
.footer-fade { display: none; }
.footer-inner {
  position: relative;
  display: flex;
}
.footer-copy {
  flex: 1 1 0;
  min-width: 0;
  padding: clamp(96px, 10.417vw, 180px) var(--pad-x);
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  gap: clamp(32px, 3.241vw, 56px);
}
.footer-copy .access-form { width: 100%; gap: clamp(16px, 1.157vw, 20px); }
.footer-copy .form-note { text-align: left; }
.footer-spacer { flex: 1 1 0; min-width: 0; }

.spec-strip {
  display: flex;
  align-items: stretch;
  width: 100%;
}
.spec-rule { width: 1px; background: var(--ink); opacity: 0.1; }
.spec-cell {
  flex: 1 1 0;
  min-width: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: clamp(10px, 0.926vw, 16px);
  padding-block: 16px;
}
.spec-num {
  font-family: var(--font-serif);
  font-weight: 200;
  font-size: var(--fs-spec);
  line-height: 0.96;
  color: var(--ink);
}
.spec-label {
  font-size: var(--fs-caption);
  font-weight: 500;
  letter-spacing: -0.01em;
  line-height: 1;
  color: var(--mut);
}

.footer-bar {
  position: relative;
  padding: 0 var(--pad-x) clamp(24px, 2.778vw, 48px);
}
.footer-hairline { height: 1px; background: var(--ink); opacity: 0.1; }
.footer-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding-top: clamp(24px, 2.315vw, 40px);
}
.footer-logo { color: var(--ink); }
.footer-logo svg { width: clamp(72px, 5.613vw, 97px); height: auto; }
.footer-copyright {
  font-size: 15px;
  letter-spacing: -0.01em;
  color: var(--mut);
}

/* ═══════════ REVEALS ═══════════ */
.reveal-up {
  opacity: 0;
  transform: translateY(32px);
  transition:
    opacity 0.8s var(--ease-luxe) var(--delay, 0s),
    transform 0.9s var(--ease-luxe) var(--delay, 0s);
}
.reveal-up.visible { opacity: var(--reveal-opacity, 1); transform: none; }
.tech-cell:nth-child(2) { --delay: 0.08s; }
.tech-cell:nth-child(3) { --delay: 0.16s; }

/* Editorial line reveal: whole lines rise through a tight clipping mask.
   This stays on transform only, avoiding the text repaints caused by blur. */
.word-fade .line-measure {
  /* inline (not inline-block) so measurement wraps like real text and mixed
     fonts on one line are detected as one line, not split by font */
  display: inline;
}
.word-fade .line-clip {
  display: block;
  overflow: hidden;
  padding-bottom: 0.08em;
  margin-bottom: -0.08em;
}
.word-fade .line-inner {
  display: block;
  transform: translate3d(0, 112%, 0);
  transition: transform 0.9s var(--ease-luxe) calc(var(--step-reveal-delay, 0ms) + var(--ld, 0ms));
  will-change: transform;
}
.word-fade.visible .line-inner {
  transform: none;
}
.word-fade.revealed .line-inner { transition: none; will-change: auto; }

/* photo bloom: the shot rests slightly over-scaled inside its clipped frame
   and settles home slowly — long tail, no jolt */
.img-reveal { overflow: hidden; }
.img-reveal img {
  opacity: 0;
  transform: scale(1.1);
  transition:
    opacity 0.9s var(--ease-luxe) var(--step-reveal-delay, 0ms),
    transform 1.5s var(--ease-luxe) var(--step-reveal-delay, 0ms);
  will-change: transform;
}
.img-reveal.visible img {
  opacity: 1;
  transform: none;
  will-change: auto;
}

/* ═══════════ RESPONSIVE ═══════════ */
@media (max-width: 1024px) {
  .why-copy { width: min(670px, 82vw); }
}

@media (max-width: 900px) {
  /* collage reflows into the column: 02/03 become an offset pair after the
     main shot, 04 leaves — absolute anchors would collide with text here */
  .why { padding-inline: var(--pad-x); }
  .why-float {
    position: static;
    transform: none !important;
    will-change: auto;
  }
  /* in-flow placement keeps the glide, just vertical: the collage shots
     rise softly into place instead of sliding in from the centre */
  .why-float .why-float-inner { --cx: 0px; --cy: 26px; }
  .why-float--04 .why-float-inner { opacity: 1; transform: none; transition: none; }
  /* main shot goes portrait on phones */
  .why-main-img { aspect-ratio: 3 / 4; }
  /* the device shot bleeds to the true left edge, past the section gutter */
  .why-float--02 {
    width: min(60vw, 420px);
    align-self: flex-start;
    margin-left: calc(var(--pad-x) * -1);
  }
  .why-float--03 { width: min(44vw, 320px); align-self: flex-end; margin-top: min(-18vw, -60px); }
  .why-float--04 { display: none; }

  .footer-inner { display: block; }
  .footer-media img { object-position: 68% 50%; }
  .footer-copy .form-note { text-align: center; }

  .hero-media img {
    object-position: 66% 22%;
    transform-origin: 66% 22%;
  }
}

@media (max-width: 767px) {
  .header-cta { display: none; }

  /* Buttons are deliberately static on touch devices: no hover carry-over,
     text roll, or platform button styling can flash during a tap. */
  .btn,
  .rail-btn,
  .btn:hover,
  .btn:active,
  .rail-btn:hover,
  .rail-btn:active {
    -webkit-appearance: none;
    appearance: none;
    -webkit-tap-highlight-color: transparent;
    touch-action: manipulation;
    transition: none !important;
  }
  .btn .roll-char {
    overflow: visible;
    padding-bottom: 0;
    margin-bottom: 0;
  }
  .btn .roll-char > span {
    transition: none !important;
    transform: none !important;
  }
  .btn .roll-char .r-bot { display: none; }

  /* round toggle docks right, Labe mobile sizing. Background keeps the same
     translucent + section-adaptive fill as desktop (via --toggle-bg /
     --toggle-hover); only the icon dimming changes below. */
  .theme-toggle {
    position: static;
    transform: none;
    margin-left: auto;
    width: 40px;
    height: 40px;
    --toggle-slide: 24px;
  }
  .toggle-icon svg { width: 18px; height: 18px; }
  /* touch has no hover, so the centred icon sits at full fill by default
     (the parked icon stays hidden at 0) */
  :root:not([data-theme='night']) .toggle-sun,
  :root[data-theme='night'] .toggle-moon { opacity: 1; }

  .mobile-cta {
    display: block;
    position: fixed;
    left: 50%;
    bottom: calc(6px + env(safe-area-inset-bottom));
    z-index: 120;
    opacity: 0;
    visibility: hidden;
    pointer-events: none;
    filter: blur(8px);
    transform: translate3d(-50%, 6px, 0) scale(0.985);
    transition:
      opacity 0.58s var(--ease-luxe),
      filter 0.72s var(--ease-luxe),
      transform 0.82s var(--ease-luxe);
    will-change: opacity, filter, transform;
  }
  body.cta-active .mobile-cta {
    opacity: 1;
    visibility: visible;
    pointer-events: auto;
    filter: blur(0);
    transform: translate3d(-50%, 0, 0) scale(1);
  }
  body.cta-docked .mobile-cta,
  html.keyboard-open .mobile-cta {
    opacity: 0;
    visibility: hidden;
    pointer-events: none;
    filter: blur(8px);
    transform: translate3d(-50%, 0, 0) scale(0.985);
  }
  .mobile-cta .btn { height: 52px; }
  /* night sections are dark — the floating pill re-inks white */
  :root[data-theme='night'] .mobile-cta .btn {
    background: #f5f5f5;
    color: #111111;
  }

  .word-fade {
    opacity: 0;
    transform: translateY(20px);
    transition:
      opacity 0.62s var(--ease-luxe) var(--step-reveal-delay, 0ms),
      transform 0.74s var(--ease-luxe) var(--step-reveal-delay, 0ms);
  }
  .word-fade.visible {
    opacity: var(--reveal-opacity, 1);
    transform: none;
  }
  .word-fade.revealed { transition: none; }
  .word-fade .line-clip,
  .word-fade .line-inner {
    display: inline;
    overflow: visible;
    padding: 0;
    margin: 0;
    transform: none;
    transition: none;
    will-change: auto;
  }
  .steps .word-fade {
    opacity: var(--reveal-opacity, 1);
    transform: none;
    transition: none;
  }

  .why-main-img img,
  .why-float img {
    transform: none;
    will-change: auto;
  }
  /* the border-radius one-shot is the shared base; phones just round deeper */
  .photo-block.photo-rounded .photo-clip {
    border-radius: 0 0 50vw 50vw;
  }
}

@media (max-width: 640px) {
  :root {
    --pad-x: 12px;
    --sec-py: 72px;
    --gap-head: 44px;
  }

  /* exactly one device-window tall: solid theme backdrop, the portrait art
     layered on top and pinned up (its baked-in fade may crop below), copy
     pinned over the bottom. --hero-h is a px value JS locks at load and only
     refreshes on orientation change, so a collapsing in-app-browser toolbar
     can't grow the section mid-scroll (svh is unreliable in some webviews).
     100svh is the pre-JS fallback. */
  .hero {
    height: 100svh;
    height: var(--hero-h, 100svh);
    min-height: 560px;
  }
  .hero-media {
    bottom: auto;
    height: auto;
  }
  .hero-media img {
    position: static;
    width: 100%;
    height: auto;
    object-fit: contain;
    object-position: top;
    transform-origin: 50% 0;
  }
  .hero-copy { padding-bottom: 48px; }
  .hero-sub { max-width: 92%; }
  /* title flows naturally on phones — no forced line break — and rises as one
     block from the bottom instead of per-line masks */
  .hero-line,
  .hero-line-in {
    display: inline;
    overflow: visible;
    padding: 0;
    margin: 0;
    animation: none;
  }
  .hero-title { animation: hero-rise 0.85s var(--ease-luxe) 40ms both; }
  .hero-sub { animation-delay: 190ms; }
  .hero .access-form { animation-delay: 300ms; }

  .form-row .input { flex: 1 1 auto; min-width: 0; width: auto; }
  .access-form { width: 100%; }
  /* no connector on narrow screens — a plain 8px seam reads cleaner */
  .form-row { gap: 8px; }
  .form-row .connector--desk,
  .form-row .connector--mob { display: none; }

  /* jewelry becomes a swipe rail */
  .tech-grid {
    margin-inline: calc(var(--pad-x) * -1);
    padding-inline: var(--pad-x);
    overflow-x: auto;
    overflow-y: hidden;
    scroll-snap-type: x mandatory;
    scroll-padding-inline-start: var(--pad-x);
    scrollbar-width: none;
  }
  .tech-grid::-webkit-scrollbar { display: none; }
  /* inside a scroller the reveal offset would grow a phantom v-scroll —
     cells fade in place instead */
  .tech-cell { flex: 0 0 78vw; scroll-snap-align: start; transform: none; }

  .rail-nav { display: none; }
  .step { width: 76vw; }
  .step-head { min-height: 0; gap: 24px; padding: 12px 12px 8px; }
  .step-img { width: 68vw; height: 88vw; }
  .steps { gap: 20px; }

  /* photo block reads twice as tall on phones — portrait crop, same arc */
  .photo-clip img {
    aspect-ratio: auto;
    height: 109vw;
  }

  .why-float--02 { width: 72vw; }
  .why-float--03 { width: 52vw; margin-top: -24vw; }

  /* mobile footer: pendant close-up capped to the top band, fading into the
     plain F4EFEC tint the copy sits on (stops from the comp) */
  .footer { background: #f4efec; }
  .footer-media {
    bottom: auto;
    height: 120vw;
  }
  .footer-media img { object-position: 50% 0; }
  .footer-fade {
    display: block;
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    height: 120vw;
    pointer-events: none;
    background: linear-gradient(180deg, rgba(244, 239, 236, 0) 55%, #f4efec 88%);
  }
  .footer-copy { padding-inline: var(--pad-x); padding-top: 100vw; }
  .spec-label { max-width: 20ch; line-height: 1.3; }
  .footer-bar { padding-bottom: max(24px, env(safe-area-inset-bottom)); }
}

/* ═══════════ REDUCED MOTION ═══════════ */
@media (prefers-reduced-motion: reduce) {
  .reveal-up { opacity: 1; transform: none; transition: none; }
  .hero-media img { animation: none; transform: none; }
  .hero-line-in, .hero-title, .hero-sub, .hero .access-form { animation: none; }
  /* JS adds .photo-rounded immediately here, so the clip-path lands at its end
     state with no transition */
  .photo-clip { transition: none; }
  .photo-clip img { transform: none; transition: none; will-change: auto; }
  .why-float { transform: none !important; }
  .why-float .why-float-inner { opacity: 1; transform: none; transition: none; }
  .word-fade { opacity: var(--reveal-opacity, 1); transform: none; transition: none; }
  .word-fade .line-clip,
  .word-fade .line-inner {
    display: inline;
    overflow: visible;
    padding: 0;
    margin: 0;
    transform: none;
    transition: none;
    will-change: auto;
  }
  .img-reveal img { opacity: 1; transform: none; transition: none; }
  .roll-char > span { transition: none; }
  .btn:hover .roll-char .r-top { transform: none; }
  .btn:hover .roll-char .r-bot { transform: translateY(110%); }
  .toggle-icon { transition: opacity 0.3s var(--ease); }
  .lock-shackle { transform: none; transition: none; }
  html { scroll-behavior: auto; }
}
