/* =========================================================================
   Storefront design system
   -------------------------------------------------------------------------
   Palette:
     brand    #129fe5  primary actions, links, active nav, badges
     price    #f9475b  product display price (red keeps savings legible
                       against the blue brand)
     deal     #ff4400  promotional price, urgency accents
     amber    #ffb400  review stars
     surface  #ffffff on a white page (grey only as subtle bands/controls)

   Surfaces are borderless — no outlines, no rings. A surface is located by
   TONE and depth: cards are WHITE on a white page lifted by the elevation
   tokens (--sf-shadow-xs..lg), each of which pairs an ambient 0-offset layer
   with a downward key light. The ambient layer is what defines the TOP edge —
   a downward-only shadow leaves the top of a card bare, so a white card looks
   like it has no top and blends into the background. Blurred and low-alpha it
   reads as ambient occlusion, not a line: a 1px ring on .sf-panel was tried at
   .10 then .07 and rejected twice as "too strong". Headers of panels/sections
   use a filled band (--sf-fill) to separate head from body by tone.
   Inputs and chips use a filled style (--sf-fill) that resolves to white plus
   a brand focus ring.

   Spacing is deliberately generous — a 4px-based scale with large card
   padding and grid gaps so nothing reads as cramped.

   Every rule is scoped under `.sf` (set on <body>). The Tailwind Play CDN
   injects its <style> at RUNTIME, i.e. after this file's <link>, so a bare
   `.card` rule would lose to Tailwind utilities at equal specificity.
   `.sf .card` (0,2,0) beats `.p-4` (0,1,0) regardless of insertion order.
   ========================================================================= */

/* -------------------------------------------------------------------------
   1. Design tokens
   ------------------------------------------------------------------------- */
/*
 * Page canvas is WHITE, matching <body>. Do NOT paint this the topbar's blue:
 * the canvas is what shows behind the page during overscroll and on any area
 * the body does not cover, so a coloured canvas reads as "the whole background
 * is blue". The notch is handled instead by the topbar's own safe-area
 * padding-height (see §4) plus a matching `theme-color` meta.
 *
 * Hard-coded on purpose: the tokens live on `.sf` (the <body>), so
 * `var(--sf-page)` is not visible from <html>.
 */
html {
    background-color: #ffffff;
}

.sf {
    /* Brand */
    --sf-brand: #129fe5;
    --sf-brand-dark: #0d86c2;
    --sf-brand-deep: #0a6fa4;
    --sf-brand-soft: #e6f5fd;
    --sf-brand-tint: #f3fafe;

    /* Price + promotion */
    --sf-price: #f9475b;
    --sf-price-deal: #ff4400;
    --sf-buy: #ff6a00;
    --sf-buy-dark: #e85d00;
    --sf-buy-soft: #fff1e6;
    --sf-save: #16a34a;

    /* Accents */
    --sf-amber: #ffb400;
    --sf-teal: #0f9d8f;
    --sf-heading: #0f172a;
    --sf-link: #129fe5;

    /* Neutrals */
    --sf-ink: #020617;
    --sf-ink-2: #2e3a4e;
    --sf-muted: #4a5870;
    --sf-muted-2: #8192a8;
    --sf-line: #e9edf2;
    --sf-line-strong: #dbe2ea;
    --sf-fill: #f1f5f9;
    --sf-page: #ffffff;
    --sf-surface: #ffffff;
    --sf-surface-2: #f8fafc;
    /*
     * Utility bar (`.sf-topbar`). In LIGHT mode it is the quiet grey band
     * (--sf-fill, the same token `.sf-usps` and panel heads use). In DARK mode
     * §27 re-points it at --sf-surface so the bar is the SAME colour as
     * `.sf-header` and the two read as one block of chrome. It is a token
     * rather than a `.sf-topbar` override so the two can never drift apart.
     */
    --sf-topbar-bg: var(--sf-fill);

    /* Spacing scale (4px base) */
    --sf-sp-1: 4px;
    --sf-sp-2: 8px;
    --sf-sp-3: 12px;
    --sf-sp-4: 16px;
    --sf-sp-5: 20px;
    --sf-sp-6: 24px;
    --sf-sp-8: 32px;
    --sf-sp-10: 40px;
    --sf-sp-12: 48px;

    /* Shared gutter for page columns and their dividers. */
    --sf-gutter: var(--sf-sp-6);

    /* Radii — generous, modern */
    --sf-radius-sm: 10px;
    --sf-radius: 14px;
    --sf-radius-lg: 20px;

    /* Elevation — soft and diffuse rather than hard 1px borders.
       Every card-level level pairs an AMBIENT layer (0 offset, no spread, small
       blur) with a downward KEY layer. The ambient layer is NOT optional: a
       downward-only shadow leaves the TOP edge of a card with no shadow at all,
       so a white card on a white page reads as having no top and blends into
       the background. Blurred and low-alpha it behaves as ambient occlusion
       rather than a line — which is why it works where a 1px ring (tried at .10,
       then .07) was rejected twice as "too strong". Keep the 0-offset layer on
       every card-level shadow. --sf-shadow / --sf-shadow-lg (dropdowns, modals)
       deliberately keep their stronger directional key light without it. */
    --sf-shadow-xs: 0 0 4px rgba(15, 23, 42, .06),
        0 1px 2px rgba(15, 23, 42, .05),
        0 2px 8px -2px rgba(15, 23, 42, .07);
    --sf-shadow-sm: 0 0 6px rgba(15, 23, 42, .08),
        0 1px 2px rgba(15, 23, 42, .05),
        0 6px 16px -6px rgba(15, 23, 42, .12);
    --sf-shadow: 0 2px 4px rgba(15, 23, 42, .03), 0 14px 32px -14px rgba(15, 23, 42, .16);
    --sf-shadow-lg: 0 4px 8px rgba(15, 23, 42, .04), 0 28px 56px -20px rgba(15, 23, 42, .22);

    /* Page width — 1360px keeps a small margin on 1366px laptops (the #2
       desktop resolution) while still filling 71% of the dominant 1920×1080
       desktop. Fluid below, so smaller screens just fill the viewport. */
    --sf-container: 1360px;
    --sf-header-h: 76px;
    --sf-ease: cubic-bezier(.2, .7, .3, 1);

    --sf-font: 'Inter', 'Noto Sans TC', system-ui, -apple-system, 'Segoe UI',
        Roboto, 'PingFang HK', 'Microsoft JhengHei', 'Helvetica Neue', Arial, sans-serif;
}

/* -------------------------------------------------------------------------
   2. Base
   ------------------------------------------------------------------------- */
/*
 * `box-sizing` is declared HERE so this stylesheet is self-sufficient.
 *
 * Until now it came only from Tailwind Play CDN's Preflight
 * (`*, ::before, ::after { box-sizing: border-box }`), which the layout loads
 * from a third party at RUNTIME. If that request ever fails (offline, CSP,
 * CDN outage) `.sf-container` — `width: 100%` PLUS `padding-inline` — overflows
 * its parent by exactly 32px and every storefront page scrolls sideways.
 *
 * Value and specificity deliberately match Preflight exactly (0,0,0), so this
 * changes nothing while the CDN is healthy and is a floor when it is not. It
 * also lets this design system be used on a page that loads no Tailwind.
 */
*,
*::before,
*::after {
    box-sizing: border-box;
}

.sf,
.sf body {
    background: var(--sf-page);
    color: var(--sf-ink);
    font-family: var(--sf-font);
    font-size: 15px;
    line-height: 1.65;
    -webkit-font-smoothing: antialiased;
}

/*
 * NOTE: use `:where()` so this base rule has specificity (0,1,0), not (0,1,1).
 * A plain `.sf h1` would OUTRANK component classes like `.sf-hero__title`
 * (0,1,0) and force near-black ink onto white-on-gradient headings.
 */
.sf :where(h1, h2, h3, h4) {
    color: var(--sf-ink);
    font-weight: 700;
    line-height: 1.35;
    letter-spacing: -.01em;
}

/*
 * NOTE: `:where()` keeps this base rule at (0,1,0), not (0,1,1). A plain
 * `.sf img` would OUTRANK single-class img rules like `.sf-logo__img` /
 * `.sf-footer__logo` (0,1,0) and force `height: auto` onto them — which is
 * exactly how the logo was rendering at its natural 40px instead of 27px.
 * Component img rules that set their own size still win by source order.
 */
.sf :where(img) {
    max-width: 100%;
    height: auto;
}

/*
 * Do NOT add `color: inherit` here. `.sf a` has specificity (0,1,1), which
 * outranks Tailwind's single-class text utilities (0,1,0) — so a link written
 * as `class="bg-indigo-600 text-white"` would keep INHERITED dark text on a
 * blue background. Tailwind's Preflight already sets `a { color: inherit }`
 * at (0,0,1), so inheritance still works without outranking the utilities.
 */
.sf a {
    text-decoration: none;
}

.sf a:hover {
    text-decoration: none;
}

.sf :focus-visible {
    outline: 2px solid var(--sf-brand);
    outline-offset: 2px;
    border-radius: 4px;
}

/* -------------------------------------------------------------------------
   3. Layout primitives
   ------------------------------------------------------------------------- */
.sf-container {
    width: 100%;
    max-width: var(--sf-container);
    margin-inline: auto;
    padding-inline: var(--sf-sp-4);
}

@media (min-width: 768px) {
    .sf-container {
        padding-inline: var(--sf-sp-6);
    }
}

.sf-main {
    padding-block: var(--sf-sp-8) var(--sf-sp-12);
}

/* Pages with a hero / big image right under the nav need less top padding. */
.sf-main--tight {
    padding-top: var(--sf-sp-4);
}

/*
 * No top padding at all. For pages whose FIRST child already supplies its own
 * top spacing — a full-bleed band, a hero, a sticky toolbar — where the default
 * --sf-sp-8 would stack with it and open a dead gap under the header.
 * Bottom padding is untouched: that gap (before the USP strip) is still wanted.
 * Same family as --tight, one step further; opt in via the layout's $mainClass.
 */
.sf-main--flush {
    padding-top: 0;
}

/*
 * Sticky header wrapper removed (2026-09): the whole header+nav used to pin
 * together on scroll; now only `.sf-nav` is sticky (see §6) and the scroll
 * shadow class moved to `.sf-nav--scrolled`.
 */

/* -------------------------------------------------------------------------
   4. Top utility bar
   ------------------------------------------------------------------------- */
.sf-topbar {
    /*
     * Grey, not brand blue. `--sf-fill` is the design system's "light grey
     * band" token (same one `.sf-usps` and panel heads use); `--sf-surface-2`
     * is too pale to read as a band. Everything below therefore uses INK
     * tokens for text — white on this background would be unreadable.
     *
     * Deliberately the QUIETEST band in the chrome: 12px type in --sf-muted,
     * on a 32px row. It is a utility strip, so it should read as a footnote to
     * the header rather than compete with it.
     *
     * The colour comes from --sf-topbar-bg because DARK mode needs this bar to
     * match `.sf-header` exactly (see the token's declaration and §27).
     */
    background: var(--sf-topbar-bg);
    color: var(--sf-muted);
    font-size: 12px;
    /*
     * `viewport-fit=cover` lets the page paint under the iOS notch/status bar,
     * and the page canvas is white — so the BAR itself has to fill that strip
     * with its own colour, or a white band shows above the bar. Zero on every
     * device without an inset (all desktop, most Android).
     */
    padding-top: env(safe-area-inset-top, 0px);
}

.sf-topbar__inner {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--sf-sp-4);
    min-height: 32px;
}

.sf-topbar__promo {
    display: flex;
    align-items: center;
    gap: var(--sf-sp-2);
    overflow: hidden;
    white-space: nowrap;
    text-overflow: ellipsis;
}

.sf-topbar__promo strong {
    color: var(--sf-ink-2);
    font-weight: 600;
}

/* Back-to-main-site link pinned to the far left of the utility bar. */
.sf-topbar__back {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    flex-shrink: 0;
    color: var(--sf-muted);
    font-weight: 500;
    transition: color .18s var(--sf-ease);
}

.sf-topbar__back svg {
    width: 14px;
    height: 14px;
}

.sf-topbar__back:hover {
    color: var(--sf-ink-2);
}

.sf-topbar__actions {
    display: flex;
    align-items: center;
    gap: var(--sf-sp-5);
    flex-shrink: 0;
}

.sf-topbar__link {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    color: var(--sf-muted);
    transition: color .18s var(--sf-ease);
}

.sf-topbar__link:hover {
    color: var(--sf-ink-2);
}

/*
 * Language switcher lives in the grey utility bar (moved out of the header to
 * free room on mobile). Compact ghost button; the dropdown panel itself is the
 * standard white `.sf-dropdown`.
 */
.sf-topbar__lang {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 2px 6px;
    border: 0;
    border-radius: 8px;
    background: none;
    color: var(--sf-muted);
    font-family: inherit;
    font-size: 12px;
    font-weight: 500;
    cursor: pointer;
    transition: background .18s var(--sf-ease), color .18s var(--sf-ease);
}

.sf-topbar__lang:hover {
    background: var(--sf-line);
    color: var(--sf-ink-2);
}

.sf-topbar__lang svg {
    width: 14px;
    height: 14px;
}

/* -------------------------------------------------------------------------
   5. Header
   ------------------------------------------------------------------------- */
.sf-header {
    background: var(--sf-surface);
    /* border-bottom: 1px solid var(--sf-line); */
}

/* A little breathing room between the logo row and the category row on
   desktop. The gap is white-on-white, so it reads as spacing rather than a
   line; it scrolls away with the header (the nav is sticky on its own). */
@media (min-width: 1024px) {
    .sf-header {
        padding-bottom: var(--sf-sp-2);
    }
}

.sf-header__inner {
    display: flex;
    align-items: center;
    gap: var(--sf-sp-5);
    min-height: var(--sf-header-h);
}

.sf-logo {
    display: inline-flex;
    align-items: center;
    gap: var(--sf-sp-3);
    flex-shrink: 0;
}

/*
 * Header logo (shop CDN artwork, transparent PNG). `height` + `width:auto`
 * scales it from the intrinsic 233x40 ratio, which is also declared by the
 * img width/height attributes so the space is reserved before it loads.
 * No plate needed — the header surface is white and the PNG is transparent.
 */
.sf-logo__img {
    display: block;
    width: auto;
    height: 40px;
}

/* Fallback text lockup, used only if the logo image is unavailable. */
.sf-logo__mark {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 42px;
    height: 42px;
    border-radius: 13px;
    background: linear-gradient(135deg, var(--sf-brand), #5cc8f7);
    color: #fff;
    box-shadow: 0 4px 12px rgba(18, 159, 229, .3);
}

.sf-logo__mark svg {
    width: 23px;
    height: 23px;
}

.sf-logo__name {
    font-size: 20px;
    font-weight: 800;
    color: var(--sf-ink);
    letter-spacing: -.02em;
}

.sf-logo__tag {
    display: block;
    font-size: 10px;
    font-weight: 700;
    letter-spacing: .18em;
    text-transform: uppercase;
    color: var(--sf-brand);
}

/* Search */
.sf-search {
    position: relative;
    flex: 1;
    min-width: 0;
    max-width: 620px;
}

.sf-search__box {
    display: flex;
    align-items: stretch;
    border: 1px solid transparent;
    border-radius: 999px;
    overflow: hidden;
    background: var(--sf-fill);
    transition: background .2s var(--sf-ease), border-color .2s var(--sf-ease),
        box-shadow .2s var(--sf-ease);
}

.sf-search__box:focus-within {
    background: var(--sf-surface);
    border-color: var(--sf-brand);
    box-shadow: 0 0 0 4px var(--sf-brand-soft);
}

.sf-search__input {
    flex: 1;
    min-width: 0;
    border: 0;
    padding: 11px var(--sf-sp-5);
    font-size: 15px;
    line-height: 1.2;
    color: var(--sf-ink);
    background: transparent;
    outline: none;
}

.sf-search__input::placeholder {
    color: var(--sf-muted-2);
}

.sf-search__btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 6px;
    padding: 11px 26px;
    border: 0;
    background: var(--sf-brand);
    color: #fff;
    font-family: inherit;
    font-size: 15px;
    font-weight: 600;
    cursor: pointer;
    transition: background .18s var(--sf-ease);
}

.sf-search__btn:hover {
    background: var(--sf-brand-dark);
}

.sf-search__btn svg {
    width: 19px;
    height: 19px;
}

.sf-search__suggest {
    position: absolute;
    inset-inline: 0;
    top: calc(100% + var(--sf-sp-2));
    z-index: 70;
    /* Token, not #fff: a hardcoded white panel stayed white in dark mode. */
    background: var(--sf-surface);
    border-radius: var(--sf-radius-lg);
    box-shadow: var(--sf-shadow-lg);
    overflow: hidden;
    padding-block: var(--sf-sp-2);
}

.sf-suggest-item {
    display: flex;
    align-items: center;
    gap: var(--sf-sp-3);
    padding: 10px var(--sf-sp-4);
    transition: background .15s var(--sf-ease);
}

.sf-suggest-item:hover {
    background: var(--sf-brand-tint);
}

.sf-suggest-item img {
    width: 44px;
    height: 44px;
    border-radius: var(--sf-radius-sm);
    object-fit: cover;
    background: var(--sf-surface-2);
}

.sf-suggest-item span {
    font-size: 14px;
    color: var(--sf-ink);
}

/* Header actions */
.sf-header__actions {
    display: flex;
    align-items: center;
    gap: var(--sf-sp-2);
    margin-inline-start: auto;
    flex-shrink: 0;
}

.sf-action {
    position: relative;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 3px;
    min-width: 64px;
    padding: 8px 10px;
    border-radius: var(--sf-radius);
    color: var(--sf-ink-2);
    font-size: 12px;
    font-weight: 500;
    /* The phone's own tap flash is blue-tinted; we supply the grey below. */
    -webkit-tap-highlight-color: rgba(15, 23, 42, .08);
    transition: background .18s var(--sf-ease), color .18s var(--sf-ease);
}

/*
 * Header button feedback is GREY ONLY. Hover, keyboard focus, the page you are
 * currently on (.is-active) and an open menu (.is-open) all use the same light
 * grey wash — a selected button reads as a quiet state, never a brand-coloured
 * one.
 *
 * The global `.sf :focus-visible` ring is brand BLUE; this rule has the same
 * specificity but lives later in the file (§5 after §2), so it wins.
 */
.sf-action:hover,
.sf-action:focus-visible,
.sf-action.is-active,
.sf-action.is-open {
    background: var(--sf-fill);
}

.sf-action:focus-visible {
    outline: 2px solid var(--sf-line-strong);
    outline-offset: 2px;
}

.sf-action svg {
    width: 24px;
    height: 24px;
    /*
     * Icons are the primary visual of the header row, so they use the darkest
     * ink — the same as the burger button. The label below stays on the
     * secondary token (--sf-ink-2), which is shared with nav links and other
     * secondary text site-wide; darkening THAT token would shift the whole
     * site, so the icon is darkened in isolation instead.
     */
    color: var(--sf-ink);
}

.sf-action__label {
    white-space: nowrap;
}

.sf-cart-badge {
    position: absolute;
    top: 2px;
    inset-inline-end: 8px;
    min-width: 20px;
    height: 20px;
    padding-inline: 6px;
    border-radius: 10px;
    background: var(--sf-buy);
    color: #fff;
    font-size: 11px;
    font-weight: 700;
    line-height: 20px;
    text-align: center;
}

