/* ==========================================================================
   泥潭日报 — design tokens
   ==========================================================================
   Single source of truth for color, typography, spacing. Use the CSS
   variables below from every other rule so future restyles change values
   here, not at the call site. */
:root {
    /* Neutrals — newsprint feel. The page sits on a warm off-white so
       it doesn't glare; "card" surfaces (masthead, nav, content area,
       summary block) are pure white and float on top with a hairline.
       This single 2-step background is enough to add visual hierarchy
       without introducing skeuomorphic shadows. */
    --ink:        #1a1d23;     /* primary text, headings */
    --ink-soft:   #4a5160;     /* secondary text, body */
    --ink-muted:  #8b94a3;     /* tertiary text, meta, captions */
    --page-bg:    #f5f3ee;     /* the canvas — warm paper, NOT pure white */
    --bg:         #ffffff;     /* card / content surface that sits on top of the canvas */
    --bg-soft:    #faf8f3;     /* faint warm-tinted alt surface (hover, secondary cards) */
    --bg-sunken:  #f1ede5;     /* slightly recessed, for inset blocks */
    --border:     #e0dcd2;     /* hairlines, dividers (warm-tinted) */
    --border-soft: #ebe7dd;    /* very faint warm dividers */

    /* Brand — one focused accent. Deep blue for links/active states; an
       orange/red highlight reserved for "hot" or "featured" affordances. */
    --accent:        #1d4ed8;
    --accent-hover:  #1e3a8a;
    --accent-soft:   #eff6ff;
    --hot:           #dc2626;
    --hot-soft:      #fef2f2;

    /* Typography — a real scale, not random pixel sizes.
       Modular 1.125 ratio from 14px. */
    --font-sans:   -apple-system, BlinkMacSystemFont, "Segoe UI", "PingFang SC",
                   "Microsoft YaHei", Roboto, "Helvetica Neue", Arial, sans-serif;
    --font-serif:  "Source Han Serif SC", "Noto Serif CJK SC", "Songti SC",
                   "SimSun", Georgia, "Times New Roman", serif;
    --fs-xs:   12px;
    --fs-sm:   13px;
    --fs-base: 15px;
    --fs-md:   16px;
    --fs-lg:   18px;
    --fs-xl:   22px;
    --fs-2xl:  28px;
    --fs-3xl:  34px;

    /* Spacing — 4px grid. Use the named tokens, not raw px values. */
    --sp-1: 4px;
    --sp-2: 8px;
    --sp-3: 12px;
    --sp-4: 16px;
    --sp-5: 24px;
    --sp-6: 32px;
    --sp-7: 48px;
    --sp-8: 64px;

    /* Layout. Wider than the previous 880 so the page doesn't feel
       suffocated on 1440 / 1920 / ultrawide monitors. 1080 keeps Chinese
       prose at ~50 chars per line (Chinese chars are ~2x English width)
       — comfortable, well within the 45-75 char editorial range, and a
       big improvement over 880 on large displays. Mobile + small laptop
       use 100% width inside `--content-pad`. Override below with the
       wide-mode toggle. */
    --content-max: 1080px;
    --content-pad: 20px;
}

/* Wide-mode: user-opt-in via the masthead toggle. State is persisted
   to localStorage (key: `wide-mode`) and applied to <html> by a tiny
   render-blocking script in <head> so we don't FOUC. 1440 doubles the
   per-row scan width on the home view — useful for desktop users who
   prefer density to comfortable line length. Still well-bounded so
   prose doesn't sprawl on ultrawide monitors. */
html[data-wide-mode="on"] {
    --content-max: 1440px;

    /* Borders + shadows. Sparingly. */
    --radius-sm: 4px;
    --radius:    6px;
    --shadow-sm: 0 1px 2px rgba(15, 23, 42, 0.04);
}

/* ==========================================================================
   Reset / base
   ========================================================================== */
*, *::before, *::after { box-sizing: border-box; }
* { margin: 0; padding: 0; }

