/* ==========================================================================
   The Olive Branch — stylesheet
   Aesop-led: neutral sans for everything, serif reserved for display.
   Sentence case. Square corners. Colour comes from the photography.
   ========================================================================== */

/* --------------------------------------------------------------- 1. TOKENS */
:root {
  --bone:       #F7F4EC;
  --bone-2:     #EDE9DE;
  --bone-3:     #E3DED0;
  --ink:        #1A1A17;
  --ink-soft:   #55554C;
  --olive:      #4A5D3A;
  --olive-deep: #2A3423;
  --burgundy:      #5C2233;
  --burgundy-deep: #431926;   /* pressed/hover state for solid burgundy */
  --rule:       rgba(26, 26, 23, 0.15);
  --rule-soft:  rgba(26, 26, 23, 0.08);

  --serif: 'EB Garamond', Georgia, 'Times New Roman', serif;
  --sans:  'Schibsted Grotesk', 'Helvetica Neue', Arial, sans-serif;

  --gut:      clamp(1.25rem, 4vw, 3rem);
  --measure:  64ch;
  --shell:    1440px;
  --ease:     cubic-bezier(0.22, 0.61, 0.36, 1);

  --h-bar:    34px;   /* announcement bar */
  --h-mast:   72px;   /* masthead */
  --h-nav:    48px;   /* category nav */
}

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

html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; }

body {
  margin: 0;
  background: var(--bone);
  color: var(--ink);
  font-family: var(--sans);
  font-size: 1rem;
  line-height: 1.65;
  font-weight: 400;
  -webkit-font-smoothing: antialiased;
  /* clip, not hidden: `hidden` makes body a scroll container and breaks
     position: sticky on descendants (masthead, product panel, reveal hero). */
  overflow-x: clip;
}

img { max-width: 100%; display: block; }
button, input, select, textarea { font: inherit; color: inherit; }

/* The UA rule for [hidden] is display:none at low specificity, so any class
   that sets display (.btn is inline-flex) beats it. Without this, hiding a
   button with the hidden attribute silently does nothing. */
[hidden] { display: none !important; }

::selection { background: var(--olive); color: var(--bone); }

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

.skip {
  position: absolute; left: -9999px; top: 0; z-index: 200;
  background: var(--ink); color: var(--bone); padding: 0.75rem 1.25rem;
}
.skip:focus { left: 0; }

.sr {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

/* ----------------------------------------------------------- 2. TYPOGRAPHY */
h1, h2, h3, h4 {
  font-family: var(--serif);
  font-weight: 400;
  line-height: 1.14;
  letter-spacing: -0.005em;
  margin: 0;
  text-wrap: balance;
}

.d-xl { font-size: clamp(2.4rem, 5.4vw, 4.2rem); }
.d-l  { font-size: clamp(1.9rem, 3.6vw, 3rem); }
.d-m  { font-size: clamp(1.4rem, 2.4vw, 1.95rem); }
.d-s  { font-size: clamp(1.15rem, 1.7vw, 1.4rem); }

p { margin: 0 0 1.1em; }
p:last-child { margin-bottom: 0; }

.lede {
  font-family: var(--serif);
  font-size: clamp(1.15rem, 1.8vw, 1.45rem);
  line-height: 1.5;
  color: var(--ink);
}

.label {
  font-family: var(--sans);
  font-size: 0.7rem;
  font-weight: 500;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink-soft);
  margin: 0 0 1.1rem;
  display: block;
}

.small { font-size: 0.85rem; line-height: 1.6; color: var(--ink-soft); }
.muted { color: var(--ink-soft); }

/* `ch` is relative to the element's own font-size, so a 34px heading with a
   30ch measure wants ~560px. min() keeps every measure inside the viewport. */
.measure { max-width: min(var(--measure), 100%); }
.measure-narrow { max-width: min(48ch, 100%); }

a { color: inherit; }

/* Aesop-style quiet text link with a hairline underline */
.tlink {
  display: inline-block;
  text-decoration: none;
  font-size: 0.82rem;
  font-weight: 500;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  padding-bottom: 0.35rem;
  border-bottom: 1px solid var(--ink);
  transition: opacity 0.4s var(--ease);
}
.tlink:hover { opacity: 0.55; }
.tlink::after { content: ' →'; letter-spacing: 0; }

