/* ============================================================
   TOKENS
   ============================================================ */
:root {
  --gold:      #AC8359;
  --gold-dark: #8E6B45;
  --navy:      #0A1C2B;
  --mist:      #C3C9CD;
  --white:     #FFFFFF;

  --espresso:  #34241C;   /* brand dark warm brown */
  --nav-solid: var(--navy);       /* header background when not transparent */

  /* section 2 — product carousel */
  --sand:   #E5DBD3;      /* carousel background        */
  --cocoa:  #341F16;      /* headline + product copy    */
  --taupe:  #604E45;      /* eyebrow + struck-out price */
  --arrow:       #805231; /* carousel arrows            */
  --arrow-hover: #946E51;

  /* section 3 — collections */
  --linen: #F0EBE5;       /* collections background     */

  /* footer */
  --footer-bg:    #34241C;
  --footer-link:  #D6D3D2;   /* nav links + social glyphs */
  --footer-arrow: #9A928E;
  --footer-label: #918986;   /* "Email" / "Phone" captions */

  --font-display: 'Archivo', 'Helvetica Neue', Arial, sans-serif;
  --font-body:    'Jost', system-ui, -apple-system, sans-serif;
  --font-nav:     'Instrument Sans', sans-serif;   /* the navigation links */

  /* the wipe button, hero and collections */
  --btn-wipe-bg: rgb(27, 53, 94);
  --btn-wipe-fg: #FFFFFF;
  --font-marquee: 'Assistant', sans-serif;         /* the marquee strip    */

  --marquee-bg: #C4301C;

  --nav-h:      clamp(68px, 6.4vw, 100px);
  /* Fixed, because the type in it is now fixed: a 32px line box has to
     fit at every width, and the old fluid 27-35px bar clipped it on a
     phone. Flush with the line box now — no bedding left to give.

     Going shorter no longer removes padding, it clips the line box.
     There is dead leading in there to spend before any letter is
     touched, but it is uneven: the ink sits 8px below the top of the
     line box and only 3px above the bottom, so a descender is the first
     thing to go. */
  --marquee-h:  32px;   /* exactly the 32.0001px line box */
  --gutter: clamp(1.25rem, 8vw, 9.5rem);   /* matches the reference inset */

  --hero-image: url('../assets/hero-vase.jpg');   /* 2000 x 1116 */

  /* No scrim. The photo carries the hero unmodified — no navy wash on
     this section or any that follow. If a future image drowns the type,
     fix it with the image (or type colour), not with a fade.          */
}

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

body {
  margin: 0;
  font-family: var(--font-body);
  background: var(--navy);
  color: var(--white);
  -webkit-font-smoothing: antialiased;
}
/* --sbw is the scrollbar width, measured in JS just before the class is
   added. Hiding the overflow takes the bar away, so hand its width back
   as padding and the content box stays exactly as wide as it was —
   no sideways jump behind an open drawer. Zero on overlay-scrollbar
   platforms (phones, macOS), where nothing is taken away to begin with. */
body.is-locked {
  overflow: hidden;
  padding-right: var(--sbw, 0px);
}

/* ============================================================
   MARQUEE
   Sits in normal flow above the hero, so it scrolls away with the
   page rather than sticking. The track holds two identical groups
   and slides exactly one group's width (-50%) before repeating —
   that's what makes the loop seamless instead of snapping back.
   JS fills the group until it's wider than the viewport and sets
   the duration from the measured width, so the speed stays even
   on any screen.
   ============================================================ */
.marquee {
  position: relative;
  z-index: 90;                   /* under the nav (100) */
  height: var(--marquee-h);
  display: flex;
  align-items: center;
  overflow: hidden;
  background-color: var(--marquee-bg);
  color: var(--white);
}

.marquee__track {
  display: flex;
  flex: none;
  will-change: transform;
  animation: marquee-scroll 30s linear infinite;   /* duration set by JS */
}
.marquee__group { display: flex; flex: none; }

/* Type supplied verbatim: Assistant 400, 22px on 32.0001px, white.
   Fixed rather than fluid — one size named, so it holds everywhere,
   and the bar above is sized to hold its line box. */
.marquee__item {
  flex: none;
  padding: 0 clamp(1.25rem, 2.6vw, 2.75rem);
  font-family: var(--font-marquee);
  font-size: 22px;
  font-weight: 400;
  line-height: 32.0001px;
  color: #FFFFFF;
  letter-spacing: .06em;
  white-space: nowrap;
}

@keyframes marquee-scroll {
  from { transform: translateX(0); }
  to   { transform: translateX(-50%); }
}

/* Announced once to a screen reader instead of however many times the
   loop happens to repeat it. */
.sr-only {
  position: absolute;
  width: 1px; height: 1px;
  margin: -1px; padding: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
  border: 0;
}

/* ============================================================
   NAV — 3 zones: search left | logo + links centred | icons right
   ============================================================ */
.nav {
  /* An ordinary section, first in the document. It scrolls away with the
     page like anything else and is there again when you return to the
     top — it never becomes fixed, and has no states. */
  position: relative;
  z-index: 100;
  min-height: var(--nav-h);
  display: grid;
  grid-template-columns: 1fr auto 1fr;   /* equal side rails keep the
                                            centre column truly centred */
  align-items: center;
  gap: 1rem;
  padding: clamp(.85rem, 1.4vw, 1.35rem) var(--gutter);
  background-color: var(--nav-solid);
}

/* --- centre: links --- */
.nav__center { grid-column: 2; justify-self: center; min-width: 0; }

/* --- logo, back on the left rail --- */
.logo {
  grid-column: 1;
  justify-self: start;
  display: inline-flex;
  align-items: center;
  gap: clamp(.5rem, 1vw, .9rem);
  text-decoration: none;
  color: var(--white);
}
/* The same two files the footer and Our Brand use, unaltered — icon on
   the left, wordmark to its right. Sized by height so the pair keeps its
   baseline together; the icon is the taller of the two and so is what
   the nav's height has to clear. At every width its height stays inside
   --nav-h minus the nav's own padding, so the lockup never grows the
   header. */
.logo__icon {
  height: clamp(36px, 3.4vw, 52px);
  width: auto;
  flex: none;
  display: block;
}
.logo__name {
  height: clamp(13px, 1.25vw, 19px);
  width: auto;
  flex: none;
  display: block;
}

/* --- links under the wordmark --- */
.nav__links {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  align-items: center;
  gap: clamp(.85rem, 1.9vw, 2rem);
  list-style: none;
  margin: 0;
  padding: 0;
}
/* Type supplied verbatim: Instrument Sans 600, 16px on 25.6px. Fixed,
   not fluid — the spec names one size, so it holds at every width the
   links are shown at.

   Sentence case, as written in the markup: no text-transform at all,
   rather than `capitalize`, which would also re-case anything typed in
   caps. The old 0.1em tracking went with it — that air was there to
   keep uppercase readable, and set against sentence case it only pulls
   the words apart. */
.nav__link {
  position: relative;
  display: inline-block;
  padding: 0.3rem 0;
  color: var(--mist);
  font-family: var(--font-nav);
  font-size: 16px;
  font-weight: 600;
  line-height: 25.6px;
  text-decoration: none;
  white-space: nowrap;
  transition: color 0.3s ease, opacity .3s ease;
}
.nav__link::after {
  content: '';
  position: absolute;
  left: 0; bottom: 0;
  width: 100%; height: 1px;
  background: currentColor;
  transform: scaleX(0);
  transform-origin: left;
  transition: transform 0.35s ease;
}
.nav__link:hover, .nav__link:focus-visible { color: var(--white); }
.nav__link:hover::after, .nav__link:focus-visible::after { transform: scaleX(1); }

/* --- right rail: cart --- */
.nav__right {
  grid-column: 3;
  justify-self: end;
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: clamp(1rem, 1.6vw, 1.75rem);
}

/* --- icon buttons: burger / cart --- */
.icon-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 40px;
  height: 40px;
  padding: 0;
  border: 0;
  background: none;
  color: var(--white);          /* matches the links beside them */
  cursor: pointer;
  transition: opacity .3s ease, transform .3s ease;
}
.icon-btn svg {
  width: clamp(19px, 1.5vw, 23px);
  height: clamp(19px, 1.5vw, 23px);
  display: block;
}
.icon-btn:hover, .icon-btn:focus-visible { opacity: .68; }
.icon-btn:active { transform: scale(.94); }

/* --- cart glyph ---
   Drawn at the size it was designed at rather than at the shared clamp
   above. The 40px button still supplies the hit area, the hover and the
   press. */
.header-actions__cart-icon .svg-wrapper svg {
  width: 20px;
  height: 20px;
}
.header-actions__cart-icon { transition: color .2s ease; }

/* --- cart count bubble ---
   The three offsets are custom properties so the badge can be nudged
   without touching the rule. It is measured from the button, which is
   the positioned ancestor, so it lands on the glyph's top-right.

   Colours are inverted from the source: that spec assumed a light
   header (black disc, white digit), and on this espresso bar a black
   disc would disappear. Cream disc, espresso digit reads the same way
   round here. */
.header-actions__cart-icon {
  --cart-bubble-size:  15px;
  --cart-bubble-top:   2px;
  --cart-bubble-right: 0px;
  position: relative;
}
.header-actions__cart-icon .svg-wrapper { display: block; }

.cart-bubble {
  position: absolute;
  top:   var(--cart-bubble-top);
  right: var(--cart-bubble-right);
  width:  var(--cart-bubble-size);
  height: var(--cart-bubble-size);
  border-radius: 50%;
  background: var(--linen);
  color: var(--espresso);
  display: none;                 /* nothing in the cart, nothing to say */
  align-items: center;
  justify-content: center;
  font-family: var(--font-body);
  font-size: 10px;
  font-weight: 500;
  line-height: 1;
  /* The disc sits on the basket's own outline; a ring of the header
     colour keeps the two from touching. */
  box-shadow: 0 0 0 2px var(--nav-solid);
}
.header-actions__cart-icon[data-has-cart="true"] .cart-bubble { display: flex; }

/* --- burger: left rail, tablet and below only --- */
.nav__burger { display: none; }        /* revealed in the ≤1080 query */

/* ============================================================
   DRAWER MENU — tablet + mobile
   Slides in from the left, matching the side the burger sits on.
   Linen panel, espresso type: the inverse of the header, so it
   reads as a separate surface rather than an extension of it —
   and the same cream the content pages sit on.
   ============================================================ */
.menu {
  position: fixed;
  inset: 0;
  z-index: 150;                    /* above the nav (100) */
  visibility: hidden;
  transition: visibility 0s linear .45s;   /* hold until the slide-out ends */
}
.menu.is-open { visibility: visible; transition-delay: 0s; }

.menu__backdrop {
  position: absolute; inset: 0;
  background: rgba(52, 36, 28, .45);
  opacity: 0;
  transition: opacity .45s ease;
}
.menu.is-open .menu__backdrop { opacity: 1; }

.menu__panel {
  position: absolute;
  inset: 0 auto 0 0;
  width: min(84vw, 390px);
  display: flex;
  flex-direction: column;
  padding: clamp(1.35rem, 5vw, 2.25rem);
  background: var(--linen);
  transform: translateX(-100%);
  transition: transform .45s cubic-bezier(.33, 1, .68, 1);
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
}
.menu.is-open .menu__panel { transform: translateX(0); }

.menu__close {
  align-self: flex-end;
  width: 42px; height: 42px;
  display: inline-flex; align-items: center; justify-content: center;
  padding: 0; border: 0;
  background: none;
  color: var(--espresso);
  cursor: pointer;
  transition: opacity .3s ease, transform .3s ease;
}
.menu__close svg { width: 20px; height: 20px; display: block; }
.menu__close:hover, .menu__close:focus-visible { opacity: .6; }
.menu__close:active { transform: scale(.92); }

.menu__list {
  list-style: none;
  margin: clamp(1.5rem, 6vh, 3rem) 0 0;
  padding: 0;
}

.menu__link {
  display: block;
  padding: clamp(.9rem, 2.4vh, 1.15rem) 0;
  border-bottom: 1px solid rgba(52, 36, 28, .10);
  color: var(--espresso);
  /* Same links, so the same type as the desktop bar — sentence case
     included, and the tracking gone with the uppercase. */
  font-family: var(--font-nav);
  font-size: 16px;
  font-weight: 600;
  line-height: 25.6px;
  text-decoration: none;
  transition: color .3s ease, padding-left .3s ease;
}
.menu__link:hover, .menu__link:focus-visible {
  color: var(--gold);
  padding-left: .4rem;
}

/* ============================================================
   HERO
   ============================================================ */
/* The height is set by the photo, not the other way round.
   hero-vase.jpg is 16:9. In a box 118svh tall — 130% of that once the
   parallax bleed is added — background-size: cover had to scale it up
   until it filled the height, which threw about a third of the image
   width off the sides. The vase and the sideboard were being cut.

   At 78svh the box is short enough that cover is driven by the width
   instead, so the whole frame is in view. The section no longer runs
   past the fold, which is the price of showing the picture whole. */
/* A fixed height, not a share of the viewport.
   Every viewport-relative value tried here — 118svh, 78svh, a clamp
   against vw — made the framing depend on the shape of the window, so
   the same photo was cropped differently on every screen. A fixed box
   is a fixed crop: wide and short, which is the shape a 16:9 photo
   wants, so cover is driven by the width and the full frame is in view.

   min-height rather than height, so the headline can never be clipped
   by the box it sits in. */
.hero {
  position: relative;
  min-height: 800px;
  overflow: hidden;
  display: flex;
  align-items: center;
}

@media (max-width: 749px) {
  .hero { min-height: 560px; }
}

/* Bled past the top and bottom of the hero so the parallax shift can
   never expose an edge. 6%, not 15%: the bleed is height the hero
   clips, so every percent of it is image the visitor never sees. At
   15% almost a quarter of the frame was being spent outside the box.
   PARALLAX in main.js is 0.05 and must stay under this number. */
.hero__bg {
  position: absolute;
  inset: -6% 0;
  background-color: var(--navy);            /* fallback while image loads */
  background-image: var(--hero-image);
  background-size: cover;
  background-position: center;
  transform: scale(1);
  transform-origin: center center;
  will-change: transform;
}

.hero__inner {
  position: relative; z-index: 2;
  width: 100%;
  /* The header no longer overlaps the hero, so the old
     calc(var(--nav-h) + 2rem) reserve is gone — it would now push the
     content off-centre inside a flex-centred section. */
  padding: clamp(3rem, 8vh, 6rem) var(--gutter);
}

/* --- staggered headline: line 1 flush left, line 2 pushed ~43% --- */
.hero__title {
  margin: 0 0 clamp(1.5rem, 3.4vh, 2.6rem);
  font-family: Poppins, sans-serif;
  font-weight: 400;
  /* 84px is the ceiling, not a fixed value. "Handcrafted Vases" is
     874px wide at 84px, so anything under roughly a 1000px window
     cannot hold it — and .hero__line is nowrap by design, so it would
     be clipped rather than wrapped. The clamp gives the specified 84px
     on a desktop and eases down through the tablet range that the
     720px rule below never reaches. */
  font-size: clamp(2.4rem, 7.6vw, 84px);
  /* 1 is 84/84 — identical at the top of the clamp, and it keeps pace
     on the way down, which a fixed 84px line box would not. */
  line-height: 1;
  color: rgb(255, 255, 255);
  text-transform: uppercase;
  /* No letter-spacing: the -.02em here was cut for Archivo at this
     size and pulls Poppins too tight. */
}
/* Never let a line break internally — the headline is two lines by
   design at every width. No-op on desktop, where both already fit. */
.hero__line { display: block; white-space: nowrap; }
.hero__line--1 { text-align: left; }
.hero__line--2 { text-align: right; }   /* right gutter — the stagger */

/* --- CTA: outlined pill, inverts to a solid fill on hover ---
   Keeps the indent the lede used to share with it, so the button still
   sits inside the headline's right-hand stagger rather than flush to
   the gutter. Dropped at the same breakpoint as before.           */
/* Shape, fill and hover all come from .btn--wipe. What is left here is
   what belongs to this button's place on the page: where it sits, and
   the tracked uppercase the rest of the hero is set in. */
.hero__cta {
  margin: clamp(1.75rem, 4vh, 2.75rem) 0 0 clamp(0px, 8%, 130px);
  font-family: var(--font-body);
  font-size: clamp(.72rem, .85vw, .82rem);
  letter-spacing: .22em;
  text-transform: uppercase;
  white-space: nowrap;
  /* transition is declared after the entry-animation block below — that
     rule resets `transition` wholesale and would otherwise kill the hover. */
}

/* ---- Entry animation ----------------------------------------
   Each element slides ~77px into its resting position while fading
   up, over 0.6s on an easeOutCubic curve, staggered 0.15s apart.
   Elements start hidden and are released by .is-revealed on the
   hero, which JS adds on the first frame after load.

   The two lines come from opposite sides, each from the edge it is
   set against: line 1 is flush left and arrives from the left, line 2
   is pushed right and arrives from the right. They close on their
   final positions from outside rather than travelling in convoy.
   The hero is overflow:hidden, so the outward start is clipped and
   never widens the page.                                        */
.hero__line--1,
.hero__line--2,
.hero__cta {
  opacity: 0;
  transition:
    opacity   .6s cubic-bezier(.33, 1, .68, 1),
    transform .6s cubic-bezier(.33, 1, .68, 1);
}

