/* =========================================================================
   BALM & BANNER -- the shared design system
   Created 2026-09-15.

   Every drift problem in this project traces to one cause: four pages each
   carrying a private copy of the system. The mobile topbar fix that landed only
   on index and left the other three overflowing. The --measure token that was
   never applied to policies, so its prose ran to 95 characters a line. Three
   pages whose :root held a SUBSET of index's tokens. Each was found separately,
   by hand, after Ben noticed.

   One file makes "fix all the pages" structural instead of something I have to
   remember. Anything page-specific -- the shop's tiles and buy block, the
   gallery's plates and lightbox -- stays inline on that page.

   Relative font URLs below resolve against THIS file's location, which is the
   site root, so they are the same paths the pages used inline.
   ========================================================================= */

/* ---- Self-hosted faces, carried over verbatim ------------------------
   All six are OFL or Apache 2.0. Dropping these in the rewrite would have
   rendered the whole site in Georgia and Impact with no error anywhere --
   caught by bt-design-state.py, which checks each live design's press face
   is actually obtainable. */
    @font-face {
        font-family: 'Cormorant Garamond';
        font-style: normal;
        font-weight: 300 700;
        font-display: swap;
        src: url('fonts/cormorant-garamond-500.woff2') format('woff2');
        unicode-range: U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD;
    }
    @font-face {
        font-family: 'Cormorant Garamond';
        font-style: italic;
        font-weight: 300 700;
        font-display: swap;
        src: url('fonts/cormorant-garamond-400-italic.woff2') format('woff2');
        unicode-range: U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD;
    }
    @font-face {
        font-family: 'Gloock';
        font-style: normal;
        font-weight: 400;
        font-display: swap;
        src: url('fonts/gloock-400.woff2') format('woff2');
        unicode-range: U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD;
    }
    @font-face {
        font-family: 'Alfa Slab One';
        font-style: normal;
        font-weight: 400;
        font-display: swap;
        src: url('fonts/alfa-slab-one-400.woff2') format('woff2');
        unicode-range: U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD;
    }
    @font-face {
        font-family: 'Anton';
        font-style: normal;
        font-weight: 400;
        font-display: swap;
        src: url('fonts/anton-400.woff2') format('woff2');
        unicode-range: U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD;
    }
    @font-face {
        font-family: 'Black Ops One';
        font-style: normal;
        font-weight: 400;
        font-display: swap;
        src: url('fonts/black-ops-one-400.woff2') format('woff2');
        unicode-range: U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD;
    }


/* ---- Faces for the held designs -------------------------------------------
   Added 2026-09-21. DESIGN-HOLDS.md told a releaser to add each of these by
   appending &family= to the deferred Google Fonts link -- a link deleted on
   2026-09-14 when the live faces were self-hosted. Five of six held designs named
   a face that was not on disk, so following the documented procedure would have
   shipped the design in a fallback: the word on the shop not matching the word on
   the shirt, because the cut file carries the real letterforms.

   bt-design-state.py could not catch it. It checks designs WITH A CARD on the
   page; held designs have no card, so it skips exactly the six at risk.

   All five are OFL or Apache -- both permit redistribution -- and each was
   verified by wOF2 magic bytes before being referenced here, because a 404 saved
   under a font filename is invisible until the site renders in Georgia. */
    @font-face {
        font-family: 'Cinzel';
        font-style: normal;
        font-weight: 600;
        font-display: swap;
        src: url('fonts/cinzel-600.woff2') format('woff2');
        unicode-range: U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD;
    }
    @font-face {
        font-family: 'Archivo Black';
        font-style: normal;
        font-weight: 400;
        font-display: swap;
        src: url('fonts/archivo-black-400.woff2') format('woff2');
        unicode-range: U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD;
    }
    @font-face {
        font-family: 'Fjalla One';
        font-style: normal;
        font-weight: 400;
        font-display: swap;
        src: url('fonts/fjalla-one-400.woff2') format('woff2');
        unicode-range: U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD;
    }
    @font-face {
        font-family: 'Ultra';
        font-style: normal;
        font-weight: 400;
        font-display: swap;
        src: url('fonts/ultra-400.woff2') format('woff2');
        unicode-range: U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD;
    }
    @font-face {
        font-family: 'Stardos Stencil';
        font-style: normal;
        font-weight: 700;
        font-display: swap;
        src: url('fonts/stardos-stencil-700.woff2') format('woff2');
        unicode-range: U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD;
    }

