/* ==========================================================================
   1. Design Tokens
   ========================================================================== */

:root {
    /* Colors */
    --color-cream: #fdf0e1;
    --color-peach: #feb47b;
    --color-coral: #cb4827;
    --color-teal: #2baab1;
    --color-slate: #383f48;
    --color-dark: #212529;
    --color-light: #ffdfcc;
    --color-white: #ffffff;
    --color-body-text: #555555;
    --color-heading: #222529;
    --color-flavors-sage: #A4C898;
    /* Reusable light border for inputs, steppers, and dividers. */
    --color-border: rgba(0, 0, 0, 0.15);
    /* WhatsApp brand green — used for the WhatsApp order CTA. */
    --color-whatsapp: #25D366;
    --color-whatsapp-dark: #1da851;

    /* Typography */
    --font-display: 'DINPro', sans-serif;
    --font-body: 'DINPro', sans-serif;

    /* Spacing scale */
    --space-xs: 0.25rem;
    --space-sm: 0.5rem;
    --space-md: 1rem;
    --space-lg: 2rem;
    --space-xl: 4rem;
    --space-2xl: 6rem;

    /* Layout */
    --container-max: 1200px;
    --container-padding: 1.5rem;
    /* Shared control height for inputs, selects, and quantity steppers. */
    --input-height: 3rem;

    /* Header */
    --header-height: 100px;

    /* Transitions */
    --transition-fast: 150ms ease;
    --transition-base: 250ms ease;
}


/* ==========================================================================
   2. Reset / Base
   ========================================================================== */

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

html {
    scroll-behavior: smooth;
    /* Native browser anchor scrolling lands here, below the sticky header. */
    scroll-padding-top: var(--header-height);
    -webkit-text-size-adjust: 100%;
}

body {
    font-family: var(--font-body);
    font-size: 1rem;
    font-weight: 400;
    line-height: 1.6;
    color: var(--color-body-text);
    background-color: var(--color-cream);
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
}

img,
svg {
    display: block;
    max-width: 100%;
    height: auto;
}

a {
    color: inherit;
    text-decoration: none;
    transition: color var(--transition-fast);
}

a:hover {
    color: var(--color-coral);
}

ul,
ol {
    list-style: none;
}

button {
    font: inherit;
    color: inherit;
    background: none;
    border: none;
    cursor: pointer;
}

input,
select,
textarea {
    font: inherit;
    color: inherit;
}

/* Skip link — visually hidden until focused */
.skip-link {
    position: absolute;
    left: -9999px;
    top: 0;
    z-index: 999;
    padding: var(--space-sm) var(--space-md);
    background-color: var(--color-dark);
    color: var(--color-white);
    text-decoration: none;
    font-family: var(--font-display);
    font-weight: 700;
    font-size: 0.875rem;
}

.skip-link:focus {
    left: var(--space-sm);
    top: var(--space-sm);
    color: var(--color-white);
}

/* Visually hidden, still announced by assistive tech (WP-canonical pattern). */
.screen-reader-text {
    border: 0;
    clip: rect(1px, 1px, 1px, 1px);
    clip-path: inset(50%);
    height: 1px;
    width: 1px;
    margin: -1px;
    overflow: hidden;
    padding: 0;
    position: absolute;
    white-space: nowrap;
    word-wrap: normal;
}


/* ==========================================================================
   3. Typography
   ========================================================================== */

@font-face {
    font-family: 'DINPro';
    src: url('../fonts/DINPro-Light.woff2') format('woff2');
    font-weight: 300;
    font-style: normal;
    font-display: swap;
}

@font-face {
    font-family: 'DINPro';
    src: url('../fonts/DINPro-Regular.woff2') format('woff2');
    font-weight: 400;
    font-style: normal;
    font-display: swap;
}

@font-face {
    font-family: 'DINPro';
    src: url('../fonts/DINPro-Medium.woff2') format('woff2');
    font-weight: 500;
    font-style: normal;
    font-display: swap;
}

@font-face {
    font-family: 'DINPro';
    src: url('../fonts/DINPro-Bold.woff2') format('woff2');
    font-weight: 700;
    font-style: normal;
    font-display: swap;
}

@font-face {
    font-family: 'DINPro';
    src: url('../fonts/DINPro-Black.woff2') format('woff2');
    font-weight: 900;
    font-style: normal;
    font-display: swap;
}

h1, h2, h3, h4, h5, h6 {
    font-family: var(--font-display);
    color: var(--color-heading);
    font-weight: 700;
    line-height: 1.2;
}

h1 { font-size: clamp(2rem, 5vw, 3.5rem); }
h2 { font-size: clamp(1.5rem, 4vw, 2.5rem); }
h3 { font-size: clamp(1.25rem, 3vw, 1.75rem); }
h4 { font-size: 1.25rem; }
h5 { font-size: 1rem; }
h6 { font-size: 0.875rem; }

p {
    margin-bottom: var(--space-md);
}

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


/* ==========================================================================
   4. Layout
   ========================================================================== */

.container {
    width: 100%;
    max-width: var(--container-max);
    margin-inline: auto;
    padding-inline: var(--container-padding);
}

.site-main {
    min-height: calc(100vh - var(--header-height));
}


/* ==========================================================================
   5. Components
   ========================================================================== */

/* --- Buttons --- */

.btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    padding: 0.75rem 2rem;
    font-family: var(--font-display);
    font-weight: 700;
    font-size: 0.875rem;
    letter-spacing: 0.05em;
    text-transform: uppercase;
    border-radius: 4px;
    transition: background-color var(--transition-base), color var(--transition-base);
    cursor: pointer;
}

.btn--primary {
    background-color: var(--color-coral);
    color: var(--color-white);
}

.btn--outline {
    background-color: transparent;
    color: var(--color-coral);
    border: 2px solid var(--color-coral);
}

/* Hover swaps gated to true-hover pointers — on touch :hover sticks after a
   tap and would leave these buttons stuck in their hover colors. */
@media (hover: hover) {
    .btn--primary:hover {
        background-color: var(--color-dark);
        color: var(--color-white);
    }

    .btn--outline:hover {
        background-color: var(--color-coral);
        color: var(--color-white);
    }
}


/* --- Header --- */

.site-header {
    position: sticky;
    top: 0;
    z-index: 100;
    background-color: var(--color-white);
    height: var(--header-height);
    transition: box-shadow var(--transition-base), transform var(--transition-base);
}

.site-header--scrolled {
    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
}

.site-header--hidden {
    transform: translateY(-100%);
}

/* Mobile-menu backdrop — dims the page behind the open menu and dismisses it
   on tap. Sits below the sticky header (z-100) and the menu (z-99, which lives
   inside the header's stacking context) but above page content. */
.site-header__backdrop {
    position: fixed;
    inset: 0;
    z-index: 90;
    background-color: rgba(0, 0, 0, 0.4);
    opacity: 0;
    visibility: hidden;
    pointer-events: none;
    transition: opacity var(--transition-base),
                visibility var(--transition-base);
}

.site-header__backdrop.is-visible {
    opacity: 1;
    visibility: visible;
    pointer-events: auto;
}

/* No hamburger menu on desktop, so the backdrop is never needed there. */
@media (min-width: 768px) {
    .site-header__backdrop {
        display: none;
    }
}

.site-header__container {
    height: 100%;
}

.site-header__nav {
    display: grid;
    grid-template-columns: 1fr auto 1fr;
    align-items: center;
    height: 100%;
    gap: var(--space-lg);
}

.site-header__menu {
    display: flex;
    gap: var(--space-sm);
    justify-self: start;
}

/* Transparent on desktop so the menu stays a direct grid item; on mobile it
   becomes the clip box for the dropdown (see the responsive section). */
.site-header__menu-wrap {
    display: contents;
}

.site-header__logo {
    justify-self: center;
}

.site-header__actions {
    justify-self: end;
}

.site-header__link {
    font-family: var(--font-display);
    font-weight: 700;
    font-size: 0.75rem;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    padding: 0.4rem 1rem;
    border-radius: 2rem;
    transition: background-color var(--transition-base), color var(--transition-base);
}

.site-header__link:hover {
    background-color: var(--color-dark);
    color: var(--color-white);
}

.site-header__link--active {
    background-color: var(--color-dark);
    color: var(--color-white);
}

.site-header__logo {
    flex-shrink: 0;
    display: inline-flex;
    align-items: center;
}

.site-header__logo img,
.site-header__logo-img {
    height: 50px;
    width: auto;
    max-width: 100%;
    display: block;
}

.site-header__site-name {
    font-family: var(--font-display);
    font-weight: 900;
    font-size: 1.25rem;
    text-transform: uppercase;
    letter-spacing: 0.05em;
}

.site-header__actions {
    display: flex;
    align-items: center;
    gap: var(--space-md);
}

.site-header__cart {
    position: relative;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 42px;
    height: 42px;
    border-radius: 50%;
    transition: background-color var(--transition-fast), color var(--transition-fast);
}

.site-header__cart:hover {
    background-color: var(--color-dark);
    color: var(--color-white);
}

.site-header__cart-icon {
    width: 22px;
    height: 22px;
}

.site-header__cart-badge {
    position: absolute;
    top: -2px;
    right: -4px;
    background-color: var(--color-coral);
    color: var(--color-white);
    font-size: 0.6rem;
    font-weight: 700;
    min-width: 16px;
    height: 16px;
    border-radius: 50%;
    display: flex;
    align-items: center;
    justify-content: center;
    line-height: 1;
}

.site-header__cart-badge--hidden {
    display: none;
}

.site-header__hamburger {
    display: none;
    flex-direction: column;
    justify-content: center;
    gap: 5px;
    width: 28px;
    height: 28px;
    padding: 0;
}

.site-header__hamburger span {
    display: block;
    width: 100%;
    height: 2px;
    background-color: var(--color-dark);
    border-radius: 1px;
    transition: transform var(--transition-base), opacity var(--transition-fast);
    transform-origin: center;
}

.site-header__hamburger[aria-expanded="true"] span:nth-child(1) {
    transform: translateY(7px) rotate(45deg);
}

.site-header__hamburger[aria-expanded="true"] span:nth-child(2) {
    opacity: 0;
}

.site-header__hamburger[aria-expanded="true"] span:nth-child(3) {
    transform: translateY(-7px) rotate(-45deg);
}


/* --- Footer --- */

.site-footer {
    background-color: var(--color-dark);
    color: var(--color-white);
    padding: var(--space-lg) 0;
}

.site-footer__grid {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: var(--space-2xl);
    align-items: center;
}

.site-footer__brand {
    display: flex;
    flex-direction: column;
    gap: var(--space-md);
    align-items: flex-start;
}

.site-footer__logo {
    width: clamp(180px, 22vw, 240px);
    height: auto;
    display: block;
}

.site-footer__copyright {
    font-size: 0.875rem;
    color: rgba(255, 255, 255, 0.6);
    margin: 0;
}

.site-footer__contacts {
    list-style: none;
    padding: 0;
    margin: 0;
    display: flex;
    flex-direction: column;
    gap: var(--space-sm);
    justify-self: end;
}

.site-footer__contact-link {
    display: inline-flex;
    align-items: center;
    gap: var(--space-md);
    color: var(--color-white);
    text-decoration: none;
    font-size: 1rem;
    transition: opacity var(--transition-fast);
}

.site-footer__contact-link:hover,
.site-footer__contact-link:focus {
    color: var(--color-white);
    opacity: 0.75;
}

.site-footer__contact-icon {
    width: 32px;
    height: 32px;
    flex-shrink: 0;
    display: block;
}


/* ==========================================================================
   6. Homepage Sections
   ========================================================================== */

/* --- Section shared --- */

.flavors,
.products-showcase,
.about-teaser {
    padding: var(--space-2xl) 0;
}

.flavors__title,
.products-showcase__title,
.about-teaser__title,
.retailers__title,
.shop-archive__title {
    text-align: center;
    margin-bottom: var(--space-xl);
    text-transform: uppercase;
    letter-spacing: 0.05em;
    /* One uniform section-title scale, bumped above the h2 default so the
       headers carry more presence on mobile (desktop max is unchanged). */
    font-size: clamp(1.75rem, 5vw, 2.5rem);
}

.flavors__title {
    color: #E96D6B;
}

.products-showcase__title {
    color: var(--color-flavors-sage);
    /* Extra breathing room — the bottle cards' emblems extend 60px above
       the card edge, eating into the shared section-title margin below. */
    margin-bottom: calc(var(--space-2xl) + var(--space-lg));
}

/* Reusable section-header subtitle tiers: a header is a title plus an
   optional tier below it. Each tier is defined once; any section opts in.
   Eyebrow — bold uppercase kicker. Caption — small muted line. */
.section-header__eyebrow {
    font-size: 1.125rem;
    font-weight: 700;
    color: var(--color-heading);
    text-transform: uppercase;
    letter-spacing: 0.08em;
    margin-bottom: var(--space-md);
}

