/* ============================================================
   PUKKR — design system
   Skeleton per Jacob's rules, with the Shapes (Shopify) read on top:
   announcement bar → fixed header → full-bleed hero → scrolling
   marquee → content sections → tight footer.
   Shapes contributes the bold type, the rounded blocks and the flat
   colour fields. Superior Nut contributes the mechanics.
   ============================================================ */

:root {
  /* ---- THE NINE. Sampled off the can. Nothing outside this list. ---- */
  --brine:   #F6F1DE;   /* page ground — the can's own cream */
  --paper:   #FCF8EC;   /* panels, cards, alternating blocks */
  --sand:    #EDE3CB;   /* second ground: hero backdrop */
  --husk:    #E0D3B6;   /* dividers, quiet surfaces. never text */
  --dill:    #D9E4C9;   /* pale green block */
  --gherkin: #A9C08C;   /* mid green block */
  --lime:    #C6D94E;   /* the logo disc — badge, announcement bar */
  --pickle:  #1E4426;   /* the label green — wordmark, marquee, footer */
  --ink:     #15120C;   /* RETIRED 2026-09-10 — nothing on the page is black */
  --white:   #FFFFFF;   /* the lineup band only — brighter than Paper on purpose */

  /* ---- Roles. Pointers at the eight, not new colours. ---- */
  --ground: var(--brine);
  --text:   var(--pickle);
  --hair:   var(--husk);
  --mist:   var(--sand);

  /* Tints of Ink on Brine for de-emphasised text only. Not brand colours. */
  --smoke: #4F6149;   /* muted text — 6.0:1 on Brine */
  --ash:   #869381;   /* lowest emphasis — never body copy */

  --gutter: 20px;
  --gutter-lg: 48px;
  --content: 1280px;
  --wide: 1600px;

  /* ONE radius and ONE shadow for the whole site. Shapes is a rounded theme, so
     unlike TRAFFIC and Superior Nut this brand takes a corner — but it takes
     exactly one, used everywhere. */
  --radius: 22px;
  --lift: 0 10px 22px -8px rgba(21,48,26,.26);

  --font:    "Outfit", ui-sans-serif, system-ui, sans-serif;
  --display: "Shantell Sans", "Outfit", ui-sans-serif, system-ui, sans-serif;
  --ease: cubic-bezier(0,0,0.2,1);

  /* Announcement bar height, read by the hero so its content clears the bar. */
  --announce-h: 38px;
}
@media (min-width: 1024px) { :root { --announce-h: 42px; } }

* { margin: 0; padding: 0; box-sizing: border-box; }
html { scroll-behavior: smooth; }
@media (prefers-reduced-motion: reduce) { html { scroll-behavior: auto; } }
body {
  font-family: var(--font);
  font-size: 16px; line-height: 1.6;
  color: var(--text); background: var(--brine);
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden; min-width: 0;
}
@media (min-width: 1024px) { body { font-size: 17px; line-height: 1.62; } }
img { display: block; max-width: 100%; }
a { color: inherit; text-decoration: none; }
ul { list-style: none; }

.wrap { width: 100%; max-width: var(--content); margin: 0 auto; padding: 0 var(--gutter); }
.wrap-wide { width: 100%; max-width: var(--wide); margin: 0 auto; padding: 0 var(--gutter); }
@media (min-width: 1024px) { .wrap, .wrap-wide { padding: 0 var(--gutter-lg); } }

/* ---------- Type scale (mobile / desktop pairs) ---------- */
.t-hero  { font-size: 46px; line-height: .96; letter-spacing: 0; font-weight: 800; text-transform: uppercase; }
.t-h1    { font-size: 32px; line-height: 1.04; letter-spacing: 0; font-weight: 800; text-transform: uppercase; }
.t-h2    { font-size: 26px; line-height: 1.08; letter-spacing: 0; font-weight: 800; text-transform: uppercase; }
.t-h3    { font-size: 18px; line-height: 1.2;  letter-spacing: .02em; font-weight: 500; }
.t-body-lg { font-size: 18px; line-height: 1.55; }
.t-small { font-size: 14px; line-height: 1.5; }
.t-label { font-size: 11px; line-height: 1.2; letter-spacing: .18em; font-weight: 500; text-transform: uppercase; }
.t-label-lg { font-size: 12px; line-height: 1.2; letter-spacing: .18em; font-weight: 500; text-transform: uppercase; }
@media (min-width: 1024px) {
  .t-hero { font-size: 104px; line-height: .9; }
  .t-h1   { font-size: 54px; line-height: 1.0; }
  .t-h2   { font-size: 36px; line-height: 1.04; }
  .t-h3   { font-size: 22px; }
  .t-body-lg { font-size: 22px; line-height: 1.5; }
  .t-label-lg { font-size: 14px; }
}
/* Every big display line is set in the label face — hero, h1, h2, the statement
   and both wordmarks. Body copy, labels and t-h3 stay in Outfit. Same split
   Superior Nut runs between Fraunces and Outfit. */
.t-hero, .t-h1, .t-h2, .statement, .foot-mark, .step .num, .door-cat,
.marquee-item > span:last-child {
  font-family: var(--display);
  font-variation-settings: "BNCE" 0, "INFM" 0, "SPAC" 0;
}
.smoke { color: var(--smoke); }
.prose { max-width: 65ch; }

/* ---------- Buttons: pills, no shadow ---------- */
.btn {
  display: inline-flex; align-items: center; justify-content: center;
  min-height: 48px; min-width: 164px; padding: 0 22px; white-space: nowrap;
  font-size: 14px; letter-spacing: .16em; font-weight: 500; text-transform: uppercase;
  border: 1px solid var(--text); background: var(--text); color: var(--brine);
  border-radius: 999px;
  transition: color .25s var(--fill-ease), translate .2s var(--ease);
  cursor: pointer; font-family: var(--font);
  position: relative; overflow: hidden; isolation: isolate;
  --fill: var(--ground, var(--brine)); --fill-label: var(--text);
  --fill-ease: cubic-bezier(.104,.204,.492,1);
}
/* Fill-on-hover: a panel parked below the button at 6deg, swinging flat as it rises. */
.btn::before {
  content: ""; display: block; position: absolute;
  top: 0; bottom: 0; left: -5%; width: 125%; height: 100%;
  background: var(--fill); z-index: -1; border-radius: inherit;
  transform-origin: left bottom; backface-visibility: hidden; will-change: transform;
  transform: rotate3d(0,0,1,6deg) translate3d(-1.2em, 110%, 0);
  transition: transform .25s var(--fill-ease);
}
.btn:hover::before, .btn:focus-visible::before { transform: rotate3d(0,0,1,0deg) translateZ(0); }
.btn:hover, .btn:focus-visible { color: var(--fill-label); translate: 0 -2px; }
@media (prefers-reduced-motion: reduce) { .btn::before { transition: none; } .btn:hover { translate: none; } }
.btn-secondary { background: transparent; color: var(--text); --fill: var(--text); --fill-label: var(--brine); }
/* The one hero CTA. Bigger than the site default because it is carrying the
   whole screen on its own — there is no second button beside it. */
.btn-hero { min-height: 60px; min-width: 224px; font-size: 18px; padding: 0 34px;
            background: var(--cta-bg, var(--lime));
            color: var(--cta-fg, var(--pickle));
            /* NO BORDER. The other buttons keep their hairline, but this one's
               border sat outside the rising fill, so hovering left a lime ring
               around the green. box-sizing is border-box, so dropping it does
               not change the pill's size. */
            border: 0;
            --fill: var(--cta-fill, var(--pickle)); --fill-label: var(--cta-bg, var(--lime)); }

/* Lime on a Lime ground would vanish, so that one hero flips the pair. */
.hero-lime  { --cta-bg: var(--pickle); --cta-fg: var(--lime); --cta-fill: var(--brine); }
/* The hero rules above raise specificity on `color`, so the hover label has to
   be restated or it keeps its resting colour and vanishes into the fill. */
.btn-hero:hover, .btn-hero:focus-visible { color: var(--fill-label); }
@media (min-width: 1024px) { .btn-hero { min-height: 66px; min-width: 252px; font-size: 19px; } }


/* ---------- Shop Now: the button fills like a poured can ----------
   Option D, chosen 2026-09-10 from five in button-options.html. The site's other
   buttons use the tilted panel that swings up flat; this one is the hero's only
   call to action, so it earns its own mechanism.

   The liquid arrives from the left on a tilt and LEVELS OFF as it fills, the way
   a can poured at an angle settles. Two details carry it:

   1. The tilt lives on the `rotate` property, not inside `transform`, so the
      levelling and the rise are independent and neither overwrites the other.
   2. THE DRAIN IS ITS OWN TRANSITION, not the pour played backwards — pouring
      and draining are not the same action, and a symmetrical one feels broken.
      The fast values sit on the RESTING rule and the slow ones on :hover, which
      is what makes it fill in half a second and empty in a fifth of that.

   The element is wider than the button so the angled surface sweeps past both
   sides instead of showing its own corners. */
.btn-hero { overflow: hidden; transition: color .3s .14s var(--ease), translate .2s var(--ease); }
.btn-hero::before {
  top: auto; bottom: 0; left: -30%; width: 160%; height: 190%;
  background: var(--cta-fill, var(--pickle));
  border-radius: 50% 40% 0 0 / 40px 22px 0 0;
  transform-origin: 0% 100%;
  transform: translate3d(0, 100%, 0);
  rotate: 10deg;
  transition: transform .22s cubic-bezier(.4,0,.9,.4), rotate .22s var(--ease);
}
.btn-hero:hover::before, .btn-hero:focus-visible::before {
  transform: translate3d(0, 12%, 0);
  rotate: 0deg;
  transition: transform .5s cubic-bezier(.2,.9,.3,1), rotate .62s cubic-bezier(.2,.9,.3,1);
}
/* Carbonation. The bubbles take their colour from the button's resting ground,
   which is always the opposite of what is pouring in, so they read against the
   liquid on every hero variant without a second rule: Lime bubbles in the green
   fill, Pickle bubbles in the cream one.
   They start a beat after the pour so they rise THROUGH liquid that is already
   there, rather than through empty button. */
