/* The Blend Bar — customer-facing site.
   ==========================================================================

   Apple-esque layout and typography on the house gold-on-cream palette.

   What "Apple-esque" means here, concretely — these are the rules the rest of
   this file follows, so a new section can be added without guessing:

     * **Type carries the page, not ornament.** Very large headlines at weight
       600 with negative tracking, a calm grey subhead under each, and nothing
       else competing. The previous design leaned on uppercase letter-spaced
       eyebrows and ✦ dividers; both are gone, because tracked-out small caps
       are the opposite of this look.
     * **Sans for everything, serif for the wordmark only.** `-apple-system`
       resolves to SF Pro on Apple hardware, which is the genuine article. The
       serif survives on the brand wordmark so the identity does not evaporate.
       Web fonts are not an option regardless: the CSP sets `font-src 'self'`.
     * **Pills, not rectangles.** 980px button radius, 22–28px on cards and
       media, no hairline boxes around content.
     * **Air.** Sections breathe at clamp(4.5rem, 9vw, 8rem); white and cream
       alternate to separate them instead of borders.
     * **Motion is a whisper.** One fade-and-rise on scroll, ~0.7s on an
       ease-out curve, and nothing moves for `prefers-reduced-motion`.

   The palette is unchanged from the original: warm gold on cream, sampled from
   the brand photography.

   One stylesheet serves every page — the marketing home, /portal, /book, /s/<id>
   and /thanks — so a class removed here breaks a page that is not this one. The
   component blocks at the bottom exist for markup generated by share.js,
   portal/app.js and book.js; keep them in step with those files. */

:root {
  --cream: #fbf7ef;
  --paper: #ffffff;
  --sand: #f1e9da;
  --sand-deep: #e7dcc6;
  --gold: #ac854a;
  --gold-deep: #8c6a36;
  --gold-soft: #c9a86c;
  --ink: #211c15;
  --text: #4c4235;
  --muted: #897a63;
  --line: #e2d7c1;

  /* SF Pro where it exists, a graceful fall through Helvetica elsewhere. */
  --sans: -apple-system, BlinkMacSystemFont, "SF Pro Display", "SF Pro Text",
    "Helvetica Neue", Helvetica, Arial, sans-serif;
  --wordmark: Georgia, "Times New Roman", serif;
  /* Retained as aliases: the old names are what the rest of this file was
     written against, and keeping them means one place to change if the brand
     ever wants the serif back for headlines. */
  --display: var(--sans);
  --body: var(--sans);

  --r-card: 22px;
  --r-media: 28px;
  --r-input: 12px;
  --r-pill: 980px;

  /* Two layers each: a tight contact shadow so an edge reads on white, and a
     wide soft one for the lift. A single large blur alone looks like a drop
     shadow; these read as depth. */
  --shadow-soft: 0 1px 4px rgba(33, 28, 21, 0.04), 0 18px 40px -26px rgba(33, 28, 21, 0.2);
  --shadow-lift: 0 2px 10px rgba(33, 28, 21, 0.06), 0 30px 64px -30px rgba(33, 28, 21, 0.26);
  /* Kept for the components below that referenced it by name. */
  --shadow: var(--shadow-soft);

  --ease-out: cubic-bezier(0.16, 1, 0.3, 1);
  --wrap: 1120px;
  --wrap-narrow: 46rem;
}

* {
  box-sizing: border-box;
}

html {
  scroll-behavior: smooth;
  /* A warm light palette throughout; stops the browser rendering form controls
     and scrollbars in dark chrome for visitors whose OS prefers dark. */
  color-scheme: light;
}

body {
  margin: 0;
  background: var(--paper);
  color: var(--text);
  font-family: var(--sans);
  /* 17px/1.47 is Apple's own body setting, and it is genuinely comfortable. */
  font-size: 17px;
  line-height: 1.47;
  letter-spacing: -0.01em;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-rendering: optimizeLegibility;
}

img {
  max-width: 100%;
  height: auto; /* always scale proportionally, ignoring the width/height attrs */
  display: block;
}

a {
  color: var(--gold-deep);
  text-decoration: none;
}

a:hover {
  color: var(--gold);
}

h1,
h2,
h3,
h4 {
  color: var(--ink);
  margin: 0;
  /* The whole look rests on this: heavy-ish weight, tight tracking, tight
     leading. Size alone does not make a headline feel designed. */
  font-weight: 600;
  letter-spacing: -0.025em;
  line-height: 1.08;
}

h1 {
  font-size: clamp(2.5rem, 6.4vw, 4.75rem);
  letter-spacing: -0.03em;
  line-height: 1.05;
}

h2 {
  font-size: clamp(1.95rem, 4.4vw, 3.15rem);
}

h3 {
  font-size: clamp(1.2rem, 2vw, 1.5rem);
  letter-spacing: -0.018em;
}

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

/* One focus treatment for every interactive thing on the site. Gold, offset so
   it never crowds the glyphs, and never suppressed — the ring is the only way a
   keyboard visitor knows where they are. */