html { -webkit-text-size-adjust: 100%; }
body {
    font-family: var(--font-sans);
    font-size: var(--fs-md);
    line-height: 1.6;
    color: var(--ink);
    background: var(--page-bg);
    /* Page sits on warm off-white. Content surfaces (masthead, nav, main)
       are pure white sitting on top, creating a subtle paper-on-desk feel
       that's restful for long reading sessions but still feels modern. */
}

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

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

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

/* ==========================================================================
   Layout — container width + outer padding
   ========================================================================== */
.container {
    max-width: var(--content-max);
    margin: 0 auto;
    padding: 0 var(--content-pad);
}

main {
    min-height: 70vh;
    padding-top: var(--sp-4);
    padding-bottom: var(--sp-7);
    background: var(--bg);
    /* The main content sits in a white "page" on the warm canvas, with
       hairlines top + bottom for the floating-card effect. Top padding
       sized so the section-head / breadcrumb / first list row sits a
       comfortable 20-ish px below the sticky category nav — not so much
       that the unfilled gap looks like a layout bug. */
}

/* ==========================================================================
   Header — masthead style. Thin, monochrome, content-first.
   ========================================================================== */
.masthead {
    background: var(--bg);
    border-bottom: 1px solid var(--border);
}
.masthead .container {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    padding-top: var(--sp-4);
    padding-bottom: var(--sp-4);
    gap: var(--sp-4);
}
.brand {
    display: flex;
    align-items: baseline;
    gap: var(--sp-3);
    text-decoration: none;
    color: var(--ink);
}
.brand:hover { text-decoration: none; color: var(--ink); }
.brand-name {
    font-family: var(--font-serif);
    font-weight: 700;
    font-size: var(--fs-2xl);
    letter-spacing: -0.01em;
    line-height: 1;
    color: var(--ink);
}
.brand-tagline {
    font-size: var(--fs-sm);
    color: var(--ink-muted);
    font-weight: 400;
    letter-spacing: 0.02em;
}
/* Masthead utility links — the VIP entrances + the wide-mode toggle.
   Sit on the right of the masthead so they're visible at every viewport
   size including mobile. Style: small pill chips, desaturated by
   default, accent on hover. They're deliberately less prominent than
   the brand on the left, but permanently discoverable, which is what
   they couldn't be when they lived at the end of the scrollable
   category nav. */
.masthead-utility {
    display: flex;
    align-items: center;
    gap: var(--sp-1);
}
/* Wide-mode toggle button. Matches the height and visual weight of the
   VIP chips next to it so the utility cluster reads as one horizontal
   group. Icon + "宽屏模式" label — icon-only was unclear in earlier
   passes. Tooltip and aria-label still describe the action for AT. */
.masthead-toggle {
    box-sizing: border-box;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 6px;
    height: 32px;
    padding: 0 10px;
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    background: var(--bg-soft);
    color: var(--ink-soft);
    font-family: inherit;
    font-size: var(--fs-sm);
    font-weight: 500;
    line-height: 1;
    cursor: pointer;
    transition: color 0.12s, background 0.12s, border-color 0.12s;
}
.masthead-toggle-icon {
    flex: 0 0 auto;
}
.masthead-toggle-label {
    /* No special styling — just a label next to the icon. Hidden on
       narrow viewports so the masthead stays compact. */
    white-space: nowrap;
}
.masthead-toggle:hover {
    color: var(--accent);
    border-color: var(--accent);
    background: var(--accent-soft);
}
.masthead-toggle.is-on {
    color: var(--accent);
    border-color: var(--accent);
    background: var(--accent-soft);
}
.masthead-toggle:focus-visible {
    outline: 2px solid var(--accent);
    outline-offset: 2px;
}
.masthead-utility a {
    box-sizing: border-box;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    height: 32px;
    padding: 0 10px;
    border-radius: var(--radius-sm);
    font-size: var(--fs-sm);
    font-weight: 500;
    line-height: 1;
    color: var(--ink-soft);
    background: var(--bg-soft);
    text-decoration: none;
    transition: color 0.12s, background 0.12s, border-color 0.12s;
    border: 1px solid var(--border);
}
.masthead-utility a:hover,
.masthead-utility a.active {
    color: var(--accent);
    border-color: var(--accent);
    background: var(--accent-soft);
    text-decoration: none;
}
.masthead-utility a.active {
    font-weight: 600;
}

