/* ==========================================================================
   RUŌOD — one stylesheet for the whole site.

   Tokens first, then the reset, then primitives, then the page sections,
   then a short set of utilities. Nothing here loads from a third party: the
   type stacks are fonts already on the device and the only image in the CSS
   is an inline data URI. That is what keeps the page at zero external
   requests, with no font swap and nothing to disclose to a visitor.

   The palette is a perfume house's, not a software product's: an ivory paper
   ground, a warm ink, and one restrained brass accent that appears in the
   Ō of the wordmark, in hairlines and in links — and almost nowhere else.
   Every pair below was measured, not eyeballed:

     --ink       on --ivory   14.8:1      --ivory-text on --ink   16.0:1
     --muted     on --ivory    6.5:1      --ivory-muted on --ink   8.0:1
     --brass     on --ivory    5.5:1      --brass-soft on --ink    8.3:1
     --line-control on --ivory 3.3:1 (a control boundary needs 3:1)
     --line      on --ivory    1.3:1 (decorative only — never a boundary)
     --error     on --ivory    6.8:1      --error-soft on --ink    8.9:1
     --brass-warm on --sand    4.1:1 (large type only)

   Check any new pair before you use it; --line and --line-control are two
   tokens for exactly this reason.
   ========================================================================== */

:root {
  /* Surfaces */
  --ivory:        #F7F3EC;
  --sand:         #EFE8DC;
  --ink:          #14120F;
  --ink-soft:     #1E1B17;

  /* Ink on light */
  --text:         #231F19;
  --muted:        #5E564A;
  --brass:        #7A5D30;   /* links and small brass text: 5.5:1 on ivory */
  --brass-warm:   #8A6A38;   /* large type and rules only: 4.5:1 on ivory */

  /* Ink on dark */
  --ivory-text:   #F2EDE4;
  --ivory-muted:  #B3A895;
  --brass-soft:   #C9A86A;
  --brass-light:  #D9BE8A;

  /* Lines */
  --line:         #DCD3C2;   /* decorative divider on light */
  --line-control: #8F8472;   /* a control's own boundary on light: 3.3:1 */
  --line-dark:    #332E27;   /* decorative divider on ink */
  --line-dark-control: #6E6558;

  /* Forms */
  --field:        #FCFAF6;   /* a field's own ground, a shade lighter than the page */
  --error:        #9B2C1F;   /* 6.8:1 on ivory, 6.2:1 on sand, 7.3:1 on --field */
  --error-soft:   #F0A08F;   /* on ink: 8.9:1 */

  /* Type — device stacks only, so there is no font request and no swap.
     macOS and iOS resolve the first few names (Didot, Bodoni) and give the
     high-contrast face this brand wants; Windows falls through to
     Constantia and Georgia, which hold the same editorial weight. */
  --font-display: Didot, "Bodoni 72", "Hoefler Text", Baskerville,
                  "Iowan Old Style", Constantia, "Palatino Linotype",
                  Palatino, Georgia, "Times New Roman", serif;
  --font-body: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
               "Helvetica Neue", Arial, sans-serif;

  /* Rhythm */
  --gutter: 22px;
  --max-w: 1220px;
  --max-prose: 62ch;
  --max-column: 860px;   /* the reading column the sections after the hero share */
  --section-y: 88px;
  --notice-h: 48px;      /* the demo notice's band, two lines on a phone */
  --announce-h: 52px;    /* the announcement bar, two lines on a phone */

  /* Motion */
  --ease: cubic-bezier(0.22, 0.61, 0.36, 1);

  /* The paper grain (see body::after), shared with the full-screen
     announcement's sheet. The one image in this stylesheet. */
  --grain: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='3' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='160' height='160' filter='url(%23n)' opacity='0.16'/%3E%3C/svg%3E");
}

@media (min-width: 720px)  { :root { --gutter: 34px; --section-y: 120px; --notice-h: 36px; --announce-h: 44px; } }
@media (min-width: 1100px) { :root { --gutter: 44px; --section-y: 148px; } }

/* --------------------------------------------------------------------------
   Reset
   -------------------------------------------------------------------------- */

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

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
  scroll-padding-top: 80px;
}

body {
  margin: 0;
  background: var(--ivory);
  color: var(--text);
  font-family: var(--font-body);
  font-size: 17px;
  line-height: 1.68;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  overflow-x: hidden;
}

h1, h2, h3, p, figure, figcaption, ul, ol, dl, dd { margin: 0; }
[hidden] { display: none !important; }
.no-js .js-only { display: none !important; }
img, svg { display: block; max-width: 100%; }

a { color: var(--brass); text-decoration-thickness: 1px; text-underline-offset: 3px; }
a:hover { color: var(--brass-warm); }

:focus-visible {
  outline: 2px solid var(--brass);
  outline-offset: 3px;
  border-radius: 2px;
}

/* The grain. One inline data URI, drawn over the whole page at a low opacity
   so the ivory reads as paper rather than as a flat fill. It is behind
   nothing and catches no pointer events. */
body::after {
  content: "";
  position: fixed;
  inset: 0;
  z-index: 9;
  pointer-events: none;
  opacity: 0.4;
  mix-blend-mode: multiply;
  background-image: var(--grain);
}

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }
}

/* --------------------------------------------------------------------------
   Primitives
   -------------------------------------------------------------------------- */

.wrap {
  width: 100%;
  max-width: var(--max-w);
  margin-inline: auto;
  padding-inline: var(--gutter);
}

.skip-link {
  position: absolute;
  left: -9999px;
  top: 0;
  z-index: 50;
  background: var(--ink);
  color: var(--ivory-text);
  padding: 12px 18px;
  font-size: 15px;
  text-decoration: none;
}
.skip-link:focus {
  left: 12px;
  top: 12px;
}

.eyebrow {
  font-size: 12px;
  letter-spacing: 0.26em;
  text-transform: uppercase;
  color: var(--brass);
  font-weight: 600;
}
.eyebrow-light { color: var(--brass-soft); }

h1 {
  font-family: var(--font-display);
  font-weight: 400;
  font-size: clamp(2.7rem, 9vw, 5.1rem);
  line-height: 1.04;
  letter-spacing: -0.015em;
  color: var(--text);
}
h1 em {
  font-style: italic;
  color: var(--brass-warm);
}

h2 {
  font-family: var(--font-display);
  font-weight: 400;
  font-size: clamp(1.8rem, 4.6vw, 2.9rem);
  line-height: 1.16;
  letter-spacing: -0.01em;
}

.lede {
  font-family: var(--font-display);
  font-size: clamp(1.08rem, 2.1vw, 1.32rem);
  line-height: 1.6;
  color: var(--muted);
  max-width: 48ch;
}

.note {
  font-size: 13.5px;
  line-height: 1.6;
  color: var(--muted);
  max-width: 46ch;
}
.note-centre { margin-inline: auto; text-align: center; }

/* Buttons. 48px minimum height, which is the tap target, not a style choice. */
.button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 52px;
  padding: 14px 30px;
  border: 1px solid var(--line-control);
  background: transparent;
  color: var(--text);
  font-family: var(--font-body);
  font-size: 13.5px;
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  text-decoration: none;
  transition: background-color 0.4s var(--ease), color 0.4s var(--ease),
              border-color 0.4s var(--ease);
}
.button:hover {
  background: var(--ink);
  border-color: var(--ink);
  color: var(--ivory-text);
}

.button-quiet {
  border-color: transparent;
  padding-inline: 12px;
  color: var(--muted);
}
.button-quiet:hover {
  background: transparent;
  border-color: transparent;
  color: var(--brass);
}

.button-dark {
  background: var(--ink);
  border-color: var(--ink);
  color: var(--ivory-text);
}
.button-dark:hover {
  background: var(--brass-warm);
  border-color: var(--brass-warm);
  color: var(--ivory-text);
}

/* The wordmark, set as text so it stays sharp, selectable and free of a
   network request. The Ō is the one place the brass appears at size. */
.wordmark {
  display: inline-flex;
  align-items: center;
  min-height: 44px;   /* the tap target, not a style choice */
  text-decoration: none;
  color: inherit;
}
.wordmark-text {
  font-family: var(--font-display);
  font-size: 21px;
  letter-spacing: 0.3em;
  text-indent: 0.3em;   /* balances the trailing letter-space */
  color: var(--text);
  display: inline-block;
}
.wordmark-o { color: var(--brass-warm); }

/* --------------------------------------------------------------------------
   Masthead and navigation

   The masthead lies over the top of each page rather than above it, so the
   hero's aura runs to the edge of the screen. Wide screens show the links in
   a row. Narrow ones fold them into a Menu button (js/script.js) that opens
   a full-screen panel of ivory — and without JavaScript, the links simply
   wrap onto a second row under the wordmark, so nothing is ever unreachable.
   -------------------------------------------------------------------------- */

.masthead {
  position: absolute;
  inset: 0 0 auto 0;
  z-index: 10;
  padding-block: 26px;
}
html.is-demo .masthead { top: var(--notice-h); }
html.has-announcement .masthead { top: var(--announce-h); }
/* :where() keeps this as specific as the two above, so the open menu's
   `top: 0` further down still wins. */
html.is-demo:where(.has-announcement) .masthead { top: calc(var(--notice-h) + var(--announce-h)); }

.masthead-inner {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 0 28px;
}
.wordmark { position: relative; z-index: 2; }

.site-nav {
  order: 3;
  width: 100%;
}
.site-nav-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-wrap: wrap;
  gap: 0 20px;
}

.site-nav a,
.bag-link {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  padding-inline: 2px;
  font-size: 12.5px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  font-weight: 600;
  color: var(--muted);
  text-decoration: none;
  /* The underline is a background, so it can grow from the left. */
  background: linear-gradient(var(--brass), var(--brass)) no-repeat 0 calc(100% - 9px) / 0 1px;
  transition: color 0.35s var(--ease), background-size 0.45s var(--ease);
}
.site-nav a:hover,
.site-nav a[aria-current="page"],
.bag-link:hover,
.bag-link[aria-current="page"] {
  color: var(--brass);
  background-size: 100% 1px;
}

.masthead-tools {
  position: relative;
  z-index: 2;
  display: flex;
  align-items: center;
  gap: 18px;
}

.bag-link { gap: 8px; min-width: 44px; justify-content: center; }
.bag-count {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 20px;
  height: 20px;
  padding-inline: 5px;
  border-radius: 10px;
  background: var(--ink);
  color: var(--ivory-text);
  font-size: 11px;
  letter-spacing: 0;
}
.bag-count.is-empty { display: none; }

.nav-toggle { display: none; }