/* ---- Tokens -------------------------------------------------------------
   Three is the organising number, per Ben. Token NAMES are unchanged so the
   tile system and the commerce script keep working; the VALUES are warmer and
   deeper, and the type scale now has real contrast at the top end. */
:root {
    /* Type. The old top step was 5rem. Every reference site Ben chose shares one
       trait -- very few elements at extreme size contrast -- and a 5rem ceiling
       cannot produce that. --t-4xl is new and is the page's voice. */
    --t-xs:   0.75rem;
    --t-sm:   0.8125rem;
    --t-base: 1.0625rem;
    --t-md:   1.1875rem;
    --t-lg:   1.5rem;
    --t-xl:   2rem;
    --t-2xl:  clamp(2.25rem, 5vw, 3.5rem);
    --t-3xl:  clamp(3rem, 8vw, 6rem);
    --t-4xl:  clamp(3.75rem, 13vw, 9rem);

    /* Space, on the same 3-based rhythm, extended upward. Premium pages are
       mostly made of space, and the old scale topped out at 6rem. */
    --s-1: 0.375rem;
    --s-2: 0.75rem;
    --s-3: 1rem;
    --s-4: 1.5rem;
    --s-5: 2.25rem;
    --s-6: 3rem;
    --s-7: 4.5rem;
    --s-8: 6rem;
    --s-9: 9rem;
    --s-section: clamp(4rem, 10vw, 8rem);

    /* Ink. Warm near-black rather than neutral #1a1a1a: a true grey against a
       cream ground reads cold and slightly cheap, because nothing in print is
       neutral grey on cream. */
    --ink:       #15140E;
    --ink-muted: #453F33;
    --ink-faint: #6B6454;        /* 4.6:1 on --surface-sunk, checked */
    --text-charcoal: var(--ink); /* legacy alias, still referenced */

    /* Surface. A warm bone, not near-white. The card sits slightly ABOVE the
       page rather than level with it, which is what makes it read as an object. */
    --surface:      #F4F0E6;
    --surface-sunk: #EAE3D4;
    --surface-rise: #FBF9F3;
    --bg-linen:     var(--surface);
    --ink-press:    #0E0D0A;     /* the tile black -- deliberately not --ink */
    --ink-reverse:  #FBF9F3;     /* warm white, never pure #fff, on the tiles */

    --accent-crimson: #7A1C1C;
    --accent-lit:     #9B2B2B;
    --border-grid:    #D9CFB9;
    --border-strong:  #BCAE91;

    --font-sans: system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
    --font-serif: 'Cormorant Garamond', Georgia, serif;
    --press-gloock: 'Gloock', 'Cormorant Garamond', Georgia, serif;
    --press-anton: 'Anton', Impact, sans-serif;
    --press-slab: 'Alfa Slab One', Georgia, serif;
    --press-blackops: 'Black Ops One', Impact, sans-serif;
    /* Held designs. Fallbacks are deliberate and each is the nearest shape available,
       so a face that somehow fails still reads as the right KIND of letterform. */
    --press-cinzel: 'Cinzel', 'Cormorant Garamond', Georgia, serif;
    --press-archivo: 'Archivo Black', Impact, sans-serif;
    --press-fjalla: 'Fjalla One', Impact, sans-serif;
    --press-ultra: 'Ultra', Georgia, serif;
    --press-stardos: 'Stardos Stencil', Impact, sans-serif;

    --measure: 34em;             /* em, not ch: ch is the width of "0" in the
                                    ELEMENT's own size, so one token meant 528px
                                    on prose and 881px on a heading. */
    --measure-tight: 22em;

    --ease: cubic-bezier(0.22, 0.61, 0.36, 1);
}

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

/* 50vw counts the scrollbar and the page's usable width does not, so every
   full-bleed block overhangs by exactly the scrollbar width. Both elements need
   it: an overflow set on body alone propagates to the viewport and body itself
   keeps computing as visible. clip, not hidden -- clip creates no scroll
   container, so the sticky topbar survives. */
html, body { overflow-x: clip; }

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

body {
    margin: 0;
    padding: 0 1rem;
    background: var(--surface);
    color: var(--ink);
    font-family: var(--font-serif);
    font-size: var(--t-md);
    line-height: 1.65;
    font-feature-settings: "kern" 1, "liga" 1, "onum" 1;
    -webkit-font-smoothing: antialiased;
    text-rendering: optimizeLegibility;
}

