/* =============================================================================
   Self-hosted webfonts — see static/fonts/. Replaces Google Fonts CDN.
   Two subsets per weight: latin + latin-ext. Browsers fetch only the subset
   that matches characters on the page (unicode-range), so most US pages pull
   only the smaller latin variants.
   ============================================================================= */

/* latin-ext */
@font-face {
  font-family: 'Inter';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("../fonts/inter-400-latin-ext.1ad231aac0a8.woff2") format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
/* latin */
@font-face {
  font-family: 'Inter';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("../fonts/inter-400-latin.260c81a4759b.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;
}
/* latin-ext */
@font-face {
  font-family: 'Inter';
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url("../fonts/inter-500-latin-ext.1ad231aac0a8.woff2") format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
/* latin */
@font-face {
  font-family: 'Inter';
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url("../fonts/inter-500-latin.260c81a4759b.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;
}
/* latin-ext */
@font-face {
  font-family: 'Inter';
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url("../fonts/inter-600-latin-ext.1ad231aac0a8.woff2") format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
/* latin */
@font-face {
  font-family: 'Inter';
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url("../fonts/inter-600-latin.260c81a4759b.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;
}
/* latin-ext */
@font-face {
  font-family: 'Inter';
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url("../fonts/inter-700-latin-ext.1ad231aac0a8.woff2") format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
/* latin */
@font-face {
  font-family: 'Inter';
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url("../fonts/inter-700-latin.260c81a4759b.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;
}
/* latin-ext */
@font-face {
  font-family: 'JetBrains Mono';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("../fonts/jetbrains-mono-400-latin-ext.bd4781a31b42.woff2") format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
/* latin */
@font-face {
  font-family: 'JetBrains Mono';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("../fonts/jetbrains-mono-400-latin.b636a65da4f0.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;
}
/* latin-ext */
@font-face {
  font-family: 'JetBrains Mono';
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url("../fonts/jetbrains-mono-500-latin-ext.bd4781a31b42.woff2") format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
/* latin */
@font-face {
  font-family: 'JetBrains Mono';
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url("../fonts/jetbrains-mono-500-latin.b636a65da4f0.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;
}
/* latin-ext */
@font-face {
  font-family: 'JetBrains Mono';
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url("../fonts/jetbrains-mono-600-latin-ext.bd4781a31b42.woff2") format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
/* latin */
@font-face {
  font-family: 'JetBrains Mono';
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url("../fonts/jetbrains-mono-600-latin.b636a65da4f0.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;
}

/* =============================================================================
   Trevul — Paper + Forest design system (light, clean, admin-grade)
   Light surfaces, hairline borders, forest-green accent. Same component
   geometry as before; palette swapped for a Django-admin-style daytime feel.
   Tabular numerics throughout (auctions are essentially a financial instrument).

   Type: Inter (humanist sans, optimized for UI legibility) + JetBrains Mono (tabular figures).
   ============================================================================= */

:root {
    /* — Surfaces — */
    --bg:           #f6f7f6;
    --bg-2:         #ffffff;
    --surface:      #ffffff;
    --surface-2:    #fafafa;
    --surface-hi:   #f0f2f0;

    /* — Borders (hairline, low contrast) — */
    --border:       #e2e5e2;
    --border-bright:#cdd2cd;

    /* — Text — */
    --text:         #1f2421;
    --text-2:       #4a524c;
    --text-3:       #757b76;
    --text-dim:     #a8aea9;

    /* — Accent: forest green — */
    --accent:       #2e7d32;
    --accent-2:     #388e3c;
    --accent-deep:  #1b5e20;
    --accent-soft:  rgba(46, 125, 50, 0.10);
    --accent-glow:  rgba(46, 125, 50, 0.22);

    /* — Secondary signals — */
    --cyan:         #0891b2;
    --cyan-soft:    rgba(8, 145, 178, 0.10);
    --amber:        #b45309;
    --amber-soft:   rgba(180, 83, 9, 0.10);
    /* Brand amber — matches the accent leaf in trevul-logo.svg /
       trevul-icon.svg (#E8A45C). Used sparingly for star ratings (where
       gold/amber is the universal convention) and the notification
       count badge. Distinct from --amber (which is the burnt-amber
       used for warning surfaces). */
    --brand-amber:  #E8A45C;
    --red:          #b91c1c;
    --red-soft:     rgba(185, 28, 28, 0.08);
    --plum:         #6d28d9;
    --plum-soft:    rgba(109, 40, 217, 0.10);
    --rose:         var(--red);
    --rose-soft:    var(--red-soft);

    /* — Backwards-compat aliases — */
    --color-bg:           var(--bg);
    --color-surface:      var(--surface);
    --color-text:         var(--text);
    --color-muted:        var(--text-2);
    --color-border:       var(--border);
    --color-accent:       var(--accent);
    --color-accent-hover: var(--accent-2);
    --color-accent-soft:  var(--accent-soft);
    --color-success:      var(--accent);
    --color-error:        var(--red);

    /* — Geometry: sharp, minimal radii — */
    --radius-sm: 3px;
    --radius-md: 6px;
    --radius-lg: 10px;

    /* — Spacing — */
    --space-1: 0.25rem;
    --space-2: 0.5rem;
    --space-3: 0.75rem;
    --space-4: 1rem;
    --space-5: 1.5rem;
    --space-6: 2rem;
    --space-8: 3rem;

    --tile-min: 170px;

    /* — Type — */
    --font-sans:    "Inter", ui-sans-serif, -apple-system, "Segoe UI", "Helvetica Neue", sans-serif;
    --font-mono:    "JetBrains Mono", ui-monospace, "SF Mono", Menlo, Consolas, monospace;
    --font-display: var(--font-sans);

    /* — Motion — */
    --ease:    cubic-bezier(0.2, 0, 0.05, 1);
    --ease-out: cubic-bezier(0.16, 1, 0.3, 1);

    /* Body background-tint stop. Overridden in dark mode. */
    --bg-tint:      rgba(46, 125, 50, 0.05);

    /* Sticky header backdrop. Translucent so the page tints through on scroll. */
    --header-bg:    rgba(255, 255, 255, 0.85);
}

/* =============================================================================
   Dark theme — token overrides only. Every rule above uses var(--…), so
   flipping these values flips the whole site. Applied via a top-of-<head>
   inline script that reads localStorage + prefers-color-scheme and sets
   `data-theme="dark"` on <html> before first paint (no FOUC).
   ============================================================================= */
[data-theme="dark"] {
    --bg:           #0e1411;
    --bg-2:         #131a16;
    --surface:      #161d18;
    --surface-2:    #1b231d;
    --surface-hi:   #232c25;

    --border:       #2a3530;
    --border-bright:#3a4640;

    --text:         #e6ece7;
    --text-2:       #aeb8b1;
    --text-3:       #828c85;
    --text-dim:     #5d655f;

    --accent:       #5fb368;
    --accent-2:     #7cc485;
    --accent-deep:  #4a9952;
    --accent-soft:  rgba(95, 179, 104, 0.14);
    --accent-glow:  rgba(95, 179, 104, 0.30);

    --cyan:         #38bdf8;
    --cyan-soft:    rgba(56, 189, 248, 0.14);
    --amber:        #f59e0b;
    --amber-soft:   rgba(245, 158, 11, 0.14);
    --red:          #ef4444;
    --red-soft:     rgba(239, 68, 68, 0.14);
    --plum:         #a78bfa;
    --plum-soft:    rgba(167, 139, 250, 0.14);

    --bg-tint:      rgba(95, 179, 104, 0.06);
    --header-bg:    rgba(30, 36, 32, 0.92);
}

/* Dark-mode header: slightly grayer than the page bg so the header reads
   as a distinct strip, with brighter text for legibility. Scoped to
   .site-header so the rest of the page keeps the standard token palette. */
[data-theme="dark"] .site-header .nav-link { color: #d4dad6; }
[data-theme="dark"] .site-header .nav-link:hover { color: #ffffff; }
[data-theme="dark"] .site-header .brand,
[data-theme="dark"] .site-header .brand:hover { color: #f5f8f6; }
[data-theme="dark"] .site-header .nav-user { color: #b8c0bb; }
[data-theme="dark"] .site-header .user-menu-trigger:hover,
[data-theme="dark"] .site-header .user-menu-trigger[aria-expanded="true"] { color: #ffffff; }

/* ── Rumblebid brand: orange accents (derived from the logo) + wordmark sizing.
   Scoped to [data-brand="rumblebid"] on <html> (emitted only for that brand),
   so Trevul is unaffected. Rumblebid runs dark-locked; these layer on the dark
   base. Primary #F07000 is locked; secondaries tuned on dev. ── */
[data-brand="rumblebid"] {
    --accent:       #F07000;
    --accent-2:     #FF8C2E;
    --accent-deep:  #D45A00;
    --accent-soft:  rgba(240, 112, 0, 0.14);
    --accent-glow:  rgba(240, 112, 0, 0.32);
    --brand-amber:  #FFA000;
    /* The full mascot logo is on pure black; make the header near-black so it
       blends seamlessly (on-brand for the moto look). */
    --header-bg:    rgba(0, 0, 0, 0.96);
}
/* The RumbleBid header is the full mascot logo (bear + wordmark), a square
   raster on black — sized as a badge in the top-left. The nav has a fixed
   88px height, so grow it to contain the larger logo (else it overflows). */
[data-brand="rumblebid"] .brand-logo { height: 122px; }
[data-brand="rumblebid"] .site-header .nav { height: 138px; }
/* Rumblebid's 162px desktop logo + 178px nav out-specify the generic mobile
   .brand-logo rule (attribute+class beats a lone class), so restate the compact
   values for it at ≤768px — otherwise the phone logo stays huge. */
@media (max-width: 768px) {
    [data-brand="rumblebid"] .brand-logo { height: 40px; }
    [data-brand="rumblebid"] .site-header .nav { height: auto; }
}

* { box-sizing: border-box; }

html {
    -webkit-text-size-adjust: 100%;
    color-scheme: light dark;
    scroll-behavior: smooth;
    scroll-padding-top: 80px;
}

/* =============================================================================
   Cross-document view transitions — opts every full-page nav into a fade
   between the outgoing and incoming root. Falls back to flat nav on
   browsers that don't support the API (Firefox <141 as of 2026-05).
   Respects prefers-reduced-motion.
   ============================================================================= */
@view-transition { navigation: auto; }

::view-transition-old(root),
::view-transition-new(root) {
    animation-duration: 220ms;
    animation-timing-function: var(--ease-out);
}

@media (prefers-reduced-motion: reduce) {
    ::view-transition-old(root),
    ::view-transition-new(root) {
        animation-duration: 1ms;
    }
}

body {
    margin: 0;
    font-family: var(--font-sans);
    font-size: 15px;
    font-weight: 400;
    line-height: 1.55;
    color: var(--text);
    background: var(--bg);
    /* Very subtle green wash at the top — establishes brand without busying
       the page. Fixed-attachment so it doesn't scroll. */
    background-image:
        radial-gradient(ellipse 80% 60% at 50% -10%, var(--bg-tint), transparent 60%);
    background-attachment: fixed;
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
    font-feature-settings: "ss01", "cv11";
    text-rendering: optimizeLegibility;
}

a { color: var(--accent); text-decoration: none; transition: color 0.15s var(--ease); }
a:hover { color: var(--accent-2); text-decoration: underline; text-decoration-thickness: 1px; text-underline-offset: 4px; }

/* Keyboard-only focus rings. `:focus-visible` fires for tab/keyboard nav
   but suppresses on click, so mouse users don't see a ring after every
   button press while keyboard users still get the accessibility cue. */
:where(a, button, [role="button"], summary, [tabindex]:not([tabindex="-1"])):focus-visible {
    outline: 2px solid var(--accent);
    outline-offset: 2px;
    border-radius: var(--radius-sm);
}

h1, h2, h3, h4 {
    font-family: var(--font-display);
    font-weight: 600;
    line-height: 1.1;
    letter-spacing: -0.025em;
    color: var(--text);
    margin: 0 0 var(--space-4);
}
h1 {
    font-size: clamp(1.875rem, 3.5vw, 2.5rem);
    font-weight: 600;
    letter-spacing: -0.035em;
}
h2 { font-size: 1.4rem; font-weight: 600; letter-spacing: -0.02em; }
h3 { font-size: 1.1rem; font-weight: 600; }
p  { margin: 0 0 var(--space-4); color: var(--text); }

::selection { background: var(--accent); color: var(--bg); }

code, pre, .mono { font-family: var(--font-mono); font-feature-settings: "tnum"; }

/* =============================================================================
   Layout
   ============================================================================= */

.container { max-width: 1240px; margin: 0 auto; padding: 0 var(--space-5); }

.site-header {
    position: sticky;
    top: 0;
    z-index: 10;
    background: var(--header-bg);
    backdrop-filter: saturate(140%) blur(14px);
    -webkit-backdrop-filter: saturate(140%) blur(14px);
    border-bottom: 1px solid var(--border);
}

.site-header .nav {
    display: flex;
    align-items: center;
    gap: var(--space-5);
    height: 88px;
}

.brand {
    display: inline-flex;
    align-items: center;
    color: var(--text);
}
.brand:hover { text-decoration: none; color: var(--text); }
.brand-logo {
    height: 72px;
    width: auto;
    display: block;
    transition: opacity 0.2s var(--ease);
}
.brand:hover .brand-logo { opacity: 0.85; }
/* Legacy fallback */
.brand-dot {
    width: 8px; height: 8px;
    background: var(--accent);
    border-radius: 50%;
    display: inline-block;
    box-shadow: 0 0 12px var(--accent-glow);
}

.nav-spacer { flex: 1; }

/* Header search */
.header-search { flex: 2; max-width: 720px; margin: 0 var(--space-4); }
.header-search form { margin: 0; }
.search-input {
    width: 100%;
    padding: 0.55rem 1rem 0.55rem 2.4rem;
    font-family: var(--font-sans);
    font-size: 0.9375rem;
    color: var(--text);
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20' fill='%236c7a6e'%3E%3Cpath d='M9 3.5a5.5 5.5 0 1 0 0 11 5.5 5.5 0 0 0 0-11ZM2 9a7 7 0 1 1 12.452 4.391l3.328 3.329a.75.75 0 1 1-1.06 1.06l-3.329-3.328A7 7 0 0 1 2 9Z'/%3E%3C/svg%3E");
    background-repeat: no-repeat;
    background-position: 0.85rem center;
    background-size: 1rem 1rem;
    transition: border-color 0.15s, box-shadow 0.15s, background-color 0.15s;
}
.search-input:focus {
    outline: none;
    border-color: var(--accent);
    background-color: var(--surface-2);
    box-shadow: 0 0 0 3px var(--accent-soft);
}
.search-input::placeholder { color: var(--text-3); font-size: 0.75rem; }
/* Mobile (≤640px): drop the search bar onto its own row below the
   brand+bell+hamburger row so it stays always-visible without crowding
   the header. flex-wrap + height:auto turns the nav into two rows;
   order:99 + flex:0 0 100% forces search to the last full-width line. */
@media (max-width: 640px) {
    .site-header .nav {
        flex-wrap: wrap;
        height: auto;
        padding-top: var(--space-3);
        padding-bottom: var(--space-3);
        row-gap: var(--space-2);
    }
    .header-search {
        flex: 0 0 100%;
        max-width: 100%;
        order: 99;
        margin: 0;
    }
}

/* Zone pill — two visual states. Unset = inviting CTA (dashed border,
   muted color). Set = active filter chip (solid lime, chevron hint). */
.zone-pill {
    display: inline-flex;
    align-items: center;
    gap: 0.4rem;
    padding: 0.35rem 0.75rem;
    font-family: var(--font-mono);
    font-weight: 500;
    font-size: 0.8125rem;
    letter-spacing: 0.02em;
    border: 1px solid;
    border-radius: var(--radius-sm);
    cursor: pointer;
    text-transform: uppercase;
    transition: background 0.18s var(--ease), border-color 0.18s, color 0.18s, box-shadow 0.2s var(--ease-out);
}

/* SET — the user has chosen a zone. Filter is active. */
.zone-pill-set {
    color: var(--accent);
    background: var(--accent-soft);
    border-color: var(--accent-deep);
}
.zone-pill-set:hover {
    color: var(--accent-2);
    background: rgba(46, 125, 50, 0.14);
    border-color: var(--accent);
    box-shadow: 0 2px 8px var(--accent-glow);
}
.zone-pill-set:hover .zone-pill-chevron { transform: translateY(1px); opacity: 1; }

/* UNSET — invites action. Dashed border to read as "needs setting". */
.zone-pill-unset {
    color: var(--text-2);
    background: transparent;
    border-color: var(--border-bright);
    border-style: dashed;
}
.zone-pill-unset:hover {
    color: var(--accent);
    background: var(--accent-soft);
    border-color: var(--accent-deep);
    border-style: solid;
}

.zone-pill-icon {
    font-size: 0.85rem;
    opacity: 0.85;
    display: inline-flex;
    align-items: center;
    line-height: 0;
}
.zone-pill-label { line-height: 1; }
.zone-pill-chevron {
    width: 10px;
    height: 10px;
    opacity: 0.65;
    margin-left: 0.1rem;
    transition: opacity 0.18s, transform 0.18s var(--ease-out);
}

/* Zone-picker modal */
.zone-modal {
    border: 1px solid var(--border-bright);
    border-radius: var(--radius-lg);
    padding: var(--space-6);
    background: var(--surface);
    color: var(--text);
    box-shadow: 0 16px 48px rgba(0, 0, 0, 0.12), 0 0 0 1px var(--border);
    max-width: 460px;
    width: calc(100% - 2rem);
}
.zone-modal h2 { color: var(--text); }
.zone-modal::backdrop {
    background: rgba(31, 36, 33, 0.40);
    backdrop-filter: blur(4px);
}
.zone-modal[open] { animation: modal-in 0.18s var(--ease-out); }
@keyframes modal-in {
    from { opacity: 0; transform: translateY(-8px); }
    to   { opacity: 1; transform: translateY(0); }
}

/* Tab strip — lower-case, dense, underline-active */
.tab-strip {
    display: flex;
    gap: 0;
    margin-bottom: var(--space-5);
    flex-wrap: wrap;
    border-bottom: 1px solid var(--border);
}
.tab {
    display: inline-flex;
    align-items: center;
    gap: var(--space-2);
    padding: 0.7rem 1rem;
    font-family: var(--font-sans);
    font-size: 0.875rem;
    font-weight: 500;
    color: var(--text-2);
    background: transparent;
    border: none;
    border-bottom: 2px solid transparent;
    border-radius: 0;
    margin-bottom: -1px;
    text-decoration: none;
    transition: color 0.15s, border-color 0.15s;
}
.tab:hover { color: var(--text); text-decoration: none; }
.tab-active {
    color: var(--accent);
    border-bottom-color: var(--accent);
    background: transparent;
}
.tab-active:hover { color: var(--accent-2); border-bottom-color: var(--accent-2); }
.tab-badge {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 1.25rem;
    height: 1.25rem;
    padding: 0 0.4rem;
    background: var(--surface-2);
    color: var(--text-2);
    font-family: var(--font-mono);
    font-size: 0.7rem;
    font-weight: 600;
    font-variant-numeric: tabular-nums;
    border-radius: 999px;
    border: 1px solid var(--border);
}
.tab-active .tab-badge {
    background: var(--accent-soft);
    color: var(--accent);
    border-color: var(--accent-deep);
}

/* Search context banner */
.search-context {
    background: var(--surface);
    border: 1px solid var(--border);
    border-left: 2px solid var(--accent);
    border-radius: var(--radius-sm);
    padding: var(--space-3) var(--space-4);
    margin-bottom: var(--space-5);
    color: var(--text-2);
    font-size: 0.875rem;
}
.search-context strong { color: var(--text); font-weight: 600; }

/* State-exclusion picker on the listing form. 49 checkboxes (48 states
   + DC) in a compact responsive grid so the seller can see the whole
   country at a glance without scrolling. */
.state-exclude-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(140px, 1fr));
    gap: 0.35rem 0.75rem;
}
.state-exclude-cell {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    font-size: 0.875rem;
    font-family: var(--font-sans);
    text-transform: none;
    letter-spacing: 0;
    color: var(--text);
    cursor: pointer;
    padding: 0.2rem 0.3rem;
    border-radius: var(--radius-sm);
}
.state-exclude-cell:hover { background: var(--surface); }
.state-exclude-cell input[type=checkbox] { accent-color: var(--amber); flex-shrink: 0; }
.state-exclude-disclosure summary::marker { color: var(--text-3); }

/* Pre-flight gate CTA on the bid form when the buyer is missing a
   prerequisite (e.g. shipping address). Replaces the bid form so the
   user can't type a bid that's just going to bounce. */
.bid-prereq-cta {
    margin-top: var(--space-4);
    padding: var(--space-4);
    background: var(--amber-soft);
    border: 1px solid rgba(245, 184, 41, 0.35);
    border-left: 3px solid var(--amber);
    border-radius: var(--radius-sm);
    color: var(--text);
}
.bid-prereq-cta strong { color: var(--amber); font-size: 0.95rem; }

.nav-link {
    color: var(--text-2);
    font-weight: 500;
    font-size: 0.875rem;
    padding: var(--space-2) var(--space-3);
    border-radius: var(--radius-sm);
    transition: color 0.15s, background 0.15s;
}
.nav-link:hover { color: var(--text); background: var(--surface-2); text-decoration: none; }

/* Visible "Admin" badge for is_staff users — links to /admin/ */
.admin-badge {
    display: inline-flex;
    align-items: center;
    padding: 0.3rem 0.7rem;
    font-family: var(--font-mono);
    font-size: 0.7rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.12em;
    color: var(--accent);
    background: var(--accent-soft);
    border: 1px solid var(--accent-deep);
    border-radius: var(--radius-sm);
    transition: background 0.15s, color 0.15s, box-shadow 0.18s;
    line-height: 1;
}
.admin-badge:hover {
    color: var(--accent-2);
    background: rgba(46, 125, 50, 0.14);
    text-decoration: none;
    box-shadow: 0 2px 8px var(--accent-glow);
}

/* Spotlight chip — appears on every Promoted listing tile (FTC
   labeling). Visually distinct from the Seedling badge below: solid
   accent fill rather than dashed outline so the "Promoted" signal
   reads at a glance. */
.spotlight-chip {
    display: inline-flex;
    align-items: center;
    gap: 0.25rem;
    padding: 0.2rem 0.55rem;
    font-family: var(--font-mono);
    font-size: 0.65rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.1em;
    color: #fff;
    background: var(--accent);
    border: 1px solid var(--accent-deep);
    border-radius: var(--radius-sm);
    line-height: 1;
    cursor: help;
    user-select: none;
}

/* Spotlight strip — front-page paid-placement rail. Subtle accent
   tint backs the strip so it reads as distinct from the regular
   browse grid below. */
.spotlight-strip {
    margin-bottom: var(--space-5);
    padding: var(--space-4);
    background: var(--accent-soft);
    border: 1px solid var(--accent-deep);
    border-radius: var(--radius-sm);
}
.spotlight-strip-header {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    margin-bottom: var(--space-3);
    font-family: var(--font-mono);
    font-size: 0.75rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.12em;
    color: var(--accent-deep);
}
.spotlight-strip-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(180px, 1fr));
    gap: var(--space-3);
}

/* Plant-level chip — shown in the header to the owner only (header
   always reflects request.user). Tooltip varies by tier: Seedling
   exposes the SafeStart caps + countdown; higher tiers describe the
   ladder progression. Public-facing surfaces use a separate, simpler
   chip without the SafeStart details. CSS-only hover popover, no JS. */
.level-chip {
    position: relative;
    display: inline-flex;
    align-items: center;
    gap: 0.3rem;
    padding: 0.25rem 0.6rem;
    font-family: var(--font-mono);
    font-size: 0.7rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.1em;
    color: var(--accent-2);
    background: var(--accent-soft);
    border: 1px dashed var(--accent-deep);
    border-radius: var(--radius-sm);
    line-height: 1;
    cursor: help;
    user-select: none;
}
.level-tooltip {
    position: absolute;
    top: calc(100% + 8px);
    right: 0;
    width: 280px;
    padding: 0.75rem 0.875rem;
    background: var(--surface);
    color: var(--text);
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    box-shadow: 0 8px 24px rgba(0, 0, 0, 0.12);
    font-family: var(--font-sans);
    font-size: 0.8125rem;
    font-weight: 400;
    text-transform: none;
    letter-spacing: 0;
    line-height: 1.4;
    color: var(--text-2);
    opacity: 0;
    visibility: hidden;
    transform: translateY(-4px);
    transition: opacity 0.12s, transform 0.12s, visibility 0s linear 0.12s;
    z-index: 1000;
    pointer-events: none;
}
.level-tooltip strong { color: var(--text); }
.level-tooltip .level-tooltip-title {
    font-family: var(--font-mono);
    font-size: 0.7rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.1em;
    color: var(--accent-2);
    margin-bottom: 0.4rem;
    display: block;
}
.level-tooltip ul {
    margin: 0.4rem 0 0;
    padding-left: 1.1rem;
}
.level-tooltip li { margin-bottom: 0.2rem; }
.level-chip:hover .level-tooltip,
.level-chip:focus-within .level-tooltip {
    opacity: 1;
    visibility: visible;
    transform: translateY(0);
    transition: opacity 0.12s, transform 0.12s, visibility 0s linear 0s;
}

/* User-menu dropdown — opens under the display name in the header.
   Mirrors the notif-dropdown look (same surface/border/shadow tokens)
   so the two header dropdowns feel like a set. JS toggle in
   static/js/user_menu.js. */
.user-menu-trigger:hover { color: var(--text); }
.user-menu-trigger[aria-expanded="true"] { color: var(--text); }
.user-menu-dropdown {
    position: absolute;
    top: calc(100% + 6px);
    right: 0;
    min-width: 220px;
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    box-shadow: 0 10px 32px rgba(0, 0, 0, 0.14);
    z-index: 1000;
    padding: 0.4rem 0;
}
.user-menu-dropdown[hidden] { display: none; }
.user-menu-dropdown a,
.user-menu-dropdown .user-menu-signout {
    display: block;
    width: 100%;
    text-align: left;
    padding: 0.5rem 1rem;
    color: var(--text);
    text-decoration: none;
    font-size: 0.9375rem;
    background: none;
    border: none;
    cursor: pointer;
    font: inherit;
}
.user-menu-dropdown a:hover,
.user-menu-dropdown .user-menu-signout:hover {
    background: var(--surface-2);
}
.user-menu-signout { color: var(--brand-amber); }
.user-menu-divider {
    height: 1px;
    background: var(--border);
    margin: 0.4rem 0;
}

/* Sunflower notification bell + dropdown. Server-renders the
   dropdown content on every page so the badge/list reflect current
   state on first paint; static/js/notifications.js handles
   open/close + AJAX delete + clear. */
.notif-bell {
    position: relative;
    display: inline-flex;
    align-items: center;
}
.notif-bell-button {
    background: none;
    border: none;
    cursor: pointer;
    padding: 0.4rem;
    line-height: 0;
    color: var(--text-2);
    display: inline-flex;
    align-items: center;
    gap: 0.3rem;
    border-radius: var(--radius-sm);
    transition: background 0.12s, color 0.12s;
}
.notif-bell-button:hover {
    background: var(--surface-hi);
    color: var(--text);
}
.notif-bell-count {
    display: inline-block;
    min-width: 18px;
    padding: 0 0.4rem;
    font-family: var(--font-mono);
    font-size: 0.7rem;
    font-weight: 700;
    color: #fff;
    background: var(--brand-amber);  /* logo amber leaf — matches trevul-logo.svg */
    border-radius: 9999px;
    line-height: 18px;
    text-align: center;
    animation: notif-pulse 1.6s ease-in-out infinite;
}
@keyframes notif-pulse {
    0%, 100% {
        box-shadow: 0 0 0 0 rgba(232, 164, 92, 0.55);
        transform: scale(1);
    }
    50% {
        box-shadow: 0 0 0 6px rgba(232, 164, 92, 0);
        transform: scale(1.08);
    }
}
@media (prefers-reduced-motion: reduce) {
    .notif-bell-count { animation: none; }
}
.notif-dropdown {
    position: absolute;
    top: calc(100% + 6px);
    right: 0;
    width: 400px;
    max-height: 480px;
    overflow-y: auto;
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    box-shadow: 0 10px 32px rgba(0, 0, 0, 0.14);
    z-index: 1000;
}
.notif-dropdown[hidden] {
    display: none;
}
/* Phones: a 400px panel anchored right:0 under the bell runs off the left
   edge of a ~390px viewport (reported from the Android shell). Pin it to
   the viewport instead — the bell stays the toggle, the panel goes
   near-full-width below the sticky header. */
@media (max-width: 640px) {
    .notif-dropdown {
        position: fixed;
        /* Compact mobile header is ~56-64px on both brands (auto height at
           this breakpoint); 72px clears it with a small gap either way. */
        top: calc(72px + env(safe-area-inset-top, 0px));
        left: 8px;
        right: 8px;
        width: auto;
        max-height: 70vh;
    }
}
.notif-dropdown-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 0.7rem 0.875rem;
    border-bottom: 1px solid var(--border);
    font-family: var(--font-mono);
    font-size: 0.7rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.1em;
    color: var(--text-3);
}
.notif-dropdown-actions {
    display: flex;
    align-items: center;
    gap: 0.5rem;
}
.notif-close {
    background: transparent;
    border: 0;
    color: var(--text-3);
    font-size: 1.15rem;
    line-height: 1;
    width: 22px;
    height: 22px;
    border-radius: var(--radius-sm);
    cursor: pointer;
    padding: 0 0 2px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
}
.notif-close:hover { color: var(--text); background: var(--surface-2); }
.notif-close:focus-visible {
    outline: none;
    box-shadow: 0 0 0 2px var(--accent-soft);
    color: var(--accent);
}
.notif-list {
    list-style: none;
    margin: 0;
    padding: 0;
}
.notif-item {
    display: flex;
    align-items: stretch;
    border-bottom: 1px solid var(--border);
}
.notif-item:last-child { border-bottom: none; }
.notif-item-unread { background: var(--accent-soft); }
.notif-link {
    flex: 1;
    display: flex;
    gap: 0.6rem;
    padding: 0.7rem 0.875rem;
    color: inherit;
    text-decoration: none;
    align-items: flex-start;
}
.notif-link:hover { background: var(--surface-2); text-decoration: none; }
.notif-kind {
    font-size: 1.1rem;
    flex-shrink: 0;
    margin-top: 0.1rem;
}
.notif-body {
    flex: 1;
    display: flex;
    flex-direction: column;
    gap: 0.15rem;
    min-width: 0;
}
.notif-title {
    font-size: 0.8125rem;
    color: var(--text);
    font-weight: 500;
    line-height: 1.3;
}
.notif-detail {
    font-size: 0.75rem;
    color: var(--text-2);
    line-height: 1.3;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.notif-time {
    font-size: 0.65rem;
    color: var(--text-3);
    font-family: var(--font-mono);
}
.notif-delete {
    background: none;
    border: none;
    color: var(--text-3);
    font-size: 1.1rem;
    cursor: pointer;
    padding: 0 0.7rem;
    line-height: 1;
    align-self: stretch;
    transition: color 0.12s, background 0.12s;
}
.notif-delete:hover { color: var(--rose); background: var(--surface-2); }
.notif-empty {
    padding: 1.5rem 0.875rem;
    margin: 0;
    color: var(--text-3);
    font-size: 0.875rem;
    text-align: center;
}

/* Site-wide Message of the Day banner — thin strip below the
   site header. Hidden by absence (template `{% if active_motd %}`),
   not by display:none. Single visual style in v1; if we add severity
   escalation later the stylesheet can branch on a class on the
   element. */
.motd-banner {
    background: var(--accent-soft);
    border-bottom: 1px solid var(--accent-deep);
    color: var(--text-2);
    font-size: 0.8125rem;
    line-height: 1.4;
    padding: 0.5rem 0;
    text-align: center;
}
.motd-banner .container { padding-top: 0; padding-bottom: 0; }

/* Plant-tier progress meter on the Gear dashboard. Six horizontal
   steps from Seedling to Curator with a connecting line; each step
   marked as done / current / (default = upcoming). Native title
   tooltips on hover surface the threshold copy without extra JS. */
.level-progress {
    margin-bottom: var(--space-4);
    padding: var(--space-4);
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
}
.level-progress-header {
    display: flex;
    justify-content: space-between;
    align-items: baseline;
    margin-bottom: var(--space-3);
}
.level-progress-track {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: 0;
    position: relative;
}
.level-progress-track::before {
    content: "";
    position: absolute;
    top: 18px;
    left: 8%;
    right: 8%;
    height: 2px;
    background: var(--border);
    z-index: 0;
}
.level-progress-step {
    flex: 1;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 0.4rem;
    cursor: help;
    position: relative;
    z-index: 1;
}
.level-progress-glyph {
    width: 36px;
    height: 36px;
    border-radius: 50%;
    background: var(--surface-2);
    border: 2px solid var(--border);
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 1.05rem;
    line-height: 1;
    transition: transform 0.15s, box-shadow 0.15s, background 0.15s;
    filter: grayscale(0.7);
    opacity: 0.6;
}
.level-progress-step.done .level-progress-glyph {
    background: var(--accent-soft);
    border-color: var(--accent);
    filter: none;
    opacity: 1;
}
.level-progress-step.current .level-progress-glyph {
    background: var(--accent);
    border-color: var(--accent-deep);
    box-shadow: 0 0 0 4px var(--accent-soft);
    transform: scale(1.12);
    filter: none;
    opacity: 1;
}
.level-progress-step:hover .level-progress-glyph {
    transform: scale(1.05);
}
.level-progress-step.current:hover .level-progress-glyph {
    transform: scale(1.18);
}
.level-progress-label {
    font-family: var(--font-mono);
    font-size: 0.7rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.08em;
    color: var(--text-3);
    text-align: center;
}
.level-progress-step.done .level-progress-label,
.level-progress-step.current .level-progress-label {
    color: var(--accent-2);
}

/* Public level chip — rendered on seller_profile + listing detail
   without the private SafeStart caps. Same look as .level-chip but
   without the popover. */
.level-chip-public {
    display: inline-flex;
    align-items: center;
    gap: 0.25rem;
    padding: 0.15rem 0.5rem;
    font-family: var(--font-mono);
    font-size: 0.65rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.1em;
    color: var(--accent-2);
    background: var(--accent-soft);
    border: 1px solid var(--accent-deep);
    border-radius: var(--radius-sm);
    line-height: 1;
    user-select: none;
}

.nav-user {
    color: var(--text-3);
    font-size: 0.875rem;
    font-family: var(--font-mono);
    font-feature-settings: "tnum";
}

main {
    padding: var(--space-8) 0;
    min-height: calc(100vh - 56px - 80px);
    animation: page-fade 0.25s var(--ease-out) both;
}
@keyframes page-fade {
    from { opacity: 0; transform: translateY(4px); }
    to   { opacity: 1; transform: translateY(0); }
}

.site-footer {
    border-top: 1px solid var(--border);
    padding: var(--space-6) 0;
    color: var(--text-3);
    font-family: var(--font-mono);
    font-size: 0.75rem;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    text-align: center;
}
.site-footer a { color: var(--text-2); }
.site-footer a:hover { color: var(--accent); }

/* =============================================================================
   Components
   ============================================================================= */

.btn {
    display: inline-flex;
    align-items: center;
    gap: var(--space-2);
    padding: 0.6rem 1.1rem;
    font-family: var(--font-sans);
    font-size: 0.875rem;
    font-weight: 600;
    line-height: 1;
    background: var(--accent);
    color: var(--bg);
    border: 1px solid var(--accent);
    border-radius: var(--radius-sm);
    cursor: pointer;
    transition: background 0.15s var(--ease), border-color 0.15s, box-shadow 0.2s var(--ease-out), transform 0.1s;
    box-shadow: 0 0 0 0 transparent;
}
.btn:hover {
    background: var(--accent-2);
    border-color: var(--accent-2);
    color: var(--bg);
    text-decoration: none;
    box-shadow: 0 0 24px var(--accent-glow);
}
.btn:active { transform: translateY(1px); }

.btn-ghost {
    background: transparent;
    color: var(--text);
    border-color: var(--border-bright);
    box-shadow: none;
}
.btn-ghost:hover {
    background: var(--surface-2);
    color: var(--text);
    border-color: var(--text-3);
    box-shadow: none;
}

.btn-cyan {
    background: var(--cyan);
    border-color: var(--cyan);
    color: var(--bg);
}
.btn-cyan:hover {
    background: #5be0a8;
    border-color: #5be0a8;
    box-shadow: 0 0 24px var(--cyan-soft);
}

.btn-link {
    background: transparent;
    color: var(--accent);
    border: none;
    padding: 0;
    font: inherit;
    font-weight: 500;
    cursor: pointer;
    box-shadow: none;
}
.btn-link:hover { color: var(--accent-2); text-decoration: underline; text-underline-offset: 4px; box-shadow: none; }

.card {
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--radius-md);
    padding: var(--space-5);
    transition: border-color 0.18s var(--ease), background 0.18s var(--ease), box-shadow 0.25s var(--ease-out);
}

.listings {
    display: grid;
    gap: var(--space-4);
    grid-template-columns: repeat(auto-fill, minmax(min(var(--tile-min), 100%), 1fr));
}
@media (min-width: 1100px) { .listings { gap: var(--space-5); } }

/* Card entrance — quick, restrained, no bounce */
.listings .card {
    opacity: 0;
    transform: translateY(6px);
    animation: card-in 0.3s var(--ease-out) forwards;
}
.listings .card:nth-child(1)  { animation-delay: 0.02s; }
.listings .card:nth-child(2)  { animation-delay: 0.05s; }
.listings .card:nth-child(3)  { animation-delay: 0.08s; }
.listings .card:nth-child(4)  { animation-delay: 0.11s; }
.listings .card:nth-child(5)  { animation-delay: 0.14s; }
.listings .card:nth-child(6)  { animation-delay: 0.17s; }
.listings .card:nth-child(7)  { animation-delay: 0.20s; }
.listings .card:nth-child(8)  { animation-delay: 0.23s; }
.listings .card:nth-child(9)  { animation-delay: 0.26s; }
.listings .card:nth-child(n+10) { animation-delay: 0.30s; }
@keyframes card-in {
    to { opacity: 1; transform: translateY(0); }
}

.listing-card {
    display: flex;
    flex-direction: column;
    padding: 0;
    overflow: hidden;
    transition: transform 0.18s var(--ease-out),
                border-color 0.18s var(--ease-out),
                background 0.18s var(--ease-out),
                box-shadow 0.18s var(--ease-out);
}
.listing-card:hover {
    transform: translateY(-2px);
    border-color: var(--border-bright);
    background: var(--surface-2);
    box-shadow: 0 0 0 1px var(--border-bright), 0 10px 28px rgba(31, 36, 33, 0.10);
}
@media (prefers-reduced-motion: reduce) {
    .listing-card { transition: none; }
    .listing-card:hover { transform: none; }
}
.listing-card a { color: inherit; display: flex; flex-direction: column; height: 100%; }
.listing-card a:hover { text-decoration: none; }

.listing-card .thumb {
    aspect-ratio: 4 / 3;
    width: 100%;
    background: var(--surface-2);
    background-image:
        linear-gradient(135deg, rgba(46, 125, 50, 0.04) 0%, transparent 50%),
        linear-gradient(to bottom right, var(--surface) 0%, var(--surface-2) 100%);
    overflow: hidden;
    display: flex;
    align-items: center;
    justify-content: center;
    position: relative;
    border-bottom: 1px solid var(--border);
}
.listing-card .thumb::after {
    content: "";
    position: absolute; inset: 0;
    background: linear-gradient(to bottom, transparent 70%, rgba(31, 36, 33, 0.10));
    pointer-events: none;
}
.listing-card .thumb img {
    width: 100%; height: 100%;
    object-fit: cover;
    display: block;
    transition: transform 0.5s var(--ease-out), filter 0.3s var(--ease);
    filter: saturate(0.95);
    animation: thumb-fade-in 0.4s var(--ease-out);
}
.listing-card:hover .thumb img { transform: scale(1.04); filter: saturate(1.05); }
.listing-card .thumb-empty {
    color: var(--text-dim);
    opacity: 0.5;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 56px;
    height: 56px;
    border: 1px dashed var(--border-bright);
    border-radius: 50%;
    background: var(--surface);
}
.listing-card .thumb-empty svg { width: 28px; height: 28px; }

@keyframes thumb-fade-in {
    from { opacity: 0; }
    to   { opacity: 1; }
}
@media (prefers-reduced-motion: reduce) {
    .listing-card .thumb img { animation: none; }
}

.listing-card .body-pad { padding: var(--space-4) var(--space-4) var(--space-5); flex: 1; display: flex; flex-direction: column; }
.listing-card .title {
    font-family: var(--font-display);
    font-weight: 600;
    margin: 0 0 var(--space-2);
    font-size: 1rem;
    line-height: 1.3;
    letter-spacing: -0.015em;
    color: var(--text);
}
.listing-card .meta { color: var(--text-2); font-size: 0.8125rem; margin-bottom: var(--space-3); }
.listing-card .body { color: var(--text); flex: 1; }

/* Countdown ticker */
.countdown {
    font-family: var(--font-mono);
    font-feature-settings: "tnum";
    font-weight: 500;
    letter-spacing: -0.01em;
}
.countdown-green   { color: var(--accent); }
.countdown-yellow  { color: var(--amber); }
.countdown-orange  { color: #d97706; font-weight: 600; }
.countdown-red {
    color: var(--red);
    animation: countdown-pulse 1.2s ease-in-out infinite;
}
.countdown-ended { color: var(--text-3); font-weight: 400; }

@keyframes countdown-pulse {
    0%, 100% { opacity: 1; }
    50%      { opacity: 0.55; }
}

/* Bid-prefill pulse — draws the eye to the bid form after a buyer returns
   from the setup wizard with their amount prefilled (see listing_detail.html
   / listings/views/browse.py::ListingDetailView). A one-shot ~2s outline
   pulse, not a loop — this is a "look here" cue, not an ongoing alert like
   .notif-bell-count above. */
.bid-prefill-pulse {
    animation: bid-prefill-pulse 2s var(--ease-out);
}
@keyframes bid-prefill-pulse {
    0%   { box-shadow: 0 0 0 0 var(--accent-glow); }
    30%  { box-shadow: 0 0 0 6px var(--accent-glow); }
    100% { box-shadow: 0 0 0 0 rgba(0, 0, 0, 0); }
}
@media (prefers-reduced-motion: reduce) {
    .bid-prefill-pulse { animation: none; }
}

.countdown-hero {
    display: inline-block;
    font-family: var(--font-mono);
    font-feature-settings: "tnum";
    font-weight: 500;
    font-size: 2.25rem;
    line-height: 1.05;
    letter-spacing: -0.03em;
    padding: var(--space-3) var(--space-5);
    border-radius: var(--radius-md);
    background: var(--surface);
    border: 1px solid var(--border);
    color: var(--text);
}
.countdown-hero.countdown-green  { color: var(--accent); border-color: var(--accent-deep); box-shadow: inset 0 0 0 1px rgba(46, 125, 50, 0.20); }
.countdown-hero.countdown-yellow { color: var(--amber); border-color: var(--amber); background: var(--amber-soft); }
.countdown-hero.countdown-orange { color: #d97706; border-color: #d97706; background: rgba(217, 119, 6, 0.08); }
.countdown-hero.countdown-red    { color: var(--red); border-color: var(--red); background: var(--red-soft); }

.countdown-label {
    display: block;
    font-family: var(--font-mono);
    font-size: 0.7rem;
    font-weight: 500;
    text-transform: uppercase;
    letter-spacing: 0.12em;
    color: var(--text-3);
    margin-bottom: var(--space-2);
}

/* Detail gallery */
.gallery {
    display: grid;
    grid-template-columns: 1fr;
    gap: var(--space-3);
    margin-bottom: var(--space-5);
}
@media (min-width: 640px) {
    .gallery.has-many {
        grid-template-columns: 2fr 1fr;
        grid-template-rows: auto auto;
    }
    .gallery.has-many > a:first-child { grid-row: span 2; }
}
.gallery a {
    display: block;
    aspect-ratio: 4 / 3;
    overflow: hidden;
    border-radius: var(--radius-md);
    background: var(--bg-2);
    border: 1px solid var(--border);
}
.gallery img { width: 100%; height: 100%; object-fit: cover; display: block; transition: transform 0.4s var(--ease-out); cursor: zoom-in; }
.gallery a:hover img { transform: scale(1.04); }

/* Image lightbox: in-page modal so clicking a gallery image doesn't
   open a new tab. Keeps users anchored on the listing page. */
.img-lightbox {
    border: none;
    padding: 0;
    background: transparent;
    max-width: 100vw;
    max-height: 100vh;
    width: 100vw;
    height: 100vh;
    overflow: hidden;
}
.img-lightbox::backdrop {
    background: rgba(8, 18, 12, 0.88);
    backdrop-filter: blur(4px);
    -webkit-backdrop-filter: blur(4px);
}
.img-lightbox-img {
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    max-width: 92vw;
    max-height: 88vh;
    width: auto;
    height: auto;
    object-fit: contain;
    border-radius: var(--radius-md);
    box-shadow: 0 20px 60px rgba(0, 0, 0, 0.45);
    cursor: zoom-out;
}
.img-lightbox-close,
.img-lightbox-nav {
    position: absolute;
    background: rgba(255, 255, 255, 0.92);
    color: #1A1A1A;
    border: none;
    cursor: pointer;
    font-family: inherit;
    line-height: 1;
    border-radius: 50%;
    box-shadow: 0 4px 14px rgba(0, 0, 0, 0.25);
    transition: background 0.15s, transform 0.15s;
}
.img-lightbox-close:hover,
.img-lightbox-nav:hover { background: #fff; transform: scale(1.06); }
.img-lightbox-close:focus-visible,
.img-lightbox-nav:focus-visible {
    outline: 3px solid var(--accent);
    outline-offset: 3px;
}
.img-lightbox-close {
    top: 1.25rem;
    right: 1.25rem;
    width: 44px;
    height: 44px;
    font-size: 1.75rem;
    font-weight: 400;
    padding: 0 0 4px;
}
.img-lightbox-nav {
    top: 50%;
    transform: translateY(-50%);
    width: 52px;
    height: 52px;
    font-size: 2.25rem;
    font-weight: 400;
    padding: 0 0 6px;
}
.img-lightbox-nav:hover { transform: translateY(-50%) scale(1.06); }
.img-lightbox-prev { left: 1.25rem; }
.img-lightbox-next { right: 1.25rem; }
.img-lightbox-counter {
    position: absolute;
    bottom: 1.5rem;
    left: 50%;
    transform: translateX(-50%);
    background: rgba(0, 0, 0, 0.55);
    color: #fff;
    padding: 0.4rem 0.85rem;
    border-radius: 999px;
    font-size: 0.8125rem;
    letter-spacing: 0.04em;
}
@media (max-width: 640px) {
    .img-lightbox-close { top: 0.75rem; right: 0.75rem; width: 40px; height: 40px; }
    .img-lightbox-nav { width: 44px; height: 44px; font-size: 2rem; }
    .img-lightbox-prev { left: 0.5rem; }
    .img-lightbox-next { right: 0.5rem; }
}

/* Tags — uppercase, monospace, tight, semantic colors */
.tag {
    display: inline-block;
    padding: 3px 8px;
    font-family: var(--font-mono);
    font-feature-settings: "tnum";
    font-size: 0.65rem;
    font-weight: 500;
    text-transform: uppercase;
    letter-spacing: 0.1em;
    border-radius: 3px;
    background: var(--accent-soft);
    color: var(--accent);
    border: 1px solid var(--accent-deep);
    line-height: 1.4;
}
.tag-muted { background: var(--surface-2); color: var(--text-3); border-color: var(--border); }
.tag-error { background: var(--red-soft); color: var(--red); border-color: rgba(239, 68, 82, 0.4); }
.tag-clay,
.tag-cyan  { background: var(--cyan-soft); color: var(--cyan); border-color: rgba(52, 211, 153, 0.4); }
.tag-ochre,
.tag-amber { background: var(--amber-soft); color: var(--amber); border-color: rgba(245, 184, 41, 0.4); }
.tag-plum  { background: var(--plum-soft); color: var(--plum); border-color: rgba(167, 139, 250, 0.4); }
.tag-rose  { background: var(--red-soft); color: var(--red); border-color: rgba(239, 68, 82, 0.4); }
/* Solid SOLD badge — high-contrast terminal-state marker so buyers can
   spot a sold listing on the overview grid without opening the detail. */
.tag-sold      { background: var(--accent-deep); color: #fff; border-color: var(--accent-deep); }
.tag-free-ship { background: #e6f4ea; color: #1e6b35; border-color: #7cc08a; }
.tag-live      { background: #eef2ff; color: #3730a3; border-color: #a5b4fc; }
.tag-live-hot  { background: #fff1f2; color: #be123c; border-color: #fda4af; font-weight: 600; }
.tag-gtc       { background: var(--surface-2); color: var(--text-3); border-color: var(--border); font-style: italic; }

/* Star color utility — matches the brand-amber leaf in the logo.
   Aligns with the universal gold/amber convention for star ratings,
   replacing the prior forest-green that quietly read as "off" against
   user expectations. Use as `<span class="star">★</span>` or apply to
   any star-bearing element. */
.star { color: var(--brand-amber); }
.tag-reserve-met,
.badge-reserve-met {
    display: inline-block; padding: 3px 8px;
    font-family: var(--font-mono); font-feature-settings: "tnum";
    font-size: 0.65rem; font-weight: 500;
    text-transform: uppercase; letter-spacing: 0.1em;
    border-radius: 3px; line-height: 1.4;
    background: var(--accent-soft); color: var(--accent);
    border: 1px solid var(--accent-deep);
}
.tag-reserve-unmet,
.badge-reserve-unmet {
    display: inline-block; padding: 3px 8px;
    font-family: var(--font-mono); font-feature-settings: "tnum";
    font-size: 0.65rem; font-weight: 500;
    text-transform: uppercase; letter-spacing: 0.1em;
    border-radius: 3px; line-height: 1.4;
    background: var(--amber-soft); color: var(--amber);
    border: 1px solid rgba(245, 184, 41, 0.4);
}
/* PARTNER badge — applied to sellers with account_type=BUSINESS.
   Trevul-verified business partners; visible buyer-side trust signal.
   Mirrors `.level-chip` chrome (mono / uppercase / dashed border) so
   the Partner / Level / Staff chips read as one visual family across
   the header. Teal palette keeps Partner distinct from the
   forest-green Level + Staff chips. */
.badge-partner {
    display: inline-flex;
    align-items: center;
    gap: 0.3rem;
    padding: 0.25rem 0.6rem;
    font-family: var(--font-mono);
    font-size: 0.7rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.1em;
    color: #0f766e;
    background: rgba(20, 184, 166, 0.12);
    border: 1px dashed rgba(20, 184, 166, 0.6);
    border-radius: var(--radius-sm);
    line-height: 1;
    vertical-align: middle;
}

.price {
    font-family: var(--font-sans);
    font-feature-settings: "tnum";
    font-weight: 600;
    font-size: 1.4rem;
    letter-spacing: -0.02em;
    color: var(--text);
}

/* Empty states */
.empty {
    text-align: center;
    padding: var(--space-8) var(--space-4);
    color: var(--text-2);
    border: 1px dashed var(--border);
    border-radius: var(--radius-md);
}
.empty .empty-icon {
    font-size: 1.75rem;
    margin-bottom: var(--space-3);
    opacity: 0.5;
}
.empty h2 {
    font-weight: 600;
    color: var(--text);
}

/* Forms */
.form { max-width: 480px; margin: 0 auto; }
.form > p, .form > div { margin: 0 0 var(--space-4); }

.form label {
    display: block;
    font-family: var(--font-mono);
    font-size: 0.7rem;
    font-weight: 500;
    color: var(--text-2);
    margin-bottom: var(--space-2);
    text-transform: uppercase;
    letter-spacing: 0.1em;
}

.form input[type=text],
.form input[type=email],
.form input[type=password],
.form input[type=number],
.form textarea,
.form select {
    width: 100%;
    padding: 0.65rem 0.85rem;
    font-family: var(--font-sans);
    font-size: 0.9375rem;
    color: var(--text);
    background: var(--surface);
    border: 1px solid var(--border-bright);
    border-radius: var(--radius-sm);
    transition: border-color 0.15s, box-shadow 0.15s, background 0.15s;
}
.form input:focus,
.form textarea:focus,
.form select:focus {
    outline: none;
    border-color: var(--accent);
    background: var(--surface-2);
    box-shadow: 0 0 0 3px var(--accent-soft);
}

.form .helptext, .form small {
    display: block;
    font-size: 0.75rem;
    color: var(--text-3);
    margin-top: var(--space-1);
    line-height: 1.5;
}

.errorlist {
    margin: 0 0 var(--space-3);
    padding: var(--space-3) var(--space-4);
    list-style: none;
    background: var(--red-soft);
    border: 1px solid rgba(239, 68, 82, 0.4);
    border-left: 2px solid var(--red);
    border-radius: var(--radius-sm);
    color: var(--red);
    font-size: 0.875rem;
}
.errorlist li { margin: 0; }

.messages {
    list-style: none;
    margin: 0 0 var(--space-5);
    padding: 0;
}
.messages li {
    padding: var(--space-3) var(--space-4);
    background: var(--accent-soft);
    border: 1px solid var(--accent-deep);
    border-left: 2px solid var(--accent);
    border-radius: var(--radius-sm);
    color: var(--accent-deep);
    margin-bottom: var(--space-2);
    font-size: 0.875rem;
}

/* Listing detail */
.listing-detail { max-width: 880px; }
.listing-detail .breadcrumb {
    color: var(--text-3);
    font-family: var(--font-mono);
    font-size: 0.75rem;
    margin-bottom: var(--space-4);
    text-transform: uppercase;
    letter-spacing: 0.08em;
}
.listing-detail .breadcrumb a { color: var(--text-3); }
.listing-detail .breadcrumb a:hover { color: var(--accent); }
.listing-detail h1 {
    font-size: clamp(1.75rem, 4vw, 2.5rem);
    font-weight: 600;
    letter-spacing: -0.035em;
}
.listing-detail .header {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: var(--space-4);
    margin-bottom: var(--space-5);
}
.listing-detail .description {
    margin: var(--space-5) 0;
    line-height: 1.7;
    color: var(--text);
}
.listing-detail .panel {
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--radius-md);
    padding: var(--space-5);
}
.listing-detail .panel + .panel { margin-top: var(--space-4); }

.kv {
    display: grid;
    grid-template-columns: max-content 1fr;
    gap: var(--space-2) var(--space-5);
    font-size: 0.875rem;
}
.kv dt {
    color: var(--text-3);
    font-family: var(--font-mono);
    font-size: 0.7rem;
    text-transform: uppercase;
    letter-spacing: 0.08em;
    font-weight: 500;
}
.kv dd { margin: 0; font-weight: 500; color: var(--text); }

/* Pagination */
.pagination {
    display: flex;
    justify-content: center;
    align-items: center;
    gap: var(--space-3);
    margin-top: var(--space-8);
    color: var(--text-3);
    font-family: var(--font-mono);
    font-size: 0.8125rem;
    text-transform: uppercase;
    letter-spacing: 0.06em;
}
.pagination a {
    color: var(--accent);
    padding: var(--space-2) var(--space-3);
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    transition: background 0.15s, border-color 0.15s;
}
.pagination a:hover { background: var(--surface-2); border-color: var(--accent-deep); text-decoration: none; }

/* Auth pages */
/* Auth-page wrapper: padding ensures content doesn't run to the
   viewport edge on screens narrower than max-width (440px on iPhone
   SE 375px, iPhone 12 mini 360px etc. would otherwise overflow). */
.auth-page { max-width: 440px; margin: 0 auto; padding: 0 var(--space-3); box-sizing: border-box; }
.auth-page h1 {
    margin-bottom: var(--space-5);
    font-size: 2rem;
    font-weight: 600;
    letter-spacing: -0.03em;
}
.auth-page .form button[type=submit] { width: 100%; justify-content: center; }
.auth-page .alt {
    text-align: center;
    margin-top: var(--space-5);
    color: var(--text-3);
    font-size: 0.875rem;
}

/* Decorative divider */
.leaf-rule {
    border: none;
    height: 1px;
    margin: var(--space-6) auto;
    background: linear-gradient(to right, transparent, var(--border-bright), transparent);
    max-width: 320px;
}

/* =============================================================================
   Mobile responsive (≤768 / ≤640)
   =============================================================================
   Two breakpoints used through the rest of the app:
     - 768px  : "tablet+phone" — stacks Gear sidebar, swaps header to
                hamburger, kicks the form-row-2col grids into single column.
     - 640px  : Inline 2-col grids in listing_form/order pages snap to
                single column. Header search hides at this point too
                (existing rule above). Lower threshold leaves room for
                small-tablet portrait users to still get the desktop
                grid layouts. */

/* Reusable responsive 2-column form grid. Replaces inline
   `grid-template-columns: 1fr 1fr` on form rows that need to drop
   to a single column on phones. */
.form-row-2col {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: var(--space-4);
}
@media (max-width: 640px) {
    .form-row-2col { grid-template-columns: 1fr; }
}

/* Notification dropdown — must never exceed viewport width. The
   absolute-positioned dropdown sits inside `.notif-bell` which lives
   on the right side of the header, so a too-wide dropdown overflows
   off the right edge on phones. The clamp keeps it inside. */
.notif-dropdown { max-width: calc(100vw - 1rem); }

/* Tap-target floor on mobile — Apple HIG recommends 44pt min, Material
   recommends 48dp. .btn-link is text-only and easy to mis-tap with a
   thumb at default ~14-16px line-height; bump it on small viewports. */
@media (max-width: 768px) {
    .btn-link {
        min-height: 44px;
        padding: 0.5rem 0;
        display: inline-flex;
        align-items: center;
    }
}

/* Prevent iOS Safari from zooming on input focus. Safari zooms when
   the input's computed font-size is < 16px; keeping it at exactly
   16px on phones avoids the jarring zoom-and-jump. */
@media (max-width: 768px) {
    input[type="text"],
    input[type="email"],
    input[type="password"],
    input[type="number"],
    input[type="search"],
    input[type="tel"],
    input[type="url"],
    select,
    textarea {
        font-size: 16px;
    }
}

/* Dashboard hub + every dashboard sub-page uses
   `<div class="dashboard-hub" style="display:grid; grid-template-columns:220px 1fr">`.
   On phones the 220px sidebar leaves no usable room for main content;
   stack vertically instead. Author !important beats the inline style
   per the CSS cascade (inline-without-!important loses to
   author-with-!important). */
@media (max-width: 768px) {
    .dashboard-hub {
        grid-template-columns: 1fr !important;
        gap: var(--space-4) !important;
    }
}

/* Mobile header pattern: hide the right-side primary-nav links + the
   nav-user + sign-out form, surface a hamburger button instead. The
   notification bell + level chip stay visible — at-a-glance status
   matters more than secondary navigation on small screens. */
.header-hamburger {
    display: none;
    background: none;
    border: none;
    cursor: pointer;
    font-size: 1.4rem;
    padding: 0.4rem 0.6rem;
    color: var(--text-2);
    line-height: 1;
    border-radius: var(--radius-sm);
}
.header-hamburger:hover { background: var(--surface-2); color: var(--text); }

/* Mobile search toggle — same icon-button treatment as the hamburger; hidden on
   desktop (the full search bar shows there), shown ≤768px via the media block. */
.header-search-toggle {
    display: none;
    background: none;
    border: none;
    cursor: pointer;
    padding: 0.4rem 0.55rem;
    color: var(--text-2);
    line-height: 0;
    border-radius: var(--radius-sm);
}
.header-search-toggle:hover { background: var(--surface-2); color: var(--text); }
.header-search-toggle svg { width: 22px; height: 22px; }
.site-header.search-open .header-search-toggle { color: var(--accent); }

/* Theme toggle button — sits in the header for anon + authed users.
   Two icons live inside; CSS shows only the relevant one for the
   active theme so the button always says "switch to the other one". */
.theme-toggle {
    background: none;
    border: 1px solid var(--border);
    color: var(--text-2);
    padding: 0.4rem;
    border-radius: var(--radius-sm);
    cursor: pointer;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    line-height: 0;
    transition: background 0.15s var(--ease), color 0.15s var(--ease), border-color 0.15s var(--ease);
}
.theme-toggle:hover {
    background: var(--surface-hi);
    color: var(--text);
    border-color: var(--border-bright);
}
.theme-toggle-icon { width: 18px; height: 18px; }
.theme-toggle-sun  { display: none; }
[data-theme="dark"] .theme-toggle-sun  { display: block; }
[data-theme="dark"] .theme-toggle-moon { display: none; }
@media (max-width: 768px) {
    /* Show the hamburger; hide the items it replaces. */
    .header-hamburger { display: inline-flex; }
    .site-header .nav .nav-link,
    .site-header .nav .admin-badge,
    .site-header .nav .nav-user,
    .site-header .nav > form,
    .site-header .nav .btn,
    .site-header .nav .level-chip,
    .site-header .nav .zone-pill {
        display: none;
    }
    /* Re-show the bell — it's the one nav element worth keeping. */
    .site-header .nav .notif-bell { display: inline-flex; }
    /* Compact logo on phones (both brands) -> a single tidy header row. */
    .brand-logo { height: 40px; }
    /* Single-row compact header; only wraps to a 2nd row when search opens. */
    .site-header .nav { height: auto; gap: var(--space-3); flex-wrap: wrap; row-gap: var(--space-2); }
    /* Search collapses to a tap-to-open icon; the bar reveals as its own row
       (so it never hovers over the scrolling feed). */
    .header-search { display: none; }
    .header-search-toggle { display: inline-flex; }
    .site-header.search-open .header-search {
        display: block;
        flex: 0 0 100%;
        max-width: 100%;
        order: 99;
        margin: 0;
        padding-bottom: var(--space-2);
    }
}

/* ≤640px the header wraps the search onto its own row, so it MUST be
   height:auto. This re-asserts it AFTER the ≤768 `height:64px` rule above —
   both match on phones and equal specificity means source order decides, so
   without this the fixed 64px clamps the two-row header and the wrapped search
   overflows on top of the page content. */
@media (max-width: 640px) {
    .site-header .nav { height: auto; }
}

/* Capacitor shell at ANY width (html.capshell, same marker as the bottom
   tab bar above): keep the MOBILE header. Wide shell screens (Galaxy Fold
   inner display ≈ 840 CSS px, tablets) otherwise cross the 768px
   breakpoint into the desktop header, which is designed for real desktop
   widths and crushes its right-side links ("logout squished into the top
   right corner"). In the app, the hamburger + bottom tab bar ARE the
   navigation — the desktop header never belongs there. MIRRORS the ≤768px
   header block above; keep the two in sync. */
html.capshell .header-hamburger { display: inline-flex; }
html.capshell .site-header .nav .nav-link,
html.capshell .site-header .nav .admin-badge,
html.capshell .site-header .nav .nav-user,
html.capshell .site-header .nav > form,
html.capshell .site-header .nav .btn,
html.capshell .site-header .nav .level-chip,
html.capshell .site-header .nav .zone-pill {
    display: none;
}
html.capshell .site-header .nav .notif-bell { display: inline-flex; }
html.capshell .brand-logo { height: 40px; }
html.capshell .site-header .nav { height: auto; gap: var(--space-3); flex-wrap: wrap; row-gap: var(--space-2); }
html.capshell .header-search { display: none; }
html.capshell .header-search-toggle { display: inline-flex; }
html.capshell .site-header.search-open .header-search {
    display: block;
    flex: 0 0 100%;
    max-width: 100%;
    order: 99;
    margin: 0;
    padding-bottom: var(--space-2);
}

/* Mobile menu dialog — centered, full-height-ish, vertically-stacked
   nav links. Uses the same `<dialog>` pattern as the zone modal so
   ESC/backdrop-click closes for free. */
.mobile-menu-dialog {
    border: none;
    border-radius: var(--radius-md);
    padding: var(--space-5);
    width: min(360px, 92vw);
    background: var(--surface);
    box-shadow: 0 20px 60px rgba(0, 0, 0, 0.18);
    /* Explicit centering. Don't rely on the UA `<dialog>` `margin:auto`
       centering — some mobile WebViews (notably iOS WKWebView) don't apply it
       reliably, leaving the modal shoved off to the left. Fixed + transform is
       robust everywhere. max-height keeps a long menu on-screen. */
    position: fixed;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    margin: 0;
    max-height: 85vh;
    overflow-y: auto;
}
.mobile-menu-dialog::backdrop {
    background: rgba(0, 0, 0, 0.4);
}
.mobile-menu-dialog nav {
    display: flex;
    flex-direction: column;
    gap: var(--space-2);
}
.mobile-menu-dialog nav a,
.mobile-menu-dialog nav button {
    display: flex;
    align-items: center;
    padding: 0.85rem 0.75rem;
    font-size: 1rem;
    color: var(--text);
    text-decoration: none;
    border-radius: var(--radius-sm);
    background: none;
    border: none;
    cursor: pointer;
    text-align: left;
    width: 100%;
    font-family: inherit;
}
.mobile-menu-dialog nav a:hover,
.mobile-menu-dialog nav button:hover {
    background: var(--surface-2);
    text-decoration: none;
}
.mobile-menu-dialog .mobile-menu-close {
    position: absolute;
    top: 0.5rem;
    right: 0.5rem;
    background: none;
    border: none;
    font-size: 1.5rem;
    cursor: pointer;
    color: var(--text-3);
    line-height: 1;
    padding: 0.4rem 0.7rem;
}
.mobile-menu-dialog .mobile-menu-close:hover { color: var(--text); }

/* Mobile bottom tab bar — app-style primary nav on phones (mirrors the native
   apps). Two things turn it on: the ≤768px phone breakpoint in a browser, OR
   `html.capshell` — the Capacitor shells at ANY viewport width (a Galaxy Fold
   inner display or tablet is wider than the phone breakpoint but is still the
   app, so it keeps the app chrome; see the base.html head marker script).
   env(safe-area-inset-bottom) keeps it above the iOS home indicator inside the
   shell, and the body padding reserves room so content/footer never hide
   behind it. Styling is unconditional; only visibility + the body padding are
   gated. */
.bottom-nav {
    display: none;
    position: fixed;
    left: 0; right: 0; bottom: 0;
    z-index: 40;
    background: var(--header-bg);
    border-top: 1px solid var(--border);
    -webkit-backdrop-filter: saturate(140%) blur(14px);
    backdrop-filter: saturate(140%) blur(14px);
    padding-bottom: env(safe-area-inset-bottom);
}
.bottom-nav a {
    flex: 1 1 0;
    min-width: 0;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 3px;
    padding: 7px 2px 6px;
    min-height: 50px;
    color: var(--text-3);
    text-decoration: none;
    font-size: 0.65rem;
    font-weight: 500;
    line-height: 1;
}
.bottom-nav a svg { width: 22px; height: 22px; }
.bottom-nav a.active { color: var(--accent); }
.bottom-nav a:active { background: var(--surface-2); }
@media (max-width: 768px) {
    .bottom-nav { display: flex; }
    /* Reserve space for the fixed bar so page content + footer clear it. */
    body { padding-bottom: calc(52px + env(safe-area-inset-bottom)); }
}
html.capshell .bottom-nav { display: flex; }
html.capshell body { padding-bottom: calc(52px + env(safe-area-inset-bottom)); }

/* Listing tile becomes a single column on very narrow viewports —
   easier to scan than two squeezed columns where the title truncates. */
@media (max-width: 480px) {
    :root { --tile-min: 100%; }
}

/* Stripe Connect Embedded Components mount points. Components render
   inside iframes that Stripe styles via the appearance config in
   templates/_stripe_connect_loader.html — we just provide a clean
   wrapper that matches Trevul's card aesthetic for the surrounding
   layout. */
.stripe-connect-mount {
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--radius-md);
    padding: var(--space-3);
    min-height: 120px;
}
.stripe-connect-mount:empty::before {
    content: "Loading…";
    display: block;
    color: var(--text-3);
    font-size: 0.875rem;
    text-align: center;
    padding: var(--space-4);
}

/* Inline gear icon (templates/_icon_gear.html). Sized in em so the
   surrounding font-size on the link/button controls scale; uses
   currentColor so it inherits the link color + hover color. */
.icon-gear {
    width: 1.1em;
    height: 1.1em;
    vertical-align: -0.18em;  /* visually center against neighboring text */
    display: inline-block;
}

/* Payment-method chip strip (templates/_payment_method_chips.html).
   Surfaces which underlying payment methods become available when the
   user connects a rail. Chip images stay on a white background even in
   dark mode — consistent with how providers render their own marks. */
.payment-method-chips {
    margin: 1rem 0 1.25rem;
}
.payment-method-chips__copy {
    margin: 0 0 0.5rem;
    color: var(--color-muted);
    font-size: 0.875rem;
}
.payment-method-chips__list {
    list-style: none;
    padding: 0;
    margin: 0;
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem;
}
.payment-method-chips__list li {
    display: inline-flex;
}
.payment-method-chips__list img {
    display: block;
    height: 36px;
    width: 36px;
    border-radius: 6px;
}

/* ─────────────────────────────────────────────────────────────────────
 * Unified payment-method screen (/account/payment-method/)
 * Two stacked rail cards (Stripe + PayPal), 5-tile picker for Stripe,
 * lazy-loaded Connect for PayPal. See payments/templates/payments/payment_method.html.
 * ───────────────────────────────────────────────────────────────────── */

.pm-banner {
    padding: var(--space-3);
    border-radius: 8px;
    margin-bottom: var(--space-4);
}
.pm-banner-warning {
    background: #fff8e6;
    border: 1px solid #ffd97a;
    color: #644700;
}
.pm-banner-success {
    background: var(--accent-soft);
    border: 1px solid var(--accent);
    color: var(--text);
}
.pm-rail-card {
    border: 1px solid var(--border);
    border-radius: 10px;
    padding: var(--space-4);
    margin-bottom: var(--space-3);
    background: var(--surface);
}
.pm-rail-card__header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    gap: var(--space-2);
    margin-bottom: var(--space-3);
}
.pm-rail-card__header h2 {
    margin: 0;
    font-size: 1.1rem;
}
.pm-pill {
    font-size: 0.7rem;
    padding: 2px 10px;
    border-radius: 10px;
    white-space: nowrap;
}
.pm-pill-warning { background: #fff3cd; color: #856404; }
.pm-pill-success { background: var(--accent-soft); color: var(--accent); }

.pm-saved-row {
    display: flex;
    justify-content: space-between;
    align-items: center;
    gap: var(--space-3);
    flex-wrap: wrap;
}
.pm-saved-row__sub {
    color: var(--text-3);
    font-size: 0.85rem;
    margin-top: 2px;
}
.pm-saved-row__actions {
    display: flex;
    gap: var(--space-2);
    flex-wrap: wrap;
}

.pm-picker__copy {
    color: var(--text-2);
    margin: 0 0 var(--space-3);
}
.pm-picker__grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
    gap: var(--space-2);
    margin-bottom: var(--space-3);
}
.pm-picker__tile {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    padding: var(--space-3);
    border: 1px solid var(--border);
    border-radius: 8px;
    cursor: pointer;
    background: var(--surface);
    transition: border-color 0.15s ease, background 0.15s ease;
}
.pm-picker__tile:hover {
    border-color: var(--accent);
}
.pm-picker__tile:has(input:checked) {
    border-color: var(--accent);
    background: var(--accent-soft);
}
.pm-picker__tile input[type="radio"] {
    margin: 0;
    accent-color: var(--accent);
}
.pm-picker__label {
    display: flex;
    flex-direction: column;
}
.pm-picker__hint {
    color: var(--text-3);
    font-size: 0.78rem;
    margin-top: 2px;
}
.pm-element-mount {
    padding: var(--space-3);
    background: var(--surface-2);
    border: 1px solid var(--border);
    border-radius: 8px;
    margin-bottom: var(--space-3);
}
.pm-picker__actions {
    display: flex;
    gap: var(--space-2);
    flex-wrap: wrap;
}
.pm-paypal-connect {
    background: #ffc439;
    color: #111;
    border-color: #f0b521;
}
.pm-paypal-connect:hover {
    background: #f0b521;
    color: #111;
}

/* Side-by-side rail cards. PayPal first per spec. Stacks on narrow viewports. */
.auth-page.auth-page--wide {
    max-width: 1080px;
}
.pm-rails-grid {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: var(--space-3);
    align-items: start;
}
@media (max-width: 720px) {
    .pm-rails-grid { grid-template-columns: 1fr; }
}
.pm-continue {
    display: flex;
    align-items: center;
    gap: var(--space-3);
    margin-top: var(--space-5);
    padding-top: var(--space-4);
    border-top: 1px solid var(--border);
    flex-wrap: wrap;
}
.pm-continue__hint {
    color: var(--text-3);
    font-size: 0.85rem;
}
.pm-picker__tile--disabled {
    pointer-events: none;
}

/* Large brand mark inside a rail-card header (replaces the h2 title for
 * brands whose logo is recognizable enough on its own — e.g. PayPal). */
.pm-rail-card__header--bigmark {
    align-items: center;
}
.pm-rail-bigmark {
    height: 144px;
    width: 144px;
    border-radius: 8px;
    display: block;
}

.pm-rail-card__footnote {
    margin: var(--space-4) 0 0;
    padding-top: var(--space-3);
    border-top: 1px solid var(--border);
    color: var(--text-3);
    font-size: 0.8125rem;
}

.pm-fee-primary {
    display: inline-block;
    margin-top: var(--space-2);
    font-size: 0.78rem;
    color: var(--text-3);
}
.pm-fee-primary--active {
    color: var(--accent);
    font-weight: 600;
}
.pm-fee-primary--btn {
    background: transparent;
    border: 1px solid var(--border);
    padding: 4px 10px;
    border-radius: 4px;
    cursor: pointer;
    color: var(--text-2);
    font-size: 0.78rem;
}
.pm-fee-primary--btn:hover {
    background: var(--surface-2);
    color: var(--text);
}

/* Radio-style indicator for the "primary for listing fees" picker. */
.pm-fee-radio {
    display: inline-block;
    width: 12px;
    height: 12px;
    border-radius: 50%;
    border: 1.5px solid var(--text-3);
    background: transparent;
    vertical-align: -1px;
    margin-right: 6px;
    position: relative;
}
.pm-fee-radio--checked {
    border-color: var(--accent);
}
.pm-fee-radio--checked::after {
    content: "";
    position: absolute;
    inset: 2px;
    border-radius: 50%;
    background: var(--accent);
}

/* "Trevul listing fees come from:" picker above the rail cards.
 * Only renders when BOTH rails are connected (the picker has no
 * meaning otherwise — the single connected rail is implicit primary). */
.pm-fee-picker {
    display: flex;
    align-items: center;
    gap: var(--space-3);
    padding: var(--space-3);
    border: 1px solid var(--border);
    border-radius: 8px;
    background: var(--surface-2);
    margin-bottom: var(--space-3);
    flex-wrap: wrap;
}
.pm-fee-picker__label {
    color: var(--text-2);
    font-size: 0.9rem;
    font-weight: 500;
}
.pm-fee-picker__option {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 6px 12px;
    border: 1px solid var(--border);
    border-radius: 6px;
    cursor: pointer;
    background: var(--surface);
    transition: border-color 0.15s, background 0.15s;
}
.pm-fee-picker__option:hover { border-color: var(--accent); }
.pm-fee-picker__option--selected {
    border-color: var(--accent);
    background: var(--accent-soft);
    color: var(--text);
    font-weight: 500;
}
.pm-fee-picker__option input[type="radio"] {
    accent-color: var(--accent);
    margin: 0;
}

/* ---- listing chat ---- */
/* Card composer + Reddit-style thread rails. Adapted from the approved
   mockup (chat-composer-looks.html, "The pick" section) onto the site's
   real tokens — no hardcoded colors, both themes + both brands free. */

.chat-thread {
    margin-top: var(--space-8);
    padding-top: var(--space-6);
    border-top: 1px solid var(--border);
}
.chat-thread h2 {
    font-size: 1.15rem;
    margin-bottom: var(--space-4);
}
.chat-closed,
.chat-empty,
.chat-signin {
    color: var(--text-3);
    font-size: 0.9rem;
}
.chat-signin a { font-weight: 500; }

/* -- a single post row: avatar + name/badge/time + body + actions -- */
.chat-post {
    display: flex;
    gap: var(--space-3);
    padding: var(--space-2) 0;
}
.chat-avatar {
    flex: none;
    width: 30px;
    height: 30px;
    border-radius: 50%;
    background: var(--accent-soft);
    color: var(--accent);
    display: flex;
    align-items: center;
    justify-content: center;
    font-weight: 700;
    font-size: 0.78rem;
    position: relative;
    z-index: 1;
}
.chat-avatar--stub { background: transparent; }
.chat-post-main { flex: 1; min-width: 0; }
.chat-post-head { display: flex; align-items: baseline; flex-wrap: wrap; gap: 0.4rem; }
.chat-who { font-weight: 600; font-size: 0.86rem; color: var(--text); }
.chat-when { color: var(--text-3); font-size: 0.72rem; }
.chat-badge-seller {
    display: inline-block;
    font-size: 0.64rem;
    font-weight: 700;
    letter-spacing: 0.05em;
    text-transform: uppercase;
    padding: 0.14rem 0.45rem;
    border-radius: 999px;
    background: var(--accent-soft);
    color: var(--accent);
}
.chat-body {
    color: var(--text);
    font-size: 0.9rem;
    margin: 0.15rem 0 0.1rem;
}
.chat-stub { color: var(--text-3); font-style: italic; }
.chat-actions { display: flex; gap: var(--space-4); }
.chat-actions .btn-link,
.chat-inline-form .btn-link {
    color: var(--text-3);
    font-size: 0.74rem;
    font-weight: 500;
}
.chat-actions .btn-link:hover,
.chat-inline-form .btn-link:hover {
    color: var(--accent);
    text-decoration: none;
}
.chat-actions .chat-remove:hover,
.chat-inline-form .chat-remove:hover { color: var(--red); }
.chat-inline-form { display: inline-block; }

/* -- Reddit-style thread rails: a line drops from the parent's avatar
   and elbows into each reply, so nesting reads at a glance. Hovering
   anywhere on a thread lights its rail up in the brand accent. -- */
.thread-item { position: relative; }
.thread-item + .thread-item { margin-top: var(--space-2); }
.thread-item.has-replies::before {
    content: "";
    position: absolute;
    left: 14px;
    top: 44px;
    bottom: 10px;
    width: 2px;
    background: var(--border-bright);
    border-radius: 2px;
    transition: background 0.15s var(--ease);
}
.thread-item.has-replies:hover::before { background: var(--accent); }
.replies { margin-left: 0; }
.reply { position: relative; padding-left: 40px; }
.reply::before {
    content: "";
    position: absolute;
    left: 14px;
    top: 0;
    width: 20px;
    height: 26px;
    border-left: 2px solid var(--border-bright);
    border-bottom: 2px solid var(--border-bright);
    border-bottom-left-radius: 12px;
    transition: border-color 0.15s var(--ease);
}
.thread-item.has-replies:hover .reply::before { border-color: var(--accent); }
/* last reply: the rail stops at its elbow, so mask the remainder
   against the page background it actually sits on. */
.reply:last-child { background: var(--bg); }

/* -- Card composer: avatar + framed card + footer row, accent glow
   on focus-within -- */
.chat-composer {
    display: flex;
    gap: var(--space-3);
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--radius-lg);
    padding: var(--space-4) var(--space-4) var(--space-3);
    margin-top: var(--space-5);
    transition: box-shadow 0.15s var(--ease), border-color 0.15s var(--ease);
}
.chat-composer:focus-within {
    border-color: var(--accent);
    box-shadow: 0 0 0 3px var(--accent-glow);
}
.chat-composer-main { flex: 1; min-width: 0; position: relative; }
.chat-composer textarea {
    font: inherit;
    color: var(--text);
    background: transparent;
    border: 0;
    outline: 0;
    resize: none;
    width: 100%;
    box-sizing: border-box;
}
.chat-composer textarea::placeholder { color: var(--text-3); }
.chat-composer-row {
    display: flex;
    align-items: center;
    gap: var(--space-4);
    margin-top: var(--space-2);
}
.chat-hint { flex: 1; color: var(--text-3); font-size: 0.75rem; }
.chat-charcount { color: var(--text-3); font-size: 0.75rem; font-variant-numeric: tabular-nums; }

/* -- @mention autocomplete dropdown -- */
.chat-mention-dropdown {
    position: absolute;
    left: 0;
    bottom: calc(100% + 6px);
    background: var(--surface);
    border: 1px solid var(--border-bright);
    border-radius: var(--radius-md);
    box-shadow: 0 6px 24px rgba(0, 0, 0, 0.14);
    padding: 0.3rem;
    display: flex;
    flex-direction: column;
    min-width: 220px;
    max-height: 220px;
    overflow-y: auto;
}
.chat-mention-dropdown button {
    text-align: left;
    font: inherit;
    font-size: 0.85rem;
    background: none;
    border: 0;
    border-radius: var(--radius-sm);
    padding: 0.45rem 0.6rem;
    color: var(--text);
    cursor: pointer;
}
.chat-mention-dropdown button:hover { background: var(--accent-soft); }

@media (prefers-reduced-motion: reduce) {
    .thread-item.has-replies::before,
    .reply::before,
    .chat-composer {
        transition: none !important;
    }
}

/* ===== Account screens — mobile pass ===== */
.seg-tabs{display:flex;gap:4px;background:var(--surface);border:1px solid var(--border);
  border-radius:var(--radius-lg);padding:4px;margin:var(--space-4) 0 var(--space-5);}
.seg-tabs a{flex:1;display:flex;align-items:center;justify-content:center;gap:7px;
  min-height:44px;padding:0 var(--space-3);border-radius:calc(var(--radius-lg) - 4px);
  font-weight:600;font-size:15px;text-decoration:none;color:var(--text-2);white-space:nowrap;}
.seg-tabs a[aria-selected="true"]{background:var(--accent);color:#fff;box-shadow:0 1px 2px var(--accent-glow);}
.seg-tabs a:focus-visible{outline:2px solid var(--accent);outline-offset:2px;}
.seg-tabs .pip{width:7px;height:7px;border-radius:50%;background:var(--amber);}
.seg-tabs a[aria-selected="true"] .pip{background:rgba(255,255,255,.9);}
.dashboard-hub{display:grid;grid-template-columns:220px 1fr;gap:var(--space-6);margin-top:var(--space-4);}
.dashboard-tile-grid{display:grid;grid-template-columns:1fr 1fr;gap:var(--space-4);}
@media (max-width:768px){
  .dashboard-hub{grid-template-columns:1fr;}
  .dashboard-hub > *{min-width:0;}
  /* Hide the dashboard section sidebar on phones — it rendered as a full
     vertical list of every destination, duplicating the hamburger menu (which
     carries the same items). The hamburger + bottom bar drive mobile nav. */
  .dashboard-hub__side{display:none;}
  .dashboard-tile-grid{grid-template-columns:1fr;gap:var(--space-3);}
  .level-progress-step{min-width:0;}
  .level-progress-label{overflow-wrap:break-word;}
}

/* ---- Type floor + 44px tap targets on account content (mobile).
   Content-scoped by design: the site header/nav has its own tap-target
   rules elsewhere and is intentionally NOT touched here (see
   scripts/mobile_metrics.py — minFont/tinyTapTargets are measured only
   inside <main>, excluding header/footer/.notif-dropdown/.site-header). ---- */
@media (max-width:768px){
  main .dashboard-hub, main #pm-page{font-size:16px;}
  main .pm-pill, main dt, main label, main .mono, main small, main .level-progress-label{font-size:12px;}
  main .kv dt, main .form label{font-size:12px;}
  main .btn:not([hidden]), main button:not([hidden]), main select:not([hidden]), main .btn-ghost:not([hidden]), main [role=tab]{min-height:44px;display:inline-flex;align-items:center;justify-content:center;}
}

/* ===== Site header — mobile hit-area (≥44px tap targets) ===== */
@media (max-width: 768px) {
  .site-header .theme-toggle,
  .site-header .notif-bell-button,
  .site-header .header-hamburger { min-width: 44px; min-height: 44px; }
  .site-header .user-menu-trigger { min-height: 44px; }
}

/* ─────────────────────────────────────────────────────────────────────
 * Seller payment-method hub (2026-07-30) — the sell wizard's
 * `accept_methods` step (templates/users/wizard_steps/accept_methods.html)
 * and the shared setup modals it opens (templates/users/_payment_setup_modals.html,
 * reused by the /account/payments/ Selling tab). Three state pills
 * (data-method/data-state="unset"|"verifying"|"off"|"ready") + two <dialog>
 * overlays, mirroring the `.zone-modal`/`.mobile-menu-dialog` pattern
 * already used elsewhere in this file.
 * ───────────────────────────────────────────────────────────────────── */
.hub-sub { margin: -0.5rem 0 var(--space-4); color: var(--text-2); font-size: 0.9375rem; }
.hub-pills { display: flex; flex-direction: column; gap: var(--space-3); margin-bottom: var(--space-4); }
.hub-pill {
    display: flex;
    align-items: flex-start;
    gap: var(--space-3);
    padding: var(--space-4);
}
.hub-cb {
    flex-shrink: 0;
    width: 22px;
    height: 22px;
    margin-top: 1px;
    border-radius: 5px;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 0.8125rem;
    font-weight: 700;
    border: 1px solid var(--border-bright);
    background: var(--surface-2);
    color: transparent;
}
.hub-cb.on { background: var(--accent); border-color: var(--accent); color: var(--bg); }
.hub-cb.pend { background: var(--amber-soft); border-color: var(--amber); color: var(--amber); }
.hub-txt { flex: 1; min-width: 0; }
.hub-txt strong { display: block; color: var(--text); font-size: 0.9375rem; }
.hub-txt p { margin: 0.25rem 0 0; color: var(--text-2); font-size: 0.875rem; line-height: 1.5; }
.hub-txt p.hub-pend-note { color: var(--amber); }
.hub-done, .hub-pending {
    flex-shrink: 0;
    font-size: 0.8125rem;
    font-weight: 600;
    white-space: nowrap;
    padding-top: 0.35rem;
}
.hub-done { color: var(--accent); }
.hub-pending { color: var(--amber); }
/* "off" pill state (prereq met, checkbox off) — inline form styled like
 * the "Set up" button it replaces, not a bare <button>, so it can carry
 * hidden sibling-preserving fields + its own CSRF token. */
.hub-turnon-form { flex-shrink: 0; margin: 0; }
/* Unset-state "Set up" — one-click create-account POST (seller-payment-hub
 * Task 2), same single-button-wrapped-in-a-form shape as .hub-turnon-form
 * above (needs its own CSRF token + hidden `next`), just a different
 * server action. */
.hub-setup-form { flex-shrink: 0; margin: 0; }
.hub-continue { width: 100%; justify-content: center; margin-top: var(--space-2); }
.hub-continue[disabled] {
    background: var(--surface-2);
    border-color: var(--border);
    color: var(--text-dim);
    cursor: not-allowed;
    box-shadow: none;
}
.hub-continue[disabled]:hover { background: var(--surface-2); border-color: var(--border); box-shadow: none; }

.hub-modal {
    border: 1px solid var(--border-bright);
    border-radius: var(--radius-lg);
    padding: var(--space-5);
    background: var(--surface);
    color: var(--text);
    box-shadow: 0 16px 48px rgba(0, 0, 0, 0.16), 0 0 0 1px var(--border);
    max-width: 420px;
    width: calc(100% - 2rem);
    max-height: 85vh;
    overflow-y: auto;
}
.hub-modal::backdrop { background: rgba(15, 18, 16, 0.45); backdrop-filter: blur(2px); }
/* Non-modal float (bank dialog): opened via dialog.show(), NOT showModal(),
   so Stripe's body-appended Financial Connections overlay (z-index 2^31-1)
   can paint above it — a top-layer modal would occlude that overlay and
   make it inert. Centered via inset+margin (the modal-in keyframes animate
   transform, so transform-centering would fight the entrance animation);
   the scrim is a real element (no ::backdrop outside the top layer). */
.hub-modal-float[open] {
    position: fixed;
    inset: 0;
    margin: auto;
    height: fit-content;
    z-index: 10000;
}
.hub-modal-scrim {
    position: fixed;
    inset: 0;
    background: rgba(15, 18, 16, 0.45);
    backdrop-filter: blur(2px);
    z-index: 9999;
}
/* Reuses the `.zone-modal` entrance keyframes (~L563) — byte-identical,
   no need for a second copy. */
.hub-modal[open] { animation: modal-in 0.18s var(--ease-out); }
@media (prefers-reduced-motion: reduce) {
    .hub-modal[open] { animation: none; }
}
.hub-modal-close {
    float: right;
    background: none;
    border: none;
    font-size: 1.25rem;
    line-height: 1;
    color: var(--text-3);
    cursor: pointer;
    padding: 0.2rem 0.4rem;
    margin: -0.4rem -0.4rem 0 0;
}
.hub-modal-close:hover { color: var(--text); }
.hub-modal h2 { margin: 0 0 var(--space-2); font-size: 1.0625rem; color: var(--text); clear: both; }
.hub-modal > p { margin: 0 0 var(--space-4); color: var(--text-2); font-size: 0.875rem; line-height: 1.5; }
.hub-modal .stripe-connect-mount { min-height: 260px; }

/* Wizard shared chrome (templates/users/setup_wizard.html) — the quiet
 * "Finish this later" escape link rendered under every step. */
.wizard-escape { margin-top: var(--space-6); text-align: center; }
.wizard-escape a { color: var(--text-3); font-size: 0.75rem; }

/* ─────────────────────────────────────────────────────────────────────
 * Settings → Payments → Selling tab: "How buyers pay you" toggle rows
 * (seller-payment-hub Task 4, mirrors the wizard hub's `.hub-pill`
 * visual language above). Each row is a real `accepts_*` checkbox for
 * form-semantics purposes — the switch look is pure CSS on a sibling
 * `<span>`, following the same "input stays the source of truth, CSS
 * repaints it" pattern already used for `.hub-cb`.
 * ───────────────────────────────────────────────────────────────────── */
.pm-toggle-sub { margin: -0.25rem 0 var(--space-3); color: var(--text-2); font-size: 0.875rem; }
.pm-toggle-sumline {
    margin: 0 0 var(--space-4);
    padding: var(--space-2) var(--space-3);
    border-radius: 8px;
    background: var(--surface-2);
    font-size: 0.9375rem;
    color: var(--text);
}
.pm-toggle-row {
    display: flex;
    align-items: flex-start;
    gap: var(--space-3);
    padding: var(--space-4);
    margin-bottom: var(--space-3);
}
.pm-toggle-row .pm-toggle-txt { flex: 1; min-width: 0; }
.pm-toggle-row .pm-toggle-txt strong { display: block; color: var(--text); font-size: 0.9375rem; }
.pm-toggle-row .pm-toggle-txt span.pm-toggle-desc { display: block; margin: 0.25rem 0 0; color: var(--text-2); font-size: 0.875rem; line-height: 1.5; }
.pm-toggle-row .pm-toggle-txt span.pm-toggle-desc a { color: var(--accent); }
.pm-toggle-offnote { display: block; margin: 0.35rem 0 0; color: var(--amber); font-size: 0.8125rem; }
/* Distinct from `.pm-toggle-offnote` on purpose (fix round 1) — that
   class means "you switched this off" (a caution, styled amber). This
   one means "still verifying," a neutral in-progress status, not a
   warning, so it's styled with the same neutral `--text-2` tone as the
   row's ordinary description copy (`.pm-toggle-desc`) rather than amber. */
.pm-toggle-pendnote { display: block; margin: 0.35rem 0 0; color: var(--text-2); font-size: 0.8125rem; }
.pm-toggle-row .setup-btn { flex-shrink: 0; }

/* The switch itself: a visually-hidden real checkbox + a painted track/thumb. */
.pm-toggle { position: relative; flex-shrink: 0; display: inline-block; width: 40px; height: 22px; margin-top: 2px; }
.pm-toggle-input {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    margin: 0;
    opacity: 0;
    cursor: pointer;
    z-index: 1;
}
.pm-toggle-track {
    position: absolute;
    inset: 0;
    border-radius: 11px;
    background: var(--surface-3, var(--border-bright));
    transition: background-color 0.15s var(--ease-out);
}
.pm-toggle-track::after {
    content: "";
    position: absolute;
    top: 2px;
    left: 2px;
    width: 18px;
    height: 18px;
    border-radius: 50%;
    background: var(--bg);
    box-shadow: 0 1px 2px rgba(0, 0, 0, 0.25);
    transition: transform 0.15s var(--ease-out);
}
.pm-toggle-input:checked + .pm-toggle-track { background: var(--accent); }
.pm-toggle-input:checked + .pm-toggle-track::after { transform: translateX(18px); }
.pm-toggle-input:focus-visible + .pm-toggle-track { outline: 2px solid var(--accent); outline-offset: 2px; }
@media (prefers-reduced-motion: reduce) {
    .pm-toggle-track, .pm-toggle-track::after { transition: none; }
}

/* ── Countdown sizing on phones ───────────────────────────────────────
   "4d 21h 4m 29s" is 13 mono characters. At the desktop sizes it wrapped
   on every phone width tested: the detail hero broke to THREE lines at
   390/360/320px, and the card ticker to two at 320px. Scale it down for
   small screens and pin it to one line — a timer that reflows mid-tick
   reads as broken. Desktop is untouched. ─────────────────────────────── */
@media (max-width: 640px) {
    .countdown { font-size: 0.75rem; white-space: nowrap; }
    .countdown-hero {
        font-size: 1.5rem;
        white-space: nowrap;
        letter-spacing: -0.02em;
        padding: var(--space-2) var(--space-4);
    }
}
@media (max-width: 360px) {
    .countdown-hero { font-size: 1.25rem; padding: var(--space-2) var(--space-3); }
}

/* ── Browse-page live public-posts feed ─────────────────────────── */
.browse-feed { margin-top: 2rem; }
.browse-feed-header { display: flex; align-items: center; gap: 0.5rem;
    font-weight: 600; margin-bottom: 0.6rem; }
.browse-feed-live { display: inline-flex; align-items: center; gap: 0.3rem;
    font-size: 0.68rem; font-weight: 600; color: var(--red);
    text-transform: uppercase; letter-spacing: 0.06em; }
.browse-feed-dot { width: 7px; height: 7px; border-radius: 50%;
    background: var(--red); animation: feed-pulse 1.5s infinite; }
@keyframes feed-pulse { 50% { opacity: 0.3; } }
@media (prefers-reduced-motion: reduce) {
    .browse-feed-dot { animation: none; }
}
#browse-feed-list { list-style: none; margin: 0; padding: 0; }
.feed-row { background: var(--surface); border: 1px solid var(--border);
    border-radius: var(--radius-md); margin-bottom: 0.4rem; overflow: hidden; }
.feed-row > a { display: flex; align-items: center; gap: 0.6rem;
    padding: 0.5rem 0.7rem; color: inherit; text-decoration: none; }
.feed-row > a:hover { background: var(--surface-2); }
.feed-text { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.feed-msg { min-width: 0; white-space: nowrap; overflow: hidden;
    text-overflow: ellipsis; font-size: 0.85rem; }
.feed-name { color: var(--accent); font-weight: 600; }
/* reply rows: dimmed original on top, reply indented beneath with an elbow */
.feed-parent { min-width: 0; white-space: nowrap; overflow: hidden;
    text-overflow: ellipsis; font-size: 0.78rem; color: var(--text-3); }
.feed-parent .feed-name { color: var(--text-3); }
.feed-reply-msg { padding-left: 1.15rem; position: relative; }
.feed-reply-msg::before { content: "↳"; position: absolute; left: 0.15rem;
    color: var(--text-dim); }
.feed-thumb { width: 28px; height: 28px; border-radius: var(--radius-sm);
    object-fit: cover; flex-shrink: 0; }
.feed-thumb-empty { display: inline-flex; align-items: center;
    justify-content: center; background: var(--surface-hi); color: var(--text-3); }
.feed-item-title { color: var(--text-2); font-size: 0.78rem; white-space: nowrap; }
/* arrival: slide down + fading highlight (spec: animation C) */
.feed-row.feed-new { animation: feed-arrive 2.5s ease; }
@keyframes feed-arrive {
    0%   { max-height: 0; opacity: 0; margin-bottom: 0; }
    12%  { max-height: 88px; opacity: 0; margin-bottom: 0.4rem; }
    20%  { opacity: 1; background: var(--accent-glow); }
    70%  { background: var(--surface); }
    100% { max-height: 88px; opacity: 1; margin-bottom: 0.4rem; }
}
@media (prefers-reduced-motion: reduce) {
    .feed-row.feed-new { animation: none; }
}
@media (max-width: 600px) { .feed-item-title { display: none; } }
