/* ============================================================
   LIEBE BLÜME — design system
   Palette: ink black / soft white / taupe, blush = accent only
   Type: Cormorant Garamond (display) + Jost (text)
   ============================================================ */

:root {
  /* color */
  --ink: #17140f;
  --ink-soft: #2e2921;
  --paper: #faf7f1;
  --paper-warm: #f4efe6;
  --taupe: #a08f78;
  --taupe-deep: #6f6250;
  --taupe-line: #e3dbcd;
  --blush: #c4837f;
  --blush-deep: #995551;
  --ok: #567051;
  --err: #995551;

  /* type */
  --serif: 'Cormorant Garamond', 'Iowan Old Style', Georgia, serif;
  --sans: 'Jost', 'Avenir Next', 'Century Gothic', sans-serif;

  /* scale */
  --w-max: 1240px;
  --gutter: clamp(20px, 4vw, 48px);
  --s1: 8px; --s2: 16px; --s3: 24px; --s4: 40px; --s5: 64px; --s6: 96px; --s7: 144px;

  /* dark (ink) section text tints */
  --ink-text: #e9e2d4;
  --ink-muted: #cfc5b2;
  --ink-kicker: #b3a68f;
  --ink-soft2: #8d8069;
  --ink-line: #353026;

  --pm-accent: #c4837f;

  /* Light text on a dark ground. Two families, because the grounds differ:
     the ink sections are a known flat colour, the hero is a photograph behind
     a scrim. Do not swap one family for the other; the hero values are pinned
     by scripts/verify-hero-scrim.py. */
  --on-ink-dim: #d8cfc0;     /* announce bar, hero scroll cue */
  --photo-kicker: #ece5d8;   /* hero kicker over the scrim */
  --photo-body: #f0ebe1;     /* hero sub over the scrim */

  --blush-wash: #e9d5cd;     /* ::selection only */

  /* Control boundaries. --taupe-line (#e3dbcd) is 1.29:1 against paper and is a
     DECORATIVE hairline only: section rules, hr, card edges. Anything a person
     operates (radio, checkbox, qty stepper, input, chip) needs 3:1 under WCAG
     1.4.11 and must use --ui-line, which clears it on all three of our surfaces:
     3.62:1 on paper, 3.38:1 on paper-warm, 4.74:1 on ink.
     Same value as --ink-soft2 by coincidence, not by relationship. Keep separate. */
  --ui-line: #8d8069;

  /* Ink as bare channels, for the places that need ink at partial alpha (scrims,
     veils, shadows). rgba() cannot take a hex custom property, so without this the
     ink colour gets hardcoded eleven times and silently forks from --ink. */
  --ink-rgb: 23, 20, 15;

  /* motion */
  --ease-out: cubic-bezier(.22,.61,.21,1);
  --ease-soft: cubic-bezier(.45,.05,.35,1);
}

/* ---------- reset / base ---------- */
*, *::before, *::after { box-sizing: border-box; }
[hidden] { display: none !important; }
html { scroll-behavior: smooth; scroll-padding-top: 96px; -webkit-text-size-adjust: 100%; }
@media (prefers-reduced-motion: reduce) { html { scroll-behavior: auto; } }
body {
  margin: 0;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--sans);
  font-weight: 300;
  font-size: 17px;
  line-height: 1.65;
  letter-spacing: .01em;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}
/* paper grain */
body::before {
  content: "";
  position: fixed; inset: 0;
  pointer-events: none;
  z-index: 2147483000;
  opacity: .35;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='140' height='140'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2' stitchTiles='stitch'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3CfeComponentTransfer%3E%3CfeFuncA type='linear' slope='0.05'/%3E%3C/feComponentTransfer%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
}
img { max-width: 100%; height: auto; display: block; }
a { color: inherit; text-decoration: none; }
p a, .prose a { border-bottom: 1px solid var(--blush); transition: border-color .25s, color .25s; }
p a:hover, .prose a:hover { color: var(--blush-deep); }
button { font: inherit; color: inherit; background: none; border: 0; cursor: pointer; }
::selection { background: var(--blush-wash); color: var(--ink); }

h1,h2,h3,h4 { font-family: var(--serif); font-weight: 500; line-height: 1.08; margin: 0 0 var(--s3); letter-spacing: .005em; }
.display { font-size: clamp(44px, 7.2vw, 104px); }
h1, .h1 { font-size: clamp(38px, 5.4vw, 76px); }
h2, .h2 { font-size: clamp(30px, 3.8vw, 52px); }
h3, .h3 { font-size: clamp(24px, 2.6vw, 32px); }
.italic { font-style: italic; }
.serif { font-family: var(--serif); }

.kicker {
  font-family: var(--sans); font-weight: 500;
  font-size: 12px; letter-spacing: .32em; text-transform: uppercase;
  color: var(--taupe-deep);
  margin: 0 0 var(--s2);
  display: flex; align-items: center; gap: 14px;
}
.kicker::before { content: ""; width: 34px; height: 1px; background: var(--taupe); }
.kicker.center { justify-content: center; }
.kicker.center::after { content: ""; width: 34px; height: 1px; background: var(--taupe); }

.lede { font-size: clamp(18px, 1.6vw, 21px); font-weight: 300; color: var(--ink-soft); max-width: 34em; }
.muted { color: var(--taupe-deep); }
.center { text-align: center; }
.center .lede { margin-inline: auto; }