/* Prose is set in the serif at 19px rather than the UI sans at 16. It is more
   legible at that size for an older reader, not less, and it is the difference
   between a page that was typeset and a page that was styled. The sans is kept
   for chrome -- labels, buttons, specs, nav -- where neutrality is the job. */

img { max-width: 100%; display: block; }

::selection { background: var(--accent-crimson); color: var(--ink-reverse); }

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

.container { max-width: 1180px; margin: 0 auto; }

/* Every in-page anchor must clear the sticky topbar, or "Skip to content" and the
   cart link both land with their target hidden underneath it. The bar is ~69px on
   desktop; --s-7 is 72px, which clears it with 3px to spare. Dropped in the rewrite
   and caught by bt-verify-anchors.py before it shipped. */
[id] { scroll-margin-top: var(--s-7); }


.skip-link {
    position: absolute; left: -9999px; top: 0;
    background: var(--ink); color: var(--ink-reverse);
    padding: var(--s-2) var(--s-3); z-index: 100;
    text-decoration: none; font-family: var(--font-sans);
    font-size: var(--t-sm); font-weight: 600;
}
.skip-link:focus { left: 1rem; top: 1rem; }

/* ---- Shared typographic parts ------------------------------------------- */

/* The small letterspaced cap line that labels a section. Real tracking, because
   caps set at text tracking always look crowded. */
.eyebrow {
    font-family: var(--font-sans);
    font-size: var(--t-xs);
    font-weight: 700;
    letter-spacing: 0.24em;
    text-transform: uppercase;
    color: var(--accent-crimson);
    margin: 0 0 var(--s-3);
}

.section-heading {
    font-family: var(--font-serif);
    font-size: var(--t-2xl);
    font-weight: 500;
    line-height: 1.05;
    letter-spacing: -0.015em;   /* large serif type needs negative tracking */
    margin: 0 0 var(--s-4);
    text-wrap: balance;
    max-width: 18ch;
}

.section-note {
    font-size: var(--t-base);
    color: var(--ink-muted);
    max-width: var(--measure);
    margin: 0 0 var(--s-6);
}

/* Links in prose, selected by structure rather than by page-specific class so the
   shared sheet stays page-agnostic.
   Links in prose: the underline draws from the left on hover rather than simply
   appearing. Background-size animates on the compositor; text-decoration does not. */
a { color: inherit; }
/* A link whose only child is an image must not carry a text underline. */
a:has(> img), a:has(> picture) { text-decoration: none; }
.prose-link, .section-note a, main p a, main li a, main dd a, footer a {
    color: var(--accent-crimson);
    text-decoration: none;
    background-image: linear-gradient(var(--accent-crimson), var(--accent-crimson));
    background-repeat: no-repeat;
    background-position: 0 100%;
    background-size: 100% 1px;
    padding-bottom: 1px;
}
@media (prefers-reduced-motion: no-preference) {
    .prose-link, .section-note a, main p a, main li a, main dd a, footer a {
        transition: background-size 260ms var(--ease);
    }
    .prose-link:hover, .section-note a:hover, main p a:hover, main li a:hover,
    main dd a:hover, footer a:hover { background-size: 0% 1px; }
}

.site-section { padding: var(--s-section) 0; }

/* Line length. A text column that runs the full page reads as unedited whatever
   else is right about it -- policies was at 1180px, roughly 150 characters a line.
   This is a container, not a blanket rule on `main > section`: on the shop page
   those sections hold the product grid and the full-bleed story, and capping them
   at a reading measure would wreck the layout. 34em resolves against the body
   size, unlike ch, which is the width of "0" in each ELEMENT's own size and so
   meant 528px on a paragraph and 881px on a heading. */
.prose { max-width: var(--measure); }
.prose h2, .prose h3 { max-width: var(--measure-tight); }
/* The ruled divider above already provides the break, so the section must not
   add its own full top pad on top of it. */
.site-section.section-tight-top { padding-top: 0; }

/* ---- Topbar ------------------------------------------------------------- */
.topbar {
    position: sticky; top: 0; z-index: 50;
    display: flex; align-items: center; justify-content: space-between;
    gap: var(--s-3);
    background: color-mix(in srgb, var(--surface) 88%, transparent);
    -webkit-backdrop-filter: blur(10px) saturate(1.4);
    backdrop-filter: blur(10px) saturate(1.4);
    border-bottom: 1px solid var(--border-grid);
    padding: var(--s-2) var(--s-3);
    margin: 0 -1rem;
}

