/* ================= Folio — editorial markdown reader ================= */

:root {
  --serif: Charter, 'Bitstream Charter', 'Sitka Text', Cambria, Georgia, 'Times New Roman', serif;
  --sans: -apple-system, BlinkMacSystemFont, 'Segoe UI', Inter, Roboto, 'Helvetica Neue', sans-serif;
  --mono: ui-monospace, 'SF Mono', SFMono-Regular, Menlo, Consolas, 'Liberation Mono', monospace;

  --safe-top: env(safe-area-inset-top, 0px);
  --safe-bottom: env(safe-area-inset-bottom, 0px);
  --safe-left: env(safe-area-inset-left, 0px);
  --safe-right: env(safe-area-inset-right, 0px);

  --topbar-h: calc(52px + var(--safe-top));
  --sidebar-w: 272px;
  --prose-size: 17.5px;

  /* Light: warm paper */
  --bg: #faf9f7;
  --bg-raised: #f1efeb;
  --bg-sidebar: #f4f2ee;
  --ink: #34302a;
  --ink-strong: #211e19;
  --muted: #7d786e;
  --faint: #a8a396;
  --border: #e4e1da;
  --accent: #8a3b2e;
  --accent-soft: rgba(138, 59, 46, 0.08);
  --code-bg: rgba(90, 80, 60, 0.07);
  --pre-bg: #f2f0ec;
  --shadow: 0 1px 3px rgba(40, 35, 25, 0.08);

  --hl-comment: #918c80;
  --hl-keyword: #9d4a34;
  --hl-string: #3f6e4b;
  --hl-number: #a06a1f;
  --hl-title: #4a5d94;
  --hl-attr: #77522e;
}

/* Dark: warm dark gray, reduced-contrast text */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --bg: #1c1b1a;
    --bg-raised: #262523;
    --bg-sidebar: #211f1e;
    --ink: #cfccc4;
    --ink-strong: #e8e5dd;
    --muted: #8f8b81;
    --faint: #6b675e;
    --border: #34322e;
    --accent: #d99a83;
    --accent-soft: rgba(217, 154, 131, 0.1);
    --code-bg: rgba(255, 250, 235, 0.07);
    --pre-bg: #232220;
    --shadow: 0 1px 3px rgba(0, 0, 0, 0.4);

    --hl-comment: #7d786e;
    --hl-keyword: #d9927b;
    --hl-string: #a3c495;
    --hl-number: #d4b06a;
    --hl-title: #97aede;
    --hl-attr: #c9a97d;
  }
}
:root[data-theme="dark"] {
  --bg: #1c1b1a;
  --bg-raised: #262523;
  --bg-sidebar: #211f1e;
  --ink: #cfccc4;
  --ink-strong: #e8e5dd;
  --muted: #8f8b81;
  --faint: #6b675e;
  --border: #34322e;
  --accent: #d99a83;
  --accent-soft: rgba(217, 154, 131, 0.1);
  --code-bg: rgba(255, 250, 235, 0.07);
  --pre-bg: #232220;
  --shadow: 0 1px 3px rgba(0, 0, 0, 0.4);

  --hl-comment: #7d786e;
  --hl-keyword: #d9927b;
  --hl-string: #a3c495;
  --hl-number: #d4b06a;
  --hl-title: #97aede;
  --hl-attr: #c9a97d;
}

/* E-ink: pure grayscale, hard edges, no motion — wins over light and dark */
:root[data-eink] {
  --bg: #ffffff;
  --bg-raised: #f0f0f0;
  --bg-sidebar: #ffffff;
  --ink: #111111;
  --ink-strong: #000000;
  --muted: #3d3d3d;
  --faint: #6e6e6e;
  --border: #9a9a9a;
  --accent: #000000;
  --accent-soft: rgba(0, 0, 0, 0.08);
  --code-bg: rgba(0, 0, 0, 0.07);
  --pre-bg: #f2f2f2;
  --shadow: none;

  --hl-comment: #666666;
  --hl-keyword: #000000;
  --hl-string: #333333;
  --hl-number: #333333;
  --hl-title: #000000;
  --hl-attr: #444444;
}
:root[data-eink] * {
  transition: none !important;
  animation: none !important;
  box-shadow: none !important;
  text-shadow: none !important;
}
:root[data-eink] body { -webkit-font-smoothing: auto; }
:root[data-eink] .topbar { backdrop-filter: none; background: var(--bg); }
:root[data-eink] .drop-veil { backdrop-filter: none; }
:root[data-eink] .prose img { filter: grayscale(1) contrast(1.05); }

/* ================= Base ================= */

* { box-sizing: border-box; }

html {
  scrollbar-gutter: stable;
  scroll-padding-top: calc(var(--topbar-h) + 16px);
  -webkit-text-size-adjust: 100%;
  /* Disable double-tap-to-zoom (pinch zoom still works); restricting the
     root restricts every descendant's touch gestures with it. */
  touch-action: manipulation;
}

body {
  margin: 0;
  background: var(--bg);
  color: var(--ink);
  font-family: var(--sans);
  font-size: 15px;
  -webkit-font-smoothing: antialiased;
  transition: background-color 0.15s ease, color 0.15s ease;
}

button { font: inherit; color: inherit; -webkit-tap-highlight-color: transparent; }
a { -webkit-tap-highlight-color: transparent; }