.section-header__caption {
    text-align: center;
    color: var(--color-body-text);
    font-size: 0.9375rem;
    margin-bottom: var(--space-md);
}

/* --- Decorative wave separator --- */

.section-wave {
    display: block;
    width: 100%;
    height: auto;
    color: var(--color-peach);
    margin: -1px 0;
    line-height: 0;
}

/* --- Hero --- */

.hero {
    position: relative;
    /* Fill the visible viewport below the sticky header. svh is stable across
       mobile URL-bar show/hide (no scroll-time reflow) and replaces the old
       JS-set --vh, which could get stuck at a wrong value on some loads (e.g. a
       backgrounded / not-yet-painted tab) and leave the hero short until a
       refresh. The plain vh line is the fallback for browsers without svh. */
    min-height: calc(100vh - var(--header-height));
    min-height: calc(100svh - var(--header-height));
    background-color: var(--color-cream);
    /* Visible bleed so the art layer can drift past the hero's vertical bounds. */
    overflow: visible;
    isolation: isolate;
}

/* All layers are <picture> elements wrapping the actual <img>. Layer-level
   sizing & positioning sits on the picture; the inner img stretches to fill
   the picture box, with object-fit handling aspect mismatch. */
.hero__layer {
    display: block;
    position: absolute;
    left: 50%;
    pointer-events: none;
    will-change: transform;
    /* --parallax-y is set by JS on scroll; default 0 means no offset. */
    --parallax-y: 0px;
}

.hero__layer > img {
    display: block;
    width: 100%;
    height: auto;
}

/* Watermark: the repeating "SHAYA KOMBUCHA" scribble tiled down the hero and
   multiply-blended into the cream so it reads as faint texture — the same
   treatment as the shop archive (.shop-archive::before). Anchored at the top
   so the tiles march downward and fill the whole hero. */
.hero__layer--watermark {
    width: 100%;
    height: calc(100vh - var(--header-height));
    height: calc(100svh - var(--header-height));
    top: 0;
    bottom: auto;
    transform: translate3d(-50%, var(--parallax-y), 0);
    z-index: 1;
    background-image: url('../img/hero/hero-image-shadow.png');
    background-image: image-set(
        url('../img/hero/hero-image-shadow.avif') type('image/avif'),
        url('../img/hero/hero-image-shadow.png') type('image/png'));
    background-repeat: repeat-y;
    background-position: center top;
    background-size: 100% auto;
    mix-blend-mode: multiply;
}

/* Graffiti: yellow blob + hatched wordmark. Center-anchored, width-driven —
   picture box derives height from the inner img's intrinsic aspect ratio. */
.hero__layer--graffiti {
    width: min(85%, 980px);
    top: 42%;
    transform: translate3d(-50%, calc(-50% + var(--parallax-y)), 0);
    z-index: 2;
}

/* Slogan: hand-brushed "FOLLOW YOUR GUT". Anchored low, drifts upward on
   scroll with its own negative --parallax-y so it tucks behind the graffiti. */
.hero__layer--slogan {
    width: min(45%, 520px);
    top: 78%;
    transform: translate3d(-50%, calc(-50% + var(--parallax-y)), 0);
    z-index: 1;
}

.hero__container {
    position: relative;
    z-index: 3;
    text-align: center;
}

@media (prefers-reduced-motion: reduce) {
    .hero__layer {
        will-change: auto;
    }
}

/* --- Flavors --- */

.flavors {
    position: relative;
    overflow: hidden;
    /* Alternating section tones (blush <-> cream) so sections don't blend. */
    background-color: var(--color-light);
}

.flavors__background {
    position: absolute;
    inset: 0;
    pointer-events: none;
    z-index: 0;
    display: flex;
    align-items: center;
    justify-content: center;
}

.flavors__silhouette {
    width: auto;
    height: 70%;
    max-width: 60%;
    object-fit: contain;
    /* Nudge down from flex-centered baseline so the silhouette sits behind
       the lower rows of the emblem grid rather than the title. */
    transform: translateY(12%);
}

.flavors__container {
    position: relative;
    z-index: 1;
}

.flavors__grid {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: var(--space-xl);
    max-width: 960px;
    margin-inline: auto;
}

.flavor-icon {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: var(--space-sm);
    text-decoration: none;
    transition: transform var(--transition-base);
}

.flavor-icon:hover {
    transform: translateY(-4px);
    color: inherit;
}

.flavor-icon__emblem {
    width: 180px;
    height: 180px;
    object-fit: contain;
    /* The PNG's organic shape carries its own visual weight; a soft drop-shadow
       hugs the alpha channel (unlike box-shadow, which would draw a square). */
    filter: drop-shadow(0 4px 10px rgba(0, 0, 0, 0.08));
    transition: filter var(--transition-base), transform var(--transition-base);
}

.flavor-icon:hover .flavor-icon__emblem {
    filter: drop-shadow(0 8px 18px rgba(0, 0, 0, 0.14));
    transform: scale(1.04);
}

.flavor-icon__name {
    font-family: var(--font-display);
    font-weight: 900;
    font-size: 0.95rem;
    text-transform: uppercase;
    letter-spacing: 0.08em;
    color: var(--color-heading);
    text-align: center;
}

/* --- Products Showcase --- */

.products-showcase {
    background-color: var(--color-cream);
}

/* Shared grid: homepage bottles section + shop archive + WC's ul.products
   on related-products / search-results surfaces. Single rule keeps the
   card cells spaced identically across every place a bottle card appears. */
.products-showcase__grid,
ul.products {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    /* Row gap deliberately heavier than column gap — the cards are tall, so
       even spacing reads cramped vertically. */
    gap: var(--space-2xl) var(--space-xl);
    max-width: 1000px;
    margin-inline: auto;
    list-style: none;
    padding: 0;
}

.product-card {
    position: relative;
    display: block;
    text-decoration: none;
    transition: transform var(--transition-base), filter var(--transition-base);
    /* html { scroll-padding-top: var(--header-height) } lands the card's top
       edge just under the header, but the emblem extends 60px ABOVE the card
       (top: -60px) and would tuck under the sticky header. Push the scroll
       target down so the emblem clears with ~16px breathing room. */
    scroll-margin-top: 76px;
}

.product-card:hover {
    transform: translateY(-6px);
    color: inherit;
    filter: drop-shadow(0 12px 22px rgba(0, 0, 0, 0.14));
}

/* Blur-up media wrapper — shared by product cards, about photos, cart/checkout
   thumbnails, and flavor emblems. Paints a placeholder behind the image (a
   blurred low-res --lqip image and/or a solid --placeholder colour), then fades
   the image in once shaya.js (window.shayaInitBlurUp) marks the wrapper
   .is-loaded. The image is visible by default, so a no-JS render is unaffected.
   Each context adds its own class for shape/size (border-radius, dimensions). */
.shaya-media {
    position: relative;
    overflow: hidden;
    /* Own stacking context so the image's z-index stays contained — it must
       sit above the ::before placeholder but never above sibling/overlay
       content (product name, flavor label, photo caption). */
    isolation: isolate;
    background-color: var(--placeholder, transparent);
}

.shaya-media::before {
    content: '';
    position: absolute;
    inset: 0;
    z-index: 0;
    background-image: var(--lqip, none);
    background-size: cover;
    background-position: center;
    /* Blur + slight scale hides the low-res edges behind the sharp image. */
    filter: blur(14px);
    transform: scale(1.08);
}

.shaya-media img {
    position: relative;
    z-index: 1;
}

.shaya-media.is-loading img {
    opacity: 0;
}

.shaya-media.is-loaded img {
    opacity: 1;
    transition: opacity var(--transition-base);
}

.product-card__media {
    display: block;
    border-radius: 44px;
}

/* No radius on the image itself: the wrapper (overflow:hidden) clips it, so the
   bottle fills edge-to-edge and fully covers the blurred --lqip placeholder.
   A rounded image would leave transparent corners that reveal the placeholder
   as a colored halo. */
.product-card__bottle {
    display: block;
    width: 100%;
    height: auto;
}

/* Merch (no-flavor) cards hold photographic images at mixed aspect ratios —
   most are portrait 4:5, but a stray landscape shot would otherwise render
   short-and-wide, leaving the grid row stretched and the absolutely-positioned
   name floating in the gap below the image. Pin every merch card to one 4:5
   frame and cover-fill it so the section stays uniform regardless of the
   uploaded photo's dimensions. Kombucha cards keep their natural bottle ratio.

   The frame is built with the padding-ratio technique (height:0 +
   padding-bottom) rather than `aspect-ratio`, because iOS 14 / older Safari
   don't support `aspect-ratio` — there the image's `height:100%` would resolve
   against an auto-height box and fall back to the photo's full intrinsic pixel
   height (a giant image). padding-bottom gives the box a DEFINITE height on
   every browser, so `height:100%` always resolves correctly. 125% = 5/4 (4:5). */
.product-card--no-flavor .product-card__media {
    height: 0;
    padding-bottom: 125%;
}

.product-card--no-flavor .product-card__bottle {
    position: absolute;
    inset: 0;
    height: 100%;
    object-fit: cover;
}

/* Flavor emblem blur-up. The emblem PNG isn't a filled rectangle and its symbol
   extends past the coloured circle, so the placeholder is a blurred low-res of
   the emblem itself (matches the artwork), not a shape. Overflow visible lets
   the symbol + drop-shadow spill; contain (no cover/scale) matches the emblem's
   object-fit so the blur and the sharp image line up. Placed after .shaya-media
   so these overrides win. */
.flavor-icon__media {
    display: inline-block;
    line-height: 0;
    overflow: visible;
}

.flavor-icon__media::before {
    background-size: contain;
    background-repeat: no-repeat;
    transform: none;
}


.product-card__emblem {
    position: absolute;
    top: -52px;
    left: 50%;
    z-index: 2;
    width: 100px;
    height: 100px;
    object-fit: contain;
    transform: translateX(-50%);
    /* drop-shadow follows the PNG's alpha so the sticker shadow hugs the
       organic blob shape instead of a rectangular bounding box. */
    filter: drop-shadow(0 4px 10px rgba(0, 0, 0, 0.22));
    transition: transform var(--transition-base), filter var(--transition-base);
}

.product-card:hover .product-card__emblem {
    transform: translateX(-50%) translateY(-4px) rotate(-3deg);
    filter: drop-shadow(0 8px 16px rgba(0, 0, 0, 0.26));
}

.product-card__name {
    position: absolute;
    left: 0;
    right: 0;
    bottom: 3%;
    z-index: 2;
    font-family: var(--font-display);
    font-weight: 900;
    font-size: 1.05rem;
    text-transform: uppercase;
    letter-spacing: 0.08em;
    text-align: center;
    color: #fff;
    /* White always — strong dark shadow keeps the label readable on the
       lighter cards (Black Original, Ginger Bomb, Native Green). */
    text-shadow: 0 2px 6px rgba(0, 0, 0, 0.4);
    pointer-events: none;
}

.product-card--highlight .product-card__bottle {
    animation: shaya-card-pulse 1.5s ease-out;
}

@media (prefers-reduced-motion: no-preference) {
    @keyframes shaya-card-pulse {
        0%   { box-shadow: 0 0 0 0 rgba(203, 72, 39, 0.55); }
        70%  { box-shadow: 0 0 0 18px rgba(203, 72, 39, 0); }
        100% { box-shadow: 0 0 0 0 rgba(203, 72, 39, 0); }
    }
}

/* --- Retailers (homepage horizontal rail) --- */

.retailers {
    /* Alternating section tones — blush, matching the flavors section. */
    background-color: var(--color-light);
    padding: var(--space-2xl) 0;
}

.retailers__title {
    /* Shared section-title styling comes from the grouped rule above; only
       the tight gap to the caption below is retailer-specific. */
    margin-bottom: var(--space-xs);
}

/* The rail's own top/bottom padding owns the gap to the logos, so the caption
   adds none — this keeps the caption-to-logos gap equal to the logos-to-CTA
   gap (the rail padding is symmetric). */
.retailers .section-header__caption {
    margin-bottom: 0;
}

/* Rail: edges soft-fade into the cream so the scroll affordance is
   atmospheric rather than utilitarian. No scrollbar. */
.retailers__rail {
    display: flex;
    align-items: center;
    gap: 3rem;
    overflow-x: auto;
    overflow-y: hidden;
    scroll-snap-type: x mandatory;
    scroll-padding-inline: 4rem;
    padding: var(--space-xl) 4rem 4rem;
    margin-bottom: 0;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
    -ms-overflow-style: none;
    -webkit-mask-image: linear-gradient(
        to right,
        transparent 0,
        #000 4rem,
        #000 calc(100% - 4rem),
        transparent 100%
    );
    mask-image: linear-gradient(
        to right,
        transparent 0,
        #000 4rem,
        #000 calc(100% - 4rem),
        transparent 100%
    );
}

.retailers__rail::-webkit-scrollbar {
    display: none;
}

