/* ============================================================================
   theme-editorial.css — the "green editorial" reskin, the site DEFAULT since
   2026-07 (classic is the opt-out; the pre-paint script in App.razor stamps
   data-theme="editorial" unless the visitor chose "classic").
   Load AFTER app.css. Inert unless <html data-theme="editorial">.
   Palette re-declaration rides app.css's own custom-property plumbing:
   every Bootstrap mapping and component rule reads var(--…), so re-declaring
   the properties here re-themes them all.
   ========================================================================== */

[data-theme="editorial"] {
    /* ---- Palette (same property names app.css declares) — Toasted Sand (2026-07 final) ---- */
    --app-bg: #F8F1E2;
    --surface: #FFFDF6;
    --surface-2: #F0E8D3;
    --surface-2-rgb: 240, 232, 211;
    --ink: #211F1A;
    --ink-rgb: 33, 31, 26;
    --muted: #7C7458;
    --muted-rgb: 124, 116, 88;
    --line: #E2D8BC;
    --line-strong: #C9BC9A;
    --accent: #2E4A3E;
    --accent-rgb: 46, 74, 62;
    --accent-hover: #243B31;
    --accent-hover-rgb: 36, 59, 49;
    --accent-active: #1D3028;
    --accent-contrast: #FFFFFF;
    --success-rgb: 76, 107, 60;
    --info-rgb: 65, 102, 111;
    --warning-rgb: 201, 146, 46;      /* premium gold, was Bootstrap #ffc107 */
    --warning-hover: #B87F24;
    --warning-active: #A6711C;
    --chip-secondary-rgb: 117, 112, 95;

    --radius: 14px;                    /* content cards, the landing's card radius (was .75rem) */
    --radius-sm: 8px;                  /* buttons/inputs (was .5rem) */
    --font-display: "Instrument Sans", "Helvetica Neue", Arial, sans-serif; /* no serif */
    --font-body: "Instrument Sans", "Helvetica Neue", Arial, sans-serif;
    --font-data: "JetBrains Mono", Consolas, monospace;

    /* Cards flip from shadowed to bordered */
    --card-border: var(--line);
    --card-shadow: none;
    --card-shadow-hover: 0 2px 4px rgba(34, 31, 25, .06), 0 12px 26px rgba(34, 31, 25, .1);

    /* Old dark sidebar recolors sanely while it still exists (Phase 0) */
    --topbar-bg: rgba(252, 248, 238, .85);
    --sidebar-bg: #22352C;
    --sidebar-line: rgba(242, 239, 228, .1);
    --sidebar-fg: #F2EFE4;
    --sidebar-muted: #C4D2C6;
    --sidebar-hover: rgba(242, 239, 228, .08);
    --sidebar-active-bg: rgba(242, 239, 228, .14);
    --sidebar-active-fg: #F2EFE4;

    --bt-line: #D4C8A8;

    /* ---- New-theme-only properties ---- */
    --accent-soft: #E4ECE7;
    --accent-soft-ink: #33443B;
    --hero-fg: #F2EFE4;
    --hero-muted: #C4D2C6;
    --gold: #C9922E;
    --gold-soft: #F3E7C8;
    --gold-ink: #6E5210;
    /* Bag-timeline phases (Resting / Ready / Tired, in that order). The names predate the
       three-zone rework: --zone-fresh doubles as a decorative pale green in the gradients
       below, so it keeps its name rather than being renamed to match its phase. */
    --zone-fresh: #C9DECD;
    --zone-peak: #8FBC9E;
    --zone-rested: #DCC26F;
    --radius-tile: 10px;
    --radius-tag: 4px;
    --drawer-shadow: -16px 0 40px rgba(34, 31, 25, .14);
    --ease-drawer: cubic-bezier(.32, .72, .33, 1);
    --dur-drawer: .28s;
}

/* ---- Typography: old rules hardcode Fraunces sizes/weights ---- */
[data-theme="editorial"] h1, [data-theme="editorial"] .h1,
[data-theme="editorial"] h2, [data-theme="editorial"] .h2,
[data-theme="editorial"] h3, [data-theme="editorial"] .h3 {
    font-family: var(--font-body);
    font-weight: 700;
    letter-spacing: -0.02em;
}

[data-theme="editorial"] h1, [data-theme="editorial"] .h1 {
    /* Same scale as the landing page's section headings (its h2 clamp). */
    font-size: clamp(30px, 3.4vw, 36px);
    letter-spacing: -0.03em;
    margin-bottom: 6px;
}
[data-theme="editorial"] h2, [data-theme="editorial"] .h2 { font-size: 19px; letter-spacing: -0.01em; }

/* ---- Cards: bordered, not shadowed (app.css sets box-shadow directly) ---- */
[data-theme="editorial"] .card {
    box-shadow: none;
    border: 1px solid var(--line);
}

[data-theme="editorial"] a.card:hover {
    transform: translateY(-3px);
    box-shadow: var(--card-shadow-hover);
}

