/* ==========================================================================
   Willis Lane design system
   --------------------------------------------------------------------------
   Loaded AFTER bootstrap and style_v2.css, so it is the last word on type,
   colour and spacing. style_v2.css is the inherited 2.0 stylesheet and is
   still doing real work (grid helpers, legacy page rules); rather than pick
   it apart, this file overrides the handful of global declarations that
   carry the old look — body font, heading font, paragraph colour, the teal
   accent — and then supplies the components the new layout needs.

   Component classes are all `wl-` prefixed. Bootstrap already owns .h2,
   .code, .card, .price and .item, so unprefixed names collide.
   ========================================================================== */

:root {
    /* Ink and surfaces */
    --wl-ink:        #191E1A;
    --wl-bluestone:  #2E463C;
    --wl-stone:      #63675F;
    --wl-chalk:      #F7F5F0;
    /* The alternating section band. Sits between chalk and paper in value, so
       a full-width section reads as a band against the page without the hard
       white edge --wl-paper gives it. Cards inside a plaster band stay
       --wl-paper and gain their contrast from it. */
    --wl-plaster:    #EAE7DE;
    --wl-rule:       #D8D3C6;
    --wl-paper:      #FFFFFF;

    /* Accents */
    --wl-brass:      #8F7238;
    --wl-brass-lit:  #C9A96A;
    --wl-good:       #3F6B4A;
    --wl-low:        #9A5B2B;
    --wl-sale:       #9A3324;

    /* Body copy sits a touch lighter than headings so a page of text does not
       read as one solid block. Still well past AA on chalk and paper. */
    --wl-body-ink:   #4A524B;

    --wl-gutter:     clamp(1rem, 3.5vw, 3rem);
    --wl-maxw:       1440px;

    --wl-display:    "Archivo", system-ui, -apple-system, sans-serif;
    --wl-body:       "IBM Plex Sans", system-ui, -apple-system, sans-serif;
    --wl-mono:       "IBM Plex Mono", ui-monospace, "SF Mono", Menlo, monospace;
}

/* ==========================================================================
   1. Base — overrides of style_v2.css / bootstrap globals
   ========================================================================== */

body {
    font-family: var(--wl-body);
    font-size: 16px;
    line-height: 1.55;
    background-color: var(--wl-chalk);
    color: var(--wl-ink);
    -webkit-font-smoothing: antialiased;
}

/* style_v2.css paints every paragraph #b3b3b3 at weight 300, which is where
   most of the old washed-out feel came from. */
p {
    color: var(--wl-body-ink);
    font-weight: 400;
}

h1, h2, h3, h4, h5, h6,
.h1, .h2, .h3, .h4, .h5, .h6 {
    font-family: var(--wl-display);
    font-weight: 700;
    font-stretch: 112%;
    letter-spacing: -0.015em;
    line-height: 1.06;
    color: var(--wl-ink);
}

h1, .h1 { font-size: clamp(2rem, 4.5vw, 3.2rem); font-stretch: 118%; letter-spacing: -0.022em; }
h2, .h2 { font-size: clamp(1.6rem, 3.2vw, 2.4rem); font-stretch: 116%; letter-spacing: -0.018em; }
h3, .h3 { font-size: clamp(1.2rem, 2vw, 1.5rem); }
h4, .h4 { font-size: 1.15rem; }
h5, .h5 { font-size: 1rem; }
h6, .h6 { font-size: 0.9rem; }

a { color: inherit; transition: color .16s ease, border-color .16s ease, background .16s ease; }
a:hover { color: var(--wl-brass); }

:focus-visible { outline: 2px solid var(--wl-brass); outline-offset: 2px; }

strong, b { font-weight: 600; }
hr { border-color: var(--wl-rule); }

/* The 2.0 sheet lets .container run to 4000px, which leaves content stranded
   at the edges of a wide monitor. The artifact caps its measure at 1440. */
@media (min-width: 1300px) {
    .container { max-width: var(--wl-maxw); }
}

/* Retire the old teal. It is hard-coded in a lot of inherited markup, so the
   utility classes below give those call sites somewhere to land. */
.wl-accent { color: var(--wl-brass); }
.current   { color: var(--wl-ink); }

/* ==========================================================================
   2. Layout and typographic helpers
   ========================================================================== */

.wl-wrap {
    max-width: var(--wl-maxw);
    margin: 0 auto;
    padding-inline: var(--wl-gutter);
}

.wl-sec { padding: clamp(2.8rem, 6vw, 4.6rem) 0; }
/* Consecutive product rows on the signed-in dashboard (Your lists → Buy again
   → Ready to re-order → New for you) get half the top padding, so the stacked
   headings don't sit an entire section-gap apart. Full top padding still
   applies when a wl-sec follows the dashboard or the categories band, so the
   first row after those still breathes off them. */
.wl-sec + .wl-sec { padding-top: clamp(.8rem, 1.5vw, 1.4rem); }
.wl-sec-tight { padding: clamp(1.6rem, 3vw, 2.4rem) 0; }

.wl-sec-hd {
    display: flex;
    align-items: flex-end;
    justify-content: space-between;
    gap: 1.5rem;
    flex-wrap: wrap;
    margin-bottom: 1.6rem;
}

/* Small mono label above a heading. The single most repeated device in the
   design — it is what makes a heading read as a section rather than a shout. */
.wl-eyebrow {
    font-family: var(--wl-body);
    font-size: 11px;
    font-weight: 500;
    letter-spacing: .14em;
    text-transform: uppercase;
    color: var(--wl-stone);
    margin: 0;
}

.wl-h2 {
    font-family: var(--wl-display);
    font-weight: 700;
    font-stretch: 116%;
    letter-spacing: -.018em;
    line-height: 1.02;
    font-size: clamp(1.7rem, 3.2vw, 2.6rem);
    margin: .5rem 0 0;
}

.wl-lede {
    margin-top: .8rem;
    max-width: 58ch;
    color: var(--wl-body-ink);
    font-size: 15.5px;
}

/* Stock codes, dimensions, quantities — anything the buyer reads as data
   rather than as prose. */
.wl-code {
    font-family: var(--wl-body);
    font-size: 10.5px;
    letter-spacing: .05em;
    color: var(--wl-stone);
}

.wl-rule-top { border-top: 1px solid var(--wl-rule); }

/* ==========================================================================
   3. Buttons
   ========================================================================== */

.wl-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: .45rem;
    font-family: var(--wl-body);
    font-size: 11.5px;
    font-weight: 500;
    letter-spacing: .08em;
    text-transform: uppercase;
    padding: .72rem 1.25rem;
    border: 1px solid var(--wl-ink);
    background: transparent;
    color: var(--wl-ink);
    cursor: pointer;
    white-space: nowrap;
    border-radius: 0;
    transition: background .16s, color .16s, border-color .16s;
}
.wl-btn:hover { background: var(--wl-ink); color: var(--wl-chalk); text-decoration: none; }