.retailer-card {
    flex: 0 0 120px;
    scroll-snap-align: center;
    display: flex;
    align-items: center;
    justify-content: center;
    text-decoration: none;
    color: inherit;
}

.retailer-card:hover,
.retailer-card:focus-visible {
    color: inherit;
}

.retailer-card__image {
    width: 120px;
    height: 120px;
    object-fit: contain;
    display: block;
    transition: transform 0.4s ease;
}

.retailer-card:hover .retailer-card__image,
.retailer-card:focus-visible .retailer-card__image {
    transform: scale(1.08);
}

.retailer-card__placeholder {
    display: block;
    width: 120px;
    height: 120px;
    border-radius: 50%;
    background: linear-gradient(135deg, var(--color-peach), var(--color-coral));
    opacity: 0.3;
}

.retailers__cta,
.products-showcase__cta {
    display: block;
    width: max-content;
    margin: 0 auto;
    /* The page's primary conversion CTA — give it more presence than the base
       button so it no longer reads as small and narrow. */
    padding: 0.9rem 2.75rem;
    font-size: 1rem;
}

/* Sits below the bottle grid, so it needs its own top separation. */
.products-showcase__cta {
    margin-top: var(--space-xl);
}

/* --- About Teaser --- */

.about-teaser {
    position: relative;
    /* White background on both the homepage section and the standalone About
       page (this partial is shared by both). */
    background-color: var(--color-white);
    overflow: hidden;
}

/* Decorative blobs — theme-owned organic shapes behind the content.
   Fixed pixel size (they're real-world objects, not responsive widgets).
   Anchored to where the centered container's edge sits, not the section's
   edge, so on wide viewports the blob has empty margin to bleed into and
   shows fully — on narrow viewports it bleeds past the viewport edge and
   gets clipped by the section's overflow:hidden. */
.about-teaser__blob {
    position: absolute;
    z-index: 0;
    pointer-events: none;
    width: 400px;
    height: auto;
    opacity: 0.9;
}

.about-teaser__blob--sage {
    top: 40px;
    /* Container's left edge = 50% - container_max/2. Pull the blob 60px
       further left so it tucks past that edge into the margin space. */
    left: calc(50% - var(--container-max) / 2 - 60px);
}

.about-teaser__blob--lavender {
    bottom: 40px;
    right: calc(50% - var(--container-max) / 2 - 60px);
}

.about-teaser__container {
    position: relative;
    z-index: 1;
    text-align: center;
}

.about-teaser__title {
    /* Size + uppercase come from the shared section-title rule, so the About
       page <h1> and the homepage <h2> match the other section titles. */
    color: var(--color-flavors-sage);
}

.about-teaser__body {
    max-width: 720px;
    margin: 0 auto var(--space-2xl);
    font-size: 1rem;
    line-height: 1.8;
    color: var(--color-body-text);
    /* Long-form story copy reads better flush-left than centered; the block
       itself stays centered via the auto margins. */
    text-align: left;
}

/* Editorial drop-cap to break up the wall of text with a touch of brand
   character. The story is a single <p>, so ::first-letter is the opening
   initial. */
.about-teaser__body::first-letter {
    float: left;
    margin: 0.05em 0.12em 0 0;
    font-family: var(--font-display);
    font-weight: 900;
    font-size: 3.2em;
    line-height: 0.78;
    color: var(--color-coral);
}

.about-teaser__photos {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: var(--space-xl);
    max-width: 900px;
    margin: 0 auto var(--space-xl);
}

.about-teaser__photo {
    position: relative;
    border-radius: 16px;
    overflow: hidden;
}

.about-teaser__photo-img {
    display: block;
    width: 100%;
    height: auto;
    aspect-ratio: 4 / 3;
    object-fit: cover;
}

.about-teaser__caption {
    position: absolute;
    inset: auto 0 0 0;
    /* Above the blur-up image (.shaya-media img is z-index 1). */
    z-index: 2;
    padding: var(--space-md) var(--space-lg);
    font-family: var(--font-display);
    font-weight: 900;
    font-size: 1.1rem;
    line-height: 1.25;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    text-align: center;
    color: #fff;
    /* Heavier shadow so the caption stays readable over any photo. */
    text-shadow: 0 2px 6px rgba(0, 0, 0, 0.5);
}


/* ==========================================================================
   7. WooCommerce Overrides
   ========================================================================== */

/* --- Shop archive --- */

.shop-archive {
    padding-top: var(--space-2xl);
    position: relative;
    isolation: isolate;
    /* flow-root contains the last section's margin-bottom inside the
       wrapper so the cards keep their breathing room before the footer,
       while the watermark pseudo (bottom: 0) still fills all the way
       down to the wrapper's edge — i.e. flush against the footer. */
    display: flow-root;
}

/* Repeating watermark behind the grid — the same hero-image-shadow
   scribble used elsewhere. Multiply blends it into the cream backdrop
   so the texture deepens the page without sitting on top. The pseudo
   starts BELOW the top padding so a clear cream gap shows under the
   sticky header; bottom is flush against the footer (no bottom inset). */
.shop-archive::before {
    content: '';
    position: absolute;
    top: var(--space-xl);
    right: 0;
    bottom: 0;
    left: 0;
    background-image: url('../img/hero/hero-image-shadow.png');
    background-image: image-set(
        url('../img/hero/hero-image-shadow.avif') type('image/avif'),
        url('../img/hero/hero-image-shadow.png') type('image/png'));
    background-repeat: repeat-y;
    background-position: center top;
    background-size: 100% auto;
    mix-blend-mode: multiply;
    pointer-events: none;
    z-index: 0;
}

.shop-archive__container {
    position: relative;
    z-index: 1;
}

.shop-archive__section {
    margin-block: var(--space-2xl);
}

.shop-archive__section:first-of-type {
    margin-top: 0;
}

/* "Our Flavors" — green title with extra margin for the emblems that
   extend above each card. Mirrors the homepage bottles section. */
.shop-archive__section--flavors .shop-archive__title {
    color: var(--color-flavors-sage);
    margin-bottom: calc(var(--space-2xl) + var(--space-lg));
}

/* "More" — plain heading colour, no emblems → no extra margin. */
.shop-archive__section--more .shop-archive__title {
    color: var(--color-heading);
}

/* Used when WC's standard <ul class="products"> wraps the card on
   non-archive surfaces (related products, search results). */
.shop-archive__cell {
    list-style: none;
}

.shop-archive__empty {
    text-align: center;
    font-family: var(--font-display);
    font-weight: 700;
    font-size: 1rem;
    letter-spacing: 0.05em;
    text-transform: uppercase;
    color: var(--color-body-text);
    padding-block: var(--space-2xl);
}

/* Result count & ordering bar */
.woocommerce-result-count {
    font-size: 0.8125rem;
    color: var(--color-body-text);
}

.woocommerce-ordering select {
    padding: 0.5rem 1rem;
    border: 1px solid rgba(0, 0, 0, 0.12);
    border-radius: 4px;
    background-color: var(--color-white);
    font-size: 0.8125rem;
}


/* Sale flash */
.onsale {
    position: absolute;
    top: var(--space-sm);
    left: var(--space-sm);
    background-color: var(--color-coral);
    color: var(--color-white);
    font-size: 0.6875rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    padding: 0.25rem 0.75rem;
    border-radius: 2rem;
    z-index: 1;
}

/* --- Product Details (page + modal) --- */

.product-details-page {
    padding-block: var(--space-xl);
}

.product-details-page__container {
    /* Standard site container provides max-width + horizontal padding. */
}

.product-details {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: var(--space-2xl);
    align-items: start;
}

.product-details__gallery {
    display: flex;
    flex-direction: column;
    gap: var(--space-md);
}

/* Flavor-coloured "stage" behind the bottle, echoing the homepage bottle cards. */
.product-details__stage {
    background-color: var(--product-bg, var(--color-cream));
    border-radius: 24px;
    aspect-ratio: 1 / 1;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: var(--space-md) var(--space-xl);
    overflow: hidden;
    position: relative;
}

/* Decorative watermark behind the bottle — the same hero-image-shadow
   scribble used by the homepage hero. Two layered passes so the
   watermark stays visible across the whole flavor palette:
     ::before — multiply, darkens light backdrops (cream, peach, sage).
     ::after  — screen, lightens dark backdrops (dark green, black) so
                the scribble doesn't vanish into them.
   On any single backdrop only one of the two pulls weight; the other
   stays close to identity. Result: a "tinted by background" feel that
   works on every flavor without per-flavor tuning. */
.product-details__stage::before,
.product-details__stage::after {
    content: '';
    position: absolute;
    inset: 0;
    background-image: url('../img/hero/hero-image-shadow.png');
    background-image: image-set(
        url('../img/hero/hero-image-shadow.avif') type('image/avif'),
        url('../img/hero/hero-image-shadow.png') type('image/png'));
    background-repeat: no-repeat;
    background-position: center;
    background-size: cover;
    pointer-events: none;
    z-index: 0;
}

.product-details__stage::before {
    mix-blend-mode: multiply;
}

.product-details__stage::after {
    mix-blend-mode: screen;
}

.product-details__main-image {
    position: relative;
    z-index: 2;
    max-width: 100%;
    max-height: 100%;
    width: auto;
    height: auto;
    display: block;
    object-fit: contain;
    border-radius: 16px;
    transform-origin: center center;
    transition: opacity var(--transition-base), transform 200ms ease;
}

/* Blurred low-res preview that stands in until the full image loads. Sits
   above the watermark (z-index 0) and below the sharp image (z-index 2). */
.product-details__lqip {
    position: absolute;
    inset: var(--space-md) var(--space-xl);
    z-index: 1;
    background-image: var(--lqip, none);
    background-repeat: no-repeat;
    background-position: center;
    background-size: contain;
    filter: blur(12px);
    pointer-events: none;
}

/* While loading: hide the sharp image so the blurred preview + spinner show;
   once loaded, fade the sharp image back in (default state is fully visible,
   so a no-JS render is unaffected). */
.product-details__stage.is-loading .product-details__main-image {
    opacity: 0;
}

.product-details__stage.is-loaded .product-details__main-image {
    opacity: 1;
}

.product-details__spinner {
    position: absolute;
    top: 50%;
    left: 50%;
    z-index: 3;
    width: 36px;
    height: 36px;
    margin: -18px 0 0 -18px;
    border-radius: 50%;
    border: 3px solid rgba(33, 37, 41, 0.18);
    border-top-color: var(--color-coral);
    opacity: 0;
    pointer-events: none;
}

.product-details__stage.is-loading .product-details__spinner {
    opacity: 1;
}

@media (prefers-reduced-motion: no-preference) {
    .product-details__stage.is-loading .product-details__spinner {
        animation: shaya-spin 0.7s linear infinite;
    }

    @keyframes shaya-spin {
        to { transform: rotate(360deg); }
    }
}

/* Hover zoom — mouse-only. JS updates --product-details transform-origin
   on mousemove so the cursor's position drives the focal point. Touch
   devices skip the scale-up so a tap doesn't lock the image at 2x. */
@media (hover: hover) {
    .product-details__stage {
        cursor: zoom-in;
    }
    .product-details__stage:hover .product-details__main-image {
        transform: scale(2);
    }
}

.product-details__thumbs {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(80px, 1fr));
    gap: var(--space-sm);
}

.product-details__thumb {
    aspect-ratio: 1 / 1;
    padding: var(--space-xs);
    border: 2px solid transparent;
    border-radius: 12px;
    background-color: var(--product-bg, var(--color-cream));
    cursor: pointer;
    overflow: hidden;
    transition: border-color var(--transition-fast);
    display: flex;
    align-items: center;
    justify-content: center;
    position: relative;
}

/* Same dual-pass watermark as the main stage so the thumbnails share
   the texture. */
.product-details__thumb::before,
.product-details__thumb::after {
    content: '';
    position: absolute;
    inset: 0;
    background-image: url('../img/hero/hero-image-shadow.png');
    background-image: image-set(
        url('../img/hero/hero-image-shadow.avif') type('image/avif'),
        url('../img/hero/hero-image-shadow.png') type('image/png'));
    background-repeat: no-repeat;
    background-position: center;
    background-size: cover;
    pointer-events: none;
    z-index: 0;
}

.product-details__thumb::before {
    mix-blend-mode: multiply;
}

.product-details__thumb::after {
    mix-blend-mode: screen;
}

.product-details__thumb img {
    position: relative;
    z-index: 1;
    max-width: 100%;
    max-height: 100%;
    object-fit: contain;
    display: block;
    border-radius: 16px;
}

.product-details__thumb:hover,
.product-details__thumb:focus-visible {
    border-color: rgba(0, 0, 0, 0.25);
}

.product-details__thumb.is-active {
    border-color: var(--color-dark);
}

.product-details__info {
    display: flex;
    flex-direction: column;
    gap: var(--space-lg);
    padding-block: var(--space-md);
}

.product-details__title {
    text-transform: uppercase;
    letter-spacing: 0.02em;
    line-height: 1.1;
    margin: 0;
    color: var(--color-heading);
}

