/*
 * Copyright © 2026 Clubs IQ LLC, All rights reserved.
 *
 * CONFIDENTIAL / PROPRIETARY
 *
 * NOTICE: All information contained herein is, and remains the property of
 * Clubs IQ, LLC. The intellectual and technical concepts contained herein
 * are proprietary to Clubs IQ, LLC and may be covered by U.S. and Foreign
 * Patents, patents in process, and are protected by trade secret or
 * copyright law. Dissemination of this information or reproduction of
 * this material is strictly forbidden unless prior written permission
 * is obtained from Clubs IQ, LLC.
 */

/*
 * © 2026 Clubs IQ. All rights reserved.
 *
 * Clubs IQ — design system stylesheet.
 *
 * Single source of truth for the application's visual language. See
 * docs/BRANDING_DESIGN.md for the locked decisions behind each
 * pattern. Loaded once by `_appshell.html`; every authenticated page
 * inherits it.
 *
 * Section index:
 *
 *    1. Design tokens             - CSS custom properties
 *    2. Base / reset              - body, headings, links, fonts
 *    3. App-shell layout grid     - the new chrome shape
 *    4. Brand zone (top-left)     - logo plate + wordmark
 *    5. Top banner (top-right)    - club context, two modes
 *    6. Transient strip           - flash / session-timeout banners
 *    7. LHS nav (accordion)       - module nav + sub-items
 *    8. Content pane              - padding, scope chip, copyright
 *    9. Section bands             - edge-to-edge dividers
 *   10. Aggregate tile strips     - 5-tile dashboard pattern
 *   11. Filter chips + sort       - list-page affordances
 *   12. Cards (generic + variants)
 *   13. Feed cards                - hub activity feed
 *   14. Vendor cards              - vendor list rows
 *   15. Pricing rows              - table-like records list
 *   16. Review cards              - rich-text + ratings
 *   17. Group buy cards           - state badges + progress + roster
 *   18. Discussion cards          - vote rail + body
 *   19. Vendor detail header      - identity card + about
 *   20. Member messaging slot     - top-of-content notifications
 *   21. Attribute filter panel    - category-driven filter UX
 *   22. Active filter pills       - removable filter strip
 *   23. Match summary chips       - per-card filter matches
 *   24. State badges + state dots - colored state indicators
 *   25. Progress bars             - state-tinted fills
 *   26. "Yours" / owner treatments - three-tier user relationship
 *   27. Vendor logo color palette
 *   28. Module badges             - review / pricing / etc.
 *   29. Buttons                   - btn-primary / btn-secondary
 *   30. Form controls             - input / select / textarea / check
 *   31. Alerts                    - success / danger / warning / info
 *   32. Module form pages         - create / edit pages
 *   33. Auth shell                - login / invite accept
 *   34. Utility classes
 */

/* ============================================================
 * 1. DESIGN TOKENS
 * ============================================================ */

:root {
    /* --- chrome (dark) --- */
    --c-chrome:           #071a33;   /* ClubsIQ dark shell navy */
    --c-chrome-2:         #0b2444;   /* topbar + nav hover */
    --c-chrome-3:         #12355f;   /* nav active bg */
    --c-chrome-ink:       #d8e2ef;   /* chrome text */
    --c-chrome-ink-strong:#f8fafc;   /* slate-50  — chrome active text */
    --c-chrome-ink-faint: #8da2ba;   /* chrome section header */
    --c-brand-asset-bg:   #04132a;   /* approved runtime logo edge */

    /* --- content (light) --- */
    --c-ink:              #0f172a;   /* primary text */
    --c-ink-muted:        #526174;   /* secondary text */
    --c-line:             #e2e8f0;   /* borders */
    --c-line-strong:      #cbd5e1;   /* stronger borders */
    --c-surface:          #f5f7fa;   /* content-pane bg */
    --c-surface-2:        #f1f5f9;   /* alt surface (hovers) */
    --c-card:             #ffffff;   /* card bg */

    /* --- accent + status (used sparingly per D6) --- */
    --c-accent:           #062e7b;   /* ClubsIQ primary navy */
    --c-accent-dark:      #071a33;   /* ClubsIQ dark shell navy */
    --c-success:          #09a651;   /* ClubsIQ growth green */
    --c-warning:          #d97706;   /* amber-600 */
    --c-danger:           #dc2626;   /* red-600 */

    /* --- type scale --- */
    --fs-xs:    11px;
    --fs-sm:    12px;
    --fs-base:  14px;
    --fs-lg:    16px;
    --fs-xl:    20px;
    --fs-2xl:   28px;
    --fs-3xl:   34px;

    /* --- layout --- */
    --w-nav:        260px;          /* LHS nav width */
    --h-topbar:     120px;          /* topbar / brand-zone height */
    --content-pad-x: 32px;          /* content pane horizontal padding */
    --content-pad-y: 24px;          /* content pane vertical padding */

    /* --- radii --- */
    --radius-sm:  4px;
    --radius:     8px;
    --radius-lg:  12px;
    --radius-pill: 14px;

    /* --- elevation --- */
    --shadow-sm: 0 1px 2px rgba(15, 23, 42, 0.06);
    --shadow:    0 1px 3px rgba(15, 23, 42, 0.08);

    /* --- font stack --- */
    --font-body: "InterVariable", "Inter", -apple-system, BlinkMacSystemFont,
                 "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
    --font-mono: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas,
                 monospace;
}

/* ============================================================
 * 2. BASE / RESET
 * ============================================================ */

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

html, body {
    margin: 0;
    padding: 0;
    height: 100%;
    font-family: var(--font-body);
    font-size: var(--fs-base);
    line-height: 1.45;
    color: var(--c-ink);
    background: var(--c-surface);
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
}

h1, h2, h3, h4, h5, h6 {
    color: var(--c-ink);
    line-height: 1.25;
    margin: 0 0 0.5em;
}
h1 { font-size: var(--fs-2xl); font-weight: 700; letter-spacing: -0.4px; }
h2 { font-size: var(--fs-xl);  font-weight: 600; }
h3 { font-size: var(--fs-lg);  font-weight: 600; }

p { margin: 0 0 1em; }

a {
    color: var(--c-accent);
    text-decoration: none;
}
a:hover { text-decoration: underline; }

code, kbd, pre {
    font-family: var(--font-mono);
    font-size: 0.92em;
}

button { font-family: inherit; }

/* ============================================================
 * 3. APP-SHELL LAYOUT GRID
 * ============================================================ */

.app-shell {
    --c-chrome:           #04132a;
    --c-chrome-2:         #071a33;
    --c-chrome-3:         #12355f;
    --c-brand-asset-bg:   #04132a;
    display: grid;
    grid-template-columns: var(--w-nav) minmax(0, 1fr);
    grid-template-rows: var(--h-topbar) auto 1fr;
    grid-template-areas:
        "brand    topbar"
        "lhsnav   transient"
        "lhsnav   content";
    height: 100vh;
    overflow: hidden;
}

/* ============================================================
 * 4. BRAND ZONE (top-left)
 * ============================================================ */

.app-shell .brand-zone {
    grid-area: brand;
    background: var(--c-brand-asset-bg) !important;
    color: var(--c-chrome-ink-strong);
    padding: 12px 14px;
    display: flex;
    align-items: center;
    justify-content: center;
    position: relative;
    border-right: 1px solid var(--c-chrome-2);
    border-bottom: 1px solid var(--c-chrome-2);
    overflow: hidden;
}
.brand-logo-underlay {
    position: absolute;
    inset: 0;
    background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR4nGNgEdb6DwABoQFB4VM0WQAAAABJRU5ErkJggg==");
    background-size: 100% 100%;
    z-index: 0;
}

/* Runtime dark-sidebar logo from the V1.4 brand package. */
.brand-logo-plate {
    background: transparent;
    border: 0;
    border-radius: 0;
    padding: 0;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 100%;
    min-height: 70px;
    box-shadow: none;
    position: relative;
    z-index: 1;
}
.brand-logo-img {
    height: auto;
    width: 228px;
    max-height: 92px;
    max-width: 100%;
    display: block;
    object-fit: contain;
}
.brand-logo-compact,
.brand-logo-mobile {
    display: none;
}

/* ============================================================
 * 5. TOP BANNER (club context, right column row 1)
 * ============================================================ */

.top-banner {
    grid-area: topbar;
    background: var(--c-chrome-2) !important;
    color: var(--c-chrome-ink-strong);
    display: flex;
    align-items: center;
    padding: 0 28px;
    gap: 20px;
    border-bottom: 1px solid var(--c-chrome-3);
    position: relative;
    min-width: 0;
    /* No overflow: hidden here — the user-menu dropdown is
       position:absolute inside .topbar-actions and must escape
       the topbar's row to render over the content-pane. The
       banner-image ``::before`` uses ``inset: 0`` so it is
       already self-bounded and does not need parent clipping.
       If the future banner-upload chunk introduces media that
       overflows the topbar box, clip that media on its own
       element (e.g. an inner wrapper or the ``::before``) — do
       not put overflow:hidden back on .top-banner. */
}

/* Banner-image mode (D4). When club.banner_image_url is set, the
   topbar renders a hero background image from --club-banner-image.
   The icon-slot is hidden in image mode; only the text overlay shows. */
.top-banner.has-banner-image::before {
    content: "";
    position: absolute;
    inset: 0;
    background:
        linear-gradient(180deg,
            rgba(15, 23, 42, 0.55) 0%,
            rgba(15, 23, 42, 0.25) 50%,
            rgba(15, 23, 42, 0.55) 100%),
        var(--club-banner-image),
        linear-gradient(135deg,
            #1e3a5f 0%, #5b3a8a 30%, #c2410c 65%, #7c2d12 100%);
    background-size: cover;
    background-position: center;
    z-index: 0;
}
.top-banner.has-banner-image > * { position: relative; z-index: 1; }
.top-banner.has-banner-image {
    color: #ffffff;
}

.club-info {
    flex: 1;
    display: flex;
    align-items: center;
    gap: 18px;
    min-width: 0;
}

/* Club icon slot. Uploaded club emblems keep the square-rounded
   framing; the default placeholder is a rendered icon instead of
   text so empty clubs still feel intentional. */
.club-logo-slot {
    width: 96px; height: 96px;
    border-radius: var(--radius-lg);
    background: var(--c-chrome-3);
    border: 1px solid rgba(255, 255, 255, 0.18);
    display: flex; flex-direction: column;
    align-items: center; justify-content: center;
    color: var(--c-chrome-ink);
    flex-shrink: 0;
    overflow: hidden;
    box-shadow: 0 1px 3px rgba(0, 0, 0, 0.2);
}
.club-logo-slot.has-image {
    background: transparent;
}
.club-logo-slot.has-default-icon {
    background: #04132a;
    border: 0;
}
.club-logo-slot img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
}
.top-banner.has-banner-image .club-logo-slot { display: none; }

