/* ---------- Satoshi (brand typeface, variable) ---------- */
@font-face {
  font-family: "Satoshi";
  src: url("fonts/Satoshi-Variable.woff") format("woff");
  font-weight: 300 900;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "Satoshi";
  src: url("fonts/Satoshi-VariableItalic.woff") format("woff");
  font-weight: 300 900;
  font-style: italic;
  font-display: swap;
}

/* ============================================================
   FORME STUDIO — shared styles (all pages)
   Direction B refined: "Bold, but elegant". Dark rooms, the lamp
   as the only light source. Orange is precious: primary CTA,
   marquee, one hero word, active states — nothing decorative.
   Motion: transform + opacity only. Glows are pre-rendered
   radial-gradient layers whose OPACITY animates.
   Panels stay square (--radius: 0); imagery cards are the one
   rounded element (--card-radius: 18px).
   ============================================================ */

:root {
  --orange: #FF5C00;
  --ink: #020C07;
  --bg: #F5F2F5;
  --bone: #ECE7DE;
  --sage: #8A9A7B;

  --char: #020C07;            /* dark section base */
  --char-2: #07140D;          /* slightly lifted charcoal */
  --char-warm: #04100A;       /* warm-tinted deep */
  --line: rgba(2, 12, 7, 0.10);
  --hairline: rgba(245, 242, 245, 0.10);   /* dark-surface hairline */

  /* text on dark — warm off-white, never pure white */
  --t-dark-hi: #F5F2F5;
  --t-dark-body: rgba(244, 241, 236, 0.78);
  --t-dark-mut: rgba(244, 241, 236, 0.62);
  /* text on light */
  --t-light-body: rgba(2, 12, 7, 0.74);
  --t-light-mut: rgba(2, 12, 7, 0.6);

  --maxw: 1560px;   /* Gantri-class container — content centers on big monitors */
  --pad: clamp(20px, 5vw, 64px);
  --radius: 0px;              /* square panels; pills stay round via --pill */
  --card-radius: 8px;         /* imagery cards — Gantri-measured radius */
  --pill: 100px;              /* one radius for pills/buttons */

  --ease: cubic-bezier(0.16, 1, 0.3, 1);
  --spring: cubic-bezier(0.34, 1.56, 0.64, 1);
  --fast: 0.25s var(--ease);
}

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

html {
  -webkit-text-size-adjust: 100%;
  /* no visible scrollbars anywhere on the site (scrolling is untouched) */
  scrollbar-width: none;
  -ms-overflow-style: none;
}
@media (prefers-reduced-motion: no-preference) {
  html { scroll-behavior: smooth; }
}

body {
  font-family: "Satoshi", system-ui, -apple-system, sans-serif;
  background: var(--bg);
  color: var(--ink);
  line-height: 1.65;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  overflow-x: hidden;
}
body.menu-open { overflow: hidden; }

img, svg { display: block; max-width: 100%; }
a { color: inherit; text-decoration: none; }
button { font-family: inherit; }

::selection { background: var(--orange); color: var(--ink); }

:focus-visible {
  outline: 2px solid var(--orange);
  outline-offset: 3px;
  border-radius: 6px;
}
/* on light surfaces an ink ring reads stronger */
.nav :focus-visible,
.section-light :focus-visible { outline-color: var(--ink); }
body.menu-open .nav :focus-visible,
.mobile-menu :focus-visible { outline-color: var(--orange); }
/* imagery cards keep their 18px corners when focused */
.card:focus-visible,
.cat-tile:focus-visible { border-radius: var(--card-radius); }

/* ---------- Layout helpers ---------- */
.wrap {
  width: 100%;
  max-width: var(--maxw);
  margin-inline: auto;
  padding-inline: var(--pad);
}

/* slow, generous vertical rhythm */
.section { padding-block: clamp(64px, 7.5vw, 104px); position: relative; }  /* tightened — was clamp(96px,12vw,160px) */
#collections, #featured, #story, #how, #journal { scroll-margin-top: 76px; }

/* clean thin rules at the light/dark seams — nothing busy */
.rule-top::before {
  content: "";
  position: absolute;
  top: 0; left: 0; right: 0;
  height: 1px;
  background: rgba(2, 12, 7, 0.12);
}
.on-dark.rule-top::before { background: var(--hairline); }

/* ONE micro-label style, shared everywhere */
.eyebrow {
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.25em;
  text-transform: uppercase;
  color: var(--t-light-mut);
  display: inline-flex;
  align-items: center;
  gap: 12px;
}
.eyebrow::before {
  content: "";
  width: 20px; height: 1px;
  background: currentColor;
  display: inline-block;
  opacity: 0.6;
}
.on-dark .eyebrow, .hero .eyebrow { color: var(--t-dark-mut); }

h1, h2, h3 {
  font-weight: 700;
  letter-spacing: -0.02em;
  line-height: 1.08;
}
/* one consistent section-heading size/weight */
h2 { font-size: clamp(1.9rem, 4vw, 2.9rem); }

/* ============================================================
   PHOTO PAIRS — every lamp is a real photograph, shot twice
   from the same angle (unlit + lit). The lit frame sits on top
   and its OPACITY crossfades — that's how lamps "switch on".
   ============================================================ */
.photo-pair img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}
.photo-pair .ph-on {
  opacity: 0;
  transition: opacity 0.5s var(--ease);
  will-change: opacity;
}

/* ============================================================
   NAV (identical on every page)
   ============================================================ */
.nav {
  position: sticky;
  top: 0;
  z-index: 100;
  background: transparent;                 /* flush with the page at the top */
}
/* the scrolled backdrop tint lives on an overlay so only OPACITY animates */
.nav::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background: rgba(245, 242, 245, 0.95);
  opacity: 0;
  transition: opacity 0.3s ease;
  pointer-events: none;
}
.nav.scrolled::before { opacity: 1; }
/* backdrop blur is desktop-only, static, and only once scrolled (a blur
   strip over the hero would betray the transparent state). */
@media (min-width: 721px) {
  .nav.scrolled {
    backdrop-filter: saturate(180%) blur(8px);
    -webkit-backdrop-filter: saturate(180%) blur(8px);
  }
}
/* no border on the scrolled nav — the frosted tint alone keeps it flush */

/* On the home page the nav floats OVER the dark hero: pull the page
   content up underneath it so "transparent" means the hero shows through
   (66px = .nav-inner height). */
.nav-on-dark { margin-bottom: -66px; }

/* On the home page the unscrolled nav floats over the DARK hero —
   flip its content light until the tint fades in. (The open mobile
   menu's own dark theme already outranks these.) */
.nav-on-dark:not(.scrolled) .wordmark,
.nav-on-dark:not(.scrolled) .nav-links a { color: var(--t-dark-hi); }
.nav-on-dark:not(.scrolled) .nav-links a:hover { color: #fff; }
.nav-on-dark:not(.scrolled) .nav-cart {
  color: var(--t-dark-hi);
  border-color: rgba(245, 242, 245, 0.32);
  background: transparent;
}
.nav-on-dark:not(.scrolled) .nav-burger .bars,
.nav-on-dark:not(.scrolled) .nav-burger .bars::before,
.nav-on-dark:not(.scrolled) .nav-burger .bars::after { background: var(--t-dark-hi); }

/* ---------- SHOP mega-menu (desktop) — compact frosted card, Gantri-style ---- */
.nav-item { display: inline-flex; position: relative; }
.mega {
  /* invisible positioning wrapper — its padding BRIDGES the hover gap
     between the link and the card so the cursor never leaves .has-mega */
  position: absolute;
  left: 50%;
  top: 100%;
  z-index: 99;
  width: max-content;
  min-width: 270px;
  padding-top: 14px;
  opacity: 0;
  transform: translate(-50%, -8px);
  visibility: hidden;
  pointer-events: none;
  transition: opacity 0.28s ease, transform 0.32s var(--ease), visibility 0s linear 0.28s;
}
.has-mega:hover .mega,
.has-mega:focus-within .mega {
  opacity: 1;
  transform: translate(-50%, 0);
  visibility: visible;
  pointer-events: auto;
  transition-delay: 0s;
}
/* after a same-page anchor click the panel must leave even though the
   cursor is still inside it — .mega-snooze (set by ui.js, cleared on the
   next mouseleave/focusout) outranks the :hover/:focus-within rule above */
.has-mega.mega-snooze .mega {
  opacity: 0;
  transform: translate(-50%, -8px);
  visibility: hidden;
  pointer-events: none;
}
/* neutralise the page-width helper inside the compact card */
.mega .wrap { max-width: none; margin: 0; }
/* the visible card — DARK frosted glass, white text (Gantri-style) */
.mega-inner {
  display: block;
  border-radius: var(--card-radius);
  background: rgba(8, 14, 11, 0.62);
  backdrop-filter: blur(26px) saturate(160%);
  -webkit-backdrop-filter: blur(26px) saturate(160%);
  border: 1px solid rgba(245, 242, 245, 0.14);
  box-shadow: 0 30px 60px -24px rgba(2, 12, 7, 0.55);
  padding: 24px 28px;
}
/* readable regardless of nav state (the on-dark nav override must not bleed in) */
.mega .mega-eyebrow { color: rgba(245, 242, 245, 0.55); }
.nav .nav-links .mega-col a { color: #F5F2F5; }
.nav .nav-links .mega-col a:hover { color: var(--orange); }
.mega-col a .count { color: rgba(245, 242, 245, 0.5); }
.mega-eyebrow {
  display: block;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  margin-bottom: 14px;
}
.mega-col { display: flex; flex-direction: column; align-items: flex-start; }
.mega-col a {
  display: inline-flex;
  align-items: baseline;
  gap: 10px;
  padding: 7px 0;
  font-size: 17px;
  font-weight: 600;
  color: var(--ink);
  letter-spacing: -0.01em;
  transition: color 0.2s ease, transform 0.25s var(--ease);
}
.mega-col a:hover { color: var(--orange); transform: translateX(4px); }
.mega-col a .count { font-size: 12px; font-weight: 500; }
/* ---------- "In your homes" — horizontal customer gallery ---------- */
.testi-rail {
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  -webkit-overflow-scrolling: touch;
  padding-bottom: 10px;
  scrollbar-width: none;
}
.testi-track { display: flex; gap: clamp(14px, 1.6vw, 22px); align-items: flex-start; }
.testi-card {
  flex: 0 0 auto;
  scroll-snap-align: start;
  margin: 0;
}
/* the customer's IG-story screenshot, shown WHOLE — never cropped. Every
   card shares one height; each photo keeps its own width (the sources run
   ~9:15–9:17), so the rail stays tidy while no frame loses its top or
   bottom. Rounded corners, lazy-loaded. */
.testi-photo {
  display: block;
  height: clamp(330px, 42vh, 420px);
  width: auto;
  max-width: none;
  border-radius: var(--card-radius);
  background: linear-gradient(165deg, #ECE7DE 0%, #E0D9CC 60%, #D6CDBE 100%);
}
.testi-card figcaption {
  padding: 12px 4px 0;
  font-size: 12px;
  font-weight: 500;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--t-light-mut);
}

/* ---------- Journal — title & copy live BELOW the photo ---------- */
.journal-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: clamp(18px, 2vw, 28px);
}
@media (max-width: 1024px) { .journal-grid { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 640px)  { .journal-grid { grid-template-columns: 1fr; } }
.post-media {
  aspect-ratio: 4 / 3;
  border-radius: var(--card-radius);
  overflow: hidden;
  background: #E8E3DA;
}
.post-media img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
  transition: transform 0.6s var(--ease);
}
.post:hover .post-media img { transform: scale(1.04); }
.post-body { padding: 16px 4px 0; }
.post-meta {
  display: block;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--t-light-mut);
}
.post h3 {
  font-size: 1.18rem;
  font-weight: 700;
  letter-spacing: -0.01em;
  margin: 9px 0 6px;
  color: var(--ink);
}
.post p { font-size: 14.5px; line-height: 1.6; color: var(--t-light-mut); max-width: 40ch; }