.btn-hero::after {
  content: ""; position: absolute; inset: 0; z-index: -1; pointer-events: none;
  opacity: 0; background-repeat: no-repeat;
  background-image:
    radial-gradient(circle 3.5px at 17% 88%, var(--cta-bubble, var(--cta-bg, var(--lime))) 98%, transparent 100%),
    radial-gradient(circle 2.5px at 34% 97%, var(--cta-bubble, var(--cta-bg, var(--lime))) 98%, transparent 100%),
    radial-gradient(circle 3px   at 52% 86%, var(--cta-bubble, var(--cta-bg, var(--lime))) 98%, transparent 100%),
    radial-gradient(circle 2px   at 68% 98%, var(--cta-bubble, var(--cta-bg, var(--lime))) 98%, transparent 100%),
    radial-gradient(circle 3px   at 84% 90%, var(--cta-bubble, var(--cta-bg, var(--lime))) 98%, transparent 100%);
}
.btn-hero:hover::after, .btn-hero:focus-visible::after { animation: btn-bubbles 1.7s ease-out .3s infinite; }
@keyframes btn-bubbles {
  0%   { opacity: 0;  translate: 0 16%; }
  20%  { opacity: .8; }
  70%  { opacity: .55; }
  100% { opacity: 0;  translate: 0 -60%; }
}

@media (prefers-reduced-motion: reduce) {
  .btn-hero::before { transition: none; }
  .btn-hero:hover::before, .btn-hero:focus-visible::before { rotate: 0deg; transform: translate3d(0, 12%, 0); }
  .btn-hero::after { display: none; }
}

/* Link hover: the label fades back. Header nav uses the roll instead. */
.ul { display: inline-block; transition: opacity .18s var(--ease); }
.ul:hover, .ul:focus-visible { opacity: .55; }
@media (prefers-reduced-motion: reduce) { .ul { transition: none; } }

/* ---------- Header nav: the logo's own underline, drawn in ----------
   Replaces the roll. The mark is the swoosh from under the PUKKR wordmark.

   IT IS A STROKED LINE, NOT A FILLED SHAPE. The first version traced the badge
   artwork as an outline, which tapers to a point at both ends — that is how the
   original vector is built, and it read as a brush mark rather than as the
   logo's line. This is a single curve given a uniform weight and round caps, so
   it is the same thickness end to end and finishes with a dome, not a point.

   THE WEIGHT IS SET IN USER UNITS, NOT PIXELS, and that is deliberate. The mask
   box is a fixed 11px tall on every link, so the SVG's vertical scale is always
   11/16 whatever the label's width — which means 6.7 user units always lands at
   4.6 rendered pixels, on SHOP and on STOCKISTS alike. (`vector-effect:
   non-scaling-stroke` looks like the right tool here and is not: inside a mask
   image it resolves against the wrong coordinate system and collapses the line
   to half a pixel. Measured, not guessed.)

   The reveal is a clip from the left rather than a growing width, which would
   squash the curve instead of drawing it.

   It is a MASK painted with currentColor, so it inverts with the nav over a dark
   hero exactly as the labels do. */
.nav .ul { position: relative; overflow: visible; padding: 0; transition: none; }
.nav .ul:hover, .nav .ul:focus-visible { opacity: 1; }
.nav .ul::after {
  content: ""; position: absolute; left: -3px; right: -3px; bottom: -9px; height: 11px;
  background-color: currentColor;
  -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 116 16' preserveAspectRatio='none'%3E%3Cpath d='M2 9C22 4 94 4 114 9' fill='none' stroke='%23000' stroke-width='6.7' stroke-linecap='round'/%3E%3C/svg%3E") no-repeat center / 100% 100%;
          mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 116 16' preserveAspectRatio='none'%3E%3Cpath d='M2 9C22 4 94 4 114 9' fill='none' stroke='%23000' stroke-width='6.7' stroke-linecap='round'/%3E%3C/svg%3E") no-repeat center / 100% 100%;
  clip-path: inset(0 100% 0 0);
  transition: clip-path .15s cubic-bezier(.5,0,1,1);           /* RETRACT — fast */
  will-change: clip-path;
}
.nav .ul:hover::after, .nav .ul:focus-visible::after {
  clip-path: inset(0 0 0 0);
  transition: clip-path .3s var(--ease);                       /* DRAW — slower */
}
@media (prefers-reduced-motion: reduce) {
  .nav .ul::after { transition: none; }
}

/* ---------- The mascot ----------
   The pickle character off the can label, held as a single ALPHA MASK rather
   than a coloured picture: the shape comes from the file, the colour from
   `currentColor`, so one 18KB asset paints Pickle on the light bands and Brine
   on the dark footer with no second file and no filter hacks.
   This base rule is what gives every .mascot on the page its shape — the size
   and colour rules elsewhere are useless without it. */
.mascot {
  display: block; aspect-ratio: 323 / 419; background-color: currentColor;
  -webkit-mask: url("assets/mascot.png") center / contain no-repeat;
          mask: url("assets/mascot.png") center / contain no-repeat;
}
/* Sprinkled decoration: he leans into a band, never into the reading column. */
.mascot-deco { position: absolute; z-index: 0; pointer-events: none; color: var(--gherkin); }
/* A tiny word riding beside the corner character. The wrapper holds the tilt so
   that the spin inside it can stay a clean 0-to-360; putting both on one element
   would mean writing the rest angle into the keyframes. */
.deco-word { position: absolute; z-index: 0; pointer-events: none; rotate: -7deg; transform-origin: 0% 50%; }
.deco-word-in {
  display: inline-block;
  font-family: var(--display); font-weight: 800; text-transform: uppercase;
  font-size: 14.6px; line-height: 1; letter-spacing: .01em; color: var(--pickle);
  transform-origin: 50% 50%; will-change: transform;
}
.deco-word-in.is-spinning { animation: doodle-spin 1.2s cubic-bezier(.22,1,.36,1) both; }
@media (max-width: 1199px) { .deco-word { display: none; } }
@media (max-width: 1199px) { .mascot-deco { display: none; } }

/* ---------- Announcement bar ----------
   Rides at the top of the fixed stack, above the header row, and paints its own
   ground so the header's transparent/solid swap never touches it. */
.announce {
  height: var(--announce-h); display: flex; align-items: center; overflow: hidden;
  background: var(--lime); color: var(--pickle);
}
/* Reads the SAME custom property the pacing script writes. It used to read
   --announce-duration, which the script never set, so the bar silently ran on
   the hardcoded fallback and ignored its speed setting entirely. */
.announce-track { display: flex; width: max-content; will-change: transform;
                  animation: marquee-reverse var(--marquee-duration, 46s) linear infinite; }
.announce-track[data-paused] { animation-play-state: paused; }
.announce-copy { display: flex; align-items: center; flex-shrink: 0; gap: 22px; padding-right: 22px; }
@media (min-width: 1024px) { .announce-copy { gap: 30px; padding-right: 30px; } }
.announce-item { display: flex; align-items: center; gap: 22px; white-space: nowrap; flex-shrink: 0;
                 font-size: 11px; letter-spacing: .18em; font-weight: 500; text-transform: uppercase; }
@media (min-width: 1024px) { .announce-item { font-size: 12px; gap: 30px; } }
/* The mascot is the separator between lines, so the bar is branded rather than
   punctuated with a bullet. */
.announce-item .mascot { width: 13px; flex-shrink: 0; opacity: .85; }
@media (min-width: 1024px) { .announce-item .mascot { width: 15px; } }


/* ---------- The badge ----------
   The sticker logo, rebuilt as inline SVG: lime disc, hand-drawn caps in Pickle,
   the underline swoosh. Sized by its container, so the same markup serves the
   header, the footer and anywhere else it turns up.
   NOTE: the letterforms are Shantell Sans standing in for the real hand
   lettering. Supply the vector artwork and swap the <text> for its path. */
.badge { display: block; width: 100%; height: auto; }
.badge-disc { fill: var(--lime); }
.badge-ink  { fill: var(--pickle); }
.badge text { font-family: var(--display); font-weight: 800; text-anchor: middle; fill: var(--pickle); }

/* ---------- Header: fixed, transparent over the hero, solid past the headline ---------- */
.header {
  position: fixed; inset: 0 0 auto 0; z-index: 50;
  color: var(--nav-fg, var(--brine));
  transition: background-color .28s var(--ease), color .28s var(--ease), border-color .28s var(--ease);
}
/* Once it goes solid the bar is Pickle green and stays Pickle green. It used to
   take the colour of whichever band it was crossing, which is what made it
   near-black over the hero's own dark ground. Cream labels need a dark bar. */
.header[data-solid], .header[data-menu-open] {
  background: var(--pickle);
  color: var(--brine);
  border-bottom: 1px solid rgba(246,241,222,.16);
}
.header-row {
  display: grid; grid-template-columns: 1fr auto 1fr; align-items: center; gap: 12px;
  width: 100%; max-width: var(--content); margin: 0 auto; padding: 10px var(--gutter);
}
@media (min-width: 640px)  { .header-row { gap: 24px; padding: 12px var(--gutter); } }
@media (min-width: 1024px) { .header-row { padding: 14px var(--gutter-lg); } }

/* Wordmark is live text in the display face, never a logo file, so it inverts. */
.wordmark { grid-column: 2; display: block; width: 58px; justify-self: center; line-height: 0;
            transition: rotate .3s var(--ease), scale .3s var(--ease); }