.product-details__description {
    font-size: 1rem;
    line-height: 1.7;
    color: var(--color-body-text);
}

/* Non-flavor products (e.g. merch) have no card colour, so the flavor
   watermark + cream stage clash with a photographic image. Drop the
   watermark and use a clean neutral stage/thumbs so the photo reads on
   its own — the blurred preview + add-to-cart behave exactly the same. */
.product-details--no-flavor .product-details__stage,
.product-details--no-flavor .product-details__thumb {
    background-color: var(--color-white);
}

.product-details--no-flavor .product-details__stage::before,
.product-details--no-flavor .product-details__stage::after,
.product-details--no-flavor .product-details__thumb::before,
.product-details--no-flavor .product-details__thumb::after {
    content: none;
}

/* Merch photos come in mixed aspect ratios and (unlike bottles) have no fixed
   stage size. Give the stage a DEFINITE height and the image a definite
   height:100% + object-fit:contain, so the image can never render at its own
   intrinsic height. Two failure modes this prevents:
     - Firefox modal: an intrinsic-height replaced element inside the flex scroll
       container leaks its full height past `.product-modal__inner`'s
       `max-height:95vh` cap, so the dialog grows taller than the viewport (the
       whole modal drifts off-screen and has to be scrolled to).
     - iOS 14 / older Safari: `height:100%` against an auto-height box falls back
       to the photo's full intrinsic pixel height — a giant image.
   The height comes from the padding-ratio technique (height:0 + padding-bottom),
   NOT `aspect-ratio`, which iOS 14 doesn't support. padding-bottom gives a
   definite, width-derived height everywhere; the image is absolutely positioned
   to fill it. 125% = 5/4 (4:5) — matches the merch card and most merch photos;
   the white letterbox for the odd landscape shot is invisible on the white stage. */
.product-details--no-flavor .product-details__stage {
    /* Explicitly cancel the base stage's aspect-ratio:1/1 — the padding-ratio
       below owns the height. The explicit height:0 already neutralizes it, but
       resetting keeps intent clear and immune to engine quirks. */
    aspect-ratio: auto;
    height: 0;
    padding: 0 0 125%;
}

.product-details--no-flavor .product-details__main-image {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    max-height: none;
    object-fit: contain;
    border-radius: 0;
}


/* Simple-product (merch) price — mirrors the variation price styling. */
.product-details__price {
    font-family: var(--font-display);
    font-weight: 900;
    font-size: 1.5rem;
    color: var(--color-coral);
}

/* Variations form — scoped to .product-details so checkout/cart aren't touched. */

.product-details .variations_form {
    margin: 0;
}

.product-details .variations {
    width: 100%;
    border-collapse: collapse;
}

.product-details .variations tr {
    display: grid;
    grid-template-columns: minmax(80px, auto) 1fr auto;
    gap: var(--space-md);
    align-items: center;
    padding-block: var(--space-sm);
    border-bottom: 1px solid rgba(0, 0, 0, 0.08);
}

.product-details .variations tr:last-child {
    border-bottom: none;
}

.product-details .variations th.label {
    text-align: left;
    font-family: var(--font-display);
    font-size: 0.8125rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: var(--color-heading);
}

.product-details .variations td.value,
.product-details .variations td.variation-price-cell {
    padding: 0;
}

.product-details .variations td.value select {
    width: 100%;
    padding: var(--space-sm) var(--space-md);
    border: 1px solid var(--color-dark);
    border-radius: 4px;
    background-color: var(--color-white);
    font-family: var(--font-body);
    font-size: 1rem;
    color: var(--color-heading);
}

.product-details .variation-price-display {
    font-family: var(--font-display);
    font-size: 1.25rem;
    font-weight: 900;
    color: var(--color-coral);
    white-space: nowrap;
}

/* WC's default "selected variation" price block is rendered inline in the
   row above, so collapse the duplicate WC injects below the table. */
.product-details .single_variation_wrap .woocommerce-variation-price,
.product-details .single_variation_wrap .woocommerce-variation-availability,
.product-details .single_variation_wrap .woocommerce-variation-description {
    position: absolute;
    width: 1px;
    height: 1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
}

.product-details .single_variation_wrap {
    margin-top: var(--space-lg);
    display: flex;
    flex-direction: column;
    gap: var(--space-md);
    position: relative;
}

/* The variable form's qty+add row AND the simple product's default form.cart
   (merch) share this layout so both lay out identically. :not(.variations_form)
   scopes the second selector to simple products. */
.product-details .woocommerce-variation-add-to-cart,
.product-details form.cart:not(.variations_form) {
    display: flex;
    align-items: stretch;
    gap: var(--space-sm);
    flex-wrap: wrap;
}

.product-details .quantity .qty {
    width: 72px;
    padding: 0.75rem;
    text-align: center;
    border: 1px solid var(--color-dark);
    background-color: var(--color-white);
    font-family: var(--font-body);
    font-size: 1rem;
}

/* Segmented stepper: [ − ] [ value ] [ + ]. White buttons with the same
   dark border as the input — the trio reads as one piece because each
   element is 48px tall (touch-target minimum from Apple HIG / Material)
   and the shared border line meets cleanly. */
.quantity--stepper {
    display: inline-flex;
    align-items: stretch;
}

.product-details .quantity--stepper .qty {
    box-sizing: border-box;
    height: var(--input-height);
    padding: 0 var(--space-sm);
    border: 1px solid var(--color-border);
    border-radius: 0;
    width: 64px;
    /* Strip native spinner UI defensively. */
    -moz-appearance: textfield;
}

.product-details .quantity--stepper .qty::-webkit-outer-spin-button,
.product-details .quantity--stepper .qty::-webkit-inner-spin-button {
    -webkit-appearance: none;
    margin: 0;
}

.quantity__btn {
    box-sizing: border-box;
    width: var(--input-height);
    height: var(--input-height);
    flex-shrink: 0;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    padding: 0;
    border: 1px solid var(--color-border);
    background-color: var(--color-white);
    color: var(--color-dark);
    cursor: pointer;
    transition: background-color var(--transition-base), color var(--transition-base);
}

.quantity__icon {
    width: 18px;
    height: 18px;
    display: block;
}

.quantity__btn:hover,
.quantity__btn:focus-visible {
    background-color: var(--color-dark);
    color: var(--color-white);
}

.quantity__btn--minus {
    border-radius: 4px 0 0 4px;
    border-right: none;
}

.quantity__btn--plus {
    border-radius: 0 4px 4px 0;
    border-left: none;
}

.quantity__btn:disabled {
    opacity: 0.35;
    cursor: not-allowed;
}

.quantity__btn:disabled:hover {
    background-color: var(--color-white);
    color: var(--color-dark);
}

/* Reuse the homepage primary CTA language on the WC add-to-cart button so
   the button feels native to the rest of the site. */
/* The .button.alt qualifiers raise specificity above WooCommerce's default
   `.woocommerce button.button.alt` rule (its own purple #7f54b3) so the
   brand coral applies on the standalone product page too — not just in the
   modal, which renders outside the .woocommerce wrapper. */
.product-details .single_add_to_cart_button.button.alt {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    padding: 0.75rem 2rem;
    font-family: var(--font-display);
    font-weight: 700;
    font-size: 0.875rem;
    letter-spacing: 0.05em;
    text-transform: uppercase;
    border-radius: 4px;
    background-color: var(--color-coral);
    color: var(--color-white);
    border: none;
    cursor: pointer;
    flex: 1 1 auto;
    min-width: 200px;
    /* Pin to the quantity stepper's height so the button keeps a constant
       height across default/loading/added states — on mobile it wraps to its
       own row and would otherwise lose the flex stretch and change height. */
    min-height: var(--input-height);
    transition: background-color var(--transition-base), color var(--transition-base);
}

/* Keyboard focus keeps the dark state on every device. The :hover swap is
   gated to true-hover pointers so a tap doesn't leave the button stuck dark
   on touch screens, where :hover sticks until the next interaction. */
.product-details .single_add_to_cart_button.button.alt:focus-visible {
    background-color: var(--color-dark);
    color: var(--color-white);
}

@media (hover: hover) {
    .product-details .single_add_to_cart_button.button.alt:hover {
        background-color: var(--color-dark);
        color: var(--color-white);
    }
}

.product-details .single_add_to_cart_button.button.alt.is-loading {
    opacity: 0.7;
    cursor: progress;
}

.product-details .single_add_to_cart_button.button.alt.is-added {
    background-color: var(--color-teal);
}

/* Disabled state — used when no variation is picked yet. */
.product-details .single_add_to_cart_button.button.alt.disabled,
.product-details .single_add_to_cart_button.button.alt[disabled] {
    opacity: 0.45;
    cursor: not-allowed;
}

.shaya-add-to-cart-error {
    padding: var(--space-sm) var(--space-md);
    border-left: 4px solid var(--color-coral);
    background-color: rgba(203, 72, 39, 0.08);
    color: var(--color-heading);
    font-size: 0.875rem;
    border-radius: 4px;
}

/* Generic WC quantity input fallback (cart, mini-cart) — unchanged from before. */
.quantity .qty {
    width: 60px;
    padding: 0.5rem;
    text-align: center;
    border: 1px solid rgba(0, 0, 0, 0.15);
    border-radius: 6px;
    font-size: 0.875rem;
}

/* --- Product modal --- */

dialog.product-modal {
    padding: 0;
    border: 0;
    background: transparent;
    width: min(1200px, 95vw);
    max-width: 95vw;
    max-height: 95vh;
    margin: auto;
    color: var(--color-body-text);
}

dialog.product-modal::backdrop {
    background: rgba(33, 37, 41, 0.72);
    backdrop-filter: blur(4px);
}

.product-modal__inner {
    background-color: var(--color-cream);
    border-radius: 24px;
    overflow: hidden;
    max-height: 95vh;
    position: relative;
    display: flex;
    flex-direction: column;
}

/* The content scrolls, not the inner — so the close button (absolute to the
   non-scrolling inner) stays pinned at the top-right while the body scrolls. */
.product-modal__content {
    overflow-y: auto;
    min-height: 0;
    padding: var(--space-xl);
}

.product-modal__close {
    position: absolute;
    top: var(--space-md);
    right: var(--space-md);
    width: 44px;
    height: 44px;
    border-radius: 50%;
    background-color: var(--color-white);
    border: none;
    cursor: pointer;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    transition: opacity var(--transition-fast);
    z-index: 2;
    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
}

.product-modal__close:hover,
.product-modal__close:focus-visible {
    opacity: 0.75;
}

.product-modal__close svg {
    width: 18px;
    height: 18px;
    stroke: var(--color-dark);
    stroke-width: 2;
    fill: none;
}

.product-modal__loading {
    display: flex;
    align-items: center;
    justify-content: center;
    min-height: 320px;
    color: var(--color-body-text);
    font-family: var(--font-display);
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    font-size: 0.875rem;
}

/* Inside the modal the layout tightens up because we already have outer padding. */
.product-modal__inner .product-details {
    gap: var(--space-xl);
}

body.shaya-modal-open {
    overflow: hidden;
}

/* --- Cart modal (overlay) ---
   Mirrors the product-modal scaffolding; narrower since it's a list,
   not a gallery. */

dialog.cart-modal {
    padding: 0;
    border: 0;
    background: transparent;
    width: min(560px, 95vw);
    max-width: 95vw;
    max-height: 95vh;
    margin: auto;
    color: var(--color-body-text);
}

dialog.cart-modal::backdrop {
    background: rgba(33, 37, 41, 0.72);
    backdrop-filter: blur(4px);
}

.cart-modal__inner {
    background-color: var(--color-cream);
    border-radius: 24px;
    overflow: hidden;
    max-height: 95vh;
    position: relative;
    display: flex;
    flex-direction: column;
}

.cart-modal__content {
    overflow-y: auto;
    min-height: 0;
    padding: var(--space-xl);
}

.cart-modal__close {
    position: absolute;
    top: var(--space-md);
    right: var(--space-md);
    width: 44px;
    height: 44px;
    border-radius: 50%;
    background-color: var(--color-white);
    border: none;
    cursor: pointer;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    transition: opacity var(--transition-fast);
    z-index: 2;
    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
}

.cart-modal__close:hover,
.cart-modal__close:focus-visible {
    opacity: 0.75;
}

.cart-modal__close svg {
    width: 18px;
    height: 18px;
    stroke: var(--color-dark);
    stroke-width: 2;
    fill: none;
}

.cart-modal__loading {
    display: flex;
    align-items: center;
    justify-content: center;
    min-height: 200px;
    color: var(--color-body-text);
    font-family: var(--font-display);
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    font-size: 0.875rem;
}

.cart-panel__title {
    margin: 0 0 var(--space-lg);
    font-family: var(--font-display);
    font-weight: 700;
    font-size: 1.5rem;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    color: var(--color-heading);
}

/* Dim + lock the panel while a quantity update is in flight. */
.cart-panel[aria-busy="true"] {
    opacity: 0.6;
    pointer-events: none;
}

