/* ---------------------------------------------------------------------------
   Forge — structure and components.
   Parent theme only. Never overridden per client; retint via theme.css tokens.
--------------------------------------------------------------------------- */

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

html { -webkit-text-size-adjust: 100%; }

body {
    margin: 0;
    background: var(--bg);
    color: var(--ink);
    font-family: var(--font-body);
    font-size: var(--step-0);
    line-height: 1.65;
    font-variant-numeric: tabular-nums;
    -webkit-font-smoothing: antialiased;
}

img { max-width: 100%; height: auto; display: block; }
h1, h2, h3 { margin: 0; font-family: var(--font-display); font-weight: 700; letter-spacing: -0.02em; line-height: 1.08; }
p { margin: 0; }
ul { margin: 0; padding: 0; list-style: none; }

a { color: inherit; text-decoration-color: color-mix(in srgb, currentColor 35%, transparent); text-underline-offset: 0.18em; }
a:hover { text-decoration-color: currentColor; }

:focus-visible {
    outline: 2px solid var(--accent);
    outline-offset: 3px;
    border-radius: var(--radius);
}

.shell { width: min(100% - (var(--gutter) * 2), var(--shell)); margin-inline: auto; }

.skip-link {
    position: absolute; left: -9999px; top: 0; z-index: 100;
    background: var(--ink); color: var(--bg);
    padding: 0.75rem 1.25rem; font-family: var(--font-display); font-weight: 600;
}
.skip-link:focus { left: 0.5rem; top: 0.5rem; }

.photo { width: 100%; height: 100%; object-fit: cover; background: var(--ink-soft); }

/* --- The label grammar: origin · producer · year -------------------------- */

.origin {
    display: flex; align-items: center; flex-wrap: wrap;
    gap: 0.55rem;
    font-family: var(--font-display);
    font-size: var(--step--1);
    font-weight: 600;
    letter-spacing: -0.005em;
    color: var(--ink-muted);
}
.origin__place { color: var(--accent); }
.origin__sep { width: 1px; height: 0.85em; background: var(--line); flex: none; }
.origin--hero { margin-bottom: var(--gap-3); }

/* --- Announcement --------------------------------------------------------- */

.announce { background: var(--announce-bg); color: var(--announce-ink); }
.announce__text {
    width: min(100% - (var(--gutter) * 2), var(--shell)); margin-inline: auto;
    padding-block: 0.6rem;
    font-family: var(--font-display); font-size: var(--step--1); font-weight: 500;
    text-align: center;
}

/* --- Masthead ------------------------------------------------------------- */

.masthead {
    position: sticky; top: 0; z-index: 40;
    background: color-mix(in srgb, var(--bg) 88%, transparent);
    backdrop-filter: blur(10px);
    border-bottom: 1px solid var(--line);
}
.masthead__inner {
    display: flex; align-items: center; gap: var(--gap-3);
    min-height: 4.5rem;
}

.wordmark { text-decoration: none; margin-right: auto; }
.wordmark__name {
    font-family: var(--font-display);
    font-size: 1.35rem; font-weight: 800; letter-spacing: -0.045em;
}
.wordmark__name--footer { font-size: var(--step-2); display: block; }

.mainnav__list { display: flex; gap: var(--gap-3); }
.mainnav__link {
    font-family: var(--font-display); font-size: var(--step--1); font-weight: 600;
    text-decoration: none; padding-block: 0.35rem;
    border-bottom: 2px solid transparent;
    transition: border-color var(--fast) var(--ease), color var(--fast) var(--ease);
}
.mainnav__link:hover { color: var(--accent); border-bottom-color: var(--accent); }

.masthead__tools { display: flex; align-items: center; gap: 0.25rem; }

.iconbtn {
    position: relative;
    display: inline-flex; align-items: center; justify-content: center;
    width: 44px; height: 44px;
    color: inherit; background: none; border: 0; cursor: pointer;
    border-radius: var(--radius);
    transition: background-color var(--fast) var(--ease);
}
.iconbtn:hover { background: var(--ink-soft); }
.icon { width: 21px; height: 21px; }

.iconbtn__count {
    position: absolute; top: 6px; right: 4px;
    min-width: 17px; height: 17px; padding: 0 4px;
    display: grid; place-items: center;
    background: var(--accent); color: var(--accent-ink);
    border-radius: 9px;
    font-family: var(--font-display); font-size: 0.66rem; font-weight: 700;
}

.navtoggle { display: none; }

/* --- Buttons -------------------------------------------------------------- */

.btn {
    display: inline-flex; align-items: center; justify-content: center;
    min-height: 44px; padding: 0 1.4rem;
    font-family: var(--font-display); font-size: var(--step--1); font-weight: 600;
    text-decoration: none; cursor: pointer;
    border: 1px solid transparent; border-radius: var(--radius);
    transition: transform var(--fast) var(--ease), background-color var(--fast) var(--ease),
                border-color var(--fast) var(--ease), color var(--fast) var(--ease);
}
.btn:active { transform: translateY(1px); }

.btn--solid { background: var(--accent); color: var(--accent-ink); }
.btn--solid:hover { background: color-mix(in srgb, var(--accent) 86%, var(--ink)); }

.btn--ghost { border-color: var(--line); color: var(--ink); }
.btn--ghost:hover { border-color: var(--ink); }

.btn--quiet {
    width: 100%; background: transparent; border-color: var(--line); color: var(--ink);
}
.btn--quiet:hover { background: var(--accent); border-color: var(--accent); color: var(--accent-ink); }

.textlink {
    display: inline-flex; align-items: center; gap: 0.45rem;
    font-family: var(--font-display); font-size: var(--step--1); font-weight: 600;
    text-decoration: none; color: var(--accent);
}
.textlink .icon { width: 17px; height: 17px; transition: transform var(--fast) var(--ease); }
.textlink:hover .icon { transform: translateX(3px); }
.textlink--strong { font-size: var(--step-0); }

/* --- Hero ----------------------------------------------------------------- */

.hero { padding-block: clamp(2.5rem, 1.5rem + 4vw, 5rem) var(--space-section); }
.hero__inner {
    display: grid; grid-template-columns: 1fr 1fr;
    gap: clamp(2rem, 1rem + 4vw, 4.5rem);
    align-items: center;
}
.hero__title {
    font-size: var(--step-4);
    letter-spacing: -0.045em;
    text-wrap: balance;
}
.hero__lede {
    margin-top: var(--gap-3);
    max-width: 34ch;
    font-size: var(--step-1);
    color: var(--ink-muted);
}
.hero__actions { margin-top: var(--space-component); display: flex; flex-wrap: wrap; gap: var(--gap-2); }

.hero__figure { position: relative; margin: 0; }
.hero__figure .photo { aspect-ratio: 4 / 5; border-radius: var(--radius-lg); }

.hero__plate {
    position: absolute; left: -2rem; bottom: 1.75rem;
    display: grid; gap: 0.15rem;
    padding: 0.85rem 1.25rem;
    background: var(--surface);
    border: 1px solid var(--line);
    border-left-width: 3px; border-left-color: var(--accent);
    box-shadow: var(--shadow-2);
}
.hero__plate-name { font-family: var(--font-display); font-weight: 700; font-size: var(--step-0); }
.hero__plate-meta { font-size: var(--step--1); color: var(--ink-muted); }

/* --- Assurances ----------------------------------------------------------- */

.assurances { border-block: 1px solid var(--line); background: var(--surface); }
.assurances__grid {
    display: grid; grid-template-columns: repeat(4, 1fr);
}
.assurance {
    display: flex; align-items: flex-start; gap: 0.85rem;
    padding: 1.5rem 1.25rem 1.5rem 0;
}
.assurance + .assurance { padding-left: 1.5rem; border-left: 1px solid var(--line); }
.assurance__icon { color: var(--accent); flex: none; margin-top: 0.15rem; }
.assurance__title { font-size: var(--step-0); font-weight: 700; letter-spacing: -0.015em; }
.assurance__note { font-size: var(--step--1); color: var(--ink-muted); line-height: 1.45; }

/* --- Sections ------------------------------------------------------------- */

.section { padding-block: var(--space-section); }

.sechead { margin-bottom: var(--space-component); }
.sechead__title { font-size: var(--step-3); }
.sechead__note { margin-top: 0.5rem; color: var(--ink-muted); max-width: 46ch; }
.sechead--split {
    display: flex; align-items: flex-end; justify-content: space-between;
    gap: var(--gap-3); flex-wrap: wrap;
}

/* --- Categories ----------------------------------------------------------- */

.cats { display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--gap-3); }
.cat__link { display: block; text-decoration: none; }
.cat__media {
    display: block; overflow: hidden; border-radius: var(--radius-lg);
    background: var(--ink-soft);
}
.cat__media .photo {
    aspect-ratio: 4 / 5;
    transition: transform var(--slow) var(--ease);
}
.cat__link:hover .cat__media .photo { transform: scale(1.03); }
.cat__body { display: block; padding-top: 0.9rem; }
.cat__name {
    display: block;
    font-family: var(--font-display); font-size: var(--step-1); font-weight: 700;
    letter-spacing: -0.025em;
}
.cat__meta { display: block; font-size: var(--step--1); color: var(--ink-muted); }

/* --- Product grid --------------------------------------------------------- */

.pgrid { display: grid; grid-template-columns: repeat(4, 1fr); gap: var(--gap-3); }

.pcard {
    display: flex; flex-direction: column;
    background: var(--surface);
    border: 1px solid var(--line);
    border-radius: var(--radius-lg);
    overflow: hidden;
    transition: border-color var(--fast) var(--ease), box-shadow var(--fast) var(--ease);
}
.pcard:hover { border-color: color-mix(in srgb, var(--ink) 30%, var(--line)); box-shadow: var(--shadow-2); }
.pcard__media { display: block; position: relative; background: var(--ink-soft); }
.pcard__media .photo { aspect-ratio: 4 / 5; }

/* Sale badge — sits on the photo, top left. One chip, accent-coloured,
   sentence case; the price row carries the exact numbers. */
.badge--sale {
    position: absolute; top: 0.5rem; left: 0.5rem; z-index: 1;
    padding: 0.25rem 0.5rem;
    background: var(--accent); color: var(--accent-ink);
    font-family: var(--font-display); font-weight: 700; font-size: var(--step--1);
    line-height: 1.2;
    border-radius: var(--radius);
}
.pcard__body { display: flex; flex-direction: column; gap: 0.5rem; padding: 1.1rem; flex: 1; }
.pcard__title { font-size: var(--step-1); letter-spacing: -0.025em; text-wrap: balance; }
.pcard__title a { text-decoration: none; }
.pcard__title a:hover { color: var(--accent); }
.pcard__price { font-family: var(--font-display); font-weight: 700; font-size: var(--step-0); }
.pcard__unit { font-weight: 500; color: var(--ink-muted); }
.pcard__add { margin-top: auto; }

/* --- Story ---------------------------------------------------------------- */

.section--story { background: var(--surface); border-block: 1px solid var(--line); }
.story {
    display: grid; grid-template-columns: 1fr 1fr;
    gap: clamp(2rem, 1rem + 4vw, 4.5rem);
    align-items: center;
}
.story__figure { margin: 0; }
.story__figure .photo { aspect-ratio: 4 / 3; border-radius: var(--radius-lg); }
.story__title { margin-top: var(--gap-2); font-size: var(--step-3); text-wrap: balance; }
.story__text { margin-top: var(--gap-2); color: var(--ink-muted); max-width: 48ch; }
.story__copy .textlink { margin-top: var(--space-component); }

/* --- Footer --------------------------------------------------------------- */

.footer { padding-block: var(--space-section) var(--space-component); }
.footer__top {
    display: grid; grid-template-columns: 1.4fr 1fr 1fr 1.1fr;
    gap: var(--gap-3);
    padding-bottom: var(--space-component);
}
.footer__tagline { margin-top: 0.35rem; color: var(--ink-muted); }
.footer__address { margin-top: var(--gap-2); font-style: normal; color: var(--ink-muted); font-size: var(--step--1); }
.footer__heading {
    font-size: var(--step--1); font-weight: 700; letter-spacing: -0.01em;
    margin-bottom: 0.75rem;
}
.footer__list { display: grid; gap: 0.4rem; font-size: var(--step--1); }
.footer__list a { text-decoration: none; color: var(--ink-muted); }
.footer__list a:hover { color: var(--accent); }
.footer__hours, .footer__direct { font-size: var(--step--1); color: var(--ink-muted); }
.footer__direct { margin-top: var(--gap-2); }

.footer__signup {
    display: grid; grid-template-columns: 1fr 1fr;
    gap: var(--gap-3); align-items: center;
    padding-block: var(--space-component);
    border-block: 1px solid var(--line);
}
.footer__signup-title { font-size: var(--step-2); }
.footer__signup-note { margin-top: 0.35rem; color: var(--ink-muted); }
.signup__label {
    display: block; margin-bottom: 0.5rem;
    font-family: var(--font-display); font-size: var(--step--1); font-weight: 600;
}
.signup__row { display: flex; gap: var(--gap-1); }
.signup__input {
    flex: 1; min-height: 44px; padding: 0 0.9rem;
    background: var(--surface); color: var(--ink);
    border: 1px solid var(--line); border-radius: var(--radius);
    font-family: var(--font-body); font-size: var(--step-0);
}
.signup__input::placeholder { color: var(--ink-muted); }
.signup__input:focus-visible { border-color: var(--accent); }

.footer__legal {
    display: flex; justify-content: space-between; flex-wrap: wrap; gap: var(--gap-2);
    padding-top: var(--space-component);
    font-size: var(--step--1); color: var(--ink-muted);
}
.footer__legal-links { display: flex; gap: var(--gap-3); }
.footer__legal-links a { text-decoration: none; }
.footer__legal-links a:hover { color: var(--accent); }

/* --- Responsive ----------------------------------------------------------- */

@media (max-width: 1080px) {
    .pgrid { grid-template-columns: repeat(2, 1fr); }
    .footer__top { grid-template-columns: repeat(2, 1fr); row-gap: var(--space-component); }
}

@media (max-width: 900px) {
    .hero__inner, .story { grid-template-columns: 1fr; }
    .hero__plate { left: 1.25rem; }
    .hero__figure { order: -1; }
    .story__figure { order: -1; }
    .assurances__grid { grid-template-columns: repeat(2, 1fr); }
    .assurance:nth-child(odd) { padding-left: 0; border-left: 0; }
    .assurance:nth-child(even) { padding-left: 1.5rem; border-left: 1px solid var(--line); }
    .footer__signup { grid-template-columns: 1fr; }
}