/* ------------------------------------------------------------- 3. BUTTONS */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.6rem;
  padding: 0.95rem 1.9rem;
  border-radius: 0;
  border: 1px solid var(--ink);
  background: transparent;
  color: var(--ink);
  font-size: 0.78rem;
  font-weight: 500;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  text-decoration: none;
  cursor: pointer;
  transition: background 0.4s var(--ease), color 0.4s var(--ease),
              border-color 0.4s var(--ease), opacity 0.4s var(--ease);
}
/* Fills burgundy, not near-black — on the bone ground a black box reads as a
   different design language to the rest of the site. */
.btn:hover { background: var(--burgundy); border-color: var(--burgundy); color: var(--bone); }

/* Commerce actions only — the one place solid fill is allowed */
.btn-solid { background: var(--burgundy); border-color: var(--burgundy); color: var(--bone); }
.btn-solid:hover { background: var(--burgundy-deep); border-color: var(--burgundy-deep); color: var(--bone); }

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

.btn-block { width: 100%; }
.btn[disabled] { opacity: 0.4; cursor: not-allowed; }

/* -------------------------------------------------------------- 4. LAYOUT */
.shell {
  max-width: var(--shell);
  margin: 0 auto;
  padding-inline: var(--gut);
}
.shell-narrow { max-width: 860px; margin: 0 auto; padding-inline: var(--gut); }

.section { padding-block: clamp(3.5rem, 8vw, 7rem); }
.section-tight { padding-block: clamp(2.25rem, 4.5vw, 3.5rem); }
.section-alt { background: var(--bone-2); }
.section-dark { background: var(--olive-deep); color: var(--bone); }
.section-dark .label,
.section-dark .muted,
.section-dark .small { color: rgba(247, 244, 236, 0.72); }
.section-dark .tlink { border-bottom-color: var(--bone); }

.centred { text-align: center; }
.centred .measure,
.centred .measure-narrow { margin-inline: auto; }

.rule { height: 1px; background: var(--rule); border: 0; margin: 0; }

/* A short centred divider, used between eyebrow and body */
.tick { width: 44px; height: 1px; background: var(--ink); margin: 1.6rem auto; }
.section-dark .tick { background: rgba(247, 244, 236, 0.5); }

.stack-sm > * + * { margin-top: 0.6rem; }
.stack   > * + * { margin-top: 1.4rem; }
.stack-l > * + * { margin-top: 2.4rem; }

/* -------------------------------------------------------------- 5. HEADER */
.bar {
  background: var(--olive-deep);
  color: var(--bone);
  text-align: center;
  font-size: 0.74rem;
  letter-spacing: 0.06em;
  line-height: var(--h-bar);
  height: var(--h-bar);
  overflow: hidden;
}

/* Deliberately not sticky. The header scrolls away and gives the viewport
   back to the photography — the declaration used to say `sticky` but never
   behaved that way, because a sticky element can only stick inside its own
   parent and #site-header is only as tall as the header itself. */
.masthead {
  background: var(--bone);
  border-bottom: 1px solid var(--rule-soft);
}

.masthead-row {
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: center;
  gap: 1rem;
  min-height: var(--h-mast);
  max-width: var(--shell);
  margin: 0 auto;
  padding-inline: var(--gut);
}

.mast-left, .mast-right {
  display: flex;
  align-items: center;
  gap: 1.5rem;
  font-size: 0.8rem;
}
.mast-right { justify-content: flex-end; }

.mast-left a, .mast-right a {
  text-decoration: none;
  transition: opacity 0.35s var(--ease);
}
.mast-left a:hover, .mast-right a:hover { opacity: 0.55; }

/* Set in capitals with wide tracking, matching the lid of the physical box. */
.wordmark {
  font-family: var(--serif);
  font-size: clamp(1.05rem, 1.75vw, 1.32rem);
  text-transform: uppercase;
  letter-spacing: 0.15em;
  text-decoration: none;
  white-space: nowrap;
  line-height: 1;
  display: flex;
  align-items: center;
  gap: 0.6rem;
}
.wordmark svg { width: 20px; height: 20px; flex: none; }

/* Category navigation */
.nav {
  border-bottom: 1px solid var(--rule-soft);
  background: var(--bone);
  position: relative;          /* containing block for the dropdown panel */
}
.nav-row {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: clamp(1rem, 2.6vw, 2.4rem);
  min-height: var(--h-nav);
  max-width: var(--shell);
  margin: 0 auto;
  padding-inline: var(--gut);
}