.hero__line--1,
.hero__cta     { transform: translateX(-77px); }
.hero__line--2 { transform: translateX(77px); }

.hero.is-revealed .hero__line--1,
.hero.is-revealed .hero__line--2,
.hero.is-revealed .hero__cta {
  opacity: 1;
  transform: translateX(0);
}

.hero.is-revealed .hero__line--1 { transition-delay: .15s; }
.hero.is-revealed .hero__line--2 { transition-delay: .30s; }

/* The CTA needs two transitions doing different jobs: the one-off entry
   slide, and the hover wipe that has to stay responsive forever after.
   A blanket `transition-delay: .6s` would have made every hover wait
   six-tenths of a second, so the entry delay is baked per-property here
   instead.

   Two classes, because .btn--wipe sets a transition of its own and is
   declared further down the file — on one class it would win on source
   order and the entry slide would simply snap into place.

   The delay was .6s when a paragraph sat between the headline and this
   button. With the paragraph gone the button is third in the stagger,
   not fourth, so it follows the second line at .45s — otherwise there
   is a beat of nothing where the copy used to be. */
.hero__cta.btn--wipe {
  transition:
    opacity      .6s cubic-bezier(.33, 1, .68, 1) .45s,
    transform    .6s cubic-bezier(.33, 1, .68, 1) .45s,
    color        .4s ease,
    border-color .4s ease;

  /* A white edge on the hero button only — the collection buttons keep
     theirs matched to the fill. The border was already there at 1px in
     the fill colour, so this recolours it rather than adding one, and
     the button does not change size. */
  border-color: var(--btn-wipe-fg);
}

/* The edge swaps colour with the label as the wipe passes under it.
   Left white it would disappear at the moment the white fill arrived —
   not removed, but with nothing to show against. Navy keeps the button
   drawn as a shape the whole way through. */
.hero__cta.btn--wipe:hover,
.hero__cta.btn--wipe:focus-visible { border-color: var(--btn-wipe-bg); }

/* ============================================================
   WIPE BUTTON
   Shared by the hero call to action and the two collection buttons.
   The fill is a ::before that scales in from the left underneath the
   label; isolation: isolate is what keeps a z-index:-1 child inside
   the button rather than sliding behind the section itself.
   ============================================================ */
.btn--wipe {
  position: relative;
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 14px 32px;
  border-radius: 999px;
  background: var(--btn-wipe-bg);
  border: 1px solid var(--btn-wipe-bg);
  color: var(--btn-wipe-fg);
  overflow: hidden;
  isolation: isolate;
  cursor: pointer;
  text-decoration: none;
  font-weight: 600;
  transition: color .4s ease;
}
/* The fill is a pill the size of the button, parked off to the left and
   slid across — not a rectangle stretched from scaleX(0).

   That is the whole difference in how the edge reads. A stretched
   rectangle meets the navy in a straight vertical line; scaling a
   rounded one squashes its radius into a flat ellipse. Sliding a pill
   keeps its cap circular the whole way, so the boundary between the two
   colours stays a bracket, and it lands exactly on the button's own
   rounded ends when it arrives. */
.btn--wipe::before {
  content: '';
  position: absolute;
  top: 0; bottom: 0; left: 0;
  width: 100%;
  background: var(--btn-wipe-fg);
  border-radius: 999px;
  /* A few pixels past its own width, not exactly its own width. At
     -100% the pill's rounded cap comes to rest touching the button's
     inner left edge at the midpoint, and that contact antialiases into
     a white hairline down the left end. Park it clear. */
  transform: translateX(calc(-100% - 4px));
  transition: transform .4s ease;
  z-index: -1;
}
/* :focus-visible as well as :hover — the wipe is the only thing telling
   you the button is live, so a keyboard should get it too. */
.btn--wipe:hover::before,
.btn--wipe:focus-visible::before { transform: translateX(0); }
.btn--wipe:hover,
.btn--wipe:focus-visible { color: var(--btn-wipe-bg); }

/* ============================================================
   SECTION 2 — PRODUCT CAROUSEL
   --per-view is the whole responsive story: 3 across on desktop,
   2 on tablet and phone. Card width is derived from it, so the
   breakpoint only ever changes that one number.
   ============================================================ */
.products {
  --per-view: 3;
  --card-gap: clamp(1.25rem, 5vw, 4.5rem);

  /* How much of the next card shows. The clip has to clear the gap
     first — the space immediately past the last full card is empty, so
     a peek smaller than the gap reveals nothing but background.

     Declared here, on the section, rather than on .carousel: the arrows
     are a sibling of the carousel, not a child, and they need the same
     numbers to work out where the middle of a photo is. A custom
     property only travels downwards. */
  --card-sliver: clamp(6px, 1vw, 24px);
  --card-peek: calc(var(--card-gap) + var(--card-sliver));

  /* Top was 3/7vh/5.5 and bottom 4/10vh/8; both came down a fifth, then
     the bottom came down again to the same 5.6vh the top uses. The two
     ends of the section now breathe alike, where the bottom used to be
     roughly half again as deep as the top. */
  padding: clamp(2.4rem, 5.6vh, 4.4rem) 0 clamp(2.25rem, 5.6vh, 4.5rem);
  background-color: var(--sand);
}

/* --- head: intro left, lede centre, arrows right --- */
/* One column now: the paragraph went, and the arrows moved onto the
   carousel itself. Nothing else shares this row. */
.products__head {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  align-items: start;
  gap: clamp(1.5rem, 4vw, 4rem);
  /* The gap down to the cards, also at 0.8. Was 2.5/6vh/4.5. */
  padding: 0 var(--gutter) clamp(2rem, 4.8vh, 3.6rem);
}

.products__eyebrow {
  margin: 0 0 clamp(.9rem, 2vh, 1.4rem);
  color: var(--taupe);
  font-size: clamp(.72rem, .85vw, .82rem);
  font-weight: 500;
  letter-spacing: .18em;
  text-transform: uppercase;
}

.products__title {
  margin: 0;
  color: var(--gold);                /* #AC8359 */
  font-family: Newsreader, serif;
  /* 48px is the ceiling. "Touched by Nature" plus its indent needs
     about 620px, so on a phone a fixed 48px wrapped both lines and the
     heading came out as four. The clamp holds 48px wherever there is
     room and steps down where there is not. */
  font-size: clamp(1.5rem, 9vw, 48px);
  /* 1.1, the ratio the 48/52.8 pair had — identical at the top of the
     clamp, and it keeps pace on the way down. */
  line-height: 1.1;
  font-weight: 400;
  /* No text-transform: the words carry their own capitals, so the
     markup is what decides the case rather than the stylesheet.
     No max-width either — the two spans below set the line breaks, so
     a measure could only ever wrap them somewhere unintended. */
}

/* nowrap so a line can never break inside itself. The heading is two
   lines by design; without this the clamp could still be defeated by a
   width it did not anticipate and the phrase would come apart. */
.products__title-line { display: block; white-space: nowrap; }

/* The second line steps in from the first. */
.products__title-line--2 { padding-left: clamp(1.25rem, 3vw, 2.5rem); }

/* The row and the two arrows over it. */
.carousel-wrap { position: relative; }

/* One button against each edge of the row. The container spans the
   wrap and is click-through, so only the circles themselves take the
   pointer — otherwise an invisible bar across the whole row would
   swallow clicks meant for the cards under it. */
.products__nav {
  position: absolute;
  inset: 0;
  z-index: 3;
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  /* No padding here. The buttons inset themselves with a margin
     instead, so this element's content box stays exactly the section's
     width — which is what the percentage in their margin-top below is
     measured against. Padding here would shrink it and drop the arrows
     a few pixels off the middle of the photo. */
  pointer-events: none;
}

/* Centred on the photo, not on the card.
   The card is the photo plus a name and a price, so centring on the
   whole row drops the arrows about fifty pixels below the middle of
   the image. This walks them down by half the photo's height instead.

   The photo is 1.25x the card's width (its 4:5 box), and the card's
   width is the same expression the cards themselves use. This element
   spans the whole section, so the two gutters come off first — that is
   the width the cards are actually laid out in. A percentage in margin
   resolves against the containing block's width, which is what makes
   it expressible at all. */
.carousel-btn {
  --btn-size: clamp(38px, 2.9vw, 46px);
  margin-inline: clamp(8px, 1.2vw, 20px);
  margin-top: calc(
    0.625 * (100%
             - 2 * var(--gutter)
             - (var(--per-view) - 1) * var(--card-gap)) / var(--per-view)
    - var(--btn-size) / 2
  );
  pointer-events: auto;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: var(--btn-size);
  aspect-ratio: 1;
  padding: 0;
  border: 0;
  border-radius: 50%;
  background-color: #0A1C2B;
  color: var(--white);
  cursor: pointer;
  transition: background-color .3s ease, color .3s ease, transform .3s ease;
}
.carousel-btn svg { width: 42%; height: 42%; display: block; }

/* The arrow turns navy as the circle turns pale. Left white it would
   sit at about 1.9:1 on #C3C9CD and all but disappear at the moment
   the pointer is on it. */
.carousel-btn:hover,
.carousel-btn:focus-visible {
  background-color: #C3C9CD;
  color: #0A1C2B;
}
.carousel-btn:active { transform: scale(.93); }

/* --- track ---
   The peek is set here rather than being whatever falls out of the
   layout. It used to be gutter minus gap — 77px of a 336px card, which
   read as a fourth product cut in half rather than as a hint. Now the
   clip box is the content box widened by --card-peek on each side, so
   exactly that much of the neighbour shows and the gap can change
   without moving it.

   The margin holds the first card on the same left edge as the heading
   above it; the padding then puts the peek back inside the clip. */
.carousel {
  overflow: hidden;
  margin: 0 calc(var(--gutter) - var(--card-peek));
  padding: 0 var(--card-peek);
}

.carousel__track {
  display: flex;
  gap: var(--card-gap);
  margin: 0;
  padding: 0;
  list-style: none;
  will-change: transform;
  /* shorter than the hero's motion — a carousel you swipe repeatedly
     has to get out of your way */
  transition: transform .45s cubic-bezier(.33, 1, .68, 1);
}

/* Exactly --per-view cards span the track, gaps included. */
.card {
  flex: 0 0 calc(
    (100% - (var(--per-view) - 1) * var(--card-gap)) / var(--per-view)
  );
  min-width: 0;
}

.card { position: relative; }

/* The card rises instead of the photo swelling. One transform on the
   whole card, so the picture, the name and the price travel together
   and the card you are pointing at is simply the one standing forward;
   everything else stays where it was and the previous card settles back
   on its own as the pointer leaves it. */
.card {
  transition: transform .35s cubic-bezier(.33, 1, .68, 1);
}
.card:hover,
.card:focus-within {
  transform: translateY(-10px);
}

.card__link { display: block; text-decoration: none; color: inherit; }

/* The anchor sits between .card__media and the photo. Left at auto height
   it collapsed to the image's own square aspect, so a 334×334 image sat in
   a 334×417 box and left 84px of white beneath it — which read as dead
   padding under every product. Stretching the anchor gives the image's
   height:100% something real to resolve against, and object-fit: cover
   then crops the sides instead (the photos carry ~34% side margin, so
   losing 10% a side never touches the vase). */
/* position: relative so the hover photo below can pin itself to this
   box rather than to .card__media. */
.card__media > .card__link { position: relative; width: 100%; height: 100%; }

/* --- the second photo, revealed on hover ---
   Stacked on the first and faded in, rather than swapping the src: a
   swap shows a gap while the new file loads, and on a slow connection
   that gap is the whole hover. */
.card__img--alt {
  position: absolute;
  inset: 0;
  opacity: 0;
  transition: opacity .45s ease;
}
.card:hover .card__img--alt,
.card:focus-within .card__img--alt { opacity: 1; }

/* The same drive-by problem the lift has: cards sliding under a
   stationary pointer would flicker between their two photos. */
.carousel.is-moving .card__img--alt {
  opacity: 0;
  transition: none;
}

/* The slivers at either edge. main.js measures which cards sit wholly
   inside the clip box and marks the rest; being unhittable is what
   withdraws the lift, the photo swap, the quick-add and the link all at
   once, since none of them can fire on an element the pointer cannot
   reach. */
.card.is-peek { pointer-events: none; }

/* Portrait, and filled. The 1cm white strip that used to sit under the
   photo is gone: with object-fit: cover the square photos are scaled up
   until they cover this box, so the frame carries no padding on any
   edge. The cost is the sides of a square photo — the vases have wide
   margins and lose nothing that matters, and the details composite is
   trimmed rather than letterboxed, which is the trade asked for. */
.card__media {
  position: relative;
  aspect-ratio: 4 / 5;
  overflow: hidden;
  background-color: var(--white);
}

/* cover, against a square box. Every photo is square too, so cover
   crops nothing today — it simply fills. It is the safer of the two
   for a photo that arrives at some other ratio later: that one gets
   trimmed rather than leaving the white bands this card is meant not
   to have. */
.card__img {
  width: 100%; height: 100%;
  display: block;
  object-fit: cover;
}

/* One inset for the name and the price, so the two always start on the
   same edge — set them separately and they drift the moment either is
   touched. */
.card { --card-text-inset: clamp(.6rem, 1.1vw, 1rem); }

.card__name {
  margin: clamp(.9rem, 2vh, 1.3rem) 0 .45rem;
  padding-left: var(--card-text-inset);
  color: rgb(82, 80, 78);
  font-family: Poppins, sans-serif;
  font-size: 18px;
  font-weight: 400;
  line-height: 25.2px;
}

/* Both prices carry the same type, so it is set once here and the two
   spans inherit it. Only the colour differs. */
.card__price {
  margin: 0;
  padding-left: var(--card-text-inset);
  display: flex; flex-wrap: wrap; gap: .55rem; align-items: baseline;
  font-family: 'Red Hat Display', sans-serif;
  font-size: 16px;
  font-weight: 500;
  line-height: 17.6px;
  color: rgb(67, 54, 37);
}

/* The old price steps back a shade. A flat colour rather than an
   opacity, so what is specified is what renders. */