/* the rest of the page blurs while the mega-menu is open (opacity-only) */
.page-veil {
  position: fixed;
  inset: 0;
  z-index: 90;
  background: rgba(2, 12, 7, 0.18);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.3s ease;
}
body.mega-open .page-veil { opacity: 1; }
@media (max-width: 720px) { .mega, .page-veil { display: none; } }

.nav-inner {
  height: 66px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
}
.wordmark {
  font-weight: 700;
  letter-spacing: -0.015em;   /* lowercase brand wordmark — tight, like the logo */
  font-size: 16.5px;
  display: inline-flex;
  align-items: center;
  gap: 9px;
  padding-block: 10px;
}
.wordmark .mark {
  display: block;
  width: 20px; height: 20px;    /* the full square logo, uncropped */
}

.nav-links {
  display: flex;
  align-items: center;
  gap: 34px;
  font-size: 14px;
  font-weight: 500;
}
.nav-links a {
  position: relative;
  color: var(--t-light-body);
  padding-block: 10px;
  transition: color var(--fast);
}
/* 1px underline that scales in — transform only */
.nav-links a::after {
  content: "";
  position: absolute;
  left: 0; right: 0; bottom: 4px;
  height: 1px;
  background: var(--ink);
  transform: scaleX(0);
  transform-origin: left;
  transition: transform var(--fast);
}
.nav-links a:hover { color: var(--ink); }
.nav-links a:hover::after { transform: scaleX(1); }

.nav-right { display: flex; align-items: center; gap: 10px; }

.nav-cart {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  font-size: 11.5px;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  min-height: 44px;
  padding: 10px 16px;
  border: 1px solid var(--line);
  border-radius: var(--pill);
  background: rgba(255,255,255,0.55);
  transition: border-color var(--fast), color var(--fast), transform var(--fast);
}
.nav-cart:hover { border-color: var(--ink); transform: translateY(-1px); }

/* hamburger — phones only */
.nav-burger {
  display: none;
  width: 44px; height: 44px;
  border-radius: var(--radius);
  border: 1px solid var(--line);
  background: rgba(255,255,255,0.55);
  color: var(--ink);
  cursor: pointer;
  transition: border-color var(--fast), color var(--fast);
}
.nav-burger .bars {
  width: 18px; height: 12px;
  position: relative;
  display: block;
  margin: 0 auto;
}
.nav-burger .bars::before,
.nav-burger .bars::after {
  content: "";
  position: absolute;
  left: 0; right: 0;
  height: 2px;
  border-radius: 2px;
  background: currentColor;
  transition: transform var(--fast);   /* transform only */
}
.nav-burger .bars::before { top: 0; }
.nav-burger .bars::after { bottom: 0; }
.nav-burger[aria-expanded="true"] .bars::before { transform: translateY(5px) rotate(45deg); }
.nav-burger[aria-expanded="true"] .bars::after { transform: translateY(-5px) rotate(-45deg); }

@media (max-width: 720px) {
  .nav-links { display: none; }
  .nav-burger { display: inline-block; }
}

/* nav flips dark while the overlay menu is open (instant — no large-surface fade) */
body.menu-open .nav {
  background: rgba(2, 12, 7, 0.92);
  border-bottom-color: rgba(245,242,245,0.08);
}
body.menu-open .nav .wordmark { color: var(--t-dark-hi); }
body.menu-open .nav-cart {
  color: var(--t-dark-hi);
  border-color: rgba(245,242,245,0.3);
  background: rgba(245,242,245,0.06);
}
body.menu-open .nav-burger {
  color: var(--t-dark-hi);
  border-color: rgba(245,242,245,0.3);
  background: rgba(245,242,245,0.08);
}

/* full-screen overlay menu */
.mobile-menu {
  position: fixed;
  inset: 0;
  z-index: 95;
  background:
    radial-gradient(120% 70% at 50% 112%, rgba(255,92,0,0.12), transparent 55%),
    var(--char);
  color: var(--t-dark-hi);
  padding: 106px var(--pad) 40px;
  display: flex;
  flex-direction: column;
  opacity: 0;
  visibility: hidden;
  transform: translateY(-10px);
  transition: opacity 0.35s var(--ease), transform 0.35s var(--ease), visibility 0s linear 0.35s;
}
body.menu-open .mobile-menu {
  opacity: 1;
  visibility: visible;
  transform: none;
  transition: opacity 0.35s var(--ease), transform 0.35s var(--ease);
}
.mobile-links { display: flex; flex-direction: column; }
.mobile-links a {
  display: flex;
  align-items: baseline;
  gap: 16px;
  font-size: clamp(1.9rem, 8.5vw, 2.4rem);
  font-weight: 700;
  letter-spacing: -0.02em;
  padding: 18px 0;
  border-bottom: 1px solid var(--hairline);
  transition: transform var(--fast);
}
.mobile-links a:hover { transform: translateX(6px); }
.mobile-links a .idx {
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.25em;
  color: var(--t-dark-mut);
}
.mobile-cta {
  margin-top: 30px;
  justify-content: center;
}
.mobile-foot {
  margin-top: auto;
  padding-top: 30px;
  font-size: 13px;
  color: var(--t-dark-mut);
}
@media (min-width: 721px) { .mobile-menu { display: none; } }

/* ============================================================
   BUTTONS — refined slim pills, transform-only motion
   ============================================================ */
.btn {
  display: inline-flex;
  align-items: center;
  gap: 12px;
  font-weight: 600;
  font-size: 13px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  min-height: 48px;
  padding: 13px 24px;
  border-radius: var(--pill);
  border: 1px solid transparent;
  cursor: pointer;
  transition: transform var(--fast), color var(--fast), border-color var(--fast);
}
.btn svg { width: 16px; height: 16px; flex: none; }

.btn-primary {
  background: var(--orange);
  color: var(--ink);   /* ink on orange = 6.4:1, passes AA */
  box-shadow: 0 12px 32px -10px rgba(255, 92, 0, 0.5);  /* static — never transitioned */
}
.btn-primary:hover { transform: translateY(-2px); }
.btn .arrow { transition: transform var(--fast); }
.btn:hover .arrow { transform: translateX(3px); }

.btn-ghost-dark {
  color: var(--t-dark-hi);
  border-color: rgba(245,242,245,0.25);
  background: transparent;
}
.btn-ghost-dark:hover { border-color: rgba(245,242,245,0.6); transform: translateY(-2px); }

.btn-ghost-light {
  color: var(--ink);
  border-color: var(--line);
  background: rgba(255,255,255,0.55);
}
.btn-ghost-light:hover { border-color: var(--ink); transform: translateY(-2px); }

/* ============================================================
   HERO — a dark room; the lamp is the only light source (home)
   ============================================================ */