/* Scoped to top-level items only, so these rules never reach into .mega */
.nav-row > a,
.nav-item > a {
  display: inline-block;
  text-decoration: none;
  font-size: 0.84rem;
  white-space: nowrap;
  padding-block: 0.35rem;
  border-bottom: 1px solid transparent;
  transition: border-color 0.35s var(--ease);
}
.nav-row > a:hover,
.nav-item > a:hover,
.nav-row > a[aria-current="page"],
.nav-item > a[aria-current="page"],
.nav-item:hover > a { border-bottom-color: var(--ink); }

/* ------------------------------------------- collection dropdown (mega) */
.nav-item { position: static; }   /* panel anchors to .nav, not to the item */

.mega {
  position: absolute;
  left: 0; right: 0; top: 100%;
  z-index: 70;
  background: var(--olive-deep);   /* fully opaque */
  color: var(--bone);
  border-top: 1px solid rgba(247, 244, 236, 0.14);
  opacity: 0;
  visibility: hidden;
  transform: translateY(-8px);
  transition: opacity 0.3s var(--ease),
              transform 0.3s var(--ease),
              visibility 0s linear 0.3s;
}
.nav-item:hover > .mega,
.nav-item:focus-within > .mega {
  opacity: 1;
  visibility: visible;
  transform: none;
  transition-delay: 0s;
}

/* The panel spans the viewport; its content is centred on a tighter measure
   so two hampers do not sit marooned in a 1440px column. */
.mega-inner {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: clamp(1.5rem, 3.5vw, 3.5rem);
  max-width: 820px;
  margin: 0 auto;
  padding: clamp(1.6rem, 2.6vw, 2.4rem) var(--gut) clamp(1.75rem, 3vw, 2.5rem);
}
.mega-col h4 {
  font-family: var(--sans);
  font-size: 0.68rem;
  font-weight: 500;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: rgba(247, 244, 236, 0.55);
  margin: 0 0 1.1rem;
}
.mega-col ul { list-style: none; margin: 0; padding: 0; }
.mega-col li + li { margin-top: 0.85rem; }

/* inline-block, so the underline below measures the text and not the column */
.mega-col ul a {
  position: relative;
  display: inline-block;
  text-decoration: none;
  font-size: 1rem;
  line-height: 1.4;
  opacity: 0.85;
  transition: opacity 0.3s var(--ease);
}
.mega-col ul a::after {
  content: '';
  position: absolute;
  left: 0;
  bottom: -3px;
  width: 100%;
  height: 1px;
  background: currentColor;
  transform: scaleX(0);
  transform-origin: left;
  transition: transform 0.4s var(--ease);
}
.mega-col ul a:hover,
.mega-col ul a:focus-visible { opacity: 1; }
.mega-col ul a:hover::after,
.mega-col ul a:focus-visible::after { transform: scaleX(1); }
.mega-note p {
  font-size: 0.9rem;
  line-height: 1.55;
  opacity: 0.72;
  margin: 0 0 1rem;
  max-width: 30ch;
}
.mega-cta {
  display: inline-block;
  font-size: 0.75rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  text-decoration: none;
  border-bottom: 1px solid rgba(247, 244, 236, 0.5);
  padding-bottom: 0.3rem;
  transition: border-color 0.35s var(--ease);
}
.mega-cta:hover { border-bottom-color: var(--bone); }

.burger {
  display: none;
  background: none;
  border: 0;
  padding: 0.5rem;
  cursor: pointer;
}
.burger span {
  display: block; width: 20px; height: 1px; background: var(--ink);
}
.burger span + span { margin-top: 5px; }

.cart-count { font-variant-numeric: tabular-nums; }

/* ---------------------------------------------------------------- 6. HERO */
/* Hero — a full-bleed photographic band edge to edge, with the copy beneath.
   The band is cropped from below the supplied image's baked-in headline, so it
   runs at full native width (1666px) rather than being upscaled. */
.hero { background: var(--bone); }

.hero-media {
  position: relative;
  overflow: hidden;
  background: var(--bone-2);
  aspect-ratio: 1858 / 846;
}
/* No parallax here, so no overscan. The drift travelled ±7% while only 3% of
   headroom was hiding it, which exposed a strip of the backing colour at the
   foot of the hero. Filling the frame exactly means there is nothing to
   expose — and it shows the photograph completely uncropped, which is what
   this image is for. */
