/* Hub-only styles. Concatenated AFTER paper.css, so equal-specificity rules here win.
   The .paper-card / .paper-grid / .paper-more / .section-title rules are duplicated from
   index.html (which has no build step); scripts/test_build_papers.py compares them rule by
   rule, and the browser harness checks the COMPOSED result — source parity alone stays green
   while the .paper cascade corrupts the page.
   Three declarations below are deltas from index.html's copy, each undoing a .paper
   rule that would otherwise reach the cards: text-decoration:none (vs .paper a),
   margin-top:0 on h3 (vs .paper h3), and color on :hover (vs .paper a:hover).
   .hub>*+* and the grid's margin-top are hub-only additions, not deltas. */
main.hub{max-width:60rem}
/* The hub template has no <article>, so paper.css's .paper article>*+* never applies
   and *{margin:0} would collapse a second body block against the first. (0,1,0) --
   .hub .paper-grid below is (0,2,0), so the grid's margin-top:2rem still wins on
   specificity, not on source order. */
.hub>*+*{margin-top:1.15rem}
.hub h1{margin-bottom:0.75rem}
.hub>p{color:var(--text-secondary);max-width:44rem}
:focus-visible{outline:2px solid var(--accent-light);outline-offset:2px}
.hub .section-title{font-size:clamp(1.5rem,2.5vw,2rem);color:var(--text-primary);letter-spacing:-0.02em;margin-bottom:1.5rem}
.hub .paper-grid{display:grid;grid-template-columns:1fr;gap:1rem;margin-top:2rem}
.hub .paper-card{display:block;background:var(--bg-surface);border:1px solid var(--border);border-radius:0.6rem;padding:1.25rem 1.5rem;transition:border-color 0.2s,box-shadow 0.2s;color:var(--text-secondary);text-decoration:none}
.hub .paper-card:hover{border-color:var(--accent);box-shadow:0 4px 16px oklch(0 0 0 / 0.3);color:var(--text-secondary)}
.hub .paper-card h3{font-size:1.1rem;color:var(--text-primary);margin-bottom:0.35rem;margin-top:0}
.hub .paper-card p{font-size:0.9rem;line-height:1.55;margin-bottom:0.5rem}
.hub .paper-more{font-size:0.85rem;color:var(--accent-light);font-weight:600}
@media(min-width:640px){
.hub .paper-grid{grid-template-columns:repeat(auto-fit,minmax(220px,1fr))}
}
.kwbar{display:flex;flex-wrap:wrap;gap:0.5rem;align-items:center;margin:1.75rem 0 0}
.kw-in{position:absolute;width:1px;height:1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap}
.kw{display:inline-block;padding:0.3rem 0.85rem;border:1px solid var(--border);border-radius:100px;background:var(--bg-base);font-size:0.8rem;color:var(--text-secondary);cursor:pointer;user-select:none}
.kw:hover{border-color:var(--accent);color:var(--accent-light)}
/* Every pill shows a glyph (+ unchecked, checkmark checked) in a fixed-width inline-block
   box, so the swap on toggle cannot change the pill's size, re-wrap the bar, or slide a
   neighbour under the pointer. Same reason the card hover uses box-shadow only. */
.kw::before{content:"+";display:inline-block;width:0.85em;margin-right:0.25em;text-align:center;opacity:0.55}
.kw-in:checked+.kw::before{content:"✓";opacity:1}
.kw-in:checked+.kw{background:var(--accent);border-color:var(--accent);color:var(--text-primary)}
.kw-in:focus-visible+.kw{outline:2px solid var(--accent-light);outline-offset:2px}
.kw-clear{padding:0.3rem 0.85rem;border:1px solid transparent;border-radius:100px;background:none;font:inherit;font-size:0.8rem;color:var(--accent-light);cursor:pointer}
.kw-clear:hover{border-color:var(--border);color:var(--text-primary)}
.kwbar-help{flex-basis:100%;margin:0.35rem 0 0;font-size:0.8rem;color:var(--text-secondary)}
.hub .chips{display:flex;flex-wrap:wrap;gap:0.35rem;margin-bottom:0.5rem}
.hub .chip{padding:0.15rem 0.55rem;border:1px solid var(--border);border-radius:100px;font-size:0.72rem;color:var(--text-secondary)}