.cart-panel__empty {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: var(--space-md);
    padding: var(--space-xl) 0;
    text-align: center;
}

.cart-panel__empty-text {
    margin: 0;
    font-size: 1.125rem;
}

.cart-panel__items {
    list-style: none;
    margin: 0;
    padding: 0;
}

.cart-item {
    display: flex;
    gap: var(--space-md);
    /* Stretch so the columns share the row height (set by the square
       thumbnail); the name pins to the top and the stepper/price/remove
       to the bottom, so the image and stepper bottoms line up. */
    align-items: stretch;
    padding: var(--space-md) 0;
    border-bottom: 1px solid rgba(0, 0, 0, 0.1);
}

.cart-item__thumb {
    flex: 0 0 auto;
    width: 5rem;
    height: 5rem;
    border-radius: 8px;
    overflow: hidden;
}

/* .cart-item ancestor raises specificity above the prose
   `.page-content__body img` rule (which sets margin: 2rem 0) — that margin
   was pushing the checkout thumbnail down and clipping it into a landscape
   sliver. The cart overlay isn't in .page-content__body, so it was fine. */
.cart-item .cart-item__thumb img {
    display: block;
    width: 100%;
    height: 100%;
    margin: 0;
    object-fit: cover;
}

.cart-item__details {
    flex: 1 1 auto;
    display: flex;
    flex-direction: column;
    /* Name at the top, stepper at the bottom of the row. No fixed gap so
       the thumbnail (not name + gap + stepper) stays the height anchor. */
    justify-content: space-between;
    min-width: 0;
}

.cart-item__name {
    font-family: var(--font-display);
    font-weight: 700;
    color: var(--color-heading);
}

.cart-item__meta {
    font-size: 0.8125rem;
    color: var(--color-body-text);
}

/* The .qty sizing rules elsewhere are scoped to .product-details, so the
   cart stepper needs its own (slightly smaller) dimensions. */
.cart-item .quantity--stepper .qty {
    box-sizing: border-box;
    height: var(--input-height);
    width: 56px;
    padding: 0 var(--space-sm);
    border: 1px solid var(--color-border);
    border-radius: 0;
    text-align: center;
    -moz-appearance: textfield;
}

.cart-item .quantity--stepper .qty::-webkit-outer-spin-button,
.cart-item .quantity--stepper .qty::-webkit-inner-spin-button {
    -webkit-appearance: none;
    margin: 0;
}

.cart-item__line {
    display: flex;
    flex-direction: column;
    align-items: flex-end;
    /* Stretch to the row height and push the remove (×) to the bottom,
       so the price sits at the top and × is pinned down by the stepper. */
    align-self: stretch;
    justify-content: space-between;
    white-space: nowrap;
}

.cart-item__total {
    font-weight: 700;
    color: var(--color-heading);
}

.cart-item__remove {
    width: 32px;
    height: 32px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border: none;
    background: transparent;
    color: var(--color-body-text);
    cursor: pointer;
    border-radius: 50%;
    transition: color var(--transition-fast), background-color var(--transition-fast);
}

.cart-item__remove:hover,
.cart-item__remove:focus-visible {
    color: var(--color-coral);
    background-color: rgba(203, 72, 39, 0.08);
}

.cart-item__remove svg {
    fill: none;
}

.cart-panel__summary {
    margin-top: var(--space-lg);
    display: flex;
    flex-direction: column;
}

/* Spacing as margins (not flex gap) so the minimum notice can slide in/out
   smoothly — its margin animates with its height instead of the gap jumping. */
.cart-panel__summary > .shaya-min-notice,
.cart-panel__summary > .cart-panel__checkout {
    margin-top: var(--space-md);
}

.cart-panel__subtotal {
    display: flex;
    justify-content: space-between;
    align-items: baseline;
    font-family: var(--font-display);
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    color: var(--color-heading);
}

.cart-panel__subtotal-value {
    font-size: 1.25rem;
}

/* Both CTAs reuse the homepage primary-button language. */
.cart-panel__checkout,
.cart-panel__shop-link {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    padding: 0.9rem 2rem;
    font-family: var(--font-display);
    font-weight: 700;
    font-size: 0.875rem;
    letter-spacing: 0.05em;
    text-transform: uppercase;
    border-radius: 4px;
    background-color: var(--color-coral);
    color: var(--color-white);
    text-decoration: none;
    transition: background-color var(--transition-base), color var(--transition-base);
}

.cart-panel__checkout:hover,
.cart-panel__checkout:focus-visible,
.cart-panel__shop-link:hover,
.cart-panel__shop-link:focus-visible {
    background-color: var(--color-dark);
    color: var(--color-white);
}

/* Below the minimum order amount the overlay Checkout is gated. */
.cart-panel__checkout--disabled {
    opacity: 0.45;
    cursor: not-allowed;
    pointer-events: none;
}

/* --- Hide "View Cart" buttons after add-to-cart and in mini-cart --- */
.added_to_cart,
.woocommerce-mini-cart__buttons .wc-forward:not(.checkout):not(.checkout-button) {
    display: none !important;
}

/* --- WooCommerce notices --- */

.woocommerce-message,
.woocommerce-info {
    padding: var(--space-md);
    margin-bottom: var(--space-md);
    border-left: 4px solid var(--color-teal);
    background-color: rgba(43, 170, 177, 0.08);
    border-radius: 4px;
    font-size: 0.875rem;
}

.woocommerce-error {
    padding: var(--space-md);
    margin-bottom: var(--space-md);
    border-left: 4px solid var(--color-coral);
    background-color: rgba(203, 72, 39, 0.08);
    border-radius: 4px;
    font-size: 0.875rem;
}

/* --- WooCommerce pagination --- */

.woocommerce-pagination {
    margin-top: var(--space-xl);
    text-align: center;
}

.woocommerce-pagination ul {
    display: inline-flex;
    gap: var(--space-xs);
}

.woocommerce-pagination .page-numbers {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 36px;
    height: 36px;
    border-radius: 6px;
    font-size: 0.875rem;
    font-weight: 500;
    color: var(--color-heading);
    transition: background-color var(--transition-fast);
}

.woocommerce-pagination .page-numbers:hover {
    background-color: rgba(0, 0, 0, 0.05);
    color: inherit;
}

.woocommerce-pagination .page-numbers.current {
    background-color: var(--color-dark);
    color: var(--color-white);
}

/* --- WooCommerce breadcrumb --- */

.woocommerce-breadcrumb {
    font-family: var(--font-display);
    font-weight: 700;
    font-size: 0.75rem;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    color: var(--color-heading);
    margin-bottom: var(--space-lg);
}

.woocommerce-breadcrumb a {
    color: var(--color-body-text);
    transition: color var(--transition-fast);
}

.woocommerce-breadcrumb a:hover {
    color: var(--color-coral);
}

.woocommerce-breadcrumb__sep {
    color: var(--color-body-text);
    opacity: 0.5;
    margin-inline: var(--space-xs);
}

.woocommerce-breadcrumb__current {
    color: var(--color-coral);
}

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

/* Scope to the <form> — WordPress also puts `woocommerce-checkout` on
   <body> on the checkout page, so an unscoped rule constrained the whole
   page (header gap + non-full-width header/footer). Width + centering
   already come from .page-content__container.container; the form only
   needs vertical rhythm. */
form.woocommerce-checkout {
    padding-block-end: var(--space-2xl);
}

.shaya-checkout__columns {
    display: grid;
    grid-template-columns: 5fr 7fr;
    gap: var(--space-xl);
    align-items: start;
}

.shaya-checkout__empty {
    text-align: center;
    padding: var(--space-2xl) 0;
}

.shaya-checkout__empty p {
    font-size: 1.125rem;
    margin-bottom: var(--space-lg);
    color: var(--color-body-text);
}

.shaya-checkout__heading {
    font-size: 1.125rem;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    margin-bottom: var(--space-lg);
}

/* Billing fields */
.woocommerce-billing-fields label {
    display: block;
    font-size: 0.8125rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    margin-bottom: var(--space-xs);
    color: var(--color-heading);
}

.woocommerce-billing-fields .form-row {
    margin-bottom: var(--space-md);
}

/* Form controls — shared height + light border across the whole checkout
   form (billing + additional fields). Built on the --input-height and
   --color-border tokens so the styling is reusable and matches the
   quantity stepper height. The selectors include .input-text and a body
   scope to out-specify WooCommerce's own default input styling. */
/* :not(.qty) leaves the order-review quantity stepper to its own styles
   (it shares the .input-text class), so it keeps matching the overlay. */
body.woocommerce-checkout form.checkout input.input-text:not(.qty),
body.woocommerce-checkout form.checkout input[type="text"]:not(.qty),
body.woocommerce-checkout form.checkout input[type="email"],
body.woocommerce-checkout form.checkout input[type="tel"],
body.woocommerce-checkout form.checkout input[type="number"]:not(.qty),
body.woocommerce-checkout form.checkout select,
body.woocommerce-checkout form.checkout textarea {
    box-sizing: border-box;
    width: 100%;
    min-height: var(--input-height);
    padding: 0 0.85rem;
    border: 1px solid var(--color-border);
    border-radius: 6px;
    background-color: var(--color-white);
    font-family: inherit;
    font-size: 0.875rem;
    color: var(--color-heading);
    transition: border-color var(--transition-fast);
}

/* Order notes reads like a paragraph — give it height to type into. */
body.woocommerce-checkout form.checkout textarea {
    min-height: 8rem;
    padding-block: 0.75rem;
    line-height: 1.6;
    resize: vertical;
}

body.woocommerce-checkout form.checkout input.input-text:focus,
body.woocommerce-checkout form.checkout input:focus,
body.woocommerce-checkout form.checkout select:focus,
body.woocommerce-checkout form.checkout textarea:focus {
    border-color: var(--color-coral);
    outline: none;
}

/* Review order — reuses the shared .cart-item row styles (see the cart
   overlay) so the checkout list and the header cart read identically.
   No table, so WooCommerce's default .shop_table borders don't apply and
   there are no double separators. */
.shaya-order-review {
    width: 100%;
}

.shaya-order-review .cart-item__remove {
    text-decoration: none;
}

/* Totals: label left, value hard-right — every amount lines up in one
   right-hand column, stacked beneath each other. */
.review-totals {
    margin-top: var(--space-md);
}

.review-totals__row {
    display: flex;
    justify-content: space-between;
    align-items: baseline;
    gap: var(--space-md);
    padding: var(--space-xs) 0;
}

.review-totals__label {
    font-size: 0.8125rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    color: var(--color-body-text);
}

.review-totals__value {
    margin-left: auto;
    font-weight: 700;
    text-align: right;
    white-space: nowrap;
    color: var(--color-heading);
}

.review-totals__row.order-total {
    margin-top: var(--space-xs);
    padding-top: var(--space-md);
    border-top: 1px solid var(--color-border);
}

.review-totals__row.order-total .review-totals__label {
    font-size: 1rem;
    color: var(--color-heading);
}

.review-totals__row.order-total .review-totals__value {
    font-family: var(--font-display);
    font-size: 1.25rem;
}

/* Place Order / WhatsApp button */
.shaya-checkout__submit {
    display: block;
    width: 100%;
    padding: 1rem 2rem;
    margin-top: var(--space-lg);
    font-family: var(--font-display);
    font-weight: 700;
    font-size: 1rem;
    letter-spacing: 0.05em;
    text-transform: uppercase;
    background-color: var(--color-dark);
    color: var(--color-white);
    border: none;
    border-radius: 8px;
    cursor: pointer;
    transition: background-color var(--transition-base);
}

.shaya-checkout__submit:hover {
    background-color: var(--color-coral);
}

.shaya-checkout__submit.disabled {
    opacity: 0.5;
    cursor: not-allowed;
}

/* WhatsApp order CTA — WhatsApp brand green + icon. The id selector
   out-specifies WooCommerce's default .button.alt (its purple) and re-asserts
   the site control height (WC had shrunk #place_order to ~36px). */
body.woocommerce-checkout #place_order.shaya-checkout__submit {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 0.6rem;
    width: 100%;
    min-height: var(--input-height);
    /* margin-bottom (not the Done button's margin-top, which collapses to
       nothing against this dynamically-inserted sibling) creates the gap
       before the Done button + the disclaimers. */
    margin-bottom: var(--space-md);
    padding: 0.9rem 2rem;
    background-color: var(--color-whatsapp);
    color: var(--color-white);
}

body.woocommerce-checkout #place_order.shaya-checkout__submit:hover {
    background-color: var(--color-whatsapp-dark);
}

/* WhatsApp glyph rendered as a pseudo-element so it survives WooCommerce's
   update_checkout AJAX, which re-renders #place_order as plain text. */
