/* ===========================================================================
   kink — shared stylesheet for the website prototype

   Structure, so this stops growing by append:

     1  Foundations        imports, reset, layout primitives, type helpers
     2  Buttons            the signature em-dash button and its variants
     3  Chrome             nav, mobile drawer, skip link, footer
     4  Surfaces           the four block themes
     5  Content            page hero, cards, tags, float bar, prose, empty states
     6  Commerce           cart affordance, qty stepper, PDP, bundles, gift, cart page
     7  Overlays           notify dialog, consent banner
     8  Forms              fields, selects, validation states
     9  Utilities          visually-hidden, placeholder markers, locale switch
     10 Responsive         EVERY media query, in one place, in cascade order

   Rule: new work goes in its section, and any breakpoint work goes in §10.
   Media queries were previously scattered across eleven places in this file, which caused
   two real regressions — a pointer rule declared after the touch block silently undid the
   44px target floor, and a global reset killed the UA centring on a modal <dialog>. One
   ordered block at the end makes that class of bug visible instead of latent.

   Tokens come from tokens.css, generated from kink-tokens.json — never hardcode a hex here.
   =========================================================================== */

/* ---------------------------------------------------------------------------
   1 · FOUNDATIONS
   --------------------------------------------------------------------------- */
@import url('fonts.css?v=f99699d734');   /* self-hosted, see fonts.css for why */
@import url('tokens.css?v=bac32906ee');   /* colour, type, spacing, motion — run build-tokens.py to regenerate.
   The ?v= is a one-time cache bust from 04/09/2026: browsers held this file under a seven-day
   max-age and would not re-request it. The cache policy is now revalidate-always, so this number
   never needs bumping again. */

*{box-sizing:border-box;margin:0;}
/* Browsers draw a border, padding and a min-width on <fieldset> by default. Nothing in this
   file ever reset it, so .bundles and .plans (both fieldsets, grouping a set of radio cards)
   have always carried an extra square frame around the cards on top of each card's own border —
   invisible until two fieldsets stacked made it obvious. */
fieldset{border:0;padding:0;margin:0;min-width:0;}
html{scroll-behavior:smooth;}
body{font-family:var(--ui);background:var(--paper);color:var(--ink);-webkit-font-smoothing:antialiased;overflow-x:hidden;}
img{display:block;max-width:100%;height:auto;}
/* The hidden attribute must actually hide. Any component that sets its own display, and most
   here do, silently beats a bare [hidden] on specificity: the 210 quantity stepper stayed on
   screen for a sold-out product because .qty sets display:flex. */
[hidden]{display:none !important;}   /* height:auto is the required companion to the intrinsic width/height attributes added 06/09: without it a scaled-down image is stretched to its attribute height. The .ph and .bottleshot rules below override it deliberately. */

.wrap{max-width:1240px;margin:0 auto;padding:0 44px;}
.eyebrow{font-size:var(--text-xs);font-weight:var(--weight-semibold);letter-spacing:var(--kicker-tracking);text-transform:uppercase;color:var(--pond);}  /* UI accent = brand green; Marigold is product-only */
.disp{font-family:var(--disp);font-weight:var(--weight-medium);letter-spacing:var(--display-tracking);line-height:.95;}
.d1{transition-delay:.07s;}.d2{transition-delay:.14s;}.d3{transition-delay:.21s;}.d4{transition-delay:.28s;}
/* .reveal / .reveal.in live once in tokens.css (generated) — see design-tokens.md §6.
   Do not redeclare them here; three divergent copies is how this went wrong before. */

/* ---------------------------------------------------------------------------
   2 · BUTTONS — monochrome, em-dash collapses and the words close up on hover, box never resizes
   --------------------------------------------------------------------------- */
.btn{--dash:40px;--gap:10px;display:inline-flex;align-items:center;justify-content:center;gap:var(--gap);font-family:var(--ui);font-weight:var(--weight-semibold);text-transform:none;font-size:var(--text-md);
  cursor:pointer;border:1.6px solid transparent;border-radius:13px;padding:18px 36px;text-decoration:none;
  transition:padding .32s ease,background .2s,box-shadow .2s,color .2s,border-color .2s;}
.btn .dash{display:inline-block;width:var(--dash);height:1px;background:currentColor;flex:none;
  transform-origin:center;transition:transform .32s ease,opacity .2s ease;}  /* 1px savor-thin hairline */
/* The hairline collapses with transform, not width, so it takes no layout space with it and the
   button box cannot change size. The previous version collapsed the width and grew the padding by
   the same amount to compensate; that arithmetic held in most places and failed where a button
   became a flex item, measured live at 2 of 9 CTAs on the home page growing 24px on hover while
   the other 7 held still. Compensation that depends on layout context is not compensation. */
.btn:hover .dash{transform:scaleX(0);opacity:0;}
/* The two words close up the same way: each moves half the hairline's width towards the other, so
   they meet where the hairline was and nothing in the layout moves. --dash is the hairline width. */
.btn > span:has(+ .dash),.btn > .dash + span{transition:transform .32s ease;}
/* Working state for a button waiting on the network: a turning ring before the label, full
   colour kept so it reads as busy rather than broken. With reduced motion the ring stays still. */
