/* ============================================================================
   REVAMP - storefront
   ========================================================================= */

/* --------------------------------------------------------------- preloader */

.preloader {
  position: fixed; inset: 0; z-index: 300;
  display: grid; place-items: center;
  background: var(--ink);
  transition: opacity 700ms var(--ease-out), visibility 700ms;
}
.preloader.is-done { opacity: 0; visibility: hidden; pointer-events: none; }

.preloader__mark { width: clamp(120px, 22vw, 190px); filter: drop-shadow(0 0 40px rgba(123 92 255 / 0.55)); }

.preloader__bar {
  margin-top: 2.2rem; width: min(240px, 50vw); height: 2px;
  background: var(--hairline); border-radius: 99px; overflow: hidden;
}
.preloader__fill {
  height: 100%; width: 0%;
  background: var(--accent);
  transition: width 260ms var(--ease-out);
}
.preloader__label {
  margin-top: 1rem; font-family: var(--font-brand); font-weight: 500;
  font-size: 0.88rem; letter-spacing: -0.01em; color: var(--text-faint);
}

/* --------------------------------------------------------------------- nav */

.nav {
  position: fixed; inset: 0 0 auto; z-index: 90;
  display: flex; align-items: center; justify-content: space-between; gap: 1rem;
  padding: 1rem var(--gutter);
  transition: background var(--dur) var(--ease-out), backdrop-filter var(--dur), border-color var(--dur), padding var(--dur);
  border-bottom: 1px solid transparent;
}
.nav.is-stuck {
  color: var(--text);
  background: var(--nav-bg);
  backdrop-filter: blur(20px) saturate(160%);
  border-bottom-color: var(--hairline);
  padding-block: 0.65rem;
}

.nav__brand { display: flex; align-items: center; gap: 0.7rem; }
.nav__brand img { width: 38px; height: 38px; object-fit: contain; }
.nav__brand span {
  font-family: var(--font-display); font-weight: 600;
  font-size: 1.12rem; letter-spacing: -0.02em;
}

.nav__links { display: flex; align-items: center; gap: 2rem; }
.nav__link {
  position: relative; font-size: 0.9rem; font-weight: 500; color: var(--text-dim);
  transition: color var(--dur-fast);
}
.nav__link::after {
  content: ''; position: absolute; left: 0; bottom: -6px; height: 2px; width: 100%;
  background: var(--text); border-radius: 2px;
  transform: scaleX(0); transform-origin: right;
  transition: transform var(--dur) var(--ease-out);
}
.nav__link:hover { color: var(--text); }
.nav__link:hover::after { transform: scaleX(1); transform-origin: left; }

.nav__actions { display: flex; align-items: center; gap: 0.65rem; }

.cart-btn {
  position: relative; display: inline-flex; align-items: center; gap: 0.55rem;
  padding: 0.6rem 1.15rem; border-radius: 99px;
  border: 1px solid var(--hairline-2); background: var(--surface);
  cursor: pointer; font-size: 0.86rem; font-weight: 600;
  backdrop-filter: blur(10px);
  transition: border-color var(--dur-fast), background var(--dur-fast), transform var(--dur-fast);
}
.cart-btn:hover { border-color: var(--blue); background: var(--surface-2); transform: translateY(-1px); }

.cart-btn__count {
  min-width: 20px; height: 20px; padding-inline: 5px;
  display: grid; place-items: center;
  border-radius: 99px; background: var(--accent);
  font-size: 0.72rem; font-weight: 500; color: var(--accent-ink);
  transform: scale(0); transition: transform var(--dur) var(--ease-spring);
}
.cart-btn__count.is-visible { transform: scale(1); }
.cart-btn.is-bumped { animation: bump 420ms var(--ease-spring); }
@keyframes bump { 0%,100% { transform: scale(1); } 40% { transform: scale(1.09); } }

.nav__toggle {
  display: none; width: 42px; height: 42px; border-radius: 12px;
  border: 1px solid var(--hairline-2); background: var(--surface); cursor: pointer;
}
.nav__toggle span {
  display: block; width: 17px; height: 1.5px; margin: 3.5px auto;
  background: var(--text); border-radius: 2px;
  transition: transform var(--dur) var(--ease-out), opacity var(--dur-fast);
}
.nav.is-open .nav__toggle span:nth-child(1) { transform: translateY(5px) rotate(45deg); }
.nav.is-open .nav__toggle span:nth-child(2) { opacity: 0; }
.nav.is-open .nav__toggle span:nth-child(3) { transform: translateY(-5px) rotate(-45deg); }

/* -------------------------------------------------------------------- hero */

.hero {
  position: relative; min-height: 100svh;
  display: grid; align-items: center;
  padding: clamp(6rem, 12vh, 8.5rem) 0 clamp(2.5rem, 6vh, 5rem);
  overflow: hidden;
}

/* The WebGL sunset lives here; a CSS gradient stands in until it boots (and
   permanently if WebGL is unavailable), so the hero is never a black box. */