@keyframes sf-badge-pop {
    0% { transform: scale(1); }
    40% { transform: scale(1.4); }
    100% { transform: scale(1); }
}

.sf-cart-badge.is-pop {
    animation: sf-badge-pop .45s var(--sf-ease);
}

.sf-action--cart {
    border: 0;
}

/*
 * Wishlist has its own header button wherever the row has room. On a phone it
 * is hidden (see §26) and reached through the user menu instead. Declared
 * explicitly so the button can never stay hidden on a larger screen just
 * because the §26 rule was re-ordered or widened.
 */
@media (min-width: 768px) {
    .sf-action--wishlist {
        display: inline-flex;
    }
}

/*
 * Search action — replaces the inline header search box at ≤1023px (the ≤1023px
 * block in §26 lifts the base `display: none`). It is a <button>, so it needs the
 * chrome reset the anchor-based actions get from the UA stylesheet for free.
 */
.sf-action--search {
    display: none;
    border: 0;
    background: none;
    font-family: inherit;
    cursor: pointer;
}

.sf-burger {
    display: none;
    align-items: center;
    justify-content: center;
    width: 44px;
    height: 44px;
    border: 0;
    border-radius: var(--sf-radius);
    background: var(--sf-fill);
    color: var(--sf-ink);
    cursor: pointer;
}

.sf-burger:hover {
    background: var(--sf-brand-soft);
    color: var(--sf-brand-dark);
}

/* Dropdowns */
.sf-dropdown {
    position: absolute;
    inset-inline-end: 0;
    top: calc(100% + var(--sf-sp-2));
    z-index: 70;
    min-width: 210px;
    padding-block: var(--sf-sp-2);
    /* Token, not #fff (see .sf-search__suggest). */
    background: var(--sf-surface);
    border-radius: var(--sf-radius-lg);
    box-shadow: var(--sf-shadow-lg);
    overflow: hidden;
}

.sf-dropdown__item {
    display: block;
    padding: 11px var(--sf-sp-5);
    font-size: 14px;
    color: var(--sf-ink-2);
    white-space: nowrap;
    transition: background .15s var(--sf-ease), color .15s var(--sf-ease);
}

.sf-dropdown__item:hover {
    background: var(--sf-brand-tint);
    color: var(--sf-brand-dark);
}

.sf-dropdown__item--active {
    color: var(--sf-brand-dark);
    font-weight: 600;
}

.sf-dropdown__item--danger {
    color: #d33333;
}

/*
 * A menu item for a link the page's own chrome stops showing at a narrow
 * width — currently "Track order" (the utility bar hides it on a phone) and
 * "My wishlist" (the header wishlist button is hidden there too; see §26).
 * Hidden at ≥768px so the desktop menu never lists a link that is already on
 * screen.
 */
.sf-dropdown__item--mobile-only {
    display: none;
}

.sf-dropdown__divider {
    height: 1px;
    margin-block: var(--sf-sp-2);
    background: var(--sf-line);
}

/* -------------------------------------------------------------------------
   6. Category navigation + mega menu
   ------------------------------------------------------------------------- */
/*
 * Sticky: only the category row stays pinned when scrolling — the logo row
 * (header) above it scrolls away. `position: sticky` is a positioned value,
 * so the mega menu still anchors to this element.
 */
.sf-nav {
    position: sticky;
    top: 0;
    z-index: 60;
    background: var(--sf-surface);
    border-bottom: 1px solid var(--sf-line);
    transition: box-shadow .22s var(--sf-ease);
}

.sf-nav--scrolled {
    box-shadow: 0 4px 20px rgba(16, 24, 40, .09);
}

.sf-nav__inner {
    display: flex;
    align-items: stretch;
    gap: var(--sf-sp-1);
    overflow-x: auto;
    scrollbar-width: none;
}

.sf-nav__inner::-webkit-scrollbar {
    display: none;
}

.sf-nav__all {
    display: inline-flex;
    align-items: center;
    gap: var(--sf-sp-2);
    flex-shrink: 0;
    margin-block: var(--sf-sp-2);
    margin-inline-end: var(--sf-sp-4);
    padding: 9px var(--sf-sp-5);
    border-radius: 999px;
    background: var(--sf-brand-soft);
    color: var(--sf-brand-deep);
    font-size: 14px;
    font-weight: 600;
    white-space: nowrap;
    box-shadow: inset 0 0 0 1px rgba(18, 159, 229, .22);
    transition: background .18s var(--sf-ease), color .18s var(--sf-ease), box-shadow .18s var(--sf-ease);
}

.sf-nav__all:hover {
    background: var(--sf-brand);
    color: #fff;
    box-shadow: inset 0 0 0 1px transparent;
}

.sf-nav__item {
    position: static;
    display: inline-flex;
}

.sf-nav__link {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 15px var(--sf-sp-4) 13px;
    border-bottom: 3px solid transparent;
    color: var(--sf-ink-2);
    font-size: 14px;
    font-weight: 600;
    white-space: nowrap;
    transition: color .18s var(--sf-ease), border-color .18s var(--sf-ease);
}

/* Hovered / keyboard-focused link is highlighted. */
.sf-nav__item:hover .sf-nav__link,
.sf-nav__link:hover,
.sf-nav__link:focus-visible {
    color: var(--sf-brand);
    border-bottom-color: var(--sf-brand);
}

/* The active (current) category is highlighted. */
.sf-nav__link--active {
    color: var(--sf-brand);
    border-bottom-color: var(--sf-brand);
}

/*
 * Only ONE highlight at a time. While the pointer is anywhere over the nav,
 * the active link yields to normal so a hovered sibling never reads as a
 * second active category. (Hovering the active item itself keeps it lit —
 * that rule is later and wins the tie.)
 */
.sf-nav:hover .sf-nav__link--active {
    color: var(--sf-ink-2);
    border-bottom-color: transparent;
}

.sf-nav__item:hover .sf-nav__link--active {
    color: var(--sf-brand);
    border-bottom-color: var(--sf-brand);
}

/* Same yield for keyboard users tabbing between links. */
.sf-nav:has(.sf-nav__link:focus-visible) .sf-nav__link--active {
    color: var(--sf-ink-2);
    border-bottom-color: transparent;
}

.sf-nav:has(.sf-nav__link:focus-visible) .sf-nav__link--active:focus-visible {
    color: var(--sf-brand);
    border-bottom-color: var(--sf-brand);
}

.sf-nav__link svg {
    width: 13px;
    height: 13px;
    opacity: .55;
    transition: transform .18s var(--sf-ease);
}

/* Chevron flips while the panel is open — tells the user what the hover did. */
.sf-nav__item:hover .sf-nav__link svg,
.sf-nav__item:focus-within .sf-nav__link svg {
    transform: rotate(180deg);
}

.sf-nav__promo {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    margin-inline-start: auto;
    padding: 15px var(--sf-sp-5) 13px;
    border-bottom: 3px solid transparent;
    color: var(--sf-price-deal);
    font-size: 14px;
    font-weight: 800;
    white-space: nowrap;
}

.sf-nav__promo:hover {
    border-bottom-color: var(--sf-price-deal);
}

/*
 * Mega menu. Absolutely positioned against `.sf-nav` (the nearest positioned
 * ancestor), so it spans the full nav width rather than the nav item.
 * No border-top: it separates from the nav by shadow + rounded bottom corners.
 */
.sf-mega {
    display: none;
    position: absolute;
    inset-inline: 0;
    top: 100%;
    z-index: 65;
    background: var(--sf-surface);
    border-radius: 0 0 var(--sf-radius-lg) var(--sf-radius-lg);
    box-shadow: var(--sf-shadow-lg);
    overflow: hidden;
}

/*
 * `:focus-within` matters as much as `:hover`: without it the whole panel was
 * unreachable by keyboard, because tabbing to a nav link is not a hover.
 */
.sf-nav__item:hover .sf-mega,
.sf-nav__item:focus-within .sf-mega {
    display: block;
    animation: sf-mega-in .18s var(--sf-ease);
}

@keyframes sf-mega-in {
    from { opacity: 0; transform: translateY(-8px); }
    to   { opacity: 1; transform: translateY(0); }
}

/*
 * `auto-fit` rather than a fixed 4 tracks: the live data is 2-3 child
 * categories per top category, and a fixed 4-column grid left the right half of
 * the panel empty. `minmax` keeps the columns readable once more are added.
 */
.sf-mega__grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
    gap: var(--sf-sp-4) var(--sf-sp-6);
    padding-block: var(--sf-sp-5);
}

/*
 * Each child category is its own column card — the whole block tints on hover
 * so the group reads as a single target, and the chevron slides in to show it
 * is clickable.
 */
.sf-mega__col {
    padding: var(--sf-sp-3) var(--sf-sp-3) var(--sf-sp-4);
    border-radius: var(--sf-radius);
    transition: background .18s var(--sf-ease);
}

.sf-mega__col:hover {
    background: var(--sf-brand-tint);
}

/*
 * Full-width row (not an inline label) with the chevron pushed to the trailing
 * edge. With only 2-3 children per category the columns are wide, and a
 * left-hugging label would leave each one looking sparse; a stretching row
 * reads as a proper menu row at any column width.
 */
.sf-mega__title {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 6px;
    font-size: 13px;
    font-weight: 600;
    color: var(--sf-ink);
    transition: color .18s var(--sf-ease);
}

.sf-mega__title svg {
    width: 13px;
    height: 13px;
    opacity: 0;
    transform: translateX(-4px);
    transition: opacity .18s var(--sf-ease), transform .18s var(--sf-ease);
}

.sf-mega__col:hover .sf-mega__title,
.sf-mega__title:hover {
    color: var(--sf-brand);
}

.sf-mega__col:hover .sf-mega__title svg {
    opacity: 1;
    transform: translateX(0);
}

.sf-mega__list {
    display: flex;
    flex-direction: column;
    margin-top: var(--sf-sp-2);
}

/*
 * Nudge rather than indent: links shift a few px on hover for immediate
 * feedback, without reflowing the column.
 */
.sf-mega__list a {
    padding: 5px 0;
    font-size: 13px;
    color: var(--sf-muted);
    transition: color .15s var(--sf-ease), transform .15s var(--sf-ease);
}

.sf-mega__list a:hover {
    color: var(--sf-brand);
    transform: translateX(3px);
}

/* Overflow hint when a column has more children than are listed. */
.sf-mega__list .sf-mega__more {
    color: var(--sf-brand);
    font-size: 12px;
    font-weight: 700;
}

/*
 * Panel foot — the escape hatch. Without it, a user who wants the whole
 * category has to go back up to the nav item they just hovered.
 */
.sf-mega__foot {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--sf-sp-4);
    flex-wrap: wrap;
    margin-bottom: var(--sf-sp-6);
    padding: var(--sf-sp-3) var(--sf-sp-5);
    border-radius: var(--sf-radius);
    background: var(--sf-surface-2);
}

.sf-mega__cta {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    font-size: 13px;
    font-weight: 700;
    color: var(--sf-brand);
}

.sf-mega__cta svg {
    width: 13px;
    height: 13px;
    transition: transform .18s var(--sf-ease);
}

.sf-mega__cta:hover svg {
    transform: translateX(3px);
}

.sf-mega__foot-links {
    display: inline-flex;
    align-items: center;
    gap: var(--sf-sp-5);
}

.sf-mega__foot-links a {
    font-size: 12px;
    color: var(--sf-muted);
    transition: color .15s var(--sf-ease);
}

.sf-mega__foot-links a:hover {
    color: var(--sf-brand);
}

/* -------------------------------------------------------------------------
   7. Mobile drawer
   ------------------------------------------------------------------------- */
.sf-drawer-backdrop {
    position: fixed;
    inset: 0;
    z-index: 80;
    background: rgba(16, 24, 40, .5);
}

.sf-drawer {
    position: fixed;
    inset-block: 0;
    inset-inline-start: 0;
    z-index: 90;
    display: flex;
    flex-direction: column;
    width: 320px;
    max-width: 88vw;
    /* Token, not #fff (see .sf-search__suggest). */
    background: var(--sf-surface);
    transform: translateX(-100%);
    transition: transform .3s var(--sf-ease);
}

[dir='rtl'] .sf-drawer {
    transform: translateX(100%);
}

.sf-drawer.is-open {
    transform: translateX(0);
}

.sf-drawer__head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: var(--sf-sp-4) var(--sf-sp-5);
    border-bottom: 1px solid var(--sf-line);
    font-size: 16px;
    font-weight: 700;
}

.sf-drawer__body {
    flex: 1;
    overflow-y: auto;
    padding-block: var(--sf-sp-2);
}

.sf-drawer__item {
    display: flex;
    align-items: center;
    justify-content: space-between;
    width: 100%;
    padding: 15px var(--sf-sp-5);
    border: 0;
    border-bottom: 1px solid var(--sf-line);
    background: none;
    text-align: start;
    font-family: inherit;
    font-size: 15px;
    font-weight: 600;
    color: var(--sf-ink-2);
    cursor: pointer;
    transition: background .15s var(--sf-ease), color .15s var(--sf-ease);
}

.sf-drawer__item:hover {
    color: var(--sf-brand);
    background: var(--sf-brand-tint);
}

.sf-drawer__sub {
    background: var(--sf-surface-2);
}

.sf-drawer__sub a {
    display: block;
    padding: 12px var(--sf-sp-5) 12px 34px;
    font-size: 14px;
    color: var(--sf-muted);
}

.sf-drawer__sub a:hover {
    color: var(--sf-brand);
}

/* -------------------------------------------------------------------------
   7b. Full-screen search overlay (mobile + tablet, ≤1023px)
   -------------------------------------------------------------------------
   Opened by `.sf-action--search` in the header. The <form> is the flex column so
   `[data-search-suggest]` stays a DESCENDANT of `[data-sf-search]` (the shared
   autocomplete wiring uses `form.querySelector`) while still rendering BELOW the
   input bar instead of beside it.

   z-index 100 — above every other layer in this file: nav 60, dropdown 65,
   header 70, suggest 70, drawer backdrop 80, drawer 90.
   ------------------------------------------------------------------------- */
.sf-search-overlay {
    position: fixed;
    inset: 0;
    z-index: 100;
    display: none;
    /* Token, not #fff: a hardcoded white sheet would stay white in dark mode. */
    background: var(--sf-surface);
    /*
     * `viewport-fit=cover` lets the page paint under the iOS notch, so the sheet
     * has to fill that strip itself or the page colour shows above it — the same
     * mechanism `.sf-topbar` uses.
     */
    padding-top: env(safe-area-inset-top, 0px);
}

.sf-search-overlay__form {
    display: flex;
    flex-direction: column;
    height: 100%;
}

.sf-search-overlay__bar {
    display: flex;
    align-items: center;
    gap: var(--sf-sp-3);
    padding: var(--sf-sp-3) var(--sf-sp-4);
    border-bottom: 1px solid var(--sf-line);
}

.sf-search-overlay__close {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
    width: 40px;
    height: 40px;
    border: 0;
    border-radius: var(--sf-radius);
    background: none;
    color: var(--sf-ink);
    cursor: pointer;
}

.sf-search-overlay__close svg {
    width: 22px;
    height: 22px;
}

.sf-search-overlay__close:hover {
    background: var(--sf-fill);
}

/* The box is the bar's only flexible item, so the field takes the remaining width. */
.sf-search-overlay .sf-search__box {
    flex: 1;
    min-width: 0;
    border-radius: 12px;
}

/* Compact controls so the bar matches the old mobile search row at EVERY width,
   not just ≤767px. */
.sf-search-overlay .sf-search__input {
    padding: 10px var(--sf-sp-4);
}

.sf-search-overlay .sf-search__btn {
    padding: 10px var(--sf-sp-4);
    font-size: 14px;
}

.sf-search-overlay__body {
    flex: 1;
    overflow-y: auto;
    padding-block: var(--sf-sp-2);
}

/*
 * The base rule floats this panel under the input with an absolute offset. In the
 * overlay the results ARE the page body, so they flow normally. (0,2,0 beats the
 * base 0,1,0 regardless of source order.)
 */
.sf-search-overlay .sf-search__suggest {
    position: static;
    box-shadow: none;
    border-radius: 0;
    padding-block: 0;
}

/* Recent searches — the overlay's empty state. */
.sf-search-overlay__head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--sf-sp-4);
    padding: var(--sf-sp-3) var(--sf-sp-4) var(--sf-sp-2);
    font-size: 12px;
    font-weight: 700;
    letter-spacing: .08em;
    text-transform: uppercase;
    color: var(--sf-muted);
}

.sf-search-overlay__clear {
    border: 0;
    background: none;
    padding: 0;
    font-family: inherit;
    font-size: 12px;
    font-weight: 600;
    letter-spacing: normal;
    text-transform: none;
    color: var(--sf-brand);
    cursor: pointer;
}

.sf-search-overlay__clear:hover {
    text-decoration: underline;
}

.sf-recent-item {
    display: flex;
    align-items: center;
    gap: var(--sf-sp-3);
    padding: 11px var(--sf-sp-4);
    font-size: 14px;
    color: var(--sf-ink);
    transition: background .15s var(--sf-ease);
}

.sf-recent-item:hover {
    background: var(--sf-brand-tint);
}

.sf-recent-item svg {
    width: 18px;
    height: 18px;
    flex-shrink: 0;
    color: var(--sf-muted-2);
}

/* "View all results" — the exit from the overlay into the full results page. */
.sf-search-overlay__all {
    display: flex;
    align-items: center;
    gap: var(--sf-sp-2);
    padding: 14px var(--sf-sp-4);
    border-top: 1px solid var(--sf-line);
    font-size: 14px;
    font-weight: 600;
    color: var(--sf-brand);
}

.sf-search-overlay__all:hover {
    background: var(--sf-brand-tint);
}

.sf-search-overlay__all svg {
    width: 16px;
    height: 16px;
    flex-shrink: 0;
}

/* -------------------------------------------------------------------------
   8. Buttons
   ------------------------------------------------------------------------- */
.sf-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: var(--sf-sp-2);
    padding: 11px var(--sf-sp-6);
    border: 1px solid transparent;
    border-radius: 10px;
    background: var(--sf-surface-2);
    color: var(--sf-ink);
    font-family: inherit;
    font-size: 15px;
    font-weight: 600;
    line-height: 1.2;
    cursor: pointer;
    text-align: center;
    transition: background .18s var(--sf-ease), color .18s var(--sf-ease),
        border-color .18s var(--sf-ease), transform .18s var(--sf-ease);
}

.sf-btn:active:not(:disabled) {
    transform: translateY(1px);
}

.sf-btn:disabled {
    opacity: .55;
    cursor: not-allowed;
}

.sf-btn--primary {
    background: var(--sf-brand);
    border-color: var(--sf-brand);
    color: #fff;
    box-shadow: 0 4px 14px rgba(18, 159, 229, .3);
}

.sf-btn--primary:hover:not(:disabled) {
    background: var(--sf-brand-dark);
    border-color: var(--sf-brand-dark);
    color: #fff;
}