.wrap { max-width: var(--w-max); margin-inline: auto; padding-inline: var(--gutter); }
.wrap-narrow { max-width: 880px; margin-inline: auto; padding-inline: var(--gutter); }
section { padding-block: var(--s6); }
.section-tight { padding-block: var(--s5); }
.hairline { border: 0; border-top: 1px solid var(--taupe-line); margin: 0; }

.skip {
  position: absolute; left: -9999px; top: 0; z-index: 10000;
  background: var(--ink); color: var(--paper); padding: 10px 18px;
  font-family: var(--sans); font-size: 14px;
}
.skip:focus { left: 12px; top: 12px; }

:focus-visible { outline: 2px solid var(--blush-deep); outline-offset: 3px; }

/* ---------- buttons ---------- */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 10px;
  font-family: var(--sans); font-weight: 400;
  font-size: 13px; letter-spacing: .22em; text-transform: uppercase;
  padding: 17px 34px;
  border: 1px solid var(--ink);
  color: var(--ink);
  background: transparent;
  transition: background .3s var(--ease-out), color .3s var(--ease-out), border-color .3s;
  white-space: nowrap;
}
.btn:hover { background: var(--ink); color: var(--paper); }
.btn-solid { background: var(--ink); color: var(--paper); }
.btn-solid:hover { background: var(--ink-soft); }
.btn-paper { border-color: var(--paper); color: var(--paper); }
.btn-paper:hover { background: var(--paper); color: var(--ink); }
.btn[disabled], .btn[aria-disabled="true"] { opacity: .45; pointer-events: none; }
.btn-sm { padding: 12px 22px; font-size: 12px; }

.textlink {
  font-family: var(--sans); font-weight: 400; font-size: 13px;
  letter-spacing: .22em; text-transform: uppercase;
  border-bottom: 1px solid var(--blush);
  padding-bottom: 4px;
  transition: color .25s;
}
.textlink:hover { color: var(--blush-deep); }

/* No-JS notice. Ported from the other build, which carried it on 21 of 27 pages
   while this one carried it on 3 of 22. It matters more here than it looks: with no
   order endpoint configured, ordering is already a hand-off to email or DM, so a
   visitor without scripting is not stuck, they just need to be told the two channels
   she actually reads. Never hide this behind a script-set class. */
.noscript-note {
  max-width: 60rem;
  margin: var(--s4) auto;
  padding: var(--s3) var(--s4);
  border: 1px solid var(--ui-line);
  background: var(--paper-warm);
  font-size: 16px;
}
.noscript-note a { border-bottom: 1px solid var(--blush); }


/* ---------- header ----------
   The wordmark sits alone and centred, with the navigation on its own line beneath.
   The previous arrangement put four nav items left and three right of the mark: the
   grid centred it to within 1px, but the two groups carried different word counts and
   touched the mark with zero gap, so it read lopsided and crowded. Nothing now
   competes with the mark for the centre line, which is the only way this reads as
   deliberate rather than as a default theme. The black delivery bar is gone; its
   promise moved into the one quiet line under the mark. */
.site-head {
  position: sticky; top: 0; z-index: 900;
  background: color-mix(in srgb, var(--paper) 94%, transparent);
  backdrop-filter: blur(14px); -webkit-backdrop-filter: blur(14px);
  border-bottom: 1px solid var(--taupe-line);
}
.head-mark {
  max-width: var(--w-max); margin-inline: auto; padding: 22px var(--gutter) 0;
  display: grid; grid-template-columns: 1fr auto 1fr; align-items: center;
}
.wordmark {
  grid-column: 2;
  font-family: var(--serif); font-weight: 500;
  font-size: clamp(24px, 2.4vw, 31px); letter-spacing: .12em;
  text-align: center; white-space: nowrap;
}
.nav-row {
  display: flex; justify-content: center; align-items: center;
  gap: clamp(16px, 2.2vw, 34px);
  max-width: var(--w-max); margin: 18px auto 0;
  padding: 14px var(--gutter);
  border-top: 1px solid var(--taupe-line);
}
.nav-link {
  font-family: var(--sans); font-weight: 400;
  font-size: 12.5px; letter-spacing: .2em; text-transform: uppercase;
  color: var(--ink); white-space: nowrap;
  padding-block: 6px; position: relative;
  transition: color .25s;
}
.nav-link:hover { color: var(--taupe-deep); }
/* the umlaut lands on the item you are pointing at */
.nav-link::after {
  content: ""; position: absolute; left: 50%; top: -2px;
  width: 11px; height: 3px; transform: translateX(-50%);
  background:
    radial-gradient(circle 1.5px at 1.5px 1.5px, currentColor 99%, transparent 100%),
    radial-gradient(circle 1.5px at 9.5px 1.5px, currentColor 99%, transparent 100%);
  opacity: 0; transition: opacity .22s;
}
.nav-link:hover::after,
.nav-link[aria-current="page"]::after { opacity: .55; }
@media (prefers-reduced-motion: reduce) { .nav-link::after { transition: none; } }