.hero {
  position: relative;
  background: linear-gradient(180deg, #020C07 0%, #02100A 62%, var(--char-warm) 100%);
  color: var(--t-dark-hi);
  overflow: hidden;
  isolation: isolate;
}
.hero::before {
  /* static vignette toward the edges — deepens the room */
  content: "";
  position: absolute; inset: 0;
  background: radial-gradient(120% 90% at 62% 60%, transparent 38%, rgba(0,0,0,0.55) 100%);
  z-index: 0;
  pointer-events: none;
}

.hero-inner {
  position: relative;
  z-index: 2;
  padding-block: clamp(72px, 12vw, 132px);
  min-height: min(92vh, 880px);
  display: grid;
  grid-template-columns: 1.05fr 0.95fr;
  align-items: center;
  gap: clamp(24px, 5vw, 64px);
}

.hero-copy { max-width: 620px; }

.hero h1 {
  margin-top: 28px;
  font-size: clamp(2.8rem, 8.4vw, 6.4rem);
  font-weight: 700;
  line-height: 1.04;
  letter-spacing: -0.03em;
}
.hero h1 .accent { color: var(--orange); }   /* the one accent word */
.hero h1 em {
  font-style: italic;
  font-weight: 400;
  letter-spacing: -0.02em;
}

.hero-sub {
  margin-top: 28px;
  font-size: clamp(1rem, 1.4vw, 1.125rem);
  line-height: 1.65;
  color: var(--t-dark-body);
  max-width: 440px;
  font-weight: 400;
}

.hero-actions {
  margin-top: 40px;
  display: flex;
  align-items: center;
  gap: 16px;
  flex-wrap: wrap;
}

.hero-scroll {
  margin-top: 52px;
  display: inline-flex;
  align-items: center;
  gap: 12px;
  font-size: 11px;
  letter-spacing: 0.25em;
  text-transform: uppercase;
  color: var(--t-dark-mut);
  font-weight: 600;
}
.hero-scroll .line {
  width: 40px; height: 1px;
  background: rgba(245,242,245,0.3);
}

/* hero photo stage — the real lamp, lit, blending into the dark room */
.hero-stage {
  position: relative;
  z-index: 2;
  display: grid;
  place-items: center;
  height: 100%;
}
.hero-photo { position: relative; width: min(86%, 420px); }
/* breathing warm radial behind/around the photograph — opacity only */
.hero-photo .glow {
  position: absolute;
  left: 50%; top: 50%;
  width: 150%;
  aspect-ratio: 1;
  transform: translate(-50%, -50%);
  background: radial-gradient(circle,
    rgba(255, 160, 80, 0.30) 0%,
    rgba(255, 110, 25, 0.13) 42%,
    rgba(255, 92, 0, 0.05) 60%,
    transparent 72%);
  pointer-events: none;
  will-change: opacity;
  animation: breathe 7s ease-in-out infinite;
}
.hero-photo img {
  position: relative;
  z-index: 1;
  width: 100%;
  height: auto;
  border-radius: var(--card-radius);
  border: 1px solid var(--hairline);
}
/* ambient breathing — opacity only, starts from 1 so the entrance hands over seamlessly */
@keyframes breathe {
  0%, 100% { opacity: 1; }
  50%      { opacity: 0.85; }
}

/* "LIGHTS ON" entrance — JS-gated, runs once, opacity/transform only.
   The room starts dim; the photo + glow bloom up, then the copy rises in. */
@keyframes fadein {
  from { opacity: 0; }
  to   { opacity: 1; }
}
@keyframes rise {
  from { opacity: 0; transform: translateY(16px); }
  to   { opacity: 1; transform: none; }
}
html.js .hero-stage { animation: fadein 0.8s ease-out both; }
html.js .hero-photo img { animation: fadein 1.2s var(--ease) 0.1s both; }
html.js .hero-photo .glow {
  animation: fadein 1.4s var(--ease) both, breathe 7s ease-in-out 1.4s infinite;
}
html.js .hero .eyebrow   { animation: rise 0.9s var(--ease) 0.2s both; }
html.js .hero h1         { animation: rise 0.9s var(--ease) 0.35s both; }
html.js .hero-sub        { animation: rise 0.9s var(--ease) 0.5s both; }
html.js .hero-actions    { animation: rise 0.9s var(--ease) 0.65s both; }
html.js .hero-scroll     { animation: rise 0.9s var(--ease) 0.8s both; }

@media (max-width: 880px) {
  .hero-inner {
    grid-template-columns: 1fr;
    min-height: auto;
  }
  .hero-stage { order: -1; min-height: 300px; padding-top: 12px; }
  .hero-photo { width: min(72%, 320px); }
}

/* orange marquee strip — the one big orange surface */
.ticker {
  background: var(--orange);
  color: var(--ink);   /* ink on orange = 6.4:1, passes AA (white was 3.1:1) */
  overflow: hidden;
  white-space: nowrap;
  border-block: 1px solid rgba(0,0,0,0.08);
}
.ticker-track {
  display: inline-flex;
  animation: marquee 60s linear infinite;
  padding-block: 12px;
  will-change: transform;
}
.ticker-half { display: inline-flex; }
.ticker-half span {
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  padding-inline: 26px;
  display: inline-flex;
  align-items: center;
  gap: 26px;
}
.ticker-half span::after {
  content: "✺";
  font-size: 10px;
  opacity: 0.55;   /* ink reads heavier than the old white — kept subordinate */
}
@keyframes marquee {
  from { transform: translateX(0); }
  to   { transform: translateX(-50%); }
}

/* ============================================================
   SECTION HEADS + GRIDS
   ============================================================ */
.sec-head {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: 30px;
  margin-bottom: clamp(44px, 6vw, 72px);
  flex-wrap: wrap;
}
.sec-head h2 { max-width: 15ch; margin-top: 18px; }
.sec-head .head-note {
  max-width: 330px;
  font-size: 15px;
  color: var(--t-light-mut);
  line-height: 1.65;
}
.head-side {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 18px;
  max-width: 330px;
}

.grid {
  display: grid;
  /* 3 large tiles per row — bigger imagery, Gantri-style presence */
  grid-template-columns: repeat(3, 1fr);
  gap: clamp(18px, 2vw, 28px);
}
.grid-feat { grid-template-columns: repeat(4, 1fr); }
@media (max-width: 1024px) {
  .grid, .grid-feat { grid-template-columns: repeat(2, 1fr); }
}
@media (max-width: 520px) {
  .grid, .grid-feat { grid-template-columns: 1fr; }
}

/* ============================================================
   CARDS — full-bleed 4:5 photo, 18px corners, no chrome.
   The whole card is one <a href="product.html?id=N">; the
   lit-crossfade on hover/focus is the signature.
   ============================================================ */
.card {
  position: relative;
  display: block;
  border-radius: var(--card-radius);
  overflow: hidden;
  background: var(--char);
  box-shadow: 0 24px 48px -30px rgba(2,12,7,0.4);   /* static depth — never transitioned */
  transition: transform 0.45s var(--ease);
}
.card:hover,
.card:focus-visible { transform: translateY(-4px); }

.card-media {
  position: relative;
  aspect-ratio: 4 / 5;             /* matches the 960×1200 photographs */
  overflow: hidden;
  background: linear-gradient(180deg, var(--char-2) 0%, var(--char) 100%);
}
/* the lamp literally switches on — lit photo crossfades in, 0.5s, opacity only.
   (Shop tiles are .ed-tile, not .card — they carry NO hover-lighting rule at
   all, so on the shop the floating switch alone owns the lamps.) */
.card:hover .ph-on,
.card:focus-visible .ph-on,
.card:focus-within .ph-on { opacity: 1; }

/* always-on legibility scrims, baked in — top for the title block,
   bottom for the circle button */
.card-scrim {
  position: absolute;
  inset: 0;
  z-index: 2;
  pointer-events: none;
  background:
    linear-gradient(180deg, rgba(2,6,4,0.45) 0%, transparent 38%),
    linear-gradient(180deg, transparent 62%, rgba(2,6,4,0.40) 100%);
}

.card-info {
  position: absolute;
  top: 18px; left: 18px; right: 18px;
  z-index: 3;
  pointer-events: none;
}
.card-eyebrow {
  display: block;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.25em;
  text-transform: uppercase;
  color: rgba(255,255,255,0.75);
}
.card-title {
  margin-top: 7px;
  font-size: clamp(1.3rem, 1.8vw, 1.6rem);
  font-weight: 600;
  letter-spacing: -0.02em;
  line-height: 1.12;
  color: #fff;
}
.card-line {
  margin-top: 6px;
  font-size: 13px;
  line-height: 1.5;
  color: rgba(255,255,255,0.82);
}

/* 46px circular glass "configure" affordance — decorative inside the link */
.card-circle {
  position: absolute;
  left: 18px; bottom: 18px;
  z-index: 3;
  width: 46px; height: 46px;
  border-radius: 50%;
  display: grid;
  place-items: center;
  background: rgba(255,255,255,0.16);
  backdrop-filter: blur(8px);            /* static style — never animated */
  -webkit-backdrop-filter: blur(8px);
  border: 1px solid rgba(255,255,255,0.25);
  color: #fff;
}
.card-circle svg { width: 18px; height: 18px; transition: transform var(--fast); }
.card:hover .card-circle svg,
.card:focus-visible .card-circle svg { transform: translateX(3px); }

/* ============================================================
   CATEGORY TILES (home) — one large tile today; the auto-fit
   grid accepts 2–3 future collections without edits.
   ============================================================ */
.cat-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(560px, 100%), 1fr));
  gap: clamp(18px, 2vw, 28px);
}
.cat-tile {
  position: relative;
  display: block;
  aspect-ratio: 16 / 9;
  border-radius: var(--card-radius);
  overflow: hidden;
  background: var(--char);
  box-shadow: 0 24px 48px -30px rgba(2,12,7,0.4);   /* static depth */
  transition: transform 0.45s var(--ease);
}
.cat-tile:hover,
.cat-tile:focus-visible { transform: translateY(-4px); }
.cat-tile > img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  /* frame the lifestyle shot on the lit lamp (it sits upper-left of centre) */
  object-position: 50% 38%;
}
@media (max-width: 720px) { .cat-tile { aspect-ratio: 4 / 5; } }

.cat-info {
  position: absolute;
  top: clamp(20px, 4vw, 36px);
  left: clamp(20px, 4vw, 36px);
  right: clamp(20px, 4vw, 36px);
  z-index: 3;
  pointer-events: none;
}
.cat-title {
  margin-top: 10px;
  font-size: clamp(2rem, 4.5vw, 3.2rem);
  font-weight: 700;
  letter-spacing: -0.02em;
  line-height: 1.05;
  color: #fff;
}
.cat-tile .card-line { max-width: 44ch; font-size: 14px; margin-top: 10px; }
.cat-tile .card-circle {
  left: clamp(20px, 4vw, 36px);
  bottom: clamp(20px, 4vw, 36px);
}
.cat-tile:hover .card-circle svg,
.cat-tile:focus-visible .card-circle svg { transform: translateX(3px); }

/* ============================================================
   SHOP HEAD — compact light header, reused by faq/policies
   (the shop page itself now uses the .ed-* editorial system)
   ============================================================ */
.shop-head { padding-block: clamp(56px, 9vw, 104px) 0; }
.shop-head h1 {
  margin-top: 18px;
  font-size: clamp(2.2rem, 5vw, 3.4rem);
  letter-spacing: -0.025em;
  line-height: 1.05;
}
.shop-sub {
  margin-top: 14px;
  font-size: 15px;
  color: var(--t-light-mut);
  max-width: 52ch;
  line-height: 1.65;
}

/* ============================================================
   STUDIO / STORY — light room, one glowing object
   ============================================================ */
.story { background: var(--bg); }
.story-grid {
  display: grid;
  grid-template-columns: 0.9fr 1.1fr;
  gap: clamp(36px, 6vw, 90px);
  align-items: center;
}
@media (max-width: 880px) { .story-grid { grid-template-columns: 1fr; } }

.story-visual {
  position: relative;
  border-radius: var(--card-radius);
  overflow: hidden;
  background: var(--char-2);
  box-shadow: 0 24px 48px -30px rgba(2,12,7,0.4);   /* static depth */
}
.story-visual img { width: 100%; height: auto; }

.story-copy h2 { margin-top: 18px; }
.story-copy p {
  margin-top: 24px;
  font-size: clamp(1.05rem, 1.5vw, 1.2rem);
  line-height: 1.7;
  color: var(--t-light-body);
  max-width: 52ch;
  font-weight: 400;
}
.story-stats {
  margin-top: 44px;
  display: flex;
  gap: 44px;
  flex-wrap: wrap;
}
.story-cta { margin-top: 36px; }
.stat .num {
  font-size: clamp(1.7rem, 3.2vw, 2.3rem);
  font-weight: 700;
  letter-spacing: -0.02em;
  color: var(--ink);
}
.stat .lbl {
  font-size: 11px;
  letter-spacing: 0.25em;
  text-transform: uppercase;
  color: var(--t-light-mut);
  font-weight: 600;
  margin-top: 6px;
}

/* ============================================================
   FOOTER — dark close (identical on every page)
   ============================================================ */
.footer {
  position: relative;
  overflow: hidden;          /* crops the giant brand mark */
  background:
    radial-gradient(80% 50% at 50% 116%, rgba(255,92,0,0.08), transparent 60%),
    var(--char);
  color: var(--t-dark-hi);
  padding-block: clamp(64px, 9vw, 104px) 0;
}
/* Gantri-style giant brand mark — the square orange logo, nearly full
   width, deliberately cropped by the footer's bottom edge */
.f-giant {
  display: flex;
  justify-content: center;
  align-items: flex-start;   /* keep the mark natural-sized; the wrapper crops it */
  height: clamp(150px, 24vw, 330px);
  margin-top: clamp(40px, 6vw, 72px);
  overflow: hidden;
}
.f-giant img {
  display: block;
  width: min(86vw, 1040px);
  height: auto;              /* square SVG — the wrapper crops its bottom */
}
.footer-top {
  display: grid;
  grid-template-columns: 1.4fr 1fr 1fr 1fr;   /* brand + Shop + Studio + Support */
  gap: 40px;
  padding-bottom: 52px;
  border-bottom: 1px solid var(--hairline);
}
@media (max-width: 720px) { .footer-top { grid-template-columns: 1fr 1fr; gap: 30px; } }
@media (max-width: 480px) { .footer-top { grid-template-columns: 1fr; } }

.footer .f-mark {
  font-weight: 700;
  font-size: clamp(2rem, 5.5vw, 3.4rem);
  letter-spacing: -0.02em;
  line-height: 1;
  color: rgba(245,242,245,0.94);
}
.footer .f-mark .dot { color: var(--orange); }   /* brand period */
.footer .f-tag {
  margin-top: 16px;
  color: var(--t-dark-body);
  font-size: 15px;
  line-height: 1.65;
  max-width: 30ch;
}
.f-col h4 {
  font-size: 11px;
  letter-spacing: 0.25em;
  text-transform: uppercase;
  color: var(--t-dark-mut);
  font-weight: 600;
  margin-bottom: 12px;
}
.f-col a {
  display: block;
  font-size: 14px;
  color: rgba(244,241,236,0.82);
  padding-block: 11px;
  transition: color var(--fast), transform var(--fast);
  width: fit-content;
}
.f-col a:hover { color: var(--t-dark-hi); transform: translateX(3px); }

.footer-bottom {
  margin-top: 28px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  flex-wrap: wrap;
  font-size: 13px;
  color: var(--t-dark-mut);
}
.footer-bottom .made {
  display: inline-flex;
  align-items: center;
  gap: 9px;
}
.footer-bottom .made .flag {
  width: 7px; height: 7px; border-radius: 50%;
  background: var(--sage);
}

/* ============================================================
   PDP — product.html. A light room, Gantri-grade and uncluttered:
   sticky gallery left, options right; the photograph is the one
   dark object on the page. Gallery colourway swaps are opacity-
   only crossfades, decode-gated in ui.js so nothing ever flashes.
   ============================================================ */
.pdp { padding-block: clamp(20px, 3vw, 40px) clamp(72px, 9vw, 120px); }

/* breadcrumb — quiet, tap-friendly */
.crumbs {
  display: flex;
  align-items: center;
  gap: 10px;
  font-size: 12.5px;
  font-weight: 500;
  color: var(--t-light-mut);
  margin-bottom: clamp(14px, 2.5vw, 26px);
}
.crumbs a {
  color: var(--t-light-mut);
  padding-block: 12px;            /* ≥44px tap target on a 1-line crumb */
  transition: color var(--fast);
}
.crumbs a:hover { color: var(--ink); }
.crumbs .sep { opacity: 0.55; }
.crumbs [aria-current] { color: var(--ink); font-weight: 600; }