.topbar-mark {
    font-family: var(--font-serif);
    font-size: var(--t-base); font-weight: 600;
    letter-spacing: 0.1em; text-transform: uppercase;
    color: var(--ink); text-decoration: none; white-space: nowrap;
    display: inline-flex; align-items: center; min-height: 44px;
}

.topbar-nav { display: flex; align-items: center; gap: var(--s-2); }
.topbar-links { display: flex; gap: var(--s-1); }
.topbar-links a {
    color: var(--ink-muted); text-decoration: none;
    font-family: var(--font-sans);
    font-size: var(--t-xs); text-transform: uppercase; letter-spacing: 0.14em;
    font-weight: 600; padding: var(--s-2) var(--s-2);
    display: inline-flex; align-items: center; min-height: 44px;
}
@media (prefers-reduced-motion: no-preference) {
    .topbar-links a { transition: color 180ms var(--ease); }
}
.topbar-links a:hover { color: var(--accent-crimson); }

/* ---- Masthead ------------------------------------------------------------ */
header {
    padding: var(--s-7) 0 var(--s-5);
    border-bottom: none;
    text-align: left;
}
@media (max-width: 700px) {
    header { padding-top: var(--s-6); }
}

h1 {
    font-family: var(--font-serif);
    font-size: var(--t-3xl);
    font-weight: 400;
    line-height: 0.92;
    letter-spacing: -0.025em;
    margin: 0;
}
/* The ampersand is the mark. Cormorant's italic ampersand is a far finer glyph
   than its roman one -- it is the reason this wordmark works -- so it is set
   italic and optically sized against the capitals around it. */
/* The brand name is a link on every page except the shop. */
h1 a { color: inherit; text-decoration: none; }

h1 .amp {
    font-style: italic;
    font-weight: 300;
    color: var(--accent-crimson);
    font-size: 0.92em;
    padding: 0 0.04em;
}

.tagline {
    font-family: var(--font-sans);
    font-size: var(--t-xs);
    letter-spacing: 0.24em;
    text-transform: uppercase;
    color: var(--ink-faint);
    margin: var(--s-4) 0 0;
    font-weight: 600;
}

@media (min-width: 768px) {
    /* The wordmark holds one column and the tagline counterweights it across the
       other two, sharing a baseline. A small element balancing a large one across
       distance is what asymmetric balance actually is; the masthead sitting in the
       left quarter with three quarters empty beside it was vacancy. */
    header {
        display: grid;
        grid-template-columns: repeat(3, 1fr);
        column-gap: var(--s-6);
        align-items: end;
    }
    header h1 { grid-column: 1 / span 2; margin: 0; }
    header .tagline { grid-column: 3; margin: 0; transform: translateY(-0.35em); }
}

/* ---- Buttons ------------------------------------------------------------- */
.order-button, .submit-button {
    display: block; width: 100%;
    min-height: 52px;
    padding: var(--s-2) var(--s-4);
    font-family: var(--font-sans);
    font-size: var(--t-xs);
    font-weight: 700;
    letter-spacing: 0.2em;
    text-transform: uppercase;
    color: var(--ink-reverse);
    background: var(--ink);
    border: 1px solid var(--ink);
    border-radius: 0;
    cursor: pointer;
    text-align: center;
    position: relative;
}
@media (prefers-reduced-motion: no-preference) {
    .order-button, .submit-button {
        transition: background-color 180ms var(--ease), transform 90ms var(--ease);
    }
}
.order-button:hover, .submit-button:hover { background: var(--accent-crimson); border-color: var(--accent-crimson); }
/* A real press. Buttons that do not move under the finger feel like images. */
.order-button:active, .submit-button:active { transform: translateY(1px); }
.order-button:disabled {
    background: var(--surface-sunk); color: var(--ink-faint);
    border-color: var(--border-grid); cursor: default; transform: none;
}
.order-button:disabled:hover { background: var(--surface-sunk); border-color: var(--border-grid); }

.submit-button { background: var(--accent-crimson); border-color: var(--accent-crimson); }
.submit-button:hover { background: var(--ink); border-color: var(--ink); }