/* Buy CTA — warm orange so the purchase action pops against the blue brand. */
.sf-btn--buy {
    background: linear-gradient(135deg, #ff8a3d, var(--sf-buy));
    border-color: var(--sf-buy);
    color: #fff;
    box-shadow: 0 4px 14px rgba(255, 106, 0, .3);
}

.sf-btn--buy:hover:not(:disabled) {
    background: linear-gradient(135deg, #ff7a2e, var(--sf-buy-dark));
    border-color: var(--sf-buy-dark);
    color: #fff;
}

.sf-btn--outline {
    background: #fff;
    border-color: var(--sf-line-strong);
    color: var(--sf-ink-2);
}

.sf-btn--outline:hover:not(:disabled) {
    border-color: var(--sf-brand);
    color: var(--sf-brand-dark);
}

.sf-btn--dark {
    background: var(--sf-ink);
    border-color: var(--sf-ink);
    color: #fff;
}

.sf-btn--dark:hover:not(:disabled) {
    background: #000;
    color: #fff;
}

.sf-btn--ghost {
    background: transparent;
    border-color: transparent;
    color: var(--sf-muted);
}

.sf-btn--ghost:hover:not(:disabled) {
    color: var(--sf-brand-dark);
    background: var(--sf-brand-soft);
}

.sf-btn--block {
    width: 100%;
}

.sf-btn--sm {
    padding: 9px var(--sf-sp-4);
    font-size: 14px;
    border-radius: 9px;
}

.sf-btn--lg {
    padding: 15px var(--sf-sp-8);
    font-size: 16px;
}

/* -------------------------------------------------------------------------
   9. Badges, tags, pills
   ------------------------------------------------------------------------- */
.sf-badge {
    display: inline-flex;
    align-items: center;
    gap: var(--sf-sp-1);
    padding: 4px 10px;
    border-radius: 7px;
    font-size: 12px;
    font-weight: 700;
    line-height: 1.45;
    white-space: nowrap;
}

/* Sale badge — warm gradient so savings pop against the blue brand. */
.sf-badge--discount {
    background: linear-gradient(135deg, var(--sf-price-deal), var(--sf-price));
    color: #fff;
    box-shadow: 0 2px 8px rgba(255, 68, 0, .28);
}

.sf-badge--new {
    background: var(--sf-teal);
    color: #fff;
}

.sf-badge--hot {
    background: linear-gradient(135deg, var(--sf-price-deal), var(--sf-buy));
    color: #fff;
}

.sf-badge--soldout {
    background: #6b7280;
    color: #fff;
}

.sf-badge--warning {
    background: #fff4e0;
    color: #a15c00;
}

.sf-badge--success {
    background: #e7f7f1;
    color: #0a7a5c;
}

.sf-badge--danger {
    background: #fdecec;
    color: #b32b2b;
}

.sf-badge--info {
    background: #eaf1fd;
    color: var(--sf-link);
}

.sf-pill {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 9px var(--sf-sp-5);
    border: 1px solid transparent;
    border-radius: 999px;
    background: var(--sf-fill);
    font-size: 14px;
    font-weight: 500;
    color: var(--sf-ink-2);
    transition: background .18s var(--sf-ease), color .18s var(--sf-ease);
}

.sf-pill:hover {
    background: var(--sf-brand-soft);
    color: var(--sf-brand-dark);
}

.sf-pill--active {
    background: var(--sf-brand);
    border-color: var(--sf-brand);
    color: #fff;
}

.sf-pill--soft {
    background: var(--sf-brand-soft);
    border-color: transparent;
    color: var(--sf-brand-dark);
}

/* -------------------------------------------------------------------------
   10. Product card
   ------------------------------------------------------------------------- */
.sf-grid {
    display: grid;
    gap: var(--sf-sp-5);
    grid-template-columns: repeat(2, minmax(0, 1fr));
}

/*
 * The 3-up step is at 768px, NOT 640px — do not lower it.
 *
 * Below 768px the container's inline padding is 16px, so a 640px viewport has
 * a 608px content box and three cards with a 20px gap would be ~189px each.
 * That is the same ~180px card size this file already rejected once: the
 * 1280px note below says 5-up at 1024px came "too early" for exactly that
 * reason. At 768px the padding steps up to 24px, giving a 720px content box
 * and ~227px cards — the same size the desktop 5-up lands on at 1280px.
 *
 * Any 2 -> 3 step shrinks cards; what matters is where it lands. Landing on a
 * size the rest of the system already uses (227px) beats landing on one it
 * has rejected (189px).
 */
@media (min-width: 768px) {
    .sf-grid {
        grid-template-columns: repeat(3, minmax(0, 1fr));
    }
}

@media (min-width: 1024px) {
    .sf-grid {
        grid-template-columns: repeat(4, minmax(0, 1fr));
        gap: var(--sf-sp-6);
    }
}

/* Five-up only once the container is actually wide (≥1280px) — at 1024px the
   container is still ~976px, so five cards would be ~180px each. */
@media (min-width: 1280px) {
    .sf-grid {
        grid-template-columns: repeat(5, minmax(0, 1fr));
        gap: var(--sf-sp-6);
    }
}

.sf-grid--4 {
    grid-template-columns: repeat(2, minmax(0, 1fr));
}

/* 768px, not 640px — same reason as `.sf-grid` above. */
@media (min-width: 768px) {
    .sf-grid--4 {
        grid-template-columns: repeat(3, minmax(0, 1fr));
    }
}

@media (min-width: 1024px) {
    .sf-grid--4 {
        grid-template-columns: repeat(4, minmax(0, 1fr));
    }
}

/* Stores page grid — one column on a phone, three on desktop. */
.sf-grid--stores {
    grid-template-columns: 1fr;
}

@media (min-width: 768px) {
    .sf-grid--stores {
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }
}

@media (min-width: 1024px) {
    .sf-grid--stores {
        grid-template-columns: repeat(3, minmax(0, 1fr));
    }
}

/* Store location card (home page). */
.sf-store__name {
    margin-bottom: var(--sf-sp-2);
    font-size: 16px;
    font-weight: 800;
    color: var(--sf-ink);
}

.sf-store__address {
    margin-bottom: var(--sf-sp-4);
    font-size: 14px;
    line-height: 1.6;
    color: var(--sf-ink-2);
}

.sf-store__meta {
    display: grid;
    gap: var(--sf-sp-2);
    margin-bottom: var(--sf-sp-5);
    font-size: 13px;
    color: var(--sf-muted);
}

.sf-store__meta a {
    color: var(--sf-brand);
    font-weight: 600;
}

.sf-store__actions {
    display: flex;
    flex-wrap: wrap;
    gap: var(--sf-sp-2);
}

/* Stores page — intro band */
.sf-stores-hero {
    display: grid;
    gap: var(--sf-sp-6);
    align-items: center;
    padding: var(--sf-sp-8) var(--sf-sp-6);
    margin-bottom: var(--sf-sp-8);
    border-radius: var(--sf-radius-lg);
    background: linear-gradient(135deg, var(--sf-brand-tint) 0%, var(--sf-brand-soft) 100%);
}

@media (min-width: 768px) {
    .sf-stores-hero {
        grid-template-columns: minmax(0, 1fr) auto;
    }
}

.sf-stores-hero__eyebrow {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    margin-bottom: var(--sf-sp-3);
    font-size: 12px;
    font-weight: 700;
    letter-spacing: .14em;
    text-transform: uppercase;
    color: var(--sf-brand-dark);
}

.sf-stores-hero__title {
    margin-bottom: var(--sf-sp-3);
    font-size: 28px;
    font-weight: 800;
    letter-spacing: -.02em;
    color: var(--sf-ink);
}

.sf-stores-hero__text {
    max-width: 54ch;
    font-size: 15px;
    line-height: 1.7;
    color: var(--sf-ink-2);
}

.sf-stores-hero__stats {
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: var(--sf-sp-3);
}

.sf-stat {
    padding: var(--sf-sp-4) var(--sf-sp-5);
    border-radius: var(--sf-radius);
    background: var(--sf-surface);
    box-shadow: var(--sf-shadow-xs);
    text-align: center;
}

.sf-stat strong {
    display: block;
    font-size: 24px;
    font-weight: 800;
    line-height: 1.1;
    color: var(--sf-brand);
}

.sf-stat span {
    display: block;
    margin-top: 4px;
    font-size: 12px;
    color: var(--sf-muted);
}

/* Stores page — corporate / bulk quote section.
   Two-column: the pitch (left) + a CTA card (right). Full-width — no more
   narrow centered column. */
.sf-quote {
    margin-top: var(--sf-sp-12);
}

.sf-quote__grid {
    display: grid;
    gap: var(--sf-sp-6);
    align-items: start;
    grid-template-columns: 1fr;
}

@media (min-width: 1024px) {
    .sf-quote__grid {
        grid-template-columns: minmax(0, 7fr) minmax(0, 5fr);
        gap: var(--sf-sp-8);
    }
}

.sf-quote__title {
    margin-bottom: var(--sf-sp-3);
    font-size: 24px;
    font-weight: 800;
    letter-spacing: -.02em;
    color: var(--sf-ink);
}

.sf-quote__text {
    margin-bottom: var(--sf-sp-5);
    font-size: 15px;
    line-height: 1.7;
    color: var(--sf-ink-2);
}

.sf-quote__list {
    display: grid;
    gap: var(--sf-sp-3);
}

.sf-quote__list li {
    display: flex;
    gap: var(--sf-sp-3);
    font-size: 14px;
    line-height: 1.6;
    color: var(--sf-ink-2);
}

.sf-quote__list svg {
    flex: none;
    margin-top: 2px;
    color: var(--sf-brand);
}

/* CTA card — white panel (surface comes from .sf-panel) with generous padding
   so the request action reads as the section's focal point. */
.sf-quote__card {
    padding: var(--sf-sp-8);
}

.sf-quote__card-title {
    margin-bottom: var(--sf-sp-2);
    font-size: 20px;
    font-weight: 800;
    letter-spacing: -.01em;
    color: var(--sf-ink);
}

.sf-quote__card-text {
    margin-bottom: var(--sf-sp-5);
    font-size: 14px;
    line-height: 1.65;
    color: var(--sf-ink-2);
}

.sf-quote__card .sf-btn--block {
    margin-bottom: var(--sf-sp-3);
}

.sf-quote__cta-note {
    font-size: 13px;
    color: var(--sf-muted);
}

.sf-quote__alt {
    margin-top: var(--sf-sp-5);
    padding-top: var(--sf-sp-5);
    border-top: 1px solid var(--sf-line);
}

.sf-quote__alt-label {
    display: block;
    margin-bottom: var(--sf-sp-3);
    font-size: 13px;
    font-weight: 600;
    color: var(--sf-muted);
}

.sf-quote__alt-links {
    display: flex;
    flex-wrap: wrap;
    gap: var(--sf-sp-2);
}

.sf-quote__actions {
    margin-top: var(--sf-sp-2);
}

/* Dedicated quote request page — form + side info.
   Full-width two-column: the form panel is dominant (2fr) with the side info
   compact (1fr). No page-level centering — a full-width title above a centred
   column left awkward gutters. The form itself is a two-column grid (see
   .sf-quote-page__form form) so short fields pair up and stay compact. */
.sf-quote-page {
    display: grid;
    gap: var(--sf-sp-6);
    align-items: start;
}

@media (min-width: 1024px) {
    .sf-quote-page {
        grid-template-columns: minmax(0, 2fr) minmax(0, 1fr);
    }
}

.sf-quote-page__side {
    display: grid;
    gap: var(--sf-sp-6);
}

/* Form fields in a two-column grid — short fields pair up, long textareas
   span the full width. Uses the panel width efficiently (no empty space)
   while keeping each field at a comfortable measure. */
.sf-quote-page__form form {
    display: grid;
    grid-template-columns: 1fr;
    gap: var(--sf-sp-5);
}

@media (min-width: 640px) {
    .sf-quote-page__form form {
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }
}

.sf-quote-page__form .sf-field {
    margin-bottom: 0;
}

.sf-quote-page__form .sf-field--full {
    grid-column: 1 / -1;
}

.sf-quote-page__form .sf-quote__actions {
    grid-column: 1 / -1;
    margin-top: 0;
}

.sf-quote__steps {
    display: grid;
    gap: var(--sf-sp-4);
}

.sf-quote__steps li {
    display: flex;
    align-items: flex-start;
    gap: var(--sf-sp-3);
    font-size: 14px;
    line-height: 1.6;
    color: var(--sf-ink-2);
}

.sf-quote__step-num {
    flex: none;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 24px;
    height: 24px;
    border-radius: 50%;
    background: var(--sf-brand-soft);
    color: var(--sf-brand-dark);
    font-size: 13px;
    font-weight: 700;
}

/* Stores page — card media */
.sf-store__media {
    position: relative;
    aspect-ratio: 16 / 10;
    overflow: hidden;
    background: var(--sf-surface-2);
}

.sf-store__media img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    transition: transform .45s var(--sf-ease);
}

.sf-store:hover .sf-store__media img {
    transform: scale(1.05);
}

/* Desktop nav — "Find a Store" link */
.sf-nav__store {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    margin-inline-start: var(--sf-sp-2);
    padding: 15px var(--sf-sp-4) 13px;
    border-bottom: 3px solid transparent;
    color: var(--sf-ink-2);
    font-size: 14px;
    font-weight: 600;
    white-space: nowrap;
    transition: color .18s var(--sf-ease), border-color .18s var(--sf-ease);
}

.sf-nav__store:hover {
    color: var(--sf-brand);
    border-bottom-color: var(--sf-brand);
}

.sf-card {
    position: relative;
    display: flex;
    flex-direction: column;
    background: var(--sf-surface);
    border-radius: var(--sf-radius-lg);
    box-shadow: var(--sf-shadow-xs);
    overflow: hidden;
    transition: box-shadow .24s var(--sf-ease), transform .24s var(--sf-ease);
}

.sf-card:hover {
    box-shadow: var(--sf-shadow);
    transform: translateY(-4px);
}

.sf-card__media {
    position: relative;
    display: block;
    aspect-ratio: 1 / 1;
    padding: var(--sf-sp-5);
    background: #fff;
    overflow: hidden;
}

.sf-card__img {
    width: 100%;
    height: 100%;
    object-fit: contain;
    transition: transform .4s var(--sf-ease);
}

.sf-card:hover .sf-card__img {
    transform: scale(1.05);
}

.sf-card__placeholder {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 100%;
    height: 100%;
    color: #dfe3e8;
}

.sf-card__placeholder svg {
    width: 60px;
    height: 60px;
}

.sf-card__flags {
    position: absolute;
    top: var(--sf-sp-3);
    inset-inline-start: var(--sf-sp-3);
    z-index: 2;
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: var(--sf-sp-2);
}

.sf-card__wish {
    position: absolute;
    top: var(--sf-sp-3);
    inset-inline-end: var(--sf-sp-3);
    z-index: 2;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 38px;
    height: 38px;
    border: 0;
    border-radius: 50%;
    background: rgba(255, 255, 255, .96);
    box-shadow: var(--sf-shadow-xs);
    color: var(--sf-muted);
    cursor: pointer;
    transition: color .18s var(--sf-ease), background .18s var(--sf-ease);
}

.sf-card__wish:hover,
.sf-card__wish.is-active {
    color: var(--sf-price);
    background: #fff;
}

.sf-card__wish svg {
    width: 18px;
    height: 18px;
}

.sf-card__body {
    display: flex;
    flex-direction: column;
    flex: 1;
    gap: var(--sf-sp-2);
    padding: var(--sf-sp-4) var(--sf-sp-4) var(--sf-sp-5);
}

.sf-card__title {
    font-size: 14px;
    font-weight: 500;
    color: var(--sf-ink);
    line-height: 1.5;
    display: -webkit-box;
    -webkit-line-clamp: 2;
    line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
    min-height: 3em;
    transition: color .18s var(--sf-ease);
}

.sf-card__title:hover {
    color: var(--sf-brand);
}

.sf-card__meta {
    display: flex;
    align-items: center;
    gap: var(--sf-sp-2);
    font-size: 12px;
    color: var(--sf-muted);
}

.sf-stars {
    display: inline-flex;
    color: var(--sf-amber);
    letter-spacing: -.5px;
    font-size: 13px;
}

.sf-stars__empty {
    color: #e1e4e8;
}

.sf-stars__half {
    opacity: .5;
}

.sf-card__prices {
    display: flex;
    align-items: baseline;
    gap: var(--sf-sp-2);
    flex-wrap: wrap;
    margin-top: auto;
    padding-top: var(--sf-sp-2);
}

.sf-price {
    color: var(--sf-price);
    font-size: 22px;
    font-weight: 800;
    letter-spacing: -.02em;
}

.sf-price--lg {
    font-size: 32px;
}

.sf-price--compare {
    color: var(--sf-muted-2);
    font-size: 13px;
    font-weight: 500;
    text-decoration: line-through;
}

/* Green savings callout — reinforces the deal. */
.sf-save {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    padding: 3px 9px;
    border-radius: 999px;
    background: #e7f7f1;
    color: #0a7a5c;
    font-size: 11px;
    font-weight: 700;
    white-space: nowrap;
}

.sf-card__stock {
    font-size: 12px;
    color: var(--sf-price-deal);
    font-weight: 600;
}

.sf-card__stock--out {
    color: var(--sf-muted-2);
}

.sf-card__cta {
    margin-top: var(--sf-sp-3);
}

/* -------------------------------------------------------------------------
   11. Sections
   ------------------------------------------------------------------------- */
/* Sections are no longer framed boxes — separation comes from whitespace. */
.sf-section {
    margin-bottom: var(--sf-sp-10);
}

@media (min-width: 768px) {
    .sf-section {
        margin-bottom: var(--sf-sp-12);
    }
}

.sf-section--bare {
    background: transparent;
    border: 0;
    padding: 0;
}

.sf-section__head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--sf-sp-4);
    margin-bottom: var(--sf-sp-6);
    padding-bottom: var(--sf-sp-4);
    border-bottom: 1px solid var(--sf-line);
}

.sf-section__title {
    display: inline-flex;
    align-items: center;
    gap: var(--sf-sp-3);
    font-size: 20px;
    font-weight: 800;
    letter-spacing: -.02em;
}

.sf-section__title::before {
    content: '';
    width: 4px;
    height: 20px;
    border-radius: 2px;
    background: var(--sf-brand);
}

.sf-section__more {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    font-size: 14px;
    font-weight: 600;
    color: var(--sf-muted);
    transition: color .18s var(--sf-ease);
}

.sf-section__more:hover {
    color: var(--sf-brand);
}

/* -------------------------------------------------------------------------
   12. Flash deals + countdown
   ------------------------------------------------------------------------- */
.sf-flash {
    margin-bottom: var(--sf-sp-8);
    background: var(--sf-surface);
    border-radius: var(--sf-radius-lg);
    box-shadow: var(--sf-shadow-sm);
    overflow: hidden;
}

/*
 * Was a saturated orange→red gradient. A full-bleed "SALE!" bar that loud
 * competes with the product cards underneath and with the hero above, so it
 * was toned down to a soft warm wash. The deal signal survives (this is
 * still the only warm-tinted section header on the page) while the red price
 * tags and orange CTAs stay the loudest things in the section.
 */
.sf-flash__head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--sf-sp-4);
    flex-wrap: wrap;
    padding: var(--sf-sp-4) var(--sf-sp-6);
    background: linear-gradient(90deg, #fff8f3 0%, var(--sf-buy-soft) 100%);
    border-bottom: 1px solid #ffe2cb;
    color: var(--sf-ink);
}

.sf-flash__title {
    display: inline-flex;
    align-items: center;
    gap: var(--sf-sp-3);
    font-size: 20px;
    font-weight: 800;
    color: #b23c07;
}