a:focus-visible,
button:focus-visible,
input:focus-visible,
textarea:focus-visible,
select:focus-visible,
summary:focus-visible {
  outline: 2px solid var(--gold);
  outline-offset: 3px;
  border-radius: 4px;
}

.wrap {
  max-width: var(--wrap);
  margin: 0 auto;
  padding: 0 1.5rem;
}

/* --- Small shared utilities --- */

/* The line above a headline. Sentence case and untracked: the old uppercase
   0.32em version is exactly the detail that stopped this reading as Apple. */
.eyebrow {
  font-size: 1.05rem;
  font-weight: 600;
  letter-spacing: -0.01em;
  color: var(--gold-deep);
  margin: 0 0 0.6rem;
}

/* Used by book.html, thanks.html and both JS-rendered pages, and previously
   styled only via compound selectors that missed most of those cases. */
.muted {
  color: var(--muted);
}

/* Apple's secondary call to action: a plain coloured link with a chevron that
   nudges on hover. Cheaper than a second button and much quieter. */
.link-more {
  display: inline-flex;
  align-items: center;
  gap: 0.3em;
  font-size: 1.05rem;
  color: var(--gold-deep);
}

.link-more::after {
  content: "›";
  font-size: 1.25em;
  line-height: 1;
  transform: translateY(-0.04em);
  transition: transform 0.25s var(--ease-out);
}

.link-more:hover::after {
  transform: translate(0.2em, -0.04em);
}

/* --- Scroll reveal ---------------------------------------------------------
   `.reveal` on its own does nothing: home.js hides an element only if it is
   below the fold when the page loads, then releases it on approach. So with JS
   off, or before the script runs, every word is on screen — a reveal that can
   swallow the whole page when one script fails is not worth the effect. */
.reveal-ready {
  opacity: 0;
  transform: translateY(1.75rem);
  transition: opacity 0.7s var(--ease-out), transform 0.7s var(--ease-out);
  will-change: opacity, transform;
}

.reveal-ready.in {
  opacity: 1;
  transform: none;
}

/* Children of a revealed grid come in one after another rather than as a slab. */
.stagger > *:nth-child(2) {
  transition-delay: 0.09s;
}
.stagger > *:nth-child(3) {
  transition-delay: 0.18s;
}
.stagger > *:nth-child(4) {
  transition-delay: 0.27s;
}

@media (prefers-reduced-motion: reduce) {
  html {
    scroll-behavior: auto;
  }
  .reveal-ready,
  .reveal-ready.in {
    opacity: 1;
    transform: none;
    transition: none;
  }
  .link-more::after,
  .tile,
  .btn {
    transition: none;
  }
}

/* --- Buttons --- */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.5rem;
  padding: 0.78rem 1.5rem;
  font-family: inherit;
  font-size: 1.0625rem;
  font-weight: 500;
  letter-spacing: -0.01em;
  /* The pill. 980px rather than 50% so the radius is stable whatever the
     button's height — the same number Apple uses. */
  border-radius: var(--r-pill);
  border: 1px solid transparent;
  cursor: pointer;
  white-space: nowrap;
  transition: background-color 0.25s var(--ease-out), color 0.25s var(--ease-out),
    border-color 0.25s var(--ease-out), transform 0.25s var(--ease-out);
}

.btn:active {
  transform: scale(0.97);
}

.btn.solid {
  background: var(--gold);
  color: #fff;
}

.btn.solid:hover {
  background: var(--gold-deep);
  color: #fff;
}

.btn.ghost {
  background: transparent;
  color: var(--gold-deep);
  border-color: var(--gold);
}

.btn.ghost:hover {
  background: var(--gold);
  border-color: var(--gold);
  color: #fff;
}

.btn.light {
  border-color: rgba(255, 255, 255, 0.55);
  color: #fff;
  background: transparent;
}

.btn.light:hover {
  background: #fff;
  color: var(--ink);
  border-color: #fff;
}

/* --- Header ---------------------------------------------------------------
   Thin, translucent, blurred — the one piece of chrome on the page. The
   saturate() is what keeps warm cream from going grey behind the blur. */
.site-header {
  position: sticky;
  top: 0;
  z-index: 20;
  background: rgba(255, 255, 255, 0.72);
  -webkit-backdrop-filter: saturate(180%) blur(20px);
  backdrop-filter: saturate(180%) blur(20px);
  border-bottom: 1px solid rgba(33, 28, 21, 0.07);
}

.site-header .wrap {
  display: flex;
  align-items: center;
  gap: 1.5rem;
  min-height: 54px;
}

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

.brand img {
  width: 30px;
  height: 30px;
  object-fit: contain;
}

/* The serif survives here and nowhere else. */
.brand .name {
  font-family: var(--wordmark);
  font-size: 0.95rem;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--ink);
}

.nav {
  display: flex;
  align-items: center;
  gap: 1.5rem;
  margin-left: auto;
}