/* ---- Footer -------------------------------------------------------------- */
footer {
    border-top: 1px solid var(--border-grid);
    padding: var(--s-7) 0 var(--s-8);
    font-family: var(--font-sans);
    font-size: var(--t-sm);
    color: var(--ink-muted);
}
footer > div { margin-bottom: var(--s-3); }
footer > div:last-child { margin-bottom: 0; }

.social-links { display: flex; gap: var(--s-4); flex-wrap: wrap; }
.social-links a {
    font-size: var(--t-xs); font-weight: 700;
    letter-spacing: 0.16em; text-transform: uppercase;
    min-height: 44px; display: inline-flex; align-items: center;
}
.contact-fast { font-size: var(--t-base); color: var(--ink); }
/* Recovered when the shared system was extracted: without these the masthead
   brand link and the contact line fall back to the browser's blue underline,
   because `a { color: inherit }` sets color but not decoration. */
/* Vertical padding on an inline link grows the hit area without moving the line,
   which matters most here: Ben says calling is the fastest way to reach him, and
   the phone number was a 21px target. WCAG 2.5.8 would exempt these as inline in
   a sentence; that is an excuse, not a reason. */
.contact-fast a, .footer-contact a {
    color: var(--ink); text-decoration: none; font-weight: 600;
    /* inline-flex + min-height rather than padding, because padding only reaches 44px
       for one font-size: the same 12px gave 45px in the shop footer and 43px on
       policies, where the contact line is set smaller. This is the pattern the nav
       links already use and it holds at any size. */
    display: inline-flex; align-items: center; min-height: 44px;
    padding: 0 0.1rem;
}
.contact-fast a:hover, .footer-contact a:hover { color: var(--accent-crimson); }
.social-links a:hover { color: var(--accent-crimson); }
.policy-statement {
    max-width: var(--measure); line-height: 1.6;
    color: var(--ink-faint); font-size: var(--t-sm);
}
.policy-statement strong { color: var(--ink-muted); }
.policy-link {
    display: inline-flex; align-items: center; min-height: 44px;
    margin-right: var(--s-4);
    font-size: var(--t-xs); font-weight: 700;
    letter-spacing: 0.14em; text-transform: uppercase;
    color: var(--accent-crimson); text-decoration: none;
}
.policy-link:hover { color: var(--ink); }
.legal-line { font-size: var(--t-xs); color: var(--ink-faint); letter-spacing: 0.04em; }

/* ---- Sticky cart bar ----------------------------------------------------- */
.cartbar {
    position: fixed; left: 0; right: 0; bottom: 0; z-index: 60;
    background: var(--ink);
    color: var(--ink-reverse);
    padding: var(--s-2) var(--s-3);
    transform: translateY(110%);
    font-family: var(--font-sans);
}
@media (prefers-reduced-motion: no-preference) {
    .cartbar { transition: transform 300ms var(--ease); }
}
.cartbar[data-open="1"] { transform: translateY(0); }
.cartbar-summary {
    max-width: 1180px; margin: 0 auto;
    display: flex; align-items: center; justify-content: space-between;
    gap: var(--s-3);
    font-size: var(--t-sm);
    font-variant-numeric: tabular-nums;
}
.cartbar a, .cartbar-summary a, .cartbar-summary button {
    color: var(--ink-reverse); font-family: var(--font-sans);
    font-size: var(--t-xs); font-weight: 700;
    letter-spacing: 0.16em; text-transform: uppercase;
    background: none; border: 1px solid color-mix(in srgb, var(--ink-reverse) 40%, transparent);
    padding: var(--s-2) var(--s-3); min-height: 44px; cursor: pointer;
    text-decoration: none; display: inline-flex; align-items: center;
}
.cartbar a:hover, .cartbar-summary a:hover, .cartbar-summary button:hover {
    background: var(--ink-reverse); color: var(--ink);
}
body.has-cart { padding-bottom: 5rem; }

/* ---- Order status -------------------------------------------------------- */
.order-status {
    border: 1px solid var(--border-strong);
    background: var(--surface-rise);
    padding: var(--s-4);
    margin: var(--s-5) 0 0;
}
#order-status-head {
    font-family: var(--font-sans); font-size: var(--t-xs);
    font-weight: 700; letter-spacing: 0.2em; text-transform: uppercase;
    color: var(--accent-crimson); margin-bottom: var(--s-2);
}
#order-status-body { font-size: var(--t-base); color: var(--ink); }
#order-status-ref { font-family: var(--font-sans); font-size: var(--t-xs); color: var(--ink-faint); }