/*
 * The bolt becomes a filled orange chip rather than a bare white glyph — it
 * carries the colour energy the flat header no longer supplies.
 */
.sf-flash__title svg {
    width: 34px;
    height: 34px;
    padding: 7px;
    border-radius: 10px;
    background: linear-gradient(135deg, #ff8a3d, var(--sf-buy));
    color: #fff;
    box-shadow: 0 3px 10px rgba(255, 106, 0, .3);
}

.sf-countdown {
    display: flex;
    align-items: center;
    gap: var(--sf-sp-2);
}

/* Explicit colours (not inherited white) now that the header is a light wash. */
.sf-countdown__label {
    margin-inline-end: var(--sf-sp-1);
    font-size: 13px;
    font-weight: 600;
    color: #96603a;
}

.sf-countdown__box {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 36px;
    padding: 5px 8px;
    border-radius: 8px;
    background: linear-gradient(180deg, var(--sf-buy) 0%, var(--sf-buy-dark) 100%);
    color: #fff;
    font-size: 15px;
    font-weight: 800;
    font-variant-numeric: tabular-nums;
    box-shadow: 0 2px 6px rgba(255, 106, 0, .25);
}

.sf-countdown__sep {
    color: #c98159;
    font-weight: 800;
}

.sf-flash__body {
    padding: var(--sf-sp-6);
}

/* -------------------------------------------------------------------------
   13. Hero banner + promo tiles
   ------------------------------------------------------------------------- */
.sf-hero {
    display: grid;
    gap: var(--sf-sp-5);
    grid-template-columns: 1fr;
    margin-bottom: var(--sf-sp-8);
}

@media (min-width: 1024px) {
    .sf-hero {
        grid-template-columns: 2.2fr 1fr;
    }
}

.sf-hero__main {
    position: relative;
    display: flex;
    flex-direction: column;
    justify-content: center;
    gap: var(--sf-sp-5);
    min-height: 300px;
    padding: var(--sf-sp-10);
    border-radius: var(--sf-radius-lg);
    background: linear-gradient(120deg, var(--sf-brand-deep) 0%, var(--sf-brand) 55%, #5cc8f7 100%);
    color: #fff;
    overflow: hidden;
}

.sf-hero__main::after {
    content: '';
    position: absolute;
    inset-inline-end: -70px;
    bottom: -100px;
    width: 300px;
    height: 300px;
    border-radius: 50%;
    background: rgba(255, 255, 255, .13);
}

.sf-hero__eyebrow {
    align-self: flex-start;
    padding: 6px var(--sf-sp-4);
    border-radius: 999px;
    background: rgba(255, 255, 255, .22);
    font-size: 12px;
    font-weight: 800;
    letter-spacing: .1em;
    text-transform: uppercase;
}

.sf-hero__title {
    max-width: 20ch;
    color: #fff;
    font-size: 38px;
    font-weight: 800;
    line-height: 1.18;
    letter-spacing: -.025em;
}

.sf-hero__text {
    max-width: 48ch;
    font-size: 16px;
    line-height: 1.7;
    color: rgba(255, 255, 255, .95);
}

.sf-hero__actions {
    display: flex;
    flex-wrap: wrap;
    gap: var(--sf-sp-3);
}

.sf-hero__actions .sf-btn {
    position: relative;
    z-index: 1;
}

.sf-hero__chips {
    display: flex;
    flex-wrap: wrap;
    gap: var(--sf-sp-5);
    font-size: 13px;
    color: rgba(255, 255, 255, .94);
}

.sf-hero__side {
    display: grid;
    gap: var(--sf-sp-5);
    grid-template-columns: repeat(2, minmax(0, 1fr));
}

@media (min-width: 1024px) {
    .sf-hero__side {
        grid-template-columns: 1fr;
    }
}

.sf-promo {
    display: flex;
    flex-direction: column;
    justify-content: space-between;
    gap: var(--sf-sp-2);
    min-height: 140px;
    padding: var(--sf-sp-6);
    border-radius: var(--sf-radius-lg);
    background: var(--sf-surface);
    box-shadow: var(--sf-shadow-xs);
    transition: box-shadow .22s var(--sf-ease), transform .22s var(--sf-ease);
}

.sf-promo:hover {
    box-shadow: var(--sf-shadow);
    transform: translateY(-3px);
}

.sf-promo__label {
    font-size: 12px;
    font-weight: 800;
    letter-spacing: .1em;
    text-transform: uppercase;
    color: var(--sf-brand);
}

.sf-promo__title {
    font-size: 19px;
    font-weight: 800;
    color: var(--sf-ink);
}

.sf-promo__text {
    font-size: 13px;
    line-height: 1.6;
    color: var(--sf-muted);
}

.sf-promo--dark {
    background: linear-gradient(140deg, #1e293b, #334155);
}

.sf-promo--dark .sf-promo__title {
    color: #fff;
}

.sf-promo--dark .sf-promo__text {
    color: #c3c9d0;
}

.sf-promo--soft {
    background: var(--sf-brand-tint);
}

.sf-promo--soft .sf-promo__label {
    color: var(--sf-buy);
}

/* -------------------------------------------------------------------------
   Collections — promotional banner (DEMO)
   -------------------------------------------------------------------------
   A slim promo strip for the top of a category page. It reuses the brand
   gradient from `.sf-hero__main` so it belongs to the same promotional
   language, and adds a warm `--sf-buy` eyebrow chip as the "offer" signal.

   The markup is a single self-contained <section> in store/category.php, so the
   banner can be deleted from the view without touching this file.
   ------------------------------------------------------------------------- */
.sf-promobar {
    position: relative;
    display: grid;
    grid-template-columns: minmax(0, 1fr);
    gap: var(--sf-sp-4);
    align-items: center;
    margin-bottom: var(--sf-sp-6);
    padding: var(--sf-sp-5);
    border-radius: var(--sf-radius-lg);
    background: linear-gradient(120deg, var(--sf-brand-deep) 0%, var(--sf-brand) 55%, #5cc8f7 100%);
    box-shadow: var(--sf-shadow-sm);
    color: #fff;
    overflow: hidden;
}

/* Keep the copy column shrinkable beside the action column. */
.sf-promobar__body {
    min-width: 0;
}

@media (min-width: 768px) {
    .sf-promobar {
        grid-template-columns: minmax(0, 1fr) auto;
        gap: var(--sf-sp-6);
        padding: var(--sf-sp-6) var(--sf-sp-8);
    }
}

.sf-promobar__eyebrow {
    display: inline-block;
    margin-bottom: var(--sf-sp-2);
    padding: 4px var(--sf-sp-3);
    border-radius: 999px;
    background: var(--sf-buy);
    color: #fff;
    font-size: 11px;
    font-weight: 800;
    letter-spacing: .08em;
    text-transform: uppercase;
}

/* Colour is set explicitly: `.sf :where(h1, h2, …)` is (0,1,0) and would
   otherwise force ink-coloured text onto an <h2> on the gradient. */
.sf-promobar__title {
    color: #fff;
    font-size: 21px;
    font-weight: 800;
    line-height: 1.25;
    letter-spacing: -.015em;
}

.sf-promobar__text {
    margin-top: var(--sf-sp-1);
    font-size: 14px;
    line-height: 1.6;
    color: rgba(255, 255, 255, .93);
}

.sf-promobar__actions {
    display: flex;
    flex-wrap: wrap;
    gap: var(--sf-sp-3);
}

.sf-promobar__actions .sf-btn {
    white-space: nowrap;
}

/* The default outline button is a white plate, which glares on the gradient —
   make the secondary action a translucent ghost instead. */
.sf-promobar .sf-btn--outline {
    background: rgba(255, 255, 255, .16);
    border-color: rgba(255, 255, 255, .5);
    color: #fff;
}

.sf-promobar .sf-btn--outline:hover:not(:disabled) {
    background: rgba(255, 255, 255, .28);
    border-color: #fff;
    color: #fff;
}

@media (max-width: 767px) {
    .sf-promobar__title {
        font-size: 18px;
    }

    /* Side-by-side full-width buttons are easier to tap than a wrapped row. */
    .sf-promobar__actions .sf-btn {
        flex: 1 1 auto;
    }
}

/* Hero-sized variant for archive and entry pages; the default promo strip stays compact. */
.sf-promobar--lg {
    gap: var(--sf-sp-8);
    min-height: 260px;
    padding: var(--sf-sp-8) var(--sf-sp-10);
}

.sf-promobar--lg .sf-promobar__eyebrow {
    padding: 5px var(--sf-sp-4);
    font-size: 12px;
}

.sf-promobar--lg .sf-promobar__title {
    font-size: 34px;
}

.sf-promobar--lg .sf-promobar__text {
    font-size: 16px;
}

.sf-promobar--lg .sf-btn {
    padding: 11px var(--sf-sp-6);
    font-size: 13px;
}

@media (max-width: 767px) {
    .sf-promobar--lg {
        min-height: 180px;
    }

    .sf-promobar--lg .sf-promobar__title {
        font-size: 24px;
    }
}

/* -------------------------------------------------------------------------
   14. Category tiles + category cards + brand strip
   ------------------------------------------------------------------------- */
/* Category tiles — compact icon tiles that adapt to the number of categories.
   Auto-fit keeps every tile at a compact measure (~140-200px) and fills the
   row, so 7 categories read as one balanced row instead of a few wide ones. */
.sf-tiles {
    display: grid;
    gap: var(--sf-sp-4);
    grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
}

.sf-tile {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: var(--sf-sp-3);
    padding: var(--sf-sp-6) var(--sf-sp-4);
    background: var(--sf-surface);
    border-radius: var(--sf-radius-lg);
    box-shadow: var(--sf-shadow-xs);
    text-align: center;
    transition: box-shadow .22s var(--sf-ease), transform .22s var(--sf-ease);
}

.sf-tile:hover {
    box-shadow: var(--sf-shadow-sm);
    transform: translateY(-3px);
}

.sf-tile__icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 60px;
    height: 60px;
    border-radius: 50%;
    background: var(--sf-brand-soft);
    color: var(--sf-brand);
}

/* Colourful icon chips — each category tile gets a different pastel accent. */
.sf-tile:nth-child(6n+1) .sf-tile__icon { background: #e6f5fd; color: #129fe5; }
.sf-tile:nth-child(6n+2) .sf-tile__icon { background: #fff1e6; color: #ff6a00; }
.sf-tile:nth-child(6n+3) .sf-tile__icon { background: #fdecec; color: #f9475b; }
.sf-tile:nth-child(6n+4) .sf-tile__icon { background: #e7f7f1; color: #0f9d8f; }
.sf-tile:nth-child(6n+5) .sf-tile__icon { background: #fdf3e0; color: #d97706; }
.sf-tile:nth-child(6n+6) .sf-tile__icon { background: #efe9fd; color: #7c3aed; }

.sf-tile__icon svg {
    width: 28px;
    height: 28px;
}

.sf-tile__name {
    font-size: 14px;
    font-weight: 600;
    color: var(--sf-ink);
    line-height: 1.45;
}

.sf-tile__count {
    font-size: 12px;
    color: var(--sf-muted);
}

.sf-cat-grid {
    display: grid;
    gap: var(--sf-sp-5);
    grid-template-columns: repeat(2, minmax(0, 1fr));
}

/*
 * 768px, not 640px — same reason as `.sf-grid` above. These cards carry a
 * 120px banner plus a 13px description in a body with 20px inline padding,
 * so at a 189px card the text measure would be ~149px.
 */
@media (min-width: 768px) {
    .sf-cat-grid {
        grid-template-columns: repeat(3, minmax(0, 1fr));
    }
}

@media (min-width: 1024px) {
    .sf-cat-grid {
        grid-template-columns: repeat(4, minmax(0, 1fr));
    }
}

.sf-cat-card {
    display: flex;
    flex-direction: column;
    background: var(--sf-surface);
    border-radius: var(--sf-radius-lg);
    box-shadow: var(--sf-shadow-xs);
    overflow: hidden;
    transition: box-shadow .22s var(--sf-ease), transform .22s var(--sf-ease);
}

.sf-cat-card:hover {
    box-shadow: var(--sf-shadow);
    transform: translateY(-3px);
}

.sf-cat-card__banner {
    display: flex;
    align-items: center;
    justify-content: center;
    height: 120px;
    background: linear-gradient(135deg, var(--sf-brand-soft), #fff);
    color: var(--sf-brand);
}

.sf-cat-card__banner svg {
    width: 46px;
    height: 46px;
}

.sf-cat-card__body {
    padding: var(--sf-sp-4) var(--sf-sp-5) var(--sf-sp-5);
}

.sf-cat-card__name {
    font-size: 15px;
    font-weight: 700;
    color: var(--sf-ink);
}

.sf-cat-card:hover .sf-cat-card__name {
    color: var(--sf-brand);
}

.sf-cat-card__desc {
    margin-top: 6px;
    font-size: 13px;
    line-height: 1.55;
    color: var(--sf-muted);
}

.sf-cat-card__meta {
    margin-top: var(--sf-sp-2);
    font-size: 12px;
    color: var(--sf-muted);
}

.sf-brands {
    display: flex;
    gap: var(--sf-sp-4);
    overflow-x: auto;
    padding-bottom: var(--sf-sp-2);
    scrollbar-width: none;
}

.sf-brands::-webkit-scrollbar {
    display: none;
}

.sf-brand {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex: 0 0 auto;
    min-width: 124px;
    height: 68px;
    padding-inline: var(--sf-sp-5);
    background: #fff;
    border-radius: var(--sf-radius);
    box-shadow: var(--sf-shadow-xs);
    font-size: 14px;
    font-weight: 700;
    color: var(--sf-ink-2);
    transition: box-shadow .18s var(--sf-ease), color .18s var(--sf-ease);
}

.sf-brand:hover {
    box-shadow: var(--sf-shadow-sm);
    color: var(--sf-brand-dark);
}

/* -------------------------------------------------------------------------
   15. Page head, breadcrumb, filter bar
   ------------------------------------------------------------------------- */
.sf-page-head {
    margin-bottom: var(--sf-sp-6);
}

/* Single-column account layout (≤1023px): the page head sits directly above
   the content, so one step down from the desktop gap keeps the phone rhythm
   tight (matches the .sf-section mobile reduction). */
@media (max-width: 1023px) {
    .sf-page-head {
        margin-bottom: var(--sf-sp-5);
    }
}

.sf-page-title {
    font-size: 28px;
    font-weight: 800;
    letter-spacing: -.02em;
}

.sf-page-sub {
    margin-top: var(--sf-sp-2);
    font-size: 14px;
    color: var(--sf-muted);
}

.sf-crumbs {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--sf-sp-2);
    margin-bottom: var(--sf-sp-5);
    font-size: 13px;
    color: var(--sf-muted);
}

.sf-crumbs a:hover {
    color: var(--sf-brand);
}

.sf-crumbs__sep {
    color: var(--sf-muted-2);
}

.sf-crumbs__current {
    color: var(--sf-ink);
    font-weight: 600;
}

.sf-filterbar {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--sf-sp-4);
    padding: var(--sf-sp-4) var(--sf-sp-5);
    margin-bottom: var(--sf-sp-6);
    background: var(--sf-surface);
    border-radius: var(--sf-radius-lg);
    box-shadow: var(--sf-shadow-xs);
}

.sf-filterbar__count {
    margin-inline-end: auto;
    font-size: 14px;
    color: var(--sf-muted);
}

.sf-select,
.sf-input {
    padding: 11px var(--sf-sp-4);
    border: 1px solid transparent;
    border-radius: var(--sf-radius);
    background: var(--sf-fill);
    color: var(--sf-ink);
    font-family: inherit;
    font-size: 14px;
    line-height: 1.2;
    transition: background .18s var(--sf-ease), border-color .18s var(--sf-ease),
        box-shadow .18s var(--sf-ease);
}

.sf-select:focus,
.sf-input:focus {
    background: var(--sf-surface);
    border-color: var(--sf-brand);
    outline: none;
    box-shadow: 0 0 0 4px var(--sf-brand-soft);
}

.sf-input--sm {
    width: 86px;
}

/* Price filter row: the Go button must sit at the same height as the inputs
   (the button's own padding/font is smaller, so an explicit height keeps the
   row aligned). */
.sf-filterbar__price .sf-input,
.sf-filterbar__price .sf-btn {
    height: 40px;
}

/* Catalog: sidebar + results */
.sf-catalog {
    display: grid;
    gap: var(--sf-sp-6);
    align-items: start;
    grid-template-columns: 1fr;
}

@media (min-width: 1024px) {
    .sf-catalog {
        grid-template-columns: 248px minmax(0, 1fr);
        gap: var(--sf-sp-8);
    }
}

.sf-sidebar {
    display: none;
    background: var(--sf-surface);
    border-radius: var(--sf-radius-lg);
    box-shadow: var(--sf-shadow-sm);
    padding: var(--sf-sp-4) 0;
}

@media (min-width: 1024px) {
    .sf-sidebar {
        display: block;
    }
}

.sf-sidebar__title {
    padding: 0 var(--sf-sp-5) var(--sf-sp-3);
    font-size: 16px;
    font-weight: 800;
}

.sf-sidebar__link {
    display: block;
    padding: 11px var(--sf-sp-5);
    border-inline-start: 3px solid transparent;
    font-size: 14px;
    color: var(--sf-ink-2);
    transition: color .15s var(--sf-ease), background .15s var(--sf-ease);
}

.sf-sidebar__link:hover {
    color: var(--sf-brand);
    background: var(--sf-brand-tint);
}

/* Expanded parent — subtle "current section" cue (faint tint + chevron), clearly
   subtler than the full active highlight. Placed BEFORE --active so the active
   style wins when a node is both expanded and the current page. */
.sf-sidebar__link--expanded {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--sf-sp-2);
    color: var(--sf-ink);
    font-weight: 600;
    background: var(--sf-brand-tint);
}

.sf-sidebar__link--expanded::after {
    content: "▾";
    font-size: 10px;
    line-height: 1;
    color: var(--sf-muted-2);
}

.sf-sidebar__link--active {
    color: var(--sf-brand-dark);
    font-weight: 700;
    border-inline-start-color: var(--sf-brand);
    background: var(--sf-brand-soft);
}

.sf-sidebar__sub a {
    display: block;
    padding: 9px var(--sf-sp-5) 9px 30px;
    font-size: 13px;
    color: var(--sf-muted);
}

.sf-sidebar__sub a:hover {
    color: var(--sf-brand);
}

/* Active subcategory link — must outrank the muted `.sf-sidebar__sub a` base. */
.sf-sidebar__sub a.sf-sidebar__link--active {
    color: var(--sf-brand-dark);
    font-weight: 600;
}

/* --- Catalog: mobile refinements -----------------------------------------
   Sub-category pills shrink to compact chips and scroll horizontally
   (Shopify-style) instead of wrapping into many rows. The filter bar becomes
   a tidy grid: count + sort on the first row, then the tag and price filters
   each full-width below — no more crammed flex-wrap on a phone. */
@media (max-width: 767px) {
    .sf-pill {
        padding: 6px 14px;
        font-size: 12px;
        min-height: 30px;
    }

    .sf-subcats {
        flex-wrap: nowrap;
        overflow-x: auto;
        -webkit-overflow-scrolling: touch;
        scrollbar-width: none;
        padding-bottom: 2px;
    }

    .sf-subcats::-webkit-scrollbar {
        display: none;
    }

    .sf-filterbar {
        display: flex;
        flex-wrap: wrap;
        gap: var(--sf-sp-3);
        padding: var(--sf-sp-3);
    }

    /* Reorder the controls with flex so the count + sort share the first row
       (the count's margin-inline-end:auto pushes the sort right) and the tag
       and price filters each take a full row below. */
    .sf-filterbar__count {
        order: 1;
    }

    .sf-filterbar__sort {
        order: 2;
    }

    .sf-filterbar__tag {
        order: 3;
        flex: 1 1 100%;
    }

    .sf-filterbar__price {
        order: 4;
        flex: 1 1 100%;
    }

    .sf-input--sm {
        width: 72px;
    }

    .sf-filterbar__price .sf-input,
    .sf-filterbar__price .sf-btn {
        height: 34px;
    }

    .sf-select {
        font-size: 13px;
    }
}

/* -------------------------------------------------------------------------
   16. Forms
   ------------------------------------------------------------------------- */
.sf-field {
    margin-bottom: var(--sf-sp-5);
}

/* A field that closes its container needs no trailing gap. */
.sf-field:last-child {
    margin-bottom: 0;
}

.sf-label {
    display: block;
    margin-bottom: var(--sf-sp-2);
    font-size: 14px;
    font-weight: 600;
    color: var(--sf-ink-2);
}

.sf-required {
    color: var(--sf-price);
}

.sf-control {
    display: block;
    width: 100%;
    padding: 11px var(--sf-sp-4);
    border: 1px solid transparent;
    border-radius: var(--sf-radius);
    background: var(--sf-fill);
    color: var(--sf-ink);
    font-family: inherit;
    font-size: 15px;
    line-height: 1.2;
    transition: background .18s var(--sf-ease), border-color .18s var(--sf-ease),
        box-shadow .18s var(--sf-ease);
}

.sf-control:focus {
    background: var(--sf-surface);
    border-color: var(--sf-brand);
    outline: none;
    box-shadow: 0 0 0 4px var(--sf-brand-soft);
}

.sf-control::placeholder {
    color: var(--sf-muted-2);
}

/* Read-only control — one step lighter than the normal filled control so it
   reads as inert, with muted text so it never looks editable. */
.sf-control[readonly] {
    background: var(--sf-surface-2);
    color: var(--sf-muted);
    cursor: default;
}

.sf-help {
    margin-top: 6px;
    font-size: 13px;
    color: var(--sf-muted);
}

/*
 * Checkbox.
 *
 * The browser default is ~13px and paints its own tick, which is both far below
 * a comfortable tap target and impossible to bring in line with the rest of the
 * system. `appearance: none` hands the box over to us: a real 24px square, the
 * brand fill when checked, and a tick we draw ourselves.
 *
 * The tick is an inline SVG data URI rather than a font glyph or a pseudo-
 * element: `::before`/`::after` are not generated on `<input>` (a replaced
 * element), so a background image is the only reliable way to paint it.
 * White on `--sf-brand` works in both themes — §27 re-points the neutral tokens
 * but deliberately leaves the brand ramp alone.
 */
.sf-checkbox {
    appearance: none;
    -webkit-appearance: none;
    flex: none;
    width: 24px;
    height: 24px;
    margin: 0;
    border: 2px solid var(--sf-line-strong);
    border-radius: 7px;
    background-color: var(--sf-surface);
    vertical-align: middle;
    cursor: pointer;
    transition: background-color .16s var(--sf-ease), border-color .16s var(--sf-ease),
        box-shadow .16s var(--sf-ease);
}

.sf-checkbox:hover {
    border-color: var(--sf-brand);
}

.sf-checkbox:checked {
    border-color: var(--sf-brand);
    background-color: var(--sf-brand);
    background-image: url("data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2024%2024'%20fill='none'%20stroke='%23fff'%20stroke-width='3.5'%20stroke-linecap='round'%20stroke-linejoin='round'%3E%3Cpath%20d='M20%206L9%2017l-5-5'/%3E%3C/svg%3E");
    background-repeat: no-repeat;
    background-position: center;
    background-size: 15px 15px;
}

/*
 * Keyboard only: `:focus-visible` keeps the ring off a mouse click, so a
 * pointer user sees a clean tick and a keyboard user still sees where they are.
 * Same ring as `.sf-control:focus`, so the two controls focus alike.
 */
.sf-checkbox:focus-visible {
    outline: none;
    border-color: var(--sf-brand);
    box-shadow: 0 0 0 4px var(--sf-brand-soft);
}

.sf-checkbox:disabled {
    opacity: .5;
    cursor: not-allowed;
}

/*
 * Label row for a `.sf-checkbox`: the box stays 24px, but the whole row is the
 * control, so `min-height` gives it the 44px touch target the raw input never
 * had. `user-select: none` stops a double-tap on the label from selecting the
 * text, which is what makes a label feel like a button.
 */
.sf-check {
    display: inline-flex;
    align-items: center;
    gap: var(--sf-sp-3);
    min-height: 44px;
    font-size: 14px;
    color: var(--sf-ink-2);
    cursor: pointer;
    user-select: none;
    -webkit-user-select: none;
}

.sf-check:hover {
    color: var(--sf-ink);
}

.sf-check:has(.sf-checkbox:disabled) {
    cursor: not-allowed;
}

/* Star rating picker (account review form) */
.sf-stars {
    display: inline-flex;
    gap: 4px;
}

.sf-star {
    background: none;
    border: 0;
    padding: 0;
    font-size: 26px;
    line-height: 1;
    color: var(--sf-muted-2);
    cursor: pointer;
    transition: color .15s var(--sf-ease);
}

.sf-star:hover,
.sf-star.is-on {
    color: var(--sf-amber);
}

.sf-card-panel {
    background: var(--sf-surface);
    border-radius: var(--sf-radius-lg);
    box-shadow: var(--sf-shadow-sm);
    padding: var(--sf-sp-6);
}

.sf-auth {
    display: flex;
    align-items: center;
    justify-content: center;
    min-height: 60vh;
    padding-block: var(--sf-sp-8);
}

.sf-auth__box {
    width: 100%;
    max-width: 440px;
    background: var(--sf-surface);
    border-radius: var(--sf-radius-lg);
    box-shadow: var(--sf-shadow);
    padding: var(--sf-sp-8);
}

.sf-auth__head {
    margin-bottom: var(--sf-sp-8);
    text-align: center;
}

.sf-auth__title {
    font-size: 24px;
    font-weight: 800;
}

.sf-auth__sub {
    margin-top: 6px;
    font-size: 14px;
    color: var(--sf-muted);
}

.sf-auth__alt {
    margin-top: var(--sf-sp-6);
    text-align: center;
    font-size: 14px;
    color: var(--sf-muted);
}

.sf-auth__alt a {
    color: var(--sf-brand-dark);
    font-weight: 600;
}

/* -------------------------------------------------------------------------
   17. Alerts / flash messages
   ------------------------------------------------------------------------- */
.sf-alert {
    display: flex;
    align-items: flex-start;
    gap: var(--sf-sp-3);
    padding: var(--sf-sp-4) var(--sf-sp-5);
    border: 1px solid transparent;
    border-radius: var(--sf-radius);
    font-size: 14px;
}

.sf-alert--success {
    background: #e9f9f1;
    border-color: #b9e9d3;
    color: #0a7a5c;
}

.sf-alert--error,
.sf-alert--danger {
    background: #fdecec;
    border-color: #f6c9c6;
    color: #b32b2b;
}

.sf-alert--warning {
    background: #fff7e6;
    border-color: #ffe0a8;
    color: #96650a;
}

.sf-alert--info {
    background: #eef4fe;
    border-color: #cfe0fb;
    color: #1a5bbf;
}

.sf-alert-wrap {
    margin-top: var(--sf-sp-4);
}

/* -------------------------------------------------------------------------
   18. Tables
   ------------------------------------------------------------------------- */
.sf-table {
    width: 100%;
    border-collapse: collapse;
    background: var(--sf-surface);
}

.sf-table thead th {
    padding: var(--sf-sp-4) var(--sf-sp-5);
    background: transparent;
    border-bottom: 1px solid var(--sf-line);
    font-size: 12px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: .05em;
    color: var(--sf-muted);
    text-align: start;
    white-space: nowrap;
}

.sf-table tbody td {
    padding: var(--sf-sp-5);
    border-bottom: 1px solid var(--sf-line);
    font-size: 14px;
    color: var(--sf-ink-2);
    vertical-align: middle;
}

.sf-table tbody tr:hover {
    background: var(--sf-surface-2);
}

.sf-table__num {
    text-align: end;
    white-space: nowrap;
}

.sf-table__center {
    text-align: center;
}

.sf-thumb {
    width: 84px;
    height: 84px;
    flex-shrink: 0;
    object-fit: contain;
    border-radius: var(--sf-radius);
    background: var(--sf-surface-2);
    padding: var(--sf-sp-2);
}

.sf-media {
    display: flex;
    align-items: center;
    gap: var(--sf-sp-4);
}

.sf-media__title {
    font-size: 14px;
    font-weight: 600;
    color: var(--sf-ink);
    transition: color .15s var(--sf-ease);
}

.sf-media__title:hover {
    color: var(--sf-brand);
}

.sf-media__sub {
    margin-top: var(--sf-sp-1);
    font-size: 13px;
    color: var(--sf-muted);
}

/* Quantity stepper */
.sf-qty {
    display: inline-flex;
    align-items: center;
    border-radius: 999px;
    background: var(--sf-fill);
    overflow: hidden;
}

.sf-qty__btn {
    width: 42px;
    height: 46px;
    border: 0;
    background: transparent;
    color: var(--sf-ink-2);
    font-size: 18px;
    font-weight: 700;
    cursor: pointer;
    transition: background .15s var(--sf-ease), color .15s var(--sf-ease);
}

.sf-qty__btn:hover {
    background: var(--sf-brand-soft);
    color: var(--sf-brand-dark);
}

.sf-qty__input {
    width: 56px;
    height: 46px;
    border: 0;
    background: transparent;
    text-align: center;
    font-family: inherit;
    font-size: 15px;
    font-weight: 600;
    color: var(--sf-ink);
}

.sf-qty__input:focus {
    outline: none;
}

/* -------------------------------------------------------------------------
   19. Panels, summaries, totals
   ------------------------------------------------------------------------- */
/* Card surface — a panel and an empty state are the SAME object visually, so
   the surface is declared once here and each adds only what is specific to it
   (.sf-panel clips, .sf-empty pads and centres). Declaring it twice let them
   drift: the panel was on --sf-shadow-sm while the empty state was on
   --sf-shadow-xs, so the two looked like different components on one page.
   Both carry the ambient layer via the token, so the top edge stays defined. */
.sf-panel,
.sf-empty {
    background: var(--sf-surface);
    border-radius: var(--sf-radius-lg);
    box-shadow: var(--sf-shadow-xs);
}

.sf-panel {
    overflow: hidden;
}

.sf-panel__head {
    padding: var(--sf-sp-5) var(--sf-sp-6);
    border-bottom: 1px solid var(--sf-line);
    font-size: 17px;
    font-weight: 800;
    letter-spacing: -.01em;
}

/* Header band — this is what defines the section. The heading sits on a filled
   strip (--sf-fill, the same token the USP band uses) so head and body
   separate by TONE alone: legible at a glance on a white page, with no
   outline and nothing added to the divider. Scoped to a direct child so the
   class can still be borrowed as a plain standalone heading
   (store/account/index.php uses it inside a <section>). */
.sf-panel > .sf-panel__head {
    background: var(--sf-fill);
}

/* Trailing qualifier on a panel heading, e.g. "Change Password (optional)". */
.sf-panel__head-note {
    margin-inline-start: 6px;
    font-size: 13px;
    font-weight: 500;
    color: var(--sf-muted);
}

/* The body is deliberately quiet: the header band above already carries the
   boundary, so adding anything here would only add noise. */
.sf-panel__body {
    padding: var(--sf-sp-6);
}

.sf-summary {
    position: sticky;
    top: calc(var(--sf-header-h) + 62px);
}

.sf-summary__row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--sf-sp-4);
    padding-block: 10px;
    font-size: 14px;
    color: var(--sf-muted);
}

.sf-summary__row strong {
    color: var(--sf-ink);
}

.sf-summary__total {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: var(--sf-sp-4);
    margin-top: var(--sf-sp-3);
    padding-top: var(--sf-sp-5);
    border-top: 1px solid var(--sf-line);
    font-size: 16px;
    font-weight: 800;
    color: var(--sf-ink);
}

.sf-summary__total .sf-price {
    font-size: 26px;
}

.sf-progress {
    height: 8px;
    border-radius: 4px;
    background: var(--sf-fill);
    overflow: hidden;
}

.sf-progress__bar {
    height: 100%;
    border-radius: 4px;
    background: linear-gradient(90deg, var(--sf-brand), #5cc8f7);
}

/* -------------------------------------------------------------------------
   20. Pagination
   ------------------------------------------------------------------------- */
.sf-pagination {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: center;
    gap: var(--sf-sp-2);
    margin-top: var(--sf-sp-8);
}

.sf-page-link {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 44px;
    height: 44px;
    padding-inline: var(--sf-sp-4);
    border-radius: 999px;
    background: transparent;
    font-size: 14px;
    font-weight: 600;
    color: var(--sf-ink-2);
    transition: background .18s var(--sf-ease), color .18s var(--sf-ease);
}

.sf-page-link:hover {
    background: var(--sf-fill);
    color: var(--sf-brand-dark);
}

.sf-page-link--active {
    background: var(--sf-brand);
    color: #fff;
}

.sf-page-link--disabled {
    opacity: .45;
    pointer-events: none;
}

/* -------------------------------------------------------------------------
   21. Product detail
   ------------------------------------------------------------------------- */
.sf-pdp-wrap {
    width: 100%;
}

.sf-pdp {
    display: grid;
    gap: var(--sf-sp-6);
    grid-template-columns: 1fr;
}

@media (min-width: 1024px) {
    .sf-pdp {
        grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
        gap: var(--sf-sp-10);
    }
}

.sf-pdp__gallery {
    background: #fff;
    border-radius: var(--sf-radius-lg);
    box-shadow: var(--sf-shadow-sm);
    padding: var(--sf-sp-5);
}

/*
 * Main image area is a horizontal scroll-snap carousel. On mobile the thumbs
 * are hidden and the user swipes; on desktop (≥1024px) it is locked to one
 * slide and the left-hand thumbnails drive it.
 */
.sf-pdp__main {
    display: flex;
    align-items: center;
    aspect-ratio: 1 / 1;
    overflow-x: auto;
    overflow-y: hidden;
    scroll-snap-type: x mandatory;
    scrollbar-width: none;
}

.sf-pdp__main::-webkit-scrollbar {
    display: none;
}

.sf-pdp__slide {
    flex: 0 0 100%;
    display: flex;
    align-items: center;
    justify-content: center;
    aspect-ratio: 1 / 1;
    scroll-snap-align: center;
}

.sf-pdp__slide img {
    width: 100%;
    height: 100%;
    object-fit: contain;
}

/* Thumbnails are desktop-only — on mobile users swipe the carousel instead. */
.sf-pdp__thumbs {
    display: none;
}

.sf-pdp__thumb {
    flex: 0 0 auto;
    width: 74px;
    height: 74px;
    padding: 5px;
    border: 2px solid var(--sf-line);
    border-radius: var(--sf-radius-sm);
    background: #fff;
    cursor: pointer;
    transition: border-color .18s var(--sf-ease);
}

.sf-pdp__thumb img {
    width: 100%;
    height: 100%;
    object-fit: contain;
}

.sf-pdp__thumb:hover,
.sf-pdp__thumb.is-active {
    border-color: var(--sf-brand);
}

/* Desktop: thumbnails move to the LEFT of the main image. */
@media (min-width: 1024px) {
    .sf-pdp__gallery:has(.sf-pdp__thumbs) {
        display: grid;
        grid-template-columns: 84px minmax(0, 1fr);
        gap: var(--sf-sp-4);
        align-items: start;
    }

    .sf-pdp__main {
        order: 2;
        overflow: hidden;
        scroll-snap-type: none;
    }

    .sf-pdp__thumbs {
        order: 1;
        display: flex;
        flex-direction: column;
        gap: var(--sf-sp-3);
        margin-top: 0;
        overflow-y: auto;
        overflow-x: hidden;
        max-height: 480px;
        padding-bottom: 0;
        scrollbar-width: thin;
    }
}

.sf-pdp__title {
    margin-bottom: var(--sf-sp-4);
    font-size: 28px;
    font-weight: 800;
    line-height: 1.35;
    letter-spacing: -.02em;
}

/* Price sits directly on the page — no tinted box. */
.sf-pdp__pricebox {
    display: flex;
    align-items: baseline;
    gap: var(--sf-sp-4);
    flex-wrap: wrap;
    margin-bottom: var(--sf-sp-5);
}

.sf-opt {
    display: inline-flex;
    align-items: center;
    padding: 11px var(--sf-sp-5);
    border: 1px solid transparent;
    border-radius: 999px;
    background: var(--sf-fill);
    font-family: inherit;
    font-size: 14px;
    font-weight: 600;
    line-height: 1.2;
    color: var(--sf-ink-2);
    cursor: pointer;
    transition: border-color .18s var(--sf-ease), color .18s var(--sf-ease),
        background .18s var(--sf-ease);
}

.sf-opt:hover {
    background: var(--sf-brand-soft);
    color: var(--sf-brand-dark);
}

.sf-opt.is-active {
    border-color: var(--sf-brand);
    background: var(--sf-brand-soft);
    color: var(--sf-brand-dark);
}

.sf-qty-block {
    display: flex;
    align-items: center;
    gap: var(--sf-sp-4);
    margin-bottom: var(--sf-sp-5);
}

.sf-buy-actions {
    display: flex;
    gap: var(--sf-sp-3);
    flex-wrap: wrap;
    align-items: center;
}

.sf-buy-actions .sf-btn {
    flex: 1 1 180px;
}

.sf-wish-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    padding: 13px var(--sf-sp-5);
    border: 1px solid transparent;
    border-radius: 999px;
    background: var(--sf-fill);
    color: var(--sf-muted);
    cursor: pointer;
    transition: color .18s var(--sf-ease), background .18s var(--sf-ease);
}

.sf-wish-btn:hover,
.sf-wish-btn.is-active {
    color: var(--sf-price);
    background: #fdecec;
}

.sf-wish-btn svg {
    width: 24px;
    height: 24px;
}

.sf-trust {
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: var(--sf-sp-3);
    margin-top: var(--sf-sp-6);
}

.sf-trust__item {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: var(--sf-sp-2);
    padding: var(--sf-sp-4) var(--sf-sp-3);
    background: var(--sf-surface-2);
    border-radius: var(--sf-radius);
    text-align: center;
    font-size: 12px;
    line-height: 1.5;
    color: var(--sf-muted);
}

.sf-trust__item svg {
    width: 22px;
    height: 22px;
    color: var(--sf-brand);
}

.sf-tabs {
    display: flex;
    gap: var(--sf-sp-1);
    margin-bottom: var(--sf-sp-5);
    border-bottom: 1px solid var(--sf-line);
}

.sf-tab {
    padding: 13px var(--sf-sp-5);
    border: 0;
    border-bottom: 3px solid transparent;
    background: none;
    font-family: inherit;
    font-size: 15px;
    font-weight: 700;
    color: var(--sf-muted);
    cursor: pointer;
}

.sf-tab.is-active {
    color: var(--sf-brand);
    border-bottom-color: var(--sf-brand);
}

/* -------------------------------------------------------------------------
   22. Account
   ------------------------------------------------------------------------- */
.sf-account {
    display: grid;
    gap: var(--sf-sp-6);
    align-items: start;
    grid-template-columns: 1fr;
}

@media (min-width: 1024px) {
    .sf-account {
        grid-template-columns: 248px minmax(0, 1fr);
        gap: var(--sf-sp-8);
    }
}

.sf-stats {
    display: grid;
    gap: var(--sf-sp-4);
    grid-template-columns: repeat(2, minmax(0, 1fr));
}

@media (min-width: 768px) {
    .sf-stats {
        grid-template-columns: repeat(4, minmax(0, 1fr));
    }
}

.sf-stat {
    padding: var(--sf-sp-6);
    background: var(--sf-surface);
    border-radius: var(--sf-radius-lg);
    box-shadow: var(--sf-shadow-xs);
    text-align: center;
}

.sf-stat__value {
    font-size: 26px;
    font-weight: 800;
    color: var(--sf-brand);
}

.sf-stat__label {
    margin-top: var(--sf-sp-2);
    font-size: 13px;
    color: var(--sf-muted);
}

/* --- Account navigation -------------------------------------------------
   Mobile-first: a back link replaces the row list on small screens so each
   sub-page has a single job. From 1024px the row list becomes the persistent
   sidebar on every account page. The back link is styled like the PDP
   breadcrumb (.sf-crumbs) so the account sub-pages read the same way. */
.sf-account__back {
    display: inline-flex;
    align-items: center;
    gap: var(--sf-sp-2);
    margin-bottom: var(--sf-sp-5);
    font-size: 13px;
    color: var(--sf-muted);
    text-decoration: none;
}

.sf-account__back:hover {
    color: var(--sf-brand);
}

.sf-account__nav {
    overflow: hidden;
    background: var(--sf-surface);
    border-radius: var(--sf-radius-lg);
    box-shadow: var(--sf-shadow-xs);
}

@media (max-width: 1023px) {
    .sf-account__nav--wide-only {
        display: none;
    }

    /* Sub-pages hide the nav list on mobile, leaving an empty <aside> that
       still occupies a grid row and adds a phantom 24px gap above the content.
       Collapse it so the page head sits directly on the content. The overview
       keeps its nav list on mobile, so its aside is left untouched. */
    .sf-account > aside:has(.sf-account__nav--wide-only) {
        display: none;
    }
}

@media (min-width: 1024px) {
    .sf-account__back {
        display: none;
    }

    /*
     * Pin the SIDEBAR, not a card inside it.
     *
     * The sticky used to sit on `.sf-account__nav` itself, which only works
     * while the aside holds a single card. A sticky element cannot leave its
     * containing block, and the aside is exactly as tall as its contents — so
     * the card was clamped after ~160px of travel and slid DOWN over the
     * Customer Service label and card, covering them for the rest of the
     * scroll. Measured (headless Edge, 1280x1000): the support card's top sat
     * 48–104px inside the menu card's box at every scroll offset, i.e. the
     * support block was permanently behind the menu.
     *
     * The aside's containing block is its grid AREA, which is as tall as the
     * page content, so sticking the aside pins the whole rail — menu and
     * Customer Service together — and every card keeps its normal spacing.
     */
    .sf-account > aside {
        position: sticky;
        top: calc(var(--sf-header-h) + var(--sf-sp-4));
    }

    .sf-account__nav {
        margin-bottom: var(--sf-sp-4);
    }
}

.sf-nav-row {
    position: relative;
    display: flex;
    align-items: center;
    gap: var(--sf-sp-3);
    min-height: 52px;
    padding: 0 var(--sf-sp-5);
    font-size: 14px;
    font-weight: 600;
    color: var(--sf-ink-2);
    text-decoration: none;
    border-top: 1px solid var(--sf-line);
}

.sf-nav-row:first-child {
    border-top: 0;
}

.sf-nav-row:hover {
    background: var(--sf-surface-2);
    color: var(--sf-ink);
}

.sf-nav-row.is-active {
    background: var(--sf-brand-tint);
    color: var(--sf-brand-deep);
}

.sf-nav-row__icon {
    display: inline-flex;
    flex-shrink: 0;
    color: var(--sf-muted);
}

.sf-nav-row.is-active .sf-nav-row__icon {
    color: var(--sf-brand);
}

.sf-nav-row__label {
    flex: 1 1 auto;
    min-width: 0;
}

.sf-nav-row__count {
    flex-shrink: 0;
    min-width: 22px;
    padding: 1px 7px;
    border-radius: 999px;
    background: var(--sf-fill);
    color: var(--sf-ink-2);
    font-size: 12px;
    font-weight: 700;
    text-align: center;
}

.sf-nav-row.is-active .sf-nav-row__count {
    background: var(--sf-brand);
    color: #fff;
}

.sf-nav-row__chev {
    display: inline-flex;
    flex-shrink: 0;
    color: var(--sf-muted-2);
}

.sf-nav-row--danger {
    color: var(--sf-price);
}

.sf-nav-row--danger .sf-nav-row__icon {
    color: currentColor;
}

/* The whole row is the tap target for the logout form. */
.sf-nav-row__hit {
    position: absolute;
    inset: 0;
    padding: 0;
    border: 0;
    background: none;
    cursor: pointer;
}

/*
 * Small group label above a second sidebar card (see account/_nav.php).
 *
 * The support links are public pages, not account sections, so they need to
 * read as a different group — the label plus the card gap does that where the
 * row list alone would show them as two more account entries.
 */
.sf-account__group-label {
    margin: var(--sf-sp-5) 0 var(--sf-sp-2);
    padding-inline: var(--sf-sp-5);
    font-size: 12px;
    font-weight: 700;
    letter-spacing: .06em;
    text-transform: uppercase;
    color: var(--sf-muted);
}

/*
 * `.sf-account__nav--support` deliberately carries NO rules of its own: neither
 * card may be sticky individually, because a sticky card inside this
 * content-height aside slides down over the Customer Service block. The whole
 * aside pins as one unit — see the `.sf-account > aside` rule in the ≥1024px
 * block above. The class stays as the hook identifying that second card.
 */

/* --- Account content ---------------------------------------------------- */
.sf-account__main {
    display: grid;
    gap: var(--sf-sp-5);
    min-width: 0;
}

.sf-account__title {
    font-size: 22px;
    font-weight: 800;
    letter-spacing: -0.01em;
    color: var(--sf-ink);
}

.sf-account__lead {
    margin-top: 2px;
    font-size: 14px;
    color: var(--sf-muted);
}

/* --- Account: order list toolbar ----------------------------------------
   Search on the left, sort on the right, one row that wraps on a phone. The
   sort control is pushed to the far end with margin-inline-start:auto so the
   bar keeps a single reading: narrow the list on the left, re-order whatever
   is left on the right.

   Both controls live in ONE form in the markup, so changing the sort keeps
   the search text and the active status chip (and vice versa) for free.
   ------------------------------------------------------------------------ */
.sf-orders-bar {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--sf-sp-3);
    /* No margin-bottom: the .sf-account__main grid gap already spaces the
       toolbar rows, so a margin here would double the gap to ~36px. */
}

/* Narrower than the standalone hero search: this one shares the row. */
.sf-orders-bar .sf-search {
    flex: 1 1 240px;
    max-width: 420px;
}

.sf-orders-bar__sort {
    display: flex;
    align-items: center;
    gap: var(--sf-sp-2);
    margin-inline-start: auto;
}

.sf-orders-bar__label {
    font-size: 13px;
    color: var(--sf-muted);
    white-space: nowrap;
}

/* Phone: sorting is rarely used on a small screen, so it is dropped and the
   search owns the full row. The chips and search read as one grouped toolbar:
   the 20px grid gap between them is tightened to 12px (the chipbar's negative
   bottom margin pulls the search up by 8px). The sort stays available on
   tablet and desktop. */
@media (max-width: 767px) {
    .sf-orders-bar__sort {
        display: none;
    }

    .sf-orders-bar .sf-search {
        flex: 1 1 auto;
        max-width: none;
    }

    .sf-chipbar {
        margin-bottom: calc(-1 * var(--sf-sp-2));
    }
}

/* --- Order status chips ------------------------------------------------- */
.sf-chipbar {
    display: flex;
    gap: var(--sf-sp-2);
    /* No margin-bottom: the .sf-account__main grid gap already spaces the
       toolbar rows, so a margin here would double the gap to ~36px. */
    padding-bottom: 2px;
    overflow-x: auto;
    scrollbar-width: none;
    -webkit-overflow-scrolling: touch;
}

.sf-chipbar::-webkit-scrollbar {
    display: none;
}

.sf-chip {
    flex: 0 0 auto;
    display: inline-flex;
    align-items: center;
    gap: 6px;
    min-height: 36px;
    padding: 0 var(--sf-sp-4);
    border: 1px solid var(--sf-line-strong);
    border-radius: 999px;
    background: var(--sf-surface);
    color: var(--sf-ink-2);
    font-size: 13px;
    font-weight: 600;
    white-space: nowrap;
    text-decoration: none;
}

.sf-chip:hover {
    border-color: var(--sf-brand);
    color: var(--sf-brand-deep);
}

.sf-chip.is-active {
    background: var(--sf-brand);
    border-color: var(--sf-brand);
    color: #fff;
}

.sf-chip__count {
    font-size: 12px;
    opacity: 0.7;
}

/* --- Order card --------------------------------------------------------- */
.sf-order-card {
    padding: var(--sf-sp-4);
    background: var(--sf-surface);
    border-radius: var(--sf-radius-lg);
    box-shadow: var(--sf-shadow-xs);
}

.sf-order-card + .sf-order-card {
    margin-top: var(--sf-sp-3);
}

.sf-order-card__head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--sf-sp-3);
}

.sf-order-card__number {
    font-size: 15px;
    font-weight: 700;
    color: var(--sf-ink);
}

.sf-order-card__meta {
    margin-top: 2px;
    font-size: 13px;
    color: var(--sf-muted);
}

.sf-order-card__thumbs {
    display: flex;
    gap: var(--sf-sp-2);
    margin-top: var(--sf-sp-3);
}

.sf-order-card__thumb {
    position: relative;
    width: 54px;
    height: 54px;
    flex: 0 0 auto;
    overflow: hidden;
    border-radius: 10px;
    background: var(--sf-surface-2);
}

.sf-order-card__thumb img {
    width: 100%;
    height: 100%;
    object-fit: cover;
}

.sf-order-card__more {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 54px;
    height: 54px;
    flex: 0 0 auto;
    border-radius: 10px;
    background: var(--sf-fill);
    font-size: 13px;
    font-weight: 700;
    color: var(--sf-ink-2);
}

.sf-order-card__foot {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--sf-sp-3);
    margin-top: var(--sf-sp-4);
    padding-top: var(--sf-sp-3);
    border-top: 1px solid var(--sf-line);
}

.sf-order-card__total {
    font-size: 15px;
    font-weight: 800;
    color: var(--sf-ink);
}

.sf-order-card__actions {
    display: flex;
    gap: var(--sf-sp-2);
}

/* --- Order status stepper ---------------------------------------------- */
.sf-steps {
    display: grid;
    gap: var(--sf-sp-4);
}

.sf-step {
    position: relative;
    display: grid;
    grid-template-columns: 22px minmax(0, 1fr);
    gap: var(--sf-sp-3);
    align-items: start;
}

/* Connector between dots. */
.sf-step:not(:last-child)::before {
    content: '';
    position: absolute;
    top: 22px;
    bottom: calc(var(--sf-sp-4) * -1);
    left: 10px;
    width: 2px;
    background: var(--sf-line-strong);
}

.sf-step.is-done:not(:last-child)::before {
    background: var(--sf-brand);
}

.sf-step__dot {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 22px;
    height: 22px;
    border-radius: 999px;
    background: var(--sf-fill);
    color: var(--sf-muted-2);
    font-size: 11px;
    font-weight: 700;
}

.sf-step.is-done .sf-step__dot {
    background: var(--sf-brand);
    color: #fff;
}

.sf-step__label {
    font-size: 14px;
    font-weight: 600;
    color: var(--sf-ink);
}

.sf-step__time {
    margin-top: 2px;
    font-size: 12px;
    color: var(--sf-muted);
}

/* --- Address card ------------------------------------------------------- */
.sf-address-card {
    position: relative;
    padding: var(--sf-sp-5);
    background: var(--sf-surface);
    border-radius: var(--sf-radius-lg);
    box-shadow: var(--sf-shadow-xs);
}

.sf-address-card.is-default {
    box-shadow: inset 0 0 0 1px var(--sf-brand), var(--sf-shadow-xs);
}

.sf-address-card__badge {
    position: absolute;
    top: var(--sf-sp-4);
    right: var(--sf-sp-4);
}

.sf-address-card__name {
    font-size: 15px;
    font-weight: 700;
    color: var(--sf-ink);
}

.sf-address-card__body {
    margin-top: 6px;
    font-size: 13px;
    line-height: 1.65;
    color: var(--sf-ink-2);
}

.sf-address-card__foot {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--sf-sp-3);
    margin-top: var(--sf-sp-4);
    padding-top: var(--sf-sp-3);
    border-top: 1px solid var(--sf-line);
}