@media (max-width: 760px) {
    .mainnav {
        position: absolute; left: 0; right: 0; top: 100%;
        background: var(--bg); border-bottom: 1px solid var(--line);
        padding: var(--gap-2) 1.25rem var(--gap-3);
        display: none;
    }
    .mainnav[data-open="true"] { display: block; }
    .mainnav__list { flex-direction: column; gap: 0; }
    .mainnav__link { display: block; padding-block: 0.7rem; border-bottom: 1px solid var(--line); }
    .navtoggle { display: inline-flex; }
    .cats { grid-template-columns: 1fr; }
    .cat__media .photo { aspect-ratio: 16 / 10; }
}

@media (max-width: 560px) {
    .pgrid { grid-template-columns: 1fr; }
    .assurances__grid { grid-template-columns: 1fr; }
    .assurance { padding: 1rem 0; }
    .assurance:nth-child(even), .assurance:nth-child(odd) { padding-left: 0; border-left: 0; }
    .assurance + .assurance { border-top: 1px solid var(--line); }
    .hero__plate { left: 0.75rem; right: 0.75rem; bottom: 0.75rem; }
    .signup__row { flex-direction: column; }
    .footer__legal { flex-direction: column; }
}

/* --- Motion: one orchestrated hero entrance, nothing else ----------------- */

.js .js-seq { opacity: 0; transform: translateY(12px); }
.js .hero--in .js-seq {
    opacity: 1; transform: none;
    transition: opacity var(--slow) var(--ease), transform var(--slow) var(--ease);
}
.js .hero--in .js-seq:nth-child(1) { transition-delay: 0ms; }
.js .hero--in .js-seq:nth-child(2) { transition-delay: 60ms; }
.js .hero--in .js-seq:nth-child(3) { transition-delay: 120ms; }
.js .hero--in .js-seq:nth-child(4) { transition-delay: 180ms; }

@media (prefers-reduced-motion: reduce) {
    *, *::before, *::after {
        animation-duration: 0.01ms !important;
        transition-duration: 0.01ms !important;
        scroll-behavior: auto !important;
    }
    .js .js-seq { opacity: 1; transform: none; }
}

/* --- Cart ----------------------------------------------------------------- */

.cartlist { display: grid; grid-template-columns: 1fr 20rem; gap: clamp(2rem, 1rem + 3vw, 3.5rem); align-items: start; }
.cartlist__items { display: grid; gap: var(--gap-2); }

.cartline {
    display: grid; grid-template-columns: 96px 1fr auto;
    gap: var(--gap-3); align-items: center;
    padding: var(--gap-2);
    background: var(--surface); border: 1px solid var(--line); border-radius: var(--radius-lg);
}
.cartline__media { display: block; width: 96px; border-radius: var(--radius); overflow: hidden; }
.cartline__media .photo { aspect-ratio: 4 / 5; }
.cartline__title { margin-top: 0.2rem; font-size: var(--step-1); letter-spacing: -0.025em; }
.cartline__meta { font-size: var(--step--1); color: var(--ink-muted); }
.cartline__price { font-family: var(--font-display); font-weight: 700; font-size: var(--step-1); }

.carttotals {
    display: grid; gap: 0.6rem;
    padding: var(--gap-3);
    background: var(--surface); border: 1px solid var(--line); border-radius: var(--radius-lg);
}
.carttotals__row { display: flex; justify-content: space-between; gap: var(--gap-2); font-family: var(--font-display); font-weight: 600; }
.carttotals__row--muted { color: var(--ink-muted); font-weight: 500; }
.carttotals__cta { margin-top: var(--gap-2); }

@media (max-width: 900px) {
    .cartlist { grid-template-columns: 1fr; }
}
@media (max-width: 560px) {
    .cartline { grid-template-columns: 72px 1fr; }
    .cartline__media { width: 72px; }
    .cartline__price { grid-column: 2; }
}

/* --- Shop: product detail --------------------------------------------------- */

.pdp { display: grid; grid-template-columns: 1fr 1fr; gap: clamp(2rem, 1rem + 4vw, 4.5rem); align-items: start; }
/* Sale prices — the was-price is struck and muted, the now-price keeps the
   normal price styling so the discount reads without shouting. */
.price__was {
    color: var(--ink-muted);
    text-decoration: line-through;
    font-weight: 400;
    font-size: 0.85em;
    margin-right: 0.375rem;
}

/* Breadcrumbs */
.crumbs { margin-bottom: 1rem; }
.crumbs__list { display: flex; flex-wrap: wrap; gap: 0.25rem; list-style: none; margin: 0; padding: 0; }
.crumbs__item { display: flex; align-items: center; gap: 0.25rem; font-size: 0.85rem; color: var(--ink-muted); }
.crumbs__item + .crumbs__item::before { content: "›"; color: var(--ink-muted); }
.crumbs__link { color: var(--ink-muted); text-decoration: none; }
.crumbs__link:hover { color: var(--ink); text-decoration: underline; }
.crumbs__current { color: var(--ink); }

/* Producers */
.producergrid { display: grid; grid-template-columns: repeat(auto-fill, minmax(16rem, 1fr)); gap: 2rem; }
.producercard { border: 1px solid var(--line); border-radius: var(--radius-lg); padding: 1.5rem; background: var(--surface); }
.producercard__name { margin: 0 0 0.5rem; }
.producercard__desc { color: var(--ink-muted); margin: 0 0 0.75rem; }
.producercard__count { font-size: 0.85rem; color: var(--ink-muted); margin: 0; }

/* Newsletter thanks */
.signup__thanks { margin: 0; color: var(--ink); }

.pdp__figure { margin: 0; }
.pdp__figure .photo { aspect-ratio: 4 / 5; border-radius: var(--radius-lg); }

.pdp__main { position: relative; }
.pdp__thumbs { display: flex; flex-wrap: wrap; gap: 0.5rem; margin-top: 0.75rem; }
.pdp__thumb {
    width: 4rem;
    padding: 0;
    border: 1px solid var(--line);
    border-radius: var(--radius);
    background: none;
    cursor: pointer;
    overflow: hidden;
}
.pdp__thumb img { display: block; width: 100%; height: auto; }
.pdp__thumb.is-current { border-color: var(--ink); }
.pdp__thumb:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.pdp__title { margin-top: var(--gap-2); font-size: var(--step-3); text-wrap: balance; }
.pdp__price { margin-top: var(--gap-2); font-family: var(--font-display); font-weight: 700; font-size: var(--step-2); }
.pdp__desc { margin-top: var(--gap-3); color: var(--ink-muted); }
.pdp__stock { margin-top: var(--gap-2); font-size: var(--step--1); color: var(--ink-muted); }
.pdp__add { margin-top: var(--space-component); display: flex; align-items: flex-end; gap: var(--gap-2); flex-wrap: wrap; }

.qty { display: grid; gap: 0.35rem; }
.qty__label { font-family: var(--font-display); font-size: var(--step--1); font-weight: 600; }
.qty__input {
    width: 5.5rem; min-height: 44px; padding: 0 0.7rem;
    background: var(--surface); color: var(--ink);
    border: 1px solid var(--line); border-radius: var(--radius);
    font-family: var(--font-body); font-size: var(--step-0);
}

/* --- Empty state ----------------------------------------------------------- */

.emptystate {
    padding: var(--space-section) var(--gap-3);
    text-align: center;
    background: var(--surface); border: 1px solid var(--line); border-radius: var(--radius-lg);
}
.emptystate__title { font-family: var(--font-display); font-size: var(--step-2); font-weight: 700; letter-spacing: -0.025em; }
.emptystate__note { margin: 0.5rem 0 var(--space-component); color: var(--ink-muted); }

/* --- Cart additions -------------------------------------------------------- */

.cartline__end { display: grid; gap: 0.35rem; justify-items: end; }
.cartline__price, .drawerline__price { white-space: nowrap; }

/* --- Quantity stepper -------------------------------------------------------
   One control for every editable line: − count +. Read-only surfaces
   (checkout summary, order pages) use the badge on the thumbnail instead. */
.stepper {
    display: inline-flex; align-items: stretch;
    border: 1px solid var(--line); border-radius: var(--radius);
    background: var(--surface);
}
.stepper__btn {
    min-width: 2.75rem; min-height: 2.75rem;
    display: inline-flex; align-items: center; justify-content: center;
    border: 0; background: none; cursor: pointer;
    font-family: var(--font-display); font-size: var(--step-0); font-weight: 600;
    color: var(--ink);
    transition: color var(--fast) var(--ease);
}
.stepper__btn:hover { color: var(--accent); }
.stepper__btn:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }
.stepper__field { display: inline-flex; }
.stepper__input {
    width: 3rem; border: 0; border-inline: 1px solid var(--line);
    background: none; text-align: center;
    font-family: var(--font-display); font-size: var(--step-0); font-weight: 600;
    color: var(--ink);
    -moz-appearance: textfield; appearance: textfield;
}
.stepper__input::-webkit-outer-spin-button,
.stepper__input::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }
.stepper__input:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }
.stepper__count {
    min-width: 2.5rem;
    display: inline-flex; align-items: center; justify-content: center;
    border-inline: 1px solid var(--line);
    font-family: var(--font-display); font-weight: 600;
    font-variant-numeric: tabular-nums;
}
.stepper--compact .stepper__btn { min-width: 2.25rem; min-height: 2.25rem; }
.stepper--compact .stepper__count { min-width: 2rem; }
.cartline__title a { text-decoration: none; }
.cartline__title a:hover { color: var(--accent); }
.cartline__qty { margin-top: var(--gap-2); display: flex; align-items: flex-end; gap: var(--gap-1); }
.cartline--compact { grid-template-columns: 1fr auto; }

.btn--tiny { min-height: 38px; padding: 0 0.9rem; }

.linkbtn {
    background: none; border: 0; padding: 0; cursor: pointer;
    font-family: var(--font-display); font-size: var(--step--1); font-weight: 600;
    color: var(--ink-muted); text-decoration: underline;
    text-decoration-color: color-mix(in srgb, currentColor 35%, transparent);
}
.linkbtn:hover { color: var(--accent); }

.carttotals__row--total { padding-top: 0.6rem; border-top: 1px solid var(--line); font-size: var(--step-1); }
.carttotals__note { font-size: var(--step--1); color: var(--ink-muted); line-height: 1.45; }

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

.checkout { display: grid; grid-template-columns: 1fr 22rem; gap: clamp(2rem, 1rem + 3vw, 3.5rem); align-items: start; }
.checkout__main { display: grid; gap: var(--space-component); }

.fieldset { margin: 0; padding: var(--gap-3); border: 1px solid var(--line); border-radius: var(--radius-lg); background: var(--surface); }
.fieldset__legend { padding: 0 0.5rem; font-family: var(--font-display); font-size: var(--step-0); font-weight: 700; }

.fieldgrid { display: grid; grid-template-columns: 1fr 1fr; gap: var(--gap-2); }
.field { display: grid; gap: 0.35rem; }
.field--wide { grid-column: 1 / -1; }
.field__label { font-family: var(--font-display); font-size: var(--step--1); font-weight: 600; }
.field__input {
    min-height: 44px; padding: 0.5rem 0.8rem;
    background: var(--bg); color: var(--ink);
    border: 1px solid var(--line); border-radius: var(--radius);
    font-family: var(--font-body); font-size: var(--step-0);
}
.field__input:focus-visible { border-color: var(--accent); }
.field__error { font-size: var(--step--1); color: var(--accent); }
.field__error:empty { display: none; }

.choices { display: grid; gap: var(--gap-1); }
.choice {
    display: flex; align-items: flex-start; gap: 0.75rem;
    padding: 0.85rem 1rem; cursor: pointer;
    border: 1px solid var(--line); border-radius: var(--radius);
    transition: border-color var(--fast) var(--ease), background-color var(--fast) var(--ease);
}
.choice:hover { border-color: color-mix(in srgb, var(--ink) 30%, var(--line)); }
.choice:has(input:checked) { border-color: var(--accent); background: var(--accent-soft); }
.choice input { margin-top: 0.35rem; accent-color: var(--accent); width: 18px; height: 18px; }
.choice__body { display: grid; gap: 0.15rem; }
.choice__label { font-family: var(--font-display); font-weight: 600; }
.choice__meta { font-size: var(--step--1); color: var(--ink-muted); }

.checkout__summary {
    position: sticky; top: 6rem;
    display: grid; gap: 0.6rem;
    padding: var(--gap-3);
    background: var(--surface); border: 1px solid var(--line); border-radius: var(--radius-lg);
}
.checkout__summary-title { font-size: var(--step-1); }
.summary__items {
    display: grid; gap: var(--gap-2);
    padding-bottom: var(--gap-2); border-bottom: 1px solid var(--line);
    list-style: none; margin: 0; padding-left: 0;
}
.summary__item { display: flex; align-items: flex-start; gap: 0.75rem; font-size: var(--step--1); }
.summary__thumb { position: relative; flex: 0 0 3.25rem; }
.summary__thumb .photo { aspect-ratio: 4 / 5; border-radius: var(--radius); }
.summary__count {
    position: absolute; top: -0.4rem; right: -0.4rem;
    display: inline-flex; align-items: center; justify-content: center;
    min-width: 1.35rem; height: 1.35rem; padding: 0 0.3rem;
    background: var(--ink); color: var(--surface);
    border-radius: 999px;
    font-family: var(--font-display); font-size: 0.72rem; font-weight: 700;
    font-variant-numeric: tabular-nums;
}
.summary__info { flex: 1; display: grid; gap: 0.15rem; padding-top: 0.1rem; min-width: 0; }
.summary__name { font-family: var(--font-display); font-weight: 600; color: var(--ink); line-height: 1.3; }
.summary__variant { color: var(--ink-muted); line-height: 1.35; }
.summary__price {
    display: grid; justify-items: end; gap: 0.1rem;
    padding-top: 0.1rem; color: var(--ink); white-space: nowrap;
}
.summary__price .price__was { margin-right: 0; }

/* On order pages the same list stands alone in the page grid, so it grows
   a little and drops the sidebar's bottom border. */
.summary__items--page { border-bottom: 0; padding-bottom: 0; gap: var(--gap-3); }
.summary__items--page .summary__item { font-size: var(--step-0); }
.summary__items--page .summary__thumb { flex-basis: 4rem; }
.summary__items--page .summary__variant { font-size: var(--step--1); }

/* Amounts never wrap mid-value. */
.carttotals__row span:last-child { white-space: nowrap; }

.notice {
    padding: var(--gap-2) var(--gap-3); margin-bottom: var(--space-component);
    background: var(--accent-soft); border-left: 3px solid var(--accent); border-radius: var(--radius);
}

/* --- Pager ----------------------------------------------------------------- */

.pager { display: flex; gap: var(--gap-1); margin-top: var(--space-component); }
.pager__link {
    display: inline-flex; align-items: center; justify-content: center;
    min-width: 44px; min-height: 44px;
    border: 1px solid var(--line); border-radius: var(--radius);
    font-family: var(--font-display); font-weight: 600; text-decoration: none;
}
.pager__link--current { background: var(--accent); border-color: var(--accent); color: var(--accent-ink); }

