/* Breakpoints — these four widths, and no others.
   Every stylesheet in the app uses them; a fifth value is a bug.

     1200  wide → standard    three-up grids drop to two, side panels unstick
      900  standard → tablet  sidebars stack, masthead labels become icons
      700  tablet → phone     the tab row becomes the bottom bar, one column
      560  phone              full-bleed rows, 16px inputs, --tap targets

   Container queries are exempt: they measure a pane, not the viewport, so
   files.css, organization.css and plot.css set their own thresholds.

   700 is mirrored once in JavaScript, in core/viewport.js, for the handful of
   decisions CSS cannot make: picking a layout, swapping a component. Keep the
   two in step. Surfaces that need width to be usable at all pair 700 with
   (orientation: portrait) and show .rotate-gate instead — see .needs-landscape
   below. */

/* Self-hosted alternates for the admin's per-role font settings (see
   core/config.js FONT_STACKS). Vendored rather than named as system fonts —
   named fonts only render as intended when that exact face happens to be
   installed on the viewer's machine, which is not something a workspace-wide
   setting can assume. Regular weight only; bold text in these faces is the
   browser's synthetic bold. Licenses: vendor/fonts/OFL.txt. */
@font-face { font-family: "JetBrains Mono"; src: url(/vendor/fonts/jetbrains-mono.woff2) format("woff2"); font-weight: 400; font-style: normal; font-display: swap; }
@font-face { font-family: "Space Mono"; src: url(/vendor/fonts/space-mono.woff2) format("woff2"); font-weight: 400; font-style: normal; font-display: swap; }
@font-face { font-family: "Inter"; src: url(/vendor/fonts/inter.woff2) format("woff2"); font-weight: 400; font-style: normal; font-display: swap; }
@font-face { font-family: "Source Serif 4"; src: url(/vendor/fonts/source-serif-4.woff2) format("woff2"); font-weight: 400; font-style: normal; font-display: swap; }
@font-face { font-family: "Lora"; src: url(/vendor/fonts/lora.woff2) format("woff2"); font-weight: 400; font-style: normal; font-display: swap; }
@font-face { font-family: "Comic Neue"; src: url(/vendor/fonts/comic-neue.woff2) format("woff2"); font-weight: 400; font-style: normal; font-display: swap; }

:root {
  --paper: #f4f1e8;
  --paper-raised: #fbf9f3;
  --ink: #171713;
  --muted: #777269;
  --line: #d8d3c8;
  --line-dashed: #c8c2b7;
  --muted-line: #aaa499;
  --blue: #184fd1;
  --blue-soft: #dbe5ff;
  --red: #b53b2f;
  --green: #2f7458;
  --pending: #d97706;
  --shadow: 0 20px 55px rgba(34, 31, 25, .12);
  --serif: "Iowan Old Style", "Palatino Linotype", "Book Antiqua", Palatino, serif;
  --sans: "Avenir Next", Avenir, "Century Gothic", Futura, sans-serif;
  --mono: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  --tracking-body: .005em;
  --text-meta: 9px;
  --text-label: 10px;
  --text-control: 11px;
  --text-body: 12px;
  --text-reading: 13px;
  --text-panel-title: 23px;
  --text-stat: 28px;
  --text-page-title: clamp(30.4px, 4vw, 48px);
  --tracking-label: .12em;
  --masthead-home-gutter: max(clamp(22px, 4vw, 64px), calc((100vw - 1500px) / 2));
  /* The Asimov letterform itself, as a mask so one asset serves every mark and
     each one takes its colour from whatever it sits on. */
  /* alpha: without it, some browsers default an SVG mask to luminance, which
     reads the glyph's own (near-black) fill as near-transparent and fades
     its anti-aliased edges in as a visible gradient. */
  --asimov-mark: url(/ASIMOV.svg) center / contain no-repeat alpha;
  /* Two sizes of touch target: --tap for things you aim at (nav, menu rows,
     dialog buttons), --tap-dense for the tool clusters that sit inside a list
     row, where a generous target costs the row its text. */
  --tap: 34px;
  --tap-dense: 26px;
  /* The gutter between boxed panels on a workspace. One value so the files,
     samples, organization, graph and resources tabs sit on the same rhythm. */
  --panel-gap: 22px;
  /* Dialog width tiers — four named sizes instead of the one-off pixel
     value each dialog picked. .editor-dialog's own default (1160px) is
     Full; nothing smaller needs its own variable for that one. */
  --dialog-sm: 430px;
  --dialog-md: 640px;
  --dialog-lg: 760px;
  --font-panel-title: 400 var(--text-panel-title)/1.2 var(--serif);
  --font-page-title: 400 var(--text-page-title)/.96 var(--serif);
}

* { box-sizing: border-box; }

html { background: var(--paper); overscroll-behavior-y: none; }

body {
  margin: 0;
  min-height: 100vh;
  overscroll-behavior-y: none;
  color: var(--ink);
  background: var(--paper);
  font: 14px/1.45 var(--sans);
  letter-spacing: var(--tracking-body);
}
body::before {
  content: "";
  position: fixed;
  inset: 0;
  z-index: -1;
  background: radial-gradient(circle at 76% -10%, rgba(24, 79, 209, .075), transparent 28rem);
  pointer-events: none;
}

button, input, textarea, select { font: inherit; }
button, a { -webkit-tap-highlight-color: transparent; }
button { color: inherit; }

.panel-title { margin: 0; color: var(--ink); font: var(--font-panel-title); letter-spacing: -.02em; }

.masthead {
  height: 74px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0 var(--masthead-home-gutter);
  border-bottom: 1px solid var(--line);
  transition: padding .45s cubic-bezier(.2, .75, .25, 1);
}
body.in-project .masthead { padding-inline: clamp(22px, 4vw, 64px); }

.wordmark {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  color: var(--ink);
  text-decoration: none;
  font-weight: 650;
  letter-spacing: -.02em;
}

.wordmark-mark {
  width: 29px;
  height: 29px;
  display: grid;
  place-items: center;
  border: 1px solid var(--ink);
  border-radius: 50%;
  font: italic 17px/1 var(--serif);
  transition: background .12s;
}

.wordmark:hover .wordmark-mark { background: var(--ink); color: var(--paper); }
.wordmark-logo { width: 100%; height: 100%; border-radius: 50%; object-fit: cover; }
.wordmark-glyph { width: 54%; height: 54%; background: currentColor; -webkit-mask: var(--asimov-mark); mask: var(--asimov-mark); }

/* Compact density, chosen in the administration console. */
:root[data-density="compact"] .shell { padding: 22px 0 60px; }
:root[data-density="compact"] .intro { margin-bottom: 18px; }
:root[data-density="compact"] .view-nav { margin-bottom: 18px; }
:root[data-density="compact"] .folder-board { gap: 22px; }
:root[data-density="compact"] .card-body { min-height: 132px; padding: 16px; }
:root[data-density="compact"] .admin-panel { padding: 11px 13px 13px; }
:root[data-density="compact"] .admin-tile { padding: 10px 12px; }

.account { display: flex; align-items: center; gap: 14px; font-size: 12px; }
.account-name { display: inline-flex; align-items: center; gap: 6px; padding: 0; border: 0; background: transparent; color: var(--muted); cursor: pointer; font: inherit; }
.account-name:hover { color: var(--ink); }
.account-name-icon { display: none; width: 18px; height: 18px; flex: 0 0 auto; fill: none; stroke: currentColor; stroke-width: 1.5; stroke-linecap: round; stroke-linejoin: round; }
/* Generated caret, so app.js writing textContent can't wipe it. */
.account-name::after { content: ""; width: 0; height: 0; border: 3.5px solid transparent; border-bottom: 0; border-top-color: currentColor; opacity: .7; }
.logout { padding: 0; border: 0; background: transparent; color: var(--ink); cursor: pointer; text-decoration: underline; text-underline-offset: 3px; }