/* --- Account: profile form ----------------------------------------------
   Fills the account main column (1fr) — no max-width, so the stats row, panels
   and fields all stretch to the full available width.
   ------------------------------------------------------------------------ */
.sf-profile {
    display: grid;
    gap: var(--sf-sp-5);
}

.sf-profile__form {
    display: grid;
    gap: var(--sf-sp-5);
}

/* Mobile-first: the save action is full width and sits last in the flow. */
.sf-profile__actions {
    display: flex;
    gap: var(--sf-sp-3);
}

.sf-profile__actions .sf-btn {
    width: 100%;
}

@media (min-width: 768px) {
    .sf-profile__actions {
        justify-content: flex-end;
    }

    .sf-profile__actions .sf-btn {
        width: auto;
    }
}

/* Two-up stats. The 4-track default would leave half the row empty with only
   two figures, so this is placed AFTER the .sf-stats media query to win at
   equal specificity. */
.sf-stats--2 {
    grid-template-columns: repeat(2, minmax(0, 1fr));
}

/* -------------------------------------------------------------------------
   23. Footer
   ------------------------------------------------------------------------- */
/* A soft grey band between the white content and the dark footer. */
.sf-usps {
    margin-top: var(--sf-sp-12);
    background: var(--sf-fill);
}

.sf-usps__grid {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: var(--sf-sp-5);
    padding-block: var(--sf-sp-8);
}