.hero-media img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: 50% 50%;
}
.hero-body {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  padding: clamp(2.75rem, 6vw, 4.75rem) var(--gut) clamp(3rem, 7vw, 5.5rem);
}
/* Measures in rem, not ch: `ch` scales with each element's own font-size,
   which cramps the lede and wraps the eyebrow onto two lines. */
.hero-body > * { max-width: min(44rem, 100%); }
.hero-body .label { max-width: none; }
.hero-body .d-xl { font-size: clamp(2.1rem, 4.4vw, 3.6rem); max-width: min(44rem, 100%); }
.hero-body .lede { max-width: min(37rem, 100%); }
/* The CTA row needs room for two buttons side by side, not the text measure. */
.hero-cta { max-width: none; }

/* ---- Hero entrance ------------------------------------------------------ */
/* The frame holds still and the photograph descends into it, so the sprig and
   the wordmark inside the picture glide down from the top. The copy follows
   in the same direction, a beat behind.
   Overscan is what makes the drop safe here: at scale 1.10 there is 5% of
   headroom hidden above and below, and the travel is 4%, so no strip of
   backing colour is ever exposed — the exact trap that took parallax off this
   image. Scale and travel reach zero together, so they stay in step. */
@keyframes hero-drop {
  from { transform: translate3d(0, -4%, 0) scale(1.10); }
  to   { transform: none; }
}
/* Once settled, a very slow breath so the hero is never quite still. Pure
   scale, never below 1, so it cannot expose an edge. It begins at identity —
   exactly where the drop ends — so the two meet without a jump. */
@keyframes hero-breathe {
  from { transform: none; }
  to   { transform: scale(1.045); }
}
.hero-media img {
  animation: hero-drop 1.9s var(--ease) both,
             hero-breathe 26s ease-in-out 2.1s infinite alternate;
}

/* Eyebrow, headline, rule, lede, buttons — in sequence, all downward. */
@keyframes hero-glide {
  from { opacity: 0; transform: translate3d(0, -24px, 0); }
  to   { opacity: 1; transform: none; }
}
.hero-body > * { animation: hero-glide 1.1s var(--ease) both; }
.hero-body > *:nth-child(1) { animation-delay: 0.15s; }
.hero-body > *:nth-child(2) { animation-delay: 0.30s; }
.hero-body > *:nth-child(3) { animation-delay: 0.44s; }
.hero-body > *:nth-child(4) { animation-delay: 0.56s; }
.hero-body > *:nth-child(5) { animation-delay: 0.68s; }

/* ------------------------------------------------- 7. FULL-BLEED PICTURES */
.bleed {
  position: relative;
  overflow: hidden;
  background: var(--bone-3);
}
.bleed-media { position: absolute; inset: -12% 0; }
.bleed-media img { width: 100%; height: 100%; object-fit: cover; }
/* A <picture> is an inline box; without this it sits between .bleed-media and
   the image and the sizing above never reaches the <img>. `contents` removes
   the wrapper from layout and leaves the image as the direct child. */
.bleed-media picture { display: contents; }
/* Same reason, for the burgundy band's single photograph. */
.scale-media picture { display: contents; }
/* No min-height here: combined with aspect-ratio it transfers into a
   *minimum width* (320 × 16/7 = 731px) and overflows narrow viewports.
   The ratio is stepped responsively instead. */
.bleed-16 { aspect-ratio: 16 / 7; }

/* Framed picture that reveals on scroll */
.frame { overflow: hidden; background: var(--bone-3); }
.frame img { width: 100%; height: 100%; object-fit: cover; }

/* A slow push-in that settles as the band opens. The scale sits on the
   wrapper, not the image, so it never fights the parallax transform. */
.bleed-zoom .bleed-media {
  transform: scale(1.12);
  transition: transform 2.2s var(--ease);
}
.bleed-zoom.is-visible .bleed-media { transform: none; }

/* ------------------------------------------------------- 8. CARDS & GRIDS */
.grid { display: grid; gap: clamp(1.5rem, 3vw, 2.75rem); }
.grid-2 { grid-template-columns: repeat(2, 1fr); }
.grid-3 { grid-template-columns: repeat(3, 1fr); }