/* ==========================================================================
   Category nav — horizontal row, no scroll on desktop. We sized the
   chips, spacing, and font so all ~14 categories fit at 880-1280px.
   On mobile (where there are too many to fit) the row scrolls.
   ========================================================================== */
.category-nav {
    background: var(--bg);
    border-bottom: 1px solid var(--border);
    position: sticky;
    top: 0;
    z-index: 10;
    /* `position:sticky` keeps the nav visible while users scroll long
       lists. Cheap on desktop, slightly costly on mobile so we keep the
       row thin and avoid box-shadows. */
}
.category-nav-inner {
    max-width: var(--content-max);
    margin: 0 auto;
    padding: 0 var(--content-pad);
    display: flex;
    align-items: stretch;
    /* No `gap` — chips pack tight with their own horizontal padding doing
       the visual spacing. This is what lets ~14 chips fit at 880px wide. */
    overflow-x: auto;
    scrollbar-width: none;
}
.category-nav-inner::-webkit-scrollbar { display: none; }

.category-nav a {
    flex-shrink: 0;
    display: inline-flex;
    align-items: center;
    padding: var(--sp-3) 10px;
    text-decoration: none;
    color: var(--ink-soft);
    font-size: var(--fs-sm);
    font-weight: 500;
    border-bottom: 2px solid transparent;
    margin-bottom: -1px;  /* overlap the nav's bottom border so active line lines up */
    transition: color 0.12s, border-color 0.12s, background 0.12s;
    white-space: nowrap;
    line-height: 1.4;
}
.category-nav a:hover {
    color: var(--ink);
    background: var(--bg-soft);
    text-decoration: none;
}
.category-nav a.active {
    color: var(--accent);
    border-bottom-color: var(--accent);
    font-weight: 600;
}
.category-nav a .count {
    display: none; /* counts were busy and added no scan value; surfaced on demand only */
}
/* VIP chips use the same shape and baseline as the main nav so they
   never look "stuck on" or vertically off-axis. The difference is
   purely color: a desaturated tone + a thin left divider hints these
   are gated/utility links rather than free categories. */
.category-nav .vip-link {
    flex-shrink: 0;
    display: inline-flex;
    align-items: center;
    padding: var(--sp-3) 10px;
    margin-bottom: -1px;
    border-bottom: 2px solid transparent;
    font-size: var(--fs-sm);
    font-weight: 500;
    color: var(--ink-muted);
    background: transparent;
    border-radius: 0;
    margin-left: 0;
    line-height: 1.4;
    text-transform: none;
    letter-spacing: 0;
    white-space: nowrap;
}
.category-nav .vip-link::before {
    /* Small left-side bullet to set this group apart from public categories
       without resorting to a different chip shape. */
    content: "";
    display: inline-block;
    width: 1px;
    height: 14px;
    background: var(--border);
    margin-right: 10px;
    margin-left: 0;
}
.category-nav .vip-link + .vip-link::before {
    /* Only the first VIP chip gets the leading divider line. */
    display: none;
}
.category-nav .vip-link:hover {
    color: var(--ink);
    background: var(--bg-soft);
    text-decoration: none;
}
/* On narrower screens the row still has to scroll — we just removed the
   forced spacer/right-aligned group on desktop so chips pack tight. */

/* ==========================================================================
   Page section header — small, left-aligned, just a label. Lives flush
   to the top of <main> so there isn't a huge unfilled gap between the
   category nav and the section label.
   ========================================================================== */