@media (min-width: 768px) {
    .sf-usps__grid {
        grid-template-columns: repeat(4, minmax(0, 1fr));
        gap: var(--sf-sp-6);
    }
}

.sf-usp {
    display: flex;
    align-items: center;
    gap: var(--sf-sp-3);
    font-size: 14px;
    font-weight: 600;
    color: var(--sf-ink-2);
}

.sf-usp svg {
    width: 30px;
    height: 30px;
    flex-shrink: 0;
    color: var(--sf-brand);
}

.sf-footer {
    /*
     * NO margin-top. The USP strip (`.sf-usps`) is always rendered directly
     * above the footer, so any margin here opens a band of PAGE background
     * between the grey strip and the dark footer — a white (light) or black
     * (dark) gap that reads as a mistake. The two bands sit flush.
     * This was fixed once already and regressed; do not re-add.
     */
    background: #23282e;
    color: #b8bec6;
    font-size: 14px;
}

.sf-footer__grid {
    display: grid;
    grid-template-columns: 1fr;
    gap: var(--sf-sp-8);
    padding-block: var(--sf-sp-12);
}

@media (min-width: 640px) {
    .sf-footer__grid {
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }
}

@media (min-width: 1024px) {
    .sf-footer__grid {
        grid-template-columns: 2fr 1fr 1fr 1fr 1fr;
        gap: var(--sf-sp-8);
    }
}

.sf-footer h3 {
    margin-bottom: var(--sf-sp-4);
    color: #fff;
    font-size: 15px;
    font-weight: 700;
}

.sf-footer__list {
    display: flex;
    flex-direction: column;
    gap: 10px;
}

.sf-footer__list a {
    color: #b8bec6;
    transition: color .18s var(--sf-ease);
}

.sf-footer__list a:hover {
    color: var(--sf-brand);
}

.sf-footer__brand {
    display: inline-flex;
    align-items: center;
    gap: var(--sf-sp-3);
    margin-bottom: var(--sf-sp-4);
    color: #fff;
    font-size: 22px;
    font-weight: 800;
}

/*
 * The footer is dark (#23282e) and the logo artwork is dark blue + yellow, so
 * it sits on a white plate rather than relying on the transparent PNG.
 */
.sf-footer__logo {
    display: block;
    width: auto;
    height: 40px;
    padding: 6px 10px;
    border-radius: 10px;
    background: #fff;
}

.sf-footer__social {
    display: flex;
    gap: var(--sf-sp-3);
    margin-top: var(--sf-sp-5);
}

.sf-footer__social a {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 40px;
    height: 40px;
    border-radius: 50%;
    background: #333940;
    color: #dfe3e8;
    transition: background .18s var(--sf-ease), color .18s var(--sf-ease);
}

.sf-footer__social a:hover {
    background: var(--sf-brand);
    color: #fff;
}

.sf-footer__social svg {
    width: 18px;
    height: 18px;
}

.sf-footer__pay {
    display: flex;
    flex-wrap: wrap;
    gap: var(--sf-sp-2);
    margin-top: var(--sf-sp-5);
}

.sf-footer__pay span {
    padding: 6px var(--sf-sp-3);
    border: 1px solid #3d444c;
    border-radius: var(--sf-radius-sm);
    background: #2b3138;
    font-size: 12px;
    font-weight: 600;
    color: #cfd5db;
}

.sf-footer__bottom {
    padding-block: var(--sf-sp-5);
    border-top: 1px solid #333940;
    font-size: 13px;
    color: #8d959e;
    text-align: center;
}

/* -------------------------------------------------------------------------
   24. Empty state
   ------------------------------------------------------------------------- */
/* Surface comes from the shared .sf-panel/.sf-empty rule in section 19 — this
   adds only what is specific to an empty state. */
.sf-empty {
    padding: var(--sf-sp-12) var(--sf-sp-6);
    text-align: center;
}

.sf-empty__icon {
    display: inline-flex;
    margin-bottom: var(--sf-sp-4);
    color: #dfe3e8;
}

.sf-empty__icon svg {
    width: 72px;
    height: 72px;
}

.sf-empty__title {
    margin-bottom: var(--sf-sp-2);
    font-size: 20px;
    font-weight: 700;
}

.sf-empty__text {
    margin-bottom: var(--sf-sp-6);
    font-size: 14px;
    color: var(--sf-muted);
}

/* -------------------------------------------------------------------------
   25. Utilities
   ------------------------------------------------------------------------- */
.sf-stack {
    display: flex;
    flex-direction: column;
    gap: var(--sf-sp-3);
}

.sf-row {
    display: flex;
    align-items: center;
    gap: var(--sf-sp-2);
    flex-wrap: wrap;
}

.sf-muted {
    color: var(--sf-muted);
}

.sf-tiny {
    font-size: 13px;
}