body.woocommerce-checkout #place_order.shaya-checkout__submit::before {
    content: "";
    width: 1.35em;
    height: 1.35em;
    flex-shrink: 0;
    background: url("data:image/svg+xml,%3Csvg%20xmlns=%22http://www.w3.org/2000/svg%22%20viewBox=%220%200%2024%2024%22%3E%3Cpath%20fill=%22%23ffffff%22%20d=%22M.057%2024l1.687-6.163a11.867%2011.867%200%200%201-1.587-5.945C.16%205.335%205.495%200%2012.05%200a11.817%2011.817%200%200%201%208.413%203.488%2011.824%2011.824%200%200%201%203.48%208.414c-.003%206.557-5.338%2011.892-11.893%2011.892a11.9%2011.9%200%200%201-5.688-1.449L.057%2024zm6.597-3.807c1.676.995%203.276%201.591%205.392%201.592%205.448%200%209.886-4.434%209.889-9.885.002-5.462-4.415-9.89-9.881-9.892-5.452%200-9.887%204.434-9.889%209.884-.001%202.225.651%203.891%201.746%205.634l-.999%203.648%203.742-.981zm11.387-5.464c-.074-.124-.272-.198-.57-.347-.297-.149-1.758-.868-2.031-.967-.272-.099-.47-.149-.669.149-.198.297-.768.967-.941%201.165-.173.198-.347.223-.644.074-.297-.149-1.255-.462-2.392-1.475-.884-.788-1.482-1.761-1.656-2.059-.173-.297-.018-.458.13-.606.134-.133.297-.347.446-.521.151-.172.2-.296.3-.495.099-.198.05-.372-.025-.521-.075-.148-.669-1.611-.916-2.206-.242-.579-.487-.501-.669-.51l-.57-.01c-.198%200-.52.074-.792.372s-1.04%201.016-1.04%202.479%201.065%202.876%201.213%203.074c.149.198%202.094%203.2%205.076%204.487.709.306%201.263.489%201.694.626.712.226%201.36.194%201.872.118.571-.085%201.758-.719%202.006-1.413.247-.694.247-1.289.173-1.413z%22/%3E%3C/svg%3E") center / contain no-repeat;
}

/* Done button */
/* Secondary "Done" action shown after submitting via WhatsApp. Dark/neutral
   so it sits back behind the green primary. The .button.alt + body scope
   out-specify WooCommerce's default purple button, and it shares the
   WhatsApp CTA's height with a gap above it. */
body.woocommerce-checkout .shaya-checkout__done.button.alt {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 100%;
    min-height: var(--input-height);
    padding: 0.9rem 2rem;
    font-family: var(--font-display);
    font-weight: 700;
    font-size: 1rem;
    letter-spacing: 0.05em;
    text-transform: uppercase;
    background-color: var(--color-dark);
    color: var(--color-white);
    border: none;
    border-radius: 8px;
    cursor: pointer;
    transition: background-color var(--transition-base);
}

body.woocommerce-checkout .shaya-checkout__done.button.alt:hover {
    background-color: var(--color-slate);
}

/* Disclaimers */
.shaya-checkout-disclaimers {
    text-align: center;
    margin-top: var(--space-md);
    font-size: 0.8125rem;
    color: var(--color-body-text);
}

.shaya-checkout-disclaimers p {
    margin-bottom: var(--space-xs);
}

/* Friendly below-minimum notice (theme-owned, see Shaya_Checkout). Shown in
   the checkout order review (between the totals and the payment box) and in
   the cart overlay summary. */
.shaya-min-notice {
    padding: var(--space-sm) var(--space-md);
    background-color: rgba(203, 72, 39, 0.08);
    border-left: 4px solid var(--color-coral);
    border-radius: 4px;
    font-size: 0.875rem;
    color: var(--color-heading);
}

.shaya-min-notice .woocommerce-Price-amount {
    font-weight: 700;
    color: var(--color-coral);
}

/* In checkout the notice lives in the persistent .shaya-min-alert host,
   which checkout.js slides in/out below the Total row. The margin sits on
   the host so it collapses away with the slide when the notice is hidden. */
#order_review .shaya-min-alert {
    margin: var(--space-md) 0;
}

/* Below the minimum, the payment (CTA) box takes the warning's tint to
   reinforce the blocked state. The id selector out-specifies WooCommerce's
   default #payment background. */
#payment.woocommerce-checkout-payment--blocked {
    background-color: rgba(203, 72, 39, 0.08);
    transition: background-color var(--transition-base);
}

/* --- Cart page (/cart/) --- */

/* Product thumbnail — square, like the overlay/checkout. The extra class
   out-specifies WooCommerce's `table.cart img { width:32px }` and the prose
   `.page-content__body img` margin. */
.woocommerce-cart-form .cart_item .product-thumbnail img {
    width: 4rem;
    height: 4rem;
    margin: 0;
    object-fit: cover;
    border-radius: 8px;
    display: block;
}

/* Blur-up wrapper on the cart page (sizes to its 4rem image). */
.product-thumbnail__media {
    display: inline-block;
    vertical-align: top;
    border-radius: 8px;
}

/* Quantity stepper input — segmented, matching the checkout / overlay. */
.woocommerce-cart-form .quantity--stepper .qty {
    box-sizing: border-box;
    height: var(--input-height);
    width: 56px;
    padding: 0 var(--space-sm);
    border: 1px solid var(--color-border);
    border-radius: 0;
    text-align: center;
    -moz-appearance: textfield;
}

.woocommerce-cart-form .quantity--stepper .qty::-webkit-outer-spin-button,
.woocommerce-cart-form .quantity--stepper .qty::-webkit-inner-spin-button {
    -webkit-appearance: none;
    margin: 0;
}

/* Remove (×) moved to the right-hand column; reuses .cart-item__remove. */
.woocommerce-cart-form .product-remove {
    text-align: right;
    width: 1%;
    white-space: nowrap;
}

/* Proceed to checkout — brand coral instead of WooCommerce's default purple. */
.woocommerce-cart .wc-proceed-to-checkout a.checkout-button {
    background-color: var(--color-coral);
    color: var(--color-white);
}

.woocommerce-cart .wc-proceed-to-checkout a.checkout-button:hover {
    background-color: var(--color-dark);
    color: var(--color-white);
}


/* ==========================================================================
   8. Page Templates
   ========================================================================== */

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

.page-content {
    padding: var(--space-xl) 0 var(--space-2xl);
}

.page-content__title {
    font-size: clamp(1.75rem, 4vw, 2.5rem);
    text-transform: uppercase;
    letter-spacing: 0.03em;
    margin-bottom: var(--space-lg);
}

.page-content__meta {
    font-size: 0.8125rem;
    color: var(--color-body-text);
    margin-bottom: var(--space-lg);
}

.page-content__featured-image {
    margin-bottom: var(--space-xl);
    border-radius: 12px;
    overflow: hidden;
}

.page-content__featured-image img {
    width: 100%;
    height: auto;
    display: block;
}

.page-content__body {
    max-width: 800px;
    font-size: 1rem;
    line-height: 1.8;
}

/* Cart/checkout render their own multi-column layouts and need the full
   container width, not the 800px reading measure used for prose pages. */
body.woocommerce-checkout .page-content__body,
body.woocommerce-cart .page-content__body {
    max-width: none;
}

/* These pages aren't prose, so drop the large heading top-margin the
   prose rule adds — it left an oversized gap under the page title. */
body.woocommerce-checkout .page-content__body h2,
body.woocommerce-checkout .page-content__body h3,
body.woocommerce-cart .page-content__body h2,
body.woocommerce-cart .page-content__body h3 {
    margin-top: 0;
}

/* But keep a clear break before the "Additional information" sub-section. */
body.woocommerce-checkout .woocommerce-additional-fields {
    margin-top: var(--space-xl);
}

.page-content__body h2,
.page-content__body h3 {
    margin-top: var(--space-xl);
    margin-bottom: var(--space-md);
}

.page-content__body p {
    margin-bottom: var(--space-md);
}

.page-content__body img {
    border-radius: 8px;
    margin: var(--space-lg) 0;
}

/* Fallback entry (index.php) */
.entry {
    padding: var(--space-xl) 0;
}

.entry__title {
    margin-bottom: var(--space-lg);
}

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

.retailers-page {
    padding-block: var(--space-2xl);
    position: relative;
    isolation: isolate;
    display: flow-root;
}

/* Repeating watermark — same hero-image-shadow treatment as the shop
   page. Multiply blends into the cream backdrop; the pseudo starts
   below the top padding so a clear cream gap shows under the sticky
   header, and runs to the wrapper's bottom (flush against the footer). */
.retailers-page::before {
    content: '';
    position: absolute;
    top: var(--space-xl);
    right: 0;
    bottom: 0;
    left: 0;
    background-image: url('../img/hero/hero-image-shadow.png');
    background-image: image-set(
        url('../img/hero/hero-image-shadow.avif') type('image/avif'),
        url('../img/hero/hero-image-shadow.png') type('image/png'));
    background-repeat: repeat-y;
    background-position: center top;
    background-size: 100% auto;
    mix-blend-mode: multiply;
    pointer-events: none;
    z-index: 0;
}

.retailers-page__container {
    position: relative;
    z-index: 1;
}

/* Match the shop archive title's visual cadence so section headings
   across the site share a single voice. Font-size mirrors the global
   h2 clamp the shop title inherits; margin-bottom mirrors the shared
   section-title cluster (xl). */
.retailers-page__title {
    font-family: var(--font-display);
    font-weight: 700;
    /* Match the Shop page title (shared section-title clamp) so both landing
       pages read consistently, especially on mobile. */
    font-size: clamp(1.75rem, 5vw, 2.5rem);
    text-transform: uppercase;
    letter-spacing: 0.05em;
    text-align: center;
    color: var(--color-heading);
    margin-bottom: var(--space-xl);
}

.retailers-page__empty {
    text-align: center;
    font-family: var(--font-display);
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    color: var(--color-body-text);
    padding-block: var(--space-2xl);
}

/* Mobile-only List/Map tab bar. Hidden at the desktop breakpoint
   below. */
.retailers-page__tabs {
    display: flex;
    justify-content: center;
    gap: var(--space-md);
    margin-bottom: var(--space-lg);
}

.retailers-page__tab {
    flex: 1;
    max-width: 160px;
    padding: 0.65rem 1.25rem;
    font-family: var(--font-display);
    font-weight: 700;
    font-size: 0.75rem;
    text-transform: uppercase;
    letter-spacing: 0.1em;
    border-radius: 2rem;
    border: 1px solid var(--color-dark);
    background-color: transparent;
    color: var(--color-dark);
    cursor: pointer;
    transition: background-color var(--transition-base), color var(--transition-base);
}

.retailers-page__tab.is-active {
    background-color: var(--color-dark);
    color: var(--color-white);
}

/* Explicit focus ring matches the dark-on-cream palette of the page;
   without this, the tabs would fall back to the browser default while
   the rest of the page's interactive elements use a custom one. */
.retailers-page__tab:focus-visible {
    outline: 2px solid var(--color-coral);
    outline-offset: 2px;
}

/* Rail — same soft-fade horizontal scroll as the homepage section,
   but with a vertical card (image on top, name + city below). The
   fade zone is wider here (8rem each side) so the edge cards trail
   off gracefully against the watermarked background. */
.retailers-page__rail {
    display: flex;
    align-items: flex-start;
    gap: var(--space-md);
    overflow-x: auto;
    overflow-y: hidden;
    scroll-snap-type: x mandatory;
    scroll-padding-inline: 8rem;
    padding: 0 8rem var(--space-sm);
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
    -ms-overflow-style: none;
    -webkit-mask-image: linear-gradient(
        to right,
        transparent 0,
        #000 8rem,
        #000 calc(100% - 8rem),
        transparent 100%
    );
    mask-image: linear-gradient(
        to right,
        transparent 0,
        #000 8rem,
        #000 calc(100% - 8rem),
        transparent 100%
    );
}

.retailers-page__rail::-webkit-scrollbar {
    display: none;
}

/* Entry wrapper — pairs the card (button) with a sibling directions
   link so we can render the directions affordance outside the button
   (HTML disallows nesting <a> inside <button>). The wrapper is the
   flex child in the rail; the directions link is hidden there and
   only surfaces in the mobile list. */
.retailers-page__rail .retailer-entry {
    flex: 0 0 160px;
    scroll-snap-align: center;
}

/* Card variant — same component the homepage uses, opened up with
   the --with-city modifier so the name + city stack neatly below
   the photo. */
.retailer-card--with-city {
    width: 100%;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: var(--space-sm);
    padding: var(--space-md) var(--space-sm) var(--space-sm);
    border: 2px solid transparent;
    border-radius: 16px;
    background-color: transparent;
    cursor: pointer;
    text-align: center;
    transition: border-color var(--transition-base), background-color var(--transition-base);
}

/* Action slot — pairs the directions link with a close button that
   appears when the entry is expanded. Both buttons stack in the same
   grid cell so we can cross-fade between them on .is-open. Hidden
   entirely outside the mobile list view (rail doesn't show either). */
.retailer-entry__action {
    display: none;
    flex-shrink: 0;
}