/* On the narrowest phones the wordmark, Bag and Menu only share one line if
   the word "Menu" gives way to its two hairlines. It stays the button's
   accessible name. */
@media (max-width: 400px) {
  .masthead-inner { column-gap: 16px; }
  .masthead-tools { gap: 10px; }
  .nav-toggle-label {
    position: absolute;
    width: 1px; height: 1px;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
  }
}

@media (min-width: 1080px) {
  .masthead-inner { flex-wrap: nowrap; }
  .site-nav {
    order: 0;
    width: auto;
    margin-left: auto;
  }
  .site-nav-list { gap: 0 28px; }
  .masthead-tools {
    padding-left: 28px;
    border-left: 1px solid var(--line);
  }
}

@media (max-width: 1079px) {
  html:not(.no-js) .nav-toggle {
    display: inline-flex;
    align-items: center;
    gap: 12px;
    min-height: 44px;
    min-width: 44px;
    padding: 0 2px;
    background: none;
    border: 0;
    color: var(--text);
    font: 600 12.5px/1 var(--font-body);
    letter-spacing: 0.16em;
    text-transform: uppercase;
    cursor: pointer;
  }
  /* Two hairlines that cross when the panel is open. */
  .nav-toggle-lines {
    position: relative;
    width: 22px;
    height: 9px;
  }
  .nav-toggle-lines::before,
  .nav-toggle-lines::after {
    content: "";
    position: absolute;
    left: 0;
    right: 0;
    height: 1px;
    background: currentColor;
    transition: transform 0.4s var(--ease), top 0.4s var(--ease);
  }
  .nav-toggle-lines::before { top: 0; }
  .nav-toggle-lines::after  { top: 8px; }
  .nav-toggle[aria-expanded="true"] .nav-toggle-lines::before { top: 4px; transform: rotate(45deg); }
  .nav-toggle[aria-expanded="true"] .nav-toggle-lines::after  { top: 4px; transform: rotate(-45deg); }

  /* While the panel is open the whole masthead holds to the top of the
     screen, so Close stays where it was even if the page had been scrolled,
     and it sits above the demo notice along with the panel. */
  html.nav-open .masthead { position: fixed; top: 0; z-index: 12; }

  html:not(.no-js) .site-nav {
    position: fixed;
    inset: 0;
    z-index: 1;
    display: flex;
    flex-direction: column;
    justify-content: center;
    padding: 112px var(--gutter) 56px;
    background: var(--ivory);
    overflow-y: auto;
    visibility: hidden;
    opacity: 0;
    transition: opacity 0.45s var(--ease), visibility 0s linear 0.45s;
  }
  html:not(.no-js) .site-nav.is-open {
    visibility: visible;
    opacity: 1;
    transition: opacity 0.45s var(--ease);
  }
  html:not(.no-js) .site-nav-list {
    flex-direction: column;
    gap: 0;
    border-top: 1px solid var(--line);
  }
  html:not(.no-js) .site-nav-list li {
    border-bottom: 1px solid var(--line);
    opacity: 0;
    transform: translateY(10px);
    transition: opacity 0.6s var(--ease), transform 0.6s var(--ease);
  }
  html:not(.no-js) .site-nav.is-open li { opacity: 1; transform: none; }
  html:not(.no-js) .site-nav.is-open li:nth-child(2) { transition-delay: 0.05s; }
  html:not(.no-js) .site-nav.is-open li:nth-child(3) { transition-delay: 0.1s; }
  html:not(.no-js) .site-nav.is-open li:nth-child(4) { transition-delay: 0.15s; }
  html:not(.no-js) .site-nav.is-open li:nth-child(5) { transition-delay: 0.2s; }
  html:not(.no-js) .site-nav a {
    width: 100%;
    min-height: 68px;
    font-family: var(--font-display);
    font-size: clamp(1.7rem, 7vw, 2.4rem);
    font-weight: 400;
    letter-spacing: 0;
    text-transform: none;
    color: var(--text);
    background: none;
  }
  html:not(.no-js) .site-nav a[aria-current="page"] { color: var(--brass-warm); }
  html:not(.no-js) .site-nav a:hover { color: var(--brass); }
  html.nav-open,
  html.nav-open body { overflow: hidden; }
}

/* The demo notice. js/store.js adds it while config.demo is true, so a
   visitor can never mistake the sample collection or the sample bank account
   for real ones. Its height is fixed so the masthead can sit beneath it. */
.demo-notice {
  position: relative;
  z-index: 11;
  height: var(--notice-h);
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 12px;
  padding-inline: var(--gutter);
  background: var(--ink);
  color: var(--ivory-muted);
  font-size: 11.5px;
  line-height: 1.35;
  letter-spacing: 0.02em;
  text-align: center;
  overflow: hidden;
}
.demo-notice-label {
  flex-shrink: 0;
  color: var(--brass-soft);
  font-size: 10.5px;
  font-weight: 600;
  letter-spacing: 0.2em;
  text-transform: uppercase;
}

/* The announcement bar. js/store.js draws it above the masthead while
   config.announcement is enabled and has a message; otherwise it does not
   exist and the masthead sits where it always has. Its height is fixed, as
   the demo notice's is, so the masthead can sit beneath it and a longer
   message never moves the page: every message is laid over the same box,
   two lines at most on a phone, one from 720px.

   Messages take turns by class alone. The one shown is .is-current; the one
   going is .is-leaving; the rest wait, hidden, where the next one enters
   from. Direction and speed are classes on the bar, named after the values
   in config.js. Vertical messages roll through the bar's own height;
   horizontal ones move a short way and cross through nothing — the old one
   is gone before the new one arrives. Under prefers-reduced-motion they
   simply change. */
.announcement {
  position: relative;
  height: var(--announce-h);
  background: var(--sand);
  border-bottom: 1px solid var(--line);
  color: var(--text);
}
.announcement-inner {
  display: flex;
  align-items: center;
  gap: 4px;
  height: 100%;
}
.announcement-window {
  position: relative;
  flex: 1 1 auto;
  min-width: 0;
  height: 100%;
  overflow: hidden;
}
.announcement-message {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  text-align: center;
  font-size: 10px;
  font-weight: 600;
  line-height: 1.5;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  visibility: hidden;
  opacity: 0;
  transform: var(--announce-in);
}
.announcement-text {
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
  overflow: hidden;
  overflow-wrap: anywhere;
}

.announcement-up    { --announce-in: translate3d(0, 100%, 0);  --announce-out: translate3d(0, -100%, 0); }
.announcement-down  { --announce-in: translate3d(0, -100%, 0); --announce-out: translate3d(0, 100%, 0); }
.announcement-left  { --announce-in: translate3d(28px, 0, 0);  --announce-out: translate3d(-28px, 0, 0); }
.announcement-right { --announce-in: translate3d(-28px, 0, 0); --announce-out: translate3d(28px, 0, 0); }
.announcement-slow   { --announce-t: 1.1s; }
.announcement-normal { --announce-t: 0.8s; }
.announcement-fast   { --announce-t: 0.5s; }

.announcement-message.is-current {
  visibility: visible;
  opacity: 1;
  transform: none;
  transition: transform var(--announce-t) var(--ease), opacity var(--announce-t) var(--ease);
}
.announcement-message.is-leaving {
  opacity: 0;
  transform: var(--announce-out);
  transition: transform var(--announce-t) var(--ease), opacity var(--announce-t) var(--ease),
              visibility 0s linear var(--announce-t);
}
/* Sideways, each half of the time is one message's: out, then in. */
.announcement-left .announcement-message.is-current,
.announcement-right .announcement-message.is-current {
  transition-duration: calc(var(--announce-t) / 2);
  transition-delay: calc(var(--announce-t) / 2);
}
.announcement-left .announcement-message.is-leaving,
.announcement-right .announcement-message.is-leaving {
  transition-duration: calc(var(--announce-t) / 2), calc(var(--announce-t) / 2), 0s;
  transition-delay: 0s, 0s, calc(var(--announce-t) / 2);
}
@media (prefers-reduced-motion: reduce) {
  .announcement .announcement-message.is-current,
  .announcement .announcement-message.is-leaving { transition: none; }
}

/* Pause and play: two hairlines, or a small triangle once paused. The
   button keeps a 44px target and lends half of it to the gutter. */
.announcement-toggle {
  flex: 0 0 44px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 3px;
  width: 44px;
  height: 44px;
  margin-right: -12px;
  padding: 0;
  border: 0;
  background: none;
  color: var(--muted);
  cursor: pointer;
  transition: color 0.3s var(--ease);
}
.announcement-toggle:hover { color: var(--brass); }
.announcement-toggle::before,
.announcement-toggle::after {
  content: "";
  width: 2px;
  height: 10px;
  background: currentColor;
}
.announcement.is-paused .announcement-toggle::before {
  width: 0;
  height: 0;
  margin-left: 2px;
  background: none;
  border-left: 8px solid currentColor;
  border-block: 5px solid transparent;
}
.announcement.is-paused .announcement-toggle::after { display: none; }

@media (min-width: 720px) {
  .announcement-message {
    font-size: 11px;
    letter-spacing: 0.16em;
  }
  .announcement-text {
    -webkit-line-clamp: 1;
  }
  /* A brass hairline either side of the words. */
  .announcement-message::before,
  .announcement-message::after {
    content: "";
    flex: 0 0 18px;
    height: 1px;
    margin-inline: 16px;
    background: var(--brass-warm);
  }
  /* While messages take turns, an empty space on the left as wide as the
     button on the right keeps the words on the page's centre line. */
  .announcement.is-rotating .announcement-inner::before {
    content: "";
    flex: 0 0 32px;
  }
}

/* --------------------------------------------------------------------------
   The full-screen announcement — not the bar above: one large, image-led
   announcement that js/store.js opens over the page as a modal <dialog>
   while config.fullScreenAnnouncement allows.

   A sheet of the same ivory paper, not an advertising pop-up. The picture
   is never cropped (object-fit: contain): upright screens get the upright
   picture, the line drawn at 4:5, the same as the <source> in store.js;
   wide screens get the wide one. With words, the picture sits above them on
   an upright screen and beside them on a wide one; on a screen too short
   for both, the sheet scrolls and the Close button stays where it is.
   It fades in, the picture settling from a hair larger; with reduced
   motion it simply appears.
   -------------------------------------------------------------------------- */

html.has-spotlight,
html.has-spotlight body { overflow: hidden; }