.card { display: flex; flex-direction: column; text-decoration: none; }
.card-media {
  aspect-ratio: 4 / 3;
  overflow: hidden;
  background: var(--bone-3);
  margin-bottom: 1.25rem;
}
.card-media img {
  width: 100%; height: 100%;
  object-fit: cover;
  transition: transform 1.1s var(--ease);
}
.card:hover .card-media img { transform: scale(1.045); }
.card-title { font-family: var(--serif); font-size: 1.3rem; line-height: 1.2; margin: 0 0 0.4rem; }
.card-meta {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: 1rem; margin-top: 0.7rem;
  font-size: 0.85rem;
}
.card-price { font-variant-numeric: lining-nums; }
.card-from { font-size: 0.72rem; letter-spacing: 0.1em; text-transform: uppercase; color: var(--ink-soft); }

/* Collection gateway — tall portrait card */
.gate-media { aspect-ratio: 3 / 4; }

/* ------------------------------------------------------- 9. PRODUCT PAGE */
.product {
  display: grid;
  grid-template-columns: minmax(0, 1.15fr) minmax(0, 0.85fr);
  gap: clamp(2rem, 5vw, 4.5rem);
  align-items: start;
}
/* overflow clips the hover magnification — see section 15. */
.product-media { position: relative; background: var(--bone-3); overflow: hidden; }
.product-media img { width: 100%; height: auto; }
.zoom-hint {
  position: absolute; left: 1rem; bottom: 1rem;
  background: rgba(247, 244, 236, 0.92);
  font-size: 0.68rem; letter-spacing: 0.12em; text-transform: uppercase;
  padding: 0.5rem 0.85rem;
  pointer-events: none;
}
/* Offset is just breathing room now; nothing is pinned above it. */
.product-buy { position: sticky; top: 1.5rem; }
.product-detail { margin-top: clamp(2.5rem, 5vw, 3.75rem); max-width: min(60ch, 100%); }

.qty {
  display: inline-flex;
  align-items: stretch;
  border: 1px solid var(--ink);
}
.qty button {
  width: 46px;
  background: none; border: 0; cursor: pointer;
  font-size: 1.1rem; line-height: 1;
  transition: background 0.3s var(--ease);
}
.qty button:hover { background: var(--bone-2); }
.qty input {
  width: 64px; text-align: center;
  border: 0; border-inline: 1px solid var(--ink);
  background: transparent;
  font-variant-numeric: tabular-nums;
  padding-block: 0.8rem;
  -moz-appearance: textfield;
}
.qty input::-webkit-outer-spin-button,
.qty input::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }

/* A named block inside a collection page — Diwali inside Celebration. The
   rule above it is what separates one block from the next; without it the
   second grid reads as more of the first. */
.collection-section {
  margin-top: clamp(3rem, 6vw, 5rem);
  padding-top: clamp(2.5rem, 5vw, 4rem);
  border-top: 1px solid var(--rule);
}
.collection-section-head { margin-bottom: clamp(2rem, 4vw, 3rem); }

/* The other views of a hamper, under its photograph. Square thumbnails so the
   row does not jump about when a landscape and a portrait sit side by side. */
.product-views {
  display: flex;
  gap: 0.6rem;
  margin-top: 0.75rem;
}
.product-view {
  width: 72px;
  height: 72px;
  padding: 0;
  border: 1px solid var(--rule);
  background: none;
  cursor: pointer;
  overflow: hidden;
  transition: border-color 0.2s;
}
.product-view img { width: 100%; height: 100%; object-fit: cover; display: block; }
.product-view:hover { border-color: var(--olive); }
/* The view being shown. A 2px inset rather than an outline, so the thumbnail
   does not shift by a pixel when it becomes current. */
.product-view[aria-current="true"] {
  border-color: var(--olive-deep);
  box-shadow: inset 0 0 0 2px var(--olive-deep);
}

.tiers { width: 100%; border-collapse: collapse; font-size: 0.88rem; }
.tiers th, .tiers td {
  text-align: left; padding: 0.65rem 0.25rem;
  border-bottom: 1px solid var(--rule-soft);
}
.tiers th {
  font-size: 0.68rem; letter-spacing: 0.12em; text-transform: uppercase;
  font-weight: 500; color: var(--ink-soft);
}
.tiers td:last-child, .tiers th:last-child { text-align: right; font-variant-numeric: lining-nums; }
.tiers tr.is-active td { color: var(--burgundy); font-weight: 600; }
.tiers tr.is-active td:first-child::before { content: '▸ '; }