#hero-canvas {
  position: absolute; inset: 0; width: 100%; height: 100%;
  z-index: 0;
}
.hero__fallback {
  position: absolute; inset: 0; z-index: 0;
  background:
    radial-gradient(120% 68% at 50% 62%, rgba(255 138 61 / 0.42) 0%, transparent 58%),
    radial-gradient(90% 55% at 50% 70%, rgba(255 45 149 / 0.45) 0%, transparent 62%),
    linear-gradient(180deg, #100b28 0%, #2a1149 42%, #6c1f5d 66%, #0a0817 100%);
}
.hero__grain {
  position: absolute; inset: 0; z-index: 2; pointer-events: none;
  opacity: 0.16; mix-blend-mode: overlay;
  background-image: var(--grain);
  background-size: 180px 180px;
}
/* Vignette + fade into the next section. */
.hero::after {
  content: ''; position: absolute; inset: 0; z-index: 2; pointer-events: none;
  /* The sunset is treated as artwork, so these scrims stay dark in both themes.
     Only the final stop uses --ink, so the hero melts into whichever page
     background is active. */
  background:
    linear-gradient(95deg, rgb(var(--shade) / 0.72) 0%, rgb(var(--shade) / 0.34) 34%, transparent 60%),
    radial-gradient(130% 92% at 50% 42%, transparent 48%, rgb(var(--shade) / 0.55) 100%),
    linear-gradient(180deg, rgb(var(--shade) / 0.45) 0%, transparent 24%, transparent 76%, var(--ink) 100%);
}

.hero__inner {
  position: relative; z-index: 3;
  display: grid;
  align-items: center;
}

.hero__badge {
  display: inline-flex; align-items: center; gap: 0.6rem;
  padding: 0.42rem 0.95rem 0.42rem 0.5rem; border-radius: 99px;
  border: 1px solid rgb(255 255 255 / 0.2); background: rgb(5 4 12 / 0.45);
  backdrop-filter: blur(12px);
  font-size: 0.92rem; letter-spacing: -0.012em;
  color: var(--text-dim); margin-bottom: clamp(1rem, 2.5vh, 1.6rem);
}
.hero__badge b { color: var(--text); font-weight: 600; }
.hero__pulse {
  width: 7px; height: 7px; border-radius: 99px; background: var(--ok);
  margin-left: 0.4rem;
  box-shadow: 0 0 0 0 rgba(61 220 151 / 0.7);
  animation: pulse 2.4s var(--ease-out) infinite;
}
@keyframes pulse {
  0%   { box-shadow: 0 0 0 0 rgba(61 220 151 / 0.65); }
  70%  { box-shadow: 0 0 0 11px rgba(61 220 151 / 0); }
  100% { box-shadow: 0 0 0 0 rgba(61 220 151 / 0); }
}

.hero__title {
  font-family: var(--font-display); font-weight: 600;
  font-size: clamp(3rem, min(10vw, 13vh), 7.8rem);
  line-height: 1.04; letter-spacing: -0.035em;
  margin: 0 0 clamp(0.9rem, 2.2vh, 1.5rem);
}
/* Each line is wrapped so it can be masked and swept up independently. */
.hero__line {
  display: block; overflow: hidden;
  padding-bottom: 0.2em; margin-bottom: -0.14em;
}
.hero__line > span { display: block; }

.hero__title .chrome { color: inherit; }

.hero__copy { color: var(--text-dim); font-size: clamp(1rem, 1.6vw, 1.15rem); max-width: 46ch; margin: 0 0 2.2rem; }
.hero__cta { display: flex; flex-wrap: wrap; gap: 0.8rem; margin-bottom: 2.6rem; }

.hero__stats { display: flex; flex-wrap: wrap; gap: clamp(1.5rem, 4vw, 3rem); }



/* Floating product showcase */









/* ----------------------------------------------------------------- marquee */

.marquee {
  position: relative; z-index: 4;
  border-block: 1px solid var(--hairline);
  background: var(--surface);
  padding: 0.9rem 0; overflow: hidden;
  display: flex; gap: 0;
  -webkit-mask-image: linear-gradient(90deg, transparent, #000 8%, #000 92%, transparent);
  mask-image: linear-gradient(90deg, transparent, #000 8%, #000 92%, transparent);
}
.marquee__track {
  display: flex; align-items: center; gap: 3rem; padding-right: 3rem;
  flex-shrink: 0; min-width: 100%;
  animation: slide 34s linear infinite;
  font-family: var(--font-brand); font-weight: 500;
  font-size: 0.92rem; letter-spacing: -0.012em;
  color: var(--text-dim); white-space: nowrap;
}
.marquee:hover .marquee__track { animation-play-state: paused; }
.marquee__track em { color: var(--text-faint); font-style: normal; }
@keyframes slide { to { transform: translateX(-100%); } }

/* ---------------------------------------------------------------- sections */

.section { padding: clamp(5rem, 12vh, 9rem) 0; position: relative; }
.section__head {
  display: flex; flex-wrap: wrap; align-items: flex-end; justify-content: space-between;
  gap: 1.6rem; margin-bottom: clamp(2.4rem, 5vw, 4rem);
}
.section__head > div { max-width: 62ch; }

/* --------------------------------------------------------------- catalogue */

.filters { display: flex; flex-wrap: wrap; gap: 0.5rem; margin-bottom: 2.4rem; }
.filter {
  padding: 0.5rem 1.15rem; border-radius: 99px;
  border: 1px solid var(--hairline); background: transparent;
  color: var(--text-dim); font-size: 0.82rem; font-weight: 500; cursor: pointer;
  transition: color var(--dur-fast), border-color var(--dur-fast), background var(--dur-fast);
}
.filter:hover { color: var(--text); border-color: var(--hairline-2); }
.filter.is-active { color: var(--ink); border-color: transparent; background: var(--text); }

.grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(272px, 1fr));
  gap: clamp(1rem, 2vw, 1.6rem);
}

.card {
  position: relative; display: flex; flex-direction: column;
  border: 1px solid var(--hairline); border-radius: var(--radius-lg);
  background: var(--card-grad);
  overflow: hidden; isolation: isolate;
  transition: transform var(--dur) var(--ease-out), border-color var(--dur), box-shadow var(--dur);
}
/* Cursor-tracked spotlight; --mx/--my are written by the pointer handler. */
.card::before {
  content: ''; position: absolute; inset: 0; z-index: 1; pointer-events: none;
  background: radial-gradient(420px circle at var(--mx, 50%) var(--my, 0%), rgb(var(--tint) / 0.06), transparent 62%);
  opacity: 0; transition: opacity var(--dur) var(--ease-out);
}
.card:hover {
  transform: translateY(-6px);
  border-color: var(--hairline-2);
  box-shadow: var(--lift);
}
.card:hover::before { opacity: 1; }

.card__media {
  position: relative; aspect-ratio: 4 / 5; overflow: hidden;
  background:
    radial-gradient(75% 60% at 50% 40%, rgba(123 92 255 / 0.22), transparent 70%),
    linear-gradient(180deg, var(--ink-3), var(--ink-2));
  display: grid; place-items: center;
}
.card__media img {
  width: 82%; height: 100%; object-fit: contain;
  transition: transform 800ms var(--ease-out);
}
.card:hover .card__media img { transform: scale(1.06) translateY(-4px); }

/* Placeholder artwork for products that have no photo uploaded yet. */
.card__placeholder {
  display: grid; place-items: center; align-content: center; gap: 0.9rem;
  width: 100%; height: 100%;
  color: var(--text-faint);
  background: var(--surface);
}
.card__placeholder svg { width: 52px; opacity: 0.5; color: var(--text-faint); }
.card__placeholder span {
  font-size: 0.84rem; letter-spacing: -0.01em; font-weight: 500;
}

.card__badge {
  position: absolute; top: 0.9rem; left: 0.9rem; z-index: 2;
  padding: 0.3rem 0.72rem; border-radius: 99px;
  background: rgb(var(--shade) / 0.72); color: var(--text);
  border: 1px solid var(--hairline-2); backdrop-filter: blur(10px);
  font-size: 0.76rem; font-weight: 500; letter-spacing: -0.01em;
}
.card__badge--out { background: rgb(var(--shade) / 0.8); border: 1px solid var(--danger); color: var(--danger); }

.card__body { position: relative; z-index: 2; padding: 1.25rem 1.3rem 1.4rem; display: flex; flex-direction: column; gap: 0.5rem; flex: 1; }
.card__cat { font-size: 0.84rem; letter-spacing: -0.01em; color: var(--text-faint); }
.card__name { font-size: 1.08rem; font-weight: 600; line-height: 1.25; margin: 0; }
.card__tag { font-size: 0.86rem; color: var(--text-dim); margin: 0; flex: 1; }

.card__foot { display: flex; align-items: center; justify-content: space-between; gap: 0.8rem; margin-top: 0.7rem; }
.price { display: flex; align-items: baseline; gap: 0.5rem; }
.price b { font-size: 1.16rem; font-weight: 700; }
.price s { font-size: 0.82rem; color: var(--text-faint); }
.price small { font-size: 0.7rem; color: var(--text-faint); }

.add-btn {
  display: inline-grid; place-items: center;
  width: 42px; height: 42px; border-radius: 50%;
  border: 1px solid var(--hairline-2); background: var(--surface);
  cursor: pointer; flex-shrink: 0;
  transition: background var(--dur-fast), border-color var(--dur-fast), transform var(--dur-fast);
}
.add-btn svg { width: 17px; height: 17px; }
.add-btn:hover:not([disabled]) {
  background: var(--text);
  border-color: transparent;
  color: var(--ink);
}
.add-btn[disabled] { opacity: 0.3; cursor: not-allowed; }

.card__view {
  position: absolute; inset: auto 1.3rem 1.4rem auto;
  font-size: 0.74rem; color: var(--text-faint);
}

/* Skeletons while the catalogue loads */
.skeleton { border-radius: var(--radius-lg); height: 420px; border: 1px solid var(--hairline);
  background: linear-gradient(100deg, var(--ink-2) 30%, var(--ink-3) 50%, var(--ink-2) 70%);
  background-size: 220% 100%; animation: shimmer 1.4s linear infinite; }
@keyframes shimmer { to { background-position-x: -220%; } }

.empty-state { padding: 4rem 1rem; text-align: center; color: var(--text-dim); grid-column: 1 / -1; }

/* ---------------------------------------------------------------- features */

.features { display: grid; grid-template-columns: repeat(auto-fit, minmax(258px, 1fr)); gap: 1rem; }
.feature {
  position: relative; padding: 2rem 1.6rem;
  border: 1px solid var(--hairline); border-radius: var(--radius-lg);
  background: var(--panel-grad);
  overflow: hidden;
  transition: border-color var(--dur), transform var(--dur) var(--ease-out);
}
.feature:hover { border-color: var(--hairline-2); transform: translateY(-4px); }
.feature::after {
  content: ''; position: absolute; inset: auto auto -40% -20%;
  width: 180px; aspect-ratio: 1; border-radius: 50%;
  background: radial-gradient(circle, rgba(255 45 149 / 0.3), transparent 68%);
  filter: blur(26px); opacity: 0; transition: opacity var(--dur);
}
.feature:hover::after { opacity: 1; }
.feature__icon {
  width: 46px; height: 46px; border-radius: 14px; display: grid; place-items: center;
  background: var(--surface-2); border: 1px solid var(--hairline);
  color: var(--text); margin-bottom: 1.2rem;
}
.feature__icon svg { width: 22px; height: 22px; }
.feature h3 { font-size: 1.05rem; margin: 0 0 0.5rem; }
.feature p { font-size: 0.9rem; color: var(--text-dim); margin: 0; }

/* ----------------------------------------------------------------- process */

.steps { display: grid; gap: 0; counter-reset: step; }
.step {
  display: grid; grid-template-columns: auto 1fr; gap: clamp(1.2rem, 3vw, 2.6rem);
  padding: clamp(1.6rem, 3vw, 2.4rem) 0;
  border-top: 1px solid var(--hairline);
  transition: background var(--dur);
}
.step:last-child { border-bottom: 1px solid var(--hairline); }
.step:hover { background: var(--row-hover); }
.step__n {
  counter-increment: step;
  font-family: var(--font-display); font-weight: 600;
  font-size: clamp(2rem, 5vw, 3.2rem); line-height: 1; letter-spacing: -0.03em;
  color: var(--text);
  min-width: 2.4ch;
}
.step__n::before { content: '0' counter(step); }
.step h3 { font-size: clamp(1.1rem, 2.2vw, 1.45rem); margin: 0 0 0.45rem; }
.step p { color: var(--text-dim); margin: 0; max-width: 62ch; }

/* ------------------------------------------------------------ testimonials */

.quotes { display: grid; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); gap: 1rem; }
.quote {
  padding: 2rem 1.7rem; border-radius: var(--radius-lg);
  border: 1px solid var(--hairline);
  background: var(--panel-grad);
}
.quote__stars { display: flex; gap: 3px; margin-bottom: 1rem; color: var(--amber); }
.quote__stars svg { width: 15px; height: 15px; }
.quote p { margin: 0 0 1.3rem; font-size: 0.98rem; }
.quote__who { display: flex; align-items: center; gap: 0.8rem; }
.quote__av {
  width: 38px; height: 38px; border-radius: 50%; display: grid; place-items: center;
  background: var(--surface-2); border: 1px solid var(--hairline);
  font-weight: 600; font-size: 0.85rem; color: var(--text);
}
.quote__who b { display: block; font-size: 0.88rem; font-weight: 600; }
.quote__who span { font-size: 0.76rem; color: var(--text-faint); }