.spotlight {
  position: fixed;
  inset: 0;
  width: 100%;
  height: 100vh;
  height: 100dvh;
  max-width: none;
  max-height: none;
  margin: 0;
  padding: 0;
  border: 0;
  background: var(--ivory);
  color: var(--text);
  overflow: hidden;
  opacity: 0;
  transition: opacity 0.6s var(--ease);
}
.spotlight.is-in { opacity: 1; }
.spotlight::backdrop { background: rgba(20, 18, 15, 0.55); }
.spotlight::after {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  opacity: 0.4;
  mix-blend-mode: multiply;
  background-image: var(--grain);
}

.spotlight-inner {
  display: grid;
  grid-template-rows: minmax(0, 1fr);
  gap: 26px;
  height: 100%;
  padding: 76px var(--gutter) var(--gutter);
  overflow-y: auto;
  overscroll-behavior: contain;
}
.spotlight-inner.has-copy { grid-template-rows: minmax(240px, 1fr) auto; }

.spotlight-figure {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 0;
  transform: scale(1.015);
  transition: transform 1.4s var(--ease);
}
.spotlight.is-in .spotlight-figure { transform: none; }
.spotlight-figure picture { display: contents; }
.spotlight-image {
  width: 100%;
  height: 100%;
  object-fit: contain;
}

.spotlight-copy {
  display: grid;
  justify-items: start;
  gap: 14px;
  max-width: 34rem;
  padding-bottom: 8px;
  opacity: 0;
  transform: translateY(10px);
  transition: opacity 0.9s var(--ease) 0.2s, transform 0.9s var(--ease) 0.2s;
}
.spotlight.is-in .spotlight-copy { opacity: 1; transform: none; }
.spotlight-title {
  font-family: var(--font-display);
  font-weight: 400;
  font-size: clamp(1.9rem, 4.4vw, 3.4rem);
  line-height: 1.08;
  letter-spacing: -0.01em;
  overflow-wrap: anywhere;
}
.spotlight-text {
  max-width: 46ch;
  font-family: var(--font-display);
  font-size: clamp(1.02rem, 1.8vw, 1.25rem);
  line-height: 1.55;
  color: var(--muted);
  overflow-wrap: anywhere;
}
.spotlight-cta { margin-top: 8px; }

/* Close: words and a hairline cross, always in the top corner. It is
   positioned against the dialog, not the scrolling sheet, so it never
   scrolls out of reach. */
.spotlight-close {
  position: absolute;
  top: 14px;
  right: calc(var(--gutter) - 10px);
  z-index: 2;
  display: inline-flex;
  align-items: center;
  gap: 12px;
  min-width: 44px;
  min-height: 44px;
  padding: 0 10px;
  border: 0;
  background: var(--ivory);
  color: var(--text);
  font: 600 12px/1 var(--font-body);
  letter-spacing: 0.18em;
  text-transform: uppercase;
  cursor: pointer;
  transition: color 0.3s var(--ease);
}
.spotlight-close:hover { color: var(--brass); }
.spotlight-close-cross { position: relative; width: 18px; height: 18px; }
.spotlight-close-cross::before,
.spotlight-close-cross::after {
  content: "";
  position: absolute;
  top: 50%;
  left: 0;
  width: 100%;
  height: 1px;
  background: currentColor;
  transform: rotate(45deg);
}
.spotlight-close-cross::after { transform: rotate(-45deg); }

/* Wide screens — computers, tablets and phones on their side: the picture
   beside the words. */
@media (min-aspect-ratio: 5/4) and (min-width: 600px) {
  .spotlight-inner { padding: 76px clamp(28px, 5vw, 80px) clamp(28px, 5vw, 64px); }
  .spotlight-inner.has-copy {
    grid-template-columns: minmax(0, 1.6fr) minmax(260px, 1fr);
    grid-template-rows: minmax(0, 1fr);
    align-items: center;
    column-gap: clamp(32px, 5vw, 88px);
  }
  .spotlight-inner.has-copy .spotlight-figure { height: 100%; }
  .spotlight-copy { align-self: center; max-height: 100%; }
}

/* Short upright screens (a small phone): a smaller picture, so the words
   and the button usually fit without scrolling. */
@media (max-height: 640px) and (max-aspect-ratio: 5/4) {
  .spotlight-inner { padding-top: 68px; gap: 18px; }
  .spotlight-inner.has-copy { grid-template-rows: minmax(170px, 1fr) auto; }
  .spotlight-title { font-size: 1.75rem; }
}

@media (prefers-reduced-motion: reduce) {
  .spotlight,
  .spotlight-figure,
  .spotlight-copy { transition: none; transform: none; }
}

/* --------------------------------------------------------------------------
   Hero
   -------------------------------------------------------------------------- */

.hero {
  position: relative;
  display: flex;
  align-items: center;
  min-height: 100vh;
  min-height: 100svh;
  padding-block: 132px 96px;
  overflow: hidden;
}

.hero-inner {
  position: relative;
  z-index: 2;
  display: grid;
  gap: clamp(40px, 7vw, 72px);
  align-items: center;
}

@media (min-width: 900px) {
  .hero-inner {
    grid-template-columns: minmax(0, 1.05fr) minmax(0, 0.95fr);
  }
}

.hero-copy > * + * { margin-top: 26px; }
.hero-copy .eyebrow + h1 { margin-top: 20px; }

.actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 12px 18px;
}

/* The aura: three soft fields of warmth behind the type. Blurred radial
   gradients rather than images, so they cost nothing to download and scale to
   any viewport. They drift very slowly, and not at all under
   prefers-reduced-motion — the rule at the top of this file stops them. */
.aura {
  position: absolute;
  inset: -12% -12% 0 -12%;
  z-index: 1;
  pointer-events: none;
}
.aura span {
  position: absolute;
  display: block;
  border-radius: 50%;
  filter: blur(60px);
  will-change: transform;
}
.aura-a {
  width: 62vmax; height: 62vmax;
  top: -16vmax; right: -12vmax;
  background: radial-gradient(circle at 50% 50%,
              rgba(201, 168, 106, 0.30), rgba(201, 168, 106, 0) 68%);
  animation: drift-a 46s var(--ease) infinite alternate;
}
.aura-b {
  width: 50vmax; height: 50vmax;
  bottom: -18vmax; left: -14vmax;
  background: radial-gradient(circle at 50% 50%,
              rgba(163, 134, 118, 0.26), rgba(163, 134, 118, 0) 70%);
  animation: drift-b 58s var(--ease) infinite alternate;
}
.aura-c {
  width: 34vmax; height: 34vmax;
  top: 32%; left: 38%;
  background: radial-gradient(circle at 50% 50%,
              rgba(122, 93, 48, 0.14), rgba(122, 93, 48, 0) 72%);
  animation: drift-c 72s var(--ease) infinite alternate;
}

@keyframes drift-a {
  from { transform: translate3d(0, 0, 0) scale(1); }
  to   { transform: translate3d(-5%, 4%, 0) scale(1.08); }
}
@keyframes drift-b {
  from { transform: translate3d(0, 0, 0) scale(1.04); }
  to   { transform: translate3d(6%, -5%, 0) scale(1); }
}
@keyframes drift-c {
  from { transform: translate3d(0, 0, 0); }
  to   { transform: translate3d(4%, 6%, 0); }
}

/* The figure. Concentric arcs opening from a point: a fragrance leaving the
   place it was made. It is decorative and abstract on purpose — there is no
   product photography on this site and nothing here should read as one. */
.hero-figure {
  position: relative;
  color: var(--brass-warm);
  text-align: center;
}
.diffusion {
  width: min(100%, 460px);
  margin-inline: auto;
  opacity: 0.75;
}
.hero-figure figcaption {
  margin-top: 18px;
  font-size: 12px;
  letter-spacing: 0.06em;
  color: var(--muted);
}

@media (max-width: 899px) {
  /* On a phone the figure moves behind the type and anchors to the foot of
     the hero, so the trail rises past the words instead of crossing the
     headline. The layout is rearranged, not merely shrunk. */
  .hero-figure {
    position: absolute;
    left: 50%;
    bottom: -14%;
    width: 132vw;
    margin-left: -66vw;
    display: flex;
    justify-content: center;
    z-index: 0;
    opacity: 0.5;
    pointer-events: none;
  }
  .hero-figure figcaption { display: none; }
  .diffusion { width: 100%; max-width: none; opacity: 0.85; }
  .hero-copy { position: relative; z-index: 1; }
}

/* Between a phone and the two-column layout the figure has room to be smaller
   than the viewport rather than wider than it: at 132vw the arcs sweep up
   behind the headline, which is busy rather than atmospheric. */
@media (min-width: 600px) and (max-width: 899px) {
  .hero-figure {
    width: 90vw;
    margin-left: -45vw;
    bottom: -12%;
    opacity: 0.42;
  }
}

/* The smallest phones still in use are 568px tall. Tightening the hero's own
   padding there is what keeps the call to action on the first screen; the
   type scale is already fluid and does not need a second set of sizes. */
@media (max-width: 420px) {
  .hero { padding-block: 106px 72px; }
  .hero-copy > * + * { margin-top: 22px; }
}

/* Each arc is fainter than the one below it: a trail thinning as it rises. */
.arc { opacity: 0.6; }
.arc-2 { opacity: 0.48; }
.arc-3 { opacity: 0.37; }
.arc-4 { opacity: 0.27; }
.arc-5 { opacity: 0.18; }
.stem { opacity: 0.3; }
.centre { opacity: 0.8; }

/* The arcs draw themselves in once, on load. pathLength="100" normalises the
   five different arc lengths, so each one draws at the same rate rather than
   the widest taking four times as long. Under prefers-reduced-motion the
   global rule collapses the animation to a single instant frame, and because
   the end state is the visible one, the figure simply appears complete. */
html:not(.no-js) .diffusion-arcs .arc {
  stroke-dasharray: 100;
  stroke-dashoffset: 100;
  animation: draw 2.4s var(--ease) forwards;
}
html:not(.no-js) .arc-2 { animation-delay: 0.16s; }
html:not(.no-js) .arc-3 { animation-delay: 0.32s; }
html:not(.no-js) .arc-4 { animation-delay: 0.48s; }
html:not(.no-js) .arc-5 { animation-delay: 0.64s; }

@keyframes draw { to { stroke-dashoffset: 0; } }

/* The scroll cue: a hairline that fills and empties. It is a real link to the
   next section, so it works by keyboard and means something without motion. */
