/* Korai Studio — shared base styles.

   Loaded on every page (see base.html). Rules that belong to exactly one
   page/feature live in frontend/static/css/pages/<page>.css instead —
   this file is only what's genuinely reused across more than one of
   those: design tokens, reset, header/nav, footer, buttons, typography,
   the product-card grid (shared by home/shop/product-related), form
   fields, and generic status/notice blocks.

   Palette is sampled directly from the logo (app/static/img/logo.png),
   not approximated: Cream #FFF3DB · Forest #044B09 · Terracotta #DE8672.
   --charcoal was near-black (#232323); replaced with a deep brick red
   (#6B2419) — it's the site's one "ink" color, doing double duty as body
   text *and* solid UI blocks (buttons, the announce bar, the subscribe
   section), so it had to stay dark enough to read as text: contrast
   against cream is 10.1:1, still past WCAG AAA's 7:1 for body copy, not
   just safe as an accent.
   Variable names (--olive/--rose/--charcoal) predate this palette and
   are kept as-is to avoid renaming ~50 call sites across this file,
   admin.css, and templates for a cosmetic-only change — what matters is
   the value. --gold is unused here (kept only because admin.css references it). */

:root {
  --cream:      #FFF3DB;
  --cream-deep: #F5E4C3;
  --charcoal:   #6B2419;
  --ink-soft:   #6A6560;
  --olive:      #044B09;
  --olive-deep: #033807;
  --rose:       #DE8672;
  --gold:       #C9A35C;
  --line:       #E9D9BC;

  --display: "Cormorant Garamond", Georgia, serif;
  --body:    "Montserrat", -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;

  --gutter: 1.75rem;
  --measure: 1180px;
}

@media (min-width: 900px) { :root { --gutter: 2.5rem; } }

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

/* Content is capped at --measure (1180px) and centered for a readable
   line length — on wide monitors that leaves real empty margin either
   side of it. Previously filled with a criss-crossed diagonal texture
   (two overlapping repeating-linear-gradients) so the margins didn't
   read as blank space; removed on request — a flat cream ground reads
   calmer, and .wrap's own solid background already covers the actual
   reading column regardless. */
body {
  margin: 0;
  background-color: var(--cream);
  color: var(--charcoal);
  font-family: var(--body);
  font-size: 15px;
  font-weight: 400;
  line-height: 1.65;
  -webkit-font-smoothing: antialiased;
}

img { max-width: 100%; display: block; }
a { color: inherit; text-decoration: none; }

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

.skip {
  position: absolute; left: -999px;
  background: var(--charcoal); color: var(--cream);
  padding: .75rem 1rem; z-index: 100;
}
.skip:focus { left: 1rem; top: 1rem; }

/* ------------------------------------------------------------ header */

.announce {
  background: var(--olive);
  color: var(--cream);
  text-align: center;
  font-size: .68rem;
  letter-spacing: .16em;
  text-transform: uppercase;
  padding: .6rem 1rem;
}

/* `backdrop-filter` is desktop-only (see the >=900px block below), not
   decorative — it's a real constraint, not a preference: `backdrop-
   filter` (like `filter`/`transform`) creates a *containing block* for
   `position: fixed` descendants (CSS spec), and .nav (below) is
   `position: fixed` on mobile so it can cover the full viewport as the
   menu overlay. With the blur applied directly here, .nav's "fixed"
   positioning was silently being contained by the header's own
   ~77px-tall box instead of the viewport, so the mobile menu rendered
   squeezed into that thin strip near the top instead of as a real
   full-screen overlay.
   A `::before` pseudo-layer (leaf node, can't have descendants, so it
   can't create that trap) was tried first as a fix that keeps the blur
   on mobile too — reverted after it still rendered blank in real Chrome
   (incognito, no extensions) despite every DOM/CSSOM check looking
   correct; sticky positioning + a negative-z-index blurred pseudo
   appears to hit a genuine Chrome compositing bug, not a spec issue this
   codebase can control. Simplest robust fix instead: skip the blur on
   mobile entirely, where .nav is `position: fixed` and the
   containing-block problem can actually occur — plain solid
   `background: var(--cream)` below, `backdrop-filter` added back only
   inside the `@media (min-width: 900px)` block further down, where .nav
   is `position: static` and immune to this whole class of bug. */