/* ----------------------------------------------------------------- contact */

.contact { display: grid; grid-template-columns: 1.05fr 0.95fr; gap: clamp(1.5rem, 4vw, 3.5rem); align-items: center; }
.contact__panel {
  padding: clamp(1.8rem, 4vw, 3rem);
  border: 1px solid var(--hairline); border-radius: var(--radius-lg);
  background:
    radial-gradient(90% 70% at 100% 0%, rgba(18 216 255 / 0.12), transparent 60%),
    var(--panel-grad);
}
.contact__rows { display: grid; gap: 1.1rem; margin: 1.8rem 0 2rem; }
.contact__row { display: flex; gap: 1rem; align-items: flex-start; }
.contact__row svg { width: 19px; height: 19px; color: var(--blue); flex-shrink: 0; margin-top: 3px; }
.contact__row b { display: block; font-size: 0.86rem; letter-spacing: -0.01em; color: var(--text-faint); font-weight: 400; }
.contact__row span { font-size: 0.98rem; }

/* ------------------------------------------------------------------ footer */

.footer {
  border-top: 1px solid var(--hairline);
  padding: clamp(3rem, 7vh, 4.5rem) 0 0;
  /* The wordmark is pulled past the page edge on purpose. */
  overflow: hidden;
}
.footer__top { display: grid; grid-template-columns: 1.4fr 1fr 1fr; gap: 2.4rem; margin-bottom: 3rem; }
.footer__brand img { width: 46px; margin-bottom: 1rem; }
.footer__brand p { color: var(--text-dim); font-size: 0.9rem; max-width: 34ch; margin: 0; }
.footer__col h4 { font-size: 0.86rem; font-weight: 600; letter-spacing: -0.01em; color: var(--text-faint); margin: 0 0 0.9rem; }
.footer__col a { display: block; font-size: 0.9rem; color: var(--text-dim); padding: 0.28rem 0; transition: color var(--dur-fast), transform var(--dur-fast); }
.footer__col a:hover { color: var(--text); transform: translateX(3px); }
.footer__bottom {
  display: flex; flex-wrap: wrap; gap: 1rem; justify-content: space-between;
  padding-top: 1.8rem; border-top: 1px solid var(--hairline);
  font-size: 0.8rem; color: var(--text-faint);
}

/* Oversized wordmark that bleeds off the bottom of the page */
.footer__wordmark {
  font-family: var(--font-display); font-weight: 700;
  font-size: clamp(2.2rem, 7vw, 5.2rem);
  line-height: 1; text-align: center; letter-spacing: -0.04em;
  background: linear-gradient(180deg, rgb(var(--tint) / 0.13), rgb(var(--tint) / 0.01) 88%);
  -webkit-background-clip: text; background-clip: text; color: transparent;
  /* Anton leaves descender space below the caps, so the negative margin crops
     the empty band rather than the letterforms. */
  margin: clamp(1.8rem, 4vw, 2.5rem) 0 -0.22em;
  user-select: none; pointer-events: none;
}

/* ------------------------------------------------------------- cart drawer */

.scrim {
  position: fixed; inset: 0; z-index: 110;
  background: rgba(3 2 8 / 0.7); backdrop-filter: blur(4px);
  opacity: 0; visibility: hidden;
  transition: opacity var(--dur) var(--ease-out), visibility var(--dur);
}
.scrim.is-open { opacity: 1; visibility: visible; }

.drawer {
  position: fixed; top: 0; right: 0; bottom: 0; z-index: 120;
  width: min(430px, 100vw);
  display: flex; flex-direction: column;
  background: var(--ink-2); border-left: 1px solid var(--hairline);
  transform: translateX(100%);
  transition: transform 520ms var(--ease-out);
  box-shadow: -30px 0 80px -30px rgb(var(--shadow-rgb) / 0.9);
}
.drawer.is-open { transform: translateX(0); }

.drawer__head {
  display: flex; align-items: center; justify-content: space-between;
  padding: 1.3rem 1.4rem; border-bottom: 1px solid var(--hairline);
}
.drawer__head h2 { font-family: var(--font-display); font-weight: 600; font-size: 1.45rem; margin: 0; }
.icon-btn {
  display: grid; place-items: center; width: 36px; height: 36px; border-radius: 10px;
  border: 1px solid var(--hairline); background: transparent; cursor: pointer;
  transition: background var(--dur-fast), border-color var(--dur-fast);
}
.icon-btn:hover { background: var(--surface-2); border-color: var(--hairline-2); }
.icon-btn svg { width: 16px; height: 16px; }

.drawer__body { flex: 1; overflow-y: auto; padding: 1.1rem 1.4rem; }
.drawer__foot { border-top: 1px solid var(--hairline); padding: 1.2rem 1.4rem 1.5rem; background: var(--ink-3); }

.line {
  display: grid; grid-template-columns: 62px 1fr auto; gap: 0.9rem;
  padding: 0.95rem 0; border-bottom: 1px solid var(--hairline);
  align-items: center;
}
.line:last-child { border-bottom: 0; }
.line__img {
  width: 62px; aspect-ratio: 4/5; border-radius: 12px; object-fit: contain;
  background: var(--ink-3); border: 1px solid var(--hairline);
}
.line__name { font-size: 0.9rem; font-weight: 600; margin: 0 0 0.15rem; }
.line__meta { font-size: 0.76rem; color: var(--text-faint); margin: 0 0 0.5rem; }
.qty { display: inline-flex; align-items: center; border: 1px solid var(--hairline); border-radius: 99px; overflow: hidden; }
.qty button {
  width: 27px; height: 27px; border: 0; background: transparent; cursor: pointer;
  color: var(--text-dim); font-size: 1rem; line-height: 1;
  transition: background var(--dur-fast), color var(--dur-fast);
}
.qty button:hover { background: var(--surface-2); color: var(--text); }
.qty span { min-width: 26px; text-align: center; font-size: 0.84rem; font-weight: 600; }
.line__total { font-size: 0.92rem; font-weight: 600; text-align: right; }
.line__remove { display: block; margin-top: 0.3rem; font-size: 0.72rem; color: var(--text-faint); background: none; border: 0; cursor: pointer; padding: 0; }
.line__remove:hover { color: var(--danger); }