/* ---- Buttons: weight + gold text color ---- */
[data-theme="editorial"] .btn { font-weight: 600; }
/* Large CTAs use the landing's .lp-btn metrics. */
[data-theme="editorial"] .btn-lg {
    padding: 13px 26px;
    border-radius: 10px;
    font-size: 15px;
}
/* outline-primary becomes the landing's ghost button: quiet border, surface fill on hover
   instead of Bootstrap's solid accent fill. */
[data-theme="editorial"] .btn-outline-primary {
    --bs-btn-bg: transparent;
    --bs-btn-color: var(--accent);
    --bs-btn-border-color: var(--line-strong);
    --bs-btn-hover-bg: var(--surface);
    --bs-btn-hover-color: var(--accent);
    --bs-btn-hover-border-color: var(--line-strong);
    --bs-btn-active-bg: var(--surface-2);
    --bs-btn-active-color: var(--accent);
    --bs-btn-active-border-color: var(--line-strong);
}
[data-theme="editorial"] .btn-warning {
    --bs-btn-color: #3C2E08;
    --bs-btn-hover-color: #3C2E08;
    --bs-btn-active-color: #3C2E08;
    --bs-btn-disabled-color: #3C2E08;
}
/* The "Try Premium" CTA: a dimensional gold instead of the flat warning fill — a soft
   top-to-bottom gradient, an inset highlight for sheen, a hairline darker-gold edge and a
   gentle gold glow, so it reads as premium next to the plainer CTAs. */
[data-theme="editorial"] .btn-premium {
    background: linear-gradient(180deg, var(--gold), var(--warning-hover));
    border-color: var(--warning-active);
    color: #3C2E08;
    box-shadow: inset 0 1px 0 rgba(255, 255, 255, .32), 0 3px 10px rgba(var(--warning-rgb), .3);
    transition: background .15s ease, box-shadow .15s ease, transform .15s ease;
}
[data-theme="editorial"] .btn-premium:hover {
    background: linear-gradient(180deg, var(--warning-hover), var(--warning-active));
    border-color: var(--warning-active);
    color: #3C2E08;
    box-shadow: inset 0 1px 0 rgba(255, 255, 255, .32), 0 5px 15px rgba(var(--warning-rgb), .4);
    transform: translateY(-1px);
}
[data-theme="editorial"] .btn-premium:active {
    transform: translateY(0);
    box-shadow: inset 0 1px 3px rgba(60, 46, 8, .25);
}
/* Give the cup mark a touch more presence on the button. */
[data-theme="editorial"] .btn-premium .premium-cup { opacity: .9; }
/* outline-secondary becomes the "ghost" button */
[data-theme="editorial"] .btn-outline-secondary {
    --bs-btn-border-color: var(--line);
    --bs-btn-bg: var(--surface);
    --bs-btn-hover-bg: var(--surface-2);
    --bs-btn-hover-border-color: var(--line);
}

/* ---- Badges become uppercase micro-tags ---- */
[data-theme="editorial"] .badge {
    font-size: 10.5px;
    font-weight: 600;
    letter-spacing: .03em;
    text-transform: uppercase;
    padding: 3px 7px;
    border-radius: var(--radius-tag);
}
[data-theme="editorial"] .text-bg-warning,
[data-theme="editorial"] .badge.bg-warning {
    background: var(--gold-soft) !important;
    color: var(--gold-ink) !important;
}
[data-theme="editorial"] .text-bg-success,
[data-theme="editorial"] .text-bg-info {
    background: var(--accent-soft) !important;
    color: var(--accent) !important;
}
[data-theme="editorial"] .text-bg-secondary {
    background: var(--surface-2) !important;
    color: var(--muted) !important;
}

/* ---- Freshness zones: solid tints replace alpha mixes ---- */
[data-theme="editorial"] .bag-timeline-zone-resting { background: var(--zone-fresh); }
[data-theme="editorial"] .bag-timeline-zone-ready { background: var(--zone-peak); }
[data-theme="editorial"] .bag-timeline-zone-tired { background: var(--zone-rested); }
[data-theme="editorial"] .bag-timeline-lock .bi { color: var(--gold-ink); }

/* ---- Facet chips: bigger pill, filter-active state ---- */
[data-theme="editorial"] .facet-chip {
    padding: 6px 14px;
    font-size: 12.5px;
    font-weight: 500;
    color: var(--muted);
}
[data-theme="editorial"] .facet-chip.active {
    background: var(--accent);
    border-color: var(--accent);
    color: #fff;
}

/* Tasting notes on the coffee detail header: paragraph-length text, so a card-radius box
   (a facet-chip pill stretches into a blob around long text). */
[data-theme="editorial"] .ed-notes-box {
    margin-top: 10px;
    padding: 12px 16px;
    background: var(--surface);
    border: 1px solid var(--line);
    border-radius: var(--radius);
    font-size: 13.5px;
    line-height: 1.55;
    color: var(--ink);
}
[data-theme="editorial"] .ed-notes-box .facet-count { color: var(--muted); }