@media (max-width: 900px) {
    .pdp, .checkout { grid-template-columns: 1fr; }
    .checkout__summary { position: static; }
}
@media (max-width: 560px) {
    .fieldgrid { grid-template-columns: 1fr; }
    .field--wide { grid-column: auto; }
}

/* --- Loading state ---------------------------------------------------------
   The AJAX framework adds .jax-attach-loader and disables the element while a
   request is in flight. The spinner replaces the label in place, so the button
   never changes size and the layout never shifts.
--------------------------------------------------------------------------- */

.btn.jax-attach-loader,
.linkbtn.jax-attach-loader {
    position: relative;
    color: transparent !important;
    pointer-events: none;
}

.btn.jax-attach-loader::after,
.linkbtn.jax-attach-loader::after {
    content: "";
    position: absolute;
    top: 50%; left: 50%;
    width: 1em; height: 1em;
    margin: -0.5em 0 0 -0.5em;
    border: 2px solid currentColor;
    border-radius: 50%;
    border-top-color: transparent;
    animation: forge-spin 640ms linear infinite;
}

/* The solid button loses its label colour, so borrow the ink it sits on. */
.btn--solid.jax-attach-loader::after { border-color: var(--accent-ink); border-top-color: transparent; }
.btn--quiet.jax-attach-loader::after,
.btn--ghost.jax-attach-loader::after { border-color: var(--ink); border-top-color: transparent; }
.linkbtn.jax-attach-loader::after { border-color: var(--ink-muted); border-top-color: transparent; }

.btn[disabled], .linkbtn[disabled] { cursor: default; }

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

/* --- Side cart -------------------------------------------------------------
   Motion level 1: functional only. Transform and opacity, exit faster than
   entrance, and nothing at all when reduced motion is asked for.
--------------------------------------------------------------------------- */

.drawer { position: fixed; inset: 0; z-index: 60; }
.drawer[hidden] { display: none; }

.drawer__scrim {
    position: absolute; inset: 0;
    background: rgba(8, 11, 10, 0.5);
    opacity: 0;
    transition: opacity 240ms var(--ease);
}
.drawer[data-open="true"] .drawer__scrim { opacity: 1; }

.drawer__panel {
    position: absolute; top: 0; right: 0; bottom: 0;
    width: min(26rem, 100%);
    display: flex; flex-direction: column;
    background: var(--bg);
    border-left: 1px solid var(--line);
    box-shadow: -12px 0 32px -20px rgba(8, 11, 10, 0.5);
    transform: translateX(100%);
    transition: transform 240ms var(--ease);
}
.drawer[data-open="true"] .drawer__panel { transform: translateX(0); }

/* Exit is quicker than the entrance so dismissing never feels sticky. */
.drawer[data-open="false"] .drawer__scrim { transition-duration: 160ms; }
.drawer[data-open="false"] .drawer__panel { transition-duration: 180ms; }

body.has-drawer { overflow: hidden; }

.drawer__head {
    flex: none;
    display: flex; align-items: center; justify-content: space-between;
    gap: var(--gap-2);
    padding: var(--gap-2) var(--gap-2) var(--gap-2) var(--gap-3);
    border-bottom: 1px solid var(--line);
}
.drawer__title { font-size: var(--step-1); }

/* The AJAX target is a layout column, not the scroll area. min-height:0 is what
   lets the body actually shrink and scroll instead of pushing the foot off. */
.drawer__stack {
    flex: 1;
    display: flex; flex-direction: column;
    min-height: 0;
}

/* The only scrolling element, and only when it overflows. overscroll-behavior
   stops a scroll at the end of the list from chaining to the page behind. */
.drawer__body {
    flex: 1 1 auto;
    min-height: 0;
    overflow-y: auto;
    overscroll-behavior: contain;
    padding: var(--gap-3);
}
.drawer__body--empty { display: grid; place-items: center; }
.drawer__empty { text-align: center; }

.drawerlist { display: grid; gap: var(--gap-3); }
.drawerline { display: grid; grid-template-columns: 72px 1fr auto; gap: var(--gap-2); align-items: start; }
.drawerline__media { display: block; width: 72px; border-radius: var(--radius); overflow: hidden; }
.drawerline__media .photo { aspect-ratio: 4 / 5; }
.drawerline__title { font-family: var(--font-display); font-size: var(--step-0); font-weight: 700; letter-spacing: -0.02em; }
.drawerline__title a { text-decoration: none; }
.drawerline__title a:hover { color: var(--accent); }
.drawerline__meta { font-size: var(--step--1); color: var(--ink-muted); }
.drawerline__row { display: flex; align-items: center; gap: var(--gap-2); margin-top: 0.5rem; }
.drawerline__price {
    display: grid; justify-items: end; gap: 0.1rem;
    font-family: var(--font-display); font-weight: 700;
}
.drawerline__price .price__was { font-weight: 400; }

/* Pinned to the bottom of the panel: a sibling of the body, never inside it,
   so it stays put however long the item list gets. */
.drawer__foot {
    flex: none;
    display: grid; gap: 0.6rem;
    padding: var(--gap-3);
    border-top: 1px solid var(--line);
    background: var(--surface);
}
.drawer__cta { width: 100%; }

@media (prefers-reduced-motion: reduce) {
    .drawer__scrim, .drawer__panel { transition: none !important; }
    .btn.jax-attach-loader::after,
    .linkbtn.jax-attach-loader::after { animation: none; }
}

.drawer__panel:focus { outline: none; }

/* --- Account ---------------------------------------------------------------- */

.shell--narrow { width: min(100% - (var(--gutter) * 2), 34rem); margin-inline: auto; }

.authform {
    display: grid; gap: var(--gap-2);
    padding: var(--gap-3);
    background: var(--surface);
    border: 1px solid var(--line);
    border-radius: var(--radius-lg);
}
.authform__submit { margin-top: var(--gap-1); }
.authform__alt { margin-top: var(--gap-3); color: var(--ink-muted); font-size: var(--step--1); }

.field__hint { font-size: var(--step--1); color: var(--ink-muted); }

/* A signed-in account carries a dot as well as a different destination, so the
   state is never communicated by colour alone. */
.iconbtn__dot {
    position: absolute; top: 9px; right: 9px;
    width: 7px; height: 7px;
    background: var(--accent);
    border: 2px solid var(--bg);
    border-radius: 50%;
}

.sechead__title--sub { font-size: var(--step-2); margin-bottom: var(--gap-3); }

.orderlist { display: grid; gap: var(--gap-1); }
.orderrow {
    display: flex; align-items: center; justify-content: space-between;
    gap: var(--gap-3);
    padding: var(--gap-2) var(--gap-3);
    background: var(--surface);
    border: 1px solid var(--line);
    border-radius: var(--radius-lg);
}
.orderrow__number { font-family: var(--font-display); font-weight: 700; font-size: var(--step-0); }
.orderrow__number a { text-decoration: none; }
.orderrow__number a:hover { color: var(--accent); }
.orderrow__meta { font-size: var(--step--1); color: var(--ink-muted); }
.orderrow__total { font-family: var(--font-display); font-weight: 700; font-size: var(--step-1); }

@media (max-width: 560px) {
    .orderrow { flex-direction: column; align-items: flex-start; gap: var(--gap-1); }
}

/* Sidebar + canvas, WooCommerce-endpoint style: each section is its own URL,
   the nav marks the current one. On narrow screens the sidebar becomes a
   horizontal row above the canvas. */
.accountlayout {
    display: grid; grid-template-columns: 15rem 1fr;
    gap: var(--space-component);
    align-items: start;
}

.accountnav {
    display: grid;
    padding: var(--gap-1);
    background: var(--surface);
    border: 1px solid var(--line);
    border-radius: var(--radius-lg);
}
.accountnav__link {
    display: block;
    padding: 0.6rem var(--gap-2);
    font-family: var(--font-display); font-size: var(--step--1); font-weight: 600;
    text-decoration: none;
    border-left: 3px solid transparent;
    border-radius: var(--radius);
    transition: background-color var(--fast) var(--ease), color var(--fast) var(--ease);
}
.accountnav__link:hover { background: var(--ink-soft); }
.accountnav__link--current {
    border-left-color: var(--accent);
    color: var(--accent);
    background: var(--accent-soft);
}

.accountcanvas { min-width: 0; }

/* Detail blocks: read-only facts by default, the Edit link swaps in the form */
.detailblock + .detailblock { margin-top: var(--space-component); }
.blockhead {
    display: flex; align-items: center; justify-content: space-between;
    gap: var(--gap-2);
    margin-bottom: var(--gap-3);
}
.blockhead .sechead__title--sub { margin-bottom: 0; }

.facts {
    display: grid; gap: var(--gap-2);
    margin: 0;
    padding: var(--gap-3);
    background: var(--surface);
    border: 1px solid var(--line);
    border-radius: var(--radius-lg);
}
.fact { display: grid; gap: 0.15rem; }
.fact__label { font-family: var(--font-display); font-size: var(--step--1); font-weight: 600; color: var(--ink-muted); }
.fact__value { margin: 0; }
.fact__value--empty { color: var(--ink-muted); }

/* Order detail inside the canvas */
.ordermeta {
    margin: calc(var(--gap-3) * -1 + var(--gap-1)) 0 var(--space-component);
    font-size: var(--step--1); color: var(--ink-muted);
}
.orderfacts {
    display: grid; grid-template-columns: repeat(3, 1fr);
    gap: var(--gap-2);
    margin-top: var(--space-component);
}
.orderfacts__cell {
    padding: var(--gap-2) var(--gap-3);
    background: var(--surface);
    border: 1px solid var(--line);
    border-radius: var(--radius-lg);
}
.orderfacts__label {
    margin-bottom: 0.35rem;
    font-family: var(--font-display); font-size: var(--step--1); font-weight: 600;
    color: var(--ink-muted);
}

/* Two-up variant for when the facts sit beside a figure (contact page). */
.orderfacts--stack { grid-template-columns: repeat(2, 1fr); margin-top: var(--gap-2); }

@media (max-width: 700px) {
    .orderfacts, .orderfacts--stack { grid-template-columns: 1fr; }
}

@media (max-width: 900px) {
    .accountlayout { grid-template-columns: 1fr; }
    .accountnav { display: flex; flex-wrap: wrap; }
    .accountnav__link { border-left-width: 0; border-bottom: 3px solid transparent; }
    .accountnav__link--current { border-bottom-color: var(--accent); }
}

.field__optional { font-weight: 500; color: var(--ink-muted); }
/* An admin session is marked with the ink colour, not the accent, so it never
   reads as a customer account at a glance. */
.iconbtn__dot--admin { background: var(--ink); }

/* --- Variable products ------------------------------------------------------ */

.variations { margin-top: var(--space-component); }
.variations__title { font-size: var(--step-1); margin-bottom: var(--gap-2); }
.variations__list { display: grid; gap: var(--gap-1); }
.variations__row {
    display: flex; align-items: baseline; justify-content: space-between; gap: var(--gap-2);
    padding: 0.7rem 0.9rem;
    background: var(--surface); border: 1px solid var(--line); border-radius: var(--radius);
}
.variations__label { font-family: var(--font-display); font-weight: 600; }
.variations__price { font-family: var(--font-display); font-weight: 700; }
.variations__stock { font-size: var(--step--1); color: var(--ink-muted); }

/* --- Variation picker ------------------------------------------------------- */

.sr-only {
    position: absolute; width: 1px; height: 1px;
    padding: 0; margin: -1px; overflow: hidden;
    clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

.pdp__lede { margin-top: var(--gap-2); font-size: var(--step-1); color: var(--ink-muted); max-width: 40ch; }

.vpick { margin-top: var(--space-component); display: grid; gap: var(--gap-3); }
.vpick__group { margin: 0; padding: 0; border: 0; }
.vpick__label {
    padding: 0; margin-bottom: 0.6rem;
    font-family: var(--font-display); font-size: var(--step--1); font-weight: 700;
}
.vpick__picked { color: var(--ink-muted); font-weight: 500; }
.vpick__select { max-width: 18rem; width: 100%; }
.vpick__swatches { display: flex; flex-wrap: wrap; gap: var(--gap-1); }
.vpick__note { min-height: 1.4em; margin-top: var(--gap-1); font-size: var(--step--1); color: var(--ink-muted); }

/* Text swatch — Flatsome-style pill */
.swatch { cursor: pointer; }
.swatch__pill {
    display: inline-flex; align-items: center;
    min-height: 44px; padding: 0 1.1rem;
    font-family: var(--font-display); font-size: var(--step--1); font-weight: 600;
    background: var(--surface);
    border: 1px solid var(--line); border-radius: var(--radius);
    transition: border-color var(--fast) var(--ease), background-color var(--fast) var(--ease);
}
.swatch:hover .swatch__pill { border-color: color-mix(in srgb, var(--ink) 40%, var(--line)); }
.swatch__input:checked + .swatch__pill {
    border-color: var(--accent);
    background: var(--accent-soft);
    color: var(--accent);
}
.swatch__input:focus-visible + .swatch__pill,
.swatch__input:focus-visible + .swatch__chip {
    outline: 2px solid var(--accent); outline-offset: 3px;
}

/* Colour swatch — hex from the admin */
.swatch__chip {
    display: inline-block; width: 44px; height: 44px;
    background: var(--swatch);
    border: 1px solid color-mix(in srgb, var(--ink) 22%, transparent);
    border-radius: 50%;
    transition: box-shadow var(--fast) var(--ease);
}
.swatch__input:checked + .swatch__chip {
    box-shadow: 0 0 0 2px var(--bg), 0 0 0 4px var(--accent);
}

.pdp__buy { margin-top: var(--gap-3); display: flex; align-items: flex-end; gap: var(--gap-2); flex-wrap: wrap; }
.btn[disabled] { opacity: 0.55; cursor: not-allowed; }

/* --- PDP sections ----------------------------------------------------------- */

/* The variable-product form stacks: picker first, then quantity + buy below.
   The base .pdp__add flex layout is for the simple product's single row. */
.pdp__add--variable { display: block; }

.section--desc { border-top: 1px solid var(--line); }
.prose { max-width: 62ch; color: var(--ink-muted); }
.prose p { margin-top: var(--gap-2); }
.prose p:first-child { margin-top: 0; }
.prose h2 {
    margin-top: var(--space-component);
    font-size: var(--step-1);
    color: var(--ink);
    text-wrap: balance;
}
.prose h2:first-child { margin-top: 0; }
.prose h2 + p { margin-top: var(--gap-1); }

.section--related { background: var(--surface); border-top: 1px solid var(--line); }

/* --- Shop archive: sidebar + grid -------------------------------------------
   Desktop: a quarter for the filters, the rest for the shelf. Below 900px the
   same markup becomes a left-hand drawer, driven by the Filter button; the
   off-canvas styles are scoped to .js so without JavaScript the filters simply
   render inline above the grid.
--------------------------------------------------------------------------- */

.shoplayout {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 3fr);
    gap: clamp(1.5rem, 1rem + 2vw, 3rem);
    align-items: start;
}