.drawer__empty { text-align: center; padding: 3.5rem 1rem; color: var(--text-dim); }
.drawer__empty svg { width: 54px; opacity: 0.3; margin: 0 auto 1.2rem; }

.field { margin-bottom: 0.8rem; }
.field label { display: block; font-size: 0.86rem; letter-spacing: -0.01em; color: var(--text-faint); margin-bottom: 0.4rem; }
.field input, .field textarea, .field select {
  width: 100%; padding: 0.7rem 0.9rem; border-radius: 12px;
  border: 1px solid var(--hairline); background: var(--input-bg);
  font-size: 0.9rem;
  transition: border-color var(--dur-fast), background var(--dur-fast);
}
.field input:focus, .field textarea:focus, .field select:focus { border-color: var(--blue); background: var(--input-bg-on); outline: none; }
.field textarea { resize: vertical; min-height: 68px; }

.totals { display: flex; justify-content: space-between; align-items: baseline; margin: 0.9rem 0 0.4rem; }
.totals span { color: var(--text-dim); font-size: 0.88rem; }
.totals b { font-family: var(--font-display); font-weight: 600; font-size: 1.6rem; letter-spacing: -0.02em; }
.drawer__note { font-size: 0.74rem; color: var(--text-faint); text-align: center; margin: 0.8rem 0 0; }

.muted-sm { font-size: 0.84rem; color: var(--text-faint); }

/* ------------------------------------------------------------ quick-view */

.modal {
  position: fixed; inset: 0; z-index: 130;
  display: grid; place-items: center; padding: var(--gutter);
  opacity: 0; visibility: hidden;
  transition: opacity var(--dur) var(--ease-out), visibility var(--dur);
}
.modal.is-open { opacity: 1; visibility: visible; }
.modal__scrim {
  position: absolute; inset: 0; z-index: 1;
  background: rgba(3 2 8 / 0.72); backdrop-filter: blur(4px);
}
.modal__panel {
  position: relative; z-index: 2;
  width: min(880px, 100%); max-height: 86vh; overflow-y: auto;
  display: grid; grid-template-columns: 1fr 1fr;
  border: 1px solid var(--hairline-2); border-radius: var(--radius-lg);
  background: var(--ink-2);
  transform: translateY(24px) scale(0.97);
  transition: transform 520ms var(--ease-out);
  box-shadow: 0 50px 120px -40px rgb(var(--shadow-rgb) / 0.95);
}
.modal.is-open .modal__panel { transform: translateY(0) scale(1); }
.modal__media {
  display: grid; place-items: center; padding: 2rem;
  background: radial-gradient(70% 60% at 50% 40%, rgba(123 92 255 / 0.28), transparent 70%), var(--ink-3);
  border-right: 1px solid var(--hairline);
}
.modal__media img { max-height: 400px; object-fit: contain; }
.modal__body { padding: clamp(1.6rem, 3vw, 2.4rem); }
.modal__body h2 { font-family: var(--font-display); font-weight: 600; font-size: clamp(1.7rem, 3.4vw, 2.4rem); margin: 0.5rem 0 0.6rem; line-height: 1.08; }
.modal__body p { color: var(--text-dim); font-size: 0.94rem; }
.modal__list { list-style: none; padding: 0; margin: 1.4rem 0; display: grid; gap: 0.55rem; }
.modal__list li { display: flex; gap: 0.65rem; align-items: flex-start; font-size: 0.9rem; }
.modal__list svg { width: 15px; height: 15px; color: var(--ok); flex-shrink: 0; margin-top: 4px; }
.modal__close { position: absolute; top: 0.9rem; right: 0.9rem; z-index: 3; background: rgb(var(--shade) / 0.7); }
.modal__buy { display: flex; align-items: center; gap: 1rem; flex-wrap: wrap; margin-top: 1.6rem; }

/* ------------------------------------------------------------------ toasts */

.toasts {
  position: fixed; left: 50%; bottom: 1.6rem; z-index: 200;
  transform: translateX(-50%);
  display: grid; gap: 0.5rem; width: min(380px, calc(100vw - 2rem));
  pointer-events: none;
}
.toast {
  display: flex; align-items: center; gap: 0.7rem;
  padding: 0.85rem 1.1rem; border-radius: 14px;
  border: 1px solid var(--hairline-2);
  background: rgb(var(--shade) / 0.94); backdrop-filter: blur(16px);
  font-size: 0.88rem;
  box-shadow: 0 20px 50px -20px rgb(var(--shadow-rgb) / 0.9);
  animation: toast-in 460ms var(--ease-spring);
}
.toast.is-out { animation: toast-out 300ms var(--ease-out) forwards; }
.toast svg { width: 17px; height: 17px; flex-shrink: 0; }
.toast--ok svg { color: var(--ok); }
.toast--err { border-color: rgba(255 77 109 / 0.5); }
.toast--err svg { color: var(--danger); }
@keyframes toast-in  { from { opacity: 0; transform: translateY(16px) scale(0.96); } }
@keyframes toast-out { to   { opacity: 0; transform: translateY(10px) scale(0.97); } }

/* ------------------------------------------------------------- responsive */

@media (max-width: 1020px) {
  .hero__chip--a { left: 2%; }
  .hero__chip--b { right: 0; }
  .contact { grid-template-columns: 1fr; }
  .footer__top { grid-template-columns: 1fr 1fr; }
  .modal__panel { grid-template-columns: 1fr; max-height: 90vh; }
  .modal__media { border-right: 0; border-bottom: 1px solid var(--hairline); padding: 1.4rem; }
  .modal__media img { max-height: 240px; }
}

@media (max-width: 900px) and (orientation: portrait) {
  /* In portrait the copy sits below the sun, so the scrim has to run vertically. */
  .hero::after {
    background:
      linear-gradient(180deg, rgb(var(--shade) / 0.5) 0%, transparent 22%, rgb(var(--shade) / 0.3) 54%, rgb(var(--shade) / 0.85) 80%, var(--ink) 100%),
      radial-gradient(130% 92% at 50% 42%, transparent 48%, rgb(var(--shade) / 0.5) 100%);
  }
}

@media (max-width: 760px) {
  .nav { padding-inline: 1rem; gap: 0.5rem; }
  .nav__brand span { font-size: 0.98rem; letter-spacing: -0.02em; }
  .nav__brand img { width: 32px; height: 32px; }
  .cart-btn { padding: 0.55rem 0.9rem; font-size: 0.8rem; }
  .hero__badge { font-size: 0.66rem; gap: 0.4rem; padding: 0.38rem 0.8rem 0.38rem 0.45rem; }
  .hero__toggle { flex-shrink: 0; }
  .nav__toggle { display: block; }
  .nav__links {
    position: fixed; inset: 0 0 auto; top: 0; z-index: -1;
    flex-direction: column; align-items: stretch; gap: 0;
    padding: 5.4rem var(--gutter) 2rem;
    background: rgb(var(--shade) / 0.97); backdrop-filter: blur(22px);
    border-bottom: 1px solid var(--hairline);
    transform: translateY(-102%);
    transition: transform 480ms var(--ease-out);
  }
  .nav.is-open .nav__links { transform: translateY(0); }
  .nav__link { padding: 0.95rem 0; border-bottom: 1px solid var(--hairline); font-size: 1.05rem; color: var(--text); }
  .nav__link::after { display: none; }
  .footer__top { grid-template-columns: 1fr; }
  .grid { grid-template-columns: repeat(auto-fill, minmax(min(100%, 250px), 1fr)); }
}

/* -------------------------------------------------------------- theme toggle */