@media (min-width: 1024px) { .wordmark { width: 74px; } }
/* A sticker should behave like one: it tilts when you touch it. */
.wordmark:hover, .wordmark:focus-visible { rotate: -6deg; scale: 1.04; }
@media (prefers-reduced-motion: reduce) { .wordmark { transition: none; } .wordmark:hover { rotate: 0deg; scale: 1; } }

.nav { grid-column: 1; display: none; }
@media (min-width: 640px) { .nav { display: block; justify-self: start; min-width: 0; overflow: hidden; } }
.nav ul { display: flex; gap: 14px; }
@media (min-width: 1024px) { .nav ul { gap: 24px; } }
.nav a { padding: 4px 0; font-size: 12px; letter-spacing: .18em; font-weight: 500; text-transform: uppercase; }
@media (min-width: 1024px) { .nav a { font-size: 14px; } }
.nav a, .mobile-nav a { white-space: nowrap; }

.util { grid-column: 3; display: flex; align-items: center; justify-self: end; margin-right: -12px; }
.util a { display: flex; width: 48px; height: 48px; align-items: center; justify-content: center; }
.util svg { width: 25px; height: 25px; transition: scale .2s var(--ease); transform-origin: 50% 50%; }
.util a:hover svg { scale: 1.25; animation: util-shake .42s var(--ease); }
@keyframes util-shake {
  0% { rotate: 0deg; } 18% { rotate: -9deg; } 36% { rotate: 7deg; }
  54% { rotate: -5deg; } 72% { rotate: 3deg; } 86% { rotate: -1.5deg; } 100% { rotate: 0deg; }
}
@media (prefers-reduced-motion: reduce) { .util a:hover svg { animation: none; } }
.header .nav a, .header .util a { color: var(--nav-fg, var(--brine)); }
/* Labels are cream in both states: transparent over the hero, and on the green
   bar once it goes solid. */
.header.on-dark:not([data-solid]) { --nav-fg: var(--brine); }

.menu-btn {
  grid-column: 1; grid-row: 1; justify-self: start; margin-left: -12px;
  display: flex; width: 48px; height: 48px; align-items: center; justify-content: center;
  background: none; border: 0; color: inherit; cursor: pointer;
}
.menu-btn svg { width: 25px; height: 25px; }
@media (min-width: 640px) { .menu-btn { display: none; } }
.mobile-nav { border-top: 1px solid var(--hair); background: var(--paper); color: var(--text); }
.mobile-nav[hidden] { display: none; }
@media (min-width: 640px) { .mobile-nav { display: none !important; } }
.mobile-nav a { display: block; padding: 15px var(--gutter); font-size: 13px; letter-spacing: .18em; font-weight: 500; text-transform: uppercase; }

/* ---------- Hero: full-bleed sunlit scene, 100svh, the can floating in it ----------
   LIGHT HERO, the same variant Superior Nut runs: the scene is bright sand, so
   the type is ink rather than paper and there are no darkening scrims.
   The photograph is assets/shots/diner-enamel-b.webp, set on .hero > img.
   STILL OUTSTANDING: heroes should be supplied twice, desktop and mobile. There
   is no mobile framing yet, so phones crop hard into the 16:9 shot. */
/* The hero ground is a VARIANT, not a fixed colour. Every variant sets the same
   four things — the ground, the type colour, the shadow the can throws, and how
   the eyebrow sits back — so swapping the class is the only edit needed and
   nothing downstream has to be re-tuned. See hero-colors.html for all four side
   by side. */
.hero {
  position: relative; width: 100%; overflow: hidden; height: 100svh;
  --ground: var(--hero-bg, var(--sand));
  --hero-bg: var(--sand);
  --hero-fg: var(--pickle);
  --hero-quiet: var(--smoke);
  --hero-cast: rgba(78,58,26,.66);
  --hero-drop: rgba(78,58,26,.34);
  background: var(--hero-paint, var(--hero-bg));
  color: var(--hero-fg);
}
/* Sand — the sunlit scene the product photography was shot in. */
.hero-sand {
  --hero-bg: var(--sand);
  --hero-paint:
    radial-gradient(120% 90% at 18% 10%, rgba(255,251,236,.95) 0%, rgba(255,251,236,0) 55%),
    radial-gradient(110% 80% at 92% 96%, rgba(150,124,78,.30) 0%, rgba(150,124,78,0) 60%),
    linear-gradient(168deg, #F3E9CF 0%, #EBDFC1 46%, #DFCFA9 100%);
}
/* Pickle — the label green. The can body is cream, so it cuts out hard against
   this and the hero reads as packaging rather than as a photograph. */
.hero-green {
  --hero-grain: .12;
  --hero-scrim: rgba(0,0,0,.22);
  --hero-bg: var(--pickle);
  --hero-fg: var(--brine);
  --hero-quiet: rgba(246,241,222,.72);
  --hero-cast: rgba(4,14,7,.78);
  --hero-drop: rgba(4,14,7,.48);
  --hero-paint:
    radial-gradient(120% 90% at 22% 8%, rgba(120,168,110,.30) 0%, rgba(120,168,110,0) 58%),
    radial-gradient(100% 80% at 88% 96%, rgba(5,16,8,.45) 0%, rgba(5,16,8,0) 62%),
    var(--pickle);
}
/* Paper — the cleanest of the four, and the closest to the Shapes theme. */
.hero-white {
  --hero-bg: #FFFFFF;
  --hero-fg: var(--pickle);
  --hero-quiet: var(--smoke);
  --hero-cast: rgba(30,46,24,.42);
  --hero-drop: rgba(30,46,24,.24);
  --hero-paint: radial-gradient(100% 80% at 84% 92%, rgba(200,217,79,.22) 0%, rgba(200,217,79,0) 60%), #FFFFFF;
}
/* Lime — the logo disc blown up to fill the screen. The loudest option. */
.hero-lime {
  --hero-bg: var(--lime);
  --hero-fg: var(--pickle);
  --hero-quiet: rgba(30,68,38,.72);
  --hero-cast: rgba(52,64,14,.58);
  --hero-drop: rgba(52,64,14,.34);
  --hero-paint: radial-gradient(110% 85% at 20% 6%, rgba(226,240,130,.85) 0%, rgba(226,240,130,0) 55%), var(--lime);
}
.hero.sub { height: 60svh; min-height: 60svh; }
.hero > img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
/* Grain, so the drawn backdrop reads as a surface rather than a gradient. */
.hero .grain {
  position: absolute; inset: 0; pointer-events: none; opacity: var(--hero-grain, .2); mix-blend-mode: multiply;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='3'/%3E%3C/filter%3E%3Crect width='160' height='160' filter='url(%23n)'/%3E%3C/svg%3E");
}
/* Short top gradient so the header stays legible against the brightest corner. */
.hero .scrim-top { position: absolute; inset: 0 0 auto 0; height: 150px; background: linear-gradient(to bottom, var(--hero-scrim, rgba(120,98,60,.14)), transparent); }

.hero-content {
  position: relative; height: 100%; display: flex; align-items: center;
  padding: calc(var(--announce-h) + 56px) var(--gutter) 40px; color: var(--hero-fg);
}
@media (min-width: 1024px) { .hero-content { padding: calc(var(--announce-h) + 64px) var(--gutter-lg) 48px; } }
.hero-inner {
  width: 100%; max-width: var(--content); margin: 0 auto;
  display: grid; gap: 4px; justify-items: center; text-align: center; align-content: center;
  max-height: 100%; min-height: 0;
}
.hero-copy { display: flex; flex-direction: column; gap: 16px; align-items: inherit; }
.hero .t-hero { max-width: 9ch; }
.hero p { max-width: 46ch; font-size: 15px; }
@media (min-width: 640px)  { .hero p { font-size: 16px; } }
@media (min-width: 1024px) { .hero p { font-size: 18px; } }
.hero p.eyebrow { max-width: none; font-size: 11px; color: var(--hero-quiet); }
@media (min-width: 1024px) { .hero p.eyebrow { font-size: 12px; } }
.hero-cta { margin-top: 8px; }
@media (min-width: 1024px) {
  .hero-inner { grid-template-columns: 1.05fr .95fr; align-items: center; justify-items: start; text-align: left; gap: 24px; }
  .hero-copy { align-items: flex-start; }
}

/* The product, floating. A slow bob with a matching shadow that widens and
   fades as the can rises, so the two read as one object and its cast rather
   than a picture that happens to move. */
.hero-can { position: relative; width: min(18svh, 44vw); justify-self: center; }
@media (min-width: 1024px) { .hero-can { width: min(32svh, 26vw); } }
.hero-can .can-art { position: relative; z-index: 2; animation: can-float 6.5s ease-in-out infinite; }
.hero-can .can-cast {
  position: absolute; left: 54%; bottom: -7%; translate: -50% 0; z-index: 1;
  width: 132%; aspect-ratio: 4.6/1; border-radius: 50%;
  background: radial-gradient(closest-side,
      var(--hero-cast) 0%, var(--hero-cast) 34%, transparent 82%);
  animation: cast-float 6.5s ease-in-out infinite;
}
@keyframes can-float {
  0%, 100% { translate: 0 0;     rotate: -0.7deg; }
  50%      { translate: 0 -11px; rotate: 0.7deg; }
}
@keyframes cast-float {
  0%, 100% { scale: .97 1.05; opacity: 1; }
  50%      { scale: 1.1 .86;  opacity: .76; }
}
@media (prefers-reduced-motion: reduce) {
  .hero-can .can-art, .hero-can .can-cast { animation: none; }
}
/* The can throws a short hard cast of its own, matching the scene's light. */
.can-art { width: 100%; height: auto; display: block; }
.hero-can .can-art { filter: drop-shadow(4px 8px 6px var(--hero-drop)) drop-shadow(14px 22px 18px var(--hero-drop)) drop-shadow(30px 46px 40px var(--hero-drop)); }


/* ---------- The hero cans: three, where one used to stand ----------
   Chosen 2026-09-10 from four arrangements in hero-cans.html.

   ONE RULE, THREE SETS OF NUMBERS. Every can is the same element driven by five
   custom properties — height, overlap, lift, tilt and float phase — so changing
   the arrangement means changing numbers, never CSS.

   CANS ARE SIZED BY HEIGHT, NOT WIDTH. A can is 2.2x taller than it is wide and
   the hero's constraint is vertical, so width-based sizing looked right at one
   window and ran off the bottom edge at every other. Heights in svh hold at any
   window; overlap is a fraction of each can's own height so it scales with them.

   EACH CAN BOBS ON ITS OWN PHASE. Three cans rising and falling together read as
   one object cut into three; offset, they read as three objects.

   PLACEHOLDER: all three are the Original, the only product photography that
   exists. Supply the other two flavours and they swap in with no layout change. */
.cans { position: relative; display: flex; align-items: flex-end; justify-content: center; width: 100%; }
.can {
  position: relative; flex: 0 0 auto;
  height: var(--h); margin-left: calc(var(--h) * var(--overlap, 0));
  translate: 0 var(--lift, 0); rotate: var(--tilt, 0deg);
  z-index: var(--z, 1);
  animation: can-float 6.5s ease-in-out infinite; animation-delay: var(--phase, 0s);
}
.can img {
  height: 100%; width: auto; display: block;
  filter: drop-shadow(4px 8px 6px var(--hero-drop)) drop-shadow(14px 22px 18px var(--hero-drop));
}
.can .cast {
  position: absolute; left: 54%; bottom: -3%; translate: -50% 0; z-index: -1;
  width: 130%; aspect-ratio: 4.6/1; border-radius: 50%;
  background: radial-gradient(closest-side, var(--hero-cast) 0%, var(--hero-cast) 34%, transparent 82%);
  animation: cast-float 6.5s ease-in-out infinite; animation-delay: var(--phase, 0s);
}
/* LINEUP: the copy sits centred above and the row spreads across the width, so
   the hero reads as a range rather than as one product. Stacked, which means the
   type and the cans share one vertical budget — roughly 28svh of copy leaves the
   cans about 45, and those are the numbers below. */
/* The three cans stand exactly where the single can stood: the right-hand column
   of the hero's two-column grid. Nothing about the copy moves — same left
   alignment, same headline size, same single call to action. */
/* ALL THREE ARE THE SAME SIZE, SIT ON THE SAME BASELINE AND MOVE TOGETHER.
   Size, lift and tilt are all identical now; only the stacking order differs, so
   the middle can laps the two beside it. The float phases are synced as well —
   staggering them was what broke the flush bottom edge, because three cans on
   different parts of the cycle are at three different heights at any instant. */
.hero-cluster .c1 { --h: 50svh; --lift: 0; --tilt: 0deg; --z: 1; --phase: 0s; }
.hero-cluster .c2 { --h: 50svh; --lift: 0; --tilt: 0deg; --z: 3; --phase: 0s; --overlap: -.16; }
.hero-cluster .c3 { --h: 50svh; --lift: 0; --tilt: 0deg; --z: 2; --phase: 0s; --overlap: -.16; }
@media (max-width: 1023px) {
  /* Stacked on a phone, so the row gets a modest share of the screen. */
  .can { --h: 28svh; --overlap: -.14; }
}
@media (prefers-reduced-motion: reduce) { .can, .can .cast { animation: none; } }

/* Eyebrow: middle dots on desktop, stacked parts on phones. */
.eyebrow { font-size: 11px; letter-spacing: .18em; font-weight: 500; text-transform: uppercase; }
.eyebrow .dot { margin: 0 6px; display: none; }
.eyebrow span.part { display: block; }
@media (min-width: 640px) { .eyebrow span.part { display: inline; } .eyebrow .dot { display: inline; } }

/* ---------- Photograph hero ----------
   The full-bleed shot, with the type laid over it. The can rig above is left in
   place but unused while this is live; putting the drawn cans back is a matter
   of swapping the markup, not restoring CSS.

   The photograph is dark on the left and bright on the right, so the type runs
   cream and the CTA flips to Lime. The wash is a LEFT-WEIGHTED gradient, not a
   blanket scrim: it lifts legibility exactly where the words are and leaves the
   cans, the plate and the counter untouched. */
.hero-shot {
  --hero-paint: none;
  --hero-bg: #101A12;
  --hero-fg: var(--brine);
  --hero-quiet: rgba(246,241,222,.78);
  --hero-cast: rgba(0,0,0,.5);
  --hero-drop: rgba(0,0,0,.35);
  /* Lime button, and the pour is Pickle rather than cream: the label flips to
     Lime as the green rises, and the bubbles are Lime too since they take the
     button's resting ground. */
  --cta-bg: var(--lime); --cta-fg: var(--pickle); --cta-fill: var(--pickle);
}
.hero-shot > img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; z-index: 0; }
.hero-shot .wash {
  position: absolute; inset: 0; z-index: 1; pointer-events: none;
  background: linear-gradient(to right, rgba(8,18,10,.62) 0%, rgba(8,18,10,.34) 34%, transparent 58%);
}
.hero-shot .hero-content { position: relative; z-index: 2; }
.hero-shot .hero-inner { grid-template-columns: 1fr; justify-items: start; text-align: left; }
/* The copy sits on the photograph's left edge, vertically centred. The width is
   held to a third of the frame and the headline to 76px: sampling the shot for
   brightness and local contrast, the near-black tile runs out at about a third
   of the frame width, and past that the type would be over the tipped can. */