.pgrid--aside { grid-template-columns: repeat(3, 1fr); }
.pgrid__empty { grid-column: 1 / -1; }

.shoptools { display: flex; align-items: center; gap: var(--gap-2); }

.sortctl { display: flex; align-items: center; gap: 0.6rem; }
.sortctl__label { font-family: var(--font-display); font-size: var(--step--1); font-weight: 600; white-space: nowrap; }
.sortctl__select { cursor: pointer; }

.filterbtn { display: none; gap: 0.55rem; }
.filterbtn__count {
    display: grid; place-items: center;
    min-width: 20px; height: 20px; padding: 0 5px;
    background: var(--accent); color: var(--accent-ink);
    border-radius: 10px;
    font-size: 0.72rem; font-weight: 700;
}

.js .nojs-only { display: none; }

/* --- The filter form -------------------------------------------------------- */

.filters { display: grid; gap: var(--space-component); }

.filters__group { margin: 0; padding: 0; border: 0; min-width: 0; }
.filters__title {
    display: block; padding: 0; margin-bottom: 0.75rem;
    font-family: var(--font-display); font-size: var(--step-0); font-weight: 700;
    letter-spacing: -0.015em;
}

.filters__list { display: grid; gap: 0.15rem; }
.filters__list--sub { margin-top: 0.15rem; padding-left: var(--gap-2); }

.filters__cat {
    display: flex; align-items: baseline; gap: var(--gap-1);
    padding-block: 0.35rem;
    font-family: var(--font-display); font-size: var(--step--1); font-weight: 600;
    color: var(--ink-muted); text-decoration: none;
}
.filters__cat:hover { color: var(--accent); }
.filters__cat--current { color: var(--ink); font-weight: 700; }
/* The current shelf is marked by weight and a bar, never colour alone. */
.filters__cat--current::before {
    content: ""; align-self: center; flex: none;
    width: 3px; height: 1em;
    background: var(--accent);
}
.filters__count { margin-left: auto; font-family: var(--font-body); font-weight: 400; color: var(--ink-muted); font-size: var(--step--1); }

.fchoice {
    display: flex; align-items: center; gap: 0.6rem;
    padding-block: 0.4rem;
    font-size: var(--step--1);
    cursor: pointer;
}
.fchoice__input { width: 18px; height: 18px; margin: 0; flex: none; accent-color: var(--accent); cursor: pointer; }
.fchoice:hover .fchoice__name { color: var(--accent); }

@media (pointer: coarse) {
    .fchoice { min-height: 44px; }
}

.filters__price { display: flex; align-items: flex-end; gap: var(--gap-1); }
.filters__pricefield { display: grid; gap: 0.35rem; min-width: 0; }
.filters__pricelabel { font-family: var(--font-display); font-size: var(--step--1); font-weight: 600; }
.filters__pricefield .field__input { width: 100%; }
.filters__pricedash { color: var(--ink-muted); padding-bottom: 0.7rem; }

.stars { letter-spacing: 0.1em; }
.stars__on { color: var(--accent); }
.stars__off { color: var(--line); }

.filters__actions { display: grid; gap: var(--gap-2); justify-items: start; }
.filters__apply { width: 100%; }

.pcard__rating { font-size: var(--step--1); font-family: var(--font-display); font-weight: 600; }
.pcard__ratingcount { color: var(--ink-muted); font-weight: 500; }

/* --- The filter drawer (mobile) --------------------------------------------- */

.fdrawer__head { display: none; }
.fdrawer__scrim { display: none; }

@media (max-width: 1080px) {
    .pgrid--aside { grid-template-columns: repeat(2, 1fr); }
}

@media (max-width: 900px) {
    .shoplayout { grid-template-columns: 1fr; }
    .filterbtn { display: inline-flex; }
    .shoptools { width: 100%; justify-content: space-between; flex-wrap: wrap; }

    /* The sort control has a fixed-width native select beside a nowrap label,
       so on a narrow screen the pair pushed the page 59px wider than the
       viewport and the whole shop scrolled sideways. Let it take its own row
       and let the select give way rather than the page. */
    .sortctl { flex: 1 1 100%; min-width: 0; }
    .sortctl__select { flex: 1 1 auto; min-width: 0; max-width: 100%; }

    .js .fdrawer {
        position: fixed; inset: 0; z-index: 60;
        visibility: hidden;
        transition: visibility 0s linear 240ms;
    }
    .js .fdrawer[data-open="true"] { visibility: visible; transition-delay: 0s; }

    .js .fdrawer__scrim {
        display: block;
        position: absolute; inset: 0;
        background: rgba(8, 11, 10, 0.5);
        opacity: 0;
        transition: opacity 240ms var(--ease);
    }
    .js .fdrawer[data-open="true"] .fdrawer__scrim { opacity: 1; }

    .js .fdrawer__panel {
        position: absolute; top: 0; left: 0; bottom: 0;
        width: min(24rem, calc(100% - 3rem));
        display: flex; flex-direction: column;
        background: var(--bg);
        border-right: 1px solid var(--line);
        box-shadow: 12px 0 32px -20px rgba(8, 11, 10, 0.5);
        transform: translateX(-100%);
        transition: transform 240ms var(--ease);
    }
    .js .fdrawer[data-open="true"] .fdrawer__panel { transform: translateX(0); }

    /* Exit faster than entrance, matching the side cart. */
    .js .fdrawer[data-open="false"] .fdrawer__scrim { transition-duration: 160ms; }
    .js .fdrawer[data-open="false"] .fdrawer__panel { transition-duration: 180ms; }

    .js .fdrawer__head {
        flex: none;
        display: flex; align-items: center; justify-content: space-between;
        gap: var(--gap-2);
        padding: var(--gap-2) var(--gap-2) var(--gap-2) var(--gap-3);
        border-bottom: 1px solid var(--line);
    }

    .js .fdrawer__body {
        flex: 1; min-height: 0;
        overflow-y: auto; overscroll-behavior: contain;
        padding: var(--gap-3);
    }
}

.fdrawer__panel:focus { outline: none; }

@media (prefers-reduced-motion: reduce) {
    .fdrawer, .fdrawer__scrim, .fdrawer__panel { transition: none !important; }
}

/* --- Reviews ----------------------------------------------------------------
   List on the left, the write-a-review card on the right. The star picker is
   the classic reversed-row trick: inputs stay focusable, labels draw the
   stars, and sibling selectors light everything up to the chosen one.
--------------------------------------------------------------------------- */

.section--reviews { border-top: 1px solid var(--line); }

.pdp__ratinglink {
    margin-top: var(--gap-1);
    display: inline-flex; align-items: baseline; gap: 0.4rem;
    font-family: var(--font-display); font-size: var(--step--1); font-weight: 700;
    text-decoration: none;
}
.pdp__ratinglink:hover { color: var(--accent); }
.pdp__ratingcount { font-weight: 500; color: var(--ink-muted); }

.reviewgrid {
    display: grid;
    grid-template-columns: minmax(0, 1.4fr) minmax(0, 1fr);
    gap: clamp(2rem, 1rem + 3vw, 3.5rem);
    align-items: start;
}

.reviews { display: grid; gap: var(--gap-2); }
.reviews__empty { color: var(--ink-muted); }

.review {
    padding: var(--gap-3);
    background: var(--surface);
    border: 1px solid var(--line);
    border-radius: var(--radius-lg);
}
.review__head { display: flex; align-items: baseline; flex-wrap: wrap; gap: 0.35rem var(--gap-2); }
.review__name { font-family: var(--font-display); font-weight: 700; }
.review__verified { font-family: var(--font-display); font-size: var(--step--1); font-weight: 600; color: var(--accent); }
.review__date { margin-left: auto; font-size: var(--step--1); color: var(--ink-muted); }
.review__body { margin-top: var(--gap-1); color: var(--ink-muted); }

.review__photos { margin-top: var(--gap-2); display: flex; flex-wrap: wrap; gap: var(--gap-1); }
.review__photos img {
    display: block; width: 90px; height: 90px; object-fit: cover;
    border: 1px solid var(--line); border-radius: var(--radius);
}

.revform {
    display: grid; gap: var(--gap-2);
    padding: var(--gap-3);
    background: var(--surface);
    border: 1px solid var(--line);
    border-radius: var(--radius-lg);
}
.revform__title { font-size: var(--step-1); }
.revform__rating { margin: 0; padding: 0; border: 0; }
.revform__body { resize: vertical; min-height: 6rem; }
/* Text inputs size themselves by character count; pin them to the card. */
.revform .field { min-width: 0; }
.revform .field__input { width: 100%; min-width: 0; }
.revform__files { font-size: var(--step--1); color: var(--ink-muted); }
.revform__submit { justify-self: start; }

.starpick { display: inline-flex; flex-direction: row-reverse; margin-top: 0.35rem; }
.starpick__input {
    position: absolute;
    opacity: 0; width: 1px; height: 1px;
}
.starpick__star {
    cursor: pointer;
    padding: 0.1rem 0.15rem;
    font-size: 1.7rem; line-height: 1;
    color: var(--line);
    transition: color var(--fast) var(--ease);
}
.starpick__input:checked ~ .starpick__star { color: var(--accent); }
.starpick__star:hover, .starpick__star:hover ~ .starpick__star { color: var(--accent); }
.starpick__input:focus-visible + .starpick__star {
    outline: 2px solid var(--accent); outline-offset: 2px; border-radius: var(--radius);
}

/* Honeypot — off canvas for people, present for bots. */
.hp { position: absolute; left: -9999px; top: auto; }

@media (max-width: 900px) {
    .reviewgrid { grid-template-columns: 1fr; }
}

/* --- Header search ---------------------------------------------------------- */

.searchbar {
    position: sticky; top: 4.5rem; z-index: 39;
    background: var(--surface);
    border-bottom: 1px solid var(--line);
    box-shadow: var(--shadow-2);
}
.searchbar[hidden] { display: none; }
.searchbar__inner { padding-block: var(--gap-2); }
.searchbar__form { display: flex; align-items: center; gap: var(--gap-2); }
.searchbar__form > .icon { flex: none; color: var(--ink-muted); }
.searchbar__input {
    flex: 1; min-height: 44px; border: 0; outline: 0;
    background: transparent; color: var(--ink);
    font-family: var(--font-body); font-size: var(--step-1);
}
.searchbar__input::placeholder { color: var(--ink-muted); }

.searchbar__results { display: grid; }
.searchhit {
    display: flex; align-items: baseline; justify-content: space-between; gap: var(--gap-3);
    padding: 0.65rem 0;
    text-decoration: none;
    border-top: 1px solid var(--line);
}
.searchhit:hover .searchhit__title { color: var(--accent); }
.searchhit__title { font-family: var(--font-display); font-weight: 600; }
.searchhit__origin { display: block; font-size: var(--step--1); color: var(--ink-muted); }
.searchhit__price { font-family: var(--font-display); font-weight: 700; white-space: nowrap; }
.searchbar__empty { padding: 0.65rem 0; color: var(--ink-muted); border-top: 1px solid var(--line); }
.searchbar__all {
    display: block; padding: 0.65rem 0;
    border-top: 1px solid var(--line);
    font-family: var(--font-display); font-size: var(--step--1); font-weight: 600;
    color: var(--accent); text-decoration: none;
}

/* ===========================================================================
   Modules added in v2: eyebrow, trust bar, feature band, swatch library,
   process, spec table, included list, maker note and the configurator.

   Structure only, as everywhere else in this file. Every colour, family and
   radius below is a token — a child retints all of it from theme.css.
   =========================================================================== */

/* --- Eyebrow ---------------------------------------------------------------
   The micro-label above a section title. One rule, used by every new module,
   so a child changes the look of all of them in one place. */

.eyebrow {
    font-family: var(--font-eyebrow, var(--font-display));
    font-size: var(--step--1);
    font-weight: 600;
    color: var(--accent);
    margin-bottom: 0.9rem;
}

/* An accented word inside a heading. <em> because it *is* emphasis; the
   italic the browser would give it is turned off, the colour carries it. */
.accent { color: var(--accent); font-style: normal; }

.signature {
    font-family: var(--font-signature, var(--font-display));
    font-size: var(--step-1);
    color: var(--accent);
    margin-top: var(--gap-2);
}

.sechead--centred { text-align: center; }
.sechead--centred .sechead__note { margin-inline: auto; }
.section__action { margin-top: var(--space-component); text-align: center; }

/* --- Trust bar -------------------------------------------------------------
   Four claim/qualifier pairs. One row on desktop, two columns on a phone. */

.trustbar { padding-block: var(--space-component); border-bottom: 1px solid var(--line); }
.trustbar__list { display: grid; grid-template-columns: repeat(4, 1fr); gap: var(--gap-3); }
.trustbar__title {
    font-family: var(--font-display); font-size: var(--step--1); font-weight: 700;
    color: var(--accent);
}
.trustbar__note { font-size: var(--step--1); color: var(--ink-muted); margin-top: 0.35rem; }

/* --- Feature band ----------------------------------------------------------
   Full-bleed photograph, copy over it. The scrim is a pseudo-element so the
   contrast holds whatever photo is uploaded. */

.band { position: relative; isolation: isolate; overflow: hidden; }
.band__media { position: absolute; inset: 0; z-index: -2; }
.band__media .photo { width: 100%; height: 100%; object-fit: cover; }
.band::after {
    content: ''; position: absolute; inset: 0; z-index: -1;
    background: var(--band-scrim, linear-gradient(90deg, var(--scrim) 0%, var(--scrim) 45%, transparent 100%));
}
.band__inner {
    display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    gap: var(--space-component); align-items: center;
    padding-block: var(--space-section);
    min-height: 30rem;
}
.band__copy { max-width: 34rem; }
.band__title { font-size: var(--step-3); }
.band__text { margin-top: var(--gap-2); color: var(--ink-muted); max-width: 44ch; }
.band__copy .btn { margin-top: var(--space-component); }
.band__note { margin-top: var(--gap-2); font-size: var(--step--1); color: var(--ink-muted); }
.band__aside { position: relative; }

/* --- Swatch library --------------------------------------------------------
   Circular material samples. The circle is decorative; the name under it is
   what actually identifies the material. */