.theme-btn {
  display: grid; place-items: center;
  width: 42px; height: 42px; border-radius: 99px;
  border: 1px solid var(--hairline-2); background: var(--surface);
  cursor: pointer; flex-shrink: 0;
  backdrop-filter: blur(10px);
  transition: border-color var(--dur-fast), background var(--dur-fast), transform var(--dur-fast);
}
.theme-btn:hover { border-color: var(--blue); transform: translateY(-1px); }
.theme-btn svg { width: 18px; height: 18px; grid-area: 1 / 1; transition: opacity var(--dur) var(--ease-out), transform var(--dur) var(--ease-spring); }

/* Only one glyph is visible; the other is rotated out of the way. */
.theme-btn__sun  { opacity: 0; transform: rotate(-90deg) scale(0.6); }
.theme-btn__moon { opacity: 1; transform: rotate(0) scale(1); }
.theme-btn[data-theme='light'] .theme-btn__sun  { opacity: 1; transform: rotate(0) scale(1); }
.theme-btn[data-theme='light'] .theme-btn__moon { opacity: 0; transform: rotate(90deg) scale(0.6); }

/* Portal sidebar variant reuses the same glyph swap. */
.side__link .theme-btn__sun,
.side__link .theme-btn__moon { grid-area: auto; transition: opacity var(--dur-fast); }
.side__link .theme-btn__sun { display: none; }
.side__link[data-theme='light'] .theme-btn__sun { display: block; }
.side__link[data-theme='light'] .theme-btn__moon { display: none; }

/* In light mode the preloader and marquee need their own treatment. */
:root[data-theme='light'] .marquee,
:root:not([data-theme]) .marquee {
  background: var(--surface);
}
:root[data-theme='light'] .footer__wordmark {
  background: linear-gradient(180deg, rgb(var(--tint) / 0.14), rgb(var(--tint) / 0.02) 88%);
  -webkit-background-clip: text; background-clip: text;
}
/* Cards carry a real shadow on a light page rather than relying on a border. */
:root[data-theme='light'] .card,
:root[data-theme='light'] .feature,
:root[data-theme='light'] .quote,
:root[data-theme='light'] .contact__panel {
  box-shadow: 0 18px 44px -28px rgb(var(--shadow-rgb) / 0.45);
}
:root[data-theme='light'] .card__media {
  background:
    radial-gradient(75% 60% at 50% 40%, rgb(123 92 255 / 0.13), transparent 70%),
    linear-gradient(180deg, #f4f1fb, #eae5f7);
}
:root[data-theme='light'] .card__placeholder svg { opacity: 0.6; }

/* ------------------------------------------------------- hero ink (pinned) --
   The sunset canvas is artwork and stays neon in both themes, so everything
   drawn on top of it is pinned to light ink instead of following the theme
   tokens. This block lives at the end of the file deliberately: the rules it
   overrides have identical specificity, so source order is what decides. */

.hero, .hero .eyebrow { color: var(--hero-text); }
.hero__copy, .hero__scroll { color: var(--hero-dim); }
.hero__badge { color: var(--hero-dim); }
.hero__badge b { color: var(--hero-text); }
.hero__chip { color: var(--hero-text); }
.hero__stat b { color: var(--hero-text); }
.hero__stat span { color: var(--hero-dim); }
.hero .btn--ghost { color: var(--hero-text); border-color: rgb(var(--tint) / 0.26); }
.hero .btn--ghost:hover { border-color: var(--blue); }

.nav:not(.is-stuck) { color: var(--hero-text); }
.nav:not(.is-stuck) .nav__link { color: var(--hero-dim); }
.nav:not(.is-stuck) .nav__link:hover { color: var(--hero-text); }
.nav:not(.is-stuck) .cart-btn,
.nav:not(.is-stuck) .theme-btn,
.nav:not(.is-stuck) .nav__toggle {
  color: var(--hero-text);
  background: rgb(var(--tint) / 0.08);
  border-color: rgb(var(--tint) / 0.22);
}
.nav:not(.is-stuck) .nav__toggle span { background: var(--hero-text); }

/* Once the mobile menu is open the nav has its own solid panel, so it rejoins
   the active theme even while still over the hero. */
@media (max-width: 760px) {
  .nav.is-open:not(.is-stuck) .nav__link { color: var(--text); }
}

/* ============================================================================
   v2 - richer surfaces, lit edges, and the location block
   ========================================================================= */

/* The page background is the ambient field, so sections must not paint over it. */
body { background: transparent; }
.section { position: relative; z-index: 1; }

/* Each section gets its own coloured wash so none of them reads as empty. */
.section::before {
  content: '';
  position: absolute; inset: 0; z-index: -1;
  pointer-events: none;
  opacity: 0.55;
}
#shop::before {
  background: radial-gradient(58% 44% at 14% 0%, rgb(255 255 255 / 0.045), transparent 70%),
              radial-gradient(50% 38% at 92% 74%, rgb(255 45 149 / 0.07), transparent 70%);
}
#why::before {
  background: radial-gradient(54% 42% at 88% 6%, rgb(255 255 255 / 0.05), transparent 70%);
}
#how::before {
  background: radial-gradient(62% 46% at 50% 0%, rgb(255 255 255 / 0.04), transparent 70%);
}
#contact::before {
  background: radial-gradient(56% 44% at 10% 20%, rgb(255 255 255 / 0.05), transparent 70%);
}

/* Glowing rule between sections instead of a hard border. */
.section + .section::after {
  content: '';
  position: absolute; inset: 0 0 auto; height: 1px;
  background: linear-gradient(90deg, transparent, rgb(var(--tint) / 0.14) 30%, rgb(var(--tint) / 0.2) 50%, rgb(var(--tint) / 0.14) 70%, transparent);
}

/* ----------------------------------------------------------- glass surfaces */

.card,
.feature,
.contact__panel,
.map-card {
  backdrop-filter: blur(14px) saturate(140%);
  background: var(--card-grad);
  box-shadow: var(--lift), inset 0 1px 0 rgb(var(--tint) / 0.12);
}

.card {
  /* Tilt is driven from JS via --rx/--ry; the transform stays on the compositor. */
  transform: perspective(900px) rotateX(var(--rx, 0deg)) rotateY(var(--ry, 0deg)) translateY(var(--ty, 0px));
  transform-style: preserve-3d;
  transition: transform 380ms var(--ease-swift), box-shadow var(--dur) var(--ease-out), border-color var(--dur);
}
.card:hover {
  --ty: -8px;
  border-color: rgb(var(--tint) / 0.24);
  box-shadow: var(--lift-hi), inset 0 1px 0 rgb(var(--tint) / 0.18);
}

/* Contents lift out of the card plane on hover, which is what sells the 3D. */
.card__media img { transform: translateZ(28px) scale(1); }
.card:hover .card__media img { transform: translateZ(46px) scale(1.07) translateY(-4px); }
.card__body { transform: translateZ(18px); }

/* Chrome-edge highlight along the top of every card. */
.card::after {
  content: '';
  position: absolute; inset: 0 0 auto; height: 1px; z-index: 3;
  background: linear-gradient(90deg, transparent, rgb(255 255 255 / 0.55), transparent);
  opacity: 0.35;
  transition: opacity var(--dur);
}
.card:hover::after { opacity: 1; }

/* A soft overhead key light on graphite. The product is the colour on the card. */
.card__media {
  background:
    radial-gradient(64% 46% at 50% 22%, rgb(255 255 255 / 0.09), transparent 70%),
    linear-gradient(180deg, var(--ink-4) 0%, var(--ink-2) 78%);
}

.card__badge { box-shadow: var(--lift); }

.feature:hover { box-shadow: var(--lift-hi); }


/* --------------------------------------------------------------- buttons v2 */


/* Controls do not move on hover. They brighten. Movement on every control
   reads as a gimmick and makes a page feel unsettled; a colour shift tells
   you the same thing and stays still under the cursor. */
.cart-btn:hover,
.theme-btn:hover {
  border-color: var(--accent);
  color: var(--text);
  background: var(--surface-2);
}

/* ------------------------------------------------------------ section heads */

.section__title { position: relative; }
/* Soft colour bloom behind big display type. */
.section__title::after {
  content: '';
  position: absolute; left: -6%; top: 10%; width: 56%; height: 90%; z-index: -1;
  background: radial-gradient(ellipse, rgb(255 255 255 / 0.07), transparent 70%);
  filter: blur(52px);
  pointer-events: none;
}