/* two columns ≥960px; phones stack gallery-first (markup order) */
.pdp-grid {
  display: grid;
  grid-template-columns: 1.05fr 0.95fr;
  gap: clamp(28px, 4.5vw, 72px);
  align-items: start;
}
@media (max-width: 959px) { .pdp-grid { grid-template-columns: 1fr; } }
@media (min-width: 960px) {
  .pdp-gallery { position: sticky; top: 86px; }   /* below the 66px nav */
}

/* the big 4:5 photo — the one rounded, dark object on the page.
   .pdp-hero-img (view-transition-name: product-hero) rides on this
   element so the clicked shop card morphs into it. */
.pdp-stage {
  position: relative;
  aspect-ratio: 4 / 5;
  border-radius: var(--card-radius);
  overflow: hidden;
  background: linear-gradient(180deg, #0A0F0C 0%, #050806 100%);
  box-shadow: 0 24px 48px -30px rgba(2,12,7,0.4);   /* static depth */
}
/* photo-swap crossfade — when the displayed colourway changes, the
   incoming pair fades in OVER the old one (opacity only, ~0.4s);
   the rocker's lit-frame crossfade (.ph-on, 0.5s — shared rule at
   the top of this file) rides inside each pair */
.pdp-stage .photo-pair {
  position: absolute;
  inset: 0;
  transition: opacity 0.4s var(--ease);
}
/* the rocker switches the LIT photo's opacity — nothing else moves */
.pdp-stage.is-on  .ph-on { opacity: 1; }
.pdp-stage.is-off .ph-on { opacity: 0; }
/* focus rings on the dark photograph need the orange, not ink */
.pdp-stage :focus-visible { outline-color: var(--orange); }

.pdp-controls {
  position: absolute;
  z-index: 4;
  left: 16px; bottom: 16px;
}

/* rocker switch — slim pill, the thumb slides on a gentle spring */
.switch {
  cursor: pointer;             /* the inner pill toggles anywhere on its surface */
  position: relative;
  display: inline-grid;
  grid-template-columns: 1fr 1fr;
  background: rgba(2,12,7,0.7);
  border: 1px solid rgba(245,242,245,0.16);
  border-radius: var(--pill);
  padding: 3px;
}
.switch-thumb {
  position: absolute;
  top: 3px; bottom: 3px; left: 3px;
  width: calc(50% - 3px);
  border-radius: var(--pill);
  background: var(--orange);    /* on = active-state orange */
  box-shadow: 0 2px 8px rgba(0,0,0,0.35);   /* static, identical in both states */
  transition: transform 0.35s var(--spring);   /* colour snaps — motion stays transform-only */
}
.switch[data-state="off"] .switch-thumb {
  transform: translateX(100%);
  background: #39413C;
}
.switch .sw-opt {
  position: relative;
  z-index: 2;
  min-width: 58px;
  min-height: 36px;   /* visual; ::before extends the hit area to 46px */
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: rgba(244,241,236,0.66);
  background: transparent;
  border: none;
  border-radius: var(--pill);
  padding: 8px 14px;
  cursor: pointer;
  transition: color var(--fast);
}
.switch .sw-opt::before {
  /* ≥44px tap target without growing the pill */
  content: "";
  position: absolute;
  inset: -5px 0;
}
.switch .sw-opt.active { color: #fff; }
/* the "On" label rides the orange thumb — ink for AA contrast */
.switch[data-state="on"] .sw-opt.active { color: var(--ink); }

.pdp-caption {
  margin-top: 12px;
  font-size: 12px;
  color: var(--t-light-mut);
  letter-spacing: 0.01em;
}

/* --- details column --- */
.pdp-title {
  font-size: clamp(1.9rem, 3.4vw, 2.6rem);
  letter-spacing: -0.025em;
  line-height: 1.08;
}
.pdp-price {
  margin-top: 16px;
  font-size: clamp(1.5rem, 2.4vw, 1.9rem);
  font-weight: 700;
  letter-spacing: -0.02em;
  line-height: 1.15;
  font-variant-numeric: tabular-nums;
}
.pdp-price-split {
  margin-top: 5px;
  font-size: 13px;
  color: var(--t-light-mut);
  font-variant-numeric: tabular-nums;
}
.pdp-desc {
  margin-top: 20px;
  font-size: 15.5px;
  line-height: 1.7;
  color: var(--t-light-body);
  max-width: 46ch;
}

/* option blocks — light-surface kin of the original configurator */
.opt-block { margin-top: 34px; }
.opt-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  margin-bottom: 13px;
}
.opt-label {
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.25em;
  text-transform: uppercase;
  color: var(--t-light-mut);
}
.opt-value {
  font-size: 13px;
  font-weight: 500;
  color: var(--ink);
}

/* texture picker */
.texture-row { display: flex; gap: 10px; }
.tex {
  flex: 1;
  cursor: pointer;
  border: 1px solid var(--line);
  background: rgba(255,255,255,0.55);
  color: var(--ink);
  border-radius: var(--radius);
  padding: 14px 58px 14px 16px;
  min-height: 64px;
  text-align: left;
  transition: border-color 0.25s var(--ease);
  position: relative;
  overflow: hidden;
}
.tex:hover { border-color: var(--ink); }
.tex.active {
  border-color: var(--orange);                 /* active state */
  background: rgba(255,92,0,0.07);
}
.tex .tex-name { font-size: 14px; font-weight: 600; letter-spacing: -0.01em; }
.tex .tex-desc { font-size: 12px; color: var(--t-light-mut); margin-top: 2px; }
.tex .tex-swatch {
  position: absolute;
  right: 16px; top: 50%;
  transform: translateY(-50%);
  width: 30px; height: 30px;
  border-radius: 50%;
  box-shadow: inset 0 0 0 1px rgba(2,12,7,0.12);   /* static */
}
.swatch-ribbed {
  background:
    repeating-linear-gradient(90deg, rgba(2,12,7,0.35) 0 1.5px, transparent 1.5px 5px),
    var(--bone);
}
.swatch-woven {
  background:
    repeating-linear-gradient(45deg, rgba(2,12,7,0.25) 0 1.5px, transparent 1.5px 5px),
    repeating-linear-gradient(-45deg, rgba(2,12,7,0.18) 0 1.5px, transparent 1.5px 5px),
    var(--bone);
}

/* colour swatches — slim chips, quiet borders, 0.25s selection ring */
.swatches { display: flex; flex-wrap: wrap; gap: 8px; }
.sw {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  min-height: 44px;            /* full-size tap target */
  padding: 7px 14px 7px 8px;
  border-radius: var(--pill);
  border: 1px solid var(--line);
  background: rgba(255,255,255,0.55);
  color: var(--t-light-body);
  font-size: 13px;
  font-weight: 500;
  cursor: pointer;
  transition: border-color 0.25s var(--ease), color 0.25s var(--ease), transform 0.25s var(--ease);
}
.sw:hover { border-color: var(--ink); color: var(--ink); transform: translateY(-1px); }
.sw.active {
  border-color: var(--orange);                 /* active state */
  background: rgba(255,92,0,0.08);
  color: var(--ink);
}
.sw .sw-dot {
  width: 22px; height: 22px;
  border-radius: 50%;
  flex: none;
  box-shadow: inset 0 0 0 1px rgba(2,12,7,0.14);   /* static */
}

/* size selector — two axes (base + shade), each a row of pill buttons */
.size-axes { display: flex; flex-wrap: wrap; gap: 18px 28px; }
.size-axis { display: flex; align-items: center; gap: 10px; }
.size-axis-label {
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--t-light-mut);
}
.size-opts { display: flex; flex-wrap: wrap; gap: 8px; }
.size-opt {
  min-width: 44px;
  min-height: 44px;
  padding: 7px 16px;
  border-radius: var(--pill);
  border: 1px solid var(--line);
  background: rgba(255,255,255,0.55);
  color: var(--t-light-body);
  font-size: 13px;
  font-weight: 600;
  cursor: pointer;
  transition: border-color 0.25s var(--ease), color 0.25s var(--ease), transform 0.25s var(--ease);
}
.size-opt:hover { border-color: var(--ink); color: var(--ink); transform: translateY(-1px); }
.size-opt.active {
  border-color: var(--orange);
  background: rgba(255,92,0,0.08);
  color: var(--ink);
}

/* quiet custom-colour note under the base swatches */
.swatch-note {
  margin-top: 12px;
  font-size: 12px;
  line-height: 1.6;
  color: var(--t-light-mut);
  letter-spacing: 0.01em;
}
.swatch-note a {
  color: var(--t-light-body);
  text-decoration: underline;
  text-underline-offset: 3px;
  transition: color var(--fast);
}
.swatch-note a:hover { color: var(--ink); }

/* ============================================================
   CUSTOM-COLOUR PICKER (PDP) — "Other colours" trigger, the
   selected custom chip, and the Bambu-filament modal. Motion is
   transform/opacity only; 44px tap targets throughout.
   ============================================================ */