.site-header {
  position: sticky; top: 0; z-index: 40;
  display: grid;
  grid-template-columns: 2rem 1fr auto;
  align-items: center;
  gap: 1rem;
  padding: 1rem var(--gutter);
  background: var(--cream);
  border-bottom: 1px solid var(--line);
}

.wordmark { display: flex; justify-content: center; }
.wordmark img { height: 44px; width: auto; }

.menu-toggle {
  display: grid; gap: 5px;
  background: none; border: 0; padding: 0; cursor: pointer;
  width: 22px;
}
.menu-toggle span { height: 1px; background: var(--charcoal); display: block; }

/* `display: none` when closed, not an off-screen `position:fixed` +
   negative-inset offset — that approach (tried first) put a full-
   viewport-sized fixed box directly adjacent to the visible viewport at
   all times (inset: 0 0 0 -100% == a box exactly viewport-width wide,
   its right edge flush against the real viewport's left edge), and in
   real Chrome testing it was intermittently hit-testable/paintable over
   the actual page even while "closed" (confirmed via DevTools'
   right-click-to-inspect landing on a `.nav` descendant while every
   computed style claimed it was positioned off-screen) — surfacing as
   the entire homepage rendering blank because the closed nav's own
   `background: var(--cream)` was covering everything beneath it.
   `display: none` has no such failure mode: a closed nav isn't part of
   the render tree at all, so it cannot occupy screen space or intercept
   a click by accident, full stop. */
.nav {
  display: none;
  position: fixed; inset: 0;
  background: var(--cream);
  flex-direction: column;
  gap: .5rem;
  padding: 6rem var(--gutter);
  font-family: var(--display);
  font-size: 2rem;
  z-index: 45;
}
.nav[data-open] { display: flex; }

/* The hamburger that opens this menu lives in the header, which this
   overlay covers (z-index 45 vs the header's 40) — with no close control
   *inside* the menu, an open menu had no way to close except Escape, see
   mobile-menu.js. Hidden at desktop (.nav is position:static there, not
   an overlay, so there's nothing to close) via the same >=900px block
   that already repositions the rest of .nav. */
.nav-close {
  position: absolute; top: 1.25rem; right: var(--gutter);
  background: none; border: 0; padding: .25rem .5rem;
  font-family: var(--body); font-size: 2rem; line-height: 1;
  color: var(--charcoal); cursor: pointer;
}

/* Collections dropdown — mobile-first: on mobile there's one top-level
   collapsible group, its heading styled to match the other top-level
   .nav links (Shop, Best Sellers, New Arrivals) since it sits in the
   same list and reads as one of them, not a smaller sub-item. Its
   "Launching Soon" sub-section (.dropdown-subgroup) is its own nested
   collapsible, independent of the outer one — opening "Collections"
   doesn't itself open "Launching Soon". The `>` combinators below are
   what keep the two levels independent: without them, a plain
   descendant selector on .dropdown-group[data-open] would also catch
   the subgroup's own arrow/links buried inside it. Desktop turns the
   whole thing into an actual hover/focus popup — see the media query
   below, which hides the mobile-only headings/arrows (the outer
   .dropdown-trigger button already says "Collections" there) and always
   shows both levels of .dropdown-links. */
.dropdown-trigger {
  display: none;
  font: inherit; letter-spacing: inherit; text-transform: inherit; color: inherit;
  background: none; border: 0; padding: 0; margin: 0; cursor: default;
}
.dropdown-panel { margin: .35rem 0 0 .1rem; }
.dropdown-group { margin: .6rem 0; }
.dropdown-heading {
  display: flex; align-items: center; justify-content: space-between; gap: .6rem;
  width: 100%; font: inherit; color: inherit; margin: 0;
  background: none; border: 0; padding: 0; cursor: pointer;
}
.dropdown-arrow {
  flex: none; width: .45em; height: .45em;
  border-right: 2px solid currentColor; border-bottom: 2px solid currentColor;
  transform: rotate(-45deg); transition: transform .2s ease; margin-top: -.15em;
}
.dropdown-group[data-open] > .dropdown-heading .dropdown-arrow { transform: rotate(45deg); margin-top: 0; }
.dropdown-links { display: none; padding-top: .6rem; }
.dropdown-group[data-open] > .dropdown-links { display: block; }
.dropdown-subgroup { margin-top: .9rem; }
.dropdown-subheading {
  display: flex; align-items: center; justify-content: space-between; gap: .5rem;
  width: 100%; font-family: var(--body); font-size: .68rem; letter-spacing: .14em;
  text-transform: uppercase; color: var(--charcoal); margin: 0;
  background: none; border: 0; padding: 0; cursor: pointer;
}
.dropdown-subgroup[data-open] > .dropdown-subheading .dropdown-arrow { transform: rotate(45deg); margin-top: 0; }
.dropdown-subgroup > .dropdown-links { padding-top: .4rem; }
.dropdown-subgroup[data-open] > .dropdown-links { display: block; }
.dropdown-panel a { display: block; padding: .2rem 0; font-size: .82em; }