/* ================= Top bar ================= */

.topbar {
  position: sticky;
  top: 0;
  z-index: 20;
  display: flex;
  align-items: center;
  gap: 10px;
  height: var(--topbar-h);
  padding: var(--safe-top) calc(14px + var(--safe-right)) 0 calc(14px + var(--safe-left));
  background: color-mix(in srgb, var(--bg) 88%, transparent);
  backdrop-filter: blur(10px);
  border-bottom: 1px solid var(--border);
}

.file-name {
  color: var(--muted);
  font-size: 13.5px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  min-width: 0;
}
.file-name:not(:empty) { cursor: pointer; }

.file-rename {
  font: inherit;
  font-size: 13.5px;
  color: var(--ink);
  background: var(--bg-raised);
  border: 1px solid var(--border);
  border-radius: 6px;
  padding: 3px 8px;
  min-width: 0;
  width: min(340px, 44vw);
  outline: none;
}
.file-rename:focus { border-color: var(--accent); }

.spacer { flex: 1; }

.icon-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  border: 1px solid transparent;
  background: none;
  border-radius: 8px;
  cursor: pointer;
  color: var(--muted);
  padding: 7px;
  touch-action: manipulation;
}
.font-btn {
  font-family: var(--serif);
  font-weight: 600;
  font-size: 13px;
  letter-spacing: 0.02em;
}
#font-inc { font-size: 15.5px; }

.icon-btn:disabled { opacity: 0.35; cursor: default; }
/* `hidden` has to win over the flex display above — the search button is
   hidden until a document is open. */
.icon-btn[hidden] { display: none !important; }
.icon-btn[aria-pressed="true"] {
  color: var(--accent);
  background: var(--accent-soft);
}

.icon-btn:hover {
  color: var(--ink-strong);
  background: var(--bg-raised);
}

/* --- settings panel --- */

/* A full-height panel on the right rather than a dropdown. It sits under the
   brightness and tone veils on purpose, so adjusting them shows their real
   effect on the page instead of on a panel floating above it. */

.menu-scrim {
  position: fixed;
  inset: 0;
  z-index: 29;
  background: rgba(0, 0, 0, 0.28);
  opacity: 0;
  /* Inert rather than removed, so the fade survives the close. */
  pointer-events: none;
  transition: opacity 0.22s ease;
}
body.menu-open .menu-scrim { opacity: 1; pointer-events: auto; }

@media (prefers-reduced-motion: reduce) {
  .menu-scrim, .menu-panel { transition: none; }
}

.menu-panel {
  position: fixed;
  top: 0;
  right: 0;
  bottom: 0;
  z-index: 30;
  width: min(320px, 86vw);
  display: flex;
  flex-direction: column;
  background: var(--bg-sidebar);
  border-left: 1px solid var(--border);
  box-shadow: -12px 0 34px rgba(0, 0, 0, 0.16);
  /* Off-screen and out of the tab order until opened. `visibility` is stepped
     rather than transitioned: on close it's delayed so the slide-out stays
     visible, but on open it must flip in the same style recalc — a visibility
     *transition* leaves the panel hidden for a frame, and a hidden element
     silently refuses focus(). */
  transform: translateX(100%);
  visibility: hidden;
  transition: transform 0.22s ease, visibility 0s linear 0.22s;
}
.menu-panel:focus { outline: none; }
body.menu-open .menu-panel {
  transform: none;
  visibility: visible;
  transition: transform 0.22s ease, visibility 0s;
}

.menu-panel-head {
  flex: none;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  height: var(--topbar-h);
  padding: var(--safe-top) calc(10px + var(--safe-right)) 0 16px;
  border-bottom: 1px solid var(--border);
}
.menu-panel-title {
  font-size: 11px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.09em;
  color: var(--faint);
}

.menu-panel-body {
  flex: 1;
  overflow-y: auto;
  padding: 10px 10px calc(24px + var(--safe-bottom));
}

.menu-item {
  display: flex;
  align-items: center;
  gap: 10px;
  width: 100%;
  border: 0;
  background: none;
  cursor: pointer;
  padding: 9px 10px;
  border-radius: 8px;
  font-size: 13.5px;
  color: var(--ink);
  text-align: left;
  text-decoration: none;
  touch-action: manipulation;
}
.menu-item svg { flex: none; color: var(--muted); }
.menu-item:hover { background: var(--bg-raised); }
.menu-item[aria-pressed="true"] {
  color: var(--accent);
  background: var(--accent-soft);
}
.menu-item[aria-pressed="true"] svg { color: var(--accent); }

.menu-sep { height: 1px; background: var(--border); margin: 6px 4px; }

.menu-size {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  padding: 2px 4px 2px 10px;
  font-size: 13.5px;
  color: var(--ink);
}
.menu-size-btns { display: inline-flex; }

/* theme toggle shows the icon for the theme you'd switch to */
.moon { display: none; }
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .sun { display: none; }
  :root:not([data-theme="light"]) .moon { display: block; }
}
:root[data-theme="dark"] .sun { display: none; }
:root[data-theme="dark"] .moon { display: block; }
:root[data-theme="light"] .sun { display: block; }
:root[data-theme="light"] .moon { display: none; }

/* ================= Find in document ================= */