.sf-center {
    text-align: center;
}

.sf-hidden {
    display: none !important;
}

.sf-scroll-x {
    overflow-x: auto;
}

.sf-clamp-2 {
    display: -webkit-box;
    -webkit-line-clamp: 2;
    line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
}

.sf-sr-only {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
    border: 0;
}

/* -------------------------------------------------------------------------
   25b. Content pages (CMS) — /shop/pages/{slug}
   -------------------------------------------------------------------------
   A quiet reading column: one panel-less prose block on the white page,
   capped at a comfortable measure. Admin-authored HTML is normalised here so
   the storefront never inherits browser-default heading sizes or spacing.
   ------------------------------------------------------------------------- */
.sf-page {
    max-width: 78ch;
    margin-inline: auto;
}

.sf-page__head {
    margin-bottom: var(--sf-sp-6);
    padding-bottom: var(--sf-sp-5);
    border-bottom: 1px solid var(--sf-line);
}

.sf-page__title {
    font-size: 28px;
    font-weight: 800;
    letter-spacing: -.02em;
    color: var(--sf-ink);
}

.sf-prose {
    font-size: 15px;
    line-height: 1.8;
    color: var(--sf-ink-2);
}

.sf-prose > * + * {
    margin-top: var(--sf-sp-5);
}

.sf-prose :where(h2) {
    margin-top: var(--sf-sp-8);
    font-size: 20px;
    font-weight: 800;
    letter-spacing: -.01em;
    color: var(--sf-ink);
}

.sf-prose :where(h3) {
    margin-top: var(--sf-sp-6);
    font-size: 17px;
    font-weight: 700;
    color: var(--sf-ink);
}

.sf-prose :where(h4) {
    margin-top: var(--sf-sp-5);
    font-size: 15px;
    font-weight: 700;
    color: var(--sf-ink);
}

.sf-prose :where(h2, h3, h4):first-child {
    margin-top: 0;
}

.sf-prose :where(ul, ol) {
    padding-inline-start: 1.4em;
}

.sf-prose :where(ul) {
    list-style: disc;
}

.sf-prose :where(ol) {
    list-style: decimal;
}

.sf-prose :where(li) + :where(li) {
    margin-top: var(--sf-sp-2);
}

.sf-prose :where(a) {
    color: var(--sf-brand-dark);
    font-weight: 600;
    text-decoration: underline;
    text-underline-offset: 2px;
}

.sf-prose :where(strong) {
    font-weight: 700;
    color: var(--sf-ink);
}

.sf-prose :where(hr) {
    margin-block: var(--sf-sp-8);
    border: 0;
    border-top: 1px solid var(--sf-line);
}

.sf-prose :where(blockquote) {
    padding-inline-start: var(--sf-sp-5);
    border-inline-start: 3px solid var(--sf-brand-soft);
    color: var(--sf-muted);
}

.sf-prose :where(table) {
    width: 100%;
    border-collapse: collapse;
    font-size: 14px;
}

.sf-prose :where(th, td) {
    padding: var(--sf-sp-3) var(--sf-sp-4);
    border-bottom: 1px solid var(--sf-line);
    text-align: start;
}

.sf-prose :where(th) {
    font-weight: 700;
    color: var(--sf-ink);
}

/* Order tracking page — a narrow single column of stacked panels. */
.sf-track {
    display: grid;
    gap: var(--sf-sp-6);
    max-width: 720px;
    margin-inline: auto;
}

.sf-track .sf-page-head {
    margin-bottom: 0;
}

/* Cart — free-delivery progress bar */
.sf-shipbar {
    margin-bottom: var(--sf-sp-6);
    padding: var(--sf-sp-4) var(--sf-sp-5);
    border-radius: var(--sf-radius);
    background: var(--sf-brand-tint);
    /* The bar is re-drawn in place after a quantity change, so the locked →
       unlocked colour change should ease rather than snap. */
    transition: background .3s var(--sf-ease);
}

.sf-shipbar__head {
    display: flex;
    align-items: center;
    gap: var(--sf-sp-3);
    margin-bottom: var(--sf-sp-3);
    font-size: 14px;
    font-weight: 600;
    color: var(--sf-brand-deep);
}

.sf-shipbar__icon {
    flex: none;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 22px;
    height: 22px;
}

.sf-shipbar__icon svg {
    width: 18px;
    height: 18px;
}

/* Both glyphs are in the markup and `.is-unlocked` picks one, so the AJAX
   update only toggles a class instead of swapping SVG markup in JS.
   (0,3,0) block rules below beat the (0,1,0) hide, so the swap is reliable. */
.sf-shipbar__glyph--done {
    display: none;
}

.sf-shipbar.is-unlocked .sf-shipbar__glyph--away {
    display: none;
}

.sf-shipbar.is-unlocked .sf-shipbar__glyph--done {
    display: block;
}

.sf-shipbar__track {
    height: 6px;
    border-radius: 999px;
    background: rgba(18, 159, 229, .18);
    overflow: hidden;
}

.sf-shipbar__fill {
    display: block;
    height: 100%;
    border-radius: 999px;
    background: var(--sf-brand);
    transition: width .3s var(--sf-ease);
}

/* Unlocked — switch to the success green so the reward reads instantly. */
.sf-shipbar.is-unlocked {
    background: #e9f9f1;
}

.sf-shipbar.is-unlocked .sf-shipbar__head {
    color: #0a7a5c;
}

.sf-shipbar.is-unlocked .sf-shipbar__track {
    background: rgba(10, 122, 92, .18);
}

.sf-shipbar.is-unlocked .sf-shipbar__fill {
    background: #0a7a5c;
}

/* Cart — line items
   -------------------------------------------------------------------------
   Desktop is a 5-column row (product | price | qty | total | remove); the
   heading band and the rows share ONE template so their columns line up.
   On a phone the row becomes a self-contained card: the product spans the
   width with the remove button pinned top-right, and the stepper + line total
   share the row beneath it.

   NOTE: do NOT go back to Tailwind `col-span-*` for these cells. The row used
   to be `grid-cols-1 md:grid-cols-12` with `col-span-5/2/2/2/1` children, but
   the spans kept applying on mobile — and `span 5` inside a 1-column grid
   creates IMPLICIT columns, so instead of stacking, the cells landed in an
   accidental zig-zag: price stranded bottom-left, the stepper 12px out of line
   on the right, and the line total back on the left next to the trash. */
.sf-cart-head,
.sf-cart-item {
    display: grid;
    grid-template-columns: 5fr 2fr 2fr 2fr 1fr;
    gap: var(--sf-sp-4);
    align-items: center;
}

.sf-cart-head {
    display: none;
    padding: var(--sf-sp-3) var(--sf-sp-6);
    background: var(--sf-fill);
    border-bottom: 1px solid var(--sf-line);
    font-size: 12px;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: .04em;
    color: var(--sf-muted);
}

.sf-cart-head__mid {
    text-align: center;
}

.sf-cart-head__end {
    text-align: right;
}

.sf-cart-item {
    padding: var(--sf-sp-4) var(--sf-sp-6);
    border-top: 1px solid var(--sf-line);
}

/* The heading band already draws the hairline under itself. */
.sf-cart-head + .sf-cart-item {
    border-top: 0;
}

/* `display: contents` on desktop: the media block and the unit price become
   grid items of the row itself, which gives the price its own column without
   needing a wrapper class in the markup. The mobile block turns this back into
   a real box. */
.sf-cart-item__product {
    display: contents;
}

.sf-cart-item__media {
    display: flex;
    align-items: center;
    gap: var(--sf-sp-4);
    min-width: 0;
}

.sf-cart-item__info {
    min-width: 0;
}

.sf-cart-item__price {
    text-align: center;
    color: var(--sf-ink);
}

.sf-cart-item__qty {
    display: flex;
    justify-content: center;
}

.sf-cart-item__total {
    text-align: right;
    font-weight: 600;
    color: var(--sf-ink);
}

.sf-cart-item__remove {
    display: flex;
    justify-content: flex-end;
}

@media (min-width: 768px) {
    .sf-cart-head {
        display: grid;
    }
}

@media (max-width: 767px) {
    .sf-cart-item {
        grid-template-columns: 1fr auto;
        grid-template-areas:
            "product remove"
            "qty     total";
        gap: var(--sf-sp-3) var(--sf-sp-4);
        padding: var(--sf-sp-4);
    }

    .sf-cart-item__product {
        grid-area: product;
        display: grid;
        grid-template-columns: auto 1fr;
        column-gap: var(--sf-sp-3);
        row-gap: var(--sf-sp-2);
        align-items: start;
    }

    /* Promoted to grid items of the wrapper above, so the thumb, the text and
       the unit price can be placed on its own 2-column grid — the price lands
       under the product name rather than under the thumbnail. */
    .sf-cart-item__media {
        display: contents;
    }

    .sf-cart-item__media > .sf-thumb {
        grid-column: 1;
        grid-row: 1;
    }

    .sf-cart-item__info {
        grid-column: 2;
        grid-row: 1;
    }

    .sf-cart-item__price {
        grid-column: 2;
        grid-row: 2;
        text-align: left;
    }

    .sf-cart-item__remove {
        grid-area: remove;
        align-self: start;
    }

    .sf-cart-item__qty {
        grid-area: qty;
        justify-content: flex-start;
    }

    .sf-cart-item__total {
        grid-area: total;
    }

    /* A smaller thumb buys back width for the product name. */
    .sf-cart-item .sf-thumb {
        width: 64px;
        height: 64px;
    }
}

/* -------------------------------------------------------------------------
   26. Responsive
   ------------------------------------------------------------------------- */
/*
 * ≤1023px (mobile + tablet): the inline header search box is replaced by the
 * magnifier action + the full-screen overlay. Declared here rather than with the
 * ≤767px block because the two must never coexist: at 768-1023px the header has
 * room for the box, but we want the overlay at every touch-ish width.
 */
@media (max-width: 1023px) {
    .sf-search--header {
        display: none;
    }

    .sf-action--search {
        display: inline-flex;
    }

    /*
     * The open state lives INSIDE this query, so if the viewport grows past the
     * breakpoint while the overlay is open (phone rotated to a wide landscape)
     * the sheet cannot stay stuck over the desktop layout. The matching JS also
     * closes it on resize, which is what releases the body scroll lock.
     */
    .sf-search-overlay.is-open {
        display: block;
    }
}

@media (max-width: 767px) {
    /*
     * The utility bar is a HOME-PAGE banner on a phone: hidden everywhere else
     * (the header then pins immediately — its offsetHeight is 0). Desktop
     * keeps it on every page, because the base rule has no display:none.
     */
    .sf-topbar {
        display: none;
        position: sticky;
        top: 0;
        z-index: 80;
        transition: transform .2s var(--sf-ease);
    }

    .sf--home .sf-topbar {
        display: block;
    }

    .sf-topbar--dismissed {
        transform: translateY(-100%);
    }

    .sf-burger {
        display: inline-flex;
    }

    /* Category nav collapses into the burger drawer on mobile (Amazon/Shopify
       pattern): the horizontal bar is hidden and the drawer
       (mobile_drawer.php) carries the full category tree. The nav's hairline
       used to divide header from content, so the header takes it over. */
    .sf-nav {
        display: none;
    }

    /*
     * Mobile: `<header>` holds ONLY the logo row (burger + logo + actions), so
     * pinning the header keeps the sticky chrome one row tall.
     *
     * IMPORTANT: sticky goes on `.sf-header`, never `.sf-header__inner`. A
     * sticky element cannot escape its containing block, so pinning the inner
     * row inside a 66px-tall header made it un-stick the moment that header box
     * scrolled past. `<header>`'s parent is <body> — the whole page — so it
     * stays pinned for the entire scroll.
     *
     * The hairline is REQUIRED here: `.sf-nav` (which draws the divider on
     * desktop) is `display: none` at this width, and the old always-visible
     * search row that used to supply it has been replaced by the search icon +
     * overlay. Without it the header block runs into the page with no divider.
     */
    .sf-header {
        position: sticky;
        top: env(safe-area-inset-top, 0px);
        z-index: 70;
        background: var(--sf-surface);
        border-bottom: 1px solid var(--sf-line);
    }

    /* Once the header has taken over from the utility bar, a soft shadow marks
       its edge. Same treatment as `.sf-nav--scrolled` on desktop. */
    .sf-header.is-pinned {
        box-shadow: 0 4px 20px rgba(16, 24, 40, .09);
    }

    .sf-header__inner {
        gap: var(--sf-sp-3);
        min-height: 66px;
    }

    .sf-logo__name {
        font-size: 17px;
    }

    .sf-logo__tag {
        display: none;
    }

    .sf-logo__mark {
        width: 36px;
        height: 36px;
        border-radius: 11px;
    }

    .sf-logo__img {
        height: 28px;
    }

    .sf-action__label {
        display: none;
    }

    /* On a phone the pill footprint is wasteful: the label is gone, so each
       action only needs to wrap its 24px icon. Tighten min-width/padding and
       the gap so more icons can share the row. */
    .sf-header__actions {
        gap: var(--sf-sp-1);
    }

    .sf-action {
        min-width: 40px;
        padding: 6px 4px;
    }

    /* No pill on a phone — plain icons only. The grey wash (hover/active/open)
       is dropped entirely; the keyboard focus outline and the subtle tap flash
       remain, so feedback is not lost, just background-free. */
    .sf-action:hover,
    .sf-action:focus-visible,
    .sf-action.is-active,
    .sf-action.is-open {
        background: transparent;
    }

    /* The header row has no room for a separate wishlist button on a phone.
       Wishlist stays reachable from the user menu, which already lists it. */
    .sf-action--wishlist {
        display: none;
    }

    .sf-topbar__promo {
        display: none;
    }

    /* "Track order" moves into the user menu on a phone: the menu already
       carries "My orders" pointing at the SAME /account/orders URL, so the
       utility bar drops to back | currency | language instead of repeating it. */
    .sf-topbar__link--track {
        display: none;
    }

    /* ...and these are the copies that replace them in the user menu: the
       hidden "Track order" link and "My wishlist" (its header button is
       hidden just above). */
    .sf-dropdown__item--mobile-only {
        display: block;
    }

    .sf-topbar__inner {
        justify-content: space-between;
    }

    .sf-search__box {
        border-radius: 12px;
    }

    .sf-page-title {
        font-size: 20px;
    }

    .sf-page__title {
        font-size: 21px;
    }

    .sf-prose {
        font-size: 14px;
    }

    .sf-prose :where(h2) {
        font-size: 18px;
    }

    .sf-pdp__title {
        font-size: 19px;
    }

    .sf-hero__title {
        font-size: 24px;
    }

    .sf-hero__main {
        min-height: 240px;
        padding: var(--sf-sp-6);
    }

    /* Sections stay padding-free on mobile too — the .sf-container's 16px
       already handles edge spacing, and margin-bottom handles separation.
       (The old 20px padding here stacked on the container and wasted ~36px
       per side on a phone.) */
    .sf-section__title {
        font-size: 15px;
    }

    /* Overall smaller type + controls on mobile. */
    .sf {
        font-size: 13px;
    }

    .sf-btn {
        padding: 9px var(--sf-sp-5);
        font-size: 13px;
        border-radius: 9px;
    }

    .sf-btn--sm {
        padding: 7px var(--sf-sp-4);
        font-size: 12px;
    }

    .sf-btn--lg {
        padding: 12px var(--sf-sp-6);
        font-size: 14px;
    }

    /* Keep inputs on the same vertical rhythm as the smaller mobile buttons. */
    .sf-input,
    .sf-select,
    .sf-control {
        padding-block: 8px;
    }

    .sf-search__btn {
        font-size: 13px;
        padding: 9px 18px;
    }

    .sf-price {
        font-size: 17px;
    }

    .sf-price--lg {
        font-size: 23px;
    }

    .sf-card__title {
        font-size: 12px;
    }

    .sf-nav__link,
    .sf-nav__all,
    .sf-nav__promo {
        font-size: 12px;
    }

    .sf-promo__title {
        font-size: 15px;
    }

    /*
     * Flash-deals head on a phone: step the whole row down. The head holds a
     * title AND a live countdown side by side, so at desktop sizes the two
     * crowded the row enough to wrap. The digits carry the most weight, so they
     * come down the most.
     *
     * "Ends in" is dropped at this width only — the digits sit immediately
     * beside the section title, so the prefix was spending room it did not need.
     * TABLET AND DESKTOP KEEP IT, so this rule must stay inside the ≤767px
     * block rather than on the base class.
     */
    .sf-flash__title {
        font-size: 15px;
    }

    .sf-countdown__label {
        display: none;
    }

    .sf-countdown__box {
        font-size: 13px;
    }

    /* Flash deals: drop the card frame on a phone so the product grid gets the
       full container width — no background/radius/shadow eating into the row.
       The head keeps its warm wash as a full-width section header. */
    .sf-flash {
        background: transparent;
        border-radius: 0;
        box-shadow: none;
        overflow: visible;
    }

    .sf-flash__head {
        padding: var(--sf-sp-3) var(--sf-sp-4);
    }

    .sf-flash__body {
        padding: var(--sf-sp-4) 0 0;
    }

    .sf-tile__name {
        font-size: 12px;
    }

    .sf-cat-card__name {
        font-size: 13px;
    }

    /* Product page: tighter variant chips, buy row and wishlist button so the
       purchase controls fit a phone without dominating the fold. */
    .sf-opt {
        padding: 8px var(--sf-sp-4);
        font-size: 13px;
    }

    .sf-buy-actions .sf-qty__btn {
        width: 34px;
        height: 38px;
        font-size: 16px;
    }

    .sf-buy-actions .sf-qty__input {
        width: 44px;
        height: 38px;
    }

    .sf-buy-actions .sf-btn--lg {
        padding: 10px var(--sf-sp-5);
        font-size: 13px;
    }

    .sf-buy-actions .sf-wish-btn {
        padding: 9px var(--sf-sp-4);
    }

    .sf-buy-actions .sf-wish-btn svg {
        width: 20px;
        height: 20px;
    }

    /* Related products: a denser 2-up grid on a phone. */
    .sf-grid--related {
        gap: var(--sf-sp-3);
    }

    .sf-grid--related .sf-card__media {
        padding: var(--sf-sp-3);
    }

    .sf-grid--related .sf-card__body {
        gap: var(--sf-sp-1);
        padding: var(--sf-sp-3) var(--sf-sp-3) var(--sf-sp-4);
    }

    .sf-grid--related .sf-card__title {
        font-size: 11px;
    }

    .sf-grid--related .sf-price {
        font-size: 15px;
    }
}

/* Mobile: collapse wide tables into stacked rows */
@media (max-width: 767px) {
    .sf-table--responsive thead {
        display: none;
    }

    .sf-table--responsive tbody tr {
        display: block;
        padding: var(--sf-sp-4) var(--sf-sp-5);
        border-bottom: 1px solid var(--sf-line);
    }

    .sf-table--responsive tbody td {
        display: flex;
        align-items: center;
        justify-content: space-between;
        gap: var(--sf-sp-4);
        padding: 6px 0;
        border: 0;
        text-align: start;
    }

    .sf-table--responsive tbody td::before {
        content: attr(data-label);
        font-size: 12px;
        font-weight: 700;
        letter-spacing: .05em;
        text-transform: uppercase;
        color: var(--sf-muted);
    }
}