.eyebrow {
  padding: 0.3rem 0.9rem 0.3rem 0;
  width: max-content;
}

/* ------------------------------------------------------------------- chrome */

.chrome-band {
  position: absolute; inset: 0; z-index: -1;
  width: 100%; height: 100%;
  pointer-events: none;
}

/* ----------------------------------------------------------------- location */

.map-section { padding-bottom: clamp(3rem, 7vh, 5rem); }

.map-card {
  position: relative;
  border: 1px solid var(--hairline);
  border-radius: var(--radius-lg);
  overflow: hidden;
  display: grid;
  grid-template-columns: 1fr 1.25fr;
  min-height: 420px;
}

.map-card__info {
  padding: clamp(1.8rem, 3.5vw, 2.8rem);
  display: flex; flex-direction: column; gap: 1.1rem; justify-content: center;
  position: relative; z-index: 2;
}
.map-card__info h3 {
  font-family: var(--font-display); font-weight: 600;
  font-size: clamp(1.7rem, 3.4vw, 2.5rem);
  margin: 0; line-height: 1.05; letter-spacing: -0.03em;
}
.map-card__addr { font-size: 1rem; color: var(--text-dim); margin: 0; max-width: 32ch; }
.map-card__addr b { color: var(--text); font-weight: 600; display: block; }

.map-card__meta { display: grid; gap: 0.7rem; margin: 0.4rem 0 0.6rem; }
.map-card__meta div { display: flex; gap: 0.7rem; align-items: center; font-size: 0.9rem; color: var(--text-dim); }
.map-card__meta svg { width: 17px; height: 17px; color: var(--blue); flex-shrink: 0; }

.map-card__actions { display: flex; flex-wrap: wrap; gap: 0.7rem; }

/* The embed itself, colour-graded to match the site rather than sitting in it
   as a bright rectangle. */
/* Sits under the embed. If Google is slow, blocked by a network policy, or
   fails entirely, the panel still reads as a designed surface instead of a
   broken-image glyph. */
.map-card__frame {
  position: relative; min-height: 340px;
  background:
    linear-gradient(115deg, transparent 40%, rgb(255 255 255 / 0.05) 50%, transparent 60%),
    repeating-linear-gradient(0deg, transparent 0 46px, rgb(var(--tint) / 0.05) 46px 47px),
    repeating-linear-gradient(90deg, transparent 0 46px, rgb(var(--tint) / 0.05) 46px 47px),
    var(--grad-steel);
}
:root[data-theme='light'] .map-card__frame { background:
    repeating-linear-gradient(0deg, transparent 0 46px, rgb(var(--tint) / 0.06) 46px 47px),
    repeating-linear-gradient(90deg, transparent 0 46px, rgb(var(--tint) / 0.06) 46px 47px),
    var(--ink-3); }
.map-card__frame iframe {
  position: absolute; inset: 0; z-index: 1;
  opacity: 0;
  transition: opacity 600ms var(--ease-out);
  width: 100%; height: 100%;
  border: 0;
  filter: invert(0.92) hue-rotate(185deg) saturate(1.5) contrast(0.92) brightness(0.95);
}
:root[data-theme='light'] .map-card__frame iframe { filter: saturate(1.15) contrast(1.02); }

/* Brand wash over the map, and a fade into the card on the left seam. */
.map-card__frame iframe.is-loaded { opacity: 1; }

.map-card__tint {
  position: absolute; inset: 0; z-index: 2; pointer-events: none;
  background:
    linear-gradient(90deg, var(--ink-2) 0%, rgb(var(--shade) / 0.35) 16%, transparent 44%),
    radial-gradient(70% 90% at 70% 50%, transparent 40%, rgb(var(--shade) / 0.55) 100%),
    linear-gradient(200deg, rgb(255 45 149 / 0.1), transparent 55%);
  mix-blend-mode: normal;
}

/* Pulsing marker sitting over the embed. */
.map-pin {
  position: absolute; z-index: 3; top: 50%; left: 62%;
  transform: translate(-50%, -100%);
  pointer-events: none;
}
.map-pin__dot {
  width: 16px; height: 16px; border-radius: 50%;
  background: var(--accent);
  box-shadow: 0 0 0 4px rgb(var(--shade) / 0.65);
  position: relative; z-index: 2;
  margin: 0 auto;
}
.map-pin__ring {
  position: absolute; left: 50%; top: 8px;
  width: 16px; height: 16px; margin: -8px 0 0 -8px;
  border-radius: 50%;
  border: 2px solid var(--pink);
  animation: ping 2.6s var(--ease-out) infinite;
}
.map-pin__ring:nth-of-type(2) { animation-delay: 0.85s; }
.map-pin__ring:nth-of-type(3) { animation-delay: 1.7s; }
@keyframes ping {
  0%   { transform: scale(1); opacity: 0.9; }
  100% { transform: scale(7); opacity: 0; }
}

.map-pin__label {
  margin-top: 0.7rem;
  padding: 0.4rem 0.85rem;
  border-radius: 99px;
  background: rgb(var(--shade) / 0.82);
  border: 1px solid var(--hairline-2);
  backdrop-filter: blur(10px);
  font-size: 0.74rem; font-weight: 600; white-space: nowrap;
  box-shadow: var(--lift);
}

@media (max-width: 900px) {
  .map-card { grid-template-columns: 1fr; }
  .map-card__frame { min-height: 300px; order: -1; }
  .map-card__tint {
    background:
      linear-gradient(180deg, transparent 40%, var(--ink-2) 100%),
      linear-gradient(200deg, rgb(255 45 149 / 0.1), transparent 60%);
  }
  .map-pin { left: 50%; top: 45%; }
}

/* ============================================================================
   v3 - restructure
   ========================================================================= */

.icon { flex-shrink: 0; }

/* ------------------------------------------------------------------- hero */

/* Wide enough for the display lines, which are nowrap. The paragraph sets its
   own measure below; constraining the column would clip the headline. */
.hero__copy-col { max-width: min(100%, 46rem); min-width: 0; }

/* The badge is the hero's single small text element. No dot, no pulse. */
.hero__badge {
  display: inline-block;
  padding: 0.42rem 1rem;
  border-radius: 99px;
  border: 1px solid var(--hairline-2);
  background: rgb(var(--shade) / 0.5);
  backdrop-filter: blur(12px);
  font-size: 0.95rem; letter-spacing: -0.012em;
  margin: 0 0 clamp(1rem, 2.5vh, 1.5rem);
}

.hero__title {
  font-size: clamp(2.5rem, min(7vw, 12vh), 5.8rem);
  line-height: 1.0;
  margin-bottom: clamp(1rem, 2.4vh, 1.6rem);
}
/* Each line is one line. The headline is capped at two, so a wrap here would
   silently make it three. */
.hero__line > span { white-space: nowrap; }

.hero__copy { font-size: clamp(1.05rem, 1.6vw, 1.28rem); max-width: 34ch; }
.hero__cta { margin-bottom: 0; }

/* ---------------------------------------------------------------- metrics */

.metrics {
  position: relative; z-index: 1;
  padding: clamp(2rem, 5vh, 3.2rem) 0;
}
.metrics__row {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: clamp(1rem, 4vw, 3rem);
}
.metric { position: relative; padding-top: 1.1rem; }
/* One short accent rule per metric, instead of gradient-filled numerals. */
.metric::before {
  content: '';
  position: absolute; top: 0; left: 0;
  width: 34px; height: 2px; border-radius: 2px;
  background: var(--text);
}
/* Hairlines between, not around: no box per metric. */
.metric + .metric {
  border-left: 1px solid var(--hairline);
  padding-left: clamp(1rem, 4vw, 3rem);
}
.metric b {
  display: block;
  font-family: var(--font-display); font-weight: 600;
  font-size: clamp(1.7rem, 4.4vw, 3.1rem); line-height: 1; letter-spacing: -0.03em;
  color: var(--text);
}
.metric span {
  display: block; margin-top: 0.4rem;
  font-size: 0.95rem; letter-spacing: -0.012em;
  color: var(--text-faint);
}