/* A slim bar under the topbar rather than a floating box: an installed iOS
   app has no browser find bar, so this is the whole search affordance and it
   has to be thumb-reachable and wide enough to type into on a phone. */
.search-bar {
  position: fixed;
  top: var(--topbar-h);
  left: 0;
  right: 0;
  z-index: 19;
  display: flex;
  align-items: center;
  gap: 4px;
  padding: 6px calc(10px + var(--safe-right)) 6px calc(12px + var(--safe-left));
  background: var(--bg);
  border-bottom: 1px solid var(--border);
  box-shadow: var(--shadow);
  font-family: var(--sans);
}
.search-bar[hidden] { display: none !important; }
.search-glyph { flex: none; color: var(--faint); }

.search-input {
  flex: 1;
  min-width: 0;
  border: 1px solid transparent;
  background: none;
  color: var(--ink);
  font-family: var(--sans);
  /* 16px keeps iOS Safari from zooming the page when the field takes focus. */
  font-size: 16px;
  padding: 6px 4px;
  border-radius: 8px;
}
.search-input:focus { outline: none; }
.search-input::placeholder { color: var(--faint); }

.search-count {
  flex: none;
  font-size: 12px;
  color: var(--faint);
  font-variant-numeric: tabular-nums;
  padding: 0 4px;
}
.search-count.none { color: var(--accent); }

/* In reader mode the topbar hides itself and would slide back over the search
   bar on hover or a scroll up. Searching is chrome work, so while the bar is
   open the topbar simply stays put above it. */
body.reader-mode.search-open .topbar { transform: none; }

/* Highlighting uses the CSS Custom Highlight API, so nothing in the document
   is rewritten to show a match — see js/app.js. Browsers without it still
   count and scroll to matches, just without the paint. */
::highlight(search) {
  background-color: color-mix(in srgb, var(--accent) 26%, transparent);
  color: var(--ink-strong);
}
::highlight(search-current) {
  background-color: var(--accent);
  color: var(--bg);
}

/* ================= Layout ================= */

.layout { display: flex; min-height: calc(100dvh - var(--topbar-h)); }

.sidebar {
  width: var(--sidebar-w);
  flex: none;
  position: sticky;
  top: var(--topbar-h);
  height: calc(100dvh - var(--topbar-h));
  overflow-y: auto;
  background: var(--bg-sidebar);
  border-right: 1px solid var(--border);
  padding: 14px 10px calc(32px + var(--safe-bottom));
}
body.sidebar-collapsed .sidebar { display: none; }

.sidebar-actions {
  margin-bottom: 10px;
  padding-bottom: 10px;
  border-bottom: 1px solid var(--border);
}

/* Drag handle straddling the sidebar's right edge. The hit area is wider than
   the line it draws so it's easy to grab without eating the border's look. */
.sidebar-resizer {
  flex: none;
  width: 9px;
  margin: 0 -5px 0 -4px;
  position: sticky;
  top: var(--topbar-h);
  height: calc(100dvh - var(--topbar-h));
  z-index: 16;
  cursor: col-resize;
  touch-action: none;
}
.sidebar-resizer::before {
  content: '';
  display: block;
  width: 3px;
  height: 100%;
  margin-left: 3px;
  background: transparent;
  transition: background 0.15s ease;
}
.sidebar-resizer:hover::before,
.sidebar-resizer:focus-visible::before,
body.sidebar-resizing .sidebar-resizer::before { background: var(--accent); }
.sidebar-resizer:focus-visible { outline: none; }

/* While dragging, keep the col-resize cursor even as the pointer outruns the
   handle, and stop the drag from selecting the contents list. */
body.sidebar-resizing { cursor: col-resize; user-select: none; }

body.sidebar-collapsed .sidebar-resizer,
body.reader-mode .sidebar-resizer { display: none; }

.main { flex: 1; min-width: 0; }

/* ================= File tree ================= */

/* Sits between the open actions and the contents outline. Hidden entirely
   until a folder is open, so single-file readers never see an empty shelf. */
.file-tree {
  margin-bottom: 12px;
  padding-bottom: 12px;
  border-bottom: 1px solid var(--border);
}
.file-tree[hidden] { display: none !important; }

.tree-root-name {
  font-size: 11px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.09em;
  color: var(--faint);
  padding: 2px 8px 8px;
  overflow-wrap: anywhere;
}

.tree-empty { color: var(--faint); font-size: 13px; padding: 8px; }

.tree-children { display: flex; flex-direction: column; }
.tree-dir > .tree-children,
details.tree-dir > .tree-children { padding-left: 14px; }

details.tree-dir > summary {
  list-style: none;
  cursor: pointer;
  padding: 4px 8px;
  border-radius: 6px;
  font-size: 13.5px;
  font-weight: 600;
  color: var(--muted);
  user-select: none;
  display: flex;
  align-items: center;
  gap: 6px;
  overflow-wrap: anywhere;
}
details.tree-dir > summary::-webkit-details-marker { display: none; }
details.tree-dir > summary::before {
  content: '';
  flex: none;
  width: 0; height: 0;
  border-left: 5px solid var(--faint);
  border-top: 4px solid transparent;
  border-bottom: 4px solid transparent;
  transition: transform 0.12s ease;
}
details.tree-dir[open] > summary::before { transform: rotate(90deg); }
details.tree-dir > summary:hover { background: var(--bg-raised); color: var(--ink-strong); }