.price-now {
  font-family: var(--serif);
  font-size: clamp(1.8rem, 3vw, 2.4rem);
  line-height: 1;
  font-variant-numeric: tabular-nums;
}
.price-each { font-size: 0.8rem; color: var(--ink-soft); margin-left: 0.5rem; }

/* States that the price above is the whole price. No figure, by design. */
.price-tax {
  margin-top: 0.5rem;
  font-size: 0.8rem;
  color: var(--ink-soft);
}

/* Contents manifest — the leaf glyph earns its place here */
.manifest { list-style: none; padding: 0; margin: 0; }
.manifest li {
  position: relative;
  padding-left: 1.65rem;
  padding-block: 0.55rem;
  border-bottom: 1px solid var(--rule-soft);
  font-size: 0.94rem;
}
.manifest li::before {
  content: '';
  position: absolute; left: 0; top: 1.05rem;
  width: 11px; height: 7px;
  background: var(--olive);
  clip-path: ellipse(50% 50% at 50% 50%);
  transform: rotate(-24deg);
}

.notes {
  background: var(--bone-2);
  padding: 1.25rem 1.4rem;
  font-size: 0.88rem;
  border-left: 2px solid var(--olive);
}

/* --------------------------------------------------- 10. GIFTING AT SCALE */
.scale-band { background: var(--burgundy); color: var(--bone); }
.scale-band .label,
.scale-band .small,
.scale-band .muted { color: rgba(247, 244, 236, 0.75); }
.scale-band .tick { background: rgba(247, 244, 236, 0.5); }

/* A single photograph, held still. No overscan, because the extra height only
   existed to give a parallax drift somewhere to travel. */
.scale-media {
  position: relative;
  overflow: hidden;
  aspect-ratio: 16 / 8;
  max-width: 940px;
  margin: clamp(2.5rem, 5vw, 3.5rem) auto 0;
  background: rgba(0, 0, 0, 0.18);
}
.scale-media img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* -------------------------------------------------------------- 11. FORMS */
.field { display: block; margin-bottom: 1.4rem; }
.field > span {
  display: block;
  font-size: 0.72rem; letter-spacing: 0.12em; text-transform: uppercase;
  margin-bottom: 0.5rem; color: var(--ink-soft);
}
.field input, .field select, .field textarea {
  width: 100%;
  padding: 0.85rem 1rem;
  background: var(--bone);
  border: 1px solid var(--rule);
  border-radius: 0;
  transition: border-color 0.35s var(--ease);
}
.field input:focus, .field select:focus, .field textarea:focus { border-color: var(--ink); }
.field textarea { min-height: 130px; resize: vertical; }
.field-row { display: grid; grid-template-columns: 1fr 1fr; gap: 0 1.25rem; }

/* Delivery address, inside the cart summary. The summary column is narrow
   (0.9fr of the cart grid), so the fields are tightened and the paired rows
   stack rather than squeezing two inputs into ~200px each. */
.ship {
  margin-top: 1.5rem;
  padding-top: 1.5rem;
  border-top: 1px solid var(--rule);
}
.ship .field { margin-bottom: 0.85rem; }
.ship .field textarea { min-height: 4.5rem; }
.ship .field-row { grid-template-columns: 1fr; gap: 0; }
@media (min-width: 1180px) {
  .ship .field-row { grid-template-columns: 1fr 1fr; gap: 0 1rem; }
}

.form-note { font-size: 0.8rem; color: var(--ink-soft); }

/* --------------------------------------------------------------- 12. CART */
.cart-layout {
  display: grid;
  grid-template-columns: minmax(0, 1.6fr) minmax(0, 0.9fr);
  gap: clamp(1.5rem, 3vw, 3rem);
  align-items: start;
}

.line {
  display: grid;
  grid-template-columns: 132px 1fr auto;
  gap: 1.5rem;
  padding-block: 1.75rem;
  border-bottom: 1px solid var(--rule-soft);
  align-items: start;
}
.line-media { aspect-ratio: 4 / 3; overflow: hidden; background: var(--bone-3); }
.line-media img { width: 100%; height: 100%; object-fit: cover; }
.line-total { text-align: right; font-variant-numeric: lining-nums; white-space: nowrap; }


