/* =====================================================================
   SA LIQUOR - storefront design system
   =====================================================================

   Built on the identity already used on the holding page - wine berry,
   deep plum, Inter - so this reads as the same business rather than a
   replacement. A serif display face is added for headings, because wine
   retail is one of the few places where a little formality is the point.

   Structure:
     1. Tokens
     2. Base and typography
     3. Header and navigation
     4. Buttons and forms
     5. Product cards and grids
     6. Product detail
     7. Cart and checkout
     8. Footer
     9. Utilities and motion

   Bootstrap 5.3 is loaded first; everything here layers on top of it.
   ===================================================================== */

/* ---------------------------------------------------------------------
   1. Tokens
   --------------------------------------------------------------------- */

:root {
    /* Brand */
    --sal-wine:        #8b1538;   /* primary - deep bordeaux */
    --sal-wine-dark:   #6d0f2b;
    --sal-wine-light:  #a8324f;
    --sal-rose:        #e34a6f;   /* accent, used sparingly */
    --sal-ink:         #17131a;   /* near-black with a plum cast */
    --sal-ink-soft:    #2a2430;

    /* Canvas - warm rather than clinical white */
    --sal-paper:       #faf8f5;
    --sal-paper-2:     #f2ede7;
    --sal-card:        #ffffff;
    --sal-line:        #e5ded6;

    /* Text */
    --sal-text:        #241f28;
    --sal-muted:       #6f6875;

    /* Feedback */
    --sal-success:     #1f6f4a;
    --sal-warn:        #8a6216;
    --sal-danger:      #a4243b;

    /* Type.

       The serif carries the brand and nothing else: page headings and section
       headings, at sizes where its contrast is an asset. Everything functional
       is Inter - product names in a grid, panel headers, and every number that
       is money. A serif at 15px in a product grid costs legibility, and prices
       set in two different families on two different screens read as two
       different shops. */
    --sal-display: 'Playfair Display', Georgia, 'Times New Roman', serif;
    --sal-body: 'Inter', system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif;

    /* Space and shape */
    --sal-radius:      4px;      /* restrained; wine labels are not rounded */
    --sal-radius-lg:   8px;
    --sal-shadow:      0 1px 2px rgba(23, 19, 26, .04), 0 8px 24px rgba(23, 19, 26, .06);
    --sal-shadow-lift: 0 2px 4px rgba(23, 19, 26, .06), 0 16px 40px rgba(23, 19, 26, .12);

    --sal-header-h:    4.25rem;
}

/* ---------------------------------------------------------------------
   2. Base and typography
   --------------------------------------------------------------------- */

body {
    background: var(--sal-paper);
    color: var(--sal-text);
    font-family: var(--sal-body);
    font-size: 1rem;
    line-height: 1.6;
    -webkit-font-smoothing: antialiased;
    text-rendering: optimizeLegibility;
}

h1, h2, h3, .sal-display {
    font-family: var(--sal-display);
    font-weight: 600;
    letter-spacing: -0.01em;
    color: var(--sal-ink);
}

h1 { line-height: 1.15; }

/* Small caps label used above headings and on section dividers. */
.sal-eyebrow {
    font-family: var(--sal-body);
    font-size: .6875rem;
    font-weight: 600;
    letter-spacing: .14em;
    text-transform: uppercase;
    color: var(--sal-wine);
}

.sal-muted { color: var(--sal-muted); }

a { color: var(--sal-wine); text-underline-offset: .15em; }
a:hover { color: var(--sal-wine-dark); }

/* A quiet rule used to separate sections without a heavy border. */
.sal-rule {
    height: 1px;
    background: linear-gradient(90deg, var(--sal-line), transparent);
    border: 0;
    opacity: 1;
}

/* ---------------------------------------------------------------------
   3. Header and navigation
   --------------------------------------------------------------------- */

.sal-announce {
    background: var(--sal-wine-dark);
    color: #f0e2e7;
    font-size: .78125rem;
    letter-spacing: .02em;
    padding: .375rem 0;
}

.sal-header {
    /* No blur or transparency here any more. This header is two solid dark
       rows and it is sticky, so a backdrop filter would repaint a large area
       on every scroll frame for an effect nobody can see behind opaque bars. */
    background: var(--sal-ink);
}

/* Row one: identity, search, account, cart. */
.sal-header-main { background: var(--sal-ink); }

.sal-topbar {
    display: flex;
    align-items: center;
    gap: .5rem;
    padding: .625rem 0;
    flex-wrap: wrap;
}

@media (min-width: 992px) {
    .sal-topbar { gap: 1.25rem; padding: .75rem 0; }
}

.sal-header-brand {
    display: inline-flex;
    align-items: center;
    flex: 0 0 auto;
    margin-right: .25rem;
}

/* The delivery promise. Only from xxl, because below that the search bar is
   worth more than the message and something has to give. */
.sal-deliver {
    align-items: center;
    gap: .625rem;
    color: #fff;
    flex: 0 0 auto;
    max-width: 20rem;
}

.sal-deliver svg { color: var(--sal-rose); flex: 0 0 auto; }

.sal-deliver span {
    display: block;
    font-size: .75rem;
    line-height: 1.25;
    color: #b9b1c0;
}

.sal-deliver strong {
    display: block;
    font-size: .8125rem;
    font-weight: 600;
    letter-spacing: .01em;
    color: #fff;
}

/* ---------------------------------------------------------------------
   The search bar

   On a liquor site people arrive knowing what they want, so this is the
   widest thing in the header on desktop. Below lg it drops to its own full
   width line rather than being squeezed to nothing beside the logo.
   --------------------------------------------------------------------- */

.sal-searchbar {
    order: 5;
    flex: 1 1 100%;
    position: relative;
    display: flex;
    align-items: center;
    background: #fff;
    border-radius: 999px;
    padding: .25rem .25rem .25rem .875rem;
    min-width: 0;
}

@media (min-width: 992px) {
    .sal-searchbar {
        order: 0;
        flex: 1 1 auto;
        max-width: 46rem;
        padding: .3125rem .3125rem .3125rem 1rem;
    }
}

.sal-searchbar-icon { color: var(--sal-muted); flex: 0 0 auto; }

.sal-searchbar input {
    flex: 1 1 auto;
    min-width: 0;
    border: 0;
    outline: 0;
    background: transparent;
    font-size: .9375rem;
    color: var(--sal-text);
    padding: .375rem .625rem;
}

.sal-searchbar input::placeholder { color: var(--sal-muted); }

/* The browser's own clear button on type=search sits awkwardly inside a pill
   and differs between engines. */
.sal-searchbar input::-webkit-search-cancel-button { display: none; }

.sal-searchbar button {
    flex: 0 0 auto;
    width: 2.25rem;
    height: 2.25rem;
    border: 0;
    border-radius: 50%;
    background: var(--sal-wine);
    color: #fff;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    transition: background .15s ease;
}

.sal-searchbar button:hover { background: var(--sal-wine-dark); }

.sal-searchbar:focus-within { box-shadow: 0 0 0 3px rgba(227, 74, 111, .35); }

/* ---------------------------------------------------------------------
   Account, delivery check, cart
   --------------------------------------------------------------------- */

.sal-actions {
    display: flex;
    align-items: center;
    gap: .25rem;
    margin-left: auto;
    flex: 0 0 auto;
}

@media (min-width: 992px) {
    .sal-actions { gap: .75rem; }
}

.sal-action {
    display: inline-flex;
    align-items: center;
    gap: .4375rem;
    padding: .5rem .625rem;
    border-radius: .5rem;
    color: #fff;
    text-decoration: none;
    font-size: .875rem;
    font-weight: 600;
    white-space: nowrap;
    transition: background .15s ease;
}