.nav .links {
  display: flex;
  gap: 1.55rem;
}

/* 12px nav links: small enough to recede, and the reason the bar can be 54px
   tall without feeling cramped. */
.nav .links a {
  color: var(--text);
  font-size: 0.75rem;
  letter-spacing: -0.005em;
  opacity: 0.85;
  transition: opacity 0.2s var(--ease-out), color 0.2s var(--ease-out);
}

.nav .links a:hover {
  color: var(--ink);
  opacity: 1;
}

.nav .actions {
  display: flex;
  gap: 0.5rem;
}

.nav .actions .btn {
  padding: 0.42rem 1rem;
  font-size: 0.8125rem;
}

/* --- Sections --- */
section {
  padding: clamp(4.5rem, 9vw, 8rem) 0;
  /* Anchor targets must clear the sticky header, or #shop lands with its
     headline tucked under the bar. */
  scroll-margin-top: 4rem;
}

.band {
  background: var(--cream);
}

.section-head {
  text-align: center;
  max-width: 40rem;
  margin: 0 auto clamp(2.5rem, 5vw, 4rem);
}

/* The calm grey line under a headline. Large, light, never bold. */
.section-head p {
  margin: 1.1rem 0 0;
  color: var(--muted);
  font-size: clamp(1.05rem, 1.7vw, 1.3rem);
  line-height: 1.4;
}

/* --- Hero ----------------------------------------------------------------
   Centred copy, then one large piece of media beneath it. The old hero put
   copy and bottle side by side; stacking them is what gives the headline the
   full width it needs to land. */
.hero {
  padding: clamp(3.5rem, 8vw, 7rem) 0 clamp(3rem, 6vw, 5.5rem);
  text-align: center;
}

.hero-copy {
  max-width: 54rem;
  margin: 0 auto;
}

.hero h1 {
  margin-bottom: 1.1rem;
  /* Wrapped in a span so the second line can take the gold without the
     browser hyphenating around it. */
  text-wrap: balance;
}

.hero h1 .accent {
  color: var(--gold-deep);
}

.hero .lede {
  font-size: clamp(1.15rem, 2.1vw, 1.5rem);
  line-height: 1.4;
  color: var(--muted);
  max-width: 34rem;
  margin: 0 auto 2.1rem;
}

.cta-row {
  display: flex;
  flex-wrap: wrap;
  gap: 1.25rem;
  align-items: center;
}

.hero .cta-row {
  justify-content: center;
}

.hero-figure {
  margin: clamp(2.5rem, 6vw, 4.5rem) auto 0;
  max-width: 560px;
}

.hero-figure img {
  width: 100%;
  border-radius: var(--r-media);
  box-shadow: var(--shadow-lift);
}

/* --- About --- */
.about-copy {
  max-width: var(--wrap-narrow);
  margin: 0 auto;
}

.about-copy p {
  margin: 0 0 1.5rem;
  color: var(--muted);
  font-size: clamp(1.05rem, 1.6vw, 1.2rem);
  line-height: 1.55;
}

.about-copy p:last-child {
  margin-bottom: 0;
}

/* --- Tiles (the experience steps, the portals) --------------------------
   `.cards`/`.card` keep their names — other pages and the JS-rendered views
   reach for them — but they are now borderless rounded tiles that lift on
   hover, left-aligned the way Apple's feature tiles are. */
.cards {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 1.25rem;
}

.card,
.tile {
  background: var(--paper);
  border: none;
  border-radius: var(--r-card);
  padding: 2.4rem 2rem;
  text-align: left;
  box-shadow: var(--shadow-soft);
  transition: transform 0.35s var(--ease-out), box-shadow 0.35s var(--ease-out);
}

/* On a cream band a white tile reads on its own; on white it needs the hairline
   back or it dissolves into the page. */
section:not(.band) .card,
section:not(.band) .tile {
  background: var(--cream);
}

.tile:hover {
  transform: translateY(-4px);
  box-shadow: var(--shadow-lift);
}

/* The step numeral: large, light, gold — a graphic mark rather than the old
   circled Roman numeral in a bordered ring. */
.card .num {
  font-size: 2.6rem;
  font-weight: 300;
  letter-spacing: -0.03em;
  line-height: 1;
  color: var(--gold);
  margin: 0 0 1.1rem;
}

.card h3 {
  margin-bottom: 0.5rem;
}

.card p {
  margin: 0;
  color: var(--muted);
  font-size: 1.0625rem;
  line-height: 1.5;
}

/* --- Statement band -----------------------------------------------------
   One dark, near-empty full-bleed section carrying a single line. The pause
   between the long reading sections. */
.statement {
  background: var(--ink);
  text-align: center;
}

.statement h2 {
  color: var(--cream);
  font-size: clamp(2.1rem, 5.4vw, 3.9rem);
  max-width: 34rem;
  margin: 0 auto;
  text-wrap: balance;
}