/* -------------------------------------------------------------------------
   27. Dark mode (Tailwind CDN defaults to prefers-color-scheme)
   -------------------------------------------------------------------------
   TRUE BLACK base. The canvas (<html>) and the page are #000 and every surface
   sits one step above it: page #000 -> surface #111111 -> surface-2 #1c1c1c ->
   fill #202020, with hairlines at #2a2a2a / #383838.
   The card surface is a BALANCE, not a guess. Tuning history: #0d0d0d
   (13/255 above black) made panel boundaries invisible; #1a1a1a (26/255) and
   then #141414 (20/255) both read as too bright. #111111 (17/255) is the
   current value — the faintest step that still shows an edge, so if the edge
   stops reading this is the floor and the fix is a hairline, not more darkness.
   Every value below is still far darker than its light-mode counterpart, so the
   storefront reads as ONE black theme.
   KEEP THE LADDER ORDERED — surface < surface-2 < fill. The panel head band is
   `--sf-fill` on a `--sf-surface` body (light mode: #f1f5f9 on #fff), so if the
   surface ever overtakes the fill the band flips to a recessed strip.
   ------------------------------------------------------------------------- */
@media (prefers-color-scheme: dark) {
    html {
        background-color: #000000;
    }

    .sf {
        --sf-ink: #eef1f4;
        --sf-ink-2: #d8dde3;
        --sf-muted: #9aa1a9;
        --sf-page: #000000;
        --sf-surface: #111111;
        --sf-surface-2: #1c1c1c;
        --sf-line: #2a2a2a;
        --sf-line-strong: #383838;
        --sf-fill: #202020;
        /* The utility bar must MATCH the header here, not sit one step above it:
           the two rows are adjacent chrome, so a lighter bar reads as a seam
           across the top of every page. (Light mode keeps the grey band.) */
        --sf-topbar-bg: var(--sf-surface);
        /* Tints must stay BRIGHTER than --sf-fill or a hover on a filled control
           (qty stepper, pill, option chip, burger) reads as a darkening. */
        --sf-brand-soft: #0b3350;
        --sf-brand-tint: #0a2233;
    }

    /* Soft chip needs a lighter text + ring on the dark bar. */
    .sf-nav__all {
        color: #7cc4ee;
        box-shadow: inset 0 0 0 1px rgba(124, 196, 238, .22);
    }

    /*
     * The logo is transparent artwork in the brand's dark blue + yellow, which
     * all but disappears on the dark header — give it a light plate. Only
     * padding/background here (no height) so the §5 and §26 sizes still apply.
     */
    .sf-logo__img {
        padding: 4px 8px;
        border-radius: 9px;
        background: #fff;
    }

    .sf-search__box,
    .sf-input,
    .sf-select,
    .sf-control,
    .form-input {
        background: var(--sf-fill);
    }

    .sf-card__media,
    .sf-pdp__gallery,
    .sf-pdp__thumb,
    .sf-btn--outline,
    .sf-brand {
        background: var(--sf-surface);
    }

    .sf-card__wish {
        background: rgba(36, 36, 36, .94);
    }

    /* Base #fff hover would flash a white disc on a dark card; lift one subtle
       step instead so the control reads as pressed, not as a hole. */
    .sf-card__wish:hover,
    .sf-card__wish.is-active {
        background: #343434;
    }

    /*
     * The drawer scrim is a leftover NAVY — rgba(16, 24, 40) = #101828. Over the
     * white light-mode page a 50% navy reads as neutral grey, so nobody noticed
     * it; over this NEUTRAL-BLACK theme the same scrim casts a clear blue over
     * everything behind the drawer. Neutral black instead, and a touch stronger
     * because dimming already-dark content needs more opacity to register.
     * If another overlay scrim is ever added, it must pair with this.
     */
    .sf-drawer-backdrop {
        background: rgba(0, 0, 0, .6);
    }

    .sf-footer {
        background: #080808;
    }

    .sf-footer__social a {
        background: #1c1c1c;
    }

    /* The footer's own chips/borders are hardcoded for the #23282e light-mode
       footer and would sit LIGHTER than the footer itself on #080808. */
    .sf-footer__pay span {
        border-color: #2a2a2a;
        background: #1c1c1c;
    }

    .sf-footer__bottom {
        border-top-color: #1f1f1f;
    }

    .sf-usps {
        background: var(--sf-surface);
    }

    /* Keep the soft warm wash — a pastel header on a dark card would glare.
       Sits a touch ABOVE --sf-surface (#141414) so the band still reads as the
       head of the card rather than a recess in it. */
    .sf-flash__head {
        background: linear-gradient(90deg, #1e140a 0%, #241a0e 100%);
        border-bottom-color: #372613;
    }

    .sf-flash__title {
        color: #ffb27a;
    }

    .sf-countdown__label {
        color: #c08a63;
    }

    .sf-countdown__sep {
        color: #8c6248;
    }

    /* Placeholder glyphs sit on `--sf-surface`, so they step with it. */
    .sf-stars__empty,
    .sf-empty__icon,
    .sf-card__placeholder {
        color: #343434;
    }

    .sf .dark\:bg-indigo-900\/30,
    .sf .dark\:has-\[\:checked\]\:bg-indigo-900\/20:has(:checked) {
        background-color: rgba(18, 159, 229, .16);
    }

    .sf .dark\:text-indigo-300,
    .sf .dark\:text-indigo-400 {
        color: #ffab6b;
    }

    /*
     * The pastel status surfaces — badges, alerts, the "Save $X" pill, the
     * wishlist button and the home tile icon chips — are mixed for a WHITE page,
     * so on the black canvas they read as bright blocks. Each keeps its hue but
     * is re-tinted onto the dark fill.
     */
    .sf-badge--warning,
    .sf-alert--warning,
    .sf .alert--warning,
    .sf .alert-warning {
        background: #2b2110;
        border-color: #45330f;
        color: #e0a94a;
    }

    .sf-badge--success,
    .sf-save,
    .sf-alert--success,
    .sf .alert--success,
    .sf .alert-success {
        background: #0c241d;
        border-color: #1b4436;
        color: #4cc79a;
    }

    .sf-badge--danger,
    .sf-alert--danger,
    .sf-alert--error,
    .sf .alert--danger,
    .sf .alert--error,
    .sf .alert-error {
        background: #2a1517;
        border-color: #4a2426;
        color: #f08a8a;
    }

    .sf-badge--info,
    .sf-alert--info,
    .sf .alert--info,
    .sf .alert-info {
        background: #101d2e;
        border-color: #1e3552;
        color: #7cc4ee;
    }

    .sf-wish-btn:hover,
    .sf-wish-btn.is-active {
        background: #2a1517;
    }

    /* The base rule fades brand-soft into #fff; on dark that is a white wedge. */
    .sf-cat-card__banner {
        background: linear-gradient(135deg, var(--sf-brand-soft), var(--sf-surface));
    }

    /* Home Collections tiles cycle six pastel icon chips via nth-child. The dark
       set keeps the hue order (blue / orange / red / teal / amber / violet) at a
       much lower luminance. */
    .sf-tile:nth-child(6n+1) .sf-tile__icon { background: #0f2438; color: #7cc4ee; }
    .sf-tile:nth-child(6n+2) .sf-tile__icon { background: #2e1a0c; color: #ff9a4d; }
    .sf-tile:nth-child(6n+3) .sf-tile__icon { background: #2a1517; color: #f08a8a; }
    .sf-tile:nth-child(6n+4) .sf-tile__icon { background: #0c241d; color: #4cc79a; }
    .sf-tile:nth-child(6n+5) .sf-tile__icon { background: #2b2110; color: #e0a94a; }
    .sf-tile:nth-child(6n+6) .sf-tile__icon { background: #201a33; color: #b39ddb; }
}

/* -------------------------------------------------------------------------
   28. Legacy component bridge
   -------------------------------------------------------------------------
   Views written before the design system use the shared `.btn`,
   `.form-input` and `.alert` classes — originally styled by
   assets/css/style.css, which the storefront never loaded — plus the older
   indigo accent palette. These rules give those screens the storefront look
   without editing every template. Scoped to `.sf`, so the admin UI (which
   loads tailadmin-styles.css) is unaffected.
   ------------------------------------------------------------------------- */
.sf .btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: var(--sf-sp-2);
    padding: 11px var(--sf-sp-6);
    border: 1px solid transparent;
    border-radius: var(--sf-radius);
    background: var(--sf-fill);
    color: var(--sf-ink);
    font-family: inherit;
    font-size: 15px;
    font-weight: 600;
    line-height: 1.2;
    text-align: center;
    cursor: pointer;
    transition: background .18s var(--sf-ease), color .18s var(--sf-ease),
        border-color .18s var(--sf-ease);
}

.sf .btn:hover {
    border-color: var(--sf-brand);
    color: var(--sf-brand-dark);
}

.sf .btn:disabled {
    opacity: .55;
    cursor: not-allowed;
}

.sf .btn--primary {
    background: var(--sf-brand);
    border-color: var(--sf-brand);
    color: #fff;
}

.sf .btn--primary:hover {
    background: var(--sf-brand-dark);
    border-color: var(--sf-brand-dark);
    color: #fff;
}

.sf .btn--secondary {
    background: var(--sf-fill);
    border-color: transparent;
    color: var(--sf-ink-2);
}

.sf .btn--secondary:hover {
    background: var(--sf-brand-soft);
    color: var(--sf-brand-dark);
}

.sf .btn--danger {
    background: #d33333;
    border-color: #d33333;
    color: #fff;
}

.sf .btn--danger:hover {
    background: #b32b2b;
    border-color: #b32b2b;
    color: #fff;
}

.sf .btn--success {
    background: #0f9d6c;
    border-color: #0f9d6c;
    color: #fff;
}

.sf .btn--success:hover {
    background: #0b7f57;
    border-color: #0b7f57;
    color: #fff;
}

.sf .btn--sm {
    padding: 9px var(--sf-sp-4);
    font-size: 14px;
    border-radius: 9px;
}

.sf .btn--lg {
    padding: 15px var(--sf-sp-8);
    font-size: 16px;
}

.sf .form-input {
    display: block;
    width: 100%;
    padding: 11px var(--sf-sp-4);
    border: 1px solid transparent;
    border-radius: var(--sf-radius);
    background: var(--sf-fill);
    color: var(--sf-ink);
    font-family: inherit;
    font-size: 15px;
    line-height: 1.2;
}

.sf .form-input:focus {
    background: var(--sf-surface);
    border-color: var(--sf-brand);
    outline: none;
    box-shadow: 0 0 0 4px var(--sf-brand-soft);
}

.sf .form-input::placeholder {
    color: var(--sf-muted-2);
}

.sf .alert {
    padding: var(--sf-sp-4) var(--sf-sp-5);
    border: 1px solid transparent;
    border-radius: var(--sf-radius);
    font-size: 14px;
}

.sf .alert--success,
.sf .alert-success {
    background: #e9f9f1;
    border-color: #b9e9d3;
    color: #0a7a5c;
}

.sf .alert--danger,
.sf .alert--error,
.sf .alert-error {
    background: #fdecec;
    border-color: #f6c9c6;
    color: #b32b2b;
}

.sf .alert--warning,
.sf .alert-warning {
    background: #fff7e6;
    border-color: #ffe0a8;
    color: #96650a;
}

.sf .alert--info,
.sf .alert-info {
    background: #eef4fe;
    border-color: #cfe0fb;
    color: #1a5bbf;
}

/* Indigo accent palette → brand orange */
.sf .text-indigo-300,
.sf .text-indigo-400,
.sf .text-indigo-500,
.sf .text-indigo-600,
.sf .text-indigo-700,
.sf .text-indigo-800 {
    color: var(--sf-brand);
}

.sf .hover\:text-indigo-500:hover,
.sf .hover\:text-indigo-600:hover {
    color: var(--sf-brand);
}

/* A brand background always carries white text, so a view that forgets
   `text-white` can never render dark-on-blue. */
.sf .bg-indigo-500,
.sf .bg-indigo-600 {
    background-color: var(--sf-brand);
    color: #fff;
}

.sf .hover\:bg-indigo-600:hover,
.sf .hover\:bg-indigo-700:hover {
    background-color: var(--sf-brand-dark);
    color: #fff;
}

.sf .bg-indigo-50,
.sf .bg-indigo-100 {
    background-color: var(--sf-brand-soft);
}

.sf .border-indigo-300,
.sf .border-indigo-400,
.sf .border-indigo-500,
.sf .border-indigo-600 {
    border-color: var(--sf-brand);
}

.sf .hover\:border-indigo-400:hover,
.sf .hover\:border-indigo-500:hover {
    border-color: var(--sf-brand);
}

.sf .focus\:ring-indigo-500:focus {
    --tw-ring-color: var(--sf-brand);
}

/* -------------------------------------------------------------------------
   Checkout coupon row (store/checkout.php)
   -------------------------------------------------------------------------
   The discount-code input and its Apply button are ONE row. These rules are
   deliberately self-contained — the input does NOT use `.form-input`, and the
   button does NOT use `.btn` — so nothing in the §28 legacy bridge (or a
   Tailwind utility injected at runtime) can stack them again.
   Declared AFTER §28 on purpose: an equal-specificity tie is won by source
   order, and `.sf .sf-coupon__input` must beat `.sf .form-input`.
   IMPORTANT: this row is only a real flex container because the view no longer
   nests a <form> inside #checkout-form — the HTML parser deletes a nested
   `<form>` (attributes included), which had silently removed the wrapper these
   rules were targeting. Keep the markup `formaction`-based.
   ------------------------------------------------------------------------- */
.sf .sf-coupon {
    display: flex;
    flex-flow: row nowrap;
    align-items: center;
    gap: var(--sf-sp-2);
}

.sf .sf-coupon__input {
    display: block;
    flex: 1 1 auto;
    width: auto;
    min-width: 0; /* lets the field shrink instead of forcing a wrap */
    padding: 11px var(--sf-sp-4);
    border: 1px solid transparent;
    border-radius: var(--sf-radius);
    background: var(--sf-fill);
    color: var(--sf-ink);
    font-family: inherit;
    font-size: 14px;
    line-height: 1.2;
    text-transform: uppercase;
}

/* Codes are upper-cased, but the placeholder should read as written. */
.sf .sf-coupon__input::placeholder {
    text-transform: none;
    color: var(--sf-muted-2);
}

.sf .sf-coupon__input:focus {
    background: var(--sf-surface);
    border-color: var(--sf-brand);
    outline: none;
    box-shadow: 0 0 0 4px var(--sf-brand-soft);
}

.sf .sf-coupon__btn {
    flex: 0 0 auto;
    white-space: nowrap;
}

.sf .sf-coupon__remove {
    flex: 0 0 auto;
    padding: 0;
    border: 0;
    background: none;
    color: #0f9d6c;
    font-family: inherit;
    font-size: 13px;
    font-weight: 600;
    line-height: 1.2;
    cursor: pointer;
}

.sf .sf-coupon__remove:hover {
    color: #0b7f57;
    text-decoration: underline;
}

@media (prefers-color-scheme: dark) {
    .sf .sf-coupon__remove {
        color: #4cc79a;
    }

    .sf .sf-coupon__remove:hover {
        color: #7bdcb5;
    }
}

/* -------------------------------------------------------------------------
   29. Touch-device form controls (prevent iOS focus zoom)
   -------------------------------------------------------------------------
   iOS Safari (and some Android browsers) auto-zoom the whole page when a
   text control with font-size < 16px receives focus. Bump every form control
   to 16px on touch devices only, so desktop keeps its compact 14-15px inputs.
   Deliberately NOT `maximum-scale=1` in the viewport meta — that blocks
   pinch-zoom for low-vision users.
   ------------------------------------------------------------------------- */
@media (hover: none) and (pointer: coarse) {
    .sf .sf-search__input,
    .sf .sf-input,
    .sf .sf-select,
    .sf .sf-control,
    .sf .sf-qty__input,
    .sf .sf-coupon__input,
    .sf .form-input,
    .sf input[type="text"],
    .sf input[type="email"],
    .sf input[type="password"],
    .sf input[type="search"],
    .sf input[type="tel"],
    .sf input[type="number"],
    .sf input[type="date"],
    .sf textarea {
        font-size: 16px;
    }
}

/* The ordering select on the collection/category pages is a compact control
   and should match the 13px mobile UI text, not the 16px touch bump above.
   Placed AFTER §29 so it wins the source-order tie at equal specificity
   (.sf .sf-filterbar__sort vs .sf .sf-select). */
@media (max-width: 767px) {
    .sf .sf-filterbar__sort {
        font-size: 13px;
    }
}

.sf .has-\[\:checked\]\:border-indigo-600:has(:checked) {
    border-color: var(--sf-brand);
}

.sf .has-\[\:checked\]\:bg-indigo-50:has(:checked) {
    background-color: var(--sf-brand-soft);
}

.sf .from-indigo-500 {
    --tw-gradient-from: var(--sf-brand) var(--tw-gradient-from-position);
    --tw-gradient-to: rgb(255 255 255 / 0) var(--tw-gradient-to-position);
    --tw-gradient-stops: var(--tw-gradient-from), var(--tw-gradient-to);
}

.sf .to-purple-500 {
    --tw-gradient-to: var(--sf-brand) var(--tw-gradient-to-position);
}

/* Legacy Tailwind panels — e.g. `<div class="bg-white rounded-lg shadow p-6">`
   in checkout / account views — get the same borderless surface treatment as
   the sf-* components so those screens match the storefront. */
.sf .rounded-lg.shadow,
.sf .rounded-lg.shadow-md,
.sf .rounded-lg.shadow-lg,
.sf .rounded-lg.shadow-xl {
    border-radius: var(--sf-radius-lg);
    box-shadow: var(--sf-shadow-sm);
    border: 0;
}

/*
 * Legacy Tailwind COLOUR utilities → storefront tokens.
 *
 * Every pre-design-system store view paints its panels as
 * `bg-white dark:bg-gray-800`. That `dark:` value is Tailwind's default
 * gray-800 — rgb(31, 41, 55) — a BLUE-grey, which clashes with the neutral
 * --sf-surface (#111111) that .sf-card / .sf-panel use. On a true-black theme
 * the mismatch is obvious: wishlist / checkout / confirmation cards rendered a
 * blue-grey body on a neutral page.
 *
 * Mapping the LIGHT class is what actually fixes it: `.sf .bg-white` is (0,2,0)
 * and therefore OUTRANKS Tailwind's `.dark\:bg-gray-800` (0,1,0), even though
 * the Play CDN injects its stylesheet at runtime — i.e. AFTER this file. In
 * light mode `--sf-surface` IS #fff, so nothing changes there. The `dark:`
 * classes are mapped too so an element carrying one WITHOUT `bg-white` is
 * covered, and they map to the SAME token so both routes agree.
 *
 * Scope: `/shop/m6` renders with the `main` layout and has no `.sf` on
 * <body>, so none of this reaches it — that UI keeps Tailwind's own dark
 * palette on purpose.
 */
.sf .bg-white,
.sf .dark\:bg-white,
.sf .dark\:bg-gray-800 {
    background-color: var(--sf-surface);
}

/* Secondary greys — image wells and thumb placeholders
   (`bg-gray-100 dark:bg-gray-700`) plus the muted status chip
   (`bg-gray-200 dark:bg-gray-600`). */
.sf .bg-gray-100,
.sf .dark\:bg-gray-600,
.sf .dark\:bg-gray-700 {
    background-color: var(--sf-surface-2);
}