.header-actions { display: flex; align-items: center; gap: 1.1rem; }

.account-link {
  font-size: .72rem;
  letter-spacing: .14em;
  text-transform: uppercase;
}

.cart-link {
  font-size: .72rem;
  letter-spacing: .14em;
  text-transform: uppercase;
  display: inline-flex; align-items: center; gap: .4rem;
}
.cart-count {
  background: var(--olive); color: var(--cream);
  border-radius: 999px;
  min-width: 1.15rem; height: 1.15rem;
  display: grid; place-items: center;
  font-size: .62rem;
}

@media (min-width: 900px) {
  .site-header {
    grid-template-columns: 1fr auto 1fr;
    background: rgba(255,243,219, .92);
    backdrop-filter: blur(8px);
  }
  .menu-toggle { display: none; }
  .nav-close { display: none; }
  .wordmark { order: -1; justify-content: flex-start; }
  .wordmark img { height: 52px; }
  .nav {
    display: flex; /* always visible at desktop — no hamburger/[data-open] gate here */
    position: static; inset: auto;
    flex-direction: row; align-self: stretch; align-items: center; gap: 2rem;
    padding: 0; background: none;
    font-family: var(--body);
    font-size: .74rem;
    letter-spacing: .14em;
    text-transform: uppercase;
    justify-content: center;
  }
  .header-actions { justify-self: end; }

  /* `align-self: stretch` (on both .nav and .dropdown) makes .dropdown's
     own box span the full header row height, not just its trigger text's
     line height — so the absolutely-positioned panel's `top: 100%` lands
     exactly at the header's bottom edge on its own, no guessed pixel
     margin needed to clear the (taller, logo-driven) header above it. */
  .dropdown { position: relative; align-self: stretch; display: flex; align-items: center; }
  .dropdown-trigger {
    display: flex; align-items: center; gap: .35rem; cursor: pointer;
  }
  .dropdown-panel {
    display: none;
    position: absolute; top: 100%; left: 50%; transform: translateX(-50%);
    margin-top: 1.5rem; /* clears .site-header's padding-bottom (1rem) plus a small visual gap */
    background: var(--cream); border: 1px solid var(--line);
    padding: 1.5rem 1.4rem 1.1rem; min-width: 190px;
    box-shadow: 0 16px 32px rgba(107,36,25,.1);
    text-align: left; z-index: 46;
  }
  .dropdown:hover .dropdown-panel, .dropdown:focus-within .dropdown-panel { display: block; }
  .dropdown-group { margin: 0; }
  /* The mobile accordion heading is a no-op here — the whole panel is
     already gated by :hover/:focus-within above (the outer
     .dropdown-trigger button already reads "Collections"), so showing
     it too would just duplicate that text again, the exact bug fixed
     for mobile earlier. */
  .dropdown-heading { display: none; }
  /* Hides the (inert, always-expanded) accordion arrows inside the
     panel — not the trigger's own arrow just below, which is the real
     open/closed indicator for the hover popup out here. */
  .dropdown-heading .dropdown-arrow, .dropdown-subheading .dropdown-arrow { display: none; }
  .dropdown:hover .dropdown-trigger .dropdown-arrow,
  .dropdown:focus-within .dropdown-trigger .dropdown-arrow { transform: rotate(45deg); margin-top: 0; }
  .dropdown-links { display: block; padding-top: 0; }
  .dropdown-panel a {
    font-size: .74rem; letter-spacing: .06em; text-transform: none;
    padding: .3rem 0;
  }
  /* Reads as a plain section label here, not a control — the panel is
     already always-expanded via :hover/:focus-within, so the tap-target
     styling (cursor, etc.) from the mobile accordion button would be
     misleading. */
  .dropdown-subgroup { margin-top: .9rem; padding-top: .9rem; border-top: 1px solid var(--line); }
  .dropdown-subheading { cursor: default; margin: 0 0 .4rem; }
}