.hero-shot .hero-copy { max-width: 34%; align-items: flex-start; }
@media (min-width: 1024px) {
  .hero-shot .t-hero { font-size: 76px; line-height: .95; max-width: 8ch; }
  .hero-shot .hero-copy > p:not(.eyebrow) { font-size: 16px; }
}
/* The wash is heavier on this shot than the options page used, because the type
   now sits over near-black tile and has to read as deliberate rather than dim. */
.hero-shot .wash {
  background: linear-gradient(to right, rgba(8,18,10,.72) 0%, rgba(8,18,10,.44) 30%, transparent 54%);
}
@media (max-width: 1023px) {
  /* Portrait crops a 16:9 frame hard. The cans sit on the right of the shot, so
     the crop is biased that way to keep them in view, and the wash turns
     top-down because the copy now sits above them rather than beside them. */
  .hero-shot > img { object-position: 74% center; }
  .hero-shot .hero-copy { max-width: 100%; }
  .hero-shot .wash {
    background: linear-gradient(to bottom, rgba(8,18,10,.72) 0%, rgba(8,18,10,.44) 46%, rgba(8,18,10,.20) 100%);
  }
}

/* ---------- Marquee: one row, fixed band height, seamless CSS loop ---------- */
.marquee {
  display: flex; align-items: center; width: 100%; overflow: hidden;
  height: 67px; background: var(--band-bg, var(--pickle)); color: var(--band-fg, var(--brine));
}
/* Under a Pickle hero the strip has to be a different colour or there is no band
   there at all. Lime is the logo disc, so it belongs to the brand already. */
.marquee.band-lime { --band-bg: var(--lime); --band-fg: var(--pickle); --band-accent: var(--brine); }
@media (min-width: 1024px) { .marquee { height: 100px; } }
.marquee-track { display: flex; width: max-content; will-change: transform; animation: marquee-reverse var(--marquee-duration, 95s) linear infinite; }
.marquee-track[data-paused] { animation-play-state: paused; }
.marquee-copy { display: flex; align-items: center; flex-shrink: 0; gap: 40px; padding-right: 40px; }
@media (min-width: 1024px) { .marquee-copy { gap: 72px; padding-right: 72px; } }
.marquee-item { display: flex; align-items: center; gap: 14px; white-space: nowrap; flex-shrink: 0; }
/* Set in the label face, not the body face: at this size the claims read as the
   brand talking rather than as a row of certification badges. */
.marquee-item > span:last-child {
  font-weight: 800; text-transform: uppercase;
  font-size: 21px; letter-spacing: .01em; line-height: 1;
}
@media (min-width: 1024px) { .marquee-item { gap: 20px; } .marquee-item > span:last-child { font-size: 32px; } }
/* Every third claim comes up in Lime, so the row has a beat instead of running
   as one undifferentiated line of cream. */
.marquee-item:nth-child(3n+2) > span:last-child { color: var(--band-accent, var(--lime)); }
/* The mascot separates the claims and bobs as he goes past. Alternating delay
   and facing stop the row reading as one rubber-stamped element repeated. */
.marquee-item .mascot { width: 30px; flex-shrink: 0; color: var(--band-accent, var(--lime)); animation: mascot-bob 2.6s ease-in-out infinite; }
@media (min-width: 1024px) { .marquee-item .mascot { width: 46px; } }
.marquee-item:nth-child(even) .mascot { animation-delay: -1.3s; }
.marquee-item:nth-child(3n) .mascot { color: var(--band-fg, var(--brine)); }
@keyframes mascot-bob {
  0%, 100% { translate: 0 0;    rotate: -5deg; }
  50%      { translate: 0 -6px; rotate: 5deg; }
}
@media (prefers-reduced-motion: reduce) { .marquee-item .mascot { animation: none; rotate: 0deg; } }
@keyframes marquee-reverse { from { transform: translateX(-50%); } to { transform: translateX(0); } }
@media (prefers-reduced-motion: reduce) {
  .marquee-track, .announce-track { animation: none; width: 100%; justify-content: center; }
  .marquee-copy:not(:first-child), .announce-copy:not(:first-child) { display: none; }
  .announce { justify-content: center; }
}