.club-text { min-width: 0; }
.club-name {
    font-weight: 700;
    font-size: var(--fs-3xl);
    letter-spacing: -0.4px;
    line-height: 1.1;
    margin-bottom: 8px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
/* A6 pass. "PebbleCreek Pickleball Club" is 27 characters and came
   out as "PebbleCreek Pickleball Cl…" — a club's own name, abbreviated
   to it on its own page. It needed about 449px and had about 444.
   Collapsing the topbar search to an icon gave the row ~226px back,
   which covers that name and most others at full size; these two
   steps cover the rest without letting the banner grow taller on
   every page. The ellipsis above stays as the last resort: a name no
   size will fit still has to degrade rather than overlap the icons.
   Lengths are decided in the template, since CSS cannot measure
   text — see the comment there for where the thresholds come from. */
.club-name.is-long { font-size: var(--fs-2xl); }
.club-name.is-very-long { font-size: var(--fs-xl); letter-spacing: -0.2px; }
.club-meta {
    color: var(--c-chrome-ink);
    font-size: var(--fs-sm);
    display: flex;
    gap: 18px;
    flex-wrap: wrap;
}
.club-meta i { margin-right: 4px; opacity: 0.75; }
.top-banner.has-banner-image .club-meta { color: rgba(255, 255, 255, 0.92); }

/* Topbar right side — icon-button actions + user chip. */
.topbar-actions {
    display: flex;
    align-items: center;
    gap: 6px;
    flex-shrink: 0;
}
/* Also matches the search <a> — an anchor needs the link defaults
   turned off to sit level with the two buttons beside it. */
.topbar-actions .icon-btn {
    background: transparent;
    border: 0;
    text-decoration: none;
    color: var(--c-chrome-ink);
    width: 36px; height: 36px;
    border-radius: var(--radius);
    display: flex; align-items: center; justify-content: center;
    cursor: pointer;
    font-size: var(--fs-lg);
}
.topbar-actions .icon-btn:hover {
    background: var(--c-chrome-3);
    color: var(--c-chrome-ink-strong);
}
.topbar-actions .user-chip,
.topbar-actions .club-chip {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 6px 12px 6px 6px;
    background: var(--c-chrome-3);
    border-radius: 18px;
    color: var(--c-chrome-ink-strong);
    font-size: var(--fs-sm);
    cursor: pointer;
    border: 0;
    font-family: inherit;
    white-space: nowrap;
}
.topbar-actions .club-chip {
    max-width: 260px;
}
.topbar-actions .club-chip span {
    overflow: hidden;
    text-overflow: ellipsis;
}
.topbar-actions .account-chip {
    width: 44px;
    height: 36px;
    justify-content: center;
    padding: 5px;
    gap: 0;
}
.topbar-actions .account-chip .xs {
    display: none;
}
.topbar-actions .user-chip .avatar,
.account-menu-header .avatar {
    width: 26px; height: 26px;
    border-radius: 50%;
    background: var(--c-accent);
    display: flex; align-items: center; justify-content: center;
    font-weight: 700;
    font-size: var(--fs-xs);
}
.mode-toggle-form { margin: 0; }
.mode-indicator {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    height: 30px;
    padding: 0 10px;
    border-radius: var(--radius-pill);
    font-size: var(--fs-xs);
    font-weight: 700;
    border: 1px solid transparent;
    white-space: nowrap;
    cursor: pointer;
    font-family: inherit;
}
.mode-indicator.is-admin {
    background: #dbeafe;
    border-color: #bfdbfe;
    color: #1e3a8a;
}
.mode-indicator.is-member {
    background: #ecfdf5;
    border-color: #bbf7d0;
    color: #065f46;
}
.mode-indicator i { font-size: 14px; }
.mode-indicator:hover {
    filter: brightness(0.98);
    box-shadow: 0 0 0 2px rgba(255, 255, 255, 0.2);
}
.mode-indicator:focus-visible {
    outline: 2px solid var(--c-accent);
    outline-offset: 2px;
}

/* User dropdown menu (replaces Bootstrap dropdown). Anchored to the
   user chip; toggled by simple JS click or HTMX. Closed by default. */
.user-menu {
    position: absolute;
    top: calc(100% - 8px);
    right: 0;
    background: var(--c-card);
    border: 1px solid var(--c-line);
    border-radius: var(--radius);
    box-shadow: 0 8px 24px rgba(15, 23, 42, 0.18);
    padding: 6px 0;
    min-width: 240px;
    z-index: 100;
    color: var(--c-ink);
    display: none;
}
.club-menu {
    min-width: 320px;
}
.account-menu-header {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 10px 16px 8px;
    color: var(--c-ink);
    font-size: var(--fs-sm);
}
.user-menu.is-open { display: block; }
.user-menu .menu-header {
    color: var(--c-ink-muted);
    font-size: var(--fs-xs);
    text-transform: uppercase;
    letter-spacing: 0.6px;
    padding: 8px 16px 4px;
    font-weight: 700;
}
.user-menu .menu-item {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 8px 16px;
    color: var(--c-ink);
    text-decoration: none;
    font-size: var(--fs-sm);
    background: transparent;
    border: 0;
    width: 100%;
    text-align: left;
    cursor: pointer;
    font-family: inherit;
}
.user-menu .menu-item:hover {
    background: var(--c-surface);
    text-decoration: none;
}
.user-menu .menu-item.is-active {
    background: #dbeafe;
    color: #1e3a8a;
}
.user-menu .menu-item.is-current-club {
    box-shadow: inset 3px 0 0 var(--c-accent);
    background: color-mix(in srgb, var(--c-accent) 12%, transparent);
}
.user-menu .menu-divider {
    height: 1px;
    background: var(--c-line);
    margin: 4px 0;
    border: 0;
}
.user-menu form { margin: 0; }

/* ============================================================
 * 6. TRANSIENT STRIP (col 2 row 2)
 * ============================================================ */

.transient-strip {
    grid-area: transient;
    background: transparent;
    min-height: 0;
}
.transient-strip:empty { display: none; }
.transient-strip .strip {
    padding: 8px 24px;
    font-size: var(--fs-sm);
    display: flex;
    align-items: center;
    gap: 10px;
}
.transient-strip .strip.warning { background: #fef3c7; color: #78350f; }
.transient-strip .strip.danger  { background: #fee2e2; color: #7f1d1d; }
.transient-strip .strip.success { background: #d1fae5; color: #064e3b; }
.transient-strip .strip.info    { background: #dbeafe; color: #1e3a8a; }

/* ============================================================
 * 7. LHS NAV (accordion)
 * ============================================================ */

.lhs-nav {
    grid-area: lhsnav;
    background: var(--c-chrome) !important;
    color: var(--c-chrome-ink);
    overflow-y: auto;
    padding: 16px 0;
}
.nav-section-header {
    color: var(--c-chrome-ink-faint);
    font-size: var(--fs-xs);
    text-transform: uppercase;
    letter-spacing: 0.6px;
    padding: 14px 20px 6px;
    margin-top: 8px;
}
.nav-item {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 9px 18px;
    color: var(--c-chrome-ink);
    text-decoration: none;
    cursor: pointer;
    border-left: 3px solid transparent;
    font-size: var(--fs-base);
}
.nav-item i {
    font-size: 16px;
    opacity: 0.85;
    width: 18px;
    text-align: center;
}
.nav-item:hover {
    background: var(--c-chrome-2);
    text-decoration: none;
}
.nav-item.is-active {
    background: var(--c-chrome-3);
    color: var(--c-chrome-ink-strong);
    border-left-color: var(--c-accent);
    font-weight: 500;
}
.nav-item .chevron {
    margin-left: auto;
    font-size: var(--fs-sm);
    opacity: 0.6;
    transition: transform 0.15s ease;
}
.nav-item.is-expanded .chevron { transform: rotate(90deg); }
.nav-children {
    background: rgba(0, 0, 0, 0.18);
    border-left: 0;
    padding: 4px 0;
}
.nav-children[hidden] { display: none; }
.nav-children .nav-item {
    padding-left: 50px;
    font-size: var(--fs-sm);
    color: var(--c-chrome-ink);
}
.nav-children .nav-item:hover { background: var(--c-chrome-2); }
.nav-children .nav-item.is-active {
    background: transparent;
    color: var(--c-chrome-ink-strong);
    border-left-color: var(--c-accent);
    font-weight: 500;
}

/* Nested sub-group inside ``.nav-children`` (e.g. Vendors → By
   category accordion, D1c 2026-05-20). Uses native <details>/
   <summary> so toggling needs no JS. The summary uses .nav-item
   styling via the .nav-subgroup-summary class. */
.nav-subgroup {
    /* <details> is a block element; reset list-style/marker
       browsers add by default to its <summary>. */
}
.nav-subgroup > summary {
    list-style: none;
    cursor: pointer;
}
.nav-subgroup > summary::-webkit-details-marker { display: none; }
.nav-subgroup-summary {
    /* Same shape as .nav-children .nav-item — the summary IS a
       nav-item visually but it lives inside a <details>. */
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 7px 18px 7px 50px;
    font-size: var(--fs-sm);
    color: var(--c-chrome-ink);
    border-left: 3px solid transparent;
}
.nav-subgroup-summary:hover { background: var(--c-chrome-2); }
.nav-subgroup-summary .chevron {
    margin-left: auto;
    font-size: var(--fs-sm);
    opacity: 0.6;
    transition: transform 0.15s ease;
}
.nav-subgroup[open] > .nav-subgroup-summary .chevron {
    transform: rotate(90deg);
}
/* Categories list nested under a sub-group — indent one level
   deeper than the parent's .nav-children. */
.nav-children .nav-children-nested .nav-item {
    padding-left: 64px;
    font-size: var(--fs-xs);
}

/* ============================================================
 * 8. CONTENT PANE
 * ============================================================ */

.content-pane {
    grid-area: content;
    overflow-y: auto;
    overflow-x: hidden;
    padding: var(--content-pad-y) var(--content-pad-x) 0;
    color: var(--c-ink);
    min-width: 0;
}

/* Scope chip (D9): active-filter affordance at top of content pane.
   Breadcrumb segments + red-accent X to clear. See
   BRANDING_DESIGN.md D9 for the segment-list contract. */
.scope-chip {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 6px 6px 6px 14px;
    background: var(--c-card);
    border: 1.5px solid #94a3b8;
    border-radius: 20px;
    font-size: var(--fs-base);
    color: var(--c-ink-muted);
    margin-bottom: 18px;
    box-shadow: var(--shadow);
}
.scope-chip .filter-icon {
    color: var(--c-ink-muted);
    font-size: 14px;
    margin-right: 2px;
}
.scope-chip .scope-segment {
    color: var(--c-ink-muted);
    text-decoration: none;
    padding: 2px 4px;
    border-radius: var(--radius-sm);
    font-weight: 500;
}
.scope-chip .scope-segment:hover {
    color: var(--c-accent);
    background: rgba(59, 130, 246, 0.08);
}
.scope-chip .scope-segment.current {
    color: var(--c-ink);
    font-weight: 700;
}
.scope-chip .scope-segment.current:hover { color: var(--c-accent); }
.scope-chip .scope-sep {
    color: #334155;
    font-size: 14px;
    font-weight: 700;
    margin: 0 3px;
}
.scope-chip .clear {
    background: transparent;
    border: 0;
    cursor: pointer;
    color: var(--c-danger);
    padding: 4px 8px;
    border-radius: var(--radius-pill);
    font-weight: 700;
    font-size: 13px;
    margin-left: 6px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    transition: background 0.12s ease, color 0.12s ease;
}
.scope-chip .clear:hover {
    background: #fee2e2;
    color: #991b1b;
}
.scope-chip .clear:focus-visible {
    outline: 2px solid var(--c-danger);
    outline-offset: 1px;
}

/* End-of-content-pane copyright footer (D15a). Muted small text;
   scrolls with content; doesn't consume chrome real estate. */
.copyright-footer {
    text-align: center;
    color: var(--c-ink-muted);
    font-size: var(--fs-xs);
    padding: 32px 16px 12px;
    margin-top: 32px;
    border-top: 1px solid var(--c-line);
}

/* ============================================================
 * 9. SECTION BANDS
 * ============================================================ */

/* Edge-to-edge dividers between content sections. Negative
   horizontal margins break out of the content-pane padding so
   they read as full-width strips. */
.section-band {
    background: var(--c-line);
    color: var(--c-ink-muted);
    padding: 8px var(--content-pad-x);
    margin: 0 calc(-1 * var(--content-pad-x)) 14px;
    display: flex;
    justify-content: space-between;
    align-items: center;
    font-size: var(--fs-xs);
    text-transform: uppercase;
    letter-spacing: 0.8px;
    border-top: 1px solid var(--c-line-strong);
    border-bottom: 1px solid var(--c-line-strong);
}
.section-band + .section-band { margin-top: 0; }
.section-band .band-eyebrow { font-weight: 700; color: var(--c-ink); }
.section-band .band-meta {
    text-transform: none;
    letter-spacing: 0;
    font-size: var(--fs-sm);
}
.section-band .band-meta strong { color: var(--c-ink); }
.section-band .band-meta a {
    color: var(--c-accent);
    text-decoration: none;
    margin-left: 6px;
    font-weight: 500;
}
.section-band .band-meta a:hover { text-decoration: underline; }
.content-pane > .section-band:first-child {
    margin-top: calc(-1 * var(--content-pad-y));
}

/* C4 (plan §5.3) — one block per tracked interest area on the
   personalised dashboard. The sub-band is the same band one step
   quieter: the member is inside "Your interest areas" already, so a
   second full-strength strip per area would out-shout the content it
   introduces. */
.interest-section { margin-bottom: 18px; }
.interest-section:last-child { margin-bottom: 0; }
.section-band-sub {
    background: var(--c-surface-2);
    border-top-color: var(--c-line);
    border-bottom-color: var(--c-line);
    margin-bottom: 10px;
}
.section-band-sub .band-meta {
    color: var(--c-ink-muted);
    max-width: 60ch;
    text-align: right;
}

/* ============================================================
 * 10. AGGREGATE TILE STRIPS
 * ============================================================ */

.aggregate-summary,
.activity-strip {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(min(220px, 100%), 1fr));
    gap: 12px;
    margin-bottom: 28px;
}
.agg-tile,
.activity-tile {
    background: var(--c-card);
    border: 1px solid var(--c-line);
    border-radius: var(--radius);
    padding: 14px 16px;
    min-width: 0;
}
/* Clickable variant — when the tile is wrapped in an <a> (e.g. the
   hub's activity strip where each tile links to its module list).
   Inherits text color, removes the default link underline, picks up
   a hover state matching the vendor-card hover for visual coherence. */
a.agg-tile,
a.activity-tile {
    color: inherit;
    text-decoration: none;
    transition: border-color 0.1s ease, background 0.1s ease;
}
a.agg-tile:hover,
a.activity-tile:hover {
    border-color: #94a3b8;
    background: #fafbfc;
    text-decoration: none;
}
.tile-label,
.agg-label {
    color: var(--c-ink-muted);
    font-size: var(--fs-xs);
    text-transform: uppercase;
    letter-spacing: 0.5px;
    margin-bottom: 6px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.tile-value,
.agg-value {
    font-size: var(--fs-2xl);
    font-weight: 600;
    line-height: 1.1;
    color: var(--c-ink);
    overflow-wrap: anywhere;
}
.category-action-row {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
    margin-top: 12px;
}
.category-action {
    display: inline-flex;
    align-items: center;
    min-height: 26px;
    padding: 4px 8px;
    border: 1px solid var(--c-line);
    border-radius: 999px;
    color: var(--c-ink-muted);
    font-size: var(--fs-xs);
    font-weight: 600;
    text-decoration: none;
    white-space: nowrap;
}
.category-action:hover {
    border-color: #94a3b8;
    color: var(--c-ink);
    text-decoration: none;
}
.callout-neutral {
    border: 1px solid var(--c-line);
    border-radius: var(--radius);
    background: #f8fafc;
    color: var(--c-ink-muted);
    padding: 10px 12px;
    font-size: var(--fs-sm);
}
.resource-admin-actions {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 8px;
    margin-top: 12px;
}
.resource-reject-form {
    display: inline-flex;
    align-items: center;
    gap: 6px;
}
.resource-reject-form input {
    width: 220px;
}
.agg-value .stars { color: var(--c-warning); }
.agg-value-sm {
    font-size: var(--fs-lg);
    font-weight: 600;
    color: var(--c-ink);
    line-height: 1.2;
}
.agg-value .agg-accent { color: var(--c-accent); }
.tile-trend,
.agg-trend {
    color: var(--c-success);
    font-size: var(--fs-xs);
    margin-top: 4px;
    overflow-wrap: anywhere;
}
.tile-trend.down,
.agg-trend.down { color: var(--c-danger); }
.tile-trend.muted-trend,
.agg-trend.muted-trend { color: var(--c-ink-muted); }

/* ============================================================
 * 11. FILTER CHIPS + SORT + VIEW TOGGLE
 * ============================================================ */

.filter-row {
    display: flex;
    justify-content: space-between;
    align-items: center;
    gap: 16px;
    margin-bottom: 14px;
    flex-wrap: wrap;
}
.filter-chips {
    display: flex;
    gap: 4px;
    flex-wrap: wrap;
    flex: 1;
}
.filter-chip {
    background: transparent;
    border: 1px solid var(--c-line);
    color: var(--c-ink-muted);
    border-radius: var(--radius-pill);
    padding: 4px 12px;
    font-size: var(--fs-xs);
    cursor: pointer;
    font-weight: 500;
    font-family: inherit;
    display: inline-flex;
    align-items: center;
    gap: 6px;
    text-decoration: none;
}
.filter-chip:hover { background: var(--c-card); }
.filter-chip.is-active {
    background: var(--c-ink);
    color: white;
    border-color: var(--c-ink);
}
.chip-count {
    font-size: 10px;
    background: rgba(255, 255, 255, 0.18);
    padding: 1px 6px;
    border-radius: 8px;
    font-weight: 600;
}
.filter-chip:not(.is-active) .chip-count {
    background: var(--c-surface);
    color: var(--c-ink-muted);
}

.sort-control {
    display: flex;
    align-items: center;
    gap: 8px;
    flex-wrap: wrap;
}
.sort-label {
    color: var(--c-ink-muted);
    font-size: var(--fs-sm);
}
.sort-select {
    background: var(--c-card);
    border: 1px solid var(--c-line);
    border-radius: var(--radius-sm);
    padding: 5px 28px 5px 10px;
    font-size: var(--fs-sm);
    color: var(--c-ink);
    font-family: inherit;
    cursor: pointer;
}
.view-toggle {
    background: var(--c-card);
    border: 1px solid var(--c-line);
    border-radius: var(--radius-sm);
    padding: 5px 10px;
    font-size: 14px;
    cursor: pointer;
    color: var(--c-ink-muted);
}
.view-toggle:hover { background: var(--c-surface); color: var(--c-ink); }
.advanced-filters-btn {
    background: var(--c-card);
    border: 1px solid var(--c-line);
    color: var(--c-ink);
    border-radius: var(--radius-sm);
    padding: 5px 12px;
    font-size: var(--fs-sm);
    text-decoration: none;
    font-weight: 500;
    display: inline-flex;
    align-items: center;
    gap: 6px;
}
.advanced-filters-btn:hover {
    background: var(--c-surface);
    border-color: #94a3b8;
    text-decoration: none;
}
.advanced-filters-btn i { font-size: 14px; color: var(--c-accent); }

/* ============================================================
 * 12. CARDS (generic base)
 * ============================================================ */

.card {
    background: var(--c-card);
    border: 1px solid var(--c-line);
    border-radius: var(--radius);
    padding: 16px 18px;
}
.card + .card { margin-top: 10px; }

/* ============================================================
 * 13. FEED CARDS (hub activity)
 * ============================================================ */

.feed { display: flex; flex-direction: column; gap: 8px; }
.feed-card {
    display: grid;
    grid-template-columns: 44px 1fr 32px;
    gap: 14px;
    background: var(--c-card);
    border: 1px solid var(--c-line);
    border-radius: var(--radius);
    padding: 14px 16px;
    align-items: start;
}
.feed-card:hover { border-color: var(--c-line-strong); }
.feed-card.admin-only {
    border-left: 3px solid var(--c-danger);
    padding-left: 13px;
}
.feed-icon {
    width: 38px; height: 38px;
    border-radius: var(--radius);
    display: flex; align-items: center; justify-content: center;
    color: white;
    font-size: 18px;
}
.feed-icon.review-bg     { background: var(--c-warning); }
.feed-icon.pricing-bg    { background: var(--c-success); }
.feed-icon.group-buy-bg  { background: var(--c-accent-dark); }
.feed-icon.discussion-bg { background: #7c3aed; }
.feed-icon.resource-bg   { background: #0f766e; }
.feed-icon.vendor-bg     { background: #db2777; }
.feed-icon.admin-bg      { background: var(--c-danger); }

.feed-meta {
    display: flex;
    align-items: center;
    gap: 8px;
    margin-bottom: 4px;
    flex-wrap: wrap;
}
.module-badge {
    display: inline-flex;
    align-items: center;
    border-radius: var(--radius-pill);
    padding: 2px 8px;
    font-size: var(--fs-xs);
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.5px;
}
.module-badge.review { background: #fef3c7; color: #92400e; }
.module-badge.pricing { background: #dcfce7; color: #166534; }
.module-badge.group-buy { background: #dbeafe; color: #1e3a8a; }
.module-badge.discussion { background: #ede9fe; color: #5b21b6; }
.module-badge.resource { background: #ccfbf1; color: #115e59; }
.feed-headline {
    font-size: var(--fs-base);
    color: var(--c-ink);
    margin-bottom: 6px;
}
.feed-headline a {
    color: var(--c-ink);
    text-decoration: none;
    border-bottom: 1px dotted var(--c-line);
}
.feed-headline a:hover { border-bottom-color: var(--c-ink); }
.feed-preview {
    color: var(--c-ink-muted);
    font-size: var(--fs-sm);
    line-height: 1.5;
}
.feed-action {
    color: var(--c-ink-muted);
    font-size: 18px;
    text-decoration: none;
    padding: 4px;
    border-radius: var(--radius-sm);
}
.feed-action:hover { background: var(--c-surface); color: var(--c-ink); }

/* "Load more" affordance used at the bottom of any list page. */
.list-loadmore,
.feed-loadmore {
    text-align: center;
    margin-top: 20px;
}
.loadmore-btn {
    background: transparent;
    border: 1px solid var(--c-line);
    color: var(--c-ink-muted);
    border-radius: 16px;
    padding: 6px 18px;
    font-size: var(--fs-sm);
    cursor: pointer;
    font-family: inherit;
}
.loadmore-btn:hover {
    background: var(--c-card);
    color: var(--c-ink);
}

/* ============================================================
 * 14. VENDOR CARDS (list view)
 * ============================================================ */

.vendor-list {
    display: flex;
    flex-direction: column;
    gap: 8px;
}
.vendor-card {
    display: grid;
    grid-template-columns: 60px 1fr 32px;
    gap: 16px;
    background: var(--c-card);
    border: 1px solid var(--c-line);
    border-radius: var(--radius);
    padding: 14px 16px;
    align-items: center;
    text-decoration: none;
    color: inherit;
    transition: border-color 0.1s ease, background 0.1s ease;
}
.vendor-card:hover {
    border-color: #94a3b8;
    background: #fafbfc;
    text-decoration: none;
}
.vendor-logo {
    width: 56px; height: 56px;
    border-radius: var(--radius-lg);
    display: flex; align-items: center; justify-content: center;
    color: white;
    font-weight: 700;
    font-size: var(--fs-lg);
    letter-spacing: 0.5px;
}
.vendor-body { min-width: 0; }
.vendor-name {
    font-size: var(--fs-lg);
    font-weight: 600;
    color: var(--c-ink);
    line-height: 1.2;
}
.vendor-domain {
    color: var(--c-ink-muted);
    font-size: var(--fs-sm);
    margin-top: 2px;
    margin-bottom: 8px;
}
.vendor-tags {
    display: flex;
    gap: 6px;
    align-items: center;
    flex-wrap: wrap;
    margin-bottom: 8px;
}
.vendor-regions {
    color: var(--c-ink-muted);
    font-size: var(--fs-xs);
    margin-left: 6px;
    font-family: var(--font-mono);
}
.vendor-stats {
    display: flex;
    gap: 16px;
    font-size: var(--fs-sm);
    color: var(--c-ink-muted);
    align-items: center;
    flex-wrap: wrap;
}
.vendor-stats strong { color: var(--c-ink); font-weight: 600; }
.vendor-stats .stars { color: var(--c-warning); font-weight: 600; }
.activity-marker {
    position: relative;
    display: inline-flex;
    align-items: center;
    gap: 4px;
    border-radius: var(--radius-pill);
    outline: none;
}
.vendor-card:focus-visible .activity-marker {
    box-shadow: 0 0 0 3px rgba(37, 99, 235, 0.24);
}
.activity-marker::after {
    content: attr(data-tooltip);
    position: absolute;
    left: 0;
    bottom: calc(100% + 8px);
    width: max-content;
    max-width: 260px;
    padding: 6px 8px;
    border-radius: var(--radius);
    background: var(--c-ink);
    color: #ffffff;
    font-size: var(--fs-xs);
    line-height: 1.35;
    white-space: normal;
    box-shadow: var(--shadow-md);
    opacity: 0;
    pointer-events: none;
    transform: translateY(4px);
    transition: opacity 120ms ease, transform 120ms ease;
    z-index: 8;
}
.activity-marker:hover::after,
.vendor-card:focus-visible .activity-marker::after {
    opacity: 1;
    transform: translateY(0);
}
.vendor-stats .activity-dot {
    color: var(--c-success);
    font-size: 7px;
    vertical-align: middle;
    margin-right: 3px;
}
.vendor-stats .activity-dot::before {
    content: "●";
}
.vendor-stats .activity-dot.recent { color: var(--c-accent); }
.vendor-stats .activity-dot.older,
.vendor-stats .activity-dot.dim { color: var(--c-ink-muted); }
.vendor-action {
    color: var(--c-ink-muted);
    font-size: 18px;
    justify-self: end;
}
.vendor-card:hover .vendor-action { color: var(--c-accent); }

/* Smaller vendor logo used inside pricing rows + review headers. */
.vendor-logo-sm {
    width: 36px; height: 36px;
    border-radius: var(--radius);
    display: flex; align-items: center; justify-content: center;
    color: white;
    font-weight: 700;
    font-size: var(--fs-sm);
    text-decoration: none;
    flex-shrink: 0;
}
.vendor-logo-sm:hover { text-decoration: none; }

/* Vendor link inline (anywhere a vendor name appears as a link). */
.vendor-link {
    color: var(--c-ink);
    font-weight: 600;
    text-decoration: none;
    font-size: inherit;
}
.vendor-link:hover { color: var(--c-accent); text-decoration: none; }

/* Dashboard hero search (§8 acceptance criterion).
 *
 * Deliberately the largest thing on the dashboard. The topbar field
 * is available everywhere and teaches nobody what it does; this one
 * is sized, headed and exemplified so that a member who has never
 * heard the word "tag" still learns that two plain words return a
 * blend across every module. */
.hero-search {
    background: var(--c-card);
    border: 1px solid var(--c-line);
    border-radius: var(--radius-lg);
    padding: 22px 24px;
    margin-bottom: 22px;
}
.hero-search-title {
    font-size: var(--fs-xl);
    font-weight: 600;
    margin: 0 0 4px;
}
.hero-search-sub {
    font-size: var(--fs-sm);
    color: var(--c-ink-muted);
    margin: 0 0 14px;
}
.hero-search-row {
    display: flex;
    gap: 10px;
    align-items: flex-start;
}
/* The shared .search-input-wrap carries a bottom margin for stacked
 * forms; inside the hero it sits in a flex row, so drop it. */
.hero-search-input-wrap {
    flex: 1 1 auto;
    margin-bottom: 0;
}
.hero-search-submit {
    flex: 0 0 auto;
    padding-left: 24px;
    padding-right: 24px;
}
.hero-search-examples {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 8px;
    margin-top: 14px;
}
.hero-search-examples-label {
    font-size: var(--fs-xs);
    color: var(--c-ink-muted);
}
.hero-search-example {
    padding: 5px 11px;
    border-radius: 999px;
    background: var(--c-surface-2);
    border: 1px solid var(--c-line);
    font-size: var(--fs-xs);
    color: var(--c-ink);
}
.hero-search-example:hover {
    border-color: var(--c-accent);
    text-decoration: none;
}

/* Search bar used on the vendor list. */
.search-area { margin-bottom: 14px; }
.search-input-wrap {
    position: relative;
    margin-bottom: 12px;
}
.search-input-wrap .search-icon {
    position: absolute;
    left: 14px; top: 50%;
    transform: translateY(-50%);
    color: var(--c-ink-muted);
    font-size: 16px;
    pointer-events: none;
}
.search-input {
    width: 100%;
    background: var(--c-card);
    border: 1px solid var(--c-line);
    border-radius: var(--radius);
    padding: 12px 50px 12px 42px;
    font-size: var(--fs-base);
    color: var(--c-ink);
    font-family: inherit;
}
.search-input::placeholder { color: var(--c-ink-muted); }
.search-input:focus {
    outline: none;
    border-color: var(--c-accent);
    box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.12);
}
.search-shortcut-hint {
    position: absolute;
    right: 14px; top: 50%;
    transform: translateY(-50%);
    color: var(--c-ink-muted);
    font-size: var(--fs-xs);
}
.search-shortcut-hint kbd {
    background: var(--c-surface);
    border: 1px solid var(--c-line);
    border-radius: var(--radius-sm);
    padding: 1px 6px;
    font-family: var(--font-mono);
    font-size: 11px;
    color: var(--c-ink-muted);
}

/* ============================================================
 * 15. PRICING ROWS (table-like records list)
 * ============================================================ */

.pricing-list {
    display: flex;
    flex-direction: column;
    gap: 4px;
}
.pricing-row {
    display: grid;
    grid-template-columns: 1.5fr 1.8fr 0.9fr 1.3fr 0.9fr;
    gap: 16px;
    background: var(--c-card);
    border: 1px solid var(--c-line);
    border-radius: var(--radius);
    padding: 12px 16px;
    align-items: center;
    font-size: var(--fs-sm);
}
/* Scoped pricing view has no vendor column → 4 columns. */
.pricing-row.scoped {
    grid-template-columns: 2fr 1fr 1.5fr 1fr;
}
.pricing-row:hover {
    border-color: #94a3b8;
    background: #fafbfc;
}
.pricing-row.pricing-yours {
    border-left: 3px solid var(--c-accent);
    background: #f0f7ff;
}
.pricing-row.pricing-yours:hover { background: #e5f0fc; }
.pricing-vendor {
    display: flex;
    align-items: center;
    gap: 10px;
}
.pricing-product-name {
    font-weight: 600;
    color: var(--c-ink);
    margin-bottom: 2px;
}
.pricing-amount {
    font-size: var(--fs-lg);
    font-weight: 600;
    color: var(--c-ink);
    font-variant-numeric: tabular-nums;
    line-height: 1.1;
}
.contributor-name {
    color: var(--c-ink);
    font-weight: 500;
    margin-bottom: 2px;
}
.contributor-name.muted em {
    color: var(--c-ink-muted);
    font-style: italic;
    font-weight: 400;
}
.pricing-when div:first-child { color: var(--c-ink); }

/* ============================================================
 * 16. REVIEW CARDS (rich-text + ratings)
 * ============================================================ */

.review-list { display: flex; flex-direction: column; gap: 10px; }
.review-card {
    background: var(--c-card);
    border: 1px solid var(--c-line);
    border-radius: var(--radius);
    padding: 16px 18px;
}
.review-card.review-yours {
    border-left: 3px solid var(--c-accent);
    background: #f0f7ff;
    padding-left: 15px;
}
.review-header {
    display: grid;
    grid-template-columns: 36px 1fr;
    gap: 12px;
    margin-bottom: 10px;
    align-items: start;
}
.review-header.scoped { display: block; }
.review-header-text { min-width: 0; }
.review-rating-line {
    display: flex;
    align-items: center;
    gap: 8px;
    font-size: var(--fs-base);
    color: var(--c-ink);
    flex-wrap: wrap;
    margin-bottom: 4px;
}
.stars-bright {
    color: var(--c-warning);
    font-size: var(--fs-base);
    letter-spacing: 1px;
}
.stars-dim {
    color: var(--c-line);
    font-size: var(--fs-base);
    letter-spacing: 1px;
}
.rating-num {
    font-weight: 600;
    color: var(--c-ink);
    font-variant-numeric: tabular-nums;
    font-size: var(--fs-sm);
    margin-left: -2px;
}
.review-vendor-link {
    color: var(--c-ink-muted);
    font-size: var(--fs-sm);
}
.review-vendor-link a {
    color: var(--c-ink);
    font-weight: 600;
    text-decoration: none;
}
.review-vendor-link a:hover { color: var(--c-accent); }

.recommend-tag {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    background: #d1fae5;
    color: #065f46;
    padding: 2px 8px;
    border-radius: 10px;
    font-size: var(--fs-xs);
    font-weight: 500;
    margin-left: 4px;
}
.recommend-tag.tentative { background: #fef3c7; color: #78350f; }
.recommend-tag.negative  { background: #fee2e2; color: #7f1d1d; }

.review-byline {
    color: var(--c-ink-muted);
    font-size: var(--fs-sm);
}
.review-byline strong { color: var(--c-ink); font-weight: 600; }
.review-body {
    color: var(--c-ink);
    font-size: var(--fs-base);
    line-height: 1.55;
    margin: 0 0 14px;
    max-width: 760px;
}
.review-footer {
    display: flex;
    gap: 4px;
    align-items: center;
    border-top: 1px solid var(--c-line);
    padding-top: 10px;
}
.footer-btn {
    background: transparent;
    border: 0;
    color: var(--c-ink-muted);
    padding: 4px 10px;
    border-radius: var(--radius-sm);
    font-size: var(--fs-sm);
    cursor: pointer;
    font-family: inherit;
    display: inline-flex;
    align-items: center;
    gap: 6px;
}
.footer-btn:hover { background: var(--c-surface); color: var(--c-ink); }
.footer-btn strong { color: var(--c-ink); }
.footer-btn.report-btn { margin-left: auto; }
.footer-btn.report-btn:hover { color: var(--c-danger); }
.footer-stat {
    color: var(--c-ink-muted);
    font-size: var(--fs-sm);
    margin-left: auto;
    display: inline-flex;
    align-items: center;
    gap: 4px;
}
.rating-chip {
    color: var(--c-warning);
    margin-right: 4px;
    font-size: 11px;
}

/* ============================================================
 * 17. GROUP BUY CARDS (state badges + progress bars + roster)
 * ============================================================ */

.gb-list { display: flex; flex-direction: column; gap: 10px; }
.gb-card {
    display: grid;
    grid-template-columns: 48px 1fr;
    gap: 14px;
    background: var(--c-card);
    border: 1px solid var(--c-line);
    border-radius: var(--radius);
    padding: 16px 18px;
    align-items: start;
}
.gb-card.scoped { display: block; }
.gb-card.gb-yours {
    border-left: 3px solid var(--c-accent);
    background: #f0f7ff;
    padding-left: 15px;
}
.gb-card.gb-yours-owner {
    border-left: 3px solid var(--c-warning);
    background: #fffbeb;
    padding-left: 15px;
}
.gb-card.is-historical { background: #fafafa; }
.gb-card.is-historical .gb-title { color: var(--c-ink-muted); }
.gb-card.is-historical .vendor-logo-sm { opacity: 0.7; }

.gb-body { min-width: 0; }
.gb-head {
    display: flex;
    align-items: center;
    gap: 10px;
    margin-bottom: 6px;
    flex-wrap: wrap;
}
.gb-deadline {
    color: var(--c-ink-muted);
    font-size: var(--fs-sm);
}
.gb-deadline i { margin-right: 3px; opacity: 0.7; }
.your-commit-pill,
.owner-pill {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    padding: 2px 8px;
    border-radius: 10px;
    font-size: var(--fs-xs);
    font-weight: 600;
}
.your-commit-pill { background: #dbeafe; color: #1e3a8a; }
.owner-pill { background: #fef3c7; color: #78350f; }

.gb-title {
    margin: 0 0 4px;
    font-size: var(--fs-lg);
    font-weight: 600;
    color: var(--c-ink);
    line-height: 1.25;
}
.gb-meta {
    color: var(--c-ink-muted);
    font-size: var(--fs-sm);
    margin-bottom: 12px;
}
.gb-meta strong { color: var(--c-ink); }

.gb-progress { margin-bottom: 12px; }
.gb-footer {
    display: flex;
    justify-content: space-between;
    align-items: center;
    gap: 12px;
    padding-top: 12px;
    border-top: 1px solid var(--c-line);
    flex-wrap: wrap;
}
.commit-summary {
    display: flex;
    gap: 4px;
    align-items: center;
    flex-wrap: wrap;
}
.club-chip {
    background: var(--c-surface);
    border: 1px solid var(--c-line);
    color: var(--c-ink-muted);
    font-size: 10px;
    font-weight: 700;
    padding: 3px 8px;
    border-radius: 10px;
    letter-spacing: 0.5px;
}
.club-chip.pc-club {
    background: var(--c-accent);
    color: white;
    border-color: var(--c-accent);
}
.gb-actions { display: flex; align-items: center; gap: 8px; }
.btn-commit {
    background: var(--c-accent);
    color: white;
    border: 1px solid var(--c-accent);
    border-radius: var(--radius);
    padding: 6px 12px;
    font-size: var(--fs-sm);
    cursor: pointer;
    font-family: inherit;
    font-weight: 500;
    display: inline-flex;
    align-items: center;
    gap: 6px;
}
.btn-commit:hover { background: var(--c-accent-dark); border-color: var(--c-accent-dark); }
.btn-edit-commit,
.btn-view {
    background: transparent;
    border: 1px solid var(--c-line);
    border-radius: var(--radius);
    padding: 6px 12px;
    font-size: var(--fs-sm);
    color: var(--c-ink);
    cursor: pointer;
    font-family: inherit;
    font-weight: 500;
    display: inline-flex;
    align-items: center;
    gap: 6px;
    text-decoration: none;
}
.btn-edit-commit:hover,
.btn-view:hover {
    background: var(--c-surface);
    border-color: #94a3b8;
    text-decoration: none;
}

/* ============================================================
 * 18. DISCUSSION CARDS (vote rail + body)
 * ============================================================ */

.disc-list { display: flex; flex-direction: column; gap: 10px; }
.disc-card {
    display: grid;
    grid-template-columns: 56px 1fr;
    gap: 14px;
    background: var(--c-card);
    border: 1px solid var(--c-line);
    border-radius: var(--radius);
    padding: 14px 16px 14px 12px;
}
.disc-card.disc-yours {
    border-left: 3px solid var(--c-accent);
    background: #f0f7ff;
    padding-left: 9px;
}
.disc-rail {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 8px;
}
.vote-block {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 1px;
}
.vote-btn {
    background: transparent;
    border: 0;
    color: var(--c-ink-muted);
    font-size: 14px;
    cursor: pointer;
    padding: 1px 6px;
    border-radius: 3px;
}
.vote-btn:hover { background: var(--c-surface); color: var(--c-ink); }
.vote-btn.voted { color: var(--c-accent); }
.vote-score {
    font-size: var(--fs-sm);
    font-weight: 700;
    color: var(--c-ink);
    font-variant-numeric: tabular-nums;
}
.vote-score.voted { color: var(--c-accent); }

.op-avatar {
    position: relative;
    width: 36px; height: 36px;
    border-radius: 50%;
    display: flex; align-items: center; justify-content: center;
    color: white;
    font-weight: 700;
    font-size: var(--fs-xs);
    text-decoration: none;
    flex-shrink: 0;
    margin-top: 4px;
}
.op-avatar::after {
    content: attr(data-tooltip);
    position: absolute;
    left: 50%;
    bottom: calc(100% + 8px);
    width: max-content;
    max-width: 220px;
    padding: 6px 8px;
    border-radius: var(--radius);
    background: var(--c-ink);
    color: #ffffff;
    font-size: var(--fs-xs);
    font-weight: 600;
    line-height: 1.35;
    white-space: normal;
    box-shadow: var(--shadow-md);
    opacity: 0;
    pointer-events: none;
    transform: translate(-50%, 4px);
    transition: opacity 100ms ease 120ms, transform 100ms ease 120ms;
    z-index: 8;
}
.op-avatar:hover::after,
.op-avatar:focus-visible::after {
    opacity: 1;
    transform: translate(-50%, 0);
}
.op-avatar.op-anonymous {
    background: var(--c-line);
    color: var(--c-ink-muted);
    font-size: 16px;
}

.disc-body { min-width: 0; }
.disc-head {
    display: flex;
    align-items: center;
    gap: 10px;
    margin-bottom: 4px;
    flex-wrap: wrap;
}
.hot-tag {
    display: inline-flex;
    align-items: center;
    gap: 3px;
    background: #fef3c7;
    color: #78350f;
    font-size: var(--fs-xs);
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.4px;
    padding: 2px 8px;
    border-radius: 10px;
}
.disc-byline {
    color: var(--c-ink-muted);
    font-size: var(--fs-sm);
}
.disc-byline strong { color: var(--c-ink); font-weight: 600; }
.disc-title {
    margin: 4px 0 6px;
    font-size: var(--fs-lg);
    font-weight: 600;
    line-height: 1.3;
}
.disc-title a {
    color: var(--c-ink);
    text-decoration: none;
}
.disc-title a:hover {
    color: var(--c-accent);
    text-decoration: underline;
}
.disc-preview {
    color: var(--c-ink);
    font-size: var(--fs-sm);
    line-height: 1.55;
    margin-bottom: 10px;
    max-width: 760px;
}
.disc-footer {
    display: flex;
    justify-content: space-between;
    align-items: center;
    gap: 12px;
    padding-top: 10px;
    border-top: 1px solid var(--c-line);
    flex-wrap: wrap;
}
.disc-meta {
    color: var(--c-ink-muted);
    font-size: var(--fs-sm);
}
.disc-meta strong { color: var(--c-ink); }
.disc-actions { display: flex; gap: 2px; }
.action-btn {
    background: transparent;
    border: 0;
    color: var(--c-ink-muted);
    padding: 4px 8px;
    border-radius: var(--radius-sm);
    font-size: var(--fs-sm);
    cursor: pointer;
    font-family: inherit;
    display: inline-flex;
    align-items: center;
    gap: 4px;
}
.action-btn:hover { background: var(--c-surface); color: var(--c-ink); }

/* ============================================================
 * 19. VENDOR DETAIL HEADER
 * ============================================================ */

.vendor-header {
    display: grid;
    grid-template-columns: 96px 1fr auto;
    gap: 24px;
    padding: 22px;
    margin: 0 calc(-1 * var(--content-pad-x));
    margin-top: calc(-1 * var(--content-pad-y));
    background: var(--c-card);
    border-bottom: 1px solid var(--c-line);
    align-items: start;
}
.vendor-header-logo {
    width: 96px; height: 96px;
    border-radius: var(--radius-lg);
    display: flex; align-items: center; justify-content: center;
    color: white;
    font-weight: 700;
    font-size: 30px;
    letter-spacing: 1px;
}
.vendor-header-info { min-width: 0; }
.vendor-header-eyebrow {
    font-size: var(--fs-sm);
    margin-bottom: 4px;
}
.vendor-header-eyebrow a {
    color: var(--c-ink-muted);
    text-decoration: none;
}
.vendor-header-eyebrow a:hover { color: var(--c-accent); }
.vendor-header-name {
    margin: 0 0 4px;
    font-size: var(--fs-2xl);
    font-weight: 700;
    letter-spacing: -0.5px;
    color: var(--c-ink);
}
.vendor-header-domain {
    color: var(--c-ink-muted);
    font-size: var(--fs-base);
    margin-bottom: 10px;
}
.vendor-header-domain a {
    color: var(--c-accent);
    text-decoration: none;
}
.vendor-header-domain a:hover { text-decoration: underline; }
.vendor-header-domain i { font-size: 12px; margin-left: 2px; }
.vendor-meta-line {
    display: flex;
    gap: 22px;
    color: var(--c-ink-muted);
    font-size: var(--fs-sm);
    flex-wrap: wrap;
}
.vendor-meta-line i { margin-right: 4px; opacity: 0.7; }
.vendor-header-actions {
    display: flex;
    flex-direction: column;
    gap: 8px;
    align-items: stretch;
}

.vendor-about {
    margin: 0 calc(-1 * var(--content-pad-x));
    padding: 18px var(--content-pad-x) 22px;
    background: var(--c-card);
    border-bottom: 1px solid var(--c-line);
    margin-bottom: 18px;
}
.about-heading {
    font-size: var(--fs-sm);
    font-weight: 600;
    color: var(--c-ink-muted);
    text-transform: uppercase;
    letter-spacing: 0.6px;
    margin: 0 0 8px;
}
.about-body {
    margin: 0;
    color: var(--c-ink);
    font-size: var(--fs-base);
    line-height: 1.55;
    max-width: 720px;
}

/* Vendor detail page — supplementary blocks used by per-club
   notes, locations, attributes, and the per-module HTMX-loaded
   preview sections. */
.vendor-locations {
    list-style: none;
    padding: 0;
    margin: 0 0 18px;
    display: flex;
    flex-direction: column;
    gap: 8px;
}
.vendor-attributes {
    margin: 0 0 18px;
    display: grid;
    grid-template-columns: minmax(180px, 1fr) 2fr;
    gap: 8px 16px;
}
.vendor-attributes dt {
    color: var(--c-ink-muted);
    font-weight: 500;
    margin: 0;
}
.vendor-attributes dd {
    color: var(--c-ink);
    margin: 0;
}
.vendor-detail-section {
    margin-bottom: 18px;
}
.vendor-detail-danger-zone {
    margin-top: 28px;
    padding-top: 14px;
    border-top: 1px solid var(--c-line);
}

/* Compact preview-row used in vendor detail's per-module previews. */
.preview-list {
    display: flex;
    flex-direction: column;
    gap: 6px;
    margin-bottom: 28px;
}
.preview-list.compact {
    margin-bottom: 10px;
}
.preview-row {
    display: grid;
    grid-template-columns: 36px minmax(0, 1fr) auto;
    gap: 12px;
    background: var(--c-card);
    border: 1px solid var(--c-line);
    border-radius: var(--radius);
    padding: 10px 14px;
    align-items: start;
}
.preview-icon {
    width: 32px; height: 32px;
    border-radius: var(--radius);
    display: flex; align-items: center; justify-content: center;
    color: white;
    font-size: 14px;
}
.preview-icon.review-bg     { background: var(--c-warning); }
.preview-icon.pricing-bg    { background: var(--c-success); }
.preview-icon.group-buy-bg  { background: var(--c-accent-dark); }
.preview-icon.discussion-bg { background: #7c3aed; }
.preview-line-1 {
    font-size: var(--fs-base);
    color: var(--c-ink);
    display: flex;
    align-items: center;
    gap: 4px;
    flex-wrap: wrap;
}
.preview-line-1 .stars { color: var(--c-warning); font-size: var(--fs-sm); }
.preview-line-2 {
    margin-top: 2px;
    line-height: 1.45;
}
.preview-row-action {
    align-self: center;
    justify-self: end;
}
.preview-empty {
    background: var(--c-card);
    border: 1px dashed var(--c-line-strong);
    border-radius: var(--radius);
    color: var(--c-ink-muted);
    font-size: var(--fs-sm);
    padding: 14px 16px;
    margin: 0 0 10px;
}
.vendor-preview-toolbar {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    flex-wrap: wrap;
    margin-bottom: 10px;
}
.vendor-preview-copy {
    color: var(--c-ink-muted);
    font-size: var(--fs-sm);
}
.vendor-preview-actions {
    display: flex;
    align-items: center;
    gap: 8px;
    flex-wrap: wrap;
}
.review-aggregates {
    background: var(--c-card);
    border: 1px solid var(--c-line);
    border-radius: var(--radius);
    box-shadow: var(--shadow-sm);
    margin-bottom: 10px;
    padding: 14px 16px;
}
.review-aggregate-row {
    display: flex;
    align-items: baseline;
    gap: 18px;
    flex-wrap: wrap;
}
.review-aggregate-value {
    color: var(--c-ink);
    font-size: var(--fs-xl);
    font-weight: 700;
    line-height: 1;
}
.review-aggregate-label {
    color: var(--c-ink-muted);
    font-size: var(--fs-sm);
}

/* ============================================================
 * 20. MEMBER MESSAGING SLOT (top-of-content notifications)
 * ============================================================ */

.member-messages {
    display: flex;
    flex-direction: column;
    gap: 8px;
    margin-bottom: 28px;
}
.member-messages:empty { display: none; margin-bottom: 0; }
.message-card {
    display: grid;
    grid-template-columns: 40px 1fr 28px;
    gap: 14px;
    background: var(--c-card);
    border: 1px solid var(--c-line);
    border-left-width: 4px;
    border-radius: var(--radius);
    padding: 12px 14px;
    align-items: center;
}
.message-icon {
    width: 32px; height: 32px;
    border-radius: var(--radius);
    display: flex; align-items: center; justify-content: center;
    color: white;
    font-size: 16px;
}
.message-headline {
    font-size: var(--fs-base);
    color: var(--c-ink);
    line-height: 1.4;
}
.message-sub {
    color: var(--c-ink-muted);
    font-size: var(--fs-sm);
    margin-top: 4px;
}
.message-sub a {
    color: var(--c-accent);
    text-decoration: none;
    font-weight: 500;
}
.message-sub a:hover { text-decoration: underline; }
.message-dismiss {
    background: transparent;
    border: 0;
    color: var(--c-ink-muted);
    width: 28px; height: 28px;
    border-radius: var(--radius-sm);
    cursor: pointer;
    display: flex; align-items: center; justify-content: center;
    font-size: 14px;
    align-self: flex-start;
}
.message-dismiss:hover { background: var(--c-surface); color: var(--c-ink); }
.message-card.tone-action       { border-left-color: var(--c-warning); }
.message-card.tone-action       .message-icon { background: var(--c-warning); }
.message-card.tone-info         { border-left-color: var(--c-accent); }
.message-card.tone-info         .message-icon { background: var(--c-accent); }
.message-card.tone-announcement { border-left-color: #7c3aed; }
.message-card.tone-announcement .message-icon { background: #7c3aed; }
.message-card.tone-warning      { border-left-color: var(--c-danger); }
.message-card.tone-warning      .message-icon { background: var(--c-danger); }

/* ============================================================
 * 21. ATTRIBUTE FILTER PANEL (filter-by-attribute UX)
 * ============================================================ */

.attr-filter-panel {
    background: var(--c-card);
    border: 1px solid var(--c-line);
    border-radius: var(--radius-lg);
    padding: 14px 16px 4px;
    margin-bottom: 14px;
    margin-top: 4px;
}
.attr-filter-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    margin-bottom: 10px;
    padding-bottom: 8px;
    border-bottom: 1px solid var(--c-line);
}
.attr-filter-label {
    font-size: var(--fs-xs);
    text-transform: uppercase;
    letter-spacing: 0.8px;
    font-weight: 700;
    color: var(--c-ink);
}
.attr-filter-groups {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
    gap: 12px 18px;
    margin-bottom: 10px;
}
.attr-cross-filter-row {
    display: grid;
    grid-template-columns: 2fr 1fr;
    gap: 18px;
    border-top: 1px dashed var(--c-line);
    padding-top: 12px;
    margin-bottom: 10px;
}
.attr-group { min-width: 0; }
.attr-group-label {
    font-size: var(--fs-xs);
    color: var(--c-ink-muted);
    text-transform: uppercase;
    letter-spacing: 0.5px;
    font-weight: 600;
    margin-bottom: 6px;
}
.attr-group-chips {
    display: flex;
    gap: 4px;
    flex-wrap: wrap;
}
.attr-chip {
    display: inline-flex;
    align-items: center;
    background: transparent;
    border: 1px solid var(--c-line);
    color: var(--c-ink);
    border-radius: var(--radius-lg);
    padding: 3px 10px;
    font-size: var(--fs-xs);
    cursor: pointer;
    font-weight: 500;
    font-family: inherit;
    text-decoration: none;
}
.attr-chip:hover {
    border-color: #94a3b8;
    background: var(--c-surface);
}
.attr-chip.is-on {
    background: var(--c-accent);
    color: white;
    border-color: var(--c-accent);
}
.attr-chip.is-on:hover { background: var(--c-accent-dark); }

/* ============================================================
 * 22. ACTIVE FILTER PILLS (filter-by-attribute removable strip)
 * ============================================================ */

.active-filters {
    display: flex;
    align-items: center;
    gap: 6px;
    flex-wrap: wrap;
    margin-bottom: 14px;
    padding: 6px 0;
}
.active-filters-label {
    font-size: var(--fs-xs);
    text-transform: uppercase;
    letter-spacing: 0.5px;
    color: var(--c-ink-muted);
    font-weight: 600;
    margin-right: 4px;
}
.active-pill {
    display: inline-flex;
    align-items: center;
    gap: 2px;
    background: #dbeafe;
    color: #1e3a8a;
    font-size: var(--fs-xs);
    padding: 2px 4px 2px 10px;
    border-radius: var(--radius-lg);
    font-weight: 600;
}
.active-pill-x {
    background: transparent;
    border: 0;
    cursor: pointer;
    color: #1e3a8a;
    width: 20px; height: 20px;
    border-radius: 50%;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    font-size: 14px;
    font-family: inherit;
    font-weight: 700;
    transition: background 0.12s;
}
.active-pill-x:hover {
    background: rgba(220, 38, 38, 0.18);
    color: var(--c-danger);
}
.clear-all-filters {
    background: transparent;
    border: 1px solid var(--c-line);
    color: var(--c-danger);
    border-radius: var(--radius-lg);
    padding: 3px 10px;
    font-size: var(--fs-xs);
    cursor: pointer;
    font-weight: 600;
    margin-left: auto;
    font-family: inherit;
    display: inline-flex;
    align-items: center;
    gap: 4px;
}
.clear-all-filters:hover {
    background: #fee2e2;
    border-color: var(--c-danger);
}

/* ============================================================
 * 23. MATCH SUMMARY CHIPS (per-card filter matches)
 * ============================================================ */

.match-summary {
    display: flex;
    gap: 6px;
    flex-wrap: wrap;
    padding-top: 6px;
    border-top: 1px dashed var(--c-line);
}
.match-chip {
    display: inline-flex;
    align-items: center;
    gap: 3px;
    background: #d1fae5;
    color: #065f46;
    font-size: 10px;
    font-weight: 600;
    padding: 2px 8px;
    border-radius: 10px;
}
.match-chip i { font-size: 10px; }
.match-chip.partial {
    background: #fef3c7;
    color: #78350f;
}

/* ============================================================
 * 24. STATE BADGES + STATE DOTS (general purpose)
 * ============================================================ */

/* 8px dot used in filter chips + state badge bodies to correlate
   "I filtered by Open" with "this card has the Open badge". */
.state-dot {
    display: inline-block;
    width: 8px; height: 8px;
    border-radius: 50%;
    background: var(--c-ink-muted);
}
.state-dot.open       { background: var(--c-accent); }
.state-dot.committed  { background: var(--c-success); }
.state-dot.fulfilled  { background: var(--c-warning); }
.state-dot.closed     { background: var(--c-ink-muted); }

.gb-state-badge,
.state-badge {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    padding: 2px 10px;
    border-radius: var(--radius-pill);
    font-size: var(--fs-xs);
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.5px;
}
.gb-state-badge.state-open,       .state-badge.state-open       { background: #dbeafe; color: #1e3a8a; }
.gb-state-badge.state-committed,  .state-badge.state-committed  { background: #d1fae5; color: #065f46; }
.gb-state-badge.state-fulfilled,  .state-badge.state-fulfilled  { background: #fef3c7; color: #78350f; }
.gb-state-badge.state-closed,     .state-badge.state-closed     { background: var(--c-line); color: #475569; }

/* ============================================================
 * 25. PROGRESS BARS (state-tinted fills)
 * ============================================================ */

.progress-bar {
    background: var(--c-line);
    border-radius: 6px;
    height: 8px;
    overflow: hidden;
    margin-bottom: 4px;
}
.progress-fill {
    background: var(--c-accent);
    height: 100%;
    border-radius: 6px;
    transition: width 0.4s ease;
}
.progress-fill.state-committed-fill { background: var(--c-success); }
.progress-fill.state-fulfilled-fill { background: var(--c-warning); }
.progress-fill.state-closed-fill    { background: #94a3b8; }
.progress-text {
    font-size: var(--fs-sm);
    color: var(--c-ink);
}
.progress-text .muted { color: var(--c-ink-muted); }

/* ============================================================
 * 26. "YOURS" / OWNER TREATMENTS (three-tier user relationship)
 * ============================================================ */

/* See BRANDING_DESIGN.md D14. Specific cards (.gb-card, .review-card,
   .disc-card, .pricing-row) carry their own .gb-yours /
   .review-yours / .disc-yours / .pricing-yours classes wired into
   those sections above. This generic `.is-yours` is for any future
   card type that wants the same treatment. */
.is-yours {
    border-left: 3px solid var(--c-accent);
    background: #f0f7ff;
    padding-left: 15px;
}
.is-yours-owner {
    border-left: 3px solid var(--c-warning);
    background: #fffbeb;
    padding-left: 15px;
}

.you-tag {
    font-size: 10px;
    background: var(--c-accent);
    color: white;
    padding: 1px 6px;
    border-radius: 10px;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.4px;
    margin-left: 2px;
    margin-right: 2px;
}

/* ============================================================
 * 27. VENDOR LOGO COLOR PALETTE
 * ============================================================ */

.bg-1 { background: #2563eb; }   /* blue */
.bg-2 { background: #7c3aed; }   /* purple */
.bg-3 { background: #16a34a; }   /* green */
.bg-4 { background: #d97706; }   /* amber */
.bg-5 { background: #db2777; }   /* pink */
.bg-6 { background: #0891b2; }   /* cyan */
.bg-7 { background: #475569; }   /* slate */

/* ============================================================
 * 28. MODULE BADGES (review / pricing / group-buy / discussion / vendor / admin)
 * ============================================================ */

.badge {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    font-size: var(--fs-xs);
    padding: 2px 8px;
    border-radius: 10px;
    font-weight: 500;
    text-transform: uppercase;
    letter-spacing: 0.4px;
    text-decoration: none;
}
.badge:hover { text-decoration: none; filter: brightness(0.96); }
.badge.review     { background: #fef3c7; color: #78350f; }
.badge.pricing    { background: #d1fae5; color: #064e3b; }
.badge.group-buy  { background: #dbeafe; color: #1e3a8a; }
.badge.discussion { background: #ede9fe; color: #4c1d95; }
.badge.vendor     { background: #fce7f3; color: #831843; }
.badge.admin      { background: #fee2e2; color: #7f1d1d; }
.badge.current    { background: #d1fae5; color: #064e3b; }
/* The topic threads land in while their real one is decided. Amber
 * rather than neutral: an admin scanning the topic-health table
 * should see which row is the holding place without reading it. */
.badge.catchall   { background: #fef3c7; color: #78350f; }

/* ------------------------------------------------------------------
 * Chip semantics: three shapes, three meanings.
 *
 * A reader could not tell a taxonomy chip from an entity link from a
 * visibility state, because all three rendered as the same pill — and
 * `.thread-type.vendor` (Global) shared its exact colours with
 * `.badge.vendor`, while `.thread-type.category` (Club-only) shared
 * its colours with the topic badge. Shape now carries the meaning, so
 * it survives colour-blindness and browser-side theming:
 *
 *   square-cornered + square glyph -> topic (taxonomy, one per thread)
 *   pill + link glyph              -> vendor (a link to an entity)
 *   round pill, lowercase, #       -> tag (secondary keyword, many)
 *   no chip at all                 -> visibility (a state, below)
 * ------------------------------------------------------------------ */

.badge.topic {
    background: #ede9fe;
    color: #4c1d95;
    border-radius: 4px;
    text-transform: none;
    letter-spacing: 0;
    font-weight: 600;
}
.badge-square {
    display: inline-block;
    width: 7px;
    height: 7px;
    border-radius: 2px;
    background: #7c3aed;
}

.badge.tag {
    background: var(--c-surface-2);
    color: var(--c-ink-muted);
    border: 1px solid var(--c-line);
    border-radius: 999px;
    text-transform: none;
    letter-spacing: 0;
    font-weight: 500;
}

/* A tag the author asked for that has not been approved yet. Dashed,
 * because it is a promise rather than a fact — and never a link,
 * because there is nothing to link to until it exists. */
.badge.tag.is-pending {
    border-style: dashed;
    color: var(--c-ink-muted);
}
.badge.tag.is-pending .pending-note {
    margin-left: 6px;
    font-size: var(--fs-xs);
    text-transform: uppercase;
    letter-spacing: 0.4px;
    opacity: 0.75;
}
/* Approval checklist: the entity types a new tag will be offered on. */
.tag-allowance {
    border: 0;
    margin: 0;
    padding: 0;
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
    align-items: center;
}
.tag-allowance legend { float: none; width: auto; padding: 0; margin: 0 4px 0 0; }
.tag-allowance .badge.tag { display: inline-flex; align-items: center; gap: 5px; }
/* "None of these fit?" — the topic-gap disclosure under the topic
 * dropdown on the new-thread form. */
.topic-gap { margin-top: 8px; }
.topic-gap summary {
    cursor: pointer;
    font-size: var(--fs-sm);
    color: var(--c-ink-muted);
}
.topic-gap .form-control { margin-top: 8px; }

/* Cross-module tag page. The slug sits beside the display name in
 * the title — members meet tags as "#resurfacing", so the page they
 * land on should say that back to them. */
.tag-page .tag-slug {
    font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
    font-size: var(--fs-base);
    font-weight: 500;
    color: var(--c-ink-muted);
    margin-left: 8px;
}
.tag-pending-note {
    margin: -4px 0 14px;
}

/* Scope chips: what a typed "in <place>" was understood to mean.
 * Filled rather than outlined, because unlike the tag chips beside
 * them these are active filters narrowing the results, not
 * explanations of why a row is present. Each one removes itself. */
.search-scope-chips {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 6px;
    margin: 10px 0 0;
    font-size: var(--fs-xs);
}
.badge.scope-chip {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    border-radius: 999px;
    text-transform: none;
    letter-spacing: 0;
    font-weight: 600;
    background: var(--c-ink);
    color: #fff;
    border: 1px solid var(--c-ink);
}
.badge.scope-chip:hover { background: var(--c-chrome-2); text-decoration: none; }
.badge.scope-chip .bi { font-size: 12px; opacity: 0.8; }
.search-syntax-hint {
    margin: 8px 0 0;
    font-size: var(--fs-xs);
    color: var(--c-ink-muted);
}

/* The "matched through tags" strip on the search page. Sits between
 * the search box and the counts, so it reads as an explanation of the
 * results rather than another control. */
.search-matched-tags {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 6px;
    margin: 10px 0 0;
    font-size: var(--fs-xs);
}
.search-matched-label {
    color: var(--c-ink-muted);
    font-weight: 600;
}

/* Visibility is a state, so it is metadata rather than a chip: no
 * fill, no uppercase, and shown only for the exception. */
.thread-visibility {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    font-size: var(--fs-xs);
    color: var(--c-ink-muted);
    font-weight: 500;
}

/* ============================================================
 * 29. BUTTONS (Bootstrap-compatible class names per D3 transition)
 * ============================================================ */

.btn,
.btn-primary,
.btn-secondary,
.btn-outline-secondary,
.btn-success,
.btn-danger,
.btn-warning,
.btn-info,
.btn-outline-danger,
.btn-outline-warning,
.btn-outline-info,
.btn-link {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 6px;
    padding: 8px 16px;
    font-size: var(--fs-sm);
    font-weight: 500;
    font-family: inherit;
    border-radius: var(--radius);
    border: 1px solid;
    cursor: pointer;
    text-decoration: none;
    line-height: 1.4;
    transition: background-color 0.12s ease, border-color 0.12s ease,
                color 0.12s ease;
}
.btn,
.btn-outline-secondary,
.btn-secondary {
    background: var(--c-card);
    color: var(--c-ink);
    border-color: var(--c-line);
}
.btn:hover,
.btn-outline-secondary:hover,
.btn-secondary:hover {
    background: var(--c-surface);
    border-color: #94a3b8;
    text-decoration: none;
}
.btn-primary {
    background: var(--c-ink);
    color: white;
    border-color: var(--c-ink);
}
.btn-primary:hover {
    background: var(--c-chrome-2);
    border-color: var(--c-chrome-2);
    color: white;
    text-decoration: none;
}
.btn-success {
    background: var(--c-success);
    color: white;
    border-color: var(--c-success);
}
.btn-danger {
    background: var(--c-danger);
    color: white;
    border-color: var(--c-danger);
}
.btn-warning {
    background: var(--c-warning);
    color: #78350f;
    border-color: var(--c-warning);
}
.btn-info {
    background: var(--c-accent);
    color: white;
    border-color: var(--c-accent);
}
.btn-outline-danger {
    background: var(--c-card);
    color: var(--c-danger);
    border-color: #fecaca;
}
.btn-outline-danger:hover {
    background: #fef2f2;
    border-color: var(--c-danger);
    color: var(--c-danger);
}
.btn-outline-warning {
    background: var(--c-card);
    color: #92400e;
    border-color: #fde68a;
}
.btn-outline-warning:hover {
    background: #fffbeb;
    border-color: var(--c-warning);
    color: #78350f;
}
.btn-outline-info {
    background: var(--c-card);
    color: var(--c-accent);
    border-color: #bfdbfe;
}
.btn-outline-info:hover {
    background: #eff6ff;
    border-color: var(--c-accent);
    color: var(--c-accent-dark);
}
.btn-link {
    background: transparent;
    color: var(--c-accent);
    border-color: transparent;
    padding-inline: 4px;
}
.btn-link:hover {
    background: transparent;
    color: var(--c-accent-dark);
    text-decoration: underline;
}
.btn-sm {
    padding: 4px 10px;
    font-size: var(--fs-xs);
}
.btn:disabled,
.btn-primary:disabled,
.btn-secondary:disabled {
    opacity: 0.55;
    cursor: not-allowed;
}

/* ============================================================
 * 30. FORM CONTROLS (drop-in Bootstrap-name replacements)
 * ============================================================ */

.form-label {
    display: block;
    color: var(--c-ink);
    font-size: var(--fs-sm);
    font-weight: 500;
    margin-bottom: 6px;
}
.form-control,
.form-select {
    display: block;
    width: 100%;
    background: var(--c-card);
    border: 1px solid var(--c-line);
    border-radius: var(--radius);
    padding: 8px 12px;
    font-size: var(--fs-base);
    color: var(--c-ink);
    font-family: inherit;
    line-height: 1.45;
}
.form-control:focus,
.form-select:focus {
    outline: none;
    border-color: var(--c-accent);
    box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.12);
}
.form-control::placeholder { color: var(--c-ink-muted); }
.form-control-plaintext {
    display: block;
    width: 100%;
    background: transparent;
    border: 0;
    padding: 8px 0;
    color: var(--c-ink);
    font-family: inherit;
    font-size: var(--fs-base);
}
.form-text {
    color: var(--c-ink-muted);
    font-size: var(--fs-xs);
    margin-top: 4px;
}

.form-check {
    display: flex;
    align-items: flex-start;
    gap: 8px;
    flex-wrap: wrap;
    padding: 2px 0;
}
.form-check-input {
    appearance: none;
    -webkit-appearance: none;
    width: 18px; height: 18px;
    border: 1.5px solid var(--c-line-strong);
    border-radius: 4px;
    background: var(--c-card);
    cursor: pointer;
    flex-shrink: 0;
    margin-top: 2px;
    position: relative;
}
.form-check-input:checked {
    background: var(--c-accent);
    border-color: var(--c-accent);
}
.form-check-input:checked::after {
    content: "";
    position: absolute;
    left: 5px; top: 1px;
    width: 5px; height: 10px;
    border: solid white;
    border-width: 0 2px 2px 0;
    transform: rotate(45deg);
}
.form-check-input:focus-visible {
    outline: 2px solid var(--c-accent);
    outline-offset: 2px;
}
.form-check-label {
    color: var(--c-ink);
    font-size: var(--fs-sm);
    cursor: pointer;
}
.form-check .form-text {
    flex-basis: 100%;
    margin-left: 26px;
}

/* Validation states — Bootstrap-compatible naming. */
.form-control.is-invalid,
.form-select.is-invalid {
    border-color: var(--c-danger);
    box-shadow: 0 0 0 3px rgba(220, 38, 38, 0.10);
}
.invalid-feedback {
    display: block;
    color: var(--c-danger);
    font-size: var(--fs-xs);
    margin-top: 4px;
}

/* Optgroup styling for the region selector and similar. */
.form-select optgroup { font-weight: 700; color: var(--c-ink); }
.form-select option   { font-weight: 400; color: var(--c-ink); }

/* ============================================================
 * 31. ALERTS (Bootstrap-compatible naming for the PRG flash pattern)
 * ============================================================ */

.alert {
    padding: 10px 14px;
    border-radius: var(--radius);
    border: 1px solid transparent;
    font-size: var(--fs-sm);
    margin-bottom: 14px;
}
.alert-success { background: #d1fae5; color: #065f46; border-color: #a7f3d0; }
.alert-danger  { background: #fee2e2; color: #7f1d1d; border-color: #fecaca; }
.alert-warning { background: #fef3c7; color: #78350f; border-color: #fde68a; }
.alert-info    { background: #dbeafe; color: #1e3a8a; border-color: #bfdbfe; }

/* ============================================================
 * 31b. EMPTY-STATE PLACEHOLDERS
 * ============================================================
 * Used on the hub's "Recent activity" section in v1 (service not
 * yet built), and as a generic pattern for any list that may
 * legitimately have zero rows.
 */

.empty-feed {
    background: var(--c-card);
    border: 1px dashed var(--c-line-strong);
    border-radius: var(--radius);
    padding: 24px;
    text-align: center;
    margin-bottom: 18px;
}
.empty-feed p { margin: 0; }

/* ============================================================
 * 32. MODULE FORM PAGES
 * ============================================================ */

.module-form-page {
    max-width: 920px;
    margin: 0 auto;
}
.module-form-back {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    color: var(--c-ink-muted);
    font-size: var(--fs-sm);
    margin-bottom: 14px;
}
.module-form-back:hover { color: var(--c-accent); text-decoration: none; }
.module-form-header {
    margin-bottom: 18px;
}
.module-form-eyebrow {
    color: var(--c-ink-muted);
    font-size: var(--fs-xs);
    font-weight: 700;
    letter-spacing: 0.7px;
    text-transform: uppercase;
    margin-bottom: 6px;
}
.module-form-title {
    margin: 0 0 8px;
    font-size: var(--fs-2xl);
    font-weight: 700;
    color: var(--c-ink);
}
.module-form-copy {
    color: var(--c-ink-muted);
    font-size: var(--fs-sm);
    line-height: 1.55;
    max-width: 760px;
    margin: 0;
}
.module-form-panel {
    background: var(--c-card);
    border: 1px solid var(--c-line);
    border-radius: var(--radius);
    box-shadow: var(--shadow-sm);
    padding: 20px;
}
.module-form-actions {
    display: flex;
    gap: 10px;
    flex-wrap: wrap;
    padding-top: 4px;
}
.module-form-section-title {
    margin: 0 0 4px;
    color: var(--c-ink);
    font-size: var(--fs-lg);
    font-weight: 700;
}
.branding-upload-section {
    border: 1px solid var(--c-line);
    border-radius: var(--radius);
    padding: 16px;
    background: var(--c-surface);
}
.branding-upload-grid {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 16px;
    margin-top: 14px;
}
.branding-upload-card {
    display: grid;
    gap: 12px;
}
.branding-upload-preview {
    border: 1px dashed var(--c-line-strong);
    border-radius: var(--radius);
    background: var(--c-card);
    color: var(--c-ink-muted);
    display: flex;
    align-items: center;
    justify-content: center;
    overflow: hidden;
    min-height: 120px;
    text-align: center;
    font-size: var(--fs-sm);
}
.branding-upload-preview.is-icon {
    width: 128px;
    aspect-ratio: 1;
}
.branding-upload-preview.is-banner {
    aspect-ratio: 4 / 1;
}
.branding-upload-preview img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
}
.branding-upload-controls {
    display: flex;
    flex-direction: column;
    gap: 6px;
}
.branding-remove-check {
    margin-top: 4px;
}
.form-stack,
.vstack {
    display: flex;
    flex-direction: column;
}
.form-stack { gap: 16px; }
.vstack.gap-2 { gap: 8px; }
.vstack.gap-3 { gap: 16px; }
.form-grid {
    display: grid;
    gap: 16px;
}
.form-grid.cols-3 {
    grid-template-columns: repeat(3, minmax(0, 1fr));
}
.form-grid.cols-2 {
    grid-template-columns: repeat(2, minmax(0, 1fr));
}
.field-span-2 { grid-column: span 2; }
.field-span-3 { grid-column: 1 / -1; }
.form-subpanel {
    border-left: 3px solid var(--c-line-strong);
    padding-left: 14px;
}
.typeahead-wrap {
    position: relative;
}
.typeahead-panel {
    position: absolute;
    inset-inline: 0;
    top: calc(100% + 4px);
    z-index: 20;
    max-height: 280px;
    overflow-y: auto;
    background: var(--c-card);
    border: 1px solid var(--c-line);
    border-radius: var(--radius);
    box-shadow: var(--shadow);
}
.typeahead-panel a {
    display: block;
    padding: 9px 12px;
    color: var(--c-ink);
    border-bottom: 1px solid var(--c-line);
    text-decoration: none;
}
.typeahead-panel a:last-child { border-bottom: 0; }
.typeahead-panel a:hover { background: var(--c-surface); }
.selected-helper {
    color: var(--c-success);
    font-size: var(--fs-xs);
    margin-top: 6px;
}
.link-button {
    border: 0;
    background: transparent;
    color: var(--c-accent);
    padding: 0;
    font: inherit;
    cursor: pointer;
}
.link-button:hover { text-decoration: underline; }
.input-group {
    display: flex;
    align-items: stretch;
}
.input-group-text {
    display: inline-flex;
    align-items: center;
    padding: 0 12px;
    background: var(--c-surface);
    border: 1px solid var(--c-line);
    border-right: 0;
    border-radius: var(--radius) 0 0 var(--radius);
    color: var(--c-ink-muted);
    font-size: var(--fs-sm);
}
.input-group .form-control {
    border-radius: 0 var(--radius) var(--radius) 0;
}

/* ============================================================
 * 33. ADMIN PAGES
 * ============================================================ */

.admin-page {
    display: flex;
    flex-direction: column;
    gap: 18px;
}
.admin-back {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    color: var(--c-ink-muted);
    font-size: var(--fs-sm);
    width: fit-content;
}
.admin-back:hover { color: var(--c-accent); text-decoration: none; }
.admin-header {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: 16px;
    flex-wrap: wrap;
}
.admin-kicker {
    color: var(--c-ink-muted);
    font-size: var(--fs-xs);
    font-weight: 700;
    letter-spacing: 0.7px;
    text-transform: uppercase;
    margin-bottom: 6px;
}
.admin-title {
    margin: 0;
    color: var(--c-ink);
    font-size: var(--fs-2xl);
    font-weight: 700;
}
.admin-copy {
    color: var(--c-ink-muted);
    font-size: var(--fs-sm);
    line-height: 1.55;
    margin: 8px 0 0;
    max-width: 860px;
}
.admin-panel {
    background: var(--c-card);
    border: 1px solid var(--c-line);
    border-radius: var(--radius);
    box-shadow: var(--shadow-sm);
    padding: 18px;
}
.admin-panel-title {
    color: var(--c-ink);
    font-size: var(--fs-lg);
    font-weight: 700;
    margin: 0 0 10px;
}
.admin-toolbar {
    display: flex;
    align-items: end;
    justify-content: space-between;
    gap: 12px;
    flex-wrap: wrap;
}
.admin-filter-form {
    display: flex;
    align-items: end;
    gap: 10px;
    flex-wrap: wrap;
}
.admin-grid {
    display: grid;
    grid-template-columns: repeat(4, minmax(0, 1fr));
    gap: 14px;
}
.admin-grid.cols-3 {
    grid-template-columns: repeat(3, minmax(0, 1fr));
}
.admin-grid.cols-2 {
    grid-template-columns: repeat(2, minmax(0, 1fr));
}
.admin-stat {
    background: var(--c-card);
    border: 1px solid var(--c-line);
    border-radius: var(--radius);
    padding: 18px;
}
.admin-stat-label {
    color: var(--c-ink-muted);
    font-size: var(--fs-xs);
    font-weight: 700;
    letter-spacing: 0.7px;
    text-transform: uppercase;
    margin-bottom: 10px;
}
.admin-stat-value {
    color: var(--c-ink);
    font-size: 32px;
    line-height: 1;
    font-weight: 700;
    margin: 0;
}
.admin-stat-copy {
    color: var(--c-ink-muted);
    font-size: var(--fs-sm);
    line-height: 1.45;
    margin-top: 10px;
}
.admin-table-wrap,
.table-responsive {
    width: 100%;
    overflow-x: auto;
}
.admin-table,
.table {
    width: 100%;
    border-collapse: collapse;
    color: var(--c-ink);
    font-size: var(--fs-sm);
}
.admin-table th,
.admin-table td,
.table th,
.table td {
    padding: 10px 12px;
    border-bottom: 1px solid var(--c-line);
    vertical-align: top;
}
.admin-table th,
.table th {
    color: var(--c-ink-muted);
    font-size: var(--fs-xs);
    font-weight: 700;
    letter-spacing: 0.6px;
    text-align: left;
    text-transform: uppercase;
    white-space: nowrap;
}
.admin-table tr:last-child td,
.table tr:last-child td { border-bottom: 0; }
.table-hover tbody tr:hover { background: var(--c-surface); }
.admin-tabs {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
    border-bottom: 1px solid var(--c-line);
    padding-bottom: 10px;
}
.admin-tabs a {
    color: var(--c-ink-muted);
    border: 1px solid var(--c-line);
    border-radius: var(--radius-pill);
    padding: 6px 12px;
    text-decoration: none;
    font-size: var(--fs-sm);
    font-weight: 500;
}
.admin-tabs a:hover {
    border-color: var(--c-line-strong);
    color: var(--c-ink);
    text-decoration: none;
}
.admin-tabs a.active {
    background: var(--c-ink);
    border-color: var(--c-ink);
    color: white;
}
.admin-actions {
    display: flex;
    gap: 10px;
    flex-wrap: wrap;
    align-items: center;
}
/* Tag curation table (admin/tags/vocabulary.html). Each row edits in
 * place, because every decision here — duplicate? in use? does the
 * description say what a member would type? — is a comparison between
 * rows, and a detail page hides the comparison. */
.admin-table td.numeric { text-align: right; font-variant-numeric: tabular-nums; }
.admin-table th.numeric { text-align: right; }
.admin-table tr.is-retired td { opacity: 0.6; }
.admin-panel-note {
    margin: 14px 0 0;
    max-width: 68ch;
}
/* The catch-all-has-grown banner. Same left-accent-plus-tint shape as
 * `.gb-card.gb-yours-owner` and `.message-card.tone-action` — this is
 * already how the app says "this one wants your attention" without
 * saying "something is broken", which would be wrong here: a full
 * catch-all is the feature working and the vocabulary lagging. */
.admin-panel-alert {
    border-left: 3px solid var(--c-warning);
    background: #fffbeb;
    margin-bottom: 16px;
    padding-left: 15px;
}
.tag-curate-form {
    display: flex;
    flex-direction: column;
    gap: 6px;
    min-width: 260px;
    margin-bottom: 8px;
}
.tag-curate-form .form-control { font-size: var(--fs-sm); padding: 6px 10px; }
.tag-curate-form textarea.form-control { resize: vertical; }
.tag-curate-form button { align-self: flex-start; }
.tag-curate-actions { gap: 8px; }
.tag-merge-form {
    display: flex;
    gap: 6px;
    align-items: center;
}

.admin-detail-list {
    display: grid;
    grid-template-columns: max-content 1fr;
    column-gap: 18px;
    row-gap: 12px;
}
.admin-detail-list dt {
    color: var(--c-ink-muted);
    font-size: var(--fs-xs);
    font-weight: 700;
    letter-spacing: 0.6px;
    text-transform: uppercase;
}
.admin-detail-list dd { margin: 0; }
.admin-card {
    background: var(--c-card);
    border: 1px solid var(--c-line);
    border-radius: var(--radius);
    box-shadow: var(--shadow-sm);
    padding: 16px 18px;
}
.admin-card + .admin-card { margin-top: 10px; }
.admin-card-head {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: 12px;
    flex-wrap: wrap;
    margin-bottom: 10px;
}
.admin-card-badges {
    display: flex;
    align-items: center;
    gap: 6px;
    flex-wrap: wrap;
}
.admin-card-title {
    color: var(--c-ink);
    font-size: var(--fs-lg);
    line-height: 1.25;
    font-weight: 700;
    margin: 0 0 4px;
}
.admin-card-meta {
    color: var(--c-ink-muted);
    font-size: var(--fs-sm);
    line-height: 1.5;
    margin-bottom: 8px;
}
.admin-card-preview {
    color: var(--c-ink);
    font-size: var(--fs-sm);
    line-height: 1.55;
    margin: 0;
}
.admin-card-preview.is-empty {
    color: var(--c-ink-muted);
    font-style: italic;
}
.admin-card-preview.is-prewrap {
    white-space: pre-wrap;
}
.admin-detail-card {
    display: flex;
    flex-direction: column;
    gap: 8px;
}
.admin-detail-card .admin-card-title {
    font-size: var(--fs-xl);
}
.admin-action-panel {
    background: #fffbeb;
    border-color: #fde68a;
}
.admin-action-title {
    color: var(--c-ink);
    font-size: var(--fs-lg);
    font-weight: 700;
    margin: 0;
}
.admin-action-note {
    color: var(--c-ink-muted);
    font-size: var(--fs-sm);
    line-height: 1.5;
    margin: 0;
}
.admin-action-grid {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
}
.admin-action-grid form {
    margin: 0;
}
.admin-report-list {
    display: flex;
    flex-direction: column;
    gap: 10px;
}
.admin-inline-actions {
    border-top: 1px solid var(--c-line);
    margin-top: 12px;
    padding-top: 14px;
}
.admin-invite-modal .modal-dialog {
    max-width: 560px;
}
.admin-invite-modal .modal-content {
    background: var(--c-card);
    border: 1px solid var(--c-line);
    border-radius: var(--radius);
    box-shadow: var(--shadow);
    overflow: hidden;
}
.admin-invite-modal .modal-header,
.admin-invite-modal .modal-footer {
    align-items: center;
    border-color: var(--c-line);
    padding: 16px 18px;
}
.admin-invite-modal .modal-body {
    padding: 18px;
}
.admin-invite-modal .modal-title {
    color: var(--c-ink);
    font-size: var(--fs-lg);
    font-weight: 700;
    margin: 0;
}
.admin-row-actions {
    display: flex;
    align-items: center;
    justify-content: flex-end;
    gap: 6px;
    flex-wrap: wrap;
}
.pagination {
    display: flex;
    gap: 6px;
    list-style: none;
    margin: 0;
    padding: 0;
}
.page-link {
    display: inline-flex;
    align-items: center;
    border: 1px solid var(--c-line);
    border-radius: var(--radius-sm);
    color: var(--c-ink);
    padding: 5px 10px;
    text-decoration: none;
}
.page-item.active .page-link {
    background: var(--c-ink);
    border-color: var(--c-ink);
    color: white;
}
.page-item.disabled .page-link {
    color: var(--c-ink-muted);
    opacity: 0.55;
}
.card-body { padding: 0; }
.card-text { line-height: 1.55; }
.border-warning { border-color: #fde68a; }
.shadow-sm { box-shadow: var(--shadow-sm); }
.text-bg-light { background: var(--c-surface); color: var(--c-ink-muted); }
.text-bg-secondary { background: #e2e8f0; color: #334155; }
.text-bg-primary { background: #dbeafe; color: #1e3a8a; }
.text-bg-success { background: #dcfce7; color: #166534; }
.text-bg-warning { background: #fef3c7; color: #92400e; }
.text-bg-info { background: #dbeafe; color: #1e3a8a; }
.list-group {
    background: var(--c-card);
    border: 1px solid var(--c-line);
    border-radius: var(--radius);
    box-shadow: var(--shadow);
}
.list-group-item {
    display: block;
    padding: 9px 12px;
    color: var(--c-ink);
    text-decoration: none;
    border-bottom: 1px solid var(--c-line);
}
.list-group-item:last-child { border-bottom: 0; }
.list-group-item:hover { background: var(--c-surface); text-decoration: none; }
.visually-hidden {
    position: absolute !important;
    width: 1px !important;
    height: 1px !important;
    padding: 0 !important;
    margin: -1px !important;
    overflow: hidden !important;
    clip: rect(0, 0, 0, 0) !important;
    white-space: nowrap !important;
    border: 0 !important;
}

@media (max-width: 780px) {
    :root {
        --w-nav: 84px;
        --h-topbar: 104px;
        --content-pad-x: 22px;
        --content-pad-y: 20px;
    }
    .brand-zone {
        justify-content: center;
        padding: 10px;
    }
    .brand-logo-expanded { display: none; }
    .brand-logo-compact {
        display: block;
        width: 58px;
        max-height: 78px;
    }
    .lhs-nav {
        padding: 12px 0;
    }
    .nav-section-header,
    .nav-children,
    .nav-subgroup {
        display: none;
    }
    .nav-item,
    .nav-subgroup-summary {
        justify-content: center;
        padding: 12px 0;
        gap: 0;
        font-size: 0;
        border-left-width: 3px;
    }
    .nav-item i,
    .nav-subgroup-summary i {
        font-size: 19px;
        width: 24px;
        margin: 0;
    }
    .nav-item .chevron,
    .nav-subgroup-summary .chevron {
        display: none;
    }
    .top-banner {
        padding: 0 18px;
        gap: 12px;
    }
    .club-logo-slot {
        width: 72px;
        height: 72px;
    }
    .club-name {
        font-size: var(--fs-2xl);
    }
    .club-meta {
        gap: 10px;
    }
    .topbar-actions {
        gap: 4px;
    }
    .mode-indicator span {
        display: none;
    }
    .mode-indicator {
        width: 30px;
        justify-content: center;
        padding: 0;
    }
    .module-form-panel { padding: 16px; }
    .branding-upload-grid {
        grid-template-columns: 1fr;
    }
    .form-grid.cols-2,
    .form-grid.cols-3 {
        grid-template-columns: 1fr;
    }
    .field-span-2,
    .field-span-3 { grid-column: auto; }
    .admin-grid,
    .admin-grid.cols-3 {
        grid-template-columns: 1fr;
    }
    .admin-detail-list {
        grid-template-columns: 1fr;
    }
    .aggregate-summary,
    .activity-strip {
        grid-template-columns: repeat(3, minmax(0, 1fr));
        gap: 10px;
    }
    .feed-card {
        grid-template-columns: 40px 1fr 28px;
        gap: 12px;
        padding: 12px 14px;
    }
    .feed-icon {
        width: 36px;
        height: 36px;
    }
    .vendor-card {
        grid-template-columns: 52px 1fr 24px;
        gap: 12px;
        padding: 12px 14px;
    }
    .vendor-logo {
        width: 48px;
        height: 48px;
        font-size: var(--fs-base);
    }
    .gb-card,
    .disc-card {
        gap: 12px;
        padding: 12px 14px;
    }
    .vendor-header {
        grid-template-columns: 72px 1fr;
    }
    .vendor-header-logo {
        width: 72px;
        height: 72px;
    }
    .detail-grid,
    .filter-layout,
    .item-form-grid,
    .search-results-grid {
        grid-template-columns: 1fr;
    }
}

@media (max-width: 620px) {
    /* The hero's field and button share a row at desktop width; at
     * phone width the button would squeeze the field to nothing, so
     * they stack. */
    .hero-search-row { flex-direction: column; align-items: stretch; }
    .hero-search-submit { width: 100%; }
    :root {
        --w-nav: 64px;
        --h-topbar: 92px;
        --content-pad-x: 16px;
        --content-pad-y: 16px;
    }
    .brand-logo-compact { display: none; }
    .brand-logo-mobile {
        display: block;
        width: 44px;
        max-height: 56px;
    }
    .top-banner {
        padding: 0 12px;
    }
    .club-logo-slot {
        display: none;
    }
    .club-name {
        font-size: var(--fs-xl);
        margin-bottom: 4px;
    }
    /* Already at the smallest step here, so the length modifiers
       would only make a phone-sized title smaller again. */
    .club-name.is-long,
    .club-name.is-very-long {
        font-size: var(--fs-xl);
    }
    .club-meta {
        font-size: var(--fs-xs);
    }
    .topbar-actions .icon-btn {
        width: 32px;
        height: 32px;
    }
    .topbar-actions .user-chip {
        padding-right: 8px;
    }
    .topbar-actions .user-chip > span {
        display: none;
    }
    .content-pane > .section-band,
    .section-band {
        margin-left: -16px;
        margin-right: -16px;
        padding-left: 16px;
        padding-right: 16px;
    }
    .section-band {
        gap: 8px;
        align-items: flex-start;
    }
    .section-band .band-meta {
        width: 100%;
    }
    .aggregate-summary,
    .activity-strip {
        grid-template-columns: repeat(2, minmax(0, 1fr));
        gap: 8px;
        margin-bottom: 20px;
    }
    .agg-tile,
    .activity-tile {
        padding: 12px;
        min-width: 0;
    }
    .tile-value,
    .agg-value {
        font-size: var(--fs-xl);
    }
    .filter-chips,
    .module-form-actions,
    .admin-actions {
        gap: 8px;
    }
    .feed-card {
        grid-template-columns: 34px minmax(0, 1fr);
        gap: 10px;
        padding: 12px;
    }
    .feed-icon {
        width: 32px;
        height: 32px;
        font-size: 15px;
    }
    .feed-action {
        grid-column: 2;
        grid-row: 2;
        justify-self: end;
    }
    .feed-headline,
    .feed-copy {
        overflow-wrap: anywhere;
    }
    .vendor-card {
        grid-template-columns: 44px minmax(0, 1fr);
        gap: 10px;
        padding: 12px;
        align-items: start;
    }
    .vendor-logo {
        width: 40px;
        height: 40px;
        border-radius: var(--radius);
        font-size: var(--fs-sm);
    }
    .vendor-name {
        font-size: var(--fs-base);
    }
    .vendor-action {
        display: none;
    }
    .activity-marker::after {
        left: auto;
        right: 0;
        max-width: min(260px, calc(100vw - var(--w-nav) - 32px));
    }
    .gb-card {
        grid-template-columns: 1fr;
        padding: 12px;
    }
    .gb-card .vendor-logo-sm {
        width: max-content;
        max-width: 100%;
    }
    .gb-title,
    .disc-title {
        font-size: var(--fs-base);
        overflow-wrap: anywhere;
    }
    .gb-footer,
    .disc-footer {
        align-items: flex-start;
        flex-direction: column;
        gap: 10px;
    }
    .disc-card {
        grid-template-columns: 40px minmax(0, 1fr);
        gap: 10px;
        padding: 12px 12px 12px 10px;
    }
    .op-avatar {
        width: 36px;
        height: 36px;
    }
    .disc-head,
    .gb-head,
    .feed-meta {
        gap: 6px;
    }
    .vendor-header {
        grid-template-columns: 1fr;
        text-align: left;
    }
    .vendor-header-logo {
        width: 64px;
        height: 64px;
    }
    .module-form-page,
    .admin-page {
        max-width: none;
    }
    .admin-header {
        align-items: flex-start;
        flex-direction: column;
        gap: 8px;
    }
    .admin-title {
        font-size: var(--fs-xl);
    }
    .admin-tabs {
        overflow-x: auto;
        flex-wrap: nowrap;
        padding-bottom: 12px;
    }
    .admin-tabs a {
        white-space: nowrap;
    }
}

@media (max-width: 420px) {
    :root {
        --w-nav: 56px;
        --content-pad-x: 12px;
    }
    .brand-zone {
        padding: 8px;
    }
    .brand-logo-mobile {
        width: 40px;
    }
    .top-banner {
        padding: 0 10px;
    }
    .club-name {
        font-size: var(--fs-lg);
    }
    .club-meta,
    .topbar-actions .icon-btn[title="Help"] {
        display: none;
    }
    .content-pane > .section-band,
    .section-band {
        margin-left: -12px;
        margin-right: -12px;
        padding-left: 12px;
        padding-right: 12px;
    }
    .aggregate-summary,
    .activity-strip {
        grid-template-columns: 1fr;
    }
    .feed-card,
    .vendor-card,
    .gb-card,
    .disc-card,
    .module-form-panel,
    .admin-panel {
        border-radius: var(--radius-sm);
    }
    .pagination {
        flex-wrap: wrap;
    }
}

/* ============================================================
 * 34. AUTH SHELL
 * ============================================================ */

.auth-shell {
    min-height: 100vh;
    background:
        linear-gradient(135deg, rgba(7, 26, 51, 0.97) 0%, rgba(11, 36, 68, 0.92) 48%),
        radial-gradient(circle at 20% 15%, rgba(9, 166, 81, 0.16), transparent 28%),
        var(--c-chrome);
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 32px 20px;
}
.auth-panel {
    width: min(100%, 440px);
    display: flex;
    flex-direction: column;
    gap: 18px;
}
.auth-brand {
    display: flex;
    justify-content: center;
}
.auth-logo {
    display: block;
    width: min(100%, 360px);
    height: auto;
}
.auth-card {
    background: var(--c-card);
    border: 1px solid rgba(226, 232, 240, 0.92);
    border-radius: var(--radius);
    box-shadow: 0 18px 48px rgba(2, 6, 23, 0.28);
}
.auth-card-inner {
    padding: 26px;
}
.auth-title {
    margin-bottom: 18px;
    color: var(--c-ink);
    font-size: var(--fs-2xl);
}
.auth-copy {
    color: var(--c-ink-muted);
    font-size: var(--fs-sm);
    line-height: 1.55;
    margin-bottom: 18px;
}
.auth-form {
    display: flex;
    flex-direction: column;
    gap: 14px;
}
.auth-field {
    display: flex;
    flex-direction: column;
    gap: 6px;
}
.auth-label {
    color: var(--c-ink);
    font-size: var(--fs-sm);
    font-weight: 600;
}
.auth-input {
    width: 100%;
    min-height: 42px;
    border: 1px solid var(--c-line-strong);
    border-radius: var(--radius-sm);
    padding: 9px 11px;
    color: var(--c-ink);
    background: var(--c-card);
    font: inherit;
}
.auth-input:focus {
    outline: 2px solid rgba(6, 46, 123, 0.2);
    border-color: var(--c-accent);
}
.auth-help {
    color: var(--c-ink-muted);
    font-size: var(--fs-xs);
}
.auth-check {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    color: var(--c-ink-muted);
    font-size: var(--fs-sm);
    cursor: pointer;
    user-select: none;
}
.auth-check input {
    width: 16px;
    height: 16px;
    accent-color: var(--c-accent);
}
.auth-submit {
    width: 100%;
    min-height: 42px;
    border: 1px solid var(--c-accent);
    border-radius: var(--radius-sm);
    background: var(--c-accent);
    color: white;
    font: inherit;
    font-weight: 700;
    cursor: pointer;
    margin-top: 2px;
}
.auth-submit:hover {
    background: var(--c-chrome);
    border-color: var(--c-chrome);
}
.auth-alert {
    border-radius: var(--radius-sm);
    padding: 10px 12px;
    margin-bottom: 14px;
    font-size: var(--fs-sm);
    font-weight: 600;
}
.auth-alert.is-danger {
    background: #fee2e2;
    border: 1px solid #fecaca;
    color: #991b1b;
}
.auth-alert.is-success {
    background: #dcfce7;
    border: 1px solid #bbf7d0;
    color: #166534;
}
.auth-link {
    display: inline-flex;
    margin-top: 14px;
    color: var(--c-accent);
    font-size: var(--fs-sm);
    font-weight: 700;
    text-decoration: none;
}
.auth-link:hover {
    text-decoration: underline;
}
.error-code {
    color: var(--c-accent);
    font-size: 44px;
    font-weight: 800;
    line-height: 1;
    margin-bottom: 10px;
}
.error-actions {
    display: flex;
    align-items: center;
    gap: 10px;
    flex-wrap: wrap;
    margin-top: 18px;
}
.error-primary-action {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    text-decoration: none;
    width: auto;
    padding: 0 16px;
}
.error-primary-action:hover {
    color: white;
    text-decoration: none;
}
.error-secondary-action {
    color: var(--c-ink-muted);
    font-size: var(--fs-sm);
    font-weight: 700;
    text-decoration: none;
}
.error-secondary-action:hover {
    color: var(--c-accent);
    text-decoration: underline;
}

@media (max-width: 520px) {
    .auth-shell {
        align-items: flex-start;
        padding: 24px 14px;
    }
    .auth-logo { width: min(100%, 300px); }
    .auth-card-inner { padding: 20px; }
    .auth-title { font-size: var(--fs-xl); }
}

/* ============================================================
 * 34. UTILITY CLASSES
 * ============================================================ */

.muted   { color: var(--c-ink-muted); }
.small   { font-size: var(--fs-sm); }
.xs      { font-size: var(--fs-xs); }
.stars   { color: var(--c-warning); }

/* Spacing utilities — modest set to support common template needs
   without reintroducing all of Bootstrap. Extend as porting
   surfaces real shortfalls. */
.mt-0 { margin-top: 0 !important; }
.mb-0 { margin-bottom: 0 !important; }
.mb-2 { margin-bottom: 0.5rem !important; }
.mb-3 { margin-bottom: 1rem !important; }
.mb-4 { margin-bottom: 1.5rem !important; }
.me-2 { margin-right: 0.5rem !important; }
.me-3 { margin-right: 1rem !important; }
.ms-2 { margin-left: 0.5rem !important; }
.ms-3 { margin-left: 1rem !important; }
.ms-auto { margin-left: auto !important; }
.me-auto { margin-right: auto !important; }

.d-flex  { display: flex !important; }
.d-inline-flex { display: inline-flex !important; }
.d-block { display: block !important; }
.d-none  { display: none !important; }
.flex-column { flex-direction: column !important; }
/* Nine templates use `flex-wrap` on a `d-flex` row (governed-tag
 * pickers, chip rows, attribute lists). Only bootstrap-icons is
 * loaded, not Bootstrap itself, so the class resolved to nothing and
 * those rows ran off the page instead of wrapping. */
.flex-wrap { flex-wrap: wrap !important; }
.flex-nowrap { flex-wrap: nowrap !important; }
.align-items-center { align-items: center !important; }
.justify-content-between { justify-content: space-between !important; }
.gap-2 { gap: 0.5rem !important; }
.gap-3 { gap: 1rem !important; }

.text-center { text-align: center; }
.text-end    { text-align: right; }
.text-muted  { color: var(--c-ink-muted); }
.text-danger { color: var(--c-danger); }
.text-success { color: var(--c-success); }

/* No-decoration link helper (for cards/rows that wrap their content
   in an <a> but shouldn't underline). */
.no-underline,
.no-underline:hover { text-decoration: none; }

/* Hidden but accessible (for screen-readers / form labels). */
.visually-hidden {
    position: absolute;
    width: 1px; height: 1px;
    padding: 0; margin: -1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
    border: 0;
}

/* ---------------------------------------------------------------------
 * Member-message destination picker (M2b).
 *
 * A radio list, not a table of buttons: choosing a destination is
 * picking one of a set, and a radio says so without JavaScript.
 *
 * The unavailable rows stay on screen rather than being filtered out.
 * An author who cannot find the document they had in mind should learn
 * *why* it is not offered — "members of this club cannot open this" —
 * rather than conclude the search is broken and go looking for a URL
 * field that no longer exists.
 * ------------------------------------------------------------------ */
.target-options {
    list-style: none;
    margin: 0;
    padding: 0;
    border: 1px solid var(--c-line);
    border-radius: var(--radius);
    max-height: 320px;
    overflow-y: auto;
}
.target-option {
    padding: 10px 14px;
    border-bottom: 1px solid var(--c-line);
}
.target-option:last-child { border-bottom: 0; }
.target-option > label {
    display: flex;
    align-items: baseline;
    gap: 10px;
    cursor: pointer;
    margin: 0;
}
.target-option.is-unavailable > label { cursor: not-allowed; }
.target-option.is-unavailable .target-option-label { color: var(--c-ink-muted); }
.target-option-label { font-weight: 500; }
.target-option:hover:not(.is-unavailable) { background: var(--c-chrome-3); }

/* ---------------------------------------------------------------------
 * Icon picker (member messages).
 *
 * This was a text field asking for ``bi-exclamation-circle-fill`` — a
 * developer's string an author has never seen and a typo in which
 * renders a blank square on every member's dashboard. It was then a
 * grid of eleven tiles, which showed the glyphs but blew out the
 * height of a row it shares with two ordinary selects.
 *
 * So: a dropdown that looks like its neighbours and shows the glyph
 * beside the name. It has to be <details> rather than <select>,
 * because the option list of a native select is text in every browser
 * that matters and an icon cannot live in it.
 * ------------------------------------------------------------------ */
.icon-picker { position: relative; }
.icon-picker-summary {
    display: flex;
    align-items: center;
    gap: 10px;
    cursor: pointer;
    list-style: none;
    user-select: none;
}
/* The default disclosure triangle, replaced by a caret on the right so
   the control reads as the select it sits beside. */
.icon-picker-summary::-webkit-details-marker { display: none; }
.icon-picker-summary::after {
    content: "";
    margin-left: auto;
    width: 0;
    height: 0;
    border-left: 4px solid transparent;
    border-right: 4px solid transparent;
    border-top: 5px solid var(--c-ink-muted);
}
.icon-picker[open] .icon-picker-summary::after { transform: rotate(180deg); }
.icon-picker-menu {
    position: absolute;
    z-index: 30;
    top: calc(100% + 4px);
    left: 0;
    right: 0;
    max-height: 280px;
    overflow-y: auto;
    background: var(--c-card);
    border: 1px solid var(--c-line-strong);
    border-radius: var(--radius);
    box-shadow: 0 8px 24px rgba(15, 23, 42, 0.18);
    padding: 4px;
}
.icon-option {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 8px 10px;
    border-radius: var(--radius);
    cursor: pointer;
    margin: 0;
}
.icon-option:hover { background: var(--c-chrome-3); }
.icon-option input {
    position: absolute;
    opacity: 0;
    pointer-events: none;
}
.icon-option i { font-size: var(--fs-lg); width: 20px; text-align: center; }
/* Checked is marked by more than colour, so it survives a colour-blind
   viewer and a high-contrast mode. */
.icon-option:has(input:checked) {
    background: var(--c-chrome-3);
    font-weight: 600;
}
.icon-option:has(input:focus-visible) {
    outline: 2px solid var(--c-accent);
    outline-offset: -2px;
}

/* ---------------------------------------------------------------------
 * Admin table: figures and dates that must not wrap.
 *
 * "0 of 6" broke across two lines and read as two numbers; "Since 18
 * Sep" broke after the day. A count and a date are each one token to a
 * reader, whatever the column width, so they say so.
 * ------------------------------------------------------------------ */
.admin-table td.numeric,
.admin-table td.numeric .small,
.admin-table td.nowrap,
.admin-table td.nowrap .small {
    white-space: nowrap;
}

/* Topic reassign control on a thread (Discussions). The topic badge
 * becomes a select plus a button for an admin, so it has to sit on the
 * header row without pushing the badges around. */
.topic-reassign {
    display: inline-flex;
    align-items: center;
    gap: 6px;
}
.topic-reassign .form-control-sm { width: auto; min-width: 180px; }