/* ---- Divider mark -------------------------------------------------------
   A character alone on a line is not a divider, it is a stray glyph -- it was
   floating in ~220px of stacked padding with nothing to relate to. Given rules
   either side it becomes a real printer's mark: the rules carry the eye across
   and the cross is what interrupts them. */
.divider-marker {
    display: flex;
    align-items: center;
    gap: var(--s-4);
    color: var(--accent-crimson);
    font-family: var(--font-serif);
    font-size: var(--t-lg);
    line-height: 1;
    margin: 0;
    padding: var(--s-4) 0;      /* was --s-6: 48px of air each side of a 24px mark */
}
.divider-marker::before, .divider-marker::after {
    content: "";
    flex: 1 1 auto;
    height: 1px;
    background: var(--border-grid);
}

/* ---- Narrow screens ------------------------------------------------------ */
@media (max-width: 430px) {
    .topbar { padding: var(--s-1) var(--s-2); gap: var(--s-1); }
    .topbar-mark { font-size: var(--t-sm); }
    .topbar-links a { padding: var(--s-2) var(--s-1); letter-spacing: 0.1em; }
}
@media (max-width: 380px) {
    /* 360px is a very common Android width (Pixel, Galaxy) and the wordmark plus
       three links still overran it. */
    .topbar-mark { font-size: var(--t-xs); }
}

/* ---- The list ------------------------------------------------------------
   Added 2026-09-25. Three sales have happened and not one of those buyers can
   be contacted a second time; this is the fix, and it is deliberately the
   quietest element in the footer. Bench's constraint was that it must not
   compete with the checkout on a product page, so it sits below every buy card
   rather than beside one. If the analytics ever show people using it, it has
   earned a stronger placement -- until then it does not get to shout. */
.list-signup {
    border-top: 1px solid var(--border-grid);
    padding-top: var(--s-5);
    max-width: 34rem;
}
.list-signup-pitch {
    margin: 0 0 var(--s-3);
    font-size: var(--t-sm);
    color: var(--ink-muted);
}
.list-signup-form {
    display: flex;
    flex-wrap: wrap;
    gap: var(--s-2);
}
.list-signup-form input[type="email"] {
    flex: 1 1 14rem;
    min-height: 44px;
    padding: var(--s-2) var(--s-3);
    font-family: var(--font-sans);
    font-size: var(--t-base);   /* 17px: under 16px iOS zooms the page on focus */
    color: var(--ink);
    background: var(--surface-rise);
    border: 1px solid var(--border-grid);
    border-radius: 0;
    -webkit-appearance: none;
    appearance: none;
}
/* The browser default placeholder grey measures 4.38:1 here, under the 4.5:1
   floor. The field has a real (screen-reader) label, so this is a low-vision
   sighted-user problem rather than an assistive-tech one -- which makes it a
   color fix, not a markup one. --ink-faint is the token already carried for
   exactly this job. */
.list-signup-form input[type="email"]::placeholder { color: var(--ink-faint); opacity: 1; }
.list-signup-form input[type="email"]:focus-visible {
    outline: 2px solid var(--accent-crimson);
    outline-offset: 1px;
}
.list-signup-form button {
    flex: 0 0 auto;
    min-height: 44px;
    padding: var(--s-2) var(--s-5);
    font-family: var(--font-sans);
    font-size: var(--t-xs);
    font-weight: 700;
    letter-spacing: 0.2em;
    text-transform: uppercase;
    color: var(--ink-reverse);
    background: var(--ink);
    border: 1px solid var(--ink);
    cursor: pointer;
}
.list-signup-form button:hover { background: var(--accent-crimson); border-color: var(--accent-crimson); }
.list-signup-form button:disabled { background: var(--surface-sunk); border-color: var(--border-grid); color: var(--ink-faint); cursor: default; }
.list-signup-status {
    margin: var(--s-2) 0 0;
    font-size: var(--t-sm);
    min-height: 1.4em;          /* reserve the line so nothing jumps on reply */
    color: var(--ink-muted);
}
.list-signup-status[data-state="error"] { color: var(--accent-crimson); }

/* Label text for screen readers only. The field has a visible placeholder, but a
   placeholder is not a label -- it disappears on focus and is not announced. */
.visually-hidden {
    position: absolute; width: 1px; height: 1px;
    margin: -1px; padding: 0; overflow: hidden;
    clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap;
}