.tree-file {
  text-align: left;
  border: 0;
  background: none;
  cursor: pointer;
  padding: 4px 8px;
  border-radius: 6px;
  font-size: 13.5px;
  color: var(--ink);
  overflow-wrap: anywhere;
}
.tree-file:hover { background: var(--bg-raised); }
.tree-file.active {
  background: var(--accent-soft);
  color: var(--accent);
  font-weight: 600;
}

/* ================= Recent documents ================= */

/* Sits above the file tree: the way back into what you were reading when no
   folder is open, which on browsers without persistent handles is every launch. */
.recents {
  margin-bottom: 12px;
  padding-bottom: 12px;
  border-bottom: 1px solid var(--border);
}
.recents[hidden] { display: none !important; }

.recents > summary {
  list-style: none;
  cursor: pointer;
  user-select: none;
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: 11px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.09em;
  color: var(--faint);
  padding: 2px 8px 8px;
}
.recents > summary::-webkit-details-marker { display: none; }
.recents > summary::before {
  content: '';
  flex: none;
  width: 0; height: 0;
  border-left: 5px solid var(--faint);
  border-top: 4px solid transparent;
  border-bottom: 4px solid transparent;
  transition: transform 0.12s ease;
}
.recents[open] > summary::before { transform: rotate(90deg); }
.recents > summary:hover { color: var(--ink-strong); }

.recents-list { display: flex; flex-direction: column; }

.recent-row { display: flex; align-items: stretch; gap: 2px; }
.recent-row > .recent-item { flex: 1; min-width: 0; }

.recent-item {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 1px;
  text-align: left;
  border: 0;
  background: none;
  cursor: pointer;
  padding: 5px 8px;
  border-radius: 6px;
  overflow-wrap: anywhere;
}
.recent-item:hover { background: var(--bg-raised); }

.recent-remove {
  flex: none;
  align-self: center;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border: 0;
  background: none;
  cursor: pointer;
  color: var(--faint);
  padding: 8px 7px;
  border-radius: 6px;
  touch-action: manipulation;
}
.recent-remove:hover { color: var(--accent); background: var(--bg-raised); }

.recent-name {
  font-size: 13.5px;
  color: var(--ink);
}
.recent-meta {
  font-size: 11px;
  color: var(--faint);
}

.recents-clear {
  margin-top: 6px;
  border: 0;
  background: none;
  cursor: pointer;
  padding: 4px 8px;
  border-radius: 6px;
  font-size: 11.5px;
  color: var(--faint);
}
.recents-clear:hover { background: var(--bg-raised); color: var(--ink-strong); }

/* The welcome screen's copy of the list. Centred to sit under the CTA, and
   boxed so it reads as a shelf rather than as more body copy. */
.welcome-recents {
  margin-top: 30px;
  text-align: left;
  border: 1px solid var(--border);
  border-radius: 12px;
  padding: 10px;
  background: var(--bg-raised);
}
.welcome-recents[hidden] { display: none !important; }

.welcome-recents-title {
  font-family: var(--sans);
  font-size: 10.5px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.1em;
  color: var(--faint);
  padding: 2px 8px 6px;
}
.welcome-recents .recent-item { width: 100%; }

/* ================= Welcome ================= */

.welcome {
  display: grid;
  place-items: center;
  min-height: calc(100dvh - var(--topbar-h));
  padding: 32px;
}
.welcome[hidden] { display: none; }

.welcome-inner { text-align: center; max-width: 26rem; }

.welcome-mark {
  width: 76px; height: 76px;
  margin: 0 auto 22px;
  display: grid;
  place-items: center;
  border-radius: 20px;
  background: var(--ink-strong);
  color: var(--bg);
  box-shadow: var(--shadow);
}
.welcome-mark svg { width: 44px; height: 36px; display: block; }
/* e-ink is pure grayscale and the tile is black — the rust arrow would vanish */
:root[data-eink] .welcome-mark .mark-arrow { fill: var(--bg); }

.welcome h1 {
  font-family: var(--serif);
  font-size: 34px;
  margin: 0 0 10px;
  color: var(--ink-strong);
}

.welcome-sub {
  font-family: var(--serif);
  font-size: 17px;
  line-height: 1.6;
  color: var(--muted);
  margin: 0 0 26px;
  text-align: justify;
  text-align-last: center;
  -webkit-hyphens: auto;
  hyphens: auto;
}

.cta {
  border: 0;
  background: var(--accent);
  color: var(--bg);
  font-size: 15px;
  font-weight: 600;
  padding: 11px 22px;
  border-radius: 10px;
  cursor: pointer;
  box-shadow: var(--shadow);
  /* also used as a link on the 404 page */
  display: inline-block;
  text-decoration: none;
}
.cta:hover { filter: brightness(1.08); }

.welcome-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  justify-content: center;
}

.cta-secondary {
  background: none;
  color: var(--muted);
  border: 1px solid var(--border);
  box-shadow: none;
}
.cta-secondary:hover { color: var(--ink-strong); border-color: var(--faint); filter: none; }
.cta-secondary[hidden] { display: none; }