/* ---------- Section dividers ----------
   A divider is one strip carrying BOTH neighbouring colours: the element paints
   the section above, and a masked layer on top paints the section below. Doing
   it with a single element would leave the mask's transparent half showing the
   page ground rather than the section above it, which is wrong everywhere the
   two differ.

   The shape is a mask, so one shape serves every colour pair. --from is the
   section above, --to the section below. */
.divide { position: relative; height: var(--dh, 30px); background-color: var(--from); }
.divide::before {
  content: ""; position: absolute; inset: 0; background-color: var(--to);
  -webkit-mask-repeat: repeat-x; mask-repeat: repeat-x;
  -webkit-mask-position: bottom;  mask-position: bottom;
  -webkit-mask-size: var(--tile);  mask-size: var(--tile);
  -webkit-mask-image: var(--shape); mask-image: var(--shape);
}
/* The scalloped edge off the side of a crinkle-cut slice. */
.d-crinkle {
  --dh: 30px; --tile: 60px 30px;
  --shape: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 60 30'%3E%3Cpath d='M0 30V15Q7.5 2 15 15T30 15T45 15T60 15V30Z' fill='%23000'/%3E%3C/svg%3E");
}
/* One long wave across the full width — no tiling, so it never repeats. */
.d-wave {
  --dh: 42px; --tile: 100% 42px;
  --shape: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 1200 42' preserveAspectRatio='none'%3E%3Cpath d='M0 42V18C200 2 420 38 620 22S1000 0 1200 16v26z' fill='%23000'/%3E%3C/svg%3E");
}
.d-wave::before { -webkit-mask-repeat: no-repeat; mask-repeat: no-repeat; }
@media (max-width: 719px) { .d-crinkle { --dh: 20px; --tile: 40px 20px; } .d-wave { --dh: 28px; --tile: 100% 28px; } }

/* ---------- Sections ---------- */
/* Grounds run in a repeating rhythm set by the top of the page, and every band
   declares its own so the header colour-matching script reads it correctly:
     hero photograph · marquee Pickle · the lineup White · statement Paper ·
     how we stack up Brine · standards Paper · how it's made Brine · find us Paper ·
     footer Pickle (the one dark band, and not a section). */
.section { padding: 32px 0; position: relative; }
@media (min-width: 1024px) { .section { padding: 48px 0; } }
.section.tight { padding: 30px 0 40px; }
@media (min-width: 1024px) { .section.tight { padding: 48px 0 64px; } }
.ground-brine { background: var(--brine); --ground: var(--brine); }
.ground-paper { background: var(--paper); --ground: var(--paper); }
.ground-sand  { background: var(--sand);  --ground: var(--sand); }
.ground-white { background: var(--white); --ground: var(--white); }

.section-head { display: flex; align-items: flex-end; justify-content: space-between; gap: 24px; margin-bottom: 24px; }
@media (min-width: 1024px) { .section-head { margin-bottom: 32px; } }
.section-head .eyebrow { color: var(--smoke); margin-bottom: 16px; }

/* Shapes decoration: flat brand-colour discs drifting behind the content. One
   shape, one colour set, no gradients — the theme's whole vocabulary. */
.blob { position: absolute; border-radius: 50%; pointer-events: none; z-index: 0; }
.section > .wrap { position: relative; z-index: 1; }

/* Statement */
.statement { max-width: 22ch; line-height: 1.0; }
@media (min-width: 1024px) { .statement { font-size: 50px; } }
.statement-row { display: grid; gap: 32px; }
@media (min-width: 1024px) { .statement-row { grid-template-columns: 1.4fr 1fr; gap: 64px; align-items: end; } }

.section.statement-band { padding-top: 36px; }
@media (min-width: 1024px) { .section.statement-band { padding-top: 66px; } }

/* ---------- Reviews ----------
   The statement headline stays as the section's opening line; the quotes sit
   under it in three cards. Same one radius as everything else, and the cards
   take the page ground rather than a tint, so the band does not turn into a
   second colour block right after the lineup. */
/* No cap here: the headline carries its own measure via .statement, and a
   second limit on the wrapper was overriding it down to a third of the page. */
.review-head { margin-bottom: 24px; }
.review-head .eyebrow { margin-bottom: 16px; }
@media (min-width: 1024px) { .review-head { margin-bottom: 32px; } }
.review {
  display: flex; flex-direction: column; gap: 12px;
  padding: 22px 22px 20px; border-radius: var(--radius);
  background: var(--brine); border: 1px solid rgba(30,68,38,.14);
  transition: transform .24s var(--ease), box-shadow .24s var(--ease);
}
.review:hover { transform: translateY(-4px); box-shadow: var(--lift); }
@media (prefers-reduced-motion: reduce) { .review { transition: none; } .review:hover { transform: none; } }
.stars { display: flex; gap: 3px; color: var(--gherkin); }
.stars svg { width: 17px; height: 17px; }
.review blockquote { margin: 0; }
.review-lead { font-family: var(--display); font-weight: 800; font-size: 17px; line-height: 1.2; color: var(--pickle); }
@media (min-width: 1024px) { .review-lead { font-size: 19px; } }
.review-body { margin-top: 10px; font-size: 14.5px; line-height: 1.55; color: var(--smoke); }
.review figcaption { margin-top: auto; padding-top: 6px; font-size: 11px; letter-spacing: .18em; font-weight: 500; text-transform: uppercase; color: var(--pickle); }
.review figcaption span { color: var(--ash); }

/* ---------- Bordered grid: who drinks it ----------
   Hairlines are an 18% tint of Ink, not Husk: 1px is already the thinnest a
   border renders, so the weight has to come from contrast. */
.stats { display: grid; grid-template-columns: 1fr 1fr; gap: 0;
         border-top: 1px solid rgba(30,68,38,.22); border-left: 1px solid rgba(30,68,38,.22); }
@media (min-width: 1024px) { .stats { grid-template-columns: repeat(3, 1fr); } }
.stat { padding: 24px 20px; border-right: 1px solid rgba(30,68,38,.22); border-bottom: 1px solid rgba(30,68,38,.22); }
@media (min-width: 1024px) { .stat { padding: 38px 30px; } }
.stat .t-label { color: var(--smoke); margin-top: 12px; display: block; }
.serve-name { text-transform: none; }
/* Hover: the cell lifts off the grid. No colour change — it keeps the section's
   own ground, declared not inherited, so the lift reads as depth. The explicit
   background is what makes it opaque. */
.stats .stat {
  position: relative; background: var(--ground, var(--paper));
  transition: transform .24s var(--ease), box-shadow .24s var(--ease);
}
.stats .stat:hover { transform: translateY(-4px); z-index: 2; box-shadow: var(--lift); }
@media (prefers-reduced-motion: reduce) { .stats .stat { transition: none; } .stats .stat:hover { transform: none; } }

/* ---------- Spilled slices ----------
   The Superior Nut spill mechanism, carried over for pickle. A piece sits at an
   angle; on hover it grows a little and STRAIGHTENS BY A FRACTION OF ITS OWN
   ANGLE rather than to a fixed one, so a piece at 20 degrees and a piece at 5
   both move about the same visible amount. --untilt is that fraction: at .92 a
   piece unwinds 8% of its tilt.

   The layer is pointer-events:none so it never sits on top of a link, and each
   piece opts back in so it can be hovered. Cursor stays an arrow — they are not
   buttons.

   REUSABLE: drop a .spill block into any section and give each .spill-slice its
   own --h, --rot and corner. Art lives in assets/slices/. */
.spill { position: absolute; inset: 0; pointer-events: none; z-index: 0; --untilt: .92; }
/* Each piece hovers: a slow vertical bob on its own timing. The bob animates
   TRANSLATE ONLY — animating rotate would fight the piece's resting tilt, which
   lives on the `rotate` property. Scale and translate are separate properties,
   so the hover lift still composes on top of it. */
@keyframes slice-float {
  0%, 100% { translate: 0 0; }
  50%      { translate: 0 calc(var(--float-lift, 9px) * -1); }
}
.spill-slice {
  position: absolute; display: block; height: var(--h, 120px);
  width: auto; rotate: var(--rot, 0deg);
  animation: slice-float var(--float-dur, 6.2s) ease-in-out infinite;
  animation-delay: var(--float-delay, 0s);
  filter: drop-shadow(5px 8px 6px rgba(30,68,38,.20))
          drop-shadow(13px 19px 16px rgba(30,68,38,.13));
  pointer-events: auto; cursor: default;
  transition: scale .26s var(--ease), rotate .26s var(--ease), filter .26s var(--ease);
}
.spill-slice:hover {
  scale: 1.06;
  rotate: calc(var(--rot, 0deg) * var(--untilt));
  filter: drop-shadow(7px 11px 8px rgba(30,68,38,.30))
          drop-shadow(18px 26px 22px rgba(30,68,38,.19));
}
/* One piece can opt out of the cast. The hover rule also sets `filter`, so the
   override has to cover both states or the shadow reappears on hover. */
.spill-slice.no-cast, .spill-slice.no-cast:hover { filter: none; }

/* The review band's slices flip like tossed coins. The flip itself is driven
   from script rather than a CSS class, because toggling a class to replay it
   would restart the float animation with it and make the slice jump. A
   scripted animation on `transform` leaves the float's `translate` and the
   tilt's `rotate` alone, so all three run together. See index.html. */
@media (prefers-reduced-motion: reduce) {
  .spill-slice { transition: none; animation: none; }
  .spill-slice:hover { scale: none; rotate: var(--rot, 0deg); }
}
/* Below this the gutter is narrower than the pieces themselves, so they would
   land on the reading column. They come off rather than fight for space. */
@media (max-width: 1419px) { .spill { display: none; } }

/* The rail. A REAL horizontal scroll container rather than a transformed track:
   the arrows just call scrollBy, which means a trackpad swipe, the keyboard and
   a screen reader all work on it without another line of code, and scroll-snap
   lands it on a card edge every time instead of mid-quote. */