.section-head {
    margin: 0 0 var(--sp-3);
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: var(--sp-3);
    padding-bottom: var(--sp-3);
    border-bottom: 1px solid var(--border);
}
.section-head-title {
    font-family: var(--font-serif);
    font-size: var(--fs-xl);
    font-weight: 700;
    color: var(--ink);
    letter-spacing: -0.005em;
}
.section-head-meta {
    font-size: var(--fs-xs);
    color: var(--ink-muted);
    flex-shrink: 0;
}

/* ==========================================================================
   Posts list — article rows, not a table. Two-line layout: title row, then
   one slim meta row with category / reply count / summary blurb.
   ========================================================================== */
.posts-list {
    display: flex;
    flex-direction: column;
    /* No top border — the first .post-row's content sits a comfortable
       padding-distance below the nav (or the section-head, where present),
       and the inter-row hairlines come from each row's own border-bottom.
       A floating top hairline above the first row looked like a half-
       finished element on the home view, which has no section-head to
       anchor it to. */
}
.post-row {
    display: block;
    padding: var(--sp-4) 0;
    border-bottom: 1px solid var(--border-soft);
    text-decoration: none;
    color: inherit;
}
.post-row:hover {
    text-decoration: none;
    color: inherit;
}
.post-row:hover .post-title {
    color: var(--accent);
}
.post-title {
    font-size: var(--fs-md);
    font-weight: 600;
    color: var(--ink);
    line-height: 1.4;
    transition: color 0.12s;
    display: block;
}
.post-summary {
    /* The AI-summary one-liner. Editorial italic so it's clearly distinct
       from the headline. Two-line clamp keeps rows scannable. */
    font-size: var(--fs-sm);
    color: var(--ink-soft);
    margin-top: var(--sp-1);
    line-height: 1.55;
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
}
.post-meta-row {
    margin-top: var(--sp-2);
    display: flex;
    flex-wrap: wrap;
    gap: var(--sp-3);
    align-items: center;
    font-size: var(--fs-xs);
    color: var(--ink-muted);
}
.post-meta-row .category-tag {
    color: var(--accent);
    font-weight: 500;
}
.post-meta-row .reply-count::before {
    /* Icon prefix; always present whether the chip is first in the row or not. */
    content: "💬";
    margin-right: 4px;
}
.post-meta-row .sep {
    /* Bullet dividers between chips, rendered by the template (not via
       generated content) so we can reliably skip the first dot when there
       are no preceding chips on the row. */
    color: var(--ink-muted);
    opacity: 0.6;
}

/* ==========================================================================
   Pagination — at the foot of the list, with a small "X of Y" caption.
   ========================================================================== */
.list-footer {
    margin-top: var(--sp-6);
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: var(--sp-3);
}
.pagination {
    display: flex;
    align-items: center;
    gap: var(--sp-1);
    flex-wrap: wrap;
    justify-content: center;
}
.pagination a,
.pagination span {
    min-width: 36px;
    padding: 6px 10px;
    border-radius: var(--radius-sm);
    text-align: center;
    font-size: var(--fs-sm);
    color: var(--ink-soft);
    text-decoration: none;
    background: transparent;
}
.pagination a:hover {
    color: var(--accent);
    background: var(--accent-soft);
    text-decoration: none;
}
.pagination .current {
    color: white;
    background: var(--accent);
    font-weight: 600;
}
.pagination .disabled {
    color: var(--ink-muted);
    opacity: 0.4;
    cursor: not-allowed;
}
.pagination .gap {
    color: var(--ink-muted);
    background: transparent;
    min-width: auto;
}
.list-meta {
    font-size: var(--fs-xs);
    color: var(--ink-muted);
}

/* ==========================================================================
   Detail page — article-shaped layout.
   ========================================================================== */
.breadcrumb {
    font-size: var(--fs-xs);
    color: var(--ink-muted);
    margin-top: var(--sp-4);
    margin-bottom: var(--sp-4);
    line-height: 1.5;
}
.breadcrumb a { color: var(--ink-soft); }
.breadcrumb a:hover { color: var(--accent); text-decoration: none; }
.breadcrumb .sep {
    color: var(--ink-muted);
    margin: 0 var(--sp-2);
    opacity: 0.6;
}
.breadcrumb .current { color: var(--ink); }