.card__price-was { color: #A79E95; }

/* ============================================================
   QUICK ADD
   A pill that fades in with the card, widens on its own hover to
   reveal the label, and on click swaps icon+label for a centred
   "Added!" before reverting.

   Selectors are mapped onto this file's existing class names
   (.card / .quick-add) instead of .product-card / .quick-add-button.
   Every property value is as specified.
   ============================================================ */
.quick-add {
  position: absolute;
  right: 16px;
  bottom: 16px;
  z-index: 2;

  display: flex;
  align-items: center;
  padding: 0;

  background: #ffffff;
  border-radius: 50px;
  border: 2px solid hsl(0 0% 0% / 0.15);
  height: 44px;
  color: #000000;

  opacity: 0;
  cursor: pointer;
  overflow: hidden;                  /* clips the label while collapsed */
  backdrop-filter: blur(20px) saturate(180%);
  transition:
    scale   .3s cubic-bezier(.33, 1, .68, 1),
    opacity .3s cubic-bezier(.33, 1, .68, 1);
}

/* revealed by the card, not by itself — it has to exist before you
   can aim at it */
.card:hover .quick-add,
.card:focus-within .quick-add { opacity: 1; }

.quick-add:hover  { scale: 1.03; }
.quick-add:active { scale: .99; }
.quick-add:focus-visible {
  outline: none;
  box-shadow: 0 0 0 3px rgba(0, 0, 0, .12);
}

/* Fixed square so the collapsed pill is a true circle. */
.qa-icon {
  display: grid;
  place-items: center;
  width: 40px;
  height: 40px;
  flex: none;
}
.qa-icon svg { width: 20px; height: 20px; display: block; }
.qa-icon svg path { stroke-width: 1.7; }

/* 0fr → 1fr is what animates the width. The grid item needs its own
   overflow, or the label would keep the track from ever collapsing. */
.quick-add .text-content {
  display: grid;
  grid-template-columns: 0fr;
  transition: grid-template-columns .3s cubic-bezier(.33, 1, .68, 1);
}
.quick-add:hover .text-content,
.quick-add:focus-visible .text-content {
  grid-template-columns: 1fr;
  transition-delay: .3s;
}
.quick-add .text-content span {
  min-width: 0;
  overflow: hidden;
  white-space: nowrap;
  /* Padding sits on the expanded state only. On the collapsed 0fr track
     it would still occupy its 8px, leaving a 51px-wide oval instead of a
     44px circle.

     It has to be in the transition list, and on the same curve as the
     grid track. Left untransitioned it snapped to 8px the instant the
     cursor arrived while the track still waited out its 0.3s delay —
     the button widened in two visible steps. */
  padding-right: 0;
  font-family: var(--font-body);
  font-size: .85rem;
  color: #000000;
  opacity: 0;
  filter: blur(2px);
  translate: .5ch 0;
  transition:
    opacity       .4s ease,
    filter        .4s ease,
    translate     .4s ease,
    padding-right .3s cubic-bezier(.33, 1, .68, 1);
}
.quick-add:hover .text-content span,
.quick-add:focus-visible .text-content span,
.quick-add[data-added="true"] .text-content span {
  padding-right: 8px;
}
.quick-add:hover .text-content span,
.quick-add:focus-visible .text-content span {
  opacity: 1;
  filter: blur(0);
  translate: 0 0;
  transition-delay: .3s;
}

/* --- "Added!" overlay --- */
.added-overlay {
  position: absolute;
  top: 50%; left: 50%;
  translate: -50% -50%;
  opacity: 0;
  display: flex;
  align-items: center;
  gap: 4px;
  white-space: nowrap;
  font-family: var(--font-body);
  font-size: .85rem;
  color: #000000;
  pointer-events: none;
}
.added-overlay svg { width: 16px; height: 16px; display: block; flex: none; }

/* The icon runs the same keyframes as the label, otherwise it would sit
   under the checkmark still fully opaque. */
.quick-add[data-added="true"] .text-content,
.quick-add[data-added="true"] .qa-icon {
  animation: atc-fade-out .2s ease forwards;
}
.quick-add[data-added="true"] .added-overlay {
  animation: atc-fade-in .2s ease .2s forwards;
}

/* Hold the pill open and visible for the whole confirmation, even if the
   cursor has already left the card — otherwise "Added!" is clipped by a
   collapsing button, or fades out with it. */
.quick-add[data-added="true"] { opacity: 1; }
.quick-add[data-added="true"] .text-content { grid-template-columns: 1fr; }

@keyframes atc-fade-out {
  to { opacity: 0; scale: 0.9; }
}
@keyframes atc-fade-in {
  from { opacity: 0; scale: 0.8; }
  to   { opacity: 1; scale: 1; }
}

/* ============================================================
   CART DRAWER
   ============================================================ */
.cart {
  position: fixed;
  inset: 0;
  z-index: 200;                    /* above nav (100) and menu (150) */
  visibility: hidden;
  transition: visibility 0s linear .45s;
}
.cart.is-open { visibility: visible; transition-delay: 0s; }

.cart__backdrop {
  position: absolute; inset: 0;
  background: rgba(52, 36, 28, .45);
  opacity: 0;
  transition: opacity .45s ease;
}
.cart.is-open .cart__backdrop { opacity: 1; }

.cart__panel {
  position: absolute;
  inset: 0 0 0 auto;               /* right-hand edge */
  width: min(92vw, 440px);
  display: flex;
  flex-direction: column;
  background: var(--sand);
  transform: translateX(100%);
  transition: transform .45s cubic-bezier(.33, 1, .68, 1);
}
.cart.is-open .cart__panel { transform: translateX(0); }

.cart__head {
  display: flex;
  align-items: center;
  gap: .75rem;
  padding: clamp(1.25rem, 3vw, 1.9rem) clamp(1.25rem, 3vw, 1.9rem) 1rem;
}
.cart__title {
  margin: 0;
  font-family: var(--font-body);
  font-size: 1.05rem;
  font-weight: 500;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--cocoa);
}
.cart__count {
  display: inline-grid; place-items: center;
  min-width: 26px; height: 26px;
  padding: 0 .45rem;
  border-radius: 999px;
  background: rgba(52, 31, 22, .10);
  color: var(--cocoa);
  font-size: .8rem;
}
.cart__close {
  margin-left: auto;
  width: 44px; height: 44px;
  display: inline-grid; place-items: center;
  border: 1px solid rgba(52, 31, 22, .22);
  border-radius: 50%;
  background: none;
  color: var(--cocoa);
  cursor: pointer;
  transition: background-color .3s ease;
}
.cart__close:hover { background-color: rgba(52, 31, 22, .07); }
.cart__close svg { width: 18px; height: 18px; }

.cart__items {
  flex: 1 1 auto;
  overflow-y: auto;
  margin: 0;
  padding: .5rem clamp(1.25rem, 3vw, 1.9rem);
  list-style: none;
}

.cart__empty {
  padding: 3rem 0;
  color: var(--taupe);
  font-size: .95rem;
  text-align: center;
}

.cart-line {
  display: grid;
  grid-template-columns: 64px 1fr auto;
  gap: .9rem;
  padding: 1.1rem 0;
  border-bottom: 1px solid rgba(52, 31, 22, .08);
}
.cart-line__thumb {
  width: 64px; height: 76px;
  object-fit: cover;
  background: var(--white);      /* the shots are on white — keep it seamless */
}
.cart-line__name {
  margin: 0 0 .3rem;
  font-size: .95rem;
  font-weight: 400;
  line-height: 1.4;
  color: var(--cocoa);
}
.cart-line__price { margin: 0 0 .7rem; display: flex; gap: .5rem; align-items: baseline; }
.cart-line__now { color: var(--cocoa); font-size: .9rem; font-weight: 500; }
.cart-line__was { color: var(--taupe); opacity: .6; font-size: .85rem; }
.cart-line__total { color: var(--cocoa); font-size: .9rem; white-space: nowrap; }

.cart-line__controls { display: flex; align-items: center; gap: .75rem; }
.qty {
  display: inline-flex;
  align-items: center;
  border: 1px solid rgba(52, 31, 22, .2);
  border-radius: 6px;
}
.qty button {
  width: 34px; height: 34px;
  display: grid; place-items: center;
  border: 0; background: none;
  color: var(--cocoa);
  font-size: 1.05rem; line-height: 1;
  cursor: pointer;
}
.qty button:hover { color: var(--arrow); }
.qty__value { min-width: 30px; text-align: center; font-size: .92rem; color: var(--cocoa); }

.cart-line__remove {
  width: 34px; height: 34px;
  display: grid; place-items: center;
  padding: 0; border: 0; background: none;
  color: var(--taupe);
  cursor: pointer;
  transition: color .3s ease;
}
.cart-line__remove:hover { color: #A33; }
.cart-line__remove svg { width: 17px; height: 17px; }

.cart__foot {
  flex: 0 0 auto;
  padding: 1.1rem clamp(1.25rem, 3vw, 1.9rem) clamp(1.25rem, 3vw, 1.9rem);
  border-top: 1px solid rgba(52, 31, 22, .1);
}
/* --- free-shipping nudge: shown while the cart holds 1 unit or fewer --- */
.cart__ship {
  display: none;                 /* JS flips this to grid */
  grid-template-columns: auto 1fr;
  align-items: center;
  gap: .85rem;
  margin-bottom: 1.1rem;
  padding: .95rem 1.05rem;
  border: 1px dashed #A9CDB3;
  border-radius: 10px;
  background-color: #F0F7F1;
}
.cart__ship.is-shown { display: grid; }
.cart__ship-icon {
  display: grid; place-items: center;
  width: 42px; height: 42px;
  border-radius: 50%;
  background-color: #2E7D4F;
  color: var(--white);
}
.cart__ship-icon svg { width: 21px; height: 21px; }
.cart__ship p {
  margin: 0;
  color: var(--cocoa);
  font-size: .95rem;
  line-height: 1.45;
}

.cart__discount {
  display: flex; align-items: center; justify-content: space-between;
  width: 100%;
  padding: .85rem 0;
  border: 0; border-bottom: 1px solid rgba(52, 31, 22, .1);
  background: none;
  color: var(--cocoa);
  font-family: var(--font-body);
  font-size: .95rem;
  cursor: pointer;
}
.cart__discount-plus {
  font-size: 1.25rem;
  line-height: 1;
  transition: transform .3s ease;
}
.cart__discount[aria-expanded="true"] .cart__discount-plus { transform: rotate(45deg); }

/* Collapsed by default; max-height animates it open without needing a
   measured height. 120px clears the field at any sane font size. */
.cart__discount-panel {
  display: grid;
  grid-template-columns: 1fr auto;
  gap: .6rem;
  max-height: 0;
  margin-top: 0;
  overflow: hidden;
  opacity: 0;
  /* visibility keeps the collapsed field out of the tab order and away
     from screen readers — max-height alone would still leave it focusable */
  visibility: hidden;
  transition: max-height .35s ease, opacity .25s ease, margin-top .35s ease,
              visibility 0s linear .35s;
}
.cart__discount-panel.is-open {
  max-height: 120px;
  margin-top: .9rem;
  opacity: 1;
  visibility: visible;
  transition: max-height .35s ease, opacity .25s ease, margin-top .35s ease,
              visibility 0s linear 0s;
}

.cart__discount-input {
  min-width: 0;
  padding: .95rem 1rem;
  border: 0;                     /* no border — white field on sand carries it */
  border-radius: 6px;
  background: var(--white);
  color: var(--cocoa);
  font-family: var(--font-body);
  font-size: .95rem;
}
.cart__discount-input::placeholder { color: var(--taupe); opacity: .75; }

/* The panel needs overflow:hidden for its slide-open animation, and that
   was slicing the default outline into four corner fragments. An inset
   ring is painted inside the element's own box, so nothing can clip it —
   a complete rectangle on both controls. */
.cart__discount-input:focus-visible,
.cart__apply:focus-visible {
  outline: none;
  box-shadow: inset 0 0 0 2px var(--arrow);
}
.cart__apply:focus-visible { box-shadow: inset 0 0 0 2px var(--white); }

.cart__apply {
  padding: .95rem 1.75rem;
  border: 0; border-radius: 6px;
  background-color: var(--arrow);
  color: var(--white);
  font-family: var(--font-body);
  font-size: .98rem;
  cursor: pointer;
  transition: background-color .3s ease;
}
.cart__apply:hover { background-color: var(--arrow-hover); }
.cart__totals { padding: 1.15rem 0 .4rem; }
.cart__totals-row {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: 1rem;
}
.cart__totals dt,
.cart__totals dd { margin: 0; font-size: .95rem; color: var(--taupe); }
.cart__totals-row + .cart__totals-row { margin-top: .45rem; }

/* The line that actually gets paid, set apart from the two that explain
   how it was arrived at. */
.cart__totals-row--sum {
  margin-top: .7rem;
  padding-top: .7rem;
  border-top: 1px solid rgba(52, 31, 22, .12);
}
.cart__totals-row--sum dt,
.cart__totals-row--sum dd { font-size: 1.05rem; color: var(--cocoa); }
.cart__note { margin: 0 0 1.1rem; color: var(--taupe); font-size: .82rem; }

.cart__checkout {
  display: block;
  width: 100%;
  padding: 1.05rem;
  text-align: center;              /* it is a link now, not a button */
  text-decoration: none;
  border: 0; border-radius: 6px;
  background-color: var(--arrow);
  color: var(--white);
  font-family: var(--font-body);
  font-size: .98rem;
  letter-spacing: .04em;
  cursor: pointer;
  transition: background-color .3s ease;
}
.cart__checkout:hover { background-color: var(--arrow-hover); }

/* Placeholder shown only while a product photo is missing — the
   error handler adds .is-missing. Delete both once the three
   files are in assets/. */
.card__media.is-missing { background-color: #DCD2C9; }
.card__media.is-missing::after {
  content: 'photo pending';
  position: absolute; inset: 0;
  display: grid; place-content: center;
  color: var(--taupe);
  font-size: .7rem; letter-spacing: .2em; text-transform: uppercase;
}

/* ============================================================
   SECTION 3 — COLLECTIONS
   Two cards side by side, stacking on phones. Vertical padding is
   copied from .products so the two sections sit on the same rhythm.
   ============================================================ */
.collections {
  /* Bottom brought down to the same 5.6vh the carousel section above
     settled on, so the two bands breathe alike rather than this one
     leaving a deep gap above the footer. Was 4rem/10vh/8rem. */
  padding: clamp(3rem, 7vh, 5.5rem) 0 clamp(2.25rem, 5.6vh, 4.5rem);
  background-color: var(--linen);
}

/* Same face, weight and colour as the carousel headline above it. */
.collections__title {
  margin: 0 0 clamp(1.75rem, 4vh, 3rem);
  padding: 0 var(--gutter);
  color: rgb(172, 131, 89);
  font-family: Newsreader, serif;
  font-weight: 400;
  /* 48px is the ceiling rather than a fixed value: at 48px this
     heading is wider than a phone, so it would wrap or run off the
     side. Full size from about 1090px up, easing down below that. */
  font-size: clamp(1.75rem, 4.4vw, 48px);
  /* 1.1, the ratio the 48/52.8 pair has, so the leading keeps pace as
     the clamp comes down. */
  line-height: 1.1;
  /* No text-transform: the markup already reads "Shop by Collection",
     so the case belongs to the words rather than the stylesheet. */
}

.collections__grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: clamp(1rem, 2vw, 1.75rem);
  padding: 0 var(--gutter);
}

.collection {
  position: relative;
  display: block;
  aspect-ratio: 4 / 3;
  overflow: hidden;              /* clips the zoom */
  background-color: #E2DAD2;     /* shows through before the photo loads */
  text-decoration: none;

  /* Dark type, not white. Both photos are bright — measured luminance
     160–199 of 255 where the text sits — so white ran at 1.7–2.6:1 and
     was effectively invisible. No scrim is allowed on this site, so the
     contrast is bought with the type colour instead. */
  color: var(--cocoa);
}

/* The media wrapper is what fills the card — the image fills the wrapper.
   Sizing the image absolutely instead would leave the wrapper at zero
   height and the "photo pending" placeholder with nothing to paint on. */
.collection__media {
  position: absolute;
  inset: 0;
  overflow: hidden;
}
.collection__img {
  width: 100%;
  height: 100%;
  display: block;
  object-fit: cover;
  transition: transform .6s cubic-bezier(.33, 1, .68, 1);
}

/* Hover only where a hover exists. Phones keep :hover applied to whatever
   you last touched, which would leave a card stuck mid-zoom. */
@media (hover: hover) and (pointer: fine) {
  .collection:hover .collection__img,
  .collection:focus-visible .collection__img { transform: scale(1.06); }
}

/* Name top-left, call to action bottom-right — diagonally opposed, both
   inset by the same amount so the card reads as one framed block. */
.collection { --collection-inset: clamp(1.1rem, 2.4vw, 2rem); }

.collection__name {
  position: absolute;
  top:  var(--collection-inset);
  left: var(--collection-inset);
  right: var(--collection-inset);   /* wraps rather than running off the edge */
  margin: 0;
  text-align: left;
  font-family: var(--font-display);
  font-weight: 500;
  font-size: clamp(1.35rem, 2.4vw, 2.25rem);
  line-height: 1.1;
  letter-spacing: .02em;
  text-transform: uppercase;
}

/* Shape, fill and hover come from .btn--wipe; this places it and sets
   the tracked uppercase to match the collection name above it. */
/* Everything here is the previous value at 0.8 — the vertical padding
   inherited from .btn--wipe, the narrower horizontal padding these two
   carry, the gap, the type and the arrow. Scaling one and not the rest
   would only change the button's proportions rather than its size.
   letter-spacing is left alone: it is in em, so it comes down with the
   type by itself. */
.collection__cta {
  position: absolute;
  bottom: var(--collection-inset);
  right:  var(--collection-inset);
  gap: 6.4px;                        /* was 8px, from .btn--wipe */
  padding-top: 11.2px;               /* was 14px, from .btn--wipe */
  padding-bottom: 11.2px;
  /* Narrower than the shared padding. These two sit inside a card
     rather than on open ground, so they carry less air at the ends. */
  padding-left: 19.2px;              /* was 24px */
  padding-right: 19.2px;
  font-family: var(--font-body);
  font-size: clamp(.6rem, .72vw, .68rem);
  letter-spacing: .18em;
  text-transform: uppercase;
}
.collection__cta svg {
  width: 11.2px; height: 11.2px;     /* was 14px */
  display: block;
  flex: none;
  transition: translate .3s ease;
}

/* The button answers to the pointer being on the button. It used to
   answer to the pointer being anywhere on the card, which meant it lit
   up while you were only looking at the photograph. */
.collection__cta:hover svg,
.collection__cta:focus-visible svg { translate: 4px 0; }

/* Smaller again on a phone. The card shrinks with the screen but the
   button's padding and type were fixed, so it kept taking a bigger
   share of the corner it sits in. */
@media (max-width: 749px) {
  .collection__cta {
    gap: 6px;
    padding: 9px 16px;
    font-size: 11px;
    letter-spacing: .14em;
  }
  .collection__cta svg { width: 12px; height: 12px; }
}

/* Same treatment as the product cards while the photos are missing. */
.collection__media.is-missing { background-color: #DCD2C9; }
.collection__media.is-missing::after {
  content: 'photo pending';
  position: absolute; inset: 0;
  display: grid; place-content: center;
  color: var(--taupe);
  font-size: .7rem; letter-spacing: .2em; text-transform: uppercase;
}

/* ============================================================
   SECTION 4 — TWO-UP PROMO
   Two photo tiles framed and divided by white.

   The white lines are the section's own background showing through:
   its padding makes the outer frame and the grid gap makes the one
   between, so there is a single number to change and the four lines
   can never end up different widths.
   ============================================================ */
.promo {
  --promo-line: clamp(8px, 1vw, 14px);

  padding: var(--promo-line);
  background-color: var(--white);
}

.promo__grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--promo-line);
  /* No cap. The row runs the full width, so the white down the outside
     is the same --promo-line as the white between — one frame of an
     even thickness on all four sides rather than a thin seam in the
     middle and a wide margin at the edges. */
}