.review-rail {
  display: grid; grid-auto-flow: column; gap: 14px;
  grid-auto-columns: 100%;
  overflow-x: auto; overscroll-behavior-x: contain;
  scroll-snap-type: x mandatory;
  scrollbar-width: none; -ms-overflow-style: none;
  padding-bottom: 2px;
}
.review-rail::-webkit-scrollbar { display: none; }
.review-rail:focus-visible { outline: 2px solid var(--pickle); outline-offset: 4px; }
@media (min-width: 700px)  { .review-rail { grid-auto-columns: calc((100% - 14px) / 2); } }
@media (min-width: 1000px) { .review-rail { grid-auto-columns: calc((100% - 28px) / 3); } }
.review { scroll-snap-align: start; }

/* The arrows sit with the headline, not over the cards. */
.review-head { display: flex; align-items: flex-end; justify-content: space-between; gap: 24px; }
.rev-nav { display: flex; gap: 8px; flex-shrink: 0; }
.rev-arrow {
  display: flex; align-items: center; justify-content: center;
  width: 42px; height: 42px; border-radius: 50%;
  background: transparent; color: var(--pickle);
  border: 1.5px solid rgba(30,68,38,.34); cursor: pointer;
  transition: background-color .2s var(--ease), color .2s var(--ease), opacity .2s var(--ease);
}
.rev-arrow svg { width: 19px; height: 19px; }
.rev-arrow:hover:not(:disabled) { background: var(--pickle); color: var(--brine); border-color: var(--pickle); }
.rev-arrow:disabled { opacity: .3; cursor: default; }
@media (max-width: 699px) { .rev-nav { display: none; } }

/* The rating block, under the headline. The score is set in the body face:
   the display face made a number read as a joke rather than a figure. */
.rating { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 12px; margin-top: 18px; }
.stars-lg svg { width: 20px; height: 20px; }
.rating-score { font-size: 15px; color: var(--pickle); }
.rating-score strong { font-family: var(--font); font-weight: 700; font-size: 17px; }
.rating-source { width: 100%; font-size: 11px; letter-spacing: .16em; font-weight: 500; text-transform: uppercase; color: var(--ash); }

/* ---------- How we stack up ----------
   Built after the LesserEvil chart rather than the boxed-grid one: no outer
   border, hairlines only between rows, and our column carried by a soft tinted
   panel with rounded ends instead of a hard cell.

   THE PANEL IS ONE CONTINUOUS SHAPE, not a stack of tinted cells. It is painted
   by a single element sitting behind the grid, so the rounded top and bottom are
   real corners rather than two cells pretending. That also lets it run past the
   first and last rows the way the reference does.

   The tick is our own pickle rather than a borrowed thumbs-up, which is the one
   place this chart gets to sound like the brand. */
.stack { display: grid; grid-template-columns: 1.35fr .85fr .85fr; }
/* THE PANEL IS PAINTED ON THE CELLS, not drawn as one element behind them.
   A single spanning element is the obvious approach and it does not work here:
   a grid item placed explicitly in column 2 occupies those cells, and the
   auto-placed cells then flow AROUND it, which threw the badge into the wrong
   column. Tinting the cells themselves gives the same continuous panel, with
   the rounding carried by the first and last cell. */
.stack-head.stack-ours, .stack-ours { background: var(--dill); }
.stack-head.stack-ours { border-radius: var(--radius) var(--radius) 0 0; padding-top: 18px; }
.stack-ours.is-last { border-radius: 0 0 var(--radius) var(--radius); padding-bottom: 22px; }
.stack-head { display: flex; align-items: center; justify-content: center; padding: 6px 8px 14px; }
.stack-head.stack-theirs span {
  font-family: var(--display); font-weight: 800; text-transform: uppercase;
  font-size: 15px; letter-spacing: .02em; color: var(--smoke); text-align: center;
}
@media (min-width: 1024px) { .stack-head.stack-theirs span { font-size: 19px; } }
.stack-badge { display: block; width: 74px; }
@media (min-width: 1024px) { .stack-badge { width: 92px; } }

/* Minimal padding, as everywhere else on this site: the rows are 14/18px, not
   the 40 the reference uses. */
.stack-label, .stack-ours, .stack-theirs { border-top: 1px solid rgba(30,68,38,.22); }
.stack-ours { border-top-color: rgba(30,68,38,.16); }
.stack-head, .stack-head.stack-ours, .stack-head.stack-theirs { border-top: 0; }
.stack-label {
  display: flex; align-items: center; padding: 14px 16px 14px 0;
  font-weight: 700; font-size: 14px; line-height: 1.25; color: var(--pickle);
}
@media (min-width: 1024px) { .stack-label { padding: 18px 24px 18px 0; font-size: 17px; } }
.stack-ours, .stack-theirs { display: flex; align-items: center; justify-content: center; padding: 12px 8px; }
@media (min-width: 1024px) { .stack-ours, .stack-theirs { padding: 14px 8px; } }
.stack-ours.is-last { padding-bottom: 14px; }

.mark-yes { width: 30px; color: var(--pickle); }
@media (min-width: 1024px) { .mark-yes { width: 44px; } }
.mark-no { width: 29px; height: 29px; color: var(--ash); }
@media (min-width: 1024px) { .mark-no { width: 34px; height: 34px; } }
.stack-value { font-family: var(--display); font-weight: 800; font-size: 22px; color: var(--pickle); }
@media (min-width: 1024px) { .stack-value { font-size: 28px; } }
.stack-intro { margin-top: 10px; max-width: 46ch; }
.section-head.centred { justify-content: center; text-align: center; }
.section-head.centred .stack-intro { margin-left: auto; margin-right: auto; }
.sr { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); }

/* ---------- Flavour doors: the can on a flat colour, the name under it ---------- */
.doors { display: grid; grid-template-columns: 1fr; gap: 12px; }
@media (min-width: 640px) { .doors { grid-template-columns: repeat(3, 1fr); } }
.door {
  position: relative; aspect-ratio: 4/5; overflow: hidden; border-radius: var(--radius);
  background: var(--door-bg, var(--dill));
  display: flex; align-items: center; justify-content: center;
}
.door .door-can { position: relative; width: 38.4%; margin-bottom: 11%; transition: scale .3s var(--ease), rotate .3s var(--ease); }
/* The can sits above its own cast rather than behind it. A negative z-index here
   would drop the ellipse behind the card's background colour instead of behind
   the can, so the two are ordered explicitly. */
.door .door-can img { position: relative; z-index: 1; }
.door .door-can::after {
  content: ""; position: absolute; z-index: 0;
  left: 50%; bottom: -2%; translate: -50% 0;
  width: 96%; aspect-ratio: 6.5/1; border-radius: 50%;
  background: radial-gradient(closest-side,
      rgba(21,48,26,.26) 0%, rgba(21,48,26,.26) 36%, transparent 80%);
}
.door:hover .door-can, .door:focus-visible .door-can { scale: 1.06; rotate: -2.5deg; }
.door .door-text {
  position: absolute; inset: auto 0 0 0; display: flex; flex-direction: column;
  align-items: center; padding: 18px; color: var(--pickle); text-align: center;
}
.door .door-cat { font-size: 20px; line-height: 1.1; letter-spacing: .02em; font-weight: 800; text-transform: uppercase; }
@media (min-width: 1024px) { .door .door-cat { font-size: 24px; } }
.door .door-note { margin-top: 3px; font-size: 11px; letter-spacing: .18em; font-weight: 500; text-transform: uppercase; color: rgba(30,68,38,.72); }
/* A second line rises in on hover, so the card says outright that it goes somewhere. */
.door .door-cat::after {
  content: "Shop this flavor"; display: block; margin-top: 7px;
  font-family: var(--font); font-size: 11px; letter-spacing: .2em; font-weight: 500;
  opacity: 0; transform: translateY(7px);
  transition: opacity .24s var(--ease), transform .24s var(--ease);
}
.door:hover .door-cat::after, .door:focus-visible .door-cat::after { opacity: 1; transform: none; }

/* A flavour mark pops in beside the name on hover: a pickle coin, a chilli, a
   lime wedge. Drawn as line doodles rather than photographed so the three read
   as one family with the mascot.

   The name is wrapped in an inline-block that hugs the text, and the mark hangs
   off it absolutely. Laying the mark out inline instead would widen the line and
   shove the centred name sideways every time the card was hovered. */
.door .door-name, .buy-shot .door-name { position: relative; display: inline-block; }
.door .door-mark, .buy-shot .door-mark {
  position: absolute; left: calc(100% + 5px); top: 48%;
  width: 21px; height: 21px; color: var(--pickle);
  opacity: 0; scale: .4; rotate: -28deg; translate: 0 -50%;
  transform-origin: 50% 50%;
  transition: opacity .18s var(--ease), scale .3s var(--ease), rotate .3s var(--ease);
}
.door .door-mark svg, .buy-shot .door-mark svg { width: 100%; height: 100%; display: block; }
.door:hover .door-mark, .door:focus-visible .door-mark, .buy-shot:hover .door-mark {
  opacity: 1; scale: 1; rotate: 0deg;
  /* Lands just behind the can's tilt, so the card moves first and the mark answers. */
  transition: opacity .2s var(--ease) .06s,
              scale .42s cubic-bezier(.2,1.5,.4,1) .06s,
              rotate .42s cubic-bezier(.2,1.5,.4,1) .06s;
}
@media (prefers-reduced-motion: reduce) {
  .door .door-can, .door .door-cat::after, .door .door-mark { transition: none; }
  .door:hover .door-can { scale: 1; rotate: 0deg; }
  .door:hover .door-cat::after { transform: none; }
  .door:hover .door-mark { scale: 1; rotate: 0deg; }
}