.statement h2 em {
  font-style: normal;
  color: var(--gold-soft);
}

.statement p {
  color: rgba(251, 247, 239, 0.62);
  font-size: clamp(1.05rem, 1.7vw, 1.25rem);
  max-width: 30rem;
  margin: 1.4rem auto 0;
}

/* --- Signature product --- */
.product {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: clamp(2.5rem, 6vw, 5rem);
  align-items: center;
}

/* Capped: the artwork is square and the copy beside it is four lines, so at the
   full half-width the emblem dwarfs what it is there to illustrate. */
.product-figure {
  margin: 0;
  max-width: 460px;
  border-radius: var(--r-media);
  overflow: hidden;
  background: var(--paper);
  box-shadow: var(--shadow-lift);
}

.product-figure img {
  width: 100%;
}

.product-copy .eyebrow {
  margin-bottom: 0.4rem;
}

.product h2 {
  margin-bottom: 1rem;
}

.product p {
  color: var(--muted);
  font-size: clamp(1.05rem, 1.7vw, 1.25rem);
  line-height: 1.5;
  margin: 0 0 2rem;
  max-width: 30rem;
}

.product .price {
  font-size: 1.4rem;
  font-weight: 600;
  letter-spacing: -0.02em;
  color: var(--ink);
  margin: 0 0 1.4rem;
}

/* --- Event booking terms --- */
.terms {
  margin-top: clamp(2.5rem, 5vw, 4rem);
}

.terms-col {
  background: var(--paper);
  border: none;
  border-radius: var(--r-card);
  padding: clamp(1.9rem, 4vw, 2.75rem);
  box-shadow: var(--shadow-soft);
  max-width: var(--wrap-narrow);
  margin: 0 auto;
}

.terms-col h3 {
  margin-bottom: 1.2rem;
}

/* Terms read better as separated statements than as a bulleted list — the list
   marker adds nothing here and the hairlines do the grouping. */
.terms-col ul {
  margin: 0;
  padding: 0;
  list-style: none;
  color: var(--muted);
  font-size: 1rem;
  line-height: 1.55;
}

.terms-col li + li {
  margin-top: 1.1rem;
  padding-top: 1.1rem;
  border-top: 1px solid rgba(33, 28, 21, 0.07);
}

/* --- Access (portals) --- */
.access .cards {
  grid-template-columns: repeat(2, 1fr);
  max-width: 860px;
  margin: 0 auto;
}

.access .card {
  padding: clamp(2rem, 4vw, 2.75rem);
  display: flex;
  flex-direction: column;
}

.access .card p {
  margin-bottom: 1.6rem;
  flex: 1;
}

.access .card .btn {
  align-self: flex-start;
}

/* --- Footer -------------------------------------------------------------
   Light, quiet, 12px — Apple's footer, not a dark slab. The page ends by
   fading out rather than stopping. */
.site-footer {
  background: var(--cream);
  color: var(--muted);
  padding: clamp(3rem, 6vw, 4.5rem) 0 2rem;
  border-top: 1px solid rgba(33, 28, 21, 0.07);
  font-size: 0.8125rem;
  line-height: 1.5;
}

.site-footer .wrap {
  display: grid;
  grid-template-columns: 1.6fr 1fr 1fr;
  gap: 2.5rem;
}

.site-footer .name {
  font-family: var(--wordmark);
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--ink);
  font-size: 0.95rem;
  margin-bottom: 0.5rem;
}

.site-footer h4 {
  color: var(--ink);
  font-size: 0.8125rem;
  font-weight: 600;
  letter-spacing: -0.005em;
  margin: 0 0 0.7rem;
}

.site-footer a {
  color: var(--muted);
  display: block;
  margin-bottom: 0.45rem;
}

.site-footer a:hover {
  color: var(--gold-deep);
  text-decoration: underline;
}

.site-footer .tagline {
  margin: 0;
  max-width: 20rem;
}

.legal {
  border-top: 1px solid rgba(33, 28, 21, 0.07);
  margin-top: 2.5rem;
  padding-top: 1.25rem;
  color: var(--muted);
}

/* ==========================================================================
   Application pages
   --------------------------------------------------------------------------
   Everything below dresses markup that lives in book.html / thanks.html or is
   generated at runtime by share.js, portal/app.js, book.js and
   portal/verify.js. The class names come from those files: renaming one here
   silently unstyles a page.
   ========================================================================== */

/* --- Portal / card pages --- */
.portal-page {
  min-height: 70vh;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 4rem 1.5rem;
}

.portal-card {
  background: var(--paper);
  border: none;
  border-radius: var(--r-card);
  box-shadow: var(--shadow-lift);
  max-width: 480px;
  width: 100%;
  padding: clamp(2.25rem, 5vw, 3rem) clamp(1.5rem, 4vw, 2.5rem);
  text-align: center;
}

.portal-card img {
  width: 56px;
  margin: 0 auto 1.4rem;
}