.article {
    margin-bottom: var(--sp-7);
}
.article-header {
    margin-bottom: var(--sp-5);
    padding-bottom: var(--sp-4);
    border-bottom: 1px solid var(--border);
}
.article-title {
    font-family: var(--font-serif);
    font-size: var(--fs-3xl);
    line-height: 1.25;
    font-weight: 700;
    color: var(--ink);
    letter-spacing: -0.01em;
    margin-bottom: var(--sp-3);
}
.article-meta {
    display: flex;
    flex-wrap: wrap;
    gap: var(--sp-3);
    font-size: var(--fs-xs);
    color: var(--ink-muted);
    align-items: center;
}
.article-meta .meta-item::before {
    content: "·";
    margin-right: var(--sp-3);
    color: var(--ink-muted);
}
.article-meta > :first-child::before { content: none; margin: 0; }
.article-meta a {
    color: var(--ink-soft);
}
.article-meta a:hover { color: var(--accent); }
.article-meta .article-category {
    color: var(--accent);
    font-weight: 500;
}

/* AI summary — primary content block, distinguished but not boxed-in. */
.summary-section {
    margin: var(--sp-5) 0 var(--sp-6);
    padding: var(--sp-5);
    background: var(--accent-soft);
    border-radius: var(--radius);
}
.summary-section .label {
    display: inline-block;
    font-size: var(--fs-xs);
    text-transform: uppercase;
    letter-spacing: 0.06em;
    font-weight: 700;
    color: var(--accent);
    margin-bottom: var(--sp-3);
}
.summary-content {
    font-size: var(--fs-md);
    line-height: 1.7;
    color: var(--ink);
}
.summary-content h1,
.summary-content h2,
.summary-content h3,
.summary-content h4 {
    font-family: var(--font-serif);
    margin: var(--sp-4) 0 var(--sp-2);
    color: var(--ink);
    font-weight: 700;
    line-height: 1.3;
}
.summary-content h2 { font-size: var(--fs-lg); }
.summary-content h3 { font-size: var(--fs-md); }
.summary-content p { margin: var(--sp-3) 0; }
.summary-content ul,
.summary-content ol { margin: var(--sp-3) 0 var(--sp-3) var(--sp-5); }
.summary-content li { margin: var(--sp-1) 0; }
.summary-content code {
    background: rgba(0,0,0,0.05);
    padding: 1px 6px;
    border-radius: var(--radius-sm);
    font-family: ui-monospace, Menlo, Consolas, monospace;
    font-size: 0.92em;
}
.summary-content pre {
    background: rgba(0,0,0,0.04);
    padding: var(--sp-3);
    border-radius: var(--radius-sm);
    overflow-x: auto;
    margin: var(--sp-3) 0;
}
.summary-content pre code { background: transparent; padding: 0; }

/* Original post body — warm-tinted inset card. Paired with the cool-blue
   AI-summary card, this creates a two-tone visual rhythm: blue = AI
   reading; warm gray = source material. Same shape and padding as the
   summary block so the page reads as a deliberately-composed article,
   not a sequence of unstyled paragraphs floating on the main canvas. */
.original-section {
    margin: var(--sp-5) 0 var(--sp-6);
    padding: var(--sp-5);
    background: var(--bg-sunken);
    border-radius: var(--radius);
}
.original-section-head {
    display: inline-block;
    font-size: var(--fs-xs);
    text-transform: uppercase;
    letter-spacing: 0.06em;
    font-weight: 700;
    color: var(--ink-muted);
    margin-bottom: var(--sp-3);
}
.original-content {
    font-size: var(--fs-md);
    line-height: 1.75;
    color: var(--ink-soft);
}
.original-content p { margin: var(--sp-3) 0; }
.original-content a {
    color: var(--accent);
    word-break: break-word;
}
.original-content .reply-divider {
    margin: var(--sp-5) 0;
    padding-top: var(--sp-3);
    border-top: 1px dashed var(--border);
    color: var(--ink-muted);
    font-size: var(--fs-sm);
}

