:root {
  --bg: #f7f6f2; --card: #ffffff; --ink: #1c1b18; --muted: #6b6963; --line: #e4e2db;
  --accent: #2f5d8a; --read: #2b7a4b; --maybe: #b07a1a; --skip: #8a8781; --danger: #a33a2c;
  --radius: 12px; --gap: 12px; --pad: 16px; --maxw: 720px;
  --font: -apple-system, BlinkMacSystemFont, "SF Pro Text", "Segoe UI", system-ui, sans-serif;
}
@media (prefers-color-scheme: dark) {
  :root { --bg: #15161a; --card: #1e2026; --ink: #ecebe6; --muted: #9a998f; --line: #2c2f37; --accent: #7fb0e0; --read: #57b87b; --maybe: #d9a441; --skip: #7d7c78; --danger: #e0715f; }
}
* { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; }
body { margin: 0; background: var(--bg); color: var(--ink); font: 16px/1.45 var(--font); }
a { color: var(--accent); text-decoration: none; }
a:hover { text-decoration: underline; }
main { max-width: var(--maxw); margin: 0 auto; padding: var(--pad) 16px calc(var(--pad) + env(safe-area-inset-bottom)); }
/* No overflow clipping on body or main: it disables position: sticky and clips hover labels. */
h1 { font-size: 1.4rem; margin: 0 0 8px; }
h2 { font-size: 1.05rem; line-height: 1.3; margin: 0 0 4px; }
.lede, .meta, .note, .empty { color: var(--muted); }
.lede { max-width: 92ch; }
/* Send button with a screen picker behind a caret. Not ".split": that is the
   two-pane layout's class, and html:has(.split) locks page scrolling. */
.sendbtn { position: relative; display: inline-flex; flex: none; }
.sendbtn > button:first-child { border-top-right-radius: 0; border-bottom-right-radius: 0; }
.sendbtn .caret { min-width: 22px; padding: 6px 4px; margin-left: -1px; border-top-left-radius: 0; border-bottom-left-radius: 0; font-size: 0.75rem; }
.sendbtn .menu { position: absolute; top: calc(100% + 6px); right: 0; z-index: 20; display: flex; flex-direction: column; gap: 2px; padding: 4px; background: var(--card); border: 1px solid var(--line); border-radius: 10px; box-shadow: 0 10px 30px rgba(0, 0, 0, 0.18); }
.sendbtn .menu[hidden] { display: none; }
.sendbtn .menu button { white-space: nowrap; text-align: left; border: 0; background: transparent; padding: 6px 10px; font-size: 0.9rem; min-width: 0; }
.sendbtn .menu button:hover { background: var(--bg); }

/* one line saying what this view is */
.viewnote { color: var(--muted); font-size: 0.88rem; margin: 0 0 12px; max-width: 80ch; }
.viewnote:empty { display: none; }

/* an article Matt has finished with, still on screen in All or a feed view */
.card.isread { opacity: 0.62; }
.card.isread h2 a { color: var(--muted); }

/* swipe to skip: the card follows the finger and shows what letting go does */
.cards .card { touch-action: pan-y; }
.cards .card.swiping { position: relative; z-index: 1; user-select: none; }
.cards .card.swiping::after {
  content: "Clear"; position: absolute; top: 0; right: -96px; height: 100%;
  display: flex; align-items: center; padding-right: 20px;
  color: var(--muted); font-size: 0.9rem; letter-spacing: 0.04em;
  opacity: var(--swipe, 0);
}

/* episode player: the article's own audio, nothing fetched until play */
.episode { margin: 0 0 1.2em; padding: 12px; border: 1px solid var(--line); border-radius: var(--radius); background: var(--card); max-width: 92ch; }
.episode figcaption { color: var(--muted); font-size: 0.85rem; margin-bottom: 8px; }
.episode audio { width: 100%; }
.episode .row { margin-top: 10px; gap: 8px; align-items: center; }
.episode button.done { border-color: var(--accent); color: var(--accent); }

/* searches: one line each, the useful ones first, the dead ones faded */
.searches { list-style: none; padding: 0; margin: 0 0 var(--gap); max-width: 92ch; }
.searches li { display: flex; align-items: center; justify-content: space-between; gap: 12px; padding: 8px 12px; border-bottom: 1px solid var(--line); }
.searches li:last-child { border-bottom: 0; }
.searches li.quiet { color: var(--muted); }
.searches li.quiet strong { font-weight: 500; }
.searches .what { min-width: 0; }
.searches .what .meta { display: block; font-size: 0.85rem; }
.searches .row { flex: none; gap: 8px; align-items: center; }
.searches .chip { white-space: nowrap; }
.searches button.danger { padding: 4px 10px; font-size: 0.85rem; }

/* numbered explanation of a feature, above its controls */
.explain { max-width: 92ch; margin: 0 0 var(--gap); padding-left: 1.2em; color: var(--muted); font-size: 0.95rem; line-height: 1.5; }
.explain li { margin-bottom: 4px; }
.explain strong { color: var(--ink); font-weight: 600; }
.meta { font-size: 0.85rem; margin: 0 0 6px; }
.top { position: sticky; top: 0; z-index: 2; display: flex; align-items: center; gap: 14px; padding: 10px 16px; background: var(--bg); border-bottom: 1px solid var(--line); max-width: var(--maxw); margin: 0 auto; }
.brand { font-weight: 700; color: var(--ink); letter-spacing: 0.02em; }
.top .back { color: var(--muted); font-size: 0.88rem; white-space: nowrap; }
.top nav { display: flex; gap: 12px; flex: 1; }
.top nav a { color: var(--muted); padding: 4px 0; border-bottom: 2px solid transparent; }
.top nav a[aria-current="page"] { color: var(--ink); border-color: var(--accent); }
.foot { max-width: var(--maxw); margin: 24px auto; padding: 0 16px; color: var(--muted); font-size: 0.8rem; }
button, .chip, select, input, textarea { font: inherit; }
button { background: var(--accent); color: #fff; border: 0; border-radius: 8px; padding: 8px 12px; cursor: pointer; }
button.secondary { background: transparent; color: var(--accent); border: 1px solid var(--line); }
button.danger { background: transparent; color: var(--danger); border: 1px solid var(--line); }
button.link { background: none; color: var(--muted); padding: 0; }
button:disabled { opacity: 0.5; cursor: default; }
.inline { display: inline; margin: 0; }
.flash { background: var(--card); border: 1px solid var(--line); border-left: 4px solid var(--read); padding: 10px 12px; border-radius: 8px; margin: 0 0 var(--gap); }
.flash.error { border-left-color: var(--danger); }
.toolbar { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; margin-bottom: var(--gap); }
.views { display: flex; flex-wrap: wrap; gap: 6px; align-items: center; }
.sep { width: 1px; height: 20px; background: var(--line); margin: 0 4px; }
.chip { display: inline-flex; align-items: center; gap: 6px; padding: 5px 10px; border-radius: 999px; border: 1px solid var(--line); color: var(--muted); background: var(--card); font-size: 0.9rem; }
.chip.on { color: var(--ink); border-color: var(--ink); }
.chip .count { font-size: 0.75rem; color: var(--muted); }
.chip.v-read.on { border-color: var(--read); color: var(--read); }
.chip.v-maybe.on { border-color: var(--maybe); color: var(--maybe); }
.chip.v-skip.on { border-color: var(--skip); color: var(--skip); }
.feedpick { display: flex; flex-wrap: wrap; gap: 8px; }
.feedpick select { padding: 6px 8px; border-radius: 8px; border: 1px solid var(--line); background: var(--card); color: var(--ink); max-width: 200px; }
.cards { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: var(--gap); }
.card { cursor: pointer; display: grid; grid-template-columns: 52px minmax(0, 1fr); gap: 12px; background: var(--card); border: 1px solid var(--line); border-radius: var(--radius); padding: 14px; transition: opacity 0.2s, transform 0.2s; }
.card.gone { opacity: 0; transform: translateX(24px); }
.score { width: 52px; height: 52px; border-radius: 50%; display: grid; place-items: center; font-weight: 700; font-variant-numeric: tabular-nums; color: #fff; background: var(--skip); }
.v-read .score { background: var(--read); }
.v-maybe .score { background: var(--maybe); }
.v-none .score { background: var(--line); color: var(--muted); }
.card .body { min-width: 0; }
.card h2, .summary, .reasons, .reader .body p, .reader .body blockquote, .reader .body h2, .reader .body h3, .reader h1 { overflow-wrap: anywhere; }
.card h2 a { color: var(--ink); }
.summary { margin: 0 0 8px; color: var(--ink); opacity: 0.9; font-size: 0.95rem; }
.reasons { margin: 0 0 10px; padding-left: 18px; color: var(--muted); font-size: 0.88rem; }
.reasons li { margin: 2px 0; }
.actions { display: flex; flex-wrap: wrap; gap: 6px; }
.actions button { background: transparent; color: var(--ink); border: 1px solid var(--line); padding: 6px 10px; font-size: 0.9rem; }
.actions button.done { border-color: var(--accent); color: var(--accent); }
/* Forms hold text, so they stop at a readable measure rather than running
   the width of a 1400px window. */
.stack { display: flex; flex-direction: column; gap: 10px; background: var(--card); border: 1px solid var(--line); border-radius: var(--radius); padding: 14px; margin-bottom: var(--gap); max-width: 92ch; }
.stack.narrow { max-width: 420px; }
.stack label { display: flex; flex-direction: column; gap: 4px; font-size: 0.9rem; color: var(--muted); flex: 1; }
.stack input, .stack textarea { padding: 8px 10px; border-radius: 8px; border: 1px solid var(--line); background: var(--bg); color: var(--ink); width: 100%; }
/* The profile editor grows with its text instead of scrolling inside itself:
   a tall box full of content swallowed every scroll that started over it and
   the page stayed put (Matt, 16 Sep 2026). Script tops this up where
   field-sizing is missing. Measured width, too — prose is unreadable across
   1400px. */
.stack textarea { min-height: 320px; line-height: 1.5; font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 0.9rem; field-sizing: content; overflow-y: hidden; resize: vertical; }
.row { display: flex; gap: 10px; flex-wrap: wrap; }
.feeds { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 8px; }
.feeds li { display: flex; justify-content: space-between; gap: 12px; align-items: flex-start; background: var(--card); border: 1px solid var(--line); border-radius: var(--radius); padding: 12px 14px; }
.feeds .meta { word-break: break-all; margin: 2px 0; }
.folder { color: var(--muted); font-size: 0.85rem; }
.bad { color: var(--danger); }
.profile { white-space: pre-wrap; background: var(--card); border: 1px solid var(--line); border-radius: var(--radius); padding: 14px; }
@media (max-width: 480px) {
  .card { grid-template-columns: 44px 1fr; padding: 12px; }
  .score { width: 44px; height: 44px; font-size: 0.95rem; }
  .top nav { gap: 10px; font-size: 0.95rem; }
}
/* reader */
.reader { max-width: 680px; margin: 0 auto; }
.reader h1 { font-size: 1.6rem; line-height: 1.25; margin: 6px 0 12px; }
.reader .body p { font-size: 1.05rem; line-height: 1.6; margin: 0 0 1em; }
/* the article's own headings, kept by the extractor as ## / ### */
.reader .body h2 { font-size: 1.25rem; line-height: 1.3; margin: 1.6em 0 0.5em; }
.reader .body blockquote { margin: 0 0 1em; padding: 2px 0 2px 16px; border-left: 3px solid var(--line); }
.reader .body blockquote p:last-child { margin-bottom: 0; }
.reader .body h3 { font-size: 1.08rem; line-height: 1.35; margin: 1.4em 0 0.4em; color: var(--ink); }
.verdict { display: grid; grid-template-columns: 44px minmax(0, 1fr); gap: 10px; align-items: start; background: var(--card); border: 1px solid var(--line); border-radius: var(--radius); padding: 10px 12px; margin-bottom: 12px; }
.verdict .score { width: 44px; height: 44px; font-size: 0.95rem; }
.verdict .reasons { margin: 0; }
.actions.sticky { position: sticky; top: 52px; z-index: 1; background: var(--bg); padding: 8px 0; margin-bottom: 12px; align-items: center; }
.actions .chip { margin-left: auto; }
.meta .ext { color: var(--muted); }
/* One ring for both keyboard focus and the article open in the pane. */
.card.focus, .card.active { outline: none; border-color: var(--accent); box-shadow: 0 0 0 1px var(--accent) inset; }
.kbd { font-size: 0.8rem; }
kbd { font: inherit; background: var(--card); border: 1px solid var(--line); border-radius: 4px; padding: 0 5px; }
@media (max-width: 480px) { .kbd { display: none; } }

/* undo toast + open button. Done and Skip take the card out of the list at
   once; the undo lives down here rather than in a strip left where the
   card was. */
.toast {
  position: fixed; left: 50%; bottom: 24px; transform: translate(-50%, 12px); z-index: 60;
  display: flex; align-items: center; gap: 12px; max-width: calc(100vw - 32px);
  background: var(--ink); color: var(--bg); border-radius: 10px; padding: 10px 12px;
  box-shadow: 0 10px 30px rgba(0, 0, 0, 0.22); font-size: 0.9rem;
  opacity: 0; pointer-events: none; transition: opacity 0.15s, transform 0.15s;
}
.toast.on { opacity: 1; transform: translate(-50%, 0); pointer-events: auto; }
.toast button { background: transparent; color: var(--bg); border: 1px solid color-mix(in srgb, var(--bg) 45%, transparent); padding: 4px 10px; font-size: 0.85rem; }
.toast button:hover { border-color: var(--bg); }
@media (prefers-reduced-motion: reduce) { .toast, .card { transition: none; } }
.actions .btn { display: inline-flex; align-items: center; padding: 6px 10px; border-radius: 8px; border: 1px solid var(--accent); color: var(--accent); font-size: 0.9rem; }
.saved-mark { color: var(--read); }

/* symbol buttons + note box */
.actions button, .actions .btn { min-width: 40px; justify-content: center; font-size: 1rem; line-height: 1; }
.notebox { display: flex; gap: 6px; margin-top: 8px; }
.notebox input { flex: 1; padding: 6px 10px; border-radius: 8px; border: 1px solid var(--line); background: var(--bg); color: var(--ink); min-width: 0; }
.notebox button { padding: 6px 10px; font-size: 0.9rem; }
.note-text { margin: 4px 0 0; color: var(--ink); }

/* hover labels (data-tip). Positioned in script as one fixed element (see
   reading.js): a pseudo-element was clipped by the scrolling list column —
   a box that scrolls on one axis clips the other — and the first chip's
   label ran off the left edge of the window. */
[data-tip] { position: relative; }
.tip {
  position: fixed; left: 0; top: -9999px; z-index: 50; max-width: min(320px, calc(100vw - 16px));
  background: var(--ink); color: var(--bg); font-size: 0.78rem; line-height: 1.25;
  padding: 6px 8px; border-radius: 6px; box-shadow: 0 6px 20px rgba(0, 0, 0, 0.18);
  pointer-events: none; opacity: 0; transform: translateY(4px);
  transition: opacity 0.12s, transform 0.12s;
}
.tip.below { transform: translateY(-4px); }
.tip.on { opacity: 1; transform: translateY(0); }

/* article images */
.reader figure { margin: 0 0 1.2em; }
.reader figure img { display: block; max-width: 100%; height: auto; border-radius: 10px; background: var(--line); }
.reader figcaption { color: var(--muted); font-size: 0.85rem; margin-top: 6px; }
.reader figure.lead { margin: 0 0 16px; }

/* two-pane desktop: compact list on the left, article on the right */
.pane { display: none; }
@media (min-width: 1000px) {
  /* Two independent scrollers, like a mail client: the page itself does
     not scroll, so the article pane can never leave the viewport. This
     belongs to the two-pane list alone — applied to every page it clipped
     Feeds, Profile and a directly opened article, which then could not be
     scrolled at all (Matt, 16 Sep 2026). Hence the :has(.split) guard. */
  html:has(.split), html:has(.split) body { height: 100%; }
  html:has(.split) body { display: flex; flex-direction: column; overflow: hidden; }
  .top { flex: none; width: 100%; }
  main { max-width: 1400px; width: 100%; padding-top: 12px; }
  html:has(.split) main { flex: 1; min-height: 0; padding-bottom: 0; }
  .split { display: grid; grid-template-columns: minmax(360px, 460px) minmax(0, 1fr); gap: 20px; height: 100%; min-height: 0; }
  .col-list { min-height: 0; overflow-y: auto; padding: 0 6px 24px 0; scrollbar-gutter: stable; }
  .col-list .toolbar { position: sticky; top: 0; z-index: 1; background: var(--bg); padding-bottom: 8px; margin-bottom: 8px; }
  .pane { display: block; min-height: 0; overflow-y: auto; padding: 4px 8px 24px; scrollbar-gutter: stable; }
  html:has(.split) .foot { display: none; }
  .pane .reader { max-width: 720px; }
  .pane .actions.sticky { top: 0; }
  .pane-hint { padding: 40px 0; text-align: center; }
  /* denser rows */
  .card { grid-template-columns: 40px minmax(0, 1fr); gap: 10px; padding: 10px 12px; }
  .score { width: 40px; height: 40px; font-size: 0.9rem; }
  .card h2 { font-size: 0.98rem; margin-bottom: 2px; }
  .card .summary { display: none; }
  .card .reasons { margin-bottom: 6px; font-size: 0.82rem; }
  .card .reasons li:not(:first-child) { display: none; }
  .card .actions button, .card .actions .btn { min-width: 32px; padding: 3px 7px; font-size: 0.9rem; }
  .kbd { display: block; }
}
.reader .body a { color: var(--accent); text-decoration: underline; text-decoration-color: color-mix(in srgb, var(--accent) 40%, transparent); }
.reader .body a:hover { text-decoration-color: var(--accent); }
@media (min-width: 1000px) { .top, .foot { max-width: 1400px; } }
.card:hover { border-color: color-mix(in srgb, var(--accent) 50%, var(--line)); }
.card .actions, .card .undo, .card .notebox { cursor: default; }

/* discovery: a side channel, styled as such */
.card.discovery { border-style: dashed; background: color-mix(in srgb, var(--card) 85%, var(--accent) 15%); }
.card.discovery .score { background: transparent; color: var(--ink); border: 2px dashed var(--accent); }
.disc-label { margin: 0 0 4px; font-size: 0.8rem; color: var(--accent); text-transform: uppercase; letter-spacing: 0.04em; }
.chip.disc { border-style: dashed; }
.reader.discovery { border-left: 3px dashed var(--accent); padding-left: 14px; }

/* toolbar chips: labels drop below so they never run under the sticky header */
.toolbar [data-tip]::after { bottom: auto; top: calc(100% + 8px); transform: translateX(-50%) translateY(-4px); }
.toolbar [data-tip]::before { bottom: auto; top: calc(100% + 2px); border-top: 0; border-bottom: 6px solid var(--ink); }
.toolbar [data-tip]:hover::after, .toolbar [data-tip]:focus-visible::after { transform: translateX(-50%) translateY(0); }
.toolbar [data-tip]:first-child::after { left: 50%; transform: translateX(-50%) translateY(-4px); }
.toolbar [data-tip]:first-child:hover::after, .toolbar [data-tip]:first-child:focus-visible::after { transform: translateX(-50%) translateY(0); }
.toolbar [data-tip]:first-child::before { left: 50%; }
/* Absolutely positioned inside a narrow chip, the label must size to its
   content or it wraps word by word. */
[data-tip]::after { width: max-content; max-width: min(320px, 80vw); white-space: normal; text-align: center; }

/* breathing room around the actions, the note box and the article body */
.reader .actions.sticky { margin-bottom: 18px; }
.reader .notebox { margin: -6px 0 18px; }
.reader .body { margin-top: 4px; }
.reader .body > :first-child { margin-top: 0; }
.card .notebox { margin: 10px 0 4px; }
.v-read-t { color: var(--read); } .v-maybe-t { color: var(--maybe); }
.flash a { margin-left: 6px; }
.offline-pill { display: inline-block; margin-left: 8px; padding: 1px 7px; border-radius: 999px; font-size: 0.75rem; color: var(--read); border: 1px solid color-mix(in srgb, var(--read) 50%, var(--line)); }
#sync-status.synced { color: var(--read); }

/* Today: the day's queue. One list, two slots — the second is the
   counterweight, picked for importance rather than for fit, so it is
   marked as its own section rather than mixed in silently. */
.today { max-width: 60rem; }
.cards .slot { list-style: none; margin: 18px 0 2px; }
.cards .slot:first-child { margin-top: 4px; }
.cards .slot h2 { margin: 0 0 2px; font-size: 1.05rem; }
.cards .slot .viewnote { margin: 0; }
.lede.cleared { color: var(--fg); border-left: 3px solid var(--accent); padding-left: 12px; }
/* Why this one matters, in the scorer's words about the world. */
.why { margin: 0 0 6px; font-size: 0.9rem; color: var(--fg); border-left: 2px solid var(--accent); padding-left: 10px; }
.proposals .row { margin-top: 6px; }

/* Phone header. Five nav items plus the brand and Sign out no longer fit on
   one line (Today made six), and flex items do not shrink below their
   content, so the header was setting the document's scroll width: the whole
   page slid sideways and Sign out and the article images ran off the right
   edge (Matt, 18 Sep 2026, iPhone). Brand and Sign out keep the first row;
   the nav takes its own, and scrolls sideways by itself if it ever needs to
   rather than taking the page with it. */
@media (max-width: 620px) {
  .top { flex-wrap: wrap; gap: 6px 12px; }
  .top .brand { margin-right: auto; }
  .top nav { order: 3; flex: 1 0 100%; gap: 16px; min-width: 0; overflow-x: auto; scrollbar-width: none; padding-bottom: 2px; }
  .top nav::-webkit-scrollbar { width: 0; height: 0; }
  .top nav a { white-space: nowrap; }
}

/* The clear control: a quiet × in the card's top right corner, where a
   dismiss belongs (Matt, 18 Sep 2026 — it started above the score on the
   left and crowded it). Desktop has no swipe, and a queue you cannot clear
   is not a queue. Deliberately not the bordered ✕ in the actions row —
   that one says "not for me"; this one just says "done with the list". */
.card { position: relative; }
.clear { position: absolute; top: 6px; right: 8px; z-index: 1; border: 0; background: transparent; color: var(--muted); font-size: 1.15rem; line-height: 1; padding: 2px 6px; min-width: 0; border-radius: 6px; }
.clear:hover { background: var(--line); color: var(--ink); }
/* Room for it, so a long headline never runs underneath. */
.card h2 { padding-right: 26px; }

/* Today's progress lives in the heading now: on a phone the explanation of
   what the page was took the whole first screen before a single article
   (Matt, 18 Sep 2026 — "we can also remove this text"). */
.today h1 .count { font-weight: 400; font-size: 0.95rem; color: var(--muted); margin-left: 8px; white-space: nowrap; }
.today h1 { margin-bottom: 14px; }