/* quiet trigger under each swatch row */
.cc-trigger {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  margin-top: 10px;
  min-height: 44px;
  padding: 7px 16px 7px 10px;
  border-radius: var(--pill);
  border: 1px dashed var(--line);
  background: transparent;
  color: var(--t-light-body);
  font-size: 13px;
  font-weight: 500;
  cursor: pointer;
  transition: border-color 0.25s var(--ease), color 0.25s var(--ease), transform 0.25s var(--ease);
}
.cc-trigger:hover { border-color: var(--ink); color: var(--ink); transform: translateY(-1px); }
.cc-trigger-dot {
  width: 22px; height: 22px;
  border-radius: 50%;
  flex: none;
  /* a tiny conic rainbow reads as "any colour" */
  background: conic-gradient(from 90deg,
    #DE4343, #F7D959, #61C680, #0086D6, #8344B0, #DE4343);
  box-shadow: inset 0 0 0 1px rgba(2,12,7,0.14);
}

/* selected custom chip (mirrors a standard .sw, with a clear ✕) */
.cc-chip-slot:empty { display: none; }
.cc-chip-slot { margin-top: 10px; }
.cc-chip {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  min-height: 44px;
  padding: 6px 6px 6px 9px;
  border-radius: var(--pill);
  border: 1px solid var(--orange);
  background: rgba(255,92,0,0.08);
  color: var(--ink);
  font-size: 13px;
  font-weight: 500;
  max-width: 100%;
}
.cc-chip-dot {
  width: 22px; height: 22px;
  border-radius: 50%;
  flex: none;
  box-shadow: inset 0 0 0 1px rgba(2,12,7,0.14);
}
.cc-chip-dot.is-pale { box-shadow: inset 0 0 0 1px rgba(2,12,7,0.30); }
.cc-chip-label { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.cc-chip-clear {
  flex: none;
  width: 32px; height: 32px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border-radius: 50%;
  border: 0;
  background: transparent;
  color: var(--t-light-mut);
  cursor: pointer;
  transition: background 0.2s var(--ease), color 0.2s var(--ease);
}
.cc-chip-clear svg { width: 15px; height: 15px; }
.cc-chip-clear:hover { background: rgba(2,12,7,0.07); color: var(--ink); }

/* ----- the modal ----- */
.cc-overlay {
  position: fixed;
  inset: 0;
  z-index: 200;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: clamp(16px, 4vw, 40px);
  background: rgba(2, 12, 7, 0.46);
  -webkit-backdrop-filter: blur(4px);
  backdrop-filter: blur(4px);
}
.cc-panel {
  width: min(640px, 100%);
  max-height: min(80vh, 760px);
  display: flex;
  flex-direction: column;
  background: var(--bg);
  border: 1px solid var(--line);
  border-radius: var(--card-radius);
  box-shadow: 0 30px 80px -24px rgba(2, 12, 7, 0.5);
  overflow: hidden;
}
.cc-head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 16px;
  padding: 22px 22px 14px;
}
.cc-title {
  font-size: clamp(1.15rem, 2.4vw, 1.4rem);
  letter-spacing: -0.02em;
  line-height: 1.15;
}
.cc-sub {
  margin-top: 6px;
  font-size: 13px;
  line-height: 1.55;
  color: var(--t-light-mut);
  max-width: 46ch;
}
.cc-close {
  flex: none;
  width: 44px; height: 44px;
  margin: -8px -8px 0 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border-radius: 50%;
  border: 0;
  background: transparent;
  color: var(--t-light-body);
  cursor: pointer;
  transition: background 0.2s var(--ease), color 0.2s var(--ease);
}
.cc-close svg { width: 18px; height: 18px; }
.cc-close:hover { background: rgba(2,12,7,0.07); color: var(--ink); }
.cc-search { padding: 0 22px 14px; }
.cc-search-input {
  width: 100%;
  min-height: 46px;
  padding: 12px 16px;
  border: 1px solid var(--line);
  border-radius: var(--pill);
  background: rgba(255,255,255,0.6);
  color: var(--ink);
  font-family: inherit;
  font-size: 14px;
  transition: border-color 0.2s var(--ease);
}
.cc-search-input::placeholder { color: var(--t-light-mut); }
.cc-search-input:focus { outline: none; border-color: var(--ink); }
.cc-search-input:focus-visible { outline: 2px solid var(--orange); outline-offset: 2px; }

.cc-body {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  padding: 4px 22px 8px;
  /* the one place a scrollbar is allowed to show — styled, quiet */
  scrollbar-width: thin;
  scrollbar-color: rgba(2,12,7,0.22) transparent;
}
.cc-body::-webkit-scrollbar { width: 10px; }
.cc-body::-webkit-scrollbar-thumb {
  background: rgba(2,12,7,0.22);
  border-radius: 100px;
  border: 3px solid var(--bg);
}
.cc-group { padding: 12px 0; border-top: 1px solid var(--line); }
.cc-group:first-child { border-top: 0; }
/* These elements set their own `display`, which out-ranks the UA `[hidden]`
   rule — so closing the modal (overlay.hidden) or filtering the grid
   (chip/group.hidden) would do NOTHING without forcing the hidden state.
   Without this the closed overlay stays a flex layer over the page and
   silently blocks every click. */
.cc-overlay[hidden], .cc-group[hidden], .cc-color[hidden] { display: none !important; }
.cc-group-head {
  display: flex;
  align-items: baseline;
  gap: 10px;
  margin-bottom: 12px;
  flex-wrap: wrap;
}
.cc-group-name {
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--ink);
}
.cc-group-note { font-size: 12px; color: var(--t-light-mut); }
.cc-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(160px, 1fr));
  gap: 8px;
}
.cc-color {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  min-height: 44px;
  padding: 7px 12px 7px 8px;
  border-radius: var(--pill);
  border: 1px solid var(--line);
  background: rgba(255,255,255,0.5);
  color: var(--t-light-body);
  font-size: 13px;
  font-weight: 500;
  text-align: left;
  cursor: pointer;
  transition: border-color 0.2s var(--ease), color 0.2s var(--ease), box-shadow 0.2s var(--ease);
}
.cc-color:hover, .cc-color:focus-visible {
  border-color: var(--ink);
  color: var(--ink);
  box-shadow: 0 0 0 2px rgba(2,12,7,0.06);
}
.cc-color-dot {
  width: 26px; height: 26px;
  border-radius: 50%;
  flex: none;
  box-shadow: inset 0 0 0 1px rgba(2,12,7,0.14);
}
/* very-light swatch gets a hairline so white reads on the off-white panel */
.cc-color-dot.is-pale { box-shadow: inset 0 0 0 1px rgba(2,12,7,0.28); }
/* name + code stack in a column beside the swatch dot */
.cc-color-text { display: flex; flex-direction: column; gap: 1px; min-width: 0; }
/* let long names (e.g. "Oxide Green Metallic") wrap to a second line
   rather than truncating — the full Bambu name stays readable */
.cc-color-name { line-height: 1.18; text-align: left; }
/* the official Bambu filament code — muted, monospace, sits under the name */
.cc-color-code {
  margin-top: 1px;
  font-size: 11px;
  font-weight: 500;
  line-height: 1.1;
  letter-spacing: 0.02em;
  color: var(--t-light-mut);
  font-family: ui-monospace, "SF Mono", "Roboto Mono", Menlo, monospace;
}
.cc-color { align-items: center; }
.cc-empty {
  padding: 28px 4px;
  text-align: center;
  font-size: 14px;
  color: var(--t-light-mut);
}
.cc-foot {
  display: flex;
  justify-content: flex-end;
  gap: 10px;
  padding: 14px 22px calc(14px + env(safe-area-inset-bottom));
  border-top: 1px solid var(--line);
}
.cc-done {
  min-height: 44px;
  padding: 11px 26px;
  border-radius: var(--pill);
  border: 1px solid var(--line);
  background: var(--ink);
  color: var(--t-dark-hi);
  font-size: 14px;
  font-weight: 600;
  cursor: pointer;
  transition: transform 0.2s var(--ease), opacity 0.2s var(--ease);
}
.cc-done:hover { transform: translateY(-1px); }
body.cc-open { overflow: hidden; }

/* entrance motion — transform/opacity only, opt-in */
@media (prefers-reduced-motion: no-preference) {
  .cc-overlay { animation: cc-fade 0.2s var(--ease); }
  .cc-panel { animation: cc-rise 0.28s var(--ease); }
}
@keyframes cc-fade { from { opacity: 0; } to { opacity: 1; } }
@keyframes cc-rise {
  from { opacity: 0; transform: translateY(14px) scale(0.985); }
  to   { opacity: 1; transform: none; }
}

/* mobile: full-height bottom sheet */
@media (max-width: 600px) {
  .cc-overlay { padding: 0; align-items: stretch; }
  .cc-panel {
    width: 100%;
    max-height: 92vh;
    margin-top: auto;
    border-radius: var(--card-radius) var(--card-radius) 0 0;
    border-bottom: 0;
  }
  .cc-grid { grid-template-columns: repeat(auto-fill, minmax(140px, 1fr)); }
  @media (prefers-reduced-motion: no-preference) {
    .cc-panel { animation: cc-sheet 0.3s var(--ease); }
  }
}
@keyframes cc-sheet {
  from { transform: translateY(100%); }
  to   { transform: none; }
}

/* dimensions — clean ruled rows, values from DIMENSIONS in data.js */
.dims { display: grid; }
.dims-row {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 16px;
  padding-block: 12px;
  border-bottom: 1px solid var(--line);
}
.dims-row:first-child { border-top: 1px solid var(--line); }
.dims-row dt {
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--t-light-mut);
}
.dims-row dd {
  margin: 0;
  font-size: 14px;
  font-weight: 500;
  color: var(--ink);
  font-variant-numeric: tabular-nums;
}

/* meta rows — lead time, material */
.pdp-meta {
  list-style: none;
  margin-top: 28px;
  display: grid;
  gap: 10px;
}
.pdp-meta li {
  display: flex;
  align-items: center;
  gap: 9px;
  font-size: 13.5px;
  font-weight: 500;
  color: var(--t-light-body);
}
.pdp-meta .pip {
  width: 7px; height: 7px; border-radius: 50%;
  background: var(--sage);
  flex: none;
}

/* the one big orange action on the page */
.btn-wa {
  margin-top: 26px;
  width: 100%;
  justify-content: center;
  background: var(--orange);
  color: var(--ink);   /* ink on orange = 6.4:1, passes AA */
  box-shadow: 0 12px 32px -10px rgba(255,92,0,0.5);   /* static */
  min-height: 54px;
  padding: 15px 26px;
}
.btn-wa:hover { transform: translateY(-2px); }
.note-indicative {
  margin-top: 14px;
  font-size: 11.5px;
  color: var(--t-light-mut);
  text-align: center;
  letter-spacing: 0.01em;
}

/* --- mobile sticky buy bar — price + order, safe-area padded --- */
.pdp-buybar {
  position: fixed;
  left: 0; right: 0; bottom: 0;
  z-index: 90;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 14px;
  padding: 10px var(--pad) calc(10px + env(safe-area-inset-bottom));
  background: rgba(245, 242, 245, 0.96);   /* near-opaque solid, no blur on phones */
  border-top: 1px solid var(--line);
}
@media (min-width: 960px) { .pdp-buybar { display: none; } }
/* clear the fixed bar so the footer's last line is never hidden */
@media (max-width: 959px) {
  body.pdp-page { padding-bottom: calc(72px + env(safe-area-inset-bottom)); }
}
.buybar-label {
  display: block;
  font-size: 10px;
  font-weight: 600;
  letter-spacing: 0.25em;
  text-transform: uppercase;
  color: var(--t-light-mut);
}
.buybar-price {
  display: block;
  font-size: 1.25rem;
  font-weight: 700;
  letter-spacing: -0.02em;
  line-height: 1.2;
  font-variant-numeric: tabular-nums;
}
.pdp-buybar .btn { flex: none; }

/* ============================================================
   REVEAL-ON-SCROLL — safe by construction:
   elements are only hidden once JS has tagged <html class="js">,
   so without JS everything is simply visible.
   ============================================================ */
.reveal { opacity: 1; transform: none; }
html.js .reveal {
  opacity: 0;
  transform: translateY(20px);
  transition: opacity 0.9s var(--ease), transform 0.9s var(--ease);
}
html.js .reveal.in { opacity: 1; transform: none; }

/* ============================================================
   VIEW TRANSITIONS — page-to-page cross-fade + shared-element
   morph. Motion-sensitive users never opt in: the whole block
   lives inside the no-preference media query. Browsers without
   cross-document view transitions simply navigate instantly.
   ============================================================ */
@media (prefers-reduced-motion: no-preference) {
  @view-transition { navigation: auto; }

  ::view-transition-old(root),
  ::view-transition-new(root) { animation-duration: 0.35s; }

  /* the clicked card's photo (named by ui.js just before navigation)
     morphs into the PDP gallery image, which statically carries
     view-transition-name: product-hero via .pdp-hero-img */
  ::view-transition-old(product-hero),
  ::view-transition-new(product-hero) { animation-duration: 0.45s; }

  .pdp-hero-img { view-transition-name: product-hero; }
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation: none !important;
    transition: none !important;
    scroll-behavior: auto !important;
  }
  html.js .reveal { opacity: 1; transform: none; }
}

/* no visible scrollbars anywhere — scrolling itself is untouched */
::-webkit-scrollbar { width: 0; height: 0; display: none; }

/* ---------- How ordering works ---------- */
.how-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: clamp(18px, 2vw, 28px);
  list-style: none;
  counter-reset: none;
}
@media (max-width: 880px) { .how-grid { grid-template-columns: 1fr; } }
.how-step {
  border-top: 1px solid rgba(2, 12, 7, 0.14);
  padding-top: 22px;
}
.how-num {
  display: block;
  font-size: 13px;
  font-weight: 700;
  letter-spacing: 0.12em;
  color: var(--orange);
}
.how-step h3 { font-size: 1.18rem; margin: 12px 0 8px; }
.how-step p { font-size: 14.5px; line-height: 1.65; color: var(--t-light-mut); max-width: 38ch; }

/* ============================================================
   STUDIO PAGE (studio.html) — dark intro band + process strip.
   Reuses the home .hero surface; motion stays transform/opacity.
   ============================================================ */
/* compact dark band — the nav (nav-on-dark) floats over its top */
.studio-hero-inner {
  padding-block: clamp(120px, 16vw, 180px) clamp(64px, 9vw, 110px);
  max-width: 780px;
}
.studio-hero h1 {
  margin-top: 24px;
  font-size: clamp(2.6rem, 6.4vw, 4.8rem);
  font-weight: 700;
  line-height: 1.04;
  letter-spacing: -0.03em;
}
.studio-hero .hero-sub { max-width: 52ch; }