.nav-div { width: 1px; height: 14px; background: var(--taupe-line); }
.cart-btn { display: inline-flex; align-items: center; gap: 8px; }
.cart-count {
  display: inline-grid; place-items: center; min-width: 20px; height: 20px;
  border-radius: 999px; background: var(--ink); color: var(--paper);
  font-size: 11px; letter-spacing: 0; padding-inline: 6px;
}
.cart-count[data-zero="true"] { background: var(--taupe-deep); }
.menu-btn { display: none; }
.cart-compact { display: none; }

@media (max-width: 900px) {
  /* phones keep the compact three-column bar: a centred six-item row cannot fit */
  .head-mark { padding: 0 var(--gutter); height: 64px; }
  .menu-btn {
    display: inline-flex; flex-direction: column; justify-content: center; align-items: center;
    gap: 5px; width: 48px; height: 48px; margin-left: -12px; grid-column: 1; justify-self: start;
  }
  .menu-btn span { display: block; width: 22px; height: 1.5px; background: var(--ink); transition: transform .3s, opacity .3s; }
  .wordmark { font-size: 21px; }
  .cart-compact {
    display: inline-flex; grid-column: 3; justify-self: end;
    min-height: 48px; padding-inline: 6px; margin-right: -6px;
  }
  

/* ---------- hero ---------- */
.hero {
  position: relative;
  min-height: min(92vh, 980px);
  display: grid; align-items: end;
  color: var(--paper);
  isolation: isolate;
  padding: 0;
}
.hero-media { position: absolute; inset: 0; z-index: -2; overflow: hidden; }
.hero-media img { width: 100%; height: 100%; object-fit: cover; object-position: center 38%; }
/* Hero scrim. Read this before changing it; it has been wrong twice.
   Attempt 1 keyed darkness to viewport-WIDTH percentages, so it did not survive
   object-fit:cover zooming into pale damask on a phone: the kicker hit 2.39:1.
   Attempt 2 keyed it to hero-HEIGHT percentages, assuming the copy sits at the bottom
   because .hero uses align-items:end. That assumption was false. .hero-inner carries
   96px of top padding and a tall stack, so the kicker actually lands around
   y=0.25-0.34 of the hero on most viewports, not 0.68. Attempt 2 darkened empty sky
   and left the kicker at 1.30:1 while a verifier reported it passing.
   The lesson is architectural: never guess where text sits. The scrim now lives
   BEHIND THE TEXT BOX, so it cannot drift. .hero-inner contains every hero text
   element, so its own background is always in the right place at every viewport and
   every crop. .hero::after is now decoration only and never load-bearing.
   scripts/verify-hero-scrim.py MEASURES the real glyph bands in headless Chrome
   rather than assuming them. Re-run it after touching any of this. */
.hero::after {
  content: ""; position: absolute; inset: 0; z-index: -1;
  background:
    linear-gradient(90deg, rgba(var(--ink-rgb), .14), rgba(var(--ink-rgb), .04) 55%, transparent),
    linear-gradient(180deg, rgba(var(--ink-rgb), .16) 0%, rgba(var(--ink-rgb), .06) 34%, rgba(var(--ink-rgb), .40) 100%);
}
/* The load-bearing scrim. It sits on the text box itself, so wherever the copy
   lands the protection lands with it. The soft top fade falls inside the 96px of
   padding, so it never touches a glyph; by the time the kicker starts, alpha is
   already at its floor. Values solved against both hero photographs at four
   viewports using the measured glyph bands. */
.hero-inner {
  width: 100%; max-width: var(--w-max); margin-inline: auto;
  padding: var(--s6) var(--gutter) var(--s5);
  background: linear-gradient(180deg,
    rgba(var(--ink-rgb), 0) 0%,
    rgba(var(--ink-rgb), .50) 9%,
    rgba(var(--ink-rgb), .66) 22%,
    rgba(var(--ink-rgb), .70) 100%);
}
.hero .kicker { color: var(--photo-kicker); }
.hero .kicker::before { background: var(--photo-kicker); }
.hero-title { color: var(--paper); margin-bottom: var(--s3); max-width: 11em; text-wrap: balance; }
.hero-sub { max-width: 36em; font-size: clamp(16px, 1.5vw, 19px); color: var(--photo-body); margin-bottom: var(--s4); }
.hero-ctas { display: flex; gap: 14px; flex-wrap: wrap; }
.hero-scroll {
  position: absolute; right: var(--gutter); bottom: var(--s4);
  writing-mode: vertical-rl;
  font-size: 11px; letter-spacing: .3em; text-transform: uppercase; color: var(--on-ink-dim);
  display: flex; align-items: center; gap: 12px;
}
.hero-scroll::after { content: ""; width: 1px; height: 54px; background: linear-gradient(var(--on-ink-dim), transparent); }
@media (max-width: 700px) { .hero-scroll { display: none; } .hero { min-height: 86vh; } }

/* ---------- marquee strip ---------- */
.strip { border-block: 1px solid var(--taupe-line); padding: 18px 0; background: var(--paper-warm); overflow: hidden; }
.marquee { overflow: hidden; }
.marquee > div { display: flex; gap: 0; width: max-content; }
.strip span {
  font-family: var(--serif); font-style: italic; font-size: clamp(18px, 2vw, 24px);
  color: var(--taupe-deep); white-space: nowrap; padding-right: 18px;
}
.strip span::after { content: "·"; padding-left: 18px; color: var(--blush); }

/* ---------- botanical line art ---------- */
.bloom-line { display: block; margin-inline: auto; overflow: visible; }
.bloom-line path, .bloom-line circle {
  fill: none; stroke: var(--taupe); stroke-width: 1.1; stroke-linecap: round;
}
.draw path { stroke-dasharray: var(--len, 400); stroke-dashoffset: var(--len, 400); }
.draw.drawn path { animation: draw 2.4s var(--ease-soft) forwards; }
.draw.drawn path:nth-child(2) { animation-delay: .3s; }
.draw.drawn path:nth-child(3) { animation-delay: .55s; }
.draw.drawn path:nth-child(4) { animation-delay: .8s; }
.draw.drawn path:nth-child(5) { animation-delay: 1.05s; }
@keyframes draw { to { stroke-dashoffset: 0; } }
@media (prefers-reduced-motion: reduce) {
  .draw path { stroke-dasharray: none; stroke-dashoffset: 0; }
  .draw.drawn path { animation: none; }
}

/* ---------- product grid ---------- */
.grid { display: grid; gap: clamp(20px, 3vw, 40px); }
.grid-3 { grid-template-columns: repeat(3, 1fr); }
.grid-4 { grid-template-columns: repeat(4, 1fr); }
.grid-2 { grid-template-columns: repeat(2, 1fr); }
@media (max-width: 1000px) { .grid-3, .grid-4 { grid-template-columns: repeat(2, 1fr); } }
/* Two-up on phones, but ONLY for product-card grids. One column made the collection
   10.7 screens with no product visible above the fold. Applying it to every .grid-3
   also hit the subscription pricing tiers, whose content cannot shrink, and pushed
   166px of horizontal overflow onto the page. minmax(0,1fr) is the guard: a bare 1fr
   has an auto minimum, so any unshrinkable child overflows the track. */
@media (max-width: 560px) {
  .grid-2, .grid-3, .grid-4 { grid-template-columns: minmax(0, 1fr); }
  .grid-cards { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 14px; }
  .grid-cards .card-name { font-size: 19px; }
  .grid-cards .card-note { font-size: 13px; }
  .grid-cards .card-price { font-size: 14px; }
}

.card { position: relative; }
/* The whole photo is the tap target. Previously only the small + was tappable:
   about 2.7% of the card's area, on the surface most people browse with a thumb. */
.card-media-link { position: absolute; inset: 0; z-index: 2; }
.card-media .quick-add { z-index: 3; }
.card-media {
  position: relative; overflow: hidden;
  aspect-ratio: 4 / 5;
  background: var(--paper-warm);
}
.card-media img {
  width: 100%; height: 100%; object-fit: cover;
  transition: transform 1.1s var(--ease-out), opacity .6s;
}
.card:hover .card-media img { transform: scale(1.045); }
@media (prefers-reduced-motion: reduce) { .card:hover .card-media img { transform: none; } }
.card-tag {
  position: absolute; top: 14px; left: 14px;
  background: color-mix(in srgb, var(--paper) 88%, transparent);
  backdrop-filter: blur(6px);
  font-size: 11px; letter-spacing: .22em; text-transform: uppercase; font-weight: 500;
  color: var(--ink); padding: 7px 12px;
}
.card-body { padding-top: 18px; display: grid; grid-template-columns: 1fr auto; gap: 4px 16px; align-items: baseline; }
.card-name { font-family: var(--serif); font-size: 24px; font-weight: 500; margin: 0; }
.card-name a::after { content: ""; position: absolute; inset: 0; }
.card-price { font-family: var(--sans); font-weight: 400; font-size: 15px; letter-spacing: .06em; color: var(--taupe-deep); white-space: nowrap; }
.card-note { grid-column: 1 / -1; font-size: 14.5px; color: var(--taupe-deep); margin: 0; }
.card-cta {
  grid-column: 1 / -1; margin-top: 12px; justify-self: start;
  position: relative; z-index: 2;
}

/* quick-add */
.quick-add {
  position: absolute; right: 14px; bottom: 14px; z-index: 3;
  background: var(--paper); color: var(--ink);
  width: 44px; height: 44px; border-radius: 50%;
  display: grid; place-items: center;
  font-size: 22px; font-weight: 300; line-height: 1;
  box-shadow: 0 8px 24px rgba(var(--ink-rgb), .18);
  opacity: 0; transform: translateY(8px);
  transition: opacity .3s var(--ease-out), transform .3s var(--ease-out), background .25s, color .25s;
}
.card:hover .quick-add, .quick-add:focus-visible { opacity: 1; transform: none; }
.quick-add:hover { background: var(--ink); color: var(--paper); }
@media (hover: none) { .quick-add { opacity: 1; transform: none; } }

/* ---------- editorial split ---------- */
.split { display: grid; grid-template-columns: 1fr 1fr; gap: clamp(32px, 6vw, 96px); align-items: center; }
.split.rev > :first-child { order: 2; }
@media (max-width: 860px) { .split, .split.rev { grid-template-columns: 1fr; } .split.rev > :first-child { order: 0; } }
.frame { position: relative; }
.frame img { width: 100%; aspect-ratio: 4/5; object-fit: cover; }
.frame-tall img { aspect-ratio: 3/4; }
.frame-caption {
  margin-top: 12px; font-size: 12.5px; letter-spacing: .18em; text-transform: uppercase;
  color: var(--taupe-deep); display: flex; justify-content: space-between; gap: 12px;
}
.frame-offset { position: absolute; inset: 18px -18px -18px 18px; border: 1px solid var(--taupe-line); z-index: -1; }

.no-list { list-style: none; padding: 0; margin: 0; }
.step-list li { display: grid; grid-template-columns: 64px 1fr; gap: 20px; padding: 26px 0; border-top: 1px solid var(--taupe-line); }
.step-list li:last-child { border-bottom: 1px solid var(--taupe-line); }
.step-no { font-family: var(--serif); font-style: italic; font-size: 30px; color: var(--blush-deep); line-height: 1; }
.step-list h3 { font-size: 24px; margin-bottom: 8px; }
.step-list p { margin: 0; color: var(--ink-soft); font-size: 16px; }

/* ---------- ink (dark) sections ---------- */
.ink-section { background: var(--ink); color: var(--ink-text); }
.ink-section .kicker { color: var(--ink-kicker); }
.ink-section .kicker::before, .ink-section .kicker.center::after { background: var(--taupe-deep); }
.ink-section h2, .ink-section h3 { color: var(--paper); }
.ink-section .lede { color: var(--ink-muted); }
.ink-section .hairline { border-color: var(--ink-line); }

/* ---------- gallery mosaic ---------- */
.mosaic { display: grid; grid-template-columns: repeat(12, 1fr); gap: clamp(12px, 1.6vw, 22px); }
.mosaic figure { margin: 0; overflow: hidden; position: relative; }
.mosaic img { width: 100%; height: 100%; object-fit: cover; transition: transform 1.2s var(--ease-out); }
.mosaic figure:hover img { transform: scale(1.04); }
.m-a { grid-column: span 5; aspect-ratio: 4/5; }
.m-b { grid-column: span 4; aspect-ratio: 1/1; align-self: end; }
.m-c { grid-column: span 3; aspect-ratio: 3/4; }
.m-d { grid-column: span 4; aspect-ratio: 1/1; }
.m-e { grid-column: span 8; aspect-ratio: 16/9; }
.m-c-wide { grid-column: span 4; aspect-ratio: 3/4; }
.m-e-offset { grid-column: 5 / -1; aspect-ratio: 16/9; }
@media (max-width: 760px) {
  .m-a, .m-b, .m-c, .m-d, .m-e, .m-c-wide, .m-e-offset { grid-column: span 6; aspect-ratio: 4/5; }
}

/* ---------- occasion ribbon ---------- */
.occasion-note {
  display: inline-flex; align-items: baseline; gap: 10px;
  border: 1px solid var(--taupe-line); background: var(--paper);
  padding: 12px 20px; font-size: 14px; color: var(--ink-soft);
}
.occasion-note b { font-weight: 500; color: var(--blush-deep); }

/* ---------- forms ---------- */
.field { display: grid; gap: 8px; margin-bottom: var(--s3); }
.field label { font-size: 12px; letter-spacing: .22em; text-transform: uppercase; font-weight: 500; color: var(--taupe-deep); }
/* 16px minimum on every text control: below that iOS silently zooms the whole page
   on focus and the visitor has to pinch back out mid-order. */
.field input, .field select, .field textarea {
  font: inherit; font-size: max(16px, 1em); font-weight: 300; color: var(--ink);
  background: transparent;
  border: 0; border-bottom: 1px solid var(--taupe-deep);
  padding: 10px 2px;
  border-radius: 0;
  transition: border-color .25s;
}
.field input::placeholder, .field textarea::placeholder { color: var(--taupe-deep); }
.field input:focus-visible, .field select:focus-visible, .field textarea:focus-visible { border-bottom: 2px solid var(--ink); padding-bottom: 9px; }
.field.invalid input, .field.invalid select, .field.invalid textarea { border-bottom-color: var(--err); }
.field-err { font-size: 13px; color: var(--err); min-height: 1em; }
.field-hint { font-size: 13.5px; color: var(--taupe-deep); }
.form-row { display: grid; grid-template-columns: 1fr 1fr; gap: 0 28px; }
@media (max-width: 620px) { .form-row { grid-template-columns: 1fr; } }
fieldset { border: 0; padding: 0; margin: 0 0 var(--s3); }
legend { font-size: 12px; letter-spacing: .22em; text-transform: uppercase; font-weight: 500; color: var(--taupe-deep); margin-bottom: 12px; padding: 0; }

.choice-row { display: flex; gap: 12px; flex-wrap: wrap; }
.choice {
  position: relative; cursor: pointer;
  border: 1px solid var(--ui-line); padding: 14px 22px;
  font-size: 14px; font-weight: 400; letter-spacing: .06em;
  transition: border-color .25s, background .25s;
  display: inline-flex; gap: 8px; align-items: center;
}
.choice input { position: absolute; opacity: 0; inset: 0; cursor: pointer; }
.choice:has(input:checked) { border-color: var(--ink); background: var(--paper-warm); }
.choice:has(input:focus-visible) { outline: 2px solid var(--blush-deep); outline-offset: 2px; }
.choice:has(input:disabled) { opacity: .45; cursor: not-allowed; }
.choice:has(input:disabled) input { cursor: not-allowed; }

/* ---------- cart drawer ---------- */
.drawer-veil {
  position: fixed; inset: 0; z-index: 990;
  background: rgba(var(--ink-rgb), .42);
  opacity: 0; visibility: hidden;
  transition: opacity .35s var(--ease-out), visibility .35s;
}
.drawer-veil.open { opacity: 1; visibility: visible; }
.drawer {
  position: fixed; top: 0; right: 0; bottom: 0; z-index: 995;
  width: min(460px, 100vw);
  background: var(--paper);
  border-left: 1px solid var(--taupe-line);
  display: flex; flex-direction: column;
  transform: translateX(102%);
  visibility: hidden;
  transition: transform .5s var(--ease-out), visibility .5s;
  box-shadow: -30px 0 80px rgba(var(--ink-rgb), .14);
}
.drawer.open { transform: none; visibility: visible; }
@media (prefers-reduced-motion: reduce) {
  .drawer { transition: none; } .drawer-veil { transition: none; }
}
.drawer-head {
  display: flex; justify-content: space-between; align-items: center;
  padding: 22px 26px; border-bottom: 1px solid var(--taupe-line);
}
.drawer-head h2 { font-size: 26px; margin: 0; }
.drawer-close { font-size: 12px; letter-spacing: .22em; text-transform: uppercase; padding: 8px; }
.drawer-items { flex: 1; overflow-y: auto; padding: 10px 26px; }
.drawer-empty { text-align: center; padding: var(--s5) 0; color: var(--taupe-deep); }
.line-item {
  display: grid; grid-template-columns: 84px 1fr auto; gap: 16px;
  padding: 18px 0; border-bottom: 1px solid var(--taupe-line);
}
.line-item img { width: 84px; height: 105px; object-fit: cover; }
.li-name { font-family: var(--serif); font-size: 19px; font-weight: 500; margin: 0 0 2px; }
.li-meta { font-size: 13px; color: var(--taupe-deep); margin: 0 0 10px; }
.li-price { font-size: 14.5px; font-weight: 400; text-align: right; }
.qty { display: inline-flex; align-items: center; border: 1px solid var(--ui-line); }
/* changing quantity is a revenue action; 32px was under every platform minimum */
.qty button { width: 44px; height: 44px; font-size: 17px; font-weight: 300; display: grid; place-items: center; transition: background .2s; }
.qty button:hover { background: var(--paper-warm); }
.qty output { width: 34px; text-align: center; font-size: 14px; font-weight: 400; }
.li-remove { font-size: 12px; letter-spacing: .14em; text-transform: uppercase; color: var(--taupe-deep);
             border-bottom: 1px solid transparent; align-self: end;
             min-height: 44px; display: inline-flex; align-items: center; padding: 6px 2px; }
.li-remove:hover { color: var(--err); border-bottom-color: var(--err); }
.drawer-foot { border-top: 1px solid var(--taupe-line); padding: 20px 26px 26px; background: var(--paper-warm); }
.drawer-total { display: flex; justify-content: space-between; font-family: var(--serif); font-size: 22px; font-weight: 500; margin-bottom: 6px; }
.drawer-note { font-size: 13px; color: var(--taupe-deep); margin: 0 0 16px; }
.drawer-foot .btn { width: 100%; }
.drawer-progress { margin: 0 0 14px; }
.drawer-progress .bar { height: 2px; background: var(--taupe-line); position: relative; overflow: hidden; }
.drawer-progress .bar i { position: absolute; inset: 0; right: auto; background: var(--blush-deep); transition: width .5s var(--ease-out); }
.drawer-progress p { font-size: 13px; margin: 8px 0 0; color: var(--ink-soft); }

/* toast */
.toast {
  /* pointer-events:none is load-bearing, not tidiness. The toast is z-index 1200 and
     the cart drawer is 995, so at 390px the full-width drawer puts its only forward
     button directly under the centred toast: without this the toast silently swallows
     the tap that would take someone to their order. A toast is an announcement and
     must never be a target. */
  position: fixed; left: 50%; bottom: 28px; z-index: 1200;
  pointer-events: none;
  transform: translate(-50%, 20px);
  background: var(--ink); color: var(--paper);
  font-size: 14px; letter-spacing: .04em;
  padding: 14px 26px;
  opacity: 0; visibility: hidden;
  transition: opacity .35s, transform .35s var(--ease-out), visibility .35s;
  max-width: min(92vw, 480px); text-align: center;
}
.toast.show { opacity: 1; visibility: visible; transform: translate(-50%, 0); }

/* ---------- cart page / checkout ---------- */
.checkout-grid { display: grid; grid-template-columns: 1.15fr .85fr; gap: clamp(32px, 5vw, 80px); align-items: start; }
@media (max-width: 900px) { .checkout-grid { grid-template-columns: 1fr; } }
.summary-panel { border: 1px solid var(--taupe-line); background: var(--paper-warm); padding: clamp(22px, 3vw, 36px); position: sticky; top: 110px; }
@media (max-width: 900px) { .summary-panel { position: static; } }

/* Mobile order bar: the phone equivalent of the sticky summary panel. */
.order-bar { display: none; }
@media (max-width: 900px) {
  .order-bar {
    display: flex; align-items: center; gap: 14px;
    position: fixed; left: 0; right: 0; bottom: 0; z-index: 980;
    padding: 12px var(--gutter) calc(12px + env(safe-area-inset-bottom, 0px));
    background: color-mix(in srgb, var(--paper) 96%, transparent);
    backdrop-filter: blur(14px); -webkit-backdrop-filter: blur(14px);
    border-top: 1px solid var(--ui-line);
  }
  .order-bar-total { display: flex; flex-direction: column; line-height: 1.15; white-space: nowrap; }
  .order-bar-total span { font-size: 11px; letter-spacing: .18em; text-transform: uppercase; color: var(--taupe-deep); }
  .order-bar-total strong { font-family: var(--serif); font-size: 22px; font-weight: 500; }
  .order-bar .btn { flex: 1; padding: 15px 18px; min-height: 48px; }
  /* keep the last field clear of the bar */
  [data-form-wrap] { padding-bottom: 96px; }
}
.sum-row { display: flex; justify-content: space-between; gap: 16px; padding: 9px 0; font-size: 15.5px; }
.sum-row.total { border-top: 1px solid var(--taupe); margin-top: 10px; padding-top: 16px; font-family: var(--serif); font-size: 23px; font-weight: 500; }
.steps { counter-reset: step; }
.step { border-top: 1px solid var(--taupe-line); padding: var(--s4) 0; }
.step:last-child { border-bottom: 1px solid var(--taupe-line); }
.step h2 { display: flex; gap: 18px; align-items: baseline; font-size: 28px; }
.step h2::before {
  counter-increment: step; content: counter(step, decimal-leading-zero);
  font-style: italic; font-size: 20px; color: var(--blush-deep);
}

.datebox { display: grid; gap: 6px; }
.date-feedback { font-size: 14px; min-height: 1.4em; }
.date-feedback.ok { color: var(--ok); }
.date-feedback.err { color: var(--err); }

/* confirmation */
.confirm-wrap { text-align: center; padding: var(--s6) 0; }
.confirm-wrap .bloom-line { margin-bottom: var(--s3); }

/* The three handoff routes on the mailto confirmation. Equal visual weight except
   for the one solid button, because any of the three genuinely reaches her and the
   right choice depends on the visitor's phone, not on our preference. */
.handoff {
  display: flex; flex-wrap: wrap; gap: 12px;
  justify-content: center;
  margin-top: var(--s4);
}
.handoff .btn { min-width: 15em; }
@media (max-width: 560px) {
  .handoff { flex-direction: column; align-items: stretch; }
  .handoff .btn { min-width: 0; width: 100%; }
}

/* ---------- accordion (FAQ / care) ---------- */
details.acc { border-top: 1px solid var(--taupe-line); }
details.acc:last-of-type { border-bottom: 1px solid var(--taupe-line); }
details.acc summary {
  list-style: none; cursor: pointer;
  display: flex; justify-content: space-between; align-items: center; gap: 20px;
  font-family: var(--serif); font-size: 22px; font-weight: 500;
  padding: 22px 4px;
}
details.acc summary::-webkit-details-marker { display: none; }
details.acc summary::after { content: "+"; font-size: 26px; font-weight: 300; color: var(--taupe-deep); transition: transform .3s var(--ease-out); }
details.acc[open] summary::after { transform: rotate(45deg); }
details.acc .acc-body { padding: 0 4px 26px; color: var(--ink-soft); max-width: 60em; }
details.acc .acc-body p { margin-top: 0; }

/* ---------- footer ---------- */
.site-foot { background: var(--ink); color: var(--ink-muted); padding: var(--s6) 0 var(--s3); }
.foot-grid { display: grid; grid-template-columns: 1.4fr 1fr 1fr 1.3fr; gap: clamp(28px, 4vw, 64px); padding-bottom: var(--s5); }
@media (max-width: 900px) { .foot-grid { grid-template-columns: 1fr 1fr; } }
@media (max-width: 560px) { .foot-grid { grid-template-columns: 1fr; } }
.foot-mark { font-family: var(--serif); font-size: 30px; letter-spacing: .1em; text-transform: uppercase; color: var(--paper); margin-bottom: 10px; }
.foot-tag { font-family: var(--serif); font-style: italic; font-size: 19px; color: var(--ink-kicker); margin: 0 0 18px; }
.site-foot h3 { font-family: var(--sans); font-size: 12px; letter-spacing: .28em; text-transform: uppercase; font-weight: 500; color: var(--ink-soft2); margin-bottom: 16px; }
.foot-links { display: grid; gap: 10px; }
.foot-links a { font-size: 15px; transition: color .25s; }
.foot-links a:hover { color: var(--paper); }
.foot-note { font-size: 13.5px; line-height: 1.7; }
.foot-form { display: flex; border-bottom: 1px solid var(--ui-line); }
.foot-form input {
  flex: 1; background: none; border: 0; color: var(--paper);
  font: inherit; font-size: 16px; padding: 12px 2px;  /* 16px: below it iOS zooms on focus */
  min-height: 44px;
}
.foot-form input::placeholder { color: var(--ink-soft2); }
.foot-form input:focus { outline: none; box-shadow: 0 2px 0 var(--paper); }
.foot-form button { font-size: 12px; letter-spacing: .2em; text-transform: uppercase; color: var(--paper); padding: 10px; }
.foot-form button:hover { color: var(--blush); }
.foot-base {
  border-top: 1px solid var(--ink-line);
  padding-top: var(--s3);
  display: flex; justify-content: space-between; gap: 16px; flex-wrap: wrap;
  font-size: 13px; color: var(--ink-soft2);
}
.foot-base a:hover { color: var(--paper); }

/* ---------- page hero (interior pages) ---------- */
.page-head { padding: var(--s6) 0 var(--s5); }
.page-head .display { max-width: 12em; text-wrap: balance; }

/* shop filters */
.filters { display: flex; gap: 10px; flex-wrap: wrap; margin-bottom: var(--s4); }
.filter-btn {
  font-size: 12.5px; letter-spacing: .18em; text-transform: uppercase; font-weight: 400;
  padding: 11px 20px; border: 1px solid var(--ui-line);
  transition: border-color .25s, background .25s, color .25s;
}
.filter-btn[aria-pressed="true"] { background: var(--ink); border-color: var(--ink); color: var(--paper); }
.filter-btn:hover:not([aria-pressed="true"]) { border-color: var(--ink); }

/* product detail */
.pd { display: grid; grid-template-columns: 1.05fr .95fr; gap: clamp(32px, 5vw, 80px); align-items: start; }
@media (max-width: 860px) { .pd { grid-template-columns: 1fr; } }
.pd-media { position: sticky; top: 110px; }
@media (max-width: 860px) { .pd-media { position: static; } }
.pd-media img { width: 100%; aspect-ratio: 4/5; object-fit: cover; }
.pd-thumbs { display: flex; gap: 10px; margin-top: 12px; }
.pd-thumbs button { width: 72px; height: 90px; overflow: hidden; opacity: .55; transition: opacity .25s; border: 1px solid transparent; padding: 0; }
.pd-thumbs button img { width: 100%; height: 100%; object-fit: cover; }
.pd-thumbs button[aria-pressed="true"] { opacity: 1; border-color: var(--ink); }
.pd-price { font-family: var(--sans); font-size: 20px; font-weight: 400; letter-spacing: .04em; margin: 0 0 var(--s3); }
.pd-desc { color: var(--ink-soft); max-width: 38em; }
.size-note { font-size: 13.5px; color: var(--taupe-deep); }

/* subscription tiers */
.tier { border: 1px solid var(--taupe-line); padding: clamp(26px, 3vw, 40px); display: flex; flex-direction: column; gap: 14px; background: var(--paper); position: relative; transition: border-color .3s; }
.tier:hover { border-color: var(--taupe); }
.tier.featured { border-color: var(--ink); }
.tier-flag { position: absolute; top: -12px; left: 26px; background: var(--ink); color: var(--paper); font-size: 11px; letter-spacing: .22em; text-transform: uppercase; padding: 6px 12px; }
.tier h3 { margin: 0; font-size: 28px; }
.tier-price { font-family: var(--serif); font-size: 38px; font-weight: 500; }
.tier-price small { font-family: var(--sans); font-size: 14px; color: var(--taupe-deep); font-weight: 300; }
.tier ul { list-style: none; padding: 0; margin: 0; display: grid; gap: 9px; font-size: 15px; color: var(--ink-soft); }
.tier ul li { padding-left: 22px; position: relative; }
.tier ul li::before { content: "·"; position: absolute; left: 4px; color: var(--blush-deep); font-weight: 700; }
.tier .btn { margin-top: auto; }

/* testimonial */
.quote { max-width: 760px; margin-inline: auto; text-align: center; }
.quote blockquote { font-family: var(--serif); font-style: italic; font-size: clamp(24px, 3vw, 34px); font-weight: 400; line-height: 1.35; margin: 0 0 var(--s3); }
.quote cite { font-style: normal; font-size: 13px; letter-spacing: .24em; text-transform: uppercase; color: var(--taupe-deep); }

/* util */
.mt-0 { margin-top: 0; } .mb-0 { margin-bottom: 0; }
.mt-4 { margin-top: var(--s4); } .mt-5 { margin-top: var(--s5); }
.mb-4 { margin-bottom: var(--s4); }
.visually-hidden { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }

@media (prefers-reduced-motion: reduce) {
  .mosaic figure:hover img, .card:hover .card-media img { transform: none; }
  .cart-count.bump { animation: none; }
}
/* marquee pause toggle (tap/click) */
.marquee.paused > div { animation-play-state: paused; }

.ink-muted { color: var(--ink-muted); }

/* ---------- the umlaut separator ----------
   The two dots over the U in BLÜME are the one genuinely ownable shape in the
   wordmark, and they were doing nothing. Every '·' on the site is now the pair, so
   the mark echoes quietly in every line without ever being announced. Side by side,
   not stacked, because that is the umlaut's own orientation. Sized in em so it scales
   with whatever text it sits in, and held at 50% opacity so it recedes. */
.uml {
  display: inline-block; position: relative;
  width: 0.72em; height: 0.2em;
  vertical-align: 0.16em;
  margin-inline: 0.5em;
}
.uml::before, .uml::after {
  content: ""; position: absolute; top: 0;
  width: 0.2em; height: 0.2em; border-radius: 50%;
  background: currentColor; opacity: .5;
}
.uml::before { left: 0; }
.uml::after  { right: 0; }
.kicker .uml, .marquee .uml { margin-inline: 0.7em; }