.portal-card h1 {
  font-size: clamp(1.7rem, 4vw, 2.1rem);
  margin-bottom: 0.9rem;
}

.portal-card p {
  color: var(--muted);
  margin: 0 0 1.6rem;
}

.portal-note {
  background: var(--cream);
  border: 1px solid rgba(33, 28, 21, 0.07);
  border-radius: var(--r-input);
  padding: 0.9rem 1.1rem;
  font-size: 0.95rem;
  color: var(--text);
  margin-bottom: 1.8rem;
}

.portal-note.bad {
  background: color-mix(in srgb, #a4402e 7%, var(--paper));
  border-color: color-mix(in srgb, #a4402e 35%, var(--paper));
  color: #8f3625;
}

.portal-wrap {
  max-width: 640px;
  margin: clamp(2rem, 5vw, 3.5rem) auto;
  padding: 0 1.5rem;
}

.portal-wrap h1 {
  font-size: clamp(1.8rem, 4vw, 2.4rem);
  margin: 0.3rem 0 0.8rem;
}

.portal-wrap > #view > p {
  color: var(--muted);
}

.portal-input,
.blend-size {
  width: 100%;
  padding: 0.8rem 0.95rem;
  font: inherit;
  /* 16px minimum, or iOS Safari zooms the page when the field is focused. */
  font-size: 1rem;
  color: var(--ink);
  background: var(--paper);
  border: 1px solid var(--line);
  border-radius: var(--r-input);
}

#loginForm {
  margin-top: 1.2rem;
  display: flex;
  flex-direction: column;
  gap: 0.8rem;
}

#loginForm .btn {
  width: 100%;
}

.portal-head {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  gap: 1rem;
  margin-bottom: 1.2rem;
}

.portal-head h1 {
  margin: 0.2rem 0 0;
}

/* Section label inside the portal — matches .eyebrow rather than the old
   tracked-out caps. */
.blend-h {
  font-size: 1.05rem;
  font-weight: 600;
  letter-spacing: -0.01em;
  color: var(--gold-deep);
  margin: 2rem 0 0.8rem;
}

.blends {
  display: flex;
  flex-direction: column;
  gap: 0.75rem;
}

.blend {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 1rem;
  flex-wrap: wrap;
  background: var(--paper);
  border: none;
  border-radius: var(--r-card);
  box-shadow: var(--shadow-soft);
  padding: 1.15rem 1.35rem;
}

.blend-name {
  font-weight: 600;
  letter-spacing: -0.015em;
  color: var(--ink);
}

.blend-controls {
  display: flex;
  gap: 0.6rem;
  align-items: center;
}

.blend-controls .blend-size {
  width: auto;
  padding: 0.6rem 0.75rem;
}

.blend-controls .btn {
  padding: 0.62rem 1.2rem;
  font-size: 1rem;
}

/* --- Portal share panel --- */
.share-panel {
  flex-basis: 100%;
  margin-top: 0.9rem;
  padding-top: 1rem;
  border-top: 1px solid rgba(33, 28, 21, 0.07);
}

.share-row {
  display: flex;
  gap: 0.5rem;
  margin: 0.5rem 0 0.9rem;
}

.share-row .share-link {
  flex: 1;
  font-size: 0.9rem;
}

.share-qr {
  display: block;
  width: 180px;
  height: 180px;
  border: 1px solid var(--line);
  border-radius: var(--r-input);
  background: #fff;
  padding: 0.4rem;
}

/* --- Public share page --- */
.share-card {
  background: var(--paper);
  border: none;
  border-radius: var(--r-card);
  box-shadow: var(--shadow-lift);
  max-width: 460px;
  margin: 0 auto;
  padding: clamp(2rem, 5vw, 2.75rem) clamp(1.5rem, 4vw, 2.25rem);
  text-align: center;
}

.share-mark {
  width: 54px;
  margin: 0 auto 1.2rem;
}

.share-card h1 {
  font-size: clamp(1.7rem, 4vw, 2.1rem);
  margin: 0.2rem 0 1.2rem;
}

/* Was unstyled: share.js renders it when a referral discount applies, and it
   should read as good news rather than as body copy. */
.ref-note {
  margin: 0 0 1rem;
  font-size: 0.95rem;
  font-weight: 600;
  color: var(--gold-deep);
}

.notes-label {
  font-size: 0.95rem;
  font-weight: 600;
  letter-spacing: -0.01em;
  color: var(--gold-deep);
  margin: 0 0 0.6rem;
}

.notes {
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem;
  justify-content: center;
  margin-bottom: 1.6rem;
}

.note-chip {
  padding: 0.35rem 0.85rem;
  border: none;
  border-radius: var(--r-pill);
  font-size: 0.9rem;
  color: var(--text);
  background: var(--cream);
}

.sizes {
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
  margin-bottom: 1.4rem;
}

