/* ============================================================
   Monarch Herbs — refreshed brand stylesheet
   Warm, handcrafted apothecary identity, polished & tidy.
   ============================================================ */

/* Fonts: all @font-face rules live in css/fonts.css (linked before this file on every page). */

/* ---------- Design tokens ---------- */
:root {
  /* Brand palette */
  --orange:        #db7a2a;   /* monarch wing */
  --orange-deep:   #b85f17;   /* hover / emphasis */
  --orange-soft:   #f3d9b9;   /* tints */
  --honey:         #e0a93b;   /* gold accents */
  --green-soft:    #aebb86;
  --sage:          #dde2c6;   /* pale section bg */
  --sage-2:        #eef0e0;
  --video-placeholder: #000;  /* video slot while playback/access resolves */
  --ink:           #38322a;   /* warm near-black text */
  --ink-soft:      #6f6657;
  --cream:         #f9f3e6;   /* page background */
  --cream-2:       #f4ecd9;
  --paper:         #fffdf8;   /* cards */
  --line:          #e6dcc6;   /* hairlines */
  --grey:          #837d72;   /* warm grey — disabled control text */
  --grey-soft:     #cfccc4;   /* warm grey tint — disabled control fill */

  /* Deep-pine band family — the dark "loud panel" ground (admin fulfilment
     band, announce bar, anything band-like). Alpha tints derive from these
     via rgb(from …) / color-mix — don't mint new literals. */
  --pine:          #4b5a2f;   /* band gradient start */
  --pine-deep:     #3c4a24;   /* band gradient end · pine ink on light grounds */
  --pine-cream:    #f4efdd;   /* body text on pine */
  --pine-bright:   #fdfaf0;   /* titles / hover text / light button on pine */
  --marigold:      #f0b268;   /* eyebrow/tag accent on dark grounds */

  /* Type */
  --display: "Fraunces", "Fraunces-fb", Georgia, "Times New Roman", serif;
  --body:    "Nunito Sans", "NunitoSans-fb", "Segoe UI", system-ui, sans-serif;
  --script:  "Caveat", "Caveat-fb", "Segoe Script", cursive;

  /* Spacing scale — 4px grid (2px at the low end). Reach for these for
     padding / gap / margin instead of raw px so spacing stays on one rhythm. */
  --space-1:  2px;
  --space-2:  4px;
  --space-3:  8px;
  --space-4: 12px;
  --space-5: 16px;
  --space-6: 24px;
  --space-8: 32px;

  /* Form */
  --radius:   16px;
  --radius-sm: 8px;
  --radius-lg: 24px;
  --shadow:   0 10px 30px -16px rgba(56, 42, 20, .35);
  --shadow-lg:0 24px 60px -28px rgba(56, 42, 20, .45);
  --shadow-soft:0 4px 12px -8px rgba(56, 42, 20, .18);   /* whisper lift — tiles inside an already-shadowed card */
  --shadow-pop:0 2px 8px rgba(56, 42, 20, .10), 0 18px 48px -12px rgba(56, 42, 20, .42);   /* floating popovers/menus — lifts on all sides */
  /* Detached overlays (toast) — contact + mid + ambient. Y offsets stay small and
     the ambient layer carries positive spread on purpose: the toast floats 24px off
     the viewport bottom, so a downward-biased shadow renders past the edge and gets
     clipped. The lift has to read on the sides and top, not below. */
  --shadow-float:0 2px 6px rgba(56, 42, 20, .22), 0 6px 22px -2px rgba(56, 42, 20, .32), 0 10px 46px 0 rgba(56, 42, 20, .26);
  --maxw: 1180px;
  --commerce-maxw: 1196px; /* 1100px content width plus the desktop side gutters */
  --gutter: clamp(16px, 4vw, 48px);

  /* Status / state tints — shared by admin pills/chips + inline states */
  --danger-solid:         #a23b2c;   /* the danger red — the whole family below derives from it */
  --status-danger-bg:     color-mix(in srgb, var(--danger-solid) 13%, var(--paper));   /* removed / cancelled / out-of-stock tint */
  --status-danger-border: color-mix(in srgb, var(--danger-solid) 32%, var(--paper));
  --status-danger-ink:    color-mix(in srgb, var(--danger-solid) 88%, #000);            /* deep red — pill / status text */
  --alarm-red:            #a80d18;   /* loud urgency accent — overdue / needs-action now; deep alarm red */
  --status-edit-bg:       #eef3df;   /* edit / processing green tint */
  --status-edit-border:   #d6e0b6;
  --status-new-bg:        #fbe9d4;   /* new / low-stock orange tint */
  --status-done-bg:       #e2efe2;   /* done / active / shipped green tint */
  --status-done-border:   #b9d8b9;
  --status-done-ink:      #2f6a3a;

  /* Focus ring — green at 15% */
  --ring:                 rgba(95,110,58,.15);
  --focus-ring:           0 0 0 3px var(--ring);   /* standard input/control focus shadow */
  --scrim:                rgba(42,37,32,.5);        /* modal/drawer overlay — wing-black at 50% */
}

/* ---------- Reset ---------- */
*, *::before, *::after { box-sizing: border-box; }
* { margin: 0; }
/* Reserve the vertical scrollbar's width even on pages that don't scroll, so the
   centered layout doesn't jump sideways when navigating between short + tall pages. */
html { scroll-behavior: smooth; -webkit-text-size-adjust: 100%; scrollbar-gutter: stable; }
body {
  font-family: var(--body);
  color: var(--ink);
  background: var(--cream);
  line-height: 1.65;
  font-size: 17px;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  overflow-x: hidden;
}
/* Full-height shell for a page whose whole content is one small card (/set-password).
   Without it the footer lands wherever the card ends and reads as a strip of links
   floating in the middle of the screen. <main> takes the slack so the card centres
   in the space that's left and the footer sits on the bottom edge.
   These pages never scroll, so the reserved gutter above is a bare stripe down the
   side with nothing in it — hand it back. Scoped to this shell only: it stays
   `stable` everywhere else, which is what keeps the layout from jumping sideways
   between a short page and a tall one. */
body.page-fill { min-height: 100dvh; display: flex; flex-direction: column; }
body.page-fill > main { flex: 1; display: flex; flex-direction: column; justify-content: center; }
html:has(> body.page-fill) { scrollbar-gutter: auto; }
img, svg { display: block; max-width: 100%; }
a { color: inherit; text-decoration: none; }
button { font-family: inherit; cursor: pointer; border: none; background: none; }
ul { list-style: none; padding: 0; }

/* ---------- Typography ---------- */
h1, h2, h3, h4 { font-family: var(--display); font-weight: 600; line-height: 1.12; color: var(--ink); letter-spacing: -.01em; }
h1 { font-size: clamp(2.4rem, 5.5vw, 4.2rem); }
h2 { font-size: clamp(1.9rem, 4vw, 3rem); }
h3 { font-size: clamp(1.3rem, 2.4vw, 1.7rem); }
p  { color: var(--ink-soft); }
.lead { font-size: 1.15rem; color: var(--ink-soft); }

.eyebrow {
  font-family: var(--script);
  font-size: 1.5rem;
  color: var(--orange);
  line-height: 1;
  display: inline-block;
}
.eyebrow--lg { font-size: 3rem; }
.kicker {
  font-family: var(--body);
  text-transform: uppercase;
  letter-spacing: .22em;
  font-size: .72rem;
  font-weight: 800;
  color: var(--pine);
}
.kicker--orange { color: var(--orange-deep); }

/* ---------- Layout helpers ---------- */
.wrap { width: 100%; max-width: var(--maxw); margin-inline: auto; padding-inline: var(--gutter); }
#checkoutWrap,
#cartPage { max-width: var(--commerce-maxw); }
.section { padding-block: clamp(48px, 8vw, 96px); position: relative; }
.section--tight { padding-block: clamp(32px, 5vw, 56px); }
.section-head { text-align: center; max-width: 640px; margin: 0 auto clamp(28px, 4vw, 48px); }
.section-head p { margin-top: 12px; }
.center { text-align: center; }
.stack > * + * { margin-top: 1rem; }

.bg-cream  { background: var(--cream); }
.bg-cream2 { background: var(--cream-2); }
.bg-sage   { background: var(--sage-2); }

/* Botanical watermark layer */
/* Sits ABOVE the section's content so the watermarks read as a layer laid over
   the page. z-index 3 clears every content layer below it: `.section > .wrap`
   (1), `.hero__copy` and `.hero__badge` (both 2) — at 2 it tied with the hero
   copy and lost on DOM order, which looked like the motif being clipped.
   Both motifs are also positioned fully inside the layer box — no negative
   offsets — so an ancestor's overflow can't crop them (.hero/.page-hero clip). */
.botanical {
  position: absolute; inset: 0; z-index: 3;
  pointer-events: none; opacity: .5;
  background-repeat: no-repeat;
  background-position: left 10px top 10px, right 14px bottom 10px;
  /* Sized by HEIGHT, not width: the motif is 220×300, so a width-based size
     renders ~1.36× that tall and a short section crops the bottom of it. The
     min() caps each motif at a share of the section's height, so it scales up
     to the fixed size where there's room and shrinks to fit where there isn't
     — it can never outgrow the layer box. */
  background-size: auto min(490px, 78%), auto min(545px, 86%);
}
.section > .wrap { position: relative; z-index: 1; }

/* ---------- Buttons ---------- */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: .55em;
  font-weight: 800; font-size: .95rem; letter-spacing: .01em;
  padding: .82em 1.5em; border-radius: 999px;
  /* Every variant carries the same (transparent) border, so a ghost button —
     the only one that colors it — is exactly the size of its primary sibling. */
  border: 1.5px solid transparent;
  transition: transform .18s ease, box-shadow .18s ease, background .18s ease, color .18s ease;
  white-space: nowrap;
  /* Pre-promote to a compositor layer so the hover translateY slides a pre-painted layer
     instead of re-rasterizing the label mid-move (text looked like it swelled/blurred). */
  will-change: transform;
}
.btn[hidden] { display: none; }  /* display:inline-flex above beats the UA [hidden]{display:none} — see reference_css_hidden_toggle */
.btn svg { width: 1.05em; height: 1.05em; }
/* Every other hover-lift element gets the same compositor-layer promotion as .btn, so the
   translateY slides a pre-painted layer instead of re-rasterizing text mid-move. */
