/* glue — "retro road-trip poster on warm paper".
 *
 * An editorial event-poster system: warm cream canvas, a single electric blue accent, and a type
 * pairing that does all the work — a hairline didone for display, a whisper-weight grotesk for
 * everything else. Surfaces are strictly flat; hairline rules do the structural work.
 *
 * This is not decoration for its own sake. Product spec §7 asks for exactly this: "The Brief
 * reads like a printed page, not an inbox. Generous margins, one column, real typography, no
 * chrome. It should look like something that ends."
 *
 * FONTS, AND WHY THERE ARE NO WEBFONTS
 * Editorial New and Founders Grotesk are commercial. Downloading substitutes would need the
 * network, which a local-first app must not require to render its own UI. macOS ships a genuine
 * didone — Didot — and SF Pro at weight 300 sits close to Founders Grotesk. Both are already on
 * every machine this runs on, so the system renders correctly offline and on first launch.
 */

:root {
  /* Voltage Blue is the only chromatic voice in the system. Everything else is ink on cream. */
  --accent: #006eff;         /* Borders and marks. 4.27:1 — fine for non-text, short of AA text. */
  --accent-text: #0063e6;    /* The same blue, darkened to 5.1:1 for anything that is words. */
  --accent-weak: #cfe2ff;
  /* Words on the tint. `--accent-text` clears AA on cream at 5.08:1 and only reaches 4.07:1 on
     `--accent-weak`, because the ground is no longer white-ish — so a chip, a count or a tag on
     the tint needs one more step down. Same hue, third value: the rule is one chromatic voice,
     not one number. 5.32:1 on the tint, 6.64:1 on cream. */
  --accent-on-weak: #0052c4;

  --bg: #fff8f1;          /* Cream — page background AND card surface; cards sit flat on it. */
  --surface: #fff8f1;
  --surface-2: #fff8f1;   /* The same cream. The source system has exactly one paper tone. */
  --ink: #000000;
  --ink-2: #2b2824;
  /* Was #8a857e — 3.48:1, below the 4.5:1 AA needs for normal text, and the 300 weight made it
     worse. Secondary text is most of the words in the app; it cannot be the least readable. */
  --muted: #6f6a63;          /* 5.09:1 */
  --line: #e2e8f0;        /* Ash — hairline dividers, card borders, rules. */
  --line-2: #d5dde8;

  --ok: #006eff;          /* No second chromatic colour: success speaks in blue too. */
  --err: #b3261e;         /* The one exception — a destructive warning must not read as a link. */

  /* Flat. No shadows, no gradients, no elevation. */
  --shadow: none;

  /* 60px on every button, tag and pill; never mixed with small radii. Cards are square. */
  --r: 0px;
  --r-sm: 0px;
  --r-pill: 60px;

  --font-display: "Didot", "Bodoni 72", "Playfair Display", "Cormorant", Georgia, serif;
  --font: "Helvetica Neue", "Inter", -apple-system, system-ui, Arial, sans-serif;
}

* { box-sizing: border-box; }
html, body { height: 100%; margin: 0; }
body {
  background: var(--bg);
  color: var(--ink);
  font-family: var(--font);
  /* Body sits in a deliberately narrow range, 16–21px. Weight 300 is the signature, not a
     fallback: the authority in this system comes from restraint. */
  font-size: 16px;
  font-weight: 300;
  line-height: 1.5;
  letter-spacing: -0.02em;
  font-feature-settings: "clig", "liga";
  -webkit-font-smoothing: antialiased;
}
/* Display is the didone, and only at size. Below 28px it loses the hairline contrast that is the
   whole point and just reads as an odd serif. */
h1 {
  font-family: var(--font-display);
  font-size: 38px;
  font-weight: 200;
  line-height: 1;
  letter-spacing: -0.02em;
  margin: 0;
}
h2 { font-size: 18px; font-weight: 300; letter-spacing: -0.02em; margin: 0; }
h3 { font-size: 18px; font-weight: 300; letter-spacing: -0.02em; margin: 0; }
/* Nothing in the system uses weight 600 or above. */
strong, b { font-weight: 400; }
.muted { color: var(--muted); }
.sm { font-size: 16px; }
button, input, textarea { font: inherit; color: inherit; }

#app { display: grid; grid-template-rows: auto 1fr; height: 100vh; }

/* ── Topline ─────────────────────────────────────────────────────────── */
.topline {
  display: flex; align-items: center; gap: 16px;
  padding: 8px 16px; border-bottom: 1px solid var(--line);
  background: var(--surface-2);
}
/* Search is an action, not a place — so it lives here, reachable from every section,
   rather than occupying one of the eight slots in the dock. */
.palette-trigger {
  flex: 1 1 0; min-width: 0; max-width: 420px; margin: 0 auto;
  display: flex; align-items: center; gap: 8px;
  background: var(--surface); border: 1px solid var(--line); border-radius: var(--r-sm);
  padding: 5px 10px; cursor: pointer; color: var(--muted); font-size: 14px;
  transition: border-color 0.12s, color 0.12s;
}
.palette-trigger:hover { border-color: var(--accent); color: var(--ink-2); }
.palette-trigger svg { width: 14px; height: 14px; flex: none; }
.palette-trigger span { flex: 1; text-align: left; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.palette-trigger kbd {
  font-family: inherit; font-size: 12px; color: var(--muted);
  border: 1px solid var(--line); border-radius: 4px; padding: 1px 5px; background: var(--surface-2);
}

/* ── Dock ────────────────────────────────────────────────────────────── */
/* The dock is the only navigation, so it must fit every window width — an 8-item bar that
   overflows would put the primary nav off-screen and take the whole app's horizontal scroll
   with it. Items flex down and labels drop before anything is ever cut off. */
.dock {
  position: fixed; left: 50%; bottom: 14px; transform: translateX(-50%);
  display: flex; justify-content: center; gap: 2px;
  width: auto; max-width: calc(100vw - 24px);
  padding: 5px 7px;
  background: var(--bg);
  border: 1px solid var(--line-2);
  border-radius: var(--r-pill);
  z-index: 40;
  /* Flat, so a hairline is the only separation from the page behind it — which is why the dock
     needs its own border where a full-width bar could rely on an edge. */
  transition: transform 0.24s cubic-bezier(0.2, 0, 0, 1), opacity 0.2s ease;
}
/* Tucked away until approached. Slid rather than hidden, so it animates back from where it
   went and keeps its position obvious. */
.dock.tucked { transform: translateX(-50%) translateY(calc(100% + 20px)); opacity: 0; }
/* Keyboard use must never depend on the pointer being somewhere: focus always brings it back. */
.dock:focus-within { transform: translateX(-50%); opacity: 1; }
/* The strip that reveals it. Sits under the dock and takes no clicks of its own. */
.dock-hotzone { position: fixed; left: 0; right: 0; bottom: 0; height: 96px; z-index: 39; pointer-events: none; }
.nav-item {
  display: flex; flex-direction: column; align-items: center; gap: 3px;
  background: none; border: 0; cursor: pointer;
  padding: 5px 6px; border-radius: var(--r-sm);
  flex: 0 1 82px; min-width: 0;
  color: var(--muted); font-size: 12px; transition: background 0.12s, color 0.12s;
}
.nav-item span { max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.nav-item:hover { background: rgba(0,0,0,0.04); color: var(--ink-2); }
.nav-item.active { background: var(--surface); color: var(--ink); box-shadow: var(--shadow); font-weight: 560; }
.nav-item.active svg { color: var(--accent-text); }
.nav-item svg { width: 18px; height: 18px; color: currentColor; flex: none; }
/* Home is the centre of the app, and the dock says so. */
.dock-home svg { width: 21px; height: 21px; }
.conn { display: flex; align-items: center; gap: 7px; color: var(--muted); font-size: 14px; flex: none; }
.dot { width: 8px; height: 8px; border-radius: 50%; background: var(--muted); }
.dot.online { background: var(--ok); }

/* ── Home ────────────────────────────────────────────────────────────── */
.brief-section { margin-bottom: 18px; }
.brief-section > h2, .brief-section summary h2 {
  font-size: 14px; font-weight: 600; letter-spacing: 0.02em;
  text-transform: uppercase; color: var(--muted); margin: 0 0 10px;
  display: inline-block;
}
.brief-section summary { cursor: pointer; list-style: none; display: flex; align-items: center; gap: 10px; }
/* A disclosure marker is a small icon, sized to the label rather than to the dock. */
.brief-section summary svg, .graph-wrap summary svg { width: 17px; height: 17px; color: var(--muted); flex: none; }
.brief-section summary::-webkit-details-marker { display: none; }
.brief-overflow { text-transform: none; letter-spacing: 0; font-weight: 400; margin-left: 8px; }
.brief-list { display: flex; flex-direction: column; gap: 1px; }
.brief-item {
  display: flex; align-items: flex-start; gap: 12px;
  padding: 11px 13px; border-radius: var(--r-sm); background: var(--surface);
  border: 1px solid var(--line); cursor: pointer; text-align: left; width: 100%;
}
.brief-item:hover { border-color: var(--accent-weak); }
.brief-item-main { flex: 1; min-width: 0; }
.brief-item-title { font-size: 14px; color: var(--ink); font-weight: 520; }
/* The reason string is displayed copy, not debug output (spec 6.3) — it is what makes the
   90%-precision claim checkable at a glance, so it gets real visual weight. */
.brief-reason { font-size: 14px; color: var(--ink-2); margin-top: 2px; }
.brief-meta { display: flex; align-items: center; gap: 8px; flex: none; color: var(--muted); font-size: 14px; }
.brief-age { white-space: nowrap; }
.brief-carried { border: 1px solid currentColor; border-radius: 999px; padding: 0 6px; font-size: 12px; }
.brief-draft { color: var(--accent-text); }
.brief-dismiss { background: none; border: 0; color: var(--muted); cursor: pointer; padding: 2px 5px; border-radius: 4px; font-size: 15px; line-height: 1; }
.brief-dismiss:hover { background: rgba(0,0,0,0.06); color: var(--ink); }
.brief-groups { display: flex; flex-direction: column; gap: 14px; }
.brief-group-topic { font-size: 14px; font-weight: 600; color: var(--ink-2); margin-bottom: 4px; }
.brief-line { font-size: 14px; color: var(--ink-2); padding: 3px 0; cursor: pointer; }
.brief-line:hover { color: var(--ink); }
.brief-line .muted { margin-left: 6px; }

/* The empty state is the product working, not an error to apologise for (spec 6.5).
   A sentence and white space — deliberately no illustration, badge or streak. */
.quiet { padding: 72px 0 96px; text-align: center; }
.quiet-line { font-size: 19px; color: var(--ink-2); font-weight: 400; margin: 0 0 8px; }
.setup-banner { display: flex; align-items: center; justify-content: space-between; gap: 16px; margin-bottom: 14px; padding: 10px 14px; }
.setup-banner h3 { margin: 0 0 3px; font-size: 14px; }
.home-activity { margin-top: 22px; border-top: 1px solid var(--line); padding-top: 14px; }
.home-activity .topbar-actions { margin: 6px 0 10px; }

/* ── People ──────────────────────────────────────────────────────────── */
.people-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(230px, 1fr)); gap: 10px; }
.person {
  background: var(--surface); border: 1px solid var(--line); border-radius: var(--r-sm);
  padding: 12px 14px; cursor: pointer; text-align: left;
}
.person:hover { border-color: var(--accent-weak); }
.person-name { font-size: 14px; font-weight: 540; color: var(--ink); }
.person-addr { font-size: 14px; color: var(--muted); margin-top: 1px; overflow: hidden; text-overflow: ellipsis; }
.person-stats { font-size: 14px; color: var(--ink-2); margin-top: 7px; display: flex; gap: 12px; }
.graph-wrap { margin-top: 30px; border-top: 1px solid var(--line); padding-top: 16px; }
.graph-wrap summary { cursor: pointer; list-style: none; display: flex; align-items: baseline; gap: 10px; }
.graph-wrap summary::-webkit-details-marker { display: none; }
.graph-wrap summary h2 { font-size: 14px; text-transform: uppercase; letter-spacing: 0.02em; color: var(--muted); margin: 0; }