.scroll-cue {
  position: absolute;
  left: 50%;
  bottom: 28px;
  z-index: 3;
  width: 44px;
  height: 56px;
  margin-left: -22px;
  display: flex;
  align-items: flex-end;
  justify-content: center;
}
.scroll-cue-line {
  display: block;
  width: 1px;
  height: 46px;
  background: linear-gradient(to bottom, rgba(122, 93, 48, 0), var(--brass-warm));
  transform-origin: top;
  animation: cue 3.4s var(--ease) infinite;
}
@keyframes cue {
  0%   { transform: scaleY(0.25); opacity: 0; }
  40%  { transform: scaleY(1);    opacity: 1; }
  100% { transform: scaleY(1);    opacity: 0; }
}
@media (max-height: 640px) { .scroll-cue { display: none; } }

/* --------------------------------------------------------------------------
   The house — the one dark passage on the page
   -------------------------------------------------------------------------- */

.statement {
  position: relative;
  background: var(--ink);
  color: var(--ivory-text);
  padding-block: var(--section-y);
  overflow: hidden;
}
.statement::before {
  /* A single warm field, low and to one side, so the ink is not flat. */
  content: "";
  position: absolute;
  width: 70vmax;
  height: 70vmax;
  left: -20vmax;
  bottom: -40vmax;
  background: radial-gradient(circle at 50% 50%,
              rgba(201, 168, 106, 0.13), rgba(201, 168, 106, 0) 66%);
  pointer-events: none;
}

.statement-inner {
  position: relative;
  z-index: 1;
  max-width: var(--max-column);
}
.statement h2 {
  margin-top: 22px;
  color: var(--ivory-text);
}
.statement .prose {
  margin-top: 34px;
  max-width: var(--max-prose);
  color: var(--ivory-muted);
  font-size: 16.5px;
}
.statement .prose p + p { margin-top: 20px; }

.signature {
  margin-top: 48px;
  padding-top: 30px;
  border-top: 1px solid var(--line-dark);
  font-family: var(--font-display);
  font-size: 15px;
  letter-spacing: 0.42em;
  color: var(--ivory-muted);
}
.signature .wordmark-o { color: var(--brass-soft); }

/* --------------------------------------------------------------------------
   RUŌOD Lab — the house's other product, served at /lab by its own site

   The statement's ivory counterpart: the same column, the same section rhythm
   and the same eyebrow → heading → prose steps, so the page reads as one
   sequence rather than a block dropped between two others. It stays quieter
   than the hero by taking the outlined button rather than the filled one.
   -------------------------------------------------------------------------- */

.lab {
  padding-block: var(--section-y);
}
.lab-inner { max-width: var(--max-column); }
.lab h2 { margin-top: 22px; }
.lab h2 em {
  font-style: italic;
  color: var(--brass-warm);
}
.lab-lede {
  margin-top: 34px;
  font-family: var(--font-display);
  font-size: clamp(1.02rem, 2vw, 1.18rem);
  line-height: 1.62;
  color: var(--muted);
  max-width: 52ch;
}
.lab-action { margin-top: 32px; }
.lab-arrow {
  margin-left: 12px;
  font-family: var(--font-body);
  letter-spacing: 0;
  transition: transform 0.4s var(--ease);
}
.lab-link:hover .lab-arrow { transform: translateX(4px); }

/* --------------------------------------------------------------------------
   Invitation
   -------------------------------------------------------------------------- */

.invite {
  background: var(--sand);
  padding-block: var(--section-y);
}
.invite-inner {
  max-width: 640px;
  text-align: center;
}
.invite-lede {
  margin-top: 20px;
  font-family: var(--font-display);
  font-size: clamp(1.02rem, 2vw, 1.18rem);
  line-height: 1.62;
  color: var(--muted);
}
.invite .button-dark { margin-top: 32px; }
.invite .note { margin-top: 22px; }

/* --------------------------------------------------------------------------
   Colophon
   -------------------------------------------------------------------------- */

.colophon {
  background: var(--sand);
  padding-block: 44px 52px;
}
.colophon-inner {
  border-top: 1px solid var(--line);
  padding-top: 34px;
  display: grid;
  gap: 14px;
  justify-items: center;
  text-align: center;
}
.colophon-mark {
  font-family: var(--font-display);
  font-size: 14px;
  letter-spacing: 0.4em;
  text-indent: 0.4em;
  color: var(--text);
}
.colophon-line {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  align-items: center;
  gap: 0 26px;
  font-size: 13.5px;
  color: var(--muted);
}
.colophon-line a {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  padding-inline: 2px;
}

/* Four links no longer fit one line on a phone; below the colophon's own
   grid breakpoint they stack. */
@media (max-width: 719px) {
  .colophon-line { flex-direction: column; gap: 0; }
}
.colophon-legal {
  font-size: 12.5px;
  color: var(--muted);
}

@media (min-width: 720px) {
  .colophon-inner {
    grid-template-columns: 1fr auto 1fr;
    align-items: center;
    justify-items: start;
    text-align: left;
  }
  .colophon-line { justify-content: center; }
  .colophon-legal { justify-self: end; }
}

/* --------------------------------------------------------------------------
   404
   -------------------------------------------------------------------------- */

.gone {
  display: flex;
  align-items: center;
  min-height: 100vh;
  min-height: 100svh;
  padding-block: 140px 100px;
  position: relative;
  overflow: hidden;
}
.gone-inner {
  position: relative;
  z-index: 2;
  max-width: 620px;
}
.gone h1 { font-size: clamp(2.2rem, 7vw, 3.6rem); }
.gone .lede { margin-top: 24px; }
.gone .actions { margin-top: 34px; }

/* --------------------------------------------------------------------------
   Shared pieces for the shop pages
   -------------------------------------------------------------------------- */

h3 {
  font-family: var(--font-display);
  font-weight: 400;
  line-height: 1.25;
}
h1 em,
h2 em {
  font-style: italic;
  color: var(--brass-warm);
}

/* An inline link inside running text. The vertical padding gives it a
   44px-tall target without moving a single line of the paragraph. */
.link-inline { padding-block: 14px; }

/* A quiet, underlined call to action for section heads. */
.text-link {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  min-height: 44px;
  font-size: 12.5px;
  font-weight: 600;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--text);
  text-decoration: none;
  background: linear-gradient(var(--brass-warm), var(--brass-warm)) no-repeat 0 calc(100% - 8px) / 100% 1px;
  transition: color 0.35s var(--ease);
}
.text-link:hover { color: var(--brass); }

.section-head {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  justify-content: space-between;
  gap: 18px 40px;
  margin-bottom: clamp(40px, 6vw, 64px);
}
.section-head .eyebrow + h2 { margin-top: 20px; }
.section-head h2 { max-width: 18ch; }

/* A page's opening, for every page that is not the front page. */
.page-head {
  position: relative;
  padding-block: 172px 64px;
  overflow: hidden;
}
.page-head-compact { padding-bottom: 36px; }
.page-head-inner { position: relative; z-index: 2; }
.page-head h1 {
  margin-top: 20px;
  max-width: 15ch;
  font-size: clamp(2.5rem, 7vw, 4.4rem);
}
.page-head .lede { margin-top: 26px; }
.aura-quiet {
  opacity: 0.7;
  /* Fade the glow out before the section ends, so it has no hard edge. */
  -webkit-mask-image: linear-gradient(to bottom, #000 55%, transparent 92%);
  mask-image: linear-gradient(to bottom, #000 55%, transparent 92%);
}
@media (max-width: 420px) {
  .page-head { padding-top: 132px; }
}

/* The quantity stepper: − [n] +. Each button is a full tap target. */
.qty {
  display: inline-flex;
  align-items: stretch;
  height: 52px;
  border: 1px solid var(--line-control);
  background: var(--field);
}
.qty-btn {
  width: 48px;
  padding: 0;
  background: none;
  border: 0;
  color: var(--text);
  font: 400 20px/1 var(--font-body);
  cursor: pointer;
  transition: background-color 0.3s var(--ease);
}
.qty-btn:hover:not(:disabled) { background: var(--sand); }
.qty-btn:disabled { color: var(--line-control); cursor: default; }
.qty-input {
  width: 52px;
  border: 0;
  border-inline: 1px solid var(--line);
  border-radius: 0;
  background: transparent;
  color: var(--text);
  font: 600 16px/1 var(--font-body);
  text-align: center;
  -moz-appearance: textfield;
  appearance: textfield;
}
.qty-input::-webkit-inner-spin-button,
.qty-input::-webkit-outer-spin-button { -webkit-appearance: none; margin: 0; }
.qty-small { height: 46px; }
.qty-small .qty-btn { width: 44px; }
.qty-small .qty-input { width: 44px; }

/* Definition rows, used for product facts and order details. */
.facts-row {
  display: grid;
  grid-template-columns: 112px minmax(0, 1fr);
  gap: 16px;
  padding-block: 14px;
  border-bottom: 1px solid var(--line);
  font-size: 15px;
}
.facts-row dt {
  padding-top: 2px;
  font-size: 11.5px;
  font-weight: 600;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--muted);
}

.button-light {
  background: var(--ivory-text);
  border-color: var(--ivory-text);
  color: var(--ink);
}
.button-light:hover {
  background: var(--brass-soft);
  border-color: var(--brass-soft);
  color: var(--ink);
}
.button:disabled { opacity: 0.7; cursor: progress; }

/* Focus on the dark passages needs the lighter brass to be seen. */
.statement :focus-visible,
.summary :focus-visible { outline-color: var(--brass-soft); }

/* --------------------------------------------------------------------------
   The collection — a list of perfumes, drawn by js/collection.js

   Editorial rather than a shop grid: large images, generous space, and the
   columns set off against each other so the page has a rhythm to it.
   -------------------------------------------------------------------------- */

.entries {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: 64px 0;
}
.entry-link {
  display: grid;
  gap: 22px;
  color: inherit;
  text-decoration: none;
}
.entry-figure {
  display: block;
  aspect-ratio: 4 / 5;
  overflow: hidden;
  background: var(--sand);
}
.entry-image {
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: transform 1.4s var(--ease);
}
.entry-link:hover .entry-image { transform: scale(1.035); }
.entry-text { display: grid; gap: 6px; }
.entry-number {
  font-size: 11.5px;
  font-weight: 600;
  letter-spacing: 0.24em;
  text-transform: uppercase;
  color: var(--brass);
}
.entry-name {
  font-family: var(--font-display);
  font-weight: 400;
  font-size: clamp(1.65rem, 3vw, 2.2rem);
  line-height: 1.1;
  letter-spacing: -0.01em;
  color: var(--text);
  transition: color 0.35s var(--ease);
}
.entry-link:hover .entry-name { color: var(--brass); }
.entry-family {
  font-size: 12px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--muted);
}
.entry-summary {
  margin-top: 8px;
  max-width: 42ch;
  font-family: var(--font-display);
  font-size: 1.06rem;
  line-height: 1.55;
  color: var(--muted);
}
.entry-foot {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  gap: 4px 16px;
  margin-top: 12px;
  padding-top: 14px;
  border-top: 1px solid var(--line);
  font-size: 14px;
}
.entry-meta { color: var(--muted); }
.entry-price { font-weight: 600; letter-spacing: 0.03em; }
/* Out of stock, in place of the price: small capitals, muted — said
   plainly, without an alarm colour. */