.welcome-secondary {
  display: block;
  margin: 12px auto 0;
  border: 0;
  background: none;
  cursor: pointer;
  font-size: 13.5px;
  color: var(--muted);
  text-decoration: underline;
  text-decoration-color: var(--border);
  text-underline-offset: 3px;
  padding: 6px 10px;
  border-radius: 8px;
}
.welcome-secondary:hover { color: var(--accent); }
.welcome-secondary[hidden] { display: none !important; }

.welcome-hint {
  margin: 16px auto 0;
  max-width: 24rem;
  font-size: 12.5px;
  line-height: 1.55;
  color: var(--faint);
  text-align: left;
  padding: 10px 12px;
  border: 1px solid var(--border);
  border-radius: 10px;
}
.welcome-hint strong { color: var(--muted); font-weight: 600; }
.welcome-hint[hidden] { display: none !important; }

.welcome-links {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 6px 18px;
  margin-top: 28px;
  font-size: 13px;
}
.welcome-links a {
  color: var(--faint);
  text-decoration: none;
}
.welcome-links a:hover { color: var(--accent); }

/* ================= Static pages (about, privacy, terms) ================= */

.doc-meta {
  color: var(--faint);
  font-size: 0.85em;
}

.doc-nav {
  display: flex;
  flex-wrap: wrap;
  gap: 8px 20px;
  margin-top: 3em;
  padding-top: 1.4em;
  border-top: 1px solid var(--border);
  font-size: 0.85em;
}
.doc-nav a { color: var(--muted); }

kbd {
  font-family: var(--mono);
  font-size: 11px;
  background: var(--bg-raised);
  border: 1px solid var(--border);
  border-bottom-width: 2px;
  border-radius: 5px;
  padding: 1px 6px;
}

/* ================= Prose ================= */

.content {
  max-width: 70ch;
  margin: 0 auto;
  /* A slim gap under the topbar — the document should start promptly. */
  padding: 10px 32px 30vh;
  padding-left: max(32px, var(--safe-left));
  padding-right: max(32px, var(--safe-right));
}

.prose {
  font-family: var(--serif);
  font-size: var(--prose-size);
  line-height: 1.7;
  color: var(--ink);
}

.prose > * { margin-top: 0; margin-bottom: 0; }
.prose > * + * { margin-top: 1.15em; }

.prose h1, .prose h2, .prose h3, .prose h4, .prose h5, .prose h6 {
  font-family: var(--serif);
  color: var(--ink-strong);
  line-height: 1.25;
  letter-spacing: -0.01em;
  position: relative;
}
.prose > h1 { font-size: 2em; margin-top: 0.4em; }
.prose > h2 { font-size: 1.5em; margin-top: 2em; }
.prose > h3 { font-size: 1.2em; margin-top: 1.8em; }
.prose > h4 { font-size: 1.05em; margin-top: 1.6em; }
.prose > :first-child { margin-top: 0; }

.prose h1 + *, .prose h2 + *, .prose h3 + *, .prose h4 + * { margin-top: 0.7em; }

/* ---------- Compact spacing ---------- */
/* Agent-written markdown is mostly headings and lists, and at the default
   editorial rhythm that becomes a page of gaps you scroll past. This tightens
   the space *between* blocks; the text itself is left alone. */

:root[data-compact] .prose { line-height: 1.55; }
:root[data-compact] .prose > * + * { margin-top: 0.6em; }
:root[data-compact] .prose > h1 { margin-top: 0.2em; }
:root[data-compact] .prose > h2 { margin-top: 1.1em; }
:root[data-compact] .prose > h3 { margin-top: 0.95em; }
:root[data-compact] .prose > h4 { margin-top: 0.85em; }
:root[data-compact] .prose h1 + *,
:root[data-compact] .prose h2 + *,
:root[data-compact] .prose h3 + *,
:root[data-compact] .prose h4 + * { margin-top: 0.4em; }

:root[data-compact] .prose li { margin-top: 0.1em; }
:root[data-compact] .prose li > ul,
:root[data-compact] .prose li > ol { margin-top: 0.1em; }

/* A blank line between list items makes marked wrap each one in a <p>, which
   then carries the browser's default 1em above and below. Agents write lists
   that way constantly, so this is the single biggest source of dead space. */
:root[data-compact] .prose li > p,
:root[data-compact] .prose blockquote > p { margin: 0; }
:root[data-compact] .prose li > p + p { margin-top: 0.4em; }

:root[data-compact] .prose blockquote { padding: 0.5em 1.1em; }
:root[data-compact] .prose blockquote > * + * { margin-top: 0.45em; }

:root[data-compact] .prose hr { margin: 1.2em auto; }
:root[data-compact] .prose th,
:root[data-compact] .prose td { padding: 0.4em 0.8em; }

.h-anchor {
  position: absolute;
  margin-left: 0.35em;
  color: var(--faint);
  text-decoration: none;
  opacity: 0;
  transition: opacity 0.12s ease;
  font-weight: 400;
}
h1:hover .h-anchor, h2:hover .h-anchor, h3:hover .h-anchor,
h4:hover .h-anchor, h5:hover .h-anchor, h6:hover .h-anchor { opacity: 1; }
.h-anchor:hover { color: var(--accent); }

.prose a {
  color: var(--accent);
  text-decoration: underline;
  text-decoration-color: color-mix(in srgb, var(--accent) 35%, transparent);
  text-underline-offset: 3px;
}
.prose a:hover { text-decoration-color: var(--accent); }