/* ── Command palette ─────────────────────────────────────────────────── */
.palette-backdrop {
  position: fixed; inset: 0; background: rgba(0,0,0,0.28);
  display: flex; align-items: flex-start; justify-content: center; padding-top: 12vh; z-index: 50;
}
.palette-backdrop[hidden] { display: none; }
.palette {
  width: min(620px, 92vw); background: var(--surface); border: 1px solid var(--line);
  border-radius: var(--r-md, 10px); box-shadow: 0 18px 48px rgba(0,0,0,0.22);
  overflow: hidden; display: flex; flex-direction: column; max-height: 66vh;
}
.palette input {
  border: 0; border-bottom: 1px solid var(--line); padding: 14px 16px;
  font-size: 15px; font-family: inherit; background: none; color: var(--ink); outline: none;
}
.palette-results { overflow: auto; padding: 6px; }
.palette-row { padding: 9px 11px; border-radius: var(--r-sm); cursor: pointer; }
.palette-row:hover, .palette-row.sel { background: var(--surface-2); }
.palette-row-title { font-size: 14px; color: var(--ink); }
.palette-row-sub { font-size: 14px; color: var(--muted); margin-top: 1px; }

/* ── Stage ──────────────────────────────────────────────────────────── */
.stage { overflow: hidden; display: flex; flex-direction: column; }
.view { display: none; flex-direction: column; min-height: 0; flex: 1; padding: 20px 24px; overflow: auto; }
.view.active { display: flex; }
/* The [hidden] attribute must win over component display rules (e.g. .note-editor{display:flex}). */
[hidden] { display: none !important; }
.topbar { display: flex; align-items: baseline; gap: 14px; margin-bottom: 20px; }
.topbar .muted { font-size: 14px; }
.topbar-actions { margin-left: auto; display: flex; gap: 8px; }

/* Buttons */
.primary, .ghost {
  border-radius: var(--r-sm); padding: 9px 15px; cursor: pointer; border: 1px solid transparent;
  font-weight: 540; transition: filter 0.12s, background 0.12s, border-color 0.12s;
}
.primary { background: var(--accent-text); color: #fff; }
.primary:hover { filter: brightness(1.06); }
.ghost { background: var(--surface); border-color: var(--line-2); color: var(--ink-2); }
.ghost:hover { background: var(--surface-2); color: var(--ink); }
.ghost.danger { color: var(--err); }
/* A button-size modifier, but `.sm` is also used on spans and paragraphs — so the padding is
   scoped to buttons. Unscoped (as it was) it silently indents body copy in ~30 places.
   The size is a deliberate deviation from the reference system's 16px floor: that floor is
   written for editorial body copy, and a dense list needs a quieter meta tier. 14px keeps the
   restraint without pretending a marketing-page scale fits a table. */
.sm { font-size: 14px; }
button.sm, .primary.sm, .ghost.sm, a.sm { padding: 6px 11px; }

input, textarea {
  background: var(--surface); border: 1px solid var(--line-2); border-radius: var(--r-sm);
  padding: 9px 12px; outline: none; transition: border-color 0.12s, box-shadow 0.12s;
}
input:focus, textarea:focus { border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-weak); }