/* the story prose reuses .story-copy; this only sizes the column */
.studio-story { max-width: 720px; }

/* process strip — model → print → finish, three captioned photos */
.process-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: clamp(18px, 2vw, 28px);
}
@media (max-width: 720px) { .process-grid { grid-template-columns: 1fr; } }
.process-step { margin: 0; }
.process-media {
  aspect-ratio: 4 / 3;
  border-radius: var(--card-radius);
  overflow: hidden;
  background: #E8E3DA;
}
.process-media img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: transform 0.6s var(--ease);   /* transform only */
}
.process-step:hover .process-media img { transform: scale(1.04); }
.process-step figcaption {
  display: flex;
  align-items: baseline;
  gap: 10px;
  padding: 14px 4px 0;
  font-size: 13.5px;
  line-height: 1.6;
  color: var(--t-light-mut);
}
.process-step .step-num {
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.12em;
  color: var(--orange);
  flex: none;
}

/* ============================================================
   CTA BAND — dark close used by content pages (studio.html)
   ============================================================ */
.cta-band {
  background:
    radial-gradient(90% 60% at 50% 118%, rgba(255, 92, 0, 0.12), transparent 60%),
    var(--char);
  color: var(--t-dark-hi);
}
.cta-inner {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
}
.cta-inner h2 { margin-top: 18px; max-width: 16ch; }
.cta-actions {
  margin-top: 36px;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 16px;
  flex-wrap: wrap;
}

/* ============================================================
   FAQ (faq.html) — native <details>/<summary> accordion.
   No JS; the open marker rotates (transform only).
   ============================================================ */
.faq-body, .policy-body { padding-block: clamp(32px, 5vw, 52px) clamp(96px, 12vw, 160px); }
.faq-wrap { max-width: 780px; }
.faq-group + .faq-group { margin-top: clamp(44px, 6vw, 72px); }
.faq-group h2 {
  font-size: clamp(1.3rem, 2.2vw, 1.6rem);
  margin-bottom: 14px;
}
.faq-item { border-bottom: 1px solid var(--line); }
.faq-item:first-of-type { border-top: 1px solid var(--line); }
.faq-item summary {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 18px;
  padding-block: 18px;            /* ≥44px target on a one-line question */
  font-size: 16px;
  font-weight: 600;
  letter-spacing: -0.01em;
  color: var(--ink);
  cursor: pointer;
  list-style: none;               /* we draw our own marker */
  transition: color var(--fast);
}
.faq-item summary::-webkit-details-marker { display: none; }
.faq-item summary:hover { color: var(--orange); }
.faq-item summary::after {
  content: "+";                  /* fallback for older Safari */
  content: "+" / "";             /* decorative — hidden from screen readers */
  flex: none;
  font-size: 19px;
  font-weight: 400;
  line-height: 1;
  color: var(--t-light-mut);
  transition: transform 0.3s var(--ease);   /* transform only */
}
.faq-item[open] summary::after { transform: rotate(45deg); }
.faq-item p {
  padding: 0 0 22px;
  max-width: 58ch;
  font-size: 15px;
  line-height: 1.7;
  color: var(--t-light-body);
}
.faq-foot, .policy-foot {
  margin-top: clamp(40px, 6vw, 60px);
  font-size: 14.5px;
  color: var(--t-light-mut);
}
.faq-foot a, .policy-foot a, .faq-item p a, .policy-block p a {
  color: var(--t-light-body);
  text-decoration: underline;
  text-underline-offset: 3px;
  transition: color var(--fast);
}
.faq-foot a:hover, .policy-foot a:hover,
.faq-item p a:hover, .policy-block p a:hover { color: var(--ink); }

/* ============================================================
   POLICIES (policies.html) — short ruled clauses, no legalese
   ============================================================ */
.policy-wrap { max-width: 720px; }
.policy-block {
  border-top: 1px solid var(--line);
  padding-top: 26px;
}
.policy-block + .policy-block { margin-top: clamp(40px, 6vw, 60px); }
.policy-block h2 { font-size: clamp(1.3rem, 2.2vw, 1.6rem); }
.policy-block p {
  margin-top: 14px;
  max-width: 58ch;
  font-size: 15.5px;
  line-height: 1.7;
  color: var(--t-light-body);
}

/* ---------- footer social icons ---------- */
.f-logo { height: 42px; width: auto; margin-bottom: 18px; }
.f-social { display: flex; gap: 10px; margin-top: 18px; }
.f-social a {
  display: grid;
  place-items: center;
  width: 44px; height: 44px;
  border: 1px solid var(--hairline);
  border-radius: var(--pill);
  color: var(--t-dark-mut);
  transition: color 0.25s ease, border-color 0.25s ease, transform 0.3s var(--ease);
}
.f-social a:hover { color: var(--orange); border-color: rgba(255, 92, 0, 0.4); transform: translateY(-2px); }
.f-social svg { width: 19px; height: 19px; }

/* ---------- LIGHTS-ON mode — the shop icebreaker ----------
   One click: the room goes dark and every lamp in the grid
   switches on (the lit frames simply fade up — opacity only). */
/* floating switch — fixed bottom-right, frosted so it reads in BOTH modes,
   always reachable at any scroll depth (the user must never miss it) */
.lights-fab {
  position: fixed;
  right: clamp(16px, 3vw, 30px);
  bottom: calc(clamp(16px, 3vw, 30px) + env(safe-area-inset-bottom, 0px));
  z-index: 80;                       /* under the veil (90) and nav (100) */
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 10px 12px 10px 18px;
  border-radius: var(--pill);
  background: rgba(8, 14, 11, 0.55);
  backdrop-filter: blur(18px) saturate(160%);
  -webkit-backdrop-filter: blur(18px) saturate(160%);
  border: 1px solid rgba(245, 242, 245, 0.16);
  box-shadow: 0 18px 40px -18px rgba(2, 12, 7, 0.5);
}
.lights-fab-label {
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: rgba(245, 242, 245, 0.75);
}
/* ============================================================
   PAGE-SHOP — permanent dark editorial theme. The shop is a dark
   room in BOTH switch states; body.lights-on only drives the
   LAMPS (the lit frames' opacity), never the page theme.
   ============================================================ */
body.page-shop { background: var(--char); color: var(--t-dark-hi); }
/* the switch owns the lamps — every lit frame fades up together */
body.lights-on .photo-pair .ph-on { opacity: 1; }

/* dark-room defaults */
body.page-shop .eyebrow { color: var(--t-dark-mut); }
body.page-shop .rule-top::before { background: var(--hairline); }
body.page-shop :focus-visible { outline-color: var(--orange); }

/* --- nav on shop: permanently on-dark. The SCROLLED tint must be a
   DARK frosted pane (never the site's off-white) so the light nav
   text keeps reading; the blur itself rides the shared
   .nav.scrolled desktop rule. --- */
body.page-shop .nav::before { background: rgba(8, 14, 11, 0.7); }
body.page-shop .wordmark,
body.page-shop .nav-links > a,
body.page-shop .nav-links .nav-item > a { color: var(--t-dark-hi); }
body.page-shop .nav-links > a:hover,
body.page-shop .nav-links .nav-item > a:hover { color: #fff; }
body.page-shop .nav-links > a::after,
body.page-shop .nav-links .nav-item > a::after { background: var(--t-dark-hi); }
body.page-shop .nav-cart {
  color: var(--t-dark-hi);
  border-color: rgba(245, 242, 245, 0.32);
  background: transparent;
}
body.page-shop .nav-cart:hover { border-color: rgba(245, 242, 245, 0.7); }
body.page-shop .nav-burger {
  color: var(--t-dark-hi);
  border-color: rgba(245, 242, 245, 0.3);
  background: rgba(245, 242, 245, 0.06);
}

/* ============================================================
   SHOP · EDITORIAL — intro story, numbered base sections and the
   magazine mosaic. No reveal-hiding anywhere on this page: every
   tile is visible at first paint. Motion is transform/opacity only.
   ============================================================ */
/* --- intro / story --- */
.ed-intro { padding-block: clamp(120px, 16vw, 180px) clamp(36px, 5vw, 56px); }
.ed-intro h1 {
  margin-top: 22px;
  font-size: clamp(2.6rem, 6vw, 4.5rem);
  letter-spacing: -0.03em;
  line-height: 1.04;
  color: var(--t-dark-hi);
}
.ed-story { margin-top: 28px; max-width: 58ch; }
.ed-story p {
  font-size: clamp(1.02rem, 1.4vw, 1.15rem);
  line-height: 1.75;
  color: var(--t-dark-body);
}
.ed-story p + p { margin-top: 16px; }
.ed-meta {
  margin-top: 26px;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--t-dark-mut);
}

/* --- numbered section header — ONE composition for all four sections:
   ghosted index + name on a shared baseline, counted label in small
   caps beneath the name, the blurb a narrow right-aligned column.
   ONE hairline above each section; the split between padding-bottom
   and padding-top keeps a consistent clamp(96px,10vw,150px) of air
   between sections. Sections are anchor targets (#cloud …). --- */
.ed-section { padding-block: clamp(48px, 5vw, 75px); scroll-margin-top: 90px; }
.ed-head {
  display: flex;
  align-items: baseline;
  gap: clamp(18px, 3vw, 40px);
  border-top: 1px solid var(--hairline);
  padding-top: clamp(24px, 3vw, 36px);
  margin-bottom: clamp(36px, 5vw, 64px);
}
.ed-index {
  flex: none;
  font-size: clamp(2.8rem, 7vw, 5.6rem);
  font-weight: 700;
  line-height: 0.9;
  letter-spacing: -0.04em;
  color: rgba(244, 241, 236, 0.2);
  font-variant-numeric: tabular-nums;
}
.ed-head-copy { min-width: 0; }
.ed-head h2 {
  font-size: clamp(2rem, 4.6vw, 3.4rem);
  letter-spacing: -0.03em;
  color: var(--t-dark-hi);
}
.ed-count {
  display: block;
  margin-top: 12px;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--t-dark-mut);
}
.ed-blurb {
  margin-left: auto;
  font-size: 15px;
  line-height: 1.65;
  color: var(--t-dark-mut);
  max-width: 36ch;
  text-align: right;
}

/* --- the mosaic: a 12-col magazine grid, never a uniform card wall.
   EVERY frame is portrait (the photographs are native 4:5) — the
   magazine variation comes from SCALE and VERTICAL STAGGER, never
   from aspect distortion. Slots are placed explicitly (auto-placement
   could strand a tile a row too low when the hero flips sides);
   stagger offsets ride the slot classes so ed-flip keeps the rhythm. --- */
.ed-mosaic {
  display: grid;
  grid-template-columns: repeat(12, 1fr);
  gap: clamp(40px, 5vw, 72px) clamp(16px, 2vw, 28px);
  align-items: start;
}
/* 5-piece sections — row 1: hero 7 + companion 5 dropped (the editorial
   stagger); row 2: thirds 4/4/4 with the middle one dipped */
.ed-m5 .slot-a { grid-column: 1 / 8;  grid-row: 1; }
.ed-m5 .slot-b { grid-column: 8 / 13; grid-row: 1; margin-top: clamp(40px, 6vw, 96px); }
.ed-m5 .slot-c { grid-column: 1 / 5;  grid-row: 2; }
.ed-m5 .slot-d { grid-column: 5 / 9;  grid-row: 2; margin-top: clamp(28px, 4vw, 64px); }
.ed-m5 .slot-e { grid-column: 9 / 13; grid-row: 2; }
/* 4-piece sections — row 1 mirrors the 5-piece pattern; row 2: 5 + 7,
   the narrow one dipped, the wide one the designated 3:4 accent */