.flash {
  background: var(--olive);
  color: var(--cream);
  padding: .8rem var(--gutter);
  font-size: .8rem;
}

/* -------------------------------------------------------------- type */

h1, h2, h3 { font-family: var(--display); font-weight: 300; margin: 0; }
h1 { font-size: clamp(2.5rem, 9vw, 4.75rem); line-height: 1.02; }
h2 { font-size: clamp(1.7rem, 4.5vw, 2.5rem); line-height: 1.15; }

.eyebrow {
  font-size: .66rem;
  letter-spacing: .2em;
  text-transform: uppercase;
  color: var(--ink-soft);
  margin: 0 0 1rem;
}

/* Solid backdrop on the reading column itself — without this, sections
   that put .wrap directly on the <section> (no separate inner div) show
   body's margin texture uniformly across their full width, so there's no
   visible line between "margin" and "content" and the texture reads as
   faint everywhere rather than filling the empty space specifically. */
.wrap { max-width: var(--measure); margin: 0 auto; padding: 0 var(--gutter); background: var(--cream); }

/* Tried widening this to 1400px so the filter sidebar + 3-up grid had
   more room. Reverted: a sidebar + 3 cards don't actually need much past
   --measure's 1180px, so the extra width mostly just created new empty
   space elsewhere (widest visibly in .page-head) rather than being used
   by anything. Kept as its own class rather than deleted in case a wider
   grid (4-up, more filters) makes the extra room earn its keep later. */
.wrap-wide { max-width: var(--measure); }

.btn {
  display: inline-block;
  font-size: .72rem;
  letter-spacing: .16em;
  text-transform: uppercase;
  padding: .95rem 2rem;
  border: 1px solid var(--charcoal);
  background: var(--charcoal);
  color: var(--cream);
  cursor: pointer;
  font-family: var(--body);
  transition: background .2s, color .2s;
}
.btn:hover { background: var(--olive-deep); border-color: var(--olive-deep); }
.btn.ghost { background: none; color: var(--charcoal); }
.btn.ghost:hover { background: var(--charcoal); color: var(--cream); }
.btn[disabled] { opacity: .4; cursor: not-allowed; }
.btn.wide { width: 100%; text-align: center; }

/* ------------------------------------------------------------- grid */

/* Longhand top/bottom only — a `padding: Y 0` shorthand here would reset
   left/right to 0 and clobber .wrap's own horizontal gutter on any
   element carrying both classes (most homepage sections), pulling their
   text flush to the viewport edge on mobile. */
.section { padding-top: clamp(3rem, 8vw, 5.5rem); padding-bottom: clamp(3rem, 8vw, 5.5rem); }

.section-head {
  display: flex; justify-content: space-between; align-items: baseline;
  gap: 1rem; margin-bottom: 2.5rem;
  border-bottom: 1px solid var(--line);
  padding-bottom: 1rem;
}
.section-head a { font-size: .7rem; letter-spacing: .14em; text-transform: uppercase; }

/* Product grid — 3 per row everywhere it's used (home, /shop, related
   products) once there's room; 2 on narrow phones only. Deliberately not
   4-up at wide viewports, so the row count stays 3 regardless of screen
   size instead of reflowing at the 1080px breakpoint. Shared by
   home.html, shop.html, and product.html's related-products strip via
   the one _card.html partial — not page-specific. */
.grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 1.25rem 1rem;
}
@media (min-width: 640px) { .grid { grid-template-columns: repeat(3, 1fr); gap: 2.5rem 1.75rem; } }

/* The card is the signature: a hairline index, then the name set in
   Cormorant, so the shop floor reads like a contents page. */
.card { position: relative; }
.card-media {
  position: relative;
  aspect-ratio: 3 / 4;
  background: var(--cream-deep);
  overflow: hidden;
}
.card-media img {
  width: 100%; height: 100%; object-fit: cover;
  transition: transform .8s cubic-bezier(.2,.8,.2,1);
}
.card:hover .card-media img { transform: scale(1.04); }