.size-opt {
  display: flex;
  align-items: center;
  gap: 0.7rem;
  padding: 0.85rem 1rem;
  border: 1px solid var(--line);
  border-radius: var(--r-input);
  cursor: pointer;
  text-align: left;
  transition: border-color 0.2s var(--ease-out), background-color 0.2s var(--ease-out);
}

.size-opt:hover {
  border-color: var(--gold-soft);
  background: var(--cream);
}

/* The chosen bottle should be obvious at a glance — this is the one decision
   the page is asking for. */
.size-opt:has(input:checked) {
  border-color: var(--gold);
  background: var(--cream);
}

.size-opt input {
  accent-color: var(--gold);
}

.size-opt span:nth-of-type(1) {
  flex: 1;
}

.size-price {
  font-weight: 600;
  letter-spacing: -0.015em;
  color: var(--ink);
}

/* --- Share-page buy form + booking form --- */
.buy-form {
  display: flex;
  flex-direction: column;
  gap: 0.95rem;
  text-align: left;
  margin-top: 1.5rem;
}

.buy-form .field {
  display: flex;
  flex-direction: column;
  gap: 0.35rem;
}

.buy-form .field > span {
  font-size: 0.95rem;
  font-weight: 500;
  letter-spacing: -0.01em;
  color: var(--ink);
}

.buy-form .field em {
  font-style: normal;
  font-weight: 400;
}

.buy-form input,
.book-form textarea {
  width: 100%;
  padding: 0.8rem 0.95rem;
  border: 1px solid var(--line);
  border-radius: var(--r-input);
  background: var(--paper);
  color: var(--ink);
  font: inherit;
  /* 16px minimum, or iOS Safari zooms the page when the field is focused. */
  font-size: 1rem;
  transition: border-color 0.2s var(--ease-out);
}

.book-form textarea {
  line-height: 1.55;
  resize: vertical;
}

.buy-form input:hover,
.book-form textarea:hover {
  border-color: var(--gold-soft);
}

.buy-form button[disabled] {
  opacity: 0.6;
  cursor: progress;
}

/* A 980px radius stretched across a whole form reads as a lozenge rather than a
   button — the pill only works at a width close to its own text. Full-width
   actions take the input radius instead, so the submit matches the fields it
   sits under. */
.buy-form > .btn,
#loginForm .btn {
  border-radius: var(--r-input);
  padding: 0.9rem 1.5rem;
}

.book-wrap {
  max-width: 680px;
}

.book-form {
  margin-top: 1.8rem;
}

/* Given and family name sit on one line on a desktop; the breakpoint below
   stacks them, because two half-width fields on a phone are unusable. */
.book-row {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 0.95rem;
}

.field-hint {
  font-size: 0.85rem;
  color: var(--muted);
}

/* Honeypot: off-screen rather than display:none, which the less naive bots
   know to skip. Never focusable, never announced. */
.book-hp {
  position: absolute;
  left: -9999px;
  width: 1px;
  height: 1px;
  overflow: hidden;
}

.book-captcha-row {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  flex-wrap: wrap;
}

.book-captcha-q {
  margin: 0;
  font-size: 1.1rem;
  font-weight: 600;
  letter-spacing: -0.015em;
  color: var(--ink);
}

.book-captcha-row input {
  width: 5.5rem;
  flex: 0 0 auto;
}

.book-captcha-new {
  padding: 0.5rem 1rem;
  font-size: 0.9rem;
}

/* `hidden` alone does not hide this form: .buy-form sets `display: flex`, and a
   class beats the UA stylesheet's [hidden] rule, so the fields stayed on screen
   underneath the result panel. */
.book-form[hidden] {
  display: none;
}

.book-panel {
  text-align: left;
  /* .portal-card caps at 480px for the sign-in box; here the panel replaces the
     form in place and should match its width. */
  max-width: none;
  padding: clamp(1.9rem, 4vw, 2.5rem);
}

.book-panel h2 {
  font-size: clamp(1.5rem, 3.5vw, 2rem);
  margin: 0.3rem 0 0.8rem;
}

.book-panel .btn {
  margin-top: 0.4rem;
}

.book-recap {
  margin: 1.6rem 0 1.2rem;
  padding-top: 1.2rem;
  border-top: 1px solid rgba(33, 28, 21, 0.07);
  display: grid;
  grid-template-columns: max-content 1fr;
  gap: 0.6rem 1.4rem;
  font-size: 0.95rem;
}

.book-recap dt {
  color: var(--muted);
  font-size: 0.875rem;
}

.book-recap dd {
  margin: 0;
  color: var(--text);
  white-space: pre-wrap;
}

.error-text {
  margin: 0;
  color: #b4462f;
  font-size: 0.95rem;
}

.buy-note,
.share-foot {
  margin: 0;
  font-size: 0.875rem;
}

.share-foot {
  margin-top: 1.3rem;
}

/* ==========================================================================
   Responsive
   ========================================================================== */