.retailer-entry__directions,
.retailer-entry__close {
    width: 44px;
    height: 44px;
    border-radius: 50%;
    color: var(--color-white);
    border: none;
    cursor: pointer;
    align-items: center;
    justify-content: center;
    text-decoration: none;
    /* Both buttons sit on the same grid cell so they cross-fade. */
    grid-area: action;
    transition:
        opacity var(--transition-base),
        transform var(--transition-base),
        background-color var(--transition-fast);
}

.retailer-entry__directions {
    background-color: var(--color-coral);
    display: inline-flex;
    opacity: 1;
    transform: scale(1);
}

.retailer-entry__close {
    background-color: var(--color-dark);
    display: inline-flex;
    opacity: 0;
    transform: scale(0.7);
    pointer-events: none;
}

.retailer-entry__directions:hover,
.retailer-entry__directions:focus-visible {
    background-color: var(--color-dark);
}

.retailer-entry__close:hover,
.retailer-entry__close:focus-visible {
    background-color: var(--color-coral);
}

.retailer-entry__directions svg,
.retailer-entry__close svg {
    width: 20px;
    height: 20px;
}

.retailer-card--with-city.is-active {
    border-color: var(--color-coral);
    background-color: var(--color-white);
    box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08);
}

.retailer-card--with-city:hover,
.retailer-card--with-city:focus-visible {
    background-color: var(--color-white);
}

/* In the list context the entry wrapper carries the bg + border, so
   the inner card shouldn't double up its own active styling. */
.retailers-page__list .retailer-card--with-city.is-active {
    background-color: transparent;
    box-shadow: none;
    border-color: transparent;
}

.retailer-card__image-wrap {
    width: 120px;
    height: 120px;
    flex-shrink: 0;
    display: flex;
    align-items: center;
    justify-content: center;
}

.retailer-card__text {
    display: flex;
    flex-direction: column;
    gap: 2px;
    align-items: center;
    min-width: 0;
    width: 100%;
}

.retailer-card__name {
    font-family: var(--font-display);
    font-weight: 700;
    font-size: 0.9375rem;
    color: var(--color-heading);
    text-transform: uppercase;
    letter-spacing: 0.04em;
    line-height: 1.2;
    /* break-word keeps the visual rhythm of whole words and only
       splits at character boundaries when no break opportunity
       exists. "anywhere" would split AALIYA'S into AALIYA' / S. */
    overflow-wrap: break-word;
}

.retailer-card__city {
    font-size: 0.8125rem;
    color: var(--color-body-text);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    max-width: 100%;
}

/* Layout: map left, detail panel right (desktop). Default state is
   a single column — the panel column collapses to 0 until JS adds
   .is-open to the detail panel (then :has() reads it and re-expands
   the second column). Animating grid-template-columns gives a smooth
   slide-in. Mobile uses tabs + bottom-sheet, defined below. */
.retailers-page__layout {
    display: grid;
    grid-template-columns: 1fr 0fr;
    gap: 0;
    align-items: stretch;
    margin-top: var(--space-sm);
    transition: grid-template-columns var(--transition-base), gap var(--transition-base);
}

.retailers-page__layout:has(.retailers-page__detail.is-open) {
    grid-template-columns: 1fr 360px;
    gap: var(--space-lg);
}

.retailers-page__map-wrap {
    position: relative;
}

.retailers-page__map {
    width: 100%;
    height: 520px;
    border-radius: 16px;
    overflow: hidden;
    background-color: var(--color-cream);
}

.retailers-page__map-fallback {
    text-align: center;
    color: var(--color-body-text);
    padding: var(--space-2xl) var(--space-lg);
    background-color: var(--color-cream);
    border-radius: 16px;
}

/* Detail panel. Hidden by default; .is-open (added by JS on selection)
   fades + slides it in. The grid layout above shrinks its column to 0
   when not .is-open, so this panel's own opacity + transform animation
   stacks on top of that for a coordinated entry/exit. */
.retailers-page__detail {
    position: relative;
    background-color: transparent;
    border-radius: 16px;
    padding: var(--space-lg);
    overflow: hidden;
    opacity: 0;
    transform: translateX(20px);
    visibility: hidden;
    transition:
        opacity var(--transition-base),
        transform var(--transition-base),
        visibility 0s linear var(--transition-base);
}

.retailers-page__detail.is-open {
    opacity: 1;
    transform: translateX(0);
    visibility: visible;
    transition:
        opacity var(--transition-base),
        transform var(--transition-base),
        visibility 0s;
}

.retailers-page__detail-close {
    position: absolute;
    top: var(--space-sm);
    right: var(--space-sm);
    width: 36px;
    height: 36px;
    border-radius: 50%;
    background-color: var(--color-white);
    border: none;
    cursor: pointer;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    box-shadow: 0 2px 6px rgba(0, 0, 0, 0.12);
    z-index: 2;
    transition: opacity var(--transition-fast);
}

.retailers-page__detail-close:hover,
.retailers-page__detail-close:focus-visible {
    opacity: 0.75;
}

.retailers-page__detail-close svg {
    width: 14px;
    height: 14px;
    color: var(--color-dark);
    fill: none;
}

.retailers-page__detail-content {
    display: flex;
    flex-direction: column;
    align-items: center;
    text-align: center;
    gap: var(--space-md);
}

/* The explicit display rules above (inline-flex / flex) have the same
   specificity as the UA's *[hidden] { display: none } and would win the
   cascade tie, defeating the JS .hidden toggles. Restore [hidden]'s
   intent explicitly so the panel's inner elements actually hide when
   no retailer is selected. */
.retailers-page__detail-close[hidden],
.retailers-page__detail-content[hidden] {
    display: none;
}

/* Square + round container so round retailer logos sit inside without
   the previous "cover" crop. object-fit:contain lets logos with their
   own padding/background render whole. The white backdrop fills the
   corners when a non-square logo is used. */
.retailers-page__detail-image {
    width: 160px;
    height: 160px;
    border-radius: 50%;
    object-fit: contain;
    background-color: var(--color-white);
    padding: var(--space-sm);
    box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08);
}

.retailers-page__detail-name {
    font-family: var(--font-display);
    font-weight: 700;
    font-size: 1.25rem;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--color-heading);
    margin: 0;
    line-height: 1.2;
}

.retailers-page__detail-city {
    font-size: 0.9375rem;
    color: var(--color-body-text);
    margin: 0;
}

.retailers-page__detail-address {
    font-style: normal;
    font-size: 0.9375rem;
    line-height: 1.6;
    color: var(--color-heading);
}

.retailers-page__detail-contact {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: var(--space-xs);
    font-size: 0.9375rem;
}

.retailers-page__detail-contact-link {
    color: var(--color-coral);
    text-decoration: none;
    transition: color var(--transition-fast);
}

.retailers-page__detail-contact-link:hover {
    color: var(--color-dark);
}

.retailers-page__detail-hours {
    font-size: 0.875rem;
    color: var(--color-body-text);
    white-space: pre-line;
    margin: 0;
}

.retailers-page__detail-cta {
    align-self: stretch;
    width: 100%;
    margin-top: var(--space-sm);
}

/* Mobile list — vertical column of cards in a horizontal layout each
   (image left, name + city right). Visible only on the mobile List
   tab. */
.retailers-page__list {
    display: flex;
    flex-direction: column;
    gap: var(--space-md);
    margin-top: var(--space-sm);
}

/* The entry wrapper becomes the row container in the list — pairs
   the card on the left with the directions affordance on the right.
   Card itself loses its own background + padding (the wrapper owns
   them now) and stretches to take all available horizontal space.
   A transparent border is preallocated so the .is-open coral border
   doesn't cause a layout shift. */
.retailers-page__list .retailer-entry {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    column-gap: var(--space-md);
    row-gap: 0;
    background-color: var(--color-white);
    padding: var(--space-md);
    border: 2px solid transparent;
    border-radius: 16px;
    transition: border-color var(--transition-fast);
}

.retailers-page__list .retailer-entry.is-open {
    border-color: var(--color-coral);
}

.retailers-page__list .retailer-card--with-city {
    flex: 1;
    flex-direction: row;
    align-items: center;
    gap: var(--space-md);
    text-align: left;
    background-color: transparent;
    padding: 0;
    border: none;
    width: auto;
}

.retailers-page__list .retailer-card__image-wrap {
    width: 72px;
    height: 72px;
}

.retailers-page__list .retailer-card__text {
    align-items: flex-start;
    flex: 1;
}

.retailers-page__list .retailer-entry__action {
    display: grid;
    grid-template-areas: "action";
    width: 44px;
    height: 44px;
}

/* On expand: fade out the directions button, fade in the close button.
   Both stack in the same grid cell so swap reads as a single tap target
   morphing. */
.retailers-page__list .retailer-entry.is-open .retailer-entry__directions {
    opacity: 0;
    transform: scale(0.7);
    pointer-events: none;
}

.retailers-page__list .retailer-entry.is-open .retailer-entry__close {
    opacity: 1;
    transform: scale(1);
    pointer-events: auto;
}

/* Inline expansion: each list entry can grow to reveal the same
   detail content the desktop panel shows. grid-template-rows
   transitions from 0fr → 1fr on .is-open so the height animates
   without us having to guess a max-height per retailer. */
.retailer-entry__details {
    display: none;
}

.retailers-page__list .retailer-entry__details {
    display: grid;
    grid-template-rows: 0fr;
    width: 100%;
    transition: grid-template-rows var(--transition-base);
}

.retailers-page__list .retailer-entry.is-open .retailer-entry__details {
    grid-template-rows: 1fr;
}

.retailer-entry__details-inner {
    overflow: hidden;
    min-height: 0;
    display: flex;
    flex-direction: column;
    align-items: center;
    text-align: center;
    gap: var(--space-md);
}

.retailers-page__list .retailer-entry.is-open .retailer-entry__details-inner {
    padding-top: var(--space-md);
    border-top: 1px solid rgba(0, 0, 0, 0.08);
    margin-top: var(--space-sm);
}

/* Desktop: hide the mobile-specific surfaces. */
@media (min-width: 768px) {
    .retailers-page__tabs {
        display: none;
    }
    .retailers-page__list {
        display: none;
    }
}

/* Mobile: swap tabs via the wrapper's data-active-tab attribute.
   Detail panel transitions to a bottom-sheet overlay. */
@media (max-width: 767px) {
    /* Mobile watermark: bigger background-size so the vertical tiles
       seam less often on a narrow viewport (matches the shop page). */
    .retailers-page::before {
        background-size: 200% auto;
    }

    /* Tighten the bottom gap to the footer on mobile. The page-level
       2xl bottom padding is too generous on a narrow viewport — leaves
       a big empty band under the rail (no selection) or under the
       detail panel (selection open). Top padding stays as-is so the
       title still gets its breathing room under the sticky header. */
    .retailers-page {
        padding-bottom: var(--space-md);
    }

    /* List view has its own visual cadence: the long vertical column
       butts straight against the footer with the tight md padding,
       which feels cramped. Restore a proper breath of space below the
       last list entry. */
    .retailers-page[data-active-tab="list"] {
        padding-bottom: var(--space-xl);
    }

    /* Card sizing: the rail's flex-child is now .retailer-entry (the
       wrapper that pairs the card with its directions link), so the
       fixed-width rule moves to the wrapper. Wider on mobile than
       before so the name doesn't crowd against the card edges. */
    .retailers-page__rail .retailer-entry {
        flex: 0 0 170px;
    }

    .retailers-page__rail .retailer-card__image-wrap,
    .retailers-page__rail .retailer-card__image,
    .retailers-page__rail .retailer-card__placeholder {
        width: 110px;
        height: 110px;
    }

    .retailers-page__rail {
        gap: var(--space-md);
        padding: var(--space-sm) 2rem var(--space-md);
        scroll-padding-inline: 2rem;
        -webkit-mask-image: linear-gradient(
            to right,
            transparent 0,
            #000 2rem,
            #000 calc(100% - 2rem),
            transparent 100%
        );
        mask-image: linear-gradient(
            to right,
            transparent 0,
            #000 2rem,
            #000 calc(100% - 2rem),
            transparent 100%
        );
    }

    /* Layout dissolves on mobile — its children (map + detail panel)
       become direct flex children of .retailers-page__container so we
       can re-order them alongside the rail. The .is-open rule below
       restores 2-column-style behaviour for inline display. */
    .retailers-page__layout {
        display: contents;
    }

    .retailers-page__map {
        height: 400px;
    }

    /* Tab visibility. The wrapper's data-active-tab attribute is the
       single source of truth; CSS just reads it. Hiding the layout
       parent also hides its dissolved children (map + detail). */
    .retailers-page[data-active-tab="list"] .retailers-page__rail,
    .retailers-page[data-active-tab="list"] .retailers-page__map-wrap,
    .retailers-page[data-active-tab="list"] .retailers-page__detail {
        display: none;
    }
    .retailers-page[data-active-tab="map"] .retailers-page__list {
        display: none;
    }

    /* Flex column on the container lets us assign explicit orders to
       the rail (sibling) and to the map / detail (children of the
       display:contents layout, which now flow as direct children). */
    .retailers-page__container {
        display: flex;
        flex-direction: column;
    }

    /* On Map tab, the visual sequence is: map → rail → detail (only
       when a retailer is selected). Source order is rail, then layout
       (map, detail); we override with order so map comes first. */
    .retailers-page[data-active-tab="map"] .retailers-page__map-wrap {
        order: 1;
    }
    .retailers-page[data-active-tab="map"] .retailers-page__rail {
        order: 2;
        margin-top: var(--space-md);
    }
    .retailers-page[data-active-tab="map"] .retailers-page__detail {
        order: 3;
        /* Breathing room between the rail (order 2) and the detail
           panel so they don't feel glued together. */
        margin-top: var(--space-lg);
    }

    /* When no retailer is selected, collapse the detail panel's layout
       footprint so the rail sits close to the footer. The aside uses
       visibility:hidden (not display:none) to keep the slide-in
       animation, which means its padding + margin still reserve space
       otherwise. .is-open restores the spacing via the rules above. */
    .retailers-page[data-active-tab="map"] .retailers-page__detail:not(.is-open) {
        padding: 0;
        margin-top: 0;
    }

    /* Inline detail on mobile Map tab — appears in normal document
       flow underneath the map (the layout grid stacks as a single
       column on mobile), instead of a fixed bottom-sheet overlay.
       The slide-up animation stays so the panel feels like it's
       arriving rather than blinking in. */
    .retailers-page__detail {
        background-color: transparent;
        transform: translateY(20px);
    }

    .retailers-page__detail.is-open {
        transform: translateY(0);
    }

    /* List tab: the panel can stay hidden via its untriggered state. */
    .retailers-page[data-active-tab="list"] .retailers-page__detail {
        display: none;
    }
}

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