.card-index {
  position: absolute; top: .7rem; left: .7rem;
  font-size: .6rem; letter-spacing: .18em;
  color: var(--cream);
  mix-blend-mode: difference;
}
.card-flag {
  position: absolute; bottom: 0; left: 0; right: 0;
  background: rgba(107,36,25,.82); color: var(--cream);
  font-size: .6rem; letter-spacing: .16em; text-transform: uppercase;
  text-align: center; padding: .5rem;
}

.card-body { padding-top: .85rem; }
.card-name {
  font-family: var(--display);
  font-size: 1.2rem;
  line-height: 1.2;
}
.card-sub { color: var(--ink-soft); font-size: .74rem; margin: .2rem 0 .45rem; }
.card-price { font-size: .8rem; letter-spacing: .04em; }
.card-price s { color: var(--ink-soft); margin-left: .4rem; font-size: .72rem; }
.card-price .discount-badge { padding: .1rem .35rem; font-size: .6rem; margin-left: .4rem; }

.card::after { content: ""; position: absolute; inset: 0; }

/* Shared by _macros.html's `price()` macro (used in _card.html on
   home/shop/product-related, and directly on product.html's own price
   line) — one definition so a discount badge never looks different
   between a card and the product page itself. */
.discount-badge {
  display: inline-block; margin-left: .6rem; padding: .2rem .5rem;
  background: var(--olive); color: var(--cream);
  font-family: var(--body); font-size: .68rem; font-weight: 600;
  letter-spacing: .04em; border-radius: 3px; vertical-align: middle;
}

/* --------------------------------------------------------------- page */

/* Capped as one compact block, divider line included — tried leaving the
   border-bottom full-width with just the text capped, but a short
   one-line heading over a long empty divider read as *more* spacious,
   not less. Shared by every page with a simple heading strip: shop,
   cart, checkout, account pages, and the generic /page/* templates. */
.page-head { max-width: 300px; padding: 3rem 0 2rem; border-bottom: 1px solid var(--line); }
.page-head-text { max-width: 300px; }

/* Generic content pages (pages/_page.html — About, Contact, Terms,
   Privacy, Wash Care, Size Guide, Returns): heading in a left rail,
   body content in the wider right column. Stacked (heading above body,
   the original layout) below 768px — a narrow phone screen doesn't have
   room for a real side-by-side split without squeezing the body column
   to an unreadable width. */
.page-split { display: flex; flex-direction: column; gap: 1rem; padding: 3rem 0 5rem; }
.page-split-head { flex: 0 0 auto; }
.page-split-body { flex: 1 1 auto; font-size: .95rem; line-height: 1.85; color: var(--ink-soft); }
@media (min-width: 768px) {
  .page-split { flex-direction: row; align-items: flex-start; gap: 3rem; }
  /* Wider than a bare one-line heading needs, on purpose — wash-care.html
     puts an eyebrow, intro paragraph, and an icon row in this column too
     (see _page.html's head_eyebrow/head_extra blocks), and 240px was only
     ever sized for a plain <h1>. */
  .page-split-head { flex: 0 0 340px; position: sticky; top: 6.5rem; }
}

/* Icon + title + description list, presented as one card — used by
   wash-care.html's 5-step care guide. Uniform icon-circle color (not a
   different pastel per icon) on purpose, to stay within this site's
   restrained palette rather than introducing a rainbow of one-off colors
   nothing else on the site uses. */
/* --cream-deep, not white — this site's cards/boxes never use pure
   white (see .custom-measurements, .summary-box, .style-card-text, all
   --cream-deep) precisely so a box like this reads as part of the warm
   page rather than a colder, generic "card" dropped on top of it. No
   shadow for the same reason — a subtle border does the "this is a
   grouped box" job without the harsher edge a shadow gives against a
   background that's this close in value to the box itself. */
.care-list {
  background: var(--cream-deep); border-radius: 8px; padding: .5rem 1.75rem;
  border: 1px solid var(--line);
}
.care-item { display: flex; gap: 1rem; align-items: flex-start; padding: 1.5rem 0; border-bottom: 1px solid var(--line); }
.care-item:last-child { border-bottom: 0; }
/* --cream, not --cream-deep — that's now .care-list's own background
   (see above), so the icon circle needs to be the *lighter* tone to
   still read as a distinct badge against it, not the same color. */
/* A thin border, not just a background-tint difference, so the circle
   reads as a defined badge rather than a faint smudge — and the emoji
   itself is desaturated/warmed (grayscale + sepia) so its native color
   (blue water drop, orange sun, purple bubbles) doesn't clash with this
   site's otherwise restrained cream/charcoal/olive palette; a little
   `opacity` softens it further so it sits back rather than popping. */