/* Square, up to a ceiling.
   Square matches the photographs, so up to 700px the tile holds the
   whole frame with nothing trimmed. Past that — a wide monitor, where
   a full-width square tile would be over 900px tall and the section
   would swallow the screen — the ceiling takes over, the tile turns
   landscape, and cover zooms the photo to fill it.

   The ratio is 10:9 rather than square, which takes roughly 1.5cm off
   the section at the widths where the ceiling is not already doing it,
   and the ceiling is 640 for what the crop costs at the far end: at
   1920 the tile is 939 wide, so 640 trims about a third of the height.
   The plume begins around 20% down the frame and the vase foot sits
   around 85%; object-position below holds the visible band between
   them rather than centring it. */
/* An explicit height, and no aspect-ratio.
   aspect-ratio plus max-height was the bug behind the uneven white.
   Once the cap engaged, the tile could no longer be as tall as the
   ratio demanded, so the box shrank in width to keep the ratio and
   then sat at the left of its grid column — leaving dead space to its
   right. That space read as extra padding in the middle and on the
   right, while the left stayed at the true frame width. It only showed
   on a wide screen, because the cap never engaged on a narrow one.

   A height in its own right leaves the width alone: the tile stretches
   to fill its column as a grid item should, so every gap is the frame
   and nothing else. The calc tracks the column — roughly nine tenths
   of half the viewport — so the tile stays near square until 640
   stops it. */
.promo__tile {
  position: relative;
  display: block;
  height: clamp(280px, calc(45vw - 19px), 640px);
  overflow: hidden;
  background-color: var(--sand);   /* while the photo loads */
  text-decoration: none;
  color: inherit;
}

.promo__img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  /* The tile is a little wider than the square photo, so the trim is
     vertical. 55% rather than centre spends slightly more of it on the
     wall above than on the table below, which is what keeps the foot
     of the vase in frame at the widest sizes. */
  object-fit: cover;
  object-position: center 55%;
}

/* Over the top of the picture, where both photos are a pale wall. */
/* One line of type over each photograph, placed per tile.
   Absolute rather than in flow, so "top left" and "centre left" are
   both expressible against the tile itself rather than against
   whatever happens to sit above the text. */
.promo__copy {
  --promo-copy-inset: clamp(1.25rem, 3vw, 2.75rem);

  position: absolute;
  left:  var(--promo-copy-inset);
  right: var(--promo-copy-inset);   /* long lines wrap inside the tile */
  z-index: 1;
  margin: 0;
  /* Was 18ch, cut for 32px type. At 16px that measure would have
     broken the navy line over three, so it is wide enough now for the
     longer of the two to sit on one. */
  max-width: 32ch;
  text-align: left;

  font-family: 'Red Hat Display', sans-serif;
  font-size: 32px;
  font-weight: 700;
  /* 1.1, the ratio this has carried since 16/17.6. */
  line-height: 35.2px;
  color: rgba(0, 0, 0, .71);
}

/* Centred on the tile, not on the text: translate takes back half the
   block's own height, whatever it wraps to. Both tiles use this now —
   the top-left variant went with the navy line when it moved.

   The entry offset is folded into this same transform rather than
   given a rule of its own. translateY is already carrying the
   centring, and a second translateY would replace it, not add to it —
   the line would drop to the top of the tile mid-animation. */
.promo__copy--middle {
  top: 50%;
  transform: translateY(calc(-50% - 28px));
  opacity: 0;
  transition:
    opacity   .7s ease,
    transform .7s cubic-bezier(.33, 1, .68, 1);
}

/* Released by JS when the section comes into view. Coming down from
   above, so the offset is negative and unwinds to the resting -50%. */
.promo.is-revealed .promo__copy--middle {
  opacity: 1;
  transform: translateY(-50%);
}

/* The second tile follows the first. */
.promo.is-revealed .promo__tile:nth-child(2) .promo__copy--middle {
  transition-delay: .15s;
}

/* Nothing to animate for a visitor who has asked for less motion —
   the lines are simply there. */
@media (prefers-reduced-motion: reduce) {
  .promo__copy--middle {
    opacity: 1;
    transform: translateY(-50%);
    transition: none;
  }
}

/* No hover state on the tiles. The photographs are left alone, and a
   keyboard still gets the browser's own focus ring on the link, which
   is what the removed rule was overriding. */

/* One above the other on a phone. Side by side, each tile would be
   about 170px wide — narrower than the words in it. The ratio carries
   over, so a stacked tile is still portrait and still shows the whole
   photograph. */
@media (max-width: 749px) {
  .promo__grid { grid-template-columns: 1fr; }

  /* Stacked, the tile is the full width of the row, so a square is the
     right shape and there is no cap to shrink it. */
  .promo__tile { height: auto; aspect-ratio: 1 / 1; }

  /* 32px is wider than a phone can hold: "pottery texture" alone runs
     past the tile and takes a third line the break was meant to
     prevent. 16px with the same 1.1 leading keeps both lines to two. */
  .promo__copy {
    font-size: 16px;
    line-height: 17.6px;
  }
}

/* ============================================================
   FOOTER
   ============================================================ */
.footer {
  position: relative;                /* anchors the decorative arrow */
  /* Fills most of the screen, leaving the section above just peeking in.
     Column layout + margin-top:auto on the divider drops the bottom bar
     to the floor and lets the gap open up in the middle, rather than
     stretching the content itself. */
  min-height: 88vh;
  display: flex;
  flex-direction: column;
  /* No vertical padding of its own — the top block owns the space above
     the rule, the bottom bar owns the space below it. */
  padding: 0 var(--gutter) clamp(.65rem, 1.2vh, .95rem);
  background-color: var(--footer-bg);
  color: var(--footer-link);
}

/* Decorative only — deliberately not a link, and hidden from readers. */
/* A grid item rather than an absolute one, sharing the top-right cell
   with the contact column. Absolute positioning pinned it to a fixed
   offset, which left it floating above the block once the content was
   centred; as a grid item it rides with the rows. pointer-events:none
   keeps it clear of the newsletter field it overlaps. */
.footer__arrow {
  grid-column: 3;
  grid-row: 1;
  justify-self: end;
  align-self: start;
  /* Nudged up and out past the content edge into the gutter. Using
     translate rather than offsets keeps it out of the layout, so the
     grid cell it sits in doesn't grow to follow it. */
  translate: 16px -16px;
  color: var(--footer-arrow);
  pointer-events: none;
}
.footer__arrow svg {
  width: clamp(56px, 6vw, 110px);
  height: auto;
  display: block;
}

.footer__top {
  position: relative;              /* anchors the arrow to the content block */
  flex: 1 1 auto;                  /* takes all the room above the rule */
  display: grid;
  /* Column 2 carries the newsletter field now, so it needs more room than
     the link list in column 1. */
  grid-template-columns: minmax(0, .85fr) minmax(0, 1.4fr) minmax(0, 1.3fr);
  column-gap: clamp(2rem, 5vw, 6rem);
  row-gap: clamp(2.25rem, 5vh, 3.75rem);
  align-items: start;
  /* Equal padding top and bottom, and align-content centres the rows in
     whatever space is left over — so the block sits in the middle with
     matching air above and below it. */
  align-content: center;
  padding: clamp(3rem, 7vh, 5.5rem) 0;
}

/* --- logo: icon left, wordmark right --- */
.footer__brand {
  grid-column: 1;
  grid-row: 1;
  display: inline-flex;
  align-items: center;
  gap: clamp(.7rem, 1.2vw, 1.1rem);
  text-decoration: none;
}
.footer__brand-icon { height: clamp(46px, 4.6vw, 66px); width: auto; display: block; }
.footer__brand-name { height: clamp(17px, 1.7vw, 24px); width: auto; display: block; }

.footer__col--links   { grid-column: 1; grid-row: 2; }
.footer__col--pay     { grid-column: 2; grid-row: 2; }
/* Row 2, so it starts level with the newsletter rather than with the
   logo. Row 1 of this column now holds only the arrow. */
.footer__col--contact { grid-column: 3; grid-row: 2; }

/* Type spec supplied verbatim. "Google Sans" is Google's proprietary
   face and is not served publicly, so for almost every visitor this
   resolves to Helvetica/Arial rather than to Google Sans. */
.footer__heading {
  margin: 0 0 clamp(1rem, 2.2vh, 1.5rem);
  color: rgb(255, 255, 255);
  font-family: "Google Sans", Helvetica, Arial, sans-serif;
  font-size: 18px;
  font-weight: 400;
  line-height: 28.8px;
  text-transform: uppercase;     /* kept — you asked for "QUICK LINKS" in caps */
}

/* Display size, for "GET IN TOUCH" only. Same caveat as above: "Google
   Sans" is not publicly served, so this resolves to Helvetica/Arial for
   almost every visitor. */
.footer__heading--display {
  font-family: "Google Sans", Helvetica, Arial, sans-serif;
  /* 34px at 375, easing down to 28px on a 320px phone, and your 48px from
     about 505px up — so every screen from small tablet to desktop gets
     the full size. The lower end is set by the arrow: the string measures
     7.11px per px of font size, and beside a 56px arrow a 320px phone has
     room for 28.3px at most. */
  font-size: clamp(28px, 10.9vw - 6.9px, 48px);
  font-weight: 400;
  /* Ratio rather than a fixed 48px, so the leading tracks the size down.
     At the 48px maximum this still computes to exactly 48px. */
  line-height: 1;
}

.footer__list { margin: 0; padding: 0; list-style: none; }
.footer__list li + li { margin-top: clamp(.55rem, 1.3vh, .85rem); }

/* Type spec supplied verbatim. var(--font-body) already resolves to
   exactly Jost, system-ui, -apple-system, sans-serif. */