.entry-out {
  font-size: 11.5px;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--muted);
}

@media (min-width: 720px) {
  .entries-featured,
  .entries-related {
    grid-template-columns: repeat(3, minmax(0, 1fr));
    column-gap: clamp(22px, 3vw, 44px);
  }
  /* The middle one set a little lower: a line, not a shelf. */
  .entries-featured .entry:nth-child(3n + 2) { margin-top: 72px; }

  .entries-all {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    column-gap: clamp(40px, 7vw, 120px);
    row-gap: 96px;
  }
  .entries-all .entry:nth-child(even) { margin-top: 160px; }
}

.featured { padding-block: var(--section-y); }
.collection { padding-block: 24px var(--section-y); }
.related { padding-block: var(--section-y); }

/* --------------------------------------------------------------------------
   Ordering, in three steps — on the front page
   -------------------------------------------------------------------------- */

.ordering {
  background: var(--sand);
  padding-block: var(--section-y);
}
.ordering h2 { margin-top: 22px; max-width: 18ch; }
.steps {
  list-style: none;
  margin: 56px 0 0;
  padding: 0;
  display: grid;
}
.step {
  display: grid;
  grid-template-columns: 52px minmax(0, 1fr);
  gap: 16px;
  padding-block: 28px;
  border-top: 1px solid var(--line-control);
}
.step-no {
  font-family: var(--font-display);
  font-style: italic;
  font-size: 1.5rem;
  line-height: 1.2;
  color: var(--brass-warm);
}
.step h3 { font-size: 1.45rem; }
.step p {
  margin-top: 10px;
  max-width: 42ch;
  font-size: 15.5px;
  color: var(--muted);
}
@media (min-width: 900px) {
  .steps {
    grid-template-columns: repeat(3, minmax(0, 1fr));
    column-gap: 48px;
  }
  .step {
    grid-template-columns: 1fr;
    gap: 18px;
    padding-top: 32px;
  }
}

/* --------------------------------------------------------------------------
   A perfume — /collection/perfume/?id=…

   On a phone the name comes first and the image after it, so the page says
   what it is before it shows it. From 900px the image takes the left and
   stays in view while the words scroll past it.
   -------------------------------------------------------------------------- */

.product { padding-block: 150px 88px; }
.product-inner {
  display: grid;
  gap: 26px;
  grid-template-areas: "crumbs" "head" "figure" "body";
}
.crumbs { grid-area: crumbs; }
.product-head { grid-area: head; }
.product-figure { grid-area: figure; }
.product-body,
.product-noscript { grid-area: body; }

.crumbs ol {
  list-style: none;
  padding: 0;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--muted);
}
.crumbs li + li::before {
  content: "/";
  margin-inline: 12px;
  color: var(--line-control);
}
.crumbs a {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  color: var(--muted);
  text-decoration: none;
}
.crumbs a:hover { color: var(--brass); }

.product-number {
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.26em;
  text-transform: uppercase;
  color: var(--brass);
}
.product-head h1 {
  margin-top: 12px;
  font-size: clamp(2.6rem, 6.4vw, 4.6rem);
}
.product-family {
  margin-top: 14px;
  font-size: 12.5px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--muted);
}

.product-figure {
  aspect-ratio: 4 / 5;
  overflow: hidden;
  background: var(--sand);
}
.product-image { width: 100%; height: 100%; object-fit: cover; }

.product-summary {
  max-width: 38ch;
  font-family: var(--font-display);
  font-size: clamp(1.15rem, 2.2vw, 1.35rem);
  line-height: 1.55;
  color: var(--muted);
}

.notes {
  display: grid;
  margin-top: 34px;
  border-top: 1px solid var(--line);
}
.notes-tier {
  display: grid;
  grid-template-columns: 72px minmax(0, 1fr);
  gap: 16px;
  padding-block: 14px;
  border-bottom: 1px solid var(--line);
}
.notes dt {
  padding-top: 3px;
  font-size: 11.5px;
  font-weight: 600;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--brass);
}
.notes dd {
  font-family: var(--font-display);
  font-size: 1.06rem;
  line-height: 1.5;
}
@media (min-width: 520px) {
  .notes {
    grid-template-columns: repeat(3, minmax(0, 1fr));
    border-bottom: 1px solid var(--line);
  }
  .notes-tier {
    grid-template-columns: 1fr;
    gap: 8px;
    padding: 18px 16px 20px 0;
    border-bottom: 0;
  }
  .notes-tier + .notes-tier { padding-left: 16px; border-left: 1px solid var(--line); }
}

.purchase { margin-top: 36px; }
.purchase-price {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: 6px 20px;
}
.product-price {
  font-family: var(--font-display);
  font-size: clamp(1.7rem, 3vw, 2.1rem);
  line-height: 1.2;
}
.product-meta { font-size: 14px; color: var(--muted); }
.product-stock {
  margin-top: 10px;
  font-size: 14px;
  color: var(--muted);
}
.product-stock.is-available::before {
  content: "";
  display: inline-block;
  width: 6px;
  height: 6px;
  margin-right: 10px;
  border-radius: 50%;
  background: var(--brass-warm);
  vertical-align: middle;
}
/* Out of stock: the same mark, emptied — a hairline ring where the brass
   dot would be — and a quiet line on how to ask. No alarm colour. */
.product-stock.is-out { display: grid; gap: 6px; margin-top: 18px; }
.product-stock-label {
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--text);
}
.product-stock-label::before {
  content: "";
  display: inline-block;
  width: 7px;
  height: 7px;
  margin-right: 12px;
  border: 1px solid var(--line-control);
  border-radius: 50%;
  vertical-align: 1px;
}
.product-stock-note { line-height: 1.5; }
.purchase-row {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  margin-top: 22px;
}
.purchase-add { flex: 1 1 200px; }
.purchase-status { margin-top: 14px; font-size: 14.5px; }
.purchase-status:empty { display: none; }
.facts { margin-top: 40px; border-top: 1px solid var(--line); }

@media (min-width: 900px) {
  .product-inner {
    grid-template-columns: minmax(0, 7fr) minmax(0, 5fr);
    grid-template-rows: auto auto 1fr;
    grid-template-areas: "figure crumbs" "figure head" "figure body";
    column-gap: clamp(48px, 6vw, 96px);
    row-gap: 22px;
  }
  .product-figure {
    position: sticky;
    top: 32px;
    align-self: start;
  }
}

.product-story .prose p + p { margin-top: 20px; }
html.is-product-missing .product-figure,
html.is-product-missing .product-story,
html.is-product-missing .reviews,
html.is-product-missing .related,
html.is-product-missing .product-number { display: none; }

/* --------------------------------------------------------------------------
   Reviews — on a perfume's page, drawn by js/reviews.js

   A quiet passage after the composition: the score on the left (sticky
   from 900px, as the product image is), the words of those who wrote on the
   right, each set as a short serif quotation between hairlines. Only
   approved reviews are ever drawn. Stars are clipped shapes in the brass,
   rounded to the nearest half; the exact number is always said in words.
   -------------------------------------------------------------------------- */

.reviews { padding-block: var(--section-y); border-bottom: 1px solid var(--line); }
.reviews-inner { display: grid; gap: 44px; }
.reviews-head h2 { margin-top: 20px; }
.reviews-summary { margin-top: 28px; }
.reviews-score {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 10px 18px;
}
.reviews-average {
  font-family: var(--font-display);
  font-size: clamp(2.6rem, 5vw, 3.4rem);
  line-height: 1;
}
.reviews-outof { font-size: 0.42em; color: var(--muted); letter-spacing: 0.04em; }
.reviews-count {
  margin-top: 12px;
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--muted);
}
.reviews-empty {
  font-family: var(--font-display);
  font-size: clamp(1.35rem, 2.6vw, 1.6rem);
  line-height: 1.3;
}
.reviews-quiet { margin-top: 6px; font-size: 15px; color: var(--muted); }
.reviews-summary > .reviews-quiet:first-child { margin-top: 0; }

.stars { display: inline-flex; gap: 4px; flex-shrink: 0; }
.star {
  width: 15px;
  height: 15px;
  background: var(--line);
  clip-path: polygon(50% 0%, 61.8% 35.3%, 100% 35.3%, 69.1% 57.1%, 80.9% 91.2%,
                     50% 69.4%, 19.1% 91.2%, 30.9% 57.1%, 0% 35.3%, 38.2% 35.3%);
}
.star.is-full { background: var(--brass-warm); }
.star.is-half { background: linear-gradient(90deg, var(--brass-warm) 50%, var(--line) 50%); }
.reviews-score .star { width: 20px; height: 20px; }

.reviews-list { list-style: none; padding: 0; border-top: 1px solid var(--line); }
.review {
  padding-block: 30px;
  border-bottom: 1px solid var(--line);
}
.review:focus { outline: none; }
.review-quote { margin: 14px 0 0; }
.review-text {
  max-width: 60ch;
  font-family: var(--font-display);
  font-size: clamp(1.08rem, 2vw, 1.25rem);
  line-height: 1.6;
  white-space: pre-line;          /* the reviewer's own line breaks, as text */
  overflow-wrap: anywhere;
}
.review-by {
  display: flex;
  flex-wrap: wrap;
  gap: 4px 18px;
  margin-top: 16px;
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--text);
}
.review-name { overflow-wrap: anywhere; }
.review-name::before { content: "— "; color: var(--brass-warm); }
.review-date { font-weight: 400; color: var(--muted); }
.reviews-more { margin-top: 18px; }
/* Space above the form only when there are reviews above it. */
.reviews-list:not([hidden]) ~ .review-write { margin-top: 36px; }

.review-form {
  display: grid;
  gap: 24px;
  max-width: 640px;
}
.review-form-title { font-size: clamp(1.5rem, 3vw, 1.9rem); }
.review-form-title:focus { outline: none; }
.review-form .note { margin-top: -12px; max-width: 52ch; }

.rating-input { min-width: 0; margin: 0; padding: 0; border: 0; display: grid; gap: 8px; }
.rating-input > legend { padding: 0; margin-bottom: 8px; }
.rating-stars { display: flex; margin-left: -8px; }
/* The radio stays in the page, focusable and announced, but unseen; its
   label is the 44px star a finger presses. */