/* ---- Autopilot hero: kill the gradient ---- */
[data-theme="editorial"] .autopilot-hero { background: var(--surface); border: 1px solid var(--line); }

/* ========================================================================
   NEW primitives (no old counterpart; only used by new-theme markup)
   ======================================================================== */

/* Top nav (replaces sidebar in Phase 1) */
[data-theme="editorial"] .topnav {
    height: 60px;
    display: flex;
    align-items: center;
    gap: 26px;
    /* The bar itself spans the viewport; its content stays inside a centered 1320px column
       (matching .editorial-content's box) so the brand and avatar never hug the screen edges. */
    padding: 0 max(40px, calc(50% - 620px));
    background: var(--topbar-bg);
    backdrop-filter: blur(6px);
    border-bottom: 1px solid var(--line);
}
[data-theme="editorial"] .topnav .brand { display: flex; align-items: center; gap: 10px; font-weight: 700; font-size: 15px; letter-spacing: -0.01em; color: var(--ink); margin-right: 10px; text-decoration: none; }
/* The primary links, centered between the brand and the account cluster (the auto margins
   push the cluster flush right; when the links hide on phones this collapses to nothing). */
[data-theme="editorial"] .topnav .nav-center { display: flex; align-items: center; gap: 26px; margin: 0 auto; }
[data-theme="editorial"] .topnav a.nav-link { font-size: 13.5px; font-weight: 500; color: var(--muted); padding: 0; transition: color .15s ease; }
[data-theme="editorial"] .topnav a.nav-link:hover { color: var(--accent); }
[data-theme="editorial"] .topnav a.nav-link.active { color: var(--ink); }
[data-theme="editorial"] .topnav .premium-pill { font-size: 12px; font-weight: 600; color: var(--gold-ink); background: var(--gold-soft); border-radius: 999px; padding: 5px 12px; }
[data-theme="editorial"] .topnav .avatar { width: 28px; height: 28px; border-radius: 50%; background: var(--accent); color: #fff; font: 600 12px/28px var(--font-body); text-align: center; overflow: hidden; }
[data-theme="editorial"] .topnav .avatar img { width: 100%; height: 100%; object-fit: cover; display: block; }
/* Owner-only "view as free/subscriber" preview, a segmented toggle in the bar next to the avatar:
   both options always visible, the active view highlighted (gold). */
[data-theme="editorial"] .topnav .viewas-toggle { display: inline-flex; align-items: center; gap: 2px; background: var(--surface-2); border: 1px solid var(--line); border-radius: 999px; padding: 2px; }
[data-theme="editorial"] .topnav .viewas-seg { font: 600 12px/1 var(--font-body); color: var(--muted); background: transparent; border: none; border-radius: 999px; padding: 4px 10px; cursor: pointer; white-space: nowrap; transition: color .15s ease, background .15s ease; }
[data-theme="editorial"] .topnav .viewas-seg:hover { color: var(--ink); }
[data-theme="editorial"] .topnav .viewas-seg.active { color: var(--gold-ink); background: var(--gold-soft); cursor: default; }

/* Vote pill ("▲ 42") */
[data-theme="editorial"] .vote-pill {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    flex: 0 0 auto;
    font: 600 12px var(--font-body);
    color: var(--accent);
    background: var(--accent-soft);
    border-radius: 999px;
    padding: 5px 10px;
    white-space: nowrap;
}

/* Dashed key/value rows (brew steps, grinders, history) */
[data-theme="editorial"] .step-list .step-row {
    display: flex;
    justify-content: space-between;
    align-items: baseline;
    padding: 8px 0;
    border-bottom: 1px dashed var(--line);
}
[data-theme="editorial"] .step-list .step-row:last-child { border-bottom: none; }
[data-theme="editorial"] .step-list .step-label { color: var(--muted); font-size: 11px; text-transform: uppercase; letter-spacing: .06em; font-weight: 600; }
[data-theme="editorial"] .step-list .step-value { font: 500 12.5px var(--font-data); }

/* Big mono figures ("96.0° bloom · 1:16 ratio") */
[data-theme="editorial"] .big-figures { display: flex; gap: 22px; }
[data-theme="editorial"] .big-figures .fig-value { font: 600 24px var(--font-data); letter-spacing: -0.02em; }
[data-theme="editorial"] .big-figures .fig-label { font: 400 12px var(--font-data); color: var(--muted); margin-top: 2px; }

/* Tinted callout ("Why:", AutoPilot notes) */
[data-theme="editorial"] .callout {
    background: var(--accent-soft);
    color: var(--accent-soft-ink);
    border-radius: var(--radius-sm);
    padding: 10px 12px;
    font-size: 12.5px;
    line-height: 1.5;
}
[data-theme="editorial"] .callout.callout-gold { background: var(--gold-soft); color: var(--gold-ink); }

/* Micro-label eyebrow */
[data-theme="editorial"] .micro-label {
    font: 600 10px var(--font-body);
    letter-spacing: .09em;
    text-transform: uppercase;
    color: var(--muted);
}

/* Drawer (desktop) — a centered dialog/modal; on phones the media query below
   flips it to a bottom sheet. Mount inside a position:relative overflow:hidden stage. */
[data-theme="editorial"] .drawer-scrim {
    position: absolute;
    inset: 0;
    background: rgba(33, 31, 26, .32);
    opacity: 0;
    pointer-events: none;
    transition: opacity .25s ease;
    z-index: 4;
}
[data-theme="editorial"] .drawer-open .drawer-scrim { opacity: 1; pointer-events: auto; }
[data-theme="editorial"] .drawer {
    position: absolute;
    top: 50%; left: 50%;
    width: min(440px, calc(100% - 48px));
    max-height: min(86vh, 760px);
    background: var(--surface);
    border: 1px solid var(--line);
    border-radius: 16px;
    box-shadow: 0 24px 60px rgba(34, 31, 25, .22);
    transform: translate(-50%, -50%) scale(.96);
    opacity: 0;
    visibility: hidden;
    pointer-events: none;
    transition: transform var(--dur-drawer) var(--ease-drawer),
                opacity var(--dur-drawer) var(--ease-drawer),
                visibility 0s linear var(--dur-drawer);
    z-index: 5;
    display: flex;
    flex-direction: column;
    overflow: hidden;
}
[data-theme="editorial"] .drawer-open .drawer {
    transform: translate(-50%, -50%) scale(1);
    opacity: 1;
    visibility: visible;
    pointer-events: auto;
    transition: transform var(--dur-drawer) var(--ease-drawer),
                opacity var(--dur-drawer) var(--ease-drawer);
}
[data-theme="editorial"] .drawer .drawer-head { display: flex; align-items: flex-start; gap: 10px; padding: 20px 22px 0; }
[data-theme="editorial"] .drawer .drawer-body { flex: 1; overflow: auto; padding: 16px 22px 18px; display: flex; flex-direction: column; gap: 16px; }
[data-theme="editorial"] .drawer .drawer-foot { border-top: 1px solid var(--line); padding: 14px 22px; display: flex; gap: 8px; background: #FDFCF9; }
[data-theme="editorial"] .drawer .drawer-close {
    margin-left: auto;
    width: 28px; height: 28px;
    border-radius: 50%;
    border: 1px solid var(--line);
    background: var(--surface);
    color: var(--muted);
    font-size: 12px;
}

/* Bottom sheet (mobile) — same pattern, slides up */
@media (max-width: 767.98px) {
    [data-theme="editorial"] .drawer {
        top: auto; left: 0; right: 0; bottom: 0;
        width: auto;
        max-height: 86%;
        border: none;
        border-radius: 16px 16px 0 0;
        box-shadow: 0 -12px 40px rgba(34, 31, 25, .16);
        /* Reset the desktop modal's fade/scale — the sheet just slides. */
        transform: translateY(105%);
        opacity: 1;
        visibility: visible;
        pointer-events: auto;
        transition: transform var(--dur-drawer) var(--ease-drawer);
    }
    [data-theme="editorial"] .drawer-open .drawer { transform: translateY(0); }
    [data-theme="editorial"] .drawer::before {
        content: "";
        display: block;
        width: 36px; height: 4px;
        border-radius: 2px;
        background: var(--line-strong);
        margin: 8px auto 0;
    }
}

/* ========================================================================
   App additions (Phase 1) — Blazor-side structure for the primitives above:
   the editorial page shell, topnav responsive behavior + avatar menu, the
   mobile tab bar, the catalog rows and the viewport-fixed drawer host.
   ======================================================================== */

/* Page shell: topnav on top, content scrolls with the page. */
[data-theme="editorial"] .editorial-page { min-height: 100vh; display: flex; flex-direction: column; }
[data-theme="editorial"] .editorial-page > main { flex: 1; display: flex; flex-direction: column; }
[data-theme="editorial"] .editorial-content { flex: 1; padding: 30px 40px; max-width: 1320px; width: 100%; margin: 0 auto; box-sizing: border-box; }

/* The home hero follows the landing page's language: open on the page background instead of
   a bg-light panel (!important because Bootstrap's bg-light/p-* utilities are !important),
   landing-scale display type, lp-btn CTA metrics, and the feature bullets dressed as the
   landing's bordered surface cards. */
[data-theme="editorial"] .ed-hero {
    background: transparent !important;
    padding: 10px 0 4px !important;
}
@media (min-width: 992px) {
    [data-theme="editorial"] .ed-hero { padding: 22px 0 10px !important; }
    /* Feature tiles keep their natural height instead of all matching the tallest
       (grid-auto-rows: 1fr in app.css). */
    [data-theme="editorial"] .ed-hero .hero-features { grid-auto-rows: auto; }
}
[data-theme="editorial"] .ed-hero h1 {
    /* The landing's hero type, a notch smaller — this headline runs longer than its 15ch. */
    font: 700 clamp(30px, 3.6vw, 40px)/1.08 var(--font-body);
    letter-spacing: -.03em;
}
[data-theme="editorial"] .ed-hero .lead {
    /* The landing's .sub */
    font: 400 17px/1.5 var(--font-body);
    max-width: 52ch;
    margin-bottom: 1rem;
}
[data-theme="editorial"] .ed-hero .hero-features { gap: 8px; }
[data-theme="editorial"] .ed-hero .hero-feature {
    /* The landing's .feat card, at bullet-list density. */
    background: var(--surface);
    border: 1px solid var(--line);
    border-radius: 12px;
    padding: 10px 14px;
}
/* Tighter feature-card typography so five tiles stack in less height. */
[data-theme="editorial"] .ed-hero .hero-feature .small { line-height: 1.35; }

/* Phones: the four CTA buttons stack full-width (the flex-wrap row leaves ragged halves). */
@media (max-width: 575.98px) {
    [data-theme="editorial"] .ed-hero .btn { width: 100%; }
}

[data-theme="editorial"] .topnav { position: sticky; top: 0; z-index: 3; }
[data-theme="editorial"] .topnav .brand:hover { color: var(--ink); }
[data-theme="editorial"] .topnav .premium-pill { text-decoration: none; }
[data-theme="editorial"] .topnav .premium-pill:hover { background: var(--gold); color: #3C2E08; }
[data-theme="editorial"] .topnav .avatar { border: none; cursor: pointer; padding: 0; }

/* Avatar menu: a small dropdown card under the topnav. It renders as a SIBLING of the
   .topnav bar (the bar's backdrop-filter would otherwise become the containing block for
   these fixed elements and shrink the click-away scrim to the bar's 60px). */
[data-theme="editorial"] .avatar-menu-scrim {
    position: fixed;
    inset: 0;
    z-index: 4;
    background: transparent;
    border: none;
    padding: 0;
    cursor: default;
}
[data-theme="editorial"] .avatar-menu {
    position: fixed;
    top: 66px;
    right: max(16px, calc(50% - 620px)); /* under the avatar, which sits inside the 1320px column */
    width: 240px;
    background: var(--surface);
    border: 1px solid var(--line);
    border-radius: var(--radius);
    box-shadow: var(--card-shadow-hover);
    padding: 6px;
    z-index: 5;
    /* The menu can grow past the viewport (Owner sees extra Admin items) — cap it and scroll. */
    max-height: calc(100vh - 66px - 16px);
    overflow-y: auto;
    overscroll-behavior: contain;
}
[data-theme="editorial"] .avatar-menu .menu-user { padding: 8px 10px 6px; font-size: 12px; color: var(--muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* Section headers over each menu group (replaced most of the old hr dividers). */
[data-theme="editorial"] .avatar-menu .menu-header {
    padding: 10px 10px 3px;
    font-size: 10.5px;
    font-weight: 600;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: var(--muted);
}
[data-theme="editorial"] .avatar-menu a.menu-item,
[data-theme="editorial"] .avatar-menu button.menu-item {
    display: flex; align-items: center; gap: 10px;
    width: 100%;
    padding: 8px 10px;
    border: none; background: none; cursor: pointer;
    border-radius: var(--radius-sm);
    font-size: 13.5px; font-weight: 500; text-align: left;
    color: var(--ink); text-decoration: none;
}
[data-theme="editorial"] .avatar-menu .menu-item:hover { background: var(--surface-2); color: var(--ink); }
[data-theme="editorial"] .avatar-menu .menu-item .bi { width: 1.1rem; text-align: center; color: var(--muted); }
[data-theme="editorial"] .avatar-menu .menu-divider { border: 0; border-top: 1px solid var(--line); margin: 6px 4px; }
[data-theme="editorial"] .avatar-menu .menu-legal { padding: 6px 10px 8px; font-size: 11.5px; color: var(--muted); display: flex; gap: 6px; }
[data-theme="editorial"] .avatar-menu .menu-legal a { color: var(--muted); text-decoration: none; }
[data-theme="editorial"] .avatar-menu .menu-legal a:hover { color: var(--accent); text-decoration: underline; }

/* Mobile tab bar (Catalog / Read a bag / My Aiden / Stats); hidden on desktop. */
[data-theme="editorial"] .tabbar { display: none; }
@media (max-width: 767.98px) {
    /* The topnav compresses into the 52px mobile header: brand + avatar, links live in the tab bar. */
    [data-theme="editorial"] .topnav { height: 52px; padding: 0 16px; gap: 12px; }
    [data-theme="editorial"] .topnav .brand { font-size: 16px; letter-spacing: -0.02em; }
    [data-theme="editorial"] .topnav a.nav-link { display: none; }
    /* Tight phone bar: keep the segmented toggle readable but compact. */
    [data-theme="editorial"] .topnav .viewas-seg { padding: 4px 8px; }
    [data-theme="editorial"] .avatar-menu { top: 58px; right: 10px; max-height: calc(100vh - 58px - 12px); }

    [data-theme="editorial"] .editorial-content { padding: 18px 16px; }
    /* The fixed tab bar only renders signed in; reserve space for it only then. */
    [data-theme="editorial"] .editorial-page:has(.tabbar) .editorial-content { padding-bottom: calc(76px + env(safe-area-inset-bottom)); }

    [data-theme="editorial"] .tabbar {
        display: flex;
        position: fixed;
        left: 0; right: 0; bottom: 0;
        z-index: 3;
        background: var(--topbar-bg);
        backdrop-filter: blur(6px);
        border-top: 1px solid var(--line);
        padding-bottom: calc(6px + env(safe-area-inset-bottom));
    }
    [data-theme="editorial"] .tabbar a {
        flex: 1;
        display: flex; flex-direction: column; align-items: center; gap: 3px;
        padding: 9px 0 4px;
        color: var(--muted);
        font: 500 10px var(--font-body);
        text-decoration: none;
    }
    [data-theme="editorial"] .tabbar a .bi { font-size: 19px; line-height: 1; }
    [data-theme="editorial"] .tabbar a.active { color: var(--accent); font-weight: 600; }

    /* The fixed tab bar would cover the site footer at the end of the page. */
    [data-theme="editorial"] .editorial-page:has(.tabbar) .site-footer { margin-bottom: calc(64px + env(safe-area-inset-bottom)); }

    /* The marketing landing renders the shared TopNav (guest tab bar included) outside the
       .editorial-page shell — reserve space for the fixed bar there too. */
    [data-theme="editorial"] .landing { padding-bottom: calc(64px + env(safe-area-inset-bottom)); }
}

/* Filter chips render as buttons in the Blazor catalog. */
[data-theme="editorial"] button.facet-chip { cursor: pointer; }

/* Stock coffee-photo placeholder: match the catalog thumbnail's soft gradient + accent glyph. */
[data-theme="editorial"] .coffee-photo-ph {
    background: linear-gradient(135deg, var(--accent-soft), var(--zone-fresh));
    color: var(--accent);
}
/* Size class for the coffee-detail header placeholder (mirrors .ed-photo's responsive box). */
[data-theme="editorial"] .ed-photo-ph { width: 132px; height: 132px; flex: 0 0 132px; border-radius: 12px; }
@media (max-width: 767.98px) {
    [data-theme="editorial"] .ed-photo-ph { width: 96px; height: 96px; flex-basis: 96px; }
}

/* Anchor offset for scroll-to-catalog: the sticky topnav (60px, 52px on phones) would
   otherwise cover the heading when it lands at the top of the viewport. */
[data-theme="editorial"] #catalog { scroll-margin-top: 76px; }
@media (max-width: 767.98px) {
    [data-theme="editorial"] #catalog { scroll-margin-top: 66px; }
}

/* Catalog rows: editorial hairline list (not cards). */
[data-theme="editorial"] .cat-row {
    display: flex; align-items: center; gap: 22px;
    padding: 18px 14px;
    margin: 0 -14px;
    border-bottom: 1px solid var(--line);
    cursor: pointer;
}
[data-theme="editorial"] .cat-row:last-of-type { border-bottom: none; }
[data-theme="editorial"] .cat-row.selected { background: var(--accent-soft); border-radius: 10px; }
/* Photoless coffees get the design's placeholder: a soft green gradient tile
   with the image glyph, instead of a flat swatch. */
[data-theme="editorial"] .cat-row .cat-thumb {
    width: 56px; height: 56px; flex: 0 0 56px;
    border-radius: 10px;
    overflow: hidden;
    display: flex; align-items: center; justify-content: center;
    background: linear-gradient(135deg, var(--accent-soft), var(--zone-fresh));
}
[data-theme="editorial"] .cat-row .cat-thumb .bi { font-size: 20px; color: var(--accent); opacity: .45; }
[data-theme="editorial"] .cat-row .cat-thumb img { width: 100%; height: 100%; object-fit: cover; cursor: zoom-in; }
[data-theme="editorial"] .cat-row .cat-title { font-size: 16.5px; font-weight: 600; letter-spacing: -0.01em; }
[data-theme="editorial"] .cat-row .cat-meta { color: var(--muted); font-size: 13px; margin-top: 3px; }
[data-theme="editorial"] .cat-row .cat-figures { text-align: right; flex: 0 0 auto; }
[data-theme="editorial"] .cat-row .cat-temp { font: 600 22px var(--font-data); letter-spacing: -0.02em; }
[data-theme="editorial"] .cat-row .cat-sub { font: 400 12px var(--font-data); color: var(--muted); margin-top: 2px; }
@media (max-width: 767.98px) {
    [data-theme="editorial"] .cat-row { gap: 12px; padding: 14px 10px; margin: 0 -10px; }
    [data-theme="editorial"] .cat-row .cat-thumb { width: 48px; height: 48px; flex-basis: 48px; }
    [data-theme="editorial"] .cat-row .cat-temp { font-size: 18px; }
}

/* List / grid layout toggle. Two segmented buttons; the active layout is filled. */
[data-theme="editorial"] .cat-view-toggle {
    display: inline-flex;
    flex: 0 0 auto;
    border: 1px solid var(--line);
    border-radius: 9px;
    overflow: hidden;
    background: var(--surface);
}
[data-theme="editorial"] .cat-view-btn {
    display: inline-flex; align-items: center; justify-content: center;
    width: 40px; height: 34px;
    border: none; background: transparent;
    color: var(--muted); font-size: 15px;
    cursor: pointer;
    transition: background .12s ease, color .12s ease;
}
[data-theme="editorial"] .cat-view-btn + .cat-view-btn { border-left: 1px solid var(--line); }
[data-theme="editorial"] .cat-view-btn:hover { color: var(--ink); }
[data-theme="editorial"] .cat-view-btn.active { background: var(--accent-soft); color: var(--accent); }

/* Card grid: same coffees as the list, laid out as tiles. Auto-fill so the count
   adapts to the viewport; single column on the narrowest phones. */
[data-theme="editorial"] .cat-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
    gap: 18px;
}
[data-theme="editorial"] .cat-card {
    display: flex; flex-direction: column;
    border: 1px solid var(--line);
    border-radius: 12px;
    overflow: hidden;
    background: var(--surface);
    cursor: pointer;
    transition: border-color .12s ease, box-shadow .12s ease, transform .12s ease;
}
[data-theme="editorial"] .cat-card:hover {
    border-color: var(--accent);
    box-shadow: 0 6px 20px rgba(0, 0, 0, .06);
    transform: translateY(-2px);
}
[data-theme="editorial"] .cat-card.selected { border-color: var(--accent); background: var(--accent-soft); }
[data-theme="editorial"] .cat-card-thumb {
    position: relative;
    aspect-ratio: 3 / 2;
    display: flex; align-items: center; justify-content: center;
    background: linear-gradient(135deg, var(--accent-soft), var(--zone-fresh));
}
[data-theme="editorial"] .cat-card-thumb img { width: 100%; height: 100%; object-fit: cover; cursor: zoom-in; }
[data-theme="editorial"] .cat-card-thumb .bi { font-size: 30px; color: var(--accent); opacity: .4; }
[data-theme="editorial"] .cat-card-badge {
    position: absolute; top: 8px; left: 8px;
    font-size: 11px;
    display: inline-flex;
    align-items: center;
    gap: 4px;
}
[data-theme="editorial"] .cat-card-badge .bi { font-size: 12px; line-height: 1; }
[data-theme="editorial"] .cat-card-admin { position: absolute; top: 8px; right: 8px; }
[data-theme="editorial"] .cat-card-body { padding: 14px; flex: 1 1 auto; }
[data-theme="editorial"] .cat-card .cat-title { font-size: 16px; font-weight: 600; letter-spacing: -0.01em; }
[data-theme="editorial"] .cat-card .cat-meta { color: var(--muted); font-size: 13px; margin-top: 3px; }
[data-theme="editorial"] .cat-card .cat-sub { font: 400 12px var(--font-data); color: var(--muted); }
@media (max-width: 419.98px) {
    [data-theme="editorial"] .cat-grid { grid-template-columns: 1fr 1fr; gap: 12px; }
}

/* Coffee detail: header photo, fact chips, two-column body (profiles + freshness
   sidebar) and the interactive profile cards. */
[data-theme="editorial"] .ed-photo {
    width: 132px; height: 132px;
    flex: 0 0 132px;
    border-radius: 12px;
    object-fit: cover;
    background: var(--accent-soft);
    cursor: zoom-in;
}
[data-theme="editorial"] .ed-cols { display: flex; gap: 14px; align-items: flex-start; }
[data-theme="editorial"] .ed-cols .ed-main { flex: 1.4; min-width: 0; }
[data-theme="editorial"] .ed-cols .ed-side { flex: 1; min-width: 0; position: sticky; top: 74px; }
@media (max-width: 767.98px) {
    [data-theme="editorial"] .ed-cols { flex-direction: column; align-items: stretch; }
    [data-theme="editorial"] .ed-cols .ed-side { position: static; }
    [data-theme="editorial"] .ed-photo { width: 96px; height: 96px; flex-basis: 96px; }
}
[data-theme="editorial"] .ed-profile-card { cursor: pointer; transition: box-shadow .15s ease, border-color .15s ease; }
[data-theme="editorial"] .ed-profile-card:hover { box-shadow: var(--card-shadow-hover); }
[data-theme="editorial"] .ed-profile-card.selected { border-color: var(--accent); }
/* Keyboard focus gets a visible ring (the card is role=button tabindex=0). */
[data-theme="editorial"] .ed-profile-card:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
[data-theme="editorial"] .ed-profile-name { font-size: 15px; font-weight: 600; letter-spacing: -0.01em; display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }

/* Tap affordances: an explicit hint line + a disclosure chevron. Hover raised only a
   box-shadow, which touch devices never show — so the drawer (send, dial in, compare)
   went undiscovered. The chevron reads as "opens" without hover; the hint says what. */
[data-theme="editorial"] .ed-profile-hint {
    font-size: 12px; font-weight: 600; color: var(--accent);
    margin-top: 5px; letter-spacing: .01em;
}
/* Per-grinder dial settings on a collapsed profile card. Deliberately tighter than the expanded
   card's step-list (8px padding + dashed rules per row): a premium user with three grinders would
   otherwise add ~70px of chrome to every card, and a coffee can carry several community recipes.
   Rules dropped, padding minimal — the label/value pairing alone reads as a list at this size.

   A shared two-column grid, NOT the step-list's space-between: the card is full-width, so
   space-between stranded the setting at the far right edge, half a card away from the grinder it
   belongs to. max-content sizes the name column to the longest name and no wider, which keeps each
   setting next to its own grinder while still lining the settings up in one scannable column.
   The rows are display:contents so every card row shares one grid — hence the tooltip lives on the
   spans in the markup, since a contents box has no hover target of its own. */
[data-theme="editorial"] .ed-profile-grind {
    margin-top: 5px;
    display: grid;
    grid-template-columns: minmax(0, max-content) auto;
    column-gap: 14px;
    align-items: baseline;
}
[data-theme="editorial"] .ed-profile-grind .step-row { display: contents; }
[data-theme="editorial"] .ed-profile-grind .step-label { font-size: 10px; letter-spacing: .05em; padding: 1px 0; }
[data-theme="editorial"] .ed-profile-grind .step-value {
    font-size: 12px; white-space: nowrap; text-align: left; padding: 1px 0;
}
[data-theme="editorial"] .ed-profile-chevron {
    flex: 0 0 auto; color: var(--muted); font-size: 18px; line-height: 1;
    transition: transform .15s ease, color .15s ease;
}
[data-theme="editorial"] .ed-profile-card:hover .ed-profile-chevron,
[data-theme="editorial"] .ed-profile-card:focus-visible .ed-profile-chevron,
[data-theme="editorial"] .ed-profile-card:active .ed-profile-chevron { transform: translateX(3px); color: var(--accent); }
[data-theme="editorial"] .ed-profile-card.selected .ed-profile-chevron { color: var(--accent); }

/* Card headings read as micro-label eyebrows across the app (the design's cards
   all carry uppercase 10px eyebrows instead of heading-sized titles). */
[data-theme="editorial"] .card > .card-header {
    background: none;
    border-bottom: none;
    padding-bottom: 0;
}
[data-theme="editorial"] .card > .card-header,
[data-theme="editorial"] .card h2.h5,
[data-theme="editorial"] .card h2.h6,
[data-theme="editorial"] .card h3.h6 {
    font: 600 10px var(--font-body);
    letter-spacing: .09em;
    text-transform: uppercase;
    color: var(--muted);
}
/* Opt-out for card headings that are real titles (a device's name), not section eyebrows. */
[data-theme="editorial"] .card h2.ed-title {
    font: 700 17px var(--font-body);
    letter-spacing: -0.01em;
    text-transform: none;
    color: var(--ink);
}

/* Read-a-bag 1-2-3 flow: numbered step eyebrows + the dashed dropzone card. */
[data-theme="editorial"] .ed-step-label {
    display: flex; align-items: center; gap: 8px;
    font-size: 12px; font-weight: 600; color: var(--muted);
    margin-bottom: 10px;
}
[data-theme="editorial"] .ed-step-label b {
    display: inline-flex; justify-content: center;
    width: 20px; height: 20px;
    border-radius: 50%;
    background: var(--accent); color: var(--accent-contrast);
    font: 600 11px/20px var(--font-body);
}
[data-theme="editorial"] .ed-dropzone {
    border: 1.5px dashed var(--line-strong);
    border-radius: 14px;
    box-shadow: none;
}
:root:not([data-theme="editorial"]) .ed-step-label { display: none; }

/* Scroll anchors stop clear of the sticky topnav (52px on phones) instead of under it. */
[data-theme="editorial"] #read-back { scroll-margin-top: 66px; }

/* Vote pill as a button (the drawer's upvote toggle). */
[data-theme="editorial"] button.vote-pill { border: none; cursor: pointer; }
[data-theme="editorial"] .vote-pill.voted { background: var(--accent); color: var(--accent-contrast); }

/* Drawer host: the Blazor drawer mounts at page level, so it anchors to the
   viewport instead of a position:relative stage. */
[data-theme="editorial"] .drawer-host .drawer-scrim,
[data-theme="editorial"] .drawer-host .drawer { position: fixed; }

/* Classic theme never shows editorial-only chrome (belt and braces: these
   components only render under the flag anyway). */
:root:not([data-theme="editorial"]) .topnav,
:root:not([data-theme="editorial"]) .tabbar,
:root:not([data-theme="editorial"]) .drawer-host { display: none; }