/* ---------- The doodle ----------
   Mascot and a hand-lettered word side by side under the lineup. The word takes
   one full turn when the block scrolls into view: 360 degrees, 1.2s, eased hard
   out so it lands rather than coasts.

   CRISPY rather than REFRESHING on purpose — a short word reads through a spin,
   a long one is unreadable for most of the turn and has to be set so small
   beside the character that it stops being the point. */
.doodle {
  display: flex; align-items: center; justify-content: center; gap: 20px;
  width: 100%; max-width: min(430px, 82vw); margin: 52px auto 4px;
  color: var(--pickle);
}
.doodle-guy { width: 78px; flex: 0 0 auto; }
@media (min-width: 1024px) { .doodle-guy { width: 92px; } }
.doodle-word {
  font-family: var(--display); font-weight: 800; text-transform: uppercase;
  font-size: 30px; line-height: 1; letter-spacing: .01em; color: var(--pickle);
  transform-origin: 50% 50%; will-change: transform;
}
@media (min-width: 1024px) { .doodle-word { font-size: 38px; } }
.doodle-word.is-spinning { animation: doodle-spin 1.2s cubic-bezier(.22,1,.36,1) both; }
@keyframes doodle-spin { from { transform: rotate(0deg); } to { transform: rotate(360deg); } }
@media (prefers-reduced-motion: reduce) { .doodle-word.is-spinning { animation: none; } }

/* ---------- Standards: one can cycling, claims either side ---------- */
.section.band-standards { padding-top: 80px; padding-bottom: 68px; }
.standards { display: grid; gap: 28px; align-items: center; grid-template-columns: 1fr; }
@media (min-width: 900px) { .standards { grid-template-columns: 1fr 2fr 1fr; gap: 0; } }
.claims { display: flex; flex-direction: column; gap: 30px; align-items: center; }
.claim-row { position: relative; width: 130px; height: 130px; }
.claim {
  display: inline-flex; align-items: center; justify-content: center; text-align: center;
  width: 130px; height: 130px; border-radius: 50%; padding: 0 12px;
  background: transparent; color: var(--pickle);
  box-shadow: inset 0 0 0 1.5px rgba(30,68,38,.34);
  font-size: 15px; line-height: 1.12; letter-spacing: .01em; font-weight: 700; text-transform: uppercase;
}
/* Loose drawn curves from each circle toward the can, so the device reads as one
   weight of line. They hang off the inner edge; the circles stay on their centres. */
.tether { position: absolute; top: 50%; translate: 0 -50%; width: 190px; height: 42px; color: rgba(30,68,38,.30); transform: scaleX(var(--fx, 1)); }
.claims.left .tether  { left: calc(100% + 30px); }
.claims.right .tether { right: calc(100% + 30px); --fx: -1; }
@media (min-width: 900px) { .claims.left { align-items: flex-start; } .claims.right { align-items: flex-end; } }
@media (max-width: 899px) {
  .tether { display: none; }
  .claims { flex-direction: row; flex-wrap: wrap; justify-content: center; gap: 10px; }
  .claim { width: 112px; height: 112px; font-size: 13px; }
  .claim-row { width: 112px; height: 112px; }
}
/* The stack: every frame in the same box, only opacity changes, so nothing
   reflows and the swap costs one composited property. */
/* Back to the tall frame the can originally filled. Every ingredient is cut
   out and fitted to this frame's HEIGHT, so each one stands as tall as the
   can rather than being shrunk to fit a square. The frame is a touch wider than
   2:3 so the wide subjects reach full height instead of being capped by width. */
.cycle { position: relative; aspect-ratio: 940/1260; justify-self: center; width: 100%; max-width: 380px; }
.cycle-frame { position: absolute; inset: 0; display: flex; align-items: center; justify-content: center; opacity: 0; transition: opacity .14s var(--ease); will-change: opacity; }
.cycle-frame img { width: 100%; height: 100%; object-fit: contain; }
.cycle-frame.is-on { opacity: 1; }
@media (prefers-reduced-motion: reduce) { .cycle-frame { transition: none; } }

/* ---------- Process steps ---------- */
.steps { display: grid; border-top: 1px solid rgba(30,68,38,.22); }
.step { display: grid; grid-template-columns: 56px 1fr; gap: 16px; padding: 24px 0; border-bottom: 1px solid rgba(30,68,38,.22); }
@media (min-width: 1024px) { .step { grid-template-columns: 120px 1fr 1.4fr; gap: 32px; padding: 38px 0; } }
.step .num { font-size: 30px; font-weight: 800; line-height: 1; color: var(--gherkin); }
@media (min-width: 1024px) { .step .num { font-size: 46px; } }
.step .t-h3 { font-weight: 700; text-transform: uppercase; letter-spacing: .02em; font-size: 16px; }
@media (min-width: 1024px) { .step .t-h3 { font-size: 20px; } }
.step p { color: var(--smoke); margin-top: 8px; }
@media (min-width: 1024px) { .step p { margin-top: 0; grid-column: 3; } .step .t-h3 { grid-column: 2; } .step .num { grid-column: 1; } }
.steps .step { position: relative; background: var(--ground, var(--brine)); transition: transform .24s var(--ease), box-shadow .24s var(--ease); }
.steps .step:hover { transform: translateY(-4px); z-index: 2; box-shadow: var(--lift); }
@media (prefers-reduced-motion: reduce) { .steps .step { transition: none; } .steps .step:hover { transform: none; } }

/* ---------- Split feature: art + copy ---------- */
.split { display: grid; gap: 32px; align-items: center; }
@media (min-width: 1024px) { .split { grid-template-columns: 1fr 1fr; gap: 64px; } .split.flip > :first-child { order: 2; } }
.split .art { width: 100%; border-radius: var(--radius); overflow: hidden; background: var(--dill); }
.split .art svg { width: 100%; height: auto; display: block; }
.split .copy > * + * { margin-top: 16px; }
.split .copy .btn { margin-top: 24px; }
.section.band-find { padding-top: 32px; padding-bottom: 26px; }

/* ---------- Buy box ----------------------------------------------------------
   The page ends on the order form rather than on another argument. It reuses the
   split band it replaced, so the section keeps its height: can on one side,
   controls on the other. Radios do the state keeping — no JS is needed to show
   which flavour or pack is chosen, only to price it. */
.split.buy { align-items: center; }
/* Equal halves left the pair hanging on the left, because the card fills only
   part of its half. Sizing the columns to what is actually in them and centring
   the group puts the whole buy box on the page's middle, spacing untouched. */
@media (min-width: 1024px) {
  .split.buy { grid-template-columns: minmax(0, 560px) auto; justify-content: center; }
}
/* The product card is a flavour door without the link behaviour: same 4:5 shape,
   same ground, same can size, so the two places a can appears on the page match.
   Capped at a door's own width and centred, since its grid column is wider. */
.buy-shot {
  /* A lineup card is 387px wide here; this one runs smaller and sits at the
     inner edge of its column, tight to the form rather than out at the page
     edge. */
  position: relative; width: 100%; max-width: 305px; margin: 0 auto 0 0;
  aspect-ratio: 4 / 5; border-radius: var(--radius); overflow: hidden;
  background: var(--dill);
  display: flex; align-items: center; justify-content: center;
}
/* Same lift as a lineup card: the can tilts, the flavour mark pops. There is
   no "shop this flavor" line here — the card already sits beside the form. */
.buy-can { position: relative; width: 36.1%; margin-bottom: 11%;
           transition: scale .3s var(--ease), rotate .3s var(--ease); }
.buy-shot:hover .buy-can { scale: 1.06; rotate: -2.5deg; }
@media (prefers-reduced-motion: reduce) { .buy-shot:hover .buy-can { scale: 1; rotate: 0deg; } }
.buy-can img { position: relative; z-index: 1; width: 100%; height: auto; display: block; }
.buy-can::after {
  content: ""; position: absolute; z-index: 0;
  left: 50%; bottom: -2%; translate: -50% 0;
  width: 96%; aspect-ratio: 6.5/1; border-radius: 50%;
  background: radial-gradient(closest-side,
      rgba(21,48,26,.26) 0%, rgba(21,48,26,.26) 36%, transparent 80%);
}
.buy-shot-text {
  position: absolute; inset: auto 0 0 0; display: flex; flex-direction: column;
  align-items: center; padding: 18px; color: var(--pickle); text-align: center;
}
.buy-shot-name { font-size: 20px; line-height: 1.1; letter-spacing: .02em; font-weight: 800; text-transform: uppercase; font-family: var(--display); }
@media (min-width: 1024px) { .buy-shot-name { font-size: 24px; } }
.buy-shot-note { margin-top: 3px; font-size: 11px; letter-spacing: .18em; font-weight: 500; text-transform: uppercase; color: rgba(30,68,38,.72); }

.buy-panel > * + * { margin-top: 14px; }
.buy-set { border: 0; margin: 0; padding: 0; min-width: 0; }
.buy-legend {
  padding: 0; margin-bottom: 7px;
  font-size: 11px; letter-spacing: .18em; text-transform: uppercase;
  font-weight: 500; color: rgba(30,68,38,.62);
}

/* Flavour chips */
.chips { display: flex; flex-wrap: wrap; gap: 8px; }
.chip { cursor: pointer; }
.chip input { position: absolute; opacity: 0; pointer-events: none; }
.chip span {
  display: inline-block; padding: 8px 15px; border-radius: 999px;
  border: 1px solid rgba(30,68,38,.28); background: transparent; color: var(--pickle);
  font-size: 13px; font-weight: 500; letter-spacing: .01em;
  transition: background .2s var(--ease), border-color .2s var(--ease), color .2s var(--ease);
}
.chip:hover span { border-color: var(--pickle); background: rgba(30,68,38,.05); }
.chip input:checked + span { background: var(--pickle); border-color: var(--pickle); color: var(--brine); }
.chip input:focus-visible + span { outline: 2px solid var(--pickle); outline-offset: 3px; }