.btn.busy,.btn.busy:disabled{cursor:progress;opacity:1;}
.btn.busy::before{content:'';width:16px;height:16px;flex:none;border:2px solid currentColor;border-right-color:transparent;border-radius:50%;animation:kspin .8s linear infinite;}
@keyframes kspin{to{transform:rotate(360deg);}}
@media (prefers-reduced-motion:reduce){.btn.busy::before{animation:none;border-right-color:currentColor;opacity:.6;}}
.btn:hover > span:has(+ .dash){transform:translateX(calc((var(--dash) + 2 * var(--gap) - .28em) / 2));}   /* the two words close to one space */
.btn:hover > .dash + span{transform:translateX(calc((var(--dash) + 2 * var(--gap) - .28em) / -2));}
.btn.pri{background:var(--ink);color:var(--paper);} .btn.pri:hover{background:#000;box-shadow:0 8px 20px rgba(30,11,12,.18);}
.btn.soft{background:var(--stone100);color:var(--ink);} .btn.soft:hover{background:var(--s200);}
.btn.out{background:transparent;color:var(--ink);border-color:var(--ink);} .btn.out:hover{background:var(--ink);color:var(--paper);}
.btn.light{background:var(--paper);color:var(--ink);border-color:rgba(30,11,12,.14);} .btn.light:hover{background:#fff;}  /* faint savor-style border */
.btn.line{background:transparent;color:var(--paper);border-color:rgba(250,249,245,.55);} .btn.line:hover{background:var(--paper);color:var(--ink);}
.btn.sm{--dash:24px;--gap:8px;font-size:var(--text-xs);padding:12px 22px;gap:var(--gap);}

.btn.added{background:var(--pond);color:var(--paper);}
.btn:focus-visible{outline:3px solid var(--action-focus-ring);outline-offset:2px;}

/* ---------------------------------------------------------------------------
   3 · CHROME — nav, drawer, skip link, footer
   --------------------------------------------------------------------------- */
/* The side padding lines the logo and the Shop button up with .wrap's 1152px content column, so the nav is as wide as the sections below it. */
nav{position:fixed;top:0;left:0;right:0;z-index:90;display:flex;align-items:center;justify-content:space-between;
  padding:20px max(44px, calc((100% - 1152px) / 2));color:var(--ink);background:rgba(250,249,245,.94);backdrop-filter:blur(8px);box-shadow:0 1px 0 var(--s200);
  transition:background .3s,color .3s,padding .3s;}
nav.over{background:transparent;color:var(--paper);box-shadow:none;}   /* transparent over a dark hero */
nav .logo{display:inline-block;width:96px;height:32px;background:var(--ink);-webkit-mask:var(--logo) no-repeat left center/contain;mask:var(--logo) no-repeat left center/contain;}
nav.solid .logo{background:var(--ink);}
nav .links{display:flex;gap:28px;align-items:center;font-size:var(--text-xs);text-transform:uppercase;letter-spacing:var(--nav-tracking);font-weight:var(--weight-medium);}
nav .links a{color:inherit;text-decoration:none;opacity:.9;} nav .links a:hover{opacity:1;}
nav .btn{padding:11px 26px;font-size:var(--text-sm);background:transparent;color:inherit;border-color:currentColor;}
nav .btn:hover{padding:11px 26px;background:currentColor;color:var(--paper);}   /* 'Shop' single word — no resize/move */
nav .btn .cart-ico{display:inline-block;}   /* the bag sits in the Shop button on every page */
.navpad{height:74px;}   /* spacer under fixed nav on light-hero pages */
/* The page you are on, marked in the bar and in the phone drawer: nav.js sets aria-current. */
nav .links a[aria-current="page"]{opacity:1;text-decoration:underline;text-underline-offset:6px;text-decoration-thickness:1px;}
.drawer nav a[aria-current="page"]{text-decoration:underline;text-underline-offset:6px;}
.backcart{display:inline-flex;align-items:center;min-height:24px;margin-bottom:10px;color:var(--s600);font-size:14px;}
/* Breadcrumbs. The recipe pages carry their own absolute-positioned version over the hero image;
   this is the ordinary in-flow one the product and policy pages use. */
.crumbs{font-size:var(--text-xs);color:var(--s500);margin-bottom:10px;}
.crumbs a{color:var(--s500);text-decoration:none;}
.crumbs a:hover{color:var(--ink);text-decoration:underline;}
.phead .crumbs{margin-bottom:14px;}
/* language offer: a quiet card under the nav, in the visitor's language (nav.js). Fixed, so nothing on the page moves. */
.langoffer{position:fixed;top:calc(var(--offer-top,74px) + 10px);right:max(44px, calc((100% - 1152px) / 2));z-index:85;display:flex;align-items:center;gap:4px;
  background:var(--bg-surface);border:1px solid var(--border-subtle);border-radius:var(--radius-lg);box-shadow:var(--effect-overlay);padding:4px 4px 4px 16px;
  font-size:var(--text-sm);color:var(--ink);opacity:0;transform:translateY(-6px);
  transition:opacity var(--motion-base) var(--motion-ease-out),transform var(--motion-base) var(--motion-ease-out);}
.langoffer.in{opacity:1;transform:none;}
.langoffer a{display:inline-flex;align-items:center;min-height:32px;color:var(--ink);font-weight:var(--weight-semibold);text-decoration:underline;text-underline-offset:3px;}
.langoffer-x{display:inline-flex;align-items:center;justify-content:center;min-width:32px;min-height:32px;background:none;border:0;border-radius:var(--radius-md);color:var(--s600);cursor:pointer;}
.langoffer-x:hover{color:var(--ink);}
.langoffer a:focus-visible,.langoffer-x:focus-visible{outline:3px solid var(--action-focus-ring);outline-offset:2px;}

/* skip link — first tab stop on every page, hidden until focused */
.skip-link{position:absolute;left:-9999px;top:0;z-index:200;background:var(--ink);color:var(--paper);
  padding:14px 22px;border-radius:0 0 var(--radius-md) 0;font-weight:var(--weight-semibold);font-size:var(--text-sm);text-decoration:none;
  min-height:44px;display:flex;align-items:center;}
.skip-link:focus{left:0;}

/* burger + drawer — below 900px the nav links collapse; nav.js supplies the panel */
.burger{display:none;width:44px;height:44px;align-items:center;justify-content:center;flex-direction:column;
  gap:5px;background:none;border:0;cursor:pointer;padding:0;margin-left:4px;}
.burger span{display:block;width:20px;height:1.5px;background:currentColor;transition:transform .22s ease,opacity .22s ease;}
.burger[aria-expanded="true"] span:first-child{transform:translateY(3.25px) rotate(45deg);}
.burger[aria-expanded="true"] span:last-child{transform:translateY(-3.25px) rotate(-45deg);}
.burger:focus-visible{outline:3px solid var(--action-focus-ring);outline-offset:2px;}

.drawer{position:fixed;inset:0;z-index:95;background:rgba(30,11,12,.42);opacity:0;transition:opacity .22s ease;}
.drawer.open{opacity:1;}
.drawer nav{position:absolute;top:0;right:0;bottom:0;width:min(84vw,340px);background:var(--bg-page);
  padding:96px 28px 32px;display:flex;flex-direction:column;gap:2px;
  transform:translateX(100%);transition:transform .28s cubic-bezier(.22,1,.36,1);
  box-shadow:var(--effect-overlay);}
.drawer.open nav{transform:none;}
.drawer nav a{display:flex;align-items:center;min-height:52px;padding:0 4px;color:var(--ink);
  text-decoration:none;font-size:var(--text-lg);font-weight:var(--weight-medium);border-bottom:1px solid var(--border-subtle);}
.drawer nav a.secondary{font-size:var(--text-md);color:var(--text-secondary);min-height:46px;}
.drawer nav a.drawer-cart{color:var(--pond);font-weight:var(--weight-semibold);}
/* An explicit close, because the burger sits under the scrim once the drawer is open. */
.drawer .dclose{position:absolute;top:14px;right:18px;display:inline-flex;align-items:center;justify-content:center;
  width:44px;height:44px;background:none;border:0;border-radius:var(--radius-md);color:var(--ink);cursor:pointer;}
.drawer .dclose:hover{background:var(--stone100);}
.drawer .dclose:focus-visible{outline:3px solid var(--action-focus-ring);outline-offset:-3px;}
.drawer nav a:focus-visible{outline:3px solid var(--action-focus-ring);outline-offset:-3px;}

footer{background:var(--pond);color:var(--paper);padding:80px 0 44px;margin-top:0;}
footer .wrap{display:flex;justify-content:space-between;flex-wrap:wrap;gap:30px;}
footer .logo .mark{display:block;width:132px;height:50px;background:var(--paper);-webkit-mask:var(--logo) no-repeat left center/contain;mask:var(--logo) no-repeat left center/contain;margin-bottom:10px;}
footer .logo span{font-size:var(--text-xs);opacity:.7;}
footer .cols{display:flex;gap:60px;flex-wrap:wrap;}
footer h2{font-size:var(--kicker-size);text-transform:uppercase;letter-spacing:var(--nav-tracking);opacity:.6;margin-bottom:12px;font-weight:var(--weight-semibold);}   /* h2 not h4 — an h4 under a page h1 is a two-level outline skip */
footer a{display:block;color:var(--paper);text-decoration:none;opacity:.85;font-size:var(--text-sm);margin-bottom:8px;}
footer .fine{opacity:.72;font-size:var(--text-xs);margin-top:44px;}   /* .5 gave 4.05:1 on Pond, under the 4.5 body floor */
footer .pending{display:block;color:var(--paper);opacity:.5;font-size:var(--text-sm);margin-bottom:8px;cursor:default;}   /* handles with no account yet — text, not a dead href="#" */
footer .social{display:flex;align-items:center;gap:16px;margin-bottom:12px;}   /* Instagram, TikTok, Facebook: each platform's own mark, cream on Pond */
footer .social a{display:inline-flex;align-items:center;justify-content:center;margin:0;opacity:.85;}
footer .social a:hover{opacity:1;}
footer .social a:focus-visible{outline:3px solid var(--action-focus-ring-on-dark);outline-offset:3px;border-radius:4px;}
footer .social svg{display:block;width:20px;height:20px;}

/* ---------------------------------------------------------------------------
   4 · SURFACES — one theme per block (color-system.md §3)
   --------------------------------------------------------------------------- */
.s-paper{background:var(--paper);color:var(--ink);}
.s-water{background:var(--water);color:var(--ink);}
.s-pond{background:var(--pond);color:var(--paper);}
.s-ink{background:var(--ink);color:var(--paper);}
.s-pond .eyebrow,.s-ink .eyebrow{color:rgba(250,249,245,.72);}   /* tonal, never a second brand hue on colour */

/* ---------------------------------------------------------------------------
   5 · CONTENT — hero, cards, tags, float bar, prose, empty states
   --------------------------------------------------------------------------- */
.phead{padding:150px 44px 70px;text-align:center;}   /* The gutter matches .wrap, 44px here and 22px at the mobile breakpoint. This header is
      used bare, outside .wrap, on eleven pages: with 0 its text ran to both screen edges on a
      phone, and with 22px it sat closer to the edge than every other block on the same page. */   /* the gutter is not optional: this header is used bare, outside .wrap, on eleven pages, so with 0 its text ran to both screen edges on a phone */
.phead .eyebrow{margin-bottom:14px;}
/* The hub now filters drinks and kitchen recipes from one row, so the kitchen half gets a
   quiet label rather than eleven undifferentiated chips. */
.tagrow-label{display:inline-block;width:100%;margin:14px 0 8px;font-size:var(--text-xs);letter-spacing:var(--nav-tracking);
  text-transform:uppercase;color:var(--s500);}

.phead h1{font-family:var(--disp);font-weight:var(--weight-medium);font-size:var(--display-1);line-height:.95;letter-spacing:var(--display-tracking);}
.phead p{font-size:var(--text-lg);color:var(--s600);max-width:min(52ch,100%);margin:18px auto 0;line-height:1.5;}

.grid3{display:grid;grid-template-columns:repeat(3,1fr);gap:22px;}
.grid4{display:grid;grid-template-columns:repeat(4,1fr);gap:20px;}
.card{border:1px solid var(--s200);border-radius:18px;overflow:hidden;background:#fff;display:flex;flex-direction:column;transition:transform .2s,box-shadow .2s;text-decoration:none;color:inherit;}
.card:hover,.card:focus-within{transform:translateY(-4px);box-shadow:0 20px 44px rgba(4,63,30,.1);}   /* focus-within so keyboard gets the same signal as hover */
.card .ph{aspect-ratio:4/5;overflow:hidden;background:var(--water-tint);}
.card .ph img{width:100%;height:100%;object-fit:cover;}
/* A recipe whose photograph has not been shot yet. The on-pack QR lands on these pages, so
   until the shoot this is the first thing a venue sees, and an empty half-screen reads as a
   broken page rather than one waiting on a photo. The mark makes the gap deliberate without
   standing a misleading picture in the photograph's place. Drops away on its own the moment
   an <img> is added. */
.card .ph:not(:has(img)),.rd .ph:not(:has(img)){background:var(--stone100);display:grid;place-items:center;}
.rd .ph:not(:has(img)){min-height:52vh;height:100%;}
.card .ph:not(:has(img))::after,.rd .ph:not(:has(img))::after{
  content:"";width:min(42%,190px);aspect-ratio:2746/1333;background:var(--s300);
  -webkit-mask:var(--logo) no-repeat center/contain;mask:var(--logo) no-repeat center/contain;}
.card .body{padding:18px;display:flex;flex-direction:column;gap:6px;}
.card h3{font-size:var(--text-lg);font-weight:var(--weight-semibold);}
.card .meta{font-size:var(--text-xs);color:var(--s500);}
.card .base{font-family:var(--disp);font-style:italic;font-size:var(--text-sm);color:var(--s600);}
.card .row{display:flex;align-items:center;justify-content:space-between;margin-top:6px;}
.card .price{font-size:var(--text-md);font-weight:var(--weight-semibold);}
.pcard .body>.btn{justify-content:center;width:100%;margin-top:12px;padding:15px;font-size:14px;}   /* one product card everywhere: shop, home, cross-sell */
.pcard a.ph{display:block;text-decoration:none;color:inherit;}
.pcard h3 a{text-decoration:none;color:inherit;}
/* Shop cards share one set of rows: photo, tag, title, description, price, button. Side by side,
   each row takes the height of its tallest card, so a card without a tag or with a one-line title
   still starts every row where its neighbours do. A card with no tag keeps the row, invisible.
   Stacked (900px and under) there is nothing to line up with, and a browser without subgrid keeps
   the flex layout above. */
@supports (grid-template-rows:subgrid){@media(min-width:901px){
  .pcard{display:grid;grid-template-rows:subgrid;grid-row:span 6;row-gap:0;}
  .pcard .body{display:grid;grid-template-rows:subgrid;grid-row:span 5;row-gap:6px;}
  .pcard .meta[hidden]{display:block!important;visibility:hidden;}   /* outranks the global [hidden] rule, so the row keeps its place */
  .pcard .body>.btn{align-self:end;}
}}
/* The drink card under a food recipe's method, written by drink-card.js: one compact row, not the grid card. */
.drink-card{flex-direction:row;align-items:stretch;max-width:440px;margin-top:28px;}
.drink-card .ph{width:112px;flex:none;}
.drink-card .body{justify-content:center;}

/* Stockist list. Deliberately a list and not a .card grid: the list starts with one venue,
   and a single card floating in a three-column grid reads as a page that failed to load,
   where a single row reads as the first row. Scales to twenty without a layout change. */
.stocklist{list-style:none;margin:0;padding:0;border-top:1px solid var(--s200);}
.stocklist li{display:flex;flex-wrap:wrap;align-items:baseline;gap:4px 14px;
  padding:18px 2px;border-bottom:1px solid var(--s200);}
.stocklist .nm{font-size:var(--text-lg);font-weight:var(--weight-semibold);}
.stocklist .meta{font-size:var(--text-xs);color:var(--s500);}
.stocklist .state{margin-inline-start:auto;font-size:var(--text-xs);color:var(--pond);
  font-weight:var(--weight-semibold);white-space:nowrap;}
@media (max-width:560px){.stocklist .state{margin-inline-start:0;flex-basis:100%;}}
/* Ships nationwide, wherever someone is deciding whether to order. Understated on purpose:
   it is a fact that removes a doubt, not a promotion, and it borrows the hairline the CTAs
   already use so it reads as part of the system rather than a badge stuck on top. */
.shipline{display:inline-flex;align-items:center;gap:9px;font-size:var(--text-xs);font-weight:var(--weight-semibold);
  color:var(--pond);letter-spacing:var(--nav-tracking);}
.shipline::before{content:"";width:20px;height:1.5px;background:var(--pond);flex:none;}
.pdp .shipline,.phead .shipline{margin-top:14px;}
.phead .shipline{margin-inline:auto;}

.pills{display:flex;gap:6px;} .pills span{font-size:var(--kicker-size);border:1px solid var(--s300);border-radius:6px;padding:4px 8px;color:var(--s600);}
.pills span.on{border-color:var(--ink);color:var(--ink);font-weight:var(--weight-semibold);}

.tags{display:flex;flex-wrap:wrap;gap:10px;justify-content:center;margin-top:26px;}
.tag{background:#fff;color:var(--ink);border:1px solid var(--s200);border-radius:999px;padding:11px 22px;font-weight:var(--weight-semibold);font-size:var(--text-sm);cursor:pointer;transition:.15s;}
.tag:hover{background:var(--water-tint);border-color:var(--water-deep);color:var(--petrol);}   /* M3 secondary-container hover */
.tag.on{background:var(--ink);color:var(--paper);border-color:var(--ink);}   /* active = ink, never orange */

.floatbar{position:fixed;left:50%;bottom:26px;transform:translateX(-50%);z-index:80;display:flex;background:var(--pond);
  color:var(--paper);border-radius:12px;box-shadow:0 14px 34px rgba(4,63,30,.28);overflow:hidden;}
.floatbar button{background:none;border:none;color:var(--paper);font-family:var(--ui);font-weight:var(--weight-semibold);font-size:var(--text-xs);
  letter-spacing:var(--nav-tracking);text-transform:uppercase;padding:15px 26px;display:flex;align-items:center;gap:8px;cursor:pointer;}
.floatbar button+button{border-left:1px solid rgba(250,249,245,.22);}
.floatbar button:hover{background:var(--pond9);}

.prose{max-width:68ch;margin-inline:auto;padding:0 0 90px;}
.prose h2{font-family:var(--disp);font-weight:var(--weight-medium);font-size:var(--display-3);letter-spacing:var(--display-tracking);margin:38px 0 12px;}
.prose p,.prose li{color:var(--text-secondary);line-height:1.7;font-size:var(--text-md);margin-bottom:12px;}
.prose ul{padding-left:20px;}
.emptyblock{border:1px dashed var(--s300);border-radius:var(--radius-lg);padding:56px 30px;text-align:center;color:var(--text-muted);}
.emptyblock h2{font-family:var(--disp);font-weight:var(--weight-medium);font-size:var(--display-3);color:var(--ink);margin-bottom:8px;}

/* ---------------------------------------------------------------------------
   6 · COMMERCE — cart affordance, stepper, PDP, bundles, gift, cart page
   --------------------------------------------------------------------------- */
nav .links .cartlink{display:inline-flex;align-items:center;gap:7px;}
nav .links .cartlink .cart-ico{display:none;}   /* the bag shows on the cart only on phones, see the 900px block */
.cartcount{display:inline-flex;align-items:center;justify-content:center;min-width:19px;height:19px;padding:0 5px;
  border-radius:999px;background:var(--ink);color:var(--paper);font-size:var(--kicker-size);font-weight:var(--weight-semibold);letter-spacing:0;}
nav.over .cartcount{background:var(--paper);color:var(--ink);}
[data-cart-link][data-cart-empty="true"] .cartcount{background:var(--s300);color:var(--s600);}

.qty{display:inline-flex;align-items:center;border:1.5px solid var(--border-input);border-radius:var(--radius-md);overflow:hidden;}
.qty button{background:none;border:0;font:inherit;font-size:var(--text-md);line-height:1;padding:12px 15px;cursor:pointer;color:var(--ink);}
.qty button:hover{background:var(--stone100);}
.qty input{width:46px;border:0;text-align:center;font:inherit;font-weight:var(--weight-semibold);padding:12px 0;background:none;color:var(--ink);}
.qty input:focus-visible,.acc summary:focus-visible{outline:3px solid var(--action-focus-ring);outline-offset:2px;}

.pdp{display:grid;grid-template-columns:1.05fr .95fr;gap:64px;padding:120px 0 90px;align-items:start;}
.pdp .gallery{position:sticky;top:100px;}
.pdp .shot{aspect-ratio:4/5;border-radius:var(--radius-lg);background:radial-gradient(120% 100% at 50% 16%,var(--water-tint),var(--paper));
  display:flex;align-items:center;justify-content:center;border:1px solid var(--s200);}
.pdp .thumbs{display:flex;gap:10px;margin-top:12px;}
.pdp .thumbs div{width:72px;aspect-ratio:1;border-radius:var(--radius-md);border:1px solid var(--s200);
  background:radial-gradient(120% 100% at 50% 20%,var(--water-tint),var(--paper));cursor:pointer;}
.pdp .thumbs div[aria-current="true"]{border-color:var(--ink);}
.pdp h1{font-family:var(--disp);font-weight:var(--weight-medium);font-size:var(--display-2);line-height:1;letter-spacing:var(--display-tracking);}
.pdp .sub{font-family:var(--disp);font-style:italic;font-size:var(--text-lg);color:var(--s600);margin-top:10px;}
.pdp .price{font-size:var(--display-3);font-weight:var(--weight-semibold);margin:22px 0 4px;}
.pdp .placeholder-note{font-size:var(--text-xs);color:var(--s500);}
.pdp .story{margin-top:30px;font-size:var(--text-md);line-height:1.6;color:var(--s600);}
.pdp .use{margin-top:28px;padding-top:26px;border-top:1px solid var(--s200);}
.pdp .use h2,.pdp .use h4{font-family:var(--disp);font-weight:var(--weight-medium);letter-spacing:var(--display-tracking);font-size:var(--display-3);margin-bottom:10px;}
.pdp .use ol{margin:0;padding-left:0;list-style:none;counter-reset:use;color:var(--s600);line-height:1.7;}
.pdp .use ol li{counter-increment:use;position:relative;padding:4px 0 4px 38px;}
.pdp .use ol li:before{content:counter(use,decimal-leading-zero);position:absolute;left:0;top:4px;font-family:var(--disp);font-style:italic;color:var(--pond);}   /* numbered like the recipe method */
.buyrow{display:flex;gap:12px;align-items:center;margin:24px 0 8px;flex-wrap:wrap;}
.buyrow .btn{flex:1;min-width:210px;}
.yield{display:inline-block;margin-top:16px;background:var(--water-tint);color:var(--petrol);border-radius:999px;
  padding:8px 16px;font-size:var(--text-xs);font-weight:var(--weight-semibold);}
/* Real bottle photography, 04/09/2026, replacing the CSS-drawn stand-in. The shots are shot on
   an off-white ground that matches --paper, so they sit inside the container's gradient rather
   than on a visible white rectangle. contain, never cover: a cropped bottle is worse than a
   small one. */
/* The shots are cut out on their own near-white ground, so the container is given --paper to
   match it. The container is given that flat ground so the bottle reads as photographed rather than pasted:
   multiply was tried first and is wrong here, because the card's --water-tint gradient showed
   through the white label and turned the product grey-green. */
img.bottleshot{width:100%;height:100%;object-fit:contain;}
.card .ph img.bottleshot{object-fit:contain;}   /* the generic card rule above sets cover and outranks
   img.bottleshot on specificity, so a wide bottle image, the three-pack, lost its outer bottles to
   the crop. contain, never cover, for every bottle shot, cards included. 10/09/2026 */
.pdp .shot:has(img.bottleshot),.ph:has(img.bottleshot){background:#fff;}   /* product photos are on pure white */
.pdp .shot img.bottleshot{padding:6% 0;}
.ph img.bottleshot{padding:4% 0;}

.bottle{width:96px;height:264px;background:linear-gradient(180deg,#ffffffcc,#E7B85E 30%,#D89A34);
  border-radius:30px 30px 14px 14px;box-shadow:0 20px 38px rgba(4,63,30,.18);position:relative;}
.bottle:before{content:"";position:absolute;left:50%;top:-16px;transform:translateX(-50%);width:34px;height:20px;background:#cfcfcf;border-radius:5px;}
.bottle.lg{height:312px;width:106px;}

.acc{margin-top:26px;border-top:1px solid var(--s200);}
.acc details{border-bottom:1px solid var(--s200);}
.acc summary{padding:17px 0;font-weight:var(--weight-semibold);cursor:pointer;list-style:none;display:flex;justify-content:space-between;align-items:center;}
.acc summary::-webkit-details-marker{display:none;}
.acc summary:after{content:"+";font-size:var(--text-lg);color:var(--s500);}
.acc details[open] summary:after{content:"−";}
.acc .in{padding:0 0 18px;color:var(--s600);line-height:1.6;font-size:var(--text-md);}
.acc .in a{color:var(--pond);font-weight:var(--weight-semibold);}   /* a link inside an answer reads as the site's link, not browser blue */

.drinks,.crosssell{padding:70px 0;}
.drinks h2,.crosssell h2{font-family:var(--disp);font-weight:var(--weight-medium);letter-spacing:var(--display-tracking);font-size:var(--display-3);margin-bottom:26px;}

/* bundles — same-SKU quantity options; the benefit is shipping, so the qualifying row is
   badged rather than discounted. Feedback roles only (info = water/petrol, success = pond). */
.bundles{display:grid;gap:10px;margin:22px 0 6px;}
.bundle{display:flex;align-items:center;gap:14px;border:1.5px solid var(--border-subtle);
  border-radius:var(--radius-lg);padding:14px 16px;cursor:pointer;background:var(--bg-surface);
  transition:border-color .16s,background .16s;position:relative;}
.bundle:hover{border-color:var(--s300);}
.bundle input{position:absolute;opacity:0;pointer-events:none;}
.bundle .dot{width:20px;height:20px;border-radius:999px;border:1.5px solid var(--s300);flex:none;display:grid;place-items:center;}
.bundle .dot:after{content:"";width:10px;height:10px;border-radius:999px;background:transparent;}
.bundle:has(input:checked){border-color:var(--ink);background:var(--stone100);}
.bundle:has(input:checked) .dot{border-color:var(--ink);}
.bundle:has(input:checked) .dot:after{background:var(--ink);}
.bundle:has(input:focus-visible){outline:3px solid var(--action-focus-ring);outline-offset:2px;}
.bundle .lbl{flex:1;min-width:0;}
.bundle .lbl b{display:block;font-size:var(--text-md);font-weight:var(--weight-semibold);}
.bundle .lbl small{display:block;font-size:var(--text-xs);color:var(--text-secondary);margin-top:2px;}
.bundle .amt{font-weight:var(--weight-semibold);font-size:var(--text-md);white-space:nowrap;}
.bundle .flag{display:inline-block;font-size:var(--kicker-size);font-weight:var(--weight-semibold);letter-spacing:var(--nav-tracking);text-transform:uppercase;
  background:var(--feedback-success-bg);color:var(--feedback-success-fg);border-radius:999px;padding:3px 9px;margin-top:6px;}

.shipmeter{background:var(--feedback-info-bg);border-radius:var(--radius-md);padding:13px 15px;margin-top:14px;}
.shipmeter p{font-size:var(--text-sm);color:var(--feedback-info-fg);margin:0 0 9px;line-height:1.4;}
.shipmeter p b{font-weight:var(--weight-semibold);}
.shipmeter .track{height:6px;border-radius:999px;background:rgba(14,58,78,.16);overflow:hidden;}
.shipmeter .fill{height:100%;background:var(--pond);border-radius:999px;transition:width var(--motion-base) var(--motion-ease-out);}
.shipmeter[data-qualifies="true"]{background:var(--feedback-success-bg);}
.shipmeter[data-qualifies="true"] p{color:var(--feedback-success-fg);}

/* gift add-on — single-bottle only, so it is a state of the quantity choice. Hidden rather
   than disabled above 1: a greyed row next to a bundle implies every bottle would be boxed. */
.addon{display:flex;align-items:flex-start;gap:13px;border:1.5px solid var(--border-subtle);
  border-radius:var(--radius-lg);padding:14px 16px;margin-top:10px;cursor:pointer;
  background:var(--bg-surface);transition:border-color .16s,background .16s,opacity .16s;}
.addon:hover{border-color:var(--s300);}
.addon input{width:20px;height:20px;margin:1px 0 0;accent-color:var(--pond);flex:none;}
.addon .lbl{flex:1;min-width:0;}
.addon .lbl b{display:block;font-size:var(--text-sm);font-weight:var(--weight-semibold);}
.addon .lbl small{display:block;font-size:var(--text-xs);color:var(--text-secondary);margin-top:2px;line-height:1.45;}
.addon .amt{font-weight:var(--weight-semibold);font-size:var(--text-sm);white-space:nowrap;}
.addon:has(input:checked){border-color:var(--ink);background:var(--stone100);}
.addon:has(input:focus-visible){outline:3px solid var(--action-focus-ring);outline-offset:2px;}
.addon[hidden]{display:none;}
.giftflag{display:inline-block;font-size:var(--kicker-size);font-weight:var(--weight-semibold);letter-spacing:var(--nav-tracking);text-transform:uppercase;
  background:var(--feedback-info-bg);color:var(--feedback-info-fg);border-radius:999px;padding:3px 9px;margin-bottom:8px;}

/* plan toggle (one-time vs subscribe & save) — same radio-card language as .bundle, since it
   is the same interaction: pick one of a short list. */
.plans{display:grid;gap:10px;margin:18px 0 6px;}
.plan{display:flex;align-items:center;gap:14px;border:1.5px solid var(--border-subtle);
  border-radius:var(--radius-lg);padding:14px 16px;cursor:pointer;background:var(--bg-surface);
  transition:border-color .16s,background .16s;position:relative;}
.plan:hover{border-color:var(--s300);}
.plan input{position:absolute;opacity:0;pointer-events:none;}
.plan .dot{width:20px;height:20px;border-radius:999px;border:1.5px solid var(--s300);flex:none;display:grid;place-items:center;}
.plan .dot:after{content:"";width:10px;height:10px;border-radius:999px;background:transparent;}
.plan:has(input:checked){border-color:var(--ink);background:var(--stone100);}
.plan:has(input:checked) .dot{border-color:var(--ink);}
.plan:has(input:checked) .dot:after{background:var(--ink);}
.plan:has(input:focus-visible){outline:3px solid var(--action-focus-ring);outline-offset:2px;}
.plan .lbl{flex:1;min-width:0;}
.plan .lbl b{font-size:var(--text-md);font-weight:var(--weight-semibold);}
.plan .lbl small{display:block;font-size:var(--text-xs);color:var(--text-secondary);margin-top:2px;}
.plan .amt{font-weight:var(--weight-semibold);font-size:var(--text-md);white-space:nowrap;text-align:right;}
/* the pre-discount price, struck through beside the real one — so "save 10%" is seen, not
   calculated, the moment the subscribe row is compared to the one-time row above it */
.plan .amt s{display:block;font-weight:var(--weight-regular);font-size:var(--text-xs);color:var(--s500);text-decoration:line-through;}
.plan .flag{display:inline-block;font-size:var(--kicker-size);font-weight:var(--weight-semibold);letter-spacing:var(--nav-tracking);text-transform:uppercase;
  background:var(--feedback-success-bg);color:var(--feedback-success-fg);border-radius:999px;padding:3px 9px;margin-left:8px;}

/* interval pills, shown only once "subscribe & save" is the chosen plan */
.intervals{display:flex;gap:8px;margin:2px 0 6px;flex-wrap:wrap;}
.intervals[hidden]{display:none;}
.interval{position:relative;}
.interval input{position:absolute;opacity:0;pointer-events:none;}
.interval span{display:inline-block;border:1px solid var(--s200);border-radius:999px;padding:9px 16px;
  font-size:var(--text-sm);cursor:pointer;transition:border-color .15s,background .15s;}
.interval:has(input:checked) span{border-color:var(--ink);background:var(--stone100);font-weight:var(--weight-semibold);}
.interval:has(input:focus-visible) span{outline:3px solid var(--action-focus-ring);outline-offset:2px;}

/* coming-soon PDP state */
.soonbox{border:1px solid var(--s200);background:var(--stone100);border-radius:var(--radius-lg);padding:22px;margin:24px 0 8px;}
.soonbox p{color:var(--text-secondary);font-size:var(--text-sm);line-height:1.55;margin-bottom:16px;}
.soonbox .btn{width:100%;}

/* cart page */
.cartwrap{padding:130px 0 100px;display:grid;grid-template-columns:1.6fr .9fr;gap:56px;align-items:start;}
.lines{border-top:1px solid var(--s200);}
.line{display:grid;grid-template-columns:96px 1fr auto;gap:20px;padding:24px 0;border-bottom:1px solid var(--s200);align-items:center;}
.line .thumb{aspect-ratio:4/5;border-radius:var(--radius-md);border:1px solid var(--s200);
  background:radial-gradient(120% 100% at 50% 20%,var(--water-tint),var(--paper));display:flex;align-items:center;justify-content:center;}
.line .thumb .bottle{width:34px;height:82px;border-radius:11px 11px 5px 5px;box-shadow:none;}
.line .thumb .bottle:before{width:13px;height:8px;top:-6px;border-radius:2px;}
.line h3{font-size:var(--text-lg);font-weight:var(--weight-semibold);}
.line .base{font-family:var(--disp);font-style:italic;font-size:var(--text-sm);color:var(--s600);margin:2px 0 10px;}
.line .rm{background:none;border:0;padding:0;margin-left:14px;font:inherit;font-size:var(--text-xs);color:var(--s500);text-decoration:underline;cursor:pointer;}
.line .rm:hover{color:var(--ink);}
.line .amt{font-weight:var(--weight-semibold);font-size:var(--text-md);white-space:nowrap;}
.summary{background:#fff;border:1px solid var(--s200);border-radius:var(--radius-lg);padding:28px;position:sticky;top:100px;}
.summary h2{font-family:var(--disp);font-weight:var(--weight-medium);font-size:var(--display-3);margin-bottom:18px;}
.summary .row{display:flex;justify-content:space-between;padding:11px 0;font-size:var(--text-sm);color:var(--s600);}
.summary .row.total{border-top:1px solid var(--s200);margin-top:10px;padding-top:16px;color:var(--ink);font-size:var(--text-lg);font-weight:var(--weight-semibold);}
.summary .btn{width:100%;margin-top:20px;}
.summary .fine{font-size:var(--text-xs);color:var(--s500);margin-top:14px;line-height:1.5;}
.empty{text-align:center;padding:60px 0 40px;}
.empty p{color:var(--s600);margin:12px 0 26px;}

/* ---------------------------------------------------------------------------
   7 · OVERLAYS — notify dialog, consent banner
   --------------------------------------------------------------------------- */
/* margin:auto is REQUIRED — the *{margin:0} reset in §1 overrides the UA rule that centres
   a modal <dialog>, and without it this renders silently in the top-left. */
dialog.notify{border:0;padding:0;border-radius:var(--radius-lg);max-width:440px;width:calc(100% - 40px);margin:auto;
  background:var(--bg-surface);color:var(--text-primary);box-shadow:var(--effect-overlay);}
dialog.notify::backdrop{background:rgba(30,11,12,.46);backdrop-filter:blur(3px);}
dialog.notify h2{font-size:var(--display-3);margin:6px 0 8px;}
.notify-in,.notify-done{padding:36px 34px 30px;position:relative;}
.notify-x{position:absolute;top:14px;right:16px;background:none;border:0;font-size:var(--display-3);line-height:1;
  color:var(--text-muted);cursor:pointer;padding:6px;border-radius:var(--radius-sm);}
.notify-x:hover{color:var(--ink);}
.notify-x:focus-visible{outline:3px solid var(--action-focus-ring);outline-offset:2px;}
.notify-sub{color:var(--text-secondary);font-size:var(--text-sm);line-height:1.55;margin-bottom:22px;}
.notify-err{color:var(--feedback-danger-fg);font-size:var(--text-sm);font-weight:var(--weight-semibold);margin-top:12px;}
.notify-actions{margin-top:22px;}
.notify-actions .btn{width:100%;}
.notify-fine{font-size:var(--text-xs);color:var(--text-muted);margin-top:14px;line-height:1.5;}
.notify-done{text-align:center;}
.notify-done .btn{margin-top:8px;}

/* Add-to-cart drawer — a <dialog> anchored to the right edge instead of centred, so it reads as
   a slide-in panel rather than the notify dialog's popup. The same margin:auto gotcha applies
   in reverse here: every inset has to be set explicitly or the *{margin:0} reset combined with
   the UA's modal centring puts it back in the middle of the screen. */
dialog.cartdrawer{position:fixed;inset:0 0 0 auto;margin:0;height:100%;width:420px;max-width:92vw;
  border:0;padding:28px 26px;background:var(--bg-surface);color:var(--text-primary);box-shadow:var(--effect-overlay);
  display:flex;flex-direction:column;overflow-y:auto;}
dialog.cartdrawer::backdrop{background:rgba(30,11,12,.46);backdrop-filter:blur(3px);}
.cd-head{display:flex;align-items:center;justify-content:space-between;margin-bottom:16px;}
.cd-head h2{font-size:var(--display-4,28px);}
.cd-head span{color:var(--s500);font-weight:var(--weight-regular);}
.cd-x{background:none;border:0;font-size:var(--display-3);line-height:1;color:var(--text-muted);
  cursor:pointer;padding:6px;border-radius:var(--radius-sm);}
.cd-x:hover{color:var(--ink);}
.cd-x:focus-visible{outline:3px solid var(--action-focus-ring);outline-offset:2px;}
.cd-lines{flex:1;overflow-y:auto;margin:16px 0;}
.cd-line{display:grid;grid-template-columns:56px 1fr auto;gap:14px;padding:14px 0;border-bottom:1px solid var(--s200);}
.cd-thumb{aspect-ratio:4/5;border-radius:var(--radius-md);border:1px solid var(--s200);
  background:radial-gradient(120% 100% at 50% 20%,var(--water-tint),var(--paper));display:flex;align-items:center;justify-content:center;}
.cd-thumb .bottle{width:22px;height:54px;border-radius:8px 8px 4px 4px;box-shadow:none;}
.cd-thumb .bottle:before{width:9px;height:6px;top:-4px;border-radius:2px;}
.cd-thumb,.line .thumb{overflow:hidden;}
.cd-thumb img,.line .thumb img{width:100%;height:100%;object-fit:cover;display:block;}
.cd-thumb .bottle.lg{width:26px;height:64px;}
.cd-info h3{font-size:var(--text-sm);font-weight:var(--weight-semibold);margin-bottom:6px;}
.cd-info .rm{display:block;background:none;border:0;color:var(--s500);font-size:var(--text-xs);text-decoration:underline;
  cursor:pointer;padding:0;margin-top:8px;}
.cd-amt{font-weight:var(--weight-semibold);font-size:var(--text-sm);white-space:nowrap;}
.cd-empty{text-align:center;padding:60px 0;color:var(--s600);}
.cd-foot{border-top:1px solid var(--s200);padding-top:16px;}
.cd-foot .row{display:flex;justify-content:space-between;margin-bottom:10px;font-size:var(--text-sm);}
.cd-foot .row.total{font-weight:var(--weight-semibold);font-size:var(--text-md);margin-top:6px;margin-bottom:14px;}
.cd-actions{display:flex;gap:10px;}
.cd-actions .btn{flex:1;justify-content:center;}

/* discount code — a plain input+button while none is applied, a single confirmation row once
   one is, so an applied code cannot be typed over by accident. */
.cd-disc{margin-bottom:16px;}
.cd-disc-row{display:flex;gap:8px;}
.cd-disc-row input{flex:1;border:1px solid var(--s200);border-radius:var(--radius-md);padding:10px 12px;font:inherit;background:var(--paper);color:inherit;}
.cd-disc-row button{border:1px solid var(--ink);border-radius:var(--radius-md);padding:10px 16px;background:none;font:inherit;font-weight:var(--weight-semibold);cursor:pointer;}
.cd-disc-applied{display:flex;justify-content:space-between;align-items:center;background:var(--feedback-success-bg);
  color:var(--feedback-success-fg);border-radius:var(--radius-md);padding:10px 12px;font-size:var(--text-sm);font-weight:var(--weight-semibold);}
.cd-disc-applied button{background:none;border:0;color:inherit;text-decoration:underline;font:inherit;font-weight:var(--weight-regular);cursor:pointer;padding:0;}

.consent{position:fixed;left:16px;right:16px;bottom:16px;z-index:120;max-width:640px;margin-inline:auto;
  background:var(--bg-surface);border:1px solid var(--border-subtle);border-radius:var(--radius-lg);
  box-shadow:var(--effect-overlay);padding:20px 22px;display:flex;gap:18px;align-items:center;
  flex-wrap:wrap;opacity:0;transform:translateY(12px);
  transition:opacity var(--motion-base) var(--motion-ease-out),transform var(--motion-base) var(--motion-ease-out);}
.consent.in{opacity:1;transform:none;}
.consent p{flex:1;min-width:240px;margin:0;font-size:var(--text-sm);line-height:1.55;color:var(--text-secondary);}
.consent p a{color:var(--ink);font-weight:inherit;}   /* there if wanted, never pulling the eye: ink, regular weight, underlined */
.consent-actions{display:flex;gap:10px;flex-wrap:wrap;}
.consent .btn.accept{background:var(--pond);border-color:var(--pond);color:var(--paper);} .consent .btn.accept:hover{background:var(--pond9);border-color:var(--pond9);}
.consent .btn.out:hover{background:transparent;color:var(--ink);}   /* essential only stays still on hover: no fill, no motion */
.consent .btn.out:hover .dash{transform:none;opacity:1;}
.consent .btn.out:hover > span{transform:none;}

/* ---------------------------------------------------------------------------
   8 · FORMS — see components.md "Form controls" for the spec these implement
   --------------------------------------------------------------------------- */
input,select,textarea{font-size:var(--text-md);}   /* iOS Safari auto-zooms anything below 16px and never zooms back out */
.field{display:block;margin-bottom:16px;}
/* label as well as span, and textarea and select as well as input. The prototype's forms marked
   their field names up as spans; the Liquid rewrite uses <label for>, which is the correct and
   accessible markup and which these rules did not select, so every form label on the site was
   rendering unstyled. Textareas and selects had never been styled at all, so the contact message
   box and the venue volume picker sat as browser defaults beside styled inputs, and neither got a
   focus ring. Fixed 03/09/2026. */
.field span,.field label{display:block;font-size:var(--text-xs);font-weight:var(--weight-semibold);letter-spacing:var(--nav-tracking);text-transform:uppercase;
  color:var(--text-secondary);margin-bottom:7px;}
.field input,.field textarea,.field select{width:100%;font:inherit;font-size:var(--text-md);padding:14px 15px;
  border:1.5px solid var(--border-input);border-radius:var(--radius-md);background:var(--bg-surface);color:var(--ink);}
.field textarea{resize:vertical;min-height:120px;line-height:1.5;}
.field input::placeholder,.field textarea::placeholder{color:var(--text-muted);}
.field input:focus-visible,.field textarea:focus-visible,.field select:focus-visible,
.check input:focus-visible{outline:3px solid var(--action-focus-ring);outline-offset:2px;}
.check{display:flex;gap:11px;align-items:flex-start;font-size:var(--text-sm);color:var(--text-secondary);line-height:1.45;cursor:pointer;}
.check input{width:19px;height:19px;margin:1px 0 0;accent-color:var(--pond);flex:none;}

.form{max-width:560px;margin-inline:auto;padding:0 0 90px;}
.form .field{margin-bottom:18px;}
.form textarea{width:100%;font:inherit;font-size:var(--text-md);padding:14px 15px;border:1.5px solid var(--border-input);
  border-radius:var(--radius-md);background:var(--bg-surface);color:var(--ink);min-height:130px;resize:vertical;}
.form select{width:100%;font:inherit;font-size:var(--text-md);padding:14px 15px;border:1.5px solid var(--border-input);
  border-radius:var(--radius-md);background:var(--bg-surface);color:var(--ink);}
.form textarea:focus-visible,.form select:focus-visible{outline:3px solid var(--action-focus-ring);outline-offset:2px;}
.form .two{display:grid;grid-template-columns:1fr 1fr;gap:16px;}
.form .ok{background:var(--feedback-success-bg);border:1px solid var(--pond);border-radius:var(--radius-lg);
  padding:22px;color:var(--feedback-success-fg);}
.form .ok h2{font-family:var(--disp);font-weight:var(--weight-medium);font-size:var(--display-3);margin-bottom:6px;}

/* ---------------------------------------------------------------------------
   9 · UTILITIES
   --------------------------------------------------------------------------- */
.vh{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;border:0;}
.todo{display:inline-block;font-size:var(--kicker-size);font-weight:var(--weight-semibold);letter-spacing:var(--nav-tracking);text-transform:uppercase;
  background:var(--feedback-warning-fg);color:var(--paper);border-radius:5px;padding:3px 7px;margin-right:8px;}
.stub{max-width:760px;margin-inline:auto;background:var(--feedback-info-bg);border:1px solid var(--water-deep);
  border-radius:var(--radius-lg);padding:18px 20px;margin-bottom:34px;font-size:var(--text-sm);line-height:1.55;color:var(--feedback-info-fg);}
.stub strong{display:block;font-size:var(--text-xs);letter-spacing:var(--nav-tracking);text-transform:uppercase;margin-bottom:6px;}
nav .links .langswitch{font-weight:var(--weight-semibold);letter-spacing:var(--nav-tracking);opacity:.75;min-height:24px;display:inline-flex;align-items:center;}
nav .links .langswitch:hover{opacity:1;}

/* ===========================================================================
   10 · RESPONSIVE — every breakpoint, in cascade order.
   Widest max-width first so narrower queries override; the pointer-only block last so it
   can never compete with the touch floors above it.
   =========================================================================== */

@media(max-width:900px){
  .wrap,nav,.phead{padding-left:22px;padding-right:22px;}
  nav .links a:not(.btn):not(.cartlink):not(.langswitch){display:none;}   /* the drawer carries the rest — nav.js */
  .burger{display:flex;}
  .grid3,.grid4{grid-template-columns:1fr 1fr;}
  /* A two-up product grid gives ~171px cards at 390px — too narrow for a two-word em-dash
     button, so the label wrapped. Product grids go single-column on phones. */
  .shopgrid .grid3,.crosssell .grid3{grid-template-columns:1fr;}

  /* the button was sized for desktop: 36px padding + a 40px hairline does not fit a two-word
     label at 390px. Shrink both, keeping the hover compensation proportional. */
  .btn{--dash:24px;--gap:8px;padding:16px 22px;font-size:var(--text-sm);gap:var(--gap);}
  .btn.sm{--dash:18px;padding:11px 16px;}

  /* touch targets — 44px floor on standalone controls. Links inline in a sentence are
     exempt (WCAG 2.2 SC 2.5.8) and are deliberately left alone. */
  /* Phone bar: logo, then language, Shop, cart and menu, all inside 360px. The cart used to be
     appended after the menu button and sat past the right edge of the screen. On phones the bag
     moves from Shop to the cart, and the word for cart stays for screen readers only. */
  nav .links{gap:8px;}
  nav .logo{width:84px;}   /* with the bar no longer squeezed, the logo would otherwise grow to the full 44px height, larger than on desktop */
  nav .links .langswitch{order:1;} nav .links .btn{order:2;} nav .links .cartlink{order:3;} nav .links .burger{order:4;}
  nav .links .btn,nav .links .btn:hover{padding:0 18px;}
  nav .links .btn .cart-ico{display:none;}
  nav .links .cartlink{min-height:44px;min-width:44px;justify-content:center;gap:3px;}
  nav .links .cartlink .cart-ico{display:inline-block;}
  nav .links .cartlink .cartlabel{position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;}
  nav .links .langswitch{display:inline-flex !important;min-height:44px;min-width:44px;justify-content:center;}
  nav .logo{height:44px;background-position:left center;}
  nav .links .btn{min-height:44px;}
  footer a,footer .pending{min-height:44px;display:flex;align-items:center;margin-bottom:2px;}
  footer .social{gap:4px;margin-left:-12px;}   /* 44px targets; the first mark still lines up with the column text */
  footer .social a{min-width:44px;}
  .card h3 a{display:flex;align-items:center;min-height:44px;}
  .tag{min-height:44px;}
  .qty button{min-width:44px;min-height:44px;}
  .line .rm{min-height:44px;display:inline-flex;align-items:center;}
  .thumbs div{min-width:44px;min-height:44px;}
  .crumbs a{min-height:44px;display:inline-flex;align-items:center;}
  .bundle,.addon{min-height:44px;}
  .btn.sm{min-height:44px;}                 /* consent banner buttons were 41px */
  .langoffer{left:16px;right:16px;justify-content:space-between;}
  .langoffer a,.langoffer-x{min-height:44px;}
  .langoffer-x{min-width:44px;}
  nav .logo{min-width:44px;}                /* mask is 34px wide at this size */
  .backcart{min-height:44px;}

  /* The float bar is a shrink-to-fit flex row, so its width is capped by the viewport, and at
     390px its two labels wrapped to two lines inside 15px/26px padding. Neither label is long
     enough to need wrapping once the padding is phone-sized. */
  .floatbar button{padding:14px 16px;white-space:nowrap;min-height:44px;}

  /* Fixed elements the consent banner would otherwise sit on top of. --consent-h is published
     by consent.js while the banner is up and removed the moment it is answered, so the fallback
     in each calc() is the normal offset. */
  /* translate, not bottom, so the bar glides up over a late banner instead of jumping; it composes
     with the translateX(-50%) that centres it. */
  .floatbar{transition:translate .32s ease;}
  .consent-on .floatbar{translate:0 calc(-1 * var(--consent-h,0px));}

  /* layout collapses */
  .pdp,.cartwrap{grid-template-columns:1fr;gap:34px;padding-top:100px;}
  .pdp .gallery,.summary{position:static;}
  .line{grid-template-columns:72px 1fr;}
  .line .amt{grid-column:2;text-align:right;}
}

@media(max-width:700px){
  .form .two{grid-template-columns:1fr;}
}

@media(max-width:560px){
  .grid3,.grid4{grid-template-columns:1fr;}
  /* The banner already stacked its text above its buttons here, but the two buttons stayed in a
     row. At 390px that leaves each of them about 150px, which is not enough for a two-word Thai
     label plus the 18px em-dash hairline, so both labels wrapped to three lines and the pair
     rendered as two 90px blobs under the hero. Stacked, each label sits on one line and the
     banner is no taller than it was, because the row was already three lines deep. */
  .consent{flex-direction:column;align-items:stretch;}
  .consent-actions{flex-direction:column;}
  .consent-actions .btn{width:100%;}
}

/* Pointer devices. WCAG 2.2 SC 2.5.8 (AA) is 24x24 for a standalone target; touch keeps the
   larger 44px treatment above. Scoped to min-width so the two can never fight. */
@media(min-width:901px){
  .drawer{display:none;}
  nav .links a{min-height:24px;display:inline-flex;align-items:center;}
  nav .links .cartlink{min-height:24px;}
  footer a,footer .pending{min-height:24px;display:flex;align-items:center;}
  footer .social a{min-width:24px;}
  .crumbs a{min-height:24px;display:inline-flex;align-items:center;}
  .card h3 a{min-height:24px;display:flex;align-items:center;}
}

/* Commerce off, set from config.js by commerce.js. See that file for what off means and for the
   one line that turns it on. Prices are hidden rather than deleted, so switching commerce on
   cannot reintroduce a wrong figure: the right one never left the markup. */
.commerce-off .price,
.commerce-off .addon,
.commerce-off [data-addon],
.commerce-off .cartlink,
.commerce-off [data-cart-link],
.commerce-off .bundles,
.commerce-off [data-bundles],
.commerce-off .plans,
.commerce-off [data-plans],
.commerce-off .intervals,
.commerce-off [data-intervals],
.commerce-off .shipmeter,
.commerce-off [data-shipmeter]{display:none !important;}

/* A Thai page linking to an English one says so. Settled 03/09/2026 (Paul): the Thai locale is
   nine pages and the nav points at English for the rest, which is honest only if the reader is
   told before they click rather than after. */
.en-tag{display:inline-block;margin-left:5px;font-size:var(--kicker-size);font-weight:var(--weight-semibold);letter-spacing:var(--nav-tracking);
  padding:1px 4px;border:1px solid currentColor;border-radius:3px;opacity:.55;vertical-align:middle;}