.prose strong { color: var(--ink-strong); }

.prose blockquote {
  margin-left: 0;
  margin-right: 0;
  padding: 0.7em 1.2em;
  border-left: 3px solid var(--accent);
  background: var(--accent-soft);
  border-radius: 0 8px 8px 0;
  color: color-mix(in srgb, var(--ink) 82%, var(--muted));
}
.prose blockquote > * + * { margin-top: 0.8em; }

.prose ul, .prose ol { padding-left: 1.4em; }
.prose li { margin-top: 0.35em; }
.prose li::marker { color: var(--faint); }

.prose ul.task-list { list-style: none; padding-left: 0.2em; }
/* Sized for thumbs: a bigger box, breathing room around the row, and the
   whole row is the tap target (wired in app.js), not just the square. */
.prose li.task-item {
  display: flex;
  flex-wrap: wrap;
  gap: 0.65em;
  align-items: flex-start;
  padding: 0.4em 0.5em;
  border-radius: 8px;
}
/* A nested list inside a task drops below the row instead of riding
   beside the label in the flex row. */
.prose li.task-item > ul,
.prose li.task-item > ol { flex-basis: 100%; }
/* Drawn, not native: a native checkbox can't be round. A circle outline
   that fills with the accent and a drawn tick when checked, Reminders-style. */
.prose li.task-item input[type="checkbox"] {
  appearance: none;
  -webkit-appearance: none;
  /* Inputs get a small UA font of their own; inheriting makes the em-sized
     circle scale with the label text instead of drifting out of alignment. */
  font: inherit;
  width: 1.55em;
  height: 1.55em;
  flex: none;
  /* Fallback: centre against the prose line-height (1.7em). */
  margin: 0.075em 0 0;
  border: 2px solid var(--faint);
  border-radius: 50%;
  background: transparent;
  display: grid;
  place-items: center;
  transition: border-color 0.12s ease, background-color 0.12s ease;
}
@supports (margin-top: calc((1lh - 1em) / 2)) {
  /* Exact: centre the circle on the label's first line box, whatever the
     text size and line height happen to be. */
  .prose li.task-item input[type="checkbox"] { margin-top: calc((1lh - 1.55em) / 2); }
}
.prose li.task-item input[type="checkbox"]:checked {
  border-color: var(--accent);
  background: var(--accent);
}
.prose li.task-item input[type="checkbox"]:checked::after {
  content: '';
  width: 0.62em;
  height: 0.34em;
  border-left: 0.16em solid var(--bg);
  border-bottom: 0.16em solid var(--bg);
  transform: rotate(-45deg) translate(0.03em, -0.06em);
}
.prose li.task-item input[type="checkbox"]:disabled { border-color: var(--border); }
.prose li.task-item input[type="checkbox"]:not(:disabled):hover { border-color: var(--accent); }
/* The label column shrinks and wraps beside the box; without min-width: 0
   a long unbreakable word would push it below the checkbox instead. */
.prose li.task-item > .task-label {
  flex: 1 1 0;
  min-width: 0;
  overflow-wrap: anywhere;
}
.prose input[type="checkbox"]:not(:disabled) { cursor: pointer; }
.prose li.task-item:has(> input[type="checkbox"]:not(:disabled)) { cursor: pointer; }
.prose li.task-item:has(> input[type="checkbox"]:not(:disabled)):hover { background: var(--bg-raised); }
/* Done items step back so the remaining work stands out. */
.prose li.task-item:has(> input[type="checkbox"]:checked) { color: var(--muted); }

/* --- checklist view tools --- */
/* View-only: hiding is display:none and the re-order is CSS `order`, so the
   DOM sequence and the markdown source are never touched. */

.task-tools {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px;
  margin: 0 0 12px;
  font-family: var(--sans);
  font-size: 12.5px;
}
.task-count { color: var(--faint); margin-right: 4px; }
.task-chip {
  font: inherit;
  border: 1px solid var(--border);
  background: none;
  color: var(--muted);
  border-radius: 999px;
  padding: 4px 12px;
  cursor: pointer;
  touch-action: manipulation;
}
.task-chip:hover { color: var(--ink-strong); border-color: var(--faint); }
.task-chip[aria-pressed="true"] {
  color: var(--accent);
  border-color: var(--accent);
  background: var(--accent-soft);
}

.tasks-hide-done li.task-item:has(> input[type="checkbox"]:checked) { display: none; }

.tasks-done-last ul.task-list { display: flex; flex-direction: column; }
.tasks-done-last ul.task-list > li.task-item:has(> input[type="checkbox"]:checked) { order: 9; }
.tasks-done-last ul.task-list > li.task-add-row { order: 10; }

/* --- the ghost "+ Add item" row --- */

.task-add-row {
  display: flex;
  align-items: center;
  gap: 0.65em;
  padding: 0.2em 0.5em;
}
.task-add {
  font-family: var(--sans);
  font-size: 13px;
  border: 0;
  background: none;
  cursor: pointer;
  color: var(--faint);
  padding: 0.3em 0;
  touch-action: manipulation;
}
.task-add:hover { color: var(--accent); }
.task-add-circle {
  flex: none;
  width: 1.35em;
  height: 1.35em;
  border: 2px dashed var(--faint);
  border-radius: 50%;
}
.task-add-input {
  flex: 1;
  min-width: 0;
  font: inherit;
  color: var(--ink);
  background: none;
  border: 0;
  border-bottom: 1px solid var(--border);
  padding: 0.15em 0;
  outline: none;
}
.task-add-input:focus { border-bottom-color: var(--accent); }
.task-add-input::placeholder { color: var(--faint); }