.masthead-right { display: flex; align-items: center; gap: 18px; }
.masthead-tools { display: flex; align-items: center; gap: 8px; }
.masthead-status { position: relative; min-height: 34px; display: inline-flex; align-items: center; gap: 7px; padding: 0 9px; border: 1px solid var(--line); border-radius: 999px; background: color-mix(in srgb, var(--paper-raised) 42%, transparent); color: var(--muted); cursor: pointer; font-size: 10px; transition: border-color .12s, background .12s, color .12s; }
.masthead-status:hover, .masthead-status.is-active { border-color: var(--ink); background: var(--paper-raised); color: var(--ink); }
.masthead-status svg { width: 16px; height: 16px; flex: 0 0 auto; fill: none; stroke: currentColor; stroke-width: 1.5; stroke-linecap: round; stroke-linejoin: round; }
.deadline-status > span:first-child { flex: 0 0 auto; font-size: 15px; line-height: 1; }
.masthead-live-timers { display: flex; align-items: center; }
.masthead-live-timer { min-width: 0; display: grid; grid-template-columns: minmax(0, auto) auto; align-items: baseline; gap: 6px; max-width: 156px; padding: 0 9px; color: var(--blue); }
.masthead-live-timer + .masthead-live-timer { border-left: 1px solid #c7d5f5; }
.masthead-live-timer > span { min-width: 0; overflow: hidden; font-size: 11px; font-weight: 600; text-overflow: ellipsis; white-space: nowrap; }
.masthead-live-timer time { font: 700 12px/1 var(--sans); font-variant-numeric: tabular-nums; letter-spacing: -.02em; white-space: nowrap; }
.masthead-status.has-live { padding-left: 5px; }
.masthead-status.has-live:not(.has-overflow) > strong { display: none; }
.masthead-status.has-active { border-color: #94a9df; color: var(--blue); }
.masthead-status.has-active strong { background: var(--blue); color: white; }
.masthead-status.deadline-status.has-deadline { border-color: #d7a08f; color: #a0442e; }
.masthead-status.deadline-status.is-overdue { border-color: var(--red); background: rgba(181, 59, 47, .08); color: var(--red); }
.masthead-status.deadline-status.is-overdue strong { background: var(--red); color: white; }
.masthead-menu { position: relative; }
.masthead-icon { position: relative; width: 34px; height: 34px; display: grid; place-items: center; border: 0; border-radius: 50%; background: transparent; color: var(--muted); cursor: pointer; transition: background .12s, color .12s; }
.masthead-icon:hover, .masthead-icon.is-active { background: rgba(23, 23, 19, .07); color: var(--ink); }
.masthead-icon svg { width: 18px; height: 18px; fill: none; stroke: currentColor; stroke-width: 1.5; stroke-linecap: round; stroke-linejoin: round; }
.masthead-badge { position: absolute; top: -1px; right: -1px; min-width: 16px; height: 16px; margin: 0; padding: 0 4px; border: 2px solid var(--paper); background: var(--blue); color: white; font-size: 9px; font-weight: 700; }
.masthead-badge[hidden] { display: none; }
.masthead-panel { position: absolute; top: calc(100% + 10px); right: 0; z-index: 50; width: 180px; overflow: hidden; }
.masthead-panel[hidden] { display: none; }
.masthead-panel button { display: block; width: 100%; padding: 11px 16px; border: 0; border-bottom: 1px solid var(--line); background: transparent; color: var(--ink); text-align: left; text-decoration: none; cursor: pointer; font-size: 12px; }
.masthead-panel button:last-child { border-bottom: 0; }
.masthead-panel button:hover { background: var(--blue-soft); color: var(--blue); }
.masthead-icon.has-error .masthead-badge { background: var(--red); }

.upload-queue-panel { width: 360px; padding: 0; }
.upload-queue-header { display: flex; align-items: center; justify-content: space-between; padding: 10px 14px; border-bottom: 1px solid var(--line); font-size: 11px; font-weight: 700; letter-spacing: var(--tracking-label); text-transform: uppercase; color: var(--muted); }
.upload-queue-header button { width: auto; padding: 0; border: 0; background: transparent; color: var(--blue); font-size: 11px; font-weight: 600; text-transform: none; letter-spacing: normal; cursor: pointer; }
.upload-queue-header button:hover { text-decoration: underline; }
.upload-queue-list { max-height: 320px; overflow-y: auto; }
.upload-queue-empty { margin: 0; padding: 16px 14px; color: var(--muted); font-size: 12px; }
.upload-queue-item { display: grid; grid-template-columns: 1fr auto; align-items: center; gap: 2px 8px; padding: 9px 14px; border-bottom: 1px solid var(--line); font-size: 12px; }
.upload-queue-item:last-child { border-bottom: 0; }
.upload-queue-item-name { grid-column: 1; min-width: 0; overflow: hidden; color: var(--ink); font-weight: 600; text-overflow: ellipsis; white-space: nowrap; }
.upload-queue-item-status { grid-column: 1 / -1; display: flex; align-items: center; gap: 6px; overflow: hidden; color: var(--muted); font-size: 11px; text-overflow: ellipsis; white-space: nowrap; font-variant-numeric: tabular-nums; }
.upload-queue-item.is-error .upload-queue-item-status { color: var(--red); }
.upload-queue-item.is-done .upload-queue-item-status { color: var(--green); }
.upload-queue-item-actions { grid-column: 2; display: flex; flex: 0 0 auto; gap: 2px; white-space: nowrap; }
.upload-queue-item-actions button { width: 20px; height: 20px; display: grid; flex: 0 0 auto; place-items: center; padding: 0; border: 0; border-radius: 50%; background: transparent; color: var(--muted); cursor: pointer; }
.upload-queue-item-actions button:hover { background: rgba(23, 23, 19, .07); color: var(--ink); }
.upload-queue-item-actions svg { width: 13px; height: 13px; fill: none; stroke: currentColor; stroke-width: 1.5; stroke-linecap: round; stroke-linejoin: round; }

.install-app { padding: 2px 0; border: 0; border-bottom: 1px solid currentColor; background: transparent; cursor: pointer; }
.install-app[hidden] { display: none; }
.save-state { color: var(--green); transition: color .12s; }
.save-state.is-saving { color: var(--muted); opacity: .6; }
.save-state.is-error { color: var(--red); }

.shell { width: min(1120px, calc(100% - 44px)); margin: 0 auto; padding: 34px 0 90px; transition: opacity .18s ease; }
body.is-routing .shell { opacity: .88; }
@media (prefers-reduced-motion: reduce) {
  .shell { transition: none; }
  body.is-routing .shell { opacity: 1; }
}
.intro { margin-bottom: 28px; }
.eyebrow { margin: 0 0 14px; color: var(--blue); font-size: 11px; font-weight: 700; letter-spacing: .16em; text-transform: uppercase; }
.title-row { display: flex; align-items: flex-end; justify-content: space-between; gap: 24px; }
h1 { margin: 0; font: 400 clamp(48px, 7vw, 84px)/.9 var(--serif); letter-spacing: -.035em; }

.view-nav { position: relative; display: flex; gap: 28px; margin-bottom: 28px; border-bottom: 1px solid var(--line); }
.nav-item {
  position: relative;
  padding: 0 0 13px;
  border: 0;
  background: transparent;
  color: var(--muted);
  cursor: pointer;
  transition: color .12s;
}
.nav-item::after { content: ""; position: absolute; right: 0; bottom: -1px; left: 0; height: 2px; background: var(--blue); transform: scaleX(0); transition: transform .14s ease-out; }
.nav-item:hover, .nav-item.is-active { color: var(--ink); }

/* A project's own prev/next, flanking its tab row (pages/project/index.js).
   At either end (Overview, Notebook by default) there's nowhere further to
   go, so [hidden] takes over — but it stays visibility:hidden, not
   display:none: the box keeps its flex slot so the tabs beside it don't
   shift left/right as the arrow appears and disappears switching tabs. */
.view-nav-arrow { display: inline-flex; align-items: center; padding: 0 0 13px; border: 0; background: transparent; color: var(--muted); cursor: pointer; transition: color .12s; }
.view-nav-arrow:hover { color: var(--ink); }
.view-nav-arrow[hidden] { display: inline-flex; visibility: hidden; pointer-events: none; }

/* A view-switcher's keyboard-accelerator letter (see core/shortcuts.js). The
   shortcut always works; the colored underline only fades in while its
   reveal key is held — Alt for a page's own nested tabs (`.access-key`),
   Shift for a page's top nav (`.access-key-shift`, Shift being what
   actually fires it too). Kept as a transparent underline rather than
   `none` so nothing shifts when it appears. */
.access-key, .access-key-shift {
  text-decoration: underline;
  text-decoration-color: transparent;
  text-decoration-thickness: 2px;
  text-decoration-skip-ink: none;
  text-underline-offset: 3px;
  border-radius: 2px;
  transition: color .15s ease-out, text-decoration-color .15s ease-out;
}
body.show-access-keys .access-key,
body.show-nav-keys .access-key-shift { color: var(--blue); text-decoration-color: var(--blue); }
.nav-item.is-active::after { transform: scaleX(1); }
/* Count badge — a number in a small tinted pill, next to a label. One
   neutral ink tint for every context; state color (Danger etc.) belongs on
   what it's attached to, not on the count itself. */
.badge-count { min-width: 19px; height: 19px; display: inline-flex; align-items: center; justify-content: center; margin-left: 5px; padding: 1px 5px 0; border-radius: 999px; background: rgba(23, 23, 19, .07); color: var(--ink); font-size: 10px; font-variant-numeric: tabular-nums; line-height: 1; vertical-align: middle; }
/* Status pill — shape only; color is the caller's own semantic modifier
   (.is-ready, .is-high, .is-leader, …), not a fixed is-good/is-bad pair, so
   each domain keeps its real state names. */
.badge-status { display: inline-flex; padding: 2px 9px 1px; border-radius: 999px; font-size: 10px; font-weight: 700; letter-spacing: .08em; text-transform: uppercase; }
/* Category pill — the same shape again, one of N arbitrary hues via --pill
   instead of a fixed state. .type-pill (parsed file/column types) was
   already the real recipe, in one page's CSS — moved here so any page can
   use it. */
.type-pill { padding: 3px 8px 2px; border-radius: 999px; background: color-mix(in srgb, var(--pill) 16%, var(--paper)); color: var(--pill); font-size: 9px; font-weight: 700; letter-spacing: .1em; }

/* Dropdown menu — a floating action panel's shape. Position/width/padding
   stay each menu's own (fixed vs absolute, how wide, one flush divided list
   vs a padded margin of rounded items) — those are real differences, not
   drift; only border/radius/background/shadow were actually the same
   everywhere and worth sharing. */
.dropdown-menu { z-index: 9999; border: 1px solid var(--line); border-radius: 3px; background: var(--paper-raised); box-shadow: var(--shadow); }

.app-view { min-height: 320px; }
.project-grid, .folder-dropzone { display: grid; grid-template-columns: repeat(12, 1fr); gap: var(--panel-gap); }

.missed-todo-alert { display: flex; align-items: center; justify-content: space-between; gap: 24px; margin: -19px 0 35px; padding: 13px 0; border-block: 1px solid #cf9c91; color: var(--ink); }
.missed-todo-alert[hidden] { display: none; }
.missed-todo-alert > div:first-child { min-width: 0; display: grid; grid-template-columns: auto auto; align-items: baseline; gap: 2px 10px; }
.missed-todo-alert span { color: var(--red); font-size: 8px; font-weight: 700; letter-spacing: .11em; text-transform: uppercase; }
.missed-todo-alert strong { font: 400 17px/1.2 var(--serif); }
.missed-todo-alert small { grid-column: 1 / -1; color: var(--muted); font-size: 9px; }
.missed-todo-actions { display: flex; align-items: center; gap: 7px; }
.missed-todo-actions button { min-height: 30px; padding: 1px 10px 0; border: 1px solid var(--line); border-radius: 2px; background: transparent; color: var(--muted); cursor: pointer; font-size: 9px; }
.missed-todo-actions button:hover { border-color: var(--ink); color: var(--ink); }
.missed-todo-actions [data-carry-missed] { border-color: var(--ink); color: var(--ink); }
.missed-todo-actions .missed-todo-dismiss { width: 30px; padding: 0 0 2px; border-color: transparent; font-size: 16px; }

.layout-toggle { display: flex; gap: 24px; margin-bottom: 26px; border-bottom: 1px solid var(--line); }
.layout-toggle button { position: relative; padding: 0 0 10px; border: 0; background: transparent; color: var(--muted); cursor: pointer; font-size: 10px; font-weight: 700; letter-spacing: .14em; text-transform: uppercase; transition: color .12s; }
.layout-toggle button::after { content: ""; position: absolute; right: 0; bottom: -1px; left: 0; height: 2px; background: var(--blue); transform: scaleX(0); transition: transform .14s ease-out; }
.layout-toggle button:hover, .layout-toggle button[aria-pressed="true"] { color: var(--ink); }
.layout-toggle button[aria-pressed="true"]::after { transform: scaleX(1); }

.folder-board { display: grid; gap: 34px; }
.folder-section { position: relative; }
.folder-head { display: flex; align-items: flex-end; justify-content: space-between; min-height: 38px; border-bottom: 3px solid var(--folder-color); }
.folder-title-wrap { display: flex; align-items: center; gap: 9px; }
.folder-tab { display: inline-block; min-width: 130px; padding: 9px 16px 7px; border-radius: 5px 5px 0 0; background: var(--folder-color); color: var(--folder-ink); font: 400 18px/1 var(--serif); letter-spacing: .01em; }
.folder-count { min-width: 14px; display: inline-flex; align-items: center; justify-content: center; color: var(--muted); font-size: 10px; font-variant-numeric: tabular-nums; line-height: 1; }
.folder-section { transition: opacity .12s, box-shadow .12s; }
.folder-section.is-folder-dragging { opacity: .35; }
.folder-section.folder-drop-before { box-shadow: 0 -3px 0 var(--blue); }
.folder-section.folder-drop-after { box-shadow: 0 3px 0 var(--blue); }
.folder-dropzone { min-height: 108px; padding: 14px 0 0; border: 1px solid transparent; border-top: 0; }
.folder-dropzone.is-empty { display: flex; align-items: center; justify-content: center; border: 1px dashed var(--line); border-top: 0; }

/* The one folder-tree row idiom (see /style#folder-trees) — Files, Resources,
   Organization's drawer and Decks' collections tree all build rows out of
   this, instead of four bespoke versions. No folder icon: indentation and
   the disclosure chevron already say "this is a folder". */
.tree-row-list { display: flex; flex-direction: column; gap: 1px; }
.tree-row-line { display: flex; align-items: center; gap: 6px; padding: 4px 7px 4px calc(7px + var(--indent, 0px)); border: 0; border-radius: 2px; background: transparent; color: var(--muted); font-size: var(--text-control); text-align: left; cursor: pointer; transition: color .12s, background .12s; }
.tree-row-line:hover { background: rgba(23, 23, 19, .05); color: var(--ink); }
.tree-row-line.is-active { background: var(--blue-soft); color: var(--ink); }
.tree-row-line.is-drop-target { background: var(--blue-soft); color: var(--blue); box-shadow: inset 0 0 0 1px var(--blue); }
.tree-row-toggle { width: 14px; height: 14px; flex: 0 0 auto; display: grid; place-items: center; padding: 0; border: 0; background: transparent; color: inherit; cursor: pointer; transition: transform .12s ease-out; }
.tree-row-toggle svg { fill: none; stroke: currentColor; stroke-width: 1.6; stroke-linecap: round; stroke-linejoin: round; }
.tree-row-line[aria-expanded="true"] .tree-row-toggle { transform: rotate(90deg); }
.tree-row-leaf-mark { width: 14px; flex: 0 0 auto; text-align: center; color: var(--line); }
.tree-row-name { flex: 1; align-self: stretch; display: flex; align-items: center; min-width: 0; padding: 0; border: 0; background: transparent; color: inherit; text-align: left; font: inherit; cursor: pointer; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.tree-row-count { flex: 0 0 auto; color: var(--muted); font-size: var(--text-meta); font-variant-numeric: tabular-nums; }
.tree-row-line.is-active .tree-row-count { color: inherit; }
.folder-dropzone.is-over { border-color: var(--project-color, var(--blue)); background: rgba(24, 79, 209, .035); }
.drop-hint, .board-note { margin: 0; color: var(--muted-line); font-size: 11px; }
.board-note { text-align: center; }

/* Pin glyph shared by the announcements board and tracker notes (core/pinning.js). */
.pin-mark { width: 15px; height: 15px; display: inline-grid; place-items: center; color: var(--muted); }
.pin-mark svg { width: 100%; height: 100%; fill: none; stroke: currentColor; stroke-width: 1.6; stroke-linecap: round; stroke-linejoin: round; }
.pin-mark.is-pinned { color: #b8860b; }
.pin-mark.is-pinned svg > :first-child { fill: currentColor; }
.pin-toggle { width: 22px; height: 22px; display: grid; place-items: center; padding: 0; border: 0; background: transparent; cursor: pointer; opacity: .5; transition: opacity .12s, color .12s; }
.pin-toggle:hover { opacity: 1; color: var(--blue); }
.pin-toggle.is-pinned { opacity: 1; }
.pin-tape {
  position: absolute;
  top: -7px;
  width: 54px;
  height: 20px;
  background: rgba(233, 224, 197, .72);
  box-shadow: 0 1px 2px rgba(52, 38, 22, .2);
}
.pin-tape-left { left: -14px; transform: rotate(-34deg); }
.pin-tape-right { right: -14px; transform: rotate(34deg); }

.project-card {
  position: relative;
  grid-column: span 4;
  min-height: 225px;
  display: flex;
  flex-direction: column;
  padding: 0;
  overflow: hidden;
  border: 1px solid var(--line);
  border-radius: 3px;
  background: color-mix(in srgb, var(--paper-raised) 62%, transparent);
  cursor: grab;
  transition: background .12s, border-color .12s, opacity .12s;
}
.project-card:hover { border-color: #b9b3a7; background: var(--paper-raised); }
.project-card:focus-visible, .project-row:focus-visible, .archive-row:focus-visible { outline: 1px solid var(--blue); outline-offset: 2px; }
.project-card:active { cursor: grabbing; }
.project-card.is-dragging { opacity: .35; }
.project-card.drop-before { border-color: var(--blue); }
.card-top { display: flex; align-items: flex-start; justify-content: flex-end; }
.card-body { min-height: 166px; flex: 1; display: flex; flex-direction: column; padding: 22px; }
.project-cover { width: 100%; height: 59px; display: block; object-fit: cover; border-bottom: 1px solid var(--line); }
.card-color-block { width: 100%; height: 30px; display: block; background: var(--project-color); border-bottom: 1px solid var(--line); }
.drag-mark { color: var(--muted-line); font-size: 17px; letter-spacing: -2px; transition: color .12s; }
.project-card:hover .drag-mark { color: var(--blue); }
.project-card h2 { min-height: 2.16em; display: -webkit-box; margin: 8px 0 7px; overflow: hidden; font: 400 27px/1.08 var(--serif); letter-spacing: -.015em; -webkit-box-orient: vertical; -webkit-line-clamp: 2; }
.role { margin: 0; color: var(--muted); font-size: 12px; }
.card-role { margin: 0; color: var(--project-color); font-size: 9px; font-weight: 700; letter-spacing: var(--tracking-label); text-transform: uppercase; }
.card-summary { min-height: 2.9em; display: -webkit-box; margin: 11px 0 0; padding-top: 10px; overflow: hidden; border-top: 1px solid var(--line); color: var(--muted); font: italic 12px/1.45 var(--serif); -webkit-box-orient: vertical; -webkit-line-clamp: 2; }
.card-bottom { flex: 0 0 auto; margin-top: auto; }
.progress-line { height: 2px; margin: 18px 0 10px; background: var(--line); }
.progress-line span { display: block; height: 100%; background: var(--blue); }
.project-meta { display: flex; justify-content: space-between; gap: 12px; color: var(--muted); font-size: 11px; }
.lane-count { display: flex; align-items: baseline; gap: 5px; }
.lane-count strong { color: var(--ink); font-weight: 600; font-variant-numeric: tabular-nums; }
.lane-count.lane-active strong { color: var(--blue); }
.lane-count.lane-done strong { color: var(--green); }
.contact-stack { min-height: 27px; display: flex; margin-top: 16px; }
.contact-dot { width: 27px; height: 27px; display: grid; place-items: center; margin-right: -6px; border: 2px solid var(--paper-raised); border-radius: 50%; background: var(--blue-soft); color: var(--blue); object-fit: cover; font: 600 10px/1 var(--sans); }

.project-rows { display: grid; gap: 1px; border-top: 1px solid var(--line); }
.project-row {
  display: grid;
  grid-template-columns: 32px minmax(0, 1fr) auto auto auto;
  align-items: center;
  gap: 18px;
  padding: 13px 6px;
  border-bottom: 1px solid var(--line);
  cursor: pointer;
  transition: background .12s;
}
.project-row:hover { background: var(--paper-raised); }
.row-mark { width: 32px; height: 32px; display: block; object-fit: cover; border: 1px solid var(--line); background: var(--project-color); }
.row-main { min-width: 0; }
.project-row h2 { margin: 0; overflow: hidden; font: 400 20px/1.15 var(--serif); letter-spacing: -.01em; text-overflow: ellipsis; white-space: nowrap; }
.project-row .card-role { margin-top: 4px; }
.row-folder { padding: 4px 10px; border-radius: 999px; background: var(--folder-color); color: var(--folder-ink); font-size: 10px; }
.project-row .contact-stack { min-height: 0; margin-top: 0; }
.project-row .project-meta { justify-content: flex-start; gap: 18px; }

.empty-state { padding: 72px 24px; border: 1px dashed var(--line-dashed); border-radius: 3px; text-align: center; }
.empty-glyph { width: 54px; height: 54px; display: grid; place-items: center; margin: 0 auto 20px; border: 1px solid var(--line); border-radius: 50%; color: var(--blue); font: italic 27px/1 var(--serif); }
.empty-state h2 { margin: 0 0 7px; font: 400 25px/1.2 var(--serif); }
.empty-state p { margin: 0; color: var(--muted); }

.section-label { display: flex; align-items: center; gap: 10px; margin: 35px 0 13px; color: var(--muted); font-size: 10px; font-weight: 700; letter-spacing: .14em; text-transform: uppercase; }
.section-label::after { content: ""; height: 1px; flex: 1; background: var(--line); }
.archive-list { display: grid; gap: 1px; border-top: 1px solid var(--line); }
.archive-row { display: grid; grid-template-columns: 1fr auto; gap: 15px; padding: 15px 4px; border-bottom: 1px solid var(--line); cursor: pointer; transition: background .12s; }
.archive-row:hover { background: rgba(255, 255, 255, .32); }
.archive-row span:last-child { color: var(--muted); font-size: 12px; }

.people-toolbar { display: flex; align-items: flex-start; justify-content: space-between; gap: 20px; margin-bottom: 18px; }
.people-groups { display: flex; flex-wrap: wrap; gap: 7px; }
.people-group-pill { height: 30px; display: inline-flex; gap: 3px; }
.people-group-filter, .people-group-edit { height: 30px; display: inline-flex; align-items: center; justify-content: center; padding: 0 11px; border: 1px solid var(--line); border-radius: 15px; background: transparent; color: var(--muted); clip-path: inset(0 round 15px); -webkit-mask-image: -webkit-radial-gradient(white, black); cursor: pointer; font-size: 10px; line-height: 1; }
.people-group-pill .people-group-filter { border-color: var(--line); background: color-mix(in srgb, var(--group-color) 10%, var(--paper)); }
.people-group-filter span { min-width: 1ch; display: inline-flex; align-items: center; justify-content: center; margin-left: 4px; padding-top: 1px; opacity: .65; font-variant-numeric: tabular-nums; line-height: 1; }
.people-group-filter:hover, .people-group-filter.is-active { border-color: var(--ink); background: var(--ink); color: var(--paper-raised); }
.people-group-pill .people-group-filter:hover, .people-group-pill .people-group-filter.is-active { border-color: var(--group-color); background: var(--group-color); color: var(--ink); }
.people-group-edit { width: 28px; padding: 0 6px 2px; border-color: var(--line); letter-spacing: -1px; }
.people-group-edit:hover { color: var(--ink); }
.people-list { display: grid; grid-template-columns: repeat(2, 1fr); gap: 1px 34px; }
.person-photo { width: 58px; height: 58px; display: block; border-radius: 50%; object-fit: cover; filter: saturate(.78); }
.person-initials { display: grid; place-items: center; border: 1px solid var(--line); background: var(--paper-raised); color: var(--blue); font: 400 18px/1 var(--serif); }
.person-name { margin: 0 36px 3px 0; font: 400 24px/1.15 var(--serif); letter-spacing: -.025em; }
.person-affiliation, .person-email { margin: 0; color: var(--muted); font-size: 12px; }
.scholar-line { display: flex; align-items: center; gap: 8px; width: fit-content; margin: 16px 0 0 73px; color: var(--blue); text-decoration: none; font-size: 10px; }
.scholar-line span:nth-child(2) { color: var(--muted); }
.person-interests, .person-groups { display: flex; flex-wrap: wrap; gap: 5px; margin: 10px 0 0 73px; }
.person-interests span { color: var(--muted); font-size: 9px; }
.person-interests span + span::before { content: "·"; margin-right: 5px; }
.person-groups span { padding: 3px 8px; border-radius: 999px; background: color-mix(in srgb, var(--group-color) 18%, transparent); color: var(--ink); font-size: 9px; }
.person-projects { display: flex; flex-wrap: wrap; gap: 5px; margin: 12px 0 0 73px; }
.tag { padding: 3px 8px; border: 1px solid var(--line); border-radius: 999px; color: var(--muted); font-size: 9px; }

.todo-view { display: grid; gap: 24px; }
.todo-tag-bar { display: flex; align-items: flex-end; justify-content: space-between; gap: 22px; padding-bottom: 12px; border-bottom: 1px solid var(--line); }
.todo-tag-bar label { min-width: 180px; display: grid; gap: 5px; }
.todo-tag-bar label span { color: var(--muted); font-size: 9px; font-weight: 700; letter-spacing: .1em; text-transform: uppercase; }
.todo-tag-bar input { padding: 6px 0; border: 0; border-bottom: 1px solid var(--muted-line); outline: 0; background: transparent; color: var(--ink); }
.todo-tag-bar input:focus { border-color: var(--blue); }
.tag-index { display: flex; flex-wrap: wrap; justify-content: flex-end; gap: 6px; }
.tag-index button { padding: 5px 7px; border: 1px solid var(--line); border-radius: 2px; background: transparent; color: var(--muted); cursor: pointer; font-size: 9px; }
.tag-index button:hover, .tag-index button.is-active { border-color: var(--blue); background: var(--blue-soft); color: var(--blue); }
.tag-index button span { margin-left: 3px; opacity: .6; font-variant-numeric: tabular-nums; }
.tag-index-empty { align-self: center; color: var(--muted); font-size: 10px; }
.todo-workspace { display: grid; grid-template-columns: minmax(0, .85fr) minmax(0, 1.15fr); gap: var(--panel-gap); align-items: start; }
.todo-panel-head, .daily-head { min-height: 57px; display: flex; align-items: flex-end; justify-content: space-between; gap: 18px; padding-bottom: 12px; border-bottom: 1px solid var(--ink); }
.todo-panel-head span, .daily-head span { color: var(--blue); font-size: 9px; font-weight: 700; letter-spacing: var(--tracking-label); text-transform: uppercase; }
.todo-panel-head h2, .daily-head h2 { margin: 3px 0 0; font: 400 27px/1 var(--serif); }
.todo-panel-head strong { color: var(--muted); font-size: 10px; font-variant-numeric: tabular-nums; }
.note-head-tools { display: flex; align-items: center; gap: 12px; }
.note-layout { display: flex; border: 1px solid var(--line); }
.note-layout button { width: 27px; height: 25px; padding: 0; border: 0; background: transparent; color: var(--muted); cursor: pointer; font-size: 9px; }
.note-layout button + button { border-left: 1px solid var(--line); }
.note-layout button:hover { color: var(--ink); }
.note-layout button[aria-pressed="true"] { background: var(--ink); color: var(--paper-raised); }
.note-composer { margin-top: 16px; border: 1px solid var(--line); background: rgba(251, 249, 243, .55); }
.note-composer:focus-within { border-color: var(--blue); }
.note-composer textarea { width: 100%; display: block; padding: 16px; border: 0; outline: 0; background: transparent; color: var(--ink); resize: vertical; }
.note-composer textarea::placeholder, .todo-composer textarea::placeholder { color: var(--muted-line); }
.note-composer > div { display: flex; align-items: center; justify-content: space-between; gap: 14px; padding: 9px 12px; border-top: 1px solid var(--line); }
.note-composer span { color: var(--muted); font-size: 9px; }
.note-composer button, .todo-composer button { padding: 0; border: 0; background: transparent; color: var(--blue); cursor: pointer; font-size: 10px; }
.note-stack { display: grid; gap: var(--panel-gap); margin-top: 17px; }
.note-stack.columns-1 { grid-template-columns: minmax(0, 1fr); }
.note-stack.columns-2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.note-stack.columns-3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.note-meta { display: flex; align-items: center; justify-content: space-between; gap: 12px; }
.note-meta time { color: var(--muted); font-size: 9px; font-variant-numeric: tabular-nums; }
.note-actions, .todo-entry-tools { display: flex; align-items: center; gap: 5px; }
.entry-edit, .entry-copy { padding: 2px 4px; border: 0; border-bottom: 1px solid transparent; background: transparent; color: var(--muted); cursor: pointer; font-size: 9px; }
.entry-edit:hover, .entry-edit:focus-visible, .entry-copy:hover, .entry-copy:focus-visible { border-color: currentColor; color: var(--blue); }
.note-delete, .todo-delete { padding: 0 3px; border: 0; background: transparent; color: var(--muted-line); cursor: pointer; font-size: 15px; }
.note-delete:hover, .todo-delete:hover { color: var(--red); }
.calendar-grid { display: grid; grid-template-columns: repeat(7, 1fr); gap: 4px; margin-top: 16px; }
.calendar-weekday { padding-bottom: 4px; color: var(--muted); font-size: 9px; font-weight: 700; letter-spacing: .08em; text-transform: uppercase; text-align: center; }
.calendar-day { position: relative; aspect-ratio: 1; padding: 4px 5px; border: 1px solid var(--line); background: transparent; color: var(--ink); cursor: pointer; display: flex; flex-direction: column; align-items: flex-start; justify-content: space-between; font-size: 10px; font-variant-numeric: tabular-nums; }
.calendar-day:hover { border-color: var(--blue); }
.calendar-day.is-outside { opacity: .35; }
.calendar-day.is-today { border-color: var(--ink); border-width: 2px; }
.calendar-day.is-selected { outline: 2px solid var(--blue); outline-offset: -2px; }
.calendar-day.is-todo-drop-target { z-index: 2; border-color: var(--blue); background: var(--blue-soft); color: var(--ink); outline: 2px solid var(--blue); outline-offset: 2px; transform: scale(1.04); }
.calendar-day-num { font-weight: 600; }
.calendar-day-count { align-self: flex-end; font-weight: 700; }
.calendar-day.level-1 { background: #e3efe9; }
.calendar-day.level-2 { background: #bcdbcb; }
.calendar-day.level-3 { background: #7fbb9d; color: #fff; }
.calendar-day.level-4 { background: var(--green); color: #fff; }
.calendar-day-tasks { display: none; position: absolute; z-index: 5; top: calc(100% + 6px); left: 0; min-width: 180px; max-width: 240px; padding: 10px 12px; border: 1px solid var(--line); background: #fbf9f3; color: var(--ink); box-shadow: 0 8px 20px rgba(23, 23, 19, .18); text-align: left; }
.calendar-day:nth-of-type(7n-1) .calendar-day-tasks, .calendar-day:nth-of-type(7n) .calendar-day-tasks { left: auto; right: 0; }
.calendar-day:hover .calendar-day-tasks, .calendar-day:focus-visible .calendar-day-tasks { display: block; }
.calendar-day-tasks strong { display: block; margin-bottom: 6px; font-size: 9px; font-weight: 700; letter-spacing: .08em; text-transform: uppercase; color: var(--blue); }
.calendar-day-tasks ul { margin: 0; padding-left: 16px; display: grid; gap: 4px; }
.calendar-day-tasks li { font-size: 10px; line-height: 1.4; }
.daily-status { display: grid; grid-template-columns: auto minmax(100px, 1fr); align-items: center; gap: 14px; margin: 16px 0 9px; color: var(--muted); font-size: 9px; font-variant-numeric: tabular-nums; }
.daily-status > div { height: 2px; background: var(--line); }
.daily-status i { height: 100%; display: block; background: var(--green); }
.todo-composer { display: grid; grid-template-columns: minmax(0, 1fr) minmax(105px, 145px) auto; align-items: end; border-bottom: 1px solid var(--muted-line); }
.todo-composer:focus-within { border-color: var(--blue); }
.todo-input { min-width: 0; display: grid; }
.todo-composer textarea { min-width: 0; min-height: 42px; max-height: 130px; padding: 10px 2px 2px; border: 0; outline: 0; background: transparent; color: var(--ink); resize: vertical; }
.todo-input > span { padding: 0 2px 7px; color: var(--muted); font-size: 9px; line-height: 1.35; }
.todo-compose-project { min-width: 0; margin: 0 9px 8px; padding: 2px 18px 2px 5px; border: 0; border-left: 1px solid var(--line); outline-color: var(--blue); background: transparent; color: var(--muted); cursor: pointer; font-size: 11px; text-overflow: ellipsis; }
.todo-composer button { padding: 0 0 10px 12px; }
.todo-list { margin-top: 8px; }
.todo-entry-tools { align-items: flex-start; }
.todo-project-control { width: fit-content; max-width: 100%; display: inline-flex; align-items: center; margin-top: 5px; color: #8f897f; opacity: .58; transition: opacity .12s; }
.todo-project-control:hover, .todo-project-control:focus-within, .todo-project-control.is-linked { opacity: 1; }
.todo-project-control > span { width: 5px; height: 5px; flex: 0 0 auto; border-radius: 50%; background: var(--todo-project-color); }
.todo-project-control::after { content: "⌄"; order: 1; width: 12px; color: var(--muted); pointer-events: none; font-size: 9px; line-height: 1; }
.todo-project-control select { min-width: 0; max-width: 180px; height: 20px; padding: 0 4px 0 5px; border: 0; outline-color: var(--blue); appearance: none; -webkit-appearance: none; background: transparent; color: inherit; cursor: pointer; font-size: 11px; text-overflow: ellipsis; }
.todo-project-control button { order: 2; width: 17px; height: 18px; display: grid; place-items: center; padding: 0; border: 0; background: transparent; color: var(--muted); opacity: .42; cursor: pointer; font-size: 9px; }
.todo-project-control button:hover, .todo-project-control button:focus-visible { color: var(--blue); opacity: 1; }
.todo-actions { display: flex; align-items: center; border: 1px solid var(--line); border-radius: 2px; }
.todo-actions button { min-width: 25px; height: 21px; display: grid; place-items: center; padding: 0 4px; border: 0; background: transparent; color: var(--muted); cursor: pointer; font-size: 10px; line-height: 1; }
.todo-actions button + button { border-left: 1px solid var(--line); }
.todo-actions button:hover, .todo-actions button:focus-visible { background: var(--paper-raised); color: var(--ink); }
.todo-actions .todo-continue { color: var(--green); }
.todo-complete-label { display: inline-block; margin-top: 5px; color: var(--green); font-size: 8px; font-weight: 700; letter-spacing: .1em; text-transform: uppercase; }
.todo-empty { margin: 0; padding: 22px 3px; color: var(--muted); font-size: 11px; }

.confirm-dialog::backdrop { background: rgba(23, 23, 19, .52); }
.confirm-card { display: grid; grid-template-columns: auto minmax(0, 1fr) auto; grid-template-areas: "mark title actions" "mark copy actions"; align-items: center; gap: 5px 20px; padding: 26px 30px; }
.confirm-mark { grid-area: mark; width: 30px; height: 30px; display: grid; place-items: center; border: 1px solid var(--red); color: var(--red); font-weight: 700; }
.confirm-card h2 { grid-area: title; margin: 0; font: 400 32px/1 var(--serif); }
.confirm-card p { grid-area: copy; margin: 3px 0 0; color: var(--muted); }
.confirm-card > div { grid-area: actions; display: flex; justify-content: flex-end; gap: 9px; }
.confirm-card .button { border-radius: 2px; }
.confirm-card .confirm-delete { border-color: var(--red); background: var(--red); color: white; }
.confirm-card .confirm-delete:hover { background: #982f25; }

.install-dialog { width: min(var(--dialog-sm), calc(100% - 28px)); }
.install-dialog::backdrop { background: rgba(23, 23, 19, .52); }
.install-card { position: relative; padding: 32px; }
.install-close { position: absolute; top: 18px; right: 18px; }
.install-mark { width: 42px; height: 42px; display: grid; place-items: center; margin-bottom: 28px; border: 1px solid var(--ink); border-radius: 50%; color: var(--ink); }
.install-mark::before { content: ""; width: 46%; height: 46%; background: currentColor; -webkit-mask: var(--asimov-mark); mask: var(--asimov-mark); }
.install-card h2 { max-width: 330px; margin: 0; font: 400 38px/1.02 var(--serif); letter-spacing: -.02em; }
.install-steps { display: grid; gap: 18px; margin: 30px 0 24px; padding: 0; list-style: none; }
.install-steps li { display: grid; grid-template-columns: 32px minmax(0, 1fr); gap: 13px; align-items: start; }
.install-steps li > span { width: 32px; height: 32px; display: grid; place-items: center; border: 1px solid var(--line); border-radius: 50%; font-size: 16px; line-height: 1; }
.install-steps strong, .install-steps small { display: block; }
.install-steps strong { margin: 1px 0 2px; font-size: 13px; }
.install-steps small { color: var(--muted); font-size: 12px; line-height: 1.4; }
.install-help { margin: 0 0 22px; padding-top: 18px; border-top: 1px solid var(--line); color: var(--muted); font-size: 11px; }
.install-done { width: 100%; min-height: 42px; }

.editor-dialog {
  width: min(1160px, calc(100% - 16px));
  max-height: min(1040px, calc(100dvh - 16px));
  padding: 0;
  overflow: hidden;
  border: 1px solid #bdb7ab;
  border-radius: 4px;
  background: var(--paper-raised);
  color: var(--ink);
  box-shadow: var(--shadow);
}
.editor-dialog::backdrop { background: rgba(23, 23, 19, .46); }
.editor-form { position: relative; max-height: min(1040px, calc(100dvh - 16px)); overflow-y: auto; padding: 32px 32px 0; }
.dialog-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 20px; margin-bottom: 28px; }
.dialog-head h2 { margin: 0; font: 400 38px/1 var(--serif); letter-spacing: -.015em; }
/* A muted description paragraph inside a dialog — Presentations' and
   Announcements' confirm dialogs each wrote a near-identical version of
   this before core/dialogs.js unified them. */
.dialog-body { margin: 0 0 20px; color: var(--muted); font-size: var(--text-reading); line-height: 1.5; }
/* Ask dialog — core/dialogs.js's askConfirm()/askText(), the app's own
   voice instead of the browser's native confirm()/prompt(). Small (Small
   tier), everything else comes from .editor-dialog/.editor-form/
   .dialog-head/.dialog-actions unmodified — no special-casing needed once
   those are real. */
.ask-dialog { width: min(var(--dialog-sm), calc(100% - 24px)); }
.ask-dialog .dialog-head h2 { font-size: 26px; }
.project-edit-back { justify-self: start; min-height: 34px; padding: 0 13px; border: 1px solid var(--ink); border-radius: 999px; background: transparent; color: var(--ink); cursor: pointer; font-size: 11px; }
.project-edit-back:hover { background: var(--ink); color: white; }
.project-details-edit { position: absolute; z-index: 3; top: 16px; left: 16px; background: rgba(251, 249, 243, .92); }
.project-details-edit:hover { background: var(--ink); }
.project-editor-back { position: absolute; z-index: 3; top: 16px; left: 16px; background: rgba(251, 249, 243, .92); }
.project-editor-back:hover { background: var(--ink); }
.project-editor-close { position: absolute; z-index: 3; top: 16px; right: 16px; background: rgba(251, 249, 243, .92); }
.icon-button { width: var(--tap); height: var(--tap); display: inline-flex; align-items: center; justify-content: center; padding: 0 0 2px; border: 0; border-radius: 50%; background: transparent; cursor: pointer; font-size: 18px; line-height: 1; transition: background .12s; }
.icon-button:hover { background: rgba(23, 23, 19, .07); }
.icon-button.is-danger:hover { color: var(--red); }
.icon-button.is-dense { width: var(--tap-dense); height: var(--tap-dense); font-size: 14px; }
.form-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 18px; }
.field { display: grid; gap: 7px; }
.field.full { grid-column: 1 / -1; }
.field label, .field > span { color: var(--muted); font-size: 10px; font-weight: 700; letter-spacing: .1em; text-transform: uppercase; }
.field input, .field textarea, .field select {
  width: 100%;
  padding: 11px 0;
  border: 0;
  border-bottom: 1px solid var(--muted-line);
  outline: 0;
  background: transparent;
  color: var(--ink);
  transition: border-color .12s;
}
.field textarea { min-height: 76px; resize: vertical; }
.field select { cursor: pointer; }
.field input:focus, .field textarea:focus, .field select:focus { border-color: var(--blue); }
.field input::placeholder, .field textarea::placeholder { color: var(--muted-line); }
.field input[type="file"] { padding: 10px; border: 1px dashed var(--line); }
.field input[type="color"] { width: 70px; height: 42px; padding: 3px; border: 1px solid var(--line); }

/* Boxed input — a search/date/time field standing alone in a toolbar, as
   opposed to .field's underline style above (which is for several labeled
   inputs stacked in a form). */
.input-boxed { min-height: var(--tap); padding: 0 10px; border: 1px solid var(--line); border-radius: 3px; background: var(--paper-raised); color: var(--ink); font: inherit; font-size: var(--text-control); }
.input-boxed:focus { border-color: var(--blue); outline: 0; }
.scholar-import { padding: 14px; border: 1px solid var(--line); background: rgba(24, 79, 209, .025); }
.scholar-import-row { display: grid; grid-template-columns: minmax(0, 1fr) auto; align-items: end; gap: 12px; }
.scholar-preview { display: grid; grid-template-columns: 43px minmax(0, 1fr) auto; align-items: center; gap: 12px; margin-top: 13px; padding-top: 13px; border-top: 1px solid var(--line); }
.scholar-preview img, .scholar-placeholder { width: 43px; height: 43px; display: grid; place-items: center; border-radius: 50%; object-fit: cover; background: var(--blue-soft); color: var(--blue); font: 400 18px/1 var(--serif); }
.scholar-preview p { margin: 2px 0 0; color: var(--muted); font-size: 10px; }
.scholar-preview button { padding: 0; border: 0; border-bottom: 1px solid currentColor; background: transparent; color: var(--red); cursor: pointer; font-size: 10px; }
.compact-form { min-height: 250px; }
.image-preview { width: min(100%, 360px); max-height: 180px; object-fit: cover; border: 1px solid var(--line); }
.color-options { display: flex; align-items: center; gap: 8px; min-height: 42px; }
.color-options input { position: absolute; width: 1px; height: 1px; padding: 0; opacity: 0; pointer-events: none; }
.color-options span { width: 24px; height: 24px; display: block; border: 3px solid var(--paper-raised); border-radius: 50%; background: var(--swatch); box-shadow: 0 0 0 1px var(--line); cursor: pointer; }
.color-options input:checked + span { box-shadow: 0 0 0 2px var(--ink); }
.subhead { display: flex; align-items: center; justify-content: space-between; margin: 28px 0 12px; }
.subhead h3 { margin: 0; font-size: 11px; letter-spacing: var(--tracking-label); text-transform: uppercase; }
.text-button { padding: 4px 0; border: 0; border-bottom: 1px solid currentColor; background: transparent; color: var(--blue); cursor: pointer; font-size: 11px; }
.contact-options { display: flex; flex-wrap: wrap; gap: 7px; }
.contact-option input { position: absolute; width: 1px; height: 1px; padding: 0; opacity: 0; pointer-events: none; }
.contact-option span { display: block; padding: 7px 11px; border: 1px solid var(--line); border-radius: 999px; color: var(--muted); cursor: pointer; transition: color .12s, background .12s, border-color .12s; }
.contact-option input:checked + span { border-color: var(--blue); background: var(--blue-soft); color: var(--blue); }
.contact-option input:focus-visible + span { outline: 2px solid var(--blue); outline-offset: 2px; }
.remove-row { border: 0; background: transparent; color: var(--muted); cursor: pointer; font-size: 18px; }
.remove-row:hover { color: var(--red); }
.toggle-row { display: flex; align-items: center; gap: 9px; margin-top: 22px; color: var(--muted); font-size: 12px; }
.toggle-row input { accent-color: var(--blue); }
.asimov-link-panel { padding: 13px; border: 1px solid var(--line); background: rgba(24, 79, 209, .025); }
.linked-asimov { display: grid; gap: 5px; }
.linked-asimov p { margin: 0; color: var(--muted); font-size: 11px; }
.linked-asimov button { justify-self: start; padding: 0; border: 0; border-bottom: 1px solid currentColor; background: none; color: var(--red); cursor: pointer; font-size: 10px; }
.asimov-picker { max-height: 240px; display: grid; gap: 5px; overflow-y: auto; }
.asimov-picker button { display: grid; grid-template-columns: 1fr auto; gap: 3px 12px; padding: 10px; border: 1px solid var(--line); background: var(--paper-raised); text-align: left; cursor: pointer; }
.asimov-picker button:hover { border-color: var(--blue); }
.asimov-picker span { color: var(--blue); font-size: 9px; text-transform: uppercase; }
.asimov-picker p { grid-column: 1 / -1; margin: 0; color: var(--muted); font-size: 10px; }
.dialog-actions { display: flex; align-items: center; justify-content: flex-end; gap: 10px; margin-top: 30px; }
.dialog-actions .is-danger { margin-right: auto; }
/* .editor-form scrolls its own content (see above) with .dialog-actions as
   its last child, so pinning it here — rather than each dialog wiring its
   own grid rows, like .file-modal does — is the one change that fixes every
   .editor-form-based dialog at once. .editor-form's own bottom padding
   moved onto this rule's padding-bottom instead of staying on the
   container: with position: sticky, that padding sat below the pinned bar
   as dead scrollable space, not room the bar was using — the bug on short
   (small/medium) dialogs, where there's nothing to scroll past it. */
.editor-form .dialog-actions {
  position: sticky;
  bottom: 0;
  z-index: 2;
  margin: 20px -32px 0;
  padding: 14px 32px;
  background: var(--paper-raised);
  border-top: 1px solid var(--line);
  box-shadow: 0 -8px 22px rgba(34, 31, 25, .045);
}
.autosave-note { color: var(--green); font-size: 9px; letter-spacing: .04em; }
.button { min-height: 39px; display: inline-flex; align-items: center; justify-content: center; padding: 1px 16px 0; border: 1px solid var(--line); border-radius: 999px; background: transparent; cursor: pointer; line-height: 1; transition: background .12s; }
.button:hover { background: rgba(23, 23, 19, .05); }
.button:active { opacity: .75; }
.button:disabled { opacity: .35; cursor: not-allowed; }
.button[hidden] { display: none; }
.button.filled { border-color: var(--ink); background: var(--ink); color: white; }
.button.filled:hover { background: var(--blue); border-color: var(--blue); }
.button.is-danger { border-color: #ddb7b1; color: var(--red); }
.button.is-danger:hover { border-color: var(--red); background: var(--red); color: white; }
.button.filled.is-danger { border-color: var(--red); background: var(--red); color: white; }
.button.filled.is-danger:hover { background: #9d3227; border-color: #9d3227; }

/* Toolbar button — small, rectangular, for a toolbar's own row of actions
   (Data Files, Organization's collection drawer, Decks). Works on <select>
   too. */
.dl-btn { min-height: 30px; max-width: 150px; padding: 1px 10px 0; border: 1px solid var(--line); border-radius: 2px; background: transparent; color: var(--muted); cursor: pointer; font-size: var(--text-control); }
.dl-btn:hover:not(:disabled) { border-color: var(--ink); color: var(--ink); }
.dl-btn:disabled { opacity: .35; cursor: not-allowed; }
.dl-btn.is-danger:hover:not(:disabled) { border-color: var(--red); color: var(--red); }
.dl-btn.is-primary { border-color: var(--ink); background: var(--ink); color: white; }
.dl-btn.is-primary:hover { background: var(--blue); border-color: var(--blue); }
.dl-btn[aria-pressed="true"] { border-color: var(--blue); color: var(--blue); }
.dl-btn.has-chevron { display: inline-flex; align-items: center; padding-right: 8px; }
.dl-btn.is-icon { width: 28px; height: 28px; min-height: 0; padding: 0; display: inline-flex; align-items: center; justify-content: center; }

/* Text action — an action styled like a text link (no border/box), for a
   secondary action inline with text or in a list row. Hover-only underline,
   same convention as the Text links tier. */
.btn-text { padding: 0; border: 0; background: none; color: var(--blue); cursor: pointer; font-size: var(--text-meta); text-underline-offset: 2px; }
.btn-text:hover { text-decoration: underline; }
.btn-text:disabled { color: var(--muted-line); cursor: default; opacity: .35; }
.btn-text.is-danger { color: var(--red); }

.editor-dialog.overview-mode, .editor-dialog.project-editor-mode { width: min(1680px, calc(100% - 16px)); }
.editor-dialog.overview-mode { height: min(1040px, calc(100dvh - 16px)); }
.editor-dialog.overview-mode #editor-content { height: 100%; }
.project-overview { position: relative; height: 100%; overflow-y: auto; overscroll-behavior: contain; scrollbar-gutter: stable; }
.overview-close { position: absolute; z-index: 3; top: 16px; right: 16px; background: rgba(251, 249, 243, .9); }
.overview-cover { width: 100%; height: clamp(80px, 12vw, 140px); display: block; object-fit: cover; }
.overview-color-block { width: 100%; height: clamp(40px, 6vw, 70px); display: block; background: var(--project-color); }
.project-editor-cover { width: calc(100% + 64px); height: clamp(80px, 12vw, 140px); display: block; margin: -32px -32px 28px; object-fit: cover; }
.project-editor-color { height: clamp(40px, 6vw, 70px); background: var(--project-color); }
.overview-content { padding: 34px; }
.overview-kicker { display: flex; gap: 10px; color: var(--project-color); font-size: 10px; font-weight: 700; letter-spacing: .1em; text-transform: uppercase; }
.overview-content h2 { margin: 12px 0; font: 400 clamp(38px, 6vw, 65px)/.95 var(--serif); letter-spacing: -.02em; }
.overview-summary { max-width: 700px; margin: 0; font: 18px/1.5 var(--serif); }
.is-muted { color: var(--muted); }
.overview-stats { display: flex; flex-wrap: wrap; gap: 34px; margin: 30px 0; padding: 18px 0; border-block: 1px solid var(--line); }
.overview-stats div { display: grid; }
.overview-stats strong { font: 400 29px/1 var(--serif); }
.overview-stats span { color: var(--muted); font-size: 9px; text-transform: uppercase; }
.overview-links { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(320px, 100%), 1fr)); gap: 9px; margin-top: 22px; }
.asimov-overview { display: grid; grid-template-columns: auto 1fr auto; align-items: start; gap: 14px; padding: 17px; border: 1px solid #c7d5f5; background: #edf2ff; color: var(--ink); text-decoration: none; }
.asimov-badge { padding: 5px 7px; background: var(--blue); color: white; font: 700 12px/1 var(--serif); }
.asimov-overview p { margin: 4px 0 0; color: var(--muted); font-size: 11px; }
.github-overview { display: grid; grid-template-columns: auto 1fr auto; align-items: start; gap: 14px; padding: 17px; border: 1px solid #c8c5bd; background: #f4f3ef; color: var(--ink); text-decoration: none; }
.github-badge { padding: 5px 7px; background: var(--ink); color: white; font: 700 11px/1 var(--sans); }
.github-overview p { margin: 4px 0; color: var(--muted); font-size: 11px; }
.github-overview small { color: var(--muted); font-size: 9px; }
.subproject-section { margin-top: 32px; padding-top: 20px; border-top: 1px solid var(--line); }
.subproject-head { display: flex; align-items: flex-end; justify-content: space-between; gap: 20px; margin-bottom: 14px; }
.subproject-head span { color: var(--project-color); font-size: 9px; font-weight: 700; letter-spacing: var(--tracking-label); text-transform: uppercase; }
.subproject-head h3 { margin: 4px 0 0; font: 400 24px/1 var(--serif); }
.subproject-head button, .subproject-back { padding: 3px 0; border: 0; border-bottom: 1px solid currentColor; background: transparent; color: var(--project-color); cursor: pointer; font-size: 10px; }
.subproject-board { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 10px; }
.subproject-lane { min-width: 0; min-height: 165px; padding: 12px; border: 1px solid var(--line); border-top: 3px solid var(--lane-color); background: rgba(251, 249, 243, .5); transition: border-color .12s, background .12s; }
.subproject-lane.lane-backlog { --lane-color: #9b958a; }
.subproject-lane.lane-active { --lane-color: var(--blue); }
.subproject-lane.lane-done { --lane-color: var(--green); }
.subproject-lane.is-over { border-color: var(--lane-color); background: rgba(24, 79, 209, .04); }
.subproject-lane > header { display: flex; align-items: center; justify-content: space-between; gap: 12px; margin-bottom: 10px; }
.subproject-lane h4 { margin: 0; font-size: 9px; font-weight: 700; letter-spacing: .11em; text-transform: uppercase; }
.subproject-lane > header span { color: var(--muted); font-size: 9px; font-variant-numeric: tabular-nums; }
.subproject-cards { display: grid; gap: 7px; }
.subproject-cards > p { margin: 24px 0; color: var(--muted-line); font-size: 9px; text-align: center; }
.subproject-card { position: relative; min-width: 0; padding: 12px 12px 11px 31px; border: 1px solid #d5d0c5; background: var(--paper-raised); cursor: grab; transition: border-color .12s, opacity .12s, transform .12s; }
.subproject-card:hover { border-color: var(--lane-color); transform: translateY(-1px); }
.subproject-card:focus-visible { outline: 2px solid var(--blue); outline-offset: 2px; }
.subproject-card.is-dragging { opacity: .35; }
.subproject-card .branch-mark { position: absolute; top: 12px; left: 11px; color: var(--lane-color); font-size: 14px; line-height: 1; }
.subproject-card h5 { margin: 0; overflow-wrap: anywhere; font: 400 15px/1.25 var(--serif); }
.subproject-card small { display: block; margin-top: 8px; color: var(--muted); font-size: 8px; }
.subproject-detail .subproject-color-block { height: 72px; background: var(--project-color); }
.subproject-back { margin-bottom: 23px; }
.subproject-editor { display: grid; grid-template-columns: minmax(0, 1fr) 180px; gap: 18px; margin-top: 28px; padding: 20px; border: 1px solid var(--line); background: rgba(251, 249, 243, .52); }
.subproject-editor label { display: grid; gap: 6px; }
.subproject-editor label span { color: var(--muted); font-size: 8px; font-weight: 700; letter-spacing: .1em; text-transform: uppercase; }
.subproject-editor input, .subproject-editor select { width: 100%; padding: 9px 0; border: 0; border-bottom: 1px solid var(--muted-line); outline: 0; background: transparent; color: var(--ink); }
.subproject-editor input:focus, .subproject-editor select:focus { border-color: var(--blue); }
.subproject-editor .dialog-actions { grid-column: 1 / -1; margin-top: 4px; }
.project-log-section { margin-top: 32px; padding-top: 20px; border-top: 1px solid var(--line); }
.project-log-head { display: flex; align-items: baseline; justify-content: space-between; gap: 14px; margin-bottom: 12px; }
.project-log-head h3 { margin: 0; font-size: 10px; letter-spacing: var(--tracking-label); text-transform: uppercase; }
.project-log-head span { color: var(--muted); font-size: 10px; }
.project-log-form { display: grid; grid-template-columns: minmax(0, 1fr) auto; border-bottom: 1px solid var(--muted-line); }
.project-log-form:focus-within { border-color: var(--blue); }
.project-log-form input { min-width: 0; padding: 12px 2px; border: 0; outline: 0; background: transparent; color: var(--ink); }
.project-log-form input::placeholder { color: var(--muted-line); }
.project-log-form button { padding: 0 2px 0 14px; border: 0; background: transparent; color: var(--muted); cursor: pointer; font-size: 10px; }
.project-log-form button:hover { color: var(--blue); }
.log-stack { margin-top: 8px; }
.log-entry { display: grid; grid-template-columns: 135px minmax(0, 1fr); gap: 5px 18px; padding: 14px 2px; border-bottom: 1px solid var(--line); }
.log-entry time { color: var(--muted); font-size: 10px; font-variant-numeric: tabular-nums; }
.log-entry p { margin: 0; overflow-wrap: anywhere; }
.log-tags { grid-column: 2; display: flex; flex-wrap: wrap; gap: 5px; }
.log-tags span { color: var(--blue); font-size: 9px; }
.log-empty { margin: 0; padding: 17px 2px; color: var(--muted); font-size: 11px; }
.github-link-panel .linked-asimov > span { color: var(--muted); font-size: 9px; }
.github-public-label { color: var(--muted); font-size: 9px; letter-spacing: .08em; text-transform: uppercase; }
.github-url-form { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 10px; }
.github-url-form input { min-width: 0; padding: 9px 2px; border: 0; border-bottom: 1px solid var(--muted-line); outline: 0; background: transparent; color: var(--ink); }
.github-url-form input:focus { border-color: var(--blue); }
.github-url-form button { padding: 0 12px; border: 1px solid var(--ink); border-radius: 2px; background: var(--ink); color: white; cursor: pointer; font-size: 9px; }
.github-url-form button:disabled { opacity: .35; cursor: wait; }
.github-public-note { margin: 9px 0 0; color: var(--muted); font-size: 9px; }
.overview-columns { display: grid; grid-template-columns: 1.2fr .8fr; gap: 38px; margin-top: 32px; }
.overview-columns h3 { margin: 0 0 12px; font-size: 10px; letter-spacing: var(--tracking-label); text-transform: uppercase; }
.overview-people { display: grid; grid-template-columns: auto 1fr; align-items: center; gap: 7px 10px; }

.toast { position: fixed; right: 24px; bottom: 24px; z-index: 2000; max-width: 360px; padding: 12px 16px; border-left: 3px solid transparent; border-radius: 3px; background: var(--ink); color: white; box-shadow: var(--shadow); opacity: 0; transform: translateY(6px); pointer-events: none; font-size: var(--text-body); transition: opacity .14s, transform .14s ease-out; }
.toast.is-visible { opacity: 1; transform: translateY(0); }
.toast[data-tone="success"] { border-left-color: #79b89c; }
.toast[data-tone="error"] { border-left-color: #ef8d82; }
.toast.is-progress { padding-left: 34px; }
.toast.is-progress::before { content: ""; position: absolute; top: 50%; left: 15px; width: 8px; height: 8px; margin-top: -4px; border: 1px solid rgba(255, 255, 255, .35); border-top-color: white; border-radius: 50%; animation: toast-spin .7s linear infinite; }
@keyframes pop { from { opacity: 0; transform: scale(.7); } }
@keyframes toast-spin { to { transform: rotate(360deg); } }

@media (max-width: 1200px) and (min-width: 901px) {
  .masthead-live-timer { display: block; max-width: none; }
  .masthead-live-timer > span { display: none; }
}

@media (max-width: 900px) {
  /* The name is the only elastic thing in the masthead, so it is what gives
     way. Laid out as a block, not a flex row, so text-overflow can reach the
     label — as a flex container the label is an anonymous item and truncates
     mid-letter instead of ellipsising. */
  .masthead-right, .account { min-width: 0; }
  /* Icon instead of the name string — reclaims the width the name was
     eating in the masthead. Same 34px circle as the other masthead icon
     buttons (.masthead-icon). */
  .account-name {
    width: 34px;
    height: 34px;
    justify-content: center;
    border-radius: 50%;
  }
  .account-name:hover { background: rgba(23, 23, 19, .07); }
  .account-name-icon { display: block; }
  #account-name-text { display: none; }
  .account-name::after { display: none; }
  /* iOS/Android auto-zoom on focus when an input's computed font-size is
     under 16px — most of this app's controls are, by design. Bumping it
     only on :focus (not at rest) keeps the zoom locked at 100% without
     resizing every input on the page. */
  input:focus, textarea:focus, select:focus { font-size: 16px; }
  .masthead-status { width: 34px; padding: 0; justify-content: center; border-radius: 50%; }
  /* :not(:first-child), not a blanket hide: .timers-status' icon is swapped
     for an <svg> by initMasthead() so it's never a span to begin with, but
     .deadline-status' flag glyph stays a literal first <span> — the same
     one desktop's .deadline-status > span:first-child already treats as the
     icon — so a blanket "every span" rule was hiding it too. */
  .masthead-status > span:not(:first-child) { display: none; }
  .masthead-status strong { position: absolute; top: -3px; right: -4px; min-width: 16px; height: 16px; border: 2px solid var(--paper); font-size: 8px; }
  .masthead-status.has-live:not(.has-overflow) > strong { display: inline-flex; }
  .project-card { grid-column: span 6; }
  .project-row { grid-template-columns: 28px minmax(0, 1fr) auto; row-gap: 10px; }
  .row-mark { width: 28px; height: 28px; }
  .project-row .contact-stack { display: none; }
  .project-row .project-meta { grid-column: 2 / -1; }
  .people-list { display: grid; grid-template-columns: 1fr; }
  .todo-workspace { grid-template-columns: 1fr; }
}

/* Surfaces that cannot be made to work in a 390px column — the graph canvas,
   the administration console — carry .needs-landscape and a .rotate-gate
   child. In portrait the gate is all that renders; turning the phone puts the
   viewport over 700px and the real content comes back. */
.rotate-gate { display: none; }

@media (max-width: 700px) and (orientation: portrait) {
  /* The host is usually a grid sized to the viewport; the gate wants neither. */
  .needs-landscape { height: auto; min-height: 0; display: block; }
  .needs-landscape > :not(.rotate-gate) { display: none; }
  .needs-landscape > .rotate-gate {
    min-height: 340px;
    display: grid;
    place-items: center;
    align-content: center;
    gap: 16px;
    padding: 48px 24px;
    border: 1px dashed var(--line-dashed);
    text-align: center;
  }
  .rotate-gate-mark {
    width: 54px;
    height: 54px;
    display: grid;
    place-items: center;
    border: 1px solid var(--line);
    border-radius: 50%;
    color: var(--blue);
    font-size: 25px;
    line-height: 1;
  }
  .rotate-gate h2 { margin: 0; font: 400 25px/1.2 var(--serif); }
  .rotate-gate p { max-width: 30ch; margin: 0; color: var(--muted); font-size: var(--text-reading); }
}

/* ── Modal sheets ────────────────────────────────────────────────────────────
   Below the phone breakpoint every modal dialog stops being a centred card and
   becomes the screen. A card inset from a 360px viewport spends the only space
   there is on margins, and a card that caps its own height then scrolls inside
   itself strands the actions below the fold.

   The dialog becomes the scroll container and its content simply grows tall.
   Nothing here is per-dialog, so a new <dialog> is covered the moment it is
   written. Two house conventions carry the rest, and both are already
   universal in this codebase:

     · open it with showModal(), so :modal matches
     · name the close control *-close

   The selector is dialog[open]:modal — one notch above the .x-dialog.x-mode
   pairs in the page stylesheets, which is what it has to outrank. So a third
   convention, for whoever adds the next one: give a dialog its geometry
   through a class or [id="…"], never a bare #id, or it will sit above this
   layer and stay a card. Mirrored in pages/projects/tracker/frame.css for the
   shadow root. */
/* A phone in landscape is 740-930px wide, so a width test never catches it —
   hence the height half of this condition. Without it a rotated phone gets a
   centred card, which is the one shape a sheet must never be. */
@media (max-width: 700px), (max-height: 520px) and (orientation: landscape) {
  dialog[open]:modal {
    inset: 0;
    width: 100%;
    max-width: none;
    height: 100dvh;
    max-height: none;
    margin: 0;
    padding: 0 0 env(safe-area-inset-bottom);
    overflow-y: auto;
    overscroll-behavior: contain;
    border: 0;
    border-radius: 0;
  }
  /* Inner cards carry their own viewport-height cap and scroller; with the
     dialog doing the scrolling, both are wrong. */
  dialog[open]:modal > * { max-height: none; }
  /* Pinned to the viewport rather than to the content, so it survives the
     scroll. A fullscreen dialog is the containing block. Opaque, because
     content now passes underneath it. */
  dialog[open]:modal [class*="-close"] {
    position: fixed;
    top: 9px;
    right: 9px;
    z-index: 5;
    background: var(--paper-raised);
  }
}

@media (max-width: 700px) {
  /* The whole scale steps down a notch: a phone column is narrower than a
     desktop one but the words in it are the same length. */
  :root {
    --tap: 38px;
    --tap-dense: 30px;
    --panel-gap: 14px;
    --text-meta: 8px;
    --text-label: 9px;
    --text-control: 10px;
    --text-body: 11px;
    --text-reading: 12px;
    --text-panel-title: 18px;
    --text-stat: 22px;
    /* The desktop clamp floors at 30.4px, so it never reaches a phone's
       width. This one scales the whole way down. */
    --text-page-title: clamp(18px, 5vw, 26px);
  }
  body { font-size: 13px; }
  h1 { font-size: 34px; }
  .missed-todo-alert strong { font-size: 15px; }
  .folder-tab { font-size: 15px; }
  .project-card h2 { font-size: 21px; }
  .project-row h2 { font-size: 17px; }
  .person-name { font-size: 19px; }
  .todo-panel-head h2, .daily-head h2 { font-size: 20px; }
  .empty-state h2 { font-size: 20px; }
  .empty-glyph { width: 42px; height: 42px; font-size: 21px; }
  .subproject-head h3 { font-size: 19px; }
  .overview-stats strong { font-size: 22px; }
  .overview-summary { font-size: 15px; }
  .dialog-head h2 { font-size: 18px; }
  .confirm-card h2 { font-size: 24px; }
  .install-card h2 { font-size: 26px; }
  .overview-content h2 { font-size: clamp(24px, 7vw, 34px); }

  .nav-item { min-height: var(--tap); }
  .pin-toggle,
  .note-layout button { width: var(--tap-dense); height: var(--tap-dense); }
  /* Inline beside a 20px select, not a row tool — it takes its scale from
     the control it belongs to. */
  .todo-project-control select { height: 24px; }
  .todo-project-control button { width: 24px; height: 24px; }
  .note-delete, .todo-delete,
  .entry-edit, .entry-copy { min-width: var(--tap-dense); min-height: var(--tap-dense); }
  .todo-actions button,
  .todo-entry-tools button { min-width: var(--tap-dense); height: var(--tap-dense); padding-inline: 6px; }
}

@media (max-width: 560px) {
  .masthead { height: 62px; padding-inline: 14px; }
  body.in-project .masthead { padding-inline: 14px; }
  .masthead-right { gap: 9px; }
  .masthead-tools { gap: 3px; }
  /* Upload/export are desktop-workflow concerns — a phone screen has no room
     for them and no real use for a background transfer queue either. */
  .upload-queue, .export-queue { display: none; }
  .wordmark > span:last-child { display: none; }
  .shell { width: min(100% - 28px, 1120px); padding-top: 22px; }
  .intro { margin-bottom: 24px; }
  .title-row { align-items: flex-start; flex-direction: column; }
  h1 { font-size: 27px; }
  .view-nav { flex-wrap: wrap; gap: 4px 18px; }
  .missed-todo-alert { align-items: stretch; flex-direction: column; gap: 11px; margin-top: -18px; padding: 13px 0; }
  .missed-todo-alert > div:first-child { grid-template-columns: 1fr; }
  .missed-todo-alert small { grid-column: 1; }
  .missed-todo-actions { display: grid; grid-template-columns: 1fr 1fr 30px; }
  .missed-todo-actions button { min-height: 36px; }
  .project-card { grid-column: 1 / -1; min-height: 205px; }
  .project-row { grid-template-columns: 28px minmax(0, 1fr); }
  .row-folder { grid-column: 2; justify-self: start; }
  .people-toolbar { align-items: stretch; flex-direction: column; }
  .todo-tag-bar { align-items: stretch; flex-direction: column; }
  .tag-index { justify-content: flex-start; }
  .todo-composer { grid-template-columns: minmax(0, 1fr) auto; }
  .todo-input { grid-column: 1 / -1; }
  .todo-compose-project { margin-left: 0; padding-left: 2px; border-left: 0; }
  .todo-complete-label { padding: 2px 6px; border-radius: 999px; background: var(--green); color: white; }
  .note-stack.columns-1, .note-stack.columns-2, .note-stack.columns-3 { grid-template-columns: 1fr; }
  .person-photo { width: 48px; height: 48px; }
  .scholar-line, .person-interests, .person-groups, .person-projects { margin-left: 63px; }
  .scholar-import-row { grid-template-columns: 1fr; }
  .overview-columns { grid-template-columns: 1fr; }
  .subproject-board { grid-template-columns: 1fr; }
  .subproject-lane { min-height: 105px; }
  .subproject-editor { grid-template-columns: 1fr; padding: 16px; }
  .subproject-editor .dialog-actions { grid-column: 1; }
  .github-url-form { grid-template-columns: 1fr; }
  .github-url-form button { min-height: 34px; justify-self: start; }
  .log-entry { grid-template-columns: 1fr; }
  .log-tags { grid-column: 1; }
  .overview-content { padding: 25px 18px; }
  .overview-color-block, .project-editor-color { min-height: 52px; }
  .project-details-edit, .project-editor-back, .project-editor-close { top: 9px; }
  .confirm-card { display: block; padding: 24px 18px; }
  .confirm-mark { margin-bottom: 18px; }
  .confirm-card p { margin: 8px 0 24px; }
  .install-card { padding: 26px 22px 22px; }
  .install-card h2 { font-size: 24px; }
  .install-mark { margin-bottom: 24px; }
  .editor-form { padding: 24px 18px 0; }
  .editor-form .dialog-actions { margin: 16px -18px 0; padding: 10px 18px; }
  .project-editor-cover { width: calc(100% + 36px); margin: -24px -18px 24px; }
  .form-grid { grid-template-columns: 1fr; }
  .field.full { grid-column: auto; }
  /* No font-size floor on fields. Every layout in this app is built around
     10-13px type, and an inline editor, a filter or a project title forced to
     16px reads as broken — which is what a floor here did to each of them in
     turn. Fields keep their designed size and iOS Safari zooms the page when
     one is focused; that is the accepted trade. Undoing it means
     maximum-scale=1 on the viewport meta in index.html, which costs
     pinch-zoom everywhere, so it is a decision rather than a tweak.
     The two properties below are unrelated: they stop iOS washing out the
     text of a disabled field. */
  input, textarea, select { -webkit-text-fill-color: currentColor; opacity: 1; }
  .logout { font-size: 0; }
  .logout::after { content: "Exit"; font-size: 12px; }
  .toast { right: 14px; bottom: 14px; left: 14px; max-width: none; }
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { scroll-behavior: auto !important; animation-duration: .01ms !important; animation-iteration-count: 1 !important; transition-duration: .01ms !important; }
}