.wl-btn-solid { background: var(--wl-ink); color: var(--wl-chalk); }
.wl-btn-solid:hover { background: var(--wl-brass); border-color: var(--wl-brass); color: #fff; }

.wl-btn-quiet { border-color: var(--wl-rule); }
.wl-btn-light { border-color: rgba(255,255,255,.4); color: #fff; }
.wl-btn-light:hover { background: #fff; color: var(--wl-ink); }

.wl-btn-sm { padding: .48rem .78rem; font-size: 11px; }
.wl-btn-block { width: 100%; }

/* Bootstrap buttons appear all over the inherited templates (cart, checkout,
   account). Rather than rewrite every call site, give them the new shape. */
.btn {
    font-family: var(--wl-body);
    font-size: 11.5px;
    font-weight: 500;
    letter-spacing: .08em;
    text-transform: uppercase;
    border-radius: 0;
    padding: .72rem 1.25rem;
    transition: background .16s, color .16s, border-color .16s;
}
.btn-primary, .btn-dark, .btn-template {
    background: var(--wl-ink);
    border-color: var(--wl-ink);
    color: var(--wl-chalk);
}
.btn-primary:hover, .btn-dark:hover, .btn-template:hover,
.btn-primary:focus, .btn-dark:focus {
    background: var(--wl-brass);
    border-color: var(--wl-brass);
    color: #fff;
}
.btn-secondary, .btn-outline-dark {
    background: transparent;
    border-color: var(--wl-ink);
    color: var(--wl-ink);
}
.btn-secondary:hover, .btn-outline-dark:hover {
    background: var(--wl-ink);
    border-color: var(--wl-ink);
    color: var(--wl-chalk);
}
.btn-danger { background: var(--wl-sale); border-color: var(--wl-sale); }
.btn-success { background: var(--wl-good); border-color: var(--wl-good); }
.btn-sm { padding: .48rem .78rem; font-size: 11px; }

/* ==========================================================================
   4. Form controls
   ========================================================================== */

input, textarea, select, button { font-family: inherit; color: inherit; }

.form-control,
input[type="text"], input[type="email"], input[type="password"],
input[type="search"], input[type="tel"], input[type="number"],
textarea, select {
    border-radius: 0;
    border: 1px solid var(--wl-rule);
    background: var(--wl-paper);
    color: var(--wl-ink);
    font-size: 14.5px;
    padding: .6rem .75rem;
    height: auto;
}
.form-control:focus,
input:focus, textarea:focus, select:focus {
    border-color: var(--wl-ink);
    box-shadow: none;
    outline: none;
}
::placeholder { color: #9BA1A5; opacity: 1; }

label {
    font-family: var(--wl-body);
    font-size: 10.5px;
    letter-spacing: .11em;
    text-transform: uppercase;
    color: var(--wl-stone);
    margin-bottom: .3rem;
}

/* ==========================================================================
   5. Utility bar
   ========================================================================== */

.wl-util {
    background: var(--wl-bluestone);
    color: #C6C9C4;
    font-family: var(--wl-body);
    font-size: 11.5px;
    letter-spacing: .04em;
}
.wl-util a { color: inherit; }
.wl-util a:hover { color: var(--wl-brass-lit); }
.wl-util-in {
    display: flex;
    /* nowrap: the utility bar must never spill to a second line. Anything
       that would push it over gets removed at breakpoints via the hide-sm
       helper below, rather than being allowed to wrap. */
    flex-wrap: nowrap;
    gap: 1.1rem;
    align-items: center;
    justify-content: space-between;
    /* padding-block only, so the .wl-wrap's inline (gutter) padding stays
       intact. The old `padding: .5rem 0` shorthand was zeroing out the inline
       padding, which is why the dark bar touched the screen edges on mobile. */
    padding-block: .5rem;
}
/* Utility-bar visibility helpers. -hide-sm is the desktop default (visible)
   that drops off on mobile; -only-sm is the mirror (hidden on desktop, shown
   on mobile) used for mobile-only stand-ins like the Contact Us link that
   replaces the missing phone number. */
.wl-util-hide-sm { }
.wl-util-only-sm { display: none; }
/* Below 500px show only the banner text — the nav links (Contact Us, My
   Account, Log out) are hidden to avoid crowding a narrow screen. */
@media (max-width: 499px) {
    .wl-util-in > .wl-util-set:last-child { display: none; }
    .wl-util-in { justify-content: center; }
}
.wl-util-set { display: flex; gap: 1.1rem; flex-wrap: nowrap; align-items: center; white-space: nowrap; }
.wl-pill { background: var(--wl-brass); color: #fff; padding: .14rem .5rem; }

/* ==========================================================================
   6. Header
   ========================================================================== */

.wl-hdr {
    position: sticky;
    top: 0;
    z-index: 900;
    background: var(--wl-chalk);
    border-bottom: 1px solid var(--wl-rule);
    transition: box-shadow .25s ease;
}
.wl-hdr.scrolled { box-shadow: 0 1px 12px rgba(21,24,26,.09); }

.wl-hdr-top {
    display: grid;
    grid-template-columns: auto minmax(0, 1fr) auto;
    gap: clamp(1rem, 3vw, 2.5rem);
    align-items: center;
    /* padding-block only — inline padding comes from .wl-wrap so the logo and
       icons breathe off the viewport edge on mobile. */
    padding-block: .85rem;
}

.wl-mark { display: block; line-height: 1; }
.wl-mark img { display: block; width: 260px; max-width: 100%; height: auto; }
@media (max-width: 1200px) { .wl-mark img { width: 210px; } }

/* The large search box. Deliberately the widest thing in the header — a
   wholesale buyer arrives knowing a stock code far more often than they
   arrive wanting to browse. */
.wl-search { position: relative; display: flex; }
.wl-search input {
    width: 100%;
    padding: .78rem 1rem .78rem 2.6rem;
    border: 1px solid var(--wl-rule);
    background: var(--wl-paper);
    font-size: 14.5px;
}
.wl-search input:focus { border-color: var(--wl-ink); outline: none; }
.wl-search-ico {
    position: absolute;
    left: .95rem;
    top: 50%;
    transform: translateY(-50%);
    color: var(--wl-stone);
    font-size: 14px;
    pointer-events: none;
}

/* Type-ahead panel, anchored to whichever search input is in play. */
.wl-suggest {
    position: absolute;
    top: calc(100% + 4px);
    left: 0;
    right: 0;
    background: var(--wl-paper);
    border: 1px solid var(--wl-ink);
    box-shadow: 0 12px 28px rgba(21,24,26,.14);
    z-index: 950;
    max-height: 460px;
    overflow-y: auto;
    display: none;
}
.wl-suggest.open { display: block; }
.wl-suggest-item {
    display: flex;
    align-items: center;
    gap: .85rem;
    padding: .6rem .8rem;
    border-bottom: 1px solid var(--wl-rule);
    color: var(--wl-ink);
}
.wl-suggest-item:last-child { border-bottom: 0; }
.wl-suggest-item:hover, .wl-suggest-item.active { background: var(--wl-plaster); color: var(--wl-ink); }
.wl-suggest-thumb {
    width: 44px; height: 44px; flex: 0 0 44px;
    display: flex; align-items: center; justify-content: center;
    background: var(--wl-paper); border: 1px solid var(--wl-rule);
}
.wl-suggest-thumb img { max-width: 38px; max-height: 38px; object-fit: contain; }
.wl-suggest-info { flex: 1; min-width: 0; }
.wl-suggest-name { font-size: 14px; font-weight: 500; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.wl-suggest-price { font-family: var(--wl-body); font-size: 13px; font-weight: 600; flex-shrink: 0; }
.wl-suggest-all {
    display: block;
    text-align: center;
    padding: .7rem;
    font-family: var(--wl-body);
    font-size: 11px;
    letter-spacing: .08em;
    text-transform: uppercase;
    color: var(--wl-brass);
    background: var(--wl-plaster);
}
.wl-suggest-empty { padding: 1rem .8rem; font-size: 14px; color: var(--wl-stone); }

.wl-hdr-acts { display: flex; align-items: center; gap: .35rem; }
.wl-icon {
    display: flex; align-items: center; justify-content: center;
    width: 38px; height: 38px;
    color: var(--wl-ink);
    position: relative;
    /* Kill the 300ms tap delay some mobile browsers add on links, and give a
       visible active-state so a tap lands with feedback before the drawer
       animation kicks in. Without this the burger felt unresponsive — users
       tapped it repeatedly wondering if the tap had registered. */
    touch-action: manipulation;
    -webkit-tap-highlight-color: transparent;
    transition: background .1s ease;
}
.wl-icon:hover { background: rgba(21,24,26,.06); color: var(--wl-ink); }
.wl-icon:active { background: var(--wl-ink); color: var(--wl-chalk); }
.wl-icon i { font-size: 17px; }
.wl-cart-badge {
    position: absolute; top: 1px; right: 1px;
    background: var(--wl-brass); color: #fff;
    font-family: var(--wl-body); font-size: 9.5px; font-weight: 600;
    min-width: 17px; height: 17px;
    display: flex; align-items: center; justify-content: center;
    padding: 0 4px; line-height: 1;
}
.wl-cart-badge:empty { display: none; }

/* --- Category nav row ---------------------------------------------------- */

.wl-hdr-nav {
    display: flex;
    gap: 1.5rem;
    padding-block: 0 .8rem;
    font-size: 14px;
    flex-wrap: wrap;
    align-items: center;
}
.wl-nav-item { position: relative; }
.wl-nav-link {
    display: inline-block;
    padding-block: .2rem;
    border-bottom: 1.5px solid transparent;
    color: var(--wl-ink);
}
.wl-nav-item:hover > .wl-nav-link,
.wl-nav-link:hover { border-bottom-color: var(--wl-brass); color: var(--wl-ink); }
/* The count is the point of the row: it tells a buyer how deep a category is
   before they spend a click finding out. */
.wl-nav-link .wl-code { margin-left: .3rem; font-size: 11px; }
.wl-nav-link.is-sale { color: var(--wl-sale); font-weight: 600; }
.wl-nav-link.is-sale:hover { border-bottom-color: var(--wl-sale); }
.wl-nav-link.is-new { color: var(--wl-brass); font-weight: 600; }
/* My Lists nav item — brass accent so it reads as a personal / saved
   affordance (matches the "Save to list" link on product cards). */
.wl-nav-link.is-lists { color: var(--wl-brass); font-weight: 600; }
.wl-nav-link.is-lists:hover { border-bottom-color: var(--wl-brass); }

/* Hover panel of subcategories. Sits flush under the nav row and inherits the
   header's hard-edged, ruled look rather than the old rounded card. */
.wl-nav-drop {
    position: absolute;
    top: 100%;
    left: -.9rem;
    min-width: 250px;
    background: var(--wl-paper);
    border: 1px solid var(--wl-ink);
    box-shadow: 0 14px 30px rgba(21,24,26,.15);
    padding: .5rem 0;
    opacity: 0;
    visibility: hidden;
    transform: translateY(5px);
    transition: opacity .18s, visibility .18s, transform .18s;
    z-index: 940;
}
/* A gap between the link and the panel would drop the hover; this pad bridges
   the nav row's bottom padding. */
.wl-nav-item::after {
    content: '';
    position: absolute;
    top: 100%; left: 0; right: 0;
    height: .8rem;
}
.wl-nav-item:hover .wl-nav-drop {
    opacity: 1;
    visibility: visible;
    transform: translateY(0);
}
.wl-nav-drop a {
    display: flex;
    justify-content: space-between;
    gap: 1rem;
    padding: .45rem 1.1rem;
    font-size: 13.5px;
    color: var(--wl-body-ink);
}
.wl-nav-drop a:hover { background: var(--wl-plaster); color: var(--wl-ink); }
.wl-nav-drop .wl-nav-drop-all {
    font-family: var(--wl-body);
    font-size: 10.5px;
    letter-spacing: .1em;
    text-transform: uppercase;
    color: var(--wl-brass);
    border-bottom: 1px solid var(--wl-rule);
    padding-bottom: .55rem;
    margin-bottom: .35rem;
}

/* Two-column panel for categories with a long child list. */
.wl-nav-drop-2col { min-width: 480px; }
.wl-nav-drop-2col .wl-nav-drop-list { columns: 2; column-gap: 0; }
.wl-nav-drop-2col .wl-nav-drop-list a { break-inside: avoid; }

/* ==========================================================================
   7. Account dropdown
   ========================================================================== */

.wl-icon-wrap { position: relative; }
.wl-acct-drop {
    position: absolute;
    top: 100%; right: 0;
    min-width: 190px;
    background: var(--wl-paper);
    border: 1px solid var(--wl-ink);
    box-shadow: 0 14px 30px rgba(21,24,26,.15);
    padding: .4rem 0;
    opacity: 0; visibility: hidden; transform: translateY(5px);
    transition: opacity .18s, visibility .18s, transform .18s;
    z-index: 940;
}
.wl-icon-wrap:hover .wl-acct-drop { opacity: 1; visibility: visible; transform: translateY(0); }
.wl-acct-drop a { display: block; padding: .5rem 1.1rem; font-size: 13.5px; color: var(--wl-body-ink); }
.wl-acct-drop a:hover { background: var(--wl-plaster); color: var(--wl-ink); }

/* ==========================================================================
   8. Announcement bar
   ========================================================================== */

.announce-bar {
    position: relative;
    background: var(--wl-ink);
    color: #fff;
    text-align: center;
    padding: .5rem 2.5rem;
    font-family: var(--wl-body);
    font-size: 11.5px;
    letter-spacing: .06em;
}
.announce-bar a { color: inherit; text-decoration: underline; }
.announce-bar .announce-close {
    position: absolute; right: 1rem; top: 50%; transform: translateY(-50%);
    background: none; border: none; color: rgba(255,255,255,.6);
    font-size: 16px; cursor: pointer; padding: 2px 6px;
}
.announce-bar .announce-close:hover { color: #fff; }

/* ==========================================================================
   9. Hero / thesis panel
   ========================================================================== */

/* Copy block above the staged banner: eyebrow, headline, lede and actions on
   the left; the founding date as a single standing credential on the right. */
.wl-hero {
    /* Tighter than the mockup's 2.2–3.6rem — the headline sits above a full
       bleed staged image, so the copy block does not need to breathe as a
       standalone panel would. */
    padding: clamp(1.2rem, 2.2vw, 1.8rem) 0 clamp(1rem, 1.8vw, 1.4rem);
    border-bottom: 1px solid var(--wl-rule);
}
.wl-hero-grid {
    display: grid;
    grid-template-columns: minmax(0, 1.5fr) minmax(0, 1fr);
    gap: clamp(1.5rem, 4vw, 4rem);
    align-items: center;
}
.wl-hero h1 {
    font-family: var(--wl-display);
    font-weight: 700;
    font-stretch: 118%;
    letter-spacing: -.02em;
    line-height: 1;
    font-size: clamp(2.1rem, 4.8vw, 3.7rem);
    max-width: 16ch;
    margin: .45rem 0 0;
}
.wl-hero h1 em { font-style: normal; color: var(--wl-brass); }
.wl-hero p { margin-top: 1.1rem; max-width: 52ch; font-size: 16px; color: var(--wl-body-ink); }
.wl-hero-cta { display: flex; flex-wrap: wrap; gap: .6rem; margin-top: 1.5rem; }

.wl-est { border-left: 2px solid var(--wl-brass); padding-left: 1.1rem; }
.wl-est-num {
    font-family: var(--wl-display);
    font-weight: 700;
    font-stretch: 122%;
    font-size: clamp(2.6rem, 5vw, 3.6rem);
    line-height: .85;
    letter-spacing: -.02em;
    color: var(--wl-ink);
}
.wl-est-txt { margin-top: .7rem; font-size: 13.5px; color: var(--wl-body-ink); max-width: 32ch; }

/* Staged photograph beneath the editorial hero. Was an inline style on the
   section; it is a named rule now that three other layouts sit alongside it. */
.wl-hero-staged-sec { padding-bottom: clamp(2rem, 4vw, 3rem); }

/* ==========================================================================
   9b. Scheduled hero layouts
   --------------------------------------------------------------------------
   One rule block per LAYOUT value in WEB_HERO. The layout owns its own type,
   spacing and colour so that staff choose a shape rather than a font and a
   hex value — see app/Services/HeroResolver.php.

   Shared: every layout reuses .wl-eyebrow, h1 sizing off .wl-hero h1, and the
   button pair from partials/hero/ctas.blade.php.
   ========================================================================== */

/* Staff-only banner shown above a ?hero=<id> preview, so nobody mistakes a
   preview for what customers are seeing. */
.wl-hero-preview {
    background: var(--wl-low);
    color: #fff;
    font-size: 12px;
    letter-spacing: .04em;
    text-align: center;
    padding: .55rem 1rem;
}

/* Filled light button, for a hero sitting on a photograph or colour band.
   .wl-btn-light is already the outline-on-dark variant, so this is its
   solid counterpart rather than a replacement. */
.wl-btn-invert { background: var(--wl-chalk); color: var(--wl-ink); border-color: var(--wl-chalk); }
.wl-btn-invert:hover { background: var(--wl-brass-lit); border-color: var(--wl-brass-lit); color: var(--wl-ink); }

/* ---------- split: photo one side, copy the other ---------- */
.wl-hero-split { border-bottom: 1px solid var(--wl-rule); }
.wl-hero-split-grid {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    gap: clamp(1.5rem, 4vw, 3.5rem);
    align-items: center;
    padding: clamp(1.4rem, 3vw, 2.6rem) 0;
}
/* rtl puts the photograph on the right by reordering, not by swapping the
   markup — the copy stays first in the document for screen readers. */
.wl-hero-split--rtl .wl-hero-split-media { order: 2; }
/* No image yet: the copy runs the full width rather than leaving half the
   row empty, so a hero saved before its photo is ready still looks intended. */
.wl-hero-split.is-textonly .wl-hero-split-grid { grid-template-columns: minmax(0, 1fr); }
.wl-hero-split-media {
    background: var(--wl-plaster);
    border: 1px solid var(--wl-rule);
    aspect-ratio: 4 / 3;
    overflow: hidden;
}
.wl-hero-split-media img { width: 100%; height: 100%; object-fit: cover; display: block; }
.wl-hero-split-copy h1 {
    font-family: var(--wl-display);
    font-weight: 700; font-stretch: 118%;
    letter-spacing: -.02em; line-height: 1;
    font-size: clamp(1.9rem, 4.2vw, 3.2rem);
    max-width: 15ch;
    margin: .45rem 0 0;
}
.wl-hero-split-copy h1 em { font-style: normal; color: var(--wl-brass); }
.wl-hero-split-copy p { margin-top: 1rem; max-width: 46ch; font-size: 16px; color: var(--wl-body-ink); }

/* ---------- overlay: copy on a scrim over one full-bleed image ---------- */
.wl-hero-overlay { position: relative; isolation: isolate; }
.wl-hero-overlay-img {
    display: block; width: 100%;
    height: clamp(320px, 46vw, 560px);
    object-fit: cover;
}
/* A gradient rather than a flat panel, so the photograph still reads through
   the top of it. Bottom stop is dark enough that chalk text clears AA over
   any image staff upload. */
.wl-hero-overlay-scrim {
    position: absolute; inset: 0;
    background: linear-gradient(to top, rgba(25,30,26,.88) 0%, rgba(25,30,26,.72) 34%, rgba(25,30,26,.12) 72%, rgba(25,30,26,0) 100%);
}
.wl-hero-overlay-in {
    position: absolute; inset: auto 0 0 0;
    padding-bottom: clamp(1.6rem, 4vw, 3rem);
}
.wl-hero-overlay-copy { max-width: 46ch; }
.wl-hero-overlay-copy .wl-eyebrow { color: var(--wl-brass-lit); }
.wl-hero-overlay-copy h1 {
    font-family: var(--wl-display);
    font-weight: 700; font-stretch: 118%;
    letter-spacing: -.02em; line-height: 1;
    font-size: clamp(1.9rem, 4.4vw, 3.3rem);
    color: var(--wl-chalk);
    margin: .45rem 0 0;
}
.wl-hero-overlay-copy h1 em { font-style: normal; color: var(--wl-brass-lit); }
.wl-hero-overlay-copy p { margin-top: .9rem; font-size: 16px; color: rgba(247,245,240,.86); }

/* ---------- poster: a solid band, type only ---------- */
.wl-hero-poster--verdigris { background: var(--wl-bluestone); --poster-ink: var(--wl-chalk); --poster-accent: var(--wl-brass-lit); }
.wl-hero-poster--ink       { background: var(--wl-ink);       --poster-ink: var(--wl-chalk); --poster-accent: var(--wl-brass-lit); }
/* The lit brass, not --wl-brass: chalk on the darker brass is 4.2:1, which
   fails AA for the body line under the headline. Lit brass takes ink text
   instead and clears it comfortably. */
.wl-hero-poster--brass     { background: var(--wl-brass-lit); --poster-ink: var(--wl-ink);   --poster-accent: var(--wl-ink); }
.wl-hero-poster-in {
    padding: clamp(2.2rem, 5.5vw, 4.2rem) 0;
    text-align: center;
}
.wl-hero-poster-in .wl-eyebrow { color: var(--poster-accent); }
.wl-hero-poster-in h1 {
    font-family: var(--wl-display);
    font-weight: 700; font-stretch: 120%;
    letter-spacing: -.022em; line-height: .98;
    font-size: clamp(2.1rem, 5.4vw, 4rem);
    color: var(--poster-ink);
    max-width: 20ch; margin: .5rem auto 0;
}
.wl-hero-poster-in h1 em { font-style: normal; color: var(--poster-accent); }
.wl-hero-poster-in p {
    margin: .9rem auto 0; max-width: 52ch; font-size: 16px;
    color: var(--poster-ink); opacity: .86;
}
.wl-hero-poster-in .wl-hero-cta { justify-content: center; }

/* ---------- mosaic: copy beside a tall shot and two squares ---------- */
.wl-hero-mosaic { border-bottom: 1px solid var(--wl-rule); }
.wl-hero-mosaic-grid {
    display: grid;
    grid-template-columns: minmax(0, 5fr) minmax(0, 7fr);
    gap: clamp(1.5rem, 4vw, 3.5rem);
    align-items: center;
    padding: clamp(1.4rem, 3vw, 2.6rem) 0;
}
.wl-hero-mosaic-copy h1 {
    font-family: var(--wl-display);
    font-weight: 700; font-stretch: 118%;
    letter-spacing: -.02em; line-height: 1;
    font-size: clamp(1.9rem, 4.2vw, 3.2rem);
    max-width: 14ch;
    margin: .45rem 0 0;
}
.wl-hero-mosaic-copy h1 em { font-style: normal; color: var(--wl-brass); }
.wl-hero-mosaic-copy p { margin-top: 1rem; max-width: 44ch; font-size: 16px; color: var(--wl-body-ink); }

/* One tall cell on the left spanning both rows, two squares stacked right. */
.wl-hero-mosaic-media {
    display: grid;
    grid-template-columns: 1fr 1fr;
    grid-template-rows: 1fr 1fr;
    gap: clamp(.6rem, 1.2vw, 1rem);
}
.wl-hero-mosaic-fig {
    margin: 0; overflow: hidden;
    background: var(--wl-plaster);
    border: 1px solid var(--wl-rule);
}
.wl-hero-mosaic-fig img { width: 100%; height: 100%; object-fit: cover; display: block; }
.wl-hero-mosaic-fig--1 { grid-row: span 2; aspect-ratio: 3 / 4.35; }
.wl-hero-mosaic-fig--2,
.wl-hero-mosaic-fig--3 { aspect-ratio: 1 / 1; }
/* Two images: the square takes the full right column rather than leaving a
   hole where the third would have been. */
.wl-hero-mosaic-media.is-two .wl-hero-mosaic-fig--2 { grid-row: span 2; aspect-ratio: 3 / 4.35; }

@media (max-width: 860px) {
    .wl-hero-split-grid { grid-template-columns: minmax(0, 1fr); }
    /* Photograph back above the copy on a phone whichever side it was on. */
    .wl-hero-split--rtl .wl-hero-split-media { order: 0; }
    .wl-hero-overlay-img { height: clamp(300px, 78vw, 420px); }
    .wl-hero-mosaic-grid { grid-template-columns: minmax(0, 1fr); }
}

/* ==========================================================================
   Signed-in dashboard band
   --------------------------------------------------------------------------
   Sits where the guest hero would. A greeting, then up to three status
   panels (draft cart / open order / last invoiced), then the personalised
   product rows below use the standard wl-sec + wl-grid pattern.
   ========================================================================== */

.wl-dash {
    padding: clamp(1.4rem, 2.5vw, 2rem) 0 clamp(1.2rem, 2vw, 1.6rem);
    border-bottom: 1px solid var(--wl-rule);
}
.wl-dash-name {
    font-family: var(--wl-display);
    font-weight: 700;
    font-stretch: 118%;
    letter-spacing: -.02em;
    font-size: clamp(1.6rem, 3vw, 2.4rem);
    line-height: 1;
    margin: .35rem 0 0;
    color: var(--wl-ink);
}
.wl-dash-panels {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
    gap: 1px;
    margin-top: 1.4rem;
    background: var(--wl-rule);
    border: 1px solid var(--wl-rule);
}
.wl-dash-panel {
    display: flex;
    flex-direction: column;
    gap: .35rem;
    padding: 1.1rem 1.2rem;
    background: var(--wl-paper);
    color: var(--wl-ink);
    text-decoration: none;
    transition: background .16s;
}
.wl-dash-panel:hover { background: var(--wl-plaster); color: var(--wl-ink); text-decoration: none; }
.wl-dash-fig {
    font-family: var(--wl-display);
    font-weight: 700;
    font-stretch: 116%;
    font-size: 1.75rem;
    line-height: 1.05;
    letter-spacing: -.015em;
    margin: 0;
}
.wl-dash-fig span {
    font-family: var(--wl-body);
    font-weight: 400;
    font-size: .95rem;
    color: var(--wl-stone);
    margin-left: .3rem;
    letter-spacing: 0;
}
.wl-dash-sub {
    font-family: var(--wl-body);
    font-size: 11px;
    letter-spacing: .05em;
    color: var(--wl-stone);
    margin: 0;
}

@media (max-width: 640px) {
    /* One column, still hairline-separated. */
    .wl-dash-panels { grid-template-columns: 1fr; }
}

/* ==========================================================================
   Cart lists (/lists, /lists/{id}, shared view, picker)
   ========================================================================== */

/* Index page — create form + grid of existing lists. */
.wl-lists-create {
    margin-top: 1.4rem;
    padding: 1.1rem 1.2rem;
    border: 1px solid var(--wl-rule);
    background: var(--wl-paper);
}
.wl-lists-create label {
    display: block;
    margin-bottom: .55rem;
}
.wl-lists-create-row {
    display: flex;
    gap: .5rem;
    flex-wrap: wrap;
}
.wl-lists-create-row input {
    flex: 1;
    min-width: 240px;
}
.wl-lists-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
    gap: 1px;
    background: var(--wl-rule);
    border: 1px solid var(--wl-rule);
    margin-top: 2rem;
}
.wl-lists-card {
    background: var(--wl-paper);
    padding: 1.1rem 1.2rem;
    color: var(--wl-ink);
    text-decoration: none;
    display: block;
    transition: background .16s;
}
.wl-lists-card:hover { background: var(--wl-plaster); color: var(--wl-ink); text-decoration: none; }
.wl-lists-card h3 {
    font-family: var(--wl-display);
    font-weight: 700;
    font-stretch: 112%;
    font-size: 1.15rem;
    margin: .3rem 0 0;
    color: var(--wl-ink);
}
.wl-lists-card:hover h3 { color: var(--wl-brass); }

/* Show page — actions row + line items. */
.wl-list-actions {
    display: flex;
    flex-wrap: wrap;
    gap: .55rem;
    align-items: flex-start;
    margin-top: 1.4rem;
    padding-bottom: 1.4rem;
    border-bottom: 1px solid var(--wl-rule);
}
/* <details> replaces would-be modals for rename / email / share URL.
   Server-rendered, no JS required, and the browser gives us open/close for free. */
.wl-list-detail summary { list-style: none; cursor: pointer; }
.wl-list-detail summary::-webkit-details-marker { display: none; }
.wl-list-detail[open] summary { background: var(--wl-ink); color: var(--wl-chalk); }
.wl-list-email-form,
.wl-list-share-panel {
    margin-top: .6rem;
    padding: 1rem 1.1rem;
    background: var(--wl-paper);
    border: 1px solid var(--wl-rule);
    max-width: 460px;
}
.wl-list-email-form label {
    display: block;
    margin-top: .6rem;
    margin-bottom: .35rem;
}
.wl-list-email-form label:first-child { margin-top: 0; }
.wl-list-email-form input,
.wl-list-email-form textarea {
    width: 100%;
    margin-bottom: .35rem;
}
.wl-list-email-form button { margin-top: .5rem; }
.wl-list-share-url {
    width: 100%;
    font-family: var(--wl-body);
    font-size: 12px;
    padding: .5rem .6rem;
    background: var(--wl-plaster);
}

.wl-list-items {
    margin-top: 1.6rem;
    display: grid;
    gap: 1px;
    background: var(--wl-rule);
    border: 1px solid var(--wl-rule);
}
.wl-list-item {
    background: var(--wl-paper);
    display: grid;
    grid-template-columns: 80px minmax(0, 1fr) auto auto;
    gap: 1rem;
    align-items: center;
    padding: .8rem 1rem;
}
.wl-list-item-thumb {
    width: 80px; height: 80px;
    display: flex; align-items: center; justify-content: center;
    background: var(--wl-paper); border: 1px solid var(--wl-rule);
}
.wl-list-item-thumb img { max-width: 68px; max-height: 68px; object-fit: contain; }
.wl-list-item-body h3 {
    font-family: var(--wl-body);
    font-size: 14.5px;
    font-weight: 500;
    margin: .15rem 0 0;
}
.wl-list-item-body h3 a { color: var(--wl-ink); text-decoration: none; }
.wl-list-item-body h3 a:hover { color: var(--wl-brass); }
.wl-list-item-qty { display: flex; gap: .4rem; align-items: center; }
.wl-list-item-qty label { margin: 0; }
.wl-list-item-qty input { width: 74px; }
.wl-list-item-remove {
    font-family: var(--wl-body);
    font-size: 10.5px;
    letter-spacing: .06em;
    text-transform: uppercase;
    color: var(--wl-stone);
}
.wl-list-item-remove:hover { color: var(--wl-sale); }

@media (max-width: 640px) {
    .wl-list-item {
        grid-template-columns: 60px 1fr;
        grid-template-areas: "thumb body" "qty qty" "remove remove";
        row-gap: .6rem;
    }
    .wl-list-item-thumb { grid-area: thumb; width: 60px; height: 60px; }
    .wl-list-item-body { grid-area: body; }
    .wl-list-item-qty { grid-area: qty; }
    .wl-list-item-remove { grid-area: remove; }
}

/* Picker — Save-to-list from a product card. */
.wl-list-picker-existing {
    display: grid;
    gap: 1px;
    background: var(--wl-rule);
    border: 1px solid var(--wl-rule);
    margin-top: .9rem;
}
.wl-list-picker-btn {
    background: var(--wl-paper);
    border: none;
    padding: .9rem 1.1rem;
    text-align: left;
    display: flex;
    justify-content: space-between;
    align-items: center;
    gap: 1rem;
    cursor: pointer;
    color: var(--wl-ink);
    font: inherit;
    transition: background .16s;
}
.wl-list-picker-btn:hover { background: var(--wl-plaster); }
.wl-list-picker-name { font-weight: 500; }
.wl-list-picker-new {
    margin-top: .9rem;
    padding: 1rem 1.1rem;
    background: var(--wl-paper);
    border: 1px solid var(--wl-rule);
}
.wl-list-picker-new label { display: block; margin-bottom: .4rem; }
.wl-list-picker-new input { width: 100%; margin-bottom: .55rem; }

/* "Save to list" link inside a product card foot. */
.pc-savelist { color: var(--wl-brass); cursor: pointer; }
.pc-savelist:hover { color: var(--wl-ink); }

/* ==========================================================================
   Save-to-list modal
   --------------------------------------------------------------------------
   Opens over the current page when a customer clicks "Save to list" on any
   product card or details page. Kept native — no external library, no jQuery
   dependency, no aria-heavy dialog polyfill. The picker page still works
   with JS off, so the modal is progressive enhancement rather than a
   requirement.
   ========================================================================== */

.wl-modal {
    position: fixed; inset: 0;
    z-index: 9998;
    display: flex; align-items: center; justify-content: center;
    padding: 1rem;
}
.wl-modal[hidden] { display: none; }
.wl-modal-backdrop {
    position: absolute; inset: 0;
    background: rgba(21,24,26,.45);
    cursor: pointer;
}
.wl-modal-panel {
    position: relative;
    background: var(--wl-paper);
    border: 1px solid var(--wl-ink);
    box-shadow: 0 20px 50px rgba(21,24,26,.25);
    max-width: 480px;
    width: 100%;
    padding: 1.6rem 1.6rem 1.4rem;
    max-height: calc(100vh - 2rem);
    overflow-y: auto;
}
.wl-modal-close {
    position: absolute; top: .55rem; right: .75rem;
    background: none; border: none;
    font-size: 24px; color: var(--wl-stone);
    line-height: 1; padding: .25rem .45rem;
    cursor: pointer;
}
.wl-modal-close:hover { color: var(--wl-ink); }
.wl-modal-title {
    font-family: var(--wl-display);
    font-weight: 700; font-stretch: 116%;
    font-size: 1.4rem; line-height: 1.15;
    letter-spacing: -.015em;
    margin: .3rem 0 0;
    color: var(--wl-ink);
}
.wl-modal-loading { padding: 1.2rem 0; }
.wl-modal-status {
    margin-top: 1rem;
    padding: .55rem .75rem;
    font-family: var(--wl-body);
    font-size: 11.5px;
    letter-spacing: .04em;
    border: 1px solid var(--wl-rule);
}
.wl-modal-status.is-ok    { border-color: var(--wl-good); color: #2E5236; background: #F1F5F1; }
.wl-modal-status.is-error { border-color: var(--wl-sale); color: #7A281C; background: #F8F0EE; }

.wl-modal-lists {
    display: grid; gap: 1px;
    background: var(--wl-rule);
    border: 1px solid var(--wl-rule);
    margin-top: 1rem;
}
.wl-modal-list-btn {
    background: var(--wl-paper);
    border: none;
    padding: .8rem 1rem;
    text-align: left;
    display: flex; justify-content: space-between; align-items: center;
    gap: 1rem;
    font: inherit; color: var(--wl-ink);
    cursor: pointer;
    transition: background .16s;
}
.wl-modal-list-btn:hover:not(:disabled) { background: var(--wl-plaster); }
.wl-modal-list-btn:disabled { opacity: .6; cursor: default; }
/* Recently-added mark so the customer sees which list just took the item. */
.wl-modal-list-btn.is-added {
    background: #F1F5F1;
    box-shadow: inset 3px 0 0 var(--wl-good);
}
.wl-modal-list-name { font-weight: 500; }

.wl-modal-new { margin-top: 1.2rem; }
.wl-modal-new input {
    padding: .55rem .7rem;
    border: 1px solid var(--wl-rule);
    background: var(--wl-paper);
    font-family: var(--wl-body); font-size: 14px;
}
.wl-modal-new input:focus { border-color: var(--wl-ink); outline: none; }

/* "View {list} →" link slotted in right under the button that just took
   the item. Sits inside the .wl-modal-lists grid as its own row, so it
   inherits the hairline separators and reads as a nested action. */
.wl-modal-list-view {
    display: block;
    padding: .55rem 1rem .65rem;
    background: #F1F5F1;
    box-shadow: inset 3px 0 0 var(--wl-good);
    font-family: var(--wl-body);
    font-size: 11px;
    letter-spacing: .06em;
    color: var(--wl-good);
    text-decoration: none;
}
.wl-modal-list-view:hover { background: #E4EEE5; color: var(--wl-good); text-decoration: none; }

/* Post-add "Continue shopping" row. Replaces the new-list form so the
   customer's primary next action is obvious after they've saved. */
.wl-modal-done { margin-top: 1.2rem; }
.wl-modal-done .wl-btn { width: 100%; }

/* Facts strip. Four columns divided by hairline verticals, sitting directly
   below the staged image as a plain statement of what the wholesale offer is
   before any product grids. First column's <dt> aligns flush with the wl-wrap
   gutter, so it sits under the hero headline and above the first product card.
   No horizontal rules top or bottom: the paper panel already reads as a band
   against the chalk page, and the section and the wrap each used to draw their
   own hairline, which stacked into one heavy grey line. Only the verticals
   between the columns are drawn. */
.wl-facts { background: var(--wl-plaster); }
.wl-facts-in {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(210px, 1fr));
    /* margin: 0 auto (not 0) so the wrap stays centred at wide viewports the
       way every other .wl-wrap does — otherwise on a monitor past 1440 the
       facts flush-left while the hero and the product grid stay centred, and
       the first fact reads as inset. */
    margin: 0 auto;
}
.wl-fact {
    padding: 1.3rem 1.4rem;
    border-left: 1px solid var(--wl-rule);
    margin: 0;
}
/* The first column pulls its left padding to zero so its label lines up with
   the wl-wrap gutter, and the last does the same on the right so the row is
   balanced against the wrap edges rather than sitting inset from both. */
.wl-fact:first-child {
    padding-left: 0;
    border-left: 0;
}
.wl-fact:last-child {
    padding-right: 0;
}
/* The term is the loud half of the pair — "Since 1984", "In stock" — and the
   description supports it underneath. That inverts the small-label/large-value
   pattern used elsewhere on the page, deliberately: these read as four short
   claims, not four labelled data points. */
.wl-fact dt {
    font-family: var(--wl-display);
    font-size: clamp(1.3rem, 2.4vw, 1.85rem);
    font-weight: 600;
    font-stretch: 110%;
    letter-spacing: -.012em;
    line-height: 1.06;
    color: var(--wl-ink);
    margin: 0;
}
.wl-fact dd {
    margin: .5rem 0 0;
    font-size: 12.5px;
    line-height: 1.45;
    letter-spacing: .02em;
    max-width: 30ch;
    color: var(--wl-body-ink);
}
@media (max-width: 640px) {
    /* Verticals become horizontals once the columns wrap. */
    .wl-fact { border-left: 0; border-top: 1px solid var(--wl-rule); padding-left: 0; padding-right: 0; }
    .wl-fact:first-child { border-top: 0; padding-top: 0; }
}

/* Staged room photograph beneath the thesis. */
.wl-staged {
    position: relative;
    border: 1px solid var(--wl-rule);
    background: #DFDBCE;
    aspect-ratio: 21 / 9;
    min-height: 280px;
    overflow: hidden;
}
.wl-staged img { width: 100%; height: 100%; object-fit: cover; display: block; }
.wl-staged-ph {
    position: absolute; inset: 0;
    display: grid; place-items: center;
    font-family: var(--wl-body);
    font-size: 11px; letter-spacing: .12em; text-transform: uppercase;
    color: rgba(21,24,26,.34);
    text-align: center; padding: 1rem;
}

/* ==========================================================================
   10. Category bar
   ========================================================================== */

.wl-catbar {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(170px, 1fr));
    gap: 1px;
    background: var(--wl-rule);
    border: 1px solid var(--wl-rule);
    margin-bottom: 1.4rem;
}
.wl-catbar a {
    background: var(--wl-paper);
    padding: .95rem 1rem;
    color: var(--wl-ink);
    transition: background .16s, color .16s;
}
.wl-catbar a:hover { background: var(--wl-bluestone); color: var(--wl-chalk); }
.wl-catbar a:hover .wl-code { color: var(--wl-brass-lit); }
.wl-catbar h3 {
    font-family: var(--wl-display);
    font-weight: 700;
    font-stretch: 110%;
    font-size: 1.1rem;
    margin: .25rem 0 0;
    color: inherit;
}

/* Ranges / categories band. A white section ruled off from the chalk page,
   with its heading stacked above a hairline grid of cards. The band is
   plaster, not paper, so the cards inside it still read as white panels. */
.wl-coll {
    background: var(--wl-plaster);
    border-block: 1px solid var(--wl-rule);
}
.wl-coll-head { padding: clamp(2.4rem, 5vw, 3.6rem) 0 0; }
.wl-coll-head .wl-h2 { margin-top: .45rem; max-width: 24ch; }
.wl-coll-head p.wl-lede { margin-top: .7rem; max-width: 56ch; font-size: 15px; }
.wl-coll-foot { padding-bottom: clamp(2.4rem, 5vw, 3.8rem); }

.wl-coll-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
    gap: 1px;
    background: var(--wl-rule);
    border-top: 1px solid var(--wl-rule);
    margin-top: 1.4rem;
}
.wl-coll-card {
    background: var(--wl-paper);
    padding: 1.4rem;
    display: flex;
    flex-direction: column;
    color: var(--wl-ink);
}
.wl-coll-card h3 {
    font-family: var(--wl-display);
    font-weight: 700;
    font-stretch: 112%;
    font-size: 1.25rem;
    letter-spacing: -.01em;
    margin: .15rem 0 0;
}
.wl-coll-media {
    margin-top: .9rem;
    border: 1px solid var(--wl-rule);
    overflow: hidden;
}
.wl-coll-media img {
    display: block;
    width: 100%;
    aspect-ratio: 4 / 3;
    object-fit: cover;
    transition: transform .5s ease;
}
.wl-coll-card:hover .wl-coll-media img { transform: scale(1.04); }
.wl-coll-card:hover h3 { color: var(--wl-brass); }
.wl-coll-spec {
    display: flex; flex-wrap: wrap; gap: 1.1rem;
    margin-top: .85rem;
    font-family: var(--wl-body); font-size: 11px; color: var(--wl-stone);
}
.wl-coll-spec b { color: var(--wl-ink); font-weight: 500; }
/* The button is a span inside the card's own anchor, so it has to take its
   hover state from the card rather than from itself. */
.wl-coll-card .wl-btn { margin-top: auto; align-self: flex-start; }
.wl-coll-card:hover .wl-btn { background: var(--wl-ink); color: var(--wl-chalk); }
.wl-coll-card .wl-coll-media + .wl-btn { margin-top: 1rem; }

/* ==========================================================================
   11. Product card
   ========================================================================== */

.wl-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
    /* Chalk gaps on both axes so cards breathe apart rather than reading as
       a solid slab. Column gap is smaller than row gap so the grid still
       feels like a grid — bigger horizontal air would break the columns
       into visually isolated cards. */
    column-gap: .75rem;
    row-gap: 1.5rem;
    background: transparent;
    border: 0;
}

.product-card {
    background: var(--wl-paper);
    /* Each card carries its own full border now. Column-gap on the grid
       provides the horizontal breathing room so no more negative-margin
       overlap trick is needed. */
    border: 1px solid var(--wl-rule);
    display: flex;
    flex-direction: column;
    /* The inherited card floated at a fixed 350px. The grid owns width now. */
    float: none;
    width: auto;
    margin: 0;
    position: relative;
    /* Native browser lazy-render for off-screen cards. On a sale page with
       500+ items the browser was laying out and painting every card at load
       time; content-visibility:auto lets it skip both for anything outside
       the viewport (and near-viewport) and reclaim on scroll. contain-
       intrinsic-size gives the layout engine a placeholder box so the scroll
       bar doesn't jump when cards resolve. */
    content-visibility: auto;
    contain-intrinsic-size: 320px 460px;
}
.product-card .thumb-wrap {
    width: auto;
    aspect-ratio: 1 / 1;
    height: auto;
    background: var(--wl-paper);
    display: flex; justify-content: center; align-items: center;
    position: relative;
    overflow: hidden;
}
.product-card .thumb-wrap > a { display: flex; align-items: center; justify-content: center; width: 100%; height: 100%; }
.product-card .thumb-wrap img { max-width: 86%; max-height: 86%; width: auto; height: auto; object-fit: contain; }

.pc-badge {
    position: absolute; top: .5rem; left: .5rem; z-index: 2;
    font-family: var(--wl-body);
    font-size: 9px; font-weight: 500; letter-spacing: .1em; text-transform: uppercase;
    padding: .18rem .42rem; border-radius: 0;
    background: var(--wl-ink); color: var(--wl-chalk);
}
.pc-badge-pre  { background: var(--wl-bluestone); }
.pc-badge-new  { background: var(--wl-brass); }
.pc-badge-sale { background: var(--wl-sale); }

.product-card .summary {
    padding: .8rem .85rem .95rem;
    display: flex; flex-direction: column; flex: 1;
    text-align: left;
}
.product-card .product-code {
    display: block;
    font-family: var(--wl-body);
    font-size: 10.5px; letter-spacing: .05em;
    color: var(--wl-stone);
    opacity: 1;
    margin-bottom: .15rem;
    line-height: 1.3;
    /* Reserve two lines. Codes appended with a category name wrap to two
       lines on one card and not the next; without a floor here the title
       and everything below it slide down on the wrapping card, which is
       what threw the "Log in for pricing" row out of alignment. */
    min-height: 2.6em;
}
.product-card .product-title {
    font-family: var(--wl-body);
    font-size: 14px; font-weight: 500;
    color: var(--wl-ink);
    line-height: 1.28;
    letter-spacing: 0;
    min-height: 2.56em;
    margin: 0 0 .1rem;
}
.product-card a:hover .product-title { color: var(--wl-brass); }

/* Dimensions / carton, in the mono spec idiom. */
.pc-spec {
    margin-top: .6rem;
    border-top: 1px solid var(--wl-rule);
    font-family: var(--wl-body);
    font-size: 10.5px;
    color: var(--wl-stone);
}
.pc-spec div {
    display: flex; justify-content: space-between; gap: .5rem;
    padding: .22rem 0;
    border-bottom: 1px dotted var(--wl-rule);
    /* Reserve two lines. A dimension string like "57.5cm × 57.5cm × 78cm"
       will wrap to a second line inside a narrow card while a shorter one
       ("58cm × 55cm × 78cm") stays on one — that inconsistency pushed the
       Log-in / More rows out of alignment across cards on the same row. */
    min-height: 2.6em;
    align-items: flex-start;
}
.pc-spec div:last-child { border-bottom: 0; }
.pc-spec b { color: var(--wl-ink); font-weight: 500; text-align: right; }

.pc-price-row { margin-top: .7rem; display: flex; align-items: baseline; gap: .4rem; flex-wrap: wrap; }
.product-card .current {
    font-family: var(--wl-display);
    font-size: 1.35rem; font-weight: 700; font-stretch: 110%;
    letter-spacing: -.01em;
    color: var(--wl-ink);
}
.product-card .current.is-sale { color: var(--wl-sale); }
.pc-was { min-height: 1.25em; font-family: var(--wl-body); font-size: 11px; color: var(--wl-stone); }
.pc-was .original { text-decoration: line-through; }
.pc-off { color: var(--wl-sale); margin-left: .3rem; }
.pc-gst { font-family: var(--wl-body); font-size: 10px; color: var(--wl-stone); }

.pc-volume { font-family: var(--wl-body); font-size: 10.5px; color: var(--wl-good); margin-top: .3rem; }
/* Sits BELOW the Add form so cards with a low-stock warning don't push the
   button out of alignment with cards next to them that don't have one. */
.pc-lowstock { font-family: var(--wl-body); font-size: 10.5px; color: var(--wl-low); margin-top: .5rem; }

/* No margin-top:auto here — .pc-foot below already bottom-anchors, and two
   auto margins in the same flex column split the space rather than one taking
   all of it. The button's Y position is whatever the natural flow of the
   preceding rows (title, spec, was, price) makes it, which is now consistent
   because those rows all have reserved heights. */
.pc-add { display: flex; gap: .4rem; padding-top: .7rem; }
.pc-qty {
    flex: 0 0 auto; width: 68px;
    padding: .42rem .4rem;
    border: 1px solid var(--wl-rule); border-radius: 0;
    font-family: var(--wl-body); font-size: 12px;
    background: var(--wl-paper);
}
.pc-add-btn {
    flex: 1;
    padding: .45rem .6rem;
    background: var(--wl-ink); color: var(--wl-chalk);
    border: 1px solid var(--wl-ink); border-radius: 0;
    font-family: var(--wl-body); font-size: 10.5px;
    letter-spacing: .08em; text-transform: uppercase;
    cursor: pointer;
    transition: background .16s, border-color .16s;
}
.pc-add-btn:hover { background: var(--wl-brass); border-color: var(--wl-brass); color: #fff; }

/* Bottom-anchored footer holding the login gate and the "more in category"
   link. margin-top:auto pushes it to the bottom of the summary column, so
   every card in a row ends its footer at the same Y regardless of how much
   spec, price or stock content sits above. Fixed line-heights make sure the
   gate and more-link occupy the same vertical slot even when one of them is
   absent — a placeholder <span> is emitted in place of a missing more-link. */
.pc-foot {
    margin-top: auto;
    padding-top: .7rem;
    border-top: 1px solid var(--wl-rule);
    display: flex;
    flex-direction: column;
    gap: .55rem;
}
.pc-login-note { line-height: 1.2; min-height: 1.2em; }
.pc-login-note a,
.wl-gate {
    font-family: var(--wl-body);
    font-size: 10.5px; letter-spacing: .06em; text-transform: uppercase;
    color: var(--wl-brass);
}
.pc-login-note a:hover, .wl-gate:hover { color: var(--wl-ink); }

.pc-more {
    display: block;
    line-height: 1.2;
    min-height: 1.2em;
    font-family: var(--wl-body);
    font-size: 10px;
    letter-spacing: .06em;
    text-transform: uppercase;
    color: var(--wl-stone);
    /* One line, ellipsised on overflow — "More Chairs, Stools and Ottomans"
       wraps to two lines in a narrow card and threw the footer height out of
       sync with cards whose category name fits. Full text is on hover title. */
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    max-width: 100%;
}
.pc-more:hover { color: var(--wl-brass); }
.pc-more-placeholder { visibility: hidden; }

/* Card carousel, retuned to the square grid cell. */
.card-carousel { width: 100%; height: 100%; aspect-ratio: 1 / 1; }
.cc-arrow {
    background: rgba(255,255,255,.9);
    border: 1px solid var(--wl-rule);
    border-radius: 0;
    width: 26px; height: 26px;
    color: var(--wl-ink);
    box-shadow: none;
}
.cc-arrow:hover { background: #fff; border-color: var(--wl-ink); }
.cc-dot { border-radius: 0; width: 5px; height: 5px; background: rgba(21,24,26,.22); }
.cc-dot.active { background: var(--wl-ink); }

/* ==========================================================================
   12. Tables — invoices, orders, cart, credits
   ========================================================================== */

.table {
    background: var(--wl-paper);
    color: var(--wl-ink);
    font-size: 14px;
    margin-bottom: 0;
}
.table thead th {
    font-family: var(--wl-body);
    font-size: 10.5px;
    font-weight: 500;
    letter-spacing: .11em;
    text-transform: uppercase;
    color: var(--wl-stone);
    background: var(--wl-plaster);
    border-bottom: 1px solid var(--wl-rule);
    border-top: 0;
    padding: .7rem .75rem;
    vertical-align: middle;
}
.table td { border-top: 1px solid var(--wl-rule); padding: .7rem .75rem; vertical-align: middle; }
.table-striped tbody tr:nth-of-type(odd) { background: rgba(234,231,222,.5); }
.table-hover tbody tr:hover { background: var(--wl-plaster); }

/* ==========================================================================
   13. Alerts and pagination
   ========================================================================== */

.alert {
    border-radius: 0;
    border: 1px solid var(--wl-rule);
    background: var(--wl-paper);
    color: var(--wl-ink);
    font-size: 14px;
    padding: .8rem 1rem;
}
.alert-success { border-color: var(--wl-good); color: #2E5236; background: #F1F5F1; }
.alert-danger  { border-color: var(--wl-sale); color: #7A281C; background: #F8F0EE; }
.alert-warning { border-color: var(--wl-low);  color: #7A4720; background: #FAF4EE; }
.alert-info    { border-color: var(--wl-brass); color: #6B551F; background: #FAF7F0; }

.page-link {
    border-radius: 0 !important;
    border-color: var(--wl-rule);
    color: var(--wl-ink);
    font-family: var(--wl-body);
    font-size: 12px;
}
.page-item.active .page-link { background: var(--wl-ink); border-color: var(--wl-ink); color: var(--wl-chalk); }

/* ==========================================================================
   14. Footer
   ========================================================================== */

footer.main-footer { background: var(--wl-bluestone); }
footer.main-footer .main-block {
    background: var(--wl-bluestone);
    color: rgba(247,245,240,.72);
    padding: clamp(2.6rem, 5vw, 4rem) 0;
}
footer.main-footer .main-block h5 {
    font-family: var(--wl-body);
    font-size: 10.5px;
    font-weight: 500;
    letter-spacing: .14em;
    text-transform: uppercase;
    color: var(--wl-brass-lit);
    margin: 0 0 1.1rem;
}
footer.main-footer .info p { font-size: 14px; line-height: 1.75; color: rgba(247,245,240,.72); }
footer.main-footer .info a, footer.main-footer .site-links a { color: rgba(247,245,240,.82); font-size: 14px; }
footer.main-footer .info a:hover, footer.main-footer .site-links a:hover { color: var(--wl-brass-lit); }
footer.main-footer .site-links li { margin-bottom: .3rem; }
footer.main-footer .footer-btn {
    display: inline-flex; align-items: center; gap: .4rem;
    padding: .55rem 1rem;
    border: 1px solid rgba(255,255,255,.28); border-radius: 0;
    color: rgba(247,245,240,.9);
    font-family: var(--wl-body); font-size: 10.5px;
    letter-spacing: .09em; text-transform: uppercase;
    background: transparent;
}
footer.main-footer .footer-btn:hover { background: #fff; color: var(--wl-ink); border-color: #fff; }
footer.main-footer .footer-user {
    width: 100%; margin-bottom: .3rem;
    font-family: var(--wl-body); font-size: 10.5px;
    letter-spacing: .09em; text-transform: uppercase;
    color: rgba(247,245,240,.5);
}
footer.main-footer .footer-brand {
    font-family: var(--wl-display); font-weight: 700; font-stretch: 118%;
    font-size: 1.5rem; letter-spacing: -.015em;
    color: var(--wl-chalk); margin-bottom: .2rem;
}

/* ==========================================================================
   15. Mobile drawer
   --------------------------------------------------------------------------
   There is no separate mobile header any more: the one header reflows via
   grid-template-areas, the nav row hides, and the hamburger opens this
   drawer. The full-screen search overlay is gone with it — the header's own
   search field goes full width on a narrow screen, so a second search UI had
   nothing left to do.
   ========================================================================== */

.wl-burger { display: none; }
@media (max-width: 960px) {
    .wl-burger { display: flex; }
    .wl-hdr-nav { display: none; }
}

.mob-overlay {
    display: none;
    position: fixed; inset: 0;
    background: rgba(21,24,26,.45);
    z-index: 9990;
}
.mob-overlay.open { display: block; }

.mob-drawer {
    /* Slides in from the right, matching the side the burger sits on — a
       thumb reaching the burger lands next to the drawer that opens, not
       across the screen from it. */
    position: fixed; top: 0; right: 0;
    width: 320px; max-width: 85vw; height: 100%;
    z-index: 9991; overflow-y: auto;
    transform: translateX(100%);
    /* Faster slide (was .3s) so the drawer feels immediate after the tap.
       ease-out lands quickly then decelerates — reads as "responsive". */
    transition: transform .2s ease-out;
    will-change: transform;
}
.mob-drawer.open { transform: translateX(0); }
/* Loading state after the customer taps a nav link. Dims the drawer's
   contents so it's obviously frozen, and overlays a slim brass progress
   bar at the top that reads as "we're on it". Cleared when the new page
   renders (the whole layout replaces this drawer node). */
.mob-drawer.is-loading > * { opacity: .35; transition: opacity .12s ease; pointer-events: none; }
.mob-drawer.is-loading::before {
    content: '';
    position: sticky; top: 0; left: 0;
    display: block; height: 3px; width: 40%;
    background: var(--wl-brass);
    animation: wl-drawer-progress 1.2s ease-in-out infinite;
    z-index: 2;
    opacity: 1;
}
@keyframes wl-drawer-progress {
    0%   { margin-left: -40%; }
    100% { margin-left: 100%; }
}

.mob-drawer-header {
    display: flex; justify-content: space-between; align-items: center;
    padding: 1.1rem 1.25rem;
}
.mob-close {
    background: none; border: none;
    font-size: 26px; color: var(--wl-stone);
    cursor: pointer; line-height: 1; padding: 0 .25rem;
}
.mob-close:hover { color: var(--wl-ink); }

.mob-search { padding: 1rem 1.25rem .5rem; }
.mob-search-wrap { display: flex; align-items: center; gap: .6rem; padding: .6rem .85rem; }
.mob-search-wrap input {
    flex: 1; border: none; background: transparent; outline: none;
    font-size: 14px; color: var(--wl-ink); padding: 0;
}

.mob-nav { padding: .5rem 0 2rem; }
.mob-section-label { padding: .9rem 1.25rem .4rem; }
.mob-link {
    display: flex; align-items: center; gap: .65rem;
    padding: .8rem 1.25rem;
    text-decoration: none;
}
.mob-link-icon { width: 18px; text-align: center; font-size: 14px; }
.mob-divider { height: 1px; margin: .5rem 1.25rem; }

.mob-accordion-header {
    display: flex; align-items: center; justify-content: space-between;
    padding: .7rem 1.25rem; cursor: pointer;
}
.mob-accordion-header a, .mob-accordion-header span { text-decoration: none; flex: 1; }
.mob-chevron { font-size: 11px; color: var(--wl-stone); transition: transform .25s; }
.mob-accordion-header.open .mob-chevron { transform: rotate(180deg); }
.mob-accordion-body { display: none; padding: 0 1.25rem .5rem 2.25rem; }
.mob-accordion-body.open { display: block; }
.mob-accordion-body a { display: block; padding: .55rem 0; text-decoration: none; }
.mob-accordion-body a:last-child { border-bottom: none; }

.mob-drawer { background: var(--wl-paper); }
.mob-drawer-header { border-bottom: 1px solid var(--wl-rule); }
.mob-section-label {
    font-family: var(--wl-body);
    font-size: 10.5px; letter-spacing: .14em; text-transform: uppercase;
    color: var(--wl-stone); font-weight: 500;
}
.mob-link { font-size: 16px; color: var(--wl-ink); touch-action: manipulation; -webkit-tap-highlight-color: transparent; }
.mob-link:hover { background: var(--wl-plaster); color: var(--wl-ink); }
/* Strong active-state so tapping a drawer option registers visually before
   the destination page loads — the previous silence made the tap feel lost. */
.mob-link:active,
.mob-accordion-body a:active {
    background: var(--wl-ink);
    color: var(--wl-chalk);
}
.mob-link:active .mob-link-icon { color: var(--wl-chalk); }
.mob-link-icon { color: var(--wl-stone); }
.mob-divider { background: var(--wl-rule); }
.mob-accordion-header a, .mob-accordion-header span { font-size: 16px; color: var(--wl-ink); }
/* The category count in the mobile drawer inherits the row's 16px ink style
   otherwise, which reads as part of the name. Restore the mono/stone look and
   push it away from the name so it's visibly a count. */
.mob-accordion-header .wl-code,
.mob-link .wl-code {
    display: inline-block;
    margin-left: .5rem;
    font-family: var(--wl-body);
    font-size: 11px;
    font-weight: 400;
    letter-spacing: .06em;
    color: var(--wl-stone);
    vertical-align: middle;
}
.mob-accordion-body a { font-size: 14.5px; color: var(--wl-body-ink); border-bottom: 1px solid var(--wl-rule); }
.mob-accordion-body a:hover { color: var(--wl-brass); }
.mob-search-wrap {
    background: var(--wl-plaster);
    border: 1px solid var(--wl-rule);
    border-radius: 0;
}
.mob-search-wrap i { color: var(--wl-stone); }

/* ==========================================================================
   16. Responsive
   ========================================================================== */

@media (max-width: 1100px) {
    .wl-hdr-nav { gap: 1.1rem; font-size: 13.5px; }
}

@media (max-width: 960px) {
    .wl-hero-grid { grid-template-columns: 1fr; align-items: start; }
    .wl-hero h1 { max-width: 18ch; }
    /* The logo column must be allowed to shrink. With two `auto` columns the
       grid is sized by the logo's intrinsic width, and the full-width search
       row below inherits that total — which is how the header ended up wider
       than the phone it was on. */
    .wl-hdr-top {
        grid-template-columns: minmax(0, 1fr) auto;
        grid-template-areas: "mark acts" "search search";
        column-gap: .6rem;
        row-gap: .7rem;
    }
    .wl-mark { grid-area: mark; min-width: 0; }
    /* No fixed width here — the img's `width:260px; max-width:100%` default
       means it grows to fill whatever the grid column allocates. At 960px
       the column has plenty of room; on a narrow phone the auto-sized acts
       column shrinks it naturally. Hardcoding it under-sized the logo on
       every mobile width. */
    .wl-search { grid-area: search; min-width: 0; }
    .wl-search input { min-width: 0; }
    .wl-hdr-acts { grid-area: acts; }
    /* min-height has to go with the ratio change: 280px against 4/3 sets a
       373px floor on the width, which is wider than the phone. */
    .wl-staged { aspect-ratio: 4 / 3; min-height: 0; }
    .wl-nav-drop-2col { min-width: 300px; }
    .wl-nav-drop-2col .wl-nav-drop-list { columns: 1; }
}

@media (max-width: 640px) {
    .wl-grid { grid-template-columns: repeat(auto-fill, minmax(155px, 1fr)); }
    .wl-est-num { font-size: 2.4rem; }
    .wl-util-in { justify-content: flex-start; gap: .6rem; }
}

@media (max-width: 460px) {
    /* Logo sizing removed — see 960 breakpoint. The default max-width:100%
       lets the logo fill the whole space the grid column allocates, which is
       twice what the hardcoded 150px was giving it. */
    .wl-hdr-acts { gap: 0; }
    .wl-icon { width: 34px; }
}

@media (prefers-reduced-motion: reduce) {
    * { transition: none !important; animation: none !important; }
}