/* ── Chat ───────────────────────────────────────────────────────────── */
.chat-log { flex: 1; overflow: auto; display: flex; flex-direction: column; gap: 14px; padding-bottom: 8px; }
.msg { max-width: 74%; padding: 11px 15px; border-radius: 14px; line-height: 1.55; white-space: pre-wrap; }
.msg.user { align-self: flex-end; background: var(--accent-text); color: #fff; border-bottom-right-radius: 4px; }
.msg.assistant { align-self: flex-start; background: var(--surface); border: 1px solid var(--line); border-bottom-left-radius: 4px; box-shadow: var(--shadow); }
.tools { margin-top: 8px; display: flex; flex-wrap: wrap; gap: 5px; }
.toolchip { font-size: 14px; color: var(--ink-2); background: var(--surface-2); border: 1px solid var(--line-2); border-radius: 999px; padding: 2px 9px; }
.toolchip.err { color: var(--err); border-color: var(--err); background: #fdeceb; }
.composer { display: flex; gap: 10px; margin-top: 14px; }
.composer input { flex: 1; }

/* ── Split Inbox tabs ───────────────────────────────────────────────── */
.tabs { display: flex; gap: 4px; margin-bottom: 14px; border-bottom: 1px solid var(--line); }
.tab { background: none; border: 0; border-bottom: 2px solid transparent; color: var(--ink-2); padding: 7px 12px 9px; cursor: pointer; font-size: 14px; display: flex; align-items: center; gap: 7px; margin-bottom: -1px; }
.tab:hover { color: var(--ink); }
.tab.active { color: var(--ink); border-bottom-color: var(--accent); font-weight: 560; }
.tab-count { font-size: 12px; color: var(--muted); background: var(--surface-2); border-radius: 999px; padding: 1px 7px; font-variant-numeric: tabular-nums; }
.tab.active .tab-count { background: var(--accent-weak); color: var(--accent-on-weak); }
.hint { margin-right: 8px; opacity: 0.8; font-variant-numeric: tabular-nums; }

/* ── Split (email / notes) ──────────────────────────────────────────── */
.split { flex: 1; min-height: 0; display: grid; grid-template-columns: 320px 1fr; gap: 18px; }
.pane-list { overflow: auto; display: flex; flex-direction: column; gap: 2px; padding-right: 4px; }
.pane-detail { overflow: auto; background: var(--surface); border: 1px solid var(--line); border-radius: var(--r); box-shadow: var(--shadow); padding: 26px 30px; }
.placeholder { color: var(--muted); display: grid; place-items: center; height: 100%; font-size: 14px; }
.li {
  border: 1px solid transparent; border-radius: var(--r-sm); padding: 10px 12px; cursor: pointer;
  display: flex; flex-direction: column; gap: 3px; transition: background 0.1s, border-color 0.1s;
}
.li:hover { background: var(--surface); border-color: var(--line); }
.li.active { background: var(--surface); border-color: var(--line-2); box-shadow: var(--shadow); }
.li-top { display: flex; align-items: center; gap: 8px; }
.li-from { font-weight: 580; font-size: 14px; }
.li-time { margin-left: auto; color: var(--muted); font-size: 14px; }
.li-subj { font-size: 14px; color: var(--ink-2); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.li-snip { font-size: 14px; color: var(--muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.unread-dot { width: 7px; height: 7px; border-radius: 50%; background: var(--accent); flex: none; }
.unread-dot.read { background: transparent; }
.li-from { font-weight: 580; }
.li.active .unread-dot.read, .li:hover .unread-dot.read { background: var(--line-2); }

/* Detail-pane triage actions */
.detail-actions { display: flex; gap: 6px; float: right; margin-left: 12px; }
.detail-head { overflow: hidden; }

/* Email headers + attachments */
.email-hdr { border-collapse: collapse; margin-top: 8px; font-size: 14px; }
.email-hdr td { padding: 1px 0; vertical-align: top; color: var(--ink-2); }
.email-hdr td.hl { color: var(--muted); padding-right: 14px; width: 48px; }
.attachments { margin-top: 10px; display: flex; flex-wrap: wrap; gap: 6px; }
.att { font-size: 14px; border: 1px solid var(--line-2); border-radius: 6px; padding: 3px 9px; color: var(--ink-2); background: var(--surface-2); cursor: pointer; }
.att:hover { border-color: var(--accent); color: var(--accent-text); }
.ai-act { color: var(--accent-text); border-color: var(--accent-weak); }
.ai-act:hover:not(:disabled) { background: var(--accent-weak); }
.ai-act:disabled { opacity: 0.7; cursor: default; }

/* Accounts list (Settings) */
.accounts-list { display: flex; flex-direction: column; gap: 4px; margin: 12px 0 6px; }
.acct { display: flex; align-items: center; gap: 9px; padding: 6px 2px; }
.acct-email { font-size: 14px; }
.acct .dot { width: 8px; height: 8px; }
.acct button { margin-left: auto; }
.acct-empty { padding: 8px 2px; }

/* Rendered (sanitized) email HTML — contained so its CSS can't escape the reader pane */
/* Email body renders in a sandboxed iframe (isolated CSS); the frame is sized to its content. */
.email-frame { width: 100%; border: 0; display: block; background: #fff; min-height: 80px; color-scheme: light; }

/* Draft cards (staged sends) */
.draft-card { display: flex; flex-direction: column; gap: 9px; }
.draft-field { display: flex; flex-direction: column; gap: 3px; font-size: 14px; color: var(--muted); }
.draft-field input { font-size: 14px; color: var(--ink); }
.draft-card textarea { min-height: 120px; line-height: 1.5; font-family: inherit; font-size: 14px; }
.pill { font-size: 12px; border-radius: 999px; padding: 2px 9px; border: 1px solid var(--line-2); color: var(--muted); background: var(--surface-2); }

/* Reader / rendered content */
.reader { max-width: 680px; line-height: 1.65; color: var(--ink); }
.reader h1, .reader h2, .reader h3, .reader h4 { letter-spacing: -0.01em; margin: 1.3em 0 0.45em; line-height: 1.3; font-weight: 640; }
.reader h1 { font-size: 21px; } .reader h2 { font-size: 17.5px; } .reader h3 { font-size: 15px; } .reader h4 { font-size: 14px; color: var(--ink-2); }
.reader h1:first-child, .reader h2:first-child, .reader h3:first-child { margin-top: 0; }
.reader p { margin: 0 0 0.9em; }
.reader a { color: var(--accent-text); text-decoration: none; } .reader a:hover { text-decoration: underline; }
.reader ul, .reader ol { margin: 0 0 0.9em; padding-left: 1.5em; }
.reader li { margin: 0.18em 0; }
.reader li > ul, .reader li > ol { margin: 0.18em 0; }
.reader blockquote { margin: 0 0 0.9em; padding: 2px 0 2px 15px; border-left: 3px solid var(--line-2); color: var(--ink-2); }
.reader code { background: var(--surface-2); padding: 1px 5px; border-radius: 5px; font-size: 0.88em; font-family: ui-monospace, "SF Mono", Menlo, monospace; }
.reader pre { background: var(--surface-2); border: 1px solid var(--line); border-radius: var(--r-sm); padding: 12px 14px; overflow-x: auto; margin: 0 0 0.9em; }
.reader pre code { background: none; padding: 0; font-size: 14px; line-height: 1.5; }
.reader hr { border: 0; border-top: 1px solid var(--line); margin: 1.6em 0; }
.reader img { max-width: 100%; height: auto; border-radius: var(--r-sm); }
.reader table { border-collapse: collapse; margin: 0 0 0.9em; font-size: 14px; }
.reader th, .reader td { border: 1px solid var(--line-2); padding: 6px 11px; text-align: left; }
.reader th { background: var(--surface-2); font-weight: 600; }
.reader strong { font-weight: 640; }
.reader .wikilink { color: var(--accent-on-weak); background: var(--accent-weak); border-radius: 4px; padding: 0 4px; cursor: pointer; text-decoration: none; white-space: nowrap; }
.reader .wikilink:hover { background: var(--accent-text); color: #fff; }
/* Broken / not-yet-created link: muted, dashed — click creates it. */
.reader .wikilink.unresolved { color: var(--muted); background: none; border-radius: 0; padding: 0; border-bottom: 1px dashed var(--line-2); }
.reader .wikilink.unresolved:hover { color: var(--accent-text); background: none; border-bottom-color: var(--accent); }

/* Backlinks / outgoing panel (Obsidian-style) */
.note-links { margin-top: 30px; padding-top: 2px; border-top: 1px solid var(--line); max-width: 680px; }
.ln-section { margin-top: 20px; }
.ln-head { font-size: 14px; text-transform: uppercase; letter-spacing: 0.05em; color: var(--muted); margin: 0 0 10px; display: flex; align-items: center; gap: 8px; }
.ln-count { background: var(--surface-2); color: var(--ink-2); border-radius: 999px; padding: 1px 8px; font-size: 12px; letter-spacing: 0; }
.ln-outs { display: flex; flex-wrap: wrap; gap: 7px; }
.ln-out { font-size: 14px; color: var(--accent-on-weak); background: var(--accent-weak); border-radius: 6px; padding: 3px 10px; cursor: pointer; text-decoration: none; }
.ln-out:hover { background: var(--accent-text); color: #fff; }
.ln-out.broken { color: var(--muted); background: none; border: 1px dashed var(--line-2); }
.ln-out.broken::before { content: "+ "; opacity: 0.7; }
.ln-out.broken:hover { color: var(--accent-on-weak); border-color: var(--accent); background: var(--accent-weak); }
.mention { padding: 9px 12px; border: 1px solid var(--line); border-radius: var(--r-sm); margin-bottom: 8px; cursor: pointer; }
.mention:hover { border-color: var(--line-2); background: var(--surface); }
.m-title { font-size: 14px; font-weight: 560; color: var(--accent-text); }
.m-snip { font-size: 14px; color: var(--ink-2); margin-top: 3px; line-height: 1.5; }

/* Note reader header + tags */
/* About. A definition list rather than prose: version, licence, updates and where the data is are
   four facts someone scans for, not a paragraph they read. */
.about-grid { display: grid; grid-template-columns: auto 1fr; gap: 6px 18px; margin: 4px 0 12px; font-size: 13px; }
.about-grid dt { color: var(--muted); }
.about-grid dd { margin: 0; color: var(--ink); }
.about-grid code { font-size: 12px; word-break: break-all; }
.oss-row { display: flex; justify-content: space-between; gap: 16px; padding: 3px 0; }
.about-oss { margin-top: 10px; }

/* Dictation. The recording state has to be unmistakable — a mic that is listening and looks like
   one that is not is the version of this feature that records a meeting by accident. */
.dictate { display: inline-flex; align-items: center; gap: 6px; font-size: 13px; padding: 5px 10px; border: 1px solid var(--line-2); background: var(--surface); color: var(--ink-2); cursor: pointer; }
.dictate:hover { border-color: var(--accent); color: var(--accent-text); }
.dictate.icon-only { padding: 5px 7px; gap: 0; }
.dictate svg { width: 15px; height: 15px; }
.dictate.recording { border-color: var(--err); color: var(--err); background: var(--bg); }
.dictate.recording svg { animation: dictate-pulse 1.2s ease-in-out infinite; }
@keyframes dictate-pulse { 0%, 100% { opacity: 1; } 50% { opacity: 0.35; } }
/* Motion is decoration here; the colour change carries the same information without it. */
@media (prefers-reduced-motion: reduce) { .dictate.recording svg { animation: none; } }
.dictate-row { display: flex; align-items: center; gap: 10px; margin-bottom: 8px; }
.dictate-hint { flex: 1; min-width: 0; }

/* A vault has thousands of notes; the list showed the first 80 with no way to look. */
.notes-filter { width: 190px; font-size: 13px; padding: 5px 9px; }

.note-reader-head { display: flex; align-items: flex-start; gap: 14px; margin-bottom: 4px; }
.note-h1 { flex: 1; font-size: 22px; font-weight: 660; letter-spacing: -0.015em; margin: 0; line-height: 1.25; }
.note-reader-head button { flex: none; margin-top: 4px; }
.note-tags-row { display: flex; flex-wrap: wrap; gap: 6px; margin: 8px 0 18px; }
.tag-chip { font-size: 14px; color: var(--accent-on-weak); background: var(--accent-weak); border-radius: 999px; padding: 2px 10px; cursor: pointer; }
.tag-chip:hover { background: var(--accent-text); color: #fff; }

/* [[ wikilink autocomplete popup */
.wl-pop { position: absolute; z-index: 50; min-width: 200px; max-width: 320px; background: var(--bg); border: 1px solid var(--line-2); border-radius: var(--r-sm); box-shadow: var(--shadow); padding: 4px; max-height: 240px; overflow-y: auto; }
.wl-item { padding: 6px 10px; border-radius: 6px; font-size: 14px; cursor: pointer; display: flex; justify-content: space-between; align-items: baseline; gap: 10px; }
.wl-item.sel, .wl-item:hover { background: var(--accent-weak); color: var(--accent-on-weak); }
.wl-alias { font-size: 12px; color: var(--muted); white-space: nowrap; }
.detail-head { border-bottom: 1px solid var(--line); padding-bottom: 14px; margin-bottom: 18px; }
.detail-subj { font-size: 18px; font-weight: 640; letter-spacing: -0.01em; }
.detail-meta { color: var(--muted); font-size: 14px; margin-top: 4px; }

/* Note editor */
.note-editor { display: flex; flex-direction: column; gap: 10px; margin-bottom: 18px; }
/* A note title is display-adjacent, but the system never goes above 400 — the authority
   comes from restraint, and one heavy input would be the only bold thing on screen. */
.note-title-input { font-size: 21px; font-weight: 300; letter-spacing: -0.02em; border: none; padding: 0 0 6px; border-radius: 0; border-bottom: 1px solid var(--line); }
.note-title-input:focus { box-shadow: none; border-color: var(--accent); }
.note-tags-input { border: none; padding: 2px 0; color: var(--muted); font-size: 14px; }
.note-tags-input:focus { box-shadow: none; }
.note-editor textarea { min-height: 280px; resize: vertical; line-height: 1.6; font-family: ui-monospace, "SF Mono", Menlo, monospace; font-size: 14px; }

/* Source and result, side by side. Doc 06 §1 asks for live preview; the editor was modal —
   raw text or rendered, never both, so you wrote blind and found out on save. */
.note-split { display: grid; grid-template-columns: 1fr 1fr; gap: 14px; align-items: stretch; }
.note-split.solo { grid-template-columns: 1fr; }
.note-split > textarea { min-height: 340px; }
.note-preview { min-height: 340px; overflow-y: auto; padding: 12px 14px; border: 1px solid var(--line-2); border-radius: 8px; background: var(--surface); }
.note-preview:empty::before { content: "Nothing to preview yet."; color: var(--muted); font-size: 13px; }
.note-preview-toggle { display: inline-flex; align-items: center; gap: 6px; font-size: 13px; color: var(--muted); }

/* An embedded note, inlined where ![[Note]] was written. Set apart from the surrounding prose so
   it reads as quoted material rather than as something the author wrote here. */
.note-rendered .embed { margin: 14px 0; padding: 10px 14px; border-left: 3px solid var(--accent); background: var(--accent-weak); border-radius: 0 8px 8px 0; }
.note-rendered .embed > figcaption { font-size: 12px; font-weight: 600; color: var(--accent-on-weak); margin-bottom: 6px; }
.note-rendered .embed > :last-child { margin-bottom: 0; }
.note-rendered .embed.missing { border-left-color: var(--line-2); background: transparent; }

/* Narrow windows: stack rather than squeeze two unreadable columns. */
@media (max-width: 900px) { .note-split { grid-template-columns: 1fr; } }
.note-actions { display: flex; align-items: center; gap: 12px; }

/* ── Tasks ──────────────────────────────────────────────────────────── */
.task-sort { margin-left: auto; font-size: 14px; color: var(--muted); display: flex; align-items: center; gap: 7px; }
.task-sort select { font-size: 14px; padding: 4px 8px; }
.task-tabs { display: flex; gap: 2px; border-bottom: 1px solid var(--line); margin-bottom: 14px; flex-wrap: wrap; }
.ttab { background: none; border: 0; border-bottom: 2px solid transparent; color: var(--ink-2); padding: 7px 13px 9px; cursor: pointer; font-size: 14px; display: flex; align-items: center; gap: 7px; margin-bottom: -1px; }
.ttab svg { width: 15px; height: 15px; opacity: 0.8; }
.ttab:hover { color: var(--ink); }
.ttab.active { color: var(--ink); border-bottom-color: var(--accent); font-weight: 560; }
.ttab .cnt { font-size: 12px; color: var(--muted); background: var(--surface-2); border-radius: 999px; padding: 1px 7px; font-variant-numeric: tabular-nums; min-width: 8px; text-align: center; }
.ttab .cnt:empty { display: none; }
.ttab.active .cnt { background: var(--accent-weak); color: var(--accent-on-weak); }
.task-add { display: flex; gap: 10px; margin-bottom: 16px; }
.task-add input { flex: 1; }

.task-list { gap: 1px; }
.task-row { display: flex; align-items: flex-start; gap: 10px; padding: 9px 10px; border-radius: var(--r-sm); cursor: pointer; border: 1px solid transparent; }
.task-row:hover { background: var(--surface); }
.task-row.sel { background: var(--surface); border-color: var(--line-2); }
.task-check { flex: none; width: 18px; height: 18px; margin-top: 1px; border-radius: 50%; border: 1.6px solid var(--line-2); background: var(--bg); cursor: pointer; display: grid; place-items: center; padding: 0; color: #fff; }
.task-check:hover { border-color: var(--accent); }
.task-check.on { background: var(--accent); border-color: var(--accent); }
.task-check svg { width: 12px; height: 12px; stroke-width: 3; }
.task-body { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 3px; }
.task-line1 { display: flex; align-items: center; gap: 7px; min-width: 0; }
.prio-flag { flex: none; display: grid; place-items: center; }
.prio-flag svg { width: 14px; height: 14px; }
.task-name { flex: 1; min-width: 0; font-size: 14px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.task-row.done .task-name { text-decoration: line-through; color: var(--muted); }
.task-line2 { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.task-line2 .meta-i svg { width: 13px; height: 13px; color: var(--muted); display: block; }
.proj-tag { font-size: 12px; color: var(--ink-2); background: var(--surface-2); border-radius: 999px; padding: 2px 9px; }
.due-chip { display: inline-flex; align-items: center; gap: 4px; font-size: 14px; color: var(--ink-2); white-space: nowrap; }
.due-chip svg { width: 13px; height: 13px; }
.due-chip.overdue { color: var(--accent-text); font-weight: 560; }

/* Task detail editor */
.empty-detail { color: var(--muted); font-size: 14px; padding: 30px 6px; }
.task-editor { display: flex; flex-direction: column; gap: 16px; }
.te-head { display: flex; align-items: center; gap: 12px; }
.te-title { flex: 1; font-size: 19px; font-weight: 580; border: 0; border-bottom: 1px solid transparent; padding: 4px 2px; background: none; }
.te-title:focus { outline: none; border-bottom-color: var(--line-2); }
.te-notes { min-height: 130px; resize: vertical; font-size: 14px; line-height: 1.6; padding: 11px 12px; border: 1px solid var(--line); border-radius: var(--r-sm); background: var(--bg); font-family: inherit; }
.te-fields { display: flex; flex-direction: column; gap: 10px; }
.te-field { display: grid; grid-template-columns: 130px 1fr; align-items: center; font-size: 14px; color: var(--ink-2); }
.te-field > span { display: flex; align-items: center; gap: 7px; }
.te-field > span svg { width: 15px; height: 15px; opacity: 0.75; }
.te-field select, .te-field input { font-size: 14px; padding: 6px 9px; }
.te-actions { display: flex; gap: 9px; align-items: center; padding-top: 6px; border-top: 1px solid var(--line); margin-top: 2px; }
.te-actions .danger { margin-left: auto; display: inline-flex; align-items: center; gap: 5px; }
.te-actions .danger svg { width: 13px; height: 13px; }

/* ── Search ─────────────────────────────────────────────────────────── */
.searchbar { display: flex; flex-direction: column; gap: 12px; max-width: 720px; }
.searchbar input { font-size: 15px; padding: 11px 14px; }
.pills { display: flex; gap: 7px; }
.pill { position: relative; }
.pill input { position: absolute; opacity: 0; inset: 0; cursor: pointer; }
.pill span { display: inline-block; padding: 5px 13px; border-radius: 999px; border: 1px solid var(--line-2); background: var(--surface); color: var(--ink-2); font-size: 14px; cursor: pointer; }
.pill input:checked + span { background: var(--accent-text); color: #fff; border-color: var(--accent-text); }
.results { display: flex; flex-direction: column; gap: 10px; margin-top: 20px; max-width: 760px; }

/* ── Cards / lists ──────────────────────────────────────────────────── */
.list { display: flex; flex-direction: column; gap: 10px; max-width: 760px; }
.card { background: var(--surface); border: 1px solid var(--line); border-radius: var(--r); box-shadow: var(--shadow); padding: 15px 17px; }
.card .title { font-weight: 580; }
.card .ctx { color: var(--muted); font-size: 14px; margin-top: 3px; }
.card .snippet { margin-top: 7px; color: var(--ink-2); font-size: 14px; line-height: 1.5; }
.card .score { float: right; color: var(--muted); font-size: 14px; font-variant-numeric: tabular-nums; }
.queue-card pre { background: var(--surface-2); border-radius: var(--r-sm); padding: 11px 13px; overflow: auto; font-size: 14px; margin: 10px 0 0; font-family: ui-monospace, Menlo, monospace; }
.queue-card .row { display: flex; align-items: center; gap: 10px; }
.queue-card .actions { margin-left: auto; display: flex; gap: 8px; }

/* ── Graph ──────────────────────────────────────────────────────────── */
#graph-canvas { width: 100%; flex: 1; min-height: 0; background: var(--surface); border: 1px solid var(--line); border-radius: var(--r); box-shadow: var(--shadow); }

/* ── Logs ───────────────────────────────────────────────────────────── */
.logs { display: flex; flex-direction: column; gap: 1px; max-width: 820px; }
.log {
  display: grid; grid-template-columns: 20px 130px 1fr auto; gap: 12px; align-items: center;
  padding: 9px 12px; border-radius: var(--r-sm); font-size: 14px;
}
.log:hover { background: var(--surface); }
.log .status { font-weight: 700; }
.log .status.ok { color: var(--ok); }
.log .status.err { color: var(--err); }
.log .tool { font-weight: 580; font-family: ui-monospace, Menlo, monospace; font-size: 14px; }
.log .result { color: var(--ink-2); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.log .time { color: var(--muted); font-size: 14px; font-variant-numeric: tabular-nums; }

/* ── Settings ───────────────────────────────────────────────────────── */
.settings { display: flex; flex-direction: column; gap: 16px; max-width: 640px; }
.setting .setting-head { display: flex; align-items: center; gap: 10px; margin-bottom: 6px; }
.badge { font-size: 14px; padding: 2px 9px; border-radius: 999px; background: var(--surface-2); color: var(--muted); border: 1px solid var(--line-2); }
.badge.good { background: var(--accent-weak); color: var(--accent-on-weak); border-color: var(--accent-weak); }
.field { display: flex; gap: 8px; margin-top: 10px; }
.field input { flex: 1; }
.row-actions { flex-wrap: wrap; }
.path { display: block; margin-top: 8px; background: var(--surface-2); border: 1px solid var(--line); border-radius: var(--r-sm); padding: 8px 11px; font-family: ui-monospace, Menlo, monospace; font-size: 14px; color: var(--ink-2); word-break: break-all; }

/* ── Connect / Home ─────────────────────────────────────────────────── */
.connect { display: flex; flex-direction: column; gap: 16px; max-width: 680px; }
.connect .lead { color: var(--ink-2); line-height: 1.6; margin: 0 0 4px; font-size: 14.5px; }
.code-block { background: #1c1b18; color: #e8e6e0; border-radius: var(--r-sm); padding: 14px 16px; margin: 12px 0; overflow: auto; font-family: ui-monospace, "SF Mono", Menlo, monospace; font-size: 14px; line-height: 1.55; white-space: pre; }
.how { margin: 4px 0 0; padding-left: 20px; color: var(--ink-2); line-height: 1.7; font-size: 14px; }
.how li { margin-bottom: 4px; }

.empty { color: var(--muted); text-align: center; padding: 40px; font-size: 14px; }


/* ═══════════════════════════════════════════════════════════════════════════════════════
   Component layout — calendar grids, split panes, modals, email detail, chips.
   Structure only. Colour, type and radius are the Drive Capital layer below; these rules were
   originally written inside the previous theme block, which is why replacing that theme
   collapsed the calendar into a single column.
   ═══════════════════════════════════════════════════════════════════════════════════════ */
.ghost:hover { border-color: var(--ink); background: var(--accent-weak); color: var(--ink); }
.ghost.danger { color: var(--ink); border-color: var(--line-2); }
.ghost.danger:hover { border-color: var(--ink); }

/* Active nav → inverted bone block; icons follow */
.nav-item.active { background: var(--ink); color: var(--bg); }
.nav-item.active svg { color: var(--bg); }
.nav-item:hover { background: var(--accent-weak); color: var(--ink); }
.nav-item svg { color: var(--ink-2); }

/* Chips / pills / counts → bordered text, no fill */
.tag-chip, .proj-tag, .pill, .toolchip, .tab-count, .ln-count, .cnt, .ttab .cnt, .badge {
  background: none !important; border: 1px solid var(--line-2); color: var(--ink-2);
}
.tag-chip { color: var(--ink); cursor: pointer; }
.tag-chip:hover { background: var(--ink) !important; color: var(--bg); }
.nav-item .count, .acct .dot, .count { background: var(--ink) !important; color: var(--bg); border: 0; }

/* Priority flags + overdue → monochrome (bone; emphasis via weight/underline) */
.prio-flag.p1, .prio-flag.p2, .prio-flag.p3 { color: var(--ink); }
.due-chip.overdue { color: var(--ink); font-weight: 400; text-decoration: underline; }
.m-title, .acct-email { color: var(--ink); }

/* Tabs — bone underline + active */
.tab.active, .ttab.active { border-bottom-color: var(--ink); color: var(--ink); }
.tab.active .tab-count, .ttab.active .cnt { background: none !important; color: var(--ink); border-color: var(--ink); }

/* Inputs / selects / code → black with a bone hairline */
input, textarea, select { background: var(--bg); color: var(--ink); border: 1px solid var(--line-2); }
input:focus, textarea:focus, select:focus { border-color: var(--ink); outline: none; }
input::placeholder, textarea::placeholder { color: var(--muted); }
.code-block, .path, code, pre { background: var(--surface-2); }

/* Lists / panels — hover via faint bone, square bordered panes */
.li:hover { background: var(--accent-weak); }
.li.active, .task-row.sel { background: var(--accent-weak); }
.pane-detail, .card { border: 1px solid var(--line); }

/* Wikilinks / outgoing / AI button → bordered monochrome */
.reader .wikilink, .ln-out, .ai-act { color: var(--ink); background: none; border: 1px solid var(--line-2); }
.reader .wikilink:hover, .ln-out:hover, .ai-act:hover:not(:disabled) { background: var(--ink); color: var(--bg); }
.reader .wikilink.unresolved, .ln-out.broken { color: var(--muted); background: none; border: 1px dashed var(--line-2); }
.task-check { border: 1.6px solid var(--line-2); background: var(--bg); color: var(--bg); }
.task-check.on { background: var(--ink); border-color: var(--ink); }
.task-check.on svg { color: var(--bg); }

/* status pips */
.dot.online { background: var(--ink); }
.dot.offline { background: var(--muted); }
.unread-dot { background: var(--ink); }

/* Dynamic film grain over the void — cthdrl's background isn't a flat black, it breathes. */
.noise {
  position: fixed; inset: 0; z-index: 9999; pointer-events: none; opacity: 0.05;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='180' height='180'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2' stitchTiles='stitch'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3C/filter%3E%3Crect width='180' height='180' filter='url(%23n)'/%3E%3C/svg%3E");
  animation: grain 0.5s steps(4) infinite;
}
@keyframes grain {
  0% { background-position: 0 0; } 25% { background-position: -28px 14px; }
  50% { background-position: 18px -22px; } 75% { background-position: -14px -10px; } 100% { background-position: 22px 18px; }
}
@media (prefers-reduced-motion: reduce) { .noise { animation: none; } }

/* Email body = an off-white "sheet" that fills the whole pane (header pinned above it). */
#email-detail { padding: 0; display: flex; flex-direction: column; overflow-y: auto; overflow-x: hidden; }
#email-detail .detail-head { padding: 16px 20px; flex: none; }
#email-detail .placeholder { padding: 30px; }
/* Sized to its content by JS; the detail pane owns the scrolling. Not flexed to fill — see
   renderEmailFrame for why that collapsed to 94px whenever an invite card shared the pane. */
.email-frame {
  display: block; width: 100%; border: 0; background: var(--bg); border-top: 1px solid var(--line);
  /* `flex: none` is load-bearing. The detail pane is a column flex container, so a default
     flex-shrink of 1 squeezes the explicit height JS sets back down to whatever is left — which
     is how a 585px message ended up in a 94px frame. */
  flex: none;
}

/* ── Email detail: icon action buttons + collapsible headers ─────────────── */
.detail-actions { display: flex; gap: 6px; align-items: center; margin-bottom: 12px; float: none; margin-left: 0; }
.meta-who { white-space: nowrap; }
.iconbtn {
  display: inline-flex; align-items: center; gap: 6px; justify-content: center;
  min-width: 30px; height: 30px; padding: 0 9px;
  background: none; border: 1px solid var(--line-2); color: var(--ink-2); cursor: pointer;
  transition: border-color .12s, color .12s;
}
.iconbtn:hover { border-color: var(--ink); color: var(--ink); }
.iconbtn svg { width: 15px; height: 15px; flex: none; }
.iconbtn span { font-size: 12px; letter-spacing: .02em; }
.iconbtn.ai-act { margin-left: auto; }
.detail-subj { font-size: 15px; font-weight: 400; margin: 2px 0 9px; line-height: 1.25; }
.meta-toggle {
  display: flex; align-items: baseline; gap: 10px; width: 100%;
  background: none; border: 0; border-bottom: 1px solid var(--line); padding: 3px 0 7px;
  cursor: pointer; text-align: left; color: var(--ink); font-size: 14px;
}
.meta-who { font-weight: 400; }
.meta-addr { font-size: 14px; }
.meta-date { margin-left: auto; font-size: 14px; white-space: nowrap; }
.meta-toggle .chev { font-size: 12px; transition: transform .12s; margin-left: 4px; }
.meta-toggle.open .chev { transform: rotate(180deg); }
.email-hdr { margin: 9px 0 2px; }
.attachments { margin-top: 10px; }
.attachments .att svg { width: 12px; height: 12px; vertical-align: -2px; margin-right: 2px; }

/* ── Resizable list / detail columns (drag the splitter; width persists) ──── */
.split { grid-template-columns: var(--col, 320px) 18px 1fr; gap: 0; }
.splitter { cursor: col-resize; position: relative; align-self: stretch; touch-action: none; }
.splitter::before { content: ""; position: absolute; left: 50%; top: 0; bottom: 0; width: 1px; background: var(--line); transform: translateX(-0.5px); transition: background .1s, width .1s; }
.splitter:hover::before, body.col-resizing .splitter::before { background: var(--ink); width: 2px; }
body.col-resizing { cursor: col-resize; user-select: none; }

/* Background-sync interval control (Settings → Gmail) */
.sync-interval { display: flex; align-items: center; justify-content: space-between; gap: 12px; }
.sync-interval label { flex: 1; }
select { background: var(--bg); color: var(--ink); border: 1px solid var(--line-2); padding: 6px 10px; font: inherit; cursor: pointer; }
select:focus { outline: none; border-color: var(--ink); }

/* ── Calendar (month view) ───────────────────────────────────────────────── */
.cal-weekdays { display: grid; grid-template-columns: repeat(7, 1fr); border: 1px solid var(--line); border-bottom: 0; }
.cal-weekdays > div { padding: 6px 8px; font-size: 12px; color: var(--muted); text-transform: uppercase; letter-spacing: .05em; border-right: 1px solid var(--line); }
.cal-weekdays > div:last-child { border-right: 0; }
.cal-grid { flex: 1; min-height: 380px; display: grid; grid-template-columns: repeat(7, 1fr); grid-auto-rows: 1fr; border: 1px solid var(--line); }
.cal-cell { border-right: 1px solid var(--line); border-bottom: 1px solid var(--line); padding: 4px 5px; overflow: hidden; cursor: pointer; display: flex; flex-direction: column; gap: 3px; }
.cal-cell:nth-child(7n) { border-right: 0; }
.cal-cell:hover { background: var(--surface-2); }
.cal-cell.out { opacity: .38; }
.cal-cell.today .cal-daynum { background: var(--ink); color: var(--bg); }
.cal-daynum { font-size: 14px; font-variant-numeric: tabular-nums; width: 19px; height: 19px; display: grid; place-items: center; align-self: flex-start; }
.cal-evs { display: flex; flex-direction: column; gap: 2px; overflow: hidden; }
.cal-ev { text-align: left; background: none; border: 1px solid var(--line-2); color: var(--ink); font-size: 12px; padding: 1px 4px; cursor: pointer; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.cal-ev:hover { border-color: var(--ink); }
.cal-ev.dirty { border-style: dashed; }   /* locally edited, not yet pushed to Google */
.cal-ev b { font-weight: 400; }
.cal-more { font-size: 12px; color: var(--muted); padding-left: 4px; }

/* Event modal */
.modal { position: fixed; inset: 0; z-index: 1000; background: rgba(0, 0, 0, 0.28); display: grid; place-items: center; }
.modal-card { width: 360px; max-width: 92vw; background: var(--bg); border: 1px solid var(--ink); padding: 20px; display: flex; flex-direction: column; gap: 10px; }
.modal-card h3 { font-size: 14px; margin-bottom: 2px; }
.modal-card input, .modal-card textarea { width: 100%; }
.ev-row { display: flex; align-items: center; gap: 8px; }
.ev-row > label { font-size: 14px; color: var(--muted); min-width: 38px; }
.ev-times input { flex: 1; }
.ev-dash { color: var(--muted); }
.ev-allday { display: flex; align-items: center; gap: 7px; font-size: 14px; color: var(--ink-2); }
.ev-allday input { width: auto; }
#event-modal.allday .ev-times { display: none; }
.modal-actions { display: flex; gap: 8px; margin-top: 4px; }
.modal-actions .danger { margin-left: auto; }

/* Linked tasks/events panel (email) + backlink chips */
.linked { display: flex; flex-wrap: wrap; gap: 6px; align-items: center; margin-top: 10px; }
.linked:empty { display: none; }
.linked-label { font-size: 12px; text-transform: uppercase; letter-spacing: .05em; color: var(--muted); margin-right: 2px; }
.link-chip { display: inline-flex; align-items: center; gap: 5px; background: none; border: 1px solid var(--line-2); color: var(--ink); font-size: 14px; padding: 3px 8px; cursor: pointer; }
.link-chip:hover { border-color: var(--ink); }
.link-chip svg { width: 11px; height: 11px; }

/* Live sync progress (Outlook-style counter + thin bar) */
.sync-status { font-size: 14px; color: var(--accent-text); font-variant-numeric: tabular-nums; align-self: center; margin-right: 6px; white-space: nowrap; }
.sync-bar { height: 3px; background: var(--line); margin: 4px 0 14px; overflow: hidden; }
.sync-bar-fill { display: block; height: 100%; width: 0; background: var(--ink); transition: width .18s ease; }

/* ── Calendar: view switcher + day/week time grid + event detail card ─────── */
.cal-month-wrap, .cal-time-wrap { flex: 1; min-height: 0; display: flex; flex-direction: column; }
.seg { display: inline-flex; border: 1px solid var(--line-2); }
.seg-btn { background: none; border: 0; border-right: 1px solid var(--line-2); color: var(--ink-2); padding: 5px 11px; cursor: pointer; font: inherit; font-size: 14px; }
.seg-btn:last-child { border-right: 0; }
.seg-btn:hover:not(.active) { color: var(--ink); }
.seg-btn.active { background: var(--ink); color: var(--bg); }

.cal-time-head { display: grid; border: 1px solid var(--line); border-bottom: 0; }
.cal-time-head > div { padding: 6px 8px; border-right: 1px solid var(--line); font-size: 14px; }
.cal-time-head > div:last-child { border-right: 0; }
.cal-th-wd { color: var(--muted); text-transform: uppercase; font-size: 12px; }
.cal-th.today .cal-th-dn { color: var(--ink); font-weight: 400; }
.cal-allday { display: grid; border: 1px solid var(--line); border-bottom: 0; min-height: 24px; }
.cal-allday-gutter { font-size: 12px; color: var(--muted); padding: 0 6px; text-transform: uppercase; letter-spacing: .04em; border-right: 1px solid var(--line); align-self: center; }
.cal-allday-cell { border-right: 1px solid var(--line); padding: 2px 3px; display: flex; flex-direction: column; gap: 2px; }
.cal-allday-cell:last-child { border-right: 0; }

.cal-time-scroll { flex: 1; min-height: 0; overflow-y: auto; display: grid; grid-template-columns: 52px 1fr; border: 1px solid var(--line); }
.cal-hour { border-bottom: 1px solid var(--line); position: relative; }
.cal-hour span { position: absolute; top: -7px; right: 6px; font-size: 12px; color: var(--muted); background: var(--bg); padding: 0 3px; }
.cal-time-cols { display: grid; position: relative; }
.cal-daycol { position: relative; border-right: 1px solid var(--line); }
.cal-daycol:last-child { border-right: 0; }
.cal-daycol.today { background: rgba(231, 222, 209, 0.035); }
.cal-gridline { position: absolute; left: 0; right: 0; border-top: 1px solid var(--line); pointer-events: none; }
.cal-nowline { position: absolute; left: 0; right: 0; border-top: 2px solid var(--ink); z-index: 4; pointer-events: none; }
.cal-block { position: absolute; overflow: hidden; background: var(--bg); border: 1px solid var(--ink); color: var(--ink); font-size: 12px; text-align: left; padding: 1px 4px; cursor: pointer; z-index: 2; line-height: 1.25; }
.cal-block:hover { z-index: 5; }
.cal-block.dirty { border-style: dashed; }
.cal-block b { display: block; font-weight: 400; font-size: 12px; color: var(--ink-2); }

/* Read-only event detail card */
.detail-card { gap: 9px; }
.ed-head { display: flex; align-items: center; gap: 9px; }
.ed-head h3 { font-size: 14px; }
.ed-dirty { font-size: 12px; border: 1px dashed var(--line-2); color: var(--muted); padding: 1px 6px; white-space: nowrap; }
.ed-when { font-size: 14px; color: var(--ink); }
.ed-loc { font-size: 14px; color: var(--ink-2); }
.ed-loc:not([hidden])::before { content: "⌖ "; color: var(--muted); }
.ed-desc { font-size: 14px; color: var(--ink-2); line-height: 1.5; white-space: pre-wrap; max-height: 240px; overflow: auto; border-top: 1px solid var(--line); padding-top: 9px; }

/* Event quick-add (AI natural-language) + clickable links in descriptions */
.quick-add { display: flex; gap: 8px; }
.quick-add input { flex: 1; border-style: dashed; }
.ed-desc a.ext-link, .link a { color: var(--ink); text-decoration: underline; text-underline-offset: 2px; cursor: pointer; }
.ed-desc a.ext-link:hover { text-decoration: none; background: var(--accent-weak); }

/* Event detail extras: type badge, conference link, reminder, guests */
.ed-type { font-size: 12px; text-transform: uppercase; letter-spacing: .05em; border: 1px solid var(--line-2); color: var(--ink-2); padding: 1px 6px; white-space: nowrap; }
.ed-conf { display: inline-block; font-size: 14px; color: var(--ink); border: 1px solid var(--ink); padding: 5px 12px; text-decoration: none; width: max-content; }
.ed-conf:hover { background: var(--ink); color: var(--bg); }
.ed-remind { font-size: 14px; color: var(--ink-2); }
.ed-guests { display: flex; flex-wrap: wrap; gap: 6px; align-items: center; }
.guest-chip { font-size: 14px; color: var(--ink-2); border: 1px solid var(--line-2); padding: 2px 7px; }
.cal-block .cal-conf, .cal-ev .cal-conf { font-weight: 400; }
.ed-repeat { font-size: 14px; color: var(--ink-2); }

/* Calendar invitation card (rendered above the email body, in app chrome) */
.invite-card { margin: 0 20px 14px; padding: 14px 16px; border: 1px solid var(--line-2); background: var(--surface-2); color: var(--ink); flex: none; }
.invite-card .inv-head { display: flex; align-items: center; gap: 8px; margin-bottom: 6px; }
.invite-card .inv-badge { font-size: 12px; letter-spacing: .08em; text-transform: uppercase; border: 1px solid var(--line-2); padding: 1px 6px; color: var(--ink-2); }
.invite-card .inv-title { font-weight: 400; font-size: 14px; }
.invite-card .inv-when { font-size: 14px; margin-bottom: 6px; }
.invite-card .inv-row { font-size: 14px; margin-bottom: 3px; }
.invite-card .inv-join-row { margin: 9px 0; }
.invite-card .inv-join { display: inline-block; border: 1px solid var(--ink); padding: 5px 12px; cursor: pointer; font-size: 14px; }
.invite-card .inv-join:hover { background: var(--ink); color: var(--bg); }
.invite-card .inv-rsvp { display: flex; align-items: center; flex-wrap: wrap; gap: 6px; margin-top: 10px; }
.invite-card .inv-rsvp-label { font-size: 14px; color: var(--muted); margin-right: 2px; }
.invite-card .inv-rsvp .chosen { background: var(--ink); color: var(--bg); }
.invite-card .inv-status { margin-left: 4px; font-size: 14px; }

/* Engine status + manual-setup disclosure on the Connect panel */
.engine-line { display: flex; align-items: center; gap: 8px; margin-top: 10px; }
.manual-setup { margin-top: 14px; border-top: 1px solid var(--line); padding-top: 10px; }
.manual-setup summary { cursor: pointer; user-select: none; }
.manual-setup summary:hover { color: var(--ink); }
.manual-setup > * { margin-top: 8px; }
.login-item { margin-top: 10px; }

/* Index health panel */
/* Cells carry their own border so a part-filled last row leaves no phantom tile. */
.health-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(120px, 1fr)); gap: 8px; margin: 10px 0; }
.health-cell { background: var(--bg); border: 1px solid var(--line); padding: 9px 11px; display: flex; flex-direction: column; gap: 2px; }
.health-cell.warn { background: var(--accent-weak); }
.health-v { font-size: 17px; font-variant-numeric: tabular-nums; }
.health-l { font-size: 12px; text-transform: uppercase; letter-spacing: .05em; color: var(--muted); }
.health-s { font-size: 12px; }
.health-sources { display: flex; flex-direction: column; gap: 4px; margin-bottom: 8px; }
.health-src { display: flex; justify-content: space-between; gap: 12px; font-size: 14px; border-bottom: 1px solid var(--line); padding-bottom: 4px; }
.warn-text { color: var(--ink); border-left: 2px solid var(--accent); padding-left: 8px; }
.model-row { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; margin-top: 10px; }

/* ── Narrow windows ──────────────────────────────────────────────────── */
/* Icons alone still identify eight familiar sections; a clipped label identifies nothing. */
@media (max-width: 620px) {
  .nav-item { flex: 0 1 46px; padding: 7px 4px; }
  .nav-item span { display: none; }
  .palette-trigger kbd { display: none; }
  .conn span { display: none; }
}
@media (max-width: 420px) {
  .ascii-logo { display: none; }
}

/* ═══════════════════════════════════════════════════════════════════════════════════════
   Drive Capital — component layer
   Cream canvas · Voltage Blue the only chromatic voice · flat surfaces · hairline Ash rules ·
   60px pills, outlined never filled · nothing above weight 400.
   ═══════════════════════════════════════════════════════════════════════════════════════ */

/* Flat, everywhere. Squared surfaces so nothing mixes a small radius with the 60px pills. */
* { box-shadow: none !important; }
.card, .view, .split, .pane-list, .reader, textarea, input, select, pre, canvas { border-radius: 0 !important; }

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

/* ── Type ──────────────────────────────────────────────────────────────────────────────── */
/* The didone earns its keep only at size; the page title is where the system announces itself. */
.topbar h1 { font-family: var(--font-display); font-weight: 200; font-size: 30px; line-height: 1; letter-spacing: -0.02em; }
/* One header row, the way Calendar already did it. Email and Tasks each spent a whole extra
   row on their tab strip — 64px and 116px of chrome above the content respectively. */
.topbar { align-items: center; gap: 16px; margin-bottom: 12px; flex-wrap: wrap; }
.topbar h1 { flex: none; }
/* Inline in the header, so no bottom border or margin of their own. */
.topbar .tabs, .topbar .task-tabs {
  border-bottom: 0; margin-bottom: 0; flex-wrap: nowrap; gap: 2px;
}
.topbar .tab, .topbar .ttab { border-bottom: 0; padding: 5px 10px; border-radius: var(--r-pill); }
.topbar .tab.active, .topbar .ttab.active {
  border-bottom: 0; color: var(--accent-text); background: rgba(0, 110, 255, 0.07);
}
.topbar .ttab svg { width: 14px; height: 14px; }
/* Sort sits at the far end regardless of markup order. */
.task-sort { margin-left: auto; }
/* The add-task row is a single control, not a section. */
.task-add { margin-bottom: 10px; }
.task-add input { padding: 6px 11px; }
.topbar .muted { font-size: 16px; }

/* Empty states are display type on open cream. §7 wants a screen that reads as finished, and
   this is the one place the hairline serif does the talking. */
/* Page-level empty states get the display treatment — they are the whole screen, and §6.5 wants
   the quiet Brief to be the best-looking thing in the app. */
.empty, .quiet-line {
  font-family: var(--font-display); font-weight: 200; font-size: 38px; line-height: 1;
  letter-spacing: -0.02em; color: var(--ink); text-align: center;
}
/* A hint inside a detail pane is not a page. At 38px it shouts louder than the content it is
   waiting for, which is the wrong emphasis for a placeholder. */
.empty-detail, .placeholder {
  font-family: var(--font); font-weight: 300; font-size: 16px; line-height: 1.4;
  letter-spacing: -0.02em; color: var(--muted); text-align: center; padding: 40px 24px;
}
.empty { padding: 56px 24px; }
.quiet { padding: 72px 0 84px; }
/* Explanatory copy under an empty state is still body copy: past ~600px the eye loses the line
   and it reads as a caption stretched across a page. The display line above it is exempt — that
   is the one thing meant to span. */
.quiet p:not(.quiet-line), .empty p:not(.empty-detail) {
  max-width: 560px; margin-left: auto; margin-right: auto; text-align: center;
}

/* Section labels: whisper-weight grotesk, not the small-caps bold of a dashboard. */
.brief-section > h2, .brief-section summary h2, .graph-wrap summary h2 {
  font-size: 16px; font-weight: 300; letter-spacing: 0.06em; text-transform: uppercase;
  color: var(--muted); margin: 0 0 14px;
}

/* ── Buttons: outlined pills, always. Never filled. ────────────────────────────────────── */
button.primary, button.ghost, .primary, .ghost, .palette-trigger, .nav-item {
  border-radius: var(--r-pill) !important;
}
.primary {
  background: transparent; color: var(--accent-text);
  border: 1px solid var(--accent); font-weight: 400; padding: 9px 22px;
}
.primary:hover { background: rgba(0, 110, 255, 0.06); }
.ghost {
  background: transparent; color: var(--ink); border: 1px solid var(--line-2); padding: 9px 22px;
}
.ghost:hover { border-color: var(--accent); color: var(--accent-text); }
.ghost.danger { color: var(--err); border-color: var(--line-2); }
.ghost.danger:hover { border-color: var(--err); }
/* `.sm` is a size utility, used on spans and paragraphs as often as on buttons — so the compact
   button padding is scoped to buttons. Unscoped it indents body copy across the whole app. */
button.sm, .primary.sm, .ghost.sm { padding: 6px 16px; }

/* ── Dock: type-led. ───────────────────────────────────────────────────────────────────── */
/* Icon over label, both quiet. The hairline icons sit with the type rather than against it —
   which the previous 8-bit glyphs did not, and why the dock was words-only before. */
.dock .nav-item { flex-direction: column; gap: 3px; padding: 5px 13px; }
.dock .nav-item svg { display: block; width: 19px; height: 19px; }
.dock { background: var(--bg); padding: 5px 7px; }
.nav-item {
  flex: 0 1 auto; padding: 6px 14px; font-size: 12px; font-weight: 300; line-height: 1.25;
  letter-spacing: -0.01em; color: var(--muted); border: 1px solid transparent;
}
.nav-item:hover { background: none; color: var(--ink); }
.nav-item.active { background: none; color: var(--accent-text); border-color: var(--accent); font-weight: 400; }
/* Icons fill with currentColor, so they inherit the item's colour and never declare their own.
   The old theme inverted the active icon against a black fill; remapped to cream that became a
   cream icon on a cream ground — present, sized, and invisible. */
.nav-item svg, .nav-item.active svg, .nav-item:hover svg { color: inherit; }
.dock-home { font-weight: 400; }

/* ── Top rail ──────────────────────────────────────────────────────────────────────────── */
.topline { background: var(--bg); border-bottom: 1px solid var(--line); padding: 8px 18px; }
.palette-trigger {
  border: 1px solid var(--line-2); background: transparent; color: var(--muted);
  font-weight: 300; font-size: 16px; padding: 7px 18px;
}
.palette-trigger:hover { border-color: var(--accent); color: var(--accent-text); }
.palette-trigger kbd { border-color: var(--line); font-size: 14px; }

/* ── Surfaces: flat on cream, distinguished only by an Ash hairline. ───────────────────── */
.card, .brief-item, .person {
  background: transparent; border: 1px solid var(--line);
}
/* An overlay is not a card. Cards sit flat on cream and are right to be transparent; the palette
   floats above the page, so transparent meant the whole app showed through its results. */
.palette {
  background: var(--bg);
  border: 1px solid var(--ink);
  border-radius: 0 !important;
}
.palette-backdrop { background: rgba(0, 0, 0, 0.35); }
/* Selection needs to be legible against cream, and surface-2 is a half-step — nearly invisible
   here. The accent tint is the only thing in the system with enough separation. */
.palette-row:hover, .palette-row.sel { background: rgba(0, 110, 255, 0.08); }
.palette-row.sel { box-shadow: inset 2px 0 0 var(--accent) !important; }
.palette-results { padding: 8px; max-height: 52vh; }
.palette-row-title { font-size: 16px; font-weight: 300; }
.palette-row-sub { font-size: 14px; }
.brief-item:hover, .person:hover { border-color: var(--accent); }
.brief-item { padding: 11px 14px; }
.brief-list { gap: 0; }
.brief-list .brief-item + .brief-item { border-top: none; }
.brief-item-title { font-size: 18px; font-weight: 300; letter-spacing: -0.02em; }
.brief-reason { font-size: 16px; font-weight: 300; color: var(--ink-2); margin-top: 4px; }
.brief-meta { font-size: 16px; font-weight: 300; }

/* ── Chips, tags, counts: outlined pills in the one accent. ────────────────────────────── */
.tag-chip, .proj-tag, .pill, .toolchip, .tab-count, .ln-count, .cnt, .ttab .cnt, .badge,
.brief-carried, .brief-draft {
  background: transparent !important; border: 1px solid var(--line-2); color: var(--ink-2);
  border-radius: var(--r-pill) !important; padding: 2px 12px; font-size: 14px; font-weight: 300;
}
.tag-chip:hover { border-color: var(--accent); color: var(--accent-text); }
.badge.good, .brief-draft { border-color: var(--accent); color: var(--accent-text); }
.brief-carried { border-color: var(--line-2); color: var(--muted); }

/* ── Rules and structure ───────────────────────────────────────────────────────────────── */
.splitter { background: var(--line); }
.tab.active, .ttab.active { border-bottom-color: var(--accent); color: var(--accent-text); }
.dot.online { background: var(--accent); }
.dot.offline { background: var(--muted); }
.prio-flag.p1, .prio-flag.p2, .prio-flag.p3 { color: var(--accent-text); }
.due-chip.overdue { color: var(--err); text-decoration: underline; }

/* ── Inputs: a hairline rule, not a box. ───────────────────────────────────────────────── */
input, textarea, select {
  background: transparent; color: var(--ink); border: 1px solid var(--line-2);
  padding: 9px 12px; font-weight: 300; letter-spacing: -0.02em;
}
input:focus, textarea:focus, select:focus { outline: none; border-color: var(--accent); }
.palette input { border: none; border-bottom: 1px solid var(--line); font-size: 21px; font-weight: 300; }

/* Code stays monospace — it is content, and proportional type misreads it. */
pre, code, .code-block, .logs, .log .tool {
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 14px; letter-spacing: 0;
}
.log .status { font-weight: 400; color: var(--accent-text); }
.log .status.err { color: var(--err); }

/* ── Generous margins. §7: "generous margins, one column, no chrome." ──────────────────── */
.view { padding: 24px 36px 104px; }
.view[data-view="home"] #home-brief, .view[data-view="home"] .quiet { max-width: 900px; }
/* Body copy stays in a narrow column — beyond ~600px the editorial reading rhythm goes. */
.brief-reason, .lead, .setting p { max-width: 600px; }

@media (max-width: 900px) {
  /* Keep the bottom clearance: the dock floats over the content at every width. */
  .view { padding: 18px 20px 104px; }
}
@media (max-width: 620px) {
  .nav-item { padding: 7px 10px; font-size: 14px; }
  .palette-trigger kbd { display: none; }
  .conn span { display: none; }
}

/* ── Active states: blue, and outlined rather than filled. ─────────────────────────────── */
/* The restored layout block inherited these from a black canvas, where an ink fill read as an
   inverted highlight. On cream it reads as a black box — twice wrong: the system fills nothing,
   and Voltage Blue is its only chromatic voice. */
.seg-btn.active { background: transparent; color: var(--accent-text); border-color: var(--accent); }
/* Today is the whole cell, tinted — the same language a selected row uses, so "where I am" reads
   the same way everywhere. A ringed number was a second idiom for the same idea, and small
   enough to hunt for in a 42-cell grid. */
.cal-cell.today { background: rgba(0, 110, 255, 0.07); }
.cal-cell.today .cal-daynum { background: transparent; color: var(--accent-text); font-weight: 400; }
.task-check.on { background: var(--accent); border-color: var(--accent); }
.unread-dot { background: var(--accent); }
/* The drag handle darkens; it does not turn blue. The accent means "selected", "active" or
   "linked" — using it for "your pointer is here" put a 700px blue rule beside the message
   whenever the cursor crossed the divider, which read as a piece of UI rather than a hover. */
.splitter:hover::before, body.col-resizing .splitter::before { background: var(--ink-2); width: 2px; }
/* The handle is a hairline plus an invisible grab area, not an 18px grey band between the panes. */
.splitter { background: transparent; }
.sync-bar-fill { background: var(--accent); }
.tag-chip:hover { background: transparent !important; color: var(--accent-text); border-color: var(--accent); }
.nav-item .count, .count { background: transparent !important; color: var(--accent-text); border: 1px solid var(--accent) !important; }
.acct .dot { background: var(--accent) !important; }
.reader .wikilink:hover, .ln-out:hover, .ai-act:hover:not(:disabled),
.ed-conf:hover, .invite-card .inv-join:hover, .invite-card .inv-rsvp .chosen {
  background: transparent; color: var(--accent-text); border-color: var(--accent);
}
/* Links are the accent's other job. */
a, .reader a, .wikilink { color: var(--accent-text); text-decoration: none; }
a:hover, .reader a:hover { text-decoration: underline; }

/* ── Settings: tabular ─────────────────────────────────────────────────────────────────── */
/* Each setting was a padded card in a vertical stack — 2,800px of scrolling for eleven of them.
   As rows with a fixed label column they read as a table and fit the screen, which is what
   settings are: a list of named things and their values. Hairline rules do the separating, so
   nothing needs a box. */
.settings { max-width: 940px; display: flex; flex-direction: column; }
.card.setting {
  display: grid;
  grid-template-columns: minmax(150px, 210px) 1fr;
  column-gap: 28px;
  row-gap: 2px;
  align-items: start;
  padding: 14px 0;
  border: 0;
  border-bottom: 1px solid var(--line);
}
.setting > *:not(.setting-head) { grid-column: 2; margin-top: 0; }
/* Pinned to the first row rather than spanning. `grid-row: 1 / span 99` looks like "fill the
   column" and actually creates 99 implicit rows, each contributing a row-gap — it made the page
   more than twice as tall as the cards it replaced. */
.setting .setting-head { grid-column: 1; grid-row: 1; display: block; margin: 0; }
.setting .setting-head h3 { font-size: 16px; font-weight: 400; }
.setting .setting-head .badge { margin-top: 6px; display: inline-block; }
/* Descriptions sit with their control rather than above the fold of a card. */
.setting p { margin: 0 0 6px; max-width: 62ch; }
.setting .field { margin-top: 8px; }
.setting details { margin-top: 8px; }
.setting:last-child { border-bottom: 0; }

/* Below the two-column threshold it stacks, because a 150px label column and a text field do
   not both fit — and a settings screen that needs horizontal scrolling is worse than a tall one. */
@media (max-width: 720px) {
  .card.setting { grid-template-columns: 1fr; }
  .setting > *, .setting .setting-head { grid-column: 1; grid-row: auto; }
  .setting .setting-head { margin-bottom: 4px; }
}

/* ── Keyboard reference ────────────────────────────────────────────────────────────────── */
/* Shortcuts live here rather than in the chrome. A cheat sheet printed beside the toolbar is
   read once and then becomes furniture — §7 asks for subtraction, and the palette trigger
   already shows ⌘K where it is actually useful, on the control it operates. */
.keys { display: grid; grid-template-columns: auto 1fr; gap: 6px 16px; margin: 4px 0 0; align-items: baseline; }
.keys dt { margin: 0; display: flex; gap: 4px; }
.keys dd { margin: 0; color: var(--ink-2); font-size: 14px; }
.keys kbd {
  font-family: inherit; font-size: 12px; color: var(--ink-2);
  border: 1px solid var(--line-2); border-radius: 4px; padding: 1px 7px; background: transparent;
  min-width: 22px; text-align: center;
}

/* ── Research ──────────────────────────────────────────────────────────────────────────── */
.research-ask { display: flex; gap: 8px; flex: 1; min-width: 260px; margin-left: auto; max-width: 620px; }
.research-ask input { flex: 1; padding: 6px 11px; }

.research-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(230px, 1fr)); gap: 10px; }
.research-card {
  text-align: left; background: transparent; border: 1px solid var(--line);
  border-radius: 0 !important; padding: 14px 16px; cursor: pointer; display: block; width: 100%;
}
.research-card:hover { border-color: var(--accent); }
/* A page that has moved gets a heavier rule, not a number. Invariant #7 rules out counts —
   the mark says "something changed", and you find out what by opening it. */
.research-card.fresh { border-left: 2px solid var(--accent); }
.research-card-head { display: flex; align-items: center; gap: 8px; }
.research-card-title { font-size: 16px; font-weight: 300; color: var(--ink); flex: 1; letter-spacing: -0.02em; }
.research-mark { width: 7px; height: 7px; border-radius: 50%; background: var(--accent); flex: none; }
.research-pin-mark svg { width: 13px; height: 13px; color: var(--muted); }
.research-card-meta { font-size: 12px; color: var(--muted); margin-top: 6px; }

.research-page-head { align-items: center; gap: 14px; }
.research-page-head h2 { font-family: var(--font-display); font-weight: 200; font-size: 26px; letter-spacing: -0.02em; }
#research-question { margin: 0 0 14px; max-width: 62ch; }

/* Bars, drawn in CSS from the same tally that fills the table — so the chart and the numbers
   under it can never disagree. */
.research-chart { margin-bottom: 18px; }
.bars { display: flex; flex-direction: column; gap: 5px; max-width: 620px; }
.bar-row { display: grid; grid-template-columns: minmax(90px, 170px) 1fr auto; gap: 10px; align-items: center; }
.bar-label { font-size: 14px; color: var(--ink-2); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.bar-track { height: 9px; background: var(--line); display: block; }
.bar-fill { display: block; height: 100%; background: var(--accent); }
.bar-count { font-size: 14px; color: var(--muted); font-variant-numeric: tabular-nums; }

.research-table { width: 100%; border-collapse: collapse; font-size: 14px; }
.research-table th {
  text-align: left; font-weight: 400; color: var(--muted); font-size: 12px;
  text-transform: uppercase; letter-spacing: 0.06em; padding: 6px 10px 6px 0;
  border-bottom: 1px solid var(--line);
}
.research-table td { padding: 8px 10px 8px 0; border-bottom: 1px solid var(--line); vertical-align: top; }
.research-table tbody tr { cursor: pointer; }
.research-table tbody tr:hover td { color: var(--accent-text); }
.research-table .src { color: var(--muted); }

.research-finding { padding: 10px 0; border-bottom: 1px solid var(--line); cursor: pointer; }
.research-finding:hover .research-finding-src { color: var(--accent-text); }
.research-finding-src { font-size: 15px; color: var(--ink); }
.research-finding-sum { font-size: 14px; color: var(--ink-2); margin-top: 3px; max-width: 70ch; }

/* The dock mark: a dot, never a number. */
.dock-new { width: 5px; height: 5px; border-radius: 50%; background: var(--accent); display: block; margin-top: 1px; }
.dock-new[hidden] { display: none; }

/* ── Readability ───────────────────────────────────────────────────────────────────────── */
/* The reference sets everything at weight 300, which is its signature at 16px and up. Below
   that a hairline stroke stops being restraint and starts being hard to read, so the two small
   tiers step to 400 — still inside the system's ceiling. */
.sm, .brief-card-meta, .research-card-meta, .bar-count, .li-time, .keys dd,
.muted.sm, .person-stats, .brief-meta, .research-finding-sum, .palette-row-sub {
  font-weight: 400;
}
/* Accent text is words, so it uses the darkened blue; borders and marks keep the exact brand
   blue, where 4.27:1 clears the 3:1 that non-text needs. */
a, .reader a, .wikilink, .brief-draft, .sync-status,
.research-table tbody tr:hover td, .nav-item.active, .tab.active, .ttab.active, .seg-btn.active {
  color: var(--accent-text);
}
.primary { color: var(--accent-text); }
.ghost:hover { color: var(--accent-text); }

/* ── People ────────────────────────────────────────────────────────────────────────────── */
.people-groups { margin-bottom: 20px; max-width: 620px; }
.people-groups .bar-row { cursor: pointer; }
.people-groups .bar-row:hover .bar-label { color: var(--accent-text); }

.person { position: relative; }
/* Someone waiting on you is the one thing here worth a mark. Volume is already in the numbers. */
.person.waiting { border-left: 2px solid var(--accent); }
.person-waiting { font-size: 12px; font-weight: 400; color: var(--accent-text); margin-top: 6px; }
.person-stats { display: flex; gap: 12px; flex-wrap: wrap; }

.person-panel { margin-top: 22px; border-top: 1px solid var(--line); padding-top: 16px; }
.person-panel-head { display: flex; align-items: center; gap: 14px; }
.person-panel-head h2 { font-family: var(--font-display); font-weight: 200; font-size: 24px; letter-spacing: -0.02em; flex: 1; }
.person-sub { font-size: 12px; font-weight: 400; text-transform: uppercase; letter-spacing: 0.06em; color: var(--muted); margin: 16px 0 8px; }
.person-links { display: flex; flex-wrap: wrap; gap: 6px; }

/* ── Selection ─────────────────────────────────────────────────────────────────────────── */
/* A selected row was a solid `--accent-weak` block — the only filled thing in an app whose
   system fills nothing, and at list height it read as a vertical blue bar. Selection is now the
   same language as everything else that marks a row: a left rule and a tint you can see through. */
.li.active, #email-list .li.active, #task-list .li.active, #note-list .li.active {
  background: rgba(0, 110, 255, 0.06);
  border-left: 2px solid var(--accent);
}
.li { border-left: 2px solid transparent; }
.li.active .li-from, .li.active .li-subj, .li.active .m-title { color: var(--ink); }

/* ── Bottom space ──────────────────────────────────────────────────────────────────────── */
/* Views that fill the window run to the bottom. Their panes scroll internally, so reserving a
   dock-sized strip under them wastes it permanently — and the dock auto-hides, so most of the
   time it was being reserved for something that was not on screen. The dock floats over the
   bottom edge when it is out, and it is 511px wide in a 1240px window, so the panes stay
   reachable either side of it. */
.view[data-view="email"], .view[data-view="tasks"],
.view[data-view="notes"], .view[data-view="calendar"] {
  padding-bottom: 14px;
}
/* Scrolling views keep the clearance: their content genuinely ends, and the last item must not
   sit under the dock permanently. */
.view[data-view="home"], .view[data-view="read"],
.view[data-view="people"], .view[data-view="research"], .view[data-view="settings"] {
  padding-bottom: 88px;
}

/* ── Attachment preview ────────────────────────────────────────────────────────────────── */
.att-backdrop {
  position: fixed; inset: 0; z-index: 60;
  background: rgba(0, 0, 0, 0.4);
  display: flex; align-items: center; justify-content: center; padding: 4vh 4vw;
}
.att-backdrop[hidden] { display: none; }
/* Opaque, like the palette. A preview floating over a visible app is unreadable, and this one
   is showing a document. */
.att-panel {
  background: var(--bg); border: 1px solid var(--ink);
  width: min(1000px, 96vw); max-height: 92vh;
  display: flex; flex-direction: column; overflow: hidden;
}
.att-head {
  display: flex; align-items: center; gap: 12px;
  padding: 10px 14px; border-bottom: 1px solid var(--line); flex: none;
}
.att-name { font-size: 16px; font-weight: 400; flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.att-actions { display: flex; gap: 6px; }
.att-body { flex: 1; min-height: 0; overflow: auto; display: flex; align-items: center; justify-content: center; }

.att-image { max-width: 100%; max-height: 84vh; display: block; }
/* A PDF gets the webview's viewer, sandboxed: an embedded link or action must not reach the app. */
.att-pdf { width: 100%; height: 84vh; border: 0; display: block; background: var(--bg); }
.att-text {
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 14px; line-height: 1.5;
  padding: 18px 20px; margin: 0; width: 100%; align-self: flex-start;
  white-space: pre-wrap; word-wrap: break-word; color: var(--ink-2);
}

/* The wordmark: GLUE lifted from the supplied logo set rather than drawn, so the app and the
   marketing material are the same letterforms. Previously generated by `scripts/make-icon.py` into
   `glue-wordmark.svg?v=8ae6a1e6`. The same four letters, from the same definition, make the app icon — the
   two used to disagree, because the wordmark was Megrim and the icon was drawn by hand.
   Applied as a mask rather than an <img> so it inherits `currentColor` and can sit in ink or in
   the accent without keeping a second copy of the file. */
/* Mark and wordmark together. The mark is the supplied logo — a full-colour asterisk that carries
   its own red, so it is an <img> rather than a masked shape: masking it would throw the colour
   away, and the colour is the only warm thing in a monochrome chrome. */
.brand { display: inline-flex; align-items: center; gap: 9px; flex: none; }
.brand-mark { display: block; width: 20px; height: 20px; border-radius: 5px; }

.wordmark {
  flex: none; user-select: none;
  width: 65px; height: 18px;  /* 3.60 : 1 — the measured bounding box of the extracted path */
  background: currentColor; color: var(--ink);
  -webkit-mask: url("glue-wordmark.svg?v=8ae6a1e6") no-repeat center / contain;
  mask: url("glue-wordmark.svg?v=8ae6a1e6") no-repeat center / contain;
}

/* ── Remote-image notice ───────────────────────────────────────────────────────────────── */
/* Stated rather than silent. A reader should know the mail wanted to phone home, and that it
   was stopped — otherwise blocking looks like a rendering fault. */
.remote-notice {
  display: flex; align-items: center; gap: 12px; flex-wrap: wrap;
  margin-top: 8px; padding: 7px 11px;
  border: 1px solid var(--line-2); font-size: 14px; color: var(--ink-2);
}
.remote-notice[hidden] { display: none; }

/* ── Lists: rules, not boxes ───────────────────────────────────────────────────────────── */
/* Rows were bordered cards with a radius, so a list read as a stack of objects and the eye had
   to separate each one. A hairline between rows does the same work with far less ink, which is
   what makes a long list scannable. */
.li {
  border: 0 !important;
  border-bottom: 1px solid var(--line) !important;
  border-radius: 0 !important;
  padding: 9px 12px;
}
.li:last-child { border-bottom: 0 !important; }
.li:hover { background: rgba(0, 0, 0, 0.022); }
/* Selection is a tint and weight, not a coloured bar. The blue rule read as a piece of chrome
   sitting between the list and the message rather than as "this row is open". */
.li.active {
  background: rgba(0, 110, 255, 0.07) !important;
  box-shadow: none !important;
}
.li.active .li-from { color: var(--accent-text); }
.li.active .li-subj { color: var(--ink); }

/* ── The message sheet ─────────────────────────────────────────────────────────────────── */
/* White, with a hairline, so the message reads as a document on the page rather than another
   panel of the app. */
.email-frame { background: #fff; border-top: 1px solid var(--line); }

/* ── Dock: dark, so it reads as a layer above the page ─────────────────────────────────── */
/* On cream, a cream dock with a hairline disappeared into the content behind it — which is
   wrong for the one element that floats. Dark inverts it: the dock is clearly a separate plane,
   and the shift also marks it as chrome rather than more page. */
/* The same light blue that marks a selected row and today's date. Black separated the dock from
   the page but read as a foreign object — a different material from everything else on screen.
   The tint separates it just as clearly while staying inside the one-chromatic-voice rule. */
.dock {
  background: var(--accent-weak);
  border-color: #b9d3f7;
}
/* Every item is a chip, not just the one under the pointer. The idle chip is the tint lifted a
   step towards white — the shade the hover pill already used — so the row reads as eight keys on
   a slightly darker tray. Black on it rather than a muted blue: at 19px the icons are hairline
   strokes, and anything short of full ink turns them into suggestions of icons.
   Hover then borrows the selected colours, so approaching an item previews landing on it. */
.dock .nav-item {
  color: var(--ink);
  background: #e9f2ff;
}
.dock .nav-item:hover,
.dock .nav-item.active {
  background: var(--bg);
  color: var(--accent-text);
  border-color: transparent;
}
.dock .nav-item:hover svg,
.dock .nav-item.active svg { color: var(--accent-text); }
/* Chips need air between them to read as separate keys; at 2px they merged into one band. */
.dock { gap: 4px; }
.dock .dock-new { background: var(--accent-text); }

/* ── A research answer ─────────────────────────────────────────────────────────────────── */
/* The conclusion sits above the evidence, because that is the order it is read in — but the
   evidence is on the same screen rather than a click away, since an answer nobody can trace is
   worth less than no answer. */
.research-answer {
  border: 1px solid var(--line-2);
  border-left: 2px solid var(--accent);
  padding: 14px 16px;
  margin-bottom: 18px;
  background: var(--surface);
}
/* A stored refusal. Quieter, and not blue: it is a real outcome, and dressing it like an answer
   would make "the corpus does not say" look like a finding. */
.research-answer-none { border-left-color: var(--line-2); }
.research-answer-none .research-answer-text { color: var(--muted); }

.research-answer-text { font-size: 15.5px; line-height: 1.55; color: var(--ink); }
.research-answer-cites { margin-top: 10px; font-size: 14px; color: var(--muted); }
/* Each source is a control, because it goes somewhere. A citation you cannot open is a footnote. */
.research-cite {
  font-size: 14px;
  color: var(--accent-text);
  background: none;
  border: 0;
  border-bottom: 1px solid var(--line-2);
  padding: 0 1px;
  cursor: pointer;
}
.research-cite:hover { border-bottom-color: var(--accent-text); }

/* The program, folded away. Present for whoever wants to check the working, absent for everyone
   else — which is most people, most of the time. */
.research-answer-how { margin-top: 10px; }
.research-answer-how summary { font-size: 14px; color: var(--muted); cursor: pointer; }
.research-answer-how pre {
  margin: 8px 0 0;
  padding: 10px 12px;
  background: var(--bg);
  border: 1px solid var(--line);
  font-size: 13px;
  line-height: 1.5;
  overflow-x: auto;
  white-space: pre;
  color: var(--ink-2);
}
.research-answer-when { margin-top: 8px; }

/* ── Read ──────────────────────────────────────────────────────────────────────────────── */
/* A reading queue, not a list of links. The summary carries the weight, so the title is a
   heading rather than a link and the actions sit quietly underneath. */
.read-list { display: flex; flex-direction: column; gap: 2px; }

.read-card {
  border-bottom: 1px solid var(--line);
  padding: 14px 2px 16px;
}
.read-card:last-child { border-bottom: 0; }
.read-head { display: flex; align-items: baseline; gap: 8px; }
.read-title { font-size: 16px; font-weight: 400; margin: 0; line-height: 1.35; }
.read-meta { margin-top: 3px; }
.read-summary { margin: 8px 0 0; font-size: 15px; line-height: 1.55; color: var(--ink-2); }
/* Why this is in front of you. Small, and always present when there is one — a recommendation
   whose reason is hidden is a recommendation nobody can argue with. */
.read-why { margin-top: 6px; font-style: italic; }

.read-actions { display: flex; gap: 6px; margin-top: 10px; }
/* The buttons stay out of the way until the row is under the pointer: three controls per article
   over a hundred articles is a wall of buttons, and the reading is the point. */
.read-actions .ghost { opacity: 0.55; transition: opacity 0.12s ease; }
.read-card:hover .read-actions .ghost { opacity: 1; }

/* Three states, not a number: nobody can act on 0.63, and printing it implies a precision the
   score does not have. */
.read-rel { flex: none; font-size: 11px; line-height: 1.9; color: var(--muted); }
.read-rel-high { color: var(--accent-text); }
.read-rel-low { color: var(--line-2); }

.read-feed { display: flex; align-items: center; gap: 14px; padding: 12px 2px; border-bottom: 1px solid var(--line); }
.read-feed-main { flex: 1; min-width: 0; }
.read-feed-error { color: var(--err); margin-top: 3px; }
.read-add { display: flex; gap: 8px; margin-top: 16px; }
.read-add input { flex: 1; }

/* ── First run ────────────────────────────────────────────────────────────────
   Wider than the other modals because it carries prose rather than a form, and
   a 4.9GB decision deserves room to be explained rather than squeezed. */
.onboard-card { width: 460px; gap: 12px; }
.onboard-steps { display: flex; gap: 6px; margin-bottom: 2px; }
.onboard-steps i { flex: 1; height: 2px; background: var(--line); border-radius: 1px; }
.onboard-steps i.on { background: var(--ink); }
.onboard-step p { margin-bottom: 0; }
.onboard-model { display: flex; align-items: baseline; justify-content: space-between; gap: 10px; padding: 8px 0; border-top: 1px solid var(--line-2); }
.onboard-model:first-child { border-top: 0; }
.onboard-model .om-name { font-weight: 500; }
.onboard-model .om-size { color: var(--muted); font-size: 12px; white-space: nowrap; }
.onboard-model .om-role { color: var(--muted); font-size: 12px; }

/* A step that cannot proceed says so in the ink colour, not the muted one: it is the reason the
   button did nothing, and muted grey is where that sentence goes to be missed. */
#onboard-mail-state, #onboard-claude-state, #onboard-progress { color: var(--ink-2); margin-top: 6px; }
#onboard-progress { font-variant-numeric: tabular-nums; }

/* Removal. Laid out as a choice rather than a warning: most people opening this want the first
   option, and burying it under a red banner would make freeing 4.9GB feel like uninstalling. */
.remove-panel { margin-top: 10px; padding: 12px; border: 1px solid var(--line); border-radius: 8px; display: flex; flex-direction: column; gap: 10px; }
.remove-opt { display: flex; gap: 9px; align-items: flex-start; cursor: pointer; }
.remove-opt input { margin-top: 3px; }
#remove-summary { color: var(--ink-2); font-variant-numeric: tabular-nums; }