.swatchgrid {
    display: grid; grid-template-columns: repeat(8, 1fr);
    gap: var(--gap-3); text-align: center;
}
.swatchcard { display: flex; flex-direction: column; align-items: center; gap: 0.4rem; }
.swatchcard__chip {
    width: 100%; max-width: 5.5rem; aspect-ratio: 1;
    border-radius: 50%; overflow: hidden;
    background: linear-gradient(150deg, var(--chip-from), var(--chip-to));
    box-shadow: var(--swatch-ring, none);
}
.swatchcard__chip img { width: 100%; height: 100%; object-fit: cover; }
.swatchcard__name {
    font-family: var(--font-display); font-size: var(--step--1); font-weight: 700;
}
.swatchcard__latin { font-size: var(--step--1); color: var(--ink-muted); }

/* --- Process ---------------------------------------------------------------
   An ordered list. The numbers are content, not decoration — they are only
   aria-hidden because the <ol> already announces the position. */

.steps { display: grid; grid-template-columns: repeat(4, 1fr); gap: var(--gap-3); }
.step {
    padding: var(--gap-3);
    border: 1px solid var(--line); border-radius: var(--radius-lg);
    background: var(--surface);
}
.step__num {
    display: block;
    font-family: var(--font-display); font-size: var(--step-2);
    color: var(--accent); line-height: 1;
}
.step__title { margin-top: var(--gap-2); font-size: var(--step-1); }
.step__body { margin-top: 0.6rem; font-size: var(--step--1); color: var(--ink-muted); }

/* --- Specification table ---------------------------------------------------
   A <dl> of name/value rows, hairline between each. */

.specs { margin-top: var(--space-component); }
.specs__row {
    display: flex; align-items: baseline; justify-content: space-between;
    gap: var(--gap-3);
    padding-block: 0.9rem;
    border-bottom: 1px solid var(--line);
}
.specs__label { color: var(--ink-muted); font-size: var(--step--1); }
.specs__value {
    margin: 0; text-align: right;
    font-family: var(--font-display); font-weight: 600;
}

/* --- Included list ---------------------------------------------------------- */

.included { margin-top: var(--space-component); display: grid; gap: var(--gap-2); }
.included__item { display: flex; align-items: center; gap: 0.85rem; }
.included__icon {
    display: grid; place-items: center; flex: none;
    width: 2rem; height: 2rem;
    border: 1px solid var(--line); border-radius: var(--radius);
    color: var(--accent);
}
.included__icon .icon { width: 16px; height: 16px; }

/* --- Maker note -------------------------------------------------------------
   A signed aside. The avatar is an initial, not a photo, so it costs nothing
   and never 404s. */

.makernote {
    display: flex; gap: var(--gap-3); align-items: flex-start;
    margin-top: var(--space-section);
    max-width: 52rem;
}
.makernote__avatar {
    display: grid; place-items: center; flex: none;
    width: 3.25rem; height: 3.25rem; border-radius: 50%;
    border: 1px solid var(--line);
    font-family: var(--font-signature, var(--font-display));
    font-size: var(--step-1); color: var(--accent);
}
.makernote__text { color: var(--ink-muted); font-size: var(--step--1); line-height: 1.7; }
.makernote__text + .makernote__text { margin-top: var(--gap-2); }
.makernote .signature { font-size: var(--step-0); }

/* --- Configurator ----------------------------------------------------------
   Two columns: the open step, and a rail that never scrolls out of reach on a
   tall screen. Below 1080px the rail moves under the step rather than
   shrinking — a summary you cannot read is worse than one further down. */

.wizard {
    display: grid; grid-template-columns: minmax(0, 2fr) minmax(0, 1fr);
    gap: var(--space-component);
    align-items: start;
}
.wizard__rail { position: sticky; top: var(--space-component); }

.wstep__head {
    display: flex; align-items: baseline; gap: 0.5rem;
    font-size: var(--step-2); margin-bottom: var(--space-component);
}
.wstep__num { color: var(--accent); }
.wstep__note { margin-top: var(--gap-2); font-size: var(--step--1); color: var(--ink-muted); }

.wopts { display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--gap-3); }
.wopts--select, .wopts--label { grid-template-columns: repeat(auto-fit, minmax(11rem, 1fr)); }

/* The whole option is the label, so the click target is the card. 44px is a
   floor here, not a target — every card clears it several times over. */
.wopt {
    display: flex; flex-direction: column; gap: 0.75rem;
    padding-bottom: var(--gap-2);
    border-bottom: 2px solid var(--line);
    cursor: pointer;
    transition: border-color var(--fast) var(--ease);
}
.wopt:hover { border-bottom-color: var(--ink-muted); }
.wopt.is-chosen { border-bottom-color: var(--accent); }
.wopt:has(.wopt__input:focus-visible) { outline: 2px solid var(--accent); outline-offset: 4px; }

.wopt__media { display: block; aspect-ratio: 16 / 10; }
.wopt__media img { width: 100%; height: 100%; object-fit: contain; }
.wopt__chip {
    display: block; width: 100%; height: 100%;
    border-radius: var(--radius); background: var(--chip);
}

.wopt__body { display: flex; flex-direction: column; gap: 0.4rem; }
.wopt__name {
    display: flex; align-items: center; gap: 0.45rem;
    font-family: var(--font-display); font-size: var(--step-0); font-weight: 700;
}
/* The tick is the second, non-colour signal that an option is chosen. */
.wopt__tick { display: none; color: var(--accent); }
.wopt__tick .icon { width: 18px; height: 18px; }
.wopt.is-chosen .wopt__tick { display: inline-flex; }
.wopt.is-chosen .wopt__name { color: var(--accent); }
.wopt__desc { font-size: var(--step--1); color: var(--ink-muted); line-height: 1.5; }
.wopt__delta { font-size: var(--step--1); color: var(--ink-muted); }

.wnav {
    display: flex; justify-content: space-between; gap: var(--gap-3);
    margin-top: var(--space-section);
}
.wnav__spacer { flex: 1; }

/* The rail ---------------------------------------------------------------- */

.rail__eyebrow { margin-bottom: var(--gap-2); }
.rail__stage {
    margin: 0 0 var(--space-component);
    border-radius: var(--radius-lg); overflow: hidden;
    background: var(--stage-glow, var(--surface));
    aspect-ratio: 12 / 7;
    display: grid; place-items: center;
}
.rail__stage .photo { object-fit: contain; padding: 8%; }

.railsteps { display: grid; }
.railstep__link {
    display: grid; grid-template-columns: 1rem minmax(0, auto) minmax(0, 1fr);
    align-items: center; gap: 0.85rem;
    min-height: 44px; padding-block: 0.55rem;
    text-decoration: none;
}
.railstep__dot {
    width: 14px; height: 14px; border-radius: 50%;
    background: var(--line);
    box-shadow: 0 22px 0 -6px var(--line);
    transition: background-color var(--fast) var(--ease);
}
.railstep:last-child .railstep__dot { box-shadow: none; }
.railstep.is-answered .railstep__dot,
.railstep.is-current .railstep__dot { background: var(--accent); }
.railstep__name { font-size: var(--step--1); color: var(--ink-muted); }
.railstep.is-answered .railstep__name,
.railstep.is-current .railstep__name { color: var(--accent); font-weight: 700; }
.railstep__value {
    text-align: right;
    font-family: var(--font-display); font-size: var(--step--1); font-weight: 700;
}
.railstep__delta { color: var(--accent); font-weight: 400; }

.railtotal {
    margin-top: var(--space-component); padding-block: var(--gap-3);
    border-top: 1px solid var(--line); border-bottom: 1px solid var(--line);
}
.railtotal__price {
    display: flex; align-items: baseline; gap: 0.6rem;
    font-family: var(--font-display); font-size: var(--step-2);
}
.railtotal__vat { font-size: var(--step--1); color: var(--ink-muted); font-weight: 400; }
.railtotal__ship {
    display: flex; align-items: center; gap: 0.5rem;
    margin-top: 0.5rem; font-size: var(--step--1); color: var(--accent);
}
.railtotal__tick .icon, .railnote__icon .icon { width: 16px; height: 16px; }

.railnotes { margin-top: var(--gap-3); display: grid; gap: 0.75rem; }
.railnote {
    display: flex; align-items: flex-start; gap: 0.6rem;
    font-size: var(--step--1); color: var(--ink-muted);
}
.railnote__icon { color: var(--accent); flex: none; margin-top: 0.2em; }
.rail__missing { margin-top: var(--gap-3); font-size: var(--step--1); color: var(--ink-muted); }

/* --- Responsive for everything above --------------------------------------- */

@media (max-width: 1080px) {
    .wizard { grid-template-columns: 1fr; }
    .wizard__rail { position: static; }
    .swatchgrid { grid-template-columns: repeat(4, 1fr); }
    .steps { grid-template-columns: repeat(2, 1fr); }
}

@media (max-width: 900px) {
    .band__inner { grid-template-columns: 1fr; min-height: 0; }
    .band__aside { display: none; }
    .band::after {
        background: var(--band-scrim-narrow, linear-gradient(180deg, var(--scrim) 0%, var(--scrim) 100%));
    }
    .trustbar__list { grid-template-columns: repeat(2, 1fr); }
    .wopts { grid-template-columns: repeat(2, 1fr); }
}

@media (max-width: 560px) {
    .swatchgrid { grid-template-columns: repeat(2, 1fr); }
    .steps { grid-template-columns: 1fr; }
    .wnav { flex-direction: column-reverse; }
    .wnav .btn { width: 100%; }
    .railstep__link { grid-template-columns: 1rem minmax(0, 1fr); }
    .railstep__value { grid-column: 2; text-align: left; }
}

/* Reduced motion: the only motion in these modules is the swatch and option
   transitions, which collapse to instant state changes. */
@media (prefers-reduced-motion: reduce) {
    .wopt, .railstep__dot { transition: none; }
}

/* --- Platform catalogue -----------------------------------------------------
   /plugins and /plugins/:code. Mode is Read, not Persuade: medium density, one
   column of prose at a sane measure, a fact panel beside it, and motion level 1
   — hover and focus only, nothing on entrance. Boldness is spent on typography;
   the only card on either page is the fact panel.
---------------------------------------------------------------------------- */

.platform { border-top: 1px solid var(--line); }

/* Identity on the left — kind, name, path — and the one-sentence description
   held beside it, so the row fills the measure instead of trailing off. */
.platform__row {
    position: relative;
    display: grid;
    grid-template-columns: minmax(0, 24rem) minmax(0, 1fr);
    column-gap: clamp(2rem, 5vw, 4rem);
    padding-block: var(--space-component);
    border-bottom: 1px solid var(--line);
}
.platform__row > .origin { grid-column: 1; grid-row: 1; }

.platform__name {
    grid-column: 1; grid-row: 2;
    margin-top: 0.35rem;
    font-size: var(--step-2);
}
.platform__link {
    text-decoration: none;
    transition: color var(--fast) var(--ease);
}
/* Stretched hit area: the whole row is clickable, but only the title is
   focusable, so the tab order stays one stop per package. */
.platform__link::after { content: ""; position: absolute; inset: 0; }
.platform__row:hover .platform__link { color: var(--accent); }
.platform__link:focus-visible { outline-offset: 4px; }

.platform__summary {
    grid-column: 2; grid-row: 1 / span 3;
    align-self: center;
    color: var(--ink-muted);
    max-width: 46ch;
}
.platform__path {
    grid-column: 1; grid-row: 3;
    margin-top: 0.6rem;
    font-size: var(--step--1); color: var(--ink-muted);
}

.platform__foot {
    margin-top: var(--space-component);
    max-width: 62ch;
    font-size: var(--step--1);
    color: var(--ink-muted);
}

/* --- Detail layout ---------------------------------------------------------- */

.platdoc {
    display: grid;
    grid-template-columns: minmax(0, 1fr) 19rem;
    gap: var(--space-component) clamp(2rem, 5vw, 4rem);
    align-items: start;
}

/* The aside comes first in the markup so the tab order is identical at every
   width and always matches what is on screen. Grid places it, not source order. */
.platdoc__main { grid-column: 1; grid-row: 1; min-width: 0; }

.platdoc__heading {
    margin-top: var(--space-section);
    padding-top: var(--gap-3);
    border-top: 1px solid var(--line);
    font-size: var(--step-2);
}
.platdoc__lede { margin-top: 0.5rem; color: var(--ink-muted); max-width: 62ch; }

.platgroup { margin-top: var(--space-component); }
.platgroup__title { font-size: var(--step-1); }
.platgroup__note { margin-top: 0.35rem; color: var(--ink-muted); max-width: 62ch; }

.platgroup__list { margin-top: var(--gap-2); display: grid; gap: 0.45rem; }
.platgroup__item {
    position: relative;
    padding-left: 1.15rem;
    color: var(--ink-muted);
    max-width: 68ch;
}
.platgroup__item::before {
    content: ""; position: absolute; left: 0; top: 0.72em;
    width: 0.4rem; height: 1px; background: var(--line);
}
.platgroup__item b { color: var(--ink); font-weight: 600; }

/* --- Demo links ------------------------------------------------------------- */

.platdemo { margin-top: var(--gap-3); border-top: 1px solid var(--line); }
.platdemo__row {
    display: flex; align-items: baseline; gap: var(--gap-2); flex-wrap: wrap;
    padding: 0.75rem 0;
    border-bottom: 1px solid var(--line);
}
.platdemo__link {
    flex: none;
    min-width: 9rem;
    font-family: var(--font-display); font-weight: 600;
    text-decoration-color: color-mix(in srgb, var(--accent) 45%, transparent);
    color: var(--accent);
}
.platdemo__note { flex: 1 1 20rem; font-size: var(--step--1); color: var(--ink-muted); }

/* --- Fact panel ------------------------------------------------------------- */

.platdoc__aside { grid-column: 2; grid-row: 1; position: sticky; top: 6rem; }

.factcard {
    padding: var(--gap-3);
    background: var(--surface);
    border: 1px solid var(--line);
    border-radius: var(--radius-lg);
}
.factcard__title { font-size: var(--step-0); font-weight: 700; }

.factlist { margin: var(--gap-2) 0 0; }
.factlist__row + .factlist__row { margin-top: 0.7rem; padding-top: 0.7rem; border-top: 1px solid var(--line); }
.factlist__key {
    font-family: var(--font-display); font-size: var(--step--1); font-weight: 600;
    color: var(--ink-muted);
}
.factlist__val {
    margin: 0.15rem 0 0;
    font-size: var(--step--1);
    overflow-wrap: anywhere;
}

.factcard__sub {
    margin-top: var(--gap-3); padding-top: var(--gap-2);
    border-top: 1px solid var(--line);
    font-family: var(--font-display); font-size: var(--step--1); font-weight: 700;
}
.factcard__links { margin-top: 0.4rem; display: grid; gap: 0.3rem; font-size: var(--step--1); }
.factcard__links a { color: var(--accent); }

/* --- Rendered changelog -----------------------------------------------------
   Markdown straight off disk, headings already demoted one level by the page so
   the outline stays sequential under the Changelog H2.
---------------------------------------------------------------------------- */