.ed-m4 .slot-a { grid-column: 1 / 8;  grid-row: 1; }
.ed-m4 .slot-b { grid-column: 8 / 13; grid-row: 1; margin-top: clamp(40px, 6vw, 96px); }
.ed-m4 .slot-c { grid-column: 1 / 6;  grid-row: 2; margin-top: clamp(28px, 4vw, 64px); }
.ed-m4 .slot-d { grid-column: 6 / 13; grid-row: 2; }
/* ed-flip mirrors the column order — offsets stay with their slots */
.ed-m4.ed-flip .slot-a { grid-column: 6 / 13; }
.ed-m4.ed-flip .slot-b { grid-column: 1 / 6; }
.ed-m4.ed-flip .slot-c { grid-column: 8 / 13; }
.ed-m4.ed-flip .slot-d { grid-column: 1 / 8; }

/* --- tiles: whole tile is one link; caption sits BELOW the photo --- */
.ed-tile { display: block; min-width: 0; }
.ed-media {
  position: relative;
  display: block;
  overflow: hidden;
  border-radius: var(--card-radius);
  background: linear-gradient(180deg, var(--char-2) 0%, var(--char) 100%);
  box-shadow: 0 24px 48px -30px rgba(0, 0, 0, 0.55);   /* static depth */
  aspect-ratio: 4 / 5;          /* the photographs' native ratio — never cropped */
}
/* the ONLY sanctioned deviation: a 3:4 accent frame — still portrait,
   a whisker of side-crop, the lamp stays whole. NO 1:1 / landscape
   product frames exist on this page. */
.as-45 { aspect-ratio: 4 / 5; }
.ed-media.as-34 { aspect-ratio: 3 / 4; }
/* hover: the photo eases to 1.03 INSIDE its frame (transform only) and
   the caption title brightens — nothing else. Both frames move together;
   the lit frame ALSO keeps its slow 1.8s switch fade — per-property
   transitions so neither steals the other. */
.ed-media img { transition: transform 0.6s var(--ease); }
.ed-media .ph-on { transition: opacity 1.8s var(--ease), transform 0.6s var(--ease); }
.ed-tile:hover .ed-media img,
.ed-tile:focus-visible .ed-media img { transform: scale(1.03); }
.ed-tile:focus-visible { border-radius: var(--card-radius); }

/* magazine caption — ONE hierarchy on every tile: title, then a single
   line of price · dots · "+ custom". 14px under the photo, 6px between. */
.ed-caption { display: block; padding: 14px 2px 0; }
.ed-title {
  display: block;
  font-size: 17px;
  font-weight: 600;
  letter-spacing: -0.01em;
  color: rgba(244, 241, 236, 0.88);
  transition: color var(--fast);
}
.ed-tile:hover .ed-title,
.ed-tile:focus-visible .ed-title { color: #fff; }
.ed-line {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 6px 12px;
  margin-top: 6px;
}
.ed-price {
  display: block;
  font-size: 13px;
  line-height: 1.5;
  color: var(--t-dark-mut);
  font-variant-numeric: tabular-nums;
}
.ed-dots {
  display: inline-flex;
  align-items: center;
  gap: 8px;
}
.ed-dot {
  width: 12px; height: 12px;
  border-radius: 50%;
  flex: none;
  box-shadow: inset 0 0 0 1px rgba(245, 242, 245, 0.2);   /* static */
}
.ed-custom {
  margin-left: 6px;
  font-size: 11.5px;
  color: var(--t-dark-mut);
  white-space: nowrap;
}

/* --- 04 · Totem: full-width editorial split — 6-col image (4:5,
   uncropped) + 5-col copy dropped by the same stagger as the mosaics.
   The copy is a clean vertical STACK with explicit spacing: lede →
   title → price line → dots row → "View piece" on its own line —
   nothing shares a line, nothing can overlap at any width. --- */
.ed-split {
  display: grid;
  grid-template-columns: repeat(12, 1fr);
  gap: clamp(28px, 4vw, 48px) clamp(16px, 2vw, 28px);
  align-items: start;
}
.ed-split .slot-split { grid-column: 1 / 7; }
.ed-split-copy {
  grid-column: 8 / 13;
  max-width: 44ch;
  margin-top: clamp(40px, 6vw, 96px);   /* the editorial stagger */
}
.ed-split-lede {
  font-size: clamp(1.05rem, 1.5vw, 1.25rem);
  line-height: 1.7;
  color: var(--t-dark-body);
}
.ed-split-title {
  margin-top: 24px;
  font-size: clamp(1.4rem, 2.4vw, 1.9rem);
  font-weight: 700;
  letter-spacing: -0.02em;
  color: var(--t-dark-hi);
}
.ed-split-copy .ed-price { margin-top: 10px; font-size: 14px; }
/* the dots become their own block-level row in the stack — the
   "+ custom" tail is a flex item inside it, never floated */
.ed-split-copy .ed-dots { display: flex; margin-top: 14px; }
.ed-view {
  display: inline-flex;          /* block-level neighbours put it on its own line */
  align-items: center;
  gap: 10px;
  margin-top: 28px;
  min-height: 44px;            /* full-size tap target */
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--t-dark-hi);
  border-bottom: 1px solid rgba(245, 242, 245, 0.35);
  transition: color var(--fast), border-color var(--fast);
}
.ed-view svg { width: 16px; height: 16px; transition: transform var(--fast); }
.ed-view:hover { color: var(--orange); border-color: rgba(255, 92, 0, 0.5); }
.ed-view:hover svg { transform: translateX(3px); }

/* --- phones: one column, EVERY tile 4:5, stagger off, consistent gap --- */
@media (max-width: 720px) {
  .ed-intro { padding-top: clamp(104px, 24vw, 140px); }
  .ed-mosaic, .ed-split { grid-template-columns: 1fr; gap: clamp(36px, 9vw, 48px); }
  .ed-mosaic [class*="slot-"],
  .ed-mosaic.ed-flip [class*="slot-"],   /* outranks the .ed-m4.ed-flip slot rules */
  .ed-split [class*="slot-"],
  .ed-split-copy { grid-column: auto; grid-row: auto; margin-top: 0; }
  .ed-split-copy { max-width: none; }
  .ed-media.as-34 { aspect-ratio: 4 / 5; }   /* the accent frame folds back to 4:5 */
  .ed-head { flex-wrap: wrap; }
  .ed-blurb { margin-left: 0; max-width: 52ch; text-align: left; flex-basis: 100%; }
}

/* ---------- shop intro split — story beside a lived-in photograph ----------
   6/5 editorial split; the photo carries the same stagger language as the
   mosaics below it. Mobile stacks copy-first (content priority). */
.ed-intro-grid {
  display: grid;
  grid-template-columns: 6fr 5fr;
  gap: clamp(32px, 5vw, 96px);
  align-items: start;
}
.ed-intro-photo {
  margin: 0;
  margin-top: clamp(24px, 3.5vw, 64px);   /* the editorial offset */
}
.ed-intro-photo img {
  width: 100%;
  height: auto;
  aspect-ratio: 4 / 5;
  object-fit: cover;
  object-position: 50% 38%;                /* keep the lamp + book stack */
  border-radius: var(--card-radius);
  display: block;
}
.ed-intro-photo figcaption {
  margin-top: 12px;
  font-size: 12.5px;
  letter-spacing: 0.04em;
  color: var(--t-dark-mut);
}
@media (max-width: 880px) {
  .ed-intro-grid { grid-template-columns: 1fr; gap: 36px; }
  .ed-intro-photo { margin-top: 0; }
}

/* ============================================================
   MEGA-MENU — "Build your own" closing link, styled slightly
   apart from the collection links (orange, breathing room above)
   ============================================================ */