.rating-radio {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: 0;
  opacity: 0;
  pointer-events: none;
}
.rating-star {
  display: grid;
  place-items: center;
  width: 44px;
  height: 44px;
  cursor: pointer;
}
.rating-star::before {
  content: "";
  width: 28px;
  height: 28px;
  background: var(--line-control);   /* 3.3:1 — a control's own boundary */
  clip-path: polygon(50% 0%, 61.8% 35.3%, 100% 35.3%, 69.1% 57.1%, 80.9% 91.2%,
                     50% 69.4%, 19.1% 91.2%, 30.9% 57.1%, 0% 35.3%, 38.2% 35.3%);
  transition: background-color 0.25s var(--ease), transform 0.25s var(--ease);
}
.rating-star.is-lit::before { background: var(--brass-warm); }
.rating-star:hover::before { transform: scale(1.08); }
.rating-radio:focus-visible + .rating-star { outline: 2px solid var(--brass); outline-offset: -2px; border-radius: 2px; }

.review-comment { min-height: 150px; }
.review-trap {
  position: absolute;
  left: -10000px;
  width: 1px;
  height: 1px;
  overflow: hidden;
}
.review-actions { display: flex; flex-wrap: wrap; gap: 12px; }
.review-status {
  font-size: 14.5px;
  font-weight: 600;
  line-height: 1.5;
  color: var(--error);
}
.review-thanks {
  max-width: 560px;
  padding: 6px 0 6px 24px;
  border-left: 1px solid var(--brass-warm);
  font-family: var(--font-display);
  font-size: clamp(1.08rem, 2vw, 1.25rem);
  line-height: 1.55;
  color: var(--muted);
}
.review-thanks:focus { outline: none; }
.review-thanks-title { font-size: 1.5rem; color: var(--text); }

@media (min-width: 900px) {
  .reviews-inner {
    grid-template-columns: minmax(0, 4fr) minmax(0, 7fr);
    column-gap: clamp(48px, 6vw, 96px);
    align-items: start;
  }
  .reviews-head { position: sticky; top: 32px; }
}

/* --------------------------------------------------------------------------
   The bag and checkout — /bag/
   -------------------------------------------------------------------------- */

.checkout { padding-block: 8px var(--section-y); }
.bag-empty { padding-block: 8px 24px; }

/* What changed in the bag to match the stock: a brass hairline beside it,
   as the review form's thanks has — information, not an alarm. */
.bag-notice {
  max-width: 680px;
  margin-bottom: 40px;
  padding: 4px 0 4px 24px;
  border-left: 1px solid var(--brass-warm);
}
.bag-notice:focus { outline: none; }   /* focused to be read; the rule marks it */
.bag-notice-title {
  font-family: var(--font-display);
  font-size: clamp(1.3rem, 2.4vw, 1.5rem);
  line-height: 1.3;
  color: var(--text);
}
.bag-notice-list {
  display: grid;
  gap: 4px;
  margin-top: 10px;
  padding-left: 1.1em;
  font-size: 15px;
  line-height: 1.5;
  color: var(--muted);
}

.checkout-form {
  display: grid;
  gap: 48px;
}
@media (min-width: 1000px) {
  .checkout-form {
    grid-template-columns: minmax(0, 1fr) minmax(320px, 400px);
    column-gap: clamp(48px, 5vw, 80px);
    align-items: start;
  }
  .checkout-form > * { grid-column: 1; }
  .checkout-form > .summary {
    grid-column: 2;
    grid-row: 1 / span 5;
    position: sticky;
    top: 32px;
  }
}

/* A fieldset per step. The legend is floated so it behaves as an ordinary
   block and can carry the hairline, instead of sitting on the border. */
.step-set {
  min-width: 0;
  margin: 0;
  padding: 0;
  border: 0;
}
.step-set > legend {
  float: left;
  width: 100%;
  display: flex;
  align-items: baseline;
  gap: 16px;
  margin-bottom: 28px;
  padding: 24px 0 0;
  border-top: 1px solid var(--line);
  font-family: var(--font-display);
  font-size: clamp(1.5rem, 3vw, 1.9rem);
  line-height: 1.2;
}
.step-set > legend + * { clear: both; }
.step-set-no {
  font: 600 12px/1 var(--font-body);
  letter-spacing: 0.2em;
  color: var(--brass);
}

/* The bag's lines */
.bag-lines { list-style: none; padding: 0; }
.bag-line {
  display: grid;
  grid-template-columns: 76px minmax(0, 1fr) auto;
  grid-template-areas: "thumb text total" "thumb controls controls";
  gap: 10px 18px;
  padding-block: 20px;
  border-bottom: 1px solid var(--line);
}
.bag-line:first-child { padding-top: 0; }
.bag-thumb {
  grid-area: thumb;
  display: block;
  aspect-ratio: 4 / 5;
  overflow: hidden;
  background: var(--sand);
}
.bag-thumb img { width: 100%; height: 100%; object-fit: cover; }
.bag-text { grid-area: text; display: grid; align-content: start; }
.bag-number {
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--brass);
}
.bag-name {
  display: inline-flex;
  align-items: center;
  justify-self: start;
  min-height: 44px;
  font-family: var(--font-display);
  font-size: 1.35rem;
  line-height: 1.15;
  color: var(--text);
  text-decoration: none;
}
.bag-name:hover { color: var(--brass); }
.bag-meta { font-size: 13.5px; color: var(--muted); }
.bag-controls {
  grid-area: controls;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px 16px;
}
.bag-remove {
  min-height: 44px;
  min-width: 44px;
  padding: 0 4px;
  background: none;
  border: 0;
  color: var(--muted);
  font: 600 11.5px/1 var(--font-body);
  letter-spacing: 0.16em;
  text-transform: uppercase;
  text-decoration: underline;
  text-decoration-color: var(--line-control);
  text-underline-offset: 4px;
  cursor: pointer;
}
.bag-remove:hover { color: var(--brass); text-decoration-color: currentColor; }
.bag-line-total {
  grid-area: total;
  padding-top: 18px;
  font-size: 15px;
  font-weight: 600;
  white-space: nowrap;
}
@media (min-width: 600px) {
  .bag-line {
    grid-template-columns: 88px minmax(0, 1fr) auto auto;
    grid-template-areas: "thumb text controls total";
    align-items: center;
  }
  .bag-line-total { padding-top: 0; min-width: 104px; text-align: right; }
}

/* Fields */
.fields { display: grid; gap: 22px 20px; }
@media (min-width: 720px) {
  .fields { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .field-wide { grid-column: 1 / -1; }
}
.field { display: grid; gap: 8px; align-content: start; }
.field-label {
  font: 600 12px/1.4 var(--font-body);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--text);
}
.field-optional {
  font-size: 13px;
  font-weight: 400;
  letter-spacing: 0.02em;
  text-transform: none;
  color: var(--muted);
}
.input {
  width: 100%;
  min-height: 52px;
  padding: 13px 15px;
  border: 1px solid var(--line-control);
  border-radius: 0;
  background: var(--field);
  color: var(--text);
  font: 16px/1.45 var(--font-body);   /* 16px: iOS does not zoom into it */
  -webkit-appearance: none;
  appearance: none;
  transition: border-color 0.3s var(--ease);
}
.input:hover { border-color: var(--muted); }
.input:focus-visible { outline-offset: 1px; border-color: var(--ink); }
.input[aria-invalid="true"] { border-color: var(--error); }
.input-area { min-height: 104px; resize: vertical; }
.field-hint { font-size: 13.5px; line-height: 1.45; color: var(--muted); }
.field-error {
  font-size: 14px;
  font-weight: 600;
  line-height: 1.45;
  color: var(--error);
}