.changelog { margin-top: var(--gap-3); max-width: 68ch; color: var(--ink-muted); }
.changelog > p { margin-top: var(--gap-2); }
.changelog > p:first-child { margin-top: 0; }

.changelog h3 {
    margin-top: var(--space-component);
    padding-top: var(--gap-2);
    border-top: 1px solid var(--line);
    font-size: var(--step-1);
    color: var(--ink);
}
.changelog h4 {
    margin: var(--gap-2) 0 0;
    font-family: var(--font-display); font-size: var(--step-0); font-weight: 600;
    letter-spacing: -0.015em;
    color: var(--ink);
}
.changelog ul { margin-top: 0.4rem; display: grid; gap: 0.35rem; }
.changelog li { position: relative; padding-left: 1.15rem; }
.changelog li::before {
    content: ""; position: absolute; left: 0; top: 0.72em;
    width: 0.4rem; height: 1px; background: var(--line);
}
.changelog a { color: var(--accent); }
.changelog table { border-collapse: collapse; margin-top: var(--gap-2); font-size: var(--step--1); }
.changelog th, .changelog td { text-align: left; padding: 0.4rem 1rem 0.4rem 0; border-bottom: 1px solid var(--line); }
.changelog th { font-family: var(--font-display); font-weight: 600; color: var(--ink); }

.platgroup__item code, .changelog code, .platform__path code, .factlist__val code, .prose code {
    padding: 0.05em 0.3em;
    background: var(--ink-soft);
    border-radius: var(--radius);
    font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
    font-size: 0.88em;
}

@media (max-width: 900px) {
    /* One column, and the facts land first — they answer "what am I looking at"
       before the prose does. No reordering needed; that is the source order. */
    .platdoc { grid-template-columns: 1fr; }
    .platdoc__aside, .platdoc__main { grid-column: 1; grid-row: auto; }
    .platdoc__aside { position: static; }
}

@media (max-width: 760px) {
    /* One column: the description follows the name it describes. */
    .platform__row { grid-template-columns: 1fr; }
    .platform__row > .origin,
    .platform__name,
    .platform__summary,
    .platform__path { grid-column: 1; grid-row: auto; }
    .platform__summary { margin-top: 0.4rem; align-self: auto; }
}

@media (max-width: 560px) {
    .platdemo__link { min-width: 0; flex: 1 1 100%; }
}

/* --- Stat row, pull quote, config chips -------------------------------------
   Three small blocks the newer sections share. */

.statrow {
    display: flex; flex-wrap: wrap; gap: var(--space-component);
    margin-top: var(--space-component);
    padding-top: var(--gap-3);
    border-top: 1px solid var(--line);
}
/* Value above label visually, label first in the DOM — a <dl> reads dt then
   dd, and the number means nothing before you know what it counts. */
.statrow__item { display: flex; flex-direction: column-reverse; }
.statrow__value {
    margin: 0;
    font-family: var(--font-display); font-size: var(--step-2);
    color: var(--accent); line-height: 1;
}
.statrow__label {
    font-family: var(--font-eyebrow, var(--font-display));
    font-size: var(--step--1); color: var(--ink-muted);
    margin-top: 0.35rem;
}

.pullquote {
    margin: var(--space-component) 0 0;
    padding-left: var(--gap-3);
    border-left: 2px solid var(--accent);
}
.pullquote__text {
    margin: 0;
    font-family: var(--font-display-alt, var(--font-display));
    font-size: var(--step-1); font-style: italic; line-height: 1.4;
}

.configchips { display: flex; flex-wrap: wrap; gap: 0.35rem 0.5rem; margin-top: 0.4rem; }
.configchip {
    font-size: var(--step--1); color: var(--ink-muted); line-height: 1.35;
}
.configchip:not(:last-child)::after { content: ' ·'; color: var(--line); }
.configchip__delta { color: var(--accent); }

/* --- Wordmark with a mark, cart pill, socials -------------------------------
   Three header/footer variants a storefront usually wants. Structure only. */

.wordmark { display: inline-flex; align-items: center; gap: 0.65rem; }
.wordmark__mark { display: inline-flex; flex: none; }
.wordmark__mark img { width: 32px; height: 32px; }

/* "BASKET 2" rather than a bare icon — the count is legible instead of being
   a 17px dot, and the control clears 44px on its own. */
.cartpill {
    display: inline-flex; align-items: center; gap: 0.55rem;
    min-height: 44px; padding: 0 0.9rem;
    background: var(--accent); color: var(--accent-ink);
    border-radius: var(--radius); text-decoration: none;
    transition: background-color var(--fast) var(--ease);
}
.cartpill:hover { background: color-mix(in srgb, var(--accent) 88%, var(--ink)); }
.cartpill .icon { width: 19px; height: 19px; }
.cartpill__label { font-family: var(--font-eyebrow, var(--font-display)); font-size: var(--step--1); font-weight: 700; }
.cartpill__count {
    display: grid; place-items: center;
    min-width: 22px; height: 22px; padding: 0 5px;
    background: color-mix(in srgb, var(--accent-ink) 22%, transparent);
    border-radius: 11px;
    font-family: var(--font-display); font-size: 0.7rem; font-weight: 700;
}

.socials { display: flex; gap: 0.5rem; }
.social {
    display: grid; place-items: center;
    width: 44px; height: 44px;
    border: 1px solid var(--line); border-radius: 50%;
    color: var(--ink-muted); text-decoration: none;
    transition: color var(--fast) var(--ease), border-color var(--fast) var(--ease);
}
.social:hover { color: var(--accent); border-color: var(--accent); }
.social .icon { width: 18px; height: 18px; }

@media (max-width: 720px) {
    .cartpill__label { display: none; }
    .cartpill { padding: 0 0.7rem; }
}

/* --- Merchandising blocks ---------------------------------------------------
   One block = one selection rule. The band variant sits under a product or the
   basket; the compact variant lives in the shop sidebar under the filters,
   where there is a quarter of the width and no room for a four-up grid.
---------------------------------------------------------------------------- */

.selection { padding-block: var(--space-section); border-top: 1px solid var(--line); }
.selection + .selection { border-top: 0; padding-top: 0; }

.selection--compact {
    padding-block: var(--space-component) 0;
    border-top: 1px solid var(--line);
    margin-top: var(--space-component);
}
.selection--compact .sechead { margin-bottom: var(--gap-2); }
.selection--compact .sechead__title--sub { font-size: var(--step-1); }

/* One column in the sidebar: a product card at a quarter width is unreadable,
   so the compact grid stacks instead of shrinking. */
.pgrid--compact { grid-template-columns: 1fr; gap: var(--gap-2); }

.producercard__link { text-decoration: none; }
.producercard__link:hover { color: var(--accent); }

@media (max-width: 1080px) {
    .pgrid--compact { grid-template-columns: repeat(2, 1fr); }
}
@media (max-width: 560px) {
    .pgrid--compact { grid-template-columns: 1fr; }
}

/* --- Checkout merchandising block -------------------------------------------
   Sits under the order summary, in the summary's column. It is a sibling of
   #orderSummary rather than a child, because that element's contents are
   replaced on every delivery and payment change.
---------------------------------------------------------------------------- */

.checkout__side {
    position: sticky; top: 6rem;
    align-self: start;
    display: grid; gap: var(--space-component);
}
/* The summary keeps its card; the wrapper above owns the stickiness now. */
.checkout__side .checkout__summary { position: static; top: auto; }

.selection--checkout { padding-block: 0; border-top: 0; }
.selection--checkout .sechead { margin-bottom: var(--gap-2); }

@media (max-width: 900px) {
    .checkout__side { position: static; }
}

/* --- Compact merchandising row ----------------------------------------------
   Sidebar, checkout, side cart. Two columns, control under the price: a third
   column for the control squeezes the title to four lines, because
   "Choose options" is a long label to stand beside a product name.
---------------------------------------------------------------------------- */

.srow {
    display: grid;
    grid-template-columns: 56px minmax(0, 1fr);
    align-items: start;
    gap: var(--gap-2);
    padding: 0.7rem 0;
}
.srow + .srow { border-top: 1px solid var(--line); }

.srow__media {
    position: relative; display: block; width: 56px;
    border-radius: var(--radius); overflow: hidden; background: var(--ink-soft);
}
.srow__media .photo { aspect-ratio: 1; }
.badge--sale-sm { font-size: 0.62rem; padding: 0.1rem 0.3rem; }

.srow__body { min-width: 0; }
.srow__name {
    font-family: var(--font-display); font-size: var(--step--1);
    font-weight: 600; letter-spacing: -0.01em; line-height: 1.25;
}
.srow__name a { text-decoration: none; }
.srow__name a:hover { color: var(--accent); }

.srow__price {
    margin-top: 0.1rem;
    font-family: var(--font-display); font-size: var(--step--1); font-weight: 700;
}
.srow__price .price__was { font-weight: 500; color: var(--ink-muted); margin-right: 0.25rem; }

.srow__add { margin-top: 0.45rem; }
.srow__add .btn, a.srow__add, button.srow__add {
    display: flex; width: 100%; min-height: 44px;
    padding-inline: 0.8rem; font-size: var(--step--1);
}

/* Rows already separate themselves; the grid gap would double the rhythm. */
.selection--checkout .pgrid--compact,
.selection--sidebar .pgrid--compact { display: block; }

/* --- Missing photography ----------------------------------------------------
   Shown when a product has no photo and demo imagery is off. Deliberately
   plain: it should read as an absence, not as a designed element, so nobody
   mistakes it for finished work. */

.photo--empty {
    display: block; width: 100%;
    background:
        repeating-linear-gradient(135deg,
            var(--ink-soft) 0 10px, transparent 10px 20px),
        var(--surface);
    border: 1px dashed var(--line);
}

/* --- Composited configurator preview ----------------------------------------
   A stack of transparent PNGs in one box. Every layer fills the same square, so
   alignment comes from the artwork being drawn on a shared canvas — there is
   deliberately no per-layer offset here, because a position nudged in CSS is a
   position nobody can reproduce when they redraw the art. */

.knife {
    position: relative;
    display: block;
    margin: 0;
    width: 100%;
    aspect-ratio: 12 / 7;
}
.knife__layer {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    object-fit: contain;
    /* Layers are art, not photographs: never crop, never stretch. */
}

/* A wizard step that cannot be opened yet. Dimmed and not interactive — the
   dot stays visible so the customer can still see how many steps remain. */
.railstep.is-locked .railstep__link { cursor: default; }
.railstep.is-locked .railstep__name,
.railstep.is-locked .railstep__value { color: var(--ink-dim, var(--ink-muted)); }

/* --- Touch targets ----------------------------------------------------------
   Below 900px every link that is a row in a list — footer navigation, legal
   links, breadcrumbs, the inline text links — gets enough vertical padding to
   clear 44px. They were 22–26px tall, which is a comfortable click with a mouse
   and a coin toss with a thumb.

   Padding rather than min-height so the targets grow without pushing the rows
   apart, and negative margin on the inline ones so the visual rhythm is
   unchanged — the target grows, the layout does not move. */

@media (max-width: 900px) {
    .footer__list a,
    .footer__legal-links a,
    .footer__direct a,
    .crumbs__link,
    .mainnav__link {
        display: inline-flex;
        align-items: center;
        min-height: 44px;
    }

    /* Inline links inside running text keep their line box; give them a bigger
       hit area without changing where the text sits. */
    .textlink {
        padding-block: 0.7rem;
        margin-block: -0.7rem;
    }

    /* The wordmark is a link too, and it is the one every customer aims at to
       get home. */
    .wordmark { min-height: 44px; }

    /* The card's photo link is aria-hidden and out of the tab order, so the
       title link is the ONLY way into a product — and it was 26px tall, which
       is the single most-tapped control in the shop. */
    .pcard__title a {
        display: inline-flex;
        align-items: center;
        min-height: 44px;
    }

    /* The star picker's real target is the label; the radio beside it is 1x1
       by design. The label was ~30px, which is a thumb-width of guesswork on
       the one control that decides whether a review gets written at all. */
    .starpick__star {
        display: inline-flex;
        align-items: center;
        justify-content: center;
        min-width: 44px;
        min-height: 44px;
        padding: 0;
    }

    /* "Create one" / "Reset it" under the sign-in form. */
    .authform__alt a {
        display: inline-flex;
        align-items: center;
        min-height: 44px;
    }
}

/* --- Sold out ---------------------------------------------------------------
   A one-off that has gone. The photo desaturates and the control reads as a
   statement rather than an action — but the card stays fully legible, because
   a sold piece is still the best evidence of what the maker makes. */

.pcard--sold .pcard__media .photo { filter: grayscale(0.85) brightness(0.75); }
.btn.is-sold {
    background: transparent;
    border-color: var(--line);
    color: var(--ink-muted);
    cursor: default;
}
.btn.is-sold:hover { background: transparent; border-color: var(--line); color: var(--ink-muted); }

/* --- Online payment -------------------------------------------------------- */
/* A notice that carries an action: text left, button right, stacking on narrow
   screens. Used by the order confirmation's "Pay now" block. */
.notice--action { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: var(--gap-2); }
.notice--action p { margin: 0; }

/* The gateway form area on /payment/:hash. */
.payform { display: grid; gap: var(--gap-2); margin-top: var(--gap-2); }
.payform__note { margin: 0; font-size: var(--step--1); line-height: 1.45; color: var(--ink-muted); }
.payform__gateway { display: grid; gap: var(--gap-2); justify-items: start; }
.payform__paypal { width: 100%; max-width: 420px; }
.payform__error { margin: 0; font-size: var(--step--1); font-weight: 600; color: var(--ink); }
.payform__error:empty { display: none; }
/* Stripe embedded: the iframe takes the column; reserve height so the page
   does not jump while it loads. */
.payform__gateway--embedded { justify-items: stretch; }
.payform__stripe { min-height: 420px; width: 100%; }
/* Stripe card form: Stripe's fields fill the column; the button is ours. */
.payform__gateway--card { justify-items: stretch; }
.payform__gateway--card .btn { justify-self: start; }
.payform__card { min-height: 96px; }
/* Card fields inside the checkout's payment fieldset, under the option list. */
.payform--inline { margin-top: var(--gap-2); }
.payform--inline[hidden] { display: none; }

/* ===========================================================================
   Builder elements — partials/builder/*.htm

   What a page or post laid out in Content › Pages / Posts renders as. Every
   option an editor can pick in the builder is a class here, and every class
   resolves to a token, so a child retints all of it from theme.css and no
   page can leave the design system.
   =========================================================================== */

/* --- Container ------------------------------------------------------------ */

.build--none    { padding-block: 0; }
.build--compact { padding-block: var(--space-component); }
.build--section { padding-block: var(--space-section); }