@media (max-width: 680px) {
  .metrics__row { grid-template-columns: 1fr; gap: 0; }
  .metric + .metric {
    border-left: 0; border-top: 1px solid var(--hairline);
    padding-left: 0; padding-top: 1rem; margin-top: 1rem;
  }
}

/* ------------------------------------------------------------------ bento */

/* Four cells, four items, deliberately unequal. */
.bento {
  display: grid;
  grid-template-columns: 1.25fr 1fr 1fr;
  grid-template-rows: auto auto;
  gap: clamp(0.8rem, 1.6vw, 1.2rem);
}
.bento__cell {
  position: relative;
  display: flex; align-items: flex-end;
  min-height: 210px;
  padding: clamp(1.3rem, 2.4vw, 1.9rem);
  border: 1px solid var(--hairline);
  border-radius: var(--radius-lg);
  background: var(--card-grad);
  backdrop-filter: blur(14px) saturate(140%);
  overflow: hidden;
  box-shadow: var(--lift), inset 0 1px 0 rgb(var(--tint) / 0.12);
  transition: transform var(--dur) var(--ease-swift), box-shadow var(--dur) var(--ease-out);
}
.bento__cell:hover { transform: translateY(-5px); box-shadow: var(--lift-hi); }

/* A single specular line along the top edge: the way a polished surface
   actually reads as polished, rather than by turning it a colour. */
.bento__cell::before,
.card::after,
.contact__panel::before,
.map-card::before {
  content: '';
  position: absolute; inset: 0 0 auto; height: 1px; z-index: 3;
  background: linear-gradient(90deg, transparent, rgb(255 255 255 / 0.5) 45%, rgb(255 255 255 / 0.18) 70%, transparent);
  opacity: 0.4;
  transition: opacity var(--dur) var(--ease-out);
  pointer-events: none;
}
.bento__cell:hover::before,
.card:hover::after,
.contact__panel:hover::before,
.map-card:hover::before { opacity: 1; }

.bento__cell--tall { grid-row: span 2; min-height: 440px; }
.bento__cell--wide { grid-column: span 2; }

/* Generated brand texture, dimmed so the copy always wins. */
.bento__art {
  position: absolute; inset: 0; z-index: 0;
  width: 100%; height: 100%; object-fit: cover;
  opacity: 0.55;
  transform: scale(1.04);
  transition: transform 1.2s var(--ease-swift), opacity var(--dur);
}
.bento__cell--tall .bento__art { opacity: 0.66; }
.bento__cell:hover .bento__art { transform: scale(1.1); opacity: 0.6; }

/* Scrim so text stays legible whatever the texture does underneath. */
.bento__cell--tall::after,
.bento__cell--art::after {
  content: '';
  position: absolute; inset: 0; z-index: 1;
  background: linear-gradient(0deg, var(--ink-2) 4%, rgb(var(--shade) / 0.72) 46%, rgb(var(--shade) / 0.22) 100%);
}
:root[data-theme='light'] .bento__cell--tall::after,
:root[data-theme='light'] .bento__cell--art::after {
  background: linear-gradient(0deg, rgb(255 255 255 / 0.95) 6%, rgb(255 255 255 / 0.72) 44%, rgb(255 255 255 / 0.3) 100%);
}

.bento__body { position: relative; z-index: 2; }
.bento__body h3 { font-size: clamp(1.05rem, 1.8vw, 1.35rem); margin: 0 0 0.5rem; }
.bento__body p { font-size: 0.92rem; color: var(--text-dim); margin: 0; max-width: 46ch; }

.bento__icon {
  width: 30px; height: 30px; margin-bottom: 0.9rem;
  color: var(--pink);
}

@media (max-width: 900px) {
  .bento { grid-template-columns: 1fr 1fr; }
  .bento__cell--tall { grid-row: span 1; grid-column: span 2; min-height: 300px; }
  .bento__cell--wide { grid-column: span 2; }
}
@media (max-width: 620px) {
  .bento { grid-template-columns: 1fr; }
  .bento__cell, .bento__cell--tall, .bento__cell--wide { grid-column: span 1; min-height: 200px; }
}

/* ------------------------------------------------------------------ steps */

/* A hairline under every row is the laziest list layout, so the steps are
   offset cards with the number carrying the rhythm instead. */
.steps {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
  gap: clamp(0.9rem, 2vw, 1.4rem);
  counter-reset: step;
}
.step {
  display: block;
  border: 0; border-top: 2px solid var(--hairline-2);
  padding: 1.4rem 0 0;
  transition: border-color var(--dur);
}
.step:last-child { border-bottom: 0; }
.step:hover { background: transparent; border-top-color: var(--pink); }
.step__n {
  display: block;
  font-size: clamp(1.6rem, 3vw, 2.4rem);
  margin-bottom: 0.5rem;
}
/* Offset every second step so the row is not a flat ruler. */
.step:nth-child(even) { margin-top: clamp(0rem, 3vw, 2.4rem); }

/* ------------------------------------------------------- card media art */

/* Products with no photograph yet get a generated brand texture rather than an
   empty grey box. Clearly not a photograph, and never pretending to be one. */
.card__placeholder {
  position: relative;
  background: none;
  padding: 0;
}
.card__placeholder img {
  position: absolute; inset: 0;
  width: 100%; height: 100%; object-fit: cover;
  /* Well back: the texture is a surface, not the subject. */
  opacity: 0.4;
  mix-blend-mode: luminosity;
}
/* Keeps the tile anchored to the card's own dark rather than floating grey. */
.card__placeholder::after {
  content: '';
  position: absolute; inset: 0; z-index: 1;
  background: linear-gradient(180deg, rgb(var(--shade) / 0.15) 0%, rgb(var(--shade) / 0.6) 100%);
}
.card__placeholder span {
  position: relative; z-index: 2;
  padding: 0.35rem 0.8rem; border-radius: 99px;
  background: rgb(var(--shade) / 0.72);
  border: 1px solid var(--hairline);
  backdrop-filter: blur(8px);
  color: var(--text-dim);
}

/* Watched by an IntersectionObserver to drive the sticky nav state. */
.scroll-sentinel {
  position: absolute; top: 0; left: 0;
  width: 1px; height: 24px;
  pointer-events: none;
}

/* ------------------------------------------------------------------ plinth */

/**
 * The product on a lit stand. The photograph was shot on dark marble, so on
 * the graphite ground it sits in the scene instead of looking pasted on: a
 * pool of light underneath, a mirrored copy fading into the floor, and a slow
 * float so it is never completely still.
 */
.hero__inner {
  grid-template-columns: minmax(0, 1fr) minmax(0, 0.8fr);
  gap: clamp(1.5rem, 4vw, 3.5rem);
}

.plinth {
  /* One height drives the product, the reflection and the offset between them,
     so the reflection cannot drift away from the bottle's base. */
  --plinth-h: min(56vh, 500px);
  position: relative;
  margin: 0;
  display: grid;
  justify-items: center;
  align-content: center;
  min-height: min(68vh, 600px);
}

/* The light the bottle appears to be standing in. */
.plinth__pool {
  position: absolute;
  left: 50%; bottom: 8%;
  width: min(120%, 460px); aspect-ratio: 2.4 / 1;
  transform: translateX(-50%);
  border-radius: 50%;
  background: radial-gradient(ellipse at center,
    rgb(var(--tint) / 0.22) 0%,
    rgb(var(--tint) / 0.08) 38%,
    transparent 72%);
  filter: blur(22px);
}

.plinth__product {
  position: relative; z-index: 2;
  height: var(--plinth-h); width: auto; max-width: 100%;
  object-fit: contain;
  filter: drop-shadow(0 30px 40px rgb(0 0 0 / 0.55));
  animation: float 7s var(--ease-in-out) infinite;
}