/* Payment */
.pay-options { display: grid; gap: 12px; }
@media (min-width: 600px) {
  .pay-options { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
.pay-option {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  gap: 4px 14px;
  padding: 20px;
  border: 1px solid var(--line-control);
  background: var(--field);
  cursor: pointer;
  transition: border-color 0.3s var(--ease), box-shadow 0.3s var(--ease);
}
.pay-option:hover { border-color: var(--muted); }
.pay-option:has(input:checked) {
  border-color: var(--ink);
  box-shadow: inset 0 0 0 1px var(--ink);
}
.pay-option input {
  grid-row: 1 / span 2;
  width: 18px;
  height: 18px;
  margin: 4px 0 0;
  accent-color: var(--ink);
}
.pay-title { font-family: var(--font-display); font-size: 1.25rem; line-height: 1.3; }
.pay-desc { grid-column: 2; font-size: 14px; line-height: 1.5; color: var(--muted); }
.step-set-payment .field-error { margin-top: 12px; }

.pay-panel {
  display: grid;
  gap: 18px;
  margin-top: 26px;
  padding: 4px 0 4px 24px;
  border-left: 1px solid var(--brass-warm);
  font-size: 15.5px;
}
.pay-amount {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  align-items: baseline;
  gap: 8px 16px;
  padding-bottom: 12px;
  border-bottom: 1px solid var(--line);
  font-family: var(--font-display);
  font-size: 1.1rem;
}
.pay-amount strong { font-size: 1.35rem; font-weight: 400; }
.bank-details { display: grid; }
.bank-row {
  display: grid;
  gap: 2px;
  padding-block: 10px;
  border-bottom: 1px solid var(--line);
}
.bank-row dt {
  font-size: 11.5px;
  font-weight: 600;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--muted);
}
.bank-row dd {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 8px 12px;
}
.bank-value {
  font-family: var(--font-display);
  font-size: 1.12rem;
  letter-spacing: 0.03em;
  overflow-wrap: anywhere;
}
.copy-button {
  min-height: 44px;
  min-width: 72px;
  padding: 0 14px;
  border: 1px solid var(--line-control);
  background: transparent;
  color: var(--text);
  font: 600 11.5px/1 var(--font-body);
  letter-spacing: 0.16em;
  text-transform: uppercase;
  cursor: pointer;
  transition: background-color 0.3s var(--ease), color 0.3s var(--ease), border-color 0.3s var(--ease);
}
.copy-button:hover { background: var(--ink); border-color: var(--ink); color: var(--ivory-text); }
.copy-button.is-done { border-color: var(--brass-warm); color: var(--brass); background: transparent; }
.pay-steps { display: grid; gap: 8px; padding-left: 1.3em; }
.pay-steps li::marker { color: var(--brass-warm); }
.pay-footnote { font-size: 13.5px; line-height: 1.55; color: var(--muted); }
.demo-warning {
  padding: 12px 16px;
  background: var(--ink);
  color: var(--ivory-text);
  font-size: 13.5px;
  font-weight: 600;
  line-height: 1.5;
}

/* The errors, summarised above the form after a failed attempt */
.form-errors {
  padding: 22px 24px;
  border: 1px solid var(--error);
  border-left-width: 3px;
  background: var(--field);
}
.form-errors:focus { outline: none; }   /* it is focused to be read; its border already marks it */
.form-errors-title { font-size: 1.35rem; }
.form-errors-list { display: grid; gap: 2px; margin-top: 8px; padding-left: 1.1em; }
.form-errors-list a { color: var(--error); }

/* The summary: the one dark panel in the checkout */
.summary {
  display: grid;
  gap: 18px;
  padding: 32px 26px 28px;
  background: var(--ink);
  color: var(--ivory-text);
}
.summary-title { font-size: 1.6rem; color: var(--ivory-text); }
.summary-lines {
  list-style: none;
  padding: 0;
  display: grid;
  gap: 8px;
  font-size: 14.5px;
  color: var(--muted);
}
.summary-line { display: flex; justify-content: space-between; gap: 16px; }
.summary-line span:last-child { white-space: nowrap; }
.summary-totals { display: grid; padding-top: 10px; border-top: 1px solid var(--line); }
.summary-row {
  display: flex;
  justify-content: space-between;
  gap: 16px;
  padding-block: 5px;
  font-size: 14.5px;
}
.summary-row dt { color: var(--muted); }
.summary-total {
  margin-top: 6px;
  padding-top: 12px;
  border-top: 1px solid var(--line);
  font-family: var(--font-display);
  font-size: 1.35rem;
}
.summary-total dt { color: inherit; }
.summary .summary-lines,
.summary .summary-row dt { color: var(--ivory-muted); }
.summary .summary-total dt { color: var(--ivory-text); }
.summary .summary-totals,
.summary .summary-total { border-color: var(--line-dark); }
.summary-free { font-size: 13.5px; color: var(--brass-soft); }
.summary-free:empty { display: none; }
.summary-submit { width: 100%; margin-top: 4px; }
.summary-status { font-size: 14px; line-height: 1.55; color: var(--error-soft); }
.summary-note { font-size: 13px; line-height: 1.55; color: var(--ivory-muted); }
.summary a { color: var(--brass-soft); }

/* The confirmation, shown only after Netlify has accepted the order */
.confirmation { max-width: 1060px; }
.confirmation-title {
  margin-top: 18px;
  font-size: clamp(2rem, 5vw, 3.2rem);
}
.confirmation-title:focus { outline: none; }
.confirmation-lede { margin-top: 20px; max-width: 54ch; }
.conf-number {
  display: inline-grid;
  gap: 8px;
  margin-top: 36px;
  padding: 20px 28px;
  border: 1px solid var(--brass-warm);
}
.conf-number dt {
  font-size: 11.5px;
  font-weight: 600;
  letter-spacing: 0.24em;
  text-transform: uppercase;
  color: var(--brass);
}
.conf-number dd {
  font-family: var(--font-display);
  font-size: clamp(1.4rem, 4vw, 1.9rem);
  letter-spacing: 0.06em;
  overflow-wrap: anywhere;
}
.conf-grid { display: grid; gap: 48px; margin-top: 52px; }
@media (min-width: 900px) {
  .conf-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); column-gap: 64px; }
}
.conf-block h3 {
  margin-bottom: 18px;
  padding-bottom: 14px;
  border-bottom: 1px solid var(--line);
  font-size: 1.5rem;
}
.conf-block > div { display: grid; gap: 18px; }
.conf-facts { margin-top: 24px; border-top: 1px solid var(--line); }
.conf-keep { margin-top: 44px; max-width: 62ch; }
.conf-track { margin-top: 18px; max-width: 62ch; font-size: 15px; color: var(--muted); }
.conf-saving { margin-top: 12px; font-size: 14px; color: var(--muted); }

/* --------------------------------------------------------------------------
   Prices with a discount, and the coupon — js/pricing.js decides them

   Said quietly, like "Out of stock": the base price struck through in the
   muted ink, what is off in small capitals in the ordinary ink. No sale
   red, no brass badge — the brass stays where it already is.
   -------------------------------------------------------------------------- */

.price-was {
  color: var(--muted);
  font-weight: 400;
  text-decoration-thickness: 1px;
}
.entry-price.is-reduced { display: inline-flex; flex-wrap: wrap; align-items: baseline; gap: 2px 8px; }
.price-off,
.product-offer {
  font-size: 11.5px;
  font-weight: 600;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--text);
}
.product-price .price-was { font-size: 0.7em; margin-right: 4px; }
.product-offer { margin-top: 8px; letter-spacing: 0.16em; line-height: 1.6; }
.summary .price-was { color: var(--ivory-muted); margin-right: 4px; }
.bag-meta .price-was { margin-right: 2px; }

/* The coupon, inside the dark summary: a field on ink, its boundary the
   dark control line (3.2:1 on --ink). */
.coupon { display: grid; gap: 8px; padding-top: 14px; border-top: 1px solid var(--line-dark); }
.coupon-label {
  font: 600 12px/1.4 var(--font-body);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ivory-text);
}
.coupon-label .field-optional { color: var(--ivory-muted); }
.coupon-row { display: flex; gap: 8px; }
.summary .coupon-input {
  flex: 1 1 auto;
  min-width: 0;
  min-height: 48px;
  background: var(--ink-soft);
  border-color: var(--line-dark-control);
  color: var(--ivory-text);
  text-transform: uppercase;
  letter-spacing: 0.08em;
}
.summary .coupon-input:focus-visible { border-color: var(--ivory-text); outline-color: var(--brass-soft); }
.coupon-apply {
  flex: 0 0 auto;
  min-height: 48px;
  min-width: 88px;
  padding: 0 16px;
  border: 1px solid var(--line-dark-control);
  background: transparent;
  color: var(--ivory-text);
  font: 600 11.5px/1 var(--font-body);
  letter-spacing: 0.16em;
  text-transform: uppercase;
  cursor: pointer;
  transition: background-color 0.3s var(--ease), color 0.3s var(--ease);
}
.coupon-apply:hover { background: var(--ivory-text); color: var(--ink); }
.coupon-apply:focus-visible { outline-color: var(--brass-soft); }
.coupon-message { font-size: 13.5px; line-height: 1.5; color: var(--ivory-muted); }
.coupon-message:empty { display: none; }
.coupon-message.is-applied { color: var(--brass-soft); }
.coupon-message.is-refused { color: var(--error-soft); }
.summary-saving { font-size: 13.5px; line-height: 1.5; color: var(--brass-soft); }
.summary-saving:empty { display: none; }

/* --------------------------------------------------------------------------
   Follow an order — /order/
   -------------------------------------------------------------------------- */

.order-page { padding-block: 8px var(--section-y); }
.order-lookup {
  display: grid;
  gap: 22px;
  max-width: 520px;
}
.order-lookup .button { justify-self: start; }
.order-lookup-status { font-size: 15px; font-weight: 600; line-height: 1.5; color: var(--error); }
.order-result { margin-top: 64px; padding-top: 40px; border-top: 1px solid var(--line); }
.order-result:focus { outline: none; }
.order-result-title { margin-top: 14px; font-size: clamp(1.9rem, 4.4vw, 2.6rem); }
.order-result-placed { margin-top: 10px; color: var(--muted); }
/* The steps: a brass dot for each one reached, a hairline ring for the
   rest — the same marks as "In stock" and "Out of stock". */
.order-steps {
  display: grid;
  gap: 0;
  max-width: 560px;
  margin-top: 36px;
  padding: 0;
  list-style: none;
}
.order-step {
  display: grid;
  grid-template-columns: 18px minmax(0, 1fr) auto;
  gap: 2px 14px;
  align-items: baseline;
  padding-block: 12px;
  border-bottom: 1px solid var(--line);
  font-size: 15px;
  color: var(--muted);
}
.order-step::before {
  content: "";
  width: 8px;
  height: 8px;
  border: 1px solid var(--line-control);
  border-radius: 50%;
}
.order-step.is-done { color: var(--text); }
.order-step.is-done::before { border-color: var(--brass-warm); background: var(--brass-warm); }
.order-step[aria-current="step"] .order-step-label { font-weight: 600; }
.order-step-date { font-size: 13.5px; color: var(--muted); text-align: right; }
@media (max-width: 480px) {
  .order-step { grid-template-columns: 18px minmax(0, 1fr); }
  .order-step-date { grid-column: 2; text-align: left; }
}

/* --------------------------------------------------------------------------
   Privacy — a readable column
   -------------------------------------------------------------------------- */

.legal { padding-block: 24px var(--section-y); }
.legal-inner { max-width: 760px; }
.legal h2 {
  margin-top: 52px;
  padding-top: 28px;
  border-top: 1px solid var(--line);
  font-size: clamp(1.45rem, 3vw, 1.85rem);
}
.legal h2:first-child { margin-top: 0; }
.legal p,
.legal ul { margin-top: 16px; max-width: var(--max-prose); }
.legal ul { padding-left: 1.2em; }
.legal li + li { margin-top: 6px; }

/* --------------------------------------------------------------------------
   The Journal — /blog/ and its articles, written by tools/build-journal.mjs

   A publication, not a feed: one large story, two beneath it, then a grid
   whose images alternate between portrait and square so the rows do not
   read as a shelf of identical cards. The articles are set for reading —
   a serif text column of about 66 characters, with room around it.
   -------------------------------------------------------------------------- */

.journal { padding-block: 8px var(--section-y); }

.journal-filter {
  display: flex;
  flex-wrap: wrap;
  gap: 0 26px;
  margin-bottom: clamp(40px, 6vw, 64px);
  padding-block: 4px;
  border-block: 1px solid var(--line);
}
.filter-button {
  min-height: 44px;
  min-width: 44px;
  padding: 0 2px;
  border: 0;
  background: linear-gradient(var(--brass), var(--brass)) no-repeat 0 calc(100% - 9px) / 0 1px;
  color: var(--muted);
  font: 600 12px/1 var(--font-body);
  letter-spacing: 0.16em;
  text-transform: uppercase;
  cursor: pointer;
  transition: color 0.35s var(--ease), background-size 0.45s var(--ease);
}
.filter-button:hover,
.filter-button[aria-pressed="true"] {
  color: var(--brass);
  background-size: 100% 1px;
}