@media (max-width: 900px) {
  .product {
    grid-template-columns: 1fr;
  }
  .product-figure {
    order: -1;
    max-width: 440px;
    margin: 0 auto;
  }
  .cards,
  .access .cards {
    grid-template-columns: 1fr;
  }
  /* A stack of tiles with staggered delays reads as a slow drip on a phone,
     where they arrive one screen at a time anyway. */
  .stagger > * {
    transition-delay: 0s;
  }
  .book-row {
    grid-template-columns: 1fr;
  }
  .book-recap {
    grid-template-columns: 1fr;
    gap: 0.2rem;
  }
  .book-recap dd {
    margin-bottom: 0.7rem;
  }
  .site-footer .wrap {
    grid-template-columns: 1fr 1fr;
  }
  .site-footer .tagline {
    grid-column: 1 / -1;
  }
}

/* 860px, not a phone width: between here and 900px the brand, five links and two
   buttons no longer fit on one 54px line, and the row would wrap raggedly before
   any phone breakpoint caught it. */
@media (max-width: 860px) {
  /* Stacked, the bar runs to three rows — sticky, that is a fifth of a phone
     screen permanently spent on chrome. It scrolls away here instead. */
  .site-header {
    position: static;
  }
  /* The nav links become a single scrollable row under the brand rather than
     disappearing, which is what the old layout did — on a phone the whole site
     map vanished and only the two buttons remained. */
  .site-header .wrap {
    flex-wrap: wrap;
    gap: 0.6rem 1rem;
    padding-top: 0.7rem;
    padding-bottom: 0.7rem;
  }
  .nav {
    width: 100%;
    flex-direction: column;
    align-items: stretch;
    gap: 0.7rem;
  }
  /* Links above the buttons: navigation should come before the two sign-in
     calls to action, not under them. */
  .nav .links {
    order: 1;
    overflow-x: auto;
    gap: 1.35rem;
    padding-bottom: 0.15rem;
    /* Hide the scrollbar but keep the scrolling: a visible bar under four words
       looks like a rendering fault. */
    scrollbar-width: none;
  }
  .nav .links::-webkit-scrollbar {
    display: none;
  }
  .nav .links a {
    white-space: nowrap;
    font-size: 0.8125rem;
  }
  .nav .actions {
    order: 2;
    width: 100%;
  }
  .nav .actions .btn {
    flex: 1;
  }
  .cta-row {
    gap: 1rem;
  }
  .hero .cta-row .btn {
    width: 100%;
  }
  .site-footer .wrap {
    grid-template-columns: 1fr;
    gap: 2rem;
  }
}

/* ==========================================================================
   Online shop (/shop) — markup generated by shop.js
   ========================================================================== */

/* For labels that a sighted visitor gets from context (the size picker sits
   under the product name) but a screen reader still needs. */
.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
  border: 0;
}

.shop-page {
  padding: clamp(2.5rem, 6vw, 4.5rem) 0 clamp(4rem, 8vw, 6rem);
  background: var(--cream);
}

.shop-head h1 {
  font-size: clamp(2.2rem, 5vw, 3.4rem);
}

/* Products on the left, the bag pinned beside them. The bag is sticky so the
   running total stays in view while browsing a long shop. */
.shop-layout {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 340px;
  gap: clamp(1.5rem, 3vw, 2.5rem);
  align-items: start;
}

/* A <section>, so it would otherwise inherit the page-section padding. */
.shop-grid {
  padding: 0;
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(230px, 1fr));
  gap: 1.25rem;
}

.shop-status,
.shop-empty {
  grid-column: 1 / -1;
}

.shop-card {
  display: flex;
  flex-direction: column;
  background: var(--paper);
  border-radius: var(--r-card);
  overflow: hidden;
  box-shadow: var(--shadow-soft);
  color: inherit;
  transition: box-shadow 0.3s var(--ease-out), transform 0.3s var(--ease-out);
}

/* The whole card is the link to the item's page. */
.shop-card:hover {
  color: inherit;
  box-shadow: var(--shadow-lift);
  transform: translateY(-2px);
}

.shop-card:focus-visible {
  outline: 2px solid var(--gold);
  outline-offset: 3px;
}

/* .shop-grid sets display: grid, which beats the UA's [hidden] rule — the same
   trap as .book-form above. The grid is hidden on an item's own page. */
.shop-grid[hidden],
.shop-detail[hidden] {
  display: none;
}

.shop-flag {
  margin: 0;
  font-size: 0.85rem;
  color: #8f3625;
}

.shop-media {
  aspect-ratio: 1 / 1;
  background: var(--sand);
  display: grid;
  place-items: center;
}

.shop-media img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* No photo yet: the monogram, small and faint, rather than a broken box. */
.shop-media img.shop-placeholder {
  width: 34%;
  height: auto;
  object-fit: contain;
  opacity: 0.45;
}

.shop-body {
  display: flex;
  flex-direction: column;
  gap: 0.55rem;
  padding: 1.2rem 1.25rem 1.35rem;
  flex: 1;
}