/* The reflection: the same image, flipped, dimmed and faded out. */
.plinth__mirror {
  position: relative; z-index: 1;
  height: calc(var(--plinth-h) * 0.26); width: auto; max-width: 100%;
  object-fit: contain; object-position: top;
  /* The asset's bottom tenth is a soft fade, so the reflection starts there
     rather than at the image box edge. */
  margin-top: calc(var(--plinth-h) * -0.1);
  transform: scaleY(-1);
  opacity: 0.16;
  -webkit-mask-image: linear-gradient(0deg, transparent 12%, #000 96%);
  mask-image: linear-gradient(0deg, transparent 12%, #000 96%);
  animation: float 7s var(--ease-in-out) infinite;
  pointer-events: none;
}

@keyframes float {
  0%, 100% { translate: 0 0; }
  50%      { translate: 0 -12px; }
}

@media (prefers-reduced-motion: reduce) {
  .plinth__product, .plinth__mirror { animation: none; }
}

@media (max-width: 1020px) {
  .hero__inner { grid-template-columns: 1fr; }
  .plinth {
    --plinth-h: min(30vh, 260px);
    order: -1; min-height: auto; margin-bottom: clamp(0.5rem, 2vh, 1.5rem);
  }
  .plinth__pool { width: min(90%, 300px); bottom: 16%; }
}

/* ------------------------------------------------------- hero photo layer */

/**
 * A full-bleed photograph behind the hero, set from the portal. When none is
 * set the WebGL studio below it carries the section, so the hero is never
 * empty either way.
 */
.hero__photo {
  position: absolute; inset: 0; z-index: 1;
  width: 100%; height: 100%;
  object-fit: cover;
  object-position: var(--hero-focus, center);
}
/* Set as data by the server, because a style attribute in markup is refused by
   the content security policy. The portal's own preview writes the custom
   property through the CSSOM instead, which is allowed. */
.hero[data-focus='left']   .hero__photo { object-position: left; }
.hero[data-focus='right']  .hero__photo { object-position: right; }
.hero[data-focus='top']    .hero__photo { object-position: top; }
.hero[data-focus='bottom'] .hero__photo { object-position: bottom; }
.hero[data-focus='center'] .hero__photo { object-position: center;
}
.hero__photo[hidden] { display: none; }

/* Two scrims: one across the bottom so the section resolves into the page,
   one from the left so the copy always has ground to sit on whatever the
   photograph is doing behind it. */
.hero__scrim {
  position: absolute; inset: 0; z-index: 2;
  background:
    linear-gradient(94deg, rgb(var(--shade) / 0.94) 0%, rgb(var(--shade) / 0.78) 28%, rgb(var(--shade) / 0.3) 58%, transparent 80%),
    linear-gradient(180deg, rgb(var(--shade) / 0.75) 0%, transparent 26%, transparent 62%, var(--ink) 100%);
}
.hero__scrim[hidden] { display: none; }

/* With a photograph present the canvas and its gradient stand-in step back. */
.hero.has-photo #hero-canvas,
.hero.has-photo .hero__fallback { opacity: 0; }

.hero.has-photo .hero__inner { grid-template-columns: minmax(0, 1fr); }
.hero.has-photo .hero__copy-col { max-width: min(100%, 44rem); }

/* The grain sits over the photograph too, which is what stops a compressed
   image from banding across a large dark gradient. */
.hero__grain { z-index: 3; }

/* ---------------------------------------------- bright hero photographs */

/**
 * A high-key photograph needs the opposite treatment to a dark one: light
 * scrim, dark ink. The section then resolves down into the page's own dark
 * over the last third, so scrolling reads as one continuous change rather
 * than a hard edge between a white block and a black one.
 */
.hero[data-tone='bright'] .hero__scrim {
  background:
    linear-gradient(94deg, rgb(248 248 250 / 0.96) 0%, rgb(248 248 250 / 0.9) 30%, rgb(248 248 250 / 0.6) 50%, rgb(248 248 250 / 0.16) 70%, transparent 86%),
    linear-gradient(180deg, rgb(248 248 250 / 0.5) 0%, transparent 18%, transparent 44%, rgb(var(--shade) / 0.55) 74%, var(--ink) 100%);
}

.hero[data-tone='bright'] { color: #101014; }
.hero[data-tone='bright'] .hero__copy { color: #3d3d47; }
.hero[data-tone='bright'] .hero__badge {
  color: #2a2a33;
  background: rgb(255 255 255 / 0.6);
  border-color: rgb(16 16 20 / 0.16);
}
.hero[data-tone='bright'] .btn--ghost { color: #101014; border-color: rgb(16 16 20 / 0.28); }
.hero[data-tone='bright'] .btn--ghost:hover { border-color: var(--pink); background: rgb(255 255 255 / 0.5); }

/* The nav sits on the bright part of the photo until it sticks. */
.hero[data-tone='bright'] ~ * .nav,
body:has(.hero[data-tone='bright']) .nav:not(.is-stuck) { color: #101014; }
body:has(.hero[data-tone='bright']) .nav:not(.is-stuck) .nav__link { color: #44444f; }
body:has(.hero[data-tone='bright']) .nav:not(.is-stuck) .nav__link:hover { color: #101014; }
body:has(.hero[data-tone='bright']) .nav:not(.is-stuck) .cart-btn,
body:has(.hero[data-tone='bright']) .nav:not(.is-stuck) .theme-btn,
body:has(.hero[data-tone='bright']) .nav:not(.is-stuck) .nav__toggle {
  color: #101014;
  background: rgb(255 255 255 / 0.55);
  border-color: rgb(16 16 20 / 0.16);
}
body:has(.hero[data-tone='bright']) .nav:not(.is-stuck) .nav__toggle span { background: #101014; }

.hero[data-tone='bright'] .btn--ghost {
  --btn-bg: rgb(255 255 255 / 0.55);
  border-color: rgb(16 16 20 / 0.16);
  color: #101014;
}
.hero[data-tone='bright'] .btn--ghost:hover {
  --btn-bg: rgb(255 255 255 / 0.78);
  border-color: rgb(16 16 20 / 0.28);
}

/* The brand wordmark is white artwork, so it needs the dark chip back. */
body:has(.hero[data-tone='bright']) .nav:not(.is-stuck) .nav__brand span { color: #101014; }

/* ==========================================================================
   Scroll choreography
   The page is one continuous move from the photograph down into the catalogue.
   Everything below is driven by GSAP in store.js; each rule declares its own
   resting value so the page is correct before any script runs and stays
   correct if none ever does.
   ========================================================================= */

/* Hero headline, split into words by store.js. The clipping is done by
   .hero__line, which already masks the line, so the word boxes stay plain
   inline-blocks and the chrome gradient keeps painting across the whole line. */
.hero__line .word,
.hero__line .word__inner { display: inline-block; }

/* Reading position, as a hairline across the top of the page. */
.scroll-progress {
  position: fixed; inset: 0 0 auto; z-index: 120;
  height: 2px; background: var(--accent);
  transform: scaleX(0); transform-origin: left center;
  pointer-events: none;
}

/* The scrim deepens as the hero leaves, so the photograph hands over to the
   page rather than being cut off by the next section's edge. */
.hero__scrim { --scrim-boost: 0; }
.hero__scrim::after {
  content: ''; position: absolute; inset: 0;
  background: linear-gradient(180deg, transparent 34%, var(--ink) 100%);
  opacity: var(--scrim-boost);
}

/* A single pass of light across a section headline as it arrives. */
/* The sweep is a background slid across a pinned overlay rather than a
   translated box, so it can never paint outside the headline and the soft
   bloom on ::after keeps its blurred edges. */
.section__title { --sweep: -60%; }
.section__title::before {
  content: ''; position: absolute; inset: 0; z-index: 1;
  background-image: linear-gradient(104deg, transparent 42%, rgb(var(--tint) / 0.22) 50%, transparent 58%);
  background-size: 260% 100%;
  background-position: var(--sweep) 0;
  background-repeat: no-repeat;
  pointer-events: none;
}

/* While GSAP drives the marquee from scroll velocity the CSS keyframes would
   fight it, so they step aside. Without JavaScript they remain the animation. */
.marquee.is-driven .marquee__track { animation: none; }

/* The step numbers are a CSS counter until JavaScript counts them up, at which
   point the real number lives in the element and the generated one would
   double it. */
.step__n[data-counted]::before { content: none; }

/* ---------------------------------------------------------------- type ---
   Anton is drawn tight. At headline sizes it wants negative tracking; the
   positive values it had were spacing the caps apart until they read as a
   label rather than a headline. */

.hero__badge-sep {
  display: inline-block; margin: 0 0.55rem;
  color: var(--text-faint);
}