.build--bg-surface { background: var(--surface); border-block: 1px solid var(--line); }
.build--bg-tinted  { background: var(--accent-soft); }

/* Dark and accent backgrounds re-scope the text tokens inside them, so every
   element's default colour (which reads --ink, --ink-muted, --line) turns
   light without each one knowing it sits on a dark section. */
.build--bg-dark {
    background: var(--announce-bg);
    --ink: var(--announce-ink);
    --ink-muted: color-mix(in srgb, var(--announce-ink) 80%, transparent);
    --line: color-mix(in srgb, var(--announce-ink) 22%, transparent);
    color: var(--ink);
}
.build--bg-accent {
    background: var(--accent);
    --ink: var(--accent-ink);
    --ink-muted: color-mix(in srgb, var(--accent-ink) 82%, transparent);
    --line: color-mix(in srgb, var(--accent-ink) 25%, transparent);
    color: var(--ink);
}
/* Inside, the accent would vanish against itself: markers and links use the
   text colour instead. Set on the children so the background keeps it. */
/* The accent's own colour, kept for the children before they re-scope it. */
.build--bg-accent { --accent-base: var(--accent); }
.build--bg-dark > *, .build--bg-accent > * { --accent: var(--ink); }
/* A solid button inside turns light, so its text must turn dark — on an accent
   section the accent itself, elsewhere the theme's darkest surface. */
.build--bg-dark > * { --accent-ink: var(--announce-bg); }
.build--bg-accent > * { --accent-ink: var(--accent-base); }

/* A custom colour (inline background-color) gets a tone class from the
   builder: dark means light text reads better on it. */
.build--tone-dark {
    --ink: #FFFFFF;
    --ink-muted: rgba(255, 255, 255, 0.8);
    --line: rgba(255, 255, 255, 0.22);
    color: var(--ink);
}
.build--tone-dark > * { --accent: var(--ink); --accent-ink: var(--announce-bg); }


/* Two outer containers on the same background read as one section: the
   second drops the rule between them. */
.build--bg-surface + .build--bg-surface { border-top: 0; }

.build__inner--page    { width: min(100% - (var(--gutter) * 2), var(--shell)); margin-inline: auto; }
.build__inner--reading { width: min(100% - (var(--gutter) * 2), 46rem); margin-inline: auto; }
.build__inner--full    { width: 100%; }

/* A container inside another: a group in its column. A background gives it
   an inset so the colour has an edge to sit inside. */
.build-group.build--bg-surface,
.build-group.build--bg-tinted,
.build-group.build--bg-dark,
.build-group.build--bg-accent,
.build-group.build--bg-custom { padding: var(--gap-3); border-radius: var(--radius-lg); border: 0; }
.build-group.build--bg-surface { border: 1px solid var(--line); }

