/* ================================================================
   UMMAH.BUZZ - "The Front Page of the Muslim Internet"
   Design System v1.0.0
   Extracted from ummah.city palette. Dark + light themes (NOT dark-only —
   [data-theme="light"] warm-cream palette ships since v1.3.3, Apr 19 2026).
   Mobile-first.
   ================================================================ */

/* ===== UMMAHONE PROMO BANNER =====
   May 14 (Mehek): slim the banner to a single compact bar on all viewports.
   Disproportionate height (items 2+3) comes from unconstrained padding + flex-wrap.
   Desktop: max-height 44px, vertically centered. No wrap allowed. */
#umg-supporter-banner {
    max-height: 52px;
    display: flex !important;
    align-items: center !important;
    overflow: hidden;
}
#umg-supporter-banner > div {
    flex-wrap: nowrap !important;
    align-items: center !important;
}
/* Jun 18: two copies of the banner text — full on desktop, terse single-line on
   mobile. The text span itself ellipsis-clips so it can NEVER wrap to a 2nd/3rd
   line and push the hero down on a phone. Default = desktop copy visible. */
.umg-banner-full { display: inline; }
.umg-banner-short { display: none; }
@media (max-width: 600px) {
    .umg-banner-full { display: none; }
    .umg-banner-short { display: inline; }
}
/* A-grade iter-4 (Jun 18): skip-to-main link (WCAG 2.4.1 A). Visually hidden
   until keyboard-focused, then a solid gold pill jumps to #main. Works in both
   themes (high-contrast gold-on-ink). */
.skip-link {
    position: fixed;
    left: 50%;
    top: 8px;
    transform: translate(-50%, -160%);
    z-index: 1000;
    padding: 10px 18px;
    min-height: 44px;
    display: inline-flex;
    align-items: center;
    background: #DFA032;
    color: #060B18;
    font-weight: 700;
    font-size: 0.875rem;
    border-radius: 8px;
    text-decoration: none;
    box-shadow: 0 4px 16px rgba(0,0,0,0.4);
    transition: transform 0.18s ease;
}
.skip-link:focus,
.skip-link:focus-visible {
    transform: translate(-50%, 0);
    outline: 2px solid #060B18;
    outline-offset: 2px;
}
/* A-grade iter-4 (Jun 18): banner dismiss "×" tap target. Was 24×22 (22×20 in
   QA's measure) → fails WCAG 2.5.5 (44px min). inline-flex centers the glyph
   inside a 44×44 hit box; negative margin keeps it from inflating banner height
   beyond the row it already occupies. */
.umg-banner-dismiss {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 44px;
    min-height: 44px;
    margin: -4px -8px -4px 0;
    border-radius: 8px;
}
.umg-banner-dismiss:focus-visible {
    outline: 2px solid rgba(255,255,255,0.7);
    outline-offset: -2px;
}

/* ===== TOKENS ===== */
:root {
    --buzz-void: #060B18;
    --buzz-deep: #0A1128;
    --buzz-surface: #0F1A33;
    --buzz-border: #1A2744;
    --buzz-border-alpha: rgba(26, 39, 68, 0.8);
    --buzz-gold: #DFA032;
    --buzz-gold-light: #F0C96E;
    /* Estate design pass round 3 (Aug 11 2026, item 2, dark-mode AA fix): #8B6914
       measured 3.86:1 against the #060B18 bold text used on .hero-cta/.submit-btn/
       .ub-ad-fallback-cta (all three share this exact gradient(--buzz-gold,
       --buzz-gold-dim) + #060B18-text pattern) - below AA 4.5:1 for 14-15px text.
       This is the DARK stop, i.e. the darkest point of the gradient, so it's the
       binding constraint for the whole gradient (--buzz-gold itself measures
       8.62:1, never the problem). Raised to #A87D1E: 5.26:1 against #060B18,
       verified both by the WCAG relative-luminance formula and by a real
       pixel-compositing sample at the gradient's darkest rendered corner (see the
       round-3 report) - not just token math. Same gold family/hue, one shade
       lighter - not a switch to a different color, and RULING-AGNOSTIC (doesn't
       touch the separate live gold-vs-forest CTA-fill decision). The light-theme
       --buzz-gold-dim below (#A6751F) is untouched - it was already AA-safe in
       its own light-theme contexts and isn't part of this bug. */
    --buzz-gold-dim: #A87D1E;
    --buzz-gold-glow: rgba(223, 160, 50, 0.15);
    --buzz-teal: #14B8A6;
    --buzz-teal-dark: #0D9488;
    --buzz-text: #C8D0E0;
    --buzz-text-muted: #8892A4;  /* May 14: raised from #6B7280 — WCAG AA on dark bg */
    --buzz-text-dim: #7A8899;    /* Aug 11 estate design pass: raised from #5E6B7E — the May 14
                                     raise still measured 3.55:1 against the real card bg (needs
                                     4.5:1 for normal-size text; verified via rendered-pixel sample,
                                     not just token math). Stays lower-contrast than --buzz-text-muted
                                     (6.13:1) so the dim/muted hierarchy holds. */
    --buzz-heading: #FFFFFF;
    --buzz-card-bg: linear-gradient(145deg, rgba(15, 26, 51, 0.7), rgba(6, 11, 24, 0.85));
    --buzz-card-border: rgba(26, 39, 68, 0.8);
    --buzz-header-bg: rgba(6, 11, 24, 0.85);
    --buzz-header-border: rgba(26, 39, 68, 0.5);
    --buzz-input-bg: rgba(6, 11, 24, 0.6);
    --buzz-hover-wash: rgba(223, 160, 50, 0.06);
    --buzz-gold-tint-strong: rgba(223, 160, 50, 0.12);
    --buzz-danger: #EF4444;
    --buzz-ease: cubic-bezier(0.16, 1, 0.3, 1);
    --buzz-radius: 14px;
    --buzz-radius-sm: 8px;
    --buzz-radius-pill: 9999px;
}

/* ===== LIGHT MODE =====
   Brand-aligned "warm cream" palette shared with ummah.email + UmmahPlaces.
   Cream background (#FAF7F2), ink text (#2C2417), brass (#C8912E) preserved,
   teal darkened (#0D9488) for AA contrast against cream.
   Apr 19 — Alisha requested a light/day mode because grey text on dark was
   hard to read even at full brightness. */
[data-theme="light"] {
    --buzz-void: #FAF7F2;           /* page background */
    --buzz-deep: #F5F0E8;           /* slightly darker variant */
    --buzz-surface: #FFFFFF;        /* card body */
    --buzz-border: #E8E1D4;         /* warm-200 border */
    --buzz-border-alpha: rgba(232, 225, 212, 0.9);
    --buzz-gold: #C8912E;           /* brass dark enough for AA on cream */
    --buzz-gold-light: #DFA032;
    --buzz-gold-dim: #A6751F;
    --buzz-gold-glow: rgba(200, 145, 46, 0.15);
    --buzz-teal: #0A6B62;           /* Aug 11 estate design pass: darkened again from #0D9488 - that
                                        value's own "AA contrast" comment was aspirational, not
                                        verified; real rendered-pixel sampling measured 3.50-3.74:1
                                        (needs 4.5:1). This value verified 5.97:1 against the real
                                        cream page bg. */
    --buzz-teal-dark: #0B7A6F;
    --buzz-text: #2C2417;           /* ink */
    --buzz-text-muted: #5C5040;     /* ink-light */
    --buzz-text-dim: #6E634F;       /* ink-muted. Aug 11 estate design pass: darkened from #8A7E6D
                                        — measured 3.72:1 on the real rendered card bg (needs 4.5:1);
                                        stays lighter/lower-contrast than --buzz-text-muted (7.34:1). */
    --buzz-heading: #1F1A10;
    --buzz-card-bg: #FFFFFF;        /* solid card, no gradient in light mode */
    --buzz-card-border: rgba(232, 225, 212, 0.95);
    --buzz-header-bg: rgba(250, 247, 242, 0.92);
    --buzz-header-border: rgba(232, 225, 212, 0.8);
    --buzz-input-bg: rgba(255, 255, 255, 0.9);
    --buzz-hover-wash: rgba(200, 145, 46, 0.07);
    --buzz-gold-tint-strong: rgba(200, 145, 46, 0.14);
    --buzz-danger: #C0392B;
    color-scheme: light;
}
/* Hide dark-mode-only ambient effects — they clash with cream. */
[data-theme="light"] .starfield,
[data-theme="light"] .grain,
[data-theme="light"] .cursor-glow { display: none !important; }

/* Smooth the flip so it doesn't feel harsh — but keep it fast. */
html { transition: background-color 0.2s var(--buzz-ease); }
body { transition: background-color 0.2s var(--buzz-ease), color 0.2s var(--buzz-ease); }

/* ===== RESET ===== */
*, *::before, *::after { margin: 0; padding: 0; box-sizing: border-box; }
/* iter-2 (Jun 18): overflow-x:hidden must be on HTML too, not just body — the
   edge-bleed filter strips (.topic-tabs/.format-filter use negative margins) let
   ~16px escape at the viewport/html level (body's clip doesn't catch it when html
   is overflow-x:visible). Clamp both so there is zero mobile horizontal scroll. */
html { scroll-behavior: smooth; overflow-x: hidden; max-width: 100%; }
[x-cloak] { display: none !important; }

body {
    font-family: 'Outfit', system-ui, -apple-system, sans-serif;
    background: var(--buzz-void);
    color: var(--buzz-text);
    overflow-x: hidden;
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
    line-height: 1.6;
    min-height: 100vh;
    /* Mobile nav clearance. A-grade polish (Jun 18): add the iOS safe-area inset
       on top of the ~64px nav height so the fixed bottom nav never overlaps the
       last content (the CD saw it cover lower content on the post page). */
    padding-bottom: calc(64px + env(safe-area-inset-bottom, 0px));
}

a { color: inherit; text-decoration: none; }
img { max-width: 100%; display: block; }
button, input, textarea, select {
    font-family: inherit;
    font-size: inherit;
    color: inherit;
    border: none;
    outline: none;
    background: none;
}
button { cursor: pointer; }