.summary { background: var(--bone-2); padding: clamp(1.5rem, 3vw, 2.25rem); }
.summary-row {
  display: flex; justify-content: space-between; gap: 1rem;
  padding-block: 0.55rem;
  font-variant-numeric: lining-nums;
}
.summary-total {
  border-top: 1px solid var(--rule);
  margin-top: 0.5rem; padding-top: 1rem;
  font-family: var(--serif); font-size: 1.4rem;
}
/* Sits under the total, quietly — a statement about the figure above, not a
   charge, so it carries no amount and no weight. */
.tax-note {
  margin: 0.35rem 0 0;
  font-size: 0.8rem;
  color: var(--ink-soft);
}

.linkish {
  background: none; border: 0; padding: 0; cursor: pointer;
  font-size: 0.78rem; color: var(--ink-soft);
  text-decoration: underline; text-underline-offset: 3px;
}
.linkish:hover { color: var(--ink); }

.empty { text-align: center; padding-block: clamp(3rem, 7vw, 5rem); }

/* Payment step — deliberately and visibly stubbed */
.stub {
  border: 1px dashed var(--rule);
  background: var(--bone);
  padding: 1.25rem 1.4rem;
  font-size: 0.85rem;
  color: var(--ink-soft);
}

/* ------------------------------------------------------------- 13. FOOTER */
.footer { background: var(--olive-deep); color: var(--bone); padding-block: clamp(3rem, 6vw, 4.5rem); }
.footer a { text-decoration: none; opacity: 0.78; transition: opacity 0.35s var(--ease); }
.footer a:hover { opacity: 1; }
.footer h4 {
  font-family: var(--sans);
  font-size: 0.7rem; letter-spacing: 0.14em; text-transform: uppercase;
  font-weight: 500; margin: 0 0 1rem; opacity: 0.66;
}
.footer ul { list-style: none; padding: 0; margin: 0; }
.footer li + li { margin-top: 0.5rem; }
.footer-grid { display: grid; grid-template-columns: 1.4fr repeat(3, 1fr); gap: clamp(1.75rem, 4vw, 3rem); }
.footer-base {
  margin-top: clamp(2.5rem, 5vw, 3.5rem);
  padding-top: 1.5rem;
  border-top: 1px solid rgba(247, 244, 236, 0.18);
  display: flex; flex-wrap: wrap; justify-content: space-between; gap: 1rem;
  font-size: 0.78rem; opacity: 0.72;
}

/* ----------------------------------------------------------- 14. WHATSAPP */
.wa {
  position: fixed;
  right: clamp(1rem, 2.5vw, 1.75rem);
  bottom: clamp(1rem, 2.5vw, 1.75rem);
  z-index: 80;
  width: 54px; height: 54px;
  display: grid; place-items: center;
  background: var(--burgundy);
  color: var(--bone);
  border-radius: 50%;
  box-shadow: 0 6px 24px rgba(26, 26, 23, 0.24);
  transition: transform 0.4s var(--ease);
}
.wa:hover { transform: scale(1.07); }
.wa svg { width: 26px; height: 26px; fill: currentColor; }

/* Inline WhatsApp link — the symbol carries the identity, so the number
   itself never has to appear on the page. */
.wa-inline {
  display: inline-flex;
  align-items: center;
  gap: 0.7rem;
  text-decoration: none;
  font-family: var(--serif);
  font-size: clamp(1.15rem, 1.7vw, 1.4rem);
  line-height: 1;
  transition: opacity 0.35s var(--ease);
}
.wa-inline:hover { opacity: 0.6; }
.wa-inline svg {
  width: 30px; height: 30px;
  flex: none;
  fill: var(--burgundy);
}

/* --------------------------------------------------------------- 15. ZOOM */
.zoom {
  position: fixed; inset: 0; z-index: 200;
  background: rgba(20, 22, 17, 0.94);
  display: none;
  place-items: center;
  cursor: zoom-out;
  overflow: hidden;
}
.zoom.is-open { display: grid; }
.zoom img {
  max-width: none;
  transition: transform 0.12s linear;
  will-change: transform;
  /* Without this the browser claims the drag for page scrolling and the
     photograph will not pan under a finger. */
  touch-action: none;
}

/* Magnify in place. `.product-media` clips (section 9), the photograph grows
   inside it, and the transform-origin set in site.js decides which part you
   are looking at. Scale never drops below 1, so the frame stays covered and
   clipping is the only containment needed — there is no edge case to guard.
   The transition eases the growing and the settling; the origin changes are
   not transitioned, so tracking stays locked to the cursor. */
