@charset "UTF-8";

:root {
  --ink: #0c1410;
  --ink-deep: #070d0a;
  --surface: #12201a;
  --surface-raised: #182a22;
  --cream: #f6f1e6;
  /* QR stays pure black-on-white in every theme so it always scans; defining
     these is required — .qr-background/.qr-module reference them, and without a
     value the SVG paints transparent (a blank square). */
  --qr-light: #ffffff;
  --qr-dark: #000000;
  --cream-soft: #dbd3c4;
  --cream-muted: #a39c8c;
  --amber: #c9a227;
  --amber-bright: #e8c65a;
  --amber-dark: #8a6d14;
  --sage: #8fbf9a;
  --line: #26402f;
  --line-soft: #1b2f24;
  --shadow: #040a07;
  --focus: #f0d97a;
  --error: #e8b3a8;
  --backdrop: #070d0ae6;
  --tray: #12201af2;
  --gradient-hero: radial-gradient(circle at 72% 44%, #1d3b2a 0%, #12241b 25%, #0c1410 52%, #070d0a 100%);
  --gradient-fallback: radial-gradient(circle at 70% 44%, #2f5c3f 0%, #17301f 28%, #0c1410 64%);
  --gradient-shade: linear-gradient(90deg, #0c1410f2 0%, #0c1410c4 35%, #0c141038 65%, #0c14101a 100%);
  --gradient-card: linear-gradient(145deg, #182a22 0%, #12201a 100%);
  --gradient-glow: radial-gradient(circle, #c9a22726 0%, #c9a22700 70%);
  --gradient-petal: radial-gradient(ellipse at 30% 25%, #f6f1e612, #c9a2270a 55%, #f6f1e600 75%);
  --gradient-grain: repeating-radial-gradient(circle at 17% 32%, #f6f1e618 0 0.45px, #00000000 0.8px 3px);

  /* 3D candle palette: ivory wax, gold key, evergreen rim */
  --wax: #a69485;
  --wax-emissive: #5d4a2a;
  --heart: #7a6352;
  --wick: #f4eee2;
  --tree: #102b1c;
  --tree-lights: #ffd27a;
  --bauble-red: #7a2027;
  --bauble-gold: #9c7730;
  --pool: #e6d8bb;
  --pool-glow: #a8741f;
  --flame-outer: #ffd25c;
  --flame-outer-tip: #ff7a1e;
  --flame-inner: #fffbe8;
  --flame-inner-tip: #ffcf70;
  --flame-light: #ffb347;
  --hemi-sky: #dfe8d8;
  --hemi-ground: #0e1a14;
  --fill-light: #8fbf9a;
  --key-light: #ffe4b0;
  --rim-light: #9fd8b4;
  --feature: #6b5a44;

  --font-display: "Cormorant Garamond", Georgia, serif;
  --font-body: "Manrope", "Helvetica Neue", sans-serif;

  --space-1: 0.25rem;
  --space-2: 0.5rem;
  --space-3: 0.75rem;
  --space-4: 1rem;
  --space-5: 1.5rem;
  --space-6: 2rem;
  --space-7: 3rem;
  --space-8: 4rem;
  --space-9: 6rem;
  --space-10: 8rem;
  --space-11: 10rem;
  --gutter: clamp(1.25rem, 4vw, 4rem);
  --section-space: clamp(6rem, 12vw, 11rem);
  --page-width: 88rem;
  --order-tray-height: 0px;
  --nav-height: 5rem;
  /* Themes override this so the warm hero footage sits inside every palette. */
  --hero-media-filter: saturate(1.08) contrast(1.03);

  --radius-small: 0.35rem;
  --radius-medium: 0.8rem;
  --radius-round: 999px;

  --ease-out: cubic-bezier(0.22, 1, 0.36, 1);
  --ease-soft: cubic-bezier(0.4, 0, 0.2, 1);
  --duration-fast: 180ms;
  --duration-medium: 420ms;
  --duration-slow: 800ms;
}

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

html {
  /* Deliberately NOT scroll-behavior: smooth, globally. On WebKit it intercepts
     EVERY programmatic scroll, including the ones a smooth-scroll library / anchor
     jump issues mid-gesture, and the page then lags the requested position by
     hundreds of pixels before catching up in a lump — measured as a 734px shortfall
     in WebKit versus 0px without it. Smooth behaviour belongs on the specific
     anchor links that want it, not on the document. */
  scroll-padding-top: calc(var(--nav-height) + var(--space-3));
  background: var(--ink);
}

body {
  margin: 0;
  min-width: 20rem;
  padding-bottom: var(--order-tray-height);
  background: var(--ink);
  color: var(--cream-soft);
  font-family: var(--font-body);
  font-size: 1rem;
  line-height: 1.7;
  -webkit-font-smoothing: antialiased;
}

body.dialog-open { overflow: hidden; }

::selection { background: var(--amber-dark); color: var(--cream); }

h1, h2, h3, p, ul, ol, pre { margin-top: 0; }
h1, h2, h3 { color: var(--cream); font-family: var(--font-display); font-weight: 400; }
p { text-wrap: pretty; }
a { color: inherit; }
button, input, textarea { font: inherit; }
button, a { -webkit-tap-highlight-color: var(--transparent); }
button { color: inherit; }
img { display: block; max-width: 100%; }

:focus-visible {
  outline: 2px solid var(--focus);
  outline-offset: 5px;
}

[hidden] { display: none !important; }

.page-width {
  width: min(100%, var(--page-width));
  margin-inline: auto;
  padding-inline: var(--gutter);
}

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

.skip-link {
  position: fixed;
  z-index: 100;
  top: var(--space-4);
  left: var(--space-4);
  padding: var(--space-3) var(--space-4);
  transform: translate3d(0, -200%, 0);
  background: var(--cream);
  color: var(--ink);
  text-decoration: none;
  transition: transform var(--duration-fast) var(--ease-out);
}
.skip-link:focus { transform: translate3d(0, 0, 0); }

.eyebrow {
  margin-bottom: var(--space-4);
  color: var(--amber);
  font-size: 0.69rem;
  font-weight: 600;
  letter-spacing: 0.2em;
  line-height: 1.5;
  text-transform: uppercase;
}

.button {
  display: inline-flex;
  min-height: 3rem;
  align-items: center;
  justify-content: center;
  border: 1px solid var(--transparent);
  border-radius: var(--radius-round);
  padding: var(--space-3) var(--space-5);
  font-size: 0.78rem;
  font-weight: 600;
  letter-spacing: 0.04em;
  line-height: 1.2;
  text-decoration: none;
  cursor: pointer;
  transition: background var(--duration-fast) var(--ease-soft), color var(--duration-fast) var(--ease-soft), border-color var(--duration-fast) var(--ease-soft), transform var(--duration-fast) var(--ease-soft);
}
.button:hover { transform: translate3d(0, -2px, 0); }
.button:active { transform: translate3d(0, 0, 0); }
.button--primary { background: var(--amber); color: var(--ink-deep); }
.button--primary:hover { background: var(--amber-bright); }
.button--secondary { border-color: var(--line); background: var(--transparent); color: var(--cream); }
.button--secondary:hover { border-color: var(--amber); }
.button:disabled { opacity: 0.45; cursor: not-allowed; transform: none; }

.icon-button {
  display: inline-grid;
  width: 2.75rem;
  height: 2.75rem;
  place-items: center;
  border: 1px solid var(--line);
  border-radius: var(--radius-round);
  background: var(--surface);
  color: var(--cream);
  font-size: 1.6rem;
  font-weight: 400;
  line-height: 1;
  cursor: pointer;
  transition: border-color var(--duration-fast) var(--ease-soft), background var(--duration-fast) var(--ease-soft);
}
.icon-button:hover { border-color: var(--amber); background: var(--surface-raised); }

.text-link {
  display: inline-block;
  color: var(--amber-bright);
  text-underline-offset: 0.35em;
  text-decoration-color: var(--amber-dark);
  transition: color var(--duration-fast) var(--ease-soft), text-decoration-color var(--duration-fast) var(--ease-soft);
}
.text-link:hover { color: var(--cream); text-decoration-color: var(--cream); }

/* Hero */
.hero {
  position: relative;
  z-index: 1;
  min-height: 100svh;
  /* Sits underneath the sticky nav, which is in normal flow above it. */
  margin-top: calc(-1 * var(--nav-height));
  overflow: hidden;
  isolation: isolate;
  background: var(--gradient-hero);
}
.hero::before {
  position: absolute;
  z-index: 2;
  inset: 0;
  background: var(--gradient-shade);
  content: "";
  pointer-events: none;
}
.hero::after {
  position: absolute;
  z-index: 2;
  right: 0;
  bottom: 0;
  left: 0;
  height: 24%;
  background: linear-gradient(0deg, var(--ink), var(--transparent));
  content: "";
  pointer-events: none;
}
.hero-media {
  position: absolute;
  z-index: 1;
  inset: 0;
  overflow: hidden;
  pointer-events: none;
  /* The theme tint lives here, on a STATIC element that never transforms. Measured
     in WebKit: removing it changed frame drops by 1 in 38 — within noise. A filter
     on a non-moving parent is rasterised once and reused, so it is kept; the cost
     would only appear if this element translated or scaled per frame. */
  filter: var(--hero-media-filter);
}
.hero-image {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: 50% 48%;
  background: var(--ink-deep);
  /* No transform, ever. The picture simply scrolls with the page, behind the copy.
     Nothing here changes per frame, so nothing needs re-rasterising: the filtered
     bitmap in the parent is produced once and then just scrolls. The depth in the
     hero comes from the COPY drifting at its own rate (see .hero-copy), which is a
     small, unfiltered element and therefore cheap. */
}

.site-header {
  position: sticky;
  z-index: 40;
  top: 0;
  display: flex;
  height: var(--nav-height);
  align-items: center;
  border-bottom: 1px solid color-mix(in srgb, var(--line) 60%, transparent);
  /* A SOLID bar, not a translucent one. `backdrop-filter` re-blurs whatever is
     beneath it on every frame the page moves, which is the single most expensive
     thing a sticky element can ask a phone to do. A 92% opaque bar looked almost
     identical and cost a per-frame blur of the whole nav width, so it is now
     opaque and the blur is gone entirely. */
  background: var(--surface);
  transition: border-color var(--duration-medium) var(--ease-soft), box-shadow var(--duration-medium) var(--ease-soft);
}
.site-header__inner { display: flex; height: 100%; align-items: center; gap: var(--space-5); }
/* Compact state, toggled by the parallax rAF loop once the hero is behind us.
   Height stays fixed so the hero below never shifts. */
.site-header.is-scrolled {
  border-bottom-color: var(--line);
  background: var(--surface);
  box-shadow: 0 0.5rem 1.75rem color-mix(in srgb, var(--shadow) 45%, transparent);
}
.site-header.is-scrolled .wordmark { transform: scale(0.88); }

.wordmark {
  color: var(--cream);
  font-family: var(--font-display);
  font-size: 1.75rem;
  font-weight: 500;
  letter-spacing: 0.02em;
  line-height: 1;
  text-decoration: none;
  transform-origin: left center;
  transition: transform var(--duration-medium) var(--ease-soft), color var(--duration-fast) var(--ease-soft);
}
.nav-links { display: flex; gap: clamp(1rem, 3vw, 2.5rem); margin-left: auto; }
.nav-links a {
  color: var(--cream-soft);
  font-size: 0.73rem;
  font-weight: 500;
  letter-spacing: 0.08em;
  text-decoration: none;
  text-transform: uppercase;
  transition: color var(--duration-fast) var(--ease-soft);
}
.nav-links a:hover { color: var(--amber-bright); }

.hero-content {
  position: relative;
  z-index: 3;
  display: flex;
  min-height: 100svh;
  align-items: center;
  padding-block: var(--space-9);
  pointer-events: none;
}
.hero-copy {
  width: min(48%, 38rem);
  pointer-events: none;
  /* Static by design. This used to drift on a per-frame transform for "depth";
     measured in WebKit the drift bought nothing perceptible and cost a promoted
     layer plus a main-thread write on every frame of the first screenful. The
     picture and the words now scroll together, which is what the brief asked for. */
  /* Theme-aware soft halo keeps the copy legible where the footage is bright. */
  text-shadow: 0 0.15rem 1.6rem color-mix(in srgb, var(--ink) 85%, transparent);
}
.hero-copy > * { pointer-events: auto; }
.hero h1 { margin-bottom: var(--space-5); line-height: 0.78; }
.hero h1 > span {
  display: block;
  font-size: clamp(5rem, 10vw, 9.5rem);
  letter-spacing: -0.055em;
}
.hero h1 > small {
  display: block;
  margin-top: var(--space-6);
  color: var(--amber-bright);
  font-family: var(--font-body);
  font-size: clamp(0.75rem, 1.2vw, 0.95rem);
  font-weight: 500;
  letter-spacing: 0.28em;
  line-height: 1.5;
  text-transform: uppercase;
}
.hero-intro { max-width: 29rem; margin-bottom: 0; color: var(--cream-soft); font-size: clamp(0.95rem, 1.4vw, 1.1rem); }
.scroll-cue {
  position: absolute;
  z-index: 4;
  bottom: var(--space-6);
  left: var(--gutter);
  display: flex;
  align-items: center;
  gap: var(--space-4);
  color: var(--cream-muted);
  font-size: 0.67rem;
  letter-spacing: 0.13em;
  text-decoration: none;
  text-transform: uppercase;
}
.scroll-line { position: relative; display: block; width: 3.5rem; height: 1px; overflow: hidden; background: var(--line); }
.scroll-line::after {
  position: absolute;
  inset: 0;
  background: var(--amber);
  content: "";
  animation: scroll-line 2.4s var(--ease-soft) infinite;
  transform: translate3d(-100%, 0, 0);
}
@keyframes scroll-line { 55%, 100% { transform: translate3d(100%, 0, 0); } }
/* An infinite animation keeps ticking and compositing even once the hero has been
   scrolled past, which stops the phone ever going idle. parallax.js sets
   .is-offscreen on the hero when it leaves the viewport; the animation pauses. */
.hero.is-offscreen .scroll-line::after { animation-play-state: paused; }
@media (prefers-reduced-motion: reduce) {
  .scroll-line::after { animation: none; }
}

/* Ambient layers */
.page-grain {
  position: fixed;
  z-index: 20;
  inset: 0;
  /* A repeatable IMAGE, not a live CSS gradient.

     This element was the single largest source of scroll jank on the site. It is a
     full-viewport overlay, so a `repeating-radial-gradient` here had to be
     re-rasterised and re-blended over the whole screen on every single frame the
     page moved. Measured in WebKit, median p95 frame time, 4 trials per variant:

       live repeating-radial-gradient   113ms   (max frame 202ms)
       this 96x96 tiled image            35ms   (max frame  36ms)

     35ms is the blank-page ceiling on this harness — i.e. the overlay now costs
     essentially nothing. The tile is 3.5KB, decodes once, and the compositor only
     has to scroll a ready-made texture. The visual difference at 0.10 alpha is
     imperceptible; the previous gradient was 0.22 over a 0.45px repeat, which read
     as faint mottling either way. */
  background-image: url("assets/grain-tile.webp");
  background-repeat: repeat;
  background-size: 96px 96px;
  pointer-events: none;
}
.site-main { position: relative; overflow: hidden; isolation: isolate; }
/* No will-change here. Each of these used to be promoted to its own composited
   layer for the whole session, even off screen: at DPR 3 that is ~58MB of GPU
   memory for decoration (17MB for the grain alone), against a much smaller
   per-tab budget on iOS than a desktop GPU has. Exceed it and Safari falls back
   to a slow compositing path, which is felt as scroll stutter. These elements
   barely move (depth <= 0.12), so a plain transform is cheap without a layer. */
.ambient-glow, .wax-petal { position: absolute; z-index: -1; pointer-events: none; }
.ambient-glow { width: 42rem; height: 42rem; border-radius: 50%; background: var(--gradient-glow); }
.ambient-glow--one { top: 8%; right: -16rem; }
.ambient-glow--two { top: 55%; left: -20rem; }
.wax-petal { width: 13rem; height: 22rem; border: 1px solid var(--line-soft); border-radius: 80% 20% 65% 35%; background: var(--gradient-petal); }
.wax-petal--one { top: 27%; left: -5rem; rotate: -28deg; }
.wax-petal--two { top: 71%; right: -5rem; rotate: 32deg; }

/* Collection */
.collection { position: relative; padding-block: var(--section-space); }
.section-heading {
  display: grid;
  grid-template-columns: minmax(0, 1.5fr) minmax(16rem, 0.7fr);
  gap: var(--space-7);
  align-items: end;
  margin-bottom: var(--space-7);
}
.section-heading h2, .craft h2, .closing-note h2, .modal h2 {
  margin-bottom: 0;
  font-size: clamp(2.75rem, 5.2vw, 5rem);
  letter-spacing: -0.035em;
  line-height: 0.98;
}
.section-heading > p { max-width: 29rem; margin-bottom: var(--space-2); color: var(--cream-muted); }
.filter-bar { display: flex; align-items: center; justify-content: space-between; gap: var(--space-5); margin-bottom: var(--space-7); }
.filters { display: flex; flex-wrap: wrap; gap: var(--space-2); }
.filter-chip {
  min-height: 2.65rem;
  border: 1px solid var(--line-soft);
  border-radius: var(--radius-round);
  padding: var(--space-2) var(--space-4);
  background: var(--transparent);
  color: var(--cream-muted);
  font-size: 0.75rem;
  cursor: pointer;
  transition: color var(--duration-fast) var(--ease-soft), background var(--duration-fast) var(--ease-soft), border-color var(--duration-fast) var(--ease-soft);
}
.filter-chip span { margin-left: var(--space-2); color: var(--cream-muted); font-size: 0.65rem; }
.filter-chip:hover { border-color: var(--amber-dark); color: var(--cream); }
.filter-chip[aria-pressed="true"] { border-color: var(--amber); background: var(--amber); color: var(--ink-deep); }
.filter-chip[aria-pressed="true"] span { color: var(--ink); }
.collection-count { flex: 0 0 auto; margin: 0; color: var(--cream-muted); font-size: 0.75rem; }
.collection-error { padding: var(--space-6); border: 1px solid var(--line); color: var(--error); text-align: center; }

.product-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(min(100%, 17rem), 1fr));
  gap: clamp(1.25rem, 2.5vw, 2rem);
}
.product-card {
  position: relative;
  display: flex;
  flex-direction: column;
  min-width: 0;
  overflow: hidden;
  /* NO content-visibility. It was added to skip offscreen cards, but measured on
     three phone viewports it made the page WORSE: each card that rendered changed
     document.scrollHeight, once per card, growing the page by 124-179px a time
     (43 height changes in a single pass down the grid). That shifting total height
     is felt as the page "bumping" under the thumb, and on the widest viewport it
     also displaced the scroll position.

     `contain-intrinsic-size: auto 26rem` measured as 0px in WebKit, so the browser
     reserved nothing and then grew the layout as each card arrived. The cards are
     also not a fixed height (542/569px at 375px wide, 597px at 430px), so no single
     reserved value is correct at every width.

     Removing it costs nothing: the page already sits at the blank-page frame-time
     floor (site p95 19ms vs blank control 20ms). Simpler and correct beats clever
     and janky. Do not re-add this. */
  border: 1px solid var(--line-soft);
  border-radius: var(--radius-small);
  background: var(--gradient-card);
  box-shadow: 0 0 0 var(--shadow);
  transform-origin: center;
  transition: border-color var(--duration-medium) var(--ease-soft), box-shadow var(--duration-medium) var(--ease-soft), transform var(--duration-medium) var(--ease-out);
}
.product-card:hover {
  border-color: var(--amber-dark);
  box-shadow: 0 1.25rem 3.5rem color-mix(in srgb, var(--shadow) 65%, var(--transparent)), 0 0 2.5rem color-mix(in srgb, var(--amber) 8%, var(--transparent));
  transform: translate3d(0, -4px, 0);
}
.product-open { display: flex; flex: 1; flex-direction: column; width: 100%; border: 0; padding: 0; background: var(--transparent); text-align: left; cursor: pointer; }
.product-image { display: block; aspect-ratio: 1; overflow: hidden; background: var(--surface-raised); }
.product-image img { display: block; width: 100%; height: 100%; object-fit: cover; object-position: center; transition: transform var(--duration-slow) var(--ease-out), filter var(--duration-medium) var(--ease-soft); }
/* Every tile is the same square so rows stay level. Shots that are distinctly wide or
   tall are letterboxed inside it rather than centre-cropped, so no product is cut off —
   the dataset keeps changing, so this must not depend on any single image. */
.product-image[data-layout="wide"] img,
.product-image[data-layout="tall"] img { object-fit: contain; }
.product-card:hover .product-image img { transform: scale(1.035); filter: saturate(1.04); }
.product-copy { display: flex; flex: 1; flex-direction: column; padding: var(--space-5) var(--space-5) var(--space-4); }
.product-category { display: block; margin-bottom: var(--space-3); color: var(--sage); font-size: 0.63rem; font-weight: 600; letter-spacing: 0.14em; text-transform: uppercase; }
.product-name { display: block; min-height: 2.2em; margin-bottom: var(--space-2); color: var(--cream); font-family: var(--font-display); font-size: 1.55rem; font-weight: 500; line-height: 1.1; }
.product-scent { display: block; min-height: 1.5em; margin-bottom: var(--space-4); color: var(--cream-muted); font-size: 0.75rem; }
.product-price { color: var(--cream); font-family: var(--font-display); font-size: 1.35rem; }
.product-footer { display: flex; align-items: center; justify-content: space-between; gap: var(--space-3); padding: 0 var(--space-5) var(--space-5); margin-top: auto; }
.add-button {
  min-height: 2.65rem;
  border: 1px solid var(--line);
  border-radius: var(--radius-round);
  padding: var(--space-2) var(--space-4);
  background: var(--transparent);
  color: var(--cream-soft);
  font-size: 0.7rem;
  font-weight: 600;
  cursor: pointer;
  transition: background var(--duration-fast) var(--ease-soft), color var(--duration-fast) var(--ease-soft), border-color var(--duration-fast) var(--ease-soft);
}
.add-button::before { margin-right: var(--space-2); color: var(--amber); content: "+"; }
.add-button:hover { border-color: var(--amber); background: var(--amber); color: var(--ink-deep); }
.add-button:hover::before { color: var(--ink-deep); }

/* Craft and closing note */
.craft {
  position: relative;
  display: grid;
  grid-template-columns: minmax(0, 0.9fr) minmax(0, 1fr);
  gap: clamp(3rem, 9vw, 9rem);
  padding-block: var(--section-space);
  border-top: 1px solid var(--line-soft);
}
.craft-heading { align-self: start; position: sticky; top: var(--space-6); }
.craft h2 { font-size: clamp(2.8rem, 4.5vw, 4.5rem); line-height: 1.02; }
.craft-lead { margin-bottom: var(--space-7); color: var(--cream-soft); font-family: var(--font-display); font-size: clamp(1.4rem, 2.2vw, 1.85rem); line-height: 1.35; }
.process-list { margin: 0; padding: 0; list-style: none; }
.process-list li { display: grid; grid-template-columns: 2.5rem 1fr; gap: var(--space-4); padding-block: var(--space-5); border-top: 1px solid var(--line-soft); }
.process-list li > span { padding-top: var(--space-1); color: var(--amber); font-size: 0.68rem; letter-spacing: 0.1em; }
.process-list h3 { margin-bottom: var(--space-2); font-size: 1.65rem; }
.process-list p { margin-bottom: 0; color: var(--cream-muted); font-size: 0.9rem; }

.closing-note { max-width: 68rem; padding-block: var(--section-space); text-align: center; }
.closing-note h2 { margin-bottom: var(--space-6); font-size: clamp(2.3rem, 4.6vw, 4.3rem); font-style: italic; line-height: 1.08; }
.closing-note > p:not(.eyebrow) { margin-bottom: var(--space-4); color: var(--cream-muted); }
.site-footer { display: flex; align-items: center; justify-content: space-between; gap: var(--space-5); padding-block: var(--space-6); border-top: 1px solid var(--line-soft); }
.site-footer p { margin: 0; color: var(--cream-muted); font-size: 0.72rem; text-align: right; }

/* Scroll reveal */
[data-reveal] { opacity: 0; transform: translate3d(0, 2rem, 0); transition: opacity var(--duration-slow) var(--ease-out), transform var(--duration-slow) var(--ease-out); }
[data-reveal].is-visible { opacity: 1; transform: translate3d(0, 0, 0); }

/* Dialogs */
.modal {
  width: min(72rem, calc(100% - (2 * var(--gutter))));
  max-width: none;
  max-height: 92svh;
  margin: auto;
  overflow: auto;
  border: 1px solid var(--line);
  border-radius: var(--radius-medium);
  padding: 0;
  background: var(--surface);
  color: var(--cream-soft);
  box-shadow: 0 2rem 8rem var(--shadow);
}
.modal::backdrop { background: var(--backdrop); backdrop-filter: blur(8px); }
.modal[open] { animation: modal-in var(--duration-medium) var(--ease-out); }
@keyframes modal-in { from { opacity: 0; transform: translate3d(0, 1.25rem, 0) scale(0.985); } to { opacity: 1; transform: translate3d(0, 0, 0) scale(1); } }
.modal-shell { position: relative; }
.modal-close { position: absolute; z-index: 2; top: var(--space-4); right: var(--space-4); }
.quick-view__layout { display: grid; grid-template-columns: minmax(0, 1.1fr) minmax(20rem, 0.9fr); min-height: 34rem; }
.quick-view__image { display: grid; min-height: 100%; place-items: center; overflow: hidden; background: var(--ink-deep); }
.quick-view__image img { width: 100%; height: 100%; max-height: 82svh; object-fit: contain; }
.quick-view__content { display: flex; flex-direction: column; justify-content: center; padding: clamp(3.5rem, 6vw, 5.5rem) clamp(2rem, 4vw, 4rem) var(--space-7); }
.quick-view__content h2 { margin-bottom: var(--space-4); font-size: clamp(2.6rem, 4vw, 4rem); }
.quick-scent { margin-bottom: var(--space-2); color: var(--amber-bright); font-size: 0.9rem; }
.quick-notes { margin-bottom: var(--space-5); color: var(--sage); font-size: 0.75rem; }
.quick-blurb { margin-bottom: var(--space-5); color: var(--cream-muted); }
.quick-price { margin-bottom: var(--space-6); color: var(--cream); font-family: var(--font-display); font-size: 2rem; }
.quick-actions { display: flex; flex-wrap: wrap; gap: var(--space-4); }
.quantity-stepper { display: inline-flex; min-height: 3rem; align-items: center; border: 1px solid var(--line); border-radius: var(--radius-round); }
.quantity-stepper button { width: 2.8rem; height: 2.8rem; border: 0; border-radius: 50%; background: var(--transparent); color: var(--cream); cursor: pointer; }
.quantity-stepper button:hover { background: var(--surface-raised); }
.quantity-stepper button:disabled { opacity: 0.35; cursor: not-allowed; }
.quantity-stepper output { min-width: 2ch; color: var(--cream); text-align: center; }

.order-modal { width: min(36rem, calc(100% - (2 * var(--gutter)))); }
.order-modal__content { padding: clamp(2rem, 5vw, 3.5rem); text-align: center; }
.order-modal h2 { margin-bottom: var(--space-4); font-size: clamp(2.5rem, 5vw, 3.8rem); }
.order-modal__content > p:not(.eyebrow, .copy-status) { color: var(--cream-muted); }
.qr-code { width: min(100%, 21rem); margin: var(--space-6) auto; padding: var(--space-3); border-radius: var(--radius-small); background: var(--qr-light); line-height: 0; }
.qr-code svg { display: block; width: 100%; height: auto; shape-rendering: crispEdges; }
.qr-background { fill: var(--qr-light); }
.qr-module { fill: var(--qr-dark); }
.order-dialog__actions { display: flex; flex-wrap: wrap; justify-content: center; gap: var(--space-3); }
.copy-status { min-height: 1.5em; margin: var(--space-3) 0 0; color: var(--sage); font-size: 0.75rem; }
.order-preview { margin-top: var(--space-4); border-top: 1px solid var(--line-soft); padding-top: var(--space-4); text-align: left; }
.order-preview summary { color: var(--cream-muted); font-size: 0.75rem; cursor: pointer; }
.order-preview pre { max-height: 14rem; margin: var(--space-4) 0 0; overflow: auto; color: var(--cream-soft); font-family: var(--font-body); font-size: 0.73rem; line-height: 1.6; white-space: pre-wrap; }

/* Persistent order */
.order-tray {
  position: fixed;
  z-index: 30;
  right: var(--space-4);
  bottom: var(--space-4);
  left: var(--space-4);
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto auto;
  gap: var(--space-5);
  align-items: center;
  max-width: var(--page-width);
  margin-inline: auto;
  padding: var(--space-4) var(--space-5);
  border: 1px solid var(--line);
  border-radius: var(--radius-medium);
  background: var(--tray);
  box-shadow: 0 1rem 4rem var(--shadow);
  backdrop-filter: blur(18px);
  opacity: 0;
  transform: translate3d(0, calc(100% + var(--space-6)), 0);
  visibility: hidden;
  transition: opacity var(--duration-medium) var(--ease-out), transform var(--duration-medium) var(--ease-out), visibility var(--duration-medium);
}
.order-tray.is-visible { opacity: 1; transform: translate3d(0, 0, 0); visibility: visible; }
.order-tray__heading .eyebrow { margin-bottom: var(--space-1); font-size: 0.58rem; }
.order-tray__heading h2 { margin: 0; font-family: var(--font-body); font-size: 0.85rem; font-weight: 600; }
.order-tray__heading h2 span { display: block; color: var(--cream-muted); font-size: 0.65rem; font-weight: 400; }
.order-lines { display: flex; min-width: 0; gap: var(--space-2); margin: 0; padding: 0; overflow-x: auto; list-style: none; scrollbar-width: thin; }
.order-line { display: grid; flex: 0 0 auto; grid-template-columns: minmax(0, 1fr) auto; column-gap: var(--space-3); align-items: center; max-width: 15rem; padding: var(--space-2) var(--space-3); border: 1px solid var(--line-soft); border-radius: var(--radius-small); background: var(--ink); }
.order-line__name { overflow: hidden; color: var(--cream-soft); font-size: 0.67rem; text-overflow: ellipsis; white-space: nowrap; }
.order-line__total { color: var(--cream-muted); font-size: 0.65rem; }
.order-line__controls { display: flex; grid-row: 1 / span 2; grid-column: 2; align-items: center; }
.order-line__controls button { width: 1.8rem; height: 1.8rem; border: 0; background: var(--transparent); color: var(--amber-bright); cursor: pointer; }
.order-line__controls span { min-width: 1.5ch; color: var(--cream); font-size: 0.7rem; text-align: center; }
.order-total { min-width: 4.5rem; }
.order-total span { display: block; color: var(--cream-muted); font-size: 0.6rem; text-transform: uppercase; }
.order-total strong { color: var(--cream); font-family: var(--font-display); font-size: 1.4rem; font-weight: 500; }

@media (max-width: 64rem) {
  .hero-copy { width: 55%; }
  .filter-bar { align-items: flex-start; flex-direction: column; }
  .order-tray { grid-template-columns: auto minmax(0, 1fr) auto; }
  .order-tray__heading { display: none; }
}

@media (max-width: 48rem) {
  :root {
    /* The copy sits in the upper band on a phone, and the candle's lit body is
       directly behind it. This shape puts real weight at the top (where the
       wordmark and paragraph are), stays clear through the middle so the candle
       still reads as the subject, then darkens again for the scroll cue. */
    --gradient-shade: linear-gradient(180deg, #0c1410e8 0%, #0c1410b8 28%, #0c14103a 52%, #0c141040 70%, #0c1410e6 100%);
    --nav-height: 4.25rem;
  }
  .site-header.is-scrolled .wordmark { transform: scale(0.9); }
  .nav-links a { font-size: 0.63rem; }
  .nav-links a:nth-child(2) { display: none; }
  .hero-content { align-items: flex-start; padding-top: 18svh; text-align: center; }
  .hero-copy { width: 100%; }
  .hero h1 > span { font-size: clamp(4.7rem, 22vw, 7rem); }
  .hero h1 > small { margin-top: var(--space-5); font-size: 0.68rem; }
  .hero-intro { max-width: 24rem; margin-inline: auto; text-shadow: 0 0.1rem 0.9rem color-mix(in srgb, var(--ink) 92%, transparent), 0 0 1.6rem color-mix(in srgb, var(--ink) 70%, transparent); }
  .scroll-cue { right: 0; left: 0; justify-content: center; }
  .section-heading, .craft { grid-template-columns: 1fr; }
  .section-heading { gap: var(--space-5); }
  .craft { gap: var(--space-7); }
  .craft-heading { position: static; }
  .quick-view__layout { grid-template-columns: 1fr; }
  .quick-view__image { min-height: 0; max-height: 43svh; }
  .quick-view__image img { height: 43svh; object-fit: contain; }
  .quick-view__content { padding-top: var(--space-7); }
  .order-tray { grid-template-columns: minmax(0, 1fr) auto; gap: var(--space-3); padding: var(--space-3); }
  .order-lines { grid-row: 2; grid-column: 1 / -1; }
  .order-total { padding-left: var(--space-2); }
  .order-tray .button { min-height: 2.75rem; padding-inline: var(--space-4); }
  .site-footer { align-items: flex-start; flex-direction: column; }
  .site-footer p { text-align: left; }
}

@media (max-width: 36rem) {
  .product-grid { grid-template-columns: minmax(0, 1fr); }
  .product-name, .product-scent { min-height: 0; }
  .modal { width: calc(100% - (2 * var(--space-3))); max-height: 95svh; }
  .quick-actions .button { flex: 1; }
  .order-dialog__actions { flex-direction: column; }
  .order-dialog__actions .button { width: 100%; }
  .closing-note h2 { font-size: 2.35rem; }
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation-duration: 0.01ms !important; animation-iteration-count: 1 !important; transition-duration: 0.01ms !important; }
  [data-parallax] { transform: none !important; }
  [data-reveal] { opacity: 1; transform: none; }
}