.shop-body h3 {
  font-size: 1.2rem;
  letter-spacing: -0.02em;
}

.shop-price {
  margin: 0;
  font-weight: 600;
  color: var(--ink);
}

.shop-desc {
  margin: 0;
  color: var(--muted);
  font-size: 0.95rem;
  line-height: 1.45;
  white-space: pre-line;
}

.shop-body .notes {
  justify-content: flex-start;
  margin: 0.1rem 0 0;
}

.shop-body .note-chip {
  font-size: 0.8rem;
  padding: 0.25rem 0.65rem;
}

/* --- One item's page (/shop/<id>) --- */
.shop-detail {
  padding: 0;
}

.link-back {
  display: inline-block;
  margin-bottom: 1.2rem;
  font-size: 0.95rem;
}

.link-back::before {
  content: "‹ ";
}

.shop-detail-grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: clamp(1.5rem, 3vw, 2.5rem);
  align-items: start;
}

.shop-detail-media {
  border-radius: var(--r-media);
  overflow: hidden;
  box-shadow: var(--shadow-soft);
}

.shop-detail-copy {
  display: flex;
  flex-direction: column;
  gap: 0.9rem;
}

.shop-detail-copy h1 {
  font-size: clamp(1.9rem, 4vw, 2.6rem);
}

.shop-detail-price {
  margin: 0;
  font-size: 1.35rem;
  font-weight: 600;
  letter-spacing: -0.02em;
  color: var(--ink);
}

.shop-detail-copy .notes {
  justify-content: flex-start;
  margin: 0;
}

.shop-detail-copy .notes-label,
.shop-detail-copy .portal-note {
  margin: 0;
}

.shop-sizes {
  border: 0;
  padding: 0;
  margin: 0.4rem 0 0;
  min-width: 0;
}

.shop-sizes legend {
  padding: 0;
}

.shop-buy {
  display: flex;
  gap: 0.9rem;
  align-items: center;
}

.shop-buy .btn {
  flex: 1;
  border-radius: var(--r-input);
}

.shop-buy .btn[disabled] {
  opacity: 0.55;
  cursor: not-allowed;
}

.shop-added {
  margin: 0;
  min-height: 1.4em;
  font-size: 0.95rem;
}

/* --- Bag --- */
.bag {
  position: sticky;
  top: 4.5rem;
  background: var(--paper);
  border-radius: var(--r-card);
  box-shadow: var(--shadow-soft);
  padding: 1.5rem;
  scroll-margin-top: 4.5rem;
}

.bag h2 {
  font-size: 1.35rem;
  margin-bottom: 1rem;
}

.bag-lines {
  list-style: none;
  margin: 0;
  padding: 0;
}

.bag-line {
  display: grid;
  grid-template-columns: 1fr auto auto;
  gap: 0.75rem;
  align-items: center;
  padding: 0.75rem 0;
  border-bottom: 1px solid rgba(33, 28, 21, 0.07);
}

.bag-line-name {
  display: flex;
  flex-direction: column;
  min-width: 0;
}

.bag-line-name strong {
  color: var(--ink);
  font-weight: 500;
  font-size: 0.95rem;
}

.bag-line-name .muted {
  font-size: 0.85rem;
}

.bag-qty {
  display: flex;
  align-items: center;
  gap: 0.45rem;
}

.bag-qty button {
  width: 1.9rem;
  height: 1.9rem;
  border-radius: 50%;
  border: 1px solid var(--line);
  background: var(--paper);
  color: var(--ink);
  font: inherit;
  line-height: 1;
  cursor: pointer;
}

.bag-qty button:hover:not([disabled]) {
  border-color: var(--gold);
}

.bag-qty button[disabled] {
  opacity: 0.4;
  cursor: default;
}

.bag-line-total {
  font-variant-numeric: tabular-nums;
  color: var(--ink);
}

.bag-totals {
  display: grid;
  grid-template-columns: 1fr auto;
  gap: 0.35rem 1rem;
  margin: 1rem 0 0;
  font-size: 0.95rem;
}

.bag-totals dt {
  color: var(--muted);
}

.bag-totals dd {
  margin: 0;
  text-align: right;
  font-variant-numeric: tabular-nums;
}

.bag-totals .bag-total {
  color: var(--ink);
  font-weight: 600;
  font-size: 1.05rem;
  padding-top: 0.35rem;
}

.bag-hint {
  font-size: 0.85rem;
  margin: 0.6rem 0 0;
}

.bag .buy-form {
  margin-top: 1.2rem;
}

.bag .portal-note {
  margin: 1.2rem 0 0;
}

@media (max-width: 900px) {
  .shop-layout,
  .shop-detail-grid {
    grid-template-columns: 1fr;
  }
  /* Stacked under the products: sticky would pin it over them. */
  .bag {
    position: static;
  }
}

@media (max-width: 520px) {
  .shop-grid {
    grid-template-columns: 1fr;
  }
}