/* Related posts — clean list. Distinctly not a card-with-border to keep
   the AI-summary block as the visual lead. */
.related-posts {
    margin: var(--sp-6) 0 var(--sp-5);
    padding-top: var(--sp-5);
    border-top: 1px solid var(--border);
}
.related-posts h2 {
    font-family: var(--font-serif);
    font-size: var(--fs-lg);
    font-weight: 700;
    color: var(--ink);
    margin-bottom: var(--sp-4);
}
.related-posts ul {
    list-style: none;
    margin: 0;
    padding: 0;
}
.related-posts li {
    padding: var(--sp-3) 0;
    border-bottom: 1px solid var(--border-soft);
}
.related-posts li:last-child { border-bottom: none; }
.related-posts a {
    color: var(--ink);
    font-weight: 500;
    font-size: var(--fs-md);
    line-height: 1.4;
}
.related-posts a:hover { color: var(--accent); text-decoration: none; }
.related-posts .reply-pill {
    color: var(--ink-muted);
    font-size: var(--fs-xs);
    margin-left: var(--sp-2);
}
.related-posts .blurb {
    color: var(--ink-soft);
    font-size: var(--fs-sm);
    margin-top: var(--sp-1);
    line-height: 1.5;
}

.article-footer {
    margin-top: var(--sp-6);
    padding-top: var(--sp-4);
    border-top: 1px solid var(--border-soft);
}
.btn-back {
    display: inline-flex;
    align-items: center;
    gap: var(--sp-2);
    padding: var(--sp-2) var(--sp-4);
    background: transparent;
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    color: var(--ink-soft);
    font-size: var(--fs-sm);
    font-weight: 500;
    text-decoration: none;
}
.btn-back:hover {
    color: var(--accent);
    border-color: var(--accent);
    text-decoration: none;
}

/* Empty / 404 / no-content states. */
.empty-state {
    padding: var(--sp-7) var(--sp-5);
    text-align: center;
    color: var(--ink-muted);
    font-size: var(--fs-md);
}

/* ==========================================================================
   Footer
   ========================================================================== */
.site-footer {
    margin-top: var(--sp-8);
    border-top: 1px solid var(--border);
    background: var(--bg-soft);
    padding: var(--sp-5) 0;
    color: var(--ink-muted);
    font-size: var(--fs-sm);
    line-height: 1.7;
}
.site-footer .container {
    text-align: center;
}
.site-footer .footer-brand {
    font-family: var(--font-serif);
    color: var(--ink-soft);
    font-weight: 600;
}
.site-footer .footer-meta {
    display: block;
    font-size: var(--fs-xs);
    margin-top: var(--sp-1);
}

/* ==========================================================================
   Lounge login (lounge-login.html). Two-step OAuth-ish gate. Visually
   matches the main site: same surface tokens, same section-head, same
   button styling — previously used a separate inline-style block
   (purple "1." pill, heavy box-shadow) that read as a different
   product.
   ========================================================================== */