.stories {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: 64px 0;
}
.story-link {
  display: grid;
  gap: 22px;
  color: inherit;
  text-decoration: none;
}
.story-figure {
  display: block;
  aspect-ratio: 3 / 2;
  overflow: hidden;
  background: var(--sand);
}
.story-figure img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: transform 1.4s var(--ease);
}
.story-link:hover .story-figure img { transform: scale(1.035); }
.story-text { display: grid; gap: 10px; align-content: start; }
.story-meta {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 4px 0;
  font-size: 11.5px;
  font-weight: 600;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--muted);
}
.story-meta > * + *::before {
  content: "·";
  margin-inline: 10px;
  color: var(--line-control);
}
.story-category { color: var(--brass); }
.story-title {
  font-family: var(--font-display);
  font-weight: 400;
  font-size: clamp(1.45rem, 2.4vw, 1.7rem);
  line-height: 1.18;
  letter-spacing: -0.005em;
  color: var(--text);
  transition: color 0.35s var(--ease);
}
.story-link:hover .story-title { color: var(--brass); }
.story-excerpt {
  max-width: 48ch;
  font-family: var(--font-display);
  font-size: 1.04rem;
  line-height: 1.55;
  color: var(--muted);
}
.story-more {
  margin-top: 8px;
  font-size: 12.5px;
  font-weight: 600;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--text);
}

.story-feature .story-figure { aspect-ratio: 4 / 3; }
.story-feature .story-title { font-size: clamp(2rem, 5vw, 3.3rem); line-height: 1.08; }
.story-feature .story-excerpt { font-size: clamp(1.08rem, 2vw, 1.25rem); }

@media (min-width: 720px) {
  .stories { grid-template-columns: repeat(2, minmax(0, 1fr)); column-gap: clamp(28px, 4vw, 56px); row-gap: 80px; }
  .story-feature { grid-column: 1 / -1; }
  .story-feature .story-figure { aspect-ratio: 16 / 9; }
}

@media (min-width: 1000px) {
  .stories { grid-template-columns: repeat(6, minmax(0, 1fr)); row-gap: 96px; align-items: start; }
  .story { grid-column: span 2; }
  .story-second { grid-column: span 3; }
  .story-second .story-title { font-size: clamp(1.7rem, 2.6vw, 2.2rem); }
  .story-feature { grid-column: 1 / -1; }
  .story-feature .story-link {
    grid-template-columns: minmax(0, 7fr) minmax(0, 5fr);
    column-gap: clamp(40px, 5vw, 80px);
    align-items: center;
  }
  .story-feature .story-figure { aspect-ratio: 4 / 3; }
  /* The grid below the first three: portrait and square, alternating, so
     each row holds a different rhythm from the one above it. */
  .story:not(.story-feature):not(.story-second):nth-child(even) .story-figure { aspect-ratio: 4 / 5; }
  .story:not(.story-feature):not(.story-second):nth-child(odd) .story-figure { aspect-ratio: 1 / 1; }
}

/* Filtered to one category, the Journal is a plain, even grid. */
.stories.is-filtered .story { grid-column: auto; }
.stories.is-filtered .story .story-figure { aspect-ratio: 3 / 2; }
.stories.is-filtered .story-feature .story-link { grid-template-columns: 1fr; }
.stories.is-filtered .story-title { font-size: clamp(1.45rem, 2.4vw, 1.7rem); }
.stories.is-filtered .story-excerpt { font-size: 1.04rem; }
.stories.is-filtered .story-more { display: none; }
@media (min-width: 1000px) {
  .stories.is-filtered { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}

.stories-related .story-figure { aspect-ratio: 3 / 2; }
@media (min-width: 1000px) {
  .stories-related { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .stories-related .story { grid-column: auto; }
  .stories-related .story .story-figure { aspect-ratio: 3 / 2; }
}
.journal-related { border-top: 1px solid var(--line); }

/* ── An article ─────────────────────────────────────────────────────── */

.article-head {
  padding-top: 164px;
  text-align: center;
}
.article-head .crumbs ol { justify-content: center; }
.article-head h1 {
  max-width: 19ch;
  margin: 18px auto 0;
  font-size: clamp(2.3rem, 6vw, 4.3rem);
  line-height: 1.06;
}
.article-dek {
  max-width: 46ch;
  margin: 26px auto 0;
  font-family: var(--font-display);
  font-size: clamp(1.12rem, 2.2vw, 1.38rem);
  line-height: 1.55;
  color: var(--muted);
}
.article-meta {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 6px 24px;   /* spaced, not dotted: a dot would be left hanging where the line wraps */
  margin-top: 28px;
  font-size: 11.5px;
  font-weight: 600;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--muted);
}
@media (max-width: 420px) {
  .article-head { padding-top: 128px; }
}

.article-hero { margin-top: clamp(40px, 6vw, 64px); }
.article-hero img {
  width: 100%;
  aspect-ratio: 4 / 3;
  object-fit: cover;
  background: var(--sand);
}
@media (min-width: 720px) {
  .article-hero img { aspect-ratio: 16 / 9; }
}

/* The reading column. The serif carries the text, at a size and measure
   meant for reading at length rather than scanning. */
.article-body {
  max-width: calc(680px + 2 * var(--gutter));
  margin: clamp(48px, 7vw, 80px) auto 0;
  padding-inline: var(--gutter);
  font-family: var(--font-display);
  font-size: clamp(1.08rem, 1.6vw, 1.2rem);
  line-height: 1.75;
  color: var(--text);
}
.article-body > * + * { margin-top: 1.25em; }
.article-body > p:first-child::first-letter {
  float: left;
  margin: 0.08em 0.1em 0 0;
  font-size: 3.6em;
  line-height: 0.82;
  color: var(--brass-warm);
}
.article-body h2 {
  margin-top: 2.2em;
  font-size: clamp(1.55rem, 3.2vw, 2.05rem);
  line-height: 1.2;
}
.article-body h3 {
  margin-top: 1.8em;
  font-size: 1.3rem;
  font-style: italic;
}
.article-body h2 + *,
.article-body h3 + * { margin-top: 0.7em; }
.article-body ul,
.article-body ol { padding-left: 1.2em; }
.article-body li + li { margin-top: 0.5em; }
.article-body li::marker { color: var(--brass-warm); }
.article-body strong { font-weight: 600; }
/* Links in running text: a 44px target without moving the line. */
.article-body a { padding-block: 14px; }
.article-filed a {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 44px;
  min-height: 44px;
}

.pull-quote {
  position: relative;
  margin-block: 2.2em;
  padding-top: 30px;
  font-size: clamp(1.5rem, 3.4vw, 2.15rem);
  font-style: italic;
  line-height: 1.3;
  text-align: center;
  color: var(--text);
}
.pull-quote::before {
  content: "";
  position: absolute;
  top: 0;
  left: 50%;
  width: 48px;
  height: 1px;
  margin-left: -24px;
  background: var(--brass-warm);
}
@media (min-width: 1000px) {
  .article-body .pull-quote { margin-inline: -72px; }
}

.article-break {
  width: 56px;
  height: 1px;
  margin: 3em auto;
  border: 0;
  background: var(--brass-warm);
}

.article-figure img { width: 100%; background: var(--sand); }
.article-figure figcaption {
  margin-top: 12px;
  font-family: var(--font-body);
  font-size: 13px;
  color: var(--muted);
}

.article-foot {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 8px 24px;
  max-width: calc(680px + 2 * var(--gutter));
  margin: 64px auto 0;
  padding-inline: var(--gutter);
}
.article-filed {
  font-size: 13.5px;
  color: var(--muted);
}

/* Previous and next */
.story-steps {
  display: grid;
  margin-top: clamp(64px, 9vw, 104px);
  border-top: 1px solid var(--line);
}
.story-step {
  display: grid;
  gap: 8px;
  padding-block: 26px;
  color: inherit;
  text-decoration: none;
}
.story-step + .story-step { border-top: 1px solid var(--line); }
.story-step.is-empty { display: none; }
.story-step-label {
  font-size: 11.5px;
  font-weight: 600;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--brass);
}
.story-step-title {
  font-family: var(--font-display);
  font-size: clamp(1.25rem, 2.4vw, 1.55rem);
  line-height: 1.25;
  transition: color 0.35s var(--ease);
}
.story-step:hover .story-step-title { color: var(--brass); }
.story-step-prev .story-step-label::before { content: "← "; }
.story-step-next .story-step-label::after { content: " →"; }
@media (min-width: 720px) {
  .story-steps { grid-template-columns: repeat(2, minmax(0, 1fr)); column-gap: 48px; border-bottom: 1px solid var(--line); }
  .story-step + .story-step { border-top: 0; }
  .story-step.is-empty { display: block; }
  .story-step-next { text-align: right; }
}

/* --------------------------------------------------------------------------
   Reveal on scroll

   Enhancement only: without JavaScript the `no-js` class never leaves the
   document element, these rules never apply, and every element is simply
   visible. Under prefers-reduced-motion the transition collapses and the
   content appears without movement.
   -------------------------------------------------------------------------- */

html:not(.no-js) .reveal {
  opacity: 0;
  transform: translateY(16px);
  transition: opacity 1.1s var(--ease), transform 1.1s var(--ease);
}
html:not(.no-js) .reveal.is-in {
  opacity: 1;
  transform: none;
}

/* The hero stagger is written here rather than set from JavaScript, because
   the deployed CSP is style-src 'self': an inline style would be dropped. */
html:not(.no-js) .hero-copy .reveal:nth-child(1) { transition-delay: 0.05s; }
html:not(.no-js) .hero-copy .reveal:nth-child(2) { transition-delay: 0.15s; }
html:not(.no-js) .hero-copy .reveal:nth-child(3) { transition-delay: 0.28s; }
html:not(.no-js) .hero-copy .reveal:nth-child(4) { transition-delay: 0.41s; }
html:not(.no-js) .hero-copy .reveal:nth-child(5) { transition-delay: 0.54s; }
html:not(.no-js) .hero-figure.reveal { transition-delay: 0.2s; }

@media (prefers-reduced-motion: reduce) {
  html:not(.no-js) .reveal { opacity: 1; transform: none; }
}

/* --------------------------------------------------------------------------
   Utilities — small placement one-offs, so that no element ever needs a
   style attribute (the CSP would drop it in production anyway).
   -------------------------------------------------------------------------- */

.u-centre      { text-align: center; }
.u-mt-0        { margin-top: 0; }
.u-mt-24       { margin-top: 24px; }
.u-mt-40       { margin-top: 40px; }
.u-measure     { max-width: var(--max-prose); }
.u-visually-hidden {
  position: absolute;
  width: 1px; height: 1px;
  margin: -1px; padding: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}