/* ===== SCROLLBAR ===== */
::-webkit-scrollbar { width: 5px; }
::-webkit-scrollbar-track { background: var(--buzz-void); }
::-webkit-scrollbar-thumb {
    background: linear-gradient(180deg, var(--buzz-border), var(--buzz-gold));
    border-radius: 3px;
}
::-webkit-scrollbar-thumb:hover {
    background: linear-gradient(180deg, #2A3A5E, var(--buzz-gold-light));
}

/* ===== STARFIELD ===== */
.starfield {
    position: fixed;
    top: 0; left: 0;
    width: 100%; height: 100%;
    pointer-events: none;
    z-index: 0;
}
.star-dot {
    position: absolute;
    border-radius: 50%;
    background: #fff;
    animation: starPulse var(--dur) ease-in-out infinite;
    animation-delay: var(--del);
}
@keyframes starPulse {
    0%, 100% { opacity: var(--min-o); transform: scale(1); }
    50% { opacity: var(--max-o); transform: scale(1.4); }
}

/* ===== GRAIN OVERLAY ===== */
.grain {
    position: fixed;
    top: 0; left: 0;
    width: 100%; height: 100%;
    pointer-events: none;
    z-index: 9999;
    opacity: 0.025;
    background-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 256 256' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='noise'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='4' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23noise)'/%3E%3C/svg%3E");
}

/* ===== CURSOR GLOW ===== */
.cursor-glow {
    position: fixed;
    width: 400px;
    height: 400px;
    border-radius: 50%;
    background: radial-gradient(circle, rgba(223, 160, 50, 0.04) 0%, transparent 70%);
    pointer-events: none;
    z-index: 1;
    transform: translate(-50%, -50%);
    transition: opacity 0.3s ease;
    will-change: left, top;
}

/* ===== SCROLL REVEAL ===== */
.reveal {
    opacity: 0;
    transform: translateY(30px);
    transition: opacity 0.8s var(--buzz-ease), transform 0.8s var(--buzz-ease);
}
.reveal.visible {
    opacity: 1;
    transform: translateY(0);
}
.reveal-d1 { transition-delay: 0.1s; }
.reveal-d2 { transition-delay: 0.2s; }
.reveal-d3 { transition-delay: 0.3s; }

/* ===== HEADER / MASTHEAD ===== */
.buzz-header {
    position: sticky;
    top: 0;
    z-index: 100;
    background: var(--buzz-header-bg);
    backdrop-filter: blur(20px);
    -webkit-backdrop-filter: blur(20px);
    border-bottom: 1px solid var(--buzz-header-border);
    padding: 0 1rem;
}
.buzz-header-inner {
    max-width: 960px;
    margin: 0 auto;
    display: flex;
    align-items: center;
    justify-content: space-between;
    height: 56px;
    gap: 1rem;
}
.buzz-logo {
    display: flex;
    align-items: center;
    gap: 9px;
    flex-shrink: 0;
    text-decoration: none;
    /* Estate design pass (Aug 11 2026): wordmark 44px floor, same pattern as
       the kit's .masthead-brand/.umg-wordmark rule - floors the tap target
       without disturbing the two-line lockup's own baseline alignment.
       Harness measured 142x33px. */
    min-height: 44px;
}
/* Bee mark (v163, Jun 18 2026). currentColor drives both strokes + fills so the
   one glyph theme-matches: gold on dark, readable brass on cream. A MARK, not a
   mascot - geometric hexagonal-bee, no face. */
.buzz-bee-mark {
    width: 22px;
    height: 22px;
    flex-shrink: 0;
    color: var(--buzz-gold);
    transition: transform 0.25s ease;
}
.buzz-logo:hover .buzz-bee-mark {
    transform: translateY(-1px);
}
[data-theme="light"] .buzz-bee-mark {
    color: #C8912E; /* readable brass on cream */
}
.buzz-logo-lockup {
    display: flex;
    flex-direction: column;
    justify-content: center;
    line-height: 1;
}
.buzz-logo-text {
    font-size: 1.25rem;
    font-weight: 700;
    color: var(--buzz-heading);
    letter-spacing: -0.02em;
    line-height: 1.05;
}
.buzz-logo-text span {
    color: var(--buzz-gold);
}
/* Estate design pass (Aug 11 2026): --buzz-gold (light) measured 2.78:1 on the
   wordmark's own header bg (real, verified by rendered-pixel sample - the
   token's "AA on cream" comment covers backgrounds, not this text use). Same
   proven amber as the other gold-on-light text fixes in this file. */
[data-theme="light"] .buzz-logo-text span { color: #B45309; }
/* Tagline "What's good rises" - quiet masthead-grade companion line under the
   wordmark. The bee's companion line; not a strapline that duplicates the hero. */
.buzz-logo-tagline {
    font-size: 0.625rem;
    font-weight: 500;
    letter-spacing: 0.02em;
    color: var(--buzz-text-muted);
    margin-top: 2px;
    white-space: nowrap;
}
[data-theme="light"] .buzz-logo-tagline {
    color: #73654A; /* WCAG AA: 5.33:1 on cream */
}
/* On the narrowest phones the tagline would crowd the search/auth row - hide it
   below the wordmark there; the bee + wordmark stay. */
@media (max-width: 380px) {
    .buzz-logo-tagline { display: none; }
}
.buzz-tagline {
    /* A-grade polish (Jun 18): the post-page nav tagline was ~11px light gray and
       read as throwaway chrome. Bumped to 0.875rem (~14px) + the brighter --buzz-text
       so "The Front Page of the Muslim Internet" reads as a confident strapline. */
    font-size: 0.875rem;
    font-weight: 500;
    color: var(--buzz-text);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    min-width: 0;
    flex-shrink: 1;
    max-width: 280px;
}
.buzz-district-badge {
    font-size: 0.625rem;
    color: var(--buzz-teal);
    background: rgba(20, 184, 166, 0.08);
    border: 1px solid rgba(20, 184, 166, 0.2);
    padding: 2px 8px;
    border-radius: var(--buzz-radius-pill);
    text-decoration: none;
    white-space: nowrap;
    flex-shrink: 0;
    transition: background 0.2s ease;
}
.buzz-district-badge:hover {
    background: rgba(20, 184, 166, 0.15);
}
.buzz-header-auth {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    flex-shrink: 0;
}
.buzz-avatar-name {
    font-size: 0.8125rem;
    font-weight: 500;
    color: var(--buzz-gold);
}
.buzz-btn-signin {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 6px;
    padding: 7px 16px;
    /* Estate design pass (Aug 11 2026): harness measured 82x29px. */
    min-height: 44px;
    /* Aug 21 2026 (card RGwajf3b item 3): gold ink on a 12%-gold tint measured
       1.22:1 on the live light page (the card's cream screenshot read 2.4:1).
       Same treatment as the ratified gold banner CTA (8.3:1): solid gold fill,
       dark ink. */
    background: var(--buzz-gold);
    border: 1px solid var(--buzz-gold);
    border-radius: var(--buzz-radius-pill);
    color: #1A1306;
    font-size: 0.8125rem;
    font-weight: 600;
    transition: all 0.3s ease;
    white-space: nowrap;
}
.buzz-btn-signin:hover {
    background: #C8912E; /* deeper gold; ink stays dark */
    border-color: #C8912E;
    transform: translateY(-1px);
}
.buzz-btn-signin:active {
    transform: translateY(0);
}
.buzz-btn-logout {
    font-size: 0.75rem;
    color: var(--buzz-text-muted);
    transition: color 0.3s ease;
    /* May 14 (Mehek #7): hide logout text on medium screens — icon-only at ≤900px
       to prevent 4-item auth row from crowding the header. */
}
.buzz-btn-logout:hover { color: var(--buzz-danger); }
@media (max-width: 900px) {
    /* On medium-small desktop, hide logout text label so auth row doesn't overflow. */
    .buzz-btn-logout {
        font-size: 0;
        width: 32px;
        height: 32px;
        display: inline-flex;
        align-items: center;
        justify-content: center;
        background: rgba(239, 68, 68, 0.06);
        border: 1px solid rgba(239, 68, 68, 0.15);
        border-radius: 50%;
        padding: 0;
    }
    /* Show an X icon instead of text on compressed desktop */
    .buzz-btn-logout::before {
        content: '×';
        font-size: 16px;
        line-height: 1;
        color: var(--buzz-text-muted);
    }
    .buzz-btn-logout:hover::before { color: var(--buzz-danger); }
    .buzz-btn-logout:hover {
        background: rgba(239, 68, 68, 0.12);
        border-color: rgba(239, 68, 68, 0.3);
    }
    /* Also hide the Saved text label at this breakpoint */
    .buzz-saved-link span { display: none; }
    .buzz-saved-link { padding: 8px; }
}

/* May 18 (BUG-133): sign-out confirm popover.
   The red circle on ≤900px viewports was a one-tap logout with no guard;
   mobile users were tapping it accidentally and losing their session. This
   popover anchors below the logout button and asks for a second tap before
   firing /api/auth/logout.php. Quiet voice — no auntie "are you sure". */
.buzz-logout-wrap {
    position: relative;
    display: inline-flex;
}
.buzz-logout-confirm {
    position: absolute;
    top: calc(100% + 8px);
    right: 0;
    z-index: 50;
    background: var(--buzz-bg-elevated, #1a1a1a);
    border: 1px solid var(--buzz-border, rgba(255, 255, 255, 0.08));
    border-radius: 10px;
    padding: 12px 14px;
    box-shadow: 0 8px 24px rgba(0, 0, 0, 0.32);
    min-width: 168px;
    display: flex;
    flex-direction: column;
    gap: 10px;
}
.buzz-logout-confirm-title {
    font-size: 0.85rem;
    color: var(--buzz-text, #e6e6e6);
    font-weight: 500;
}
.buzz-logout-confirm-actions {
    display: flex;
    gap: 6px;
    justify-content: flex-end;
}
.buzz-logout-confirm-btn {
    font-size: 0.78rem;
    padding: 6px 12px;
    border-radius: 6px;
    border: 1px solid transparent;
    cursor: pointer;
    transition: background 0.15s ease, border-color 0.15s ease;
    font-family: inherit;
}
.buzz-logout-confirm-btn.cancel {
    background: transparent;
    color: var(--buzz-text-muted, #999);
    border-color: var(--buzz-border, rgba(255, 255, 255, 0.12));
}
.buzz-logout-confirm-btn.cancel:hover {
    background: rgba(255, 255, 255, 0.04);
    color: var(--buzz-text, #e6e6e6);
}
.buzz-logout-confirm-btn.confirm {
    background: rgba(239, 68, 68, 0.12);
    color: #ef4444;
    border-color: rgba(239, 68, 68, 0.35);
}
.buzz-logout-confirm-btn.confirm:hover {
    background: rgba(239, 68, 68, 0.2);
    border-color: rgba(239, 68, 68, 0.55);
}
[data-theme="light"] .buzz-logout-confirm {
    background: #ffffff;
    border-color: rgba(0, 0, 0, 0.08);
    box-shadow: 0 8px 24px rgba(0, 0, 0, 0.1);
}
[data-theme="light"] .buzz-logout-confirm-title { color: #1a1a1a; }
[data-theme="light"] .buzz-logout-confirm-btn.cancel {
    color: #666;
    border-color: rgba(0, 0, 0, 0.12);
}
[data-theme="light"] .buzz-logout-confirm-btn.cancel:hover {
    background: rgba(0, 0, 0, 0.04);
    color: #1a1a1a;
}

/* Desktop Submit button — subtle teal secondary action, distinct from the brass
   auth block. Hidden on mobile (mobile-nav already owns Submit). */
.buzz-btn-submit {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 7px 14px;
    background: rgba(20, 184, 166, 0.12);
    border: 1px solid rgba(20, 184, 166, 0.25);
    border-radius: var(--buzz-radius-pill);
    color: var(--buzz-teal);
    font-size: 0.8125rem;
    font-weight: 600;
    transition: all 0.25s var(--buzz-ease);
    cursor: pointer;
    white-space: nowrap;
    -webkit-tap-highlight-color: transparent;
}
.buzz-btn-submit:hover {
    background: rgba(20, 184, 166, 0.2);
    border-color: rgba(20, 184, 166, 0.4);
    transform: translateY(-1px);
}
.buzz-btn-submit:active { transform: translateY(0); }
.buzz-btn-submit.active {
    background: rgba(20, 184, 166, 0.24);
    border-color: rgba(20, 184, 166, 0.5);
}
@media (max-width: 768px) {
    .buzz-btn-submit { display: none; }
}

/* Desktop header search */
.header-search-wrap {
    flex: 1;
    max-width: 320px;
    display: none;
}
@media (min-width: 768px) {
    .header-search-wrap { display: block; }
}
.header-search-wrap .buzz-search {
    height: 36px;
    font-size: 0.8125rem;
}

/* ===== HERO SECTION =====
   May 13 2026 (Abdullah UB3): tightened mobile + desktop top padding —
   excessive whitespace between nav→728 ad→hero on desktop.
   May 14 2026 (Mehek): logged-out hero gets extra top clearance via class toggle
   on .hero-section; logged-in state removes the .hero-loggedout extra padding.
   Base padding kept minimal so the promo bar + header stack doesn't eat the fold. */
.hero-section {
    text-align: center;
    /* BUG-065 (May 18): trimmed top padding 1rem→0.25rem to reduce navbar→hero gap */
    padding: 0.25rem 1rem 1.5rem;
    position: relative;
    z-index: 2;
}
/* Estate design pass round 3 (Aug 11 2026, throat item 1 continued): the round-2
   fix got the featured card's CONTAINER into the 390x844 viewport (top y=837)
   but its real headline text still rendered at y~1098 - the card itself is
   restructured below (see .buzz-hero mobile block), and that restructure needs
   real headroom above it too. This block + the matching mobile-only trims on
   .hero-stats/.gold-line/.topic-tabs/.format-filter/.ub-explainer-strip/
   .ub-reader-cta/.feed-sort below reclaim ~75px total from pure static margin/
   padding - none of it touches content, only whitespace, and none of it is
   paired to a CLS-sensitive skeleton except hero-stats + explainer-strip,
   whose skeletons are trimmed by the identical amount in the same edit so the
   skeleton-to-real swap stays a no-op (same technique the CLS fix already
   relies on). Desktop (>=769px) padding is untouched. */
@media (max-width: 768px) {
    .hero-section { padding-bottom: 0.35rem; }
}
.hero-title {
    font-size: clamp(1.5rem, 5vw, 2.5rem);
    font-weight: 800;
    color: var(--buzz-heading);
    letter-spacing: -0.03em;
    line-height: 1.1;
    margin-bottom: 0.625rem;
}
/* Throat item 1 (Aug 11 round 3b): the mobile-nav is FIXED (position:fixed,
   bottom:0, measured live at y=787 on a 390x844 viewport, see .mobile-nav) -
   it overlays the last ~57px of every screen, so the REAL usable fold on a
   phone is ~787px, not 844. Round-3a's first pass got the new headline to
   y=808 - inside the 844 CSS viewport but still hidden UNDER the fixed nav on
   a real screen (verified with a live screenshot, not just getBoundingClientRect
   math - screenshot showed nothing below "Sort" at all). This second pass
   reclaims the extra ~55-60px needed against the REAL 787px fold. Spacing
   only, same as every other rule in this pass - no font-size, no copy, no
   change to .hero-title's or .hero-sub's own text. */
@media (max-width: 768px) {
    .hero-title { margin-bottom: 0.15rem; }
}
.hero-title .gold {
    /* Jun 18: differentiate the headline gold from the solid gold CTA pill so the
       two don't compete. The headline leans into the LIGHTER end of the gold ramp
       (gold-light -> a soft cream-gold) and drops the glow, reading as elegant
       emphasis TEXT; the CTA stays the loud, solid, glowing gold PILL — the single
       dominant gold call-to-action. Same brand hue, clear visual hierarchy. */
    background: linear-gradient(105deg, var(--buzz-gold-light), #FBE3AE);
    -webkit-background-clip: text;
    background-clip: text;
    -webkit-text-fill-color: transparent;
    font-weight: 700;
    filter: drop-shadow(0 0 10px rgba(240, 201, 110, 0.12));
}
[data-theme="light"] .hero-title .gold {
    /* On cream, the lighter gold ramp would wash out — keep a readable brass that
       still sits a notch softer than the CTA. */
    background: linear-gradient(105deg, var(--buzz-gold), #B8841F);
    -webkit-background-clip: text;
    background-clip: text;
    -webkit-text-fill-color: transparent;
    filter: none;
}
.hero-sub {
    /* A-grade polish (Jun 18): the CD saw this render as thin light-gray. Bumped
       from --buzz-text-muted (#8892A4) to the brighter --buzz-text (#C8D0E0, ~9:1
       on the void) + weight 500 so it reads as a confident statement under the
       headline and clears WCAG AA comfortably. */
    font-size: clamp(0.9375rem, 2.5vw, 1.125rem);
    color: var(--buzz-text);
    font-weight: 500;
    max-width: 520px;
    margin: 0 auto 1.5rem;
    line-height: 1.5;
}
/* Throat item 1 (Aug 11 round 3b): see .hero-title's round-3b comment above -
   same real-fold-vs-844 finding, same spacing-only trim. */
@media (max-width: 768px) {
    .hero-sub { margin-bottom: 0.4rem; }
}
.hero-cta {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    padding: 12px 28px;
    min-height: 44px;
    /* CLS fix (Aug 11 estate design pass, round 2 — QA F5): hero-section mixes this
       inline-level element with block-level h1/p siblings, so the browser wraps it
       in an anonymous block whose height comes from the INLINE line box, not just
       this element's own border-box. A <button> (form control, baseline tied to its
       own font metrics) contributes a different line-box height than a plain <div>
       skeleton even at an identical 44px border-box height — measured live as a
       reproducible ~7px .hero-section collapse the instant .hero-cta-skeleton
       swapped to this real <button>. vertical-align:top removes the baseline
       dependency entirely (also set on .hero-cta-skeleton + .hero-promo-link, the
       signed-in <a> variant, so all three tag types agree). */
    vertical-align: top;
    background: linear-gradient(135deg, var(--buzz-gold), var(--buzz-gold-dim));
    color: #060B18;
    font-weight: 700;
    font-size: 0.9375rem;
    border-radius: var(--buzz-radius-pill);
    transition: all 0.3s var(--buzz-ease);
    box-shadow: 0 4px 20px rgba(223, 160, 50, 0.25);
}
.hero-cta:hover {
    transform: translateY(-2px);
    box-shadow: 0 8px 30px rgba(223, 160, 50, 0.35);
}
.hero-cta:active {
    transform: translateY(0);
    box-shadow: 0 2px 12px rgba(223, 160, 50, 0.2);
}
.hero-cta svg {
    width: 16px;
    height: 16px;
}
/* BUG-131 (May 18): Skeleton placeholder reserves vertical space while
   checkAuth() resolves, so the hero doesn't jank when the real CTA paints.
   Matches the .hero-cta / .hero-promo-link min-height (44px) + pill radius. */
.hero-cta-skeleton {
    /* CLS fix (Aug 11 estate design pass, round 2 — QA F5): display:inline-block ->
       inline-flex (matches .hero-cta's own display) + vertical-align:top (see the
       full explanation on .hero-cta above — this element sits among block-level
       hero-title/hero-sub siblings, so its baseline behavior affects the
       surrounding anonymous block's height, and a <div> vs the real <button>
       disagreed on that baseline by ~7px even at an identical 44px own-height). */
    display: inline-flex;
    vertical-align: top;
    width: 200px;
    height: 44px;
    border-radius: var(--buzz-radius-pill);
    background: rgba(255, 255, 255, 0.03);
    border: 1px solid rgba(255, 255, 255, 0.05);
}
[data-theme="light"] .hero-cta-skeleton {
    background: rgba(20, 17, 10, 0.03);
    border-color: rgba(20, 17, 10, 0.06);
}

/* SUGG-163 hero lift (Jun 15): compact stat strip in the hero zone.
   Real counts only — no fabricated numbers (amanah).
   Inline flex row, centered, appears below the CTA before the gold rule. */
.hero-stats {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 0;
    margin: 1.25rem auto 0;
    max-width: 360px;
}
.hero-stat {
    display: flex;
    flex-direction: column;
    align-items: center;
    padding: 0 1.25rem;
}
.hero-stat-num {
    font-size: 1.375rem;
    font-weight: 800;
    color: var(--buzz-gold);
    line-height: 1;
    font-variant-numeric: tabular-nums;
    letter-spacing: -0.02em;
}
.hero-stat-label {
    font-size: 0.6875rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: var(--buzz-text-muted);
    margin-top: 0.25rem;
    white-space: nowrap;
}
.hero-stat-sep {
    width: 1px;
    height: 2rem;
    background: var(--buzz-border);
    flex-shrink: 0;
}
[data-theme="light"] .hero-stat-num {
    color: var(--buzz-gold-dim);
}
[data-theme="light"] .hero-stat-sep {
    background: rgba(20, 17, 10, 0.12);
}
/* CLS fix (Aug 11 estate design pass, round 2): reserves the exact .hero-stats
   footprint (measured live, Playwright, 390px: 44px content height + the
   1.25rem top margin the real box carries) so the async /api/stats.php fetch
   can never shift .gold-line/.topic-tabs/.format-filter/.ub-explainer-strip/
   .ub-reader-cta beneath it, regardless of how it races against buzzApp's own
   checkAuth()+loadFeed() chain. Same reserve-the-space technique + same
   translucent-box styling as .hero-cta-skeleton just above in this file. */
.hero-stats-skeleton {
    margin: 1.25rem auto 0;
    max-width: 360px;
    height: 44px;
    border-radius: var(--buzz-radius-sm, 10px);
    background: rgba(255, 255, 255, 0.03);
    border: 1px solid rgba(255, 255, 255, 0.05);
}
/* Throat item 1 (Aug 11 round 3): both the real .hero-stats and its skeleton
   get the SAME reduced top margin, so the skeleton-to-real swap stays a
   no-op (zero new CLS) - only the amount of whitespace above BOTH states
   changes. See .hero-section's round-3 comment for the full budget. */
@media (max-width: 768px) {
    .hero-stats,
    .hero-stats-skeleton { margin-top: 0.15rem; }
}
[data-theme="light"] .hero-stats-skeleton {
    background: rgba(20, 17, 10, 0.03);
    border-color: rgba(20, 17, 10, 0.06);
}

.hero-promo {
    text-align: center;
}
.hero-promo-link {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    padding: 12px 28px;
    min-height: 44px;
    /* CLS fix (Aug 11 estate design pass, round 2): same baseline fix as .hero-cta
       above — this <a> is the signed-in-visitor swap-in for the same skeleton slot. */
    vertical-align: top;
    background: linear-gradient(135deg, var(--buzz-teal), #0f9484);
    color: #fff;
    font-weight: 700;
    font-size: 0.9375rem;
    border-radius: var(--buzz-radius-pill);
    text-decoration: none;
    transition: all 0.3s var(--buzz-ease);
    box-shadow: 0 4px 20px rgba(20, 184, 166, 0.25);
}
.hero-promo-link:hover {
    transform: translateY(-2px);
    box-shadow: 0 8px 30px rgba(20, 184, 166, 0.35);
}
.hero-tag {
    display: inline-block;
    padding: 6px 14px;
    background: rgba(223, 160, 50, 0.06);
    border: 1px solid rgba(223, 160, 50, 0.15);
    border-radius: var(--buzz-radius-pill);
    color: var(--buzz-gold-dim);
    font-size: 0.75rem;
    font-weight: 400;
    letter-spacing: 0.01em;
}

/* ===== EXPLAINER STRIP (Issue-3, Jun 9) =====
   First-time visitor context bar — shown only to anonymous users.
   Single-line strip between the filter pills and the feed. Plain-voiced,
   no jargon. Collapses gracefully on mobile (wraps). */
.ub-explainer-strip {
    max-width: 960px;
    margin: 0.5rem auto 0.75rem;
    padding: 0.5rem 1rem;
    display: flex;
    align-items: flex-start;
    gap: 0.5rem;
    font-size: 0.8125rem;
    color: var(--buzz-text-muted);
    line-height: 1.5;
}
/* CLS fix (Aug 11 estate design pass, round 2 — QA F5): with the Outfit font link
   now display=optional (see index.html's <link> comment), a pageview can commit
   to EITHER Outfit (narrower, wraps this copy to 2 lines, ~75px) or the fallback
   font (wider, 3 lines, ~94px measured live at 390px) for its entire render — no
   later swap between them. .ub-explainer-strip-skeleton below only reserved the
   Outfit-sized 76px, so a fallback-committed pageview still showed a real,
   reproducible ~18px shift when the skeleton (76px) swapped to the real strip
   (94px) — this is what was still pushing CLS to ~0.09 on a fraction of trials.
   Flooring the REAL element at the fallback-sized worst case (not just its
   skeleton) makes the skeleton-to-real swap a no-op regardless of which font won. */
@media (max-width: 768px) {
    .ub-explainer-strip { min-height: 96px; }
    /* Throat item 1 (Aug 11 round 3): margin only (never min-height - that's
       the CLS-critical fallback-font floor from the comment above, untouched).
       Paired 1:1 with the skeleton's own margin below so the swap stays a
       CLS no-op. */
    .ub-explainer-strip { margin: 0.2rem auto 0.25rem; }
}
.ub-explainer-link {
    color: var(--buzz-gold);
    font-weight: 600;
}
/* Estate design pass (Aug 11 2026): --buzz-gold (light, #C8912E) measured
   2.60:1 against the real cream page bg (needs 4.5:1) - the shared token's
   own "AA on cream" comment covers its use as a BACKGROUND (paired with dark
   text), not as small TEXT on the cream page itself, so it's scoped here
   rather than darkening the token estate-wide. #B45309 is the same amber
   already proven in production on .rising-badge's light theme (measured
   4.70:1). */
[data-theme="light"] .ub-explainer-link { color: #B45309; }
.ub-explainer-link:hover {
    text-decoration: underline;
}
/* Estate design pass (Aug 11 2026, CLS fix): same reserve-the-space technique
   as .hero-cta-skeleton just above in this file — the strip is wrapped in a
   template x-if="!initialLoad && !auth.authenticated" (index.html), so it did
   not exist in the DOM at all until checkAuth() resolved, then inserted with
   ZERO reserved space and pushed everything below it (reader CTA, EPOM zone,
   feed) down by its own height. Measured live at both breakpoints (Playwright,
   ummahbuzz.com): 74.5px at 390px width, 55px at >=768px (the strip's text
   wraps to more lines on mobile) - rounded up 1-2px for a small safety margin,
   never under the real value or the shift just moves to when the skeleton
   itself swaps in. Auth'd users never see the strip at all (x-if stays false
   for them, always), so they never see this skeleton either.
   Matches min-height/border-radius/margin of the real strip so the skeleton
   doesn't itself look like a second bug while resolving. */
.ub-explainer-strip-skeleton {
    max-width: 960px;
    margin: 0.5rem auto 0.75rem;
    /* CLS fix (Aug 11 estate design pass, round 2): 76px -> 96px, matching the
       real .ub-explainer-strip's new min-height above — see that rule's comment
       for the fallback-vs-Outfit font-commit measurement. */
    min-height: 96px;
    border-radius: var(--buzz-radius-sm, 10px);
    background: rgba(255, 255, 255, 0.03);
    border: 1px solid rgba(255, 255, 255, 0.05);
}
[data-theme="light"] .ub-explainer-strip-skeleton {
    background: rgba(20, 17, 10, 0.03);
    border-color: rgba(20, 17, 10, 0.06);
}
@media (min-width: 768px) {
    .ub-explainer-strip-skeleton { min-height: 57px; }
}
@media (max-width: 768px) {
    /* Same margin values as the real .ub-explainer-strip above - identical
       change, kept as its own rule for the same reason the skeleton itself
       is a separate ruleset (paired 1:1, edited together). */
    .ub-explainer-strip-skeleton { margin: 0.2rem auto 0.25rem; }
}

/* Reader/member CTA strip (A-grade polish iter-2, Jun 18): the prime above-feed
   slot now leads with a READER-facing member CTA (join the conversation / Ummah
   One) instead of the advertiser-facing MAN house banner. The EPOM advertiser
   zone stays below it as paid inventory (attribution chip always-visible); the
   advertiser pitch also lives in the footer "Advertise with us" link. */
.ub-reader-cta {
    max-width: 960px;
    margin: 0.75rem auto 0.5rem;
    padding: 0.7rem 1rem;
    display: flex;
    align-items: center;
    gap: 0.75rem;
    flex-wrap: wrap;
    border: 1px solid var(--buzz-gold-tint, rgba(223,160,50,0.25));
    border-radius: var(--buzz-radius-sm, 10px);
    background: linear-gradient(135deg, rgba(223,160,50,0.10), rgba(223,160,50,0.03));
}
/* Throat item 1 (Aug 11 round 3): this strip has no async skeleton (renders
   synchronously, unlike explainer-strip/hero-stats above) so its margin is
   free to trim with zero CLS consideration. */
@media (max-width: 768px) {
    .ub-reader-cta { margin: 0.25rem auto 0.2rem; }
}
.ub-reader-cta-icon { flex-shrink: 0; color: var(--buzz-gold); display: flex; }
.ub-reader-cta-text {
    font-size: 0.875rem;
    color: var(--buzz-text);
    line-height: 1.4;
    flex: 1 1 200px;
    min-width: 0;
}
/* Estate design pass round 2 (Aug 11 2026, CD #6 "throat" fix): short copy is
   hidden by default (desktop keeps the full sentence); shown only at <=560px
   (see the media query below), where it's short enough to sit on ONE row with
   the icon + button instead of the full sentence wrapping to 2-3 lines and
   pushing the button to its own row — collapses this banner from ~139px to
   ~64px at 390px width, which is what actually brings the first real story
   headline back within one screen (was y~915, >one screen at 844px viewport). */
.ub-reader-cta-text-short { display: none; }
.ub-reader-cta-text strong { color: var(--buzz-gold); font-weight: 700; }
/* Estate design pass (Aug 11 2026): same real-contrast gap as .ub-explainer-link
   above (measured 2.38:1 on the reader-CTA's own faint gradient tint - real,
   not the harness's documented gradient false-positive class - verified by
   rendered-pixel sample, not DOM-walk). Same proven amber. */
[data-theme="light"] .ub-reader-cta-text strong { color: #B45309; }
.ub-reader-cta-btn {
    flex-shrink: 0;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 0.35rem;
    padding: 0.45rem 0.9rem;
    /* Estate design pass (Aug 11 2026): 40px -> 44px (harness measured 155x40px). */
    min-height: 44px;
    box-sizing: border-box;
    border-radius: 999px;
    background: linear-gradient(135deg, var(--buzz-gold), var(--buzz-gold-light));
    color: #060B18;
    font-weight: 700;
    font-size: 0.8125rem;
    text-decoration: none;
    white-space: nowrap;
    transition: filter 0.18s ease, transform 0.18s ease;
}
.ub-reader-cta-btn:hover { filter: brightness(1.06); transform: translateY(-1px); }
[data-theme="light"] .ub-reader-cta {
    border-color: rgba(196,162,101,0.45);
    background: linear-gradient(135deg, rgba(223,160,50,0.12), rgba(223,160,50,0.04));
}
[data-theme="light"] .ub-reader-cta-btn { color: #060B18; }
@media (max-width: 560px) {
    .ub-reader-cta {
        flex-direction: row;
        /* Estate design pass round 2 (Aug 11 2026, CD #6): tighter padding at this
           width — the "throat" fix needs every reclaimable px, and the compact
           single-row layout below no longer needs the extra breathing room. */
        padding: 0.5rem 0.85rem;
    }
    .ub-reader-cta-btn { width: auto; }
    /* Estate design pass round 2 (Aug 11 2026, CD #6): swap to the short one-line
       copy so icon + text + button fit on a SINGLE row instead of wrapping to
       3 stacked rows (icon+text, text continued, button) — see the CLAUDE.md
       "throat" finding: the first real story headline sat below one screen at
       390px, and this banner's height was the single largest reclaimable chunk. */
    .ub-reader-cta-text-full { display: none; }
    .ub-reader-cta-text-short { display: inline; }
    .ub-reader-cta-text { flex: 0 1 auto; white-space: nowrap; }
}
/* Estate design pass round 2 (Aug 11 2026, CD #6 "throat" fix): even the short
   copy above doesn't fit alongside the icon + button on ONE row once the
   viewport itself is this narrow (measured live at 390px: still wraps to icon+
   text on row 1, button on row 2, ~94px total — the first real story headline
   was still below one screen at y~870 of 844). Below 480px, drop the
   supporting text and keep icon + button only, all on one compact row
   (~60px). Nothing is removed functionally — the link/button is unchanged and
   still visible; the same message ("Ummah One" / member context) is already
   carried by the banner directly above this one and repeated in the footer,
   so this is the LEAST-lossy place to cut a 5-word supporting phrase. */
@media (max-width: 480px) {
    .ub-reader-cta {
        padding: 0.4rem 0.75rem;
        gap: 0.5rem;
    }
    .ub-reader-cta-text { display: none; }
}

/* ===== LAYOUT ===== */
.buzz-layout {
    max-width: 960px;
    margin: 0 auto;
    padding: 0 1rem;
    display: flex;
    gap: 1.5rem;
    position: relative;
    z-index: 2;
}
.buzz-feed {
    flex: 1;
    min-width: 0;
    max-width: 680px;
}
.buzz-sidebar {
    width: 280px;
    flex-shrink: 0;
    display: none;
}
@media (min-width: 960px) {
    .buzz-sidebar { display: block; }
}

/* ===== HERO CARD (top story) — Apr 20 Saad feedback ===== */
.buzz-hero {
    display: grid;
    grid-template-columns: 1.2fr 1fr;
    gap: 0;
    background: var(--buzz-card-bg);
    border: 1px solid var(--buzz-card-border);
    border-radius: var(--buzz-radius);
    margin-bottom: 1.25rem;
    overflow: hidden;
    cursor: pointer;
    transition: all 0.35s var(--buzz-ease);
    position: relative;
    min-height: 280px;
}
.buzz-hero::before {
    content: '';
    position: absolute;
    top: 0; left: 0; right: 0;
    height: 2px;
    background: linear-gradient(90deg, transparent, rgba(223, 160, 50, 0.5), transparent);
    z-index: 2;
}
.buzz-hero:hover {
    border-color: rgba(223, 160, 50, 0.35);
    box-shadow: 0 16px 48px rgba(0, 0, 0, 0.4), 0 0 40px rgba(223, 160, 50, 0.08);
    transform: translateY(-2px);
}
.buzz-hero-image {
    position: relative;
    min-height: 280px;
    background: rgba(0, 0, 0, 0.3);
    overflow: hidden;
}
.buzz-hero-image img {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    object-fit: cover;
    transition: transform 0.6s var(--buzz-ease);
}
.buzz-hero:hover .buzz-hero-image img { transform: scale(1.02); }
.buzz-hero-content {
    padding: 1.5rem 1.75rem;
    display: flex;
    flex-direction: column;
    justify-content: center;
    gap: 0.75rem;
}
.buzz-hero-badge {
    display: inline-flex;
    align-items: center;
    gap: 0.35rem;
    font-size: 0.7rem;
    font-weight: 700;
    letter-spacing: 0.5px;
    text-transform: uppercase;
    color: #E8C252;
    padding: 0.25rem 0.6rem;
    background: rgba(223, 160, 50, 0.1);
    border: 1px solid rgba(223, 160, 50, 0.25);
    border-radius: 999px;
    align-self: flex-start;
}
.buzz-hero-title {
    font-size: 1.45rem;
    font-weight: 700;
    line-height: 1.3;
    color: rgba(255, 255, 255, 0.95);
    margin: 0;
    letter-spacing: -0.01em;
}
.buzz-hero-desc {
    font-size: 0.9rem;
    line-height: 1.55;
    color: rgba(255, 255, 255, 0.6);
    margin: 0;
    display: -webkit-box;
    -webkit-line-clamp: 3;
    -webkit-box-orient: vertical;
    overflow: hidden;
}
/* Estate design pass (Aug 11 2026): 0.45 measured 4.51:1 dark (a hair under
   4.5:1 once rounding is removed) and the light override below at 3.52:1
   (real fail, needs 4.5:1) - this is the featured/hero post's own byline row,
   a DIFFERENT container from .card-meta (already fixed) so it needed its own
   pass. */
.buzz-hero-meta {
    display: flex;
    align-items: center;
    gap: 0.45rem;
    font-size: 0.78rem;
    color: rgba(255, 255, 255, 0.55);
    flex-wrap: wrap;
    margin-top: 0.25rem;
}
/* Throat item 1 (Aug 11 round 3, real fix): the round-2 fix got the CARD's
   top edge into the 390x844 viewport (y=837) but the round-2 layout still
   STACKED the image above a separate content block below it - the real
   headline text rendered at y~1098, ~254px past the fold, even though the
   container itself was "in viewport". Restructured as an OVERLAY at this
   width only: the image becomes the card's absolute-positioned background
   and the title sits in a top-anchored scrim directly over it - the CD's
   own "headline sits above/over the image" option. The "Featured" badge and
   the desc/meta rows are dropped AT THIS WIDTH ONLY - the acute constraint
   is a legible HEADLINE above the fold, not the full card; badge/desc/meta
   all still render exactly as before at >=769px, including the full tall
   two-column hero at 1440 (this rule only fires <=768px, nothing here
   touches the base/desktop rules above). Scrim + forced-light title color
   are deliberately THEME-INDEPENDENT (see the [data-theme="light"] override
   below) - legibility here is about contrast against an arbitrary photo,
   not the site's light/dark palette. */
@media (max-width: 768px) {
    .buzz-hero {
        display: block;
        min-height: 220px;
    }
    .buzz-hero-image {
        position: absolute;
        inset: 0;
        min-height: 0;
    }
    .buzz-hero-image::after {
        content: '';
        position: absolute;
        inset: 0;
        background: linear-gradient(180deg, rgba(6,11,24,0.88) 0%, rgba(6,11,24,0.5) 42%, rgba(6,11,24,0.08) 100%);
    }
    .buzz-hero-content {
        position: absolute;
        inset: 0 0 auto 0;
        z-index: 3;
        padding: 0.1rem 1rem 2rem;
        justify-content: flex-start;
    }
    /* Throat item 1 (Aug 11 round 3c): font-size/line-height only (not the
       Outfit typeface itself, which stays the live pending ruling) - a
       slightly tighter first line means less of it sits under the fixed
       mobile-nav's real 785px overlay line at the same top position. */
    .buzz-hero-title {
        font-size: 1.05rem;
        line-height: 1.2;
        color: #FFFFFF;
        text-shadow: 0 1px 4px rgba(0, 0, 0, 0.6);
        display: -webkit-box;
        -webkit-line-clamp: 3;
        -webkit-box-orient: vertical;
        overflow: hidden;
    }
    /* Featured badge, description and byline meta are hidden ONLY at this
       width - see the block comment above. Still present in the DOM (no HTML
       change), still rendered at >=769px. */
    .buzz-hero-badge,
    .buzz-hero-desc,
    .buzz-hero-meta {
        display: none;
    }
}
/* Light-mode override */
[data-theme="light"] .buzz-hero-title { color: #2C2417; }
[data-theme="light"] .buzz-hero-desc { color: rgba(44, 36, 23, 0.65); }
[data-theme="light"] .buzz-hero-meta { color: rgba(44, 36, 23, 0.75); }
/* Estate design pass (Aug 11 2026): #C8912E measured 2.78:1 on its own tinted
   background (needs 4.5:1, real - not the gradient false-positive class,
   this background is a flat rgba). Same proven amber as the other gold-on-light
   fixes above; background tint raised slightly too for a touch more separation. */
[data-theme="light"] .buzz-hero-badge { color: #B45309; background: rgba(200, 145, 46, 0.14); border-color: rgba(200, 145, 46, 0.3); }
/* Throat item 1 (Aug 11 round 3): the light-theme title override above (2C2417,
   dark ink) would sit on the SAME dark photo scrim at this width and go
   unreadable - this wins on source order (declared after it, same specificity,
   media query narrows it further) to keep the overlay title white in both
   themes, matching the theme-independent scrim comment above. */
@media (max-width: 768px) {
    [data-theme="light"] .buzz-hero-title { color: #FFFFFF; }
}
/* KNOWN HARNESS FALSE POSITIVE (confirmed, do not "fix" by chasing the
   checker): /opt/umg-scripts/site-design-harness flags this h2 in light theme
   at "1:1" contrast. Its checker walks the DOM ancestor chain reading
   background-color and cannot see a background painted by a sibling
   ::after pseudo-element (.buzz-hero-image::after, the scrim) - it falls
   through to the page's own white/cream background and compares that
   against the white text, hence "1:1". This is the SAME documented bug
   class as #umg-supporter-banner's gradient false positive (see that
   element's own comment). Real measured contrast, verified by rendered-
   pixel sample (not DOM-walk math): white text vs the actual scrim pixel
   directly behind the glyphs = ~18.9:1 dark theme and light theme alike
   (the scrim is intentionally theme-independent - see the comment on
   .buzz-hero-image::after above). Confirmed via a fresh Playwright context
   replicating the harness's own emulateMedia+reload methodology, sampling
   real screenshot pixels at the glyph row. */

/* ===== FEED CARDS (buzz-card) ===== */
.buzz-card {
    display: flex;
    align-items: stretch;
    background: var(--buzz-card-bg);
    border: 1px solid var(--buzz-card-border);
    border-radius: var(--buzz-radius);
    margin-bottom: 0.75rem;
    overflow: hidden;
    transition: all 0.35s var(--buzz-ease);
    position: relative;
    backdrop-filter: blur(8px);
    -webkit-backdrop-filter: blur(8px);
}
.buzz-card::before {
    content: '';
    position: absolute;
    top: 0; left: 0; right: 0;
    height: 1px;
    background: linear-gradient(90deg, transparent, rgba(223, 160, 50, 0.2), transparent);
    opacity: 0;
    transition: opacity 0.4s ease;
}
.buzz-card:hover::before { opacity: 1; }
.buzz-card:hover {
    border-color: rgba(223, 160, 50, 0.15);
    box-shadow: 0 8px 32px rgba(0, 0, 0, 0.35), 0 0 24px rgba(223, 160, 50, 0.04);
    transform: translateY(-1px);
}
.buzz-card:active {
    transform: translateY(0);
}

/* Vote column */
/* ===== UPVOTE AFFORDANCE (A-grade polish, Jun 18) =====
   The CD flagged the old vote control as "a tiny arrow that reads as a bullet".
   This is the product's KEY interaction, so it now reads unambiguously as an
   upvote BUTTON: a bordered pill, a bold ≥24px filled triangle, gold-on-hover,
   and the count directly below. 44px tap target on mobile. */
/* Feed-card vote column (A-grade polish iter-2, Jun 18): the whole column is now
   ONE bordered "upvote box" — arrow + score stacked inside a single gold-bordered
   pill — so the vote affordance reads as obviously tappable and matches the
   post-page treatment (.vote-btn-detail). Was a near-invisible thin-bordered
   triangle that the CD flagged as inconsistent with the post page. */
.vote-col {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    padding: 0.5rem 0.5rem;
    min-width: 60px;
    flex-shrink: 0;
    cursor: pointer;
    -webkit-tap-highlight-color: transparent;
    user-select: none;
    border-right: 1px solid rgba(26, 39, 68, 0.4);
}
.vote-col:focus-visible {
    outline: 2px solid var(--buzz-gold);
    outline-offset: -2px;
    border-radius: 8px;
}
/* The bordered box itself wraps arrow + score. */
.vote-col .vote-arrow {
    display: block;
    width: 44px;
    height: 40px;
    padding: 8px 8px 4px;
    box-sizing: border-box;
    color: var(--buzz-text-muted);
    background: rgba(255, 255, 255, 0.04);
    border: 1.5px solid rgba(223, 160, 50, 0.4);
    border-radius: 10px 10px 0 0;
    border-bottom: none;
    transition: all 0.2s var(--buzz-ease);
}
.vote-col .vote-score {
    display: block;
    width: 44px;
    padding: 2px 0 5px;
    text-align: center;
    box-sizing: border-box;
    font-size: 0.8125rem;
    font-weight: 800;
    color: var(--buzz-text);
    font-variant-numeric: tabular-nums;
    line-height: 1;
    min-height: 0.9em;
    background: rgba(255, 255, 255, 0.04);
    border: 1.5px solid rgba(223, 160, 50, 0.4);
    border-top: none;
    border-radius: 0 0 10px 10px;
    transition: all 0.2s var(--buzz-ease);
}
/* Zero-vote score renders EMPTY (amanah: never invent a number, and never a
   placeholder glyph that reads AS a score). The JS sets score=0 → '' (see
   index.html: post.score > 0 ? post.score : ''); we must NOT inject a '·'
   middle-dot via ::before — every audit (Suhaib/Mehek, Jun 11-20) read that dot
   as "every story shows 0 / a dot instead of a number". The box shape is held by
   the min-height below, so the empty box still looks intentional with no glyph. */
.vote-col .vote-score:empty {
    min-height: 0.9em;
}
.vote-col:hover .vote-arrow,
.vote-col:hover .vote-score {
    color: var(--buzz-gold);
    border-color: rgba(223, 160, 50, 0.75);
    background: rgba(223, 160, 50, 0.1);
}
.vote-col:active .vote-arrow,
.vote-col:active .vote-score {
    background: rgba(223, 160, 50, 0.16);
}
.vote-col.voted .vote-arrow {
    color: #060B18;
    background: linear-gradient(135deg, var(--buzz-gold), var(--buzz-gold-light));
    border-color: var(--buzz-gold);
    filter: drop-shadow(0 0 6px rgba(223, 160, 50, 0.5));
}
.vote-col.voted .vote-score {
    color: var(--buzz-gold);
    border-color: var(--buzz-gold);
    background: rgba(223, 160, 50, 0.14);
}
[data-theme="light"] .vote-col .vote-arrow,
[data-theme="light"] .vote-col .vote-score {
    background: rgba(13, 17, 23, 0.03);
    border-color: rgba(196, 162, 101, 0.6);
    color: var(--buzz-text-muted);
}
[data-theme="light"] .vote-col:hover .vote-arrow,
[data-theme="light"] .vote-col:hover .vote-score {
    color: var(--buzz-gold);
    background: rgba(223, 160, 50, 0.1);
    border-color: var(--buzz-gold);
}
[data-theme="light"] .vote-col.voted .vote-arrow {
    color: #FFFFFF;
    background: linear-gradient(135deg, var(--buzz-gold), var(--buzz-gold-light));
    border-color: var(--buzz-gold);
}
[data-theme="light"] .vote-col.voted .vote-score {
    color: var(--buzz-gold);
    border-color: var(--buzz-gold);
}

/* Vote bounce animation */
@keyframes voteBounce {
    0% { transform: scale(1); }
    30% { transform: scale(1.3); }
    50% { transform: scale(0.9); }
    70% { transform: scale(1.1); }
    100% { transform: scale(1); }
}
.vote-col.vote-animate .vote-arrow {
    animation: voteBounce 0.4s var(--buzz-ease);
}

/* Card content area */
.card-content {
    flex: 1;
    min-width: 0;
    padding: 0.75rem 0.75rem;
    display: flex;
    flex-direction: column;
    justify-content: center;
    gap: 6px;
}
.card-title {
    font-size: 0.9375rem;
    font-weight: 600;
    color: var(--buzz-heading);
    line-height: 1.35;
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
    transition: color 0.2s ease;
}
.card-title:hover { color: var(--buzz-gold); }

.card-description {
    font-size: 0.8125rem;
    color: var(--buzz-text-muted);
    line-height: 1.4;
    display: -webkit-box;
    -webkit-line-clamp: 1;
    -webkit-box-orient: vertical;
    overflow: hidden;
}

.card-meta {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 6px;
    font-size: 0.6875rem;
    color: var(--buzz-text-muted);
}
/* BUG-047 (May 18): tighten meta-item visual hierarchy.
   - Domain reads as a pill chip (subtle background)
   - Author + meta-sep get explicit color tokens
   - source-type badge (TEXT/LINK/VIDEO/TWITTER) reads as a label, not a word */
.card-meta .domain-badge {
    background: rgba(255,255,255,0.04);
    border: 1px solid rgba(255,255,255,0.06);
    padding: 1.5px 6px;
    border-radius: 4px;
    color: var(--buzz-text-muted);
    font-weight: 500;
    display: inline-flex;
    align-items: center;
    gap: 4px;
}
.card-meta .source-badge,
.card-meta .text-badge,
.card-meta .rising-badge {
    text-transform: uppercase;
    letter-spacing: 0.04em;
    font-size: 0.625rem;
    padding: 2px 7px;
    border-radius: 999px;
    font-weight: 600;
}
.card-meta .source-badge { background: rgba(20, 184, 166, 0.1); color: var(--buzz-teal); }
.card-meta .text-badge   { background: rgba(168, 162, 158, 0.12); color: var(--buzz-text-muted); }
.card-meta .rising-badge { background: linear-gradient(90deg, rgba(223,160,50,0.18), rgba(223,160,50,0.08)); color: var(--buzz-gold); }
.card-meta .meta-author { color: var(--buzz-text); font-weight: 500; }
.card-meta .meta-author-ummahme { color: var(--buzz-gold); }
.card-meta .meta-views { font-variant-numeric: tabular-nums; }
[data-theme="light"] .card-meta .domain-badge {
    background: rgba(13, 17, 23, 0.04);
    border-color: rgba(13, 17, 23, 0.08);
}
.card-actions {
    display: flex;
    align-items: center;
    gap: 12px;
    margin-top: 2px;
}
.card-action-btn {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    font-size: 0.6875rem;
    color: var(--buzz-text-dim);
    transition: color 0.2s ease;
    cursor: pointer;
    /* Estate design pass (Aug 11 2026): the shared per-card component behind
       ~100+ tap-target misses in the harness run (Share 47x14, Save 46x16,
       the comments icon-link 18x14 - one fix propagates down the whole feed,
       per the audit's own #2 finding). .card-actions is already its own row
       below the meta line, so growing it to 44px reads as a normal mobile
       card action bar, not a layout break. */
    min-height: 44px;
    /* Re-run after the first fix round (Aug 11): the icon-only comments link
       (0 comments = empty text, just the SVG) still measured 18px WIDE.
       min-height alone only fixes one axis. */
    min-width: 44px;
    justify-content: center;
}
.card-action-btn:hover { color: var(--buzz-text); }
.card-action-btn svg { width: 14px; height: 14px; }

/* Card thumbnail */
.card-thumb {
    width: 80px;
    min-height: 80px;
    flex-shrink: 0;
    overflow: hidden;
    display: flex;
    align-items: center;
    margin: 0.5rem 0.5rem 0.5rem 0;
    border-radius: var(--buzz-radius-sm);
}
.card-thumb img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    border-radius: var(--buzz-radius-sm);
}

/* ===== BADGES ===== */
.domain-badge {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    padding: 2px 8px;
    background: rgba(15, 26, 51, 0.6);
    border: 1px solid rgba(26, 39, 68, 0.5);
    border-radius: var(--buzz-radius-pill);
    font-size: 0.625rem;
    color: var(--buzz-text-muted);
    white-space: nowrap;
}
.domain-badge img {
    width: 12px;
    height: 12px;
    border-radius: 2px;
}
.text-badge {
    display: inline-flex;
    align-items: center;
    padding: 2px 8px;
    background: rgba(20, 184, 166, 0.12);
    border: 1px solid rgba(20, 184, 166, 0.25);
    border-radius: var(--buzz-radius-pill);
    font-size: 0.625rem;
    font-weight: 600;
    color: var(--buzz-teal);
    letter-spacing: 0.03em;
}
.source-badge {
    display: inline-flex;
    align-items: center;
    gap: 3px;
    padding: 2px 8px;
    border-radius: var(--buzz-radius-pill);
    font-size: 0.625rem;
    font-weight: 600;
    letter-spacing: 0.02em;
}
.source-badge.youtube { background: rgba(255, 0, 0, 0.12); color: #FF4444; border: 1px solid rgba(255, 0, 0, 0.2); }
.source-badge.twitter { background: rgba(29, 161, 242, 0.12); color: #1DA1F2; border: 1px solid rgba(29, 161, 242, 0.2); }
.source-badge.instagram { background: rgba(225, 48, 108, 0.12); color: #E1306C; border: 1px solid rgba(225, 48, 108, 0.2); }
.source-badge.tiktok { background: rgba(255, 0, 80, 0.12); color: #FF0050; border: 1px solid rgba(255, 0, 80, 0.2); }
.source-badge.reddit { background: rgba(255, 69, 0, 0.12); color: #FF4500; border: 1px solid rgba(255, 69, 0, 0.2); }
.source-badge.facebook { background: rgba(24, 119, 242, 0.12); color: #1877F2; border: 1px solid rgba(24, 119, 242, 0.2); }
.source-badge.article { background: rgba(200, 208, 224, 0.08); color: var(--buzz-text-muted); border: 1px solid rgba(200, 208, 224, 0.12); }

/* Buzzing badge (was "Rising") - Apr 22 (Saad Apr 20 ask); bee glyph + "Buzzing"
   label v163 (Jun 18 2026). Keeps the gold/amber ember treatment - it already
   lives in bee territory tonally. The inline bee inherits the badge color via
   currentColor. Subtle pulse. */
.rising-badge {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    padding: 2px 9px 2px 7px;
    background: linear-gradient(135deg, rgba(223,160,50,0.20), rgba(234,88,12,0.10));
    border: 1px solid rgba(223,160,50,0.38);
    border-radius: var(--buzz-radius-pill);
    font-size: 0.625rem;
    font-weight: 700;
    color: #fbbf24;
    letter-spacing: 0.03em;
    text-transform: uppercase;
    line-height: 1;
    animation: rising-glow 2.4s ease-in-out infinite;
}
/* Inline bee glyph in the Buzzing badge - inherits badge color. */
.rising-bee {
    flex-shrink: 0;
    display: block;
}
@keyframes rising-glow {
    0%, 100% { box-shadow: 0 0 0 0 rgba(223,160,50,0.0); }
    50%      { box-shadow: 0 0 12px 0 rgba(223,160,50,0.30); }
}
[data-theme="light"] .rising-badge {
    background: linear-gradient(135deg, rgba(200,145,46,0.18), rgba(234,88,12,0.10));
    border-color: rgba(200,145,46,0.42);
    color: #B45309;
}
/* Respect reduced-motion: drop the pulse, keep the badge. */
@media (prefers-reduced-motion: reduce) {
    .rising-badge { animation: none; }
}

/* Compact view count next to time — Apr 22 */
.meta-views {
    color: var(--buzz-text-muted);
    font-variant-numeric: tabular-nums;
}

.meta-sep { color: var(--buzz-text-dim); }
.meta-author {
    color: var(--buzz-gold);
    font-weight: 500;
    transition: opacity 0.2s ease;
}
.meta-author:hover { opacity: 0.8; }

.status-citizen { color: var(--buzz-gold); }
.status-resident { color: var(--buzz-teal); }

/* ===== SIDEBAR ===== */
.sidebar-card {
    background: var(--buzz-card-bg);
    border: 1px solid var(--buzz-card-border);
    border-radius: var(--buzz-radius);
    padding: 1.25rem;
    margin-bottom: 1rem;
}
.sidebar-title {
    font-size: 0.8125rem;
    font-weight: 700;
    color: var(--buzz-heading);
    margin-bottom: 0.75rem;
    letter-spacing: 0.02em;
}
.sidebar-text {
    font-size: 0.8125rem;
    color: var(--buzz-text-muted);
    line-height: 1.5;
    margin-bottom: 1rem;
}

/* "How UmmahBuzz works" 3-step (A-grade polish, Jun 18). */
.sidebar-howto {
    list-style: none;
    margin: 0 0 0.875rem;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 0.625rem;
}
.sidebar-howto li {
    display: flex;
    align-items: flex-start;
    gap: 0.5rem;
    font-size: 0.8125rem;
    line-height: 1.45;
    color: var(--buzz-text-muted);
}
.sidebar-howto-num {
    flex-shrink: 0;
    width: 1.25rem;
    height: 1.25rem;
    border-radius: 50%;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    font-size: 0.6875rem;
    font-weight: 800;
    color: var(--buzz-gold);
    background: rgba(223, 160, 50, 0.14);
    border: 1px solid rgba(223, 160, 50, 0.3);
    margin-top: 0.05rem;
}
[data-theme="light"] .sidebar-howto-num {
    color: #6f5a36;
    background: rgba(223, 160, 50, 0.16);
    border-color: rgba(196, 162, 101, 0.5);
}

/* SUGG-163 (May 22): honest social-proof trust strip. Theme-agnostic tokens. */
.sidebar-trust .trust-stats {
    display: flex;
    gap: 0.5rem;
    margin-bottom: 0.75rem;
}
.trust-stat {
    flex: 1 1 0;
    display: flex;
    flex-direction: column;
    align-items: center;
    text-align: center;
    padding: 0.625rem 0.25rem;
    background: var(--buzz-gold-tint, rgba(223, 160, 50, 0.07));
    border: 1px solid var(--buzz-card-border);
    border-radius: 10px;
}
.trust-stat-num {
    font-size: 1.25rem;
    font-weight: 800;
    line-height: 1.1;
    color: var(--buzz-gold);
    font-variant-numeric: tabular-nums;
}
.trust-stat-label {
    font-size: 0.625rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--buzz-text-muted);
    margin-top: 0.25rem;
    line-height: 1.2;
}
.trust-note {
    font-size: 0.75rem;
    color: var(--buzz-text-muted);
    line-height: 1.5;
    margin: 0;
}
.sidebar-cta {
    display: block;
    width: 100%;
    text-align: center;
    padding: 10px 16px;
    background: rgba(223, 160, 50, 0.12);
    border: 1px solid rgba(223, 160, 50, 0.25);
    border-radius: var(--buzz-radius-sm);
    color: var(--buzz-gold);
    font-size: 0.8125rem;
    font-weight: 600;
    transition: all 0.3s ease;
}
.sidebar-cta:hover {
    background: rgba(223, 160, 50, 0.2);
    border-color: rgba(223, 160, 50, 0.4);
    transform: translateY(-1px);
}
/* A-grade iter-4 (Jun 18): light-theme contrast fix. The default
   color: var(--buzz-gold) = #C8912E reads at only 2.40:1 on the gold-tinted
   cream button background (WCAG AA fail). Darken the gold to a brass that
   clears 4.5:1 both on the tint AND plain cream. (The teal "Claim yours"
   email CTA sets its own inline #fff-on-teal and is unaffected.) */
[data-theme="light"] .sidebar-cta:not([style*="color"]) {
    color: #855F00;
}

/* BUG-131 (May 18): Discreet inline Submit link inside the sidebar UmmahPass
   card — replaces the top-nav Submit pill so news stays visually primary.
   Teal secondary action, smaller than .sidebar-cta. */
.sidebar-submit-link {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 6px 12px;
    background: rgba(20, 184, 166, 0.10);
    border: 1px solid rgba(20, 184, 166, 0.22);
    border-radius: var(--buzz-radius-pill);
    color: var(--buzz-teal);
    font-size: 0.75rem;
    font-weight: 600;
    text-decoration: none;
    transition: all 0.25s var(--buzz-ease);
}
.sidebar-submit-link:hover {
    background: rgba(20, 184, 166, 0.18);
    border-color: rgba(20, 184, 166, 0.38);
}

/* UmmahPass sidebar CTA - gold accent */
.sidebar-ummahpass {
    border-color: rgba(223, 160, 50, 0.2);
    position: relative;
    overflow: hidden;
}
.sidebar-ummahpass::before {
    content: '';
    position: absolute;
    top: 0; left: 0; right: 0;
    height: 2px;
    background: linear-gradient(90deg, transparent, var(--buzz-gold), transparent);
}

/* ===== SUBMIT FORM ===== */
.submit-section {
    max-width: 680px;
    margin: 0 auto;
    padding: 2rem 1rem;
    position: relative;
    z-index: 2;
}
.submit-form {
    background: var(--buzz-card-bg);
    border: 1px solid var(--buzz-card-border);
    border-radius: var(--buzz-radius);
    padding: 1.5rem;
}
.submit-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    margin-bottom: 1.25rem;
}
.submit-title {
    font-size: 1.25rem;
    font-weight: 700;
    color: var(--buzz-heading);
}

/* Type toggle */
.type-toggle {
    display: inline-flex;
    background: rgba(15, 26, 51, 0.6);
    border: 1px solid var(--buzz-border-alpha);
    border-radius: var(--buzz-radius-pill);
    padding: 3px;
    gap: 2px;
}
.type-toggle-btn {
    padding: 6px 16px;
    border-radius: var(--buzz-radius-pill);
    font-size: 0.8125rem;
    font-weight: 600;
    color: var(--buzz-text-muted);
    transition: all 0.25s ease;
}
.type-toggle-btn.active {
    background: rgba(223, 160, 50, 0.15);
    color: var(--buzz-gold);
}
.type-toggle-btn:hover:not(.active) { color: var(--buzz-text); }

/* Form elements */
.form-group { margin-bottom: 1rem; }
.form-label {
    display: block;
    font-size: 0.75rem;
    font-weight: 600;
    color: var(--buzz-text-muted);
    margin-bottom: 0.375rem;
    letter-spacing: 0.03em;
    text-transform: uppercase;
}
.form-input, .form-textarea {
    width: 100%;
    padding: 10px 14px;
    background: rgba(6, 11, 24, 0.6);
    border: 1px solid var(--buzz-border-alpha);
    border-radius: var(--buzz-radius-sm);
    color: var(--buzz-text);
    font-size: 0.9375rem;
    transition: border-color 0.3s ease, box-shadow 0.3s ease;
}
.form-input:focus, .form-textarea:focus {
    border-color: rgba(223, 160, 50, 0.4);
    box-shadow: 0 0 0 3px rgba(223, 160, 50, 0.08);
}
.form-input::placeholder, .form-textarea::placeholder {
    color: var(--buzz-text-dim);
}
.form-textarea {
    min-height: 140px;
    resize: vertical;
    line-height: 1.5;
}

/* Category picker (Jun 17 — submit-form topic <select>). Shares the
   .form-input shell but adds a custom caret and removes the native
   appearance so it reads consistently across dark + light themes. */
.form-select {
    width: 100%;
    padding: 10px 38px 10px 14px;
    background-color: rgba(6, 11, 24, 0.6);
    background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%23DFA032' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'><polyline points='6 9 12 15 18 9'/></svg>");
    background-repeat: no-repeat;
    background-position: right 12px center;
    border: 1px solid var(--buzz-border-alpha);
    border-radius: var(--buzz-radius-sm);
    color: var(--buzz-text);
    font-size: 0.9375rem;
    line-height: 1.4;
    appearance: none;
    -webkit-appearance: none;
    -moz-appearance: none;
    cursor: pointer;
    transition: border-color 0.3s ease, box-shadow 0.3s ease;
}
.form-select:focus {
    outline: none;
    border-color: rgba(223, 160, 50, 0.4);
    box-shadow: 0 0 0 3px rgba(223, 160, 50, 0.08);
}
/* Native option list inherits the OS surface — force a readable dark surface
   so options aren't white-on-white on some platforms. */
.form-select option {
    background: #0D1117;
    color: #E6E9EF;
}

/* URL preview card */
.url-preview {
    background: rgba(6, 11, 24, 0.5);
    border: 1px solid var(--buzz-border-alpha);
    border-radius: var(--buzz-radius-sm);
    padding: 0.875rem;
    display: flex;
    gap: 0.875rem;
    align-items: flex-start;
    margin-bottom: 1rem;
}
.url-preview-thumb {
    width: 72px;
    height: 72px;
    border-radius: 6px;
    overflow: hidden;
    flex-shrink: 0;
    background: var(--buzz-deep);
}
.url-preview-thumb img {
    width: 100%;
    height: 100%;
    object-fit: cover;
}
.url-preview-info { flex: 1; min-width: 0; }
.url-preview-domain {
    font-size: 0.6875rem;
    color: var(--buzz-gold);
    margin-bottom: 4px;
}
.url-preview-title {
    font-size: 0.875rem;
    font-weight: 600;
    color: var(--buzz-heading);
    line-height: 1.3;
    margin-bottom: 4px;
}
.url-preview-desc {
    font-size: 0.75rem;
    color: var(--buzz-text-muted);
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
}

/* Submit button */
.submit-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
    width: 100%;
    padding: 12px 24px;
    background: linear-gradient(135deg, var(--buzz-gold), var(--buzz-gold-dim));
    color: #060B18;
    font-weight: 700;
    font-size: 0.9375rem;
    border-radius: var(--buzz-radius-sm);
    transition: all 0.3s var(--buzz-ease);
    box-shadow: 0 4px 16px rgba(223, 160, 50, 0.2);
}
.submit-btn:hover:not(:disabled) {
    transform: translateY(-1px);
    box-shadow: 0 8px 24px rgba(223, 160, 50, 0.3);
}
.submit-btn:disabled {
    opacity: 0.5;
    cursor: not-allowed;
}

/* Error / success messages */
.form-error {
    padding: 10px 14px;
    background: rgba(239, 68, 68, 0.1);
    border: 1px solid rgba(239, 68, 68, 0.25);
    border-radius: var(--buzz-radius-sm);
    color: #F87171;
    font-size: 0.8125rem;
    margin-bottom: 1rem;
}
.form-success {
    padding: 10px 14px;
    background: rgba(20, 184, 166, 0.1);
    border: 1px solid rgba(20, 184, 166, 0.25);
    border-radius: var(--buzz-radius-sm);
    color: var(--buzz-teal);
    font-size: 0.8125rem;
    margin-bottom: 1rem;
}
.form-hint {
    font-size: 0.75rem;
    color: var(--buzz-text-dim);
    margin-top: 4px;
}

/* Fetching meta spinner */
.meta-loading {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 12px;
    color: var(--buzz-text-muted);
    font-size: 0.8125rem;
}
.spinner {
    width: 16px;
    height: 16px;
    border: 2px solid rgba(223, 160, 50, 0.2);
    border-top-color: var(--buzz-gold);
    border-radius: 50%;
    animation: spin 0.7s linear infinite;
}
@keyframes spin { to { transform: rotate(360deg); } }

/* ===== SEARCH ===== */
.buzz-search {
    width: 100%;
    padding: 10px 14px 10px 40px;
    background: rgba(6, 11, 24, 0.6);
    border: 1px solid var(--buzz-border-alpha);
    border-radius: var(--buzz-radius-pill);
    color: var(--buzz-text);
    font-size: 0.9375rem;
    transition: border-color 0.3s ease, box-shadow 0.3s ease;
}
.buzz-search:focus {
    border-color: rgba(223, 160, 50, 0.4);
    box-shadow: 0 0 0 3px rgba(223, 160, 50, 0.08);
}
.buzz-search::placeholder { color: var(--buzz-text-dim); }
.search-wrap {
    position: relative;
}
.search-icon {
    position: absolute;
    left: 14px;
    top: 50%;
    transform: translateY(-50%);
    width: 16px;
    height: 16px;
    color: var(--buzz-text-dim);
    pointer-events: none;
}
.buzz-search-clear {
    position: absolute;
    right: 6px;
    top: 50%;
    transform: translateY(-50%);
    width: 36px;
    height: 36px;
    padding: 0;
    border: none;
    background: rgba(223, 160, 50, 0.08);
    color: var(--buzz-text-muted);
    border-radius: 50%;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    transition: color 0.2s ease, background 0.2s ease;
    -webkit-tap-highlight-color: transparent;
}
.buzz-search-clear:hover {
    color: var(--buzz-gold);
    background: rgba(223, 160, 50, 0.18);
}
.buzz-search-clear svg {
    width: 14px;
    height: 14px;
}
/* Bump to 44x44 on touch so iOS minimum tap target (Creative Director flag Apr 19) */
@media (max-width: 768px) {
    .buzz-search-clear { width: 44px; height: 44px; right: 4px; }
}
.buzz-search {
    padding-right: 42px !important;
}
.search-section {
    max-width: 680px;
    margin: 0 auto;
    padding: 2rem 1rem;
    position: relative;
    z-index: 2;
}
.search-section .search-wrap {
    margin-bottom: 1.5rem;
}
/* BUG-132 (May 18): on desktop (>=768px), the .header-search-wrap input is
   already visible in the header. The in-page .search-section search bar is
   redundant on the homepage's search view — hide it to avoid the duplicate.
   On the standalone /search/ page there is no header-search-wrap, so we
   keep the in-page bar via a body-class opt-out. */
@media (min-width: 768px) {
    body:not(.search-page) .search-section > .search-wrap { display: none; }
}

/* ===== PROFILE ===== */
.profile-section {
    max-width: 680px;
    margin: 0 auto;
    padding: 2rem 1rem;
    position: relative;
    z-index: 2;
}
.profile-card {
    background: var(--buzz-card-bg);
    border: 1px solid var(--buzz-card-border);
    border-radius: var(--buzz-radius);
    padding: 2rem;
    text-align: center;
}
.profile-name {
    font-size: 1.5rem;
    font-weight: 700;
    color: var(--buzz-heading);
    margin-bottom: 0.25rem;
}
.profile-screenname {
    font-size: 1rem;
    color: var(--buzz-gold);
    margin-bottom: 0.25rem;
}
.profile-status {
    font-size: 0.8125rem;
    color: var(--buzz-text-muted);
    margin-bottom: 1rem;
}
.profile-stat-row {
    display: flex;
    justify-content: center;
    gap: 2rem;
    padding-top: 1rem;
    border-top: 1px solid rgba(26, 39, 68, 0.5);
}
.profile-stat {
    text-align: center;
}
.profile-stat-val {
    font-size: 1.25rem;
    font-weight: 700;
    color: var(--buzz-heading);
}
.profile-stat-label {
    font-size: 0.6875rem;
    color: var(--buzz-text-muted);
    text-transform: uppercase;
    letter-spacing: 0.05em;
}

/* ===== MOBILE BOTTOM NAV ===== */
.mobile-nav {
    position: fixed;
    bottom: 0;
    left: 0;
    right: 0;
    z-index: 200;
    display: flex;
    background: rgba(6, 11, 24, 0.92);
    backdrop-filter: blur(20px);
    -webkit-backdrop-filter: blur(20px);
    border-top: 1px solid rgba(26, 39, 68, 0.6);
    padding: 0;
    padding-bottom: env(safe-area-inset-bottom, 0);
}
.mobile-nav-item {
    flex: 1;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 3px;
    padding: 10px 4px;
    min-height: 52px;
    color: var(--buzz-text-dim);
    font-size: 0.625rem;
    font-weight: 500;
    letter-spacing: 0.02em;
    transition: color 0.2s ease;
    cursor: pointer;
    -webkit-tap-highlight-color: transparent;
    user-select: none;
    text-decoration: none;
    position: relative;
}
.mobile-nav-item svg {
    width: 22px;
    height: 22px;
    transition: all 0.2s ease;
}
.mobile-nav-item.active {
    color: var(--buzz-gold);
}
.mobile-nav-item.active::before {
    content: '';
    position: absolute;
    top: 0;
    left: 25%;
    right: 25%;
    height: 2px;
    background: var(--buzz-gold);
    border-radius: 0 0 2px 2px;
}
.mobile-nav-item:hover:not(.active) { color: var(--buzz-text-muted); }

/* Desktop: hide mobile nav */
@media (min-width: 768px) {
    .mobile-nav { display: none; }
    body { padding-bottom: 0; }
}

/* ===== LOADING / EMPTY STATES ===== */
.feed-loading {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 10px;
    padding: 2.5rem;
    color: var(--buzz-text-muted);
    font-size: 0.875rem;
}
.feed-loading .spinner {
    width: 22px;
    height: 22px;
}
/* IntersectionObserver sentinel for infinite scroll (Apr 29).
   DEPRECATED May 4, 2026 — replaced by .feed-loadmore-btn (HYBRID scroll).
   Class kept for any stale CSS references; the element is no longer in DOM. */
.feed-sentinel {
    height: 1px;
    width: 100%;
    margin: 0;
    pointer-events: none;
}
/* "Load more" button (May 4, 2026 - HYBRID scroll).
   Full-width on mobile, centered/auto on desktop. Gold-bordered ghost button
   with subtle fill on hover; matches existing .feed-end-link gold accent. */
.feed-loadmore-wrap {
    display: flex;
    justify-content: center;
    padding: 1.5rem 0 0.75rem;
    margin: 0.25rem 0 1rem;
}
.feed-loadmore-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 0.5rem;
    padding: 0.875rem 1.75rem;
    background: rgba(223, 160, 50, 0.08);
    color: var(--buzz-gold);
    border: 1px solid rgba(223, 160, 50, 0.4);
    border-radius: 999px;
    font-family: inherit;
    font-size: 0.9375rem;
    font-weight: 600;
    letter-spacing: 0.01em;
    cursor: pointer;
    transition: background-color 0.18s ease, border-color 0.18s ease, transform 0.12s ease;
    min-width: 200px;
    -webkit-tap-highlight-color: transparent;
}
.feed-loadmore-btn:hover {
    background: rgba(223, 160, 50, 0.18);
    border-color: rgba(223, 160, 50, 0.7);
}
/* Estate design pass (Aug 11 2026): no light-theme override existed at all -
   var(--buzz-gold) (#C8912E) on this button's own low-opacity tint measured
   2.46:1 (needs 4.5:1, real). #B45309 (the proven amber used elsewhere in this
   file) still only reached 4.24:1 against THIS button's own tinted background
   (alpha-composited, verified) - one step darker to clear the bar with margin. */
[data-theme="light"] .feed-loadmore-btn {
    color: #8A4E12;
    background: rgba(200, 145, 46, 0.12);
    border-color: rgba(200, 145, 46, 0.4);
}
[data-theme="light"] .feed-loadmore-btn:hover {
    background: rgba(200, 145, 46, 0.2);
    border-color: rgba(200, 145, 46, 0.6);
}
.feed-loadmore-btn:active { transform: translateY(1px); }
.feed-loadmore-btn:disabled,
.feed-loadmore-btn[aria-busy="true"] {
    opacity: 0.6;
    cursor: wait;
}
.feed-loadmore-icon {
    flex-shrink: 0;
    opacity: 0.75;
}
@media (max-width: 640px) {
    .feed-loadmore-btn {
        width: 100%;
        max-width: 360px;
    }
}
@media (prefers-reduced-motion: reduce) {
    .feed-loadmore-btn { transition: none; }
    .feed-loadmore-btn:active { transform: none; }
}
/* "All caught up" terminator (Apr 29). Replaces the sentinel once the
   server confirms has_more=false. Subtle gold accent + back-to-top link. */
.feed-end {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 0.5rem;
    padding: 2rem 1rem;
    margin: 0.5rem 0 1.5rem;
    color: var(--buzz-text-muted);
    font-size: 0.9375rem;
    text-align: center;
    flex-wrap: wrap;
}
.feed-end-icon {
    font-size: 1rem;
    line-height: 1;
}
.feed-end-text { color: var(--buzz-text); }
.feed-end-link {
    color: var(--buzz-gold);
    text-decoration: none;
    font-weight: 500;
    margin-left: 0.25rem;
    -webkit-tap-highlight-color: transparent;
}
.feed-end-link:hover { text-decoration: underline; }
@media (prefers-reduced-motion: reduce) {
    .feed-end { transition: none !important; animation: none !important; }
}
.feed-empty {
    position: relative;
    overflow: hidden;
    text-align: center;
    padding: 3.5rem 1.5rem;
    color: var(--buzz-text-muted);
    background: var(--buzz-card-bg);
    border: 1px solid var(--buzz-card-border);
    border-radius: var(--buzz-radius);
}
/* Faint honeycomb texture behind the empty state (v163). <=7% opacity so it reads
   as atmosphere, never competes with content. Gold on dark, brass on cream. */
.feed-empty-honeycomb {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    pointer-events: none;
    color: var(--buzz-gold);
    opacity: 0.07;
}
[data-theme="light"] .feed-empty-honeycomb {
    color: #C8912E;
    opacity: 0.06;
}
/* Geometric bee mark (faceless) for the quiet feed. */
.feed-empty-bee {
    position: relative;
    z-index: 1;
    display: block;
    width: 56px;
    height: 56px;
    margin: 0 auto 1.25rem;
    color: var(--buzz-gold);
}
[data-theme="light"] .feed-empty-bee {
    color: #C8912E;
}
.feed-empty-arabesque {
    display: block;
    width: 96px;
    height: 96px;
    margin: 0 auto 1.5rem;
    opacity: 0.75;
}
.feed-empty-icon {
    width: 56px;
    height: 56px;
    margin: 0 auto 1.25rem;
    color: var(--buzz-text-dim);
    opacity: 0.6;
}
.feed-empty-text {
    position: relative;
    z-index: 1;
    font-size: 1.0625rem;
    font-weight: 600;
    color: var(--buzz-text);
    margin-bottom: 0.5rem;
}
.feed-empty-sub {
    position: relative;
    z-index: 1;
    font-size: 0.8125rem;
    color: var(--buzz-text-dim);
    line-height: 1.5;
    max-width: 320px;
    margin: 0 auto;
}
.feed-empty-cta {
    position: relative;
    z-index: 1;
    display: inline-block;
    margin-top: 1.25rem;
    padding: 0.5rem 1.25rem;
    background: rgba(223, 160, 50, 0.12);
    border: 1px solid rgba(223, 160, 50, 0.3);
    border-radius: 9999px;
    color: var(--buzz-gold);
    font-size: 0.8125rem;
    font-weight: 600;
    text-decoration: none;
    transition: background 0.2s ease, border-color 0.2s ease;
}
.feed-empty-cta:hover {
    background: rgba(223, 160, 50, 0.2);
    border-color: rgba(223, 160, 50, 0.5);
}

/* ===== FEED TRANSPORT-ERROR BANNER (Jun 12, Mehek BUG) =====
   Non-destructive notice shown when a refetch hits the rate limit (429) or a
   transient server error. Sits above the feed; existing posts stay visible. */
.feed-error-banner {
    display: flex;
    align-items: center;
    gap: 0.6rem;
    margin: 0 0 1rem;
    padding: 0.7rem 0.9rem;
    background: rgba(223, 160, 50, 0.08);
    border: 1px solid rgba(223, 160, 50, 0.28);
    border-radius: 12px;
    color: var(--buzz-gold);
    font-size: 0.8125rem;
    line-height: 1.4;
}
.feed-error-banner svg { flex: 0 0 auto; opacity: 0.9; }
.feed-error-text { flex: 1 1 auto; color: #E6D2A6; }
.feed-error-retry {
    flex: 0 0 auto;
    padding: 0.35rem 0.8rem;
    background: rgba(223, 160, 50, 0.14);
    border: 1px solid rgba(223, 160, 50, 0.35);
    border-radius: 9999px;
    color: var(--buzz-gold);
    font-size: 0.75rem;
    font-weight: 600;
    cursor: pointer;
    transition: background 0.2s ease, border-color 0.2s ease;
}
.feed-error-retry:hover {
    background: rgba(223, 160, 50, 0.24);
    border-color: rgba(223, 160, 50, 0.55);
}

/* ===== GOLD DIVIDER ===== */
.gold-line {
    height: 1px;
    background: linear-gradient(90deg, transparent, rgba(223, 160, 50, 0.15), transparent);
    margin: 0 auto;
}
/* Throat item 1 (Aug 11 round 3): the hero's gold-line carries its bottom
   margin as an INLINE style (index.html) - !important is the only way a
   stylesheet rule beats that at this one narrower breakpoint without
   touching the shared .gold-line class's desktop behavior or index.html's
   own markup. Only this one instance exists on the page (grep-confirmed). */
@media (max-width: 768px) {
    .gold-line { margin-bottom: 0.1rem !important; }
}

/* ===== FOOTER — legacy link strip (kept for /profile, /search) ===== */
.buzz-footer {
    position: relative;
    z-index: 2;
    text-align: center;
    padding: 2rem 1rem;
    border-top: 1px solid rgba(26, 39, 68, 0.3);
    margin-top: 2rem;
}
.buzz-footer-text {
    font-size: 0.6875rem;
    color: var(--buzz-text-dim);
}
.buzz-footer a {
    color: var(--buzz-gold-dim);
    transition: color 0.3s ease;
}
.buzz-footer a:hover { color: var(--buzz-gold); }

/* ===== ECOSYSTEM FOOTER — flywheel-focused (Apr 21, 2026) ===== */
.ub-eco-footer {
    position: relative;
    z-index: 2;
    margin-top: 3rem;
    padding: 3rem 1.5rem 1.5rem;
    background: linear-gradient(180deg, transparent, rgba(0,0,0,0.25));
    border-top: 1px solid rgba(223,160,50,0.12);
}
.ub-eco-wrap {
    max-width: 1200px;
    margin: 0 auto;
    display: grid;
    grid-template-columns: 1.3fr 1fr 1fr 1.1fr;
    gap: 2.25rem 2.5rem;
    align-items: start;
}
.ub-eco-col { min-width: 0; }
.ub-eco-brand {
    font-family: 'Outfit', system-ui, sans-serif;
    font-size: 1.15rem;
    font-weight: 700;
    color: rgba(255,255,255,0.92);
    letter-spacing: -0.01em;
    margin-bottom: 0.35rem;
}
.ub-eco-tagline {
    font-size: 0.82rem;
    color: rgba(255,255,255,0.58);
    font-style: italic;
    margin-bottom: 0.6rem;
    line-height: 1.4;
}
.ub-eco-blurb {
    font-size: 0.78rem;
    color: rgba(255,255,255,0.48);
    line-height: 1.5;
    margin-bottom: 0.75rem;
}
/* Estate design pass (Aug 11 2026): the harness's theme-toggle bug (fixed in
   site-design-harness/harness.js this same pass) had been masking real dark-
   mode contrast findings on this whole footer column - these alpha'd colors
   needed alpha-composited math (fg*alpha + bg*(1-alpha)) against the real
   rendered background, not the raw foreground color, to verify correctly.
   .ub-eco-trust 0.38 measured 3.53:1 (needs 4.5:1, real, both themes). */
.ub-eco-trust {
    list-style: none;
    padding: 0;
    margin: 0;
    font-size: 0.72rem;
    color: rgba(255,255,255,0.55);
    line-height: 1.75;
}
.ub-eco-trust li::before {
    content: '✓';
    color: rgba(223,160,50,0.55);
    margin-right: 0.4rem;
}
.ub-eco-heading {
    font-size: 0.68rem;
    font-weight: 700;
    letter-spacing: 0.12em;
    text-transform: uppercase;
    color: rgba(255,255,255,0.75);
    margin: 0 0 0.9rem 0;
    padding-bottom: 0.4rem;
    border-bottom: 1px solid rgba(223,160,50,0.15);
}
.ub-eco-heading-gold { color: #E8C252; border-bottom-color: rgba(223,160,50,0.35); }
.ub-eco-link {
    display: block;
    padding: 0.4rem 0;
    text-decoration: none;
    color: rgba(255,255,255,0.8);
    transition: color 0.2s ease, transform 0.2s ease;
}
.ub-eco-link:hover { color: #E8C252; transform: translateX(2px); }
.ub-eco-link-title {
    display: block;
    font-size: 0.85rem;
    font-weight: 600;
    margin-bottom: 0.1rem;
}
/* Estate design pass (Aug 11 2026): 0.45 measured 4.51:1 (needs 4.5:1) - a
   hair under threshold once measured correctly; small bump for margin. */
.ub-eco-link-desc {
    display: block;
    font-size: 0.72rem;
    color: rgba(255,255,255,0.55);
    line-height: 1.4;
}
.ub-eco-link:hover .ub-eco-link-desc { color: rgba(255,255,255,0.6); }

/* Primary CTA card */
.ub-eco-cta {
    background: linear-gradient(135deg, rgba(223,160,50,0.08), rgba(223,160,50,0.03));
    border: 1px solid rgba(223,160,50,0.2);
    border-radius: 14px;
    padding: 1.25rem 1.1rem;
}
.ub-eco-cta-headline {
    font-size: 0.95rem;
    font-weight: 700;
    color: rgba(255,255,255,0.95);
    line-height: 1.3;
    margin: 0 0 0.35rem 0;
}
/* Estate design pass (Aug 11 2026): 0.55 measured 6.24:1 dark (fine) but
   3.52:1 light (real fail, needs 4.5:1) - see the light-theme override below. */
.ub-eco-cta-sub {
    font-size: 0.72rem;
    color: rgba(255,255,255,0.7);
    line-height: 1.5;
    margin-bottom: 0.9rem;
}
.ub-eco-cta-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 0.5rem;
    padding: 0.65rem 1rem;
    /* Estate design pass (Aug 11 2026): harness measured 169x42px. */
    min-height: 44px;
    box-sizing: border-box;
    background: linear-gradient(135deg, #DFA032, #C8912E);
    color: #1a1208;
    font-size: 0.82rem;
    font-weight: 700;
    text-decoration: none;
    border-radius: 8px;
    box-shadow: 0 2px 8px rgba(223,160,50,0.25);
    transition: transform 0.18s ease, box-shadow 0.18s ease;
}
.ub-eco-cta-btn:hover {
    transform: translateY(-1px);
    box-shadow: 0 4px 14px rgba(223,160,50,0.4);
    color: #1a1208;
}
.ub-eco-cta-secondary {
    display: inline-flex;
    align-items: center;
    /* Estate design pass (Aug 11 2026): harness measured 321x18px. Standalone
       CTA link on its own line, not inline prose - real fix. */
    min-height: 44px;
    margin-top: 0.75rem;
    font-size: 0.72rem;
    color: rgba(255,255,255,0.55);
    text-decoration: none;
    transition: color 0.2s ease;
}
.ub-eco-cta-secondary:hover { color: #E8C252; }

/* Bottom bar */
.ub-eco-bottom {
    max-width: 1200px;
    margin: 2.5rem auto 0;
    padding-top: 1.5rem;
    text-align: center;
    border-top: 1px solid rgba(255,255,255,0.06);
}
/* Estate design pass (Aug 11 2026): 0.5 measured 2.87:1 (needs 4.5:1, real).
   A sacred-layer element deserves a clean solid color, not a chased alpha
   value - reuses the estate's own --buzz-gold dark token (8.51:1 here). */
.ub-eco-bismillah {
    font-family: 'Amiri', 'Scheherazade New', serif;
    font-size: 1.1rem;
    color: var(--buzz-gold);
    letter-spacing: 0.02em;
    margin-bottom: 0.9rem;
    direction: rtl;
}
/* Estate design pass (Aug 11 2026): 0.35 measured 3.16:1 (needs 4.5:1, real -
   the "© 2009-2026 CE / 1447 AH" copyright + Hijri year line). */
.ub-eco-meta {
    font-size: 0.7rem;
    color: rgba(255,255,255,0.55);
    line-height: 1.7;
    margin: 0;
}
/* Estate design pass (Aug 11 2026): 0.55 measured 3.26:1 (needs 4.5:1, real -
   alpha-composited against the real rendered footer bg). */
.ub-eco-meta a { color: rgba(223,160,50,0.75); text-decoration: none; }
.ub-eco-meta a:hover { color: #E8C252; }

/* Mobile stack */
@media (max-width: 960px) {
    .ub-eco-wrap { grid-template-columns: 1fr 1fr; gap: 1.75rem; }
    .ub-eco-cta { grid-column: 1 / -1; }
}
@media (max-width: 640px) {
    .ub-eco-footer { padding: 2rem 1rem 1rem; }
    .ub-eco-wrap { grid-template-columns: 1fr; gap: 1.5rem; }
    .ub-eco-cta { grid-column: auto; }
}

/* Light-mode override */
[data-theme="light"] .ub-eco-footer {
    background: linear-gradient(180deg, transparent, rgba(0,0,0,0.025));
    border-top-color: rgba(200,145,46,0.18);
}
[data-theme="light"] .ub-eco-brand { color: #2C2417; }
[data-theme="light"] .ub-eco-tagline { color: rgba(44,36,23,0.7); }
/* Estate design pass (Aug 11 2026): these two + cta-sub/cta-secondary/
   link-desc below all measured real fails once alpha-composited against the
   actual rendered bg (not just the raw foreground color) - the harness's own
   theme-toggle bug (fixed in harness.js this pass) had been masking most of
   these as "identical, so probably fine" duplicate readings. */
[data-theme="light"] .ub-eco-blurb { color: rgba(44,36,23,0.75); }
[data-theme="light"] .ub-eco-trust { color: rgba(44,36,23,0.75); }
[data-theme="light"] .ub-eco-heading { color: rgba(44,36,23,0.75); border-bottom-color: rgba(200,145,46,0.25); }
/* Estate design pass (Aug 11 2026): #C8912E measured 2.54-2.61:1 (needs 4.5:1). */
[data-theme="light"] .ub-eco-heading-gold { color: #B45309; border-bottom-color: rgba(200,145,46,0.4); }
[data-theme="light"] .ub-eco-link { color: rgba(44,36,23,0.8); }
[data-theme="light"] .ub-eco-link:hover { color: #C8912E; }
[data-theme="light"] .ub-eco-link-desc { color: rgba(44,36,23,0.75); }
/* May 4 audit (Mehek): on hover the dark-mode rule at line 1457 turned desc
   text near-white, making it disappear on the light cream background. */
[data-theme="light"] .ub-eco-link:hover .ub-eco-link-desc { color: rgba(44,36,23,0.7); }
[data-theme="light"] .ub-eco-cta { background: linear-gradient(135deg, rgba(200,145,46,0.08), rgba(200,145,46,0.02)); border-color: rgba(200,145,46,0.25); }
[data-theme="light"] .ub-eco-cta-headline { color: #2C2417; }
[data-theme="light"] .ub-eco-cta-sub { color: rgba(44,36,23,0.75); }
[data-theme="light"] .ub-eco-cta-secondary { color: rgba(44,36,23,0.75); }
[data-theme="light"] .ub-eco-cta-secondary:hover { color: #C8912E; }
[data-theme="light"] .ub-eco-bottom { border-top-color: rgba(44,36,23,0.1); }
/* Estate design pass (Aug 11 2026): the 0.6-alpha gold measured 2.59-2.60:1
   (needs 4.5:1). Solid (no alpha) proven amber instead of chasing an alpha
   value - alpha over a light bg only gets LESS accessible, never more. */
[data-theme="light"] .ub-eco-bismillah { color: #B45309; }
/* Estate design pass (Aug 11 2026): 0.45 measured 2.68:1 (needs 4.5:1, real -
   this is the "© 2009-2026 CE / 1447 AH" copyright + Hijri year line). */
[data-theme="light"] .ub-eco-meta { color: rgba(44,36,23,0.7); }
/* Estate design pass (Aug 11 2026): the 0.65-alpha gold measured 2.59-2.61:1
   (needs 4.5:1, real - verified by rendered-pixel sample). Solid proven amber. */
[data-theme="light"] .ub-eco-meta a { color: #B45309; }
[data-theme="light"] .ub-eco-meta a:hover { color: #E8C252; }

/* May 14 (Mehek #10): ecosystem context blurb in footer CTA column. */
.ub-eco-about-blurb {
    margin-top: 1rem;
    font-size: 0.75rem;
    color: var(--buzz-text-dim);
    line-height: 1.5;
    border-top: 1px solid rgba(26, 39, 68, 0.4);
    padding-top: 0.75rem;
}
.ub-eco-about-link {
    color: var(--buzz-teal);
    text-decoration: none;
    transition: opacity 0.2s ease;
}
.ub-eco-about-link:hover { opacity: 0.8; }
[data-theme="light"] .ub-eco-about-blurb { color: #8a7146; border-top-color: rgba(196,162,101,0.25); }
[data-theme="light"] .ub-eco-about-link { color: var(--buzz-teal); }

/* ===== BACK LINK ===== */
.back-link {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    font-size: 0.8125rem;
    color: var(--buzz-text-muted);
    margin-bottom: 1.25rem;
    transition: color 0.2s ease;
}
.back-link:hover { color: var(--buzz-gold); }
.back-link svg { width: 16px; height: 16px; }

/* ===== TOAST / NOTIFICATION ===== */
.buzz-toast {
    position: fixed;
    bottom: 84px;
    left: 50%;
    transform: translateX(-50%) translateY(20px);
    background: rgba(15, 26, 51, 0.95);
    backdrop-filter: blur(16px);
    border: 1px solid rgba(223, 160, 50, 0.25);
    border-radius: var(--buzz-radius-pill);
    padding: 10px 20px;
    color: var(--buzz-gold);
    font-size: 0.8125rem;
    font-weight: 500;
    z-index: 300;
    opacity: 0;
    transition: all 0.35s var(--buzz-ease);
    pointer-events: none;
    white-space: nowrap;
}
.buzz-toast.show {
    opacity: 1;
    transform: translateX(-50%) translateY(0);
}

/* ===== RESPONSIVE ===== */
@media (min-width: 768px) {
    /* May 14 (Mehek #1): reduce desktop hero top padding — promo+ad+header
       already consume ~150px before the hero. 1.25rem top is enough breathing room. */
    .hero-section {
        padding: 1.25rem 1rem 2rem;
    }
    .card-content {
        padding: 0.875rem 1rem;
    }
    .card-thumb {
        width: 100px;
        min-height: 100px;
        margin: 0.625rem 0.625rem 0.625rem 0;
    }
    .vote-col {
        padding: 0.625rem 0.6rem;
        min-width: 60px;
    }
}

@media (max-width: 480px) {
    .buzz-header-inner { height: 48px; }
    .buzz-tagline { display: none; }
    .buzz-district-badge { display: none; }
    .card-thumb {
        width: 64px;
        min-height: 64px;
    }
    .vote-col {
        min-width: 56px;
        padding: 0.5rem 0.375rem;
    }
    .card-content { padding: 0.625rem 0.5rem; }
    .card-title { font-size: 0.875rem; }
    .hero-section {
        padding: 2rem 1rem 1.5rem;
    }
    .hero-cta {
        padding: 12px 24px;
        font-size: 0.875rem;
        width: 100%;
        justify-content: center;
        max-width: 280px;
    }
}

/* ===== Mobile audit (Abdullah May 9) =====
   Items 2/3/5/6: condense top banner to single line; hide tagline + district
   badge across the whole mobile range (was 480-only, leaked into 481-768);
   give the hero proper full-width breathing room; bleed the filter pill nav
   to viewport edges so the rightmost pill is reachable instead of clipped. */
@media (max-width: 768px) {
    /* Item 3: kill the long tagline + district badge across all mobile sizes
       (was only hidden ≤480, leaked into the 481-767 cramped tablet range). */
    .buzz-tagline { display: none; }
    .buzz-district-badge { display: none; }

    /* Item 2/3/4: slim banner to ~44px, prevent text truncation on mobile.
       May 14 (Mehek): wrap the text span instead of ellipsis-truncating it —
       the old ellipsis approach cut off at "Y..." which looks broken. Use a
       shorter message (text set in HTML) that fits in 2 lines max at 12px. */
    /* A-grade iter-4 (Jun 18): the mobile banner rendered at ~16px text height
       (cramped, near-unreadable). Give it an ergonomic, readable row: larger
       font + vertical padding, and lift the desktop 52px max-height cap so the
       single-line message + 44px dismiss target are not clipped. */
    #umg-supporter-banner {
        font-size: 13px !important;
        padding: 9px 12px !important;
        line-height: 1.35 !important;
        max-height: 60px;
    }
    #umg-supporter-banner > div {
        gap: 8px !important;
        flex-wrap: nowrap !important;
        align-items: center !important;
    }
    /* Hide moon emoji and code block — too wide on mobile */
    #umg-supporter-banner > div > span:first-of-type {
        display: none !important;
    }
    #umg-supporter-banner code {
        display: none !important;
    }
    /* Let the text shrink gracefully — no ellipsis, allow wrapping to 2 lines.
       Jun 23 (Suhaib/Mehek audit — "Upgrade to Ummah One overlaps / button cut
       off on mobile"): the .umg-banner-text span carries INLINE
       white-space:nowrap;overflow:hidden;text-overflow:ellipsis, which a plain
       stylesheet rule cannot beat → the text stayed nowrap, ran 393px wide on a
       390px screen, and shoved the "Become a member" CTA off the right edge.
       Force-override the inline declarations so the copy wraps and the CTA stays
       on-screen. */
    #umg-supporter-banner > div > span:nth-of-type(2) {
        flex: 1 1 auto;
        min-width: 0;
        white-space: normal !important;
        overflow: visible !important;
        text-overflow: clip !important;
        line-height: 1.3;
    }
    #umg-supporter-banner a[href] {
        flex-shrink: 0;
        font-size: 12px !important;
        padding: 7px 11px !important;
        white-space: nowrap;
    }
    /* Dismiss button keeps the 44×44 tap target on mobile too (WCAG 2.5.5);
       negative margins keep it from inflating the banner row. */
    #umg-supporter-banner button.umg-banner-dismiss {
        flex-shrink: 0;
        min-width: 44px;
        min-height: 44px;
        margin: -6px -6px -6px 0 !important;
        padding: 0 !important;
    }

    /* Item 6: filter pills must reach to the screen edges so users can scroll
       to the last pill without it being clipped under the parent's max-width.
       Negative margin punches through the 1rem layout padding; padding inside
       restores a touchable inset but lets the row scroll edge-to-edge. */
    .source-pills {
        margin-left: -1rem;
        margin-right: -1rem;
        padding-left: 1rem;
        padding-right: 1rem;
        max-width: none;
        justify-content: flex-start;
    }
    /* Subtle gradient edges hint that there's more content to scroll. */
    .source-pills::after {
        content: '';
        position: sticky;
        right: 0;
        flex: 0 0 12px;
        align-self: stretch;
        pointer-events: none;
    }
}

/* Item 5: hero polish on the narrowest phones (Galaxy S8 / iPhone SE).
   May 14 (Mehek #1): further reduce top padding on mobile — banner+header already
   compress the fold, extra whitespace pushes the feed below the fold. */
@media (max-width: 480px) {
    .hero-section {
        padding: 0.875rem 1rem 1.25rem;
        margin: 0 -0.5rem;
    }
    .hero-title {
        font-size: clamp(1.55rem, 7.5vw, 2rem);
        padding: 0 0.25rem;
    }
    .hero-sub {
        font-size: 0.9375rem;
        padding: 0 0.5rem;
        margin-bottom: 1.25rem;
        /* CLS fix (Aug 11 estate design pass, round 2 — QA F5): with the fallback
           font this line measures 2 lines / 45px at this width; with Outfit it
           fits 1 line / 23px. The Outfit link is now display=optional (see
           index.html), which commits a pageview to ONE font with no later swap —
           but that means a fallback-committed pageview needs the TALLER 2-line
           box from first paint, not just as a transient pre-swap state. Flooring
           at the worst case keeps this element (and the .hero-cta/.hero-stats
           positions below it) identical no matter which font won the race. 46px
           = 45px measured + 1px safety margin, never under the real value. Does
           not touch the Outfit-vs-Amiri hero-font CHOICE — that stays a live,
           untouched Tab ruling; this only floors a box height. */
        min-height: 46px;
    }
    /* Item 4 reinforcement: ensure the auth-block buttons in the right cluster
       never wrap or get hidden on the narrowest viewports. Both Sign In + the
       theme toggle are present in .buzz-header-auth — keep them tight. */
    .buzz-header-auth { gap: 0.5rem; }
    .buzz-btn-signin {
        padding: 6px 12px;
        font-size: 0.75rem;
    }
    .buzz-btn-signin svg { width: 14px; height: 14px; }
}

/* Card-clickable affordance (Abdullah audit Item 7). The whole .buzz-card now
   acts as a link — keep the existing internal interactive elements (vote
   column, action buttons, byline link, save heart) usable via @click.stop
   on each, but make the card itself feel tappable. */
.buzz-card-clickable { cursor: pointer; }
.buzz-card-clickable:focus-visible {
    outline: 2px solid var(--buzz-gold);
    outline-offset: 2px;
}

/* ===== SIDEBAR LINKS ===== */
.sidebar-link {
    font-size: 0.8125rem;
    color: var(--buzz-teal);
    transition: opacity 0.2s ease, color 0.2s ease;
    text-decoration: none;
}
.sidebar-link:hover {
    opacity: 0.8;
    color: var(--buzz-teal-dark);
}

/* ===== SKELETON LOADING ===== */
.skeleton-card {
    display: flex;
    align-items: stretch;
    background: var(--buzz-card-bg);
    border: 1px solid var(--buzz-card-border);
    border-radius: var(--buzz-radius);
    margin-bottom: 0.75rem;
    overflow: hidden;
    padding: 1rem;
    gap: 0.75rem;
}
.skeleton-line {
    background: linear-gradient(90deg, rgba(26, 39, 68, 0.4) 0%, rgba(26, 39, 68, 0.7) 50%, rgba(26, 39, 68, 0.4) 100%);
    background-size: 200% 100%;
    animation: shimmer 1.8s ease-in-out infinite;
    border-radius: 4px;
}
.skeleton-vote {
    width: 40px;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 6px;
    flex-shrink: 0;
}
.skeleton-vote-arrow {
    width: 18px;
    height: 18px;
    border-radius: 3px;
}
.skeleton-vote-num {
    width: 20px;
    height: 12px;
}
.skeleton-content {
    flex: 1;
    min-width: 0;
    display: flex;
    flex-direction: column;
    gap: 8px;
}
.skeleton-title {
    height: 16px;
    width: 80%;
}
.skeleton-desc {
    height: 12px;
    width: 60%;
}
.skeleton-meta {
    height: 10px;
    width: 40%;
}
@keyframes shimmer {
    0% { background-position: 200% 0; }
    100% { background-position: -200% 0; }
}

/* ===== REDUCED MOTION ===== */
@media (prefers-reduced-motion: reduce) {
    *, *::before, *::after {
        animation-duration: 0.01ms !important;
        animation-iteration-count: 1 !important;
        transition-duration: 0.01ms !important;
    }
    .starfield, .grain, .cursor-glow { display: none !important; }
    .reveal { opacity: 1; transform: none; }
}

/* =================================================================
   LIGHT MODE OVERRIDES
   Stubborn hardcoded dark rgba() values elsewhere in this stylesheet
   are replaced here via `[data-theme="light"] .selector` rules so the
   dark defaults stay intact (zero regression risk). Paired with the
   token overrides at the top of the file.
   Apr 19 — Alisha requested light mode.
   ================================================================= */
[data-theme="light"] {
    /* Readable body text on cream */
    color: var(--buzz-text);
}
[data-theme="light"] body { background: var(--buzz-void); }

/* Scrollbar — cream track, brass thumb */
[data-theme="light"] ::-webkit-scrollbar-track { background: var(--buzz-deep); }
[data-theme="light"] ::-webkit-scrollbar-thumb {
    background: linear-gradient(180deg, var(--buzz-border), var(--buzz-gold));
}

/* Feed & card surfaces */
[data-theme="light"] .buzz-card,
[data-theme="light"] .feed-empty,
[data-theme="light"] .hero-section,
[data-theme="light"] .sidebar-card,
[data-theme="light"] .post-detail-card,
[data-theme="light"] .comment-card,
[data-theme="light"] .comment-login-prompt,
[data-theme="light"] .submit-form,
[data-theme="light"] .profile-card {
    background: var(--buzz-card-bg) !important;
    border-color: var(--buzz-card-border) !important;
}

/* Inputs, textareas */
[data-theme="light"] .buzz-search,
[data-theme="light"] .form-input,
[data-theme="light"] .form-textarea,
[data-theme="light"] .comment-textarea {
    background: var(--buzz-input-bg) !important;
    border-color: var(--buzz-card-border) !important;
    color: var(--buzz-text);
}
[data-theme="light"] .buzz-search::placeholder,
[data-theme="light"] .form-input::placeholder,
[data-theme="light"] .form-textarea::placeholder,
[data-theme="light"] .comment-textarea::placeholder { color: var(--buzz-text-dim); }

/* Category <select> — light theme (Jun 17) */
[data-theme="light"] .form-select {
    background-color: var(--buzz-input-bg) !important;
    border-color: var(--buzz-card-border) !important;
    color: var(--buzz-text);
}
[data-theme="light"] .form-select option {
    background: #FFFFFF;
    color: #1A1A1A;
}

/* Vote column + buttons */
[data-theme="light"] .vote-col,
[data-theme="light"] .vote-btn-detail,
[data-theme="light"] .card-action-btn,
[data-theme="light"] .comment-action-btn,
[data-theme="light"] .buzz-btn-logout {
    color: var(--buzz-text-muted);
}
[data-theme="light"] .vote-btn-detail {
    background: var(--buzz-input-bg);
    border-color: var(--buzz-card-border);
}
[data-theme="light"] .vote-btn-detail.voted,
[data-theme="light"] .vote-col.voted {
    color: var(--buzz-gold);
    /* Voted highlight now lives on the inner upvote box (.vote-arrow/.vote-score),
       not the whole column — keep the column transparent so the box reads clean. */
}

/* Brass-on-brass CTAs need dark text against brass in light mode too.
   BUG-318 (Jun 17): was #FFFFFF on the gold gradient = 2.78:1 (WCAG FAIL).
   Dark ink #060B18 on the brass gradient = 4.85-7.06:1 (passes AA at both
   ends of the C8912E→A6751F gradient), matching the dark-theme .submit-btn
   rule which already uses #060B18. */
[data-theme="light"] .comment-submit-btn,
[data-theme="light"] .submit-btn,
[data-theme="light"] .hero-cta {
    color: #060B18;
}

/* Mobile bottom nav */
[data-theme="light"] .mobile-nav {
    background: rgba(250, 247, 242, 0.95) !important;
    border-top-color: var(--buzz-card-border) !important;
    backdrop-filter: blur(20px);
    -webkit-backdrop-filter: blur(20px);
}
[data-theme="light"] .mobile-nav-item { color: var(--buzz-text-muted); }
[data-theme="light"] .mobile-nav-item.active { color: var(--buzz-gold); }

/* Search clear button */
[data-theme="light"] .buzz-search-clear {
    background: var(--buzz-gold-tint-strong);
    color: var(--buzz-text-muted);
}
[data-theme="light"] .buzz-search-clear:hover {
    background: var(--buzz-gold-glow);
    color: var(--buzz-gold);
}

/* Desktop Submit pill — teal on cream needs darker AA contrast */
[data-theme="light"] .buzz-btn-submit {
    background: rgba(13, 148, 136, 0.12);
    border-color: rgba(13, 148, 136, 0.38);
    color: var(--buzz-teal-dark);
}
[data-theme="light"] .buzz-btn-submit:hover {
    background: rgba(13, 148, 136, 0.2);
    border-color: rgba(13, 148, 136, 0.55);
}

/* Submit-form type toggle (Link / Text picker) — dark navy pill on cream reads broken */
[data-theme="light"] .type-toggle {
    background: var(--buzz-deep) !important;
    border-color: var(--buzz-card-border) !important;
}
[data-theme="light"] .type-toggle-btn { color: var(--buzz-text-muted); }
[data-theme="light"] .type-toggle-btn.active {
    background: var(--buzz-surface) !important;
    color: var(--buzz-gold);
}

/* "Copied!" toast — near-opaque navy reads wrong on cream */
[data-theme="light"] .buzz-toast {
    background: var(--buzz-surface) !important;
    border-color: rgba(200, 145, 46, 0.35) !important;
    color: var(--buzz-gold);
    box-shadow: 0 6px 18px rgba(44, 36, 23, 0.12);
}

/* Vote column needs its own override — the shared cards rule uses card-bg */
[data-theme="light"] .vote-col {
    background: transparent;
    border-right: 1px solid var(--buzz-border);
}

/* Feed divider on light mode — darker warm border */
[data-theme="light"] .buzz-card { border-color: var(--buzz-border) !important; }

/* Source badges + metadata pills */
[data-theme="light"] .domain-badge,
[data-theme="light"] .source-badge,
[data-theme="light"] .text-badge,
[data-theme="light"] .district-badge,
[data-theme="light"] .buzz-district-badge {
    background: var(--buzz-gold-tint-strong) !important;
    color: var(--buzz-text-muted) !important;
    border-color: var(--buzz-card-border) !important;
}

/* Skeleton shimmer: warm version */
[data-theme="light"] .skeleton {
    background: linear-gradient(90deg, rgba(232, 225, 212, 0.35) 0%, rgba(232, 225, 212, 0.7) 50%, rgba(232, 225, 212, 0.35) 100%) !important;
}

/* Gold divider line — tighter contrast on cream */
[data-theme="light"] .gold-line {
    background: linear-gradient(90deg, transparent, rgba(200, 145, 46, 0.5), transparent);
}

/* Theme toggle button itself */
.buzz-theme-toggle {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    /* Estate design pass (Aug 11 2026): 34px -> 44px (kit toggle-button.css
       sizes this control "exactly 44x44px"; harness measured 30x30 on
       mobile, the @media override below). The visible glyph/circle stays
       the same optical weight - only the tap area grows. */
    width: 44px;
    height: 44px;
    padding: 0;
    background: var(--buzz-gold-tint-strong);
    border: 1px solid var(--buzz-card-border);
    border-radius: 50%;
    color: var(--buzz-text-muted);
    cursor: pointer;
    transition: color 0.2s ease, background 0.2s ease, transform 0.2s ease;
    -webkit-tap-highlight-color: transparent;
}
.buzz-theme-toggle:hover {
    color: var(--buzz-gold);
    background: var(--buzz-gold-glow);
    transform: translateY(-1px);
}
.buzz-theme-toggle svg { width: 16px; height: 16px; }
@media (max-width: 480px) {
    .buzz-theme-toggle svg { width: 14px; height: 14px; }
}

/* ===== MAN AD SLOTS ===== */
.ub-ad {
    display: flex;
    justify-content: center;
    align-items: center;
    width: 100%;
    overflow: hidden;
    background: transparent;
}
.ub-ad-728 { display: none; }
@media (min-width: 768px) {
    /* BUG-065 (May 18): trimmed margin 0.75rem→0.25rem to tighten navbar→hero stack.
       Jun 23: column flow (like .ub-ad-300/.ub-ad-320) so the right-aligned
       "Ads by Muslim Ad Network" attribution chip flows BELOW the <ins> instead
       of sitting beside it and getting clipped by overflow:hidden — the chip is
       always-visible per the CLAUDE.md amanah rule. */
    .ub-ad-728 { display: flex; flex-direction: column; align-items: stretch; min-height: 90px; margin: 0.25rem 0; }
}
/* May 5 2026 (Ilma A48): tightened from 1rem to 0.75rem so the post-body→ad→
   comments stack reads as one continuous flow instead of three separated cards.
   Pairs with .comments-section margin tightening in /post/index.php. */
/* Jun 12 2026 (intern-reported): stack the slot vertically so on an EPOM no-fill
   the "Ads by Muslim Ad Network" chip flows BELOW the <ins> instead of centering
   on top of the absolutely-positioned "Upgrade to Ummah One" fallback. Column flow
   (not an absolute chip) keeps the chip clear of a live ad creative too. */
.ub-ad-300 { min-height: 250px; margin: 0.75rem auto; max-width: 300px; position: relative; flex-direction: column; justify-content: flex-start; }
/* House-ad fallback (A-grade polish, Jun 18): a SOLID, finished house creative —
   not a dashed muted "broken/empty" placeholder. Paints whenever EPOM no-fills so
   the 300x250 zone is never an empty beige box (CD post-page item 1). */
.ub-ad-fallback {
    position: absolute;
    inset: 0;
    z-index: 1;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 0.5rem;
    padding: 1.5rem 1.25rem;
    text-align: center;
    text-decoration: none;
    border-radius: 12px;
    background: linear-gradient(140deg, rgba(223,160,50,0.14), rgba(20,184,166,0.06));
    border: 1px solid rgba(223,160,50,0.4);
    color: #6f5a36;
    transition: transform 200ms var(--buzz-ease), box-shadow 200ms ease, border-color 200ms ease;
}
.ub-ad-fallback:hover {
    border-color: rgba(223,160,50,0.7);
    box-shadow: 0 6px 20px rgba(223,160,50,0.18);
    transform: translateY(-1px);
}
.ub-ad-fallback-eyebrow { font-size: 0.625rem; letter-spacing: 0.12em; text-transform: uppercase; font-weight: 700; color: var(--buzz-teal); }
.ub-ad-fallback-title { font-size: 1.25rem; font-weight: 800; color: #5a4824; line-height: 1.15; }
.ub-ad-fallback-meta { font-size: 0.8125rem; line-height: 1.4; color: #7a6030; max-width: 16rem; }
.ub-ad-fallback-cta {
    display: inline-flex;
    align-items: center;
    gap: 0.35rem;
    margin-top: 0.35rem;
    padding: 0.5rem 1rem;
    border-radius: 999px;
    background: linear-gradient(135deg, var(--buzz-gold), var(--buzz-gold-dim));
    color: #060B18;
    font-size: 0.8125rem;
    font-weight: 800;
}
[data-theme="dark"] .ub-ad-fallback {
    background: linear-gradient(140deg, rgba(223,160,50,0.12), rgba(20,184,166,0.05));
    border-color: rgba(223,160,50,0.32);
    color: #d4b87a;
}
[data-theme="dark"] .ub-ad-fallback-title { color: #f0d49a; }
[data-theme="dark"] .ub-ad-fallback-meta { color: #c2a878; }
[data-theme="dark"] .ub-ad-fallback-cta { color: #060B18; }
/* Jun 23 (Suhaib/Mehek audit — "ad attribution chip clipped on mobile / ad zone
   looks empty"): the 320x50 slot was a horizontal flex, so the <ins> (320px) +
   the "Ads by Muslim Ad Network" chip ran wider than a 390px phone and the chip
   was clipped at the right edge by .ub-ad's overflow:hidden. Stack vertically
   (chip BELOW the ad) so the attribution disclosure is always fully visible
   (CLAUDE.md amanah rule) regardless of fill state.
   Aug 25 2026 flagship fix (item 4): that vertical stack still ran edge-to-edge
   (align-items:stretch, no side padding), so the right-aligned chip's text sat
   flush against the true viewport edge at 390px (measured 0px gap live). Added
   1rem side padding, matching .hero-section's own mobile side padding. */
.ub-ad-320 { display: flex; flex-direction: column; align-items: stretch; min-height: 50px; margin: 0.75rem 0; padding: 0 1rem; }
@media (min-width: 768px) {
    .ub-ad-320 { display: none; }
}
[data-theme="light"] .ub-ad { background: transparent; }

/* MAN attribution chip (May 24 — ad-ops audit BUG-180-adjacent).
   Always-visible per CLAUDE.md (never x-show="filled"). A-grade iter-4 (Jun 18):
   it was rendering at ~1.9:1 (opacity 0.55, 10px, dim tan/blue) — technically
   present but near-invisible in both themes. Keep it subordinate to content but
   LEGIBLE: bump to 11px, opacity 0.9, and theme-specific muted colors that clear
   WCAG AA (≥4.5:1) so the "Ads by Muslim Ad Network" disclosure is actually
   readable, not just nominally compliant. */
.man-attr-chip {
    display: block;
    font-size: 0.6875rem;
    color: #8892A4;
    opacity: 0.9;
    text-align: right;
    padding: 0.125rem 0;
    letter-spacing: 0.03em;
}
[data-theme="light"] .man-attr-chip {
    color: #6B5D45;
}
.man-attr-link {
    color: inherit;
    text-decoration: underline;
    text-decoration-color: rgba(136,146,164,0.45);
    text-underline-offset: 2px;
}
[data-theme="light"] .man-attr-link {
    text-decoration-color: rgba(107,93,69,0.45);
}
.man-attr-link:hover { opacity: 1; text-decoration-color: currentColor; }

/* ============================================================
   APR 29 ADDITIONS - Save / Filter / Anon prompt / Byline
   ============================================================ */

/* Source-type filter pills (horizontal scroll on mobile, centered on desktop). */
.source-pills {
    display: flex;
    gap: 8px;
    overflow-x: auto;
    overflow-y: hidden;
    padding: 0 0 12px;
    margin: 0 auto 1.25rem;
    max-width: 680px;
    justify-content: center;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
}
.source-pills::-webkit-scrollbar { display: none; }
/* Feed sort toggle (Suhaib Jun 12 UX) — right-aligned, label + pills, sits
   just above the hero. max-width:none + flex-start override the centered
   .source-pills defaults; smaller bottom margin keeps it tight to the feed. */
.feed-sort {
    max-width: 100%;
    justify-content: flex-end;
    align-items: center;
    gap: 6px;
    margin: 0 0 0.85rem;
    padding-bottom: 4px;
}
/* Throat item 1 (Aug 11 round 3): last gap before the featured card - no
   skeleton, static margin, safe to trim. */
@media (max-width: 768px) {
    .feed-sort { margin-bottom: 0.15rem; }
}
.feed-sort-label {
    font-size: 0.7rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: var(--buzz-ink-soft);
    margin-right: 2px;
    flex: 0 0 auto;
}
.feed-sort .source-pill { padding: 5px 12px; font-size: 0.8125rem; }
.source-pill {
    flex: 0 0 auto;
    display: inline-flex;
    align-items: center;
    /* Estate design pass (Aug 11 2026): min-height 36px -> 44px (WCAG 2.5.5),
       same fix .topic-tab/.format-pill already got in "A-grade iter-4" (Jun 18)
       - this sibling pill (the New/Most Upvoted sort toggle) was missed then.
       Harness: "New" 52x36px, "Most Upvoted" 111x36px. */
    padding: 8px 16px;
    min-height: 44px;
    border: 1px solid rgba(223, 160, 50, 0.25);
    border-radius: 999px;
    background: transparent;
    color: var(--buzz-text-muted);
    font-family: inherit;
    font-size: 0.8125rem;
    font-weight: 600;
    letter-spacing: 0.01em;
    cursor: pointer;
    transition: background 0.18s ease, color 0.18s ease, border-color 0.18s ease;
    white-space: nowrap;
}
.source-pill:hover {
    color: var(--buzz-gold);
    border-color: rgba(223, 160, 50, 0.55);
}
.source-pill.active {
    background: linear-gradient(135deg, rgba(223,160,50,0.18), rgba(223,160,50,0.06));
    color: var(--buzz-gold);
    border-color: var(--buzz-gold);
    box-shadow: 0 0 0 1px rgba(223,160,50,0.25);
}
[data-theme="light"] .source-pill {
    color: #6f5a36;
    border-color: rgba(196,162,101,0.45);
}
[data-theme="light"] .source-pill.active {
    color: #6f5a36;
    background: linear-gradient(135deg, rgba(223,160,50,0.18), rgba(223,160,50,0.04));
}

/* Category pills (May 4 - Suhaib S23). Visually distinct from source-pills:
   slightly smaller, thinner border, blue-grey accent on active to signal
   "different axis" without competing with the gold source-pill row.
   May 14 2026 (Mehek): on mobile collapse both pill rows into one scrollable row
   to reduce double-row cognitive load. .source-pills and .category-pills merge
   into a single horizontal strip on ≤768px via the .filter-pill-row wrapper. */
.category-pills {
    margin: 0.25rem auto 1.25rem;
}
/* May 22, 2026 (Suhaib follow-up — multi-select topic filtering): the topic
   pill row USED to be display:none on mobile, which meant topic filtering was
   simply unavailable below 768px (the "collapse into source row" the May 14
   note describes was never actually wired). Now that topics are multi-select
   and a primary discovery surface, the row stays visible on mobile as its own
   horizontally-scrollable strip (mirroring .source-pills): edge-to-edge so the
   last pill is reachable, tighter top margin to keep the two filter rows
   compact. */
@media (max-width: 768px) {
    .category-pills {
        margin: 0 -1rem 1rem;
        padding-left: 1rem;
        padding-right: 1rem;
        max-width: none;
        justify-content: flex-start;
    }
}
.category-pill {
    padding: 6px 13px !important;
    min-height: 30px !important;
    font-size: 0.75rem !important;
    border-color: rgba(255,255,255,0.12) !important;
    color: rgba(255,255,255,0.55) !important;
}
.category-pill:hover {
    color: rgba(255,255,255,0.9) !important;
    border-color: rgba(201,168,76,0.4) !important;
}
.category-pill.active {
    background: rgba(201,168,76,0.12) !important;
    color: var(--buzz-gold) !important;
    border-color: rgba(201,168,76,0.6) !important;
    box-shadow: 0 0 0 1px rgba(201,168,76,0.18) !important;
}
[data-theme="light"] .category-pill {
    /* BUG-318: #8a7146 on cream = 4.34:1 (just under AA). Darkened to
       #7A6030 = 5.55:1 so inactive topic pills pass WCAG AA. */
    color: #7A6030 !important;
    border-color: rgba(196,162,101,0.3) !important;
}
[data-theme="light"] .category-pill.active {
    color: #6f5a36 !important;
    background: rgba(223,160,50,0.12) !important;
    border-color: rgba(196,162,101,0.7) !important;
}

/* ============================================================
   A-GRADE FILTER IA (Jun 18) — Topic tabs (primary) + Format
   refinement (secondary). Replaces the two stacked .source-pill
   rows the CD flagged as a "double-row UI bug". The two axes
   are now visually + semantically distinct.
   ============================================================ */
/* PRIMARY: Topic tabs — prominent, the main discovery surface for a news feed. */
.topic-tabs {
    display: flex;
    gap: 8px;
    overflow-x: auto;
    overflow-y: hidden;
    padding: 0 0 4px;
    margin: 0 auto 0.85rem;
    max-width: 680px;
    justify-content: center;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
}
.topic-tabs::-webkit-scrollbar { display: none; }
/* Throat item 1 (Aug 11 round 3): static margin, no skeleton, safe to trim. */
@media (max-width: 768px) {
    .topic-tabs { margin-bottom: 0.15rem; }
}
.topic-tab {
    flex: 0 0 auto;
    display: inline-flex;
    align-items: center;
    /* A-grade iter-4 (Jun 18): min-height 40px → 44px (WCAG 2.5.5). */
    padding: 11px 18px;
    min-height: 44px;
    border: 1px solid rgba(223, 160, 50, 0.28);
    border-radius: 999px;
    background: transparent;
    color: var(--buzz-text);
    font-family: inherit;
    font-size: 0.875rem;
    font-weight: 600;
    letter-spacing: 0.01em;
    cursor: pointer;
    transition: background 0.18s ease, color 0.18s ease, border-color 0.18s ease, box-shadow 0.18s ease;
    white-space: nowrap;
    -webkit-tap-highlight-color: transparent;
}
.topic-tab:hover {
    color: var(--buzz-gold);
    border-color: rgba(223, 160, 50, 0.6);
}
.topic-tab:focus-visible {
    outline: 2px solid var(--buzz-gold);
    outline-offset: 2px;
}
.topic-tab.active {
    background: linear-gradient(135deg, rgba(223,160,50,0.22), rgba(223,160,50,0.08));
    color: var(--buzz-gold);
    border-color: var(--buzz-gold);
    box-shadow: 0 0 0 1px rgba(223,160,50,0.3);
}
[data-theme="light"] .topic-tab {
    color: var(--buzz-text);
    border-color: rgba(196,162,101,0.5);
}
[data-theme="light"] .topic-tab.active {
    color: #6f5a36;
    background: linear-gradient(135deg, rgba(223,160,50,0.2), rgba(223,160,50,0.05));
    border-color: var(--buzz-gold);
}

/* Discoverability hint (Aug 11, Tab clarify ruling 7, card jpjSe1E4) - see the
   HTML comment above .topic-tabs for the full "why". Sits inline as the row's
   first flex child so it rides the SAME 44px height as the tab buttons (no
   min-height/height of its own - default flex `stretch` + this span's own
   align-items:center just position the text within that shared height), which
   means it adds no new vertical space and can't push the mobile throat budget
   (.buzz-hero-title) down. Color = --buzz-text-muted, already AA-checked at
   this exact small size two lines down in .format-filter-label (6.26:1 dark /
   7.34:1 light against the page void, both re-verified for this addition). */
.topic-tabs-hint {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    flex: 0 0 auto;
    font-size: 0.7rem;
    font-weight: 600;
    color: var(--buzz-text-muted);
    white-space: nowrap;
    padding-right: 4px;
}
.topic-tabs-hint svg {
    flex-shrink: 0;
    opacity: 0.75;
}

/* SECONDARY: Format refinement — labeled + visibly lighter than the topic tabs
   so it reads as "narrow down", not a second peer tab row. */
.format-filter {
    display: flex;
    align-items: center;
    gap: 7px;
    overflow-x: auto;
    overflow-y: hidden;
    padding: 0 0 12px;
    margin: 0 auto 1.1rem;
    max-width: 680px;
    justify-content: center;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
}
.format-filter::-webkit-scrollbar { display: none; }
/* Throat item 1 (Aug 11 round 3): static margin/padding, no skeleton, safe
   to trim - this row's own bottom padding (12px) plus margin (1.1rem) was
   one of the larger reclaimable gaps in the pre-fold stack. */
@media (max-width: 768px) {
    .format-filter { margin-bottom: 0.2rem; padding-bottom: 2px; }
}
.format-filter-label {
    flex: 0 0 auto;
    font-size: 0.68rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.07em;
    color: var(--buzz-text-muted);
    margin-right: 2px;
}
.format-pill {
    flex: 0 0 auto;
    display: inline-flex;
    align-items: center;
    /* A-grade iter-4 (Jun 18): min-height 30px → 44px (WCAG 2.5.5 target size).
       inline-flex centers the 12px label inside the taller tap target so the
       chip reads compact while the touch box clears 44px. */
    padding: 6px 14px;
    min-height: 44px;
    border: 1px solid rgba(255,255,255,0.12);
    border-radius: 999px;
    background: transparent;
    color: var(--buzz-text-muted);
    font-family: inherit;
    font-size: 0.75rem;
    font-weight: 600;
    cursor: pointer;
    transition: background 0.18s ease, color 0.18s ease, border-color 0.18s ease;
    white-space: nowrap;
    -webkit-tap-highlight-color: transparent;
}
.format-pill:hover {
    color: var(--buzz-text);
    border-color: rgba(223,160,50,0.4);
}
.format-pill:focus-visible {
    outline: 2px solid var(--buzz-gold);
    outline-offset: 2px;
}
/* Teal resolution (A-grade polish iter-2, Jun 18): teal is now a SINGLE
   semantic token reserved for "external / source actions" only (Visit Source,
   Original Creator, source-type badges, ecosystem links). A FILTER SELECTION is
   not an external action — it's the same "active/selected" state as the topic
   tabs + source pills, which are GOLD. So the active Format pill now matches its
   sibling filters in gold instead of reading as a stray teal accent. */
.format-pill.active {
    background: rgba(223,160,50,0.12);
    color: var(--buzz-gold);
    border-color: rgba(223,160,50,0.6);
    box-shadow: 0 0 0 1px rgba(223,160,50,0.18);
}
[data-theme="light"] .format-pill {
    color: #7A6030;
    border-color: rgba(196,162,101,0.3);
}
[data-theme="light"] .format-pill.active {
    background: rgba(223,160,50,0.12);
    color: #6f5a36;
    border-color: rgba(196,162,101,0.7);
}
/* Mobile: each filter row becomes its own edge-to-edge scrollable strip; tap
   targets stay ≥30px (format) / 40px (topic). */
@media (max-width: 768px) {
    .topic-tabs {
        margin: 0 -1rem 0.75rem;
        padding-left: 1rem;
        padding-right: 1rem;
        max-width: none;
        justify-content: flex-start;
    }
    .format-filter {
        margin: 0 -1rem 1rem;
        padding-left: 1rem;
        padding-right: 1rem;
        max-width: none;
        justify-content: flex-start;
    }
}

/* Save button (heart icon). */
.card-action-btn.save-btn { gap: 6px; }
.card-action-btn.save-btn svg {
    width: 16px;
    height: 16px;
    transition: transform 0.18s var(--buzz-ease), color 0.18s ease;
}
.card-action-btn.save-btn:hover svg { color: var(--buzz-gold); }
.card-action-btn.save-btn.saved {
    color: var(--buzz-gold);
}
.card-action-btn.save-btn.saved svg {
    color: var(--buzz-gold);
    transform: scale(1.08);
    filter: drop-shadow(0 0 6px rgba(223,160,50,0.45));
}

/* Header "Saved" link (logged-in only). */
.buzz-saved-link {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 8px 12px;
    min-height: 36px;
    border: 1px solid rgba(223, 160, 50, 0.25);
    border-radius: 8px;
    background: transparent;
    color: var(--buzz-text-muted);
    font-size: 0.8125rem;
    font-weight: 600;
    text-decoration: none;
    transition: color 0.18s ease, border-color 0.18s ease, background 0.18s ease;
}
.buzz-saved-link:hover {
    color: var(--buzz-gold);
    border-color: rgba(223, 160, 50, 0.55);
    background: rgba(223, 160, 50, 0.06);
}
.buzz-saved-link svg { color: var(--buzz-gold); }
@media (max-width: 640px) {
    .buzz-saved-link span { display: none; }
    .buzz-saved-link { padding: 8px; }
}

/* Anonymous sign-in prompt tooltip. */
.anon-prompt {
    position: absolute;
    z-index: 1100;
    transform: translate(-50%, -100%);
    display: inline-flex;
    align-items: center;
    gap: 10px;
    padding: 10px 14px;
    background: linear-gradient(135deg, rgba(20, 26, 45, 0.98), rgba(11, 16, 32, 0.98));
    border: 1px solid rgba(223, 160, 50, 0.45);
    border-radius: 10px;
    color: #f5e9c8;
    font-size: 0.8125rem;
    font-weight: 600;
    box-shadow: 0 14px 38px rgba(0, 0, 0, 0.55), 0 0 0 1px rgba(223,160,50,0.12);
    max-width: 320px;
    pointer-events: auto;
}
.anon-prompt-cta {
    background: linear-gradient(135deg, var(--buzz-gold), #c8902a);
    border: none;
    color: #1a1306;
    padding: 6px 12px;
    border-radius: 6px;
    font-family: inherit;
    font-size: 0.75rem;
    font-weight: 700;
    cursor: pointer;
    transition: filter 0.15s ease;
}
.anon-prompt-cta:hover { filter: brightness(1.1); }
.anon-prompt-close {
    background: none;
    border: none;
    color: rgba(245, 233, 200, 0.55);
    font-size: 1.1rem;
    line-height: 1;
    cursor: pointer;
    padding: 0 4px;
}
.anon-prompt-close:hover { color: var(--buzz-gold); }
[data-theme="light"] .anon-prompt {
    background: linear-gradient(135deg, #2a1f0e, #1a1306);
    color: #f5e9c8;
}

/* Byline link styling for ummah.me-bound real users. */
.meta-author.meta-author-ummahme {
    color: var(--buzz-teal);
    border-bottom: 1px dotted rgba(20, 184, 166, 0.4);
}
.meta-author.meta-author-ummahme:hover {
    color: var(--buzz-gold);
    border-bottom-color: var(--buzz-gold);
}

/* Mobile vote-column tap target hardening (Apr 29) -
   bump 480px-and-down min-width 44 -> 48 to clear Apple/Google 48dp guideline. */
@media (max-width: 480px) {
    .vote-col { min-width: 56px; padding: 0.625rem 0.5rem; }
    .source-pills {
        margin-left: -0.5rem;
        padding-left: 0.5rem;
        padding-right: 0.5rem;
        max-width: none;
        justify-content: flex-start;
    }
}

/* BUG-044 (May 18): pill-count chip rendered inside category-pill in the
   trending sidebar card. Tiny rounded badge that doesn't compete with the label. */
.category-pill-count {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 1.4em;
    margin-left: 6px;
    padding: 0 5px;
    border-radius: 8px;
    font-size: 0.65rem;
    font-weight: 700;
    background: rgba(201, 168, 76, 0.18);
    color: var(--buzz-gold);
}
[data-theme="light"] .category-pill-count {
    background: rgba(223, 160, 50, 0.18);
    color: #6f5a36;
}

/* Top Categories proportion bars (A-grade polish, Jun 18). Real counts only. */
.cat-bars {
    display: flex;
    flex-direction: column;
    gap: 10px;
}
.cat-bar-row {
    display: block;
    text-decoration: none;
    cursor: pointer;
}
.cat-bar-head {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 8px;
    margin-bottom: 5px;
}
.cat-bar-label {
    font-size: 0.8125rem;
    font-weight: 600;
    color: var(--buzz-text);
    transition: color 0.18s ease;
}
.cat-bar-row:hover .cat-bar-label { color: var(--buzz-gold); }
.cat-bar-count {
    font-size: 0.75rem;
    font-weight: 700;
    color: var(--buzz-text-muted);
    font-variant-numeric: tabular-nums;
    flex-shrink: 0;
}
.cat-bar-track {
    height: 6px;
    width: 100%;
    border-radius: 999px;
    background: rgba(255, 255, 255, 0.06);
    overflow: hidden;
}
.cat-bar-fill {
    height: 100%;
    border-radius: 999px;
    background: linear-gradient(90deg, var(--buzz-gold-dim), var(--buzz-gold));
    transition: width 0.5s var(--buzz-ease);
}
.cat-bar-row:hover .cat-bar-fill {
    background: linear-gradient(90deg, var(--buzz-gold), var(--buzz-gold-light));
}
[data-theme="light"] .cat-bar-track { background: rgba(13, 17, 23, 0.07); }

/* Jun 18: graceful empty/sparse state for Top Categories — a muted icon + note
   instead of a near-blank white box when the week's data is sparse or a load was
   throttled. Low-key so it never competes with real content. */
.cat-empty {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 4px 0 2px;
    color: var(--buzz-text-muted);
}
.cat-empty-icon { flex-shrink: 0; opacity: 0.7; }
.cat-empty-text { font-size: 0.8125rem; line-height: 1.35; }

/* BUG-048 (May 18): "Verified Source" inline badge on card-meta strip.
   Small green chip with check icon. Only renders for whitelisted domains. */
.verified-badge {
    display: inline-flex;
    align-items: center;
    gap: 3px;
    padding: 1px 6px 1px 4px;
    border-radius: 999px;
    background: rgba(16, 122, 84, 0.14);
    color: #0d8a5e;
    font-size: 0.65rem;
    font-weight: 600;
    line-height: 1.4;
    letter-spacing: 0.02em;
}
.verified-badge svg {
    width: 10px;
    height: 10px;
    stroke: currentColor;
    fill: none;
    stroke-width: 3;
}
[data-theme="light"] .verified-badge {
    background: rgba(16, 122, 84, 0.10);
    color: #0a7048;
}

/* BUG-043 (May 18): /about explainer page styles — minimal, follows
   the UmmahBuzz light-mode editorial vocabulary. */
body.ub-about-page {
    background: var(--buzz-bg, #FDFBF5);
    color: var(--buzz-ink, #1B1B1B);
    font-family: 'Inter', system-ui, -apple-system, sans-serif;
    margin: 0;
    padding: 0;
    line-height: 1.65;
}
.ub-about-wrap {
    max-width: 720px;
    margin: 0 auto;
    padding: 48px 24px 64px;
}
.ub-about-header { text-align: center; margin-bottom: 40px; }
.ub-about-back {
    display: inline-block;
    color: var(--buzz-gold, #C9A84C);
    text-decoration: none;
    font-size: 13px;
    margin-bottom: 24px;
    letter-spacing: 0.02em;
}
.ub-about-back:hover { text-decoration: underline; }
.ub-about-h1 {
    font-family: 'Playfair Display', Georgia, serif;
    font-weight: 700;
    font-size: 44px;
    line-height: 1.15;
    margin: 0 0 12px;
}
.ub-about-sub { color: #6b6b6b; margin: 0; font-size: 16px; }
.ub-about-section {
    margin-top: 36px;
    padding-top: 24px;
    border-top: 1px solid rgba(0, 0, 0, 0.08);
}
.ub-about-section h2 {
    font-family: 'Playfair Display', Georgia, serif;
    font-size: 24px;
    margin: 0 0 10px;
    color: var(--buzz-gold, #C9A84C);
}
.ub-about-section ul { padding-left: 18px; }
.ub-about-section li { margin-bottom: 6px; }
.ub-about-section code {
    background: rgba(0, 0, 0, 0.05);
    padding: 1px 6px;
    border-radius: 4px;
    font-size: 0.92em;
}
.ub-about-footer {
    margin-top: 48px;
    padding-top: 32px;
    border-top: 1px solid rgba(0, 0, 0, 0.08);
    text-align: center;
}
.ub-about-cta {
    display: inline-block;
    background: var(--buzz-gold, #C9A84C);
    color: #1B1B1B;
    padding: 10px 22px;
    border-radius: 8px;
    text-decoration: none;
    font-weight: 700;
    font-size: 14px;
    letter-spacing: 0.02em;
}
.ub-about-cta:hover { background: #B89638; }
.ub-about-link {
    display: block;
    margin-top: 16px;
    color: #6b6b6b;
    font-size: 13px;
    text-decoration: none;
}
.ub-about-link:hover { text-decoration: underline; }

/* ===== NEWSLETTER CAPTURE (Aug 16 2026 estate-wide rollout, CAPTURE only —
   js/newsletter-capture.js mounts the form into [data-newsletter-mount]).
   Shared across all 4 pages that ship a footer: index.html (.ub-eco-footer,
   dark/light theme-toggled), submit/ + search/ (.buzz-footer, same toggle),
   about.html (.ub-about-footer, ALWAYS light — that page never sets
   data-theme, confirmed by grep: no theme-bootstrap <script> on that page).
   Reuses .form-input (already theme-aware, battle-tested elsewhere on this
   site) for the email field instead of inventing new input styling. ===== */
.ub-nl-mount { position: relative; z-index: 2; }
.ub-eco-footer .ub-nl-mount { margin: 0 0 1.75rem 0; max-width: 640px; }
.buzz-footer .ub-nl-mount { margin: 0 0 1.5rem 0; }
.ub-about-footer .ub-nl-mount { margin: 0 0 1.5rem 0; }

.ub-nl-form { display: flex; flex-direction: column; gap: 0.6rem; }
.ub-nl-intro { display: flex; flex-direction: column; gap: 0.1rem; margin-bottom: 0.15rem; }
.ub-nl-heading { font-weight: 700; font-size: 0.88rem; color: inherit; }
.ub-nl-sub { font-size: 0.74rem; color: var(--buzz-text-dim); line-height: 1.4; }

.ub-nl-row { display: flex; flex-wrap: wrap; gap: 0.5rem; align-items: stretch; }
.ub-nl-email {
    flex: 1 1 200px;
    min-height: 44px;
    box-sizing: border-box;
    font-size: 0.85rem;
}
/* Honeypot — off-screen, not display:none (some bots specifically skip
   display:none/visibility:hidden fields), unreachable by Tab, hidden from
   assistive tech. A real visitor never sees this element exist. */
.ub-nl-honeypot {
    position: absolute;
    left: -9999px;
    width: 1px;
    height: 1px;
    overflow: hidden;
    opacity: 0;
}
.ub-nl-submit {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-height: 44px;
    min-width: 44px;
    box-sizing: border-box;
    padding: 0 1.15rem;
    background: linear-gradient(135deg, #DFA032, #C8912E);
    color: #1a1208;
    font-size: 0.82rem;
    font-weight: 700;
    border: none;
    border-radius: 8px;
    cursor: pointer;
    box-shadow: 0 2px 8px rgba(223,160,50,0.25);
    transition: transform 0.18s ease, box-shadow 0.18s ease, opacity 0.18s ease;
}
.ub-nl-submit:hover { transform: translateY(-1px); box-shadow: 0 4px 14px rgba(223,160,50,0.4); }
.ub-nl-submit:disabled { opacity: 0.65; cursor: default; transform: none; }

.ub-nl-cadence { display: flex; flex-wrap: wrap; gap: 0.25rem 1rem; }
.ub-nl-cadence-label {
    display: inline-flex;
    align-items: center;
    gap: 0.4rem;
    min-height: 44px;
    font-size: 0.76rem;
    color: var(--buzz-text-dim);
    cursor: pointer;
}
.ub-nl-cadence-radio { width: 16px; height: 16px; accent-color: var(--buzz-gold); flex-shrink: 0; }

.ub-nl-status {
    font-size: 0.74rem;
    min-height: 1.3em; /* reserves space so the success/error message doesn't shift layout (CLS) */
    margin: 0.1rem 0 0 0;
    color: var(--buzz-teal);
    line-height: 1.4;
}
.ub-nl-status-error { color: #E8674F; }
[data-theme="light"] .ub-nl-status-error { color: #B3401F; }

/* about.html's footer never toggles theme (confirmed: no data-theme bootstrap
   on that page) — force the light-safe palette directly rather than relying
   on a [data-theme="light"] selector that will never match there. */
.ub-about-footer .ub-nl-heading,
.ub-about-footer .ub-nl-sub,
.ub-about-footer .ub-nl-cadence-label { color: #4A4438; }
.ub-about-footer .ub-nl-email {
    background: rgba(0,0,0,0.03);
    border: 1px solid rgba(0,0,0,0.15);
    color: #1B1B1B;
}
.ub-about-footer .ub-nl-email::placeholder { color: #8a8371; }
.ub-about-footer .ub-nl-status { color: #1a6e4a; }
.ub-about-footer .ub-nl-status-error { color: #B3401F; }

@media (max-width: 480px) {
    .ub-nl-row { flex-direction: column; }
    /* Bug found in live Playwright verification (Aug 16 2026): flex-basis is
       resolved against the MAIN axis, which flex-direction:column just made
       vertical — the 200px meant as a horizontal flex-basis was rendering
       the email input 200px TALL on mobile. Pin it to a real height instead
       of a flex-basis once the axis has flipped. */
    .ub-nl-email, .ub-nl-submit { width: 100%; flex: none; height: 44px; }
}