.footer__link {
  color: var(--footer-link);       /* #D6D3D2 */
  font-family: var(--font-body);
  font-size: 16px;
  font-weight: 300;
  line-height: normal;
  text-decoration: none;
  transition: color .3s ease;
}
.footer__link:hover, .footer__link:focus-visible { color: #805231; }

/* --- social --- */
.footer__social {
  margin: clamp(1.6rem, 3.5vh, 2.5rem) 0 0;
  padding: 0;
  list-style: none;
  display: flex;
  gap: clamp(.5rem, 1vw, .8rem);
}
.footer__social a {
  width: 40px; height: 40px;
  display: grid;
  place-items: center;
  border-radius: 10px;
  background-color: transparent;
  color: var(--footer-link);
  transition: background-color .3s ease, color .3s ease;
}
.footer__social a:hover,
.footer__social a:focus-visible {
  background-color: #FFFFFF;
  color: #333333;
}
.footer__social svg { width: 19px; height: 19px; display: block; }

/* --- payment methods ---
   The Visa / Mastercard / Apple Pay marks are inline SVGs that already
   draw their own 38x24 card, so they need no backing. The InstaPay and
   Etisalat files are artwork only — the Etisalat one is near-black with
   no background of its own and would disappear against this footer — so
   those two get a white card of matching size to sit on. */
.footer__pay-row {
  --pay-w: 48px;
  --pay-h: 30px;

  display: flex;
  flex-wrap: wrap;                 /* back to a horizontal row */
  align-items: center;
  gap: clamp(.45rem, .9vw, .7rem);
}
.footer__pay-row svg {
  width: var(--pay-w);
  height: var(--pay-h);
  display: block;
}

.pay-card {
  width: var(--pay-w);
  height: var(--pay-h);
  flex: none;
  padding: 2px;
  border-radius: 3px;
  background: #FFFFFF;
}

/* Fill the card and let object-fit do the scaling. The previous
   max-width/max-height:100% pair looked equivalent but wasn't: a
   percentage max-height against an auto-height track is a cyclic
   dependency, so the browser discards it. Only the width limit survived,
   which let the square InstaPay artwork render 34x34 and hang 12px below
   a 24px card. Explicit 100%/100% has no such ambiguity. */
.pay-card img {
  width: 100%;
  height: 100%;
  display: block;
  object-fit: contain;
}

/* --- newsletter --- */
/* No bottom margin: the payment cards this used to clear are gone, and a
   trailing gap on the last child of the column is just dead space. */
.signup { margin: 0; }
.signup__row {
  display: flex;
  gap: .6rem;
  max-width: 460px;
}
.signup__input {
  flex: 1 1 auto;
  min-width: 0;
  padding: .95rem 1.1rem;
  border: 1px solid rgba(255, 255, 255, .28);
  border-radius: 6px;
  background: transparent;
  color: #FFFFFF;
  font-family: var(--font-body);
  font-size: .95rem;
}
.signup__input::placeholder { color: var(--footer-label); }
.signup__input:focus-visible {
  outline: none;
  border-color: rgba(255, 255, 255, .7);
}
.signup__btn {
  flex: 0 0 auto;
  padding: .95rem 1.6rem;
  border: 0;
  border-radius: 6px;
  background-color: #FFFFFF;
  color: var(--footer-bg);
  font-family: var(--font-body);
  font-size: .92rem;
  font-weight: 500;
  letter-spacing: .06em;
  cursor: pointer;
  transition: background-color .3s ease;
}
.signup__btn:hover { background-color: #E8E2DC; }
.signup__btn:disabled,
.signup__input:disabled { opacity: .55; cursor: default; }

/* The reply, under the row. Reserves no height while hidden — the
   footer must not shift the moment someone submits. */
.signup__notice {
  margin: .7rem 0 0;
  max-width: 460px;
  color: #FFFFFF;
  font-family: var(--font-body);
  font-size: .88rem;
  line-height: 1.45;
}
.signup__notice.is-bad { color: #F0B8AE; }

/* --- get in touch --- */
.footer__label {
  margin: 0 0 .3rem;
  color: var(--footer-label);
  font-family: var(--font-body);
  font-size: clamp(.85rem, .95vw, .95rem);
  font-weight: 300;
}
.footer__value {
  margin: 0 0 clamp(1.1rem, 2.5vh, 1.7rem);
  font-family: var(--font-display);
  font-size: clamp(1rem, 1.35vw, 1.35rem);
  font-weight: 500;
  letter-spacing: .01em;
  text-transform: uppercase;
}
/* plain text, deliberately not linked */

/* --- divider + bottom bar --- */
/* The top block's flex:1 already pushes this to the footer's floor, so no
   margin-top is needed. The negative side margins cancel the footer's
   gutter so the rule runs the full width of the page, edge to edge. */
.footer__divider {
  margin: 0 calc(var(--gutter) * -1);
  border-top: 1px solid rgba(255, 255, 255, .12);
}

/* Three tracks so the middle one centres on the footer itself, not on
   whatever space the copyright happens to leave over. */
.footer__bottom {
  padding-top: clamp(.65rem, 1.2vh, .95rem);
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: center;
  gap: 1rem;
}
.footer__copy  { grid-column: 1; }
.footer__bottom .policies { grid-column: 2; justify-self: center; }
.footer__copy {
  margin: 0;
  color: var(--footer-link);
  font-family: var(--font-body);
  font-size: .9rem;
  font-weight: 300;
}

/* --- terms dropdown --- */
.policies { position: relative; }
.policies__trigger {
  padding: 0;
  border: 0;
  background: none;
  color: var(--footer-link);
  font-family: var(--font-body);
  font-size: .9rem;
  font-weight: 300;
  cursor: pointer;
  transition: color .3s ease;
}
.policies:hover .policies__trigger,
.policies:focus-within .policies__trigger { color: #FFFFFF; }

/* Opens upward — there is nothing below the footer to open into.
   focus-within keeps it reachable by keyboard, not hover alone. */
.policies__menu {
  position: absolute;
  bottom: calc(100% + .85rem);
  left: 50%;                       /* centred on the trigger, not right-aligned */
  min-width: 210px;
  margin: 0;
  padding: .6rem 0;
  list-style: none;
  border-radius: 12px;
  background: #FFFFFF;
  box-shadow: 0 12px 30px rgba(0, 0, 0, .22);
  opacity: 0;
  visibility: hidden;
  transform: translate(-50%, 6px);
  transition: opacity .25s ease, transform .25s ease, visibility 0s linear .25s;
}
.policies:hover .policies__menu,
.policies:focus-within .policies__menu {
  opacity: 1;
  visibility: visible;
  transform: translate(-50%, 0);
  transition-delay: 0s;
}
/* Bridges the gap so the menu doesn't close as the cursor travels to it. */
.policies__menu::after {
  content: '';
  position: absolute;
  top: 100%; left: 0; right: 0;
  height: .85rem;
}
.policies__menu a {
  display: block;
  padding: .6rem 1.2rem;
  color: #34241C;
  font-family: var(--font-body);
  font-size: .92rem;
  font-weight: 300;
  text-decoration: none;
  white-space: nowrap;
  transition: background-color .2s ease;
}
.policies__menu a:hover,
.policies__menu a:focus-visible { background-color: #F2EEEA; }

/* ============================================================
   A11Y
   ============================================================ */
:focus-visible { outline: 2px solid var(--gold); outline-offset: 4px; }
.skip {
  position: absolute; left: -9999px; top: 0; z-index: 200;
  padding: .9rem 1.4rem;
  background: var(--gold); color: var(--white);
  font-size: .75rem; letter-spacing: .14em; text-transform: uppercase;
  text-decoration: none;
}
.skip:focus { left: var(--gutter); top: 1rem; }

/* ============================================================
   RESPONSIVE
   ============================================================ */
/* Tablet and below: the header re-forms as burger | logo | icons.
   The inline links move into the drawer, which also retires the
   two-row wrap the old layout fell back on. */
@media (max-width: 1080px) {
  .nav { --gutter: clamp(1rem, 3.5vw, 2.5rem); gap: .5rem; }

  .nav__burger { display: inline-flex; grid-column: 1; justify-self: start; }
  .logo        { grid-column: 2; justify-self: center; }
  .nav__center { display: none; }

  /* two products per screen on tablet and phone */
  .products { --per-view: 2; }

  .products__head {
    gap: clamp(1.1rem, 3vh, 1.8rem);
  }
}

/* Arrows are a mouse affordance, so they key off the input device rather
   than the screen width: a tablet in landscape is still a tablet, and a
   narrow desktop window is still a desktop. Touch-primary devices get
   the swipe instead. pan-y keeps vertical scrolling native while
   horizontal movement stays ours to interpret. */
@media (pointer: coarse) {
  .products__nav { display: none; }
  .carousel      { touch-action: pan-y; }

  /* No hover swap on a finger. There is no hovering on a touch screen —
     a tap sets :hover and leaves it set, so the card would silently
     change photo and stay changed, with no way to put it back. The
     gallery on the product page is where the other views belong here. */
  .card__img--alt { display: none; }

  /* Touch gets a plain circle: always visible, icon only, never widens.
     There is no hover on a phone, so an expanding label would either
     never appear or appear at the wrong moment. */
  .quick-add,
  .card:hover .quick-add,
  .card:focus-within .quick-add { opacity: 1; }

  /* Smaller, and further into the corner. At 44px on a ~150px-wide card
     the button was a quarter of the card and sat up alongside the vase;
     32px tucked 8px from each edge keeps it clear of the subject now
     that the photo reaches the bottom.

     Width as well as height: with the label taken out of the layout the
     button was sizing itself from its contents and coming out 0.8px
     narrower than it was tall — an oval, which shows at this size. */
  .quick-add {
    width: 32px;
    height: 32px;
    right: 8px;
    bottom: 8px;
    border-width: 1.5px;
    /* the label is display:none here, so nothing needs clipping — and
       the hit area below has to be able to escape the button's box */
    overflow: visible;
  }
  .qa-icon { width: 100%; height: 100%; }
  .qa-icon svg { width: 15px; height: 15px; }

  /* 32px is smaller than a fingertip. This gives the button a 44px
     target without changing anything that gets drawn. */
  .quick-add::after {
    content: '';
    position: absolute;
    inset: -6px;
    border-radius: 50%;
  }

  /* display:none rather than a 0fr track — it takes the label out of the
     layout entirely, so the button is exactly icon + border = 44px. */
  .quick-add .text-content,
  .quick-add:hover .text-content,
  .quick-add:focus-visible .text-content,
  .quick-add[data-added="true"] .text-content { display: none; }

  /* no hover scale on touch; keep the press feedback */
  .quick-add:hover  { scale: 1; }
  .quick-add:active { scale: .98; }

  /* A 44px circle has no room for the word, so the tick confirms alone. */
  .added-overlay span { display: none; }

  /* No lift on touch. A phone leaves :hover applied to whatever you last
     touched, so the card under your finger would rise as you reached it
     and only settle once the next card took the hover — reading as a
     card that moves itself while you swipe. :focus-within does the same
     after a tap lands on the card's link. Neither expresses intent here,
     so both are neutralised; the desktop rule is untouched. */
  .card:hover,
  .card:focus-within { transform: none; }
}

.carousel.is-dragging .card__link { pointer-events: none; }

/* A hover the visitor never asked for.
   The cursor sits still while the row slides past it, so each card in
   turn takes :hover for the moment it crosses the pointer — rising and
   dropping on its way by, which reads as the row glitching rather than
   as a hover. It is the same problem the phone rule above solves for a
   finger. So the lift is withdrawn for as long as the track is in
   motion, and the transition with it, so nothing animates on the way
   out. Whatever the row settles under keeps its hover. */
.carousel.is-moving .card {
  transform: none;
  transition: none;
}

@media (max-width: 720px) {
  .nav { padding-top: .75rem; padding-bottom: .75rem; }
  /* Matches the 34px icon buttons opposite it, so the three sit on one
     optical line and the centred lockup stays clear of both rails. */
  .logo__icon { height: 34px; }
  .logo__name { height: 12px; }
  .icon-btn   { width: 34px; height: 34px; }
  .nav__right { gap: clamp(.5rem, 2.5vw, 1rem); }

  /* One card plus half of the next. The half-card is what tells you the
     row scrolls, and it pulls each card's width down to ~2/3 of the
     viewport, so the 4:5 photo gets shorter and the whole section stops
     dominating the screen. */
  .products { --per-view: 1.5; }

  /* Collections stack. Side by side on a phone would leave each card
     around 160px wide — too small for the name to read over a photo. */
  .collections__grid { grid-template-columns: minmax(0, 1fr); }
  .collection { aspect-ratio: 3 / 2; }

  /* Footer stacks. Desktop-only styling was the brief, so this is just
     enough to keep it from breaking — not a designed mobile layout. */
  /* Explicit rows rather than auto-placement, so the arrow can be given
     the same cell as the contact block below. */
  .footer__top { grid-template-columns: minmax(0, 1fr); }
  .footer__brand        { grid-column: 1; grid-row: 1; }
  .footer__col--links   { grid-column: 1; grid-row: 2; }
  .footer__col--pay     { grid-column: 1; grid-row: 3; }
  .footer__col--contact { grid-column: 1; grid-row: 4; }

  /* Shares the contact cell and pins to its top-right, which puts it
     level with GET IN TOUCH. The desktop nudge into the gutter is
     dropped — here it sits flush with the content edge. */
  .footer__arrow {
    grid-column: 1;
    grid-row: 4;
    justify-self: end;
    align-self: start;
    translate: none;
  }

  /* Both phrases on one line, with the three gaps — left edge, between
     them, right edge — coming out equal. Cancelling the footer's gutter
     is what makes that true: left it in place, the outer two gaps would
     each carry the padding on top of their share and only the middle one
     would be the "even" width. gap must stay 0 for the same reason. */
  .footer__bottom {
    display: flex;
    flex-wrap: nowrap;
    align-items: center;
    justify-content: space-evenly;
    margin: 0 calc(var(--gutter) * -1);
    gap: 0;
  }
  .footer__copy,
  .policies__trigger { white-space: nowrap; }

  /* Centred on the trigger, the 210px menu hangs off the right of a small
     phone — and because it is only visibility:hidden at rest, it still
     counted toward the page width and produced a horizontal scrollbar.
     Anchoring its right edge to the trigger keeps it on screen. */
  .policies__menu {
    left: auto;
    right: 0;
    min-width: 0;
    width: max-content;
    max-width: calc(100vw - 2rem);
    transform: translateY(6px);
  }
  .policies:hover .policies__menu,
  .policies:focus-within .policies__menu { transform: translateY(0); }

  /* Sized off the longer line. "HANDCRAFTED VASES" renders 10.87× its
     own font-size, and the hero's 8vw gutters leave 84% of the viewport,
     so the ceiling is 84/10.87 = 7.73vw. 7.4vw sits just under it with
     headroom for the fallback font if Archivo is slow. Both the gutter
     and the type are vw-based, so that ratio holds at every phone width
     instead of only the one I measured. */
  .hero__title   { font-size: clamp(1.35rem, 7.4vw, 2.6rem); line-height: 1.08; }
  .hero__line--2 { text-align: right; }    /* same stagger as desktop */
  .hero__cta  { margin-left: 0; }

  /* --- cart drawer on phones ---
     Goes edge to edge instead of leaving a backdrop sliver, and the
     footer clears the iOS home indicator so Check out is never sat
     under it. Colours are untouched — same --sand panel, same green
     shipping nudge, same --arrow buttons as desktop. */
  .cart__panel { width: 100%; }

  .cart__head  { padding: 1.05rem 1.05rem .7rem; }
  .cart__items { padding: .4rem 1.05rem; }
  .cart__foot  {
    padding: .95rem 1.05rem calc(1.05rem + env(safe-area-inset-bottom, 0px));
  }

  .cart__ship      { gap: .7rem; padding: .8rem .9rem; margin-bottom: .95rem; }
  .cart__ship-icon { width: 36px; height: 36px; }
  .cart__ship-icon svg { width: 18px; height: 18px; }
  .cart__ship p    { font-size: .88rem; }

  .cart__checkout { min-height: 52px; }
}

@media (max-width: 420px) {
  .nav__link { font-size: .74rem; }
  .nav__links { gap: .3rem .8rem; }
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .01ms !important;
    transition-duration: .01ms !important;
  }
  /* The blanket .01ms above would whip the marquee round at absurd speed
     rather than calming it, since a loop's duration is its whole point.
     Stop it outright and leave a readable static first frame. */
  .marquee__track {
    animation: none !important;
    transform: none !important;
  }

  /* never leave the headline stranded off-position or invisible */
  .hero__line--1, .hero__line--2, .hero__cta {
    opacity: 1 !important;
    transform: none !important;
  }
}

/* ============================================================
   PRODUCT PAGE
   Two columns on desktop: gallery left, detail right. The page
   sits on --linen, the same cream as the collections section.
   ============================================================ */
.pdp {
  --pdp-ink: #341F16;

  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: clamp(1.5rem, 4vw, 4rem);
  align-items: start;
  padding: clamp(1.5rem, 4vh, 3rem) var(--gutter) clamp(4rem, 9vh, 7rem);
  background-color: #F0EBE5;
}

/* --- gallery --- */
.pdp__stage {
  position: relative;
  aspect-ratio: 1 / 1;
  overflow: hidden;
  background: #FFFFFF;
  /* the whole stage is the zoom target, so the cursor advertises it */
  cursor: zoom-in;
}
.pdp__stage.is-zoomed { cursor: zoom-out; }

.pdp__slides { margin: 0; padding: 0; list-style: none; height: 100%; }

/* The photo fills the whole card. It used to stop short of the bottom
   to leave a white strip for the dots to sit in, which is what kept the
   picture from filling the frame. The dots are over the photo now, so
   there is nothing to reserve. */
.pdp__slide {
  position: absolute;
  inset: 0;
  opacity: 0;
  transition: opacity .4s ease;
  pointer-events: none;
}
.pdp__slide[data-active] { opacity: 1; pointer-events: auto; }
.pdp__slide img {
  width: 100%; height: 100%;
  display: block;
  object-fit: contain;
  /* transform-origin is set from the pointer position, so the point you
     click is the point that stays put as it scales */
  transition: transform .35s ease;
}
.pdp__stage.is-zoomed .pdp__slide[data-active] img { transform: scale(2); }

.pdp__arrow {
  position: absolute;
  top: 50%;
  translate: 0 -50%;
  z-index: 2;
  width: 42px; height: 42px;
  display: grid; place-items: center;
  padding: 0; border: 0;
  background: none;
  color: var(--pdp-ink);
  cursor: pointer;
  transition: opacity .3s ease;
}
.pdp__arrow:hover { opacity: .55; }
.pdp__arrow svg { width: 26px; height: 26px; }
.pdp__arrow--prev { left: clamp(.25rem, 1vw, .75rem); }
.pdp__arrow--next { right: clamp(.25rem, 1vw, .75rem); }
.pdp__arrow[hidden] { display: none; }

/* Over the photo, inside the card, near its foot. */
.pdp__dots {
  position: absolute;
  left: 0; right: 0;
  bottom: clamp(12px, 2.5%, 20px);
  z-index: 2;
  display: flex;
  justify-content: center;
  gap: .5rem;
}
.pdp__dots[hidden] { display: none; }

/* Ringed in mist, filled navy when it is the one showing. The ring is
   on every dot so the row reads as a row even where the photo behind
   it is pale; the fill is what says which slide you are on. */
.pdp__dot {
  width: 9px; height: 9px;
  padding: 0;
  border: 1px solid #C3C9CD;
  border-radius: 50%;
  background: transparent;
  cursor: pointer;
  transition: background-color .3s ease, border-color .3s ease;
}
.pdp__dot[aria-current="true"] {
  background: #0A1C2B;
  border-color: #0A1C2B;
}

/* --- detail column --- */
.pdp__title {
  margin: 0 0 clamp(.6rem, 1.4vh, 1rem);
  color: var(--pdp-ink);
  font-family: Newsreader, serif;
  font-size: 32px;
  font-weight: 300;
  line-height: 35.2px;
}

.pdp__prices {
  margin: 0 0 .35rem;
  display: flex; align-items: baseline; gap: .7rem; flex-wrap: wrap;
  color: var(--pdp-ink);
  font-family: Poppins, sans-serif;
  font-size: 24px;
  font-weight: 400;
  line-height: 33.6px;
}
.pdp__was { color: var(--pdp-ink); opacity: .45; }

.pdp__shipnote {
  margin: 0 0 clamp(1.1rem, 2.5vh, 1.75rem);
  color: var(--pdp-ink);
  font-family: Poppins, sans-serif;
  font-size: 18px;
  font-weight: 400;
  line-height: 25.2px;
}


/* --- buy row --- */
.pdp__buy {
  display: flex;
  flex-wrap: wrap;
  gap: .6rem;
  margin: 0 0 clamp(1.25rem, 3vh, 2rem);
}

.pdp__qty {
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  border: 1px solid rgba(52, 31, 22, .35);
  border-radius: 4px;
  background: transparent;
}
.pdp__qty button {
  width: 40px; height: 48px;
  display: grid; place-items: center;
  border: 0; background: none;
  color: var(--pdp-ink);
  font-size: 1.05rem;
  cursor: pointer;
}
.pdp__qty-value {
  width: 34px; height: 48px;
  border: 0; background: none;
  color: var(--pdp-ink);
  font-family: Poppins, sans-serif;
  font-size: .95rem;
  text-align: center;
}
.pdp__qty-value:focus-visible { outline: none; }

.pdp__btn {
  flex: 1 1 190px;
  min-height: 48px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: .5rem;
  padding: .8rem 1.4rem;
  border: 0; border-radius: 4px;
  background: #111111;
  color: #FFFFFF;
  font-family: Poppins, sans-serif;
  font-size: 1rem;
  font-weight: 500;
  cursor: pointer;
  transition: background-color .3s ease;
}
.pdp__btn:hover { background: #2C2C2C; }
.pdp__btn svg { width: 20px; height: 20px; flex: none; }
.pdp__btn.is-done { background: #3F6B4A; }

.pdp__notice {
  margin: -.5rem 0 clamp(1rem, 2.5vh, 1.5rem);
  color: var(--pdp-ink);
  font-family: Poppins, sans-serif;
  font-size: .92rem;
  line-height: 1.5;
}

/* ============================================================
   ACCORDIONS
   Headers take the footer link hover (#805231) but not its resting
   colour — #D6D3D2 runs at 1.26:1 on this cream and would be
   invisible until pointed at. The page ink is used instead.
   ============================================================ */
.acc { border-top: 1px solid rgba(52, 31, 22, .16); }
.acc__row { border-bottom: 1px solid rgba(52, 31, 22, .16); }

.acc__head {
  width: 100%;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  padding: 1.15rem 0;
  border: 0; background: none;
  color: var(--pdp-ink);
  font-family: "Red Hat Display", sans-serif;
  font-size: 16px;
  font-weight: 500;
  line-height: 17.6px;
  letter-spacing: .04em;
  text-transform: uppercase;
  text-align: left;
  cursor: pointer;
  transition: color .3s ease;
}
.acc__head:hover, .acc__head:focus-visible { color: #805231; }

/* +/− drawn in CSS so it animates rather than swapping glyphs */
.acc__sign { position: relative; width: 14px; height: 14px; flex: none; }
.acc__sign::before, .acc__sign::after {
  content: '';
  position: absolute; left: 0; top: 50%;
  width: 14px; height: 1.5px;
  background: currentColor;
  transition: transform .3s ease;
}
.acc__sign::after { transform: rotate(90deg); }
.acc__head[aria-expanded="true"] .acc__sign::after { transform: rotate(0deg); }

.acc__panel {
  display: grid;
  grid-template-rows: 0fr;                 /* 0fr → 1fr animates height */
  transition: grid-template-rows .35s ease;
}
.acc__panel.is-open { grid-template-rows: 1fr; }
.acc__inner { overflow: hidden; }
.acc__panel.is-open .acc__inner { padding-bottom: 1.25rem; }

.acc__inner p, .acc__inner li {
  color: rgba(0, 0, 0, .71);
  font-family: Poppins, sans-serif;
  font-size: 18px;
  font-weight: 400;
  line-height: 25.2px;
}
.acc__inner p { margin: 0 0 1rem; }
.acc__inner p:last-child { margin-bottom: 0; }
.acc__inner strong { color: var(--pdp-ink); font-weight: 500; }
.acc__inner ul { margin: 0; padding-left: 1.1rem; }
.acc__inner li { margin-bottom: .4rem; }

@media (max-width: 900px) {
  .pdp {
    grid-template-columns: minmax(0, 1fr);
  }

  /* Both prices on one line. nowrap stops the flex row breaking, and the
     type shrinks with the viewport so it fits rather than overflowing —
     at 24px the pair needs ~343px, which a 375px phone cannot give it
     once the gutters are taken off. Desktop keeps the specified 24px. */
  .pdp__prices {
    flex-wrap: nowrap;
    font-size: clamp(17px, 5.4vw, 24px);
    line-height: 1.45;
  }
  .pdp__now, .pdp__was { white-space: nowrap; }
}

/* ============================================================
   RECOMMENDED PRODUCTS
   Reuses the carousel's .card, so the product name and prices are
   the same face, size and colour by construction rather than by
   copied values.
   ============================================================ */
.recs {
  padding: clamp(3rem, 7vh, 5.5rem) var(--gutter) clamp(4rem, 10vh, 8rem);
  background-color: var(--sand);              /* #E5DBD3 */
}

.recs__title {
  margin: 0 0 clamp(1.5rem, 3.5vh, 2.5rem);
  color: var(--cocoa);
  font-family: Newsreader, serif;
  font-style: italic;
  font-size: clamp(1.05rem, 1.5vw, 1.35rem);
  font-weight: 400;
}

.recs__grid {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: clamp(1rem, 2vw, 1.75rem);
  margin: 0;
  padding: 0;
  list-style: none;
}

/* .card sizes itself with flex-basis for the carousel; in a grid the
   track decides the width, so that basis has to stop applying. */
.recs__grid .card { flex: none; }

/* --- sale badge --- */
/* Held off both edges rather than wedged into the corner, so it reads as
   sitting on the photo instead of being part of the frame. */
.card__badge {
  position: absolute;
  top:  clamp(8px, .8vw, 12px);
  left: clamp(8px, .8vw, 12px);
  z-index: 2;
  padding: .38rem .85rem;
  background-color: #AC8359;
  color: #FFFFFF;
  font-family: var(--font-body);
  font-size: .72rem;
  font-weight: 500;
  letter-spacing: .12em;
  text-transform: uppercase;
  line-height: 1;
}

@media (max-width: 1080px) {
  .recs__grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

/* ============================================================
   PRODUCTS LISTING
   ============================================================ */
.listing-band {
  /* The same block padding as .brand-band, so this header and the one on
     Contact Us / Our Brand are the same height — the titles already
     share their type, so matching the padding matches the band. */
  padding: clamp(.7rem, 1.6vh, 1.1rem) var(--gutter);
  background-color: var(--sand);              /* #E5DBD3 */
}
.listing-band__title {
  margin: 0;
  color: #341F16;
  font-family: Newsreader, serif;
  font-size: 32px;
  font-weight: 300;
  line-height: 35.2px;
}

.listing {
  --list-cols: 3;
  padding: clamp(1.5rem, 3.5vh, 2.5rem) var(--gutter) clamp(4rem, 10vh, 8rem);
  background-color: #F0EBE5;
}

/* --- filter bar --- */
.listing__bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  flex-wrap: wrap;
  margin-bottom: clamp(1.25rem, 3vh, 2rem);
}
.listing__filters, .listing__tools {
  display: flex;
  align-items: center;
  gap: clamp(.85rem, 2vw, 1.6rem);
}

.listing__count {
  font-family: Poppins, sans-serif;
  font-size: 18px;
  font-weight: 400;
  line-height: 25.2px;
  color: rgba(67, 54, 37, 0.6);
  white-space: nowrap;          /* "2 items", never "2" over "items" */
}

/* --- dropdowns: <details> so they work before any JS runs --- */
.fdrop { position: relative; }
.fdrop > summary {
  display: flex;
  align-items: center;
  gap: .4rem;
  list-style: none;
  cursor: pointer;
  font-family: Poppins, sans-serif;
  font-size: 18px;
  font-weight: 400;
  line-height: 25.2px;
  color: rgb(67, 54, 37);
}
.fdrop > summary::-webkit-details-marker { display: none; }
.fdrop > summary::after {
  content: '';
  width: 8px; height: 8px;
  border-right: 1.5px solid currentColor;
  border-bottom: 1.5px solid currentColor;
  transform: rotate(45deg) translate(-2px, -2px);
  transition: transform .25s ease;
}
.fdrop[open] > summary::after { transform: rotate(-135deg) translate(-2px, -2px); }

.fdrop__panel {
  position: absolute;
  top: calc(100% + .6rem);
  left: 0;
  z-index: 20;
  min-width: 210px;
  display: flex;
  flex-direction: column;
  gap: .55rem;
  padding: .9rem 1.1rem;
  border-radius: 8px;
  background: #FFFFFF;
  box-shadow: 0 12px 30px rgba(52, 31, 22, .16);
}
.fdrop--right .fdrop__panel { left: auto; right: 0; }
.fdrop__panel label {
  display: flex;
  align-items: center;
  gap: .55rem;
  font-family: Poppins, sans-serif;
  font-size: .95rem;
  color: rgb(67, 54, 37);
  cursor: pointer;
  white-space: nowrap;
}
/* --- price range --- */
.fdrop__panel--price { min-width: 22rem; }
.fprice {
  display: flex;
  align-items: center;
  gap: .6rem;
}
/* Wide enough for the number it has to hold. `flex: 1 1 0` divided the
   dropdown's own width between them and squeezed both to about 80px,
   which left "430.00" fighting the LE for room. They now start from
   their content and grow from there, and the dropdown is sized to fit
   the pair rather than the pair to fit the dropdown. */
.fprice__field {
  flex: 1 1 auto;
  min-width: 8.5rem;
  display: flex;
  align-items: center;
  gap: .35rem;
  padding: .45rem .6rem;
  border: 1px solid rgba(67, 54, 37, .35);
  border-radius: 4px;
  background: transparent;
}
.fprice__field:focus-within { border-color: rgba(67, 54, 37, .7); }
.fprice__cur {
  flex: none;
  font-family: Poppins, sans-serif;
  font-size: .9rem;
  color: rgba(67, 54, 37, .6);
}
.fprice__field input {
  width: 100%;
  min-width: 0;
  padding: 0;
  border: 0;
  background: none;
  font-family: Poppins, sans-serif;
  font-size: .95rem;
  color: rgb(67, 54, 37);
  text-align: right;
}
.fprice__field input:focus { outline: none; }
.fprice__to {
  flex: none;
  font-family: Poppins, sans-serif;
  font-size: .95rem;
  color: rgb(67, 54, 37);
}
.fprice__note {
  margin: 0;
  font-family: Poppins, sans-serif;
  font-size: .9rem;
  color: rgba(67, 54, 37, .7);
}

/* --- sort --- */
.fsort {
  display: flex;
  align-items: center;
  gap: .6rem;
}
.fsort__label {
  font-family: Poppins, sans-serif;
  font-size: 18px;
  font-weight: 400;
  line-height: 25.2px;
  color: rgb(67, 54, 37);
}
.fsort__select {
  max-width: 100%;
  padding: .2rem 1.4rem .2rem .2rem;
  border: 0;
  border-radius: 4px;
  background: none;
  /* the chevron, drawn rather than fetched */
  background-image:
    linear-gradient(45deg, transparent 50%, currentColor 50%),
    linear-gradient(135deg, currentColor 50%, transparent 50%);
  background-position: right 10px center, right 5px center;
  background-size: 5px 5px, 5px 5px;
  background-repeat: no-repeat;
  font-family: Poppins, sans-serif;
  font-size: 18px;
  color: rgb(67, 54, 37);
  cursor: pointer;
  appearance: none;
  -webkit-appearance: none;
}

/* --- how many to a row ---
   Sizes and states taken from the supplied component: a 44px row, 12px
   between, a 36px picker with a 4px radius, muted until chosen. The
   colours are the brand brown at those same alphas rather than black —
   everything else in this bar is rgb(67,54,37), and a black icon reads
   cold against the cream.

   Two pairs, one per layout. Only the pair that fits the width is
   rendered; display:none also takes the other out of the tab order, so
   a keyboard never lands on a control that isn't there. */
.column-options-wrapper {
  display: flex;
  gap: 12px;
  align-items: center;
  height: 44px;                  /* the minimum touch target */
}
.column-options {
  display: flex;
  gap: 12px;
  border: none;
  padding: 0;
  margin: 0;
}
.column-options__option { cursor: pointer; }
.column-options__option--phone { display: none; }

/* Off-screen rather than display:none, so it stays focusable and the
   picker beside it can answer :checked. */
.column-options__option-input {
  position: absolute;
  opacity: 0;
  width: 0;
  height: 0;
}

.column-picker {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 36px;
  height: 36px;
  border-radius: 4px;
  color: rgba(67, 54, 37, .4);
  transition: background-color .2s ease, color .2s ease;
}
.column-picker svg { display: block; }
.column-picker:hover { background-color: rgba(67, 54, 37, .05); }

.column-options__option-input:checked + .column-picker {
  background-color: rgba(67, 54, 37, .08);
  color: rgba(67, 54, 37, .9);
}
/* The input is invisible, so its focus ring has to be borrowed. */
.column-options__option-input:focus-visible + .column-picker {
  outline: 2px solid rgba(67, 54, 37, .5);
  outline-offset: 2px;
}

/* --- grid --- */
.listing__grid {
  display: grid;
  grid-template-columns: repeat(var(--list-cols), minmax(0, 1fr));
  gap: clamp(1rem, 2vw, 1.75rem);
  margin: 0; padding: 0;
  list-style: none;
}
.listing__grid .card { flex: none; }
.listing__grid .card[hidden],
.listing__grid .collection[hidden] { display: none; }

/* --- the collections page ---
   The same shell as the product listings. Only two differences: it
   starts two to a row rather than three, and with no filters in the bar
   the tools sit over on the right on their own. */
.listing--collections { --list-cols: 2; }
.listing--collections .listing__tools { margin-left: auto; }

/* The phone hides the tally on the product listings because the filter
   drawer's own button carries it there. This page has no drawer, so
   hiding it would simply lose the number. */
.listing--collections .listing__count { display: inline; }

/* All three controls share one row here, with no drawer to move any of
   them into, so on a phone the row is tightened to fit rather than
   allowed to wrap or overflow. */
@media (max-width: 749px) {
  .listing--collections .listing__tools { gap: 10px; }
  .listing--collections .listing__count { font-size: 15px; }
}

.listing__empty {
  margin: 3rem 0;
  font-family: Poppins, sans-serif;
  font-size: 18px;
  color: rgba(67, 54, 37, .6);
  text-align: center;
}

/* ============================================================
   FILTER DRAWER — phone
   The controls are the same elements as the bar's; the script moves
   them in here rather than a second copy being written. So everything
   below is presentation only.
   ============================================================ */
.filter-open {
  display: none;                 /* revealed at the phone breakpoint */
  align-items: center;
  gap: .5rem;
  padding: 0;
  border: 0;
  background: none;
  color: rgb(67, 54, 37);
  font-family: Poppins, sans-serif;
  font-size: 16px;
  line-height: 25.2px;
  cursor: pointer;
}
.filter-open svg { width: 18px; height: 18px; flex: none; }

.filters {
  position: fixed;
  inset: 0;
  z-index: 200;                  /* alongside the cart, above the nav */
  visibility: hidden;
  transition: visibility 0s linear .45s;
}
.filters.is-open { visibility: visible; transition-delay: 0s; }

.filters__backdrop {
  position: absolute; inset: 0;
  background: rgba(52, 36, 28, .45);
  opacity: 0;
  transition: opacity .45s ease;
}
.filters.is-open .filters__backdrop { opacity: 1; }

/* Slides in from the left, as in the reference, and wears the cart
   drawer's own #E5DBD3 so the two read as one piece of furniture. */
.filters__panel {
  position: absolute;
  inset: 0 auto 0 0;
  width: min(86vw, 420px);
  display: flex;
  flex-direction: column;
  background: var(--sand);
  transform: translateX(-100%);
  transition: transform .45s cubic-bezier(.33, 1, .68, 1);
}
.filters.is-open .filters__panel { transform: translateX(0); }

.filters__head {
  display: flex;
  align-items: center;
  gap: .75rem;
  padding: 1.1rem 1.25rem;
  border-bottom: 1px solid rgba(67, 54, 37, .18);
}
.filters__title {
  margin: 0;
  font-family: Poppins, sans-serif;
  font-size: 18px;
  font-weight: 400;
  line-height: 25.2px;
  color: rgb(67, 54, 37);
}
.filters__close {
  margin-left: auto;
  width: 34px; height: 34px;
  display: inline-grid; place-items: center;
  padding: 0; border: 0;
  background: none;
  color: rgb(67, 54, 37);
  cursor: pointer;
}
.filters__close svg { width: 18px; height: 18px; }

.filters__body {
  flex: 1 1 auto;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
}

.filters__foot { padding: 1.25rem; }
.filters__apply {
  width: 100%;
  padding: .95rem 1rem;
  border: 0;
  border-radius: 6px;
  background: #1A1A1A;
  color: #FFFFFF;
  font-family: Poppins, sans-serif;
  font-size: 16px;
  cursor: pointer;
}
.filters__apply:active { transform: scale(.99); }

/* ============================================================
   LISTING — phone
   ============================================================ */
@media (max-width: 1080px) {
  .listing { --list-cols: 2; }
  .listing--collections { --list-cols: 1; }
  .column-options__option--wide  { display: none; }
  .column-options__option--phone { display: block; }
}

@media (max-width: 749px) {
  /* Edge to edge. The bar keeps its inset, the grid gives it up, so the
     only space left between products is the one between the columns. */
  .listing { padding-left: 0; padding-right: 0; }
  .listing__bar {
    margin-left: var(--gutter);
    margin-right: var(--gutter);
    gap: .75rem;
  }
  .listing__grid { gap: 14px 12px; }

  /* The photos go to the edge, the words do not — flush against the
     screen they read as if they had fallen off it. The media keeps its
     full bleed; only the name and the price are inset. */
  .listing__grid .card__name,
  .listing__grid .card__price { padding-left: 10px; padding-right: 10px; }

  /* The bar is reduced to what the reference shows: the opener on the
     left, the row-count buttons on the right. The controls themselves
     have gone into the drawer, and the tally with them — it is the
     drawer's own button that reports it. */
  .filter-open   { display: inline-flex; }
  .listing__count { display: none; }
  .listing__tools { margin-left: auto; }

  /* Inside the drawer the groups are stacked sections, not dropdowns:
     no absolute panel, no card, no shadow — just a divider between
     them, as in the reference. */
  .filters__body .listing__filters {
    display: block;
  }
  .filters__body .fdrop,
  .filters__body .fsort {
    padding: 1.05rem 1.25rem;
    border-bottom: 1px solid rgba(67, 54, 37, .18);
  }
  .filters__body .fdrop { position: static; }
  .filters__body .fdrop > summary { font-size: 16px; }
  .filters__body .fdrop > summary::after { margin-left: auto; }
  .filters__body .fdrop[open] > summary { margin-bottom: .9rem; }

  .filters__body .fdrop__panel {
    position: static;
    min-width: 0;
    padding: 0;
    border-radius: 0;
    background: none;
    box-shadow: none;
    gap: .8rem;
  }
  .filters__body .fdrop__panel label { white-space: normal; }
  .filters__body .fsort { justify-content: space-between; }
  .filters__body .fsort__label { font-size: 16px; }
  .filters__body .fsort__select { font-size: 16px; text-align: right; }

  /* Checkboxes at a size a thumb can hit. */
  .filters__body input[type="checkbox"] {
    width: 18px; height: 18px;
    accent-color: rgb(67, 54, 37);
    flex: none;
  }

}

/* ============================================================
   SOLD OUT
   The photo is dimmed rather than the whole card, so the name and
   price stay readable — a shopper still needs to know what it was.
   ============================================================ */
.card__badge--out { background-color: #6E6A66; }

.card.is-soldout .card__media { opacity: .55; }
.card.is-soldout .quick-add { display: none; }
/* the lift is an invitation to buy; withdraw it */
.card.is-soldout:hover,
.card.is-soldout:focus-within { transform: none; }

.pdp__soldout {
  margin: 0 0 clamp(1rem, 2.5vh, 1.5rem);
  color: #6E6A66;
  font-family: Poppins, sans-serif;
  font-size: 18px;
  font-weight: 400;
  line-height: 25.2px;
}

.pdp__btn:disabled {
  background: #B9B4AF;
  cursor: not-allowed;
}
.pdp__btn:disabled:hover { background: #B9B4AF; }
.pdp.is-soldout .pdp__qty { opacity: .5; pointer-events: none; }

/* ============================================================
   CART PAGE
   The whole section is white; only the summary panel carries a
   colour. Its rows are the same state the drawer shows, and carry
   the same data-act attributes, so both move together.
   ============================================================ */
/* No padding at the top or on the right: the summary is a grid item, so
   with nothing between it and those two edges it lands flush in the
   corner, directly under the header. The left column carries the insets
   the section used to. */
.cartpage {
  padding: 0 0 clamp(4rem, 10vh, 8rem);
  background-color: #FFFFFF;
}

.cartpage__main {
  min-width: 0;
  padding: clamp(2rem, 5vh, 3.5rem) var(--gutter) 0;
}

.cartpage__title {
  display: flex;
  align-items: center;
  gap: 12px;
  margin: 0;
  color: #341F16;
  font-family: Newsreader, serif;
  font-size: 32px;
  font-weight: 300;
  line-height: 35.2px;
}
.cartpage__count {
  display: inline-grid; place-items: center;
  min-width: 28px; height: 28px;
  padding: 0 .5rem;
  border-radius: 999px;
  background: #F0EBE5;
  color: #341F16;
  font-family: Poppins, sans-serif;
  font-size: 14px;
  line-height: 1;
}

.cartpage__layout {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  /* the space the summary keeps from everything in the cart */
  gap: clamp(1.5rem, 4vw, 3rem);
  align-items: start;
}
.cartpage__layout[hidden] { display: none; }

/* --- a row --- */
.cartrow {
  display: grid;
  grid-template-columns: 100px minmax(0, 1fr) auto auto auto;
  align-items: center;
  gap: clamp(1rem, 2vw, 1.5rem);
  padding: 24px 0;
  border-bottom: 1px solid #F0EBE5;
}
.cartrow__thumb {
  width: 100px; height: 100px;
  display: block;
  object-fit: cover;
  border-radius: 8px;
  background: #FBF5F1;
}
.cartrow__detail { min-width: 0; }
.cartrow__name {
  margin: 0 0 6px;
  font-family: Poppins, sans-serif;
  font-size: 16px;
  font-weight: 400;
  line-height: 1.4;
  color: #341F16;
}
.cartrow__price { margin: 0; display: flex; align-items: baseline; gap: .5rem; }
.cartrow__now { font-family: Poppins, sans-serif; font-size: 14px; color: #341F16; }
.cartrow__was { font-family: Poppins, sans-serif; font-size: 14px; color: rgb(112, 103, 96); }

.cartrow__remove {
  width: 40px; height: 40px;
  display: inline-grid; place-items: center;
  padding: 0; border: 0;
  background: none;
  color: rgb(112, 103, 96);
  cursor: pointer;
  transition: color .25s ease;
}
.cartrow__remove svg { width: 20px; height: 20px; }
.cartrow__remove:hover { color: #341F16; }

.cartrow__total {
  min-width: 110px;
  font-family: Poppins, sans-serif;
  font-size: 15px;
  color: #341F16;
  text-align: right;
  white-space: nowrap;
}

/* --- summary --- */
.cartpage__summary {
  padding: clamp(1.25rem, 2.5vw, 1.75rem);
  background-color: #F0EBE5;
}

.cartpage__discount {
  display: flex; align-items: center; justify-content: space-between;
  width: 100%;
  padding: .85rem 0;
  border: 0; border-bottom: 1px solid rgba(52, 31, 22, .12);
  background: none;
  color: #341F16;
  font-family: Poppins, sans-serif;
  font-size: 15px;
  cursor: pointer;
}
.cartpage__discount-plus { font-size: 18px; line-height: 1; }
.cartpage__discount-panel {
  display: none;
  gap: .5rem;
  padding-top: .85rem;
}
.cartpage__discount-panel.is-open { display: flex; }
/* No border, and none on focus either — the white against the panel is
   what says "field" here. The focus ring is a hairline rather than the
   browser's own, which came out a heavy brown against this cream. */
.cartpage__discount-input {
  flex: 1 1 auto; min-width: 0;
  padding: .7rem .85rem;
  border: 0;
  border-radius: 4px;
  background: #FFFFFF;
  font-family: Poppins, sans-serif;
  font-size: .95rem;
  color: #341F16;
}
.cartpage__discount-input:focus,
.cartpage__discount-input:focus-visible {
  outline: none;
  box-shadow: 0 0 0 1px rgba(52, 31, 22, .35);
}
.cartpage__apply {
  flex: none;
  padding: .7rem 1.1rem;
  border: 0; border-radius: 4px;
  background: rgba(52, 31, 22, .1);
  color: #341F16;
  font-family: Poppins, sans-serif;
  font-size: .95rem;
  cursor: pointer;
}

.cartpage__total {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: 1rem;
  margin: 1.25rem 0 0;
}
.cartpage__total dt,
.cartpage__total dd {
  margin: 0;
  font-family: Poppins, sans-serif;
  font-size: 18px;
  color: #341F16;
}

.cartpage__note {
  margin: .5rem 0 1.25rem;
  font-family: Poppins, sans-serif;
  font-size: 13px;
  color: rgb(112, 103, 96);
}

.cartpage__checkout {
  display: block;
  padding: 16px;
  border-radius: 999px;
  background: #8D6B48;
  color: #FFFFFF;
  font-family: Poppins, sans-serif;
  font-size: 16px;
  font-weight: 600;
  text-align: center;
  text-decoration: none;
  transition: background-color .3s ease;
}
.cartpage__checkout:hover { background: #AC8359; }

.cartpage__empty { padding: clamp(2rem, 6vh, 4rem) var(--gutter); }
.cartpage__empty[hidden] { display: none; }
.cartpage__empty p {
  margin: 0 0 1.5rem;
  font-family: Poppins, sans-serif;
  color: rgba(67, 54, 37, .75);
}

@media (min-width: 900px) {
  .cartpage__layout { grid-template-columns: minmax(0, 1fr) 380px; }
}

/* The row folds rather than squeezing: photo and name across the top,
   the controls and the line total beneath. */
@media (max-width: 700px) {
  .cartrow {
    grid-template-columns: 84px minmax(0, 1fr) auto;
    gap: .75rem 1rem;
  }
  .cartrow__thumb { width: 84px; height: 84px; }
  .cartrow__qty    { grid-column: 2; }
  .cartrow__remove { grid-column: 3; grid-row: 2; }
  .cartrow__total  { grid-column: 2 / -1; text-align: left; min-width: 0; }
}

/* ============================================================
   CHECKOUT
   Details on the left, what they are for on the right. The summary is
   a <details>: open on a wide screen, and on a phone a bar carrying
   the total that you tap to see the rest — the total is what you want
   there, not three photographs between you and the form.
   ============================================================ */
/* The column the whole page hangs off, and the lead-in that sets where
   it starts: far enough right to land under the end of the first "e" of
   the wordmark above it. The right edge does not move, so the boxes get
   narrower by the same amount. */
:root {
  --checkout-head-h:  92px;
  --checkout-col-gap: 14px;
  --checkout-edge:    clamp(1.25rem, 5vw, 3rem);

  /* Where the boxes — and the logo above them — begin. This does not
     move when the divider does; the boxes give up width on their right
     instead. */
  --checkout-box-left: clamp(1.25rem, 16vw, 300px);

  /* Breathing room either side of the rule. */
  --checkout-gutter:   clamp(1.5rem, 4vw, 3.5rem);
}

.checkout {
  padding: clamp(1.25rem, 3vh, 2rem) var(--checkout-edge) clamp(3rem, 8vh, 6rem);
  background-color: #F0EBE5;
}

.checkout__grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: clamp(1.5rem, 4vh, 2.5rem);
  align-items: start;
}
.checkout__grid[hidden] { display: none; }

/* --- the checkout's own header ---
   A slim bar. Its logo starts on the same lead as the boxes below, so
   the page reads as one column rather than two unrelated ones. */
.nav--checkout {
  display: flex;
  align-items: center;
  min-height: 0;
  height: var(--checkout-head-h);
  padding: 0 var(--checkout-edge);
  /* The same navy as the site header, taken from the same token so the
     two can never drift apart. It was tan, and the gold mark is #AC8359
     — the very colour of that bar — so the logo had to be forced white
     to survive on it. On navy the mark keeps its own colours. */
  background-color: var(--nav-solid);
}
.nav--checkout__wrap {
  width: 100%;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
}

/* Icon only — no count. The tally is already in the summary beside it,
   and a second one that could disagree is worse than none. */
.checkout-cart {
  flex: none;
  width: 44px; height: 44px;
  display: inline-grid; place-items: center;
  padding: 0; border: 0;
  border-radius: 50%;
  background: none;
  color: var(--white);
  cursor: pointer;
  transition: background-color .25s ease, opacity .25s ease;
}
.checkout-cart[hidden] { display: none; }
.checkout-cart svg { width: 22px; height: 22px; display: block; }
.checkout-cart:hover { background-color: rgba(255, 255, 255, .18); }
.checkout-cart:focus-visible {
  outline: none;
  box-shadow: 0 0 0 3px rgba(255, 255, 255, .45);
}
.checkout-cart:active { opacity: .8; }
/* The lockup at the homepage header's own size — same two files, same
   proportions, nothing re-cut for this page. */
.nav--checkout .logo__icon { height: clamp(36px, 3.4vw, 52px); }
.nav--checkout .logo__name { height: clamp(13px, 1.25vw, 19px); }

/* No filter on the mark here.
   There used to be one — brightness(0) invert(1) — because the gold
   artwork is #AC8359, the very colour this bar was asked to be, so it
   vanished against it and had to be forced white. The icon on these
   pages is the black cut now, which reads on the tan as drawn. The
   wordmark beside it is untouched and still white. */

/* --- summary ---
   No box: the tally sits on the page itself, divided from the form by
   a rule rather than fenced off in a panel of its own. */
.checkout__summary {
  border: 0;
  border-radius: 0;
  background: none;
}
.checkout__summary-bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  padding: 1rem 1.15rem;
  border: 1px solid #DEDEDE;
  border-radius: 8px;
  background: #FFFFFF;
  list-style: none;
  cursor: pointer;
  font-family: Poppins, sans-serif;
  font-size: 1rem;
  color: rgb(67, 54, 37);
}
.checkout__summary-bar::-webkit-details-marker { display: none; }
.checkout__summary-total { font-weight: 500; }
.checkout__summary-body { padding: 1.15rem 0 0; }

.checkout__lines { list-style: none; margin: 0; padding: 0; }
.checkout__line {
  display: grid;
  grid-template-columns: 64px minmax(0, 1fr) auto;
  align-items: center;
  gap: .9rem;
  padding: .7rem 0;
}

/* The count rides the corner of the photograph, as it does in the
   header — one convention for "how many", used twice. */
.checkout__thumb { position: relative; display: block; }
.checkout__thumb img {
  width: 64px; height: 64px;
  display: block;
  object-fit: cover;
  border-radius: 6px;
  background: var(--white);
}
.checkout__qty {
  position: absolute;
  top: -7px; right: -7px;
  min-width: 20px; height: 20px;
  display: grid; place-items: center;
  padding: 0 5px;
  border-radius: 999px;
  background: var(--cocoa);
  color: var(--white);
  font-family: Poppins, sans-serif;
  font-size: 11px;
  line-height: 1;
}
.checkout__line-name {
  font-family: Poppins, sans-serif;
  font-size: .95rem;
  line-height: 1.4;
  color: rgb(67, 54, 37);
}
.checkout__line-price {
  font-family: Poppins, sans-serif;
  font-size: .95rem;
  color: rgb(67, 54, 37);
  white-space: nowrap;
}

.checkout__totals {
  margin: .6rem 0 0;
  padding-top: .9rem;
  border-top: 1px solid rgba(67, 54, 37, .18);
}
.checkout__totals-row {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: 1rem;
}
.checkout__totals dt,
.checkout__totals dd {
  margin: 0;
  font-family: Poppins, sans-serif;
  font-size: .95rem;
  color: rgba(67, 54, 37, .8);
}
.checkout__totals-row + .checkout__totals-row { margin-top: .4rem; }
.checkout__totals-row--sum {
  margin-top: .8rem;
  padding-top: .8rem;
  border-top: 1px solid rgba(67, 54, 37, .18);
}
.checkout__totals-row--sum dt,
.checkout__totals-row--sum dd { font-size: 1.35rem; color: #341F16; }
.checkout__cur { font-size: .8rem; color: rgba(67, 54, 37, .6); }

.checkout__direct {
  margin: 1rem 0 0;
  padding: .8rem .95rem;
  border-radius: 6px;
  background: rgba(172, 131, 89, .12);
  font-family: Poppins, sans-serif;
  font-size: .88rem;
  line-height: 1.5;
  color: rgb(67, 54, 37);
}
.checkout__direct[hidden] { display: none; }
.checkout__direct a { color: #805231; }

/* --- the form --- */
/* The left column, whether it collects the order or reports it. */
.checkout__form,
.checkout__col { min-width: 0; }
.cform__group { margin: 0 0 clamp(1.4rem, 3.5vh, 2.2rem); padding: 0; border: 0; }
.checkout__legend {
  padding: 0 0 .7rem;
  font-family: Poppins, sans-serif;
  font-size: 1.15rem;
  color: #341F16;
}
/* Direct children only. Without the child combinator this also caught
   the second and third field *inside* a row — they are siblings too —
   and dropped each one 12.8px below the one beside it. */
.cform__group > .cform__field + .cform__field,
.cform__group > .cform__row   + .cform__field,
.cform__group > .cform__field + .cform__row,
.cform__group > .cform__row   + .cform__row { margin-top: .8rem; }
/* Two classes: .cform__row is declared further down, in the contact
   form's block, and on one class would win on source order. */
.cform__row.cform__row--three { grid-template-columns: repeat(3, minmax(0, 1fr)); }

.cform__select { appearance: none; -webkit-appearance: none; cursor: pointer; }
.cform__input[readonly] { color: rgba(67, 54, 37, .7); cursor: default; }

/* White fields with a hairline, only here — the contact form's cream
   boxes belong to that page's cream section and are left alone.

   Heights are given rather than derived from padding, because the
   supplied sizes are exact: 60px for the full-width and half-width
   boxes, 58px for the three across. */
.checkout .cform__input {
  height: 60px;
  padding: 0 1.1rem;
  border: 1px solid #DEDEDE;
  border-radius: 8px;
  background-color: #FFFFFF;
  font-size: 1rem;
}
.checkout .cform__row--three .cform__input { height: 58px; }

/* Every width comes out of the column: whatever room is left between
   the boxes' fixed left edge and the rule, split two ways or three with
   a 14px gap. Nothing is set per-box, so moving the rule resizes them
   all and keeps them flush at both ends. */
.checkout .cform__row { gap: var(--checkout-col-gap); }
.checkout .cform__input:focus-visible { border-color: rgba(67, 54, 37, .55); }
.checkout .cform__input[aria-invalid="true"] { border-color: #A3402F; }
/* --- phone and contact ---
   The country marker sits inside the box on the right, as in the
   reference, and the input keeps clear of it. */
.cform__tel { position: relative; }
.cform__tel .cform__input { padding-right: 92px; }
.cform__flag {
  position: absolute;
  top: 50%; right: 14px;
  transform: translateY(-50%);
  display: flex;
  align-items: center;
  gap: .4rem;
  pointer-events: none;          /* it is a label, not a control */
}
.cform__flag svg { display: block; border-radius: 2px; }
.cform__dial {
  font-family: Poppins, sans-serif;
  font-size: .95rem;
  color: rgba(67, 54, 37, .75);
}

/* The select's own chevron, since appearance is off. */
.checkout .cform__select {
  padding-right: 2.4rem;
  background-image:
    linear-gradient(45deg, transparent 50%, rgba(67, 54, 37, .7) 50%),
    linear-gradient(135deg, rgba(67, 54, 37, .7) 50%, transparent 50%);
  background-position: right 1.25rem center, right 1rem center;
  background-size: 6px 6px, 6px 6px;
  background-repeat: no-repeat;
}

.checkout__method {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  padding: 1rem 1.1rem;
  border: 1px solid rgba(67, 54, 37, .25);
  border-radius: 6px;
  font-family: Poppins, sans-serif;
  font-size: .95rem;
  color: rgb(67, 54, 37);
}
.checkout__method--pay { flex-direction: column; align-items: flex-start; gap: .3rem; }
.checkout__pay-name { font-weight: 500; }
.checkout__pay-note { font-size: .88rem; color: rgba(67, 54, 37, .7); }

/* The same tan as the bar at the top of the page — the two ends of the
   checkout, in one colour. */
.checkout__place {
  width: 100%;
  height: 54px;
  padding: 0 1.05rem;
  border: 0; border-radius: 6px;
  background-color: #AC8359;
  color: var(--white);
  font-family: var(--font-body);
  font-size: 1rem;
  letter-spacing: .04em;
  cursor: pointer;
  transition: background-color .3s ease, opacity .3s ease;
}
.checkout__place:hover { background-color: #97714B; }
.checkout__place:disabled { opacity: .6; cursor: progress; }

.checkout__notice {
  margin: 1rem 0 0;
  padding: .9rem 1rem;
  border-radius: 6px;
  background: rgba(172, 131, 89, .12);
  font-family: Poppins, sans-serif;
  font-size: .92rem;
  line-height: 1.55;
  color: rgb(67, 54, 37);
}
.checkout__notice a { color: #805231; }

/* Just the links, ruled off from the button above them. */
.checkout__legal {
  display: flex;
  flex-wrap: wrap;
  gap: .35rem 1.35rem;
  margin-top: clamp(1.75rem, 4vh, 2.75rem);
  padding-top: clamp(1.1rem, 2.5vh, 1.6rem);
  border-top: 1px solid #DEDEDE;
}
.checkout__legal a {
  font-family: Poppins, sans-serif;
  font-size: .88rem;
  color: #805231;
  text-decoration: underline;
  text-underline-offset: .18em;
}
.checkout__legal a:hover { color: #946E51; }

/* --- nothing to check out --- */
.checkout__empty { padding: clamp(2rem, 6vh, 4rem) 0; }
.checkout__empty[hidden] { display: none; }
.checkout__empty-title {
  margin: 0 0 .6rem;
  color: #341F16;
  font-family: Newsreader, serif;
  font-size: 32px;
  font-weight: 300;
  line-height: 35.2px;
}
.checkout__empty p {
  margin: 0 0 1.6rem;
  font-family: Poppins, sans-serif;
  color: rgba(67, 54, 37, .75);
}

/* ---------- the confirmation page ----------
   Sits in the checkout's own left column, so the rule down the middle,
   the insets and the paddings are the checkout's without being
   restated. */
.thanks__head {
  display: flex;
  align-items: flex-start;
  gap: 1rem;
  margin-bottom: clamp(1.5rem, 4vh, 2.25rem);
}
.thanks__tick {
  flex: none;
  width: 44px; height: 44px;
  display: grid; place-items: center;
  border: 1px solid #AC8359;
  border-radius: 50%;
  color: #AC8359;
}
.thanks__tick svg { width: 22px; height: 22px; }
.thanks__ref {
  margin: 0 0 .25rem;
  font-family: Poppins, sans-serif;
  font-size: .9rem;
  color: rgba(67, 54, 37, .75);
}
.thanks__title {
  margin: 0;
  color: #341F16;
  font-family: Newsreader, serif;
  font-size: 32px;
  font-weight: 300;
  line-height: 35.2px;
}

.thanks__card {
  margin-bottom: 1rem;
  padding: 1.15rem 1.25rem;
  border: 1px solid #DEDEDE;
  border-radius: 8px;
  background: #FFFFFF;
}
.thanks__card-title {
  margin: 0 0 .4rem;
  font-family: Poppins, sans-serif;
  font-size: 1rem;
  font-weight: 500;
  color: #341F16;
}
.thanks__card p {
  margin: 0;
  font-family: Poppins, sans-serif;
  font-size: .92rem;
  line-height: 1.6;
  color: rgba(67, 54, 37, .8);
}

.thanks__button {
  display: inline-flex;
  align-items: center;
  gap: .5rem;
  margin-top: .9rem;
  padding: .7rem 1.1rem;
  border: 1px solid #DEDEDE;
  border-radius: 6px;
  font-family: Poppins, sans-serif;
  font-size: .9rem;
  color: #341F16;
  text-decoration: none;
  transition: border-color .25s ease, background-color .25s ease;
}
.thanks__button svg { width: 18px; height: 18px; }
.thanks__button:hover { border-color: #AC8359; background-color: rgba(172, 131, 89, .07); }

/* Two columns of detail, as in the reference — one on a phone. */
.thanks__details {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 1.15rem;
  margin-top: 1rem;
}
.thanks__label {
  margin: 0 0 .3rem;
  font-family: Poppins, sans-serif;
  font-size: .88rem;
  font-weight: 500;
  color: #341F16;
}
.thanks__details p {
  margin: 0;
  font-family: Poppins, sans-serif;
  font-size: .88rem;
  line-height: 1.6;
  color: rgba(67, 54, 37, .8);
  white-space: pre-line;         /* phone and email on their own lines */
}

.thanks__foot {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 1rem;
  margin-top: clamp(1.5rem, 4vh, 2.25rem);
}
.thanks__help {
  margin: 0;
  font-family: Poppins, sans-serif;
  font-size: .92rem;
  color: rgba(67, 54, 37, .8);
}
.thanks__help a { color: #805231; }
.thanks__continue {
  padding: .9rem 1.75rem;
  border-radius: 6px;
  background: #AC8359;
  color: #FFFFFF;
  font-family: Poppins, sans-serif;
  font-size: .95rem;
  text-decoration: none;
  transition: background-color .3s ease;
}
.thanks__continue:hover { background: #97714B; }

@media (max-width: 640px) {
  .thanks__details { grid-template-columns: minmax(0, 1fr); }
  .thanks__continue { flex: 1 1 100%; text-align: center; }
}

/* Two columns once there is room for them, form first in the source so
   a keyboard and a screen reader reach the fields before the tally. */
@media (min-width: 900px) {
  /* The section gives up its side padding so the grid spans the page —
     which is what lets the column boundary be measured from the page's
     own centre rather than from wherever a container edge happened to
     fall. */
  .checkout { padding-inline: 0; padding-block: 0; }

  .checkout__grid {
    /* The rule sits three pixels past the middle of the page. */
    grid-template-columns: calc(50% + 3px) minmax(0, 1fr);
    gap: 0;
    align-items: stretch;          /* so the rule between them runs the
                                      height of the taller column */
    /* And at least the height of what is left of the window, so on a
       short order the rule still reaches the bottom of the page rather
       than stopping under the last field. */
    min-height: calc(100vh - var(--checkout-head-h));
  }

  /* The block padding moves off the section and onto the columns, so
     the rule between them starts under the header rather than below a
     band of padding, and runs to the last pixel of the page. */
  .checkout__form,
  .checkout__col,
  .checkout__summary { padding-block: clamp(1.5rem, 4vh, 3rem) clamp(3rem, 8vh, 6rem); }

  /* Left edge fixed, right edge wherever the rule now is: the boxes
     keep their alignment and give up the width instead. */
  .checkout__form,
  .checkout__col {
    grid-column: 1; grid-row: 1;
    padding-left: var(--checkout-box-left);
    padding-right: var(--checkout-gutter);
  }

  /* The vertical divider. On the column rather than drawn separately,
     so it is exactly as tall as the section is.

     The tally keeps its distance from the rule and lets the slack
     gather on its right, mirroring the form's own left inset — so the
     page is inset by the same amount at both edges. */
  .checkout__summary {
    grid-column: 2; grid-row: 1;
    border-left: 1px solid #DEDEDE;
    padding-left: var(--checkout-gutter);
    padding-right: var(--checkout-box-left);
  }

  /* The logo begins on the boxes' own left edge. */
  .nav--checkout { padding-inline: var(--checkout-box-left) var(--checkout-edge); }
  /* There is room for the whole tally here, so there is nothing to
     expand and no bar to expand it with. */
  .checkout__summary-bar { display: none; }
  /* Stays with you down the page, so the total is never scrolled away
     from the fields you are filling in to reach it. On the <details>
     itself, not on anything inside it — see the note in the markup. */
  .checkout__summary-inner {
    position: sticky;
    top: clamp(1.5rem, 4vh, 3rem);
  }
  .checkout__summary-body { padding-top: 0; }
}

/* Three across is too many below this, and the contact form's own rule
   only collapses them at 600. */
@media (max-width: 760px) {
  .cform__row.cform__row--three { grid-template-columns: minmax(0, 1fr); }
}

/* ============================================================
   CONTENT PAGES
   Contact, Our Brand and the policies. One band + prose column,
   reusing the listing band so the page headers stay consistent.
   ============================================================ */
.page {
  padding: clamp(2rem, 5vh, 3.5rem) var(--gutter) clamp(4rem, 10vh, 8rem);
  background-color: #F0EBE5;
}
.page__inner { max-width: 68ch; }

.prose h2 {
  margin: clamp(2rem, 4vh, 3rem) 0 .75rem;
  color: #341F16;
  font-family: Newsreader, serif;
  font-size: clamp(1.25rem, 2vw, 1.6rem);
  font-weight: 400;
  line-height: 1.25;
}
.prose h2:first-child { margin-top: 0; }

.prose p, .prose li {
  color: rgba(0, 0, 0, .71);
  font-family: Poppins, sans-serif;
  font-size: 18px;
  font-weight: 400;
  line-height: 25.2px;
}
.prose p { margin: 0 0 1.1rem; }
.prose ul { margin: 0 0 1.1rem; padding-left: 1.2rem; }
.prose li { margin-bottom: .5rem; }
.prose a { color: #805231; }
.prose strong { color: #341F16; font-weight: 500; }

/* --- 404 --- */
.page--404 { text-align: center; }
.page--404 .prose--policy { text-align: center; }
.notfound__code {
  margin: 0 0 .5rem;
  color: rgba(0, 0, 0, .28);
  font-family: Newsreader, serif;
  font-size: clamp(3.5rem, 12vw, 6rem);
  font-weight: 300;
  line-height: 1;
}
.notfound__title {
  margin: 0 0 .9rem;
  color: #341F16;
  font-family: Newsreader, serif;
  font-size: clamp(1.5rem, 3vw, 2.1rem);
  font-weight: 300;
}
.notfound__body { margin: 0 auto 2rem; max-width: 46ch; }
.notfound__actions {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 1.1rem;
}
.notfound__link {
  color: #805231;
  font-family: Poppins, sans-serif;
  font-size: 16px;
}

/* --- policy pages ---
   The measure is centred on the page rather than set against the left
   gutter, and each clause is separated by a rule. The text inside stays
   left-aligned: centred body copy gives every line a different starting
   edge, which is what makes a long policy hard to read. */
.prose--policy { margin-inline: auto; }

/* A standing paragraph above the first clause. It takes the gap the
   clauses use between themselves, but no rule — the clauses are what
   the rules divide.
   Two classes: `.prose p` above is a class *and* an element, so it
   outranks a lone `.policy__lead` and the margin would stay at 1.1rem. */
.prose--policy .policy__lead { margin-bottom: clamp(1.75rem, 3.5vh, 2.75rem); }

.policy__clause + .policy__clause {
  margin-top: clamp(1.75rem, 3.5vh, 2.75rem);
  padding-top: clamp(1.75rem, 3.5vh, 2.75rem);
  border-top: 1px solid rgba(52, 31, 22, .14);
}
/* The clause's own padding sets the space above its heading, so the
   heading must not add its own on top. */
.policy__clause > h2:first-child { margin-top: 0; }
.policy__clause > :last-child { margin-bottom: 0; }
.prose--policy .policy__lead > :last-child { margin-bottom: 0; }

/* The privacy policy runs long enough that a rule every few paragraphs
   turns into stripes. Spacing alone separates the clauses there. */
.prose--flush .policy__clause + .policy__clause {
  padding-top: 0;
  border-top: 0;
}

/* The date sits above the policy, not inside it. */
.prose--policy .policy__updated {
  margin-bottom: 1.6rem;
  font-size: 16px;
  opacity: .75;
}

/* Weight alone does the emphasis here — the bold runs keep the body
   colour rather than darkening to the heading brown, so a clause reads
   as one continuous paragraph with terms picked out, not as two
   different colours of text. */
.prose--policy strong {
  color: rgba(0, 0, 0, .71);
  font-weight: 700;
}

/* The numbered headings and the bullets sit in the body colour too, so
   the whole clause is one ink and only the serif and the weight
   separate a heading from the text under it. */
.prose--policy h2      { color: rgba(0, 0, 0, .71); }
.prose--policy li::marker { color: rgba(0, 0, 0, .71); }

/* --- contact details --- */
.contact__list { margin: 0 0 2rem; padding: 0; list-style: none; }
.contact__row { margin-bottom: 1.4rem; }
.contact__label {
  margin: 0 0 .2rem;
  color: rgba(67, 54, 37, .6);
  font-family: Poppins, sans-serif;
  font-size: 16px;
}
.contact__value {
  margin: 0;
  color: #341F16;
  font-family: Poppins, sans-serif;
  font-size: 20px;
}
.contact__value a { color: #341F16; text-decoration: none; }
.contact__value a:hover { color: #805231; }

/* Drafts that still need the owner's own wording, marked so they cannot
   be mistaken for finished copy. Delete the block with the notice. */
.draft-note {
  margin: 0 0 2rem;
  padding: .9rem 1.1rem;
  border-left: 3px solid #AC8359;
  background: rgba(172, 131, 89, .12);
  color: #341F16;
  font-family: Poppins, sans-serif;
  font-size: 16px;
  line-height: 1.5;
}

/* ============================================================
   OUR BRAND
   One measure shared by the band and the section, so the heading,
   the logo and the copy all begin on the same left edge while the
   column itself sits centred in the page.
   ============================================================ */
.brand-wrap {
  /* the gutter is added to the measure rather than taken out of it, so
     the text column stays 640px wide instead of shrinking on desktop */
  max-width: calc(640px + 2 * var(--gutter));
  margin-inline: auto;
  padding-inline: var(--gutter);
}

.brand-band {
  /* shorter than the other page bands, as asked */
  padding-block: clamp(.7rem, 1.6vh, 1.1rem);
  background-color: #E5DBD3;
}
.brand-band__title {
  margin: 0;
  color: #341F16;
  font-family: Newsreader, serif;
  font-size: 32px;
  font-weight: 300;
  line-height: 35.2px;
}

.brand {
  padding-block: clamp(2.5rem, 6vh, 4.5rem) clamp(4rem, 10vh, 8rem);
  background-color: #F0EBE5;
}

/* --- lockup ---
   The wordmark fills the text column, so its left edge lines up with the
   copy above it. The icon then hangs in the margin to the left, which is
   what the negative margin buys: the flex row starts further left by
   exactly the icon plus the gap, leaving the wordmark on the measure. */
.brand__logo {
  --brand-icon-w: clamp(38px, 5vw, 74px);
  --brand-icon-gap: clamp(.85rem, 1.8vw, 1.75rem);

  display: flex;
  align-items: center;
  gap: var(--brand-icon-gap);
  margin-top: clamp(2.5rem, 6vh, 4.5rem);
  margin-left: calc(-1 * (var(--brand-icon-w) + var(--brand-icon-gap)));
  text-decoration: none;
}
.brand__logo-icon {
  width: var(--brand-icon-w);
  height: auto;
  flex: none;
  display: block;
}
.brand__logo-name {
  flex: 1 1 auto;
  min-width: 0;
  width: 100%;              /* spans the measure, as in the reference */
  height: auto;
  display: block;
}

/* Below this the margin has no room to hang into, so the lockup comes
   back inside the column and the icon shrinks to suit. */
@media (max-width: 900px) {
  .brand__logo {
    margin-left: 0;
    --brand-icon-w: clamp(30px, 8vw, 46px);
  }
}

.brand__copy p {
  margin: 0 0 1.35rem;
  font-family: "Google Sans", Helvetica, Arial, sans-serif;
  font-size: clamp(1rem, 1.15vw, 1.125rem);
  font-weight: 400;
  line-height: 1.7;
  color: rgba(52, 31, 22, 0.75);
}
.brand__copy p:last-child { margin-bottom: 0; }
.brand__copy strong { font-weight: 700; color: rgba(52, 31, 22, 0.92); }

/* ============================================================
   CONTACT FORM
   Colours, measure and type all come from the Our Brand shell —
   this only adds the field styling.
   ============================================================ */
/* The form is the first thing in the section now, so it needs no top
   margin of its own — the section's padding already sets the distance
   from the band, exactly as it does for the copy on Our Brand. */
.cform {
  display: flex;
  flex-direction: column;
  gap: clamp(.7rem, 1.6vh, 1rem);
}

/* Name and Email share a row; everything else runs full width. */
.cform__row {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: clamp(.7rem, 1.6vw, 1rem);
}

.cform__field { display: flex; flex-direction: column; }

/* The placeholder is the visible label, as in the reference. The real
   label stays for screen readers and for clicking into the field. */
.cform__label {
  position: absolute;
  width: 1px; height: 1px;
  margin: -1px; padding: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
  border: 0;
}

.cform__input {
  width: 100%;
  padding: clamp(1rem, 2.2vh, 1.3rem) clamp(1rem, 2vw, 1.4rem);
  border: 1px solid transparent;
  border-radius: 4px;
  background-color: #F5F2EE;
  font-family: "Google Sans", Helvetica, Arial, sans-serif;
  font-size: clamp(1rem, 1.15vw, 1.125rem);
  line-height: 1.5;
  color: #341F16;
}
.cform__input::placeholder { color: rgba(52, 31, 22, 0.75); opacity: 1; }
.cform__input:focus-visible {
  outline: none;
  border-color: rgba(52, 31, 22, 0.45);
}
.cform__textarea { resize: vertical; min-height: clamp(200px, 34vh, 340px); }

/* Invalid fields are outlined and explained — colour alone would not
   say what is wrong, and would say nothing at all to a screen reader. */
.cform__input[aria-invalid="true"] { border-color: #A3402F; }
.cform__error {
  margin: .45rem 0 0;
  font-family: "Google Sans", Helvetica, Arial, sans-serif;
  font-size: .92rem;
  color: #A3402F;
}

/* Honeypot. Moved off-screen rather than display:none or hidden:
   a bot that skips hidden inputs will still find and fill this one,
   which is the whole point of it. It stays out of the tab order and
   out of the accessibility tree via the markup. */
.cform__trap {
  position: absolute;
  left: -9999px;
  width: 1px;
  height: 1px;
  overflow: hidden;
}

.cform__submit {
  align-self: flex-start;
  margin-top: clamp(.5rem, 1.5vh, 1rem);
  padding: clamp(.95rem, 2vh, 1.15rem) clamp(2rem, 4vw, 2.75rem);
  border: 0;
  border-radius: 4px;
  background-color: #34241C;
  color: #FFFFFF;
  font-family: "Google Sans", Helvetica, Arial, sans-serif;
  font-size: clamp(1rem, 1.15vw, 1.125rem);
  cursor: pointer;
  transition: background-color .3s ease;
}
.cform__submit:hover { background-color: #4A362B; }

.cform__notice {
  margin: .25rem 0 0;
  padding: .9rem 1.1rem;
  border-left: 3px solid #AC8359;
  background: rgba(172, 131, 89, .12);
  font-family: "Google Sans", Helvetica, Arial, sans-serif;
  font-size: 1rem;
  line-height: 1.6;
  color: rgba(52, 31, 22, 0.9);
}
.cform__notice a { color: #805231; }


@media (max-width: 600px) {
  .cform__row { grid-template-columns: minmax(0, 1fr); }
  .cform__submit { align-self: stretch; }
}