/* Pack cards */
.packs { display: grid; grid-template-columns: repeat(3, 1fr); gap: 8px; }
.pack { cursor: pointer; }
.pack input { position: absolute; opacity: 0; pointer-events: none; }
.pack-box {
  position: relative; display: block; height: 100%; padding: 13px 10px 11px; text-align: center;
  border: 1.5px solid rgba(30,68,38,.22); border-radius: 14px; background: transparent;
  transition: border-color .2s var(--ease), background .2s var(--ease), box-shadow .2s var(--ease);
}
.pack:hover .pack-box { border-color: rgba(30,68,38,.5); }
.pack input:checked + .pack-box {
  border-color: var(--pickle); background: rgba(169,192,140,.2);
  box-shadow: inset 0 0 0 1px var(--pickle);
}
.pack input:focus-visible + .pack-box { outline: 2px solid var(--pickle); outline-offset: 3px; }
.pack-n { display: block; font-family: var(--display); font-weight: 700; font-size: 16px; color: var(--pickle); }
.pack-p { display: block; margin-top: 2px; font-size: 14px; font-weight: 500; color: var(--pickle); }
.pack-e { display: block; margin-top: 1px; font-size: 11px; letter-spacing: .04em; color: rgba(30,68,38,.6); }
/* The badge sits above the card's own top edge, so cards stay the same height. */
.pack-tag {
  position: absolute; top: -9px; left: 50%; translate: -50% 0; white-space: nowrap;
  background: var(--lime); color: var(--pickle); border-radius: 999px; padding: 3px 9px;
  font-size: 9.5px; font-weight: 700; letter-spacing: .12em; text-transform: uppercase;
}
.packs { margin-top: 12px; }

/* Add button on its own row, centred. It keeps the hero button's height and
   type; only the dead width either side of the label comes off. */
.buy-row { display: flex; justify-content: center; margin-top: 18px; }
.buy-add { min-width: 0; padding: 0 30px; }
.buy-fine { margin-top: 12px; font-size: 12.5px; text-align: center; }

/* Cart count on the header icon, hidden until something is in the cart. */
.util a { position: relative; }
.cart-count {
  position: absolute; top: -5px; right: -7px; min-width: 17px; height: 17px; padding: 0 4px;
  display: grid; place-items: center; border-radius: 999px;
  background: var(--lime); color: var(--pickle);
  font: 700 10px/1 var(--font); letter-spacing: 0;
}
.cart-count[hidden] { display: none; }

@media (max-width: 1023px) {
  .buy-shot img { max-height: 240px; }
  .packs { gap: 6px; }
  .pack-box { padding: 12px 6px 10px; }
  .pack-n { font-size: 14px; }
}


/* ---------- Footer: Pickle, tight, playful, full-bleed hairline, bottom bar ----------
   Same tight geometry as TRAFFIC and Superior Nut — the footer is a utility, not
   a section. The play comes from the oversized wordmark and the mascot leaning on
   it, not from extra vertical space. */
.footer { background: var(--pickle); --ground: var(--pickle); color: var(--brine); padding: 24px 0 28px; overflow: hidden; }
.footer .wrap { width: 100%; max-width: var(--wide); margin: 0 auto; padding: 0 var(--gutter); }
@media (min-width: 1024px) { .footer .wrap { padding: 0 var(--gutter-lg); } }
/* Blocks distributed start / centre / end across the width; the text inside each
   block stays left aligned — the block moves, not the lines. */
/* Brand block, the three link columns, then the newsletter. The link columns sit
   in their own wrapper so they can be pulled tight together without also
   tightening the gap between the three blocks. */
.foot-grid { display: grid; grid-template-columns: 1fr; gap: 26px; margin-bottom: 18px; }
@media (min-width: 720px)  { .foot-grid { grid-template-columns: 1fr 1fr; } }
@media (min-width: 1040px) { .foot-grid { grid-template-columns: 1.05fr 1.95fr 1.05fr; gap: 40px; align-items: start; } }
/* THE THREE COLUMNS STRETCH ACROSS THEIR TRACK, they do not sit in the middle of
   it. Sized to their content and centred, they bunched into a clump with dead
   space on both sides; equal fractions spread them across the gap between the
   brand block and the signup. */
.foot-links { display: grid; grid-template-columns: repeat(3, 1fr); gap: 24px; }
@media (min-width: 1040px) { .foot-links { justify-self: stretch; gap: 28px; } }
@media (max-width: 719px)  { .foot-links { gap: 20px; } }
.foot-brand { display: flex; flex-direction: column; }
/* The lockup: wordmark with the mascot standing next to it, peeking over the
   baseline. Live text, same face as the header, so it is one brand voice. */
.foot-lockup { display: flex; align-items: flex-end; gap: 12px; }
.foot-badge { width: 84px; flex-shrink: 0; }
@media (min-width: 1024px) { .foot-badge { width: 104px; } }
.foot-mascot { width: 44px; flex-shrink: 0; color: var(--brine); margin-bottom: 2px; transition: rotate .3s var(--ease), translate .3s var(--ease); }
@media (min-width: 1024px) { .foot-mascot { width: 58px; } }
.foot-lockup:hover .foot-mascot { rotate: -8deg; translate: 0 -4px; }
@media (prefers-reduced-motion: reduce) { .foot-mascot { transition: none; } .foot-lockup:hover .foot-mascot { rotate: 0deg; translate: 0; } }
.foot-sub { margin-top: 5px; font-size: 9px; letter-spacing: .34em; text-indent: .34em; text-transform: uppercase; font-weight: 500; color: rgba(246,241,222,.74); }
.foot-brand p { margin-top: 10px; max-width: 34ch; font-size: 13px; line-height: 1.55; color: rgba(246,241,222,.74); }
.footer h2 { font-size: 14px; letter-spacing: .18em; font-weight: 700; text-transform: uppercase; color: var(--brine); margin-bottom: 10px; }
.footer ul li { margin-bottom: 4px; }
.footer ul a { font-size: 16.6px; color: rgba(246,241,222,.74); }
/* The global .ul hover fades to 55%, which on a dark ground reads as darker —
   the opposite of the intent. Footer links brighten to full Brine instead. */
.footer .ul:hover, .footer .ul:focus-visible, .footer a:hover, .footer a:focus-visible { opacity: 1; color: var(--brine); }
.foot-social { display: flex; gap: 1.6px; margin-top: auto; padding-top: 16px; margin-left: -2px; }
.foot-social a { display: inline-flex; padding: 2px; color: rgba(246,241,222,.74); transition: color .18s var(--ease); }
.foot-social svg { width: 30.5px; height: 30.5px; transition: scale .2s var(--ease); transform-origin: 50% 50%; }
.foot-social a:hover svg, .foot-social a:focus-visible svg { scale: 1.25; animation: util-shake .42s var(--ease); }
@media (prefers-reduced-motion: reduce) { .foot-social a:hover svg { animation: none; scale: 1; } }
/* Full-bleed hairline right after the link columns, then the copyright bar.
   The line runs the whole page width, outside the container, so the bottom bar
   reads as closing the page. */
/* ---------- Footer newsletter ----------
   Modelled on the reference: heading in the display face, a dashed pill for the
   field and a solid pill for the button. It sits inside the footer's existing
   height rather than adding a band of its own, so the footer stays tight. */
.foot-news { max-width: 420px; }
@media (min-width: 1040px) { .foot-news { justify-self: end; max-width: none; } }
.footer .news-head {
  font-family: var(--display); font-weight: 800; text-transform: uppercase;
  font-size: 30px; line-height: .98; letter-spacing: .01em; color: var(--brine);
  max-width: 9ch; margin-bottom: 14px;
}
@media (min-width: 1040px) { .footer .news-head { font-size: 46px; } }
.news-form { display: flex; align-items: center; gap: 8px; }
.news-input {
  flex: 1 1 auto; min-width: 0; height: 44px; padding: 0 16px;
  border: 2px dashed rgba(246,241,222,.55); border-radius: 999px;
  background: transparent; color: var(--brine);
  font-family: var(--font); font-size: 14px;
}
.news-input::placeholder { color: rgba(246,241,222,.5); }
.news-input:focus { outline: none; border-color: var(--lime); border-style: solid; }
.news-btn {
  flex: 0 0 auto; height: 44px; padding: 0 20px; border: 0; border-radius: 999px;
  background: var(--brine); color: var(--pickle); cursor: pointer;
  font-family: var(--font); font-size: 12px; letter-spacing: .16em;
  font-weight: 500; text-transform: uppercase; white-space: nowrap;
  transition: background-color .2s var(--ease), color .2s var(--ease);
}
.news-btn:hover, .news-btn:focus-visible { background: var(--lime); color: var(--pickle); }
.news-fine { margin-top: 9px; font-size: 11px; letter-spacing: .1em; text-transform: uppercase; color: rgba(246,241,222,.55); }

/* Payment marks. Set in our own face rather than imitating the networks'
   artwork — swap for the official badge SVGs once the methods are confirmed. */
.pay-row { display: flex; flex-wrap: wrap; gap: 6px; align-items: center; }
.pay-mark {
  display: inline-flex; align-items: center; justify-content: center;
  height: 22px; padding: 0 8px; border-radius: 4px;
  border: 1px solid rgba(246,241,222,.32); color: rgba(246,241,222,.72);
  font-size: 9.5px; letter-spacing: .1em; font-weight: 500; text-transform: uppercase;
}

.foot-rule { border-top: 1px solid rgba(246,241,222,.16); }
.foot-bottom { padding-top: 12px; display: flex; align-items: center; justify-content: space-between; gap: 12px 20px; flex-wrap: wrap; font-size: 12px; color: rgba(246,241,222,.62); }

/* Honor hidden state for the mobile navigation SVG icons. */
.menu-btn svg[hidden] { display: none !important; }