.build-grid { display: grid; grid-template-columns: minmax(0, 1fr); align-items: start; }
.build-grid--2   { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.build-grid--3   { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.build-grid--4   { grid-template-columns: repeat(4, minmax(0, 1fr)); }
.build-grid--1-2 { grid-template-columns: minmax(0, 1fr) minmax(0, 2fr); }
.build-grid--2-1 { grid-template-columns: minmax(0, 2fr) minmax(0, 1fr); }

.build-grid--gap-small  { gap: var(--gap-2); }
.build-grid--gap-medium { gap: var(--gap-3); }
.build-grid--gap-large  { gap: var(--space-component); }

/* Columns in a row need more air between them than lines in a stack. */
.build-grid:not(.build-grid--stack).build-grid--gap-small  { column-gap: var(--gap-3); }
.build-grid:not(.build-grid--stack).build-grid--gap-medium { column-gap: var(--space-component); }
.build-grid:not(.build-grid--stack).build-grid--gap-large  { column-gap: calc(var(--space-component) * 2); }

.build-grid--align-center { align-items: center; }
.build-grid--align-end    { align-items: end; }

@media (max-width: 900px) {
    .build-grid--4 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (max-width: 720px) {
    .build-grid--2, .build-grid--3, .build-grid--4,
    .build-grid--1-2, .build-grid--2-1 { grid-template-columns: minmax(0, 1fr); }
    .build-grid:not(.build-grid--stack) { column-gap: 0; }
}

/* --- Title ---------------------------------------------------------------- */

.build-title {
    margin: 0;
    font-family: var(--font-display);
    font-weight: 700;
    line-height: 1.08;
    color: var(--ink);
    text-wrap: balance;
}
.build-title--xl { font-size: var(--step-4); letter-spacing: -0.045em; line-height: 1.02; }
.build-title--l  { font-size: var(--step-3); letter-spacing: -0.035em; }
.build-title--m  { font-size: var(--step-2); letter-spacing: -0.025em; }
.build-title--s  { font-size: var(--step-1); letter-spacing: -0.015em; line-height: 1.2; }

/* --- Text ----------------------------------------------------------------- */

.build-text { max-width: 62ch; }
.build-text--lead  { font-size: var(--step-1); line-height: 1.55; color: var(--ink); }
.build-text--small { font-size: var(--step--1); line-height: 1.55; }

/* The global reset strips list bullets for navigation; prose wants them back. */
.build-text ul, .build-text ol { margin-top: var(--gap-2); padding-left: 1.25em; }
.build-text ul { list-style: disc; }
.build-text ol { list-style: decimal; }
.build-text ul:first-child, .build-text ol:first-child { margin-top: 0; }
.build-text li + li { margin-top: 0.35em; }
.build-text li::marker { color: var(--accent); }
.build-text a { color: var(--ink); }
.build-text strong { color: var(--ink); font-weight: 600; }

.build-align--center { text-align: center; }
.build-align--right  { text-align: right; }
.build-text.build-align--center { margin-inline: auto; }
.build-text.build-align--center :is(ul, ol) { list-style-position: inside; padding-left: 0; }

/* --- Image ---------------------------------------------------------------- */

.build-image { margin: 0; }
.build-image__img { width: 100%; height: auto; border-radius: var(--radius-lg); background: var(--ink-soft); }
.build-image__caption {
    margin-top: var(--gap-1);
    font-size: var(--step--1);
    line-height: 1.45;
    color: var(--ink-muted);
}
.build-image__empty { display: grid; place-items: center; border-radius: var(--radius-lg); }
.build-image__hint { font-family: var(--font-display); font-size: var(--step--1); font-weight: 600; color: var(--ink-muted); }

/* --- Background image ------------------------------------------------------
   A real <img> behind the content (partials/builder/container.htm). The
   overlay is a layer over it; Darken also re-scopes the text tokens
   (.build--tone-dark), so default text turns light. */

.build--has-image { position: relative; isolation: isolate; }
.build__bg { position: absolute; inset: 0; z-index: -1; overflow: hidden; }
.build__bgimg { width: 100%; height: 100%; object-fit: cover; object-position: center; }
.build__bgimg--top { object-position: center top; }
.build__bgimg--bottom { object-position: center bottom; }
.build__bg--darken::after,
.build__bg--darker::after,
.build__bg--lighten::after { content: ''; position: absolute; inset: 0; }
.build__bg--darken::after  { background: rgba(0, 0, 0, 0.42); }
.build__bg--darker::after  { background: rgba(0, 0, 0, 0.62); }
.build__bg--lighten::after { background: color-mix(in srgb, var(--bg) 78%, transparent); }
.build-group.build--has-image { padding: var(--space-component); border-radius: var(--radius-lg); overflow: hidden; }

/* --- Button ----------------------------------------------------------------- */

.build-button { margin: 0; }
.build-button--center { text-align: center; }
.build-button--right  { text-align: right; }
.build-button--full .btn { width: 100%; }
.btn--large { min-height: 56px; padding: 0 2rem; font-size: var(--step-1); }

/* --- Shop elements (Forge.ShopBlocks) -------------------------------------
   Products, Product spotlight and Categories. The cards and tiles are the
   shop's own; this only lays them out, on the same breakpoints as .pgrid. */

.build-products--grid .build-products__track { display: grid; gap: var(--gap-3); grid-template-columns: repeat(4, minmax(0, 1fr)); }
.build-products--grid.build-products--cols-2 .build-products__track { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.build-products--grid.build-products--cols-3 .build-products__track { grid-template-columns: repeat(3, minmax(0, 1fr)); }

/* Slider: one row that scrolls sideways and snaps to a card. */
.build-products--slider { position: relative; }
.build-products--slider .build-products__track {
    --per: 4;
    display: grid; grid-auto-flow: column; gap: var(--gap-3);
    grid-auto-columns: calc((100% - (var(--per) - 1) * var(--gap-3)) / var(--per));
    overflow-x: auto; overscroll-behavior-x: contain;
    scroll-snap-type: x mandatory; scroll-padding-inline: 0;
    scrollbar-width: thin;
    padding-bottom: var(--gap-1);
}
.build-products--slider.build-products--cols-2 .build-products__track { --per: 2; }
.build-products--slider.build-products--cols-3 .build-products__track { --per: 3; }
.build-products--slider .build-products__item { scroll-snap-align: start; }
.build-products__track:focus-visible { outline-offset: 6px; }
.build-products__nav { display: flex; justify-content: flex-end; gap: var(--gap-1); margin-top: var(--gap-2); }
.build-products__arrow { border: 1px solid var(--line); border-radius: 50%; }
.build-products__arrow:disabled { opacity: 0.35; cursor: default; }

.build-spotlight {
    display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    gap: var(--space-component) calc(var(--space-component) * 1.5); align-items: center;
}
.build-spotlight--photo-right .build-spotlight__media { order: 2; }
.build-spotlight__media { position: relative; display: block; overflow: hidden; border-radius: var(--radius-lg); background: var(--ink-soft); }
.build-spotlight__media .photo { aspect-ratio: 4 / 5; }
.build-spotlight__title { margin-top: var(--gap-2); font-size: var(--step-3); letter-spacing: -0.03em; text-wrap: balance; }
.build-spotlight__title a { text-decoration: none; }
.build-spotlight__title a:hover { text-decoration: underline; text-decoration-thickness: 1px; text-underline-offset: 0.12em; }
.build-spotlight .pcard__rating { margin-top: var(--gap-1); }
.build-spotlight__price { margin-top: var(--gap-2); font-family: var(--font-display); font-weight: 700; font-size: var(--step-2); }
.build-spotlight__lede { margin-top: var(--gap-2); color: var(--ink-muted); max-width: 52ch; }
.build-spotlight__actions { display: flex; flex-wrap: wrap; align-items: center; gap: var(--gap-2) var(--gap-3); margin-top: var(--space-component); }
.build-spotlight__add .btn { min-height: 52px; padding: 0 1.8rem; }
.build-spotlight__add .btn--quiet { background: var(--accent); border-color: var(--accent); color: var(--accent-ink); }
.build-spotlight__add .btn--quiet:hover { background: color-mix(in srgb, var(--accent) 86%, var(--ink)); }
.build-spotlight__more { font-family: var(--font-display); font-weight: 600; }

.build-cats--cols-2 { grid-template-columns: repeat(2, 1fr); }
.build-cats--cols-4 { grid-template-columns: repeat(4, 1fr); }

/* In the builder's preview: where an element is waiting for a choice. */
.build-placeholder {
    display: grid; place-items: center; min-height: 160px; padding: var(--gap-3);
    border: 1px dashed var(--line); border-radius: var(--radius-lg); background: var(--ink-soft);
}
.build-placeholder--tall { min-height: 320px; }
.build-placeholder__text { font-family: var(--font-display); font-size: var(--step--1); font-weight: 600; color: var(--ink-muted); text-align: center; }

@media (max-width: 1080px) {
    .build-products--grid .build-products__track,
    .build-products--grid.build-products--cols-3 .build-products__track { grid-template-columns: repeat(2, minmax(0, 1fr)); }
    .build-products--slider .build-products__track { --per: 2.3 !important; }
    .build-cats--cols-4 { grid-template-columns: repeat(2, 1fr); }
}
@media (max-width: 720px) {
    .build-spotlight { grid-template-columns: 1fr; }
    .build-spotlight--photo-right .build-spotlight__media { order: 0; }
    .build-cats--cols-2, .build-cats--cols-4 { grid-template-columns: 1fr; }
}
@media (max-width: 560px) {
    .build-products--grid .build-products__track,
    .build-products--grid.build-products--cols-2 .build-products__track,
    .build-products--grid.build-products--cols-3 .build-products__track { grid-template-columns: 1fr; }
    .build-products--slider .build-products__track { --per: 1.25 !important; }
}

/* --- A product description laid out in the builder ------------------------
   pages/product.htm: the template keeps its heading; the builder's sections
   follow it without a section's worth of space in between. */

.section--desc-built { padding-bottom: 0; }
.section--desc-built .build-root > .build:first-child.build--section { padding-top: var(--space-component); }
.section--desc-built .build-root > .build:first-child.build--compact { padding-top: var(--gap-2); }

/* --- HTML ----------------------------------------------------------------- */

.build-html { min-width: 0; }
.build-html > :first-child { margin-top: 0; }
.build-html img, .build-html iframe, .build-html video { max-width: 100%; }
.build-html--empty {
    display: grid; place-items: center; min-height: 96px;
    border: 1px dashed var(--line); border-radius: var(--radius-lg);
}
.build-html__hint { font-family: var(--font-display); font-size: var(--step--1); font-weight: 600; color: var(--ink-muted); }

/* --- Text colour -----------------------------------------------------------
   On a title or text element; Default follows the section. After the element
   rules above, which set their own colour with the same specificity. */

.build-color--muted  { color: var(--ink-muted); }
.build-color--accent { color: var(--accent); }
.build-text.build-color--accent strong, .build-text.build-color--accent a,
.build-text.build-color--custom strong, .build-text.build-color--custom a { color: inherit; }

/* --- Posts ---------------------------------------------------------------- */

.shell--reading { width: min(100% - (var(--gutter) * 2), 46rem); margin-inline: auto; }

.post__head { padding-bottom: 0; }
.post__title { margin-top: var(--gap-2); font-size: var(--step-4); letter-spacing: -0.045em; line-height: 1.02; }
.post__lead { margin-top: var(--gap-3); font-size: var(--step-1); line-height: 1.55; color: var(--ink-muted); max-width: 52ch; }
.post__foot { padding-bottom: var(--space-section); }
.post__back { font-family: var(--font-display); font-weight: 600; }

/* The builder's first container sits under the post header, not a section
   away from it. */
.post--theme .build-root > .build:first-child.build--section { padding-top: var(--space-component); }

.postgrid { display: grid; grid-template-columns: repeat(auto-fill, minmax(18rem, 1fr)); gap: var(--space-component) var(--gap-3); }
.postcard__link { display: block; text-decoration: none; }
.postcard__media { display: block; overflow: hidden; border-radius: var(--radius-lg); background: var(--ink-soft); }
.postcard__media .photo { aspect-ratio: 3 / 2; transition: transform var(--slow) var(--ease); }
.postcard__link:hover .postcard__media .photo { transform: scale(1.02); }
.postcard__date { margin-top: var(--gap-2); }
.postcard__title { margin-top: var(--gap-1); font-size: var(--step-1); letter-spacing: -0.02em; line-height: 1.2; }
.postcard__link:hover .postcard__title { text-decoration: underline; text-decoration-thickness: 1px; text-underline-offset: 0.18em; }
.postcard__excerpt { margin-top: var(--gap-1); color: var(--ink-muted); font-size: var(--step--1); line-height: 1.55; }

@media (prefers-reduced-motion: reduce) {
    .postcard__media .photo { transition: none; }
    .postcard__link:hover .postcard__media .photo { transform: none; }
}

/* Discount lines in the totals (a bundle, a coupon) — the amount off reads in
   the accent, so a saving is told apart from a fee by more than its sign. */
.carttotals__row--discount span:last-child { color: var(--accent); font-weight: 600; }

/* A line priced by an offer (an upsell, a bundle) says so under its name, in
   the accent — the reason for the lower price, next to the price. */
.cartline__meta--offer,
.drawerline__meta--offer,
.summary__variant--offer { color: var(--accent); font-weight: 600; }

/* A saving that waits for its product (a parent-mode upsell on its own) */
.cartline__meta--waiting,
.drawerline__meta--waiting,
.summary__variant--waiting { color: var(--ink-muted); font-weight: 600; }

/* --- Free-shipping bar — partials/cart/free-shipping-bar.htm ---------------
   A line of text and a thin track that fills in the accent. The fill is a
   transform, not a width, so a basket change animates without layout. */
.freeship-bar { margin-bottom: var(--gap-2); }
.freeship-bar__text { font-size: var(--step--1); font-weight: 600; }
.freeship-bar__track {
    display: block; height: 6px; margin-top: 0.4rem; overflow: hidden;
    border-radius: 999px; background: var(--ink-soft);
}
.freeship-bar__fill {
    display: block; height: 100%; background: var(--accent);
    transform-origin: left center; transform: scaleX(var(--freeship, 0));
    transition: transform var(--slow) var(--ease);
}
.freeship-bar--done .freeship-bar__text { color: var(--accent); }
@media (prefers-reduced-motion: reduce) { .freeship-bar__fill { transition: none; } }

/* --- Checkout: consents, a different delivery address, the guarantee ------ */
.consents { display: grid; gap: var(--gap-1); margin-top: var(--space-component); }
.consent { display: flex; align-items: flex-start; gap: 0.6rem; min-height: 44px; padding-block: 0.6rem; cursor: pointer; font-size: var(--step--1); }
.consent input { width: 20px; height: 20px; margin-top: 0.1rem; flex: none; accent-color: var(--accent); }
.consent a { color: var(--accent); }
.field__optional { font-weight: 400; color: var(--ink-muted); }
.shipto { margin-top: var(--gap-2); }
.shipto__fields { display: none; margin-top: var(--gap-1); }
.shipto:has(.shipto__toggle:checked) .shipto__fields { display: block; }
.checkout__guarantee {
    display: flex; align-items: center; justify-content: center; gap: 0.5rem;
    margin-top: var(--space-component); padding-top: var(--gap-3); border-top: 1px solid var(--line);
    font-size: var(--step--1); color: var(--ink-muted); text-align: center;
}
.checkout__guarantee .icon { width: 20px; height: 20px; color: var(--accent); flex: none; }

/* --- Checkout: coupon box -------------------------------------------------- */
.coupon { margin-top: var(--gap-3); padding: var(--gap-2); border: 1px solid var(--line); border-radius: var(--radius-lg); background: var(--surface); }
.coupon__title { display: flex; align-items: center; gap: 0.5rem; font-family: var(--font-display); font-size: var(--step--1); font-weight: 700; }
.coupon__title .icon { width: 18px; height: 18px; color: var(--accent); }
.coupon__row { display: flex; gap: var(--gap-1); margin-top: var(--gap-1); }
.coupon__input { flex: 1; min-width: 0; text-transform: none; }
.coupon__btn { flex: none; }
.coupon__applied { display: flex; align-items: center; justify-content: space-between; margin-top: var(--gap-1); }
.coupon__problem { margin-top: 0.4rem; font-size: var(--step--1); color: var(--ink-muted); }

/* --- Offers from selection rules ------------------------------------------ */
.srow__pct { font-size: 0.75rem; font-weight: 600; color: var(--ink-muted); }
.add-size { min-height: 40px; margin-bottom: 0.4rem; font-size: var(--step--1); }

/* The hidden offer at checkout — the one dark block in the column */
.hoffer {
    margin-top: var(--gap-3); padding: var(--gap-3); border-radius: var(--radius-lg);
    background: var(--ink); color: var(--bg); text-align: center;
}
.hoffer__title { font-family: var(--font-display); font-size: var(--step-1); font-weight: 800; letter-spacing: -0.02em; }
.hoffer__media { width: min(14rem, 70%); margin: var(--gap-2) auto 0; border-radius: var(--radius-lg); overflow: hidden; }
.hoffer__media .photo { aspect-ratio: 4 / 5; }
.hoffer__name { margin-top: var(--gap-2); font-family: var(--font-display); font-weight: 700; }
.hoffer__pitch { margin-top: 0.3rem; font-size: var(--step--1); color: color-mix(in srgb, var(--bg) 80%, var(--ink)); }
.hoffer__price { display: flex; align-items: baseline; justify-content: center; gap: 0.5rem; margin-top: var(--gap-1); }
.hoffer__price del { color: color-mix(in srgb, var(--bg) 60%, var(--ink)); }
.hoffer__price strong { font-size: var(--step-1); }
.hoffer__pct { padding: 0.15rem 0.5rem; border-radius: var(--radius); background: var(--accent); color: var(--accent-ink); font-weight: 800; }
.hoffer .add-size { margin-top: var(--gap-1); }
.hoffer__add { width: 100%; margin-top: var(--gap-1); background: var(--accent); color: var(--accent-ink); border-color: var(--accent); }

/* --- Checkout: a method's note, and the appointment it books -------------- */
.choice__note { display: block; margin-top: 0.3rem; font-size: var(--step--1); color: var(--ink-muted); }
.choice__slot { display: none; grid-template-columns: 1fr 1fr; gap: var(--gap-1) var(--gap-2); margin: 0.25rem 0 var(--gap-1); padding: var(--gap-2); border: 1px solid var(--line); border-radius: var(--radius-lg); }
.choice:has(input:checked) + .choice__slot { display: grid; }
.choice__slot-title { grid-column: 1 / -1; font-family: var(--font-display); font-size: var(--step--1); font-weight: 700; }
.choice__slot .field__error { grid-column: 1 / -1; }

/* --- Focused basket and checkout: the step bar ----------------------------- */
.stepbar {
    position: relative; display: flex; align-items: center; justify-content: center;
    min-height: 4rem; padding: 0 var(--gutter); border-bottom: 1px solid var(--line); background: var(--bg);
}
.stepbar__back { position: absolute; left: var(--gutter); }
.stepbar__back .icon { transform: rotate(180deg); }
.stepbar__steps { display: flex; align-items: center; gap: 0.6rem; list-style: none; margin: 0; padding: 0; }
.stepbar__step { font-family: var(--font-display); font-size: var(--step--1); font-weight: 600; color: var(--ink-muted); }
.stepbar__step + .stepbar__step::before { content: '›'; margin-right: 0.6rem; color: var(--line); }
.stepbar__step.is-current { color: var(--ink); font-weight: 800; }
.stepbar__step a { color: inherit; text-decoration: none; }
.stepbar__step a:hover { color: var(--accent); }

/* --- Basket page: side column, delivery choice ----------------------------- */
.cartlist__side { display: grid; gap: var(--gap-2); align-content: start; }
.cartship { margin: var(--gap-1) 0; padding: 0; border: 0; }
.cartship__legend { margin-bottom: 0.4rem; font-family: var(--font-display); font-size: var(--step--1); font-weight: 700; }
.cartship__option { display: flex; align-items: center; gap: 0.6rem; min-height: 40px; font-size: var(--step--1); cursor: pointer; }
.cartship__option input { accent-color: var(--accent); }
.cartship__cost { margin-left: auto; font-weight: 600; }

/* --- Shop: the category's photo, its description, colour swatches, badges - */
/* Full bleed without a horizontal scrollbar: 100vw counts the scrollbar, so the
   page clips sideways overflow (clip, not hidden — sticky headers keep working). */
html { overflow-x: clip; }
.section:has(> .shell > .shophero:first-child) { padding-top: 0; }
.shophero { position: relative; isolation: isolate; margin: 0 calc(50% - 50vw) var(--space-component); min-height: clamp(14rem, 26vw, 22rem); display: flex; align-items: flex-end; color: var(--bg); }
.shophero__img { position: absolute; inset: 0; z-index: -2; width: 100%; height: 100%; object-fit: cover; }
.shophero::after { content: ''; position: absolute; inset: 0; z-index: -1; background: linear-gradient(180deg, transparent 30%, color-mix(in srgb, var(--ink) 70%, transparent) 100%); }
.shophero__body { width: min(100% - (var(--gutter) * 2), var(--shell)); margin-inline: auto; padding-block: var(--gap-3); }
.shophero .crumbs__link, .shophero .crumbs__item, .shophero .crumbs__current, .shophero .sechead__note { color: inherit; }
.shophero .sechead { margin-bottom: 0; }
.shophero .sortctl__label { color: inherit; }
.shopdesc { margin-top: var(--space-component); padding-top: var(--gap-3); border-top: 1px solid var(--line); font-size: var(--step--1); max-width: none; }

.filters__list--swatches { display: grid; grid-template-columns: repeat(auto-fill, minmax(3.25rem, 1fr)); gap: var(--gap-1); }
.fchoice--swatch { display: grid; justify-items: center; gap: 0.25rem; text-align: center; cursor: pointer; }
.fchoice--swatch .fchoice__input { position: absolute; opacity: 0; width: 1px; height: 1px; }
.fchoice__swatch { width: 44px; height: 44px; border-radius: var(--radius-lg); background: var(--swatch); border: 1px solid var(--line); }
.fchoice--swatch .fchoice__input:checked + .fchoice__swatch { box-shadow: 0 0 0 2px var(--bg), 0 0 0 4px var(--ink); }
.fchoice--swatch .fchoice__input:focus-visible + .fchoice__swatch { outline: 2px solid var(--accent); outline-offset: 3px; }
.fchoice--swatch .fchoice__name { font-size: 0.72rem; color: var(--ink-muted); }

.badges { position: absolute; top: 0.5rem; right: 0.5rem; z-index: 1; display: grid; justify-items: end; gap: 0.25rem; }
.badge { padding: 0.15rem 0.45rem; border-radius: var(--radius); font-family: var(--font-display); font-size: 0.7rem; font-weight: 700; }
.badge--accent { background: var(--accent); color: var(--accent-ink); }
.badge--ink { background: var(--ink); color: var(--bg); }

/* --- Back in stock: the request on the product page ----------------------- */
.stockreq { margin-top: var(--gap-3); padding: var(--gap-2); border: 1px dashed var(--line); border-radius: var(--radius-lg); }
.stockreq__title { display: flex; align-items: center; gap: 0.5rem; font-family: var(--font-display); font-size: var(--step--1); font-weight: 700; }
.stockreq__title .icon { width: 18px; height: 18px; color: var(--accent); }
.stockreq__row { display: flex; flex-wrap: wrap; gap: var(--gap-1); margin-top: var(--gap-1); }
.stockreq__size { flex: 0 0 7rem; }
.stockreq__email { flex: 1 1 12rem; min-width: 0; }

/* --- Product page: 30-day lowest price, size guide ------------------------- */
.lowest30 { margin-top: 0.25rem; font-size: 0.75rem; color: var(--ink-muted); }
.sizeguide__open { display: inline-flex; align-items: center; gap: 0.6rem; min-height: 44px; margin-top: var(--gap-1); padding: 0; border: 0; background: none; font-family: var(--font-display); font-size: var(--step--1); font-weight: 700; cursor: pointer; }
.sizeguide__icon { display: grid; place-items: center; width: 34px; height: 34px; border-radius: 50%; background: var(--ink); color: var(--bg); }
.sizeguide__icon .icon { width: 18px; height: 18px; }
.sizeguide__open:hover { color: var(--accent); }
.sizeguide { width: min(40rem, calc(100vw - 2rem)); max-height: min(44rem, calc(100dvh - 2rem)); padding: 0; border: 0; border-radius: var(--radius-lg); background: var(--bg); color: var(--ink); }
.sizeguide::backdrop { background: rgba(0, 0, 0, 0.5); }
.sizeguide__head { display: flex; align-items: center; justify-content: space-between; padding: var(--gap-1) var(--gap-2); border-bottom: 1px solid var(--line); }
.sizeguide__title { font-family: var(--font-display); font-size: var(--step-0); font-weight: 800; }
.sizeguide__body { padding: var(--gap-2); max-width: none; overflow-x: auto; }
.sizeguide__body table { width: 100%; border-collapse: collapse; font-size: var(--step--1); }
.sizeguide__body th, .sizeguide__body td { padding: 0.45rem 0.6rem; border-bottom: 1px solid var(--line); text-align: left; }
.sizeguide__body th { font-family: var(--font-display); }

/* --- Header dropdowns (theme option "Menu") -------------------------------- */
.mainnav__item { position: relative; }
.mainnav__item--sub > .mainnav__link .icon { width: 12px; height: 12px; transform: rotate(90deg); }
.mainnav__sub {
    display: none; position: absolute; left: 50%; top: 100%; z-index: 50; transform: translateX(-50%);
    min-width: 13rem; padding: 0.5rem 0; list-style: none; margin: 0;
    background: var(--bg); border: 1px solid var(--line); border-radius: var(--radius-lg); box-shadow: var(--shadow-2);
}
.mainnav__item--sub:hover > .mainnav__sub,
.mainnav__item--sub:focus-within > .mainnav__sub { display: block; }
.mainnav__sublink { display: block; padding: 0.55rem 1rem; color: var(--ink); text-decoration: none; font-size: var(--step--1); white-space: nowrap; }
.mainnav__sublink:hover { background: var(--surface); color: var(--accent); }
@media (max-width: 760px) {
    .mainnav__sub { display: block; position: static; transform: none; border: 0; box-shadow: none; padding: 0 0 0.5rem 1rem; }
    .mainnav__item--sub > .mainnav__link .icon { display: none; }
}

/* The picker's availability: "In stock" in the theme's --ok colour when it has one */
.vpick__note[data-state="in"] { color: var(--ok, var(--ink)); font-weight: 600; }
.build-products--static .build-products__nav { display: none; }