.product-media img {
  cursor: zoom-in;
  transition: transform 0.35s var(--ease);
  will-change: transform;
}
.zoom-close {
  position: absolute; top: 1.25rem; right: 1.25rem;
  background: none; border: 1px solid rgba(247, 244, 236, 0.5);
  color: #F7F4EC;
  width: 44px; height: 44px;
  cursor: pointer; font-size: 1.1rem; line-height: 1;
}
.zoom-close:hover { background: rgba(247, 244, 236, 0.12); }

/* ------------------------------------------------------------- 16. MOTION */
/* Elements fade and rise once as they enter the viewport. */
.reveal {
  opacity: 0;
  transform: translate3d(0, 22px, 0);
  transition: opacity 1s var(--ease), transform 1s var(--ease);
}
.reveal.is-visible { opacity: 1; transform: none; }
.reveal-d1 { transition-delay: 0.09s; }
.reveal-d2 { transition-delay: 0.18s; }
.reveal-d3 { transition-delay: 0.27s; }

/* Frames open from a slim band to full height. */
.wipe { clip-path: inset(38% 0 38% 0); transition: clip-path 1.35s var(--ease); }
.wipe.is-visible { clip-path: inset(0 0 0 0); }

/* Parallax: `--p` runs 0 → 1 across the element's travel through the viewport.
   Set by assets/js/motion.js; consumed here only. */
.par img,
.par-el {
  transform: translate3d(0, calc((var(--p, 0.5) - 0.5) * -14%), 0);
  will-change: transform;
}

/* --------------------------------------------------------- 17. RESPONSIVE */
@media (max-width: 1024px) {
  .product { grid-template-columns: 1fr; }
  .product-buy { position: static; }
  .footer-grid { grid-template-columns: 1fr 1fr; }
  .cart-layout { grid-template-columns: 1fr; }
}

@media (max-width: 860px) {
  .nav-row { display: none; }
  .nav-row.is-open {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 0;
    padding-block: 0.5rem 1.25rem;
  }
  .nav-row.is-open a {
    width: 100%;
    padding-block: 0.7rem;
    border-bottom: 1px solid var(--rule-soft);
  }
  .nav-row.is-open .nav-item { width: 100%; }
  /* Hover has no meaning on touch; the drawer lists the collections and the
     collection pages carry the hampers. */
  .mega { display: none; }
  .burger { display: block; }
  /* Both utility rails go — at this width they push the masthead wider
     than the viewport and the whole page scrolls sideways. */
  .mast-left .util,
  .mast-right .util { display: none; }
  .mast-left, .mast-right { gap: 1rem; }
  .masthead-row { gap: 0.5rem; }
  .wordmark { font-size: 0.92rem; letter-spacing: 0.12em; gap: 0.45rem; }
  .wordmark svg { width: 16px; height: 16px; }
  .grid-3 { grid-template-columns: repeat(2, 1fr); }

  /* A little taller than the source so the wordmark keeps some breathing
     room, but shallow enough that cover never crops into it. */
  .hero-media { aspect-ratio: 16 / 10; }
  .bleed-16 { aspect-ratio: 3 / 2; }
}

@media (max-width: 620px) {
  .grid-2, .grid-3 { grid-template-columns: 1fr; }
  .field-row { grid-template-columns: 1fr; }
  .footer-grid { grid-template-columns: 1fr; }
  .line { grid-template-columns: 92px 1fr; }
  .line-total { grid-column: 2; text-align: left; }
  .scale-media { aspect-ratio: 4 / 3; }
  .bleed-16 { aspect-ratio: 4 / 3; }
  .hero-body .d-xl { font-size: clamp(1.85rem, 8vw, 2.3rem); }
  /* Let the announcement bar wrap rather than clip a sentence mid-word. */
  .bar {
    height: auto;
    line-height: 1.45;
    padding: 0.5rem 1rem;
    font-size: 0.7rem;
  }
}

/* ----------------------------------------------- 18. REDUCED MOTION (HARD) */
/* Not a reduction — every animation renders its finished state immediately. */
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
  }
  .reveal { opacity: 1; transform: none; }
  .wipe { clip-path: inset(0 0 0 0); }
  .par img, .par-el { transform: none; }
  .bleed-zoom .bleed-media { transform: none; }
  /* Kills the delays too — zeroing duration alone would still hold the hero
     copy invisible through its stagger. */
  .hero-media img,
  .hero-body > * { animation: none !important; opacity: 1; transform: none; }
}