.sal-action:hover { background: rgba(255, 255, 255, .1); color: #fff; }
.sal-action svg { flex: 0 0 auto; }

.sal-action-cart { position: relative; }

/* The count sits on the cart icon, so it needs to be legible against both the
   icon and the dark bar behind it. */
.sal-action-cart .sal-cart-count {
    position: absolute;
    top: .125rem;
    right: .0625rem;
    min-width: 1.125rem;
    height: 1.125rem;
    padding: 0 .25rem;
    border-radius: 999px;
    background: var(--sal-rose);
    color: #fff;
    font-size: .6875rem;
    font-weight: 700;
    line-height: 1.125rem;
    text-align: center;
}

.sal-burger {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 2.5rem;
    height: 2.5rem;
    padding: 0;
    border: 0;
    border-radius: .5rem;
    background: transparent;
    color: #fff;
}

.sal-burger:hover { background: rgba(255, 255, 255, .1); }

/* ---------------------------------------------------------------------
   Row two: the range
   --------------------------------------------------------------------- */

.sal-header-nav {
    background: var(--sal-wine);
    border-top: 1px solid rgba(255, 255, 255, .08);
}

.sal-catnav {
    display: flex;
    align-items: center;
    gap: .25rem;
    margin: 0;
    padding: 0;
    list-style: none;
    /* A long category list should scroll rather than wrap the bar to two
       lines and shove the page down. */
    overflow-x: auto;
    scrollbar-width: none;
}

.sal-catnav::-webkit-scrollbar { display: none; }

/* Centred - but not with justify-content: center. On a scrolling flex row
   that pushes the first items off the left edge where no scroll can reach
   them, so on a narrower laptop "Spring Sale" would simply vanish. Auto
   margins on the ends centre the row when there is room and collapse to
   nothing when there is not, so an overflowing bar still starts at its first
   item. */
.sal-catnav > li:first-child { margin-left: auto; }
.sal-catnav > li:last-child { margin-right: auto; }

.sal-catnav a {
    display: inline-block;
    padding: .8125rem 1rem;
    color: #f3e8ec;
    text-decoration: none;
    font-size: .9375rem;
    font-weight: 600;
    white-space: nowrap;
    border-bottom: 3px solid transparent;
    transition: color .15s ease, border-color .15s ease;
}

.sal-catnav a:hover { color: #fff; border-bottom-color: rgba(255, 255, 255, .45); }
.sal-catnav a.active { color: #fff; border-bottom-color: #fff; }

/* THIRTEEN SHELVES HAVE TO FIT A LAPTOP.
   The bar scrolls by design rather than wrapping, but a shelf you can only
   reach by dragging a bar with no scrollbar is a shelf most people never
   find. Tightening the gaps below 1600px keeps every item on screen down to
   about 1400, which covers the common laptop widths; narrower than that it
   scrolls, as it always did. */
@media (max-width: 1599.98px) {
    .sal-catnav a { padding-left: .7rem; padding-right: .7rem; }
}

/* 1366 is the single most common laptop width there is, and one more step
   gets the last two shelves onto it. Below this the bar genuinely has to
   scroll, and the fade below is what says so. */
@media (max-width: 1439.98px) {
    .sal-catnav a { padding-left: .5rem; padding-right: .5rem; font-size: .90625rem; }
}

/* Where it does still scroll, say so. The bar hides its scrollbar, so
   without this the only clue that Accessories and Blog exist is knowing
   they should. The fade sits over the bar's own colour, so on a wide screen
   where nothing overflows it is invisible. */
.sal-header-nav { position: relative; }

.sal-header-nav::after {
    content: "";
    position: absolute;
    top: 0;
    right: 0;
    bottom: 0;
    width: 2.5rem;
    pointer-events: none;
    background: linear-gradient(to right, rgba(139, 21, 56, 0), var(--sal-wine));
}

@media (min-width: 1600px) {
    .sal-header-nav::after { display: none; }
}

/* ---------------------------------------------------------------------
   The mobile menu
   --------------------------------------------------------------------- */

/* ---------------------------------------------------------------------
   The off-canvas panels

   The menu slides in from the left, the cart from the right. Both sit over the
   page rather than pushing it: the menu used to be a collapse, and with eleven
   shelves plus the account links it shoved the content the customer was
   reading off the bottom of the screen.
   --------------------------------------------------------------------- */

.sal-offcanvas-nav {
    background: var(--sal-ink);
    color: #e7e1ec;
    width: min(20rem, 85vw);
}

.sal-offcanvas-nav .offcanvas-header {
    border-bottom: 1px solid rgba(255, 255, 255, .12);
}

.sal-offcanvas-nav .offcanvas-title { color: #fff; letter-spacing: .08em; text-transform: uppercase; }

.sal-offcanvas-nav a {
    display: block;
    padding: .7rem .25rem;
    color: #e7e1ec;
    text-decoration: none;
    font-weight: 600;
}

.sal-offcanvas-nav a:hover,
.sal-offcanvas-nav a.active { color: #fff; }

/* The current shelf, marked the same way the desktop bar marks it. */
.sal-offcanvas-nav a.active {
    border-left: 3px solid var(--sal-wine-light);
    padding-left: .6rem;
    margin-left: -.6rem;
}

.sal-mobile-utility { border-top: 1px solid rgba(255, 255, 255, .12); padding-top: .5rem; }
.sal-mobile-utility a { font-weight: 500; color: #b9b1c0; }

/* ---------------------------------------------------------------------
   The cart drawer
   --------------------------------------------------------------------- */

.sal-offcanvas-cart {
    width: min(26rem, 92vw);
    background: var(--sal-paper);
}

.sal-offcanvas-cart .offcanvas-header {
    border-bottom: 1px solid var(--sal-line);
    background: #fff;
}

/* The lines scroll; the total and the buttons do not. Nobody should have to
   scroll a cart to find the checkout button. */
.sal-offcanvas-cart .offcanvas-body {
    display: flex;
    flex-direction: column;
    padding: 0;
}

.sal-drawer-lines {
    flex: 1 1 auto;
    overflow-y: auto;
    padding: 1rem;
}

.sal-drawer-line {
    display: flex;
    gap: .75rem;
    padding-bottom: .9rem;
    margin-bottom: .9rem;
    border-bottom: 1px solid var(--sal-line);
}

.sal-drawer-line:last-child { border-bottom: 0; margin-bottom: 0; padding-bottom: 0; }

.sal-drawer-thumb {
    flex: 0 0 auto;
    width: 3.25rem;
    height: 4.25rem;
    display: flex;
    align-items: center;
    justify-content: center;
    background: #fff;
    border: 1px solid var(--sal-line);
    border-radius: var(--sal-radius);
}

.sal-drawer-thumb img {
    max-width: 100%;
    max-height: 100%;
    object-fit: contain;
    mix-blend-mode: multiply;
}

.sal-drawer-footer {
    flex: 0 0 auto;
    padding: 1rem;
    border-top: 1px solid var(--sal-line);
    background: #fff;
}

/* A long product name must not push the price out of the panel. */
.min-w-0 { min-width: 0; }
.sal-drawer-line a { overflow-wrap: anywhere; }

/* The supplied logo, used in the header, the footer and the two admin
   layouts. The artwork is burgundy lettering over dark charcoal: it reads on a
   light ground and disappears against the ink header and footer, so those
   force the same file to solid white rather than shipping a second asset that
   could drift out of step with the first. brightness(0) flattens every colour
   to black, then invert(1) lifts it to white - the order matters. */
.sal-logo {
    height: 2.25rem;
    width: auto;
    display: block;
}

.sal-logo-invert { filter: brightness(0) invert(1); }

@media (max-width: 575.98px) {
    .sal-logo { height: 1.85rem; }
}

/* ---------------------------------------------------------------------
   4. Buttons and forms
   --------------------------------------------------------------------- */

.btn {
    border-radius: var(--sal-radius);
    font-weight: 500;
    letter-spacing: .01em;
    transition: transform .12s ease, background-color .15s ease, box-shadow .15s ease;
}

.btn:active { transform: translateY(1px); }

.btn-wine {
    background: var(--sal-wine);
    border: 1px solid var(--sal-wine);
    color: #fff;
}

.btn-wine:hover,
.btn-wine:focus {
    background: var(--sal-wine-dark);
    border-color: var(--sal-wine-dark);
    color: #fff;
}

.btn-outline-wine {
    background: transparent;
    border: 1px solid var(--sal-wine);
    color: var(--sal-wine);
}

.btn-outline-wine:hover {
    background: var(--sal-wine);
    color: #fff;
}

.btn-ghost {
    background: transparent;
    border: 1px solid var(--sal-line);
    color: var(--sal-text);
}

.btn-ghost:hover {
    border-color: var(--sal-ink);
    background: #fff;
}

.form-control, .form-select {
    border-color: var(--sal-line);
    border-radius: var(--sal-radius);
    padding: .55rem .75rem;
}

.form-control:focus, .form-select:focus {
    border-color: var(--sal-wine-light);
    box-shadow: 0 0 0 3px rgba(139, 21, 56, .10);
}

.form-label {
    font-size: .8125rem;
    font-weight: 600;
    letter-spacing: .01em;
    color: var(--sal-ink);
    margin-bottom: .3rem;
}

/* ---------------------------------------------------------------------
   5. Product cards and grids
   --------------------------------------------------------------------- */

.sal-card {
    background: var(--sal-card);
    border: 1px solid var(--sal-line);
    border-radius: var(--sal-radius-lg);
    overflow: hidden;
    /* POSITIONED SO ITS OWN OVERFLOW RULE ACTUALLY APPLIES.
       The quantity stepper carries a <label class="visually-hidden">, and
       Bootstrap gives that position:absolute !important. With a static card
       the label's containing block is whatever is positioned further up the
       page, so neither this overflow:hidden nor the rail's overflow-x:auto
       clips it: the label keeps its place in the document at the card's
       scrolled-out x position and drags the page's scroll width out with it.
       Seven cards of gifts made the home page 4,896px wide on a 1,249px
       screen, and the only visible symptom was a horizontal scrollbar under
       a page where everything looked correctly laid out. */
    position: relative;
    transition: transform .2s ease, box-shadow .2s ease, border-color .2s ease;
    height: 100%;
    display: flex;
    flex-direction: column;
}

@media (hover: hover) {
    .sal-card:hover {
        transform: translateY(-3px);
        box-shadow: var(--sal-shadow-lift);
        border-color: transparent;
    }
}

/* The bottle shot sits on its own tinted panel. The imported images are
   portrait and transparent-backed, so a flat tint reads better than
   white-on-white and hides their inconsistent edges. */
.sal-card-media {
    position: relative;
    aspect-ratio: 3 / 4;
    background:
        radial-gradient(120% 80% at 50% 0%, #fff 0%, var(--sal-paper-2) 100%);
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 1.25rem;
}

.sal-card-media img {
    max-width: 100%;
    max-height: 100%;
    object-fit: contain;
    mix-blend-mode: multiply;   /* drops the white box around legacy PNGs */
    transition: transform .35s ease;
}

@media (hover: hover) {
    .sal-card:hover .sal-card-media img { transform: scale(1.045); }
}

/* PHONES: A SHORTER PANEL. Two cards sit side by side, and a 3:4 panel grows
   with the card, so on a larger phone each bottle shot was around 420px tall -
   more than half the screen spent on two bottles, with the prices and buttons
   pushed below the fold. A height that stops growing keeps the bottle a
   recognisable size and the price in view. */
@media (max-width: 767.98px) {
    .sal-card-media {
        aspect-ratio: auto;
        height: clamp(150px, 40vw, 210px);
        padding: .75rem;
    }
}

.sal-card-body {
    padding: .9rem 1rem 1rem;
    display: flex;
    flex-direction: column;
    flex: 1 1 auto;
}

.sal-card-vintage {
    font-size: .75rem;
    letter-spacing: .08em;
    color: var(--sal-muted);
    text-transform: uppercase;
}

.sal-card-title {
    font-family: var(--sal-body);
    font-size: 1.02rem;
    font-weight: 600;
    line-height: 1.25;
    color: var(--sal-ink);
    margin: .15rem 0 .2rem;

    /* Two lines then ellipsis, so cards in a row stay the same height
       without truncating most names. */
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
}

.sal-card-varietal {
    font-size: .8125rem;
    color: var(--sal-muted);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.sal-card-price {
    font-size: 1.05rem;
    font-weight: 600;
    color: var(--sal-ink);
    margin-top: auto;
    padding-top: .6rem;
}

.sal-card-price .from {
    font-size: .75rem;
    font-weight: 400;
    color: var(--sal-muted);
}

.sal-badge {
    display: inline-block;
    padding: .12rem .45rem;
    border-radius: 2px;
    font-size: .6875rem;
    font-weight: 600;
    letter-spacing: .04em;
    text-transform: uppercase;
}

.sal-badge-sale { background: var(--sal-wine); color: #fff; }
.sal-badge-new  { background: var(--sal-ink); color: #fff; }

/* ---------------------------------------------------------------------
   6. Product detail
   --------------------------------------------------------------------- */

.sal-product-media {
    background: radial-gradient(120% 80% at 50% 0%, #fff 0%, var(--sal-paper-2) 100%);
    border: 1px solid var(--sal-line);
    border-radius: var(--sal-radius-lg);
    aspect-ratio: 3 / 4;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 2rem;
}

.sal-product-media img {
    max-width: 100%;
    max-height: 100%;
    object-fit: contain;
    mix-blend-mode: multiply;
}

.sal-price-lg {
    font-family: var(--sal-body);
    font-variant-numeric: tabular-nums;
    font-size: 2rem;
    font-weight: 600;
    color: var(--sal-ink);
    line-height: 1;
}

.sal-compare {
    color: var(--sal-muted);
    text-decoration: line-through;
    font-size: 1rem;
}

/* Purchase unit tiles.
   -------------------------------------------------------------------
   A tile per unit, each carrying its own price. The old control was a row of
   text pills, which meant the price of a case was only discoverable by
   selecting the case - and the price is the entire basis of the decision.
   Showing both at once is the difference between choosing and guessing.

   Equal columns rather than flex-wrap pills, so two tiles of very different
   name lengths ("Bottle" against "Case of 12") still read as a comparison of
   like with like. */
.sal-units {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(10.5rem, 1fr));
    gap: .6rem;
}

.sal-unit {
    display: flex;
    align-items: center;
    gap: .7rem;
    width: 100%;
    height: 100%;
    padding: .7rem .8rem;
    border: 1px solid var(--sal-line);
    border-radius: var(--sal-radius-lg);
    background: #fff;
    cursor: pointer;
    transition: border-color .15s ease, box-shadow .15s ease, background-color .15s ease;
}

.sal-unit:hover { border-color: var(--sal-wine-light); }

.sal-unit-icon {
    flex: 0 0 auto;
    width: 1.9rem;
    height: 2.2rem;
    color: var(--sal-muted);
    transition: color .15s ease;
}

.sal-unit-icon svg { width: 100%; height: 100%; display: block; }

.sal-unit-body { display: flex; flex-direction: column; min-width: 0; }

.sal-unit-name {
    font-size: .8125rem;
    font-weight: 600;
    letter-spacing: .06em;
    text-transform: uppercase;
    color: var(--sal-muted);
    line-height: 1.2;
    transition: color .15s ease;
}

.sal-unit-price {
    font-size: 1.0625rem;
    font-weight: 600;
    font-variant-numeric: tabular-nums;
    color: var(--sal-ink);
    line-height: 1.3;
}

.sal-unit-was {
    font-size: .8125rem;
    font-weight: 400;
    color: var(--sal-muted);
    margin-left: .2rem;
}

.sal-unit-each {
    font-size: .75rem;
    color: var(--sal-muted);
    line-height: 1.3;
}

/* The tick. Present but invisible when unselected, so choosing a tile does not
   reflow the row it sits in. */
.sal-unit-tick {
    flex: 0 0 auto;
    margin-left: auto;
    width: 1.05rem;
    height: 1.05rem;
    border-radius: 50%;
    background: var(--sal-wine);
    color: #fff;
    display: flex;
    align-items: center;
    justify-content: center;
    opacity: 0;
    transform: scale(.7);
    transition: opacity .15s ease, transform .15s ease;
}

.sal-unit-tick svg { width: .65rem; height: .65rem; display: block; }

.btn-check:checked + .sal-unit {
    border-color: var(--sal-wine);
    background: rgba(139, 21, 56, .04);
    box-shadow: inset 0 0 0 1px var(--sal-wine);
}

.btn-check:checked + .sal-unit .sal-unit-icon,
.btn-check:checked + .sal-unit .sal-unit-name,
.btn-check:checked + .sal-unit .sal-unit-price { color: var(--sal-wine-dark); }

.btn-check:checked + .sal-unit .sal-unit-tick { opacity: 1; transform: scale(1); }

/* Keyboard focus has to be visible on the tile, because the input it belongs
   to is off screen. */
.btn-check:focus-visible + .sal-unit {
    outline: 2px solid var(--sal-wine);
    outline-offset: 2px;
}

/* A unit nobody can sell is still shown, greyed, rather than hidden. A missing
   option reads as a site that does not stock cases; a dimmed one reads as the
   truth, which is that this case cannot be got right now. */
.sal-unit.is-unavailable { opacity: .55; }

/* Specification table - rules only between rows, no outer box. */
.sal-specs { width: 100%; font-size: .9375rem; }
.sal-specs th {
    width: 38%;
    padding: .55rem 0;
    font-weight: 500;
    color: var(--sal-muted);
    border-bottom: 1px solid var(--sal-line);
    vertical-align: top;
}
.sal-specs td {
    padding: .55rem 0;
    border-bottom: 1px solid var(--sal-line);
}
.sal-specs tr:last-child th,
.sal-specs tr:last-child td { border-bottom: 0; }

/* The compliance panel. Deliberately plain and factual - this is a legal
   notice, not a marketing callout, and dressing it up would be wrong. */
.sal-compliance {
    border: 1px solid var(--sal-line);
    border-left: 3px solid var(--sal-wine);
    border-radius: var(--sal-radius);
    background: #fff;
    padding: .9rem 1rem;
}

/* The product page.
   -------------------------------------------------------------------
   Its own classes rather than restyling .sal-price-lg, .sal-compliance and
   .sal-specs, which the cart, checkout and register pages also use.

   The bottle is the subject, so it gets the larger column and stays in view
   while the buy panel and notes scroll past it. Everything around it is
   quiet: one serif for the name, one colour for the action, and the stock
   status as a line of text rather than an alert box, because "ordered in
   for you" is information, not a warning. */

/* One measure for the whole page. Across a 1900px screen the two columns
   drifted so far apart that the bottle and its price no longer read as one
   thing, so the page stops widening at a comfortable reading width and
   centres, crumbs and all, so everything lines up on the same edges. */
.sal-pdp-crumbs,
.sal-pdp,
.sal-pdp-about,
.sal-pdp-related {
    max-width: 1360px;
    margin-left: auto;
    margin-right: auto;
}

.sal-pdp-crumbs {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: .15rem .5rem;
    font-size: .8125rem;
    color: var(--sal-muted);
    margin-bottom: 1.25rem;
}

.sal-pdp-crumbs a { color: var(--sal-muted); text-decoration: none; }
.sal-pdp-crumbs a:hover { color: var(--sal-wine); }
.sal-pdp-crumbs span[aria-hidden] { color: #c4bbb1; }
.sal-pdp-crumbs [aria-current] {
    color: var(--sal-ink);
    max-width: 40ch;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.sal-pdp {
    display: grid;
    grid-template-columns: minmax(0, 1fr);
    gap: 1.75rem;
}

@media (min-width: 992px) {
    .sal-pdp {
        grid-template-columns: minmax(0, 1.1fr) minmax(0, 1fr);
        gap: 3.5rem;
        align-items: start;
    }

    .sal-pdp-gallery { position: sticky; top: 1.5rem; }
}

@media (min-width: 1400px) {
    .sal-pdp { gap: 5rem; }
}

/* The stage: a soft pool of light behind the bottle, the way a bottle is lit
   on a shelf, rather than a flat beige box. */
.sal-pdp-stage {
    position: relative;
    /* Width stated outright. Left automatic, the browser keeps the square by
       carrying max-height across to the width, so on a wide, short screen the
       panel shrank inside its column and opened a gap beside the price. With
       the width fixed to the column, a short screen gets a panel a little
       wider than tall instead. */
    width: 100%;
    aspect-ratio: 1 / 1;
    max-height: 78vh;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: clamp(1.5rem, 5vw, 3.5rem);
    border-radius: 16px;
    background:
        radial-gradient(60% 55% at 50% 42%, #ffffff 0%, rgba(255, 255, 255, 0) 70%),
        radial-gradient(90% 60% at 50% 100%, rgba(139, 21, 56, .06) 0%, rgba(139, 21, 56, 0) 70%),
        linear-gradient(180deg, #f7f3ee 0%, #efe8e0 100%);
    overflow: hidden;
}

.sal-pdp-stage::after {
    content: "";
    position: absolute;
    left: 50%;
    bottom: 9%;
    width: 42%;
    height: 5%;
    transform: translateX(-50%);
    border-radius: 50%;
    background: radial-gradient(closest-side, rgba(40, 20, 30, .18), rgba(40, 20, 30, 0));
    pointer-events: none;
}

.sal-pdp-stage img {
    position: relative;
    z-index: 1;
    max-width: 100%;
    max-height: 100%;
    object-fit: contain;
    mix-blend-mode: multiply;
}

.sal-pdp-thumbs { display: flex; flex-wrap: wrap; gap: .5rem; margin-top: .75rem; }

.sal-pdp-thumb {
    padding: .25rem;
    background: var(--sal-paper-2);
    border: 1px solid transparent;
    border-radius: 8px;
    line-height: 0;
}

.sal-pdp-thumb img { object-fit: contain; mix-blend-mode: multiply; }
.sal-pdp-thumb:hover { border-color: var(--sal-line); }
.sal-pdp-thumb.is-active { border-color: var(--sal-wine); }

/* The buy panel. */
.sal-pdp-info { padding-top: .25rem; }

.sal-pdp-brand {
    display: inline-block;
    font-size: .75rem;
    font-weight: 600;
    letter-spacing: .14em;
    text-transform: uppercase;
    color: var(--sal-wine);
    text-decoration: none;
}

.sal-pdp-brand:hover { color: var(--sal-wine-dark); text-decoration: underline; }

.sal-pdp-title {
    font-family: var(--sal-display);
    font-size: clamp(1.75rem, 1.2rem + 1.6vw, 2.6rem);
    font-weight: 600;
    line-height: 1.12;
    letter-spacing: -.01em;
    color: var(--sal-ink);
    margin: .5rem 0 .75rem;
}

.sal-pdp-facts {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: .25rem .6rem;
    color: var(--sal-muted);
    font-size: .9375rem;
    margin-bottom: 1.5rem;
}

.sal-pdp-fact { display: inline-flex; align-items: center; gap: .6rem; }

.sal-pdp-dot {
    width: 3px;
    height: 3px;
    border-radius: 50%;
    background: #bcb2a8;
}

.sal-pdp-price {
    padding: 1.25rem 0;
    border-top: 1px solid var(--sal-line);
    margin-bottom: 1.25rem;
}

.sal-pdp-price-row {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: .35rem .75rem;
}

.sal-pdp-amount {
    font-size: 2.25rem;
    font-weight: 600;
    font-variant-numeric: tabular-nums;
    line-height: 1;
    color: var(--sal-ink);
}

.sal-pdp-was {
    font-size: 1.0625rem;
    color: var(--sal-muted);
}

.sal-pdp-saving {
    align-self: center;
    padding: .2rem .6rem;
    border-radius: 999px;
    background: rgba(139, 21, 56, .08);
    color: var(--sal-wine);
    font-size: .8125rem;
    font-weight: 600;
    font-variant-numeric: tabular-nums;
}

.sal-pdp-price-sub {
    display: flex;
    flex-wrap: wrap;
    gap: .25rem 1rem;
    margin-top: .5rem;
    color: var(--sal-muted);
    font-size: .8125rem;
}

.sal-pdp-units { margin-bottom: 1.25rem; }
.sal-pdp-units legend { font-size: .8125rem; font-weight: 600; color: var(--sal-ink); margin-bottom: .5rem; }

.sal-pdp-cta {
    display: flex;
    gap: .75rem;
    align-items: stretch;
}

.sal-pdp-add {
    flex: 1 1 auto;
    font-weight: 600;
    letter-spacing: .01em;
}

/* Stock status: a coloured dot and a sentence. */
.sal-pdp-stock {
    display: flex;
    align-items: baseline;
    gap: .55rem;
    margin: .9rem 0 0;
    font-size: .875rem;
    color: var(--sal-text);
}

.sal-pdp-stock-dot {
    flex: 0 0 auto;
    width: .55rem;
    height: .55rem;
    border-radius: 50%;
    transform: translateY(-.05rem);
    background: var(--sal-muted);
}

.sal-pdp-stock-success .sal-pdp-stock-dot { background: var(--sal-success); box-shadow: 0 0 0 3px rgba(31, 111, 74, .15); }
.sal-pdp-stock-warning .sal-pdp-stock-dot { background: #c98a1a; box-shadow: 0 0 0 3px rgba(201, 138, 26, .18); }
.sal-pdp-stock-error .sal-pdp-stock-dot   { background: var(--sal-danger); box-shadow: 0 0 0 3px rgba(164, 36, 59, .15); }

/* What every order comes with. */
.sal-pdp-promise {
    list-style: none;
    margin: 1.75rem 0 0;
    padding: .25rem 1.25rem;
    background: var(--sal-card);
    border: 1px solid var(--sal-line);
    border-radius: 12px;
}

.sal-pdp-promise li {
    display: flex;
    align-items: flex-start;
    gap: .85rem;
    padding: .9rem 0;
    font-size: .875rem;
    line-height: 1.5;
    color: var(--sal-muted);
}

.sal-pdp-promise li + li { border-top: 1px solid var(--sal-line); }
.sal-pdp-promise strong { color: var(--sal-ink); font-weight: 600; }

.sal-pdp-promise svg {
    flex: 0 0 auto;
    width: 1.35rem;
    height: 1.35rem;
    color: var(--sal-wine);
    margin-top: .05rem;
}

/* About this wine: notes to read, facts to scan. */
.sal-pdp-about {
    display: grid;
    grid-template-columns: minmax(0, 1fr);
    gap: 2rem;
    margin-top: 3.5rem;
    padding-top: 3rem;
    border-top: 1px solid var(--sal-line);
}

@media (min-width: 992px) {
    .sal-pdp-about {
        grid-template-columns: minmax(0, 1.4fr) minmax(0, 1fr);
        gap: 4rem;
        margin-top: 4.5rem;
    }
}

.sal-pdp-about-title {
    font-family: var(--sal-display);
    font-size: 1.75rem;
    margin-bottom: 1rem;
}

.sal-pdp-notes {
    max-width: 62ch;
    font-size: 1.0625rem;
    line-height: 1.8;
    color: #3c3540;
}

.sal-pdp-notes p:last-child { margin-bottom: 0; }

.sal-pdp-pdf {
    display: inline-flex;
    align-items: center;
    gap: .85rem;
    margin-top: 1.75rem;
    padding: .85rem 1.1rem;
    border: 1px solid var(--sal-line);
    border-radius: 12px;
    background: var(--sal-card);
    color: var(--sal-ink);
    text-decoration: none;
    transition: border-color .15s ease, box-shadow .15s ease;
}

.sal-pdp-pdf:hover { border-color: var(--sal-wine); box-shadow: 0 6px 18px rgba(23, 19, 26, .06); color: var(--sal-ink); }
.sal-pdp-pdf svg { width: 1.6rem; height: 1.6rem; color: var(--sal-wine); flex: 0 0 auto; }
.sal-pdp-pdf span { display: flex; flex-direction: column; line-height: 1.3; }
.sal-pdp-pdf strong { font-weight: 600; font-size: .9375rem; }
.sal-pdp-pdf small { color: var(--sal-muted); font-size: .75rem; }

.sal-pdp-glance {
    align-self: start;
    padding: 1.5rem 1.5rem .5rem;
    background: var(--sal-card);
    border: 1px solid var(--sal-line);
    border-radius: 16px;
}

.sal-pdp-glance-title {
    font-family: var(--sal-body);
    font-size: .75rem;
    font-weight: 600;
    letter-spacing: .14em;
    text-transform: uppercase;
    color: var(--sal-muted);
    margin-bottom: .5rem;
}

.sal-pdp-glance dl { margin: 0; }

.sal-pdp-glance-row {
    display: grid;
    grid-template-columns: 2.25rem minmax(0, 1fr);
    grid-template-rows: auto auto;
    column-gap: .75rem;
    padding: .85rem 0;
}

.sal-pdp-glance-row + .sal-pdp-glance-row { border-top: 1px solid var(--sal-line); }

.sal-pdp-glance-icon {
    grid-row: 1 / span 2;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 2.25rem;
    height: 2.25rem;
    border-radius: 50%;
    background: rgba(139, 21, 56, .06);
    color: var(--sal-wine);
}

.sal-pdp-glance-icon svg { width: 1.15rem; height: 1.15rem; }
.sal-pdp-glance dt { font-size: .75rem; font-weight: 500; color: var(--sal-muted); }
.sal-pdp-glance dd { margin: 0; font-size: .9375rem; font-weight: 500; color: var(--sal-ink); }

.sal-pdp-related {
    margin-top: 4rem;
    padding-top: 3rem;
    border-top: 1px solid var(--sal-line);
}

.sal-pdp-related-all { font-size: .875rem; font-weight: 600; color: var(--sal-wine); text-decoration: none; }
.sal-pdp-related-all:hover { text-decoration: underline; }

/* The phone buy bar. Below lg only, and only once the real button has
   scrolled away (see the page script). */
.sal-pdp-buybar {
    position: fixed;
    left: 0;
    right: 0;
    bottom: 0;
    z-index: 1030;
    display: flex;
    align-items: center;
    gap: 1rem;
    padding: .7rem 1rem calc(.7rem + env(safe-area-inset-bottom));
    background: rgba(255, 255, 255, .97);
    border-top: 1px solid var(--sal-line);
    box-shadow: 0 -8px 24px rgba(23, 19, 26, .08);
}

.sal-pdp-buybar-text { display: flex; flex-direction: column; min-width: 0; flex: 1 1 auto; }

.sal-pdp-buybar-name {
    font-size: .75rem;
    color: var(--sal-muted);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.sal-pdp-buybar-price { font-weight: 600; font-variant-numeric: tabular-nums; }
.sal-pdp-buybar .btn { flex: 0 0 auto; padding-left: 1.5rem; padding-right: 1.5rem; }

@media (min-width: 992px) {
    .sal-pdp-buybar { display: none !important; }
}

/* ---------------------------------------------------------------------
   7. Cart and checkout
   --------------------------------------------------------------------- */

.sal-panel {
    background: var(--sal-card);
    border: 1px solid var(--sal-line);
    border-radius: var(--sal-radius-lg);
}

.sal-panel-header {
    padding: .9rem 1.15rem;
    border-bottom: 1px solid var(--sal-line);
    font-family: var(--sal-body);
    font-size: 1.05rem;
    font-weight: 600;
}

.sal-panel-body { padding: 1.15rem; }

.sal-summary-row {
    display: flex;
    justify-content: space-between;
    padding: .3rem 0;
}

.sal-summary-total {
    display: flex;
    justify-content: space-between;
    align-items: baseline;
    padding-top: .7rem;
    margin-top: .5rem;
    border-top: 1px solid var(--sal-line);
    font-family: var(--sal-body);
    font-variant-numeric: tabular-nums;
    font-size: 1.35rem;
    font-weight: 600;
}

/* Checkout progress. Numbered, because a customer needs to know how much
   is left before they commit card details. */
.sal-steps {
    display: flex;
    gap: .35rem;
    list-style: none;
    padding: 0;
    margin: 0 0 1.75rem;
    flex-wrap: wrap;
}

.sal-step {
    display: flex;
    align-items: center;
    gap: .45rem;
    font-size: .8125rem;
    color: var(--sal-muted);
    padding: .3rem .7rem .3rem .3rem;
    border-radius: 999px;
}

.sal-step-num {
    width: 1.5rem; height: 1.5rem;
    border-radius: 50%;
    background: var(--sal-paper-2);
    color: var(--sal-muted);
    display: grid;
    place-items: center;
    font-size: .75rem;
    font-weight: 600;
    flex: 0 0 auto;
}

.sal-step.is-current { color: var(--sal-ink); font-weight: 600; }
.sal-step.is-current .sal-step-num { background: var(--sal-wine); color: #fff; }
.sal-step.is-done .sal-step-num { background: var(--sal-success); color: #fff; }

/* ---------------------------------------------------------------------
   8. Footer
   --------------------------------------------------------------------- */

.sal-footer {
    background: var(--sal-ink);
    color: #cdc6d2;
    font-size: .9375rem;
}

.sal-footer a { color: #cdc6d2; text-decoration: none; }
.sal-footer a:hover { color: #fff; text-decoration: underline; }

.sal-footer-brand {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: .75rem 1.5rem;
    padding: 2.25rem 0 1.75rem;
    border-bottom: 1px solid rgba(255, 255, 255, .12);
    color: #9d94a6;
}

.sal-footer-brand .sal-logo { height: 36px; width: auto; }

/* Four columns on a desktop, two on a phone: headings in sentence case and
   links spaced for a thumb, not a table of contents. */
.sal-footer-links { padding: 2rem 0 2.25rem; }

.sal-footer-links h2 {
    font-family: var(--sal-body);
    font-size: 1rem;
    font-weight: 600;
    color: #fff;
    margin-bottom: .9rem;
}

.sal-footer-links li + li { margin-top: .6rem; }

.sal-footer-social a {
    display: inline-flex;
    align-items: center;
    gap: .55rem;
}

.sal-footer-social svg { width: 1.15rem; height: 1.15rem; flex: 0 0 auto; }

.sal-footer-apps {
    display: flex;
    flex-wrap: wrap;
    gap: .75rem;
}

.sal-footer-apps a { display: block; line-height: 0; border-radius: 6px; }
.sal-footer-apps a:hover { opacity: .88; }
.sal-footer-apps a:focus-visible { outline: 2px solid #fff; outline-offset: 3px; }
.sal-footer-apps img { height: 40px; width: auto; }

/* Pregnancy warning, where to get help, and responsible service: three
   statements side by side, each with its mark. */
.sal-footer-care {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(16rem, 1fr));
    gap: 1.25rem 2rem;
    padding: 1.75rem 0;
    border-top: 1px solid rgba(255, 255, 255, .12);
}

.sal-footer-care-item {
    display: flex;
    align-items: center;
    gap: .9rem;
    font-size: .875rem;
    line-height: 1.5;
}

.sal-footer-care-item strong { color: #fff; }
.sal-footer-care-item a { color: #fff; text-decoration: underline; }

.sal-footer-care-icon { width: 2.5rem; height: 2.5rem; flex: 0 0 auto; }
.sal-footer-care-line { color: #cdc6d2; padding: .25rem; }

/* The licence block. Kept visually quiet but never hidden - it is a
   condition of the licence that it appears on every page. */
.sal-licence {
    border-top: 1px solid rgba(255, 255, 255, .12);
    padding: 1.25rem 0 1.75rem;
    color: #9d94a6;
    font-size: .8125rem;
    line-height: 1.6;
}

.sal-licence strong { color: #cdc6d2; }

/* The copyright line, on a light band, the way a document ends. */
.sal-footer-bar {
    background: var(--sal-paper);
    color: var(--sal-ink);
    font-size: .875rem;
    padding: 1.1rem 0;
}

.sal-footer-bar .container-fluid {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: .35rem .75rem;
}

.sal-footer-bar a { color: var(--sal-wine); font-weight: 500; }
.sal-footer-bar a:hover { color: var(--sal-wine-dark); }
.sal-footer-bar-sep { color: var(--sal-wine); margin-right: .6rem; }
.sal-footer-bar-item { white-space: nowrap; }

/* ---------------------------------------------------------------------
   The auth screens

   Full width is right for a product grid and wrong for a sign-in form, which
   has nothing to fill it with. A capped, centred band keeps the panels a
   comfortable size on any monitor without the page looking abandoned.
   --------------------------------------------------------------------- */

.sal-auth {
    max-width: 60rem;
    margin-inline: auto;
}

/* ---------------------------------------------------------------------
   Long-form copy

   The page is full width now, which is right for a product grid and wrong for
   a paragraph: on a wide monitor an unconstrained line of text runs to several
   hundred characters and the eye loses its place returning to the left margin.
   Grids stretch; prose does not. Roughly 70 characters is the usual comfortable
   measure.
   --------------------------------------------------------------------- */

.sal-page-content,
.sal-prose {
    max-width: 70ch;
}

.sal-page-content > :last-child { margin-bottom: 0; }

/* ---------------------------------------------------------------------
   9. Utilities and motion
   --------------------------------------------------------------------- */

/* ---------------------------------------------------------------------
   The hero

   Call to action on one side, banner on the other.

   The banner keeps its own 2.23:1 and the row takes whatever height that
   comes to. That is the whole trick: an earlier version stretched it to fill
   a square-ish half with object-fit: cover, which sliced the lettering set
   into the artwork. Nothing may crop this image.
   --------------------------------------------------------------------- */

.sal-hero {
    display: grid;
    grid-template-columns: 1fr;
    background:
        linear-gradient(180deg, rgba(23, 19, 26, .82) 0%, rgba(23, 19, 26, .68) 100%),
        radial-gradient(90% 120% at 80% 0%, #5c1030 0%, #17131a 70%);
    color: #fff;
    border-radius: var(--sal-radius-lg);
    overflow: hidden;
}

.sal-hero-cta {
    padding: clamp(1.75rem, 4vw, 3rem) clamp(1.5rem, 4vw, 3rem);
    align-self: center;
}

/* The picture is the loud one. This heading has to exist - a page whose only
   heading is inside an image is invisible to a search engine and to a screen
   reader - but it does not have to shout over it. */
.sal-hero-cta h1 {
    color: #fff;
    font-size: clamp(1.5rem, 3vw, 2.25rem);
    max-width: 20ch;
}

.sal-hero-cta p {
    color: #e5dfe9;
    max-width: 46ch;
    font-size: .9375rem;
}

.sal-hero-actions {
    display: flex;
    flex-wrap: wrap;
    gap: .5rem;
}

/* No object-fit and no fixed height, deliberately. The image sets its own
   proportions, so nothing is ever cut off it at any width. */
.sal-hero-banner {
    align-self: center;
    order: -1;
}

.sal-hero-banner picture { display: block; }

.sal-hero-banner img {
    display: block;
    width: 100%;
    height: auto;
}

@media (min-width: 992px) {
    .sal-hero { grid-template-columns: 1fr 1fr; align-items: center; }

    /* Copy first on a wide screen, picture second. Stacked, the picture goes
       on top - it is the thing that earns the scroll. */
    .sal-hero-banner { order: 0; }
}

/* ---------------------------------------------------------------------
   Product rails

   One component, used by the seasonal sale, Our top picks and Gift-worthy
   bottles. A scroll container with snap points, not a slide carousel: seven
   cards fit on a wide screen and two on a phone, and a scroll container gets
   that right by itself, where slides of a fixed seven would show one and a
   half on a phone and cut the rest.
   --------------------------------------------------------------------- */

.sal-rail-track {
    display: grid;
    grid-auto-flow: column;
    grid-auto-columns: calc((100% - 6 * .75rem) / 7);
    gap: .75rem;
    overflow-x: auto;
    scroll-snap-type: x mandatory;
    scroll-behavior: smooth;
    scrollbar-width: none;
    padding-bottom: .25rem;
}

.sal-rail-track::-webkit-scrollbar { display: none; }

.sal-rail-item { scroll-snap-align: start; }

/* Seven only where seven can be read. Below that the cards keep a usable
   width and the rail simply scrolls further. */
@media (max-width: 1399.98px) {
    .sal-rail-track { grid-auto-columns: calc((100% - 4 * .75rem) / 5); }
}

@media (max-width: 1199.98px) {
    .sal-rail-track { grid-auto-columns: calc((100% - 3 * .75rem) / 4); }
}

@media (max-width: 991.98px) {
    .sal-rail-track { grid-auto-columns: calc((100% - 2 * .75rem) / 3); }
}

@media (max-width: 767.98px) {
    .sal-rail-track { grid-auto-columns: calc((100% - .75rem) / 2); }
}

.sal-rail-nav { display: flex; gap: .5rem; flex: 0 0 auto; }

.sal-rail-arrow {
    width: 2.25rem;
    height: 2.25rem;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border: 1px solid var(--sal-line);
    border-radius: 50%;
    background: var(--sal-card);
    color: var(--sal-ink);
    transition: border-color .15s ease, color .15s ease, opacity .15s ease;
}

.sal-rail-arrow:hover:not(:disabled) { border-color: var(--sal-wine); color: var(--sal-wine); }
.sal-rail-arrow:disabled { opacity: .35; cursor: default; }

/* On the dark band the wine hover would vanish, so it lifts to white. */
.sal-rail-arrow-light {
    background: transparent;
    border-color: rgba(255, 255, 255, .28);
    color: #fff;
}

.sal-rail-arrow-light:hover:not(:disabled) { border-color: #fff; color: #fff; }

.sal-rail-dots { display: flex; gap: .375rem; }

.sal-rail-dot {
    width: .4375rem;
    height: .4375rem;
    border-radius: 999px;
    background: var(--sal-line);
    transition: width .15s ease, background .15s ease;
}

.sal-rail-dot.is-active { width: 1.25rem; background: var(--sal-wine); }

/* The saving, in dollars, over the bottle shot. */
.sal-save-badge {
    position: absolute;
    top: .5rem;
    right: .5rem;
    z-index: 2;
    display: inline-block;
    padding: .3rem .45rem;
    border-radius: 999px;
    background: var(--sal-wine);
    color: #fff;
    font-size: .625rem;
    font-weight: 700;
    line-height: 1.15;
    text-align: center;
    letter-spacing: .01em;
}

/* The price it used to be, struck through beside the one being charged. */
.sal-card-was {
    margin-left: .375rem;
    font-size: .8125rem;
    font-weight: 400;
    color: var(--sal-muted);
    text-decoration: line-through;
}

/* ---------------------------------------------------------------------
   Shop by category

   Copy on the left, a scrolling strip of glasses on the right. The arrows sit
   over the ends of the strip rather than above it, because at this size the
   strip is the whole control and a header row of arrows would float
   unattached.
   --------------------------------------------------------------------- */

.sal-range {
    display: grid;
    grid-template-columns: 1fr;
    gap: 1.5rem;
    align-items: center;
    padding: clamp(1.25rem, 3vw, 2rem);
    background: var(--sal-card);
    border: 1px solid var(--sal-line);
    border-radius: var(--sal-radius-lg);
}

@media (min-width: 768px) {
    .sal-range { grid-template-columns: minmax(13rem, 20rem) 1fr; gap: 2rem; }
}

.sal-range-intro p { max-width: 30ch; }

.sal-range-scroller { position: relative; min-width: 0; }

.sal-range-track {
    display: grid;
    grid-auto-flow: column;
    grid-auto-columns: calc((100% - 5 * 1rem) / 6);
    gap: 1rem;
    overflow-x: auto;
    scroll-snap-type: x mandatory;
    scroll-behavior: smooth;
    scrollbar-width: none;
}

.sal-range-track::-webkit-scrollbar { display: none; }

@media (max-width: 1199.98px) { .sal-range-track { grid-auto-columns: calc((100% - 4 * 1rem) / 5); } }
@media (max-width: 991.98px)  { .sal-range-track { grid-auto-columns: calc((100% - 3 * 1rem) / 4); } }
@media (max-width: 575.98px)  { .sal-range-track { grid-auto-columns: calc((100% - 2 * 1rem) / 3); } }

.sal-range-tile {
    scroll-snap-align: start;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: .5rem;
    padding: .5rem .25rem;
    color: var(--sal-ink);
    text-decoration: none;
    text-align: center;
    transition: color .15s ease, transform .15s ease;
}

.sal-range-tile:hover { color: var(--sal-wine); transform: translateY(-2px); }

.sal-range-icon { display: block; }

.sal-range-label {
    font-size: .75rem;
    font-weight: 600;
    letter-spacing: .02em;
    line-height: 1.2;
}

/* Over the ends of the strip, so they read as part of it. */
.sal-range-arrow {
    position: absolute;
    top: 50%;
    transform: translateY(-50%);
    z-index: 2;
    box-shadow: var(--sal-shadow);
}

.sal-range-arrow-prev { left: -1rem; }
.sal-range-arrow-next { right: -1rem; }

/* ---------------------------------------------------------------------
   Discover South Australian favourites

   A dark band with wide landscape cards, deliberately unlike the product
   rails above it. Three identical rails in a row read as one long rail and a
   customer stops seeing where one ends and the next begins.
   --------------------------------------------------------------------- */

.sal-local {
    padding: clamp(1.5rem, 3vw, 2.5rem);
    border-radius: var(--sal-radius-lg);
    background:
        linear-gradient(180deg, rgba(23, 19, 26, .86) 0%, rgba(23, 19, 26, .72) 100%),
        radial-gradient(90% 130% at 15% 0%, #5c1030 0%, #17131a 72%);
    color: #fff;
}

.sal-local h2 { color: #fff; }

.sal-eyebrow-light { color: var(--sal-rose); }

.sal-local-sub { color: #e5dfe9; font-size: .875rem; max-width: 52ch; }

.sal-local-head {
    display: flex;
    justify-content: space-between;
    align-items: flex-end;
    gap: 1rem;
    margin-bottom: 1.25rem;
}

.sal-local-track {
    display: grid;
    grid-auto-flow: column;
    grid-auto-columns: calc((100% - 3 * 1rem) / 4);
    gap: 1rem;
    overflow-x: auto;
    scroll-snap-type: x mandatory;
    scroll-behavior: smooth;
    scrollbar-width: none;
}

.sal-local-track::-webkit-scrollbar { display: none; }

@media (max-width: 1199.98px) { .sal-local-track { grid-auto-columns: calc((100% - 2 * 1rem) / 3); } }
@media (max-width: 767.98px)  { .sal-local-track { grid-auto-columns: calc((100% - 1rem) / 2); } }
@media (max-width: 479.98px)  { .sal-local-track { grid-auto-columns: 100%; } }

.sal-local-card {
    scroll-snap-align: start;
    display: flex;
    gap: .875rem;
    padding: .875rem;
    border-radius: var(--sal-radius);
    background: rgba(255, 255, 255, .06);
    border: 1px solid rgba(255, 255, 255, .1);
    text-decoration: none;
    color: #fff;
    transition: background .15s ease, border-color .15s ease;
}

.sal-local-card:hover {
    background: rgba(255, 255, 255, .1);
    border-color: rgba(255, 255, 255, .22);
    color: #fff;
}

/* A fixed box for the bottle shot so the row does not reflow as images land. */
.sal-local-shot {
    flex: 0 0 4rem;
    height: 6.5rem;
    display: flex;
    align-items: center;
    justify-content: center;
}

.sal-local-shot img { max-width: 100%; max-height: 100%; width: auto; height: auto; }

.sal-local-text { display: flex; flex-direction: column; gap: .125rem; min-width: 0; }

.sal-local-brand {
    font-size: .6875rem;
    font-weight: 700;
    letter-spacing: .1em;
    text-transform: uppercase;
    color: var(--sal-rose);
}

.sal-local-region { font-size: .6875rem; color: #c9c1cf; }

.sal-local-name {
    font-family: var(--sal-body);
    font-weight: 600;
    font-size: .9375rem;
    line-height: 1.25;
    margin-top: .125rem;
}

.sal-local-price { margin-top: auto; font-weight: 600; font-size: .9375rem; }

.sal-local-dots { display: flex; gap: .375rem; justify-content: center; margin-top: 1.25rem; }

.sal-local-dots .sal-rail-dot { background: rgba(255, 255, 255, .28); }
.sal-local-dots .sal-rail-dot.is-active { background: #fff; }

/* ---------------------------------------------------------------------
   The delivery band

   NO object-fit AND NO FIXED HEIGHT ON THE BANNER, deliberately, for the same
   reason as the hero: the artwork has "YOUR DRINKS. YOUR DOORSTEP." set into
   it and cropping slices the lettering. The image sets its own proportions.
   --------------------------------------------------------------------- */

.sal-delivery {
    display: grid;
    grid-template-columns: 1fr;
    gap: 1.5rem;
    align-items: center;
    padding: clamp(1.25rem, 3vw, 2rem);
    background: var(--sal-card);
    border: 1px solid var(--sal-line);
    border-radius: var(--sal-radius-lg);
}

@media (min-width: 992px) {
    .sal-delivery { grid-template-columns: 1fr 1fr; gap: 2.5rem; }
}

.sal-delivery-banner picture { display: block; }

.sal-delivery-banner img {
    display: block;
    width: 100%;
    height: auto;
    border-radius: var(--sal-radius);
}

.sal-delivery-points {
    list-style: none;
    padding: 0;
    margin: 0 0 1.5rem;
    display: grid;
    gap: .625rem;
}

.sal-delivery-points li {
    position: relative;
    padding-left: 1.5rem;
    font-size: .875rem;
    color: var(--sal-text);
}

.sal-delivery-points li::before {
    content: "";
    position: absolute;
    left: 0;
    top: .45em;
    width: .5rem;
    height: .5rem;
    border-radius: 50%;
    background: var(--sal-wine);
}

.sal-delivery-check { max-width: 22rem; }

/* ---------------------------------------------------------------------
   Three reasons
   --------------------------------------------------------------------- */

.sal-features {
    display: grid;
    grid-template-columns: 1fr;
    gap: 1rem;
}

@media (min-width: 768px) { .sal-features { grid-template-columns: repeat(3, 1fr); } }

.sal-feature {
    padding: 1.5rem;
    background: var(--sal-card);
    border: 1px solid var(--sal-line);
    border-radius: var(--sal-radius-lg);
}

.sal-feature-icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 2.5rem;
    height: 2.5rem;
    margin-bottom: .875rem;
    border-radius: 50%;
    background: var(--sal-paper-2);
    color: var(--sal-wine);
}

/* ---------------------------------------------------------------------
   The signup offer
   --------------------------------------------------------------------- */

.sal-signup {
    padding: clamp(1.5rem, 3vw, 2.5rem);
    border-radius: var(--sal-radius-lg);
    background:
        linear-gradient(180deg, rgba(23, 19, 26, .88) 0%, rgba(23, 19, 26, .74) 100%),
        radial-gradient(80% 130% at 85% 0%, #5c1030 0%, #17131a 72%);
    color: #fff;
}

.sal-signup h2 { color: #fff; }

.sal-signup-inner {
    display: grid;
    grid-template-columns: 1fr;
    gap: 1.5rem;
    align-items: center;
}

@media (min-width: 992px) {
    .sal-signup-inner { grid-template-columns: 1.2fr 1fr; gap: 2.5rem; }
}

.sal-signup-sub { color: #e5dfe9; font-size: .875rem; max-width: 52ch; }

/* The asterisk is the qualifier, so it must be findable rather than
   decorative, but it is not the headline either. */
.sal-signup-star { color: var(--sal-rose); }

.sal-signup-form { display: flex; gap: .5rem; flex-wrap: wrap; }

.sal-signup-form .form-control { flex: 1 1 12rem; min-width: 0; }

.sal-signup-fine {
    margin-top: 1.25rem;
    font-size: .75rem;
    color: #b9b1c0;
}

/* The honeypot. Off-screen rather than display:none, because a bot that reads
   CSS skips a hidden field and fills in one it thinks is visible. */
.sal-hp {
    position: absolute;
    left: -10000px;
    width: 1px;
    height: 1px;
    overflow: hidden;
}

/* The welcome code, on the page the confirmation link lands on. */
.sal-code {
    font-family: var(--sal-body);
    font-size: 1.75rem;
    font-weight: 700;
    letter-spacing: .18em;
    color: var(--sal-wine);
    border: 1px dashed var(--sal-line);
    border-radius: var(--sal-radius);
    padding: .875rem 1rem;
    background: var(--sal-paper-2);
}

/* Category tiles on the home page. */
.sal-tile {
    position: relative;
    display: block;
    border-radius: var(--sal-radius-lg);
    border: 1px solid var(--sal-line);
    background: var(--sal-card);
    padding: 1.4rem 1.25rem;
    text-decoration: none;
    color: var(--sal-ink);
    transition: border-color .18s ease, transform .18s ease, box-shadow .18s ease;
}

@media (hover: hover) {
    .sal-tile:hover {
        transform: translateY(-2px);
        border-color: transparent;
        box-shadow: var(--sal-shadow);
        color: var(--sal-wine-dark);
    }
}

.sal-tile-count { font-size: .8125rem; color: var(--sal-muted); }

/* Filters column on the listing page. */
.sal-filters {
    background: var(--sal-card);
    border: 1px solid var(--sal-line);
    border-radius: var(--sal-radius-lg);
    padding: 1.15rem;
}

.sal-filter-group + .sal-filter-group {
    margin-top: 1rem;
    padding-top: 1rem;
    border-top: 1px solid var(--sal-line);
}

/* Applied-filter chips. */
.sal-chip {
    display: inline-flex;
    align-items: center;
    gap: .35rem;
    background: var(--sal-paper-2);
    border: 1px solid var(--sal-line);
    border-radius: 999px;
    padding: .2rem .6rem;
    font-size: .8125rem;
    text-decoration: none;
    color: var(--sal-text);
}

.sal-chip:hover { border-color: var(--sal-wine); color: var(--sal-wine); }

/* Flash messages, restyled away from Bootstrap's default alerts. */
.sal-flash {
    border: 1px solid var(--sal-line);
    border-left: 3px solid var(--sal-muted);
    border-radius: var(--sal-radius);
    background: #fff;
    padding: .8rem 1rem;
}

.sal-flash-success { border-left-color: var(--sal-success); }
.sal-flash-error   { border-left-color: var(--sal-danger); }
.sal-flash-warning { border-left-color: var(--sal-warn); }

/* Respect a reduced-motion preference: every transition above is
   decorative, and none of them carry meaning. */
@media (prefers-reduced-motion: reduce) {
    *,
    *::before,
    *::after {
        animation-duration: .001ms !important;
        transition-duration: .001ms !important;
        scroll-behavior: auto !important;
    }
}

/* Visible focus for keyboard users. Bootstrap's default is easy to lose
   against a warm background. */
:focus-visible {
    outline: 2px solid var(--sal-wine);
    outline-offset: 2px;
}

/* ---------------------------------------------------------------------
   The discount code at checkout

   Understated on purpose. A large "HAVE A PROMO CODE?" box is the single
   most reliable way to send somebody off to search for one and not come
   back, so this reads as a field rather than an invitation.
   --------------------------------------------------------------------- */

.sal-coupon {
    padding: .875rem 1rem;
    background: var(--sal-paper-2);
    border: 1px solid var(--sal-line);
    border-radius: var(--sal-radius);
}

.sal-coupon form { margin: 0; }

/* The discount gets its own line in the totals. A customer who entered a
   code needs to see it working: a smaller subtotal is not the same
   reassurance as "minus $10.00". */
.sal-summary-discount { color: var(--sal-success); }

/* ---------------------------------------------------------------------
   Quantity steppers

   A real number input with a button either side. The input is inside the
   same form as the Add button, so with JavaScript blocked the field is
   still typeable and the form still posts the right value; the buttons
   are the part that degrades, which is the right way round.
   --------------------------------------------------------------------- */

.sal-stepper {
    display: inline-flex;
    align-items: center;
    gap: .125rem;
    border: 1px solid var(--sal-line);
    border-radius: 999px;
    padding: .125rem;
    background: var(--sal-card);
}

.sal-stepper form { margin: 0; display: flex; }

.sal-stepper-btn {
    width: 1.75rem;
    height: 1.75rem;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border: 0;
    border-radius: 50%;
    background: var(--sal-paper-2);
    color: var(--sal-ink);
    transition: background .15s ease, color .15s ease;
}

.sal-stepper-btn:hover { background: var(--sal-wine); color: #fff; }
.sal-stepper-btn:disabled { opacity: .35; cursor: default; }

.sal-stepper-count,
.sal-stepper-input {
    min-width: 2rem;
    text-align: center;
    font-size: .875rem;
    font-weight: 600;
    font-variant-numeric: tabular-nums;
    color: var(--sal-ink);
}

.sal-stepper-input {
    width: 2.5rem;
    border: 0;
    background: transparent;
    padding: 0;
    -moz-appearance: textfield;
    appearance: textfield;
}

/* The native spinners duplicate the buttons and are far too small to hit. */
.sal-stepper-input::-webkit-outer-spin-button,
.sal-stepper-input::-webkit-inner-spin-button {
    -webkit-appearance: none;
    margin: 0;
}

.sal-stepper-input:focus { outline: 2px solid var(--sal-wine); outline-offset: 2px; border-radius: 4px; }

/* On a card the stepper centres over the full-width Add button. */
/* The stepper on a product card spans the card, so its parts have to span it
   too. It was a full-width pill holding three fixed-width children, which
   flex then packed against the left: minus at the edge, plus stranded near
   the middle, and a stretch of empty pill after it. The buttons now sit at
   the two ends and the number takes what is between them, so it reads as
   centred at every card width.

   Only the card variant. The cart, the drawer and the product page use a
   stepper sized to its own content, which is right there. */
.sal-stepper-inline {
    display: flex;
    align-items: center;
    justify-content: space-between;
    width: 100%;
}

.sal-stepper-inline .sal-stepper-input {
    flex: 1 1 auto;
    width: auto;
    min-width: 0;
}

.sal-stepper-lg { padding: .25rem; }
.sal-stepper-lg .sal-stepper-btn { width: 2.25rem; height: 2.25rem; }
.sal-stepper-lg .sal-stepper-input { width: 3rem; font-size: 1rem; }

.sal-add-form { display: block; }

/* ---------------------------------------------------------------------
   The cart drawer
   --------------------------------------------------------------------- */

.sal-drawer-pricing {
    display: flex;
    align-items: baseline;
    gap: .25rem;
    margin-top: .25rem;
}

.sal-drawer-price { font-weight: 600; color: var(--sal-wine); }

.sal-drawer-controls {
    display: flex;
    justify-content: space-between;
    align-items: center;
    gap: .5rem;
    margin-top: .5rem;
}

.sal-clear-cart {
    border: 1px solid var(--sal-line);
    background: transparent;
    color: var(--sal-muted);
    border-radius: 999px;
    padding: .3rem .875rem;
    font-size: .75rem;
    transition: border-color .15s ease, color .15s ease;
}

.sal-clear-cart:hover { border-color: var(--sal-danger); color: var(--sal-danger); }

/* Green, and only when something is genuinely marked down. A "saving
   $0.00" bar is worse than no bar at all. */
.sal-savings-bar {
    display: block;
    padding: .625rem .875rem;
    border-radius: var(--sal-radius);
    background: var(--sal-success);
    color: #fff;
    font-weight: 700;
    font-size: .8125rem;
    letter-spacing: .02em;
    text-align: center;
}

/* You may also like */
.sal-drawer-suggest {
    margin-top: 1.25rem;
    padding-top: 1.25rem;
    border-top: 1px solid var(--sal-line);
}

.sal-suggest-track {
    display: grid;
    grid-auto-flow: column;
    grid-auto-columns: calc((100% - .75rem) / 2);
    gap: .75rem;
    overflow-x: auto;
    scroll-snap-type: x mandatory;
    scrollbar-width: none;
    padding-bottom: .25rem;
}

.sal-suggest-track::-webkit-scrollbar { display: none; }

.sal-suggest-card {
    scroll-snap-align: start;
    display: flex;
    flex-direction: column;
    border: 1px solid var(--sal-line);
    border-radius: var(--sal-radius);
    overflow: hidden;
    background: var(--sal-card);
}

.sal-suggest-link {
    display: flex;
    flex-direction: column;
    gap: .25rem;
    padding: .625rem;
    text-decoration: none;
    color: var(--sal-ink);
    flex: 1 1 auto;
}

.sal-suggest-shot {
    display: flex;
    align-items: center;
    justify-content: center;
    height: 5rem;
}

.sal-suggest-shot img { max-height: 100%; max-width: 100%; width: auto; }

.sal-suggest-name {
    font-size: .75rem;
    line-height: 1.25;
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
}

.sal-suggest-price { font-size: .8125rem; font-weight: 700; margin-top: auto; }

.sal-suggest-card .btn { border-radius: 0; }

.sal-cart-qty { display: flex; align-items: center; gap: .5rem; }

/* Stock state on a product card.
   Small and quiet: the button already carries the message, and a card in a
   rail of seven should not shout about what it does not have. */
.sal-card-stock {
    color: var(--sal-muted);
    font-size: .75rem;
    margin-top: .35rem;
    text-align: center;
}