.login-page {
    max-width: 640px;
    margin: var(--sp-6) auto var(--sp-7);
}
.login-section-head {
    text-align: center;
    border-bottom: 0;
    padding-bottom: var(--sp-2);
}
.login-section-head .section-head-meta {
    display: block;
    margin-top: var(--sp-1);
    font-size: var(--fs-sm);
    color: var(--ink-muted);
}
.login-steps {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: var(--sp-4);
}
.login-step {
    display: grid;
    grid-template-columns: 36px 1fr;
    gap: var(--sp-4);
    padding: var(--sp-5);
    background: var(--bg);
    border: 1px solid var(--border);
    border-radius: var(--radius);
}
.login-step-num {
    width: 32px;
    height: 32px;
    border-radius: 50%;
    background: var(--accent);
    color: #fff;
    font-weight: 600;
    font-size: var(--fs-md);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    line-height: 1;
}
.login-step-title {
    margin: 0 0 var(--sp-2);
    font-size: var(--fs-lg);
    font-weight: 600;
    color: var(--ink);
}
.login-step-text {
    margin: 0 0 var(--sp-3);
    color: var(--ink-soft);
    font-size: var(--fs-sm);
    line-height: 1.7;
}
.login-step-text code {
    font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
    font-size: 0.92em;
    background: var(--bg-sunken);
    padding: 1px 6px;
    border-radius: 4px;
}
.login-action {
    display: inline-flex;
    align-items: center;
    padding: 9px 16px;
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    background: var(--bg-soft);
    color: var(--ink);
    font-size: var(--fs-sm);
    font-weight: 500;
    text-decoration: none;
    cursor: pointer;
    transition: color 0.12s, background 0.12s, border-color 0.12s;
    font-family: inherit;
}
.login-action:hover {
    color: var(--accent);
    border-color: var(--accent);
    background: var(--accent-soft);
    text-decoration: none;
}
.login-action-primary {
    background: var(--accent);
    border-color: var(--accent);
    color: #fff;
}
.login-action-primary:hover {
    background: var(--accent-hover);
    border-color: var(--accent-hover);
    color: #fff;
}
.login-form {
    display: flex;
    flex-direction: column;
    gap: var(--sp-2);
}
.login-label {
    font-size: var(--fs-sm);
    font-weight: 500;
    color: var(--ink-soft);
}
.login-textarea {
    width: 100%;
    min-height: 96px;
    padding: var(--sp-3);
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    background: var(--bg);
    color: var(--ink);
    font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
    font-size: var(--fs-sm);
    line-height: 1.5;
    resize: vertical;
}
.login-textarea:focus {
    outline: 2px solid var(--accent);
    outline-offset: -1px;
    border-color: var(--accent);
}
.login-note {
    margin-top: var(--sp-5);
    padding: var(--sp-3) var(--sp-4);
    background: var(--bg-sunken);
    border-left: 3px solid var(--accent);
    border-radius: 0 var(--radius-sm) var(--radius-sm) 0;
    font-size: var(--fs-sm);
    color: var(--ink-soft);
    line-height: 1.7;
}

/* ==========================================================================
   Responsive
   ========================================================================== */
@media (max-width: 768px) {
    :root {
        --content-pad: 16px;
        --fs-3xl: 26px;
        --fs-2xl: 22px;
        --fs-xl: 19px;
    }
    .masthead .container {
        padding-top: var(--sp-3);
        padding-bottom: var(--sp-3);
    }
    .brand-name { font-size: var(--fs-xl); }
    .brand-tagline { display: none; } /* tagline at this width crowds the meta — drop it */
    .masthead-meta { font-size: 11px; }
    /* Mobile already uses 100% width — wide-mode has no effect at this
       viewport, so the toggle would just be a confusing dead button.
       Hide it; localStorage state still persists across viewport
       changes, so a user who toggled on desktop sees the same state
       when they reopen on phone (it just doesn't change anything
       visible). */
    .masthead-toggle { display: none; }

    /* Mobile nav can't fit all chips in one row — it scrolls. Pad both
       ends so the first/last chip don't touch the edge. */
    .category-nav-inner { padding: 0 var(--content-pad); }
    .category-nav a,
    .category-nav .vip-link { padding: var(--sp-3) 8px; }

    .post-row { padding: var(--sp-3) 0; }
    .post-title { font-size: var(--fs-md); }
    .post-summary {
        /* The list is already information-dense on small screens; one line
           of summary is enough. The detail page is one tap away. */
        -webkit-line-clamp: 1;
        font-size: var(--fs-xs);
    }

    .article-title { font-size: var(--fs-2xl); line-height: 1.3; }
    .summary-section { padding: var(--sp-4); }
}