.nav .nav-links .mega-col a.mega-build { color: var(--orange); margin-top: 8px; }
.nav .nav-links .mega-col a.mega-build:hover { color: #fff; }

/* ============================================================
   "BEYOND THE FIFTEEN" — quiet builder CTA band on the shop
   (the dark page provides the background; this only composes)
   ============================================================ */
.cta-line {
  margin-top: 16px;
  max-width: 52ch;
  font-size: 15.5px;
  line-height: 1.7;
  color: var(--t-dark-mut);
}
.beyond-cta .btn { margin-top: 32px; }

/* ============================================================
   BUILDER (builder.html) — "Build your own Kumo".
   A dark editorial page consistent with the shop: body carries
   page-shop (permanent nav-on-dark + var(--char) background) and
   page-builder scopes everything below. Two columns ≥960px —
   choices left, sticky live summary right. The builder UI is
   never reveal-hidden; all motion is transform/opacity only.
   ============================================================ */
.bld-intro { padding-block: clamp(110px, 14vw, 160px) clamp(32px, 4vw, 52px); }
.bld-intro h1 {
  margin-top: 18px;
  font-size: clamp(2rem, 4.6vw, 3.4rem);
  letter-spacing: -0.025em;
  max-width: 16ch;
}
.bld-lede {
  margin-top: 18px;
  max-width: 56ch;
  font-size: 15.5px;
  line-height: 1.7;
  color: var(--t-dark-mut);
}

/* --- layout: steps left, sticky summary right (markup is
   summary-first so phones get the photo above the steps) --- */
.bld-grid {
  display: grid;
  gap: clamp(28px, 4vw, 72px);
  align-items: start;
  padding-bottom: clamp(72px, 9vw, 120px);
}
@media (min-width: 960px) {
  .bld-grid { grid-template-columns: 1.05fr 0.95fr; }
  .bld-steps   { grid-column: 1; grid-row: 1; }
  .bld-summary { grid-column: 2; grid-row: 1; position: sticky; top: 86px; }
}

/* --- steps --- */
.bld-step + .bld-step { margin-top: clamp(44px, 5vw, 64px); }
.bld-step-head {
  display: flex;
  align-items: baseline;
  gap: 14px;
}
.bld-num {
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.18em;
  color: var(--t-dark-mut);
  font-variant-numeric: tabular-nums;
}
.bld-step h2 { font-size: clamp(1.35rem, 2.3vw, 1.7rem); letter-spacing: -0.02em; }
.bld-step-sub {
  margin-top: 8px;
  font-size: 13.5px;
  line-height: 1.6;
  color: var(--t-dark-mut);
  max-width: 52ch;
}

/* pills — design row + size row (size shows letter · price) */
.pills { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 18px; }
.pill {
  min-height: 44px;                       /* full-size tap target */
  padding: 10px 18px;
  border-radius: var(--pill);
  border: 1px solid var(--hairline);
  background: rgba(245, 242, 245, 0.05);
  color: var(--t-dark-body);
  font-size: 13.5px;
  font-weight: 500;
  cursor: pointer;
  transition: border-color 0.25s var(--ease), color 0.25s var(--ease),
              background-color 0.25s var(--ease), transform 0.25s var(--ease);
}
.pill:hover { border-color: rgba(245, 242, 245, 0.6); color: var(--t-dark-hi); transform: translateY(-1px); }
.pill.active {
  border-color: var(--orange);            /* active state */
  background: rgba(255, 92, 0, 0.12);
  color: var(--t-dark-hi);
}
.pill .pill-price { color: var(--t-dark-mut); font-variant-numeric: tabular-nums; }
.pill.active .pill-price { color: var(--t-dark-body); }

/* the chosen part's dims line under each size row */
.bld-dimline {
  margin-top: 14px;
  font-size: 12.5px;
  letter-spacing: 0.01em;
  color: var(--t-dark-mut);
  font-variant-numeric: tabular-nums;
}

/* --- step 03 reuses the PDP chip components on the dark surface --- */
.page-builder .opt-label { color: var(--t-dark-mut); }
.page-builder .opt-value { color: var(--t-dark-hi); }
.page-builder .tex {
  background: rgba(245, 242, 245, 0.04);
  border-color: var(--hairline);
  color: var(--t-dark-hi);
}
.page-builder .tex:hover { border-color: rgba(245, 242, 245, 0.6); }
.page-builder .tex.active { border-color: var(--orange); background: rgba(255, 92, 0, 0.1); }
.page-builder .tex .tex-desc { color: var(--t-dark-mut); }
.page-builder .sw {
  background: rgba(245, 242, 245, 0.04);
  border-color: var(--hairline);
  color: var(--t-dark-body);
}
.page-builder .sw:hover { border-color: rgba(245, 242, 245, 0.6); color: var(--t-dark-hi); }
.page-builder .sw.active {
  border-color: var(--orange);
  background: rgba(255, 92, 0, 0.12);
  color: var(--t-dark-hi);
}
.page-builder .swatch-note { color: var(--t-dark-mut); }
.page-builder .swatch-note a { color: var(--t-dark-body); }
.page-builder .swatch-note a:hover { color: var(--t-dark-hi); }

/* --- sticky summary: photo, captions, title, price, dims, order --- */
.bld-stage {
  position: relative;
  aspect-ratio: 4 / 5;
  border-radius: var(--card-radius);
  overflow: hidden;
  background: linear-gradient(180deg, #0A0F0C 0%, #050806 100%);
  box-shadow: 0 24px 48px -30px rgba(0, 0, 0, 0.6);   /* static depth */
}
/* two stacked frames (lit or unlit per the lights switch) — the new
   one decodes, then fades in on top (opacity only) while the old
   stays opaque underneath */
.bld-stage img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  opacity: 0;
  transition: opacity 0.45s var(--ease);
}
.bld-stage img.front { opacity: 1; z-index: 2; }
.bld-stage img.under { opacity: 1; z-index: 1; transition: none; }
/* a lights flip glows over slowly — the same 1.8s as the shop's lamps */
.bld-stage.glow-swap img { transition-duration: 1.8s; }
.bld-stage.glow-swap img.under { transition: none; }

.bld-note {
  margin-top: 10px;
  font-size: 12px;
  letter-spacing: 0.01em;
  color: var(--t-dark-mut);
}
.bld-note + .bld-note { margin-top: 4px; }
.bld-sum-title {
  margin-top: 20px;
  font-size: clamp(1.5rem, 2.6vw, 2rem);
  letter-spacing: -0.02em;
}
.bld-sum-price {
  margin-top: 10px;
  font-size: clamp(1.3rem, 2.2vw, 1.7rem);
  font-weight: 700;
  letter-spacing: -0.02em;
  line-height: 1.15;
  font-variant-numeric: tabular-nums;
}
.bld-sum-split {
  margin-top: 4px;
  font-size: 13px;
  color: var(--t-dark-mut);
  font-variant-numeric: tabular-nums;
}
.bld-dims { margin-top: 20px; }
.page-builder .dims-row { border-color: var(--hairline); }
.page-builder .dims-row:first-child { border-top-color: var(--hairline); }
.page-builder .dims-row dt { color: var(--t-dark-mut); }
.page-builder .dims-row dd { color: var(--t-dark-hi); }

.bld-meta {
  list-style: none;
  margin-top: 22px;
  display: grid;
  gap: 10px;
}
.bld-meta li {
  display: flex;
  align-items: center;
  gap: 9px;
  font-size: 13.5px;
  font-weight: 500;
  color: var(--t-dark-body);
}
.bld-meta .pip {
  width: 7px; height: 7px; border-radius: 50%;
  background: var(--sage);
  flex: none;
}

/* the one big orange action — full-width btn-primary */
.bld-order {
  margin-top: 24px;
  width: 100%;
  justify-content: center;
  min-height: 54px;
  padding: 15px 26px;
  box-shadow: 0 12px 32px -10px rgba(255, 92, 0, 0.5);   /* static */
}
.page-builder .note-indicative { color: var(--t-dark-mut); }

/* --- phones: the summary dissolves — the photo (with captions)
   rides ABOVE the steps, the review card follows them, and price +
   Order live in a fixed bottom bar. The aside's three groups
   (.bld-photo / .bld-card / .bld-ctas) join the page grid via
   display:contents — no duplicate markup, spacing stays internal. --- */
@media (max-width: 959px) {
  .bld-summary { display: contents; }
  .bld-photo { order: 0; }
  .bld-steps { order: 1; }
  .bld-card  { order: 2; }
  /* the bar owns the order action — no duplicate button in the flow */
  .bld-ctas  { display: none; }
  body.page-builder { padding-bottom: calc(72px + env(safe-area-inset-bottom)); }
}

/* fixed bottom bar — dark frosted kin of the PDP buy bar */
.bld-buybar {
  position: fixed;
  left: 0; right: 0; bottom: 0;
  z-index: 90;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 14px;
  padding: 10px var(--pad) calc(10px + env(safe-area-inset-bottom));
  background: rgba(8, 14, 11, 0.92);
  border-top: 1px solid var(--hairline);
}
@media (min-width: 960px) { .bld-buybar { display: none; } }
.bld-buybar .buybar-label { color: var(--t-dark-mut); }
/* the price never wraps — slightly smaller than the PDP's, the bar
   button is tighter, so even "Rp 1.270.000" fits a 360px phone */
.bld-buybar .buybar-price {
  color: var(--t-dark-hi);
  font-size: 1.1rem;
  white-space: nowrap;
}
.bld-buybar .btn { flex: none; padding: 13px 18px; }
/* small screens: the buy bar owns the bottom edge, so the floating
   lights switch rides just above it instead of underneath */
@media (max-width: 959px) {
  body.page-builder .lights-fab {
    bottom: calc(82px + env(safe-area-inset-bottom, 0px));
  }
}

/* ============================================================
   CMS SURFACES — journal page (journal.html), studio objects on
   the shop, and the object PDP view. All of these render ONLY
   from published content.json; none affect the baked pages.
   ============================================================ */

/* --- journal.html — light editorial kin of the home #journal --- */
.journal-empty {
  font-size: 15px;
  color: var(--t-light-mut);
}
.journal-back {
  display: inline-flex;
  align-items: center;
  min-height: 44px;            /* comfortable tap target */
  font-size: 14px;
  font-weight: 600;
  color: var(--t-light-mut);
  transition: color var(--fast);
}
.journal-back:hover { color: var(--ink); }
.journal-article { max-width: 720px; }
.journal-article .post-meta { display: block; margin-top: 10px; }
.ja-title {
  font-size: clamp(1.9rem, 3.4vw, 2.6rem);
  letter-spacing: -0.025em;
  line-height: 1.12;
  margin: 10px 0 20px;
}
.ja-cover {
  border-radius: var(--card-radius);
  overflow: hidden;
  background: #E8E3DA;
  margin: 0 0 26px;
}
.ja-cover img { width: 100%; height: auto; display: block; }
.ja-body p {
  font-size: 16px;
  line-height: 1.75;
  color: var(--t-light-body);
}
.ja-body p + p { margin-top: 1.1em; }
.ja-foot { margin-top: 34px; }

/* --- shop · dashboard-driven collection grid (#shop-collection) —
   the published-object cards reuse the editorial caption hierarchy.
   Same grid is also used by the object PDP "More" rail. --- */
.obj-grid { align-items: start; }
.obj-card .ed-media.as-45 { aspect-ratio: 4 / 5; }
.obj-photo {
  width: 100%;
  height: 100%;
  object-fit: cover;
}
/* object cards carry both lit/unlit frames — reveal the lit one on
   hover/focus, like the baked combo cards. Snappy 0.5s (the .ed-media 1.8s
   fade is for the global lights toggle); the 3-class selectors outrank
   `.ed-media .ph-on` so this transition + reveal win. */
.obj-card .photo-pair .ph-on { transition: opacity 0.5s var(--ease); }
/* object cards stay UNLIT at rest even while body.lights-on is set (it forces
   every other lit frame on), so the lit frame is a pure hover/focus reveal. */
body.lights-on .obj-card .ph-on { opacity: 0; }
/* reveal on hover/focus. The body.lights-on-prefixed selectors (specificity
   0,4,1) MUST outrank the rest rule above (0,3,1) — the `body` type selector
   makes it 0,3,1, so a bare `.obj-card:hover` (0,3,0) would lose. The unprefixed
   selectors cover pages without lights-on. */
body.lights-on .obj-card:hover .ph-on,
body.lights-on .obj-card:focus-visible .ph-on,
body.lights-on .obj-card:focus-within .ph-on,
.obj-card:hover .ph-on,
.obj-card:focus-visible .ph-on,
.obj-card:focus-within .ph-on { opacity: 1; }

/* --- CMS shop mode — once the owner publishes ANY object, the
   dashboard-driven #shop-collection becomes the primary grid and the
   four baked base-shape sections + the .ed-split close, and the lights
   switch (no lit/unlit pairs to drive) is removed from reach. A class
   toggle keeps the fallback byte-identical and the switch reversible. --- */
body.shop-cms #cloud,
body.shop-cms #cone,
body.shop-cms #cylinder,
body.shop-cms #totem,
body.shop-cms .ed-split,
body.shop-cms .lights-fab { display: none; }

/* --- object PDP (?p=slug) — single hero photo + thumb rail --- */
.pdp-stage .obj-hero {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}
.obj-hero-empty { display: block; }    /* the stage gradient shows through */
.obj-thumbs {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  margin-top: 12px;
}
.obj-thumb {
  width: 64px;
  height: 64px;                /* ≥44px tap target */
  padding: 0;
  border: 1px solid var(--line);
  border-radius: var(--card-radius);
  overflow: hidden;
  background: #E8E3DA;
  cursor: pointer;
  opacity: 0.7;
  transition: opacity var(--fast);
}
.obj-thumb img { width: 100%; height: 100%; object-fit: cover; }
.obj-thumb:hover { opacity: 1; }
.obj-thumb.active {
  opacity: 1;
  border-color: var(--ink);
}
.obj-desc { margin-top: 20px; max-width: 46ch; }
.obj-desc p {
  font-size: 15.5px;
  line-height: 1.7;
  color: var(--t-light-body);
}
.obj-desc p + p { margin-top: 0.9em; }
.obj-shop-link { margin-top: 18px; }

/* --- object PDP with COLOURWAYS — reuses the combo PDP's photo-pair
   stage, lights rocker (.pdp-controls/.switch) and colour swatches
   (.swatches/.sw); only the additions live here. A near-white swatch
   dot gets a firmer hairline so it reads on the off-white panel, and
   the rocker hides cleanly for a colour with no off photo. Motion is
   inherited (opacity/transform crossfades) — nothing new moves. --- */
.sw .sw-dot.is-pale { box-shadow: inset 0 0 0 1px rgba(2,12,7,0.30); }
.pdp-controls[hidden] { display: none; }

/* ============================================================
   KUMI (kumi.html) — landing page for the shelving line, and the
   second mega-menu column that points to it. 2026-08-20.
   ============================================================ */
/* the mega card was single-column (display:block); two columns sit side by side */
.mega-inner { display: flex; gap: 56px; }
.mega-col { min-width: 150px; }

.kumi-hero-actions {
  margin-top: 30px;
  display: flex;
  align-items: center;
  gap: 16px;
  flex-wrap: wrap;
}
.kumi-art {
  display: block;
  width: min(680px, 88%);
  height: auto;
  margin: clamp(8px, 2vw, 24px) auto 0;
}
.kumi-facts {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
  gap: clamp(24px, 3vw, 44px);
}
.kumi-fact h3 { font-size: 18px; letter-spacing: -0.01em; margin-bottom: 8px; }
.kumi-fact p { color: var(--t-light-body); font-size: 15px; line-height: 1.65; max-width: 42ch; }
.kumi-steps {
  list-style: none;
  margin: 28px 0 0;
  padding: 0;
  display: grid;
  gap: 14px;
  max-width: 60ch;
}
.kumi-steps li {
  display: flex;
  align-items: baseline;
  gap: 14px;
  font-size: 16.5px;
  line-height: 1.6;
  color: var(--t-light-body);
}
.kumi-step-idx { font-size: 12px; font-weight: 700; letter-spacing: 0.14em; color: var(--orange); }