.card, .cat-card, .product, .post, .article-embed--cta, .share-btn, .like-btn, .social a, .svc-row { will-change: transform; }
.btn--primary { background: var(--orange); color: #fff; box-shadow: 0 8px 20px -10px rgba(184, 95, 23, .8); }
.btn--primary:hover { background: var(--orange-deep); transform: translateY(-2px); box-shadow: 0 14px 26px -10px rgba(184, 95, 23, .8); }
.btn--green { background: var(--pine); color: #fff; }
.btn--green:hover { background: var(--pine-deep); transform: translateY(-2px); }
/* Disabled buttons (e.g. a sold-out Add to Basket) read greyed-out: no hover lift, no pointer. */
.btn:disabled, .btn:disabled:hover { background: var(--grey-soft); color: var(--grey); cursor: not-allowed; transform: none; box-shadow: none; }
.btn--ghost { background: transparent; color: var(--pine-deep); border-color: var(--green-soft); }
.btn--ghost:hover { background: var(--sage); border-color: var(--pine); transform: translateY(-2px); }
.btn--light { background: #fff; color: var(--ink); }
.btn--light:hover { transform: translateY(-2px); box-shadow: var(--shadow); }
/* Ghost for dark grounds (pine panels) — pale hairline + cream text. */
.btn--ghostlight { background: transparent; color: var(--pine-cream); border-color: rgb(from var(--pine-cream) r g b / .45); }
.btn--ghostlight:hover { background: rgb(from var(--pine-cream) r g b / .12); border-color: var(--pine-cream); transform: translateY(-2px); }
.btn--sm { padding: .6em 1.1em; font-size: .85rem; }
.btn--block { width: 100%; }
.link-arrow { font-weight: 800; color: var(--orange-deep); display: inline-flex; align-items: center; gap: .25em; }
.link-arrow:hover { color: var(--orange); }
.link-arrow::after { content: "→"; transition: transform .2s ease; }
.link-arrow:hover::after { transform: translateX(.15em); }
.link-back { display: inline-flex; align-items: center; gap: .45em; font-size: .88rem; font-weight: 700; color: var(--ink-soft); transition: color .15s; }
/* Sometimes a <button> (the account change-plan back) — shed the UA chrome.
   font-family only: the shorthand would wipe .link-back's size/weight. */
button.link-back { background: none; border: none; padding: 0; font-family: inherit; cursor: pointer; }
.link-back::before { content: "←"; transition: transform .2s; }
.link-back:hover { color: var(--orange-deep); }
.link-back:hover::before { transform: translateX(-3px); }
.link-back[hidden] { display: none; }

/* ---------- Load more (paged category grid / blog list) ----------
   No button at the foot of a grid gets reliably noticed — and colouring one
   loudly enough to fix that just clones the card's Add to Basket CTA. So the
   next batches load themselves as the foot comes into view (.load-more--auto:
   spinner instead of the button), and the button only returns once auto-loading
   has had its turn, so the footer stays reachable. */
.load-more { display: flex; flex-direction: column; align-items: center; gap: var(--space-4); padding-top: var(--space-3); }
.load-more[hidden] { display: none; }  /* display:flex above beats the UA [hidden]{display:none} — see reference_css_hidden_toggle */
.load-more__count { font-size: .85rem; color: var(--ink-soft); }
.load-more__count b { font-weight: 800; color: var(--ink); }
.load-more .btn { min-width: 300px; max-width: 100%; padding: 1em 2em; border-color: var(--pine); }
.load-more__spin { display: none; }
.load-more__spin .spinner { width: 26px; height: 26px; border-width: 2px; }
/* Auto phase — the spinner stands in for the button. */
.load-more--auto .load-more__spin { display: block; }
.load-more--auto .btn { display: none; }

/* ---------- Chrome space reservation (CLS) ----------
   The announce bar + header are injected into #siteHeader by site.js AFTER
   first paint, so without a reservation every page paints top-of-content and
   then jumps down by the chrome height (a huge layout shift on every nav).
   Reserve the rendered height up front: announce ~37px + header ~100px
   (brand type 75px + 24px padding + 1px border). min-height, so a few px of
   drift (font swap, wrapping) costs a sliver, not the full jump. The admin
   header is a different, shorter bar — excluded, it renders before paint
   matters there. ~740px is where the announce copy wraps to two lines.
   --mh-chrome-h is set pre-paint by js/chrome-boot.js from the height
   measured on the previous page view (exact, per-device); the px values here
   are only the first-visit fallback. */
body:not([data-page="admin"]) #siteHeader { min-height: var(--mh-chrome-h, 137px); }
@media (max-width: 740px) {
  body:not([data-page="admin"]) #siteHeader { min-height: var(--mh-chrome-h, 156px); }
}

/* Catalog-driven grids fill in after the data lands — hold two card rows of
   space while empty so below content doesn't leap up the page on first visit
   (repeat visits render instantly from the localStorage catalog snapshot). */
.grid--3:empty, .grid--4:empty { min-height: 340px; }

/* ---------- Announcement bar ---------- */
.announce {
  background: var(--pine-deep); color: var(--pine-cream);
  text-align: center; font-size: .85rem; font-weight: 700;
  letter-spacing: .03em; padding: 9px 16px;
}
.announce b { color: var(--honey); }
.announce__mark { display: inline-block; vertical-align: -4px; margin-right: 2px; border-radius: 50%; }

/* ---------- Header ---------- */
.site-header { position: sticky; top: 0; z-index: 60; background: var(--cream); border-bottom: 1px solid var(--line); }
.header-inner { display: grid; grid-template-columns: 1fr auto 1fr; align-items: center; gap: 18px; padding-block: 12px; }
.brand { display: inline-flex; align-items: center; gap: 12px; justify-self: center; }
.brand__mark { width: 54px; height: 54px; flex: none; }
.brand__type { display: flex; flex-direction: column; line-height: 1.1; gap: 0px; }
.brand__name { font-family: var(--display); font-weight: 600; font-size: 2.5rem; color: var(--pine-deep); letter-spacing: .01em; }
.brand__tag  { font-family: var(--script); color: var(--orange); font-size: 1.75rem; }

.header-tools { display: inline-flex; align-items: center; gap: 6px; justify-self: end; }
.icon-btn {
  width: 42px; height: 42px; border-radius: 50%;
  display: inline-grid; place-items: center; color: var(--ink);
  transition: background .15s, color .15s; position: relative;
}
.icon-btn:hover { background: var(--cream-2); color: var(--orange-deep); }
.icon-btn svg { width: 21px; height: 21px; }
.cart-count {
  position: absolute; top: 2px; right: 2px; background: var(--orange);
  color: #fff; font-size: .62rem; font-weight: 800; min-width: 17px; height: 17px;
  border-radius: 9px; display: grid; place-items: center; padding: 0 4px;
}
.header-search { justify-self: start; max-width: 300px; width: 100%; }
.search-field {
  display: flex; align-items: center; gap: 8px; width: 100%;
  background: var(--paper); border: 1px solid var(--line); border-radius: 999px;
  padding: 8px 14px; color: var(--ink-soft);
}
.search-field svg { width: 17px; height: 17px; flex: none; }
.search-field input { border: none; background: none; outline: none; width: 100%; font-size: .9rem; color: var(--ink); }

/* Search dropdown — a floating panel anchored under the active search field
   (position set inline by site.js from the field's rect). No full-screen scrim:
   it reads as a clean autocomplete, and an outside-click closes it. */
#searchOverlay { display: none; position: fixed; z-index: 1300; top: 0; left: 0; width: min(420px, 94vw); }
#searchOverlay.open { display: block; }
.search-results {
  background: var(--paper); border: 1px solid var(--line);
  border-radius: var(--radius); box-shadow: var(--shadow-pop);
  overflow: hidden;   /* clips the inner scroller + its scrollbar to the rounded corners */
}
/* The actual scroll port — a slim, on-brand scrollbar that the rounded outer clips. */
.search-scroll {
  max-height: min(70vh, 560px); overflow-y: auto;
  scrollbar-width: thin; scrollbar-color: var(--line) transparent;
}
.search-scroll::-webkit-scrollbar { width: 10px; }
.search-scroll::-webkit-scrollbar-track { background: transparent; }
.search-scroll::-webkit-scrollbar-thumb {
  background: var(--line); border-radius: 999px;
  border: 3px solid var(--paper);   /* inset the thumb so it reads slim */
}
.search-scroll::-webkit-scrollbar-thumb:hover { background: var(--ink-soft); }
.search-group__label {
  position: sticky; top: 0; z-index: 1;
  padding: 9px 16px 5px; background: var(--cream-2);
  font-size: .68rem; font-weight: 800; letter-spacing: .08em;
  text-transform: uppercase; color: var(--ink-soft);
}
.search-hit {
  display: flex; align-items: center; gap: 12px;
  padding: 10px 16px; text-decoration: none; color: var(--ink);
  border-top: 1px solid var(--line); transition: background .12s;
}
.search-group__label + .search-hit { border-top: none; }
.search-hit:hover, .search-hit:focus { background: var(--sage-2); }
.search-hit__thumb {
  flex: none; width: 40px; height: 40px; border-radius: var(--radius-sm);
  overflow: hidden; background: var(--cream-2); display: grid; place-items: center;
}
.search-hit__thumb img { width: 100%; height: 100%; object-fit: cover; }
.search-hit__thumb .ph { width: 100%; height: 100%; }
.search-hit__text { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.search-hit__name { font-weight: 700; font-size: .9rem; line-height: 1.2; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.search-hit__sub { font-size: .76rem; color: var(--ink-soft); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.search-hit--concern .search-hit__name, .search-hit--page .search-hit__name { color: var(--pine); }
.search-empty { padding: 20px 18px; color: var(--ink-soft); font-size: .9rem; }
.search-all {
  display: block; padding: 12px 16px; text-align: center;
  font-size: .82rem; font-weight: 700; color: var(--orange);
  text-decoration: none; border-top: 1px solid var(--line); background: var(--cream);
}
.search-all:hover { background: var(--cream-2); }

/* Nav row */
.site-nav { border-top: 1px solid var(--line); background: var(--cream); }
.nav-inner { display: flex; justify-content: center; gap: 4px; flex-wrap: wrap; }
.nav-link {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 13px 16px; font-weight: 700; font-size: .92rem; color: var(--ink);
  position: relative; transition: color .15s;
}
.nav-link:hover { color: var(--orange-deep); }
.nav-link[aria-current="page"] { color: var(--orange-deep); }
.nav-link[aria-current="page"]::after {
  content: ""; position: absolute; left: 16px; right: 16px; bottom: 6px;
  height: 2.5px; border-radius: 2px; background: var(--orange);
}
.nav-toggle { display: none; }

/* Auto-hiding phone header — the bar tucks away while you read down the page
   and slides back the instant you nudge up, so menu / search / basket are one
   small flick away anywhere on a long page instead of a trip to the top.

   Note the header's own `position: sticky` can't carry this: sticky is confined
   to the parent box, and #siteHeader is only as tall as the chrome, so the bar
   unsticks the moment the announce bar is scrolled past. Floating it mid-page
   means taking it out of the flow — hence .hdr-pin, and #siteHeader taking back
   the exact height the bar gave up so nothing under it moves at the swap.
   site.js (wireHeaderAutoHide) enters that state only while the bar is already
   scrolled off screen, and leaves it only at the one scroll position where
   fixed and in-flow put the bar in the same place, so neither edge jumps.

   Phones only: on a wide screen the bar never costs enough of the view to be
   worth hiding, so this media query alone decides where any of it applies —
   and a page whose script never ran is left exactly as it was. */
@media (max-width: 880px) {
  .site-header { transition: transform .28s ease; }
  body.hdr-pin .site-header { position: fixed; top: 0; left: 0; right: 0; box-shadow: var(--shadow); }
  body.hdr-pin #siteHeader { padding-bottom: var(--mh-hdr-h, 0px); }
  body.hdr-away .site-header { transform: translateY(-100%); }
}
@media (prefers-reduced-motion: reduce) {
  .site-header { transition: none; }   /* the bar still hides/returns, just without the slide */
}

/* ---------- Minimal chrome ----------
   body[data-chrome="minimal"], set in the served HTML on the pages a visitor is
   mid-payment on (checkout, checkout-services, invoice, set-password) and on the
   members' classroom pages (videos, video-category). The full
   chrome is still BUILT and cached — it's hidden here, never unbuilt, so the
   header's wired controls survive and MH.setChromeMode("") can hand it all back
   on the confirmation screen. Rationale in full: chromeMode in js/site.js.

   Everything a half-typed card form can leak through goes: the announce bar (a
   discount offer is a reason to leave and hunt for the code), search, nav, cart,
   account. The brand stays — and stays a link home, standard on real checkouts;
   trapping someone reads as a scam, which is not what to evoke while they type
   a card number. Specificity beats .nav-toggle's mobile media query on its own. */
body[data-chrome="minimal"] .announce,
body[data-chrome="minimal"] .site-nav,
body[data-chrome="minimal"] .header-search,
body[data-chrome="minimal"] .header-tools,
body[data-chrome="minimal"] .nav-toggle { display: none; }
/* .header-inner is a 1fr auto 1fr grid centring the brand between search and
   tools. With both gone, one column keeps the brand centred and nothing else
   needs to move. Static, not sticky: a brand bar shadowing a long form is just
   chrome taking up space (matches .site-header--admin). */
body[data-chrome="minimal"] .site-header { position: static; }
body[data-chrome="minimal"] .header-inner { grid-template-columns: 1fr; }

/* The minimal FOOTER lives down in the footer section, not here: it has to
   override .site-footer's pine ground at equal specificity, so it must come
   after it in source order. */

/* Payment landed and MH.setChromeMode("") handed the chrome back — the nav and
   footer would otherwise pop in hard over the confirmation. One-shot, `both` to
   hold the end state, and staggered so the bar above settles before the sitemap. */
body[data-chrome-restored] .announce,
body[data-chrome-restored] .site-nav,
body[data-chrome-restored] .header-search,
body[data-chrome-restored] .header-tools { animation: chromeIn .5s ease-out both; }
body[data-chrome-restored] .site-footer:not(.site-footer--minimal) { animation: chromeIn .5s ease-out .1s both; }
@keyframes chromeIn { from { opacity: 0; transform: translateY(-6px); } to { opacity: 1; transform: none; } }
@media (prefers-reduced-motion: reduce) {
  body[data-chrome-restored] .announce,
  body[data-chrome-restored] .site-nav,
  body[data-chrome-restored] .header-search,
  body[data-chrome-restored] .header-tools,
  body[data-chrome-restored] .site-footer:not(.site-footer--minimal) { animation: none; }
}

/* ---------- Hero ---------- */
.hero { position: relative; overflow: hidden; background: linear-gradient(180deg, var(--cream) 0%, var(--cream-2) 100%); }
.hero__grid { display: grid; grid-template-columns: 1.05fr .95fr; gap: clamp(24px, 5vw, 64px); align-items: center; padding-block: clamp(40px, 6vw, 80px); }
.hero__copy { position: relative; z-index: 2; }
.hero__copy h1 { margin: 10px 0 18px; }
.hero__actions { display: flex; gap: 14px; flex-wrap: wrap; margin-top: 28px; }
.hero__art { position: relative; }
.hero__card {
  background: var(--paper); border-radius: var(--radius-lg); box-shadow: var(--shadow-lg);
  padding: 18px; border: 1px solid var(--line);
}
.hero__card .ph { aspect-ratio: 4/5; border-radius: var(--radius); }
.hero__badge {
  position: absolute; bottom: -22px; left: -22px; background: var(--honey); color: var(--ink);
  border-radius: 50%; width: 116px; height: 116px; display: grid; place-content: center; text-align: center;
  font-family: var(--display); font-weight: 600; line-height: 1.05; box-shadow: var(--shadow);
  transform: rotate(-8deg); border: 3px solid #fff;
}
.hero__badge b { font-size: 1.7rem; display: block; }
.hero__badge span { font-size: .72rem; font-family: var(--body); font-weight: 800; text-transform: uppercase; letter-spacing: .08em; }

/* ---------- Placeholder "photo" tiles ---------- */
.ph { position: relative; overflow: hidden; background: var(--sage-2); display: grid; place-items: center; }
.ph svg { width: 56%; height: 56%; }
.ph--green  { background: linear-gradient(150deg, #e7ecd2, #cdd6ab); }
.ph--gold   { background: linear-gradient(150deg, #f6e9c8, #ecd49a); }
/* Neutral "no photo" placeholder — parchment tile + softened butterfly mark. */
.ph--brand  { background: linear-gradient(150deg, var(--cream), var(--cream-2)); }
.ph--brand svg { opacity: .55; }
/* Fills a .ph tile when a real product photo exists (mirrors .product__img). */
.ph__img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }

/* ---------- Free shipping ribbon ---------- */
.ribbon {
  display: inline-flex; flex-direction: column; align-items: center;
  background: var(--pine); color: #fff; padding: 14px 46px; position: relative;
  border-radius: 6px; box-shadow: var(--shadow);
}
.ribbon b { font-family: var(--display); font-size: 1.5rem; font-weight: 600; }
.ribbon span { font-size: .8rem; letter-spacing: .04em; opacity: .9; }
.ribbon::before, .ribbon::after {
  content: ""; position: absolute; top: 0; bottom: 0; width: 18px; background: var(--pine-deep);
}
.ribbon::before { left: -14px; clip-path: polygon(0 50%, 100% 0, 100% 100%); }
.ribbon::after  { right: -14px; clip-path: polygon(0 0, 100% 50%, 0 100%); }

/* ---------- Category / feature cards ---------- */
.grid { display: grid; gap: clamp(16px, 2.2vw, 26px); }
.grid--2 { grid-template-columns: repeat(2, 1fr); }
.grid--3 { grid-template-columns: repeat(3, 1fr); }
.grid--4 { grid-template-columns: repeat(4, 1fr); }
/* Card grid for narrower columns (the account wishlist): columns cap at the
   shop's own card width (~250px) instead of stretching to fill, so a saved
   product card reads the same size as it does while browsing. */
.grid--cards { grid-template-columns: repeat(auto-fill, minmax(200px, 250px)); }

.card {
  background: var(--paper); border: 1px solid var(--line); border-radius: var(--radius);
  overflow: hidden; transition: transform .2s ease, box-shadow .2s ease; height: 100%;
  display: flex; flex-direction: column;
}
/* .reveal restates transition on this element and drops box-shadow; restate at higher
   specificity so the entrance fade AND the hover shadow both animate (see .svc-row.reveal). */
.card.reveal { transition: opacity .6s ease, transform .6s ease, box-shadow .2s ease; }
.card:hover { transform: translateY(-4px); box-shadow: var(--shadow); }
.card__media { aspect-ratio: 1/1; position: relative; }
.card__body { padding: 16px 16px 18px; display: flex; flex-direction: column; gap: 6px; flex: 1; }
.card__title { font-family: var(--display); font-size: 1.12rem; font-weight: 600; }
.card__title a:hover { color: var(--orange-deep); }
.card__meta { font-size: .82rem; color: var(--ink-soft); }

/* Concern / category pill cards */
.cat-card {
  display: flex; align-items: center; gap: 14px; background: var(--paper);
  border: 1px solid var(--line); border-radius: var(--radius); padding: 14px 16px;
  transition: transform .18s, box-shadow .18s, border-color .18s;
}
/* .reveal restates transition on this element and drops box-shadow/border-color; restate at
   higher specificity so the entrance fade AND the hover shadow both animate (see .card.reveal). */
.cat-card.reveal { transition: opacity .6s ease, transform .6s ease, box-shadow .18s, border-color .18s; }
.cat-card:hover { transform: translateY(-3px); box-shadow: var(--shadow); border-color: var(--green-soft); }
/* Green-ringed circle icon, matching the home value-band cards. */
.cat-card__icon { width: 46px; height: 46px; border-radius: 50%; border: 1px solid var(--green-soft); display: grid; place-items: center; flex: none; color: var(--pine-deep); }
.cat-card__icon svg { width: 24px; height: 24px; }
.cat-card__t { font-weight: 800; font-size: .98rem; color: var(--ink); }

/* Home value strip — one continuous paper band, four cells split by soft
   hairlines, green-ringed icons. Static on purpose: no hover motion. */
.value-band {
  display: grid; grid-template-columns: repeat(4, 1fr);
  background: var(--paper); border: 1px solid var(--line);
  border-radius: var(--radius); overflow: hidden; box-shadow: var(--shadow);
}
.value-band li { display: flex; align-items: center; gap: 14px; padding: 20px 22px; }
.value-band li + li { border-left: 1px solid var(--line); }
.value-band__icon {
  width: 42px; height: 42px; border-radius: 50%; flex: none;
  border: 1px solid var(--green-soft);
  color: var(--pine-deep); display: grid; place-items: center;
}
.value-band__icon svg { width: 22px; height: 22px; }
.value-band__txt { display: flex; flex-direction: column; }
.value-band__t { font-weight: 700; font-size: .95rem; color: var(--ink); }
.value-band__s { font-size: .78rem; color: var(--ink-soft); }

/* ---------- Product cards ---------- */
.product { background: var(--paper); border: 1px solid var(--line); border-radius: var(--radius); overflow: hidden; display: flex; flex-direction: column; transition: transform .2s, box-shadow .2s; }
.product:hover { transform: translateY(-4px); box-shadow: var(--shadow); }
/* .reveal drops box-shadow from the transition; restate it (see .card.reveal). */
.product.reveal { transition: opacity .6s ease, transform .6s ease, box-shadow .2s; }
.product__media { aspect-ratio: 1/1; position: relative; }
.product__img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; object-position: center; background: var(--paper); }
.product__badge { position: absolute; top: 10px; left: 10px; background: var(--orange); color: #fff; font-size: .68rem; font-weight: 800; text-transform: uppercase; letter-spacing: .06em; padding: 4px 9px; border-radius: 999px; }
.product__age { position: absolute; bottom: 10px; left: 10px; background: var(--ink); color: #fff; font-size: .66rem; font-weight: 800; letter-spacing: .06em; padding: 4px 8px; border-radius: 999px; }
.product__fav { position: absolute; top: 8px; right: 8px; width: 34px; height: 34px; border-radius: 50%; background: rgba(255,255,255,.85); display: grid; place-items: center; color: var(--ink-soft); }
.product__fav:hover { color: var(--orange); }
.product__fav.is-saved { color: var(--orange); }
.product__fav.is-saved svg { fill: currentColor; }
.product__fav svg { width: 18px; height: 18px; }
.product__body { padding: 14px 14px 16px; display: flex; flex-direction: column; gap: 8px; flex: 1; }
.product__name { font-family: var(--display); font-size: 1.05rem; font-weight: 600; line-height: 1.25; }
.product__name a:hover { color: var(--orange-deep); }
.product__stars { color: var(--honey); font-size: .8rem; letter-spacing: 1px; }
.product__desc { font-size: .82rem; color: var(--ink-soft); line-height: 1.45; display: -webkit-box; -webkit-line-clamp: 2; line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
.product__price { font-weight: 800; color: var(--pine-deep); margin-top: auto; }
.product__price s { color: var(--ink-soft); font-weight: 600; margin-right: 6px; }
.product__stock { font-size: .76rem; font-weight: 800; color: var(--orange-deep); margin-top: 4px; }

/* ---------- Pricing (membership) ---------- */
.price-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 20px; align-items: stretch; }
.plan { background: var(--paper); border: 1px solid var(--line); border-radius: var(--radius-lg); padding: 26px; display: flex; flex-direction: column; gap: 14px; position: relative; }
.plan--featured { border: 2px solid var(--orange); box-shadow: var(--shadow); background: color-mix(in srgb, var(--orange-soft) 45%, var(--paper)); }
.plan__flag { position: absolute; top: -13px; left: 50%; transform: translateX(-50%); background: var(--orange); color: #fff; font-size: .68rem; font-weight: 800; text-transform: uppercase; letter-spacing: .08em; padding: 5px 14px; border-radius: 999px; }
.plan__name { font-family: var(--display); font-size: 1.35rem; font-weight: 600; line-height: 1.2; }
.plan__price { font-size: 2.6rem; font-family: var(--display); font-weight: 600; line-height: 1.05; color: var(--pine-deep); }
.plan__price small { font-size: .9rem; font-family: var(--body); color: var(--ink-soft); font-weight: 700; }
/* Two-plan variant — a centered pair instead of the 3-up grid. */
.price-grid--duo { grid-template-columns: repeat(2, minmax(0, 380px)); justify-content: center; }
/* Price + its billing note read as one unit — tighter than the card's own gap. */
.plan__cost { display: flex; flex-direction: column; gap: var(--space-3); }
.plan__sub { font-size: .78rem; line-height: 1.3; color: color-mix(in srgb, var(--ink-soft) 68%, var(--paper)); min-height: 1.3em; }
.plan__blurb { font-size: .95rem; color: var(--ink); }

/* ---------- Service rows (consults) ---------- */
/* One full-width row per service — photo on one side (--flip mirrors it),
   copy + price board + CTA on the other. */
.svc-row {
  display: grid; grid-template-columns: 400px 1fr; gap: clamp(22px, 4vw, 44px); align-items: center;
  background: var(--paper); border: 1px solid var(--line); border-radius: var(--radius-lg); padding: 22px;
  transition: transform .2s ease, box-shadow .2s ease;
}
/* .reveal (shared) sets its own transition on this same element and would drop box-shadow;
   restate it here at higher specificity so the entrance fade AND the hover shadow both animate. */
.svc-row.reveal { transition: opacity .6s ease, transform .6s ease, box-shadow .2s ease; }
.svc-row:hover { transform: translateY(-4px); box-shadow: var(--shadow); }
.svc-row--flip { grid-template-columns: 1fr 400px; }
.svc-row--flip .svc-row__ph { order: 2; }
.svc-row__ph { position: relative; aspect-ratio: 4/3; border-radius: var(--radius); overflow: hidden; background: var(--sage-2); }
.svc-row__ph img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
.svc-row__body { display: flex; flex-direction: column; align-items: flex-start; gap: 14px; padding: 10px 6px; }
.svc-row__body h3 { font-family: var(--display); font-weight: 600; font-size: clamp(1.4rem, 2.4vw, 1.7rem); }
.svc-row__body > p { color: var(--ink-soft); font-size: .97rem; max-width: 52ch; }
.svc-row__cta { display: flex; align-items: center; gap: 18px; flex-wrap: wrap; }
/* Prices — big display numerals over small-caps labels, framed by two quiet
   hairlines like a printed-menu section: menu info, deliberately nothing
   button-like. */
.svc-prices { display: flex; gap: clamp(28px, 3vw, 48px); align-self: stretch; max-width: 400px; border-top: 1px solid var(--line); border-bottom: 1px solid var(--line); padding: 12px 2px 14px; }
.svc-price { display: flex; flex-direction: column; gap: 3px; }
/* Vertical hairline between price stacks — padding matches the parent gap so the rule sits centered. */
.svc-price + .svc-price { border-left: 1px solid var(--line); padding-left: clamp(28px, 3vw, 48px); }
.svc-price small { font-size: .7rem; font-weight: 800; letter-spacing: .14em; text-transform: uppercase; color: var(--ink-soft); }
.svc-price b { font-family: var(--display); font-weight: 600; font-size: 1.9rem; color: var(--pine-deep); line-height: 1.05; }
.svc-price b small { font-family: var(--body); font-size: .85rem; font-weight: 700; letter-spacing: 0; text-transform: none; }
@media (max-width: 860px) {
  .svc-row, .svc-row--flip { grid-template-columns: 1fr; }
  .svc-row--flip .svc-row__ph { order: 0; }
}

/* ---------- Split / feature sections ---------- */
.split { display: grid; grid-template-columns: 1fr 1fr; gap: clamp(24px, 5vw, 60px); align-items: center; }
.split__media .ph { aspect-ratio: 4/3; border-radius: var(--radius-lg); box-shadow: var(--shadow); }
.feature-list { display: grid; gap: 16px; margin-top: 22px; }
.feature-list li { display: flex; gap: 14px; }
.feature-list .fi { width: 44px; height: 44px; border-radius: 12px; background: var(--orange-soft); color: var(--orange-deep); display: grid; place-items: center; flex: none; }
.feature-list .fi svg { width: 23px; height: 23px; }
.feature-list b { display: block; color: var(--ink); }
.feature-list p { margin: 0; font-size: .92rem; }
.feature-list--cols { grid-template-columns: repeat(2, 1fr); gap: 22px clamp(24px, 4vw, 48px); }

/* ---------- Consult detail template (/herbal-consultation, /custom-blends) ---------- */
/* Content column + sticky booking rail. Collapses to one column with .split at 880px. */
.section--detail { padding-block: clamp(10px, 2vw, 18px) clamp(48px, 6vw, 80px); }
.split--rail { grid-template-columns: minmax(0, 1fr) 384px; align-items: start; }
.detail__main { display: flex; flex-direction: column; gap: clamp(28px, 4vw, 40px); }
.dhead { display: flex; flex-direction: column; gap: 14px; }
.dhead__titles { display: flex; flex-direction: column; gap: 8px; }
.dhead h1 { font-size: clamp(2.1rem, 4.5vw, 3.1rem); }
.dhead .lead { font-size: 1.06rem; max-width: 56ch; }

/* Session / path panels — icon coin + fee + "includes" rows */
.sessions { display: flex; flex-direction: column; gap: 16px; }
.spanel { position: relative; display: flex; gap: 18px; align-items: flex-start; background: var(--paper); border: 1px solid var(--line); border-radius: var(--radius); padding: clamp(18px, 3vw, 26px); box-shadow: var(--shadow-soft); transition: transform .25s ease, box-shadow .25s ease, border-color .25s ease; }
.spanel:hover { transform: translateY(-3px); box-shadow: var(--shadow); border-color: var(--green-soft); }
/* .reveal drops box-shadow/border-color from the transition; restate them (see .card.reveal). */
.spanel.reveal { transition: opacity .6s ease, transform .6s ease, box-shadow .25s ease, border-color .25s ease; }
.spanel__coin { width: 54px; height: 54px; flex: none; border-radius: 50%; background: var(--sage-2); border: 1px solid var(--green-soft); display: grid; place-items: center; color: var(--pine-deep); }
.spanel__coin svg { width: 26px; height: 26px; }
.spanel__body { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 8px; }
.spanel__top { display: flex; align-items: baseline; gap: 12px; flex-wrap: wrap; }
.spanel__top h3 { font-size: 1.22rem; }
.spanel__fee { display: inline-flex; align-items: baseline; gap: 7px; white-space: nowrap; }
.spanel__price { font-family: var(--display); font-weight: 600; font-size: 1.25rem; color: var(--pine-deep); }
.spanel__mins { font-size: .8rem; font-weight: 700; color: var(--ink-soft); }
.spanel__desc { font-size: .95rem; color: var(--ink-soft); }
.spanel__incl { display: flex; flex-direction: column; gap: 6px; }
.spanel__incl li { display: flex; align-items: flex-start; gap: 9px; font-size: .88rem; color: var(--ink-soft); }
.spanel__incl svg { width: 15px; height: 15px; flex: none; margin-top: 5px; color: var(--pine); }
/* Static markup hydrates icons via <span data-ic>; promote the injected svg to a
   flex item of the row so the svg sizing rules above/below apply directly. */
.spanel__incl [data-ic], .book__sure [data-ic], .book__where [data-ic] { display: contents; }
/* Script annotation for the recommended starting point — special-case panels only */
.spanel__hint { position: absolute; top: -13px; right: 22px; font-family: var(--script); font-size: 1.25rem; font-weight: 600; color: var(--orange-deep); transform: rotate(-2deg); background: var(--cream); padding: 0 10px; border-radius: 999px; }

/* "Good to know" — handwritten fee note */
.gtk { display: flex; gap: 16px; align-items: flex-start; background: var(--orange-soft); border: 1px solid var(--orange); border-radius: var(--radius); padding: 16px 20px; }
.gtk__tag { font-family: var(--script); font-size: 1.35rem; font-weight: 600; color: var(--orange-deep); white-space: nowrap; transform: rotate(-3deg); line-height: 1.2; padding-top: 2px; }
.gtk p { font-size: .93rem; font-weight: 600; color: var(--orange-deep); }

/* Detail subsection — shared shell for the in-column blocks (how-it-works trail,
   what-to-expect). Head + content spaced by the parent gap. */
.dsub { display: flex; flex-direction: column; gap: 18px; scroll-margin-top: 110px; }
.dsub__head { display: flex; flex-direction: column; gap: 2px; }
.dsub__head h2 { font-size: clamp(1.45rem, 2.6vw, 1.85rem); }
.dsub__head .sub { font-size: .92rem; color: var(--ink-soft); }
/* feature-list owns a margin-top for its usual .split context; in here the gap owns it */
.dsub .feature-list { margin-top: 0; }

/* "How it works" — numbered trail with a dotted connector */
.trail__steps { display: grid; grid-template-columns: repeat(4, 1fr); gap: clamp(14px, 2vw, 22px); }
.tstep { position: relative; display: flex; flex-direction: column; gap: 9px; }
.tstep__no { width: 46px; height: 46px; border-radius: 50%; background: var(--paper); border: 1.5px solid var(--green-soft); display: grid; place-items: center; font-family: var(--script); font-size: 1.5rem; font-weight: 600; color: var(--pine-deep); box-shadow: var(--shadow-soft); }
.tstep:not(:last-child)::before { content: ""; position: absolute; top: 23px; left: 56px; right: -10px; border-top: 2px dotted var(--green-soft); }
.tstep__txt { display: flex; flex-direction: column; gap: 3px; }
.tstep__txt b { font-size: .95rem; }
.tstep__txt p { font-size: .85rem; color: var(--ink-soft); line-height: 1.5; }

/* Sticky booking rail — photo in a hand-drawn double frame, session picker, CTAs */
.book-rail { position: sticky; top: 110px; display: flex; flex-direction: column; gap: 16px; }
.book { display: flex; flex-direction: column; background: var(--paper); border: 1px solid var(--line); border-radius: var(--radius-lg); overflow: hidden; box-shadow: var(--shadow-lg); }
.book__photo { padding: 18px 18px 0; }
.book__arch { position: relative; border-radius: var(--radius); overflow: hidden; }
.book__arch img { width: 100%; aspect-ratio: 16/10; object-fit: cover; display: block; }
.book__arch::after { content: ""; position: absolute; inset: 8px; border: 1.5px solid rgba(253, 250, 240, .75); border-radius: calc(var(--radius) - 6px); pointer-events: none; }
.book__body { display: flex; flex-direction: column; gap: 14px; padding: 18px 22px 22px; }
.book__title { display: flex; flex-direction: column; gap: 2px; }
.book__title h3 { font-size: 1.3rem; }
.book__where { display: inline-flex; align-items: center; gap: 7px; font-size: .84rem; color: var(--ink-soft); }
.book__where svg { width: 15px; height: 15px; flex: none; color: var(--pine); }
.book__ctas { display: flex; flex-direction: column; gap: 9px; }
.book__sure { display: flex; flex-direction: column; gap: 6px; }
.book__sure li { display: flex; align-items: center; gap: 9px; font-size: .82rem; color: var(--ink-soft); }
.book__sure svg { width: 15px; height: 15px; flex: none; color: var(--pine); }

/* Session picker — radio rows; the primary CTA follows the selection.
   Interactive rows are <button role="radio">; a lone informational row is a div
   (no hover lift, default cursor). */
.pick { display: flex; flex-direction: column; gap: 9px; }
.pick__opt { display: flex; align-items: center; gap: 12px; text-align: left; width: 100%; background: var(--cream); border: 1.5px solid var(--line); border-radius: var(--radius); padding: 12px 15px; font-family: var(--body); transition: border-color .2s ease, background .2s ease, transform .2s ease; }
button.pick__opt { cursor: pointer; }
button.pick__opt:hover { transform: translateY(-1px); border-color: var(--green-soft); }
.pick__opt[aria-checked="true"] { background: var(--sage-2); border-color: var(--pine); }
.pick__dot { width: 19px; height: 19px; flex: none; border-radius: 50%; border: 2px solid var(--green-soft); background: var(--paper); display: grid; place-items: center; transition: border-color .2s ease; }
.pick__dot::after { content: ""; width: 9px; height: 9px; border-radius: 50%; background: var(--pine-deep); transform: scale(0); transition: transform .2s ease; }
.pick__opt[aria-checked="true"] .pick__dot { border-color: var(--pine-deep); }
.pick__opt[aria-checked="true"] .pick__dot::after { transform: scale(1); }
.pick__info { flex: 1; min-width: 0; display: flex; flex-direction: column; }
.pick__name { font-weight: 800; font-size: .94rem; color: var(--ink); }
.pick__mins { font-size: .78rem; color: var(--ink-soft); }
.pick__price { font-family: var(--display); font-weight: 600; font-size: 1.18rem; color: var(--pine-deep); white-space: nowrap; }

@media (max-width: 880px) {
  .book-rail { position: static; }
  .trail__steps { grid-template-columns: 1fr 1fr; }
  /* In the 2-up grid the row-end connector would point off-grid at the wrapped row. */
  .tstep:nth-child(even)::before { display: none; }
}

/* ---------- Page hero (interior) ---------- */
.page-hero { position: relative; overflow: hidden; background: var(--pine-deep); color: #f3efe0; text-align: center; padding-block: clamp(46px, 7vw, 84px); }
.page-hero h1 { color: #fff; margin-bottom: 12px; }
.page-hero p { color: #dfe3cc; max-width: 620px; margin-inline: auto; }
.page-hero .eyebrow { color: var(--honey); }
.page-hero .botanical { opacity: .14; }
.crumbs { font-size: .82rem; color: var(--ink-soft); display: flex; gap: 8px; align-items: center; padding-block: 14px; }
.crumbs a:hover { color: var(--orange-deep); }
.crumbs span { opacity: .5; }

/* ---------- Reviews ---------- */
.review { background: var(--paper); border: 1px solid var(--line); border-radius: var(--radius); padding: 22px; height: 100%; display: flex; flex-direction: column; gap: 12px; }
.review__stars { color: var(--honey); letter-spacing: 2px; }
.review p { color: var(--ink); font-style: italic; }
.review__who { display: flex; align-items: center; gap: 10px; margin-top: auto; }
.review__av { width: 38px; height: 38px; border-radius: 50%; background: var(--sage); display: grid; place-items: center; font-weight: 800; color: var(--pine-deep); font-size: .85rem; }
.review__who b { font-size: .9rem; }
.review__who span { font-size: .78rem; color: var(--ink-soft); }

/* ---------- Video / responsive embed ---------- */
.embed { position: relative; aspect-ratio: 16/9; border-radius: var(--radius-lg); overflow: hidden; box-shadow: var(--shadow); background: var(--sage); }
.embed iframe { position: absolute; inset: 0; width: 100%; height: 100%; border: 0; }
.embed--square { aspect-ratio: 1/1; }
.embed--portrait { aspect-ratio: 9/16; }
.embed__cap { margin: 12px 2px 0; font-size: .85rem; color: var(--ink-soft); line-height: 1.5; }

/* ---------- Markets / locations ---------- */
.market { background: var(--paper); border: 1px solid var(--line); border-radius: var(--radius); overflow: hidden; }
.market__map { aspect-ratio: 16/9; background: linear-gradient(135deg, #e7ecd6, #d3dcb4); position: relative; display: grid; place-items: center; }
.market__map svg { width: 46px; height: 46px; color: var(--orange-deep); }
.market__map iframe { position: absolute; inset: 0; width: 100%; height: 100%; border: 0; z-index: 1; }
.market__map::after { content: ""; position: absolute; inset: 0; background-image: linear-gradient(rgba(95,110,58,.12) 1px, transparent 1px), linear-gradient(90deg, rgba(95,110,58,.12) 1px, transparent 1px); background-size: 26px 26px; }
.market__body { padding: 18px 20px 20px; }
.market__day { font-family: var(--script); color: var(--orange); font-size: 1.4rem; }
.market__hours { display: flex; align-items: center; gap: 6px; font-size: .88rem; color: var(--orange); font-weight: 700; margin: 6px 0 0; }
.market__hours svg { width: 15px; height: 15px; flex: none; }
.market__name { font-family: var(--display); font-size: 1.3rem; font-weight: 600; }
.market__addr { font-size: .88rem; color: var(--ink-soft); margin: 6px 0 8px; }
.market__desc { font-size: .9rem; color: var(--ink); line-height: 1.5; margin: 0 0 12px; }
.markets-note { max-width: 760px; margin: 30px auto 0; text-align: center; font-size: .92rem; color: var(--ink-soft); line-height: 1.6; }

/* ---------- Careers / "Come work with us" (careers.html) ----------
   Page-scoped, like .market above. The left column is the posting (facts +
   duties + the market shifts), the right is .apply-form. Everything here spaces
   with gap on a shared parent — the only margins are .field's own (the form
   convention) and the divider-ish rules that own their air. */
/* The posting reads fine narrow; the form carries paired fields and needs the
   room, so it takes the larger share instead of .split's default 1fr 1fr.
   Collapses to one column with .split at 880px. */
.split--apply { grid-template-columns: 5fr 7fr; }
.job-col { display: flex; flex-direction: column; gap: var(--space-6); }
.job-col__intro { display: flex; flex-direction: column; gap: var(--space-3); }
.job-col__intro h2 { margin: 0; }
.job-col__body { display: flex; flex-direction: column; gap: var(--space-4); }
.job-col__body p { margin: 0; font-size: .95rem; line-height: 1.65; color: var(--ink); }
.job-facts__sub { color: var(--ink-soft); font-size: .88rem; }

.job-markets { display: flex; flex-direction: column; gap: var(--space-5); padding: 22px; background: var(--sage-2); }
.job-markets__head { font-family: var(--display); font-size: 1.2rem; margin: 0; }
.job-markets__list { display: flex; flex-direction: column; gap: var(--space-5); }
.job-market { display: flex; flex-direction: column; gap: var(--space-1); }
.job-market__day { font-family: var(--script); color: var(--orange); font-size: 1.3rem; font-weight: 600; }
.job-market__name { font-family: var(--display); font-size: 1.02rem; font-weight: 600; color: var(--ink); }
.job-market__addr { font-size: .86rem; color: var(--ink-soft); }
.job-market__hours { font-size: .86rem; color: var(--ink); }
.job-market__hours b { color: var(--orange-deep); }

/* The form is one gap column end to end (heading → fields → checks → button),
   so .field's own bottom margin is zeroed and every gap is owned by a parent —
   the same shape as .co-form/.co-fields on the checkout form. */
.apply-form { display: flex; flex-direction: column; gap: var(--space-6); }
.apply-form .field { margin-bottom: 0; }
.apply-form__fields { display: flex; flex-direction: column; gap: var(--space-4); }
.apply-form__head { font-family: var(--display); margin: 0; }
.apply-form .grid--2 { gap: var(--space-4); }
.apply-form__checks { display: flex; flex-direction: column; gap: var(--space-3); }
/* The check-card title is a lone label here (no description line under it), so
   it reads as one row rather than the block heading the shared class assumes. */
.apply-form__checks .check-card__text b { display: inline; font-weight: 600; font-size: .9rem; color: var(--ink); }
/* Button + the one note under it, spaced by the parent's gap. The note starts
   as the red outstanding-requirements ask and fades to the quiet thank-you once
   the gate opens (syncApplyGate toggles .is-ok). */
.apply-form__send { display: flex; flex-direction: column; gap: var(--space-4); }
.apply-form__note { margin: 0; text-align: center; font-size: .84rem; color: var(--orange-deep); transition: color .25s ease; }
.apply-form__note.is-ok { color: var(--ink-soft); }
@media (max-width: 560px) {
  .apply-form .grid--2 { grid-template-columns: 1fr; }
}
/* Sent state — .apply-done replaces .apply-form in the same grid slot once the
   application posts, so both need the [hidden] guard: each sets its own
   display, which would otherwise beat the attribute and show both at once. */
.apply-form[hidden] { display: none; }
.apply-done { display: flex; flex-direction: column; align-items: center; text-align: center; gap: var(--space-5);
  animation: applyDoneIn .5s ease both; }
.apply-done[hidden] { display: none; }
.apply-done:focus { outline: none; }
.apply-done__mark { display: grid; place-items: center; width: 64px; height: 64px; border-radius: 50%;
  background: var(--sage-2); color: var(--pine); animation: applyDoneMark .45s .18s ease both; }
.apply-done__mark svg { width: 30px; height: 30px; }
.apply-done__copy { display: flex; flex-direction: column; gap: var(--space-3); }
.apply-done__head { font-family: var(--display); font-size: 1.5rem; margin: 0; }
.apply-done__body { margin: 0; font-size: .95rem; line-height: 1.65; color: var(--ink-soft); }
.apply-done__body b { color: var(--ink); font-weight: 600; }
@keyframes applyDoneIn { from { opacity: 0; transform: translateY(12px); } to { opacity: 1; transform: none; } }
@keyframes applyDoneMark { from { opacity: 0; transform: scale(.6); } to { opacity: 1; transform: none; } }
@media (prefers-reduced-motion: reduce) {
  .apply-done, .apply-done__mark { animation: none; }
}

/* ---------- Newsletter band ---------- */
.newsletter { background: var(--orange); color: #fff; border-radius: var(--radius-lg); padding: clamp(28px, 5vw, 52px); text-align: center; position: relative; overflow: hidden; }
.newsletter h2 { color: #fff; margin: 8px 0 6px; }
.newsletter p { color: #fff3e3; }
.newsletter .kicker { color: #fff3e3; }
/* justify-content only bites once the button wraps onto its own row (phones) —
   it centers there instead of hugging the left. On wider screens the input's
   flex:1 eats all the free space, so the row is unchanged. */
.newsletter form { display: flex; gap: 10px; max-width: 480px; margin: 22px auto 0; flex-wrap: wrap; justify-content: center; }
.newsletter input { flex: 1; min-width: 200px; border: none; border-radius: 999px; padding: 14px 20px; font-size: 1rem; }
.newsletter input:focus { outline: 3px solid rgba(255,255,255,.6); }

/* ---------- Forms ---------- */
/* min-width:0 lets a .field shrink inside a grid/flex row (e.g. the City/State/ZIP
   .account-row3 in the narrow add/edit modal) instead of forcing horizontal overflow. */
.field { display: flex; flex-direction: column; gap: 6px; margin-bottom: 16px; min-width: 0; }
.field[hidden] { display: none; }  /* display:flex above beats the UA [hidden]{display:none} — see reference_css_hidden_toggle */
.field label { font-weight: 700; font-size: .88rem; color: var(--ink); }
/* Required-field asterisk inside a label — <label>Email <span class="required">*</span></label>.
   Shared by the intake and careers forms; mark the star aria-hidden and put the
   real signal on the input's `required`/`aria-required`. */
.required { color: var(--orange-deep); }
.field input, .field textarea, .field select {
  border: 1px solid var(--line); border-radius: var(--radius-sm); padding: 12px 14px;
  font-family: inherit; font-size: 1rem; background: var(--paper); color: var(--ink);
}
/* Textareas default to resize:both, which lets the drag handle pull them wider than
   the field (breaking the layout) or shorter than their content. Constrain to vertical
   with a sensible floor, matching the basket note. */
.field textarea { resize: vertical; min-height: 120px; }
/* Native fallback only — JS (MH.enhanceSelects) skins this into .mh-select below.
   Arrow pinned to the right edge (was inset ~1.8cm, drifting into the middle). */
.field select {
  appearance: none; -webkit-appearance: none;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8'%3E%3Cpath d='M1 1l5 5 5-5' stroke='%23555' stroke-width='1.8' fill='none' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 15px center;
  padding-right: 42px;
}
.field input:focus, .field textarea:focus, .field select:focus { outline: none; border-color: var(--pine); box-shadow: var(--focus-ring); }
/* A value the form shows but can't change (the account email, a promo code —
   both name the record). Reads as settled, not as an empty box to type in. */
.field input[readonly], .field textarea[readonly] { background: var(--cream-2); color: var(--ink-soft); cursor: not-allowed; }
/* Chrome paints autofilled fields pale blue via an internal UA rule that `background`
   can't touch — the only lever is an opaque inset shadow flooding the field, plus
   text-fill-color for the ink. Focus repeats the ring first so autofill + focus keeps it.
   Chrome also renders the text in its own ~13px system font until the first click
   anywhere in the page clears the autofill state. That part is NOT fixable from CSS —
   specificity, `appearance: none` and `!important` on font-family/size were all tried
   and lost. Don't re-litigate it; the only "fix" is dropping our font in every field. */
.field input:-webkit-autofill,
.field input:-webkit-autofill:hover,
.field textarea:-webkit-autofill,
.field select:-webkit-autofill {
  box-shadow: inset 0 0 0 100px var(--paper);
  -webkit-text-fill-color: var(--ink); caret-color: var(--ink);
}
.field input:-webkit-autofill:focus,
.field textarea:-webkit-autofill:focus,
.field select:-webkit-autofill:focus { box-shadow: var(--focus-ring), inset 0 0 0 100px var(--paper); }
/* Floating-label fields (opt-in via .field-float on the form) — the label doubles
   as the placeholder, resting centered inside the input, then lifting + shrinking
   on focus or once the field has a value. Inputs carry placeholder=" " so
   :placeholder-shown reads "empty"; :has() lets the markup keep label-before-input. */
.field-float .field { position: relative; gap: 0; }
.field-float .field > label {
  position: absolute; left: 15px; top: 50%; transform: translateY(-50%);
  margin: 0; font-weight: 600; font-size: 1rem; color: var(--ink-soft);
  pointer-events: none; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  max-width: calc(100% - 30px);
  transition: top .16s ease, font-size .16s ease, color .16s ease, transform .16s ease;
}
.field-float .field > input, .field-float .field > textarea { padding: 23px 14px 8px; }
.field-float .field > input::placeholder, .field-float .field > textarea::placeholder { color: transparent; }
.field-float .field:focus-within > label,
.field-float .field:has(> input:not(:placeholder-shown)) > label,
/* Textarea's label stays permanently lifted (static top-left, never centered). */
.field-float .field:has(> textarea) > label,
/* A chosen state lifts the label; empty (placeholder row → --ph) rests centered. */
.field-float .field:has(.mh-select__label:not(.mh-select__label--ph)) > label {
  top: 8px; transform: none; font-size: .72rem; color: var(--pine);
}
/* Optional focus hint: a helper line that fades in only while the field is focused
   AND empty, sitting where the typed value goes (the lifted label names the field,
   this spells out what to enter). Once the user types, :placeholder-shown turns off
   and the hint hides. Add a <span class="field-float-hint"> after the input. */
.field-float .field > .field-float-hint {
  position: absolute; left: 15px; right: 14px; top: 22px; margin: 0;
  font-size: 1rem; font-weight: 600; color: var(--ink-soft);
  pointer-events: none; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  opacity: 0; transition: opacity .2s ease;
}
.field-float .field > input:focus:placeholder-shown ~ .field-float-hint { opacity: 1; transition-delay: .1s; }
/* Address state <select> (checkout / consultation / membership) is skinned into a
   .mh-select; make it a full-width form control instead of shrink-wrapping to its
   widest option (the site-wide default). Pre-enhance native select matches too. */
.field > .mh-select:has(select[data-states]),
.field > .mh-select:has(select[data-country]),
.field > select[data-states],
.field > select[data-country] { width: 100%; }
/* !important overrides the inline min-width JS sizes it to (widest option) so the
   control can shrink to a narrow 50/50 cell on phones; the open menu still matches
   the button, so a long option (District of Columbia) just wraps there when tight. */
.field > .mh-select:has(select[data-states]) .mh-select__btn,
.field > .mh-select:has(select[data-country]) .mh-select__btn { width: 100%; min-width: 0 !important; }
/* In a floating-label form the skinned control stands in for the tall input: match
   its padding, and reserve one line so the empty (placeholder="") button keeps the
   input's height — an empty label span would collapse it. The label lifts on select
   via the :has(.mh-select__label:not(--ph)) rule above. */
.field-float .field > .mh-select .mh-select__btn { padding: 23px 44px 8px 14px; line-height: 1.2; }
.field-float .field > .mh-select .mh-select__label { min-height: 1.2em; }
.field-float .field > select[data-states],
.field-float .field > select[data-country] { padding: 23px 44px 8px 14px; }
/* The skinned button is position:relative (a positioned box painted after the
   label in DOM order), so its opaque background hides the floating label — lift
   the label above it. It's pointer-events:none, so clicks still reach the button. */
.field-float .field:has(> .mh-select) > label,
.field-float .field:has(> select) > label { z-index: 1; }
.form-card { background: var(--paper); border: 1px solid var(--line); border-radius: var(--radius-lg); padding: clamp(22px, 4vw, 36px); box-shadow: var(--shadow); }
/* Inline form error box — hidden by default; callers reveal it via inline style.display
   (this rule only sets the default, so an inline display:block/"" override still shows it).
   Off-token pins: self-contained red error palette + 10px radius, intentionally off the brand scale. */
.form-error { display: none; background: #ffeaea; border: 1px solid #f5b7b7; border-radius: 10px; padding: 12px 16px; color: #c0392b; font-size: .92rem; }

/* ---------- Custom select (shared dropdown UI) ----------
   ONE apothecary-styled dropdown for every native <select> site-wide — skins
   BOTH the closed control (arrow pinned right) and the open menu, which native
   <option> lists can't be styled to do. Progressive enhancement in site.js
   (MH.enhanceSelects) wraps each <select>; the <select> stays in the DOM,
   visually hidden, as the source of truth (form value + real `change` events),
   so existing handlers keep working. Opt out with `data-native`.
   Sizing contract — ONE rule site-wide, no per-context width patches: the control
   shrink-wraps (fit-content beats both block-stretch and flex/grid stretch), JS
   pre-sizes the button (min-width) to the widest option AS THE MENU RENDERS IT,
   and the open menu always matches the button's width — so no option ever wraps
   and no control ever stretches to fill its container. A context that truly wants
   a full-width control pins width:100% on wrap + btn. */
.mh-select { position: relative; display: inline-flex; flex: none; width: fit-content; max-width: 100%; vertical-align: middle; }
.mh-select__native {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); clip-path: inset(50%);
  white-space: nowrap; border: 0; pointer-events: none;
}
.mh-select__btn {
  position: relative; display: block; width: auto; text-align: left;
  font: inherit; font-size: 1rem; line-height: 1.35;
  color: var(--ink); background: var(--paper);
  border: 1px solid var(--line); border-radius: var(--radius-sm);
  padding: 12px 44px 12px 14px;
  transition: border-color .15s, box-shadow .15s;
}
.mh-select__btn:hover { border-color: var(--green-soft); }
.mh-select__btn:focus-visible,
.mh-select.is-open .mh-select__btn {
  outline: none; border-color: var(--pine); box-shadow: var(--focus-ring);
}
.mh-select__label { display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.mh-select__label--ph { color: var(--ink-soft); }
.mh-select__chev {
  position: absolute; top: 50%; right: 15px; width: 12px; height: 8px; margin-top: -4px;
  color: var(--ink-soft); pointer-events: none; transition: transform .18s ease, color .15s;
}
.mh-select.is-open .mh-select__chev { transform: rotate(180deg); color: var(--pine); }
.mh-select__menu {
  position: absolute; z-index: 70; left: 0; right: 0; top: calc(100% + 6px);
  min-width: 100%; max-height: 300px; overflow-y: auto; padding: 6px;
  background: var(--paper); border: 1px solid var(--line); border-radius: var(--radius);
  box-shadow: var(--shadow-lg); animation: mh-select-pop .14s ease;
}
.mh-select--up .mh-select__menu { top: auto; bottom: calc(100% + 6px); }
/* On open the menu is portaled to <body> and viewport-pinned (JS sets left/top/width),
   so no ancestor's overflow-clip or stacking context (cards' will-change layers, scroll
   boxes, modals) can clip or bury it. z-index tops every overlay so a dropdown is always
   frontmost; min-width is reset because fixed resolves the base `min-width:100%` against
   the viewport, not the control. */
.mh-select__menu--portal { position: fixed; z-index: 1400; left: 0; right: auto; min-width: 0; }
.mh-select__menu[hidden] { display: none; }
@keyframes mh-select-pop { from { opacity: 0; transform: translateY(-5px); } to { opacity: 1; transform: none; } }
.mh-select__menu::-webkit-scrollbar { width: 10px; }
.mh-select__menu::-webkit-scrollbar-thumb { background: var(--line); border-radius: 999px; border: 3px solid var(--paper); }
.mh-select__group {
  padding: 9px 12px 4px; font-size: .7rem; font-weight: 800;
  text-transform: uppercase; letter-spacing: .07em; color: var(--ink-soft);
}
.mh-select__group:not(:first-child) { margin-top: 4px; border-top: 1px solid var(--line); padding-top: 10px; }
.mh-select__opt {
  display: flex; align-items: center; gap: 8px;
  padding: 10px 12px; border-radius: var(--radius-sm);
  font-size: .95rem; color: var(--ink); cursor: pointer; scroll-margin: 6px;
  white-space: nowrap; /* options stay on one line — the button is pre-sized to the widest */
}
.mh-select__opt.is-active { background: var(--cream-2); }
.mh-select__opt[aria-selected="true"] { color: var(--pine-deep); font-weight: 700; }
.mh-select__opt[aria-selected="true"]::after {
  content: ""; width: 15px; height: 15px; margin-left: auto; flex: none;
  background: no-repeat center / 15px url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 16 16'%3E%3Cpath d='M3 8.6l3.3 3.2L13 5' fill='none' stroke='%2341502a' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
}
.mh-select__opt[aria-disabled="true"] { color: var(--ink-soft); opacity: .55; cursor: not-allowed; }
.mh-select__opt[aria-disabled="true"].is-active { background: none; }

/* ---------- Blog ---------- */
.post { background: var(--paper); border: 1px solid var(--line); border-radius: var(--radius); overflow: hidden; display: flex; flex-direction: column; transition: transform .2s, box-shadow .2s; }
.post:hover { transform: translateY(-4px); box-shadow: var(--shadow); }
/* .reveal drops box-shadow from the transition; restate it (see .card.reveal). */
.post.reveal { transition: opacity .6s ease, transform .6s ease, box-shadow .2s; }
.post__media { aspect-ratio: 16/10; position: relative; }
.post__tag { position: absolute; top: 12px; left: 12px; background: rgba(255,253,248,.92); color: var(--pine-deep); font-size: .7rem; font-weight: 800; text-transform: uppercase; letter-spacing: .06em; padding: 4px 10px; border-radius: 999px; }
.post__body { padding: 18px 18px 20px; display: flex; flex-direction: column; gap: 8px; flex: 1; }
.post__date { font-size: .76rem; color: var(--ink-soft); text-transform: uppercase; letter-spacing: .08em; font-weight: 700; }
.post__title { font-family: var(--display); font-size: 1.25rem; font-weight: 600; line-height: 1.2; }
.post__title a:hover { color: var(--orange-deep); }
.post__img { width: 100%; height: 100%; object-fit: cover; display: block; }
.post__excerpt { font-size: .9rem; color: var(--ink-soft); line-height: 1.55; margin: 0; }
/* Featured hero media on the blog landing (a real cover photo or a tone panel) */
.split__media--feature { position: relative; display: block; aspect-ratio: 3/2; max-height: 320px; border-radius: var(--radius-lg); overflow: hidden; box-shadow: var(--shadow); }
.split__media--feature .ph { width: 100%; height: 100%; aspect-ratio: auto; border-radius: 0; box-shadow: none; }
.split__media--feature .post__img { position: absolute; inset: 0; }

/* ---------- Article (single Herbal Journal post) ---------- */
.article .wrap { max-width: 760px; }
.article__head { text-align: center; padding-top: 8px; }
.article__head h1 { font-size: clamp(2rem, 4.4vw, 3rem); line-height: 1.12; margin: 10px 0 14px; }
.article__meta { font-size: .82rem; color: var(--ink-soft); text-transform: uppercase; letter-spacing: .08em; font-weight: 700; }
.article__cover { max-width: 1000px; margin: clamp(24px, 4vw, 40px) auto; border-radius: var(--radius-lg); overflow: hidden; box-shadow: var(--shadow); }
.article__cover img { width: 100%; display: block; }
.article__cover--ph { aspect-ratio: 16/9; }
.article__cover--ph .ph { width: 100%; height: 100%; aspect-ratio: auto; border-radius: 0; box-shadow: none; }
.article__body { font-size: 1.08rem; line-height: 1.75; color: var(--ink); overflow-wrap: break-word; }
.article__body p { margin: 0 0 1.15em; }
.article__body h2 { font-family: var(--display); font-size: 1.5rem; font-weight: 600; margin: 1.6em 0 .5em; text-decoration: underline; text-underline-offset: 6px; }
.article__body h3 { font-family: var(--display); font-size: 1.2rem; font-weight: 600; margin: 1.4em 0 .4em; }
.article__body strong { font-weight: 800; color: var(--ink); }
.article__body a:not(.btn):not(.article-embed) { color: var(--orange-deep); text-decoration: underline; text-underline-offset: 2px; }
.article__body ul, .article__body ol { margin: 0 0 1.15em; padding-left: 1.3em; }
.article__body ul { list-style: disc; }
.article__body ol { list-style: decimal; }
.article__body li { margin: 0 0 .4em; }
.article__body img { max-width: 100%; }
.article-quote { margin: 0 0 1.15em; padding: .2em 0 .2em 1.1em; border-left: 3px solid var(--orange-soft); font-family: var(--display); font-style: italic; color: var(--ink-soft); }
.article-quote p { margin: 0 0 .5em; }
.article-quote p:last-child { margin-bottom: 0; }
.article__body code { font-family: ui-monospace, "SF Mono", Consolas, monospace; font-size: .92em; background: var(--cream-2); padding: .1em .4em; border-radius: 4px; }
.mh-c-orange { color: var(--orange-deep); }
.mh-c-green { color: var(--pine); }
.mh-hl-cream, .mh-hl-orange, .mh-hl-green { padding: .05em .3em; border-radius: 4px; }
.mh-hl-cream { background: var(--cream-2); }
.mh-hl-orange { background: var(--orange-soft); }
.mh-hl-green { background: var(--green-soft); }
/* Inline figure (an [[image:…]] shortcode) */
.article-figure { margin: 1.5em 0; }
.article-figure img { width: 100%; border-radius: var(--radius); display: block; box-shadow: var(--shadow), 0 -10px 30px -16px rgba(56, 42, 20, .35); }
.article-figure figcaption { margin-top: 8px; font-size: .85rem; color: var(--ink-soft); text-align: center; }
/* Inline data table (a | pipe | table) */
.article-table-wrap { overflow-x: auto; margin: 1.4em 0; }
.article-table { width: 100%; border-collapse: collapse; font-size: .96rem; }
.article-table th, .article-table td { text-align: left; padding: 9px 14px; border: 1px solid var(--line); }
.article-table th { background: var(--cream-2); font-weight: 700; }
/* Inline store embeds ([[product:…]] / [[membership]] / [[button:…]]) */
.article-embed { display: flex; align-items: center; gap: 16px; margin: 1.5em 0; padding: 14px; background: var(--paper); border: 1px solid var(--line); border-radius: var(--radius); box-shadow: var(--shadow); }
.article-embed__media { width: 88px; height: 88px; flex: none; border-radius: var(--radius-sm); overflow: hidden; background: var(--cream-2); display: block; }
.article-embed__media img, .article-embed__media .ph { width: 100%; height: 100%; object-fit: cover; aspect-ratio: auto; border-radius: 0; box-shadow: none; }
.article-embed__body { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 3px; }
.article-embed__name { font-family: var(--display); font-size: 1.15rem; font-weight: 600; line-height: 1.2; }
a.article-embed__name:hover { color: var(--orange-deep); }
.article-embed__blurb { font-size: .85rem; color: var(--ink-soft); line-height: 1.4; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
.article-embed__price { font-weight: 800; color: var(--pine-deep); }
.article-embed__cta { display: flex; flex-direction: column; gap: 8px; flex: none; }
/* CTA embed — a big centered pill button (the old Wix banner button, modernized) */
.article-embed--cta { width: fit-content; max-width: 100%; margin-inline: auto; justify-content: center; text-align: center; padding: 16px 38px; border-radius: 999px; background: var(--pine); border-color: var(--pine-deep); text-decoration: none; transition: background .18s ease, transform .18s ease, box-shadow .18s ease; }
.article-embed--cta:hover, .article-embed--cta:focus-visible { background: var(--pine-deep); transform: translateY(-2px); box-shadow: var(--shadow-lg); }
.article-embed__cta-label { font-weight: 700; font-size: 1.05rem; color: var(--cream); letter-spacing: .01em; }
.article-embed__cta-arrow { display: inline-block; transition: transform .18s ease; }
.article-embed--cta:hover .article-embed__cta-arrow { transform: translateX(4px); }
.article-embed--missing { display: block; color: var(--orange-deep); background: var(--status-new-bg); border-color: var(--orange-soft); box-shadow: none; font-size: .9rem; }
/* Booking / consultation card — reuses the product-embed frame + a duration row */
.article-embed__dur { display: inline-flex; align-items: center; gap: 5px; font-size: .9rem; color: var(--ink-soft); }
.article-embed__dur svg { width: 15px; height: 15px; color: var(--pine); }
.article-embed__media--ph { display: grid; place-items: center; color: var(--pine-deep); }
.article-embed__media--ph svg { width: 44%; height: 44%; }
@media (max-width: 560px) {
  .article-embed { flex-wrap: wrap; }
  .article-embed__cta { flex-direction: row; width: 100%; }
  .article-embed__cta .btn { flex: 1; }
}
.article__disclaimer { position: relative; margin: 30px 0 8px; padding: 16px 18px 16px 44px; background: var(--cream-2); border: 1px solid var(--green-soft); border-radius: var(--radius-sm); font-size: .88rem; color: var(--ink-soft); line-height: 1.6; }
.article__disclaimer::before { content: "✳"; position: absolute; left: 17px; top: 16px; color: var(--pine); font-size: 1rem; line-height: 1; }

/* ---------- Recipe card (blog post [[recipe:...]] embed) ---------- */
.recipe-card { margin: 1.8em 0; padding: 22px 24px; background: var(--paper); border: 1px solid var(--line); border-radius: var(--radius); box-shadow: var(--shadow); }
.recipe-card__title { font-family: var(--display); font-size: 1.4rem; font-weight: 600; margin-bottom: 8px; }
.recipe-card__meta { display: flex; flex-wrap: wrap; gap: 6px 18px; font-size: .88rem; color: var(--ink-soft); margin-bottom: 16px; }
.recipe-card__meta b { color: var(--ink); }
.recipe-card__cols { display: grid; grid-template-columns: 1fr 1.4fr; gap: 24px; }
.recipe-card__ingredients h4, .recipe-card__steps h4 { font-family: var(--display); font-size: 1rem; font-weight: 600; margin-bottom: 8px; color: var(--pine-deep); }
.recipe-card__ingredients ul { padding-left: 1.1em; margin: 0; }
.recipe-card__ingredients li { margin-bottom: 6px; font-size: .95rem; }
.recipe-card__steps ol { padding-left: 1.2em; margin: 0; }
.recipe-card__steps li { margin-bottom: 10px; font-size: .95rem; line-height: 1.55; }
.recipe-card__notes { margin-top: 16px; padding-top: 14px; border-top: 1px dashed var(--line); font-size: .88rem; color: var(--ink-soft); font-style: italic; }
.recipe-card__print { margin-top: 18px; }
@media (max-width: 640px) { .recipe-card__cols { grid-template-columns: 1fr; } }

/* Print — a shopper clicks "Print Recipe" and gets JUST the recipe, in plain
   black-on-white ink-friendly type, not the whole colored page. #recipePrintArea
   is populated at click time (see mount()) and only shown while body carries
   .printing-recipe (added right before window.print(), removed on afterprint). */
#recipePrintArea { display: none; }
@media print {
  body.printing-recipe > *:not(#recipePrintArea) { display: none !important; }
  #recipePrintArea { display: block !important; max-width: 100%; padding: 0; font-family: Georgia, "Times New Roman", serif; color: #000; background: #fff; }
  #recipePrintArea * { color: #000 !important; background: transparent !important; box-shadow: none !important; border-color: #000 !important; }
  .recipe-print__brand { font-size: .8rem; letter-spacing: .04em; text-transform: uppercase; margin-bottom: 14px; }
  #recipePrintArea .recipe-card__title { font-size: 1.6rem; }
  #recipePrintArea .recipe-card__cols { display: grid; grid-template-columns: 1fr 1.4fr; gap: 24px; }
}

/* Shared note callout (soft tinted fine-print box) */
.note { position: relative; padding: 13px 16px 13px 40px; background: var(--cream-2); border: 1px solid var(--green-soft); border-radius: var(--radius-sm); font-size: .92rem; color: var(--ink-soft); line-height: 1.6; }
.note--orange { background: var(--orange-soft); border-color: var(--orange); color: var(--orange-deep); font-weight: 600; }
.note--orange::before { color: var(--orange-deep); }

/* Article foot — tags, category, share + views/like (the old Wix post footer) */
.article__foot { margin-top: 34px; display: flex; flex-direction: column; gap: 14px; }
.article__tags { display: flex; flex-wrap: wrap; gap: 8px; }
.tag-chip { display: inline-block; padding: 5px 13px; font-size: .78rem; font-weight: 700; letter-spacing: .02em; color: var(--pine-deep); background: var(--sage-2); border: 1px solid var(--line); border-radius: 999px; }
.article__engage { display: flex; align-items: center; justify-content: space-between; gap: 12px; flex-wrap: wrap; border-top: 1px solid var(--line); padding-top: 14px; }
.article__cat { font-size: .85rem; color: var(--ink-soft); }
.article__cat a { font-weight: 800; color: var(--pine-deep); }
.article__cat a:hover { color: var(--orange-deep); text-decoration: underline; text-underline-offset: 3px; }
.article__share { display: flex; gap: 8px; }
.share-btn { width: 36px; height: 36px; border-radius: 50%; border: 1px solid var(--line); background: var(--paper); color: var(--ink-soft); display: grid; place-items: center; cursor: pointer; transition: color .18s ease, border-color .18s ease, background .18s ease, transform .18s ease; }
.share-btn svg { width: 16px; height: 16px; }
.share-btn:hover { color: var(--pine-deep); border-color: var(--green-soft); background: var(--sage-2); transform: translateY(-1px); }
.article__stats { display: flex; align-items: center; justify-content: space-between; gap: 12px; border-top: 1px solid var(--line); padding-top: 14px; }
.article__views { font-size: .85rem; color: var(--ink-soft); }
.like-btn { display: inline-flex; align-items: center; gap: 7px; padding: 7px 15px; border-radius: 999px; border: 1px solid var(--line); background: var(--paper); color: var(--ink-soft); font: inherit; font-size: .88rem; font-weight: 700; line-height: 1; cursor: pointer; transition: color .18s ease, border-color .18s ease, background .18s ease, transform .18s ease; }
.like-btn svg { width: 17px; height: 17px; display: block; }
.like-btn__count:empty { display: none; }   /* 0 likes = just the heart */
.like-btn:hover { color: var(--orange-deep); border-color: var(--orange-soft); transform: translateY(-1px); }
.like-btn.is-liked { color: var(--orange-deep); border-color: var(--orange-soft); background: var(--status-new-bg); }
.like-btn.is-liked svg { fill: var(--orange); stroke: var(--orange-deep); }

.article__missing { text-align: center; padding: clamp(40px, 8vw, 90px) 0; }
.article__missing h1 { margin-bottom: 12px; }
.article__missing p { color: var(--ink-soft); max-width: 460px; margin: 0 auto 22px; }

/* ---------- Shop "shop by" columns ---------- */
.shopby { display: grid; grid-template-columns: 1fr 1fr; gap: clamp(18px, 3vw, 36px); }
.shopby__col { background: var(--paper); border: 1px solid var(--line); border-radius: var(--radius-lg); padding: clamp(22px, 3vw, 34px); }
.shopby__col h3 { display: flex; align-items: center; gap: 12px; }
.shopby__col h3 .dot { width: 12px; height: 12px; border-radius: 50%; background: var(--orange); }
.shopby__col.is-green h3 .dot { background: var(--pine); }
.linklist { columns: 2; column-gap: 24px; }
.linklist li { break-inside: avoid; margin-bottom: 4px; }
.linklist a { display: block; padding: 7px 10px; border-radius: 8px; font-size: .92rem; font-weight: 600; color: var(--ink); transition: background .14s, color .14s; }
.linklist a:hover { background: var(--sage-2); color: var(--pine-deep); }

/* ---------- Single product ---------- */
.pdp { display: grid; grid-template-columns: 1.05fr 1fr; gap: clamp(28px, 5vw, 56px); align-items: start; }
.pdp__gallery .ph { aspect-ratio: 1/1; border-radius: var(--radius-lg); box-shadow: var(--shadow); }
/* real product photo — fits the whole image at its natural ratio (no square crop) */
.pdp__photo { border-radius: var(--radius-lg); overflow: hidden; box-shadow: var(--shadow); background: var(--paper); }
.pdp__photo img { display: block; width: 100%; height: auto; border-radius: inherit; }
/* main gallery slot showing an embedded video (the .embed frames itself) */
.pdp__video .embed { margin: 0; }
.pdp__thumbs { display: grid; grid-template-columns: repeat(4, 1fr); gap: 10px; margin-top: 12px; }
.pdp__thumbs .ph { aspect-ratio: 1/1; border-radius: var(--radius-sm); cursor: pointer; border: 2px solid transparent; }
.pdp__thumbs .ph.is-active { border-color: var(--orange); }
/* real-photo picker (only shown when a product has 2+ images) */
.pdp__thumbs--photos { display: flex; flex-wrap: wrap; }
.pdp__thumb { width: 74px; height: 74px; padding: 0; border: 2px solid transparent; border-radius: var(--radius-sm); overflow: hidden; cursor: pointer; background: var(--paper); box-shadow: var(--shadow); transition: border-color .15s; }
.pdp__thumb img { display: block; width: 100%; height: 100%; object-fit: cover; }
.pdp__thumb.is-active { border-color: var(--orange); }
.pdp__thumb:hover { border-color: var(--honey); }
/* video thumbnail — poster frame (when known) under a play badge; the green
   tile shows through as a fallback when there's no poster (e.g. Vimeo). */
.pdp__thumb--video { position: relative; background: var(--pine-deep); }
.pdp__play { position: absolute; inset: 0; margin: auto; width: 26px; height: 26px; display: grid; place-items: center;
  background: rgba(0, 0, 0, .55); color: #fff; border-radius: 50%; font-size: .66rem; padding-left: 2px; }
.pdp__price { font-size: 1.8rem; font-family: var(--display); font-weight: 600; color: var(--pine-deep); margin: 8px 0 4px; }
.pdp__price s { color: var(--ink-soft); font-weight: 400; }
.pdp__stock { font-size: .9rem; font-weight: 800; color: var(--orange-deep); margin: 2px 0 6px; }
.pdp__stock--out { color: var(--status-danger-ink); }
.pdp__row { display: flex; align-items: center; gap: 14px; flex-wrap: wrap; margin: 20px 0; }
.qty { display: inline-flex; align-items: center; border: 1px solid var(--line); border-radius: 999px; overflow: hidden; }
.qty button { width: 42px; height: 46px; font-size: 1.2rem; color: var(--ink); }
.qty button:not(:disabled):hover { background: var(--cream-2); color: var(--orange-deep); }
/* Override the UA button:disabled background (more specific than the base reset) so a
   disabled stepper button reads as muted, not a stray tan fill. */
.qty button:disabled { background: none; color: var(--line); cursor: default; }
.qty span { width: 42px; text-align: center; font-weight: 800; }
.pdp__list { display: grid; gap: 8px; margin-top: 10px; }
.pdp__list li { display: flex; gap: 10px; font-size: .92rem; }
.pdp__list svg { width: 18px; height: 18px; color: var(--pine); flex: none; margin-top: 3px; }
/* "About this remedy" — soft card under the gallery in the left column */
.pdp__about { margin-top: 22px; background: var(--sage-2); border: 1px solid var(--line); border-radius: var(--radius-lg); padding: 22px 26px; }
.pdp__about h2 { font-family: var(--display); font-size: clamp(1.35rem, 3vw, 1.8rem); font-weight: 600; line-height: 1.2; margin: 4px 0 10px; }
.pdp__about p { color: var(--ink-soft); line-height: 1.7; margin: 0 0 10px; }
.pdp__about p:last-child { margin-bottom: 0; }
/* Subscribe & Save — soft option tiles with nested frequency */
.buy-options { display: grid; gap: 10px; }
.buy-opt { display: flex; gap: 13px; align-items: flex-start; border: 1.5px solid var(--line); border-radius: var(--radius); padding: 14px 16px; cursor: pointer; background: var(--paper); transition: border-color .15s, background .15s, box-shadow .15s; }
.buy-opt:hover { border-color: var(--green-soft); }
.buy-opt.is-sel { border-color: var(--orange); background: #fdf3e6; box-shadow: 0 8px 22px -14px rgba(184,95,23,.7); }
.buy-opt__radio { width: 20px; height: 20px; border-radius: 50%; border: 2px solid var(--green-soft); flex: none; margin-top: 3px; display: grid; place-items: center; transition: border-color .15s; }
.buy-opt.is-sel .buy-opt__radio { border-color: var(--orange); }
.buy-opt.is-sel .buy-opt__radio::after { content: ""; width: 10px; height: 10px; border-radius: 50%; background: var(--orange); }
.buy-opt__main { flex: 1; display: flex; flex-direction: column; gap: 5px; }
.buy-opt__row { display: flex; align-items: baseline; justify-content: space-between; gap: 10px; }
.buy-opt__t { font-family: var(--display); font-weight: 600; font-size: 1.12rem; display: flex; align-items: center; gap: 9px; flex-wrap: wrap; }
.buy-opt__price { font-weight: 800; color: var(--pine-deep); font-size: 1.12rem; white-space: nowrap; }
.buy-opt__price s { color: var(--ink-soft); font-weight: 600; font-size: .82rem; margin-right: 5px; }
.buy-opt__sub { font-size: .85rem; color: var(--ink-soft); }
.save-pill { font-size: .64rem; font-weight: 800; text-transform: uppercase; letter-spacing: .06em; color: #fff; background: var(--pine); padding: 3px 9px 3px 7px; border-radius: 999px; display: inline-flex; align-items: center; gap: 4px; transform: translateY(-1px); }
.save-pill svg { width: 12px; height: 12px; }
.buy-opt__freq { margin-top: 10px; padding-top: 12px; border-top: 1px dashed #e7c9a3; display: flex; align-items: center; gap: 12px; flex-wrap: wrap; }
.buy-opt__freq[hidden] { display: none; }
.buy-opt__freq select { border: 1px solid var(--line); border-radius: var(--radius-sm); padding: 8px 12px; font-family: inherit; font-size: .9rem; background: var(--paper); color: var(--ink); cursor: pointer; }
.buy-opt__freq select:focus { outline: none; border-color: var(--pine); box-shadow: var(--focus-ring); }
.buy-opt__freq .freq-note { font-size: .8rem; color: var(--pine-deep); font-weight: 700; margin-left: auto; }
/* The frequency <select> is skinned into a .mh-select by MH.enhanceSelects. The
   "Deliver every …" phrasing lives in the options themselves, so the control and
   the "$/delivery" note share one line. Fixed 230px pill, with the note trailing
   it via margin-left. No max-width — MHSelect's measured min-width still wins if
   an option ever needs more than 230px, so options grow rather than clip. */
.buy-opt__freq .mh-select { flex: 0 0 auto; width: 230px; }
.buy-opt__freq .mh-select__btn { width: 100%; }

.accordion { border-top: 1px solid var(--line); margin-top: 26px; }
.accordion details { border-bottom: 1px solid var(--line); }
.accordion summary { padding: 16px 0; font-family: var(--display); font-size: 1.08rem; font-weight: 600; cursor: pointer; list-style: none; display: flex; justify-content: space-between; align-items: center; }
.accordion summary::-webkit-details-marker { display: none; }
.accordion summary::after { content: "+"; font-size: 1.4rem; color: var(--orange); }
.accordion details[open] summary::after { content: "–"; }
.accordion .acc-body { padding-bottom: 18px; }
.accordion .acc-body p { font-size: .95rem; }

/* ---------- Video Library — the library (videos.html) ----------
   Cream hero band + module cards. Each card: a photo spot (a .ph tile until
   modules get real photos), the module number, name, blurb, video count, and
   the category icon kept as a chip straddling the photo's bottom edge. */
.lib-hero { background: linear-gradient(180deg, var(--cream) 0%, var(--cream-2) 100%); border-bottom: 1px solid var(--line); }
.lib-hero .wrap { display: flex; flex-direction: column; align-items: flex-start; gap: var(--space-6); padding: var(--space-6) calc(var(--space-6) * 2); }
.lib-hero h1 { font-size: clamp(2rem, 4.2vw, 3rem); }
.lib-hero p { color: var(--ink-soft); max-width: 56ch; }

.mod-card { display: flex; flex-direction: column; background: var(--paper); border: 1px solid var(--line); border-radius: var(--radius-lg); overflow: hidden; transition: transform .18s ease, box-shadow .18s ease; }
/* .reveal drops box-shadow from the transition; restate it (see .card.reveal). */
.mod-card.reveal { transition: opacity .6s ease, transform .6s ease, box-shadow .18s ease; }
.mod-card:hover { transform: translateY(-4px); box-shadow: var(--shadow); }
/* Wraps the photo tile so the icon chip can hang past its bottom edge — the
   .ph tile itself clips at overflow:hidden. */
.mod-card__figure { position: relative; }
.mod-card__media { aspect-ratio: 16/9; }
.mod-card__media .ph-mark { display: flex; flex-direction: column; align-items: center; gap: var(--space-2); color: var(--pine-deep); opacity: .5; }
.mod-card__media .ph-mark svg { width: 30px; height: 30px; }
.mod-card__media .ph-mark span { font-size: .72rem; font-weight: 800; letter-spacing: .1em; text-transform: uppercase; }
.mod-card__num { position: absolute; z-index: 1; left: 14px; top: 14px; background: color-mix(in srgb, var(--paper) 94%, transparent); border: 1px solid var(--line); border-radius: 999px; padding: 4px 13px; font-size: .72rem; font-weight: 800; letter-spacing: .09em; text-transform: uppercase; color: var(--pine-deep); }
.mod-card__ic { position: absolute; right: 16px; bottom: -19px; z-index: 1; width: 44px; height: 44px; border-radius: 50%; background: var(--paper); border: 1px solid var(--green-soft); display: grid; place-items: center; color: var(--pine-deep); box-shadow: var(--shadow); transition: transform .18s ease; }
.mod-card__ic svg { width: 20px; height: 20px; }
.mod-card:hover .mod-card__ic { transform: rotate(-8deg) scale(1.06); }
.mod-card__body { flex: 1; display: flex; flex-direction: column; gap: var(--space-3); padding: var(--space-6); }
.mod-card__body h3 { font-size: 1.22rem; }
.mod-card__body p { font-size: .88rem; color: var(--ink-soft); flex: 1; }
.mod-card__meta { display: flex; align-items: center; justify-content: space-between; gap: var(--space-4); }
.mod-card__count { display: inline-flex; align-items: center; gap: var(--space-3); font-size: .8rem; font-weight: 800; color: var(--pine-deep); }
.mod-card__count svg { width: 13px; height: 13px; color: var(--orange); }
.mod-card__go { display: inline-flex; align-items: center; gap: .4em; font-size: .86rem; font-weight: 800; color: var(--orange-deep); transition: gap .15s ease; }
.mod-card:hover .mod-card__go { gap: .7em; }

/* ---------- Collective member hub (collective.html) ----------
   The members' home — one featured doorway into the Video Library plus a card
   per membership benefit. Sits between /account's membership tab and /videos. */
.hub { display: flex; flex-direction: column; gap: var(--space-6); }
.hub-head { display: flex; align-items: flex-end; justify-content: space-between; gap: var(--space-5); flex-wrap: wrap; }

/* Featured library card — copy beside a small collage of module thumbnails. */
.hub-lead { display: grid; grid-template-columns: 1.05fr .95fr; background: var(--paper); border: 1px solid var(--line); border-radius: var(--radius-lg); overflow: hidden; transition: transform .18s ease, box-shadow .18s ease; }
/* .reveal overwrites `transition` while animating in — restate the hover shadow
   alongside it or the lift snaps (see .mod-card.reveal). */
.hub-lead.reveal { transition: opacity .6s ease, transform .6s ease, box-shadow .18s ease; }
.hub-lead:hover { transform: translateY(-4px); box-shadow: var(--shadow); }
.hub-lead__body { display: flex; flex-direction: column; gap: var(--space-4); padding: clamp(24px, 3.4vw, 40px); }
.hub-lead__body p { font-size: .95rem; color: var(--ink-soft); flex: 1; max-width: 52ch; }
.hub-lead__meta { display: flex; align-items: center; justify-content: space-between; gap: var(--space-4); flex-wrap: wrap; }
.hub-lead__count { display: inline-flex; align-items: center; gap: var(--space-3); font-size: .8rem; font-weight: 800; color: var(--pine-deep); }
.hub-lead__count[hidden] { display: none; }
.hub-lead__count svg { width: 13px; height: 13px; color: var(--orange); }
.hub-lead__go { display: inline-flex; align-items: center; gap: .4em; font-size: .9rem; font-weight: 800; color: var(--orange-deep); transition: gap .15s ease; }
.hub-lead:hover .hub-lead__go { gap: .7em; }
.hub-lead__art { position: relative; display: grid; grid-template-columns: 1fr 1fr; gap: var(--space-1); background: var(--sage-2); border-left: 1px solid var(--line); min-height: 220px; }
.hub-lead__art img { width: 100%; height: 100%; object-fit: cover; }
.hub-lead__play { position: absolute; inset: 0; margin: auto; width: 54px; height: 54px; border-radius: 999px; background: color-mix(in srgb, var(--paper) 92%, transparent); border: 1px solid var(--green-soft); display: grid; place-items: center; color: var(--pine-deep); box-shadow: var(--shadow); transition: transform .18s ease; }
.hub-lead__play svg { width: 22px; height: 22px; }
.hub-lead:hover .hub-lead__play { transform: scale(1.08); }

/* One card per benefit. */
.hub-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--space-5); }
.hub-card { display: flex; flex-direction: column; gap: var(--space-4); background: var(--paper); border: 1px solid var(--line); border-radius: var(--radius-lg); padding: var(--space-6); transition: transform .18s ease, box-shadow .18s ease; }
.hub-card.reveal { transition: opacity .6s ease, transform .6s ease, box-shadow .18s ease; }
.hub-card:hover { transform: translateY(-3px); box-shadow: var(--shadow); }
.hub-card__top { display: flex; align-items: center; justify-content: space-between; gap: var(--space-4); }
.hub-card__dot { flex: none; width: 46px; height: 46px; border-radius: 999px; background: var(--sage-2); border: 1px solid var(--sage); display: grid; place-items: center; color: var(--pine-deep); transition: transform .18s ease; }
.hub-card__dot svg { width: 21px; height: 21px; }
.hub-card:hover .hub-card__dot { transform: rotate(-8deg) scale(1.06); }
.hub-card__txt { flex: 1; display: flex; flex-direction: column; gap: var(--space-3); }
.hub-card__txt h3 { font-size: 1.1rem; }
.hub-card__txt p { font-size: .88rem; color: var(--ink-soft); }
.hub-card__go { display: inline-flex; align-items: center; gap: .4em; font-size: .84rem; font-weight: 800; color: var(--orange-deep); transition: gap .15s ease; }
.hub-card__go:hover { gap: .7em; }
.hub-card__note { font-size: .8rem; font-weight: 700; color: var(--pine-deep); }

@media (max-width: 900px) { .hub-grid { grid-template-columns: 1fr 1fr; } }
@media (max-width: 720px) {
  .hub-lead { grid-template-columns: 1fr; }
  .hub-lead__art { min-height: 170px; border-left: 0; border-top: 1px solid var(--line); order: -1; }
}
@media (max-width: 560px) { .hub-grid { grid-template-columns: 1fr; } }

/* ---------- Video Library — the classroom (video-category.html) ----------
   One category page = one module: the player and the lesson body on the left,
   a rail listing every lesson in that module on the right. */

/* Head band — module title, at-a-glance meta, access note. */
.class-head { background: linear-gradient(180deg, var(--cream) 0%, var(--cream-2) 100%); border-bottom: 1px solid var(--line); }
.class-head .wrap { display: flex; flex-direction: column; gap: var(--space-4); padding-block: var(--space-6); }
.class-head .link-back { align-self: flex-start; }
.class-head__row { display: flex; align-items: flex-end; justify-content: space-between; gap: var(--space-5); flex-wrap: wrap; }
.class-head__intro { display: flex; flex-direction: column; gap: var(--space-3); }
.class-head h1 { font-size: clamp(1.7rem, 3.4vw, 2.4rem); }
.class-head__meta { display: flex; align-items: center; gap: var(--space-5); flex-wrap: wrap; font-size: .85rem; font-weight: 700; color: var(--ink-soft); }
.class-head__meta span { display: inline-flex; align-items: center; gap: var(--space-3); }
.class-head__meta svg { width: 15px; height: 15px; color: var(--orange); }

/* Whether this membership reaches the module. */
.tier-note { display: inline-flex; align-items: center; gap: var(--space-3); background: var(--sage-2); border: 1px solid var(--sage); border-radius: 999px; padding: 7px 16px; font-size: .8rem; font-weight: 700; color: var(--pine-deep); }
.tier-note svg { width: 14px; height: 14px; color: var(--pine); }
.tier-note[hidden] { display: none; }
/* Names the tier a locked lesson needs — only on lessons gated above the
   visitor's own tier, never on the lessons their plan already covers. */
.tier-chip { display: inline-flex; align-items: center; gap: var(--space-2); background: var(--paper); border: 1px solid var(--honey); border-radius: 999px; padding: 3px 12px; font-size: .72rem; font-weight: 800; color: var(--orange-deep); }

.classroom { display: grid; grid-template-columns: minmax(0, 1fr) 360px; gap: clamp(24px, 3.2vw, 40px); align-items: start; padding-block: clamp(28px, 4vw, 44px) clamp(48px, 6vw, 72px); }
.classroom[hidden] { display: none; }
.classroom__main { display: flex; flex-direction: column; gap: var(--space-6); }
.class-empty { padding-block: clamp(48px, 6vw, 72px); text-align: center; }

.player { position: relative; aspect-ratio: 16/9; border-radius: var(--radius-lg); overflow: hidden; background: var(--video-placeholder); box-shadow: var(--shadow-lg); }
.player iframe { position: absolute; inset: 0; width: 100%; height: 100%; border: 0; }

/* The player slot when the lesson is gated — no membership, or the wrong tier. */
.locked-pane { aspect-ratio: 16/9; border-radius: var(--radius-lg); background: var(--sage-2); border: 1px solid var(--sage); display: grid; place-items: center; text-align: center; padding: var(--space-6); }
.locked-pane__in { display: grid; justify-items: center; gap: var(--space-4); max-width: 46ch; }
.locked-pane__lock { width: 56px; height: 56px; border-radius: 999px; background: var(--paper); border: 1px solid var(--line); display: grid; place-items: center; color: var(--pine-deep); box-shadow: var(--shadow); }
.locked-pane__lock svg { width: 26px; height: 26px; }
.locked-pane h3 { font-size: 1.15rem; color: var(--pine-deep); }
.locked-pane p { font-size: .88rem; }

.lesson-intro { display: flex; flex-direction: column; gap: var(--space-4); }
.lesson-head { display: flex; align-items: flex-start; justify-content: space-between; gap: var(--space-5); flex-wrap: wrap; }
.lesson-head__title { display: flex; flex-direction: column; gap: var(--space-2); }
.lesson-head h2 { font-size: clamp(1.35rem, 2.6vw, 1.8rem); }
.lesson-desc { font-size: .96rem; max-width: 64ch; }
.dur-chip { flex: none; display: inline-flex; align-items: center; gap: var(--space-3); background: var(--paper); border: 1px solid var(--line); border-radius: 999px; padding: 7px 15px; font-size: .8rem; font-weight: 800; color: var(--ink-soft); }
.dur-chip svg { width: 14px; height: 14px; color: var(--orange); }

/* Worksheet PDFs, as document cards. */
.sheets { display: flex; flex-direction: column; gap: var(--space-4); }
.sheet-row { display: flex; gap: var(--space-4); flex-wrap: wrap; }
.sheet { display: flex; align-items: center; gap: var(--space-4); background: var(--paper); border: 1px solid var(--line); border-radius: var(--radius); padding: var(--space-4) 18px var(--space-4) var(--space-4); transition: transform .18s ease, box-shadow .18s ease, border-color .18s ease; }
.sheet:hover { border-color: var(--green-soft); transform: translateY(-2px); box-shadow: var(--shadow); }
.sheet__ic { flex: none; width: 40px; height: 40px; border-radius: var(--radius-sm); background: var(--sage-2); display: grid; place-items: center; color: var(--pine-deep); }
.sheet__ic svg { width: 20px; height: 20px; }
.sheet__text { display: flex; flex-direction: column; }
.sheet__name { font-size: .86rem; font-weight: 800; line-height: 1.3; color: var(--ink); }
.sheet__sub { font-size: .73rem; font-weight: 700; color: var(--ink-soft); }

/* The next lesson in the module. */
.upnext { display: flex; align-items: center; gap: var(--space-5); width: 100%; text-align: left; background: var(--cream-2); border: 1px dashed var(--green-soft); border-radius: var(--radius); padding: var(--space-5) 18px; transition: background-color .18s ease; }
.upnext:hover { background: var(--sage-2); }
.upnext__k { flex: none; font-family: var(--script); font-size: 1.15rem; color: var(--orange-deep); transform: rotate(-2deg); }
.upnext__t { flex: 1; font-size: .9rem; font-weight: 800; color: var(--ink); }
.upnext__d { font-size: .8rem; font-weight: 700; color: var(--ink-soft); }
.upnext svg { flex: none; width: 16px; height: 16px; color: var(--orange-deep); }

/* The lesson rail stays in the classroom grid's normal page flow. */
.rail { position: static; background: var(--paper); border: 1px solid var(--line); border-radius: var(--radius-lg); overflow: hidden; box-shadow: var(--shadow); }
.rail__head { display: flex; flex-direction: column; gap: var(--space-1); padding: 18px 20px 14px; background: var(--cream-2); border-bottom: 1px solid var(--line); }
.rail__head h3 { font-size: 1.05rem; }
.rail__head .sub { font-size: .78rem; font-weight: 700; color: var(--ink-soft); }
.rail__lessons { display: grid; gap: var(--space-1); padding: var(--space-3) 10px var(--space-4); }
.rail__foot { padding: 14px 20px; background: var(--cream); border-top: 1px solid var(--line); }

.lesson-row { display: flex; align-items: center; gap: var(--space-4); width: 100%; text-align: left; padding: 10px; border-radius: var(--radius-sm); font-size: .88rem; color: var(--ink); transition: background-color .15s ease; }
.lesson-row:hover { background: var(--cream-2); }
.lesson-row .n { flex: none; width: 26px; height: 26px; border-radius: 999px; background: var(--sage-2); display: grid; place-items: center; font-size: .72rem; font-weight: 800; color: var(--pine-deep); }
.lesson-row .n svg { width: 13px; height: 13px; }
.lesson-row .t { flex: 1; font-weight: 700; line-height: 1.35; }
.lesson-row .d { flex: none; font-size: .76rem; font-weight: 700; color: var(--ink-soft); }
/* .st is the padlock that stands in for the numeral on a gated lesson. */
.lesson-row .st { flex: none; display: grid; place-items: center; color: var(--ink-soft); }
.lesson-row .st svg { width: 15px; height: 15px; }
.lesson-row .tier-chip { padding: 2px 9px; font-size: .64rem; }
/* Now playing — the numeral + title carry it (no left accent bar). */
.lesson-row.is-active { background: var(--sage-2); }
.lesson-row.is-active .n { background: var(--orange); color: #fff; }
.lesson-row.is-active .t { color: var(--orange-deep); }
/* Watched — the green check replaces the numeral. Ordered after .is-active on
   purpose: re-watching a finished lesson keeps its check, and the orange title
   plus the "Now playing" chip already say which one is playing. */
.lesson-row.is-done .n { background: var(--pine); color: #fff; }
.lesson-row.is-locked { opacity: .82; }
.now-chip { flex: none; border-radius: 999px; padding: 2px 8px; background: var(--orange); font-size: .64rem; font-weight: 800; letter-spacing: .08em; text-transform: uppercase; color: #fff; }

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

/* ---------- Terms & Conditions ---------- */
.terms-body h2 { font-size: 1.25rem; margin: 2rem 0 .5rem; color: var(--pine-deep); border-bottom: 1px solid var(--line); padding-bottom: .4rem; }
.terms-body h3 { font-size: 1.05rem; margin: 1.4rem 0 .4rem; }
.terms-body p { margin: 0 0 .9rem; }
.terms-body ul { margin: .4rem 0 .9rem 1.4rem; }
.terms-body ul li { margin-bottom: .35rem; }
.terms-body a { color: var(--pine); }

/* ---------- Footer ---------- */
.site-footer { background: var(--pine-deep); color: #dfe3cc; margin-top: clamp(40px, 6vw, 80px); }
.footer-top { display: grid; grid-template-columns: 1.4fr repeat(3, 1fr); gap: 32px; padding-block: clamp(40px, 5vw, 64px); }
.footer-brand .brand__name { color: #fff; }
.footer-brand p { color: #c4cbab; font-size: .9rem; margin-top: 12px; max-width: 280px; }
.footer-col h4 { color: #fff; font-family: var(--body); font-size: .8rem; text-transform: uppercase; letter-spacing: .14em; margin-bottom: 14px; }
.footer-col a { display: block; padding: 5px 0; font-size: .9rem; color: #cfd5b6; }
.footer-col a:hover { color: var(--honey); }
.social { display: flex; gap: 10px; margin-top: 16px; }
.social a { width: 38px; height: 38px; border-radius: 50%; background: rgba(255,255,255,.08); display: grid; place-items: center; color: #e9ecd6; transition: background .15s, transform .15s; }
.social a:hover { background: var(--orange); transform: translateY(-2px); color: #fff; }
.social svg { width: 18px; height: 18px; }
.site-footer .mh-divider { border-top-color: rgba(255,255,255,.12); margin-block: 0; }
.footer-bottom { padding-block: 20px; display: flex; justify-content: space-between; align-items: center; gap: 16px; flex-wrap: wrap; font-size: .8rem; color: #b9c09c; }
.pay { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; }
.pay img { width: 46px; height: 30px; border-radius: 4px; box-shadow: 0 0 0 1px rgba(255,255,255,.14); display: block; }
.disclaimer { background: var(--pine); color: #d3d9bb; font-size: .72rem; text-align: center; padding: 12px 16px; line-height: 1.5; }

/* Minimal chrome's footer — see the Minimal chrome block up in the header
   section for the whole rationale. Both footers render on every shopper page and
   body[data-chrome] picks one, so the switch can't desync. Cream + a hairline
   rather than the pine slab above: quiet punctuation under a payment form.
   MUST stay after .site-footer — same specificity, so source order decides the
   ground it paints on. */
.site-footer--minimal { display: none; }
body[data-chrome="minimal"] .site-footer:not(.site-footer--minimal) { display: none; }
body[data-chrome="minimal"] .site-footer--minimal { display: block; }
.site-footer--minimal {
  background: var(--cream); color: var(--ink-soft);
  border-top: 1px solid var(--line); margin-top: clamp(32px, 5vw, 56px);
}
.minimal-footer__inner {
  display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between;
  gap: var(--space-4) var(--space-6); padding-block: var(--space-6);
}
.minimal-footer__links { display: flex; flex-wrap: wrap; gap: var(--space-3) var(--space-5); }
.minimal-footer__links a { display: block; color: var(--ink-soft); font-size: .88rem; transition: color .2s ease; }
.minimal-footer__links a:hover { color: var(--pine-deep); text-decoration: underline; }
.minimal-footer__copy { font-size: .82rem; }

/* ---------- Cart drawer (visual) ---------- */
.drawer-overlay { position: fixed; inset: 0; background: var(--scrim); opacity: 0; visibility: hidden; transition: opacity .25s; z-index: 90; }
.drawer-overlay.open { opacity: 1; visibility: visible; }
.drawer { position: fixed; top: 0; right: 0; bottom: 0; width: min(400px, 92vw); background: var(--cream); z-index: 95; transform: translateX(100%); transition: transform .3s ease; display: flex; flex-direction: column; box-shadow: var(--shadow-lg); }
.drawer.open { transform: translateX(0); }
.drawer__head { display: flex; justify-content: space-between; align-items: center; padding: 18px 20px; border-bottom: 1px solid var(--line); }
.drawer__head h3 { font-size: 1.2rem; }
/* Positioned port around the basket list — holds the bottom fade still while the
   lines scroll under it. min-height:0 lets the list (not the drawer) do the
   scrolling; the menu drawer's body has no wrapper and stays a plain flex child. */
.drawer__scroll { position: relative; flex: 1; min-height: 0; display: flex; flex-direction: column; }
.drawer__body { flex: 1; overflow-y: auto; padding: 18px 20px; display: flex; flex-direction: column; gap: 14px;
  scrollbar-width: thin; scrollbar-color: var(--line) transparent; }
/* slim on-brand scrollbar (mirrors .search-scroll, inset border matched to the drawer's cream bg) */
.drawer__body::-webkit-scrollbar { width: 10px; }
.drawer__body::-webkit-scrollbar-track { background: transparent; }
.drawer__body::-webkit-scrollbar-thumb { background: var(--line); border-radius: 999px; border: 3px solid var(--cream); }
.drawer__body::-webkit-scrollbar-thumb:hover { background: var(--ink-soft); }
.cart-item { display: grid; grid-template-columns: 62px 1fr auto; gap: 12px; align-items: start; }
/* basket lines wrapper — a flex column with a fixed gap between rows */
.cart-lines { display: flex; flex-direction: column; gap: 20px; }
.cart-item .ph { width: 62px; height: 62px; border-radius: 10px; }
/* basket line photo: fills the fixed thumb column, natural height (no square crop) */
.cart-thumb { display: block; width: 100%; height: auto; border-radius: var(--radius-sm); background: var(--paper); }
/* clickable basket lines → product page */
.cart-thumb-link { display: block; border-radius: var(--radius-sm); transition: opacity .15s; }
.cart-thumb-link:hover { opacity: .82; }
.cartline__name a:hover { color: var(--orange-deep); }
/* basket line body (name / price-each / qty stepper) + end column (line price + remove) */
.cart-item__body { min-width: 0; display: flex; flex-direction: column; align-items: flex-start; gap: 7px; }
.cart-item__text { display: flex; flex-direction: column; align-items: flex-start; gap: 0; }
.cart-item__body .cartline__name { font-size: .96rem; }
.cart-item__end { display: flex; flex-direction: column; align-items: flex-end; gap: 10px; }
.drawer__foot { border-top: 1px solid var(--line); padding: 18px 20px; }
/* A rule is content in its own right: use this shared element instead of attaching
   a divider border to the block it happens to follow. */
.mh-divider { display: block; width: 100%; height: 0; margin: var(--space-4) 0; border: 0; border-top: 1px solid var(--line); }
.mh-divider--strong { border-top-width: 2px; }
/* Bottom-fade scroll hint. Put this on the POSITIONED port wrapping a capped scroll
   box (never on the scrolling box itself, or the fade scrolls away with the content);
   MH.scrollFade(box) drives the state classes. The gradient has to land on the
   surface behind it, so a port on anything but --cream sets --scrollfade-bg.
   Add --top for the mirrored fade on the leading edge (see below). */
.mh-scrollfade::after,
.mh-scrollfade--top::before { content: ""; position: absolute; left: 0; right: 0; height: 56px;
  pointer-events: none; opacity: 0; transition: opacity .2s; }
.mh-scrollfade::after { bottom: 0; background: linear-gradient(to bottom, transparent, var(--scrollfade-bg, var(--cream))); }
.mh-scrollfade.is-scrollable::after { opacity: 1; }   /* content overflows → hint there's more */
.mh-scrollfade.is-bottom::after { opacity: 0; }       /* reached the end → nothing left to hint */
/* Opt-in top fade — the same hint for what you've scrolled PAST, softening rows into
   the chrome above instead of clipping them at a hard edge. Off by default: a port
   sitting under its own heading (the order receipt) wants that edge crisp. Each rule
   must stay after its .is-scrollable twin above — the pair ties on specificity, so
   source order is what lets "nothing to hint" win. */
.mh-scrollfade--top::before { top: 0; background: linear-gradient(to top, transparent, var(--scrollfade-bg, var(--cream))); }
.mh-scrollfade--top.is-scrollable::before { opacity: 1; }
.mh-scrollfade--top.is-top::before { opacity: 0; }    /* still at the start → nothing above to hint */
/* "N more items" hint riding the fade — a soft green pill; click scrolls the list to the
   end. Sits inside the .mh-scrollfade port (a sibling of the scroll box, not inside it),
   and rides the same two state classes as the fade it sits on. */
.mh-scrollmore { position: absolute; left: 50%; bottom: 8px; transform: translateX(-50%); z-index: 1;
  display: inline-flex; align-items: center; gap: 5px; padding: 4px 12px; border: 0; cursor: pointer;
  border-radius: 999px; background: var(--pine-deep); color: var(--paper);
  font-family: var(--body); font-size: .72rem; font-weight: 700; line-height: 1; letter-spacing: .01em;
  box-shadow: var(--shadow); opacity: 0; transition: opacity .2s; }
.mh-scrollmore[hidden] { display: none; }   /* class sets display:inline-flex, so [hidden] needs this to win */
.mh-scrollmore::after { content: "▾"; font-size: .82rem; line-height: 1; }
.mh-scrollfade.is-scrollable .mh-scrollmore { opacity: 1; }
.mh-scrollfade.is-bottom .mh-scrollmore { opacity: 0; pointer-events: none; }
/* The basket drawer uses lone rules between its chrome and its contents; the menu
   drawer keeps its existing compact chrome treatment. Each rule owns the air below
   it, so it sits at its own level (never inside a gap parent) and spaces itself.
   `width: auto` is load-bearing: the base .mh-divider width:100% would fight the
   bleed margin below and offset the rule sideways instead of stretching it. */
#cartDrawer .drawer__head, #cartDrawer .drawer__foot { border: 0; }
#cartDrawer .drawer__divider { width: auto; margin: 0 0 var(--space-5); }
/* the foot rule bleeds past the foot's own side padding to reach the panel edges */
#cartDrawer .drawer__foot .drawer__divider { margin-inline: -20px; }
/* free-shipping progress sits just above the subtotal; collapses when the basket is
   empty (out of the flow entirely, so .drawer__summary's gap closes up with it) */
.drawer__summary { display: flex; flex-direction: column; gap: 14px; }
.drawer__shipbar:empty { display: none; }
.drawer__shipbar .ship-bar { margin-top: 0; }
.drawer__total { display: flex; justify-content: space-between; font-weight: 800; }
/* lone element in the lines list — no sibling to share a gap parent with */
.drawer__empty { text-align: center; color: var(--ink-soft); margin: 36px 0; }

/* Scroll lock — the page stays put while an overlay surface owns the screen.
   One canonical rule; each surface just adds its own body class. */
body.mh-modal-open, body.mh-drawer-open, body.mh-gate-open { overflow: hidden; }
/* A fixed element's right edge is the viewport MINUS the reserved scrollbar
   gutter, so the locked page (scrollbar gone, gutter still stable) would strand
   the right-anchored drawer ~15px short of the screen. Release the gutter and
   hand the page back that exact width as padding: the drawer reaches the edge,
   nothing behind the scrim reflows. --mh-sbw is measured once by site.js.
   Modals/gate keep the gutter — centred, so the strip never shows. */
html:has(> body.mh-drawer-open) { scrollbar-gutter: auto; }
body.mh-drawer-open { padding-right: var(--mh-sbw, 0px); }

/* ---------- Modal (reusable centered dialog — MH.modal) ---------- */
.modal-overlay { position: fixed; inset: 0; z-index: 900; display: flex; padding: 20px;
  background: var(--scrim); backdrop-filter: blur(6px); -webkit-backdrop-filter: blur(6px);
  opacity: 0; visibility: hidden; transition: opacity .2s; }
.modal-overlay.open { opacity: 1; visibility: visible; }
.modal { position: relative; margin: auto; width: min(560px, 100%); max-height: calc(100vh - 40px);
  display: flex; flex-direction: column; background: var(--paper); border-radius: var(--radius-lg);
  box-shadow: var(--shadow-lg); overflow: hidden; transform: translateY(12px) scale(.98); transition: transform .2s ease; }
.modal-overlay.open .modal { transform: none; }
/* Stacked second layer (MH.modal.openTop) — a smaller dialog above the base
   modal, with a lighter scrim so the dialog underneath stays visible. */
.modal-overlay--top { z-index: 910; background: color-mix(in srgb, var(--scrim) 55%, transparent); }
.modal-overlay--top .modal { width: min(440px, 100%); }
.modal__close { position: absolute; top: 10px; right: 10px; z-index: 2; }
.modal__scroll { flex: 1 1 auto; min-height: 0; overflow-y: auto; padding: 22px; }
.modal__title { font-family: var(--display); font-size: 1.3rem; font-weight: 600; margin: 0 0 14px; padding-right: 34px; }
.modal__title:empty { display: none; }
/* Order modal spacing lives on two knobs: --order-inset (top + both sides of the header
   text blocks) and --order-gap (the single flex gap between every block in the body). The
   body is a flex column so every block is evenly spaced with no per-element margins; the
   cards + full-width buttons keep the base .modal__scroll width (only the header text is inset). */
.modal--order { --order-inset: 4px; --order-gap: 16px; }
/* "Order Details" is rendered inside the body header (.account-order__head) so it can share
   a gap with the order bar; the chrome title stays (hidden) only to name the dialog for a11y. */
.modal--order .modal__title { display: none; }
.modal--order .modal__body { display: flex; flex-direction: column; gap: var(--order-gap); }
.modal--order .account-order__head { margin: var(--order-inset) var(--order-inset) 0; }
.modal--order .account-order__status { margin-left: var(--order-inset); margin-right: var(--order-inset); }
/* Subscription "Manage" modal — same evenly-spaced flex-column body as the order
   modal (blocks separated by --sub-gap, header text inset by --sub-inset), with its
   own product-forward content; the frequency select fills the body width. */
.modal--sub { --sub-inset: 4px; --sub-gap: 16px; }
.modal--sub .modal__title { display: none; }
.modal--sub .modal__body { display: flex; flex-direction: column; gap: var(--sub-gap); }
.modal--sub .sub-detail__head { margin: var(--sub-inset) var(--sub-inset) 0; }
.modal--sub .sub-detail__status { margin-left: var(--sub-inset); margin-right: var(--sub-inset); }
.modal--sub .club-cycle { margin: 0; width: 100%; }
.modal--sub .club-cycle select { width: 100%; }
/* Full-width frequency dropdown — the sanctioned wrap+btn width:100% pin (see .mh-select). */
.modal--sub .club-cycle .mh-select,
.modal--sub .club-cycle .mh-select__btn { width: 100%; }
/* Frequency + quantity sit side by side in the Manage modal. */
.modal--sub .sub-detail__controls { display: grid; grid-template-columns: 1fr auto; gap: 14px; align-items: end; }
/* Keep the quantity stepper its natural width — the column-flex label would else stretch it.
   Restyled here to sit flush with the frequency select beside it: same paper fill,
   radius-sm corners, and border-box height as .club-cycle select (not the cart's pill). */
.modal--sub .sub-detail__controls .qty { align-self: start; border-radius: var(--radius-sm); background: var(--paper); }
.modal--sub .sub-detail__controls .qty button { width: 42px; height: 46px; font-size: 1.05rem; }
.modal--sub .sub-detail__controls .qty span { width: 40px; align-self: stretch; display: flex; align-items: center; justify-content: center; font-size: .95rem; border-left: 1px solid var(--line); border-right: 1px solid var(--line); }
/* Confirm dialog (MH.confirm) — a centered message + Cancel / Confirm buttons. */
.modal--confirm .modal__title, .modal--confirm .modal__body { text-align: center; }
.modal-confirm__msg { font-size: 1rem; color: var(--ink); line-height: 1.55; margin: 4px 0 22px; text-wrap: balance; }
/* The load-bearing detail in a confirm (a date, an amount) — weight only, no accent. */
.modal-confirm__msg b { font-weight: 800; white-space: nowrap; }
.modal-confirm__actions { display: flex; gap: 12px; justify-content: center; flex-wrap: wrap; }

/* ---------- Free-shipping progress bar (cart drawer + checkout summary) ---------- */
.ship-bar { display: flex; flex-direction: column; gap: var(--space-3); margin-top: 14px; }
.ship-bar__content { display: flex; flex-direction: column; gap: var(--space-2); }
.ship-bar__meter { display: flex; flex-direction: column; }
/* The cart summary's parent gap owns this component's outer spacing. */
.cart-summary__shipbar .ship-bar { margin: 0; }
/* Stays a PLAIN BLOCK — do not make this a flex container. The single-line states are
   one text run with an inline <b> in the middle ("You're $0.50 away from free U.S.
   shipping"), and flex would promote each inline piece to its own flex item, stacking
   one sentence into three lines. The mid-ladder state stacks via .ship-bar__lines
   below, which is a real element and can own the gap. */
.ship-bar__label { font-size: .82rem; text-align: center; color: var(--ink-soft); }
.ship-bar__label b { color: var(--orange-deep); }
/* Stacks the label's two lines (won above, next below) — flex so each span gets its own
   line, with no gap: the lines sit on their natural line-height alone. BOTH lines always
   render — a state with nothing for a slot fills it with &nbsp; (see MH.shipBar) — so
   the label's height never changes and the summary below it never jumps. */
.ship-bar__lines { display: flex; flex-direction: column; }
/* The prize already banked — pine says "won" above the line that still says "keep
   going". Carries its own weight/colour, so it needs no <b> and no state class. */
.ship-bar__won { color: var(--pine-deep); font-weight: 700; }
.ship-bar__next { color: var(--ink-soft); }
.ship-bar__track {
  position: relative; height: 9px; border-radius: 999px; overflow: hidden;
  background: var(--cream-2); box-shadow: inset 0 1px 2px rgba(56, 42, 20, .14);
}
/* ONE bar — a STATIC PAINT with a MOVING REVEAL. This is the whole trick, and it's why
   nothing here animates width:
     The element is ALWAYS the full width of the track, painted once with both ramps in
   TRACK coordinates — green from 0 to --won-stop, orange from --won-stop to the end. The
   paint never moves. What moves is the clip edge: inset() hides everything right of
   --fill, so growing the basket UNCOVERS more of a picture that was already there.
     Only ONE edge is ever in motion. An earlier build animated the element's width AND
   the colour boundary together, and since two edges then swept at different rates it read
   as two bars stacked and animating separately — which is exactly what it looked like.
     --won-stop is therefore TRACK-relative (no conversion): 0 below $75 → all orange; the
   $75 tick's position between the rungs → green to it, orange past it; 100% at $125+ →
   all green. It is deliberately NOT transitioned — it must snap, so the paint stays still
   while the reveal travels. `round 999px` keeps the leading edge a rounded pill cap. */
/* The reveal edge, REGISTERED so it can be transitioned directly. This is load-bearing,
   not decoration: `clip-path` here is built out of var(--fill), and a property whose
   value comes from an unregistered custom property carries a pending-substitution value
   that the transition machinery can't interpolate — so `transition: clip-path` silently
   snapped and the bar landed on the page already full. Typed as a <percentage>, --fill
   itself animates, and clip-path is simply recomputed each frame from it. `--won-stop`
   stays unregistered ON PURPOSE — it must snap (see below). */
@property --fill { syntax: "<percentage>"; inherits: false; initial-value: 0%; }
.ship-bar__fill {
  height: 100%; width: 100%;
  background: linear-gradient(90deg,
    var(--green-soft) 0,
    var(--pine) calc(var(--won-stop, 0%) * 0.55),
    var(--pine-deep) var(--won-stop, 0%),
    var(--honey) var(--won-stop, 0%),
    var(--orange) calc(var(--won-stop, 0%) + (100% - var(--won-stop, 0%)) * 0.55),
    var(--orange-deep) 100%);
  clip-path: inset(0 calc(100% - var(--fill, 0%)) 0 0 round 999px);
  /* Fill/empty smoothly from the current reveal on each cart change — JS moves --fill in place (see MH.shipBar), no restart-from-0 keyframe. */
  transition: --fill 1s cubic-bezier(.22, .61, .36, 1);
}
/* Milestone notch — one per free-ship rung below the top one (Standard's $75 on a
   track that measures to Priority's $125). `--at` is its position along the track, set
   inline from the ladder. Unreached it's a faint scratch on the empty cream: a goal to
   reach. Once the reveal passes it, it lights up as a cream notch with a soft halo,
   marking the rung you banked — it sits exactly where the paint turns green→orange, so
   it reads as the marker ON that boundary. (It is drawn over the fill, and the fill's
   colours are static, so this is a label on the bar — not a seam between two of them.)
     Three states, one per phase of the climb: a scratch (goal ahead) → a lit notch (rung
   banked, still climbing) → gone (see is-maxed below). */
.ship-bar__tick {
  position: absolute; top: 0; bottom: 0; left: var(--at, 50%);
  width: 2px; transform: translateX(-50%); border-radius: 999px;
  background: color-mix(in srgb, var(--ink-soft) 30%, transparent);
  transition: background .5s ease, box-shadow .5s ease, opacity .5s ease;
}
.ship-bar__tick.is-hit {
  background: color-mix(in srgb, var(--cream) 85%, transparent);
  box-shadow: 0 0 0 1.5px color-mix(in srgb, var(--cream) 35%, transparent);
}
/* The whole ladder is won — a milestone only means something while there's still a climb
   left to measure against it. With the bar full and green there's nothing being marked,
   so the notch fades out and leaves a clean finished bar. */
.ship-bar.is-maxed .ship-bar__tick { opacity: 0; }
@media (prefers-reduced-motion: reduce) {
  .ship-bar__fill, .ship-bar__tick { transition: none; }   /* --fill lands on its value instantly */
}

/* ---------- Cart / checkout page ---------- */
.cartpage { display: grid; grid-template-columns: minmax(0, 1.6fr) minmax(0, 1fr); gap: clamp(24px, 4vw, 48px); align-items: start; }
/* An empty basket needs one clear next step, not an inert checkout rail. */
.cartpage--basket:has(.cart-summary[hidden]) { grid-template-columns: minmax(0, 1fr); }
.cart-basket,
.cart-summary {
  background: var(--paper);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  padding: clamp(22px, 3vw, 30px);
  box-shadow: var(--shadow);
}
.cart-basket { display: flex; flex-direction: column; gap: var(--space-4); }
/* Both cards free-size to their own content, with one exception: a single-line basket
   would look stubby beside the summary, so it takes the summary's height as a floor
   (cart.html measures it, promo states excluded) and still grows past it when the row
   needs to. Two or more lines get no floor at all. */
.cartpage--basket.is-single .cart-basket { min-height: var(--cart-summary-height, 0px); }
.cart-basket__content,
.cart-basket__lines,
.cartline__details,
.cartline__copy,
.cart-summary__stack,
.cart-summary__content,
.cart-summary__totals { display: flex; flex-direction: column; }
.cart-basket__content { gap: var(--space-6); }
/* Every basket-note state sits closer to the final line's divider. */
.cart-basket__content:has(#cartMeta .cart-note),
.cart-basket__content:has(#cartMeta .cart-note__open) { gap: var(--space-4); }
.cart-basket__lines { gap: var(--space-4); }
.cart-basket__divider,
.cart-line__divider { width: 100%; height: 1px; border: 0; background: var(--line); }
/* display:grid beats the UA [hidden]{display:none}, so a bare `hidden` attribute
   won't hide the grid (e.g. checkout collapsing the form on success) — re-assert it. */
.cartpage[hidden] { display: none; }
.cart-head { display: flex; justify-content: space-between; align-items: baseline; }
/* .link-arrow is inline-flex, so explicitly preserve the hidden empty-cart state. */
#cartContinue[hidden] { display: none; }
.cart-line { display: grid; grid-template-columns: 96px minmax(0, 1fr) auto; gap: var(--space-5); align-items: center; }
.cartline__details { min-width: 0; align-items: flex-start; gap: var(--space-3); }
.cartline__copy { gap: var(--space-1); }
.cartline__actions { display: flex; align-items: center; gap: var(--space-3); }
.cart-line .ph { width: 96px; height: 96px; border-radius: 12px; }
.cartline__name { font-family: var(--display); font-weight: 600; font-size: 1.05rem; }
.cartline__meta { font-size: .82rem; color: var(--ink-soft); }
.cartline__price { font-weight: 800; color: var(--pine-deep); white-space: nowrap; }
.cartline__remove { color: var(--ink-soft); padding: 6px; border-radius: 8px; }
.cartline__remove:hover { color: var(--danger-solid); background: var(--status-danger-bg); }
.cartline__remove svg { width: 18px; height: 18px; }
.qty--sm button { width: 36px; height: 36px; font-size: 1.1rem; }
/* Hairline dividers between −│value│+ so the compact stepper reads as one segmented control. */
.qty--sm span { width: 36px; align-self: stretch; display: flex; align-items: center; justify-content: center; border-left: 1px solid var(--line); border-right: 1px solid var(--line); }
.cart-basket__empty { display: flex; flex-direction: column; align-items: center; gap: var(--space-5); padding-block: var(--space-4); text-align: center; }
/* Basket skeleton: a returning shopper's saved cart loads from Supabase a beat
   after paint, so hold their line count here rather than flash "empty".
   Mirrors .cart-line's grid; widths approximate a real line's copy. */
.cart-line--sk .cartline__copy { width: 100%; }
.cart-line__sk-thumb { width: 96px; height: 96px; border-radius: 12px; }
.cart-line__sk-name { width: min(58%, 260px); height: 1.05rem; }
.cart-line__sk-meta { width: min(34%, 150px); }
.cart-line__sk-qty { width: 108px; height: 36px; border-radius: var(--radius-sm); }
.cart-line__sk-price { width: 64px; }
.cart-meta-actions { display: flex; gap: var(--space-5); flex-wrap: wrap; font-size: .9rem; font-weight: 700; }
.cart-meta-actions a { display: inline-flex; align-items: center; gap: 8px; color: var(--pine-deep); }
.cart-meta-actions a:hover { color: var(--orange-deep); }
/* Optional order note: a calm inline disclosure on the basket, before checkout. */
.cart-note { width: 100%; display: flex; flex-direction: column; gap: var(--space-3); }
.cart-note__editor { display: flex; flex-direction: column; gap: var(--space-4); }
.cart-note label { font-size: .9rem; color: var(--ink); }
.cart-note label span { font-weight: 600; color: var(--ink-soft); }
.cart-note textarea { width: 100%; resize: vertical; border: 1px solid var(--line); border-radius: var(--radius-sm); padding: 12px 14px; font: inherit; line-height: 1.5; color: var(--ink); background: var(--paper); }
.cart-note textarea:focus { outline: none; border-color: var(--pine); box-shadow: var(--focus-ring); }
.cart-note__open, .cart-note__edit, .cart-note__remove { color: var(--pine-deep); font-size: .9rem; font-weight: 800; }
.cart-note__open { display: inline-flex; align-items: center; gap: 8px; align-self: start; }
.cart-note__open:hover, .cart-note__edit:hover { color: var(--orange-deep); }
.cart-note__controls, .cart-note__actions { display: flex; align-items: center; gap: var(--space-4); }
.cart-note__controls { justify-content: space-between; }
.cart-note__count { align-self: flex-start; font-size: .78rem; font-weight: 600; color: var(--ink-soft); }
.cart-note__actions { justify-content: flex-start; }
.cart-note__remove { color: var(--ink-soft); }
.cart-note__remove:hover { color: var(--danger-solid); }
.cart-note--saved { width: 100%; flex-direction: row; align-items: flex-start; justify-content: space-between; padding: var(--space-4); border: 1px solid var(--green-soft); border-radius: var(--radius-sm); background: var(--sage-2); }
.cart-note--saved > div { min-width: 0; }
.cart-note--saved b { font-size: .86rem; color: var(--pine-deep); }
.cart-note--saved p { margin: 2px 0 0; white-space: pre-wrap; font-size: .88rem; font-weight: 600; color: var(--ink-soft); }
.cart-note--saved .cart-note__edit { align-self: center; }
/* The basket note is a full card; checkout keeps its own compact placement below. */
#cartMeta .cart-note--saved,
#cartMeta .cart-note textarea { border-radius: var(--radius); }
/* On checkout, the saved note belongs with the selected delivery/payment rows. */
#coNoteSection .cart-note--saved { padding: 12px 14px; border-radius: var(--radius); border-color: var(--green-soft); background: var(--sage-2); }
.cart-summary { position: sticky; top: 120px; }
.cartpage--basket .cart-summary__stack { gap: var(--space-4); }
.cartpage--basket .cart-summary__content { gap: var(--space-4); }
.cartpage--basket .cart-summary__totals { gap: var(--space-2); }
.cartpage--basket .cart-summary__shipbar .ship-bar,
.cartpage--basket .cart-summary__promo .promo,
.cartpage--basket .cart-summary__notice { margin: 0; }
.cartpage--basket .summary-row { padding: 0; }
.summary-row { display: flex; justify-content: space-between; padding: 9px 0; font-size: .96rem; }
.summary-row span:last-child { font-weight: 700; }
.summary-row.muted span { color: var(--ink-soft); font-weight: 600; }
/* Membership cadence is a supporting detail beneath its plan name. */
#svcGrid[data-service-mode="club"] #svcSummaryItems small {
  color: color-mix(in srgb, var(--ink-soft) 76%, transparent);
  font-size: .82em;
  font-weight: 500;
}
/* Service-ledger details are supporting billing context, not the total. */
#svcGrid #svcSubLabel,
#svcGrid #svcTaxLabel {
  color: var(--ink-soft);
  font-size: .82rem;
  font-weight: 500;
}
#svcGrid #svcSubtotal,
#svcGrid #svcTaxAmount { font-size: .82rem; font-weight: 500; }
/* Owns the air around it via margin, not a parent's gap — see CLAUDE.md. */
.summary-divider { width: 100%; height: 2px; margin: var(--space-3) 0; border: 0; background: var(--line); }
.summary-row.total { padding: 0; font-family: var(--display); font-size: 1.35rem; font-weight: 600; }
.summary-row.total span { color: var(--ink); }
/* Rows toggled off with [hidden] (discount, total) collapse fully — the base .summary-row display:flex would otherwise beat [hidden] */
.summary-row[hidden] { display: none; }
.secure { display: flex; align-items: center; justify-content: center; gap: 8px; font-size: .82rem; color: var(--ink-soft); margin-top: 12px; }

/* The checkout look — shared by BOTH checkouts: the product basket checkout
   (checkout.html) and the services checkout (checkout-services.html, which sells
   consultations + memberships). They are deliberately separate flows with
   separate code; this is the one place their appearance is defined, so the two
   can never drift into looking like different websites.

   Spaces its sections, field groups, and order summary with flex `gap` on shared
   parents — never sibling margins (CLAUDE.md layout directive). Class-scoped
   (.co-form / .co-grid, applied by both pages) rather than id-scoped so cart.html's
   shared .cart-summary, .secure, .promo, and .summary-row keep their own
   (different) spacing. */
.co-form { display: flex; flex-direction: column; gap: 28px; }
.co-form .co-section,
.co-form .co-fields { display: flex; flex-direction: column; }
.co-form .co-section { gap: 16px; }   /* section heading → its body */
.co-form .co-fields { gap: 12px; }    /* between stacked fields */
.co-form .grid--2 { gap: 0 12px; }    /* side-by-side field pairs match the stacked-field gap */
/* An empty (guest) saved-address/card picker must actually collapse — .addr-pick's
   display:grid otherwise beats the `hidden` attribute, leaving a 0-height element that
   pads Shipping/Payment with an extra co-section gap the other sections don't have. */
.co-form .addr-pick[hidden] { display: none; }
/* Checkout sticks the summary lower than the shared .cart-summary default (120px,
   which the basket page keeps) so it clears the sticky header with real air below
   the "Back to basket" row — 168px from the top of the viewport. */
.co-grid .cart-summary { top: 168px; }
/* Services checkout parks the fine print BELOW the summary card, so the sticky
   element is the whole column (card + note), not the card itself. */
.co-grid .co-summary-col { position: sticky; top: 168px; display: flex; flex-direction: column; gap: var(--space-5); }
.co-grid .co-summary-col .cart-summary { position: static; }
.co-grid .co-summary-col .cart-summary__notice { padding: 0 var(--space-5); justify-content: flex-start; text-align: left; }
.co-grid .co-summary-col .cart-summary__notice[hidden] { display: none; }
/* Place Order lives in the order-summary aside (outside the form), so its shared
   card stack owns every vertical relationship with flex gap. */
.co-grid .cart-summary__stack { gap: var(--space-6); }
.co-grid .cart-summary__content { gap: var(--space-4); }
.co-grid .co-summary__items,
.co-grid .cart-summary__totals,
.co-grid .co-submit { display: flex; flex-direction: column; }
/* Keep the receipt totals compact, but give individual cart lines enough air to scan. */
.co-grid .co-summary__items { gap: var(--space-2); }
/* Reserve a clear price column so long product names wrap before they crowd it. */
.co-grid .co-summary__items .summary-row {
  display: grid;
  grid-template-columns: minmax(0, 1fr) max-content;
  align-items: start;
  column-gap: var(--space-6);
  padding: var(--space-3);
  border-radius: var(--radius-sm);
  line-height: 1.35;
  transition: background-color .2s ease;
}
.co-grid .co-summary__items .summary-row span:first-child { min-width: 0; }
.co-grid .co-summary__items .summary-row span:last-child { white-space: nowrap; }
.co-grid .co-summary__items .summary-row:hover {
  background-color: color-mix(in srgb, var(--sage-2) 72%, transparent);
}
/* Service line items are informational, so their shared receipt treatment stays still. */
#svcGrid .co-summary__items .summary-row:hover { background-color: transparent; }
.co-grid .cart-summary__totals { gap: var(--space-2); }
/* The service subtotal and its zero-tax line read as one compact billing pair. */
#svcGrid .cart-summary__totals { gap: 0; }
.co-grid .co-summary__divider { width: 100%; height: 1px; background: var(--line); }
.co-grid .cart-summary__promo .promo,
.co-grid .cart-summary__notice { margin: 0; }
.co-grid .summary-row { padding: 0; }
/* the gap parents own the vertical spacing now — drop the per-child margins */
.co-form .field { margin-bottom: 0; }
.co-form .addr-pick { margin-bottom: 0; }
.co-form .save-toggle { margin-top: 0; }
/* flex containers toggled via the `hidden` attribute need this or they never hide */
.co-form .co-section[hidden],
.co-form .co-fields[hidden] { display: none; }

/* Contact row — full name + phone share the first line, email takes the whole second
   one. A signed-in shopper's name + email cells hide, so the row drops to one column
   and the phone (the only cell left) spans it instead of hugging the left half. */
.co-form .co-contact { gap: 12px; }   /* two rows here, so restore the stacked-field row gap */
.co-contact__wide { grid-column: 1 / -1; }
/* A two-cell row currently holding one cell (Contact when only the name or only the
   phone is asked for; the Shipping-address name row when the phone sits in Contact
   instead) — the lone field spans the row rather than hugging the left half. */
.co-form .grid--solo { grid-template-columns: 1fr; }

/* Checkout callout — the soft tinted aside both checkouts use for a guest nudge,
   a "your card is charged now" heads-up, or a pickup note. The canonical home for
   what was an inline `background:var(--cream-2);border-radius:10px;…` box copied
   between the checkout pages. Distinct from the shared `.note`, which reserves a
   40px gutter for a leading icon these don't have. */
.co-note { background: var(--cream-2); border-radius: var(--radius-sm); padding: 12px 16px; font-size: .9rem; color: var(--ink-soft); line-height: 1.6; }
.co-note__link { color: var(--pine); font-weight: 700; transition: color .15s; }
.co-note__link:hover { color: var(--orange-deep); }

/* Services checkout (checkout-services.html) — consultations + memberships. */
.svc-loading { display: grid; place-items: center; padding: 60px 20px; color: var(--ink-soft); }
.svc-loading[hidden] { display: none; }
/* "What's included" perk list in the summary card. */
.svc-includes { display: flex; flex-direction: column; gap: var(--space-2); font-size: .9rem; color: var(--ink-soft); }
.svc-includes[hidden] { display: none; }
.svc-includes__item { display: flex; align-items: flex-start; gap: 9px; line-height: 1.5; }
.svc-includes__item svg { flex: none; width: 15px; height: 15px; margin-top: 3px; color: var(--pine); }
.svc-done-actions { display: flex; gap: 14px; justify-content: center; flex-wrap: wrap; }

/* Session-time picker (consultation checkout) — the date rail + time pills fed
   by MH.consults.slots(). One flex column owns the vertical rhythm (days rail →
   times → timezone foot); selection state is carried by aria-selected /
   aria-pressed with .is-on as the styling hook. Selected = pine, matching the
   primary summary emphasis, never a new accent. */
.slot-pick { display: flex; flex-direction: column; gap: 14px; }
.slot-pick__loading { color: var(--ink-soft); font-size: .9rem; }
/* One horizontal rail — scrolls sideways on narrow screens instead of stacking
   forty day cards down the form. */
.slot-cal { display: flex; flex-direction: column; gap: 20px; }
.slot-cal__body { display: flex; flex-direction: column; gap: 10px; }
.slot-cal__head { display: flex; align-items: center; justify-content: space-between; gap: 8px; padding-inline: 25%; }
.slot-cal__month { font-family: var(--display); font-size: 1.05rem; color: var(--ink); }
.slot-cal__nav { display: flex; align-items: center; justify-content: center; width: 32px; height: 32px; background: var(--paper); border: 1px solid var(--line); border-radius: 999px; color: var(--ink); cursor: pointer; transition: border-color .18s ease, box-shadow .18s ease, opacity .18s ease; }
.slot-cal__nav svg { width: 15px; height: 15px; }
.slot-cal__nav:hover { border-color: var(--green-soft); box-shadow: var(--shadow-soft); }
.slot-cal__dows, .slot-cal__grid { display: grid; grid-template-columns: repeat(7, 1fr); gap: 4px; }
.slot-cal__dow { text-align: center; font-size: .7rem; text-transform: uppercase; letter-spacing: .06em; color: var(--ink-soft); }
.slot-cal__day { display: flex; align-items: center; justify-content: center; min-height: 58px; background: var(--paper); border: 1px solid var(--line); border-radius: var(--radius-sm); font-size: .9rem; color: var(--ink); cursor: pointer; transition: border-color .18s ease, background .18s ease, color .18s ease, box-shadow .18s ease; }
.slot-cal__day:hover:not(:disabled) { border-color: var(--green-soft); box-shadow: var(--shadow-soft); }
.slot-cal__day.is-on { background: var(--pine-deep); border-color: var(--pine-deep); color: var(--pine-bright); }
.slot-cal__day:disabled { background: transparent; color: var(--ink-soft); opacity: .45; cursor: default; }
.slot-pick__timeswrap { display: flex; flex-direction: column; gap: 8px; }
.slot-pick__daylabel { font-size: .85rem; color: var(--ink-soft); }
.slot-pick__times { display: grid; grid-template-columns: repeat(5, 1fr); gap: 8px; }
/* .reveal replays a gentle fade when the times re-render on a day click; the
   wrapper is flex, so it needs the [hidden] guard like every toggled flex box. */
.slot-pick__times[hidden] { display: none; }
.slot-time { padding: 9px 6px; text-align: center; background: var(--paper); border: 1px solid var(--line); border-radius: 999px; font-size: .9rem; color: var(--ink); cursor: pointer; transition: border-color .18s ease, background .18s ease, color .18s ease, box-shadow .18s ease; }
.slot-time:hover { border-color: var(--green-soft); box-shadow: var(--shadow-soft); }
.slot-time.is-on { background: var(--pine-deep); border-color: var(--pine-deep); color: var(--pine-bright); }
/* Blank stand-in pills while the availability read runs — the same .slot-time
   shape, muted exactly like the calendar's no-times days so the loading state
   reads as one system. */
.slot-time:disabled { background: transparent; color: var(--ink-soft); opacity: .45; cursor: default; box-shadow: none; }
.slot-cal__day:focus-visible, .slot-cal__nav:focus-visible, .slot-time:focus-visible { outline: none; box-shadow: var(--focus-ring); }
.slot-pick__tz { font-size: .8rem; color: var(--ink-soft); }

/* ── The invoice document (.invp-*) ──────────────────────────────────────────
   THE canonical invoice-as-paper vocabulary: brand head, billed-to, memo,
   line items, dashed tear, totals, amount due, small print. The admin editor's
   live preview renders the full .invp-paper behind its Preview button
   (.modal--invpaper, css/admin.css); the customer pay page (invoice.html) reuses the
   line/total pieces in its bill summary card, and its Download PDF renders the
   print-grade document via MH.printHtml. One home — change it here, all match. */
/* Page shell: hero over a two-column grid. The bill's cards (.invp-side) come
   FIRST in the DOM — phones read the bill before the card form — and the
   desktop grid places them in the right column explicitly. */
.invp-wrap { display: grid; gap: clamp(22px, 3.5vw, 34px); }
.invp-wrap[hidden] { display: none; }
/* The shared two-column skeleton: the hero AND the page grid both use it, so
   the h1's column is always exactly as wide as the pay card below it. */
.invp-cols { display: grid; grid-template-columns: minmax(0, 1.35fr) minmax(300px, 1fr); gap: clamp(24px, 4vw, 44px); align-items: start; }
.invp-hero__lead { display: grid; gap: var(--space-3); }
.invp-hero h1 { margin: 0; font-size: clamp(1.6rem, 3.6vw, 2.3rem); line-height: 1.15; }
.invp-hero h1 b { color: var(--pine-deep); white-space: nowrap; }
.invp-hero__due { margin: 0; color: var(--ink-soft); font-size: .95rem; }
.invp-hero__pdf { display: flex; justify-content: flex-end; align-items: center; }
.invp-page > form { grid-column: 1; grid-row: 1; min-width: 0; }
.invp-side { grid-column: 2; grid-row: 1; display: grid; gap: var(--space-5); align-content: start; position: sticky; top: 110px; }
.invp-card { background: var(--paper); border: 1px solid var(--line); border-radius: var(--radius); box-shadow: var(--shadow);
  padding: var(--space-6); display: grid; gap: var(--space-4); }
.invp-card[hidden] { display: none; }
.invp-card__h { margin: 0; font-family: var(--display); font-weight: 650; font-size: 1.05rem; line-height: 1.2; }
/* The customer's two lines — name and email carry the SAME size/weight/color
   on purpose (a pair of quiet facts, not a headline + caption). */
.invp-cust { display: grid; gap: var(--space-1); }
.invp-cust span { font-size: .85rem; color: var(--ink-soft); overflow-wrap: anywhere; }
.invp-summary__head { display: flex; justify-content: space-between; align-items: baseline; gap: var(--space-4); }
.invp-summary__head b { font-family: var(--display); font-weight: 650; font-size: 1.05rem; }
.invp-summary__head span { font-size: .78rem; color: var(--ink-soft); white-space: nowrap; }
.invp-paper { background: var(--paper); border: 1px solid var(--line); border-radius: var(--radius-lg);
  box-shadow: var(--shadow); padding: clamp(26px, 5vw, 48px); display: grid; gap: clamp(18px, 3vw, 26px); }
.invp-head { display: flex; justify-content: space-between; align-items: flex-start; gap: var(--space-5); flex-wrap: wrap; }
.invp-brand { display: flex; align-items: center; gap: var(--space-4); min-width: 0; }
.invp-logo { width: 46px; height: 46px; object-fit: contain; flex: none; }
.invp-co { display: grid; gap: var(--space-1); }
.invp-co b { font-family: var(--display); font-weight: 650; font-size: 1.15rem; line-height: 1.15; }
.invp-co span { font-size: .78rem; color: var(--ink-soft); }
.invp-no { display: grid; gap: var(--space-1); justify-items: end; text-align: right; }
.invp-kind { font-size: .68rem; font-weight: 800; letter-spacing: .2em; text-transform: uppercase; color: var(--orange-deep); }
.invp-no b { font-size: .95rem; }
.invp-no span { font-size: .78rem; color: var(--ink-soft); }
.invp-label { font-size: .66rem; font-weight: 800; letter-spacing: .14em; text-transform: uppercase; color: var(--ink-soft); }
.invp-to { display: grid; gap: var(--space-1); }
.invp-to[hidden] { display: none; }
.invp-to b { font-size: 1rem; overflow-wrap: anywhere; }
.invp-to small { font-size: .8rem; color: var(--ink-soft); overflow-wrap: anywhere; }
.invp-memo { margin: 0; background: var(--cream-2); border-radius: var(--radius-sm);
  padding: var(--space-4) var(--space-5); font-size: .9rem; line-height: 1.6; color: var(--ink-soft); }
.invp-memo[hidden] { display: none; }
.invp-lines { display: grid; gap: var(--space-3); }
.invp-line { display: flex; justify-content: space-between; gap: var(--space-5); font-size: .92rem; }
.invp-line b { font-variant-numeric: tabular-nums; white-space: nowrap; }
.invp-line--empty { color: var(--ink-soft); }
.invp-what { display: grid; gap: var(--space-1); min-width: 0; }
.invp-what small { font-size: .78rem; color: var(--ink-soft); }
/* The money region is a plain block (no gap): its dividers — the dashed tear and
   the amount-due top border — own their air with margin, the standing exception. */
.invp-money { display: block; }
.invp-rule { border: 0; border-top: 2px dashed var(--line); margin: var(--space-5) 0; }
.invp-totals { display: grid; gap: var(--space-2); }
.invp-row { display: flex; justify-content: space-between; gap: var(--space-5); font-size: .88rem; color: var(--ink-soft); }
.invp-row b { color: var(--ink); font-weight: 700; font-variant-numeric: tabular-nums; }
.invp-row--due { font-size: 1.02rem; color: var(--ink); border-top: 1px solid var(--line);
  margin-top: var(--space-5); padding-top: var(--space-5); align-items: baseline; }
.invp-row--due b { font-family: var(--display); font-size: 1.35rem; font-weight: 650; color: var(--pine-deep); }
.invp-terms { margin: 0; font-size: .78rem; line-height: 1.7; color: var(--ink-soft); }
.invp-terms[hidden] { display: none; }

/* The pay form's own head — cards are the only method, so no picker, just a
   quiet heading over the fields. */
.invp-pay__card { display: flex; flex-direction: column; gap: var(--space-5); }
.invp-pay__head { display: flex; flex-direction: column; gap: var(--space-1); }
.invp-pay__h { font-size: 1.35rem; margin: 0; }
.invp-pay__head p { margin: 0; font-size: .85rem; color: var(--ink-soft); }
@media (max-width: 900px) {
  /* Single column, natural DOM order: hero → the bill's cards → the pay form.
     The PDF button falls under the due line and hugs the left with the text. */
  .invp-cols { grid-template-columns: 1fr; }
  .invp-hero__pdf { justify-content: flex-start; }
  .invp-page > form { grid-column: auto; grid-row: auto; }
  .invp-side { grid-column: auto; grid-row: auto; position: static; }
}


/* Empty-basket / order-placed states — centered stacks spaced by gap, not margins.
   Class-based (not inline display) so the `hidden` attribute still hides them. */
.co-empty, .co-done { display: flex; flex-direction: column; text-align: center; }
.co-empty[hidden], .co-done[hidden] { display: none; }
.co-empty { align-items: center; gap: 18px; }
.co-done { gap: 24px; max-width: 560px; margin: 0 auto; padding: 48px 20px; }
/* The confirmation itself (check, headline, detail lines, buttons) sits in one
   .form-card so it reads as the receipt; the account nudge stays outside it,
   a bare postscript under the card. */
.co-done-card { display: flex; flex-direction: column; gap: 24px; }
.co-done .co-done-hero,
.co-done .co-done-lines { display: flex; flex-direction: column; }
.co-done .co-done-hero { align-items: center; gap: 10px; }  /* check → heading */
.co-done .co-done-lines { gap: 6px; }                       /* confirmation detail lines */
/* The confirmation check — the same bare mark as the payment-result page's hero.
   Pops in on the shared applyDoneMark keyframe: this whole branch flips from
   [hidden] at once, so the animation only starts when the screen appears. */
.co-done-hero__check { display: grid; place-items: center; animation: applyDoneMark .45s .15s ease both; }
.co-done-hero__check svg { width: 44px; height: 44px; }
@media (prefers-reduced-motion: reduce) {
  .co-done-hero__check { animation: none; }
}

/* Order-placed → account nudge (guests only, see MH.guestOrders). A guest order is
   invisible to every account until it's claimed, so the offer still lives here —
   but as a postscript under the confirmation, not a pitch: one soft line, text
   links instead of buttons, no card chrome. */
.co-claim { display: flex; flex-direction: column; align-items: center; text-align: center; }
.co-claim[hidden] { display: none; }   /* display:flex above would otherwise beat the [hidden] attribute */
.co-claim__line { max-width: 46ch; font-size: .92rem; line-height: 1.6; color: var(--ink-soft); }

/* Recap — compact "already on file" card (checkout contact + saved address): the details
   in a single line with an inline Edit/Change action, standing in for a full field group. */
.recap { display: flex; align-items: center; justify-content: space-between; gap: 14px;
  padding: 12px 14px; border: 1px solid var(--line); border-radius: var(--radius-sm); background: var(--sage-2); margin-bottom: 14px; }
.recap[hidden] { display: none; }  /* display:flex above would otherwise beat the [hidden] attribute */
.recap__text { min-width: 0; font-size: .92rem; color: var(--ink); overflow-wrap: anywhere; }
.recap__edit { appearance: none; border: none; background: none; font: inherit; font-weight: 700; font-size: .85rem;
  color: var(--pine-deep); cursor: pointer; white-space: nowrap; padding: 2px 4px; }
.recap__edit:hover { color: var(--orange-deep); text-decoration: underline; }

/* Promo code — discount summary row + the entry / applied box in the order summary */
.summary-row--discount span { color: var(--pine-deep); }
.summary-row--discount span:last-child { font-weight: 800; }
.promo { margin: 10px 0 4px; }
.promo svg.promo__icon { width: 15px; height: 15px; flex: none; fill: none; stroke: currentColor;
  stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; }
/* Collapsed trigger — the field stays hidden until this is clicked */
.promo__toggle { appearance: none; border: none; background: none; font: inherit; cursor: pointer;
  display: inline-flex; align-items: center; gap: 7px; padding: 2px 0;
  color: var(--pine-deep); font-weight: 700; font-size: .88rem; }
.promo__toggle:hover { color: var(--orange-deep); }
.promo__toggle:hover .promo__toggle-txt { text-decoration: underline; text-underline-offset: 2px; }
/* One unified field: input flush-left, Apply integrated flush-right (no mismatched pill) */
.promo__form { display: flex; align-items: stretch; border: 1px solid var(--line); border-radius: var(--radius-sm);
  background: var(--paper); overflow: hidden; transition: border-color .15s, box-shadow .15s; animation: promo-reveal .18s ease-out; }
.promo__form:focus-within { border-color: var(--pine); box-shadow: var(--focus-ring); }
.promo__form input { flex: 1; min-width: 0; padding: 10px 14px; border: none; background: transparent;
  font: inherit; color: var(--ink); text-transform: uppercase; letter-spacing: .05em; }
.promo__form input:focus { outline: none; }
.promo__form input::placeholder { text-transform: none; letter-spacing: normal; color: var(--ink-soft); }
.promo__apply { appearance: none; border: none; border-left: 1px solid var(--line); background: none; cursor: pointer;
  font: inherit; font-weight: 800; font-size: .85rem; color: var(--pine-deep); padding: 0 16px; white-space: nowrap;
  transition: color .15s, background .15s; }
.promo__apply:hover { color: #fff; background: var(--pine); }
.promo__applied { display: flex; align-items: center; justify-content: space-between; gap: 10px; padding: 10px 12px;
  border: 1px dashed var(--green-soft); border-radius: var(--radius-sm); background: var(--status-edit-bg); animation: promo-reveal .18s ease-out; }
.promo__info { display: flex; flex-direction: column; gap: 1px; min-width: 0; }
.promo__code { display: inline-flex; align-items: center; gap: 6px; font-weight: 800; color: var(--pine-deep); letter-spacing: .02em; }
.promo__val { font-size: .8rem; color: var(--ink-soft); font-weight: 700; }
.promo__remove { appearance: none; border: none; background: none; font: inherit; font-weight: 700; font-size: .82rem;
  color: var(--ink-soft); cursor: pointer; padding: 4px 6px; }
.promo__remove:hover { color: var(--orange-deep); text-decoration: underline; }
@keyframes promo-reveal { from { opacity: 0; transform: translateY(-4px); } to { opacity: 1; transform: none; } }

/* ---------- Toast ---------- */
/* Hidden offset must clear the toast's own height AND the bottom:24px gap (+ its
   shadow), or the top edge peeks above the viewport — translateY(100%) alone
   leaves the 24px gap showing. */
/* width:max-content is load-bearing: a shrink-to-fit box anchored at left:50%
   may only grow into the right half of the viewport, so a long message wrapped
   at half the screen (three stacked lines inside a narrow pill on a phone).
   Size to the content and let max-width be the only limit. */
.toast { position: fixed; bottom: 24px; left: 50%; transform: translateX(-50%) translateY(calc(100% + 60px)); width: max-content; max-width: min(460px, calc(100vw - 32px)); background: var(--pine-deep); color: #fff; padding: 13px 22px; border-radius: 999px; font-weight: 700; font-size: .9rem; line-height: 1.35; border: 1px solid color-mix(in srgb, var(--pine-cream) 14%, transparent); box-shadow: var(--shadow-float); z-index: 1400; transition: transform .35s cubic-bezier(.2,.8,.2,1); display: flex; align-items: center; gap: 10px; }
.toast.show { transform: translateX(-50%) translateY(0); }
.toast svg { width: 18px; height: 18px; flex: 0 0 auto; color: var(--honey); }
/* Phone: still a centred, content-width pill — the max-width above is a ceiling,
   not a target, so it never stretches to the gutters. Only the resting spot (above
   the home indicator) and the radius change, the latter so the shape stays graceful
   if a long product name does wrap to two lines. */
@media (max-width: 640px) {
  .toast { bottom: calc(16px + env(safe-area-inset-bottom, 0px)); padding: 12px 18px; border-radius: var(--radius-lg); text-align: left; }
}

/* ---------- Age verification gate ---------- */
.age-gate {
  position: fixed; inset: 0; z-index: 1000;
  display: flex; align-items: center; justify-content: center;
  padding: clamp(16px, 4vw, 40px);
  background: var(--cream);
  overflow-y: auto;
  animation: ageGateIn .3s ease both;
}
.age-gate--closing { animation: ageGateOut .26s ease both; }
@keyframes ageGateIn  { from { opacity: 0; } to { opacity: 1; } }
@keyframes ageGateOut { to { opacity: 0; } }
.age-gate__bg {
  position: absolute; inset: 0; z-index: 0; opacity: .45; pointer-events: none;
  background-repeat: no-repeat;
  background-position: left -40px top -30px, right -60px bottom -50px;
  background-size: 300px, 360px;
}
.age-gate__card {
  position: relative; z-index: 1; margin: auto;
  width: min(560px, 100%);
  background: var(--paper);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-lg);
  padding: clamp(28px, 5vw, 48px);
  text-align: center;
  animation: ageGateRise .42s cubic-bezier(.2,.8,.2,1) both;
}
@keyframes ageGateRise { from { opacity: 0; transform: translateY(14px); } to { opacity: 1; transform: none; } }
.age-gate__logo { display: flex; justify-content: center; margin-bottom: 12px; }
.age-gate__logo img, .age-gate__logo svg { width: 78px; height: 78px; }
.age-gate__title { color: var(--orange); margin: 2px 0 18px; }
.age-gate .kicker { display: inline-block; margin-bottom: 8px; }
.age-gate__intro { font-size: .92rem; color: var(--ink-soft); max-width: 42ch; margin: 0 auto 14px; }
.age-gate__intro b { color: var(--ink); }
.age-gate__q { font-family: var(--display); font-size: clamp(1.15rem, 2.6vw, 1.45rem); color: var(--ink); margin-bottom: 22px; }
.age-gate__actions { display: flex; gap: 14px; justify-content: center; flex-wrap: wrap; margin-bottom: 22px; }
.age-gate__actions .btn { padding: .9em 2.2em; font-size: 1rem; min-width: 132px; justify-content: center; }
.age-gate__fine { font-size: .86rem; color: var(--ink-soft); line-height: 1.6; max-width: 46ch; margin: 0 auto; }
.age-gate__note { font-size: .8rem; font-style: italic; color: var(--ink-soft); max-width: 46ch; margin: 12px auto 0; }
.age-gate__terms { color: var(--orange-deep); font-weight: 700; text-decoration: underline; }
.age-gate__terms:hover { color: var(--orange); }

/* Per-product age-restriction notice (product page) */
.age-note { display: flex; gap: 12px; align-items: flex-start; background: #fbf0e2; border: 1px solid var(--orange-soft); border-left: 4px solid var(--orange); border-radius: var(--radius-sm); padding: 12px 14px; margin: 14px 0 4px; }
.age-note__tag { flex: none; background: var(--ink); color: #fff; font-weight: 800; font-size: .72rem; padding: 3px 9px; border-radius: 999px; margin-top: 2px; }
.age-note p { font-size: .82rem; color: var(--ink); line-height: 1.55; margin: 0; }

/* Always-visible product caution (product page) — ribbon-label style */
.pdp-caution { margin: 18px 0 2px; background: var(--orange); border-radius: var(--radius); padding: 2px; box-shadow: 0 16px 34px -14px rgba(56,42,20,.28); }
.pdp-caution__head { display: flex; align-items: center; gap: 9px; color: #fff; padding: 9px 16px; }
.pdp-caution__head svg { flex: none; width: 18px; height: 18px; }
.pdp-caution__head b { font-family: var(--display); font-weight: 700; font-size: .92rem; letter-spacing: .02em; }
.pdp-caution__body { background: #fdf4e7; padding: 13px 16px; font-size: .83rem; color: var(--ink); line-height: 1.6; border-radius: 0 0 calc(var(--radius) - 2px) calc(var(--radius) - 2px); }
.pdp-caution__body p { margin: 0 0 5px; }
.pdp-caution__body p:last-child { margin-bottom: 0; }
/* Serious variant — a warm brick-red ribbon for the most serious warnings
   (kratom, restricted-botanical bans); stacks ABOVE the orange caution box. */
.pdp-caution--serious { background: var(--danger-solid); }
.pdp-caution--serious .pdp-caution__body { background: color-mix(in srgb, var(--danger-solid) 8%, var(--paper)); }

/* ---------- Account & auth (login + manage account) ---------- */
/* header avatar (logged-in) */
.acct-avatar { width: 30px; height: 30px; border-radius: 50%; background: var(--pine); color: #fff; display: grid; place-items: center; font-size: .78rem; font-weight: 800; letter-spacing: .02em; }
.icon-btn--avatar:hover { background: none; }
.icon-btn--avatar:hover .acct-avatar { background: var(--pine-deep); }
.acct-avatar--lg { width: 52px; height: 52px; font-size: 1.15rem; flex: none; }

/* ── Skeleton placeholder (canonical) ─────────────────────────────────────
   A warm parchment block standing in for content that's a beat away — used
   where we KNOW something is coming (a returning shopper's saved basket) and
   an empty state would be wrong for a split second. A slow cream sweep reads
   as "loading", never as a flashing pulse. Size it from the consumer (see
   .cart-line__sk-*); .mh-sk--text is the ready-made copy-line bar. */
.mh-sk { position: relative; overflow: hidden; background: var(--sage-2); border-radius: var(--radius-sm); }
.mh-sk--text { height: .72rem; border-radius: 999px; }
.mh-sk::after { content: ""; position: absolute; inset: 0; transform: translateX(-100%);
  background: linear-gradient(90deg, transparent, color-mix(in srgb, var(--paper) 70%, transparent), transparent);
  animation: mh-sk-sweep 1.5s ease-in-out infinite; }
@keyframes mh-sk-sweep { to { transform: translateX(100%); } }
@media (prefers-reduced-motion: reduce) { .mh-sk::after { animation: none; } }

/* ── Segmented pill switcher (canonical) ──────────────────────────────────
   A horizontal group of mutually-exclusive options where the active one is
   marked by a single sliding "thumb" (.mh-seg__thumb) that glides behind the
   labels — the labels never move, the active one just changes colour (an iOS
   segmented control). The thumb is created + positioned by MH.segThumbs()
   (site.js); call it after any render that adds/reactivates a .mh-seg (like
   MH.observeReveals). Reskin via the --seg-* custom props on the container.
   Consumers: public auth tabs (.auth-tabs), admin filters (.adm-seg). */
.mh-seg { position: relative; display: inline-flex; border-radius: 999px;
  --seg-fill: var(--pine-deep); --seg-ink: var(--ink-soft); --seg-ink-on: #fff; }
.mh-seg__thumb { position: absolute; top: 0; left: 0; border-radius: inherit; background: var(--seg-fill); pointer-events: none;
  transition: transform .3s cubic-bezier(.22, 1, .36, 1), width .3s cubic-bezier(.22, 1, .36, 1), height .3s cubic-bezier(.22, 1, .36, 1); }
.mh-seg button { position: relative; z-index: 1; appearance: none; border: none; background: none; font: inherit; cursor: pointer;
  border-radius: 999px; color: var(--seg-ink); transition: color .3s cubic-bezier(.22, 1, .36, 1); white-space: nowrap; }
.mh-seg button:hover { color: var(--ink); }
.mh-seg button:disabled { cursor: not-allowed; opacity: .4; }
.mh-seg button:disabled:hover { color: var(--seg-ink); }
.mh-seg button.is-on { color: var(--seg-ink-on); }
/* FLIP start-states set for one frame by MH.segThumbs so the labels cross-fade in
   step with the thumb — no active-colour label flashes on the track before the
   thumb reaches it. .is-preon = new active label held muted; .is-preoff = old. */
.mh-seg button.is-on.is-preon { color: var(--seg-ink); }
.mh-seg button.is-preoff { color: var(--seg-ink-on); }
@media (prefers-reduced-motion: reduce) { .mh-seg__thumb, .mh-seg button { transition: none; } }

/* Sign in / create account card (logged out) */
.auth-wrap { display: flex; justify-content: center; }
.auth-card { width: min(460px, 100%); background: var(--paper); border: 1px solid var(--line); border-radius: var(--radius-lg); box-shadow: var(--shadow); padding: clamp(26px, 4vw, 40px); text-align: center; }
.auth-card__logo { display: flex; justify-content: center; margin-bottom: 10px; }
.auth-card__logo img, .auth-card__logo svg { width: 64px; height: 64px; }
.auth-card__title { font-size: clamp(1.6rem, 3.4vw, 2.1rem); margin-bottom: 6px; }
.auth-card__sub { font-size: .92rem; color: var(--ink-soft); max-width: 40ch; margin: 0 auto 22px; }
/* Full-width cream-tracked skin of the shared .mh-seg sliding switcher (paper thumb,
   pine ink) — the public auth tabs and the checkout delivery-mode toggle. */
.auth-tabs, .deliv-seg { display: flex; gap: 6px; background: var(--cream-2); padding: 5px;
  --seg-fill: var(--paper); --seg-ink: var(--ink-soft); --seg-ink-on: var(--pine-deep); }
/* Checkout's ship/pickup toggle rides the monarch-orange thumb (white active ink) so
   the chosen delivery mode reads in the brand colour rather than the paper default. */
.deliv-seg { --seg-fill: var(--orange); --seg-ink-on: #fff; }
.auth-tabs .mh-seg__thumb, .deliv-seg .mh-seg__thumb { box-shadow: var(--shadow); }
.auth-tabs { margin-bottom: 22px; }
.auth-tab, .deliv-seg button { flex: 1; padding: 10px 14px; font-weight: 800; font-size: .9rem; }
/* Weight only — scoped to outrank `.mh-seg button { font: inherit }`. Deliberately not
   the whole rule above: that would also land font-size and resize the tabs. */
.auth-tabs .auth-tab { font-weight: 800; }
/* Nested gap columns, widening outward: fields sit tight together, the submit button
   gets more air so it reads as the end of the form rather than another field row.
   The signin/signup forms are toggled by the `hidden` attribute — display:flex here
   beats the UA [hidden] rule, so re-assert it (see reference_css_hidden_toggle). */
.auth-form { text-align: left; display: flex; flex-direction: column; gap: var(--space-5); }
.auth-form[hidden] { display: none; }
.auth-form__body { display: flex; flex-direction: column; gap: var(--space-6); }
.auth-form__fields { display: flex; flex-direction: column; gap: var(--space-4); }
/* Spacing belongs to the gap parents above, not to these children. */
.auth-form .field, .auth-form .auth-err { margin-bottom: 0; }
.auth-form .auth-alt { margin-top: 0; }
.auth-alt { font-size: .88rem; color: var(--ink-soft); margin-top: 16px; text-align: center; }
/* Inline link-styled <button> that flows mid-sentence: the global button reset
   keeps the UA's padding + font-SIZE (it only inherits family), which reads as
   detached words in running text — zero both here so it sits like a real link. */
.auth-link { padding: 0; font: inherit; font-weight: 800; color: var(--orange-deep); text-decoration: underline; }
.auth-link:hover { color: var(--orange); }
.auth-err { background: var(--status-danger-bg); border: 1px solid var(--status-danger-border); color: var(--danger-solid); border-radius: var(--radius-sm); padding: 10px 12px; font-size: .86rem; font-weight: 700; margin-bottom: 14px; }
.field-hint, .field-opt { font-size: .78rem; color: var(--ink-soft); font-weight: 600; }
.field-hint { margin-top: 2px; }

/* Quiet loading state — shown for the instant we mint the /admin gate cookie
   and redirect a signed-in staff member straight to the back office, and while
   /set-password redeems its emailed token. */
.auth-loading { display: grid; place-items: center; min-height: 38vh; }
.auth-loading[hidden] { display: none; }  /* display:grid above beats the UA [hidden]{display:none} — see reference_css_hidden_toggle */
.spinner { width: 38px; height: 38px; border-radius: 50%; border: 3px solid var(--orange-soft); border-top-color: var(--orange); animation: spin .7s linear infinite; }
@keyframes spin { to { transform: rotate(360deg); } }

/* /set-password holds all four of its states (checking the link → the form →
   saved → expired) in the served HTML and shows one at a time, so each takes the
   card's place with a gentle lift instead of appearing flat. The animation starts
   the moment the state stops being display:none, which is exactly the swap. */
.auth-state { animation: authStateIn .5s ease-out both; }
@keyframes authStateIn { from { opacity: 0; transform: translateY(14px); } to { opacity: 1; transform: none; } }
@media (prefers-reduced-motion: reduce) { .auth-state { animation: none; } }

/* Account dashboard (logged in) — "My Herbal Cabinet": a warm greeting band with
   the resident monarch, a cabinet-rail nav on the left, and panels of cards under
   a shelf-label heading. Ported from preview/redesigns to discuss/account-redesign.html. */
/* Greeting + layout share one gap column. */
.account-shell { display: flex; flex-direction: column; gap: clamp(18px, 3vw, 28px); }
.account-greet { position: relative; }
.account-greet__txt { display: flex; flex-direction: column; gap: 6px; }
.account-greet h1 { font-size: clamp(1.7rem, 3.4vw, 2.5rem); }
.account-greet__script { font-family: var(--script); color: var(--orange-deep); font-size: 1.15em; font-weight: 600; }
.account-greet p { color: var(--ink-soft); max-width: 56ch; }
/* The resident monarch — drifts gently beside the greeting. */
/* --drift-t / --flap-t (set inline by account.js) are negative delays that phase-
   sync the loops to a page-lifetime clock, so re-renders (tab switches) don't
   reset the butterfly to the start of its drift. */
.account-greet__flutter { position: absolute; right: clamp(20px, 8vw, 120px); top: 2px; width: 46px; height: 40px; pointer-events: none; opacity: .9; animation: acctDrift 7s ease-in-out infinite; animation-delay: var(--drift-t, 0s); }
.account-greet__flutter .wingL, .account-greet__flutter .wingR,
.acct-trail__moth .wingL, .acct-trail__moth .wingR,
.ov-sub__moth .wingL, .ov-sub__moth .wingR { transform-origin: 50% 55%; animation: acctFlap 3.2s ease-in-out infinite; animation-delay: var(--flap-t, 0s); }
.account-greet__flutter .wingR, .acct-trail__moth .wingR, .ov-sub__moth .wingR { animation-delay: calc(var(--flap-t, 0s) + .12s); }
@keyframes acctDrift { 0%, 100% { transform: translate(0, 0) rotate(-4deg); } 30% { transform: translate(-14px, -9px) rotate(3deg); } 65% { transform: translate(8px, -16px) rotate(-2deg); } }
@keyframes acctFlap { 0%, 100% { transform: scaleX(1); } 50% { transform: scaleX(.68); } }

/* The account dashboard runs wider than the site's default .wrap — the cabinet
   rail plus the content columns want the extra room. Scoped to this page so the
   rest of the site keeps --maxw. (1300 − two 48px gutters ≈ 1200 of content.) */
body[data-page="account"] .wrap { max-width: 1300px; }
.account-layout { display: grid; grid-template-columns: 260px minmax(0, 1fr); gap: clamp(20px, 3vw, 36px); align-items: start; }
/* The cabinet rail — sticky spine card; the active item earns a sage fill and an
   orange accent bar bleeding off the card's left edge. */
.account-nav { background: var(--paper); border: 1px solid var(--line); border-radius: var(--radius-lg); padding: 18px 14px; display: flex; flex-direction: column; gap: 2px; position: sticky; top: 120px; box-shadow: var(--shadow); }
.account-nav__me { display: flex; align-items: center; gap: 12px; padding: 6px 8px 12px; }
.account-nav__avatar { flex: none; display: flex; }
.account-nav__id { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.account-nav__name { font-family: var(--display); font-size: 1.02rem; line-height: 1.2; }
.account-nav__email { font-size: .76rem; color: var(--ink-soft); overflow-wrap: anywhere; }
.account-nav__item { position: relative; display: flex; align-items: center; gap: 11px; padding: 10px 12px; border-radius: var(--radius-sm); font-weight: 700; font-size: .92rem; color: var(--ink-soft); text-align: left; transition: background .16s ease, color .16s ease; }
.account-nav__item svg { width: 17px; height: 17px; color: currentColor; flex: none; }
.account-nav__item:hover { background: var(--cream-2); color: var(--ink); }
.account-nav__item.is-active { background: var(--sage-2); color: var(--pine-deep); }
.account-nav__item.is-active::before { content: ""; position: absolute; left: -14px; top: 9px; bottom: 9px; width: 4px; border-radius: 0 4px 4px 0; background: var(--orange); }
/* Count bubble trailing a nav label (the wishlist tally). */
.account-nav__bub { margin-left: auto; background: var(--orange-soft); color: var(--orange-deep); font-size: .68rem; font-weight: 800; border-radius: 999px; padding: 1px 8px; }
/* Standalone divider element above Sign out — its own row, dashed like a ledger rule. */
.account-nav__div { flex: none; height: 0; margin: 10px 0; background: none; border: 0; border-top: 1px dashed var(--line); }

.account-content { display: flex; flex-direction: column; gap: 18px; min-width: 0; }
/* A .link-back at the top of a panel (change-plan) hugs its text, not the column. */
.account-content .link-back { align-self: flex-start; }
/* Panels stagger softly into place on a fresh view (tab switch / sign-in); the
   re-renders data loads trigger add --settled, which keeps everything still. */
.account-content > * { animation: acctStagIn .5s ease backwards; }
.account-content > *:nth-child(2) { animation-delay: .06s; }
.account-content > *:nth-child(3) { animation-delay: .12s; }
.account-content > *:nth-child(4) { animation-delay: .18s; }
.account-content > *:nth-child(5) { animation-delay: .24s; }
.account-content > *:nth-child(6) { animation-delay: .3s; }
.account-content--settled > * { animation: none; }
@keyframes acctStagIn { from { opacity: 0; transform: translateY(12px); } to { opacity: 1; transform: none; } }

/* Panel heading above the cards — h2 + muted sub on one baseline, optional
   right-aligned action. The shelf label for each tab. */
.account-phead { display: flex; align-items: baseline; gap: 14px; flex-wrap: wrap; }
.account-phead h2 { font-size: clamp(1.3rem, 2.4vw, 1.7rem); }
.account-phead__sub { color: var(--ink-soft); font-size: .9rem; }
.account-phead__right { margin-left: auto; }

.account-card { background: var(--paper); border: 1px solid var(--line); border-radius: var(--radius-lg); padding: clamp(20px, 2.8vw, 28px); box-shadow: var(--shadow); }
/* Small in-card title (Plan options, Change password, Email preferences). */
.account-card__h3 { font-size: 1.12rem; margin-bottom: 6px; }
.account-card__lead { color: var(--ink-soft); font-size: .9rem; margin-bottom: 16px; }
.account-card form { max-width: 520px; }
.account-card .field { margin-bottom: 16px; }
.account-row3 { display: grid; grid-template-columns: 2fr 1fr 1fr; gap: 12px; }
.account-row2 { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; }

/* Two-column form grid (Profile) — uppercase ledger labels; spacing owned by the
   grid gap, not per-field margins. */
.acct-frm { display: grid; grid-template-columns: 1fr 1fr; gap: 14px 16px; }
.account-card--slim { max-width: 720px; }
.account-card form.acct-frm { max-width: none; }
.acct-frm .field { margin-bottom: 0; }
.acct-frm .field label { font-size: .78rem; font-weight: 800; letter-spacing: .04em; text-transform: uppercase; color: var(--ink-soft); }
.acct-frm .field label .field-opt { text-transform: none; letter-spacing: 0; }
.acct-frm .auth-err { margin-bottom: 0; }
.acct-frm__full { grid-column: 1 / -1; }
.acct-frm__foot { grid-column: 1 / -1; display: flex; gap: 10px; align-items: center; margin-top: 4px; }

/* Saved shipping addresses + payment cards — a two-up grid of tiles (account
   #addresses / #payment; the add/edit form opens in the shared MH.modal). The
   default tile is sage-tinted with a corner badge; the last slot is a dashed
   "add" tile. The checkout radio picker is the separate .addr-pick below. */
.addr-list, .pay-list { list-style: none; margin: 0; padding: 0; display: grid; grid-template-columns: repeat(2, 1fr); gap: 14px; }
.addr-card, .pay-card { position: relative; display: flex; flex-direction: column; border: 1.5px solid var(--line); border-radius: var(--radius-lg); padding: 18px 20px; background: var(--paper); transition: border-color .2s ease, transform .2s ease, box-shadow .2s ease; }
.addr-card:hover, .pay-card:hover { transform: translateY(-2px); box-shadow: var(--shadow); }
.addr-card--default, .pay-card--default { border-color: var(--green-soft); background: linear-gradient(160deg, var(--paper), var(--sage-2)); }
.addr-card__df { position: absolute; top: 14px; right: 16px; }
.addr-card__label { font-family: var(--display); font-weight: 600; font-size: 1rem; margin-bottom: 5px; }
.addr-badge { display: inline-block; vertical-align: middle; font-size: .64rem; text-transform: uppercase; letter-spacing: .08em;
  font-weight: 800; color: var(--pine-deep); background: var(--sage); border-radius: 999px; padding: 3px 9px; }
.addr-card__lines { margin: 0; font-size: .88rem; color: var(--ink-soft); line-height: 1.5; }
.addr-card__lines strong { color: var(--ink); }
.addr-card__acts { display: flex; flex-wrap: wrap; gap: 8px; margin-top: auto; padding-top: 14px; }
/* Dashed "add another" tile filling the last grid slot. */
.addr-card__slot { display: grid; }
.addr-card--add { display: grid; place-items: center; min-height: 130px; width: 100%; border-style: dashed; cursor: pointer; color: var(--ink-soft); font-weight: 800; font-size: .9rem; background: transparent; box-shadow: none; }
.addr-card--add:hover { color: var(--pine-deep); border-color: var(--green-soft); background: var(--sage-2); transform: none; box-shadow: none; }
.addr-form__actions { display: flex; gap: 10px; flex-wrap: wrap; align-items: center; }
/* "Save this address/card to my account" checkbox row (checkout). display:flex needs
   the [hidden] guard or the inline attribute won't hide it — see reference_css_hidden_toggle. */
.save-toggle { display: flex; align-items: center; gap: 9px; font-size: .88rem; font-weight: 600; color: var(--ink-soft); cursor: pointer; margin-top: 6px; }
.save-toggle input { appearance: none; -webkit-appearance: none; width: 19px; height: 19px; flex: none; cursor: pointer; margin: 0; border: 1.5px solid var(--green-soft); border-radius: 6px; background: var(--paper); transition: border-color .15s, background-color .15s; }
.save-toggle input:hover { border-color: var(--pine); }
.save-toggle input:focus-visible { outline: none; box-shadow: var(--focus-ring); }
.save-toggle input:checked { background: var(--pine) url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12'%3E%3Cpath d='M2 6.5 4.8 9.2 10 3.5' fill='none' stroke='%23fff' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E") center/12px no-repeat; border-color: var(--pine); }
.save-toggle:hover { color: var(--ink); }
.save-toggle[hidden] { display: none; }

/* Card-style checkbox — a framed option with a bold title + description that tints
   sage and shows a green tick when on. Site default; reuse anywhere a single toggle
   wants an explanation. Margins are contextual — add them at the usage site.
   <label class="check-card"><input type="checkbox">
     <span class="check-card__box" aria-hidden="true"></span>
     <span class="check-card__text"><b>Title</b>Supporting description.</span></label> */
.check-card { display: flex; align-items: flex-start; gap: 12px; padding: 13px 15px; cursor: pointer;
  border: 1px solid var(--line); border-radius: var(--radius-sm); background: var(--paper);
  transition: border-color .15s ease, background .15s ease; }
.check-card:hover { border-color: var(--green-soft); }
.check-card:has(input:checked) { border-color: var(--pine); background: var(--sage-2); }
.check-card input { position: absolute; opacity: 0; width: 0; height: 0; }
.check-card__box { flex: none; width: 20px; height: 20px; margin-top: 1px; border-radius: 6px;
  border: 1.5px solid var(--green-soft); background: var(--paper); display: grid; place-items: center;
  transition: background .15s ease, border-color .15s ease; }
.check-card__box::after { content: ""; width: 10px; height: 6px; margin-top: -2px;
  border-left: 2px solid #fff; border-bottom: 2px solid #fff; transform: rotate(-45deg) scale(0); transition: transform .15s ease; }
.check-card input:checked + .check-card__box { background: var(--pine); border-color: var(--pine); }
.check-card input:checked + .check-card__box::after { transform: rotate(-45deg) scale(1); }
.check-card input:focus-visible + .check-card__box { box-shadow: var(--focus-ring); }
.check-card__text { font-size: .84rem; line-height: 1.4; color: var(--ink-soft); }
.check-card__text b { display: block; font-size: .88rem; font-weight: 700; color: var(--ink); }
/* Small green section heading inside checkout / consultation-checkout forms. */
.form-section-h { font-size: 1rem; color: var(--pine-deep); }

/* Saved payment cards — card-specific bits; the list frame, tile frame, default
   state + corner badge + actions row are shared with the .addr-* rules above
   (comma-joined). Display data only (brand + last 4 + expiry). */
.pay-card__line { display: flex; align-items: center; gap: 14px; }
.pay-card__id { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.pay-card__id h4 { font-family: var(--display); font-weight: 600; font-size: 1rem; line-height: 1.25; }
.pay-card__meta { margin: 0; font-size: .85rem; color: var(--ink-soft); }
/* Little gradient card illustration — a warm chip + swipe line, no brand marks.
   Orange for the default card, green otherwise. */
.paychip { flex: none; width: 58px; height: 38px; border-radius: 8px; position: relative; box-shadow: var(--shadow);
  background: linear-gradient(135deg, var(--orange-deep), var(--orange)); }
.paychip::before { content: ""; position: absolute; left: 8px; top: 9px; width: 14px; height: 10px; border-radius: 3px; background: var(--honey); }
.paychip::after { content: ""; position: absolute; left: 8px; right: 8px; bottom: 8px; height: 3px; border-radius: 2px; background: color-mix(in srgb, var(--paper) 55%, transparent); }
.paychip--green { background: linear-gradient(135deg, var(--pine-deep), var(--pine)); }

/* Checkout: choose which saved address to ship to (radio cards). */
.addr-pick { display: grid; gap: 10px; margin-bottom: 12px; }
.addr-pick__opt { display: flex; align-items: flex-start; gap: 14px; cursor: pointer;
  border: 1px solid var(--line); border-radius: var(--radius); padding: 12px 14px; background: var(--paper);
  transition: border-color .15s, background .15s; }
.addr-pick__opt:has(input:checked) { border-color: var(--green-soft); background: var(--sage-2); }
.addr-pick__opt input { margin-top: 3px; width: 17px; height: 17px; flex: none; accent-color: var(--pine); }
.addr-pick__text { font-size: .9rem; color: var(--ink); line-height: 1.45; }
.addr-pick__label { font-weight: 700; }
/* An unselectable row — an expired card on file. Shown rather than dropped, so
   the shopper can see why we aren't offering it, but it can't be chosen. */
.addr-pick__opt:has(input:disabled) { cursor: default; opacity: .55; background: var(--cream-2); }
/* Picker rows ease in instead of snapping into the section: both pickers are
   painted after auth resolves, so they always arrive a beat after the form.
   Reuses the promo-reveal keyframes (the same soft 4px rise the promo row uses)
   with a short stagger over the first few rows. */
.addr-pick__opt { animation: promo-reveal .3s ease both; }
.addr-pick__opt:nth-child(2) { animation-delay: .05s; }
.addr-pick__opt:nth-child(3) { animation-delay: .1s; }
.addr-pick__opt:nth-child(n+4) { animation-delay: .15s; }
@media (prefers-reduced-motion: reduce) {
  .addr-pick__opt { animation: none; }
}

/* Checkout delivery options — Amazon-style radio cards: a carrier-free name + one
   computed arrival date + the price, grouped (Shipping / Free local pickup). Shares
   the selected-card look with .addr-pick (sage tint, green-soft border). */
.ship-opts { display: grid; gap: 16px; }
.ship-optgroup { display: grid; gap: 10px; }
.ship-optgroup__h { font-size: .72rem; font-weight: 800; letter-spacing: .05em; text-transform: uppercase; color: var(--ink-soft); }
.ship-opt { display: flex; align-items: center; gap: 16px; cursor: pointer;
  border: 1px solid var(--line); border-radius: var(--radius); padding: 13px 16px; background: var(--paper);
  transition: border-color .15s, background .15s; }
.ship-opt:hover { border-color: var(--green-soft); }
.ship-opt:has(input:checked) { border-color: var(--green-soft); background: var(--sage-2); }
.ship-opt input { width: 18px; height: 18px; flex: none; accent-color: var(--pine); margin: 0; }
.ship-opt input:focus-visible { outline: none; box-shadow: var(--focus-ring); }
.ship-opt__body { flex: 1; min-width: 0; display: flex; align-items: baseline; justify-content: space-between; gap: 12px; }
.ship-opt__main { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.ship-opt__name { font-weight: 700; color: var(--ink); }
.ship-opt__eta { font-size: .85rem; color: var(--ink-soft); }
.ship-opt__price { font-weight: 700; color: var(--ink); white-space: nowrap; }
.ship-opt.is-free .ship-opt__price { color: var(--status-done-ink); }

.account-empty { text-align: center; padding: 26px 10px; }
.account-empty svg { width: 46px; height: 46px; color: var(--green-soft); margin: 0 auto 12px; }
.account-empty p { margin: 0; }
.account-empty p.account-empty__sub { color: var(--ink-soft); font-size: .9rem; margin: 4px auto 18px; max-width: 36ch; }

.account-card--danger { border-color: var(--orange-soft); }
/* Ledger rows — one card per line item; bookings use the static form (orders
   moved to the .oacc accordion cards below). */
.account-orders { display: flex; flex-direction: column; gap: 12px; }
.account-order { display: flex; align-items: center; gap: 16px; width: 100%; text-align: left;
  font: inherit; color: var(--ink); border: 1px solid var(--line); border-radius: var(--radius-lg);
  padding: 16px 20px; background: var(--paper); box-shadow: var(--shadow); cursor: pointer; transition: background .15s, border-color .15s; }
.account-order:hover { background: var(--cream); border-color: var(--green-soft); }
/* A row with nothing to open (bookings — read-only for the customer): same card,
   no affordance it can't honour. */
.account-order--static { cursor: default; }
.account-order--static:hover { border-color: var(--line); background: var(--paper); }
.account-order__info { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.account-order__id { font-family: var(--display); font-weight: 600; font-size: 1.02rem; line-height: 1.25; }
/* Order number sits beside the display-face date — kept small + light so the date leads. */
.account-order__id .account-order__dim { font-family: var(--body); font-size: .8rem; font-weight: 600; }
/* Status line — same human label + tone as the order modal (orderStatusHead). */
.account-order__state { font-size: .84rem; font-weight: 700; }
.account-order__state--active { color: var(--orange-deep); }
.account-order__state--done   { color: var(--pine-deep); }
.account-order__state--off    { color: var(--ink-soft); }
/* Dimmed secondary text (order number, item count) trailing each info line. */
.account-order__dim { font-weight: 600; color: var(--ink-soft); }
.account-order__total { font-weight: 800; color: var(--pine-deep); white-space: nowrap; }
/* Chevron in a hairline ring — the "this opens" affordance. */
.account-order__chev { width: 26px; height: 26px; flex: none; color: var(--ink-soft); border: 1px solid var(--line); border-radius: 999px; padding: 4px; }
/* Order detail (rendered into the modal body) */
.account-order__head { display: flex; flex-direction: column; gap: 8px; padding-bottom: var(--order-gap, 16px); border-bottom: 1px solid var(--line); }
.account-order__title { font-family: var(--display); font-size: 1.3rem; font-weight: 600; line-height: 1.12; letter-spacing: -.01em; color: var(--ink); padding-right: 34px; }
.account-order__line { display: flex; align-items: center; gap: 16px; }
.account-order__line-img { width: 80px; height: 80px; flex: none; border-radius: var(--radius); border: 1px solid var(--line); }
img.account-order__line-img { object-fit: cover; background: var(--paper); }
.account-order__line-body { flex: 1; min-width: 0; }
.account-order__line-name { font-weight: 700; font-size: .95rem; }
.account-order__line-meta { font-size: .8rem; color: var(--ink-soft); }
.account-order__line-price { font-weight: 700; white-space: nowrap; color: var(--pine-deep); }
/* Amazon-style status headline (tone set by JS) — its own flex column keeps the title +
   subtext tight; the body's --order-gap spaces it from the blocks around it. */
.account-order__status { display: flex; flex-direction: column; gap: 4px; }
.account-order__status-title { font-family: var(--display); font-weight: 700; font-size: clamp(1.5rem, 6vw, 1.85rem); line-height: 1.15; letter-spacing: -.01em; color: var(--pine-deep); }
.account-order__status-sub { font-size: .95rem; color: var(--ink-soft); }
.account-order__status--active .account-order__status-title { color: var(--orange-deep); }
.account-order__status--off .account-order__status-title { color: var(--ink-soft); }
/* Order header bar (Amazon-style): "Order placed <date>" | "Order # <id>". */
.account-order__bar { display: flex; align-items: stretch; gap: 14px; font-size: .78rem; }
.account-order__bar-item { display: inline-flex; align-items: baseline; gap: 6px; min-width: 0; }
.account-order__bar-k { color: var(--ink-soft); }
.account-order__bar-v { color: var(--ink); font-weight: 700; overflow-wrap: anywhere; }
.account-order__bar-sep { flex: none; width: 1px; background: var(--line); }
/* Soft tinted cards group the flat list into distinct blocks (delivery info + receipt). */
.account-order__panel { background: var(--cream-2); border: 1px solid var(--line); border-radius: var(--radius); padding: 14px 16px; }
.account-order__facts { display: grid; gap: 12px; }
/* Ship-to (recipient + stacked address) left; fulfilment + payment method stacked right. */
.account-order__facts-cols { display: grid; grid-template-columns: 1fr 1fr; gap: 12px 20px; }
.account-order__facts-col { display: grid; gap: 12px; align-content: start; }
/* Receipt: a flex column with a gap; the money rows + dividers are explicit divs (own
   classes so cart/checkout keep the shared .summary-row). */
.account-order__summary { display: flex; flex-direction: column; gap: 10px; }
.account-order__row { display: flex; justify-content: space-between; font-size: .96rem; }
.account-order__row > span:last-child { font-weight: 700; }
.account-order__row--discount > span { color: var(--pine-deep); }
.account-order__row--discount > span:last-child { font-weight: 800; }
.account-order__row--total { font-family: var(--display); font-size: 1.35rem; font-weight: 600; color: var(--ink); }
.account-order__hr { height: 1px; background: var(--line); }
.account-order__hr--total { height: 2px; background: var(--line); }
.account-order__fact { font-size: .88rem; overflow-wrap: anywhere; }
.account-order__fact-k { font-size: .75rem; text-transform: uppercase; letter-spacing: .07em; font-weight: 800; color: var(--ink); margin-bottom: 3px; }
.account-order__fact-v { line-height: 1.4; color: var(--ink); }
.account-order__actions .btn { width: 100%; }
/* Receipt item list: a capped scroll box so a long order's rows scroll while the money
   rows + Total below (siblings, outside the box) stay put. wireOrderScroll() drives it
   through the shared MH.scrollFade, which toggles .is-scrollable (rows overflow → show
   fade + pill) and .is-bottom (scrolled to the end → hide both) on .account-order__scroll. */
.account-order__scroll { position: relative; --scrollfade-bg: var(--cream-2); }   /* fade lands on the panel, not the page */
/* The item list scrolls only once the whole modal reaches its max-height — not at a fixed
   row count. The modal → scroll port → body → receipt → list are a flex column with
   min-height:0 at every level, so a tall order shrinks the list (it scrolls) while the money
   rows + Total stay pinned; a short order that fits shows every row. .modal__scroll
   keeps its overflow-y:auto as a last-ditch fallback if even the fixed blocks can't fit. */
.modal--order .modal__scroll { display: flex; flex-direction: column; }
.modal--order .modal__body { min-height: 0; }
.modal--order .account-order__summary { min-height: 0; }
.modal--order .account-order__scroll { min-height: 0; display: flex; flex-direction: column; }
/* On-brand scrollbar (matches .search-scroll) hidden until the list is hovered: the 10px
   gutter is always reserved (no layout shift) — only the thumb colour appears, --line on
   hover then --ink-soft on the thumb itself. The fade + pill still hint the scroll. */
.account-order__lines { display: flex; flex-direction: column; gap: 10px; flex: 1 1 auto; min-height: 0; overflow-y: auto;
  scrollbar-width: thin; scrollbar-color: transparent transparent; }
.account-order__lines:hover { scrollbar-color: var(--line) transparent; }
.account-order__lines::-webkit-scrollbar { width: 10px; }
.account-order__lines::-webkit-scrollbar-track { background: transparent; }
.account-order__lines::-webkit-scrollbar-thumb { background: transparent; border-radius: 999px; border: 3px solid var(--cream-2); }
.account-order__lines:hover::-webkit-scrollbar-thumb { background: var(--line); }
.account-order__lines::-webkit-scrollbar-thumb:hover { background: var(--ink-soft); }
/* The fade + its "N more items" pill are both the shared .mh-scrollfade /
   .mh-scrollmore pattern; the receipt only tints the fade (--scrollfade-bg above). */

/* ---- Orders — expandable cards (/account/orders). Header = order #, placed
   date + item count, status pill, total, ring chevron; the dropdown carries the
   monarch tracking trail, the item lines and the actions (Track package /
   Order details opens the full modal). Most recent starts open. ---- */
.oacc-list { display: flex; flex-direction: column; gap: 14px; }
.oacc { background: var(--paper); border: 1px solid var(--line); border-radius: var(--radius-lg); box-shadow: var(--shadow); overflow: hidden; }
.oacc__head { display: flex; align-items: center; gap: 16px; width: 100%; text-align: left; font: inherit; color: var(--ink); padding: 16px 20px; cursor: pointer; transition: background .15s; }
.oacc__head:hover { background: var(--cream); }
.oacc__lead { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.oacc__id { font-family: var(--display); font-weight: 600; font-size: 1.05rem; line-height: 1.2; }
.oacc__meta { font-size: .82rem; color: var(--ink-soft); }
.oacc__total { margin-left: auto; font-weight: 800; white-space: nowrap; }
.oacc__chev { flex: none; width: 26px; height: 26px; border-radius: 999px; border: 1px solid var(--line); display: grid; place-items: center; color: var(--ink-soft); transition: transform .28s ease; }
.oacc__chev svg { width: 14px; height: 14px; }
.oacc.is-open .oacc__chev { transform: rotate(180deg); }
/* The dropdown — a grid-rows accordion so height animates without a fixed cap. */
.oacc__body { display: grid; grid-template-rows: 0fr; transition: grid-template-rows .38s cubic-bezier(.4, 0, .2, 1); }
.oacc.is-open .oacc__body { grid-template-rows: 1fr; }
.oacc__inner { overflow: hidden; min-height: 0; }
.oacc__pad { display: flex; flex-direction: column; gap: 16px; padding: 4px 20px 20px; border-top: 1px dashed var(--line); }
.oacc__lines { display: flex; flex-direction: column; gap: 10px; }
.oacc__line { display: flex; align-items: center; gap: 12px; background: var(--cream); border: 1px solid var(--line); border-radius: var(--radius); padding: 9px 14px 9px 9px; }
.oacc__line-img { width: 46px; height: 46px; flex: none; border-radius: var(--radius-sm); border: 1px solid var(--line); }
img.oacc__line-img { object-fit: cover; background: var(--paper); }
.oacc__line-body { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 1px; }
.oacc__line-name { font-weight: 800; font-size: .9rem; line-height: 1.3; }
.oacc__line-meta { font-size: .78rem; color: var(--ink-soft); }
.oacc__line-price { font-weight: 800; font-size: .9rem; white-space: nowrap; }
.oacc__foot { display: flex; gap: 10px; flex-wrap: wrap; }
/* "Show all N orders" expander — closes the capped preview list; the list's own
   gap owns the space around it. Revealed cards enter on the shared acctStagIn
   (delays set inline per card by account.js). */
.oacc-more { display: flex; justify-content: center; }
.oacc--enter { animation: acctStagIn .5s ease backwards; }

/* ---- Buy it again — restock strip below the order list (/account/orders). Up
   to four of the customer's most-restocked products (MH.orders.buyAgain,
   frequency-first) as the shared buy-again mini card (buyAgainRow — same row as
   the overview cell). NOT a card: it's an open section on the page (no panel box)
   so it doesn't mimic another order card. A shared .mh-divider hairline above it
   (in its own no-gap .bagain-block) marks the zone boundary off the order list;
   the white .ovba__row tiles carry the visual weight, flipped to paper so they
   read crisp on the open cream page. Here the cards run two-up and scaled up
   (.bagain-grid) for the roomier tab, staggering in on the shared acctStagIn. -- */
.bagain-block { display: block; }
/* Divider owns the air across the zone break — a little above (the panel gap
   already seats the block), more below before the heading. */
.bagain-block .mh-divider { margin: 6px 0 22px; }
.bagain-sec { display: flex; flex-direction: column; gap: 14px; }
.bagain-sec__head { display: flex; flex-direction: column; gap: 2px; }
.bagain-sec__head h3 { font-family: var(--display); font-size: 1.15rem; }
.bagain-sec__head p { font-size: .84rem; color: var(--ink-soft); }
.bagain-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(260px, 1fr)); gap: 12px; }
.bagain-grid > .ovba__row { padding: 14px 15px; gap: 14px; align-items: stretch; background: var(--paper); box-shadow: var(--shadow); animation: acctStagIn .5s ease backwards; }
/* Cards in a grid row are equal height (grid stretch); let the txt column fill
   that height and split top/bottom so the Add-to-basket button always sits on the
   baseline, however many lines the name wraps to. */
.bagain-grid > .ovba__row .ovba__txt { justify-content: space-between; }
.bagain-grid > .ovba__row:nth-child(2) { animation-delay: .05s; }
.bagain-grid > .ovba__row:nth-child(3) { animation-delay: .1s; }
.bagain-grid > .ovba__row:nth-child(4) { animation-delay: .15s; }
.bagain-grid > .ovba__row .ovba__img { width: 74px; }
.bagain-grid > .ovba__row .ovba__name { font-size: .98rem; }
.bagain-grid > .ovba__row .ovba__price { font-size: .92rem; }
.bagain-grid > .ovba__row .ovba__meta { font-size: .8rem; }
.bagain-grid > .ovba__row .ovba__btn { font-size: .8rem; padding: 7px 16px; }

/* Order status pill (dot + status word) on each card header. Honey is mixed from
   the token (no minted literal) — the in-transit tone between processing-orange
   and delivered-green. */
.opill { display: inline-flex; align-items: center; gap: 6px; flex: none; border-radius: 999px; font-size: .68rem; font-weight: 800; letter-spacing: .05em; text-transform: uppercase; padding: 4px 12px; white-space: nowrap; }
.opill__dot { width: 7px; height: 7px; border-radius: 999px; background: currentColor; }
/* Not an order yet — the checkout was never paid for (status 'Pending payment').
   Deliberately the quietest pill of the set: muted ink, no colour of its own, so
   it reads as "unfinished" rather than as a stage of a real order. */
.opill--pending-payment { background: color-mix(in srgb, var(--ink-soft) 12%, var(--paper)); color: var(--ink-soft); }
.opill--processing { background: var(--status-new-bg); color: var(--orange-deep); }
.opill--shipped { background: color-mix(in srgb, var(--honey) 22%, var(--paper)); color: color-mix(in srgb, var(--honey) 55%, #000); }
.opill--delivered { background: var(--status-done-bg); color: var(--status-done-ink); }
.opill--cancelled { background: var(--status-danger-bg); color: var(--status-danger-ink); }

/* ---- Order tracking trail — the signature moment: a monarch perched on the
   current stage of the journey, shown in each expanded order card. On a fresh
   render the fill bar + moth start at 0 and glide to the stage (placeTrails in
   account.js); settled renders inline the final state. padding-top gives the
   moth headroom above the bar. ---- */
/* Trail geometry: --trail-edge (set inline by account.js) is half a stop
   column, so the bar/fill run dot-center to dot-center — no line before the
   first stop or after the last. */
.acct-trail { position: relative; padding: 20px 0 0; --trail-edge: 12.5%; }
.acct-trail__bar { position: absolute; left: var(--trail-edge); right: var(--trail-edge); top: 31px; height: 3px; background: var(--sage); border-radius: 999px; }
.acct-trail__fill { position: absolute; left: var(--trail-edge); top: 31px; height: 3px; background: var(--pine); border-radius: 999px; width: 0; max-width: calc(100% - var(--trail-edge) * 2); transition: width 1s .25s cubic-bezier(.4, 0, .2, 1); }
.acct-trail__stops { position: relative; display: flex; justify-content: space-between; }
.acct-trail__stop { display: flex; flex-direction: column; align-items: center; gap: 6px; flex: 1; }
.acct-trail__dot { width: 25px; height: 25px; border-radius: 999px; background: var(--paper); border: 2.5px solid var(--sage); display: grid; place-items: center; font-size: .68rem; line-height: 1; color: transparent; transition: border-color .3s ease, background .3s ease, color .3s ease; z-index: 1; }
.acct-trail__stop.is-done .acct-trail__dot { background: var(--pine); border-color: var(--pine); color: #fff; }
.acct-trail__lb { font-size: .72rem; font-weight: 800; color: var(--ink-soft); text-transform: uppercase; letter-spacing: .05em; }
.acct-trail__stop.is-done .acct-trail__lb { color: var(--pine-deep); }
.acct-trail__dt { font-size: .72rem; color: var(--ink-soft); margin-top: -5px; }
.acct-trail__moth { position: absolute; top: 2px; left: var(--trail-edge); width: 30px; height: 26px; transform: translateX(-50%); transition: left 1s .25s cubic-bezier(.4, 0, .2, 1); }

/* ---- Overview — "the ledger": the latest order leads as the hero (warm status
   headline + the monarch tracking trail), membership gets the page's single
   deep-pine panel with a compact next-box card beside it, then the supporting
   cell row (wishlist / buy-again / consultations). ---- */
/* Three lanes left-to-right (story | trail | doors) so the card stays shallow;
   the CTA pins to the last column so the no-orders state (body + cta only)
   keeps its buttons on the right. */
.ov-order { display: grid; grid-template-columns: minmax(0, 1fr) minmax(300px, 1.15fr) auto; gap: clamp(18px, 3vw, 34px); align-items: center;
  background: linear-gradient(120deg, var(--paper) 55%, var(--sage-2)); border: 1px solid var(--line); border-radius: var(--radius-lg);
  padding: clamp(20px, 3vw, 30px); box-shadow: var(--shadow-lg); }
.ov-order__body { display: flex; flex-direction: column; gap: 10px; min-width: 0; }
.ov-order__track { display: flex; flex-direction: column; gap: 2px; min-width: 0; align-self: center; }
.ov-order__meta--sub { text-align: center; font-size: .82rem; max-width: none; }
.ov-order__head { display: flex; flex-direction: column; gap: 2px; }
.ov-order__kicker { font-size: .76rem; font-weight: 800; letter-spacing: .13em; text-transform: uppercase; color: var(--orange-deep); }
.ov-order__head h2 { font-size: clamp(1.25rem, 2.4vw, 1.6rem); }
.ov-order__meta { font-size: .88rem; color: var(--ink-soft); max-width: 52ch; }
.ov-order__meta b { color: var(--ink); }
.ov-order__items { display: flex; gap: 8px; }
.ov-order__thumb { width: 44px; height: 44px; border-radius: var(--radius-sm); border: 1px solid var(--line); transition: transform .2s ease; }
img.ov-order__thumb { object-fit: cover; background: var(--cream-2); }
img.ov-order__thumb:hover { transform: translateY(-2px) scale(1.05); }
.ov-order__cta { display: flex; flex-direction: column; gap: 9px; align-items: stretch; grid-column: -2; }
/* Membership pine panel + its side card (buy-again; the S&S next-box card
   before the first order) — on the SAME three-column grid as the cell row
   below (panel spans two columns), so the seam lines up with the cards'
   gutter. */
.ov-club { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 16px; }
.ov-club .club-hero { grid-column: span 2; }
/* The overview variant of .club-hero: a botanical fleuron in the corner, a
   tighter title, and body-font facts (the panel is narrower here). */
.club-hero--ov::before { content: "❦"; position: absolute; right: -14px; bottom: -34px; font-size: 9rem; line-height: 1;
  color: rgb(from var(--pine-bright) r g b / .07); pointer-events: none; }
.club-hero--ov h3 { font-size: clamp(1.2rem, 2.2vw, 1.45rem); }
.club-hero--ov .club-hero__fact .v { font-family: var(--body); font-weight: 700; font-size: .92rem; }
.club-hero--ov .club-hero__cta { margin-top: auto; }
.ov-club__top { display: flex; align-items: center; justify-content: space-between; gap: 10px; }
.ov-club__top .club-badge { margin-left: 0; }
/* The S&S box wears a soft sage wash + green hairline (vs the plain paper
   cells) so the living, scheduled thing reads apart — without echoing the
   membership panel's full pine. The resident monarch perches on its top edge
   (position: relative anchors it; wings share the greet/trail flap). */
.ov-sub { position: relative; display: flex; flex-direction: column; gap: 12px; background: linear-gradient(120deg, var(--sage-2), var(--paper) 70%);
  border: 1px solid var(--green-soft); border-radius: var(--radius-lg); padding: 20px 22px; box-shadow: var(--shadow); }
.ov-sub__moth { position: absolute; top: -21px; right: 30px; width: 34px; height: 30px; transform: rotate(-5deg); pointer-events: none; }
.ov-sub__head { display: flex; flex-direction: column; }
.ov-sub__top { display: flex; align-items: flex-start; justify-content: space-between; gap: 10px; }
.ov-sub__top h3 { font-size: 1rem; }
.ov-sub p { font-size: .86rem; color: var(--ink-soft); }
.ov-sub p b { color: var(--ink); }
.ov-sub__row { display: flex; align-items: center; justify-content: space-between; gap: 10px; }
.ov-sub__thumbs { display: flex; flex-wrap: wrap; gap: 6px; }
.ov-sub__thumb { width: 100px; height: 100px; border-radius: var(--radius-sm); border: 1px solid var(--line); }
img.ov-sub__thumb { object-fit: cover; background: var(--cream-2); }
/* Supporting cells fold the small stats into their context. auto-fit: the
   S&S box only joins this row once there's a past order (see overviewPanel),
   so the row reflows on its own. The S&S box goes double-wide, mirroring the
   membership panel on the row above (wishlist 1 col, box 2). */
.ov-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); grid-auto-rows: minmax(210px, auto); gap: 16px; }
/* The S&S box has two sizes: single-track by default, double-wide with the
   --wide modifier (account.js sets it from the batch's thumb count for now). */
.ov-grid .ov-sub--wide { grid-column: span 2; }
.ov-cell { background: var(--paper); border: 1px solid var(--line); border-radius: var(--radius-lg); padding: 18px 20px; box-shadow: var(--shadow);
  display: flex; flex-direction: column; gap: 8px; transition: transform .2s ease, box-shadow .2s ease; }
.ov-cell:hover { transform: translateY(-3px); box-shadow: var(--shadow-lg); }
.ov-cell__top { display: flex; align-items: center; justify-content: space-between; }
.ov-cell__note { font-size: .74rem; color: var(--ink-soft); text-align: right; }
.ov-cell h3 { font-size: 1rem; white-space: nowrap; }
.ov-cell p { font-size: .86rem; color: var(--ink-soft); }
.ov-cell__go { margin-top: auto; align-self: flex-start; display: inline-flex; align-items: center; gap: 5px; padding: 0;
  border: 0; background: none; color: var(--orange-deep); font-weight: 800; font-size: .85rem; cursor: pointer; }
.ov-cell__go:hover { text-decoration: underline; }
.ov-cell__go::after { content: "→"; transition: transform .18s ease; }
.ov-cell__go:hover::after { transform: translateX(3px); }
/* Wishlist cell: a plain paper card — heart chip in the title row (echoing
   the shop's save affordance), one line of copy, the go-link, and a faint
   heart watermark filling the corner. */
.ov-cell--wish { position: relative; overflow: hidden; }
.ov-cell--wish::after { content: "♥"; position: absolute; right: -14px; bottom: -38px; font-size: 8rem; line-height: 1;
  color: rgb(from var(--orange) r g b / .06); pointer-events: none; }
.ov-wish__heart { width: 30px; height: 30px; border-radius: 999px; flex: none; display: grid; place-items: center;
  background: color-mix(in srgb, var(--orange-soft) 60%, var(--paper)); color: var(--orange-deep); }
.ov-wish__heart svg { width: 15px; height: 15px; }
/* The overview cells' closing action — a green pill in the card's bottom-left
   corner, under the thumbs (S&S) / opposite the heart watermark (wishlist). */
.ov-wish__btn, .ov-sub__btn { margin-top: auto; align-self: flex-start; }
/* Buy-again cell: a tap-to-add mini list of the most-reordered products (rows
   fire [data-buyagain]). Each row is a full-width button — thumb, name + cadence
   sub, price, and a soft ＋ that fills orange on hover to read as "add". */
.ovba__list { display: flex; flex-direction: column; gap: 8px; }
.ovba__row { display: flex; align-items: flex-start; gap: 11px;
  background: var(--cream); border: 1px solid var(--line); border-radius: var(--radius); padding: 10px 11px; }
/* Product photos are portrait, not square — let the thumb take the image's own
   aspect (fixed width, auto height) so there's no letterbox to crop or pad, and
   centre it vertically in the row. */
.ovba__img { width: 58px; height: auto; align-self: center; flex: none; display: block;
  border-radius: var(--radius-sm); border: 1px solid var(--line); background: var(--cream-2); }
/* Info block (name + price) stacks tight; the Buy-again button sits below it
   with the txt column's wider gap owning the space. */
.ovba__txt { display: flex; flex-direction: column; gap: 4px; flex: 1 1 auto; min-width: 0; }
.ovba__info { display: flex; flex-direction: column; gap: 3px; min-width: 0; }
/* Name wraps to two lines instead of truncating — with the action moved below,
   the words get the full row width to tell the product apart. */
.ovba__name { font-weight: 800; font-size: .86rem; line-height: 1.25;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
.ovba__sub { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.ovba__price { font-weight: 800; font-size: .82rem; color: var(--ink); }
.ovba__meta { font-size: .74rem; color: var(--ink-soft); }
.ovba__btn { align-self: flex-start; border: 1px solid var(--green-soft); background: var(--paper); color: var(--pine-deep);
  font: inherit; font-weight: 800; font-size: .74rem; padding: 5px 13px; border-radius: 999px; cursor: pointer;
  transition: background .15s ease, color .15s ease, border-color .15s ease; }
.ovba__btn:hover { background: var(--pine); color: var(--pine-cream); border-color: var(--pine); }
.ovba__btn:focus-visible { outline: none; box-shadow: var(--focus-ring); }

/* ── Toggle switch (canonical) ────────────────────────────────────────────
   A labelled on/off pill — track slides pine when checked. Markup:
   <label class="mh-switch"><input type="checkbox"><span class="mh-switch__tr"></span><span>Label</span></label> */
.mh-switch { display: inline-flex; align-items: center; gap: 9px; cursor: pointer; font-size: .88rem; font-weight: 700; color: var(--ink-soft); user-select: none; }
.mh-switch:hover { color: var(--ink); }
.mh-switch input { position: absolute; opacity: 0; width: 0; height: 0; }
.mh-switch__tr { flex: none; width: 42px; height: 24px; border-radius: 999px; background: var(--sage); position: relative; transition: background .25s ease; }
.mh-switch__tr::after { content: ""; position: absolute; top: 3px; left: 3px; width: 18px; height: 18px; border-radius: 999px; background: var(--paper); box-shadow: 0 1px 4px rgba(56, 42, 20, .3); transition: left .25s cubic-bezier(.4, 0, .2, 1); }
.mh-switch input:checked + .mh-switch__tr { background: var(--pine); }
.mh-switch input:checked + .mh-switch__tr::after { left: 21px; }
.mh-switch input:focus-visible + .mh-switch__tr { box-shadow: var(--focus-ring); }

/* Password-strength bar (account #security + /set-password) — a slim track whose
   fill widens and warms from orange to pine as the new password strengthens
   (MH.paintPwMeter in site.js sets data-score). Empty at rest, so the resting
   state is just the hint text.
   Words first, track immediately after them (Finn's call — it was pinned to the
   field's right edge for a beat, which read as two separate things). The bar
   shifts a little as the wording changes with the score; that's accepted. */
.pw-meter { display: flex; align-items: center; gap: 10px; }
.pw-meter__lb { min-width: 0; font-size: .78rem; font-weight: 700; color: var(--ink-soft); }
.pw-meter__track { position: relative; overflow: hidden; flex: none; width: 110px; height: 7px; border-radius: 999px; background: var(--cream-2); }
.pw-meter__fill { position: absolute; inset: 0 auto 0 0; width: 0; border-radius: inherit; background: var(--orange); transition: width .4s cubic-bezier(.4, 0, .2, 1), background-color .3s ease; }
.pw-meter[data-score="1"] .pw-meter__fill { width: 25%; }
.pw-meter[data-score="2"] .pw-meter__fill { width: 50%; }
.pw-meter[data-score="3"] .pw-meter__fill { width: 75%; background: color-mix(in srgb, var(--pine) 60%, var(--green-soft)); }
.pw-meter[data-score="4"] .pw-meter__fill { width: 100%; background: var(--pine); }

/* ---- Membership / Monarch Herbal Club (account) ---- */
/* The member hero — a deep-pine card with a slow sheen, script welcome tag and
   a facts row (status / since / renews). */
.club-hero { position: relative; overflow: hidden; display: flex; flex-direction: column; gap: 8px;
  background: linear-gradient(135deg, var(--pine-deep), var(--pine) 70%); color: var(--pine-cream);
  border-radius: var(--radius-lg); padding: clamp(22px, 3vw, 32px); box-shadow: var(--shadow-lg); }
.club-hero::after { content: ""; position: absolute; top: -40%; left: -60%; width: 50%; height: 180%;
  background: linear-gradient(100deg, transparent, color-mix(in srgb, var(--pine-bright) 4%, transparent) 40%,
    color-mix(in srgb, var(--pine-bright) 4%, transparent) 60%, transparent);
  transform: rotate(8deg); animation: clubSheen 6s ease-in-out infinite; }
@keyframes clubSheen { 0%, 55%, 100% { left: -60%; } 35% { left: 120%; } }
.club-hero__tag { font-family: var(--script); font-size: 1.4rem; color: var(--marigold); }
.club-hero h3 { font-size: clamp(1.4rem, 2.6vw, 1.9rem); color: var(--pine-bright); }
.club-hero p { color: var(--pine-cream); font-size: .92rem; max-width: 56ch; }
.club-hero__facts { display: flex; gap: 26px; flex-wrap: wrap; padding-top: 10px; }
.club-hero__fact { display: flex; flex-direction: column; gap: 2px; }
.club-hero__fact .k { font-size: .7rem; font-weight: 800; letter-spacing: .1em; text-transform: uppercase; color: var(--green-soft); }
.club-hero__fact .v { font-family: var(--display); font-size: 1.15rem; color: var(--pine-bright); }
/* The hero's door row — "Open your lessons" (/videos) on the membership tab,
   lessons + manage on the overview variant. Sits above the sheen sweep. */
.club-hero__cta { position: relative; z-index: 1; display: flex; gap: 10px; flex-wrap: wrap; padding-top: 4px; }
/* The full membership tab uses the hero's open right side as a compact control
   rail. Copy stays generous on the left; facts + full-width actions sit on the
   right, cutting the card's height without squeezing its message. */
.club-hero--member { display: grid; grid-template-columns: minmax(0, 1fr) minmax(190px, 220px); align-items: center; gap: clamp(24px, 4vw, 48px); padding-block: clamp(22px, 2.6vw, 28px); }
.club-hero__intro, .club-hero__tools { position: relative; z-index: 1; display: flex; flex-direction: column; }
.club-hero__intro { gap: 8px; }
.club-hero__tools { gap: 14px; }
.club-hero--member .club-hero__facts { padding-top: 0; }
.club-hero--member .club-hero__cta { flex-direction: column; padding-top: 0; }
.club-hero--member .club-hero__cta .btn { width: 100%; }
/* Perk tiles under the hero. */
.club-perkgrid { display: grid; grid-template-columns: repeat(2, 1fr); gap: 12px; }
.club-perk { display: flex; gap: 12px; align-items: center; background: var(--paper); border: 1px solid var(--line); border-radius: var(--radius); padding: 14px 16px; font-size: .9rem; box-shadow: var(--shadow); }
.club-perk__ic { flex: none; width: 36px; height: 36px; border-radius: 999px; background: var(--sage-2); display: grid; place-items: center; color: var(--pine-deep); }
.club-perk__ic svg { width: 17px; height: 17px; }
.club-badge { display: inline-block; font-size: .66rem; text-transform: uppercase; letter-spacing: .07em; font-weight: 800; padding: 3px 9px; border-radius: 999px; vertical-align: middle; margin-left: 6px; }
.club-badge--active { background: var(--sage); color: var(--pine-deep); }
.club-badge--paused { background: var(--cream-2); color: var(--ink-soft); }
.club-badge--cancelled { background: var(--status-danger-bg); color: var(--status-danger-ink); }
/* Labelled control column (label over a select / qty stepper) — the S&S Manage
   modal's delivery-frequency + quantity controls. The account change-plan screen
   reuses the /education pricing column instead (.edu-pricing / .plan /
   .edu-compare — see switchPlan in account.js). */
.club-cycle { display: inline-flex; flex-direction: column; gap: 5px; margin: 4px 0 18px; font-size: .8rem; font-weight: 700; color: var(--ink-soft); }
.club-cycle select { font: inherit; font-weight: 600; padding: 9px 12px; border: 1px solid var(--line); border-radius: var(--radius-sm); background: var(--paper); color: var(--ink); }
.club-cancel { color: var(--status-danger-ink); border-color: var(--status-danger-border); }
.club-cancel:hover { background: var(--status-danger-bg); border-color: color-mix(in srgb, var(--status-danger-border) 55%, var(--status-danger-ink)); }

/* Subscribe & Save — the /account/subscriptions tab. Three stacked moments: a
   preferred-delivery-day card (calendar seal + Change-day → the day-picker
   modal), the next-delivery hero (item tiles beside a cream receipt card), and
   the subscribed-item cards (each opens the Manage modal). The Manage modal
   (.sub-detail__*, filled via .modal--sub) borrows the order modal's block
   language; its Reschedule picker stacks above it via MH.modal.openTop. */
.sub-stack { display: flex; flex-direction: column; gap: 20px; }
/* Preferred-delivery-day card — the seal shows the chosen day of the month. */
.sub-dayrow { display: flex; align-items: center; gap: 16px; flex-wrap: wrap; background: var(--paper); border: 1px solid var(--line); border-radius: var(--radius-lg); box-shadow: var(--shadow); padding: 16px 20px; }
.sub-seal { flex: none; width: 58px; display: flex; flex-direction: column; border-radius: var(--radius-sm); border: 1px solid var(--line); overflow: hidden; background: var(--paper); box-shadow: var(--shadow-soft); }
.sub-seal__top { background: var(--orange); color: #fff; font-size: .58rem; font-weight: 800; letter-spacing: .14em; text-transform: uppercase; text-align: center; padding: 3px 2px; }
.sub-seal__num { font-family: var(--display); font-weight: 600; font-size: 1.5rem; line-height: 1.3; text-align: center; color: var(--ink); }
.sub-seal--unset .sub-seal__num { font-family: var(--script); font-size: 1.15rem; line-height: 1.7; color: var(--ink-soft); }
.sub-dayrow__txt { flex: 1; min-width: 220px; display: flex; flex-direction: column; }
.sub-dayrow__t { font-weight: 800; font-size: .98rem; color: var(--ink); }
.sub-dayrow__s { font-size: .83rem; color: var(--ink-soft); }
/* The day-picker modal's 1–28 grid. */
.sub-daypick { display: grid; grid-template-columns: repeat(7, 1fr); gap: 7px; }
.sub-daypick button { aspect-ratio: 1; border-radius: var(--radius-sm); border: 1px solid var(--line); background: var(--paper); font: inherit; font-weight: 800; font-size: .88rem; color: var(--ink-soft); cursor: pointer; transition: border-color .15s, background .15s, color .15s; }
.sub-daypick button:hover { border-color: var(--green-soft); color: var(--pine-deep); }
.sub-daypick button.is-on { background: var(--orange); border-color: var(--orange); color: #fff; }
/* Subscribed-item cards — a two-up grid; the whole card opens the Manage modal. */
.sub-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 14px; }
.sub-items { display: flex; flex-direction: column; gap: 14px; }
.sub-card { display: flex; align-items: center; gap: 14px; width: 100%; text-align: left;
  padding: 16px; border: 1px solid var(--line); border-radius: var(--radius-lg); background: var(--paper);
  box-shadow: var(--shadow); cursor: pointer; transition: border-color .2s ease, transform .2s ease, box-shadow .2s ease; }
.sub-card:hover { border-color: var(--green-soft); transform: translateY(-3px); box-shadow: var(--shadow-lg); }
.sub-card--paused { background: repeating-linear-gradient(-45deg, var(--paper), var(--paper) 14px, var(--cream) 14px, var(--cream) 15px); }
.sub-card--paused .sub-card__media { opacity: .55; }
.sub-card__media { width: 60px; height: 60px; flex: none; border-radius: 12px; border: 1px solid var(--line); }
img.sub-card__media { object-fit: cover; background: var(--paper); }
.sub-card__info { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 3px; }
/* ×N count marker at the end of a product name (sub cards, next-delivery rows,
   order-detail modal lines) when more than one ships — bold brand-orange text,
   no background, so it pops without reading as a status chip. */
.sub-qty-x { font-family: var(--body); font-weight: 800; font-size: .86em; color: var(--orange-deep); white-space: nowrap; }
/* Paused/Cancelled pill on its own row between the name and the meta lines. */
.sub-card__status { line-height: 1; }
.sub-card__status .club-badge { margin-left: 0; }
.sub-card__name { font-family: var(--display); font-weight: 600; font-size: 1.1rem; color: var(--ink); line-height: 1.2; }
.sub-card__meta { font-size: .8rem; color: var(--ink-soft); }
/* Chevron in a hairline circle — nudges right as the card lifts. */
.sub-card__chev { width: 26px; height: 26px; flex: none; border-radius: 999px; border: 1px solid var(--line); display: grid; place-items: center; color: var(--ink-soft); transition: background .2s ease; }
.sub-card__chev svg { width: 13px; height: 13px; }
.sub-card:hover .sub-card__chev { background: var(--sage-2); }
.sub-card--cancelled .sub-card__media { opacity: .5; }
.sub-card--cancelled .sub-price__now { color: var(--ink-soft); }
/* Shared subscription price block — regular price struck → Subscribe & Save price →
   per-unit breakdown (when >1 ships). ONE block for the item cards AND the
   Manage-modal panel, so every price reads identically. The modal keeps the
   right-aligned stack; cards use the --inline variant, one baseline row. */
.sub-price { display: flex; flex-direction: column; align-items: flex-end; gap: 2px; flex: none; text-align: right; }
.sub-price--inline { flex-direction: row; align-items: baseline; gap: 6px; text-align: left; flex-wrap: wrap; }
.sub-price__amt { white-space: nowrap; }
.sub-price__was { font-weight: 700; font-size: .82rem; color: var(--ink-soft); }
.sub-price__now { font-weight: 800; font-size: 1rem; color: var(--pine-deep); }
.sub-price__per { font-weight: 700; font-size: .74rem; color: var(--ink-soft); }
.sub-price__unit { font-weight: 700; font-size: .72rem; color: var(--ink-soft); white-space: nowrap; }
/* Next-delivery hero — "Arriving <date>" over the box: cream item tiles beside a
   cream receipt card (subtotal → discount → shipping → tax → total + one Skip),
   on the same warm gradient as the overview hero. */
.sub-next { display: flex; flex-direction: column; gap: 16px; background: linear-gradient(120deg, var(--paper) 58%, var(--sage-2)); border: 1px solid var(--line); border-radius: var(--radius-lg); box-shadow: var(--shadow-lg); padding: clamp(20px, 3vw, 28px); }
.sub-next__head { display: flex; flex-direction: column; gap: 2px; }
.sub-next__label { font-size: .7rem; font-weight: 800; text-transform: uppercase; letter-spacing: .08em; color: var(--orange-deep); }
.sub-next__when { display: flex; align-items: baseline; gap: 12px; flex-wrap: wrap; }
.sub-next__date { font-family: var(--display); font-weight: 600; font-size: clamp(1.3rem, 2.6vw, 1.6rem); line-height: 1.15; color: var(--ink); }
.sub-next__away { font-family: var(--script); font-size: 1.25rem; font-weight: 600; color: var(--pine); white-space: nowrap; }
/* The box: items left, receipt card right. */
.sub-next__slip { display: grid; grid-template-columns: minmax(0, 1fr) 300px; gap: clamp(18px, 3vw, 28px); align-items: start; }
.sub-next__items { display: flex; flex-direction: column; gap: 10px; }
.sub-next__item { display: flex; align-items: center; gap: 13px; background: var(--cream); border: 1px solid var(--line); border-radius: var(--radius); box-shadow: var(--shadow-soft); padding: 10px 16px 10px 10px; }
.sub-next__img { width: 54px; height: 54px; flex: none; border-radius: var(--radius-sm); border: 1px solid var(--line); }
img.sub-next__img { object-fit: cover; background: var(--paper); }
.sub-next__item-info { flex: 1; min-width: 0; }
.sub-next__item-name { font-family: var(--display); font-weight: 600; font-size: 1.02rem; line-height: 1.25; color: var(--ink); }
.sub-next__item-meta { font-size: .78rem; color: var(--ink-soft); margin-top: 1px; }
/* Rows show the LIST price (it sums to Subtotal; the discount is one summed line). */
.sub-next__item-amt { flex: none; font-weight: 800; font-size: 1rem; color: var(--pine-deep); white-space: nowrap; }
/* Receipt card: rows → divider → total → Skip → the packed-with-care stamp. */
.sub-next__sum { display: flex; flex-direction: column; gap: 12px; background: var(--cream); border: 1px solid var(--line); border-radius: var(--radius); box-shadow: var(--shadow-soft); padding: 18px 20px 16px; }
/* Free-shipping progress atop the receipt rows — the shared bar (MH.shipBar), filled
   post-render; collapse the mount until it lands so the card's gap doesn't double. */
.sub-next__shipbar:empty { display: none; }
.sub-next__shipbar .ship-bar { margin: 0; }
.sub-next__rows { display: flex; flex-direction: column; gap: 7px; }
.sub-next__row { display: flex; align-items: baseline; justify-content: space-between; gap: 12px; font-size: .9rem; color: var(--ink-soft); }
.sub-next__row--save { color: var(--pine-deep); font-weight: 700; }
.sub-next__div { border: 0; border-top: 1px solid var(--line); margin: 2px 0; }
.sub-next__total { display: flex; align-items: baseline; justify-content: space-between; gap: 12px; font-weight: 700; color: var(--ink); }
.sub-next__total-amt { font-family: var(--display); font-weight: 600; font-size: 1.35rem; color: var(--pine-deep); }
.sub-next__skip { width: 100%; }
.sub-next__foot { font-family: var(--script); font-size: 1.05rem; color: var(--orange-deep); text-align: center; transform: rotate(-2deg); }
.sub-next__note { font-size: .83rem; color: var(--ink-soft); }
.sub-next__note b { color: var(--pine-deep); }
/* Heading over the full list once the next-delivery hero splits the section. */
.sub-section__h { font-family: var(--display); font-weight: 600; font-size: 1.25rem; color: var(--ink); margin: 0; }
/* Manage-modal body (fills MH.modal via .modal--sub) */
.sub-detail__head { display: flex; flex-direction: column; gap: 6px; padding-bottom: var(--sub-gap, 16px); border-bottom: 1px solid var(--line); }
.sub-detail__title { font-family: var(--display); font-size: 1.5rem; font-weight: 600; line-height: 1.14; letter-spacing: -.01em; color: var(--ink); padding-right: 34px; }
.sub-detail__bar { font-size: .8rem; color: var(--ink-soft); }
.sub-detail__status { display: flex; flex-direction: column; gap: 4px; }
.sub-detail__status-title { font-family: var(--display); font-weight: 700; font-size: clamp(1.4rem, 5.5vw, 1.7rem); line-height: 1.15; letter-spacing: -.01em; color: var(--pine-deep); }
.sub-detail__status-sub { font-size: .92rem; color: var(--ink-soft); }
.sub-detail__status--off .sub-detail__status-title { color: var(--ink-soft); }
.sub-detail__panel { display: flex; align-items: center; gap: 14px; background: var(--cream-2); border: 1px solid var(--line); border-radius: var(--radius); padding: 12px 16px; }
.sub-detail__panel-img { width: 60px; height: 60px; flex: none; border-radius: 12px; border: 1px solid var(--line); }
img.sub-detail__panel-img { object-fit: cover; background: var(--paper); }
.sub-detail__panel-info { flex: 1; min-width: 0; }
.sub-detail__panel-name { font-weight: 700; font-size: 1rem; color: var(--ink); line-height: 1.25; }
.sub-detail__panel-meta { font-size: .8rem; color: var(--ink-soft); margin-top: 2px; }
.sub-detail__actions { display: grid; gap: 10px; }
.sub-detail__actions .btn { width: 100%; }
/* Pause + Cancel share one row, equal halves (Cancel on the right). */
.sub-detail__row2 { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; }
/* "Reschedule next delivery" picker — stacked above the Manage modal (openSubMonths
   via MH.modal.openTop): a tappable list of upcoming months; picking one moves the
   next delivery. Also dressed by these: the day-picker modal's hint. */
.sub-months__hint { font-size: .92rem; color: var(--ink-soft); line-height: 1.5; }
.sub-months { display: flex; flex-direction: column; gap: 8px; }
.sub-months__opt { display: flex; align-items: center; justify-content: space-between; gap: 10px; width: 100%; padding: 13px 16px; font: inherit; font-weight: 700; text-align: left; color: var(--ink); background: var(--paper); border: 1px solid var(--line); border-radius: var(--radius-sm); cursor: pointer; transition: border-color .15s, background .15s; }
.sub-months__opt:hover, .sub-months__opt.is-current { border-color: var(--pine); background: var(--sage); }
.sub-months__tag { font-size: .72rem; font-weight: 800; letter-spacing: .04em; text-transform: uppercase; color: var(--pine-deep); }
/* The box goes single-column (receipt under the items) once the panel narrows;
   the item-card grid follows on phones. */
@media (max-width: 1000px) { .sub-next__slip { grid-template-columns: 1fr; } }
@media (max-width: 700px) { .sub-grid { grid-template-columns: 1fr; } }

/* Mid widths: the trail lane gets cramped between the story and the buttons —
   drop it to its own full-width row under the pair. */
@media (max-width: 1150px) {
  .ov-order { grid-template-columns: minmax(0, 1fr) auto; }
  .ov-order__track { grid-column: 1 / -1; }
}
@media (max-width: 880px) {
  .account-layout { grid-template-columns: 1fr; }
  /* The rail lies down: identity up top, items in a swipeable row. */
  .account-nav { position: static; flex-direction: row; flex-wrap: nowrap; overflow-x: auto; align-items: center; padding: 10px 12px; }
  .account-nav__me { flex: none; padding: 6px 8px; }
  .account-nav__id { display: none; }
  .account-nav__item { flex: none; }
  .account-nav__item.is-active::before { display: none; }
  .account-nav__div { display: none; }
  .account-greet__flutter { right: 8px; }
  .ov-order { grid-template-columns: 1fr; }
  .ov-order__cta { flex-direction: row; flex-wrap: wrap; }
  .ov-club { grid-template-columns: 1fr; }
  .ov-club .club-hero { grid-column: auto; }
  .addr-list, .pay-list { grid-template-columns: 1fr; }
  .club-perkgrid { grid-template-columns: 1fr; }
  .acct-frm { grid-template-columns: 1fr; }
  .acct-trail__dt { display: none; }
}
@media (max-width: 700px) {
  .club-hero--member { grid-template-columns: 1fr; gap: 18px; }
  .club-hero__tools { gap: 12px; }
  .club-hero--member .club-hero__cta { flex-direction: row; }
  .club-hero--member .club-hero__cta .btn { width: auto; }
}
@media (max-width: 560px) {
  /* The cell grid is down to one track here — the S&S box can't span two. */
  .ov-grid .ov-sub--wide { grid-column: auto; }
  /* Order-card header wraps: id + date take the first row, pill/total/chevron the second. */
  .oacc__head { flex-wrap: wrap; gap: 8px 14px; }
  .oacc__lead { flex: 1 1 100%; }
}
@media (prefers-reduced-motion: reduce) {
  .account-greet__flutter, .account-greet__flutter .wingL, .account-greet__flutter .wingR,
  .acct-trail__moth .wingL, .acct-trail__moth .wingR, .ov-sub__moth .wingL, .ov-sub__moth .wingR,
  .account-content > *, .club-hero::after, .bagain-grid > .ovba__row, .oacc--enter { animation: none; }
  .acct-trail__fill, .acct-trail__moth { transition: none; }
}
@media (max-width: 480px) {
  .account-row3, .account-row2 { grid-template-columns: 1fr; }
  /* Stack the order header bar so the long value doesn't overflow a phone-width modal. */
  .account-order__bar { flex-direction: column; align-items: flex-start; gap: 3px; }
  .account-order__bar-sep { display: none; }
  .account-order__facts-cols { grid-template-columns: 1fr; }
  /* Stack the Reschedule / Pause pair so the labels aren't cramped on a phone-width modal. */
  .sub-detail__row2 { grid-template-columns: 1fr; }
  /* Stack frequency + quantity on a phone-width modal too. */
  .modal--sub .sub-detail__controls { grid-template-columns: 1fr; }
  .club-hero--member .club-hero__cta { display: grid; grid-template-columns: 1fr; }
  .club-hero--member .club-hero__cta .btn { width: 100%; }
}

/* ---------- Education (Herbal Wellness Collective) page ---------- */
/* Split hero — copy left, photo right in an offset honey frame with a paper
   guarantee badge. Rides the shared .hero / .hero__grid scaffolding. */
.edu-hero h1 { font-size: clamp(2.1rem, 4.4vw, 3.4rem); }
.edu-hero h1 em { font-style: normal; color: var(--pine); }
.edu-hero .lead { max-width: 52ch; }
.edu-hero__hint { font-family: var(--script); font-size: 1.25rem; color: var(--pine); align-self: center; }
.edu-hero__pic { position: relative; }
.edu-hero__pic img { width: 100%; aspect-ratio: 4 / 3.4; object-fit: cover; border-radius: var(--radius-lg); box-shadow: var(--shadow-lg); }
.edu-hero__pic::before { content: ""; position: absolute; inset: -14px 14px 14px -14px; border: 2px solid var(--honey); border-radius: var(--radius-lg); opacity: .55; }
.edu-hero__badge { position: absolute; left: -12px; bottom: 22px; display: flex; align-items: center; gap: 10px; background: var(--paper); border: 1px solid var(--line); border-radius: var(--radius); box-shadow: var(--shadow); padding: 12px 18px; }
.edu-hero__badge .n { font-family: var(--display); font-size: 1.5rem; font-weight: 600; color: var(--orange-deep); }
.edu-hero__badge .t { font-size: .8rem; color: var(--ink-soft); line-height: 1.3; }

/* "What's inside" strip — three icon cells on a hairlined sage band. */
.edu-inside { border-top: 1px solid var(--line); border-bottom: 1px solid var(--line); }
.edu-inside__grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 22px; }
.edu-cell { display: flex; align-items: flex-start; gap: 14px; }
.edu-cell__txt { display: flex; flex-direction: column; gap: 4px; }
.edu-cell h3 { font-size: 1.05rem; }
.edu-cell p { font-size: .9rem; }
.edu-dot { flex: none; width: 46px; height: 46px; border-radius: 999px; background: var(--paper); border: 1px solid var(--line); display: grid; place-items: center; color: var(--pine-deep); }
.edu-dot svg { width: 22px; height: 22px; }

/* Pricing column — billing toggle, plan pair, comparison table and fineprint
   share one gap parent. Consumers: /education and the account membership
   change-plan screen (switchPlan in account.js). */
.edu-pricing { display: flex; flex-direction: column; gap: clamp(26px, 4vw, 40px); }
.edu-cycle { position: relative; display: flex; justify-content: center; }
/* Paper-tracked skin of the shared .mh-seg sliding switcher (pine thumb). */
.edu-cycle .mh-seg { gap: 6px; padding: 5px; background: var(--paper); border: 1px solid var(--line); box-shadow: var(--shadow); --seg-fill: var(--pine); }
.edu-cycle .mh-seg button { padding: 9px 24px; font-weight: 800; font-size: .92rem; }
.edu-cycle__save { position: absolute; left: calc(50% + 118px); top: -6px; display: flex; flex-direction: column; align-items: center; gap: 2px; font-family: var(--script); font-size: 1.25rem; line-height: 1.2; color: var(--orange-deep); transform: rotate(-4deg); white-space: nowrap; }

/* Roots-vs-Rhythm feature comparison table */
.edu-compare { width: 100%; max-width: 860px; margin-inline: auto; background: var(--paper); border: 1px solid var(--line); border-radius: var(--radius-lg); overflow: hidden; box-shadow: var(--shadow); }
.edu-compare__scroll { overflow-x: auto; }
.edu-compare table { width: 100%; border-collapse: collapse; font-size: .92rem; }
.edu-compare th, .edu-compare td { padding: 13px 20px; text-align: center; border-top: 1px solid var(--line); }
.edu-compare th:first-child, .edu-compare td:first-child { text-align: left; }
.edu-compare thead th { border-top: 0; background: var(--sage-2); font-family: var(--display); font-size: 1rem; font-weight: 600; padding: 16px 20px; }
.edu-compare thead th small { display: block; font-family: var(--body); font-size: .75rem; font-weight: 700; color: var(--ink-soft); }
.edu-compare tbody tr:nth-child(even) td { background: var(--cream); }
.edu-compare .yes svg { width: 18px; height: 18px; color: var(--pine); margin-inline: auto; }
.edu-compare .no { color: var(--line); }
.edu-fineprint { text-align: center; font-size: .85rem; }

@media (max-width: 880px) {
  .edu-hero__pic { order: -1; max-width: 480px; margin-inline: auto; }
  .edu-cycle__save { display: none; }
  .edu-inside__grid { grid-template-columns: 1fr; }
}

/* ---------- Reveal on scroll ---------- */
.reveal { opacity: 0; transform: translateY(18px); transition: opacity .6s ease, transform .6s ease; }
.reveal.in { opacity: 1; transform: none; }
/* Entrance stagger for sibling reveals visible on load. NOTE: the delay applies to
   every transitioned property, so keep data-d off elements whose hover state rides
   the same transition (or accept the small hover lag, as the spanels do). */
.reveal[data-d="1"] { transition-delay: .08s; }
.reveal[data-d="2"] { transition-delay: .16s; }
.reveal[data-d="3"] { transition-delay: .24s; }
.reveal[data-d="4"] { transition-delay: .32s; }

/* ---------- Responsive ---------- */
@media (max-width: 1020px) {
  .footer-top { grid-template-columns: 1fr 1fr; }
  .grid--4 { grid-template-columns: repeat(3, 1fr); }
}
@media (max-width: 880px) {
  .header-search { display: none; }
  /* Phone header: [hamburger] [brand] [account · wishlist · cart]. The desktop
     brand is a 90px badge + 2.5rem wordmark — far too big beside the toggle and
     three tools, so it wrapped and overflowed. Shrink the badge + wordmark to a
     single clean row and pull the tool icons in tight. */
  .header-inner { grid-template-columns: auto 1fr auto; gap: 8px; }
  .brand { justify-self: start; gap: 9px; }
  /* !important beats the inline width/height MH.logo(90) writes on the <img>. */
  .site-header .brand__mark { width: 46px !important; height: 46px !important; }
  .brand__name { font-size: 1.5rem; white-space: nowrap; }
  .brand__tag { font-size: 1.05rem; white-space: nowrap; }
  .header-tools { gap: 2px; }
  .site-nav { display: none; }
  .nav-toggle { display: inline-grid; }
  /* Botanical watermarks sit above the content (z-index 3) at the section's
     left/right edges. Once columns stack full-width they fall behind the copy
     and fight it for legibility, so drop the decorative layer on phones. */
  .botanical { display: none; }
  /* Announcement bar: stack the default line's three segments onto their own
     rows (shipping / local pickup / & weekend markets) rather than wrapping
     mid-phrase. seg1 stays inline with the logo mark; the "·" separator hides. */
  .announce__dot { display: none; }
  .announce__seg:not(:first-of-type) { display: block; }
  .hero__grid, .split, .pdp, .cartpage { grid-template-columns: 1fr; }
  /* Stacked, there's no summary alongside to match — the floor would only pad the basket. */
  .cartpage--basket.is-single .cart-basket { min-height: 0; }
  .cart-summary, .co-summary-col { position: static; }
  .hero__art { order: -1; max-width: 420px; margin-inline: auto; }
  .price-grid { grid-template-columns: 1fr; max-width: 420px; margin-inline: auto; }
  .grid--3, .grid--4 { grid-template-columns: repeat(2, 1fr); }
  .shopby { grid-template-columns: 1fr; }
  .feature-list--cols { grid-template-columns: 1fr; }
  .value-band { grid-template-columns: repeat(2, 1fr); }
  .value-band li:nth-child(3) { border-left: none; }
  .value-band li:nth-child(n+3) { border-top: 1px solid var(--line); }
}
@media (max-width: 560px) {
  body { font-size: 16px; }
  /* Breadcrumbs wrap to two or three ragged lines on a phone and push the real
     content down for little navigational gain — the back gesture and the header
     cover it. Hidden visually only: the BreadcrumbList JSON-LD is injected
     separately (MH.injectLd), so Google still sees the trail. */
  .crumbs { display: none; }
  /* Phones: drop the script tagline and tighten the wordmark so the whole
     header holds one clean row — badge + name + the three tool icons. */
  .header-inner { gap: 6px; }
  .brand__tag { display: none; }
  .brand__name { font-size: 1.3rem; }
  .site-header .brand__mark { width: 44px !important; height: 44px !important; }
  .header-inner .icon-btn { width: 40px; height: 40px; }
  .value-band { grid-template-columns: 1fr; }
  .value-band li + li { border-left: none; border-top: 1px solid var(--line); }
  .grid--2, .grid--3, .grid--4, .grid--cards { grid-template-columns: 1fr 1fr; }
  .footer-top { grid-template-columns: 1fr; }
  .footer-bottom { justify-content: center; text-align: center; }
  .linklist { columns: 1; }
  .hero__badge { width: 92px; height: 92px; }
  .product__add .btn { padding: .6em .9em; font-size: .78rem; }
}
@media (max-width: 420px) {
  .grid--3, .grid--4, .grid--cards { grid-template-columns: 1fr; }
  /* Product cards never stack — a shopper scans a 2-wide grid at every phone
     width (category pages, the home Apothecary/Bundles rows, shop, wishlist).
     Scoped to grids actually holding .product cards, so the concern, journal,
     market and review card grids still fall to one column as before. Comes
     after the rule above so it wins at equal specificity. */
  .grid:has(> .product) { grid-template-columns: 1fr 1fr; gap: 12px; }
  /* Half-width cards: tighten the copy block so the name, price and add button
     still breathe at ~150px wide. */
  .grid:has(> .product) .product__body { padding: 11px 11px 13px; gap: 6px; }
  .grid:has(> .product) .product__name { font-size: .95rem; }
  .grid:has(> .product) .product__desc { font-size: .78rem; }
  .grid:has(> .product) .product__fav { width: 30px; height: 30px; }
  .grid:has(> .product) .product__fav svg { width: 16px; height: 16px; }
  /* Narrowest phones: keep the "Monarch Herbs" wordmark, just tighten the badge,
     name and tools so it all stays on one clean row beside the icons. */
  .header-inner { gap: 4px; }
  .brand { gap: 7px; }
  .brand__name { font-size: 1.1rem; }
  .site-header .brand__mark { width: 40px !important; height: 40px !important; }
  .header-inner .icon-btn { width: 38px; height: 38px; }
}
@media (max-width: 374px) {
  /* Sub-iPhone widths (older/smaller phones down to 320px): shave a touch more
     so the wordmark and all three tools still clear the right edge. */
  .brand__name { font-size: .95rem; }
  .site-header .brand__mark { width: 36px !important; height: 36px !important; }
  .header-inner .icon-btn { width: 32px; height: 32px; }
  .icon-btn svg { width: 18px; height: 18px; }
}