/* Unsaved ticks waiting to be written — the accent makes the button read
   as "you have changes", not as one more quiet tool. */
#save-btn { color: var(--accent); }

/* ================= Source editor ================= */

.editor {
  display: block;
  width: min(76ch, 100% - 40px);
  margin: 0 auto;
  height: calc(100dvh - var(--topbar-h) - 16px);
  padding: 26px 8px calc(40px + var(--safe-bottom));
  border: 0;
  outline: none;
  resize: none;
  background: transparent;
  color: var(--ink);
  font-family: var(--mono);
  font-size: 13.5px;
  line-height: 1.7;
  tab-size: 2;
}
.editor[hidden] { display: none; }
.editor::placeholder { color: var(--faint); }

.prose hr {
  border: 0;
  margin: 2.6em auto;
  text-align: center;
  height: auto;
}
.prose hr::after {
  content: '· · ·';
  color: var(--faint);
  font-size: 1.1em;
  letter-spacing: 0.6em;
  padding-left: 0.6em;
}

.prose img { max-width: 100%; height: auto; border-radius: 8px; }

/* Stand-in for an image that couldn't load — see explainBrokenImages() */
.prose .img-missing {
  display: inline-flex;
  align-items: center;
  gap: 0.5em;
  max-width: 100%;
  padding: 0.5em 0.8em;
  border: 1px dashed var(--border);
  border-radius: 8px;
  background: var(--bg-raised);
  font-family: var(--sans);
  font-size: 0.8em;
  line-height: 1.4;
  color: var(--muted);
  cursor: help;
}
.prose .img-missing svg { flex: none; color: var(--faint); }
.prose .img-missing em { color: var(--faint); font-style: italic; }

/* --- inline code & code blocks --- */

.prose code {
  font-family: var(--mono);
  font-size: 0.82em;
}
.prose :not(pre) > code {
  background: var(--code-bg);
  padding: 0.15em 0.42em;
  border-radius: 5px;
  color: var(--ink-strong);
}

.codeblock { position: relative; }
.prose pre {
  margin: 0;
  background: var(--pre-bg);
  border: 1px solid var(--border);
  border-radius: 10px;
  padding: 1em 1.2em;
  overflow-x: auto;
  line-height: 1.55;
}
.prose pre code { font-size: 0.78em; }

.copy-btn {
  position: absolute;
  top: 8px;
  right: 8px;
  border: 1px solid var(--border);
  background: var(--bg);
  color: var(--muted);
  font-family: var(--sans);
  font-size: 11.5px;
  padding: 3px 9px;
  border-radius: 6px;
  cursor: pointer;
  opacity: 0;
  transition: opacity 0.12s ease;
}
.codeblock:hover .copy-btn, .copy-btn:focus-visible { opacity: 1; }
.copy-btn:hover { color: var(--ink-strong); }
.copy-btn.copied { color: var(--accent); border-color: var(--accent); opacity: 1; }

/* --- syntax highlighting (theme-aware) --- */

.hljs { color: var(--ink); background: transparent; }
.hljs-comment, .hljs-quote { color: var(--hl-comment); font-style: italic; }
.hljs-keyword, .hljs-selector-tag, .hljs-doctag, .hljs-meta .hljs-keyword,
.hljs-template-tag, .hljs-name { color: var(--hl-keyword); }
.hljs-string, .hljs-regexp, .hljs-addition { color: var(--hl-string); }
.hljs-number, .hljs-literal, .hljs-symbol, .hljs-bullet, .hljs-link { color: var(--hl-number); }
.hljs-title, .hljs-title.class_, .hljs-title.function_, .hljs-section,
.hljs-selector-id, .hljs-selector-class { color: var(--hl-title); }
.hljs-attr, .hljs-attribute, .hljs-variable, .hljs-template-variable,
.hljs-type, .hljs-built_in, .hljs-params, .hljs-property { color: var(--hl-attr); }
.hljs-meta, .hljs-deletion { color: var(--hl-comment); }
.hljs-emphasis { font-style: italic; }
.hljs-strong { font-weight: 600; }

/* --- tables --- */

.prose table {
  border-collapse: collapse;
  width: 100%;
  font-family: var(--sans);
  font-size: 0.82em;
  line-height: 1.5;
}
.prose th, .prose td {
  padding: 0.6em 0.95em;
  text-align: left;
  vertical-align: top;
}
.prose th {
  color: var(--ink-strong);
  font-weight: 600;
  border-bottom: 2px solid var(--border);
}
.prose td { border-bottom: 1px solid var(--border); }
.prose tbody tr:nth-child(even) { background: var(--bg-raised); }

/* ================= Outline (TOC) ================= */

/* Lives inside the left sidebar, under the actions. */
.outline { font-family: var(--sans); }
.outline[hidden] { display: none !important; }

.outline-title {
  font-size: 10.5px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.1em;
  color: var(--faint);
  margin-bottom: 8px;
  padding-left: 12px;
}