.care-icon {
  flex: 0 0 auto; width: 2.5rem; height: 2.5rem; border-radius: 50%;
  background: var(--cream); border: 1px solid var(--line);
  display: flex; align-items: center; justify-content: center;
  font-size: 1.15rem;
}
.care-icon span { filter: grayscale(.6) sepia(.3); opacity: .85; }
.care-item h3 { font-size: 1.15rem; margin-bottom: .3rem; }
.care-item p { margin: 0; color: var(--ink-soft); font-size: .9rem; line-height: 1.6; }

/* Order line-item list — shared by cart, checkout's summary, and the
   order confirmation/tracking page, so a line item always looks the
   same wherever an order's contents are shown. */
.lines { border-top: 1px solid var(--line); }
.line {
  display: grid; grid-template-columns: 72px 1fr auto;
  gap: 1rem; padding: 1.25rem 0;
  border-bottom: 1px solid var(--line);
  align-items: start;
}
.line img { width: 72px; aspect-ratio: 3/4; object-fit: cover; background: var(--cream-deep); }
.line-name { font-family: var(--display); font-size: 1.1rem; }
.line-meta { font-size: .72rem; color: var(--ink-soft); }
.qty { display: inline-flex; align-items: center; gap: .5rem; margin-top: .5rem; }
.qty select { font-family: var(--body); font-size: .76rem; padding: .3rem .4rem; border: 1px solid var(--line); background: none; }
.remove { font-size: .68rem; letter-spacing: .1em; text-transform: uppercase; color: var(--ink-soft); background: none; border: 0; cursor: pointer; padding: 0; }
.remove:hover { color: var(--rose); }

.totals { margin: 2rem 0; max-width: 380px; margin-left: auto; }
.totals div { display: flex; justify-content: space-between; padding: .45rem 0; font-size: .85rem; }
.totals .grand { border-top: 1px solid var(--line); margin-top: .5rem; padding-top: .9rem; font-size: 1.05rem; }
.totals .discount-line, .discount-line { color: var(--olive); }

/* Generic form field — shared by checkout and account login/register. */
.field { display: grid; gap: .35rem; margin-bottom: 1.1rem; }
.field label { font-size: .68rem; letter-spacing: .14em; text-transform: uppercase; color: var(--ink-soft); }
.field input, .field select, .field textarea {
  font-family: var(--body); font-size: .92rem;
  padding: .8rem .9rem;
  border: 1px solid var(--line);
  background: #fff;
  color: var(--charcoal);
  border-radius: 0;
}
.field input:focus, .field select:focus { border-color: var(--olive); outline: none; }
.field-note { font-size: .72rem; color: var(--olive); margin: 0; }
.field-note-error { color: var(--rose); }
.row { display: grid; gap: 0 1rem; grid-template-columns: 1fr 1fr; }