.error-404 {
    min-height: 60vh;
    display: flex;
    align-items: center;
    justify-content: center;
    text-align: center;
}

.error-404__title {
    font-size: clamp(5rem, 15vw, 10rem);
    font-weight: 900;
    color: var(--color-peach);
    line-height: 1;
    margin-bottom: var(--space-md);
}

.error-404__message {
    font-size: 1.125rem;
    color: var(--color-body-text);
    margin-bottom: var(--space-xl);
}


/* ==========================================================================
   9. Responsive
   ========================================================================== */

/* Mobile: up to 767px */
@media (max-width: 767px) {
    :root {
        --header-height: 76px;
    }

    /* Mobile: revert to flex so the logo sits on the left,
       actions on the right (no empty grid column). */
    .site-header__nav {
        display: flex;
        justify-content: space-between;
    }

    /* The mobile menu is always laid out (position:absolute, so no flow
       impact) but hidden behind the sticky header and slid up out of view;
       .is-open slides it down. Animating transform/opacity rather than
       toggling display lets it animate both in AND out. The sticky header
       (z-100) masks the menu (z-99) while it sits up behind it. */
    /* Clip box pinned just below the header. The menu slides within it, so it
       emerges from underneath the header bar (which stays on top — the logo is
       never covered) instead of sliding over it. */
    .site-header__menu-wrap {
        display: block;
        position: absolute;
        top: var(--header-height);
        left: 0;
        right: 0;
        z-index: 99;
        overflow: hidden;
        /* Bottom room so the card's drop shadow isn't clipped; the top stays
           clipped so the menu tucks up behind the header bar. */
        padding: 0 0 var(--space-md);
        pointer-events: none;
    }

    .site-header__hamburger {
        display: flex;
    }

    .site-header__menu--left {
        display: flex;
        flex-direction: column;
        gap: var(--space-xs);
        width: 100%;
        background-color: var(--color-white);
        padding: var(--space-md) var(--container-padding) var(--space-lg);
        box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08);
        transform: translateY(-100%);
        opacity: 0;
        visibility: hidden;
        pointer-events: none;
        transition: transform var(--transition-base),
                    opacity var(--transition-base),
                    visibility var(--transition-base);
    }

    .site-header__menu--left.is-open {
        transform: translateY(0);
        opacity: 1;
        visibility: visible;
        pointer-events: auto;
    }

    /* Block so each link fills its row — the link (not the <li>) carries the
       active/hover background, so without this the dark pill is only
       content-wide and juts left of the other items' text. Kept outside
       .is-open so the rows don't reflow mid-close-animation. */
    .site-header__menu--left .site-header__link {
        display: block;
        padding: 0.75rem 1rem;
        font-size: 0.875rem;
        border-radius: 8px;
    }

    .site-header__logo img,
    .site-header__logo-img {
        height: 40px;
    }

    /* Homepage mobile hero. The watermark now tiles from the top (see the base
       rule), so no bottom offset is needed here. Phones are tall and narrow:
       nudge the graffiti down and pull the slogan up so the title + tagline
       sit as one balanced, centered composition instead of drifting apart. */
    .hero__layer--graffiti {
        /* 90% (not 95%) leaves a little breathing room so the wide "KOMBUCHA"
           wordmark doesn't kiss the left/right screen edges. */
        width: min(90%, 520px);
        top: 44%;
    }

    .hero__layer--slogan {
        width: min(80%, 320px);
        top: 66%;
    }

    .flavors__grid {
        grid-template-columns: repeat(3, 1fr);
        gap: var(--space-lg) var(--space-md);
    }

    .flavor-icon__emblem {
        width: 128px;
        height: 128px;
    }

    .flavor-icon__name {
        font-size: 0.8125rem;
    }

    .products-showcase__grid,
    ul.products {
        grid-template-columns: repeat(2, 1fr);
        /* Generous row gap so the emblems that overhang each card (top: -42px)
           clear the card above instead of crowding it — the old 1rem gap left
           them colliding and made the grid feel cramped. */
        gap: var(--space-xl) var(--space-md);
    }

    .product-card {
        /* Mobile emblem overhang is 42px; same +16px breathing buffer. */
        scroll-margin-top: 58px;
    }

    .product-card__emblem {
        width: 72px;
        height: 72px;
        top: -42px;
    }

    .product-card__name {
        font-size: 0.875rem;
        bottom: 2.5%;
    }

    /* Mobile watermark: at 100% viewport width the tiles are narrow
       and the vertical seams stack up too often on long catalogues.
       Bump the image size so each tile fills more of the viewport
       and the vertical repeat is calmer. */
    .shop-archive::before {
        background-size: 200% auto;
    }

    .about-teaser__photos {
        grid-template-columns: 1fr;
        gap: var(--space-md);
    }

    .about-teaser__caption {
        font-size: 0.95rem;
        padding: var(--space-sm) var(--space-md);
    }

    .about-teaser__blob {
        /* No room for atmospheric decoration on phones — clips into content
           or eats the section's visual real estate. */
        display: none;
    }

    .retailers__rail {
        gap: 1.75rem;
        /* Symmetric top/bottom so the caption-to-logos and logos-to-CTA gaps
           match (#5). */
        padding: var(--space-lg) 2rem;
        scroll-padding-inline: 2rem;
        -webkit-mask-image: linear-gradient(
            to right,
            transparent 0,
            #000 2rem,
            #000 calc(100% - 2rem),
            transparent 100%
        );
        mask-image: linear-gradient(
            to right,
            transparent 0,
            #000 2rem,
            #000 calc(100% - 2rem),
            transparent 100%
        );
    }

    /* Scoped to .retailers__rail — these size rules are for the homepage
       retailers badge (an 80×80 circular logo). The retailers-page rail
       uses the .retailer-card--with-city variant, which is a tall column
       layout and must not be clamped to 80×80. */
    .retailers__rail .retailer-card,
    .retailers__rail .retailer-card__image,
    .retailers__rail .retailer-card__placeholder {
        width: 104px;
        height: 104px;
    }

    .retailers__rail .retailer-card {
        flex-basis: 104px;
    }

    .product-details {
        grid-template-columns: 1fr;
        gap: var(--space-lg);
    }

    /* Mobile order: info first (title + description + add-to-cart),
       gallery underneath. Desktop keeps source order via the 1-1 grid. */
    .product-details__info {
        order: 1;
    }

    .product-details__gallery {
        order: 2;
    }

    .product-details__title {
        font-size: clamp(1.75rem, 7vw, 2.5rem);
    }

    /* Keep the [label] [select] [price] row layout on mobile too — the
       price should sit next to the size select, not stack below it. */
    .product-details .variation-price-display {
        font-size: 1.125rem;
    }

    /* Quantity row mirrors the SIZE row on mobile so the stepper isn't
       orphaned: a QUANTITY label under SIZE, the stepper under the size
       dropdown, and the add-to-cart button full-width below. --pd-label-col
       fixes the shared label column so SIZE and QUANTITY line up (QUANTITY is
       wider than the default content-sized column). */
    .product-details {
        --pd-label-col: 6rem;
    }

    .product-details .variations tr {
        grid-template-columns: var(--pd-label-col) 1fr auto;
    }

    .product-details .woocommerce-variation-add-to-cart,
    .product-details form.cart:not(.variations_form) {
        display: grid;
        grid-template-columns: var(--pd-label-col) 1fr;
        align-items: center;
        gap: var(--space-md);
    }

    .product-details .woocommerce-variation-add-to-cart::before,
    .product-details form.cart:not(.variations_form)::before {
        content: var(--shaya-qty-label, "Quantity");
        font-family: var(--font-display);
        font-size: 0.8125rem;
        font-weight: 700;
        text-transform: uppercase;
        letter-spacing: 0.06em;
        color: var(--color-heading);
    }

    .product-details .woocommerce-variation-add-to-cart .quantity--stepper,
    .product-details form.cart:not(.variations_form) .quantity--stepper {
        justify-self: start;
    }

    .product-details .single_add_to_cart_button.button.alt {
        grid-column: 1 / -1;
    }

    /* Tighten the SIZE -> QUANTITY gap so it matches the QUANTITY -> CTA gap.
       WooCommerce reveals the (empty, price-clipped) .single_variation a moment
       after load — inline display:block via slideDown — which would re-introduce
       a flex gap before the quantity row (the gap "grows after a second"). Zero
       the wrap gap so that reveal can't change spacing; the top margin alone
       sets the SIZE -> QUANTITY gap. */
    .product-details .single_variation_wrap {
        margin-top: var(--space-sm);
        gap: 0;
    }

    /* The wrap gap is 0 now, so the inline add-to-cart error keeps its own gap. */
    .product-details .shaya-add-to-cart-error {
        margin-top: var(--space-md);
    }

    /* Pull the gallery a little closer beneath the add-to-cart button. */
    .product-modal__inner .product-details {
        gap: calc(var(--space-xl) - var(--space-md));
    }

    .product-modal__inner,
    .cart-modal__inner {
        border-radius: 16px;
    }

    .product-modal__content,
    .cart-modal__content {
        padding: var(--space-lg);
    }

    /* Checkout mobile */
    .shaya-checkout__columns {
        grid-template-columns: 1fr;
    }

    form.woocommerce-checkout {
        padding-block-end: var(--space-xl);
    }

    .store-locator__map {
        height: 300px;
    }

    .store-card__inner {
        flex-wrap: wrap;
    }

    .site-footer__grid {
        grid-template-columns: 1fr;
        /* Tighter once stacked so the copyright sits closer to the
           social/contact block instead of across a wide void (#7). */
        gap: var(--space-lg);
        text-align: center;
    }

    .site-footer__brand {
        align-items: center;
    }

    .site-footer__contacts {
        justify-self: center;
        align-items: flex-start;
    }
}

/* Tablet: 768px to 1023px */
@media (min-width: 768px) and (max-width: 1023px) {
    .products-showcase__grid,
    ul.products {
        grid-template-columns: repeat(2, 1fr);
    }

    .about-teaser__container {
        gap: var(--space-lg);
    }
}

/* Focus indicators */
:focus-visible {
    outline: 2px solid var(--color-coral);
    outline-offset: 2px;
}

.btn:focus-visible,
.site-header__link:focus-visible,
.site-header__cart:focus-visible,
.shaya-checkout__submit:focus-visible,
.shaya-checkout__done:focus-visible,
.product-card:focus-visible,
.flavor-icon:focus-visible {
    outline: 2px solid var(--color-coral);
    outline-offset: 2px;
}

.woocommerce-billing-fields input:focus-visible,
.woocommerce-billing-fields select:focus-visible,
.store-locator__search-input:focus-visible,
.quantity .qty:focus-visible,
.variations td.value select:focus-visible {
    outline: 2px solid var(--color-coral);
    outline-offset: -1px;
    border-color: var(--color-coral);
}

/* Reduced motion */
@media (prefers-reduced-motion: reduce) {
    *,
    *::before,
    *::after {
        animation-duration: 0.01ms !important;
        animation-iteration-count: 1 !important;
        transition-duration: 0.01ms !important;
        scroll-behavior: auto !important;
    }
}