.toc-link {
  display: block;
  font-size: 12.5px;
  line-height: 1.45;
  color: var(--muted);
  text-decoration: none;
  padding: 3px 12px;
  border-left: 2px solid var(--border);
}
.toc-link.toc-h3 { padding-left: 24px; }
.toc-link:hover { color: var(--ink-strong); }
.toc-link.active {
  color: var(--accent);
  border-left-color: var(--accent);
  font-weight: 600;
}

/* ================= Kindle-style reading aids ================= */
/* Active in e-ink and reader modes: progress %, justified book-page text. */

.progress {
  position: fixed;
  right: calc(14px + var(--safe-right));
  bottom: calc(10px + var(--safe-bottom));
  z-index: 10;
  font-family: var(--sans);
  font-size: 11.5px;
  letter-spacing: 0.03em;
  color: var(--faint);
  background: color-mix(in srgb, var(--bg) 85%, transparent);
  padding: 2px 7px;
  border-radius: 6px;
  pointer-events: none;
}
.progress[hidden] { display: none; }

/* Color temperature: a click-through multiply-blended tint — amber for warm,
   blue for cold. --tone-color/--tone-opacity are set from the menu steppers. */
.tone {
  position: fixed;
  inset: 0;
  z-index: 59;
  background: var(--tone-color, transparent);
  opacity: var(--tone-opacity, 0);
  mix-blend-mode: multiply;
  pointer-events: none;
  transition: opacity 0.15s ease, background-color 0.15s ease;
}
/* E-ink promises pure grayscale — never tint it. */
:root[data-eink] .tone { display: none; }

/* Software brightness: a click-through black veil over the whole page.
   --dim is 0 (off) to ~0.6, set from the menu's brightness steppers. */
.dim {
  position: fixed;
  inset: 0;
  z-index: 60;
  background: #000;
  opacity: var(--dim, 0);
  pointer-events: none;
  transition: opacity 0.15s ease;
}

:root[data-eink] .prose > p,
body.reader-mode .prose > p {
  text-align: justify;
  -webkit-hyphens: auto;
  hyphens: auto;
}

/* ================= Toasts & drop veil ================= */

.toast-root {
  position: fixed;
  bottom: calc(24px + var(--safe-bottom));
  left: 50%;
  transform: translateX(-50%);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 8px;
  z-index: 50;
  pointer-events: none;
}
.toast {
  background: var(--ink-strong);
  color: var(--bg);
  font-size: 13.5px;
  padding: 9px 16px;
  border-radius: 10px;
  box-shadow: 0 4px 16px rgba(0, 0, 0, 0.25);
  opacity: 0;
  transform: translateY(6px);
  transition: opacity 0.25s ease, transform 0.25s ease;
}
.toast.show { opacity: 1; transform: translateY(0); }

.drop-veil {
  position: fixed;
  inset: 0;
  z-index: 40;
  display: grid;
  place-items: center;
  background: color-mix(in srgb, var(--bg) 72%, transparent);
  backdrop-filter: blur(3px);
  pointer-events: none;
  font-family: var(--serif);
  font-size: 26px;
  color: var(--ink-strong);
}
.drop-veil[hidden] { display: none; }
.drop-veil > div {
  border: 2px dashed var(--accent);
  border-radius: 16px;
  padding: 36px 64px;
  background: var(--bg);
  box-shadow: var(--shadow);
}

/* ================= Reader mode ================= */
/* Content only, like a book page; the topbar tucks away and peeks back on hover. */

body.reader-mode .sidebar { display: none; }

body.reader-mode .topbar {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  transform: translateY(calc(-100% + 5px));
  transition: transform 0.18s ease;
}
body.reader-mode .topbar:hover,
body.reader-mode .topbar:focus-within { transform: translateY(0); }

body.reader-mode .layout { min-height: 100dvh; }
body.reader-mode .content {
  max-width: 64ch;
  padding-top: calc(72px + var(--safe-top));
}

/* On touch screens there's no hover or Esc key: the bar hides as you scroll
   down and comes back when you scroll up or reach the top. */
@media (hover: none) {
  body.reader-mode .topbar { transform: translateY(-100%); }
  body.reader-mode.reader-bar-show .topbar { transform: translateY(0); }
}

/* ================= Small screens ================= */

@media (max-width: 720px) {
  .sidebar {
    position: fixed;
    left: 0;
    z-index: 15;
    width: min(var(--sidebar-w), 84vw);
    padding-left: calc(10px + var(--safe-left));
    box-shadow: 4px 0 20px rgba(0, 0, 0, 0.15);
  }
  /* The phone sidebar floats over the page, so there's no column to resize. */
  .sidebar-resizer { display: none; }
  .content {
    padding: 12px 20px 20vh;
    padding-left: max(20px, var(--safe-left));
    padding-right: max(20px, var(--safe-right));
  }
  .prose { font-size: calc(var(--prose-size) - 1px); }
  .welcome { padding-bottom: calc(32px + var(--safe-bottom)); }
}

/* ================= Touch ergonomics ================= */

@media (pointer: coarse) {
  .icon-btn { min-width: 44px; min-height: 44px; }
  .menu-item { padding: 12px 10px; }
  .topbar { gap: 2px; }
}