.errors { border-left: 2px solid var(--rose); padding: .85rem 1rem; margin-bottom: 1.5rem; background: #fff; }
.errors p { margin: .2rem 0; font-size: .82rem; }

/* Generic centered status block — 404, error, launching-soon, pay,
   order confirmation's "payment didn't go through" state, and the shop
   page's "nothing matches" empty state all use this same shape. */
.notice { text-align: center; padding: 5rem var(--gutter); }
.notice h1 { margin-bottom: 1rem; }
.notice p { color: var(--ink-soft); max-width: 42ch; margin: 0 auto 2rem; }
.notice-subscribe {
  display: flex; gap: .5rem; flex-wrap: wrap; justify-content: center;
  max-width: 480px; margin: -1rem auto 1.5rem;
}
/* flex: 1 1 200px (was 1 1 0, i.e. `flex: 1`) so the input actually
   claims real width from its 200px basis instead of starting from
   nothing and only growing to fill leftover space after the button —
   at this row's actual width that left just ~200px for the input, not
   enough for its own placeholder text ("Email or WhatsApp number"
   truncated to "...numbe"). min-width relaxed to 160px so wrapping to
   two lines (button below input) can still happen on genuinely narrow
   screens without the input being forced wider than the row itself. */
.notice-subscribe input {
  flex: 1 1 200px; min-width: 160px; padding: .8rem 1rem;
  border: 1px solid var(--line); background: transparent; color: var(--charcoal);
  font: inherit;
}
.notice-subscribe input::placeholder { color: var(--ink-soft); }

/* ------------------------------------------------------------ footer */

.subscribe { background: var(--charcoal); color: var(--cream); padding: clamp(3rem,8vw,5rem) var(--gutter); }
.subscribe .inner { max-width: 520px; margin: 0 auto; text-align: center; }
.subscribe h2 { color: var(--cream); }
.subscribe p { color: rgba(255,243,219,.66); font-size: .88rem; }
.subscribe form { display: flex; gap: .5rem; margin-top: 1.5rem; flex-wrap: wrap; }
.subscribe input {
  flex: 1 1 200px; padding: .9rem 1rem;
  background: none; border: 1px solid rgba(255,243,219,.3);
  color: var(--cream); font-family: var(--body); font-size: .9rem;
}
.subscribe input::placeholder { color: rgba(255,243,219,.45); }
.subscribe .btn { background: var(--cream); color: var(--charcoal); border-color: var(--cream); }

/* Compact variant: the same "list" signup, as its own footer column
   (split out from "Follow" so each has equal width) — a highlighted card
   rather than plain link-list styling so the signup still stands out,
   just an eyebrow + inline form, footer-scale type, no full-bleed banner
   treatment. */
.site-footer .subscribe {
  background: var(--cream-deep); color: inherit;
  padding: 1.1rem; border-radius: 4px;
  border: 1px solid var(--line);
}
.site-footer .subscribe .eyebrow { font-family: var(--body); font-size: .7rem; font-weight: 700; letter-spacing: .12em; text-transform: uppercase; color: var(--charcoal); margin-bottom: .3rem; }
.site-footer .subscribe .hint { font-size: .78rem; color: var(--ink-soft); margin-bottom: .8rem; }
.site-footer .subscribe form { display: flex; flex-direction: column; gap: .6rem; margin-top: 0; }
.site-footer .subscribe input {
  flex: none; width: 100%; max-width: 240px;
  color: inherit; border: 1px solid var(--line); background: var(--cream);
  font-family: var(--body); font-size: .84rem; padding: .65rem .8rem;
}
.site-footer .subscribe input::placeholder { color: var(--ink-soft); }
.site-footer .subscribe .btn { background: var(--charcoal); color: var(--cream); border-color: var(--charcoal); align-self: flex-start; }

.site-footer { position: relative; z-index: 10; border-top: 1px solid var(--line); padding: 3rem var(--gutter) 2rem; }
/* Four equal columns — Shop | Help | Follow | The list. Follow and the
   newsletter signup used to share one column (stacked); split into their
   own columns here since each stands on its own. The Founder's Vision
   column (and its logo) was removed from the footer entirely — the logo
   already appears in the header's .wordmark, so nothing lost it as a
   brand mark. */
.foot-cols { display: grid; grid-template-columns: repeat(4, 1fr); gap: 2rem; }
.foot-cols h3 { font-family: var(--body); font-size: .66rem; letter-spacing: .18em; text-transform: uppercase; margin-bottom: .9rem; color: var(--ink-soft); }
.foot-cols a { display: block; font-size: .84rem; padding: .18rem 0; }
.foot-cols a:hover { color: var(--olive-deep); }

/* Below this width the 4 equal desktop columns get too narrow — auto-fit
   wraps down to however many 140px-minimum columns actually fit instead
   of squeezing 4 into not enough space. 860px matches the breakpoint
   used for .shop-layout in pages/shop.css, for consistency. */
@media (max-width: 860px) {
  .foot-cols { grid-template-columns: repeat(auto-fit, minmax(140px, 1fr)); }
}
/* Decorative footer illustration — original artwork (see the SVG's own
   comments for the figure-by-figure breakdown), not a reproduction of
   any reference image. Full-bleed regardless of .site-footer's own
   gutter padding, so it reads as a banner strip, not a boxed-in graphic. */
.foot-illustration {
  width: calc(100% + var(--gutter) * 2); margin: 3rem calc(var(--gutter) * -1) 0;
  max-width: none; height: auto; display: block;
}

.copyright { font-size: .68rem; color: var(--ink-soft); margin-top: 2rem; letter-spacing: .06em; }

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation-duration: .01ms !important; transition-duration: .01ms !important; }
}
