/* ================================================================
   Vantanote — brand design system
   "A calm, luminous home for connected thought.
    Soft light, frosted surfaces, one confident blue."
   Surfaces: L1 panel (r16, frosted) · L2 card (r13, white) · L3 active (r9, accent)
   ================================================================ */

:root {
  /* brand light defaults (the Vantanote theme); gallery themes override all of these */
  --bg-primary: #FBFCFE;
  --bg-secondary: #F3F6FC;
  --bg-tertiary: #E9EEF8;
  --bg-hover: #E4EAF5;
  --bg-active: #3B6EF6;
  --border: #ECEFF5;
  --text-normal: #3A4152;
  --text-muted: #6A7284;
  --text-faint: #98A0B3;
  --text-heading: #161C2C;
  --code-bg: #EEF2FB;
  --code-text: #2B5BD7;
  --code-block-text: #313848;
  --highlight-bg: #FDF0D4;
  --highlight-text: #8A6410;
  --accent: #3B6EF6;
  --accent-strong: #2B5BD7;
  --link: #2B5BD7;
  --link-unresolved: #8A93B0;
  --danger: #D64550;
  /* chips */
  --tag-bg: #EFE6FB;
  --tag-text: #7B4FD0;
  --chip-bg: #E3EBFE;
  --chip-text: #2B5BD7;
  /* surfaces & depth */
  --app-bg: linear-gradient(135deg, #E8EDF7 0%, #EEF0F6 40%, #F0ECF4 100%);
  --panel-bg: rgba(255, 255, 255, 0.72);
  --panel-border: rgba(255, 255, 255, 0.78);
  --card-bg: #FFFFFF;
  --radius-panel: 16px;
  --radius-card: 13px;
  --radius-active: 9px;
  --shadow-panel: 0 12px 32px rgba(22, 28, 44, 0.10);
  --shadow-card: 0 6px 18px rgba(22, 28, 44, 0.07);
  --shadow-active: 0 6px 16px rgba(59, 110, 246, 0.35);
  --panel-blur: 24px;
  /* graph */
  --graph-node: #7fa3f9;
  --graph-node-ghost: #C6CDDC;
  --graph-node-tag: #7B4FD0;
  --graph-node-focus: #3B6EF6;
  --graph-edge: #D9DFEC;
  --graph-edge-focus: #9DB8FA;
  --graph-text: #6A7284;
  /* type */
  --font-ui: 'Instrument Sans', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;
  --font-mono: 'IBM Plex Mono', 'SF Mono', SFMono-Regular, ui-monospace, Menlo, Consolas, monospace;
  --editor-font-size: 15px;
}

* { box-sizing: border-box; margin: 0; padding: 0; }

html, body { height: 100%; overflow: hidden; }

body {
  font-family: var(--font-ui);
  background: var(--app-bg);
  background-attachment: fixed;
  color: var(--text-normal);
  font-size: 15px;
  -webkit-font-smoothing: antialiased;
}

/* ============ Wallpaper ============
   A picture between the page background and the app, for the surface that was
   already built to have something behind it: frosted panels are translucent
   with a 24px backdrop blur, and until now they floated over a gradient.

   INSET PAST THE EDGES. filter: blur() samples the transparency outside the
   element and draws a pale frame all the way round; -5% of the viewport is more
   than any blur radius we allow can reach.

   z-index -1 puts it above the root background and below every piece of
   in-flow content, which is exactly the one slot it needs. */
#wallpaper {
  position: fixed; inset: -5%; z-index: -1; pointer-events: none;
  /* background-image rather than the shorthand: a gradient preset is a STACK of
     radial-gradients, and the shorthand's position/size would attach to the last
     layer only. */
  background-image: var(--wallpaper, none);
  background-size: cover; background-position: center; background-repeat: no-repeat;
  filter: blur(var(--wallpaper-blur, 0px));
}
#wallpaper::after {
  content: ''; position: absolute; inset: 0;
  background: var(--wallpaper-scrim, transparent);
}
body:not(.has-wallpaper) #wallpaper { display: none; }
/* GLASS OVER A PHOTOGRAPH SHOULD SHOW THE PHOTOGRAPH.

   The three panels tile almost the whole viewport, so at 82% opacity a
   wallpaper was visible only in the 10px gutters between them — a feature that
   technically worked and could not be seen. Thinning the SIDEBARS lets the
   picture come through where the backdrop blur was always meant to be doing
   something, and color-mix against the theme's own panel colour keeps whatever
   that theme chose, just less of it.

   #main IS DELIBERATELY NOT IN THIS LIST. It is the sheet the prose sits on,
   and prose is what the app is for; a photograph coming through behind body
   text is where every wallpaper feature turns into an unreadable one. The
   writing surface stays as opaque as its theme made it. */
body.has-wallpaper :is(#left-sidebar, #right-sidebar) {
  background: color-mix(in srgb, var(--panel-bg) var(--glass-rail, 62%), transparent);
}
/* The writing sheet joins in, but on its own much shorter leash — see
   glassStops() for why the three ranges differ. */
body.has-wallpaper #main {
  background: color-mix(in srgb, var(--panel-bg) var(--glass-main, 100%), transparent);
}
/* AND THE WIDGETS ON THEM, or the rails turn into windows with solid blocks
   bolted over the view. Every panel block paints an opaque --card-bg, so
   thinning only the rail produced exactly that: the picture visible around the
   file tree and stopped dead by Chat, Connections and Calendar.

   Cards stay MORE solid than the rail they sit on — 72% against the rail's 62%
   — because that difference is what still reads as a card rather than a tinted
   rectangle. Their own backdrop blur keeps short labels and calendar numbers
   legible over a busy photograph.

   What is INSIDE a card keeps its opacity: a chat bubble, the active tree row,
   today's date. Those are depth on top of a surface, and glass all the way down
   is just fog. */
body.has-wallpaper .wg-card {
  background: color-mix(in srgb, var(--card-bg) var(--glass-card, 72%), transparent);
  backdrop-filter: blur(12px) saturate(1.2);
  -webkit-backdrop-filter: blur(12px) saturate(1.2);
}
/* The app's own background has to get out of the way, or it paints over the
   picture — it is the canvas, and the canvas is below z-index -1. */
body.has-wallpaper { background: transparent; }
/* THE SHEET SURFACES LET IT THROUGH TOO, on the shortest leash of the four.
   Engraved Paper and Reading Room have no floating panels — their sidebars and
   main are already transparent and the only opaque thing in the app is the body
   itself, the sheet. Leaving it solid was the reason a background "did nothing"
   on those two, which is a restriction nobody asked for: one flat sheet is still
   one flat sheet when the colour behind it moves. Prose sits directly on it with
   no panel in between, so it reveals least — see glassStops. */
body.has-wallpaper:is(.surface-paper, .surface-open) {
  background: color-mix(in srgb, var(--bg-primary) var(--glass-sheet, 100%), transparent);
}
@media (prefers-reduced-motion: reduce) { #wallpaper { transition: none; } }

::selection { background: color-mix(in srgb, var(--accent) 24%, transparent); }

#app { display: flex; height: 100vh; height: 100dvh; padding: 10px; gap: 10px; }

button { font-family: inherit; background: none; border: none; color: inherit; cursor: pointer; font-size: inherit; }

/* ============ Checkboxes, one voice ============
   Every checkbox in the app — note checklists, graph filters, settings —
   wears the same soft rounded box the To-dos panel introduced. Native squares
   read as someone else's furniture. appearance:none keeps them REAL inputs:
   every existing change handler and serializer sees the same element. */
input[type="checkbox"] {
  appearance: none; -webkit-appearance: none;
  width: 15px; height: 15px; flex: 0 0 auto;
  border: 1.5px solid var(--text-faint); border-radius: 5px;
  background: transparent; cursor: pointer; position: relative;
  vertical-align: -2.5px; margin: 0 2px 0 0; padding: 0;
  transition: background 0.12s, border-color 0.12s;
}
input[type="checkbox"]:hover { border-color: var(--accent); }
input[type="checkbox"]:checked { background: var(--accent); border-color: var(--accent); }
input[type="checkbox"]:checked::after {
  content: ''; position: absolute; left: 4.2px; top: 1.4px; width: 4px; height: 8px;
  border: solid var(--bg-primary); border-width: 0 2px 2px 0; transform: rotate(45deg);
}

input[type="text"], input[type="password"] {
  font-family: inherit;
  background: var(--bg-primary);
  border: 1px solid var(--border);
  border-radius: var(--radius-active);
  color: var(--text-normal);
  padding: 7px 11px;
  font-size: 13.5px;
  outline: none;
  width: 100%;
  transition: border-color 0.12s, box-shadow 0.12s;
}
input[type="text"]:focus, input[type="password"]:focus {
  border-color: var(--accent);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 18%, transparent);
}

kbd {
  font-family: var(--font-mono);
  font-size: 0.82em;
  background: var(--chip-bg);
  color: var(--chip-text);
  border-radius: 6px;
  padding: 2px 7px;
}

::-webkit-scrollbar { width: 9px; height: 9px; }
::-webkit-scrollbar-thumb {
  background: color-mix(in srgb, var(--text-faint) 45%, transparent);
  border-radius: 6px;
  border: 2px solid transparent;
  background-clip: content-box;
}
::-webkit-scrollbar-thumb:hover { background: color-mix(in srgb, var(--text-faint) 70%, transparent); background-clip: content-box; border: 2px solid transparent; }
::-webkit-scrollbar-track { background: transparent; }

/* ============ L1 frosted panel treatment ============ */
#left-sidebar, #right-sidebar, #main {
  background: var(--panel-bg);
  backdrop-filter: blur(var(--panel-blur)) saturate(1.35);
  -webkit-backdrop-filter: blur(var(--panel-blur)) saturate(1.35);
  border: 1px solid var(--panel-border);
  border-radius: var(--radius-panel);
  box-shadow: var(--shadow-panel);
  overflow: hidden;
}

/* ============ Sidebars ============ */
#left-sidebar, #right-sidebar {
  display: flex;
  flex-direction: column;
  flex-shrink: 0;
}
#left-sidebar { width: 274px; }
#right-sidebar { width: 274px; }
#left-sidebar.collapsed, #right-sidebar.collapsed { display: none; }

.sidebar-tabs {
  display: flex;
  gap: 4px;
  padding: 10px 10px 8px;
  flex-shrink: 0;
}
.sidebar-tab {
  flex: 1;
  padding: 6px 4px;
  font-size: 12.5px;
  font-weight: 600;
  color: var(--text-faint);
  border-radius: var(--radius-active);
  transition: background 0.12s, color 0.12s;
}
.sidebar-tab:hover { color: var(--text-muted); background: var(--bg-hover); }
.sidebar-tab.active { color: var(--accent-strong); background: var(--chip-bg); }

.sidebar-pane { display: none; flex: 1; overflow-y: auto; flex-direction: column; min-height: 0; }
.sidebar-pane.active { display: flex; }

/* Recent notes — a panel block (see Panel blocks, below). */
#recent-list { display: flex; flex-direction: column; max-height: 30vh; overflow-y: auto; margin: -3px -4px; }
.recent-row {
  display: flex; align-items: center; gap: 7px; padding: 4px 8px; border-radius: 6px;
  cursor: pointer; font-size: 13px; color: var(--text-muted);
}
.recent-row:hover { background: var(--bg-hover); color: var(--text-normal); }
.recent-row.active { color: var(--accent-strong); }
.recent-row .rc-icon { display: inline-flex; width: 15px; height: 15px; flex-shrink: 0; opacity: 0.7; }
.recent-row .rc-icon svg { width: 15px; height: 15px; }
.recent-row .rc-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.recent-empty { padding: 4px 14px 6px; font-size: 12px; color: var(--text-faint); }

/* Calendar and Graph — panel blocks; the card supplies the frame and heading. */
.cal-dock { padding: 0; }
#graph-dock { padding: 0; }
#graph-dock-canvas { width: 100%; height: 150px; display: block; border-radius: 8px; background: var(--bg-secondary); cursor: grab; }
#graph-dock-canvas.dragging { cursor: grabbing; }
.dock-graph-modes { display: flex; gap: 4px; margin-bottom: 6px; }
.dock-mode {
  flex: 1; padding: 3px 4px; border: 1px solid var(--border); background: transparent;
  color: var(--text-muted); border-radius: 6px; font-size: 11px; font-weight: 600; cursor: pointer;
}
.dock-mode:hover { color: var(--text-normal); }
.dock-mode.active { background: var(--chip-bg); color: var(--accent-strong); border-color: transparent; }
.dock-graph-actions { display: flex; gap: 6px; margin-top: 7px; }
.dock-expand {
  flex: 1; padding: 5px; border: 1px solid var(--border);
  background: var(--bg-secondary); color: var(--text-muted); border-radius: 7px; font-size: 11.5px; cursor: pointer;
}
.dock-expand:hover { color: var(--accent-strong); border-color: var(--accent); }

.pane-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 8px 14px 6px;
  gap: 8px;
  flex-shrink: 0;
}
/* PANEL LABEL · 11 / 700 / +0.1em / caps */
.vault-name {
  font-size: 11px;
  font-weight: 700;
  color: var(--text-faint);
  text-transform: uppercase;
  letter-spacing: 0.1em;
}
.pane-actions { display: flex; gap: 2px; }

.icon-btn {
  width: 27px; height: 27px;
  border-radius: 8px;
  color: var(--text-muted);
  font-size: 15px;
  display: inline-flex; align-items: center; justify-content: center;
  transition: background 0.12s, color 0.12s;
}
.icon-btn:hover { background: var(--bg-hover); color: var(--text-heading); }
.icon-btn:disabled { opacity: 0.35; cursor: default; }
.icon-btn:disabled:hover { background: none; color: var(--text-muted); }
.icon-btn svg, [data-icon] svg { width: 16px; height: 16px; display: block; }
/* THIS NOTE IS SHARED. The button looked the same whether a note was published
   to anyone with the link or had never left the library, and the only way to
   find out was to open the dialog and read the list.

   AN ACCENT TINT, mixed here rather than taken from a token. Two tokens were
   tried and both are wrong. A badge dot needs a ring in the colour of the
   surface behind the button, and --card-bg is defined exactly once as #FFFFFF
   and never per theme, so that ring is white on every dark one. --chip-bg /
   --chip-text looked right — it is the app's soft-accent pair — until measured
   on Daylight, where themes.js sets --chip-bg to #EFEDE9 and --chip-text to the
   body ink: a neutral grey fill indistinguishable from --dl-hover, so the
   signal would have been invisible on the surface this app actually opens in.

   Derived from --accent, which every theme sets, so one rule is a real signal
   everywhere and follows a recoloured theme for free.

   :hover is restated because .icon-btn:hover sets background, which would
   otherwise wipe the fill on the way to the click. */
.icon-btn.is-shared,
.icon-btn.is-shared:hover {
  background: color-mix(in srgb, var(--accent) 14%, transparent);
  color: var(--accent);
}
.icon-btn.is-shared:hover { background: color-mix(in srgb, var(--accent) 22%, transparent); }
.brand-row { display: flex; align-items: center; gap: 8px; min-width: 0; }
/* No radius and no shadow: the mark is transparent art, so a box-shadow would
   draw a grey rectangle around its bounding box and a radius would round a
   corner that is not there. */
.brand-mark { width: 20px; height: 20px; }

/* ============ File tree ============ */
#file-tree { padding: 4px 10px 20px; flex: 1; overflow-y: auto; user-select: none; border-radius: var(--radius-active); }
.tree-item {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 5px 9px;
  border-radius: var(--radius-active);
  font-size: 13.5px;
  color: var(--text-muted);
  cursor: pointer;
  white-space: nowrap;
  overflow: hidden;
  transition: background 0.1s, color 0.1s;
}
.tree-item:hover { background: var(--bg-hover); color: var(--text-heading); }
.tree-item.active {
  background: var(--bg-active);
  color: #fff;
  box-shadow: var(--shadow-active);
}
.tree-item .tree-label { overflow: hidden; text-overflow: ellipsis; flex: 1; min-width: 0; }
.tree-item.pinned > .tree-label { font-weight: 600; }
.tree-pin { flex-shrink: 0; opacity: 0.7; color: var(--accent); }
.tree-count { flex-shrink: 0; margin-left: 6px; font-size: 11px; font-family: var(--font-mono); color: var(--text-faint); }
.tree-folder:hover .tree-count { color: var(--text-muted); }
.tree-icon { display: inline-flex; align-items: center; width: 15px; height: 15px; flex-shrink: 0; color: var(--text-muted); }
.tree-icon svg { width: 14px; height: 14px; }
.tree-item.active .tree-icon { color: #fff; }

/* Custom-icon picker popover */
.icon-picker {
  position: fixed; z-index: 200;
  background: var(--panel-bg); backdrop-filter: blur(var(--panel-blur)); -webkit-backdrop-filter: blur(var(--panel-blur));
  border: 1px solid var(--panel-border); border-radius: var(--radius-card); box-shadow: var(--shadow-card); padding: 8px;
}
.icon-grid { display: grid; grid-template-columns: repeat(6, 1fr); gap: 2px; }
.icon-choice { width: 30px; height: 30px; display: inline-flex; align-items: center; justify-content: center; border: none; background: transparent; color: var(--text-muted); cursor: pointer; border-radius: 7px; }
.icon-choice:hover { background: var(--bg-hover); color: var(--accent-strong); }
.icon-choice svg { width: 17px; height: 17px; }
.icon-clear { width: 100%; margin-top: 6px; padding: 5px; border: 1px solid var(--panel-border); background: var(--bg-secondary); color: var(--text-muted); border-radius: 7px; font-size: 12px; cursor: pointer; }
.icon-clear:hover { color: var(--text-normal); }
/* 12px A LEVEL, NOT 19.

   margin 15 + the 1px rule + padding 4 came to 19px per level, and the cost
   compounds: four deep — Library ▸ Midterm 1 ▸ Practice ▸ Attachments, which
   is an ordinary shape for coursework — spent 76px on indentation before a
   letter of the filename, and the name elided while the column looked like it
   had room. Finder and Notion both sit around 12. This gives back ~28px at
   that depth, which is four or five characters, for no loss of structure: the
   rule still says where a level begins.

   The rule itself fades with depth. One guide line per level reads as a
   ladder on the left of every deep tree; the first two carry the structure
   and the rest only add ink. */
.tree-folder-children { margin-left: 9px; border-left: 1px solid var(--border); padding-left: 3px; }
.tree-folder-children .tree-folder-children .tree-folder-children { border-left-color: transparent; }
/* The file tree's twisty, given the same treatment as .deck-caret above and for
   the same reason — it was the smaller of the two. */
.tree-chevron {
  /* 24 - 6 - 6 = the 12px it always occupied. See .deck-caret. */
  width: 24px; height: 24px; margin: -6px; flex-shrink: 0;
  transition: transform 0.12s; color: var(--text-faint);
  display: flex; align-items: center; justify-content: center; border-radius: 6px;
}
.tree-chevron:hover { color: var(--text-normal); }
.tree-chevron svg { width: 13px; height: 13px; }
.tree-folder.collapsed-folder + .tree-folder-children { display: none; }
.tree-folder.collapsed-folder .tree-chevron { transform: rotate(-90deg); }
/* WEIGHT MARKS WHERE YOU ARE, not what kind of thing a row is.

   Every folder at every depth was 600, so eleven bold rows competed and none
   of them won — and semibold is wider than regular, so the emphasis was also
   costing characters in the column that had none to spare. .tree-item.active
   already carries weight for the row you are on, which is the thing worth
   finding. Folders keep their icon and their chevron to say what they are. */
.tree-folder .tree-label { font-weight: 500; }
.tree-item .tree-kind {
  font-family: var(--font-mono);
  font-size: 9.5px;
  color: var(--tag-text);
  background: var(--tag-bg);
  border-radius: 5px;
  padding: 1px 5px;
  margin-left: auto;
}
.tree-item.drop-target, #file-tree.drop-target { background: var(--chip-bg); color: var(--accent-strong); }

/* Drag-to-arrange: a line on the edge you would drop against. Drawn inside the
   row because .tree-item clips its overflow. */
.tree-item.drop-before, .tree-item.drop-after { position: relative; }
.tree-item.drop-before::before, .tree-item.drop-after::after {
  content: '';
  position: absolute;
  left: 4px;
  right: 4px;
  height: 2px;
  border-radius: 2px;
  background: var(--accent-strong, var(--accent));
}
.tree-item.drop-before::before { top: 0; }
.tree-item.drop-after::after { bottom: 0; }

/* Hidden items are invisible in the sidebar by default; when "Show hidden
   items" is on they come back dimmed, with a slash, so it's obvious which
   rows are only visible because you asked. */
#file-tree.showing-hidden .tree-item.tree-hidden { opacity: 0.45; }
#file-tree.showing-hidden .tree-item.tree-hidden > .tree-label { text-decoration: line-through; text-decoration-thickness: 1px; }

/* ============ Search pane ============ */
#pane-search .pane-header { padding: 10px 12px 8px; }
#search-results { padding: 4px 10px 20px; flex: 1; overflow-y: auto; }
.search-result {
  padding: 8px 11px;
  border-radius: var(--radius-card);
  cursor: pointer;
  margin-bottom: 6px;
  background: var(--card-bg);
  border: 1px solid var(--border);
  box-shadow: var(--shadow-card);
  transition: transform 0.12s, box-shadow 0.12s;
}
.search-result:hover { transform: translateY(-1px); box-shadow: var(--shadow-panel); }
.search-result .sr-title { font-size: 13.5px; font-weight: 600; color: var(--text-heading); margin-bottom: 2px; }
.search-result .sr-snippet { font-size: 12px; color: var(--text-muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.search-result mark { background: var(--highlight-bg); color: var(--highlight-text); border-radius: 3px; padding: 0 2px; }
.search-empty { padding: 14px; font-size: 13px; color: var(--text-faint); text-align: center; }

/* ============ Tags pane ============ */
#tag-list { padding: 4px 10px 20px; flex: 1; overflow-y: auto; }
.tag-row {
  display: flex; justify-content: space-between; align-items: center;
  padding: 6px 9px; border-radius: var(--radius-active); cursor: pointer; font-size: 13.5px;
  transition: background 0.1s;
}
.tag-row:hover { background: var(--bg-hover); }
.tag-row .tag-name {
  color: var(--tag-text);
  background: var(--tag-bg);
  border-radius: 20px;
  padding: 1px 10px;
  font-size: 12.5px;
  font-weight: 600;
}
.tag-row .tag-count { color: var(--text-faint); font-size: 11.5px; font-family: var(--font-mono); }

/* ============ Bookmarks ============ */
#bookmark-list { padding: 4px 10px 20px; flex: 1; overflow-y: auto; }
.bookmark-row {
  display: flex; align-items: center; gap: 8px;
  padding: 6px 9px; border-radius: var(--radius-active); cursor: pointer; font-size: 13.5px;
  color: var(--text-muted);
  transition: background 0.1s, color 0.1s;
}
.bookmark-row:hover { background: var(--bg-hover); color: var(--text-heading); }
.bookmark-row .bm-star { color: var(--accent); display: flex; }
.bookmark-row .bm-star svg { width: 13px; height: 13px; }
.bookmark-row .bm-folder { color: var(--text-faint); font-size: 11.5px; margin-left: auto; }

/* ============ Main ============ */
#main { flex: 1; display: flex; flex-direction: column; min-width: 0; position: relative; }

/* ---- tabs ---- */
#tab-bar {
  display: flex;
  gap: 5px;
  padding: 8px 10px 0;
  overflow-x: auto;
  flex-shrink: 0;
  scrollbar-width: none;
}
#tab-bar::-webkit-scrollbar { display: none; }
#tab-bar:empty { display: none; }
.tab {
  display: flex;
  align-items: center;
  gap: 7px;
  padding: 6px 8px 6px 13px;
  font-size: 12.5px;
  font-weight: 500;
  color: var(--text-faint);
  border-radius: var(--radius-active);
  cursor: pointer;
  white-space: nowrap;
  max-width: 190px;
  flex-shrink: 0;
  transition: background 0.12s, color 0.12s, box-shadow 0.12s;
}
.tab:hover { color: var(--text-muted); background: var(--bg-hover); }
.tab.active {
  background: var(--card-bg);
  color: var(--text-heading);
  box-shadow: var(--shadow-card);
  font-weight: 600;
}
.tab .tab-label { overflow: hidden; text-overflow: ellipsis; }
.tab .tab-close {
  width: 17px; height: 17px;
  border-radius: 5px;
  display: inline-flex; align-items: center; justify-content: center;
  color: var(--text-faint);
  font-size: 11px;
  visibility: hidden;
}
.tab:hover .tab-close, .tab.active .tab-close { visibility: visible; }
.tab .tab-close:hover { background: var(--bg-hover); color: var(--text-heading); }
.tab .tab-close svg { width: 10px; height: 10px; }
.tab-new {
  display: inline-flex; align-items: center; justify-content: center; flex-shrink: 0;
  width: 26px; height: 26px; margin-top: 2px;
  border: none; background: transparent; color: var(--text-faint);
  border-radius: var(--radius-active); cursor: pointer;
}
.tab-new:hover { background: var(--bg-hover); color: var(--text-heading); }
.tab-new svg { width: 15px; height: 15px; }

#view-header {
  display: flex;
  align-items: center;
  padding: 6px 12px;
  gap: 8px;
  flex-shrink: 0;
  height: 46px;
}
.nav-btns { display: flex; gap: 2px; flex-shrink: 0; }
/* The right icon cluster is a row that never shrinks or wraps — when the
   header tightens, the omnibox and title give way, never the controls.

   margin-left: auto is what actually holds it to the RIGHT EDGE, and it is not
   belt-and-braces. The cluster used to be pushed there by #note-title's flex:1
   — which works until the title is not in the header at all. On Daylight it is
   relocated into the document and the omnibox is display:none, so the header is
   left with two flex:0 children, they pack to the start, and the controls end
   up stranded in the middle of the row with the panel toggle nowhere near the
   panel it opens. An auto margin takes the free space whatever else is there. */
.header-actions { display: flex; align-items: center; gap: 2px; flex-shrink: 0; margin-left: auto; }
#note-title {
  flex: 1;
  min-width: 0;
  text-align: center;
  font-size: 14.5px;
  font-weight: 650;
  letter-spacing: -0.01em;
  color: var(--text-heading);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  cursor: pointer;
  padding: 4px 10px;
  border-radius: var(--radius-active);
  transition: background 0.12s;
}
#note-title:hover { background: var(--bg-hover); }
#note-title input {
  width: 100%; text-align: center; background: var(--card-bg);
  border: 1px solid var(--accent); border-radius: 7px;
  color: var(--text-normal); font-size: 14px; padding: 2px 6px; outline: none;
}

/* ---- formatting toolbar ---- */
#toolbar {
  display: none;
  align-items: center;
  gap: 2px;
  padding: 5px 14px 9px;
  border-bottom: 1px solid var(--border);
  flex-shrink: 0;
  flex-wrap: wrap;
}
body[data-mode="edit"] #toolbar { display: flex; }
#toolbar button {
  min-width: 30px; height: 28px;
  padding: 0 8px;
  border-radius: 8px;
  color: var(--text-muted);
  font-size: 13px;
  display: inline-flex; align-items: center; justify-content: center;
  transition: background 0.1s, color 0.1s;
}
#toolbar button:hover { background: var(--bg-hover); color: var(--text-heading); }
#toolbar button mark { background: var(--highlight-bg); color: var(--highlight-text); border-radius: 3px; padding: 0 3px; }
#toolbar button svg { width: 16px; height: 16px; }
.tb-sep { width: 1px; height: 18px; background: var(--border); margin: 0 6px; }
.tb-hint { margin-left: auto; font-size: 11px; color: var(--text-faint); font-family: var(--font-mono); }

/* ---- find bar ---- */
#find-bar {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 7px 14px;
  border-bottom: 1px solid var(--border);
  flex-shrink: 0;
}
#find-bar.hidden { display: none; }
#find-input { max-width: 300px; }
#find-count { font-size: 12px; color: var(--text-faint); min-width: 54px; font-family: var(--font-mono); }
mark.find-hit { background: var(--highlight-bg); color: var(--highlight-text); border-radius: 3px; padding: 0 1px; }
mark.find-hit.active { background: color-mix(in srgb, var(--highlight-text) 30%, var(--highlight-bg)); outline: 1.5px solid var(--highlight-text); }

/* ---- editor ---- */
#editor-scroll { flex: 1; overflow-y: auto; display: none; }

/* ---- floating outline (Notion-style) ----
   Sticky inside the note scroller: pinned mid-height while the note scrolls
   under it, gone whenever the note view is. Collapsed it is a stack of bars;
   hovering the wrap swaps in the real list. */
#outline-float { position: sticky; top: 42%; height: 0; z-index: 60; text-align: right; pointer-events: none; }
#outline-float .of-wrap {
  display: inline-block; pointer-events: auto; margin-right: 10px;
  transform: translateY(-50%); text-align: left;
}
#outline-float .of-bars { display: flex; flex-direction: column; align-items: flex-end; gap: 7px; padding: 6px 2px; }
#outline-float .of-bar { height: 2px; border-radius: 2px; background: var(--border-strong, var(--border)); transition: background .15s; }
#outline-float .of-bar.active { background: var(--accent); }
#outline-float .of-panel {
  display: none; max-height: 62vh; overflow-y: auto; min-width: 200px; max-width: 280px;
  background: var(--bg-secondary); border: 1px solid var(--border); border-radius: 10px;
  box-shadow: 0 12px 34px rgba(0,0,0,.22); padding: 8px 6px;
}
#outline-float .of-item {
  padding: 5px 10px; font-size: 12.5px; color: var(--text-muted, var(--text-normal));
  border-radius: 6px; cursor: pointer; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
#outline-float .of-item.h1 { font-weight: 600; color: var(--text-normal); }
#outline-float .of-item:hover { background: var(--bg-hover); }
#outline-float .of-item.active { color: var(--accent); }
#outline-float .of-wrap:hover .of-bars { display: none; }
#outline-float .of-wrap:hover .of-panel { display: block; }
#editor-scroll.visible { display: block; }
#editor-container { max-width: var(--editor-max-width, 780px); margin: 0 auto; padding: 28px 36px 140px; min-height: 100%; }

#editor {
  width: 100%;
  min-height: calc(100vh - 300px);
  outline: none;
  caret-color: var(--accent);
  word-break: break-word;
  font-family: var(--editor-font-family, var(--font-ui));
}
#editor:empty::before {
  content: 'Start writing… type / for blocks, [[ for links';
  color: var(--text-faint);
  pointer-events: none;
}
body[data-mode="preview"] #editor { cursor: default; }

/* ============ Markdown / note body ============ */
.markdown-body { line-height: 1.65; font-size: var(--editor-font-size); padding-bottom: 60px; }
.markdown-body h1, .markdown-body h2, .markdown-body h3,
.markdown-body h4, .markdown-body h5, .markdown-body h6 {
  margin: 1.15em 0 0.45em;
  font-weight: 700;
  line-height: 1.25;
  color: var(--text-heading);
  letter-spacing: -0.02em;
}
.markdown-body h1 { font-size: 1.95em; }
.markdown-body h2 { font-size: 1.42em; }
.markdown-body h3 { font-size: 1.18em; }
.markdown-body h4 { font-size: 1.05em; }
.markdown-body p { margin: 0.6em 0; }
.markdown-body ul, .markdown-body ol { padding-left: 1.6em; margin: 0.5em 0; }
.markdown-body li { margin: 0.24em 0; }
.markdown-body li::marker { color: var(--text-faint); }
.markdown-body li.task-item { list-style: none; margin-left: -1.4em; }
.markdown-body li:has(> input[type="checkbox"]) { list-style: none; margin-left: -1.4em; }
.markdown-body li > input[type="checkbox"] { margin-right: 8px; accent-color: var(--accent); cursor: pointer; width: 14px; height: 14px; }
.markdown-body li:has(> input[type="checkbox"]:checked) { color: var(--text-faint); text-decoration: line-through; }
.markdown-body li.task-item input { margin-right: 8px; accent-color: var(--accent); cursor: pointer; }
.markdown-body li.task-item.done > .task-text { color: var(--text-faint); text-decoration: line-through; }
.markdown-body blockquote {
  border-left: 3px solid var(--accent);
  padding: 2px 0 2px 16px;
  margin: 0.7em 0;
  color: var(--text-muted);
}
.markdown-body code {
  font-family: var(--font-mono);
  background: var(--code-bg);
  border-radius: 6px;
  padding: 1.5px 6px;
  font-size: 0.84em;
  color: var(--code-text);
}
.markdown-body pre {
  background: var(--code-bg);
  border: 1px solid var(--border);
  border-radius: var(--radius-card);
  padding: 14px 16px;
  overflow-x: auto;
  margin: 0.7em 0;
  position: relative;
}
.markdown-body pre code { background: none; padding: 0; color: var(--code-block-text); font-size: 13px; line-height: 1.6; }
.code-copy {
  position: absolute;
  top: 7px; right: 7px;
  font-family: var(--font-mono); font-size: 11px; line-height: 1;
  padding: 4px 8px; border-radius: 6px; cursor: pointer;
  background: var(--bg-secondary); color: var(--text-muted);
  border: 1px solid var(--border);
  opacity: 0; transition: opacity 0.12s ease, color 0.12s ease, border-color 0.12s ease;
  user-select: none;
}
.markdown-body pre:hover .code-copy { opacity: 0.92; }
.code-copy:hover { color: var(--text-normal); border-color: var(--accent); }
.code-copy.copied { color: var(--accent); border-color: var(--accent); opacity: 1; }
.code-collapse {
  position: absolute; top: 7px; left: 7px;
  width: 20px; height: 20px; display: inline-flex; align-items: center; justify-content: center;
  border: none; background: transparent; color: var(--text-muted); cursor: pointer; border-radius: 6px;
  opacity: 0; transition: opacity 0.12s ease; user-select: none; padding: 0;
}
.code-collapse::before { content: "\25BE"; font-size: 11px; line-height: 1; transition: transform 0.12s ease; }
.markdown-body pre:hover .code-collapse { opacity: 0.7; }
.code-collapse:hover { color: var(--text-normal); background: var(--bg-hover); }
.markdown-body pre.collapsed { padding-left: 32px; }
.markdown-body pre.collapsed > code { display: none; }
.markdown-body pre.collapsed .code-collapse { opacity: 0.7; }
.markdown-body pre.collapsed .code-collapse::before { transform: rotate(-90deg); }
.markdown-body pre.collapsed::after { content: attr(data-lang); color: var(--text-faint); font-family: var(--font-mono); font-size: 12px; }
.markdown-body a { color: var(--link); text-decoration: none; font-weight: 500; }
.markdown-body a:hover { text-decoration: underline; }
.markdown-body a.internal-link { cursor: pointer; }
/* A note that is not written yet. The same words, quietened, with a dotted
   underline so the difference is not carried by colour alone — a resolved and
   an unresolved link were identical, and the only way to tell was to click and
   watch the app create the note. Clicking still creates it.

   Applied as a decoration in split-embeds and stripped again before the save,
   so no note's saved markup depends on what happens to exist. */
.markdown-body a.internal-link.unresolved {
  color: var(--link-unresolved);
  text-decoration: underline dotted;
  text-decoration-color: color-mix(in srgb, var(--link-unresolved) 55%, transparent);
  text-underline-offset: 3px;
}
/* AN EXTERNAL LINK SAYS SO.

   A [[wikilink]] and a link to youtube.com were the same colour, the same
   weight and the same underline — nothing told you which one would leave the
   app until you had already clicked it and a video was playing. A wikilink
   carries no href at all, only data-target, so the mark can go on exactly the
   links that go out and on nothing else.

   It is CSS rather than markup on purpose: generated content never enters the
   DOM, so it cannot island a block, cannot be copied along with the text, and
   needs no change to a single saved note. The bookmark card is left alone
   because it already prints its own URL underneath. */
.markdown-body a[href^="http"]:not(.tn-bookmark)::after,
.markdown-body a[href^="mailto:"]:not(.tn-bookmark)::after {
  content: '\2197';
  display: inline-block;
  margin-left: 0.15em;
  font-size: 0.78em;
  font-weight: 600;
  line-height: 1;
  vertical-align: 0.12em;
  opacity: 0.6;
}
/* Empty alt text where the syntax is supported, so a screen reader is not told
   "north east arrow" after every link in the note. */
@supports (content: 'a' / 'b') {
  .markdown-body a[href^="http"]:not(.tn-bookmark)::after,
  .markdown-body a[href^="mailto:"]:not(.tn-bookmark)::after { content: '\2197' / ''; }
}
/* A picture that happens to be a link is not a word — no arrow after it. */
.markdown-body a:has(img)::after { content: none; }
.markdown-body hr { border: none; border-top: 1px solid var(--border); margin: 1.5em 0; }
.markdown-body table {
  border-collapse: separate;
  border-spacing: 0;
  margin: 0.9em 0;
  width: 100%;
  border: 1px solid var(--border);
  border-radius: var(--radius-card);
  overflow: hidden;
  box-shadow: var(--shadow-card);
  background: var(--card-bg);
}
.markdown-body th, .markdown-body td { border-bottom: 1px solid var(--border); padding: 8px 14px; text-align: left; font-size: 14px; }
.markdown-body td + td, .markdown-body th + th { border-left: 1px solid var(--border); }
.markdown-body tr:last-child td { border-bottom: none; }
.markdown-body th { background: var(--bg-secondary); font-weight: 650; color: var(--text-heading); font-size: 13px; }
.markdown-body img { max-width: 100%; border-radius: var(--radius-card); box-shadow: var(--shadow-card); }
.markdown-body mark { background: var(--highlight-bg); color: var(--highlight-text); border-radius: 3px; padding: 0 2px; }
.markdown-body .tag {
  background: var(--tag-bg);
  color: var(--tag-text);
  border-radius: 20px;
  padding: 1.5px 10px;
  font-size: 0.8em;
  font-weight: 600;
  cursor: pointer;
  transition: filter 0.12s;
}
.markdown-body .tag:hover { filter: brightness(0.94); }
.markdown-body .embed {
  border: 1px solid var(--border);
  border-left: 3px solid var(--accent);
  border-radius: var(--radius-card);
  padding: 4px 16px 10px;
  margin: 0.8em 0;
  background: var(--card-bg);
}
.markdown-body .embed-title { font-size: 12px; color: var(--text-faint); margin: 8px 0 2px; display: flex; align-items: center; gap: 5px; }
.markdown-body .embed-missing { color: var(--text-faint); font-style: italic; }
.markdown-body figure { margin: 1em 0; text-align: center; }
.markdown-body figcaption { font-size: 12.5px; color: var(--text-faint); margin-top: 7px; }
.markdown-body time { color: var(--accent-strong); font-weight: 600; }

/* frontmatter properties */
.markdown-body .properties {
  border: 1px solid var(--border);
  border-radius: var(--radius-card);
  padding: 12px 16px;
  margin: 0.4em 0 1.2em;
  background: var(--card-bg);
  box-shadow: var(--shadow-card);
  font-size: 13.5px;
}
.properties .prop-row { display: flex; gap: 14px; padding: 3px 0; }
.properties .prop-key {
  color: var(--text-faint);
  min-width: 92px;
  flex-shrink: 0;
  font-size: 11px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  padding-top: 2px;
}
.properties .prop-value { color: var(--text-normal); display: flex; flex-wrap: wrap; gap: 5px; }

/* block templates */
.markdown-body .callout {
  border: 1px solid var(--border);
  border-left: 4px solid var(--accent);
  border-radius: var(--radius-card);
  padding: 10px 18px;
  margin: 0.85em 0;
  background: color-mix(in srgb, var(--accent) 5%, var(--card-bg));
  box-shadow: var(--shadow-card);
}
.markdown-body .callout .callout-title { font-weight: 700; font-size: 14px; margin-bottom: 2px; color: var(--text-heading); }
.markdown-body .callout .callout-title::before {
  content: '';
  display: inline-block;
  width: 8px; height: 8px;
  border-radius: 50%;
  background: var(--accent);
  margin-right: 9px;
}
.markdown-body .callout-warn .callout-title::before { background: #DFA23E; }
.markdown-body .callout-success .callout-title::before { background: #4FA860; }
.markdown-body .callout .callout-body p { margin: 0.35em 0; }
.markdown-body .callout-warn { border-left-color: #DFA23E; background: color-mix(in srgb, #DFA23E 7%, var(--card-bg)); }
.markdown-body .callout-success { border-left-color: #4FA860; background: color-mix(in srgb, #4FA860 7%, var(--card-bg)); }

/* Toggles — Notion-style collapsible blocks (foldable callouts underneath).
   Plain look: no box, a rotating triangle, body hidden when data-fold=closed. */
.markdown-body .callout-toggle, .markdown-body .callout-toggle-h1,
.markdown-body .callout-toggle-h2, .markdown-body .callout-toggle-h3 {
  border: none; border-left: none; background: transparent; box-shadow: none;
  padding: 2px 0 2px 2px; margin: 0.35em 0;
}
.markdown-body .callout-toggle .callout-title::before,
.markdown-body .callout-toggle-h1 .callout-title::before,
.markdown-body .callout-toggle-h2 .callout-title::before,
.markdown-body .callout-toggle-h3 .callout-title::before {
  content: '▸'; background: none; width: 18px; height: auto; border-radius: 0;
  display: inline-block; color: var(--text-faint); cursor: pointer;
  transition: transform 0.12s ease; transform-origin: 40% 50%;
  margin-right: 4px; -webkit-user-modify: read-only;
}
.markdown-body [data-fold="open"] > .callout-title::before { transform: rotate(90deg); }
.markdown-body [data-fold="closed"] > .callout-body { display: none; }
.markdown-body .callout-toggle .callout-title { font-size: inherit; font-weight: 600; margin-bottom: 0; }
.markdown-body .callout-toggle-h1 .callout-title { font-size: 1.7em; font-weight: 700; }
.markdown-body .callout-toggle-h2 .callout-title { font-size: 1.4em; font-weight: 700; }
.markdown-body .callout-toggle-h3 .callout-title { font-size: 1.15em; font-weight: 700; }
.markdown-body .callout-toggle .callout-body,
.markdown-body .callout-toggle-h1 .callout-body,
.markdown-body .callout-toggle-h2 .callout-body,
.markdown-body .callout-toggle-h3 .callout-body { padding-left: 22px; }

/* Code-block chip — a FIXED overlay (never inside the note DOM): language
   label/picker + Copy, appearing on pre hover. */
:is(#code-chip, .pm-code-chip) {
  position: fixed; z-index: 70; display: none; align-items: center; gap: 4px;
  background: var(--card-bg); border: 1px solid var(--panel-border);
  border-radius: 8px; padding: 2px 4px; box-shadow: var(--shadow-card);
  font-size: 11.5px; color: var(--text-muted);
}
:is(#code-chip, .pm-code-chip) button {
  font: inherit; color: inherit; background: none; border: none;
  padding: 3px 8px; border-radius: 6px; cursor: pointer;
}
:is(#code-chip, .pm-code-chip) button:hover { background: var(--bg-hover); color: var(--text-heading); }
:is(#code-chip, .pm-code-chip) .chip-lang { font-family: var(--font-mono, ui-monospace, monospace); }

.markdown-body .columns { display: flex; gap: 22px; margin: 0.85em 0; }
.markdown-body .column { flex: 1; min-width: 0; }

.markdown-body .card {
  border: 1px solid var(--border);
  border-radius: var(--radius-card);
  padding: 16px 20px;
  margin: 0.85em 0;
  background: var(--card-bg);
  box-shadow: var(--shadow-card);
}
.markdown-body .card > h3:first-child { margin-top: 0.2em; }

/* ============ Graph view ============ */
#graph-container { display: none; flex: 1; position: relative; overflow: hidden; }
#graph-container.visible { display: block; }
#graph-canvas { position: absolute; inset: 0; width: 100%; height: 100%; cursor: grab; }
#graph-canvas.dragging { cursor: grabbing; }

#graph-settings {
  position: absolute;
  top: 14px; right: 14px;
  width: 236px;
  max-height: calc(100% - 28px);
  overflow-y: auto;
  background: var(--panel-bg);
  backdrop-filter: blur(var(--panel-blur));
  -webkit-backdrop-filter: blur(var(--panel-blur));
  border: 1px solid var(--panel-border);
  border-radius: var(--radius-card);
  box-shadow: var(--shadow-card);
  padding: 13px;
  display: flex;
  flex-direction: column;
  gap: 8px;
  font-size: 12.5px;
  color: var(--text-muted);
}
#graph-settings::-webkit-scrollbar { width: 8px; }
#graph-settings::-webkit-scrollbar-thumb { background: var(--panel-border); border-radius: 4px; }
.gs-title {
  font-weight: 700;
  color: var(--text-heading);
  font-size: 13px;
  letter-spacing: -0.01em;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
}
.gs-collapse-btn {
  display: inline-flex; align-items: center; justify-content: center;
  width: 22px; height: 22px; flex-shrink: 0; padding: 0;
  border: none; background: transparent; cursor: pointer;
  color: var(--text-faint); border-radius: 6px;
}
.gs-collapse-btn:hover { color: var(--text-normal); background: rgba(128, 128, 128, 0.14); }
.gs-collapse-btn::after {
  content: "\203A"; font-size: 16px; line-height: 1;
  display: inline-block; transform: rotate(-90deg); /* points up = collapse */
}
.gs-collapse-ic { display: none; }
.gs-collapse-ic svg { width: 15px; height: 15px; display: block; }
/* collapsed: panel shrinks to just the toggle, showing a small graph glyph */
#graph-settings.collapsed { width: auto; padding: 8px; gap: 0; }
#graph-settings.collapsed > *:not(.gs-title) { display: none; }
#graph-settings.collapsed .gs-title-label { display: none; }
#graph-settings.collapsed .gs-collapse-btn::after { display: none; }
#graph-settings.collapsed .gs-collapse-ic { display: inline-flex; }
/* collapsible accordion sections (Filters / Groups / Display / Forces) */
.gs-section { border-top: 1px solid var(--panel-border); padding-top: 8px; }
.gs-section > summary {
  list-style: none; cursor: pointer; display: flex; align-items: center; gap: 6px;
  font-weight: 700; color: var(--text-faint); font-size: 10.5px;
  text-transform: uppercase; letter-spacing: 0.08em; user-select: none;
}
.gs-section > summary::-webkit-details-marker { display: none; }
.gs-section > summary::before {
  content: "›"; font-size: 13px; line-height: 1; color: var(--text-faint);
  transition: transform 0.14s ease; display: inline-block;
}
.gs-section[open] > summary::before { transform: rotate(90deg); }
.gs-section[open] > summary { margin-bottom: 9px; }
.gs-section-body { display: flex; flex-direction: column; gap: 9px; }
.gs-row { display: flex; align-items: center; gap: 7px; cursor: pointer; }
.gs-row input[type="checkbox"] { accent-color: var(--accent); }
.gs-slider { display: flex; flex-direction: column; gap: 3px; }
.gs-slider input[type="range"] { width: 100%; accent-color: var(--accent); }
.gs-local-opts { display: flex; flex-direction: column; gap: 9px; padding-left: 10px; margin-left: 2px; border-left: 2px solid var(--panel-border); }
.gs-local-opts.hidden { display: none; }
.gs-select { display: flex; align-items: center; justify-content: space-between; gap: 8px; cursor: pointer; }
.gs-select select {
  background: var(--bg-secondary); color: var(--text-normal);
  border: 1px solid var(--border); border-radius: 6px; padding: 3px 6px;
  font-size: 12px; font-family: inherit; cursor: pointer;
}
#graph-info {
  position: absolute;
  left: 16px; bottom: 12px;
  font-size: 12px;
  color: var(--text-faint);
  pointer-events: none;
  font-family: var(--font-mono);
}

/* ============ Canvas / whiteboard ============ */
#canvas-view { display: none; flex: 1; position: relative; overflow: hidden; }
#canvas-view.visible { display: block; }
.cv-viewport {
  position: absolute; inset: 0;
  overflow: hidden;
  cursor: grab;
  background-image: radial-gradient(color-mix(in srgb, var(--text-faint) 32%, transparent) 1px, transparent 1px);
  background-size: 26px 26px;
}
.cv-viewport:active { cursor: grabbing; }
.cv-world { position: absolute; left: 0; top: 0; transform-origin: 0 0; }
.cv-edges { position: absolute; left: 0; top: 0; width: 1px; height: 1px; overflow: visible; color: var(--text-faint); }
.cv-edge { fill: none; stroke: color-mix(in srgb, var(--text-faint) 70%, transparent); stroke-width: 2; }
.cv-edge.selected { stroke: var(--accent); }
.cv-edge-temp { stroke: var(--accent); stroke-dasharray: 6 5; }
.cv-edge-hit { fill: none; stroke: transparent; stroke-width: 16; cursor: pointer; }
.cv-edge-label {
  fill: var(--text-muted);
  font-size: 12px;
  font-family: var(--font-ui);
  font-weight: 600;
  paint-order: stroke;
  stroke: var(--card-bg);
  stroke-width: 4px;
}

.cv-card {
  position: absolute;
  background: var(--card-bg);
  border: 1.5px solid var(--border);
  border-radius: var(--radius-card);
  box-shadow: var(--shadow-card);
  display: flex;
  flex-direction: column;
  overflow: visible;
  cursor: grab;
  transition: box-shadow 0.12s;
}
.cv-card.selected {
  border-color: var(--accent);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 22%, transparent), var(--shadow-panel);
}
.cv-card-title svg { width: 12px; height: 12px; vertical-align: -2px; margin-right: 5px; }
.cv-card-title {
  padding: 8px 13px 6px;
  font-size: 12px;
  font-weight: 700;
  color: var(--text-muted);
  border-bottom: 1px solid var(--border);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  flex-shrink: 0;
}
.cv-card-body {
  flex: 1;
  padding: 8px 15px;
  overflow: hidden;
  font-size: 13px;
  border-radius: 0 0 var(--radius-card) var(--radius-card);
}
.cv-card-body.markdown-body { line-height: 1.5; padding-bottom: 8px; }
.cv-card-body.markdown-body h1 { font-size: 1.25em; margin: 0.3em 0; }
.cv-card-body.markdown-body h2 { font-size: 1.12em; }
.cv-note-card .cv-card-body { pointer-events: none; }
.cv-text[contenteditable="true"] { outline: none; cursor: text; background: color-mix(in srgb, var(--accent) 5%, transparent); }
.cv-missing { color: var(--text-faint); font-style: italic; }

.cv-resize {
  position: absolute; right: -3px; bottom: -3px;
  width: 14px; height: 14px;
  cursor: nwse-resize;
  border-right: 2.5px solid var(--text-faint);
  border-bottom: 2.5px solid var(--text-faint);
  border-radius: 0 0 6px 0;
  opacity: 0;
}
.cv-card:hover .cv-resize, .cv-card.selected .cv-resize { opacity: 1; }
.cv-dot {
  position: absolute;
  width: 11px; height: 11px;
  background: var(--accent);
  border: 2px solid var(--card-bg);
  border-radius: 50%;
  opacity: 0;
  cursor: crosshair;
  z-index: 2;
}
.cv-card:hover .cv-dot, .cv-card.selected .cv-dot { opacity: 1; }
.cv-dot-top { top: -6px; left: calc(50% - 5.5px); }
.cv-dot-bottom { bottom: -6px; left: calc(50% - 5.5px); }
.cv-dot-left { left: -6px; top: calc(50% - 5.5px); }
.cv-dot-right { right: -6px; top: calc(50% - 5.5px); }

.cv-color-red { border-color: #e0565f; background: color-mix(in srgb, #e0565f 10%, var(--card-bg)); }
.cv-color-orange { border-color: #e09c4f; background: color-mix(in srgb, #e09c4f 10%, var(--card-bg)); }
.cv-color-yellow { border-color: #d6c04f; background: color-mix(in srgb, #d6c04f 10%, var(--card-bg)); }
.cv-color-green { border-color: #5fa860; background: color-mix(in srgb, #5fa860 10%, var(--card-bg)); }
.cv-color-cyan { border-color: #4fb8c9; background: color-mix(in srgb, #4fb8c9 10%, var(--card-bg)); }
.cv-color-blue { border-color: #3B6EF6; background: color-mix(in srgb, #3B6EF6 10%, var(--card-bg)); }
.cv-color-purple { border-color: #7B4FD0; background: color-mix(in srgb, #7B4FD0 10%, var(--card-bg)); }

.cv-toolbar {
  position: absolute;
  top: 12px; left: 50%;
  transform: translateX(-50%);
  display: flex;
  align-items: center;
  gap: 6px;
  background: var(--panel-bg);
  backdrop-filter: blur(var(--panel-blur));
  -webkit-backdrop-filter: blur(var(--panel-blur));
  border: 1px solid var(--panel-border);
  border-radius: 12px;
  box-shadow: var(--shadow-card);
  padding: 6px 10px;
}
.cv-toolbar button {
  padding: 4px 10px;
  border-radius: 8px;
  font-size: 12.5px;
  font-weight: 600;
  color: var(--text-muted);
  transition: background 0.1s, color 0.1s;
}
.cv-toolbar button:hover { background: var(--bg-hover); color: var(--text-heading); }
.cv-toolbar button { display: inline-flex; align-items: center; gap: 5px; }
.cv-toolbar button svg { width: 14px; height: 14px; }
.cv-colors { display: flex; gap: 4px; margin: 0 4px; padding: 0 8px; border-left: 1px solid var(--border); border-right: 1px solid var(--border); }
.cv-swatch { width: 16px; height: 16px; border-radius: 50%; border: 1.5px solid var(--border); padding: 0 !important; transition: transform 0.1s; }
.cv-swatch:hover { transform: scale(1.25); }
.cv-swatch-none { background: var(--card-bg); }
.cv-swatch-red { background: #e0565f; } .cv-swatch-orange { background: #e09c4f; }
.cv-swatch-yellow { background: #d6c04f; } .cv-swatch-green { background: #5fa860; }
.cv-swatch-cyan { background: #4fb8c9; } .cv-swatch-blue { background: #3B6EF6; }
.cv-swatch-purple { background: #7B4FD0; }
.cv-hint {
  position: absolute;
  bottom: 12px; left: 50%;
  transform: translateX(-50%);
  font-size: 11.5px;
  color: var(--text-faint);
  pointer-events: none;
  white-space: nowrap;
}

/* ============ Empty state ============ */
#empty-state { display: none; flex: 1; align-items: center; justify-content: center; }
#empty-state.visible { display: flex; }
.empty-inner { display: flex; flex-direction: column; gap: 10px; align-items: center; }
.empty-title { font-size: 22px; font-weight: 650; letter-spacing: -0.02em; color: var(--text-faint); margin-bottom: 12px; }
.empty-action {
  color: var(--text-muted);
  font-size: 14px;
  padding: 8px 14px;
  border-radius: var(--radius-active);
  transition: background 0.12s, color 0.12s;
}
.empty-action:hover { background: var(--card-bg); color: var(--text-heading); box-shadow: var(--shadow-card); }
.empty-action kbd { margin-left: 8px; }

/* ============ Status bar ============ */
#status-bar {
  display: flex;
  gap: 16px;
  padding: 6px 16px;
  border-top: 1px solid var(--border);
  font-size: 11.5px;
  color: var(--text-faint);
  flex-shrink: 0;
  font-family: var(--font-mono);
}
.status-spacer { flex: 1; }

/* ============ Right sidebar panels ============ */
/* Connections and Outline are panel blocks; the card supplies the frame. They
   keep an inner scroll only as a ceiling — a note with two hundred unlinked
   mentions must not push every block below it out of reach. */
#backlinks-list { padding: 0; max-height: 42vh; overflow-y: auto; }
.panel-section-title {
  font-size: 11px;
  font-weight: 700;
  color: var(--text-faint);
  padding: 8px 4px 6px;
  text-transform: uppercase;
  letter-spacing: 0.1em;
}
/* Connections panel: linked / unlinked / outgoing as collapsible sections. */
.conn-section { margin-bottom: 2px; }
.conn-section > summary { list-style: none; cursor: pointer; user-select: none; display: flex; align-items: center; gap: 6px; }
.conn-section > summary::-webkit-details-marker { display: none; }
.conn-section > summary::before {
  content: "›"; font-size: 13px; line-height: 1; display: inline-block; transition: transform 0.14s ease;
}
.conn-section[open] > summary::before { transform: rotate(90deg); }
.backlink-item {
  padding: 9px 12px;
  border-radius: var(--radius-card);
  cursor: pointer;
  margin-bottom: 6px;
  background: var(--card-bg);
  border: 1px solid var(--border);
  box-shadow: var(--shadow-card);
  transition: transform 0.12s, box-shadow 0.12s;
}
.backlink-item:hover { transform: translateY(-1px); box-shadow: var(--shadow-panel); }
.backlink-item .bl-title { font-size: 13px; font-weight: 650; color: var(--link); margin-bottom: 3px; }
.backlink-item .bl-snippet { font-size: 12px; color: var(--text-muted); line-height: 1.5; }
.backlink-item .bl-snippet b { color: var(--highlight-text); background: var(--highlight-bg); border-radius: 3px; font-weight: 600; padding: 0 2px; }
.panel-empty { padding: 10px 6px; font-size: 12.5px; color: var(--text-faint); text-align: center; }

/* Related notes (the similarity index): quiet rows like the other
   connection sections, plus a one-click link-insert on the active note. */
.rel-item { position: relative; }
.rel-item .bl-snippet { color: var(--text-faint); font-style: italic; }
.rel-link {
  position: absolute;
  top: 8px;
  right: 8px;
  font-size: 10.5px;
  padding: 2px 8px;
  border-radius: 999px;
  border: 1px dashed var(--border);
  background: transparent;
  color: var(--text-muted);
  cursor: pointer;
  opacity: 0;
  transition: opacity 0.12s ease;
}
.rel-item:hover .rel-link { opacity: 1; }
.rel-link:hover { color: var(--chip-text); border-color: var(--chip-text); }

/* ============ Outline ============ */
#outline-list { padding: 0; margin: -3px -4px; max-height: 42vh; overflow-y: auto; }
.outline-item {
  padding: 4px 9px;
  border-radius: 7px;
  cursor: pointer;
  font-size: 13px;
  color: var(--text-muted);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  transition: background 0.1s, color 0.1s;
}
.outline-item:hover { background: var(--bg-hover); color: var(--text-heading); }
.outline-item.h1 { font-weight: 650; color: var(--text-heading); }

/* ============ Modals ============ */
#modal-overlay, #prompt-overlay, #settings-overlay, #auth-overlay {
  position: fixed; inset: 0;
  background: rgba(22, 28, 44, 0.28);
  backdrop-filter: blur(5px);
  -webkit-backdrop-filter: blur(5px);
  display: flex; justify-content: center;
  z-index: 100;
}
#modal-overlay.hidden, #prompt-overlay.hidden, #settings-overlay.hidden, #auth-overlay.hidden { display: none; }

#palette {
  margin-top: 12vh;
  /* Wider than it was (580px). Note names in a nested vault are long, and the
     switcher's whole job is letting you recognise one at a glance. */
  width: min(760px, 92vw);
  height: fit-content;
  background: var(--card-bg);
  border: 1px solid var(--panel-border);
  border-radius: var(--radius-panel);
  overflow: hidden;
  box-shadow: 0 24px 64px rgba(22, 28, 44, 0.28);
}
#palette-input {
  width: 100%;
  background: transparent;
  border: none;
  border-bottom: 1px solid var(--border);
  border-radius: 0;
  padding: 15px 18px;
  font-size: 15px;
  box-shadow: none !important;
}
#palette-results { max-height: 46vh; overflow-y: auto; padding: 8px; }
#palette-foot { padding: 7px 16px 9px; border-top: 1px solid var(--border); font-size: 11.5px; color: var(--text-faint); }
#palette-foot[hidden] { display: none; }
#palette-foot kbd { font: inherit; font-family: var(--font-mono); font-size: 11px; color: var(--text-muted); }
#palette-foot span { margin: 0 6px; }
.palette-item {
  padding: 9px 13px;
  border-radius: var(--radius-active);
  cursor: pointer;
  font-size: 14px;
  display: flex;
  flex-direction: column;
  gap: 3px;
  color: var(--text-normal);
}
/* The ask is a different KIND of thing from a command match — it spends money
   and leaves the machine — so it reads as its own section rather than as one
   more row in the list. Only when something matched above it; alone, it is the
   answer to "nothing found" and needs no divider. */
.palette-item.palette-ai:not(:first-child) {
  border-top: 1px solid var(--border);
  margin-top: 5px;
  padding-top: 11px;
  border-radius: 0 0 var(--radius-active) var(--radius-active);
}
.palette-item.palette-ai .pi-label { color: var(--text-normal); }
.palette-item .pi-row { display: flex; align-items: center; justify-content: space-between; gap: 10px; }
.palette-item .pi-label { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.palette-item .pi-hint {
  color: var(--text-faint); font-size: 11.5px; font-family: var(--font-mono);
  /* Allowed to shrink, and capped. It used to be flex-shrink: 0, so a deep
     folder path held its full width and the NOTE NAME — the thing being
     searched for — was the half that got truncated. The name wins now; the
     folder is context and can ellipsis away. */
  flex: 0 1 auto; min-width: 0; max-width: 42%;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; direction: rtl;
}
/* direction:rtl truncates the FRONT of a path, keeping the folder nearest the
   note — "…/ISYE 6501" tells you more than "Georgia Tech - OMSA/…". */
.palette-item .pi-hint { text-align: right; }
/* …and a hint that is not a path is read the way it was written. */
.palette-item .pi-hint-plain { direction: ltr; }
.palette-item .pi-sub { font-size: 12px; color: var(--text-faint); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.palette-item .pi-sub mark { background: rgba(240, 190, 90, 0.32); color: inherit; border-radius: 3px; padding: 0 1px; }
.palette-item.selected { background: var(--bg-active); color: #fff; }
.palette-item.selected .pi-hint { color: rgba(255, 255, 255, 0.7); }
.palette-item.selected .pi-sub { color: rgba(255, 255, 255, 0.78); }
.palette-empty { padding: 16px; text-align: center; color: var(--text-faint); font-size: 13.5px; }

#prompt-overlay { align-items: center; }
#prompt-box {
  width: min(440px, 90vw);
  background: var(--card-bg);
  border: 1px solid var(--panel-border);
  border-radius: var(--radius-panel);
  padding: 20px;
  box-shadow: 0 24px 64px rgba(22, 28, 44, 0.28);
}
#prompt-title { font-size: 15px; font-weight: 700; letter-spacing: -0.01em; color: var(--text-heading); margin-bottom: 13px; }
/* In-app confirm/alert (dialogs.js): the prompt dialog's family, built per
   call. Sits above the record overlays (410) — a confirm can interrupt one. */
.vn-dialog-overlay {
  position: fixed; inset: 0; z-index: 430; background: rgba(0,0,0,.45);
  display: flex; align-items: center; justify-content: center;
}
.vn-dialog {
  width: min(440px, 90vw);
  /* A dialog may never be taller than the screen it is shown on. Without this a
     long form ran off BOTH edges — its title above the top and its buttons
     below the bottom — so the one control you needed was the one you could not
     reach. A blunt safety net for every dialog; .wg-cfg below does the nicer
     version, scrolling only the fields. */
  max-height: min(86vh, 900px);
  overflow-y: auto;
  background: var(--card-bg);
  border: 1px solid var(--panel-border);
  border-radius: var(--radius-panel);
  padding: 20px;
  box-shadow: 0 24px 64px rgba(22, 28, 44, 0.28);
}
.vn-dialog-title { font-size: 15px; font-weight: 700; letter-spacing: -0.01em; color: var(--text-heading); margin-bottom: 10px; }
.vn-dialog-msg { font-size: 13.5px; line-height: 1.55; color: var(--text-normal); white-space: pre-line; }
.prompt-btns { display: flex; justify-content: flex-end; gap: 8px; margin-top: 16px; }
.prompt-btns button {
  padding: 7px 16px;
  border-radius: var(--radius-active);
  font-size: 13.5px;
  font-weight: 600;
  background: var(--bg-tertiary);
  color: var(--text-muted);
  transition: background 0.12s, transform 0.12s, box-shadow 0.12s;
}
.prompt-btns button:hover { background: var(--bg-hover); color: var(--text-heading); }
.prompt-btns button.accent {
  background: var(--accent);
  color: #fff;
  box-shadow: var(--shadow-active);
}
.prompt-btns button.accent:hover { background: var(--accent-strong); transform: translateY(-1px); }

/* ============ Sign in / account ============ */
#auth-overlay { align-items: center; z-index: 150; }
#auth-box {
  position: relative;
  width: min(400px, 92vw);
  background: var(--card-bg);
  border: 1px solid var(--panel-border);
  border-radius: var(--radius-panel);
  padding: 34px 32px 30px;
  box-shadow: 0 24px 72px rgba(22, 28, 44, 0.34);
}
#auth-close { position: absolute; top: 14px; right: 14px; }
#auth-brand { display: flex; align-items: center; gap: 9px; font-weight: 600; font-size: 15px; color: var(--text-heading); margin-bottom: 20px; }
#auth-brand svg { width: 26px; height: 26px; }
#auth-title { font-size: 22px; font-weight: 700; letter-spacing: -0.02em; color: var(--text-heading); margin-bottom: 6px; }
#auth-sub { font-size: 13.5px; color: var(--text-muted); margin-bottom: 4px; line-height: 1.5; }
#auth-form label { display: block; font-size: 12.5px; font-weight: 500; color: var(--text-muted); margin: 16px 0 6px; }
#auth-form input {
  width: 100%;
  padding: 10px 13px;
  border-radius: var(--radius-active);
  border: 1px solid var(--border);
  background: var(--bg-primary);
  color: var(--text-normal);
  font-size: 14px;
  font-family: inherit;
}
#auth-form input:focus { outline: none; border-color: var(--accent); box-shadow: var(--shadow-active); }
#auth-submit {
  width: 100%;
  margin-top: 22px;
  padding: 11px;
  border-radius: var(--radius-active);
  border: none;
  font-weight: 600;
  font-size: 14px;
  cursor: pointer;
  background: var(--accent);
  color: #fff;
  box-shadow: var(--shadow-active);
  transition: background 0.12s, transform 0.12s;
}
#auth-submit:hover { background: var(--accent-strong); transform: translateY(-1px); }
#auth-submit:disabled { opacity: 0.6; cursor: default; transform: none; }
#auth-error, #auth-info { margin-top: 15px; font-size: 13px; padding: 9px 12px; border-radius: var(--radius-active); line-height: 1.45; }
#auth-error { color: #d0524a; background: rgba(208, 82, 74, 0.1); border: 1px solid rgba(208, 82, 74, 0.24); }
#auth-info { color: var(--accent-strong); background: rgba(130, 110, 200, 0.1); border: 1px solid var(--accent); }
/* Set by applyWebMissing() (js/app/web-unavailable.js) and by nothing else:
   controls whose route the web build cannot answer.

   An ATTRIBUTE rather than the `hidden` class, for two reasons. There is no
   global `.hidden` rule (see the line below), so `hidden` is simply inert on a
   .settings-section heading, on #snippets-list, on #sync-history — most of what
   this has to reach. And `hidden` is a shared channel: refreshShareBtn,
   paintImproveButton and the encryption panel all toggle it, so whichever ran
   last would switch a web-dead control back on.

   !important for the same reason .settings-page.hidden needs it: both
   .settings-page.active and the settings search box switch pages back on, and
   typing in that box must not resurrect a control with no route behind it. */
[data-web-missing] { display: none !important; }

/* No global .hidden in this app — each element hides itself explicitly. */
#auth-error.hidden, #auth-info.hidden, #account-signed-in.hidden, #account-signed-out.hidden,
#account-password-form.hidden, #account-password-btn.hidden { display: none; }

/* ...which is a rule with a sharp edge: JS that toggles `hidden` on an element
   nobody wrote a selector for does NOTHING, silently, and the markup reads as
   if it works. The AI pane hid three mode hints, four key rows and two notes
   that way — so every mode showed all three privacy sentences at once, two of
   which are false whichever mode you are in ("AI is off. Nothing is sent
   anywhere." sat directly above "Requests go straight to the provider").
   Scoped to the settings sheet rather than made global, so the note above
   stays true everywhere else. */
/* Rows and hints already hid themselves; SECTION HEADINGS did not, and
   web-unavailable.js says so outright — "hidden does nothing at all on a
   settings-section heading". Hiding the Encryption block left its heading
   floating above nothing, which is how a removed feature still looks present. */
#settings-overlay .settings-row.hidden,
#settings-overlay .settings-section.hidden,
#settings-overlay .settings-hint.hidden { display: none; }
/* Un-hidden only when the Electron shell exposes the capture API. */
#capture-settings.hidden { display: none; }
/* Calendar one-time setup: shown only while a provider has no OAuth client. */
#cal-setup.hidden { display: none; }

/* The AI entitlement gate. applyAiVisibility() toggles `hidden` on BOTH the nav
   button and the page, and neither had a rule — so the AI settings page has
   been visible to every account since it shipped, entitled or not, while the
   palette (which asks the predicate directly rather than through CSS) correctly
   hid the AI commands. The two disagreeing is what it looks like from outside:
   a green "Connected to OpenAI ✓" on a page you were never meant to see, and no
   way to invoke anything from it.

   `!important` is deliberate and belongs here: two later rules of equal or
   greater weight turn a settings page back on — `.settings-page.active` for the
   selected page, and `#settings-box.searching .settings-page` which reveals
   every page at once while the settings search box has text in it. A gate that
   loses to whichever rule happens to come last is not a gate, and the search
   one would hand the whole AI page to anyone who typed in that box. */
.settings-nav-item.hidden,
.settings-page.hidden { display: none !important; }
#auth-toggle { margin-top: 20px; text-align: center; font-size: 13px; color: var(--text-muted); }
#auth-toggle button { background: none; border: none; color: var(--accent); font-weight: 600; cursor: pointer; font-size: 13px; padding: 0 0 0 4px; }
#auth-toggle button:hover { text-decoration: underline; }
/* Quieter than the sign-up switch above it: this is the way out of a problem,
   not the other half of the choice. Hidden in sign-up mode (auth.js) — nobody
   creating an account has a password to have forgotten. */
#auth-forgot { margin-top: 10px; text-align: center; }
#auth-forgot.hidden { display: none; }
#auth-forgot button { background: none; border: none; color: var(--text-muted); font-size: 12.5px; cursor: pointer; padding: 2px; }
#auth-forgot button:hover { color: var(--text-normal); text-decoration: underline; }

/* Signing in through the system browser. A real alternative to the form above
   rather than a footnote, so it gets a divider and a full-width button. */
#auth-browser-wrap.hidden { display: none; }
#auth-or { display: flex; align-items: center; gap: 10px; margin: 16px 0 12px; font-size: 12px; color: var(--text-muted); }
#auth-or::before, #auth-or::after { content: ''; flex: 1; height: 1px; background: var(--border); }
#auth-browser-btn {
  width: 100%; padding: 10px 14px; border-radius: var(--radius-active);
  border: 1px solid var(--border); background: var(--bg-primary); color: var(--text-normal);
  font: inherit; font-size: 13.5px; font-weight: 600; cursor: pointer;
}
#auth-browser-btn:hover { border-color: var(--accent); background: var(--bg-hover); }
#auth-browser-btn:disabled { opacity: 0.6; cursor: default; }
#auth-browser-note { margin-top: 10px; font-size: 12.5px; color: var(--text-muted); text-align: center; }
#auth-browser-note.hidden { display: none; }

/* ============ Encryption overlay ============ */
/* Above .web-gate (z-index 9000), and that ordering is load-bearing rather than
   arbitrary. The web app's locked-vault gate is an OPAQUE full-screen cover, and
   its only button hands off to exactly this overlay — so at the old z-index of
   155 the unlock panel opened faithfully, behind the cover, and clicking Unlock
   looked like nothing happening at all. Any modal the gate can hand off to has
   to sit above it. */
#e2e-overlay {
  position: fixed; inset: 0;
  background: rgba(22, 28, 44, 0.28);
  backdrop-filter: blur(5px); -webkit-backdrop-filter: blur(5px);
  display: flex; justify-content: center; align-items: center; z-index: 9500;
}
#e2e-overlay.hidden { display: none; }

/* Delete choice: everywhere vs remove-from-this-device (built dynamically). */
.delete-choice-overlay { position: fixed; inset: 0; z-index: 200; display: flex; align-items: center; justify-content: center; background: rgba(20, 24, 38, 0.44); backdrop-filter: blur(4px); -webkit-backdrop-filter: blur(4px); }
.delete-choice { width: min(420px, 92vw); background: var(--card-bg); border: 1px solid var(--panel-border); border-radius: var(--radius-panel); padding: 22px 22px 18px; box-shadow: 0 24px 72px rgba(22, 28, 44, 0.34); }
.delete-choice h3 { font-size: 17px; font-weight: 700; letter-spacing: -0.01em; color: var(--text-heading); margin: 0 0 14px; }
.delete-choice button[data-choice] { display: block; width: 100%; text-align: left; background: var(--bg-primary); border: 1px solid var(--panel-border); border-radius: var(--radius-active); padding: 11px 13px; margin-bottom: 9px; cursor: pointer; color: var(--text-normal); transition: border-color .12s, background .12s; }
.delete-choice button[data-choice]:hover { border-color: var(--accent); background: var(--bg-hover); }
.delete-choice button[data-choice] b { display: block; font-size: 13.5px; font-weight: 650; margin-bottom: 2px; }
.delete-choice button[data-choice] span { display: block; font-size: 12px; color: var(--text-muted); line-height: 1.45; }
.delete-choice button.dc-danger b { color: #d0524a; }
.delete-choice button.dc-cancel { text-align: center; background: none; border: none; color: var(--text-muted); font-size: 13px; font-weight: 500; padding: 8px; margin: 2px 0 0; }
.delete-choice button.dc-cancel:hover { background: none; color: var(--text-normal); text-decoration: underline; }

/* ---------- The first-run screen (onboarding.js) ----------

   ABOVE THE BOOT CURTAIN, which is z-index 9999 and is removed up to 220ms
   after it is told to go — long enough to fade, and long enough to cover this
   screen for a fifth of a second if the numbers were the other way round.

   It is also the only screen in the app with no way to dismiss it by clicking
   away: there is nothing behind it yet worth reaching, and the way past it is
   Skip. */
/* --app-bg and --border, NOT --bg-primary and --panel-border, which is how
   every other dialog in this file is painted. On Daylight — the surface a new
   library opens as, so the only one this screen is ever seen on by default —
   --panel-border is literally `transparent` and --bg-primary is the same white
   as --card-bg, so the house idiom draws a white card on a white screen with
   no edge: the first version of this looked like loose text on a blank page.
   --app-bg is the desk, --card-bg the tile on it, --border the hairline
   between, which is the whole of how Daylight is built. */
/* CENTRED BY `margin: auto`, NOT by align-items: center — with the second, a
   card taller than the window is centred by overflowing BOTH ways, and the top
   of it goes above the scroll origin where nothing can reach it. The second
   step is eight pages long and does exactly that on a short window: the title
   was cut off and no amount of scrolling brought it back. An auto margin on a
   flex item centres it the same way and stops at the padding edge instead. */
.onb-overlay { position: fixed; inset: 0; z-index: 10000; display: flex; align-items: flex-start; justify-content: center; padding: 24px; background: var(--app-bg); overflow-y: auto; }
.onb { width: min(520px, 100%); margin: auto; background: var(--card-bg); border: 1px solid var(--border); border-radius: var(--radius-panel); padding: 30px 30px 22px; box-shadow: 0 24px 72px rgba(22, 28, 44, 0.12); }
.onb-mark { display: block; width: 46px; height: 46px; object-fit: contain; margin-bottom: 16px; }
.onb h2 { font-size: 23px; font-weight: 700; letter-spacing: -0.02em; color: var(--text-heading); margin: 0 0 7px; }
.onb-sub { font-size: 13.5px; line-height: 1.55; color: var(--text-muted); margin: 0 0 20px; }
.onb-step.hidden { display: none; }

.onb-picks { display: flex; flex-direction: column; gap: 9px; }
.onb-picks button { display: block; width: 100%; text-align: left; background: var(--bg-secondary); border: 1px solid var(--border); border-radius: var(--radius-active); padding: 13px 15px; cursor: pointer; color: var(--text-normal); font: inherit; transition: border-color .12s, background .12s; }
.onb-picks button:hover, .onb-picks button:focus-visible { border-color: var(--accent); background: var(--bg-hover); outline: none; }
.onb-picks button b { display: block; font-size: 14.5px; font-weight: 650; margin-bottom: 3px; color: var(--text-heading); }
.onb-picks button span { display: block; font-size: 12.5px; color: var(--text-muted); line-height: 1.45; }

.onb-pages { display: flex; flex-direction: column; gap: 2px; margin-bottom: 20px; }
.onb-page { display: flex; align-items: flex-start; gap: 11px; padding: 9px 10px; border-radius: var(--radius-active); cursor: pointer; }
.onb-page:hover { background: var(--bg-hover); }
.onb-page input { margin: 2px 0 0; flex: none; }
/* Notes cannot be switched off (PAGES `always`), and a disabled checkbox that
   looks like the others invites a click that does nothing. */
.onb-page-fixed { cursor: default; opacity: 0.72; }
.onb-page-fixed:hover { background: none; }
.onb-page-text { display: block; min-width: 0; }
.onb-page-text b { display: block; font-size: 13.5px; font-weight: 600; color: var(--text-heading); }
.onb-page-text span { display: block; font-size: 12px; color: var(--text-muted); line-height: 1.45; }

/* Settings → General → Pages, same reason as .onb-page-fixed above: Daylight
   draws these checkboxes as toggle switches and gives a disabled one no mark
   of its own. */
.settings-row-fixed { opacity: 0.6; }
.settings-row-fixed label { cursor: default; }

.onb-actions { display: flex; align-items: center; justify-content: space-between; gap: 10px; }
.onb-back { background: none; border: none; color: var(--text-muted); font: inherit; font-size: 13px; padding: 8px 2px; cursor: pointer; }
.onb-back:hover { color: var(--text-normal); text-decoration: underline; }
.onb-done { border: none; border-radius: var(--radius-active); padding: 11px 20px; font: inherit; font-weight: 600; font-size: 14px; cursor: pointer; background: var(--accent); color: #fff; box-shadow: var(--shadow-active); }
.onb-skip { display: block; width: 100%; margin: 18px 0 0; padding: 8px; background: none; border: none; color: var(--text-muted); font: inherit; font-size: 12.5px; cursor: pointer; }
.onb-skip:hover { color: var(--text-normal); text-decoration: underline; }

/* ---------- The guided tour (tour.js) ----------

   Above the app but BELOW the first-run screen's 10000, because the tour starts
   as that screen closes and for a frame they can both be in the document.
   No backdrop: a dimming layer would hide the page the card is pointing at. */
.tour-card {
  position: fixed; z-index: 9500; width: min(330px, calc(100vw - 24px));
  background: var(--card-bg); border: 1px solid var(--border);
  border-radius: var(--radius-panel); padding: 18px 18px 14px;
  box-shadow: 0 18px 54px rgba(22, 28, 44, 0.22);
}
.tour-step { font-size: 11px; font-weight: 600; letter-spacing: 0.04em; text-transform: uppercase; color: var(--text-muted); margin-bottom: 7px; }
.tour-card h3 { font-size: 17px; font-weight: 700; letter-spacing: -0.01em; color: var(--text-heading); margin: 0 0 6px; }
.tour-card p { font-size: 13px; line-height: 1.5; color: var(--text-normal); margin: 0 0 8px; }
.tour-card p.tour-tip { font-size: 12.5px; color: var(--text-muted); margin-bottom: 14px; }
.tour-actions { display: flex; align-items: center; justify-content: space-between; gap: 10px; }
.tour-skip { background: none; border: none; color: var(--text-muted); font: inherit; font-size: 12.5px; padding: 6px 2px; cursor: pointer; }
.tour-skip:hover { color: var(--text-normal); text-decoration: underline; }
/* Empty on the last step — kept in the DOM so the Next button stays put rather
   than sliding across on the final card. */
.tour-skip:empty { pointer-events: none; }
.tour-next { margin-left: auto; border: none; border-radius: var(--radius-active); padding: 9px 17px; font: inherit; font-weight: 600; font-size: 13.5px; cursor: pointer; background: var(--accent); color: #fff; box-shadow: var(--shadow-active); }

/* The nav button the card is talking about. An outline rather than a fill: the
   button also carries .active while you are on that page, and a second fill on
   top of that one just looks like a rendering fault. */
.pnav-btn.tour-spot {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
  border-radius: 8px;
}
body.surface-daylight #primary-nav .pnav-btn.tour-spot { border-radius: 16px; }

#share-overlay { position: fixed; inset: 0; z-index: 60; display: flex; align-items: center; justify-content: center; background: rgba(20, 24, 38, 0.44); }
#share-overlay.hidden { display: none; }
#share-box {
  position: relative; width: min(460px, 92vw); max-height: 86vh; overflow-y: auto;
  background: var(--card-bg); border: 1px solid var(--panel-border);
  border-radius: var(--radius-panel); padding: 30px 28px 26px;
  box-shadow: 0 24px 72px rgba(22, 28, 44, 0.34);
}
#share-close { position: absolute; top: 14px; right: 14px; }
#share-title { font-size: 20px; font-weight: 700; letter-spacing: -0.02em; color: var(--text-heading); margin-bottom: 6px; }
#share-sub { font-size: 13px; color: var(--text-muted); margin-bottom: 8px; }
#share-warn { font-size: 12.5px; line-height: 1.5; color: var(--text-normal); background: rgba(240, 190, 90, 0.14); border: 1px solid rgba(240, 190, 90, 0.4); border-radius: var(--radius-active); padding: 11px 13px; margin: 12px 0; }
#share-perm-row { display: flex; align-items: center; justify-content: space-between; gap: 10px; font-size: 13px; color: var(--text-normal); margin-bottom: 14px; }
#share-perm { padding: 7px 10px; border-radius: var(--radius-active); border: 1px solid var(--border); background: var(--bg-primary); color: var(--text-normal); font: inherit; }
#share-create { width: 100%; padding: 11px; border: none; border-radius: var(--radius-active); font-weight: 600; font-size: 14px; cursor: pointer; background: var(--accent); color: #fff; box-shadow: var(--shadow-active); }
#share-create:disabled { opacity: 0.55; cursor: default; }
#share-consent.hidden, #share-error.hidden { display: none; }
.share-link { border: 1px solid var(--border); border-radius: var(--radius-active); padding: 12px; margin-top: 12px; background: var(--bg-primary); }
.share-link-url { display: flex; gap: 8px; align-items: center; }
.share-link-url input { flex: 1; min-width: 0; padding: 8px 10px; border-radius: var(--radius-active); border: 1px solid var(--border); background: var(--card-bg); color: var(--text-normal); font-family: var(--font-mono); font-size: 12px; }
.share-link-meta { font-size: 11.5px; color: var(--text-muted); margin: 8px 0; }
/* People with access (share-ui.js) — one row per person, a role each. */
.share-people { margin-top: 10px; border-top: 1px solid var(--border); padding-top: 10px; }
.share-people-head { font-size: 11.5px; font-weight: 600; color: var(--text-muted); margin-bottom: 6px; }
.share-person { display: flex; align-items: center; gap: 9px; padding: 5px 0; }
.share-person-who { flex: 1; min-width: 0; display: flex; flex-direction: column; line-height: 1.25; }
.share-person-name { font-size: 13px; color: var(--text-normal); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.share-person-email { font-size: 11.5px; color: var(--text-muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.share-person-role { font-size: 12px; color: var(--text-muted); }
/* Sits before the per-person select and says the link is overruling it (0053);
   wrapped so a long name cannot push it off the row. */
.share-person-capped { font-size: 11px; color: var(--text-faint); text-align: right; max-width: 10em; line-height: 1.2; }
.share-person select { font-size: 12px; padding: 3px 6px; }
.share-person.removed .share-person-who, .share-person.removed .np-face { opacity: 0.5; }
.share-people-hint { font-size: 11.5px; color: var(--text-faint); margin-top: 6px; line-height: 1.4; }
.share-link-actions { display: flex; gap: 8px; }
.settings-mini.danger { color: #d0524a; }
#share-error { margin-top: 14px; font-size: 13px; padding: 9px 12px; border-radius: var(--radius-active); color: #d0524a; background: rgba(208, 82, 74, 0.1); border: 1px solid rgba(208, 82, 74, 0.24); }

#e2e-box {
  position: relative; width: min(420px, 92vw);
  background: var(--card-bg); border: 1px solid var(--panel-border);
  border-radius: var(--radius-panel); padding: 32px 30px 28px;
  box-shadow: 0 24px 72px rgba(22, 28, 44, 0.34);
}
#e2e-close { position: absolute; top: 14px; right: 14px; }
#e2e-title { font-size: 21px; font-weight: 700; letter-spacing: -0.02em; color: var(--text-heading); margin-bottom: 6px; }
#e2e-sub { font-size: 13px; color: var(--text-muted); margin-bottom: 4px; line-height: 1.5; }
#e2e-form label, #e2e-kit label { display: block; font-size: 12.5px; font-weight: 500; color: var(--text-muted); margin: 15px 0 6px; }
#e2e-form input[type="password"], #e2e-form input[type="text"] {
  width: 100%; padding: 10px 13px; border-radius: var(--radius-active);
  border: 1px solid var(--border); background: var(--bg-primary);
  color: var(--text-normal); font-size: 14px; font-family: inherit;
}
#e2e-form input:focus { outline: none; border-color: var(--accent); box-shadow: var(--shadow-active); }
#e2e-submit, #e2e-kit-done, #e2e-fr-on {
  width: 100%; margin-top: 20px; padding: 11px; border-radius: var(--radius-active);
  border: none; font-weight: 600; font-size: 14px; cursor: pointer;
  background: var(--accent); color: #fff; box-shadow: var(--shadow-active);
}
#e2e-submit:disabled, #e2e-kit-done:disabled { opacity: 0.55; cursor: default; }
#e2e-error { margin-top: 14px; font-size: 13px; padding: 9px 12px; border-radius: var(--radius-active); color: #d0524a; background: rgba(208, 82, 74, 0.1); border: 1px solid rgba(208, 82, 74, 0.24); }
#e2e-error.hidden, #e2e-confirm-wrap.hidden, #e2e-sk-wrap.hidden, #e2e-form.hidden, #e2e-kit.hidden, #e2e-lock.hidden, #e2e-action.hidden, #e2e-encrypt.hidden, #e2e-forgot.hidden, #e2e-kit-sk-row.hidden, #e2e-verify-msg.hidden, #e2e-custody-row.hidden, #e2e-touchid-row.hidden, #e2e-touchid-hint.hidden, #e2e-rotate.hidden { display: none; }
#e2e-forgot { display: block; margin: 14px auto 0; background: none; border: none; color: var(--accent); font-size: 12.5px; font-weight: 500; cursor: pointer; }
#e2e-forgot:hover { text-decoration: underline; }
#e2e-warn { font-size: 12.5px; line-height: 1.5; color: var(--text-normal); background: rgba(240, 190, 90, 0.14); border: 1px solid rgba(240, 190, 90, 0.4); border-radius: var(--radius-active); padding: 11px 13px; margin-bottom: 2px; }
.e2e-code { display: flex; align-items: center; gap: 8px; }
.e2e-code code { flex: 1; font-family: var(--font-mono); font-size: 13px; background: var(--bg-primary); border: 1px solid var(--border); border-radius: var(--radius-active); padding: 9px 11px; color: var(--text-normal); letter-spacing: 0.03em; user-select: all; }
#e2e-link.hidden, #e2e-linkbtn.hidden, #e2e-firstrun.hidden, #e2e-addpass.hidden, #e2e-pass.hidden, #e2e-pass-label.hidden { display: none; }
#e2e-fr-copy { font-size: 13px; line-height: 1.55; color: var(--text-normal); margin-top: 12px; }
#e2e-fr-skip { display: block; margin: 12px auto 0; background: none; border: none; color: var(--text-muted); font-size: 12.5px; font-weight: 500; cursor: pointer; }
#e2e-fr-skip:hover { text-decoration: underline; color: var(--text-normal); }
#e2e-linkbtn { display: block; margin: 10px auto 0; background: none; border: none; color: var(--accent); font-size: 12.5px; font-weight: 500; cursor: pointer; }
#e2e-linkbtn:hover { text-decoration: underline; }
#e2e-link-sub, #e2e-link-wait { font-size: 12.5px; line-height: 1.5; color: var(--text-muted); margin-top: 14px; }
#e2e-link-sas {
  margin-top: 14px; text-align: center; font-family: var(--font-mono);
  font-size: 26px; font-weight: 700; letter-spacing: 0.12em; color: var(--text-heading);
  background: var(--bg-primary); border: 1px solid var(--border); border-radius: var(--radius-active); padding: 14px;
  user-select: all;
}
#e2e-link-cancel { display: block; margin: 16px auto 0; }
#e2e-kit-steer { font-size: 12.5px; line-height: 1.5; color: var(--text-muted); margin-top: 14px; }
.cloudb-list { margin: 8px 0 14px; border: 1px solid var(--border); border-radius: var(--radius-active); background: var(--bg-primary); max-height: 300px; overflow-y: auto; }
.cloudb-row { display: flex; align-items: baseline; gap: 10px; padding: 4px 10px; font-size: 12.5px; color: var(--text-normal); }
.cloudb-row + .cloudb-row { border-top: 1px solid color-mix(in srgb, var(--border) 45%, transparent); }
.cloudb-folder .cloudb-name, .cloudb-folder { font-weight: 600; color: var(--text-muted); }
.cloudb-name { flex: 1 1 auto; min-width: 35%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.cloudb-meta { flex: 0 1 auto; min-width: 0; max-width: 60%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 11.5px; color: var(--text-muted); }
.cloudb-trashed .cloudb-name { text-decoration: line-through; opacity: 0.7; }
#e2e-kit #e2e-verify {
  width: 100%; padding: 10px 13px; border-radius: var(--radius-active);
  border: 1px solid var(--border); background: var(--bg-primary);
  color: var(--text-normal); font-size: 13px; font-family: var(--font-mono); letter-spacing: 0.03em;
}
#e2e-kit #e2e-verify:focus { outline: none; border-color: var(--accent); box-shadow: var(--shadow-active); }
#e2e-verify-msg { margin-top: 10px; font-size: 12.5px; padding: 8px 11px; border-radius: var(--radius-active); color: #d0524a; background: rgba(208, 82, 74, 0.1); border: 1px solid rgba(208, 82, 74, 0.24); }
#e2e-verify-msg.ok { color: #3d9a5f; background: rgba(84, 178, 122, 0.12); border-color: rgba(84, 178, 122, 0.32); }

/* ============ Settings ============ */
#settings-overlay { align-items: center; }
#settings-box {
  width: min(920px, 94vw);
  height: min(640px, 86vh);
  display: flex;
  overflow: hidden;
  background: var(--card-bg);
  border: 1px solid var(--panel-border);
  border-radius: var(--radius-panel);
  padding: 0;
  box-shadow: 0 24px 64px rgba(22, 28, 44, 0.28);
}
.settings-title { font-size: 17px; font-weight: 700; letter-spacing: -0.02em; color: var(--text-heading); margin-bottom: 12px; }

/* Left nav column */
#settings-side {
  width: 208px;
  flex-shrink: 0;
  display: flex;
  flex-direction: column;
  gap: 10px;
  padding: 16px 12px;
  background: var(--bg-secondary);
  border-right: 1px solid var(--border);
}
#settings-search { font-size: 12.5px; padding: 6px 10px; }
.settings-nav { overflow-y: auto; display: flex; flex-direction: column; gap: 1px; }
.settings-nav-group {
  font-size: 10.5px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.1em;
  color: var(--text-faint); margin: 12px 6px 5px; user-select: none;
}
.settings-nav .settings-nav-group:first-child { margin-top: 2px; }
.settings-nav-item {
  display: flex; align-items: center; gap: 6px;
  text-align: left; font-size: 13px; font-weight: 550; color: var(--text-muted);
  padding: 6px 9px; border-radius: var(--radius-active);
  transition: background 0.1s, color 0.1s;
}
.settings-nav-item:hover { background: var(--bg-hover); color: var(--text-heading); }
.settings-nav-item.active { background: var(--chip-bg); color: var(--chip-text); }
.soon-chip {
  font-size: 9.5px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.07em;
  background: var(--highlight-bg); color: var(--highlight-text);
  border-radius: 6px; padding: 1.5px 6px;
}

/* Right content column */
#settings-main { flex: 1; display: flex; flex-direction: column; min-width: 0; }
#settings-head {
  display: flex; align-items: center; justify-content: space-between;
  padding: 16px 20px 10px;
}
#settings-head .settings-title { margin-bottom: 0; }
.settings-scroll { flex: 1; overflow-y: auto; padding: 4px 20px 20px; }
.settings-page { display: none; }
.settings-page.active { display: block; }
#settings-box.searching .settings-page { display: block; }
#settings-box.searching .settings-page > * { display: none; }
#settings-box.searching .settings-page > .search-hit { display: block; }
#settings-box.searching .settings-page > .settings-row.search-hit { display: flex; }
#settings-box.searching .settings-page > .settings-page-badge.search-hit { display: block; }
.settings-page-badge {
  display: none;
  font-size: 10.5px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.1em;
  color: var(--text-faint); margin: 14px 0 8px;
}
.settings-value { font-size: 12.5px; color: var(--text-muted); }
.settings-value.dim { color: var(--text-faint); }
.settings-input {
  width: 190px; font-size: 12.5px; padding: 6px 10px;
}
.settings-input.grow { flex: 1; width: auto; }
.path-value { max-width: 340px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; margin: 0; }
.settings-mini.danger { background: color-mix(in srgb, var(--danger) 14%, transparent); color: var(--danger); }
/* ---- Theme store gallery ---- */
#theme-gallery { margin-top: 8px; }
.tc-group { font-size: 11px; font-weight: 700; letter-spacing: 0.06em; text-transform: uppercase; color: var(--text-faint); margin: 14px 0 8px; }
.theme-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(120px, 1fr)); gap: 10px; }
.theme-card {
  position: relative; display: flex; flex-direction: column; gap: 7px; padding: 8px; cursor: pointer;
  background: var(--card-bg); border: 1px solid var(--border); border-radius: 10px; text-align: left;
  transition: border-color .12s, transform .08s;
}
.theme-card:hover { border-color: var(--text-faint); transform: translateY(-1px); }
.theme-card.cur { border-color: var(--accent); box-shadow: 0 0 0 2px color-mix(in srgb, var(--accent) 30%, transparent); }
.tc-swatch { position: relative; display: block; height: 46px; border-radius: 7px; overflow: hidden; border: 1px solid rgba(0,0,0,0.12); }
.tc-surface { position: absolute; left: 0; bottom: 0; width: 100%; height: 40%; }
.tc-aa { position: absolute; left: 8px; top: 6px; font-size: 15px; font-weight: 700; }
.tc-dot { position: absolute; right: 8px; bottom: 7px; width: 14px; height: 14px; border-radius: 50%; box-shadow: 0 0 0 2px rgba(255,255,255,0.4); }
.tc-name { font-size: 12.5px; font-weight: 550; color: var(--text-heading); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.tc-del, .tc-share { position: absolute; top: 4px; width: 18px; height: 18px; line-height: 17px; text-align: center; border-radius: 50%;
  background: var(--card-bg); border: 1px solid var(--border); color: var(--text-muted); font-size: 12px; opacity: 0; transition: opacity .12s; }
.tc-del { right: 4px; } .tc-share { right: 26px; }
.theme-card:hover .tc-del, .theme-card:hover .tc-share { opacity: 1; }
.tc-del:hover { color: var(--danger); border-color: var(--danger); }
.theme-form { display: flex; flex-wrap: wrap; align-items: center; gap: 10px; margin: 8px 0; padding: 12px; background: var(--bg-subtle, var(--code-bg)); border: 1px solid var(--border); border-radius: 10px; }
.theme-form.hidden { display: none; }
.tf-color { display: inline-flex; align-items: center; gap: 5px; font-size: 12px; color: var(--text-muted); }
.tf-color input[type="color"] { width: 26px; height: 24px; padding: 0; border: 1px solid var(--border); border-radius: 5px; background: none; cursor: pointer; }
.settings-section {
  font-size: 11px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.1em;
  color: var(--text-faint);
  margin: 16px 0 10px;
  padding-bottom: 5px;
  border-bottom: 1px solid var(--border);
}
.settings-scroll .settings-section:first-child { margin-top: 0; }
.settings-row {
  display: flex; align-items: center; justify-content: space-between;
  gap: 12px; margin-bottom: 13px; font-size: 13.5px;
}
.settings-row label { color: var(--text-muted); font-weight: 500; }
.settings-row select {
  background: var(--bg-secondary); color: var(--text-normal);
  border: 1px solid var(--border); border-radius: 8px; padding: 6px 9px; font-size: 13px;
  font-family: inherit;
}
.settings-row input[type="color"] {
  width: 44px; height: 28px; border: 1px solid var(--border); border-radius: 8px;
  background: var(--bg-secondary); padding: 2px; cursor: pointer;
}
.settings-row input[type="checkbox"] { accent-color: var(--accent); width: 15px; height: 15px; }
.settings-range { display: flex; align-items: center; gap: 8px; }
.settings-range input[type="range"] { accent-color: var(--accent); }
#set-fontsize-val { font-size: 11.5px; color: var(--text-faint); min-width: 44px; text-align: right; font-family: var(--font-mono); }
#set-stats { font-size: 12.5px; color: var(--text-faint); font-family: var(--font-mono); }
.settings-mini {
  font-size: 11.5px;
  font-weight: 600;
  padding: 4px 10px;
  border-radius: 7px;
  background: var(--chip-bg);
  color: var(--chip-text);
  transition: filter 0.12s;
}
.settings-mini:hover { filter: brightness(0.95); }

/* ============ Right-side reference panels (Hotkeys · Features) ============ */
.rpanel-head {
  display: flex; align-items: center; justify-content: space-between;
  padding: 10px 10px 4px 14px; flex-shrink: 0;
}
.rpanel-search { padding: 4px 10px 8px; flex-shrink: 0; }
.rpanel-search input { width: 100%; font-size: 12.5px; padding: 6px 10px; }
/* The pane header and filter stay put; only the list scrolls. */
#rpane-hotkeys, #rpane-guide { overflow: hidden; }
#hotkeys-panel, #guide-panel { flex: 1; min-height: 0; overflow-y: auto; padding: 0 10px 20px; }

.hk-doc-group { margin-bottom: 6px; }
.hk-doc-row {
  display: flex; align-items: baseline; justify-content: space-between; gap: 10px;
  padding: 5px 4px; font-size: 12.5px; border-radius: 7px;
}
.hk-doc-row:hover { background: var(--bg-hover); }
.hk-doc-action { color: var(--text-muted); line-height: 1.45; }
.hk-doc-keys { flex-shrink: 0; white-space: nowrap; display: flex; gap: 3px; align-items: center; }
.hk-doc-keys kbd { font-size: 0.78em; padding: 1.5px 6px; }
.hk-doc-context { display: block; font-size: 11px; color: var(--text-faint); }

.guide-item {
  border: 1px solid var(--border); border-radius: var(--radius-card);
  background: var(--card-bg); box-shadow: var(--shadow-card);
  margin-bottom: 7px; overflow: hidden;
}
.guide-item-head {
  display: flex; align-items: center; gap: 7px; width: 100%;
  padding: 8px 11px; font-size: 13px; font-weight: 600; color: var(--text-normal);
  text-align: left; transition: background 0.1s;
}
.guide-item-head:hover { background: var(--bg-hover); }
.guide-item-head .tree-chevron { transition: transform 0.12s; flex-shrink: 0; color: var(--text-faint); display: inline-flex; }
.guide-item-head .tree-chevron svg { width: 13px; height: 13px; }
.guide-item.open .guide-item-head .tree-chevron { transform: rotate(90deg); }
.guide-item-body { display: none; padding: 0 12px 10px; font-size: 12.5px; color: var(--text-muted); line-height: 1.55; }
.guide-item.open .guide-item-body { display: block; }
.guide-item-body code, .hk-doc-action code {
  font-family: var(--font-mono); font-size: 0.85em;
  background: var(--code-bg); color: var(--code-text); border-radius: 4px; padding: 0 4px;
}
.guide-item-body .guide-try {
  margin-top: 8px; font-size: 11.5px; font-weight: 600;
  padding: 4px 10px; border-radius: 7px;
  background: var(--chip-bg); color: var(--chip-text);
}
.guide-item-body .guide-try:hover { filter: brightness(0.95); }
.guide-what { color: var(--text-normal); margin-bottom: 5px; }

/* ============ Inline naming (new note / new folder / rename) ============ */
.inline-rename {
  outline: none;
  cursor: text;
  user-select: text;
  -webkit-user-select: text;
  background: var(--bg-primary);
  border-radius: 6px;
  padding: 0 6px;
  min-width: 50px;
  box-shadow: 0 0 0 2px var(--accent);
}
.tree-item .tree-label.inline-rename { overflow: visible; text-overflow: clip; }

/* ============ Study: flashcards & spaced repetition ============ */

/* Card blocks stand apart from prose (RemNote-style) — in both modes, in the
   editor and the split pane. Answer blocks of a multi-block card carry
   data-card-part and join visually with their prompt. */
:is(#editor, .editor2) [data-card-id], #split-content [data-card-id],
:is(#editor, .editor2) [data-card-part], #split-content [data-card-part] {
  background: color-mix(in srgb, var(--tag-bg) 50%, transparent);
  border-left: 3px solid color-mix(in srgb, var(--tag-text) 55%, transparent);
  border-radius: 0 var(--radius-active) var(--radius-active) 0;
  padding: 5px 10px 5px 12px;
}
/* A card is ONE block, not a stack of tinted strips.

   Every block carried margin-bottom: 2px, so a card whose answer is several
   paragraphs showed a dark seam between each of them — the page background
   showing through a 2px gap. Joined instead: no margin where a card continues
   into its own answer, square corners inside the run, rounded only at the two
   ends. Two ADJACENT but separate cards keep their gap, because they are two
   cards; the join is only ever between a prompt and its own parts. */
:is(#editor, .editor2) [data-card-id], #split-content [data-card-id] {
  margin-bottom: 2px;
}
:is(#editor, .editor2) [data-card-part], #split-content [data-card-part] {
  margin-top: 0;
  margin-bottom: 2px;
  border-top-right-radius: 0;
}
/* Anything a card part follows is mid-run: close the gap under it. */
:is(#editor, .editor2) [data-card-id]:has(+ [data-card-part]),
:is(#editor, .editor2) [data-card-part]:has(+ [data-card-part]),
#split-content [data-card-id]:has(+ [data-card-part]),
#split-content [data-card-part]:has(+ [data-card-part]) {
  margin-bottom: 0;
  border-bottom-right-radius: 0;
}
/* List answers keep room for their bullets inside the tinted block. */
:is(#editor, .editor2) ul[data-card-part], :is(#editor, .editor2) ol[data-card-part],
#split-content ul[data-card-part], #split-content ol[data-card-part] {
  padding-left: calc(1.6em + 12px);
}
:is(#editor, .editor2) [data-card-part] + :not([data-card-part]),
#split-content [data-card-part] + :not([data-card-part]) { margin-top: 14px; }

/* Reading-mode typography: bold question, violet divider, dimmed answer,
   cloze marks with the braces hidden. */
.tn-card-front { font-weight: 650; color: var(--text-heading); }
.tn-card-back { color: var(--text-muted); }
/* The separator you TYPE is " :: "; the separator you SEE is an arrow —
   the RemNote convention, and the owner's ask. The literal text stays in
   the span (dehydrate restores it byte-for-byte), only the paint changes. */
.tn-card-sep { font-size: 0; }
.tn-card-sep::after {
  content: '→';
  font-size: 14px;
  font-weight: 600;
  color: var(--tag-text);
  margin: 0 9px;
  vertical-align: 0.5px;
}
/* ---- due markers in the note body ----

   Raw `due:2026-08-10T15:00` at full weight mid-sentence reads as prose when
   it is metadata. Two treatments, and which one you get depends on whether a
   caret can reach it:

   READING mode paints a chip over the literal (font-size:0 + ::after, the same
   trick .tn-card-sep uses for " :: " -> arrow). Safe because nothing is
   editable there.

   EDIT mode keeps the characters VISIBLE and merely demotes them. Hiding text
   you can type into means typing into an invisible zone — and worse, the caret
   lands inside the span, so what you type is absorbed by it. The literal has to
   stay on screen for the line to remain honest while you edit it. */
.tn-due {
  font-size: 0;
  /* Never let a chip stretch the line's leading. */
  line-height: inherit;
  /* The chip moves as ONE unit to the next line rather than punching out of a
     narrow container. Without this it overflowed a two-column layout by up to
     73px: the task's words wrap, but the chip's nowrap content cannot, so it
     just kept going past the edge. inline-block + max-width gives the line
     breaker a box it is allowed to move, while nowrap below still stops
     "Tomorrow 09:00" from splitting across two lines mid-label. */
  display: inline-block;
  max-width: 100%;
  vertical-align: baseline;
}
.tn-due::after {
  content: attr(data-label);
  font-size: 10.5px;
  font-family: var(--font-mono);
  font-weight: 600;
  letter-spacing: .01em;
  color: var(--text-faint);
  background: color-mix(in srgb, var(--text-faint) 11%, transparent);
  border-radius: 5px;
  padding: 1px 6px;
  margin-left: 2px;
  vertical-align: 1px;
  white-space: nowrap;
}
/* Late is the one state worth colour. Everything else recedes on purpose —
   the ask was "less visible", and a violet chip would compete with cards. */
.tn-due[data-tone="late"]::after {
  color: var(--danger, #c2410c);
  background: color-mix(in srgb, var(--danger, #c2410c) 12%, transparent);
}
.tn-due[data-tone="bad"]::after {
  color: var(--danger, #c2410c);
  background: transparent;
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--danger, #c2410c) 45%, transparent);
}
/* A finished task's date stops mattering. */
li > input[type="checkbox"][checked] ~ .tn-due::after,
.editor2 li.pm-done .tn-due::after,
.todo-row.done .tn-due::after { opacity: .55; }

/* Tighter where space is scarce — a column or a table cell. The chip should
   tuck in against the words rather than hold the same airy spacing it gets in
   a full-width note. */
.cols .col .tn-due::after,
td .tn-due::after,
th .tn-due::after,
.tn-tasks .tn-due::after {
  font-size: 10px;
  padding: 1px 5px;
  margin-left: 1px;
}

/* EDIT mode paints the SAME chip. That is only safe because the span is
   contenteditable="false" — the caret cannot enter it, so nothing can be typed
   into an invisible zone and no keystroke can be absorbed by the marker. You
   change a date by clicking the chip or pressing Cmd/Ctrl+Shift+L. */
:is(#editor[contenteditable="true"], .editor2) .tn-due { cursor: pointer; }
:is(#editor[contenteditable="true"], .editor2) .tn-due:hover::after {
  color: var(--accent);
  background: color-mix(in srgb, var(--accent) 13%, transparent);
}
/* A selected atomic chip — Backspace here clears the date outright, so it has
   to look selected rather than merely hovered. */
:is(#editor, .editor2) .tn-due::selection, :is(#editor, .editor2) .tn-due *::selection { background: transparent; }

mark.tn-cloze {
  background: color-mix(in srgb, var(--tag-bg) 85%, transparent);
  color: var(--tag-text);
  font-weight: 600;
  border-bottom: 2px solid color-mix(in srgb, var(--tag-text) 55%, transparent);
  border-radius: 4px;
  padding: 0 4px;
}

/* A line that became a card says so while you write. Folded headings keep
   their fold indicator — the chip yields. */
body[data-mode="edit"] :is(#editor, .editor2) [data-card-id]:not(.tn-folded)::after {
  content: 'card';
  margin-left: 8px;
  padding: 1px 7px;
  border-radius: 8px;
  font-size: 9.5px;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  font-family: var(--font-mono);
  background: var(--tag-bg);
  color: var(--tag-text);
  vertical-align: 1px;
}

#status-cards { cursor: pointer; }
#status-cards:hover { color: var(--link); }
#status-cards:empty { display: none; }
#status-sync { cursor: pointer; }
#status-sync:hover { color: var(--link); }
#status-sync:empty { display: none; }
#status-sync.pending { color: var(--accent); }

/* Study tab (left sidebar) */
#study-dash { padding: 4px 12px 10px; border-bottom: 1px solid var(--border); }
.sd-numbers { display: flex; gap: 6px; margin-bottom: 10px; }
.sd-stat {
  flex: 1; display: flex; flex-direction: column; align-items: center; gap: 1px;
  padding: 7px 2px; background: var(--card-bg); border: 1px solid var(--border);
  border-radius: var(--radius-card); box-shadow: var(--shadow-card);
}
.sd-n { font-size: 15px; font-weight: 700; color: var(--text-heading); font-family: var(--font-mono); }
.sd-l { font-size: 9.5px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.06em; color: var(--text-faint); }
.sd-forecast { display: flex; align-items: flex-end; gap: 2px; height: 36px; margin-bottom: 10px; padding: 0 2px; }
.sd-bar { flex: 1; background: var(--chip-bg); border-radius: 2px 2px 0 0; min-height: 2px; }
.sd-bar.today { background: var(--accent); }
.sd-study-btn {
  width: 100%; padding: 8px 0; border-radius: var(--radius-active);
  font-size: 13px; font-weight: 650;
  background: var(--accent); color: #fff; box-shadow: var(--shadow-active);
}
.sd-study-btn:hover { background: var(--accent-strong); }
.sd-study-btn:disabled { background: var(--bg-tertiary); color: var(--text-faint); box-shadow: none; cursor: default; }
#study-decks { padding: 4px 10px 20px; overflow-y: auto; }
.deck-row {
  display: flex; align-items: center; gap: 6px;
  padding: 6px 9px; border-radius: var(--radius-active); cursor: pointer;
  font-size: 13.5px; color: var(--text-muted);
  transition: background 0.1s, color 0.1s;
}
.deck-row:hover { background: var(--bg-hover); color: var(--text-heading); }
/* "This is the deck you came from" — set when the right rail opens the Study
   page pointing at a note, and removed after a few seconds. It fades because
   it is a pointer, not a selection; one that stayed would read as state the
   page does not actually have. */
.deck-row-here { background: var(--bg-hover); box-shadow: inset 2px 0 0 var(--accent); transition: background .4s ease, box-shadow .4s ease; }
.deck-name { flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* Study card: revealed cloze answer + Anki-style Extra on the back */
.cloze-blank { color: var(--accent, #6b5bd6); font-weight: 700; letter-spacing: 0.04em; }
.cloze-reveal { background: color-mix(in srgb, var(--accent, #6b5bd6) 16%, transparent); color: var(--accent, #6b5bd6); font-weight: 700; padding: 0 4px; border-radius: 5px; }
.study-extra { margin-top: 16px; padding-top: 14px; border-top: 1px solid var(--panel-border); color: var(--text-muted); font-size: 0.92em; }
.study-extra p { margin: 0 0 8px; }
.study-extra img { max-width: 100%; max-height: 46vh; border-radius: 10px; display: block; margin: 10px auto 0; }
/* A picture written INTO a question or an answer (study-view faceHtml), as
   opposed to one trailing the card in the note (.study-extra img above). Same
   ceiling, so a card with one of each does not look like two different things.
   Block, because an image in a card face is the content, not a word in it. */
.study-img { max-width: 100%; max-height: 46vh; border-radius: 10px; display: block; margin: 10px auto; }
.ex-opt .study-img, .ex-q .study-img { max-height: 28vh; margin: 6px 0; }

/* TWO FIGURES IN ONE QUESTION MUST BOTH BE ON SCREEN.

   Asked for directly: "if there are 2 images in a quiz question then when we
   do a practice exam then it should show both images." They both rendered
   already — faceHtml walks every ![](…) in the text, so the count was never
   the problem — but each claimed its full height, so a two-figure question
   came to 1,082px inside a 496px card and the second one sat below the fold.
   A question that says "compare A with B" and shows you A is not showing you
   both.

   `img ~ img` is "there is an image with an image before it", which is true
   exactly when there are two or more; :has() hangs that test on the container
   so EVERY image in it shrinks together rather than only the later ones. No
   counting, no JavaScript, and a single-image question keeps its full size —
   which is the common case and should not pay for this. */
:is(.ex-q, #study-front, #study-back):has(img ~ img) .study-img { max-height: 20vh; }
/* Three or more and they tile instead, because a column of four short strips
   is harder to compare than a grid of four. */
:is(.ex-q, #study-front, #study-back):has(img ~ img ~ img) .study-img {
  max-height: 16vh; display: inline-block; margin: 6px 6px 6px 0; vertical-align: top;
}
.deck-study svg { position: relative; left: 1px; }

/* Study deck tree: folders are decks too */
.deck-folder-row { font-weight: 650; color: var(--text-heading); }
/* THE HIT BOX GROWS, THE LAYOUT DOES NOT. Padding makes the target about 26px
   square — a real one for a finger or a hurried mouse — and the matching
   negative margin cancels it out of the flow, so no row moves a pixel. It was
   a 15x15 glyph and the owner kept missing it. */
.deck-caret {
  /* WIDTH grows and the margin pulls it back, because box-sizing is border-box
     here: padding alone is drawn INSIDE the declared width, so the first
     attempt made the target taller and not one pixel wider. 25 - 5 - 5 = the
     15px it always occupied. */
  width: 25px; height: 26px; margin: -6px -5px; flex-shrink: 0;
  color: var(--text-muted); font-size: 13px;
  display: flex; align-items: center; justify-content: center; border-radius: 6px;
}
.deck-caret:hover { color: var(--text-heading); background: var(--bg-hover); }
.deck-tree-head { display: flex; align-items: center; justify-content: space-between; }
.deck-tree-head .icon-btn { width: 24px; height: 24px; font-size: 14px; }

/* Suspended-cards section on the Study home */
.link-btn {
  background: none; border: none; padding: 0; cursor: pointer;
  color: var(--accent, #4a72ff); font-size: 12px; font-weight: 550;
}
.link-btn:hover { text-decoration: underline; }
.suspended-section { margin-top: 14px; border-top: 1px solid var(--border); padding-top: 10px; }
.suspended-head { display: flex; align-items: center; justify-content: space-between; }
.suspended-list { display: flex; flex-direction: column; gap: 2px; margin-top: 6px; }
.suspended-row { display: flex; align-items: center; gap: 8px; justify-content: space-between; }
.suspended-open {
  flex: 1; text-align: left; background: none; border: none; cursor: pointer;
  color: var(--text-muted); font-size: 12.5px; padding: 3px 4px; border-radius: 5px;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.suspended-open:hover { background: var(--bg-hover); color: var(--text-heading); }
.suspended-row .link-btn { flex-shrink: 0; }

/* Flagged cards — the same shape as Suspended, which is deliberate: they are
   two lists of cards you said something about, and making them look like two
   different features would be a lie about how they relate. The flag mark is
   the one difference, in the highlight colour the session button uses. */
.flagged-section { margin-top: 14px; border-top: 1px solid var(--border); padding-top: 10px; }
.flagged-head { display: flex; align-items: center; justify-content: space-between; }
.flagged-head > span::before {
  content: ''; display: inline-block; width: 6px; height: 6px; border-radius: 50%;
  margin-right: 6px; vertical-align: middle;
  background: color-mix(in srgb, var(--highlight-text, #8A6410) 60%, transparent);
}
.flagged-list { display: flex; flex-direction: column; gap: 2px; margin-top: 6px; }
.flagged-row { display: flex; align-items: center; gap: 8px; justify-content: space-between; }
.flagged-open {
  flex: 1; text-align: left; background: none; border: none; cursor: pointer;
  color: var(--text-muted); font-size: 12.5px; padding: 3px 4px; border-radius: 5px;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.flagged-open:hover { background: var(--bg-hover); color: var(--text-heading); }
.flagged-row .link-btn { flex-shrink: 0; }

/* Recent sittings — three columns that line up down the list, so a run of
   scores reads as a trend without a chart. */
.sessions-section { margin-top: 14px; border-top: 1px solid var(--border); padding-top: 10px; }
.sessions-head { display: flex; align-items: center; justify-content: space-between; }
.sessions-list { display: flex; flex-direction: column; gap: 1px; margin-top: 6px; }
.session-row {
  display: grid; grid-template-columns: 42px 1fr auto; align-items: center; gap: 8px;
  font-size: 12px; color: var(--text-muted); padding: 3px 4px; border-radius: 5px;
}
.session-row:hover { background: var(--bg-hover); }
.session-when { font-family: var(--font-mono); font-size: 11px; color: var(--text-faint); }
.session-title { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.session-result { font-family: var(--font-mono); font-size: 11.5px; color: var(--text-normal); }
/* A paper's score is the number worth finding again in this list. */
.session-exam .session-result { font-weight: 650; color: var(--text-heading); }
/* The rows are buttons now — click one to read the paper back, or to pick a
   half-sat one up. */
.session-row { cursor: pointer; }
.session-row:focus-visible, .st-sit-row:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; border-radius: 6px; }
/* Left part way through: the one most worth clicking, marked so you do not
   have to open it to find out. */
.session-row.session-open .session-when::after,
.st-sit-row.st-sit-open .st-sit-when::after {
  content: '•'; margin-left: 4px; color: var(--accent); font-weight: 700;
}
.st-sit-row { cursor: pointer; }

/* ---- one sitting, opened ---- */
#sitting-overlay {
  position: fixed; inset: 0; z-index: 64; display: flex;
  align-items: center; justify-content: center;
  background: rgba(20, 24, 38, 0.44); padding: 24px;
}
#sitting-overlay.hidden { display: none; }
#sitting-box {
  width: min(680px, 94vw); max-height: 86vh; display: flex; flex-direction: column;
  background: var(--card-bg); border: 1px solid var(--panel-border);
  border-radius: var(--radius-panel, 14px); box-shadow: var(--shadow-card);
  overflow: hidden;
}
#sitting-head {
  display: flex; align-items: center; gap: 10px;
  padding: 14px 16px 10px; border-bottom: 1px solid var(--border); flex-shrink: 0;
}
#sitting-title { flex: 1; font-size: 15px; font-weight: 700; color: var(--text-heading); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
#sitting-body { overflow-y: auto; padding: 14px 16px 18px; }
.si-meta { display: flex; flex-wrap: wrap; gap: 6px; align-items: center; font-size: 12px; color: var(--text-faint); }
.si-meta i { font-style: normal; opacity: 0.6; }
.si-result { font-size: 17px; font-weight: 700; color: var(--text-heading); margin: 6px 0 2px; }
.si-open {
  margin: 8px 0 2px; padding: 8px 11px; border-radius: 10px;
  background: var(--highlight-bg); color: var(--highlight-text, #8A6410);
  font-size: 12.5px; line-height: 1.5;
}
.si-tally { font-size: 13px; color: var(--text-muted); font-family: var(--font-mono); margin-top: 8px; }
.si-sub { margin: 14px 0 4px; font-size: 12px; font-weight: 700; letter-spacing: 0.02em; text-transform: uppercase; color: var(--text-faint); }
.si-missed { margin: 0; padding-left: 18px; font-size: 13px; color: var(--text-normal); }
.si-missed li { margin: 3px 0; }
.si-from { margin-left: 8px; font-size: 11.5px; color: var(--text-faint); }
.si-none { margin-top: 12px; font-size: 12px; color: var(--text-faint); line-height: 1.5; }

/* The paper, question by question. */
.si-qs { list-style: none; margin: 12px 0 0; padding: 0; display: flex; flex-direction: column; gap: 8px; }
.si-q {
  display: grid; grid-template-columns: 20px minmax(0, 1fr) 18px; gap: 10px;
  padding: 10px 12px; border-radius: 10px; background: var(--bg-secondary, var(--bg-tertiary));
  border-left: 3px solid transparent;
}
.si-q.si-ok { border-left-color: var(--success, #2f855a); }
.si-q.si-no { border-left-color: var(--danger); }
.si-n { font-size: 11.5px; font-family: var(--font-mono); color: var(--text-faint); padding-top: 2px; }
.si-qbody { min-width: 0; }
.si-qtext { font-size: 13.5px; font-weight: 600; color: var(--text-heading); line-height: 1.45; }
.si-line { display: flex; gap: 8px; margin-top: 4px; font-size: 12.5px; line-height: 1.45; }
.si-k { flex: none; width: 50px; color: var(--text-faint); }
.si-v { min-width: 0; color: var(--text-normal); overflow-wrap: anywhere; }
.si-v.si-blank { color: var(--text-faint); font-style: italic; }
.si-v.si-want { color: var(--success, #2f855a); font-weight: 600; }
.si-mark { font-size: 14px; font-weight: 700; text-align: right; }
.si-q.si-ok .si-mark { color: var(--success, #2f855a); }
.si-q.si-no .si-mark { color: var(--danger); }
.si-actions { display: flex; flex-wrap: wrap; gap: 10px; align-items: center; margin-top: 16px; }

/* Browse-all deck modal — same shell as the share dialog, wider */
#deck-modal-overlay { position: fixed; inset: 0; z-index: 60; display: flex; align-items: center; justify-content: center; background: rgba(20, 24, 38, 0.44); }
#deck-modal-overlay.hidden { display: none; }
#deck-modal-box {
  position: relative; width: min(720px, 92vw); max-height: 84vh; overflow-y: auto;
  background: var(--card-bg); border: 1px solid var(--panel-border);
  border-radius: var(--radius-panel); padding: 26px 26px 22px;
  box-shadow: 0 24px 72px rgba(22, 28, 44, 0.34);
}
#deck-modal-close { position: absolute; top: 14px; right: 14px; }
#deck-modal-title { font-size: 20px; font-weight: 700; letter-spacing: -0.02em; color: var(--text-heading); margin-bottom: 6px; }

/* ---- Study statistics page ---- */
.sd-stats-btn {
  width: 100%; margin-top: 8px; padding: 9px; font-size: 13px; font-weight: 600;
  color: var(--text-muted); background: transparent; border: 1px solid var(--border);
  border-radius: var(--radius-btn, 8px); cursor: pointer;
}
.sd-stats-btn:hover { background: var(--bg-hover); color: var(--text-heading); }
#stats-modal-overlay { position: fixed; inset: 0; z-index: 60; display: flex; align-items: center; justify-content: center; background: rgba(20, 24, 38, 0.44); }
#stats-modal-overlay.hidden { display: none; }
#stats-modal-box {
  position: relative; width: min(860px, 94vw); max-height: 88vh; overflow-y: auto;
  background: var(--card-bg); border: 1px solid var(--panel-border);
  border-radius: var(--radius-panel); padding: 26px 28px 24px;
  box-shadow: 0 24px 72px rgba(22, 28, 44, 0.34);
}
#stats-modal-close { position: absolute; top: 14px; right: 14px; }
#stats-modal-title { font-size: 20px; font-weight: 700; letter-spacing: -0.02em; color: var(--text-heading); margin-bottom: 14px; }
.st-scope { display: flex; align-items: center; gap: 10px; margin-bottom: 18px; }
.st-scope label { font-size: 12px; color: var(--text-faint); text-transform: uppercase; letter-spacing: 0.04em; }
#st-scope-sel {
  flex: 1; max-width: 360px; font-size: 13px; padding: 6px 10px;
  color: var(--text-heading); background: var(--bg-subtle, var(--code-bg));
  border: 1px solid var(--border); border-radius: 8px; cursor: pointer;
}
#st-open-note { flex-shrink: 0; }
.st-crumbs { display: flex; align-items: center; flex-wrap: wrap; gap: 2px; margin-bottom: 18px; }
.st-crumb { background: none; border: none; cursor: pointer; font-size: 12.5px; color: var(--accent, #4a72ff); padding: 2px 4px; border-radius: 5px; }
.st-crumb:hover { background: var(--bg-hover); }
.st-crumb.cur { color: var(--text-heading); font-weight: 600; cursor: default; }
.st-crumb-sep { color: var(--text-faint); font-size: 12px; margin: 0 1px; }
.st-deck-folder .st-deck-name { font-weight: 600; color: var(--text-heading); }
.st-deck-count { color: var(--text-faint); font-weight: 400; font-size: 11px; font-family: var(--font-mono); }
.st-cards { display: grid; grid-template-columns: repeat(5, 1fr); gap: 10px; margin-bottom: 22px; }
.st-card { background: var(--bg-subtle, var(--code-bg)); border: 1px solid var(--border); border-radius: 12px; padding: 12px 14px; display: flex; flex-direction: column; gap: 3px; }
.st-card .st-n { font-size: 22px; font-weight: 750; color: var(--text-heading); letter-spacing: -0.02em; }
.st-card .st-l { font-size: 11px; color: var(--text-faint); text-transform: uppercase; letter-spacing: 0.04em; }
.st-section { margin-bottom: 22px; }
.st-h { font-size: 13px; font-weight: 650; color: var(--text-heading); margin-bottom: 10px; }
.st-h .st-sub { font-weight: 400; color: var(--text-faint); font-size: 12px; }
.st-stack { display: flex; height: 20px; border-radius: 6px; overflow: hidden; gap: 2px; }
.st-seg { min-width: 2px; }
.st-mature { background: #2e9e5b; } .st-young { background: #7fd18e; }
.st-learning { background: #e6923d; } .st-new { background: #4a72ff; }
.st-susp { background: #b8b0a0; } .st-empty { background: var(--border); }
.st-legend { display: flex; flex-wrap: wrap; gap: 14px; margin-top: 10px; font-size: 12px; color: var(--text-muted); }
.st-key { display: inline-flex; align-items: center; gap: 5px; }
.st-key b { color: var(--text-heading); font-weight: 650; }
.st-dot { width: 9px; height: 9px; border-radius: 2px; display: inline-block; }
/* heatmap */
.st-hm-months { display: flex; gap: 3px; margin-bottom: 3px; padding-left: 0; }
.st-hm-month { flex: 1; font-size: 9px; color: var(--text-faint); text-align: left; min-width: 13px; }
.st-hm { display: flex; gap: 3px; }
.st-hm-col { display: flex; flex-direction: column; gap: 3px; flex: 1; }
.st-hm-cell { width: 100%; aspect-ratio: 1; border-radius: 2px; display: block; background: var(--border); }
.st-hm-cell.empty { background: transparent; }
.st-hm-cell.l0 { background: var(--bg-hover, #edeef2); } .st-hm-cell.l1 { background: #a9d5b6; }
.st-hm-cell.l2 { background: #6fc088; } .st-hm-cell.l3 { background: #3fa35f; } .st-hm-cell.l4 { background: #22733f; }
.st-hm-key { display: flex; align-items: center; gap: 4px; justify-content: flex-end; margin-top: 8px; font-size: 11px; color: var(--text-faint); }
.st-hm-key .st-hm-cell { width: 11px; height: 11px; aspect-ratio: auto; }
/* bar charts */
.st-two { display: grid; grid-template-columns: 1fr 1fr; gap: 22px; }
.st-bars { display: flex; align-items: flex-end; gap: 2px; height: 48px; }
.st-bar { flex: 1; min-width: 2px; border-radius: 2px 2px 0 0; background: var(--accent, #4a72ff); opacity: 0.85; }
.st-b-rev { background: #4a72ff; } .st-b-due { background: #7fa0d8; } .st-b-today { background: #2e9e5b; }
.st-ret-row { display: flex; justify-content: space-between; font-size: 13px; color: var(--text-muted); padding: 4px 0; }
.st-ret-row b { color: var(--text-heading); }
.st-ret-hint { font-size: 11px; color: var(--text-faint); margin-top: 4px; }

/* Sittings: one grid so the dates, the kinds and the scores line up down the
   column — which is what turns a list of numbers into a trend you can see. */
.st-sits { display: flex; flex-direction: column; gap: 1px; margin-top: 6px; }
.st-sit-row {
  display: grid; grid-template-columns: 48px 62px 1fr auto 56px;
  align-items: center; gap: 8px; padding: 4px 4px; border-radius: 5px;
  font-size: 12.5px; color: var(--text-muted);
}
.st-sit-row:hover { background: var(--bg-hover); }
.st-sit-when { font-family: var(--font-mono); font-size: 11px; color: var(--text-faint); }
.st-sit-kind {
  font-size: 10.5px; font-weight: 650; text-transform: uppercase; letter-spacing: 0.03em;
  padding: 1px 6px; border-radius: 4px; text-align: center;
  background: var(--bg-tertiary); color: var(--text-muted);
}
.st-sit-exam { background: color-mix(in srgb, var(--accent) 16%, transparent); color: var(--accent); }
.st-sit-title { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.st-sit-score { font-family: var(--font-mono); font-size: 12px; color: var(--text-normal); white-space: nowrap; }
.st-sit-row.st-sit-exam .st-sit-score,
.st-sit-row:has(.st-sit-exam) .st-sit-score { font-weight: 650; color: var(--text-heading); }
.st-sit-extra { font-family: var(--font-mono); font-size: 10.5px; color: var(--text-faint); text-align: right; }
.st-delta { margin-left: 6px; font-weight: 700; font-size: 11px; }
.st-delta.up { color: var(--success, #2f855a); }
.st-delta.down { color: var(--danger); }
/* per-deck */
.st-decks { display: flex; flex-direction: column; gap: 1px; max-height: 300px; overflow-y: auto; }
.st-deck { display: grid; grid-template-columns: 1fr 90px auto; align-items: center; gap: 12px; background: none; border: none; cursor: pointer; padding: 6px 6px; border-radius: 6px; text-align: left; }
.st-deck:hover { background: var(--bg-hover); }
.st-deck-name { font-size: 13px; color: var(--text-heading); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.st-deck-bar { height: 6px; background: var(--border); border-radius: 3px; overflow: hidden; }
.st-deck-bar i { display: block; height: 100%; background: #2e9e5b; }
.st-deck-nums { font-size: 12px; color: var(--text-faint); font-family: var(--font-mono); white-space: nowrap; }
.st-deck-nums b { color: #2e9e5b; }
@media (max-width: 620px) { .st-cards { grid-template-columns: repeat(2, 1fr); } .st-two { grid-template-columns: 1fr; } }
#deck-modal-tree .deck-row { font-size: 14px; padding-top: 7px; padding-bottom: 7px; }
.deck-badge {
  font-size: 10.5px; font-weight: 700; font-family: var(--font-mono);
  border-radius: 9px; padding: 1px 7px; flex-shrink: 0;
}
.deck-badge.due { background: var(--chip-bg); color: var(--chip-text); }
.deck-badge.fresh { background: var(--tag-bg); color: var(--tag-text); }
.deck-deadline {
  font-size: 10px; font-weight: 700; font-family: var(--font-mono);
  border-radius: 6px; padding: 1.5px 6px; flex-shrink: 0;
  background: var(--bg-tertiary); color: var(--text-muted);
}
.deck-deadline.risk { background: var(--highlight-bg); color: var(--highlight-text); }
.deck-deadline.past { background: color-mix(in srgb, var(--danger) 15%, transparent); color: var(--danger); }
.deck-actions { display: none; gap: 2px; flex-shrink: 0; }
.deck-row:hover .deck-actions { display: flex; }
#study-decks .panel-empty code { font-family: var(--font-mono); background: var(--code-bg); color: var(--code-text); border-radius: 4px; padding: 0 4px; }

/* Study session view */
#study-view { display: none; flex: 1; flex-direction: column; min-height: 0; overflow: hidden; }
#study-view.visible { display: flex; }
#study-head {
  display: flex; align-items: center; gap: 10px;
  padding: 14px 22px 8px; flex-shrink: 0;
}
#study-deck-title { font-size: 14px; font-weight: 650; color: var(--text-heading); flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
#study-progress { font-size: 12px; color: var(--text-faint); font-family: var(--font-mono); }
.study-pull {
  font-size: 12px; font-weight: 550; color: var(--text-muted);
  background: transparent; border: 1px solid var(--border);
  border-radius: var(--radius-btn, 7px); padding: 3px 10px; cursor: pointer;
  white-space: nowrap; transition: background .12s, color .12s, border-color .12s;
}
.study-pull:hover { background: var(--bg-hover); color: var(--text-heading); border-color: var(--text-faint); }
/* Suspend/bury belong to SRS cards only; renderCard() hides them otherwise and
   needs a rule to do it with, or they linger through cram and the done screen
   as two buttons whose handler silently declines. */
.study-pull.hidden { display: none; }
/* The ··· that holds Bury and Suspend: the same chip as its neighbours, sized
   so three dots do not read as a wide empty button. */
#study-more { padding: 3px 9px; letter-spacing: 0.08em; line-height: 1.15; }
/* Back with nothing behind it. Shown-but-dead rather than hidden, because a
   control that appears and vanishes as you move through a deck is harder to
   find than one that is simply not available yet. */
.study-pull:disabled { opacity: 0.4; cursor: default; }
.study-pull:disabled:hover { background: transparent; color: var(--text-muted); border-color: var(--border); }
/* A flagged card wears its flag: the button IS the indicator, so there is no
   second piece of state to keep in step with it.

   THE FALLBACK IS LOAD-BEARING. Some themes define --highlight-bg and leave
   --highlight-text unset, and an undefined custom property makes the whole
   declaration invalid at computed-value time — so `color` silently inherits
   and the marker below comes out transparent. Measured on the shipped theme,
   not guessed at. The literal is the :root default. */
.study-pull.on {
  background: color-mix(in srgb, var(--highlight-bg) 70%, transparent);
  color: var(--highlight-text, #8A6410);
  border-color: color-mix(in srgb, var(--highlight-text, #8A6410) 35%, transparent);
}
.study-pull.on:hover { background: var(--highlight-bg); color: var(--highlight-text, #8A6410); }
/* Progress, as a bar. Two pixels of it, under the head, full width. */
#study-bar { height: 2px; background: var(--border); flex-shrink: 0; margin: 0 22px 2px; border-radius: 2px; overflow: hidden; }
#study-bar.hidden { display: none; }
#study-bar-fill { display: block; height: 100%; width: 0; background: var(--accent); transition: width .22s ease; }
#study-warnings { padding: 0 22px; flex-shrink: 0; }
.study-warning {
  font-size: 12.5px; line-height: 1.5; color: var(--highlight-text);
  background: var(--highlight-bg); border-radius: var(--radius-card);
  padding: 8px 12px; margin-bottom: 6px;
}
#study-card {
  flex: 1; min-height: 0; overflow-y: auto;
  margin: 10px auto; width: min(640px, calc(100% - 44px));
  background: var(--card-bg); border: 1px solid var(--border);
  border-radius: var(--radius-panel); box-shadow: var(--shadow-card);
  padding: 28px 30px;
  font-size: 16px;
}
#study-front p, #study-back p { margin: 0 0 8px; }
#study-back-wrap hr { border: none; border-top: 1px solid var(--border); margin: 14px 0; }
#study-done { flex: 1; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 8px; }
#study-done.hidden { display: none; }
.study-done-title { font-size: 17px; font-weight: 700; color: var(--text-heading); }
.study-done-sub { font-size: 13px; color: var(--text-muted); font-family: var(--font-mono); }
/* The one number worth reading on the finished screen, sized to be read first
   and the four-count tally kept beneath it as the detail. */
.study-done-recall { font-size: 14px; font-weight: 650; color: var(--text-normal); }
.study-done-trend { font-size: 13px; font-weight: 600; }
.study-done-trend.up { color: var(--success, #2f855a); }
.study-done-trend.down { color: var(--danger); }
.study-done-trend.flat { color: var(--text-muted); }
.study-done-flagged { font-size: 13px; color: var(--text-muted); margin-top: 6px; text-align: center; }
.study-done-kept { font-size: 11.5px; color: var(--text-faint); margin-top: 4px; }
#study-actions { flex-shrink: 0; display: flex; justify-content: center; flex-wrap: wrap; padding: 6px 22px 4px; }
#study-grades button { min-width: 68px; }
#study-reveal { padding: 9px 26px; border-radius: var(--radius-active); font-size: 13.5px; font-weight: 650; background: var(--accent); color: #fff; box-shadow: var(--shadow-active); }
#study-reveal:hover { background: var(--accent-strong); }
#study-grades, #study-cram-actions { display: flex; gap: 8px; flex-wrap: wrap; justify-content: center; }
#study-grades.hidden, #study-cram-actions.hidden, #study-card.hidden, #study-reveal.hidden,
#study-back-wrap.hidden, #study-warnings.hidden { display: none; }
#study-grades button, #study-cram-actions button {
  display: flex; flex-direction: column; align-items: center; gap: 1px;
  min-width: 76px; padding: 7px 14px; border-radius: var(--radius-active);
  font-size: 13px; font-weight: 650; background: var(--bg-tertiary); color: var(--text-normal);
  transition: filter 0.1s, transform 0.1s;
}
#study-grades button:hover, #study-cram-actions button:hover { filter: brightness(0.95); transform: translateY(-1px); }
#study-grades button span { font-size: 10.5px; font-weight: 600; font-family: var(--font-mono); color: var(--text-faint); }
#study-grades .g-again { background: color-mix(in srgb, var(--danger) 14%, transparent); color: var(--danger); }
#study-grades .g-again span { color: color-mix(in srgb, var(--danger) 70%, var(--text-faint)); }
#study-grades .g-easy, #study-cram-actions .accent { background: var(--accent); color: #fff; }
#study-grades .g-easy span { color: rgba(255, 255, 255, 0.75); }
#study-foot {
  display: flex; align-items: center; justify-content: space-between; gap: 10px;
  padding: 4px 22px 12px; flex-shrink: 0;
}
#study-source { font-size: 11.5px; color: var(--text-faint); font-family: var(--font-mono); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
#study-source:hover { color: var(--link); }
#study-hint { font-size: 11px; color: var(--text-faint); white-space: nowrap; }

/* ============ Import dialog ============ */
#import-overlay {
  position: fixed; inset: 0;
  background: rgba(22, 28, 44, 0.28);
  backdrop-filter: blur(5px);
  -webkit-backdrop-filter: blur(5px);
  display: flex; align-items: center; justify-content: center;
  z-index: 110;
}
#import-overlay.hidden { display: none; }
#import-box {
  width: min(480px, 90vw);
  background: var(--card-bg);
  border: 1px solid var(--panel-border);
  border-radius: var(--radius-panel);
  padding: 22px;
  box-shadow: 0 24px 64px rgba(22, 28, 44, 0.28);
}
.import-options { display: flex; flex-direction: column; gap: 9px; margin-top: 4px; }
.import-option {
  display: flex;
  align-items: center;
  gap: 14px;
  text-align: left;
  padding: 13px 16px;
  border: 1px solid var(--border);
  border-radius: var(--radius-card);
  background: var(--bg-secondary);
  transition: border-color 0.12s, transform 0.12s, box-shadow 0.12s;
}
.import-option:hover {
  border-color: var(--accent);
  transform: translateY(-1px);
  box-shadow: var(--shadow-card);
}
.import-option:disabled { opacity: 0.55; cursor: default; transform: none; }
.io-icon { flex-shrink: 0; color: var(--accent); display: flex; }
.io-icon svg { width: 26px; height: 26px; }
.io-name { display: block; font-weight: 650; font-size: 14px; color: var(--text-heading); }
.io-desc { display: block; font-size: 12px; color: var(--text-muted); margin-top: 2px; }
#import-status {
  min-height: 20px;
  margin-top: 12px;
  font-size: 12.5px;
  color: var(--text-muted);
  font-family: var(--font-mono);
}

/* ============ Autocomplete ============ */
#autocomplete {
  position: fixed;
  z-index: 120;
  background: var(--card-bg);
  border: 1px solid var(--panel-border);
  border-radius: var(--radius-card);
  min-width: 230px;
  max-width: 340px;
  max-height: 260px;
  overflow-y: auto;
  box-shadow: 0 16px 40px rgba(22, 28, 44, 0.18);
  padding: 5px;
}
#autocomplete.hidden { display: none; }
.ac-item {
  padding: 7px 11px;
  border-radius: 7px;
  cursor: pointer;
  font-size: 13.5px;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.ac-item .ac-folder { color: var(--text-faint); font-size: 11.5px; margin-left: 6px; }
.ac-item.selected { background: var(--bg-active); color: #fff; }
.ac-item.selected .ac-folder { color: rgba(255, 255, 255, 0.7); }

/* ============ Slash menu ============ */
#slash-menu {
  position: fixed;
  z-index: 125;
  background: var(--card-bg);
  border: 1px solid var(--panel-border);
  border-radius: var(--radius-card);
  min-width: 260px;
  max-height: 320px;
  overflow-y: auto;
  box-shadow: 0 16px 40px rgba(22, 28, 44, 0.18);
  padding: 5px;
}
#slash-menu.hidden { display: none; }
.slash-item {
  display: flex;
  align-items: center;
  gap: 11px;
  padding: 7px 10px;
  border-radius: var(--radius-active);
  cursor: pointer;
}
.slash-item .si-icon svg { width: 15px; height: 15px; }
.slash-item .si-icon {
  width: 28px; height: 28px;
  display: flex; align-items: center; justify-content: center;
  background: var(--bg-secondary);
  border: 1px solid var(--border);
  border-radius: 8px;
  font-size: 12px;
  font-weight: 700;
  flex-shrink: 0;
}
.slash-item .si-name { font-size: 13.5px; font-weight: 550; }
.slash-item .si-desc { font-size: 11.5px; color: var(--text-faint); }
.slash-item.selected { background: var(--bg-active); color: #fff; }
.slash-item.selected .si-desc { color: rgba(255, 255, 255, 0.7); }
.slash-item.selected .si-icon { background: rgba(255, 255, 255, 0.16); border-color: transparent; color: #fff; }

/* ============ Context menu ============ */
#context-menu, .cm-submenu {
  position: fixed;
  z-index: 130;
  background: var(--card-bg);
  border: 1px solid var(--panel-border);
  border-radius: var(--radius-card);
  padding: 5px;
  min-width: 180px;
  box-shadow: 0 16px 40px rgba(22, 28, 44, 0.18);
}
.cm-submenu { z-index: 131; min-width: 160px; }
#context-menu.hidden { display: none; }
.cm-item {
  padding: 7px 13px;
  border-radius: 7px;
  cursor: pointer;
  font-size: 13.5px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 14px;
  white-space: nowrap;
}
.cm-item:hover, .cm-item.has-sub:hover { background: var(--bg-hover); }
.cm-item.danger { color: var(--danger); }
.cm-arrow { color: var(--text-faint); font-size: 11px; }
.cm-label { display: inline-flex; align-items: center; }
.cm-swatch { display: inline-block; width: 11px; height: 11px; border-radius: 50%; margin-right: 9px; flex-shrink: 0; }
.cm-sep { height: 1px; background: var(--border); margin: 4px 6px; }


/* ================= 32-feature expansion ================= */

/* ---- side by side (split-embeds.js) ---- */
#main-body { flex: 1; display: flex; min-height: 0; }
#main-views { flex: 1; display: flex; flex-direction: column; min-width: 0; }
#split-divider {
  width: 5px; cursor: col-resize; flex-shrink: 0;
  background: transparent; border-left: 1px solid var(--border);
  transition: background 0.12s;
}
#split-divider:hover { background: color-mix(in srgb, var(--accent) 25%, transparent); }
#split-divider.hidden, #split-pane.hidden { display: none; }
#split-pane { position: relative; width: 42%; min-width: 220px; min-height: 0; display: flex; flex-direction: column; flex-shrink: 0; }
/* The pane FIRST: the editor went to the note on the other side, and the two
   change places in the order so that on screen neither note moves. */
body.split-flip #split-pane { order: -2; }
body.split-flip #split-divider { order: -1; }
/* Stacked (split-down): #main-body becomes a column; the divider resizes height. */
body.split-down #main-body { flex-direction: column; }
/* Column flex children must be allowed to shrink below content height, or the
   editor keeps its full height and shoves the split pane off-screen. */
body.split-down #main-views { min-height: 0; }
body.split-down #split-divider {
  width: auto; height: 5px; cursor: row-resize;
  border-left: none; border-top: 1px solid var(--border);
}
body.split-down #split-pane { width: auto; height: 42%; min-width: 0; min-height: 140px; }
/* A phone or a very narrow window has no room for two columns: stack them,
   whatever the setting says. The divider reads the layout, not the setting. */
@media (max-width: 760px) {
  #main-body:has(#split-pane:not(.hidden)) { flex-direction: column; }
  #main-body:has(#split-pane:not(.hidden)) #main-views { min-height: 0; }
  #split-divider { width: auto; height: 5px; cursor: row-resize; border-left: none; border-top: 1px solid var(--border); }
  #split-pane { width: auto !important; height: 45%; min-width: 0; min-height: 140px; }
  #split-orient { display: none; }
}

/* The pane's controls sit in the top padding, above the crumb line, so they
   never cover a word at rest; scrolled text passes under a frosted chip. */
#split-tools {
  position: absolute; top: 6px; right: 10px; z-index: 3;
  display: flex; align-items: center; gap: 2px; padding: 2px;
  border-radius: 9px;
  background: color-mix(in srgb, var(--bg-primary) 80%, transparent);
  backdrop-filter: blur(8px);
}
#split-tools .icon-btn { width: 26px; height: 26px; color: var(--text-faint); }
#split-tools .icon-btn:hover { color: var(--text-normal); }
.split-edit-btn {
  height: 24px; padding: 0 10px; margin-right: 2px; border-radius: 7px;
  border: 1px solid var(--border); background: transparent;
  font: inherit; font-size: 11.5px; font-weight: 600; color: var(--text-normal); cursor: pointer;
}
.split-edit-btn:hover { border-color: var(--accent); color: var(--accent); }
.split-edit-btn[hidden] { display: none; }
#split-scroll { flex: 1; min-height: 0; overflow-y: auto; }

/* THE NOTE COLUMN'S OWN MEASURE AND RHYTHM — #editor-container, #doc-crumb and
   #editor-container #note-title, restated for the pane. A note reads the same
   on either side, and when the editor changes sides nothing jumps. */
#split-doc { max-width: var(--editor-max-width, 780px); margin: 0 auto; padding: 28px 36px 140px; min-height: 100%; }
#split-crumb { display: flex; align-items: center; min-height: 18px; margin: 10px 0 8px; min-width: 0; }
#split-switch {
  display: inline-flex; align-items: center; gap: 5px; min-width: 0; max-width: 100%;
  padding: 0; border: 0; background: none; cursor: pointer;
  font-size: 10.5px; font-weight: 650; letter-spacing: 0.09em; text-transform: uppercase;
  color: var(--text-faint);
}
#split-switch:hover { color: var(--text-normal); }
#split-path { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0; }
#split-switch svg { flex: none; opacity: .7; }
/* Two ids, like #editor-container #note-title, so a surface's own title rule
   reaches both titles or neither. */
#split-doc #split-title {
  font-family: "Iowan Old Style", "Literata", "Palatino Linotype", Georgia, serif;
  font-size: 42px; line-height: 1.12; font-weight: 700; letter-spacing: -0.012em;
  color: var(--text-heading); text-wrap: balance;
  margin: 0 0 20px;
}
/* A narrow pane — a laptop split in two with both rails open — gets a smaller
   title and margin rather than a word broken in half. Measured on the pane
   itself, not the window. */
#split-pane { container-type: inline-size; }
@container (max-width: 460px) {
  #split-doc { padding: 22px 20px 120px; }
  #split-doc #split-title { font-size: 30px; }
}
#split-content { padding-bottom: 40px; }
#split-content a { cursor: pointer; }
/* Writable by clicking: say so with the caret the click will produce. */
#split-pane.can-write #split-content { cursor: text; }
#split-pane.can-write #split-content :is(a, input, button, summary, .embed, .tn-due) { cursor: pointer; }
.split-locked { color: var(--text-faint); font-size: 14px; }

/* A document fills the pane: a crumb line with its name, then the viewer. */
#split-pane.doc-mode #split-scroll { overflow: hidden; display: flex; flex-direction: column; }
#split-pane.doc-mode #split-doc { max-width: none; width: 100%; padding: 10px 14px 12px; display: flex; flex-direction: column; flex: 1; min-height: 0; }
#split-pane.doc-mode #split-crumb { margin: 2px 128px 8px 0; }
#split-pane.doc-mode #split-title { display: none; }
#split-pane.doc-mode #split-content { flex: 1; min-height: 0; overflow: auto; padding-bottom: 0; }
.split-pdf { display: block; width: 100%; height: 100%; border: 0; border-radius: 8px; background: var(--bg-secondary); }
.split-sheets:empty { display: none; }
.split-sheets { display: flex; gap: 4px; flex-wrap: wrap; margin-bottom: 8px; }

/* The header button reads as on while there is a side. */
#hdr-side[aria-pressed="true"] { color: var(--accent); }

/* ---- find & replace ---- */
.find-replace-group { display: none; align-items: center; gap: 6px; margin-left: 10px; }
body[data-mode="edit"] .find-replace-group { display: flex; }
#replace-input { max-width: 200px; }

/* ---- base view ---- */
#base-view { display: none; flex: 1; flex-direction: column; overflow: hidden; }
#base-view.visible { display: flex; }
#base-toolbar { display: flex; gap: 10px; align-items: center; padding: 10px 16px; border-bottom: 1px solid var(--border); flex-shrink: 0; }
#base-toolbar input { max-width: 420px; }
#base-count { font-size: 12px; color: var(--text-faint); font-family: var(--font-mono); white-space: nowrap; }
#base-table-wrap { flex: 1; overflow: auto; padding: 14px 16px 40px; }
/* Flat like the database view: rows divide with hairlines, nothing boxes it. */
.base-table { border-collapse: collapse; width: 100%; font-size: 14px; }
.base-table th { text-align: left; padding: 8px 14px; font-size: 10.5px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.12em; color: var(--text-faint); cursor: pointer; user-select: none; white-space: nowrap; border-bottom: 1px solid var(--border); }
.base-table th.sorted { color: var(--accent-strong); }
.base-table td { padding: 11px 14px; border-bottom: 1px solid color-mix(in srgb, var(--border) 62%, transparent); }
.base-table tr:hover td { background: var(--bg-hover); cursor: pointer; }
.base-table .bt-name { font-weight: 600; color: var(--text-heading); }
.base-table tr:hover .bt-name { color: var(--accent); }
.base-table .bt-dim { color: var(--text-faint); font-size: 12px; }

/* ---- folding ---- */
.tn-hidden { display: none !important; }
.markdown-body h1.tn-folded::after, .markdown-body h2.tn-folded::after, .markdown-body h3.tn-folded::after,
.markdown-body h4.tn-folded::after, .markdown-body h5.tn-folded::after, .markdown-body h6.tn-folded::after {
  content: '…'; color: var(--text-faint); margin-left: 10px; font-size: 0.7em; vertical-align: middle;
  background: var(--bg-tertiary); border-radius: 6px; padding: 0 8px;
}

/* ---- embeds ---- */
.markdown-body .embed[data-embed] {
  border: 1px solid var(--border); border-left: 3px solid var(--accent);
  border-radius: var(--radius-card); margin: 0.8em 0; background: var(--card-bg);
  box-shadow: var(--shadow-card); overflow: hidden;
}
.embed[data-embed] .embed-head {
  display: flex; align-items: center; gap: 7px;
  font-size: 11.5px; font-weight: 700; letter-spacing: 0.05em; text-transform: uppercase;
  color: var(--text-faint); padding: 7px 14px 5px; cursor: pointer;
}
.embed[data-embed] .embed-head:hover { color: var(--link); }
/* The head's icon at text size: without a size an inline SVG grows to the
   width of the box — every note embed in edit view showed a page-sized icon. */
.embed[data-embed] .embed-head svg { width: 15px; height: 15px; flex: none; }
.embed[data-embed] .embed-inner { padding: 0 16px 10px; max-height: 420px; overflow: auto; }
.embed[data-embed] .embed-inner > h1:first-child { margin-top: 0.2em; }

/* ---- math & mermaid ---- */
.tn-math-block { display: block; text-align: center; margin: 0.8em 0; overflow-x: auto; }
/* Calendar popover (ribbon daily-notes button) */
.cal-popover {
  position: fixed; z-index: 200; width: 236px;
  background: var(--panel-bg); backdrop-filter: blur(var(--panel-blur)); -webkit-backdrop-filter: blur(var(--panel-blur));
  border: 1px solid var(--panel-border); border-radius: var(--radius-card); box-shadow: var(--shadow-card);
  padding: 12px; color: var(--text-normal);
}
.cal-head { display: flex; align-items: center; justify-content: space-between; margin-bottom: 8px; }
.cal-title { font-size: 13px; font-weight: 700; color: var(--text-heading); }
.cal-nav { border: none; background: transparent; color: var(--text-muted); cursor: pointer; font-size: 17px; line-height: 1; width: 24px; height: 24px; border-radius: 6px; }
.cal-nav:hover { background: var(--bg-hover); color: var(--text-normal); }
/* minmax(0, …), not a bare 1fr. `1fr` means `minmax(auto, 1fr)`, so a column
   cannot shrink below its content's min-content width — and a day cell holds
   "30" at 12px. Narrow the rail far enough and the seven columns stop fitting,
   the grid overflows its block, and the last day of the week is clipped
   instead of the whole row getting smaller. .dbl-cal-grid below already spells
   it this way; this one was the copy that did not. */
.cal-grid { display: grid; grid-template-columns: repeat(7, minmax(0, 1fr)); gap: 2px; }
.cal-wd { text-align: center; font-size: 10px; font-weight: 700; color: var(--text-faint); padding: 2px 0; }
.cal-days { margin-top: 2px; }
.cal-day { position: relative; aspect-ratio: 1; border: none; background: transparent; color: var(--text-muted); cursor: pointer; font-size: 12px; border-radius: 7px; display: flex; align-items: center; justify-content: center; }
.cal-day.empty { pointer-events: none; }
.cal-day:not(.empty):hover { background: var(--bg-hover); color: var(--text-normal); }
.cal-day.has-note { color: var(--text-normal); font-weight: 600; }
.cal-day.has-note::after { content: ''; position: absolute; bottom: 3px; width: 4px; height: 4px; border-radius: 50%; background: var(--accent); }
.cal-day.today { box-shadow: inset 0 0 0 1.5px var(--accent); color: var(--accent-strong); }
.cal-today { margin-top: 10px; width: 100%; padding: 6px; border: 1px solid var(--panel-border); background: var(--bg-secondary); color: var(--text-normal); border-radius: 8px; font-size: 12px; font-weight: 600; cursor: pointer; }
.cal-today:hover { border-color: var(--accent); color: var(--accent-strong); }

.tn-mermaid { text-align: center; margin: 0.9em 0; background: var(--card-bg); border: 1px solid var(--border); border-radius: var(--radius-card); padding: 14px; overflow-x: auto; }
.tn-mermaid svg { max-width: 100%; }

/* ```tasks aggregation block */
.tn-tasks { margin: 0.9em 0; background: var(--card-bg); border: 1px solid var(--border); border-radius: var(--radius-card); padding: 12px 14px; }
.tn-tasks-head { font-size: 11px; font-weight: 700; letter-spacing: 0.06em; text-transform: uppercase; color: var(--text-faint); margin-bottom: 8px; }
.tn-tasks-empty { color: var(--text-faint); font-style: italic; font-size: 13px; }
/* ```dataview live dashboards */
.tn-dataview { margin: 0.9em 0; }
.tn-dv-head { font-size: 11px; font-weight: 700; letter-spacing: 0.06em; text-transform: uppercase; color: var(--text-faint); margin-bottom: 8px; }
.tn-dv-list { display: flex; flex-direction: column; gap: 1px; }
.tn-dv-item { padding: 5px 8px; border-radius: 6px; cursor: pointer; color: var(--link); font-size: 14px; }
.tn-dv-item:hover { background: var(--bg-hover); }
.tn-dv-table .tn-dv-link { color: var(--link); font-weight: 600; cursor: pointer; text-decoration: none; }
.tn-dv-table .tn-dv-link:hover { text-decoration: underline; }
.tn-dv-table td:first-child { cursor: pointer; }
.tn-tasks-group { margin-bottom: 10px; }
.tn-tasks-group:last-child { margin-bottom: 0; }
.tn-tasks-note { font-size: 12px; font-weight: 600; color: var(--accent); cursor: pointer; margin-bottom: 3px; }
.tn-tasks-note:hover { text-decoration: underline; }
.tn-task { display: flex; align-items: flex-start; gap: 8px; padding: 2px 0 2px 10px; cursor: pointer; font-size: 14px; color: var(--text-normal); border-radius: 5px; }
.tn-task:hover { background: var(--bg-hover); }
/* The box is a CONTROL — it checks the task off where it lives (the text
   still opens the note). Its pseudo-element pads the hit area: a 14px square
   is chart-dot territory, not something to aim at. */
.tn-task-box { flex-shrink: 0; width: 15px; height: 15px; margin-top: 2px; border: 1.5px solid var(--text-faint); border-radius: 5px; position: relative; }
/* the oversized hit area */
.tn-task-box::before { content: ''; position: absolute; inset: -8px; }
.tn-task-box:hover { border-color: var(--accent); box-shadow: 0 0 0 2px var(--chip-bg); }
/* the same tick every checkbox in the app draws */
.tn-task.done .tn-task-box::after {
  content: ''; position: absolute; left: 4.2px; top: 1.4px; width: 4px; height: 8px;
  border: solid var(--bg-primary); border-width: 0 2px 2px 0; transform: rotate(45deg);
}
.tn-task.done .tn-task-box { background: var(--accent); border-color: var(--accent); }
.tn-task.done .tn-task-text { color: var(--text-faint); text-decoration: line-through; }

/* ============================ Charts ============================
   One engine draws the ```chart block and a database's Chart layout, so the
   look is defined once, here.

   The series palette is FIXED and theme-independent: a series is identified by
   its color, and identity must not shift when the reader changes theme (or
   when a filter changes how many series are on screen — slot order never
   cycles). Both columns are validated against the app's card surfaces for the
   lightness band, chroma floor, colorblind separation (protan/deutan ΔE) and
   contrast; the dark steps are chosen for the dark surface, not flipped from
   the light ones. Three light-mode hues sit under 3:1 on white, which is legal
   only with relief — every chart here ships direct labels, a legend and the
   source table right beside it, so no value is ever color-only. */
:root {
  --chart-1: #3987e5; --chart-2: #d95926; --chart-3: #199e70; --chart-4: #c98500;
  --chart-5: #d55181; --chart-6: #008300; --chart-7: #9085e9; --chart-8: #e66767;
  --chart-grid: color-mix(in srgb, var(--text-faint) 26%, transparent);
  --chart-surface: var(--card-bg);
}
body.theme-light {
  --chart-1: #2a78d6; --chart-2: #eb6834; --chart-3: #1baf7a; --chart-4: #eda100;
  --chart-5: #e87ba4; --chart-6: #008300; --chart-7: #4a3aa7; --chart-8: #e34948;
}

.tn-chart { margin: 0.9em 0; }
/* Exports bake ```tasks / ```dataview fences into this quiet stub — a live
   query has no vault to run over in a standalone file. (Shares style their
   own copy in share.html.) */
.live-stub { border: 1px dashed var(--border); border-radius: 10px; color: var(--text-faint);
  font-size: 13.5px; font-style: italic; padding: 12px 16px; margin: 1.1em 0; }
/* The chart's source table, stepped off the page ("Hide table" on the chart
   toolbar). Still in the note, still feeding the chart — just not shown. */
.markdown-body table.tn-chart-src-hidden { display: none; }
.ch-body { position: relative; }
.ch-svg { width: 100%; height: auto; display: block; overflow: visible; }
/* Text wears TEXT tokens, never the series color — a light hue that reads fine
   as a bar is illegible as a word. */
.ch-svg text { font-family: var(--font-ui); }
.ch-title { font-size: 13px; font-weight: 650; fill: var(--text-heading); }
.ch-axis { font-size: 11px; fill: var(--text-faint); }
.ch-legend { font-size: 11.5px; fill: var(--text-muted); }
.ch-value { font-size: 10.5px; font-weight: 600; fill: var(--text-muted); }
.ch-hero { font-size: 26px; font-weight: 650; fill: var(--text-heading); font-variant-numeric: tabular-nums; }
.ch-empty { font-size: 13px; fill: var(--text-faint); }
/* Recessive chrome: hairline, solid, one step off the surface. */
.ch-grid { stroke: var(--chart-grid); stroke-width: 1; }
.ch-zero { stroke: var(--text-faint); stroke-width: 1; opacity: 0.5; }
.ch-line { fill: none; stroke-width: 2; stroke-linejoin: round; stroke-linecap: round; }
/* The ring and the gap are surface-colored: white does the separating, never a
   border drawn around the mark. */
.ch-dot { stroke: var(--chart-surface); stroke-width: 2; }
.ch-slice { stroke: var(--chart-surface); stroke-width: 2; }
.ch-bar, .ch-dot, .ch-slice { transition: opacity 0.1s; }
.tn-chart:hover .ch-slice:hover { opacity: 0.82; }
/* Invisible hover targets, larger than the marks they stand in for — a dot is
   ~3px on screen once the chart scales down, which is not something a person
   can aim at. They sit UNDER the visible marks and carry the tooltip data. */
.ch-hit { fill: transparent; }
/* Marks are painted ON TOP of their oversized hit targets, and SVG hit-testing
   takes the topmost painted element — so without this, hovering the bar ink
   itself (the natural gesture) missed the hit target and killed the tooltip.
   Slices keep their pointer: they ARE their own hit target. */
.ch-bar, .ch-dot, .ch-line, .ch-svg text { pointer-events: none; }
.ch-hit:hover + .ch-bar, .ch-hit:hover + .ch-dot { opacity: 0.82; }

.ch-note { font-size: 13px; color: var(--text-faint); padding: 10px 2px; font-style: italic; }
.ch-bar-ui { display: flex; align-items: center; gap: 4px; flex-wrap: wrap; margin-bottom: 6px; }
.ch-space { flex: 1; }
.ch-type, .ch-pick {
  font-family: var(--font-ui); font-size: 11.5px; cursor: pointer;
  padding: 3px 9px; border-radius: 999px; border: 1px solid var(--border);
  background: transparent; color: var(--text-muted);
}
.ch-type:hover, .ch-pick:hover { color: var(--text-heading); border-color: var(--accent); }
.ch-type.is-on { background: var(--chip-bg); color: var(--chip-text); border-color: transparent; font-weight: 600; }
.ch-pick { border-style: dashed; }

/* Hover tooltip — an HTML/SVG chart is interactive by default. */
.ch-tip {
  position: fixed; z-index: 120; display: none; pointer-events: none;
  background: var(--card-bg); border: 1px solid var(--panel-border);
  border-radius: 9px; box-shadow: var(--shadow-panel);
  padding: 6px 9px; font-family: var(--font-ui); font-size: 12px; line-height: 1.45;
}
.ch-tip-l { display: block; color: var(--text-heading); font-weight: 650; }
.ch-tip-v { display: block; color: var(--text-muted); font-variant-numeric: tabular-nums; }

/* ---- footnotes ---- */
.markdown-body sup.footnote-ref a { font-size: 0.8em; color: var(--accent-strong); text-decoration: none; font-weight: 700; }
.markdown-body ol.footnotes { border-top: 1px solid var(--border); margin-top: 2em; padding-top: 0.8em; font-size: 0.9em; color: var(--text-muted); }

/* ---- saved searches ---- */
#saved-searches { padding: 0 10px; }
#saved-searches:empty { display: none; }
.saved-search {
  display: flex; align-items: center; gap: 7px;
  padding: 5px 9px; border-radius: var(--radius-active);
  font-size: 12.5px; color: var(--text-muted); cursor: pointer;
  font-family: var(--font-mono);
}
.saved-search:hover { background: var(--bg-hover); color: var(--text-heading); }
.saved-search svg { width: 11px; height: 11px; color: var(--accent); flex-shrink: 0; }

/* ---- settings extras ---- */
.settings-hint { font-size: 11.5px; color: var(--text-faint); line-height: 1.5; margin: -4px 0 12px; }
.settings-hint code { font-family: var(--font-mono); background: var(--code-bg); border-radius: 4px; padding: 0 4px; }
.settings-hint kbd { font-family: var(--font-mono); font-size: 11px; }
/* A second heading inside one settings page, for a related but separate group. */
.settings-sub {
  font-size: 11px; font-weight: 700; letter-spacing: .08em; text-transform: uppercase;
  color: var(--text-faint); margin: 22px 0 10px; padding-top: 16px;
  border-top: 1px solid var(--border);
}
.settings-hint.warn { color: var(--danger, #c2410c); }
.hotkey-row { display: flex; align-items: center; justify-content: space-between; gap: 10px; margin-bottom: 8px; font-size: 13px; }

/* A command with no key at all: an invitation, not a dead dash — the list used
   to be a column of "—" and read as something broken. And a hint that is a
   BADGE ("AI") sits beside the key slot instead of inside it, because it is
   not a chord. */
.hotkey-row kbd.unset { opacity: 0.55; font-style: italic; }
.hotkey-row:hover kbd.unset { opacity: 1; }
.hk-badge {
  flex: none; margin-left: auto; font-size: 10.5px; font-weight: 600;
  letter-spacing: 0.04em; padding: 2px 6px; border-radius: 999px;
  background: var(--bg-tertiary); color: var(--text-faint);
}
.hotkey-row .hk-label { color: var(--text-muted); }
.hotkey-row kbd { cursor: pointer; }
.hotkey-row kbd.default { background: var(--bg-tertiary); color: var(--text-faint); }
.hotkey-row kbd.recording { background: var(--danger); color: #fff; }
.ws-row { display: flex; align-items: center; justify-content: space-between; gap: 10px; margin-bottom: 8px; font-size: 13px; }
.plugin-row { display: flex; align-items: center; gap: 9px; margin-bottom: 7px; font-size: 13px; color: var(--text-muted); }
.plugin-row code { font-family: var(--font-mono); font-size: 12px; }

/* ---- graph groups ---- */
/* ---- color groups ---- */
#gs-groups { display: flex; flex-direction: column; gap: 6px; }
.gs-groups-empty { font-size: 11px; color: var(--text-faint); line-height: 1.5; }
.gs-groups-empty code { font-family: var(--font-mono); font-size: 10.5px; color: var(--accent); background: color-mix(in srgb, var(--accent) 12%, transparent); padding: 1px 4px; border-radius: 4px; }
.gs-group-row { position: relative; display: flex; align-items: center; gap: 6px; }
.gs-group-row.hidden-group { opacity: 0.5; }
.gs-swatch {
  width: 16px; height: 16px; border-radius: 5px; flex-shrink: 0; cursor: pointer;
  border: 1px solid rgba(0, 0, 0, 0.15); box-shadow: 0 1px 3px rgba(0, 0, 0, 0.18);
  transition: transform 0.1s;
}
.gs-swatch:hover { transform: scale(1.12); }
.gs-q-input {
  flex: 1; min-width: 0; padding: 5px 8px; font-size: 11.5px;
  font-family: var(--font-mono); border: 1px solid var(--border);
  border-radius: var(--radius-active); background: var(--bg-primary);
  color: var(--text-normal); box-shadow: none !important;
}
.gs-q-input:focus { outline: none; border-color: var(--accent); }
.gs-eye, .gs-remove {
  flex-shrink: 0; display: flex; align-items: center; justify-content: center;
  width: 22px; height: 22px; border-radius: 6px; color: var(--text-faint);
  cursor: pointer; transition: background 0.12s, color 0.12s;
}
.gs-eye:hover { background: var(--bg-hover); color: var(--text-normal); }
.gs-remove { font-size: 17px; line-height: 1; }
.gs-remove:hover { background: color-mix(in srgb, var(--danger) 14%, transparent); color: var(--danger); }
.gs-groups-actions { display: flex; gap: 6px; }
.gs-groups-actions .gs-ghost { background: transparent; border: 1px solid var(--panel-border); }

/* swatch color-picker popover */
.gs-palette {
  position: absolute; top: 22px; left: 0; z-index: 5;
  display: grid; grid-template-columns: repeat(4, 1fr); gap: 5px; padding: 8px;
  background: var(--card-bg); border: 1px solid var(--panel-border);
  border-radius: var(--radius-card); box-shadow: var(--shadow-card);
}
.gs-palette button { width: 18px; height: 18px; border-radius: 5px; cursor: pointer; border: 1px solid rgba(0, 0, 0, 0.12); }
.gs-palette button.active { outline: 2px solid var(--text-normal); outline-offset: 1px; }

/* ---- on-canvas legend ---- */
#graph-legend {
  position: absolute; left: 16px; bottom: 40px; z-index: 4;
  display: flex; flex-wrap: wrap; gap: 6px; max-width: min(60%, 520px);
}
#graph-legend.hidden { display: none; }
.graph-legend-chip {
  display: inline-flex; align-items: center; gap: 7px; cursor: pointer;
  padding: 5px 11px 5px 9px; font-size: 12px; color: var(--text-muted);
  background: var(--panel-bg); backdrop-filter: blur(var(--panel-blur));
  -webkit-backdrop-filter: blur(var(--panel-blur));
  border: 1px solid var(--panel-border); border-radius: 100px;
  transition: color 0.12s, opacity 0.12s;
}
.graph-legend-chip:hover { color: var(--text-normal); }
.graph-legend-chip.off { opacity: 0.45; }
.graph-legend-chip.off .lc-label { text-decoration: line-through; }
.graph-legend-chip .lc-dot { width: 10px; height: 10px; border-radius: 50%; flex-shrink: 0; box-shadow: 0 0 6px currentColor; }
.graph-legend-chip .lc-label { font-family: var(--font-mono); font-size: 11px; max-width: 160px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* ---- canvas groups & web cards ---- */
.cv-group {
  position: absolute;
  border: 1.5px dashed color-mix(in srgb, var(--accent) 45%, transparent);
  border-radius: var(--radius-panel);
  background: color-mix(in srgb, var(--accent) 5%, transparent);
  cursor: grab;
}
.cv-group.selected { border-color: var(--accent); }
.cv-group .cv-group-label {
  position: absolute; top: -24px; left: 8px;
  font-size: 11.5px; font-weight: 700; letter-spacing: 0.06em; text-transform: uppercase;
  color: var(--text-muted); white-space: nowrap;
}
.cv-web-card iframe { width: 100%; height: 100%; border: none; border-radius: 0 0 var(--radius-card) var(--radius-card); pointer-events: none; background: #fff; }

/* ---- slides / present mode ---- */
#slides-overlay {
  position: fixed; inset: 0; z-index: 300;
  background: var(--app-bg);
  display: flex; align-items: center; justify-content: center;
}
#slides-overlay.hidden { display: none; }
#slide {
  max-width: 860px; width: 86vw; max-height: 82vh; overflow-y: auto;
  background: var(--card-bg); border-radius: var(--radius-panel);
  box-shadow: var(--shadow-panel); padding: 48px 56px; font-size: 19px;
}
#slide h1, #slide h2 { letter-spacing: -0.02em; }
#slides-nav { position: fixed; bottom: 22px; right: 28px; font-size: 13px; color: var(--text-faint); font-family: var(--font-mono); }

/* ---- syntax highlighting tokens (theme-aware) ---- */
.hljs-keyword, .hljs-selector-tag, .hljs-literal { color: var(--accent-strong); font-weight: 600; }
.hljs-string, .hljs-attr, .hljs-template-tag { color: color-mix(in srgb, var(--graph-node-tag) 80%, var(--text-normal)); }
.hljs-number, .hljs-symbol { color: var(--highlight-text); }
.hljs-comment, .hljs-quote { color: var(--text-faint); font-style: italic; }
.hljs-title, .hljs-name, .hljs-function .hljs-title { color: var(--link); }
.hljs-built_in, .hljs-type { color: color-mix(in srgb, var(--accent) 70%, var(--text-normal)); }

/* ---- print / PDF export ---- */
@media print {
  body { background: #fff !important; }
  #app { padding: 0; }
  #left-sidebar, #right-sidebar, #tab-bar, #view-header, #toolbar, #find-bar,
  #status-bar, #split-divider, #split-pane, #note-presence { display: none !important; }
  /* Reading Room chrome: the breadcrumb line, floating guide cards, and
     canvas chips never print (the serif title itself does — it IS the note). */
  #doc-crumb, #cv-pick, #cv-zoom, #mode-hint, #reading-bar,
  body > .sidebar-pane[id^="rpane-"] { display: none !important; }
  #main { border: none; box-shadow: none; background: #fff; border-radius: 0; }
  #editor-scroll { overflow: visible; }
}


/* ---- version diff viewer ---- */
#diff-overlay {
  position: fixed; inset: 0; z-index: 140;
  background: rgba(22, 28, 44, 0.28);
  backdrop-filter: blur(5px);
  display: flex; align-items: center; justify-content: center;
}
#diff-overlay.hidden { display: none; }
#diff-box {
  width: min(760px, 92vw);
  background: var(--card-bg);
  border: 1px solid var(--panel-border);
  border-radius: var(--radius-panel);
  padding: 22px;
  box-shadow: 0 24px 64px rgba(22, 28, 44, 0.28);
}
#diff-body {
  max-height: 52vh; overflow-y: auto;
  font-size: 13.5px; line-height: 1.7;
  background: var(--bg-secondary);
  border: 1px solid var(--border);
  border-radius: var(--radius-card);
  padding: 14px 16px;
  white-space: pre-wrap;
  word-break: break-word;
}
.diff-same { color: var(--text-muted); }
.diff-del { background: color-mix(in srgb, var(--danger) 18%, transparent); color: var(--danger); text-decoration: line-through; border-radius: 3px; }
.diff-ins { background: color-mix(in srgb, #4FA860 20%, transparent); color: #2e7d43; border-radius: 3px; }
.diff-info { color: var(--text-faint); font-style: italic; }

/* Relaunch-to-update toast (local update channel) */
.update-toast {
  position: fixed; left: 50%; bottom: 84px; /* clears the bottom nav */
  transform: translateX(-50%) translateY(12px);
  z-index: 4000;
  display: flex; align-items: center; gap: 12px;
  min-width: 300px; max-width: 420px;
  padding: 12px 16px;
  border-radius: 14px;
  background: var(--panel-bg);
  backdrop-filter: blur(var(--panel-blur, 18px));
  -webkit-backdrop-filter: blur(var(--panel-blur, 18px));
  border: 1px solid var(--panel-border);
  box-shadow: var(--shadow-panel);
  color: var(--text-heading);
  cursor: pointer; font: inherit; text-align: left;
  opacity: 0;
  transition: opacity .25s ease, transform .25s ease, border-color .15s ease;
}
.update-toast.in { opacity: 1; transform: translateX(-50%) translateY(0); }
.update-toast:hover { border-color: var(--accent); }
.update-toast:disabled { cursor: default; opacity: .85; }
/* The meeting record-offer wears the updater toast's shell but is a DIV with
   its own buttons — the container must not read as one big click target. */
#meeting-toast { cursor: default; }
#meeting-toast:hover { border-color: var(--panel-border); }
.meeting-toast-btn {
  padding: 6px 13px; border-radius: 9px; cursor: pointer; font-size: 12.5px;
  border: 1px solid var(--border); background: transparent; color: var(--text-normal); white-space: nowrap;
}
.meeting-toast-btn:hover { border-color: var(--accent); color: var(--text-heading); }
.meeting-toast-btn.accent {
  background: var(--accent); border-color: var(--accent); color: #fff; font-weight: 600;
}
.meeting-toast-btn.accent:hover { background: var(--accent-strong); }
/* Today's real events under the month grid (calendar.js renderAgenda). */
.cal-agenda { display: flex; flex-direction: column; gap: 2px; margin-top: 10px; }
.cal-agenda-head { font-size: 10.5px; font-weight: 700; letter-spacing: .08em; text-transform: uppercase; color: var(--text-faint); margin-bottom: 3px; }
.cal-agenda-empty { font-size: 12px; color: var(--text-faint); }
.cal-agenda-row { display: flex; align-items: baseline; gap: 8px; font-size: 12.5px; line-height: 1.5; min-width: 0; }
.cal-agenda-time { color: var(--text-faint); font-variant-numeric: tabular-nums; white-space: nowrap; font-size: 11.5px; }
.cal-agenda-title { color: var(--text-normal); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.update-toast-icon {
  display: grid; place-items: center;
  width: 34px; height: 34px; flex: none;
  border-radius: 9px; background: var(--bg-tertiary); color: var(--accent);
}
.update-toast-text { display: flex; flex-direction: column; flex: 1 1 auto; line-height: 1.25; }
.update-toast-text strong { font-size: 14px; font-weight: 600; color: var(--text-heading); }
.update-toast-text small { font-size: 12px; color: var(--text-muted); }
.update-toast-arrow { display: grid; place-items: center; color: var(--text-muted); flex: none; }
.update-toast:hover .update-toast-arrow { color: var(--accent); }

/* Selective-sync picker */
.sync-scope-row { padding: 4px 0; }
.sync-scope-row label { display: flex; align-items: center; gap: 8px; cursor: pointer; color: var(--text-normal); }
.sync-selection-tree {
  max-height: 260px; overflow: auto;
  margin: 6px 0 10px; padding: 6px;
  border: 1px solid var(--border); border-radius: 10px;
  background: var(--bg-secondary);
}
.sync-tree-row { display: flex; align-items: center; gap: 8px; padding: 3px 4px; cursor: pointer; border-radius: 6px; font-size: 13px; color: var(--text-normal); }
.sync-tree-row:hover { background: var(--bg-hover); }
.sync-tree-folder { font-weight: 600; color: var(--text-heading); }
.sync-tree-file { color: var(--text-muted); }

/* Settings → Sync: Your devices + Recent syncs */
.sync-device-row { display: flex; align-items: center; gap: 8px; padding: 8px 4px; border-bottom: 1px solid var(--border-subtle, rgba(128,128,128,.15)); }
.sync-device-row:last-child { border-bottom: none; }
.sync-device-main { flex: 1; min-width: 0; }
.sync-device-name { font-weight: 600; color: var(--text-heading); }
.sync-device-badge { margin-left: 8px; font-size: 11px; padding: 1px 8px; border-radius: 999px; background: var(--accent); color: #fff; vertical-align: 1px; }
.sync-device-meta { font-size: 12px; color: var(--text-muted); margin-top: 2px; }
.sync-history-row { display: flex; gap: 10px; padding: 4px 4px; font-size: 13px; color: var(--text-normal); }
.sync-history-when { color: var(--text-muted); white-space: nowrap; min-width: 108px; }
.sync-history-error { color: var(--danger, #c0392b); }

.hdr-svg svg { width: 17px; height: 17px; }

/* The Study panel block's body (the block card supplies frame and heading). */
.rail-card.hidden { display: none; }
.rail-study-row { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
.rail-study-nums { font-size: 13px; color: var(--text-normal); }
.rail-due { color: var(--accent); }
.rail-review {
  font-size: 12px;
  font-weight: 600;
  padding: 5px 12px;
  border-radius: 999px;
  background: var(--text-normal);
  color: var(--bg-primary);
}
.rail-review:hover { background: var(--text-heading); }

/* Library: the card-grid home (reading-room redesign) */
#library-view { display: none; flex: 1; min-height: 0; }
#library-view.visible { display: block; }

/* ---- To-dos page ----
   Every checkbox in the vault on one screen. Rows are deliberately plain: the
   note name is the group, so a task never appears without the context that
   gives it meaning. Colours come only from tokens, because themes are inline
   custom properties on <html> — a hard-coded hex or a prefers-color-scheme
   query would fight an explicit theme choice. */
/* ============ Calendar page ============
   Day is a timeline you read downwards; Week and Month are grids. The reasoning
   for that split is in calendar-model.js — in short, at one day the question is
   "what happens next" and a list answers it, while an hour grid turns a
   fifteen-minute stand-up into an eleven-pixel sliver.

   Nothing here is positioned by duration EXCEPT in the week grid, where the
   whole point is proportion. In the day view every row is as tall as its
   contents need, which is what keeps a short thing readable. */
/* The mini calendar's month name is a button now (it opens the Calendar page);
   it has to keep looking like the label it always was. */
.cal-head .cal-title { font: inherit; color: inherit; padding: 0; }
.cal-head .cal-title:hover { color: var(--accent); }

#calendar-view { display: none; flex: 1; min-height: 0; }
#calendar-view.visible { display: flex; flex-direction: column; }

.cv-head {
  display: flex; align-items: center; gap: 14px; flex-wrap: wrap;
  padding: 20px 30px 14px; border-bottom: 1px solid var(--border);
}
.cv-title { font-size: 20px; font-weight: 700; color: var(--text-heading); letter-spacing: -.01em; flex: 1; }
.cv-nav { display: flex; align-items: center; gap: 6px; }
.cv-step {
  width: 28px; height: 28px; border-radius: 8px; font-size: 17px; line-height: 1;
  color: var(--text-muted); border: 1px solid var(--border);
}
.cv-step:hover, .cv-today:hover, .cv-mode:hover { background: var(--bg-hover); color: var(--text-normal); }
.cv-today, .cv-mode {
  height: 28px; padding: 0 11px; border-radius: 8px; font-size: 12.5px;
  color: var(--text-muted); border: 1px solid var(--border);
}
.cv-modes { display: flex; gap: 5px; }
.cv-mode.on { background: var(--bg-active); border-color: transparent; color: #fff; }
.cv-body { flex: 1; min-height: 0; overflow: hidden; display: flex; flex-direction: column; }

/* ---- Day: the thread ----
   A single line with beads on it, each as long as the thing it stands for. Four
   columns — the time ruler, the thread, the thing, the ring — with the thread
   drawn as one continuous line behind the beads. That line is what makes a day
   read as time passing rather than as a list with clocks printed beside it. */
.cv-day { height: 100%; overflow-y: auto; padding: 20px 26px 140px; }
/* Two columns: the pile on the left, the day on the right. The pile is fixed
   and narrow because it is a list of names; the thread takes the rest because
   it is the thing this page is for. Stacked below 980px, pile first — on a
   phone the loose items are what you triage. */
.cv-cols { display: grid; grid-template-columns: 288px minmax(0, 1fr); gap: 28px; align-items: start; max-width: 1080px; }
@media (max-width: 980px) { .cv-cols { grid-template-columns: 1fr; gap: 18px; } }
.cv-col-loose { display: flex; flex-direction: column; gap: 4px; position: sticky; top: 0; }
@media (max-width: 980px) { .cv-col-loose { position: static; } }
.cv-loose-empty { font-size: 12px; color: var(--text-faint); padding: 6px 4px 2px; }

/* A THIRD COLUMN, only when a meeting is picked: the notes that say they belong
   to it (calendar-view.js). It takes its own width rather than squeezing the
   thread, and everything stacks once there is no room for three. */
.cv-cols.with-notes { grid-template-columns: 236px minmax(0, 1fr) 300px; max-width: 1420px; }
@media (max-width: 1240px) { .cv-cols.with-notes { grid-template-columns: 1fr; gap: 18px; } }
.cv-col-notes { display: flex; flex-direction: column; gap: 6px; position: sticky; top: 0; }
@media (max-width: 1240px) { .cv-col-notes { position: static; } }
.cv-notes-head { display: flex; align-items: baseline; gap: 6px; padding: 0 2px 4px; }
.cv-notes-k { font-size: 11px; letter-spacing: 0.04em; text-transform: uppercase; color: var(--text-faint); flex: none; }
.cv-notes-for {
  font-size: 12.5px; font-weight: 600; color: var(--text-heading);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; flex: 1;
}
.cv-notes-x { flex: none; width: 20px; height: 20px; border-radius: 50%; color: var(--text-faint); font-size: 15px; line-height: 1; }
.cv-notes-x:hover { background: var(--bg-hover); color: var(--text-heading); }
.cv-notes-list { display: flex; flex-direction: column; gap: 4px; }
.cv-notes-row {
  display: flex; align-items: baseline; gap: 8px; text-align: left; width: 100%;
  padding: 8px 10px; border: 1px solid var(--panel-border); border-radius: var(--radius-card);
  background: var(--card-bg); font-size: 12.5px; color: var(--text-normal);
}
.cv-notes-row:hover { border-color: var(--accent); background: var(--bg-hover); }
.cv-notes-name { flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.cv-notes-when { flex: none; font-size: 11px; color: var(--text-faint); }
.cv-notes-wait, .cv-notes-empty { font-size: 12px; color: var(--text-faint); padding: 4px 4px 2px; line-height: 1.5; }
.cv-notes-attach {
  margin-top: 2px; text-align: left; padding: 8px 10px;
  border: 1px dashed var(--border-strong); border-radius: var(--radius-card);
  font-size: 12.5px; color: var(--text-faint);
}
.cv-notes-attach:hover { color: var(--text-normal); border-color: var(--accent); background: var(--bg-hover); }
/* The picked meeting keeps a mark while its notes are open. */
.cv-item.picked .cv-bead { box-shadow: 0 0 0 2px var(--accent); }
.cv-item.cv-event .cv-info.cv-clickable { cursor: pointer; border-radius: 8px; }
.cv-item.cv-event .cv-info.cv-clickable:hover .cv-name { color: var(--accent); }
.cv-add {
  margin-top: 6px; align-self: stretch; text-align: left; padding: 8px 10px;
  border: 1px dashed var(--border-strong); border-radius: var(--radius-card);
  font-size: 12.5px; color: var(--text-faint);
}
.cv-add:hover { color: var(--text-normal); border-color: var(--accent); background: var(--bg-hover); }
.cv-addbtn {
  width: 28px; height: 28px; border-radius: 8px; font-size: 17px; line-height: 1;
  border: 1px solid var(--border); color: var(--text-muted);
}
.cv-addbtn:hover { background: var(--bg-active); color: #fff; border-color: transparent; }
.cv-notelink { font: inherit; color: inherit; padding: 0; text-align: left; }
.cv-notelink:hover { color: var(--accent); text-decoration: underline; }
/* A gap is a place to put something, so it behaves like one. */
.cv-gap-add { display: flex; align-items: center; gap: 8px; font: inherit; padding: 0; }
.cv-gap-put { font-size: 10.5px; color: var(--accent); opacity: 0; }
.cv-gap-add:hover .cv-gap-put { opacity: 1; }
.cv-gap-add:hover .cv-gap-label { color: var(--text-muted); }
.cv-day-sum { display: flex; gap: 12px; align-items: baseline; margin-bottom: 16px; padding-left: 4px; }
.cv-sum-n { font-size: 14px; font-weight: 600; color: var(--text-normal); }
.cv-sum-free { font-size: 12.5px; color: var(--text-faint); }

.cv-tray { display: flex; flex-direction: column; gap: 4px; margin-bottom: 10px; }
.cv-tray-head {
  font-family: var(--font-mono); font-size: 10px; text-transform: uppercase;
  letter-spacing: .08em; color: var(--text-faint); padding-left: 4px; margin-bottom: 2px;
}
.cv-loose {
  display: grid; grid-template-columns: 34px 1fr 26px; align-items: center; gap: 10px;
  padding: 7px 8px; border-radius: var(--radius-card);
  background: hsl(var(--hue) 42% 52% / 0.07);
}
.cv-loose:hover { background: hsl(var(--hue) 42% 52% / 0.13); }
.cv-loose-ic {
  width: 30px; height: 30px; border-radius: 99px; display: grid; place-items: center;
  font-size: 14px; background: hsl(var(--hue) 42% 52% / 0.22);
}
.cv-loose.done { opacity: .5; }
.cv-loose.done .cv-name { text-decoration: line-through; }

.cv-thread { position: relative; }
.cv-item { display: grid; grid-template-columns: 52px 46px 1fr 30px; gap: 12px; align-items: start; }
/* THE LINE. Drawn on the rail column and running the full height of every row,
   so consecutive beads are joined and a gap is the same line gone thin. */
.cv-rail { position: relative; display: flex; justify-content: center; }
.cv-rail::before {
  content: ''; position: absolute; top: 0; bottom: -1px; left: 50%; width: 2px;
  transform: translateX(-50%); background: var(--border);
}
.cv-item.cv-event .cv-rail::before, .cv-item.cv-task .cv-rail::before {
  background: hsl(var(--hue) 42% 52% / 0.35);
}
.cv-bead {
  position: relative; width: 40px; border-radius: 22px; overflow: hidden;
  background: hsl(var(--hue) 42% 52% / 0.16);
  border: 1px solid hsl(var(--hue) 42% 52% / 0.30);
  display: grid; place-items: center; z-index: 1;
}
/* The clock, drawn as a filling capsule: empty ahead of you, part-full for the
   thing you are in, solid behind you. */
.cv-bead-fill { position: absolute; left: 0; right: 0; top: 0; background: hsl(var(--hue) 42% 52% / 0.62); }
.cv-bead-ic { position: relative; display: grid; place-items: center; font-size: 14px; line-height: 1; z-index: 1; }
/* Line drawings take the bead's own colour; an emoji brings its own and is left
   alone — that is the point of choosing one. */
.sched-ic { display: grid; place-items: center; color: hsl(var(--hue) 55% 32%); }
.theme-dark .sched-ic, body:not(.theme-light) .sched-ic { color: hsl(var(--hue) 60% 82%); }
.sched-ic.emoji { font-size: 14px; line-height: 1; }
.cv-loose-ic .sched-ic svg { width: 15px; height: 15px; }

/* The picker in the date dialog. */
/* The label sits by the first row of icons, not halfway down the groups:
   .vn-due-row centres its children and is declared further down, so this
   needs the extra class to win. */
.vn-due-row.vn-due-iconrow { align-items: flex-start; }
.vn-due-row.vn-due-iconrow > span:first-child { padding-top: 7px; }
.vn-icons { display: flex; flex-direction: column; gap: 6px; flex: 1; min-width: 0; }
.vn-icons-quick, .vn-icons-set { display: flex; flex-wrap: wrap; gap: 4px; }
/* The chosen one joins the quick row as though it were part of it. */
.vn-icons-chosen { display: contents; }
.vn-icons-all { display: flex; flex-direction: column; gap: 4px; padding: 2px 0 2px; }
.vn-icons-all[hidden] { display: none; }
.vn-icons-group {
  margin-top: 4px; font-size: 10.5px; letter-spacing: .06em; text-transform: uppercase;
  color: var(--text-faint);
}
.vn-icons-emoji-row { display: flex; align-items: center; gap: 8px; margin-top: 6px; font-size: 12px; color: var(--text-faint); }
.vn-icon-btn {
  width: 28px; height: 28px; border-radius: 8px; display: grid; place-items: center;
  border: 1px solid var(--border); color: var(--text-muted); background: transparent;
}
.vn-icon-btn:hover { background: var(--bg-hover); color: var(--text-normal); }
.vn-icon-btn.on { border-color: var(--accent); color: var(--accent); background: color-mix(in srgb, var(--accent) 12%, transparent); }
.vn-icon-auto, .vn-icon-more { width: auto; padding: 0 9px; font-size: 11.5px; }
.vn-icon-custom { font-size: 15px; line-height: 1; }
/* flex-basis, not width: the dialog's rows set a width on every input they
   contain, so a plain width let this one stretch across its own line. */
.vn-icon-emoji {
  flex: 0 0 40px; width: 40px; min-width: 0; height: 28px; text-align: center; font-size: 15px;
  border-radius: 8px; border: 1px solid var(--border); background: var(--bg-primary); color: var(--text-normal);
}
.vn-due-for { flex: 1; }

/* The gradient swatches: each one painted with the gradient it applies, because
   ten names would be ten words nobody can picture. */
/* A row whose control cannot do anything says so by looking like it. */
.settings-row.is-dead { opacity: .45; }
.settings-row.is-dead input[type="range"] { cursor: not-allowed; }
.settings-hint.warn .settings-mini { margin-left: 6px; vertical-align: baseline; }

.wp-swatches { display: flex; flex-wrap: wrap; gap: 7px; flex: 1; }
.wp-swatch {
  width: 46px; height: 32px; border-radius: 9px; background-size: cover;
  border: 1px solid var(--border-strong); box-shadow: var(--shadow-card);
}
.wp-swatch:hover { transform: translateY(-1px); }
.wp-swatch.on { outline: 2px solid var(--accent); outline-offset: 2px; }
@media (prefers-reduced-motion: reduce) { .wp-swatch:hover { transform: none; } }
.cv-item.done .cv-bead { opacity: .55; }
.cv-item.past { opacity: .62; }
.cv-item.current .cv-bead { box-shadow: 0 0 0 3px hsl(var(--hue) 42% 52% / 0.18); }

.cv-gut { display: flex; flex-direction: column; justify-content: space-between; align-self: stretch; padding: 1px 0 8px; text-align: right; }
.cv-gut-t { font-size: 11.5px; color: var(--text-muted); font-variant-numeric: tabular-nums; }
.cv-gut-t.on { font-weight: 700; color: var(--text-heading); }
.cv-gut-t.now { color: var(--danger); font-weight: 700; }
.cv-gut-e { font-size: 10.5px; color: var(--text-faint); font-variant-numeric: tabular-nums; }

.cv-info { padding: 0 0 14px; min-width: 0; }
.cv-info.cv-clickable { cursor: pointer; }
.cv-range { font-size: 11px; color: var(--text-faint); font-variant-numeric: tabular-nums; }
.cv-item.current .cv-range { color: hsl(var(--hue) 45% 45%); font-weight: 600; }
.cv-name { font-size: 14.5px; font-weight: 600; color: var(--text-heading); line-height: 1.3; margin-top: 1px; }
.cv-item.done .cv-name, .cv-loose.done .cv-name { text-decoration: line-through; color: var(--text-faint); }
.cv-meta { display: flex; align-items: center; gap: 5px; font-size: 11.5px; color: var(--text-faint); margin-top: 2px; }
.cv-meta-ic { font-size: 10.5px; opacity: .8; }

/* The ring, on the right, where the one thing you can finish lives. */
.cv-ring {
  width: 20px; height: 20px; border-radius: 99px; margin-top: 12px;
  border: 1.5px solid hsl(var(--hue) 42% 52% / 0.55); background: transparent;
}
.cv-ring:hover { border-color: hsl(var(--hue) 45% 45%); background: hsl(var(--hue) 42% 52% / 0.12); }
.cv-ring.on { background: hsl(var(--hue) 45% 48%); border-color: transparent; }
.cv-ring.on::after { content: '✓'; color: #fff; font-size: 11px; line-height: 17px; display: block; }
.cv-ring.ghost { border: none; pointer-events: none; }

/* A gap: the same thread, gone thin, with how long it lasts beside it. */
.cv-thin { width: 2px; height: 30px; }
.cv-gapinfo { display: flex; align-items: center; gap: 6px; padding-bottom: 12px; height: 30px; }
.cv-gap-label { font-size: 11.5px; color: var(--text-faint); }
.cv-nowdot { width: 9px; height: 9px; border-radius: 99px; background: var(--danger); margin-top: 3px; z-index: 1; }
.cv-nowline { height: 1px; background: var(--danger); opacity: .45; margin-top: 7px; }
.cv-empty { padding: 26px 4px; color: var(--text-faint); font-size: 13.5px; }

/* ---- Week as the same thread ---- */
.cv-weekthread { height: 100%; overflow-y: auto; padding: 14px 26px 140px; max-width: 760px; }
.cv-wtday { margin-bottom: 10px; }
.cv-wthead {
  display: flex; align-items: baseline; gap: 9px; width: 100%; text-align: left;
  padding: 8px 4px 6px; border-bottom: 1px solid var(--border); margin-bottom: 10px;
}
.cv-wthead:hover .cv-wthead-w { color: var(--accent); }
.cv-wthead-w { font-size: 13px; font-weight: 600; color: var(--text-normal); }
.cv-wthead-n { font-size: 13px; color: var(--text-faint); font-variant-numeric: tabular-nums; }
.cv-wthead-c { margin-left: auto; font-size: 11px; color: var(--text-faint); }
.cv-wtday.today .cv-wthead-w { color: var(--accent); }
.cv-wtday.today .cv-wthead-n { background: var(--bg-active); color: #fff; border-radius: 99px; padding: 1px 7px; font-size: 11.5px; }
.cv-wtempty { font-size: 12px; color: var(--text-faint); padding: 0 0 10px 52px; }
.cv-thread.compact .cv-info { padding-bottom: 9px; }

/* A repeat that has not happened yet: the same shape as the real thing, drawn
   faintly and outlined, so a week of "every Monday and Friday" shows where it
   falls without any of those days looking like a to-do you could tick. */
.cv-item.ghost-ahead .cv-bead { opacity: .5; border: 1.5px dashed color-mix(in srgb, var(--text-faint) 70%, transparent); }
/* A repeat still ahead of you has nothing to fill. One that is happening now,
   or already has, fills like anything else — see ghost-ahead in calendar-view. */
.cv-item.ghost-ahead .cv-bead-fill { display: none; }
.cv-item.ghost-ahead .cv-name, .cv-item.ghost-ahead .cv-range { opacity: .6; }
.cv-loose.ghost, .cv-chip.ghost, .cv-block.ghost { opacity: .55; border-style: dashed; }
.cv-thread.compact .cv-name { font-size: 13.5px; }

.cv-shapes { display: flex; gap: 4px; }
.cv-shape { height: 28px; padding: 0 10px; border-radius: 8px; font-size: 12px; color: var(--text-muted); border: 1px solid var(--border); }
.cv-shape:hover { background: var(--bg-hover); color: var(--text-normal); }
.cv-shape.on { background: var(--bg-hover); color: var(--text-normal); border-color: var(--border-strong); }


/* ---- Week ---- */
.cv-week { display: flex; flex-direction: column; height: 100%; min-height: 0; }
.cv-week-heads, .cv-allday { display: grid; grid-template-columns: 54px repeat(7, 1fr); }
.cv-week-heads { border-bottom: 1px solid var(--border); }
.cv-dayhead { padding: 8px 4px; display: flex; flex-direction: column; align-items: center; gap: 1px; }
.cv-dayhead-w { font-family: var(--font-mono); font-size: 10px; text-transform: uppercase; letter-spacing: .07em; color: var(--text-faint); }
.cv-dayhead-n { font-size: 16px; font-weight: 600; color: var(--text-normal); }
.cv-dayhead.today .cv-dayhead-n {
  background: var(--bg-active); color: #fff; width: 26px; height: 26px;
  border-radius: 99px; display: grid; place-items: center; font-size: 13px;
}
.cv-allday { border-bottom: 1px solid var(--border); min-height: 30px; }
.cv-allday-cell { padding: 3px; display: flex; flex-direction: column; gap: 2px; border-left: 1px solid var(--border); }
.cv-gutter-head { font-family: var(--font-mono); font-size: 9.5px; color: var(--text-faint); padding: 6px; text-align: right; }
.cv-week-scroll { flex: 1; min-height: 0; overflow-y: auto; }
.cv-week-grid { display: grid; grid-template-columns: 54px repeat(7, 1fr); min-height: 900px; }
.cv-gutter { display: flex; flex-direction: column; }
.cv-hour-label {
  flex: 1; font-family: var(--font-mono); font-size: 10px; color: var(--text-faint);
  text-align: right; padding-right: 7px; transform: translateY(-6px);
}
.cv-daycol { position: relative; border-left: 1px solid var(--border); display: flex; flex-direction: column; }
.cv-daycol.today { background: color-mix(in srgb, var(--accent) 4%, transparent); }
.cv-hour { flex: 1; border-bottom: 1px solid color-mix(in srgb, var(--border) 55%, transparent); }
.cv-block {
  position: absolute; overflow: hidden; padding: 2px 5px; border-radius: 6px;
  font-size: 11px; line-height: 1.25; cursor: pointer;
  background: color-mix(in srgb, var(--accent) 20%, var(--card-bg));
  border-left: 2px solid var(--accent);
}
.cv-block.cv-task { background: color-mix(in srgb, var(--text-faint) 16%, var(--card-bg)); border-left-color: var(--text-faint); }
.cv-block.done { opacity: .5; text-decoration: line-through; }
.cv-block-t { font-family: var(--font-mono); font-size: 9.5px; color: var(--text-muted); margin-right: 4px; }
.cv-block-n { color: var(--text-normal); }
.cv-weeknow { position: absolute; left: 0; right: 0; height: 2px; background: var(--danger); z-index: 2; }

/* ---- Month ---- */
.cv-month { display: flex; flex-direction: column; height: 100%; min-height: 0; }
.cv-month-heads { display: grid; grid-template-columns: repeat(7, 1fr); border-bottom: 1px solid var(--border); }
.cv-month-head {
  font-family: var(--font-mono); font-size: 10px; text-transform: uppercase;
  letter-spacing: .07em; color: var(--text-faint); padding: 7px; text-align: center;
}
.cv-month-grid { flex: 1; min-height: 0; display: grid; grid-template-columns: repeat(7, 1fr); grid-auto-rows: 1fr; overflow-y: auto; }
.cv-cell {
  border-left: 1px solid var(--border); border-bottom: 1px solid var(--border);
  padding: 4px; min-height: 92px; display: flex; flex-direction: column; gap: 2px; overflow: hidden;
}
.cv-cell.out { background: color-mix(in srgb, var(--text-faint) 5%, transparent); }
.cv-cell.out .cv-cell-n { color: var(--text-faint); }
.cv-cell-n { align-self: flex-start; font-size: 12px; color: var(--text-muted); padding: 1px 5px; border-radius: 99px; }
.cv-cell.today .cv-cell-n { background: var(--bg-active); color: #fff; font-weight: 600; }
.cv-chip {
  display: block; width: 100%; text-align: left; font-size: 11px; line-height: 1.3;
  padding: 2px 5px; border-radius: 5px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  background: color-mix(in srgb, var(--accent) 16%, transparent); color: var(--text-normal);
}
.cv-chip.cv-task { background: color-mix(in srgb, var(--text-faint) 13%, transparent); }
.cv-chip.done { opacity: .5; text-decoration: line-through; }
.cv-more { align-self: flex-start; font-size: 10.5px; color: var(--text-faint); padding: 1px 5px; }
.cv-more:hover { color: var(--text-normal); }

@media (max-width: 900px) {
  .cv-week-heads, .cv-allday, .cv-week-grid { grid-template-columns: 40px repeat(7, 1fr); }
  .cv-day, .cv-weekthread { padding: 16px 12px 110px; }
  /* The ruler and the thread give up width first; the thing itself keeps it. */
  .cv-item { grid-template-columns: 42px 38px 1fr 26px; gap: 9px; }
  .cv-bead { width: 34px; }
}

#todos-view { display: none; flex: 1; min-height: 0; }
#todos-view.visible { display: block; }
.todo-scroll { height: 100%; overflow-y: auto; padding: 26px 34px 110px; }

.todo-head { display: flex; align-items: flex-start; gap: 14px; flex-wrap: wrap; margin-bottom: 16px; }
.todo-title {
  font-size: 24px; font-weight: 700; color: var(--text-heading);
  font-family: 'Iowan Old Style', 'Literata', 'Palatino Linotype', Georgia, serif;
}
.todo-sub { margin-top: 2px; font-size: 12px; color: var(--text-faint); font-family: var(--font-mono); }
.todo-seg {
  display: flex; gap: 2px; margin-left: auto; align-self: center;
  background: var(--bg-tertiary); border-radius: 9px; padding: 2px;
}
.todo-seg button {
  font: inherit; font-size: 12px; font-weight: 600; color: var(--text-muted, var(--text-normal));
  background: transparent; border: 0; border-radius: 7px; padding: 4px 13px; cursor: pointer;
}
.todo-seg button.on { background: var(--card-bg); color: var(--text-heading); box-shadow: var(--shadow-card); }
.todo-search {
  align-self: center; font: inherit; font-size: 13px; color: var(--text-normal);
  background: var(--bg-tertiary); border: 1px solid var(--border);
  border-radius: 9px; padding: 6px 11px; min-width: 190px;
}
.todo-search:focus { outline: none; border-color: var(--accent); }

/* The composer is a to-do that doesn't exist yet — same shape as a row, so
   where a new one will land is obvious before you type. */
.todo-add {
  display: flex; align-items: center; gap: 10px;
  background: var(--card-bg); border: 1px solid var(--panel-border);
  border-radius: var(--radius-card); box-shadow: var(--shadow-card);
  padding: 11px 14px; margin-bottom: 22px;
}
.todo-add-box {
  width: 16px; height: 16px; flex: none; border-radius: 5px;
  border: 1.5px solid var(--border-strong, var(--border)); opacity: .6;
}
.todo-add-text { flex: 1; font: inherit; font-size: 14.5px; color: var(--text-normal); background: transparent; border: 0; }
.todo-add-text:focus { outline: none; }
.todo-add-target {
  font: inherit; font-size: 12px; color: var(--text-muted, var(--text-normal));
  background: var(--bg-tertiary); border: 1px solid var(--border);
  border-radius: 8px; padding: 5px 8px; max-width: 230px; cursor: pointer;
}

/* WHAT THE WORDS WERE READ AS. "call the dentist Wed 9am" is understood while
   it is typed and shown here as chips, so the guess is visible before anything
   is written; the × puts those words back in the to-do (typed-todo.js). */
.todo-add-chips { display: inline-flex; align-items: center; gap: 6px; flex: none; }
.todo-add-chips[hidden] { display: none; }
.todo-add-chip {
  display: inline-flex; align-items: center; height: 22px; padding: 0 9px;
  border-radius: 999px; background: var(--chip-bg); color: var(--chip-text);
  font-size: 12px; font-weight: 600; white-space: nowrap;
}
.todo-add-chip-off {
  width: 22px; height: 22px; border: 0; background: transparent; cursor: pointer;
  border-radius: 50%; color: var(--text-faint); font-size: 15px; line-height: 1;
  display: inline-flex; align-items: center; justify-content: center;
}
.todo-add-chip-off:hover { background: var(--bg-hover); color: var(--text-heading); }

.todo-group { margin-bottom: 20px; }
.todo-group-head { display: flex; align-items: baseline; gap: 9px; margin: 0 0 6px 2px; }
.todo-group-label {
  font-size: 11px; font-weight: 700; letter-spacing: .08em; text-transform: uppercase;
  color: var(--text-faint); cursor: pointer;
}
.todo-group-label:hover { color: var(--accent); }
.todo-group-count { font-size: 10.5px; font-family: var(--font-mono); color: var(--text-faint); }

.todo-row { display: flex; align-items: flex-start; gap: 10px; padding: 5px 8px 5px 4px; border-radius: 8px; }
.todo-row:hover { background: var(--bg-hover); }
.todo-box {
  flex: none; margin-top: 2px; width: 16px; height: 16px; padding: 0;
  border: 1.5px solid var(--border-strong, var(--border)); border-radius: 5px;
  background: transparent; cursor: pointer; position: relative;
}
.todo-box:hover { border-color: var(--accent); }
.todo-box.on { background: var(--accent); border-color: var(--accent); }
.todo-box.on::after {
  content: ''; position: absolute; left: 4.5px; top: 1px; width: 4px; height: 8px;
  border: solid #fff; border-width: 0 2px 2px 0; transform: rotate(45deg);
}
.todo-text { font-size: 14.5px; line-height: 1.45; color: var(--text-normal); cursor: pointer; }
.todo-text:hover { color: var(--accent); }
.todo-row.done .todo-text { text-decoration: line-through; color: var(--text-faint); }

.todo-empty { padding: 40px 8px; max-width: 520px; }
.todo-empty-title { font-size: 16px; font-weight: 650; color: var(--text-heading); margin-bottom: 6px; }
.todo-empty-body { font-size: 13.5px; line-height: 1.55; color: var(--text-faint); }

/* The landing flash when a row opens its note — same gesture as a block link. */
.todo-flash { transition: background 1.2s; background: color-mix(in srgb, var(--accent) 18%, transparent); }

/* ---- dates ---- */

.todo-late { color: var(--danger, #c2410c); font-weight: 600; }
.todo-filters { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; margin: -6px 0 16px; }
.todo-filters-gap { flex: 1; }
.todo-pill {
  font: inherit; font-size: 11.5px; font-weight: 600; color: var(--text-faint);
  background: transparent; border: 1px solid var(--border); border-radius: 999px;
  padding: 3px 11px; cursor: pointer;
}
.todo-pill:hover { color: var(--text-normal); border-color: var(--border-strong, var(--border)); }
.todo-pill.on { color: var(--text-heading); background: var(--bg-tertiary); border-color: var(--border-strong, var(--border)); }
.todo-group-label.plain { cursor: default; }
.todo-group-label.plain:hover { color: var(--text-faint); }
.todo-group.late .todo-group-label { color: var(--danger, #c2410c); }

/* The row's date sits at the far right and stays the same width whether it
   holds a chip or the "+ due" affordance, so the column never jitters. */
.todo-row .todo-text { flex: 1; }
.todo-from {
  flex: none; font: inherit; font-size: 11px; color: var(--text-faint);
  background: transparent; border: 0; padding: 2px 4px; cursor: pointer;
  max-width: 160px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.todo-from:hover { color: var(--accent); }
.todo-due {
  flex: none; margin-top: 1px; font: inherit; font-size: 11px; font-weight: 600;
  font-family: var(--font-mono); white-space: nowrap;
  color: var(--text-muted, var(--text-normal)); background: var(--bg-tertiary);
  border: 1px solid var(--border); border-radius: 999px; padding: 2px 9px; cursor: pointer;
}
.todo-due:hover { border-color: var(--accent); color: var(--accent); }
.todo-due.late { color: var(--danger, #c2410c); border-color: color-mix(in srgb, var(--danger, #c2410c) 40%, transparent); background: color-mix(in srgb, var(--danger, #c2410c) 10%, transparent); }
.todo-due.now { color: var(--accent); border-color: color-mix(in srgb, var(--accent) 45%, transparent); }
.todo-due.bad { color: var(--danger, #c2410c); font-weight: 700; }
/* Invisible until the row is hovered — an undated to-do shouldn't shout. */
.todo-due.none { opacity: 0; background: transparent; border-style: dashed; }
.todo-row:hover .todo-due.none { opacity: .7; }
.todo-row.done .todo-due { opacity: .5; }
.todo-add-due {
  flex: none; font: inherit; font-size: 11.5px; font-weight: 600; font-family: var(--font-mono);
  color: var(--text-faint); background: var(--bg-tertiary); border: 1px solid var(--border);
  border-radius: 8px; padding: 5px 9px; cursor: pointer; white-space: nowrap;
}
.todo-add-due:hover { color: var(--accent); border-color: var(--accent); }
.todo-add-due.on { color: var(--accent); border-color: color-mix(in srgb, var(--accent) 50%, transparent); }

/* ---- the due-date dialog ---- */

.vn-due { min-width: 340px; }
.vn-due-quick { display: flex; gap: 6px; flex-wrap: wrap; margin: 4px 0 14px; }
.vn-due-quick button {
  font: inherit; font-size: 12px; font-weight: 600; color: var(--text-muted, var(--text-normal));
  background: var(--bg-tertiary); border: 1px solid var(--border); border-radius: 999px;
  padding: 4px 12px; cursor: pointer;
}
.vn-due-quick button:hover { color: var(--accent); border-color: var(--accent); }
.vn-due-row { display: flex; align-items: center; gap: 10px; margin-bottom: 10px; font-size: 13px; }
.vn-due-row > span:first-child { width: 54px; flex: none; color: var(--text-faint); font-size: 12px; }
.vn-due-row input, .vn-due-row select {
  font: inherit; font-size: 13px; color: var(--text-normal);
  background: var(--bg-tertiary); border: 1px solid var(--border);
  border-radius: 8px; padding: 6px 9px;
}
.vn-due-row input:focus, .vn-due-row select:focus { outline: none; border-color: var(--accent); }
.vn-due-row select { flex: 1; cursor: pointer; }
.vn-due-hint { font-size: 11px; color: var(--text-faint); }
.vn-due-note { font-size: 11.5px; line-height: 1.5; color: var(--text-faint); min-height: 17px; margin: 2px 0 4px; }
.vn-due-note.bad { color: var(--danger); }

/* ---- the dialog as one form: the name, a sentence saying what will be saved,
   then when, how long, how often, and which picture ---- */
.vn-dialog.vn-due { width: min(540px, 94vw); }
.vn-due-name {
  width: 100%; font: inherit; font-size: 17px; font-weight: 650; color: var(--text-heading);
  background: transparent; border: 0; border-bottom: 1px solid var(--border);
  padding: 2px 0 8px; margin-bottom: 8px;
}
.vn-due-name:focus { outline: none; border-bottom-color: var(--accent); }
.vn-due-name::placeholder { color: var(--text-faint); font-weight: 500; }
/* The sentence: what the choices below amount to, in words, before anything is
   written — so a wrong day or a wrong rhythm shows here first. */
.vn-due-sum {
  font-size: 12.5px; color: var(--accent); font-weight: 600; margin-bottom: 12px; min-height: 18px;
}
.vn-due-allday {
  display: inline-flex; align-items: center; gap: 7px; margin: 0 0 10px 64px;
  font-size: 12.5px; color: var(--text-muted, var(--text-normal)); cursor: pointer;
}
.vn-due-allday input { accent-color: var(--accent); }
.vn-due-row input[type="date"] { flex: 0 0 auto; }
.vn-due-row input[type="time"] { flex: 0 0 auto; width: 118px; }
/* Lengths: set the end from the start in one click. */
.vn-due-lens { display: flex; gap: 4px; margin-left: 2px; }
.vn-due-lens button, .vn-due-daypreset {
  font: inherit; font-size: 11.5px; font-weight: 600; color: var(--text-muted, var(--text-normal));
  background: var(--bg-tertiary); border: 1px solid var(--border); border-radius: 999px;
  padding: 3px 9px; cursor: pointer;
}
.vn-due-lens button:hover, .vn-due-daypreset:hover { color: var(--accent); border-color: var(--accent); }
.vn-due-repn { width: 58px; flex: 0 0 58px; text-align: center; }
.vn-due-repmode, .vn-due-repunit { flex: 0 1 auto !important; }
/* The week, Monday first: tap the days it happens on. */
.vn-due-days { display: flex; align-items: center; gap: 5px; margin: -2px 0 12px 64px; }
.vn-due-day {
  width: 30px; height: 30px; border-radius: 50%; font: inherit; font-size: 12px; font-weight: 700;
  color: var(--text-muted, var(--text-normal)); background: var(--bg-tertiary);
  border: 1px solid var(--border); cursor: pointer; padding: 0;
}
.vn-due-day:hover { border-color: var(--accent); }
.vn-due-day.on { background: var(--accent); border-color: var(--accent); color: #fff; }
.vn-due-daypreset { margin-left: 6px; }
@media (max-width: 560px) {
  .vn-due-lens { display: none; }
  .vn-due-allday, .vn-due-days { margin-left: 0; }
}
.lib-scroll { height: 100%; overflow-y: auto; padding: 26px 34px 110px; }
.lib-head { display: flex; align-items: baseline; gap: 12px; margin-bottom: 18px; }
.lib-title {
  font-size: 24px; font-weight: 700; color: var(--text-heading);
  font-family: 'Iowan Old Style', 'Literata', 'Palatino Linotype', Georgia, serif;
}
.lib-sub { font-size: 12.5px; color: var(--text-faint); }
.lib-group { margin-bottom: 24px; }
/* ---- Shared with me: notes somebody else owns, under your own tree ----

   A heading and a short list, deliberately not a folder. They cannot be
   renamed, moved, pinned or coloured, and "delete" is leaving rather than
   trashing — a separate section says all of that by its shape instead of by
   greying out eight menu items. The rule follows .lib-group-label because the
   Library page already names its groups this way; Daylight takes the uppercase
   back off both (css/daylight/base.css). */
.tree-group-label {
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--text-faint);
  margin: 14px 0 4px 9px;
}
/* The link glyph marks the row as something reached rather than owned. Dimmed,
   because it is a label and not an action — the row itself is the action. */
.tree-item.tree-shared .tree-icon { opacity: 0.65; }
/* "Other people are in this note" — yours or somebody else's. Quiet, at the
   end of the row like the pin, and in the accent so it reads as a state and
   not as part of the name. */
.tree-shared-mark {
  display: inline-flex; align-items: center; flex: none;
  margin-left: 6px; color: var(--accent); opacity: 0.8;
}
.tree-shared-mark svg { width: 13px; height: 13px; }
.tree-item.active .tree-shared-mark { color: inherit; opacity: 0.9; }

.lib-group-label {
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--text-faint);
  margin: 0 0 10px 2px;
}
.lib-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
  gap: 12px;
}
.lib-card {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 7px;
  text-align: left;
  padding: 14px 16px;
  min-height: 104px;
  background: var(--card-bg);
  border: 1px solid var(--border);
  border-radius: 12px;
  box-shadow: var(--shadow-card);
  transition: transform 0.12s ease, box-shadow 0.12s ease, border-color 0.12s ease;
}
.lib-card:hover { transform: translateY(-1px); box-shadow: var(--shadow-panel); border-color: var(--text-faint); }
.lib-card-title { font-size: 15px; font-weight: 650; color: var(--text-heading); }
body.surface-paper .lib-card-title { font-family: 'Iowan Old Style', 'Literata', 'Palatino Linotype', Georgia, serif; }
.lib-card-body { font-size: 12.5px; line-height: 1.5; color: var(--text-muted); }
.lib-card-chips { display: flex; gap: 6px; margin-top: auto; }
.lib-chip {
  font-size: 11px;
  padding: 2px 8px;
  border-radius: 999px;
  background: var(--chip-bg);
  color: var(--chip-text);
}
.lib-card.lib-new, .lib-card.lib-more {
  align-items: center;
  justify-content: center;
  border-style: dashed;
  background: transparent;
  box-shadow: none;
  color: var(--text-faint);
  font-size: 13.5px;
  font-weight: 550;
}
.lib-card.lib-new:hover, .lib-card.lib-more:hover { color: var(--accent); border-color: var(--accent); transform: none; }

/* Omnibox: the header find/create/command bar (reading-room redesign).
   Takes the header's center slot; the old inline note-title is retired here. */
/* Compact header title: keeps click-to-rename + the inline naming flow alive
   next to the omnibox. Hidden when empty (graph/library set no title). */
#view-header #note-title {
  flex: 0 1 auto;
  max-width: 200px;
  font-size: 12.5px;
  font-weight: 550;
  color: var(--text-muted);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  cursor: text;
  padding: 3px 8px;
  border-radius: 6px;
}
#view-header #note-title:hover { background: var(--bg-hover); color: var(--text-normal); }
#view-header #note-title:empty { display: none; }
#omnibox {
  flex: 1 1 auto;
  max-width: 560px;
  /* min-width: 0 lets the box shrink below its label — without it the long
     placeholder is a hard floor and the header's right icons get pushed out. */
  min-width: 0;
  margin: 0 auto;
  display: flex;
  align-items: center;
  gap: 9px;
  height: 38px;
  padding: 0 14px;
  background: var(--bg-secondary);
  border: 1px solid var(--border);
  border-radius: 10px;
  color: var(--text-muted);
  cursor: text;
  font: inherit;
  font-size: 13.5px;
  transition: border-color 0.12s ease, background 0.12s ease;
}
#omnibox:hover { border-color: var(--text-faint); background: var(--card-bg); }
.omnibox-ic { flex: none; opacity: 0.7; }
.omnibox-label { flex: 1; text-align: left; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.omnibox-kbd {
  flex: none;
  font-size: 11px;
  color: var(--text-faint);
  border: 1px solid var(--border);
  border-radius: 5px;
  padding: 1px 6px;
  background: var(--bg-primary);
}

/* Primary navigation — five rows at the top of the left sidebar. The sidebar
   is the app's permanent chrome (it stays on every view), so "where am I
   going" lives at the top of it and the note tree is always one click away. */
#primary-nav { display: flex; flex-direction: column; gap: 1px; padding: 10px 10px 8px; }
.pnav-btn {
  appearance: none;
  border: 0;
  background: transparent;
  color: var(--text-muted);
  font: inherit;
  font-size: 13px;
  font-weight: 500;
  display: flex;
  align-items: center;
  gap: 9px;
  text-align: left;
  padding: 6px 9px;
  border-radius: 8px;
  cursor: pointer;
  transition: background 0.12s ease, color 0.12s ease;
}
.pnav-btn:hover { background: var(--bg-hover); color: var(--text-normal); }
/* A page somebody switched off (Settings → General → Pages). Both .pnav-btn
   rules — this one and Daylight's dock version — set `display: flex`, which
   beats the browser's own [hidden] { display: none }, so the attribute does
   nothing on its own here. The button is hidden rather than removed because
   daylight-dom.js relocates these exact elements into its dock and keeps the
   handlers on them. Same guard base.css already carries for #hdr-more. */
.pnav-btn[hidden] { display: none !important; }
.pnav-btn.active { background: var(--text-normal); color: var(--bg-primary); font-weight: 600; }
.pnav-ic { display: inline-flex; width: 16px; height: 16px; opacity: 0.75; }
.pnav-ic svg { width: 16px; height: 16px; }
.pnav-btn.active .pnav-ic { opacity: 1; }
#editor { padding-bottom: 40px; }

/* Live-sync presence banner under the note header */
#note-presence {
  padding: 4px 18px;
  font-size: 12px;
  color: var(--accent);
  background: color-mix(in srgb, var(--accent) 9%, transparent);
  border-bottom: 1px solid color-mix(in srgb, var(--accent) 22%, transparent);
}
#note-presence.hidden { display: none; }

/* Inline PDF embeds (![[file.pdf]] in reading view) */
.tn-pdf { padding: 0; }
.tn-pdf-bar {
  display: flex; align-items: center; gap: 8px;
  padding: 8px 12px;
  border-bottom: 1px solid var(--border);
  background: var(--bg-secondary);
  border-radius: var(--radius-card) var(--radius-card) 0 0;
  font-size: 13px; color: var(--text-heading);
}
.tn-pdf-bar svg { width: 15px; height: 15px; flex: none; }
.tn-pdf-name { flex: 1 1 auto; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.tn-pdf-dl {
  flex: none; font-size: 12px; font-weight: 600;
  color: var(--accent); text-decoration: none;
  padding: 3px 10px; border-radius: 7px; border: 1px solid var(--border);
  /* A <button> since the download stopped being a link to a URL that may not
     resolve. These four lines are the difference between the two elements. */
  background: none; font-family: inherit; line-height: inherit; cursor: pointer;
}
.tn-pdf-dl:hover { background: var(--bg-hover); }
.tn-pdf-frame { display: block; width: 100%; height: 480px; border: 0; background: var(--bg-secondary); }

/* Full-page PDF view (first-class vault documents) */
#pdf-view { display: none; flex: 1; flex-direction: column; overflow: hidden; }
#pdf-view.visible { display: flex; }
#pdf-toolbar {
  display: flex; align-items: center; gap: 12px;
  padding: 10px 18px;
  border-bottom: 1px solid var(--border);
  background: var(--bg-secondary);
  font-size: 13px; color: var(--text-heading);
}
#pdf-title {
  flex: 1 1 auto; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  font-family: "Iowan Old Style", "Literata", "Palatino Linotype", Georgia, serif;
  font-size: 16px; font-weight: 650; color: var(--text-heading);
}
#pdf-frame { flex: 1; width: 100%; border: 0; background: var(--bg-secondary); }
.tree-pdf .tree-kind { color: var(--text-faint); }

/* Non-PDF file rendering (CSV / Excel / Word) — full page + inline embeds */
#file-render { flex: 1; overflow: auto; padding: 18px 24px; }
#file-sheets { display: flex; gap: 6px; flex-wrap: wrap; }
.tn-sheet-tab {
  font-size: 12px; font-weight: 600; color: var(--text-muted);
  padding: 3px 12px; border-radius: 100px; border: 1px solid var(--border);
  background: var(--card-bg); cursor: pointer;
}
.tn-sheet-tab:hover { color: var(--text-heading); }
.tn-sheet-tab.active { background: var(--accent); border-color: transparent; color: #fff; }
.tn-filedoc-table { overflow: auto; }
.tn-filedoc-table table { border-collapse: collapse; font-size: 13px; }
.tn-filedoc-table th, .tn-filedoc-table td {
  border: 1px solid var(--border); padding: 5px 10px; text-align: left;
  max-width: 340px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.tn-filedoc-table th { background: var(--bg-secondary); font-weight: 650; color: var(--text-heading); position: sticky; top: 0; }
.tn-filedoc-note { color: var(--text-faint); font-size: 12.5px; padding: 10px 2px; }
/* Plain text in a file document: a log, a README, a dataset with no delimiter.
   Wrapped rather than side-scrolling, because these are read, not scrubbed. */
.tn-filedoc-text {
  max-width: 900px;
  margin: 0;
  padding: 12px 14px;
  white-space: pre-wrap;
  overflow-wrap: anywhere;
  font: 12.5px/1.6 var(--mono, ui-monospace, SFMono-Regular, Menlo, monospace);
  color: var(--text);
  background: var(--bg-alt, transparent);
  border-radius: 8px;
}
.tn-filedoc-doc { max-width: 760px; }
.tn-filedoc-doc img { max-width: 100%; }
/* A slide deck reads as slides, not as one long column of runs: each slide is
   a card, each text box on it a block. */
.tn-deck .tn-slide {
  border: 1px solid var(--border); border-radius: 12px;
  padding: 18px 20px 20px; margin: 0 0 16px; background: var(--bg-secondary);
}
.tn-deck .tn-slide-n {
  font-size: 10.5px; font-weight: 700; letter-spacing: .09em; text-transform: uppercase;
  color: var(--text-faint); margin-bottom: 8px;
}
.tn-deck .tn-slide h3 { margin: 0 0 10px; font-size: 18px; line-height: 1.3; }
.tn-deck .tn-slide-block { margin: 0 0 10px; }
.tn-deck .tn-slide-block:last-child { margin-bottom: 0; }
.tn-deck .tn-slide-block p { margin: 0; }
.tn-deck .tn-slide-block ul { margin: 0; padding-left: 20px; }
.tn-deck .tn-slide-block li { margin: 2px 0; }
/* inline embed variant: cap the height, scroll inside */
.embed .tn-filedoc-body { max-height: 420px; overflow: auto; padding: 12px 14px; background: var(--card-bg); }

/* Notion-style block handles (edit mode, floating overlay — not editor content) */
:is(#block-handle, .pm-block-handle) {
  position: fixed; z-index: 900;
  display: none; align-items: center; gap: 1px;
  padding: 1px; border-radius: 8px;
}
:is(#block-handle, .pm-block-handle) button {
  display: grid; place-items: center;
  width: 22px; height: 22px;
  border-radius: 6px; color: var(--text-faint);
  cursor: pointer;
}
:is(#block-handle, .pm-block-handle) button:hover { background: var(--bg-hover); color: var(--text-heading); }
:is(#block-handle, .pm-block-handle) .bh-grip { cursor: grab; }
:is(#block-handle, .pm-block-handle) .bh-grip:active { cursor: grabbing; }
:is(#block-drop-line, .pm-block-drop-line) {
  position: fixed; z-index: 899; display: none;
  height: 3px; border-radius: 2px;
  background: var(--accent);
  box-shadow: 0 0 6px color-mix(in srgb, var(--accent) 60%, transparent);
  pointer-events: none;
}
.bh-dragging { opacity: 0.4; }
/* Notion-style gutter selection: whole blocks highlighted */
:is(#editor > .bh-selected, .editor2 .bh-selected) {
  background: color-mix(in srgb, var(--accent) 11%, transparent);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 11%, transparent);
  border-radius: 4px;
}
:is(#block-select-band, .pm-block-band) {
  position: fixed; z-index: 898; display: none;
  background: color-mix(in srgb, var(--accent) 7%, transparent);
  border: 1px solid color-mix(in srgb, var(--accent) 30%, transparent);
  border-radius: 4px;
  pointer-events: none;
}

/* ============ Engraved Paper surface (Settings → Appearance → Surface style) ============
   A material, not a theme: the frosted floating panels become one flat sheet
   with hairline dividers and serif note headings. Colors come from whatever
   theme is active — only the surfaces change. */
body.surface-paper { background: var(--bg-primary); }
body.surface-paper #app { padding: 0; gap: 0; }
body.surface-paper #left-sidebar, body.surface-paper #right-sidebar, body.surface-paper #main {
  background: transparent;
  backdrop-filter: none; -webkit-backdrop-filter: none;
  border: none; border-radius: 0; box-shadow: none;
}
body.surface-paper #left-sidebar { border-right: 1px solid var(--border); }
body.surface-paper #right-sidebar { border-left: 1px solid var(--border); }

/* Serif note headings — the engraving. UI text stays on the interface font. */
body.surface-paper #note-title,
body.surface-paper #split-title,
body.surface-paper .markdown-body h1,
body.surface-paper .markdown-body h2,
body.surface-paper .markdown-body h3 {
  font-family: "Iowan Old Style", "Literata", "Palatino Linotype", Georgia, serif;
  font-weight: 500;
  letter-spacing: 0;
}

/* Selection becomes a rubric line instead of a filled pill. */
body.surface-paper .tree-item.active {
  background: color-mix(in srgb, var(--accent) 9%, transparent);
  color: var(--accent-strong);
  box-shadow: inset 2.5px 0 0 var(--accent);
  border-radius: 0;
}
body.surface-paper .tree-item.active .tree-icon { color: var(--accent-strong); }

/* Tabs rest on the sheet as underlined names, not floating cards. */
body.surface-paper .tab { border-radius: 0; }
body.surface-paper .tab.active {
  background: transparent;
  box-shadow: inset 0 -2px 0 var(--accent);
}
body.surface-paper .sidebar-tab { border-radius: 0; }
body.surface-paper .sidebar-tab.active {
  background: transparent;
  box-shadow: inset 0 -2px 0 var(--accent);
}

/* ============ Sheet editor (editable CSV / Excel in the file view) ============ */
.sheet-editor { display: flex; flex-direction: column; height: 100%; min-height: 0; }
.se-toolbar {
  display: flex; align-items: center; gap: 6px; flex-wrap: wrap;
  padding: 7px 12px; border-bottom: 1px solid var(--border); flex-shrink: 0;
}
.se-status { font-size: 12px; color: var(--text-faint); }
.se-status.dirty { color: var(--text-muted); }
.se-status.error { color: #c0392b; }
.se-note { font-size: 11.5px; color: var(--text-faint); font-style: italic; }
.se-sep { width: 1px; height: 16px; background: var(--border); margin: 0 4px; }
.se-flex { flex: 1; }
.se-btn {
  font-size: 12px; padding: 4px 9px; border-radius: 7px;
  background: var(--chip-bg); color: var(--chip-text);
}
.se-btn:hover { background: var(--bg-hover); color: var(--text-heading); }
.se-quick { width: 180px; font-size: 12.5px; padding: 4px 9px; }
.se-count { font-size: 11.5px; color: var(--text-faint); font-family: var(--font-mono); }
.se-scroll { flex: 1; overflow: auto; outline: none; position: relative; min-height: 0; }
.se-canvas { position: relative; }
.se-head {
  position: sticky; top: 0; z-index: 3; display: grid; height: 28px;
  background: var(--bg-primary);
  border-bottom: 1.5px solid var(--border);
  box-shadow: 0 1px 0 color-mix(in srgb, var(--border) 60%, transparent);
}
.se-hcell {
  position: relative; display: flex; align-items: center; gap: 6px;
  padding: 0 8px; font-size: 12px; font-weight: 600; color: var(--text-muted);
  border-right: 1px solid var(--border); overflow: hidden; white-space: nowrap;
  user-select: none; cursor: pointer;
}
.se-hcell.sel { background: color-mix(in srgb, var(--accent) 10%, transparent); }
.se-hcell.filtered .se-hlabel { color: var(--accent); }
.se-hcell.se-corner { position: sticky; left: 0; z-index: 4; background: var(--bg-primary); cursor: default; }
.se-hlabel { font-family: var(--font-mono); font-size: 10px; color: var(--text-faint); flex-shrink: 0; }
.se-htext { overflow: hidden; text-overflow: ellipsis; flex: 1; min-width: 0; }
.se-resize { position: absolute; right: -3px; top: 0; bottom: 0; width: 7px; cursor: col-resize; z-index: 2; }
.se-resize:hover { background: color-mix(in srgb, var(--accent) 35%, transparent); }
.se-row { position: absolute; left: 0; right: 0; display: grid; height: 28px; }
.se-gutter {
  position: sticky; left: 0; z-index: 2; display: flex; align-items: center; justify-content: center;
  font-family: var(--font-mono); font-size: 10.5px; color: var(--text-faint);
  background: var(--bg-primary); border-right: 1px solid var(--border);
  border-bottom: 1px solid color-mix(in srgb, var(--border) 55%, transparent);
  user-select: none; cursor: pointer;
}
.se-gutter.sel { background: color-mix(in srgb, var(--accent) 10%, transparent); color: var(--accent); }
.se-cell {
  padding: 0 8px; display: flex; align-items: center; font-size: 12.5px;
  border-right: 1px solid color-mix(in srgb, var(--border) 55%, transparent);
  border-bottom: 1px solid color-mix(in srgb, var(--border) 55%, transparent);
  overflow: hidden; white-space: nowrap; cursor: cell;
  font-variant-numeric: tabular-nums;
}
.se-cell.sel { background: color-mix(in srgb, var(--accent) 9%, transparent); }
.se-cell.anchor { box-shadow: inset 0 0 0 2px var(--accent); }
.se-cell.se-formula { color: var(--accent-strong); }
.se-input {
  width: 100%; height: 100%; border: none; outline: 2px solid var(--accent);
  outline-offset: -2px; padding: 0 6px; font: inherit; background: var(--bg-primary);
  color: var(--text-normal); border-radius: 0;
}
.se-pastebox { position: fixed; left: -9999px; top: 0; width: 2px; height: 2px; opacity: 0; }

/* Media file documents */
.tn-filedoc-audio { width: 100%; margin: 18px 0; outline: none; }

/* ============ Reading Room (open) surface (Settings → Appearance → Surface style) ============
   The third surface material: NO BOXES. One continuous page on the theme's
   ground color; sidebars are typography on the page, not panels; only soft
   cards float. Each tab composes its own page via body[data-view] (stamped by
   showView). Colors come from the active theme — pairs best with Reading Room. */
body.surface-open { background: var(--bg-primary); }
body.surface-open #app { padding: 0 22px 22px; gap: 26px; }
body.surface-open #left-sidebar, body.surface-open #right-sidebar, body.surface-open #main {
  background: transparent;
  backdrop-filter: none; -webkit-backdrop-filter: none;
  border: none; border-radius: 0; box-shadow: none;
}
body.surface-open #left-sidebar { width: 252px; padding-top: 56px; }
body.surface-open #right-sidebar { width: 296px; padding-top: 56px; }

/* Serif engraving — the note voice, same treatment as paper. */
body.surface-open #note-title,
body.surface-open #split-title,
body.surface-open .markdown-body h1,
body.surface-open .markdown-body h2,
body.surface-open .markdown-body h3 {
  font-family: "Iowan Old Style", "Literata", "Palatino Linotype", Georgia, serif;
  font-weight: 500;
  letter-spacing: 0;
}

/* Header: a quiet strip on the page; the omnibox is the one floating card. */
body.surface-open #view-header { height: 56px; padding: 10px 0; }
body.surface-open #omnibox {
  max-width: 660px;
  height: 40px;
  background: var(--card-bg);
  border-color: var(--panel-border);
  border-radius: 12px;
  box-shadow: var(--shadow-card);
}
body.surface-open #omnibox:hover { border-color: var(--text-faint); }
body.surface-open .omnibox-kbd { background: var(--bg-primary); }

/* On a surface the active nav chip goes espresso-on-cream (theme-orthogonal:
   heading ink on the page ground). */
body.surface-open .pnav-btn.active { background: var(--text-heading); color: var(--bg-primary); }

/* Tabs rest on the page as quiet names; selection rows become ink pills. */
body.surface-open .tab { border-radius: 0; }
body.surface-open .tab.active { background: transparent; box-shadow: inset 0 -2px 0 var(--accent); }
body.surface-open .sidebar-tab { border-radius: 0; }
body.surface-open .sidebar-tab.active { background: transparent; box-shadow: inset 0 -2px 0 var(--accent); }
body.surface-open .tree-item.active {
  background: color-mix(in srgb, var(--text-heading) 94%, var(--bg-primary));
  color: var(--bg-primary);
  border-radius: 9px;
  box-shadow: none;
}
body.surface-open .tree-item.active .tree-icon { color: inherit; }

/* Per-view composition: the LEFT sidebar is permanent chrome — it stays on
   every full-page tab so the primary nav and the note tree never leave the
   screen. Only the RIGHT rail steps off: it is note-scoped (connections,
   outline, panels of the open note) and means nothing on Graph or Library. */
body[data-view="graph"] #right-sidebar,
body[data-view="canvas"] #right-sidebar,
body[data-view="library"] #right-sidebar,
body[data-view="study"] #right-sidebar,
body[data-view="studyhome"] #right-sidebar,
body[data-view="todos"] #right-sidebar,
/* Home and Calendar are full pages too. Calendar was missing from this list, so
   it kept showing the connections of whatever note was open before — a panel
   about a note that is not on screen. */
body[data-view="calendar"] #right-sidebar,
body[data-view="home"] #right-sidebar { display: none; }

/* ---- Reading Room: the Write page ----
   The document column owns the note voice: quiet tab chips (only when more
   than one note is open), a breadcrumb + presence + save-notice line, the big
   serif title (the SAME #note-title element — it is the rename affordance),
   a quiet edit-only toolbar, and word/card counters floating bottom-right in
   place of the status bar. */

/* Header first, then chips: the header is the page's one fixed line. */
body.surface-open #view-header { order: -1; }
body.surface-open:not([data-view="note"]):not([data-view="pdf"]):not([data-view="base"]) #tab-bar { display: none; }
body.surface-open #tab-bar:not(:has(.tab + .tab)) { display: none; }
body.surface-open #tab-bar {
  max-width: var(--editor-max-width);
  width: 100%;
  margin: 0 auto;
  padding: 8px 36px 0;
}
body.surface-open .tab {
  padding: 4px 8px 4px 12px;
  font-size: 12px;
  border-radius: 999px;
  background: transparent;
}
body.surface-open .tab.active {
  background: var(--bg-hover);
  color: var(--text-heading);
  box-shadow: none;
  font-weight: 550;
}

/* Breadcrumb line: FOLDER / NOTE · live presence · gold save-gate notice. */
#doc-crumb {
  display: flex;
  align-items: center;
  gap: 14px;
  min-height: 18px;
  margin: 10px 0 8px;
}
#doc-crumb { min-width: 0; }
#crumb-path {
  font-size: 10.5px;
  font-weight: 650;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--text-faint);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  min-width: 0;
  flex: 0 1 auto;
}
#doc-crumb #note-presence {
  background: transparent;
  border: none;
  padding: 0;
  font-size: 11.5px;
  color: var(--chip-text);
  display: inline-flex;
  align-items: center;
  gap: 6px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
#doc-crumb #note-presence.hidden { display: none; }
#doc-crumb #note-presence::before {
  content: "";
  flex: none;
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--accent);
}
#crumb-notice {
  font-size: 11.5px;
  color: var(--chip-text);
  background: var(--chip-bg);
  padding: 2px 11px;
  border-radius: 999px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
#crumb-notice.hidden { display: none; }

/* The big serif document title — the rename affordance. Never display:none.
   UNIVERSAL since 2026-07-22 (user decision): every surface shows it. */
#editor-container #note-title {
  display: block;
  font-family: "Iowan Old Style", "Literata", "Palatino Linotype", Georgia, serif;
  flex: none;
  font-size: 42px;
  line-height: 1.12;
  font-weight: 700;
  letter-spacing: -0.012em;
  color: var(--text-heading);
  white-space: normal;
  overflow: visible;
  text-overflow: clip;
  text-align: left;
  text-wrap: balance;
  max-width: none;
  padding: 0;
  margin: 0 0 20px;
  border-radius: 10px;
  cursor: text;
  min-height: 20px; /* stays clickable even while empty */
}
#editor-container #note-title:hover { background: transparent; opacity: 0.85; }
/* RENAMING LOOKS ONE WAY, hovered or not.

   The base .inline-rename dresses a small tree label: a filled background,
   padding, a radius and a ring around it. This rule replaced only the
   box-shadow, so a 36px heading in rename mode kept the filled box underneath —
   and #note-title:hover sets `background: transparent`, which stripped it again
   the moment the pointer was over it. Same state, two looks, depending on where
   the mouse happened to be. The underline IS the treatment; the small-label
   chrome is undone here. */
#editor-container #note-title.inline-rename {
  outline: none;
  box-shadow: inset 0 -2px 0 var(--accent);
  opacity: 1;
  background: transparent;
  padding: 0;
  border-radius: 0;
}
/* …and hover must not move it mid-rename. */
#editor-container #note-title.inline-rename:hover { background: transparent; opacity: 1; }

/* Edit toolbar: a quiet icon row on the column (edit mode only, as before). */
body.surface-open #toolbar {
  border-bottom: none;
  max-width: var(--editor-max-width);
  width: 100%;
  margin: 0 auto;
  padding: 2px 32px 4px;
}
body.surface-open #toolbar button { background: transparent; color: var(--text-faint); }
body.surface-open #toolbar button:hover { background: var(--bg-hover); color: var(--text-heading); }

/* Find & replace: a floating capsule at the top of the column (Cmd+F). */
body.surface-open #find-bar {
  position: absolute;
  top: 58px;
  left: 50%;
  transform: translateX(-50%);
  width: min(660px, calc(100% - 48px));
  z-index: 45;
  background: var(--card-bg);
  border: 1px solid var(--panel-border);
  border-radius: 14px;
  box-shadow: var(--shadow-panel);
  padding: 9px 14px;
}
body.surface-open #find-bar.hidden { display: none; }

/* The status bar dies: save + words + cards float bottom-right as quiet text. */
body.surface-open #status-bar {
  position: fixed;
  right: 24px;
  bottom: 22px;
  left: auto;
  z-index: 30;
  border-top: none;
  background: transparent;
  padding: 0;
  gap: 9px;
}
body.surface-open:not([data-view="note"]) #status-bar { display: none; }
/* The same decision on every surface: a note's card count, backlinks, words and
   characters describe the NOTE, and on Home, To-dos, Calendar or the Library
   they were the last-open note's numbers under a page that is not that note —
   "6 words · 1 min read" beneath a list of forty tasks. Save and sync status
   are about the app, so they stay. */
body:not([data-view="note"]) #status-cards,
body:not([data-view="note"]) #status-backlinks,
body:not([data-view="note"]) #status-words,
body:not([data-view="note"]) #status-chars { display: none; }
body.surface-open #status-backlinks,
body.surface-open #status-chars,
body.surface-open #status-bar .status-spacer { display: none; }

/* Sync pill lives in the header now (the element relocates there). */
body.surface-open .header-actions #status-sync {
  font-size: 11.5px;
  color: var(--text-muted);
  font-family: var(--font-ui);
  padding: 4px 10px;
  border-radius: 999px;
  white-space: nowrap;
}
body.surface-open .header-actions #status-sync:hover { background: var(--bg-hover); color: var(--text-heading); }
body.surface-open .header-actions #status-sync.pending { color: var(--accent); }

/* The split button belongs to the note page only. */


/* Narrow windows: the counters step above the nav pill instead of under it. */
@media (max-width: 980px) {
  body.surface-open #status-bar { bottom: 74px; right: 16px; }
}

/* ---- Reading Room: the Write left rail — typography, not a panel ---- */
/* The pane switcher hides in the default Files state, but reappears whenever
   another pane is active (Cmd+Shift+F lands on Search — there must be a way
   back to the file tree). */
body.surface-open #left-sidebar .sidebar-tabs { display: none; }
body.surface-open #left-sidebar:has(.sidebar-pane.active:not(#pane-files)) .sidebar-tabs { display: flex; }
body.surface-open #pane-files .pane-header { flex-wrap: wrap; padding: 0 6px 8px; }
body.surface-open #pane-files .brand-row { width: 100%; padding: 2px 4px 10px; }
body.surface-open #pane-files .pane-actions { display: flex; width: 100%; gap: 8px; }
body.surface-open #pane-files .pane-actions [data-action="new-note"] {
  flex: 1;
  height: 38px;
  border-radius: 11px;
  background: var(--text-heading);
  color: var(--bg-primary);
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
}
body.surface-open #pane-files .pane-actions [data-action="new-note"]:hover { opacity: 0.92; background: var(--text-heading); color: var(--bg-primary); }
body.surface-open #pane-files .pane-actions [data-action="new-note"]::after {
  content: "Note";
  font-size: 13px;
  font-weight: 600;
}
body.surface-open #pane-files .pane-actions [data-action="new-folder"],
body.surface-open #pane-files .pane-actions #sort-btn {
  width: 38px;
  height: 38px;
  border: 1px solid var(--border);
  border-radius: 11px;
  color: var(--text-muted);
}

/* Top-level folders read as uppercase section labels. */
body.surface-open #file-tree > .tree-item.tree-folder {
  font-size: 10.5px;
  font-weight: 650;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--text-faint);
  background: transparent;
  margin-top: 12px;
}
body.surface-open #file-tree > .tree-item.tree-folder .tree-chevron { display: none; }
body.surface-open #file-tree > .tree-item.tree-folder.collapsed-folder { opacity: 0.6; }

/* Hover "+" on folder rows: a note right where you're looking. */
.tree-add { display: none; }
body.surface-open .tree-item.tree-folder:hover .tree-add {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 18px;
  height: 18px;
  margin-left: 4px;
  border-radius: 6px;
  color: var(--text-faint);
  font-size: 13px;
  line-height: 1;
}
body.surface-open .tree-add:hover { background: var(--bg-hover); color: var(--text-heading); }

/* Rail foot: the Library page in one click. */

/* ---- Reading Room: the right rail ----
   The rail is the block list now (see Panel blocks), identical on every
   surface — so this surface only softens the frame around it. Block ORDER is
   the user's, stored per side; nothing here may reorder it. */
body.surface-open #right-sidebar { padding-right: 2px; }
body.surface-open .pb-list { gap: 12px; }
body.surface-open .wg-card { border-color: var(--panel-border); border-radius: 14px; }

/* ---- Reading Room: the Library page ----
   The view brings its own left rail (folders + counts, Canvases/Tables/
   Files/Trash rows, + New folder) above soft cards for Tags, Saved
   searches, Bookmarks, and Workspaces. Works on every surface — the open
   surface just drops the app rails around it. */
.lib-wrap {
  height: 100%;
  min-height: 0;
}
/* The kind groups (Canvases · Tables · Files · Trash) in the grid header —
   the one part of the old rail the app sidebar can't say. */
.lib-kinds { display: flex; gap: 6px; margin-left: 18px; }
.lib-kind {
  font-size: 11.5px;
  padding: 4px 11px;
  border-radius: 999px;
  background: var(--bg-hover);
  color: var(--text-muted);
  cursor: pointer;
}
.lib-kind:hover { color: var(--text-heading); }
.lib-kind.active { background: var(--chip-bg); color: var(--chip-text); font-weight: 600; }
.lib-sort {
  margin-left: auto;
  border: 1px solid var(--border);
  background: transparent;
  color: var(--text-muted);
  font-size: 12px;
  padding: 6px 13px;
  border-radius: 999px;
  cursor: pointer;
}
.lib-sort:hover { color: var(--text-heading); border-color: var(--text-faint); }
.lib-when {
  margin-left: auto;
  font-size: 10px;
  font-weight: 650;
  letter-spacing: 0.07em;
  color: var(--chip-text);
}
.lib-card-title { display: flex; align-items: center; gap: 8px; }
.lib-chip-due { background: var(--chip-bg); color: var(--chip-text); font-weight: 600; }
body.surface-open .lib-title,
body.surface-open .lib-card-title { font-family: "Iowan Old Style", "Literata", "Palatino Linotype", Georgia, serif; }
/* A quiet, clickable nudge when someone types into reading view. */
#mode-hint {
  position: fixed;
  bottom: 84px; /* clear of the floating nav pill */
  left: 50%;
  transform: translateX(-50%) translateY(8px);
  z-index: 60;
  background: var(--card-bg);
  border: 1px solid var(--panel-border);
  border-radius: 999px;
  box-shadow: var(--shadow-panel);
  color: var(--text-normal);
  font-size: 12.5px;
  padding: 8px 16px;
  cursor: pointer;
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.15s ease, transform 0.15s ease;
}
#mode-hint.show { opacity: 1; pointer-events: auto; transform: translateX(-50%) translateY(0); }
#mode-hint:hover { color: var(--text-heading); border-color: var(--text-faint); }

/* READING VIEW, SAID AT THE TOP OF THE NOTE (index.html #reading-bar, shown by
   views.js setMode). Sticky and zero-height, like #outline-float: the pill
   hangs from the top of the note scroller and stays there as the note
   scrolls, and switching views moves no text — at the top of a note it sits
   in the column's own top padding, above the crumb line. */
#reading-bar {
  position: sticky;
  top: 0;
  height: 0;
  z-index: 61;
  display: flex;
  justify-content: center;
  align-items: flex-start;
  pointer-events: none;
}
#reading-bar[hidden] { display: none; }
#reading-bar-btn {
  pointer-events: auto;
  margin-top: 6px;
  display: inline-flex;
  align-items: center;
  gap: 8px;
  max-width: calc(100% - 32px);
  height: 28px;
  padding: 0 12px 0 10px;
  border: 1px solid var(--border);
  border-radius: 999px;
  background: var(--card-bg);
  box-shadow: var(--shadow-panel);
  color: var(--text-muted);
  font: 500 12.5px/1 var(--font-ui);
  white-space: nowrap;
  cursor: pointer;
  transition: color 0.12s ease, border-color 0.12s ease;
}
#reading-bar-btn:hover { color: var(--text-heading); border-color: var(--accent); }
#reading-bar-btn:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
#reading-bar .rb-ic { display: inline-flex; color: var(--accent); }
#reading-bar .rb-ic svg { width: 15px; height: 15px; }
#reading-bar .rb-what { color: var(--text-heading); font-weight: 600; }
#reading-bar .rb-how { overflow: hidden; text-overflow: ellipsis; }
#reading-bar .rb-tap { display: none; }
#reading-bar kbd {
  display: inline-block;
  margin: 0 1px;
  padding: 2px 6px;
  border: 1px solid var(--border);
  border-radius: 5px;
  background: var(--chip-bg);
  color: var(--chip-text);
  font: 600 11.5px/1.2 var(--font-ui);
}
/* Typing in reading view: the bar asks to be looked at (shell.js showModeHint). */
#reading-bar.rb-nudge #reading-bar-btn { animation: rb-nudge 0.5s ease; border-color: var(--accent); }
@keyframes rb-nudge {
  0%, 100% { transform: translateX(0); }
  20% { transform: translateX(-4px); }
  40% { transform: translateX(4px); }
  60% { transform: translateX(-3px); }
  80% { transform: translateX(2px); }
}
@media (prefers-reduced-motion: reduce) {
  #reading-bar.rb-nudge #reading-bar-btn { animation: none; }
}
/* A touch screen has no ⌘E to press — the bar is the way in. */
@media (pointer: coarse) {
  #reading-bar .rb-how { display: none; }
  #reading-bar .rb-tap { display: inline; }
}

/* The scoped-search input replaces the omnibox button in the header (an
   input may not live INSIDE a button), so it wears the same capsule. */
.omni-live {
  flex: 1 1 auto;
  max-width: 560px;
  margin: 0 auto;
  height: 38px;
  padding: 0 14px;
  background: var(--bg-secondary);
  border: 1px solid var(--border);
  border-radius: 10px;
  color: var(--text-normal);
  font: inherit;
  font-size: 13.5px;
  outline: none;
  width: auto;
}
body.surface-open .omni-live {
  max-width: 660px;
  height: 40px;
  background: var(--card-bg);
  border-color: var(--panel-border);
  border-radius: 12px;
  box-shadow: var(--shadow-card);
}
.omni-live:focus { border-color: var(--accent); box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 18%, transparent); }

/* ---- Reading Room: the Graph page ----
   Full-bleed dot-grid world (the rails already leave via body[data-view]);
   the settings accordion floats as one soft card, the stats read as a quiet
   chip. Every existing control stays. */
body.surface-open #graph-container {
  background-image: radial-gradient(color-mix(in srgb, var(--text-heading) 9%, transparent) 1px, transparent 1px);
  background-size: 26px 26px;
}
body.surface-open #graph-settings {
  top: 22px;
  right: 26px;
  width: 288px;
  background: var(--card-bg);
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
  border: 1px solid var(--panel-border);
  border-radius: 14px;
  box-shadow: var(--shadow-card);
  padding: 16px;
}
body.surface-open #graph-info {
  left: 26px;
  bottom: 24px;
  font-family: var(--font-ui);
  color: var(--text-muted);
  background: var(--card-bg);
  border: 1px solid var(--panel-border);
  border-radius: 999px;
  padding: 7px 14px;
  box-shadow: var(--shadow-card);
}
body.surface-open #graph-legend {
  background: var(--card-bg);
  border: 1px solid var(--panel-border);
  border-radius: 12px;
  box-shadow: var(--shadow-card);
}

/* ---- Reading Room: the Study page ----
   Stats, forecast, Study now, and decks form the page's own left column
   (the renderer is the old sidebar pane's, re-homed); sessions run in the
   main area beside it. Works on every surface. */
#study-home { display: none; flex: 1; min-height: 0; }

/* ONE THING AT A TIME, AND IT GETS THE PAGE.

   This was a 300px rail beside `minmax(0, 1fr)`, and the 1fr held a panel that
   said "Nothing in session. Pick a deck on the left, or press Study now." So
   on a 1,400px window the dashboard, the decks and everything else were
   crammed into 300px while eleven hundred said there was nothing to show —
   and the moment a session DID start, the dashboard sat beside it narrow and
   unreadable instead of getting out of the way.

   The Daylight surface had already worked this out and solved it in its own
   stylesheet; this is the same answer in the base, so every surface gets it:
   no session, the page is the dashboard; session running, the page is the
   session. The empty panel is gone rather than hidden — see index.html. */
#study-home.visible {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  padding: 14px 26px 0;
}
body[data-view="studyhome"] #study-home-main { display: none; }
body[data-view="study"] #study-home-left { display: none; }
body[data-view="study"] #study-home.visible { padding: 0; }
/* MEASURED ON THE COLUMN, NOT THE WINDOW — the same move #split-pane makes,
   and for the same reason: what decides whether two columns fit is how much
   room this page actually got, and that depends on the sidebars. A 1,200px
   window with both rails open leaves about 600px here, which a viewport media
   query would happily call wide enough for a 320px side column beside a deck
   list. */
#study-home-left {
  container-type: inline-size;
  overflow-y: auto;
  padding-bottom: 90px;
  display: flex;
  flex-direction: column;
  gap: 18px;
  min-height: 0;
}
#study-home-main { position: relative; min-width: 0; min-height: 0; display: flex; flex-direction: column; }
#study-home #study-view { flex: 1; }

/* Decks on the left, where you act; what you glance at on the right. Same
   shape and the same breakpoint idiom as .cv-cols on the Calendar page —
   stacked once there is no room for two, decks first, because the decks are
   what the page is for. `align-items: start` so a short side column does not
   stretch its cards down the length of a long deck list. */
.sh-cols { display: grid; grid-template-columns: minmax(0, 1fr) 320px; gap: 28px; align-items: start; }
.sh-cols.sh-no-side { grid-template-columns: minmax(0, 1fr); }
@container (max-width: 720px) { .sh-cols { grid-template-columns: 1fr; gap: 18px; } }
.sh-col-decks { min-width: 0; }
.sh-col-side { min-width: 0; display: flex; flex-direction: column; gap: 14px; }
/* In a column of their own these are cards, not run-on sections: the rule and
   the top margin they used to separate themselves with inside one long stack
   are exactly what a gap already says here. */
.sh-col-side > * { margin-top: 0; border-top: 0; padding-top: 0; }

/* The old sidebar dashboard, restyled as page furniture. */
#study-home #study-dash { border-bottom: none; padding: 0; flex-shrink: 0; }
/* Across the page now rather than two-by-two in a 300px rail. auto-fit rather
   than a fixed four, so the row answers to the space it is actually in — four
   on a wide page, two in a narrow column, without a breakpoint to keep in step
   with the one above. */
#study-home .sd-numbers {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
  gap: 12px; margin-bottom: 12px;
}
#study-home .sd-stat {
  background: var(--card-bg);
  border: 1px solid var(--panel-border);
  border-radius: 14px;
  box-shadow: var(--shadow-card);
  padding: 12px 15px;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 3px;
}
#study-home .sd-n { font-size: 22px; font-family: var(--font-ui); }
#study-home .sd-forecast {
  background: var(--card-bg);
  border: 1px solid var(--panel-border);
  border-radius: 14px;
  box-shadow: var(--shadow-card);
  height: 62px;
  padding: 12px 14px;
  gap: 5px;
  margin-bottom: 12px;
}
/* THE TWO ACTIONS ARE BUTTONS, NOT BANDS. `width: 100%` was right when the
   dashboard was a 300px rail; on a full-width page it drew Study now as a
   1,100px bar with four words floating in the middle of it, and Statistics as
   a second one underneath. Auto width puts them side by side at the size of
   what they say. */
#study-home .sd-study-btn,
#study-home .sd-stats-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: auto;
  min-width: 170px;
  height: 40px;
  margin: 0;
  padding: 0 22px;
  border-radius: 12px;
  font-size: 14px;
  font-weight: 600;
}
#study-home .sd-study-btn {
  background: var(--text-heading);
  color: var(--bg-primary);
  box-shadow: none;
}
#study-home .sd-stats-btn { margin-left: 8px; }
#study-home .sd-study-btn:hover { background: var(--text-heading); opacity: 0.92; }
#study-home .sd-study-btn:disabled { background: var(--bg-tertiary); color: var(--text-faint); opacity: 1; }
/* The fortnight ahead, given room to be a chart rather than a strip — it is
   the full width of the page now, and 62px tall over 1,100px wide reads as a
   rule with lumps on it. */
#study-home .sd-forecast { height: 96px; align-items: flex-end; }
#study-home #study-decks {
  background: var(--card-bg);
  border: 1px solid var(--panel-border);
  border-radius: 14px;
  box-shadow: var(--shadow-card);
  padding: 8px 8px 10px;
  overflow-y: auto;
}
/* The name's hitbox is the text, not the stretched flex slot — whitespace
   right of a short name still starts the session (the row's action). */
#study-home .deck-name { flex: 0 1 auto; margin-right: auto; min-width: 0; }
#study-home .deck-name:hover { text-decoration: underline; }

/* The session reads as one serif card on the open surface. */
body.surface-open #study-card {
  background: var(--card-bg);
  border: 1px solid var(--panel-border);
  border-radius: 16px;
  box-shadow: var(--shadow-card);
}
body.surface-open #study-front {
  font-family: "Iowan Old Style", "Literata", "Palatino Linotype", Georgia, serif;
  font-size: clamp(20px, 2.6vw, 32px);
  color: var(--text-heading);
  text-align: center;
  text-wrap: balance;
}
body.surface-open #study-source { color: var(--chip-text); }

/* ---- Reading Room: the Canvas page ----
   The same dot-grid world as Graph: a floating board picker top-left, the
   tool bar becomes a vertical card on the right, zoom reads in a corner
   chip. All existing tools stay. */
body.surface-open #canvas-view {
  background-image: radial-gradient(color-mix(in srgb, var(--text-heading) 9%, transparent) 1px, transparent 1px);
  background-size: 26px 26px;
}
#cv-pick {
  position: absolute;
  top: 18px;
  left: 26px;
  z-index: 20;
  display: flex;
  align-items: center;
  gap: 10px;
  background: var(--card-bg);
  border: 1px solid var(--panel-border);
  border-radius: 12px;
  box-shadow: var(--shadow-card);
  padding: 8px 12px;
}
#cv-pick-name { font-size: 13px; font-weight: 600; color: var(--text-heading); }
#cv-pick-name .cv-caret { color: var(--text-faint); font-size: 10px; }
#cv-pick-new { font-size: 12px; color: var(--chip-text); }
#cv-pick button:hover { opacity: 0.8; }
#cv-zoom {
  position: absolute;
  right: 26px;
  bottom: 24px;
  z-index: 20;
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 12px;
  color: var(--text-muted);
  background: var(--card-bg);
  border: 1px solid var(--panel-border);
  border-radius: 999px;
  padding: 6px 12px;
  box-shadow: var(--shadow-card);
}
#cv-zoom button { font-size: 14px; color: var(--text-muted); padding: 0 3px; }
#cv-zoom button:hover { color: var(--text-heading); }
#cv-zoom-val { font-variant-numeric: tabular-nums; min-width: 34px; text-align: center; }
body.surface-open .cv-toolbar {
  top: 50%;
  left: auto;
  right: 26px;
  transform: translateY(-50%);
  flex-direction: column;
  gap: 3px;
  padding: 8px 6px;
  background: var(--card-bg);
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
  border: 1px solid var(--panel-border);
  border-radius: 14px;
  box-shadow: var(--shadow-card);
}
body.surface-open .cv-toolbar > button {
  width: 36px;
  height: 36px;
  justify-content: center;
  font-size: 11px;
}
body.surface-open .cv-toolbar button span { display: none; }
body.surface-open .cv-colors {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 5px;
  padding: 5px 0;
}

/* ---- Reading Room: documents go full-width; guides float ----
   PDFs, sheets, tables, Word, and audio open as tab chips; the right rail
   yields so the document column takes the room. Their toolbars read as a
   quiet serif title line with the document's own tools + Download. */
body.surface-open[data-view="pdf"] #right-sidebar,
body.surface-open[data-view="base"] #right-sidebar { display: none; }
body.surface-open #pdf-toolbar,
body.surface-open #base-toolbar {
  border-bottom: none;
  background: transparent;
  padding: 10px 26px 6px;
}
body.surface-open #pdf-title {
  font-family: "Iowan Old Style", "Literata", "Palatino Linotype", Georgia, serif;
  font-size: 24px;
  font-weight: 650;
  color: var(--text-heading);
}
body.surface-open #pdf-download {
  font-size: 12px;
  color: var(--chip-text);
  background: var(--chip-bg);
  border-radius: 999px;
  padding: 4px 12px;
}
#base-title { display: none; }
body.surface-open #base-title {
  display: block;
  font-family: "Iowan Old Style", "Literata", "Palatino Linotype", Georgia, serif;
  font-size: 24px;
  font-weight: 650;
  color: var(--text-heading);
  margin-right: 12px;
  white-space: nowrap;
}

/* Hotkeys + Features guides: floating cards over any page, on every surface.
   They live at body level, so they outlive the right rail — which leaves
   entirely on the full-page views. */
body > .sidebar-pane[id^="rpane-"] { display: none; }
body > .sidebar-pane[id^="rpane-"].active {
  display: flex;
  flex-direction: column;
  position: fixed;
  top: 64px;
  right: 24px;
  bottom: 96px;
  width: 348px;
  z-index: 70;
  background: var(--card-bg);
  border: 1px solid var(--panel-border);
  border-radius: 14px;
  box-shadow: var(--shadow-panel);
  overflow: hidden;
  padding: 6px 4px;
}

/* Phase 2 — rich content */
/* Bookmark cards: a lone external link in its own paragraph. */
.markdown-body a.tn-bookmark {
  display: block; padding: 12px 16px; margin: 2px 0;
  border: 1px solid var(--panel-border); border-radius: 12px;
  background: var(--card-bg); box-shadow: var(--shadow-card);
  font-weight: 600; color: var(--text-heading); text-decoration: none;
  overflow-wrap: anywhere;
}
.markdown-body a.tn-bookmark:hover { border-color: var(--accent); }
.markdown-body a.tn-bookmark::after {
  content: attr(href); display: block; margin-top: 2px;
  font-size: 12px; font-weight: 400; color: var(--text-faint);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
/* YouTube player decoration under the link. */
.tn-yt { margin: 8px 0 2px; }
.tn-yt iframe { width: 100%; aspect-ratio: 16 / 9; border: 0; border-radius: 12px; display: block; }
/* Image resize overlay. */
:is(#img-resize, .pm-img-resize) { position: fixed; z-index: 70; display: none; pointer-events: none;
  border: 2px solid var(--accent); border-radius: 6px; }
:is(#img-resize, .pm-img-resize) .ir-handle { position: absolute; right: -7px; bottom: -7px; width: 14px; height: 14px;
  background: var(--accent); border: 2px solid var(--card-bg); border-radius: 50%;
  cursor: ew-resize; pointer-events: auto; }
:is(#img-resize, .pm-img-resize) .ir-label { position: absolute; left: 6px; top: 6px; font-size: 11px;
  font-family: var(--font-mono, ui-monospace, monospace); color: #fff;
  background: color-mix(in srgb, var(--accent) 85%, black); padding: 1px 7px; border-radius: 6px; }

/* ---- Image occlusion ---- */
/* The figure is a positioned box; its img sizes normally. The mask overlay
   (edit + reading mode) covers the target regions. */
figure.tn-occ { position: relative; display: block; margin: 0.6em 0; width: fit-content; max-width: 100%; }
figure.tn-occ img { display: block; max-width: 100%; }
.tn-occ-layer { position: absolute; inset: 0; pointer-events: none; }
.tn-occ-mask { position: absolute; background: #414a63; border: 1px solid #2a3047; border-radius: 2px; }
/* Mask editor overlay (body-level, over the selected image). Mostly opaque so
   it's clear what a box covers, in a neutral slate that reads on any image. */
#img-occ { position: fixed; z-index: 71; }
#img-occ .occ-surface { position: absolute; inset: 0; cursor: crosshair; }
#img-occ .occ-box { position: absolute; background: rgba(65,74,99,0.82); border: 1.5px solid #8b97b8; border-radius: 2px; cursor: move; }
#img-occ .occ-box.sel { border-color: var(--accent); box-shadow: 0 0 0 2px color-mix(in srgb, var(--accent) 40%, transparent); }
#img-occ .occ-box-handle { position: absolute; right: -6px; bottom: -6px; width: 12px; height: 12px;
  background: var(--accent); border: 2px solid #fff; border-radius: 50%; cursor: nwse-resize; }
#img-occ .occ-toolbar { position: absolute; left: 0; right: 0; bottom: -40px; display: flex; align-items: center;
  justify-content: space-between; gap: 10px; background: var(--card-bg); border: 1px solid var(--border);
  border-radius: 8px; padding: 6px 10px; box-shadow: var(--shadow-card); }
#img-occ .occ-hint { font-size: 11.5px; color: var(--text-faint); }
#img-occ .occ-done { background: var(--accent); color: #fff; border: none; border-radius: 6px; padding: 4px 14px; font-size: 13px; font-weight: 600; cursor: pointer; }
/* Study rendering: covers hide regions; the target is highlighted, revealed on the back. */
.study-occ { position: relative; display: inline-block; max-width: 100%; }
.study-occ img { display: block; max-width: 100%; max-height: 60vh; border-radius: 8px; }
.study-occ .occ-cover { position: absolute; background: #414a63; border: 1px solid #2a3047; border-radius: 2px; }
.study-occ .occ-cover.occ-target { background: #4a72ff; border-color: #2f5aef; box-shadow: 0 0 0 2px color-mix(in srgb, #4a72ff 35%, transparent); }
.study-occ .occ-cover.occ-revealed { background: transparent; border: 2px solid #2e9e5b; box-shadow: 0 0 0 2px color-mix(in srgb, #2e9e5b 30%, transparent); }
/* Table tools bar. */
#table-tools { position: fixed; z-index: 70; display: none; gap: 4px;
  background: var(--card-bg); border: 1px solid var(--panel-border); border-radius: 8px;
  padding: 2px 4px; box-shadow: var(--shadow-card); font-size: 12px; }
#table-tools button { font: inherit; color: var(--text-muted); background: none; border: none;
  padding: 3px 9px; border-radius: 6px; cursor: pointer; }
#table-tools button:hover { background: var(--bg-hover); color: var(--text-heading); }

/* Phase 3 — columns, text colors */
/* Columns — borderless like Notion; stretch so every column is the full row
   height, which makes the whole column area clickable (not just the text). */
.markdown-body .cols { display: flex; gap: 22px; margin: 0.6em 0; align-items: stretch; }
.markdown-body .cols .col { flex: 1 1 0; min-width: 0; }
.markdown-body .cols .col > :first-child { margin-top: 0; }
/* Empty column keeps a little height so it stays clickable while editing. */
#editor[contenteditable="true"] .cols .col:empty { min-height: 1.8em; }
#editor[contenteditable="true"] .cols .col { border-radius: 6px; transition: background 0.1s; }
#editor[contenteditable="true"] .cols .col:hover { background: color-mix(in srgb, var(--text-heading) 3%, transparent); }
@media (max-width: 700px) { .markdown-body .cols { flex-direction: column; gap: 6px; } }
.tn-color-red    { color: #D14D41; }
.tn-color-orange { color: #DA702C; }
.tn-color-yellow { color: #C9A227; }
.tn-color-green  { color: #4FA860; }
.tn-color-blue   { color: #4385BE; }
.tn-color-purple { color: #8B7EC8; }
.tn-color-pink   { color: #CE5D97; }
.tn-color-gray   { color: #878580; }
/* Highlighter colours.

   A highlighter is INK ON PAPER, not a text colour: the text stays readable and
   the paper behind it changes. So these set a background and deliberately leave
   `color` alone — inheriting whatever the theme (or a tn-color- span inside)
   already decided. That is also what makes the two features compose: you can
   highlight red text in blue and both survive.

   color-mix against the page background rather than fixed pastels, so a
   highlight that reads as a soft wash in the light themes does not glow in the
   dark ones. */
mark[class^="tn-hl-"] {
  background: var(--tn-hl); color: inherit;
  border-radius: 3px; padding: 0 2px;
  box-decoration-break: clone; -webkit-box-decoration-break: clone;
}
.tn-hl-red    { --tn-hl: color-mix(in srgb, #D14D41 26%, var(--bg-primary)); }
.tn-hl-orange { --tn-hl: color-mix(in srgb, #DA702C 26%, var(--bg-primary)); }
.tn-hl-yellow { --tn-hl: color-mix(in srgb, #C9A227 30%, var(--bg-primary)); }
.tn-hl-green  { --tn-hl: color-mix(in srgb, #4FA860 26%, var(--bg-primary)); }
.tn-hl-blue   { --tn-hl: color-mix(in srgb, #4385BE 26%, var(--bg-primary)); }
.tn-hl-purple { --tn-hl: color-mix(in srgb, #8B7EC8 26%, var(--bg-primary)); }
.tn-hl-pink   { --tn-hl: color-mix(in srgb, #CE5D97 26%, var(--bg-primary)); }
.tn-hl-gray   { --tn-hl: color-mix(in srgb, #878580 24%, var(--bg-primary)); }

.tb-color-a { font-weight: 700; background: linear-gradient(90deg,#D14D41,#DA702C,#4FA860,#4385BE,#8B7EC8); -webkit-background-clip: text; background-clip: text; color: transparent; }

/* ============================ Panel blocks ============================
   Each side panel is ONE scroller holding an ordered list of blocks: the
   built-in panels (Connections, Outline, Recent, Study, Calendar, Graph) and
   the widgets the user adds, in the same list, with the same header, grip and
   ••• menu. They sit inside the existing sidebars, so they inherit panel width
   and theme tokens rather than carrying a palette of their own. */
.pb-scroll {
  flex: 1 1 auto; min-height: 0;
  overflow-y: auto; overscroll-behavior: contain;
}
/* On the LEFT the file tree keeps its own scroll above the blocks — the tree
   is how you move around the vault, so it never loses its floor to a long
   block list. The block list takes the height its blocks need and no more (so
   a nearly empty panel does not strand "+ Add block" in the middle of it),
   capped at half the panel, past which it scrolls. On the right the blocks own
   the whole panel. */
#left-sidebar > .pb-scroll { flex: 0 1 auto; max-height: 52%; }
#left-sidebar .sidebar-pane { min-height: 132px; }
.pb-list { display: flex; flex-direction: column; gap: 8px; padding: 8px; }

/* The add button is the last BLOCK in the flow, not a pinned footer: you scroll
   to the end of the panel to reach it, the way you reach the end of any list. */
.pb-add {
  flex: 0 0 auto;
  padding: 7px 9px; border-radius: var(--radius-card);
  border: 1px dashed var(--border); background: transparent;
  color: var(--text-faint); font-family: var(--font-ui); font-size: 12px;
  cursor: pointer; transition: color 0.12s, border-color 0.12s, background 0.12s;
}
.pb-add:hover { color: var(--accent); border-color: var(--accent); background: var(--bg-hover); }

.wg-card {
  /* Never compress. A block has a height because its contents need one; the
     panel scrolls when they do not all fit. Without this every card shrinks as
     you add more and the whole panel turns to slivers. */
  flex: 0 0 auto;
  background: var(--card-bg); border: 1px solid var(--border);
  border-radius: var(--radius-card); box-shadow: var(--shadow-card);
  overflow: hidden; position: relative;
}
.wg-head {
  display: flex; align-items: center; gap: 2px;
  padding: 7px 7px 5px; border-bottom: 1px solid var(--border);
}
.pb-collapsed .wg-head { border-bottom-color: transparent; }
.pb-collapsed > .wg-body { display: none; }
.wg-title {
  flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  font-size: 10.5px; font-weight: 700; letter-spacing: 0.07em; text-transform: uppercase;
  color: var(--text-faint);
}
.pb-fold {
  border: 0; background: transparent; text-align: left; cursor: pointer;
  font-family: var(--font-ui); padding: 1px 2px; border-radius: 5px;
}
.pb-fold::before {
  content: "›"; display: inline-block; margin-right: 4px;
  font-size: 12px; line-height: 1; transform: rotate(90deg); transition: transform 0.14s ease;
}
.pb-collapsed .pb-fold::before { transform: none; }
.pb-fold:hover { color: var(--text-heading); }
/* The drag handle appears on hover — never drag-anywhere: these blocks are full
   of buttons, lists and a canvas, all of which want the pointer themselves. */
.pb-grip {
  flex: 0 0 auto; width: 11px; cursor: grab; user-select: none; touch-action: none;
  color: var(--text-faint); opacity: 0; font-size: 11px; line-height: 1;
  transition: opacity 0.12s;
}
.wg-card:hover .pb-grip, .pb-dragging .pb-grip { opacity: 0.75; }
.pb-grip:active { cursor: grabbing; }
.wg-menu {
  border: 0; background: transparent; color: var(--text-faint); cursor: pointer;
  font-size: 15px; line-height: 1; padding: 0 3px; border-radius: 5px;
}
.wg-menu:hover { color: var(--text-heading); background: var(--bg-hover); }
.wg-body { padding: 9px 10px 10px; display: flex; flex-direction: column; gap: 7px; }

/* Dragging: the block dims in place, a line shows where it will land, and the
   pointer keeps the grab cursor across the whole window. */
.pb-dragging { opacity: 0.4; }
body.pb-reordering, body.pb-reordering * { cursor: grabbing !important; user-select: none; }
.pb-drop-line {
  flex: 0 0 auto; height: 2px; margin: -5px 2px; border-radius: 2px; background: var(--accent);
}
/* The Study block is note-scoped: no cards in this note, no block. */
.pb-block:has(> .wg-body > #rail-study.hidden) { display: none; }

.wg-scroll { max-height: 230px; overflow-y: auto; }
.wg-empty { font-size: 12.5px; color: var(--text-faint); padding: 2px 0; }
.wg-sub { font-size: 11.5px; color: var(--text-faint); }

.wg-row { display: flex; align-items: center; gap: 8px; padding: 4px 5px; border-radius: 6px; font-size: 13px; }
.wg-row.wg-click { cursor: pointer; }
.wg-row.wg-click:hover { background: var(--bg-hover); }
.wg-row-l { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--text-normal); }
.wg-row-v { font-family: var(--font-mono); font-size: 11px; color: var(--text-faint); font-variant-numeric: tabular-nums; }

.wg-big { display: flex; align-items: baseline; gap: 7px; }
.wg-big-n {
  font-family: var(--font-mono); font-size: 27px; font-weight: 600; line-height: 1.05;
  letter-spacing: -0.02em; color: var(--text-heading); font-variant-numeric: tabular-nums;
}
.wg-big-l { font-size: 12px; color: var(--text-faint); }

.wg-stats { display: flex; gap: 16px; }
.wg-stat { display: flex; flex-direction: column; gap: 1px; }
.wg-stat-n {
  font-family: var(--font-mono); font-size: 19px; font-weight: 600; line-height: 1.1;
  color: var(--text-heading); font-variant-numeric: tabular-nums;
}
.wg-stat-l { font-size: 10.5px; color: var(--text-faint); text-transform: uppercase; letter-spacing: 0.06em; }

.wg-clock {
  font-family: var(--font-mono); font-size: 29px; font-weight: 600; line-height: 1.05;
  letter-spacing: -0.02em; color: var(--text-heading); font-variant-numeric: tabular-nums;
}
.wg-clock-date { font-size: 12px; color: var(--text-faint); }

.wg-timer {
  font-family: var(--font-mono); font-size: 30px; font-weight: 600; line-height: 1.05;
  letter-spacing: -0.02em; color: var(--text-heading); font-variant-numeric: tabular-nums;
}
.wg-timer-done { color: var(--accent); }
.wg-timer-bar { height: 5px; border-radius: 3px; background: var(--bg-hover); overflow: hidden; }
.wg-timer-bar i { display: block; height: 100%; background: var(--accent); border-radius: 3px; transition: width 0.25s linear; }
/* Life Span. The big number can carry ten decimals of a year, so it is allowed
   to shrink and wrap rather than overflow a narrow rail — tabular figures keep
   the digits from dancing as the last places tick over every second. */
/* The connect-an-assistant guide: collapsed steps, so the page stays scannable
   for someone who is only here to check what is connected. */
.connect-guide { margin: 10px 0 4px; display: flex; flex-direction: column; gap: 6px; }
.connect-guide details {
  border: 1px solid var(--border); border-radius: 8px; background: var(--bg-secondary);
  padding: 8px 12px;
}
.connect-guide summary { cursor: pointer; font-size: 13px; color: var(--text-normal); }
.connect-guide summary::marker { color: var(--text-faint); }
.connect-guide ol, .connect-guide ul { margin: 8px 0 4px; padding-left: 20px; }
.connect-guide li {
  font-size: 12.5px; color: var(--text-muted); line-height: 1.55; margin-bottom: 5px;
}
.connect-guide code {
  font-family: var(--font-mono); font-size: 11.5px;
  background: var(--bg-hover); padding: 1px 4px; border-radius: 4px;
}
.connect-guide .settings-hint { margin-top: 6px; }

#status-offline {
  color: var(--text-on-accent, #fff); background: var(--warn, #b26a00);
  padding: 1px 7px; border-radius: 999px; font-size: 11px; white-space: nowrap;
}

.study-done-actions { display: flex; gap: 8px; justify-content: center; margin-top: 14px; flex-wrap: wrap; }

/* NEVER BROKEN MID-NUMBER. word-break: break-all split "26.6742969971" across
   two lines in the middle of its decimals — the fix for an overflowing number
   is a smaller number, not half of one on each line. widgets.js scales the font
   to the box; this only has to promise it stays on one line. */
.ls-big-n { font-size: 23px; white-space: nowrap; }
.ls-units { display: flex; flex-direction: column; gap: 7px; margin-top: 2px; }
.ls-unit { display: flex; flex-direction: column; gap: 2px; }
.ls-unit-top { display: flex; align-items: baseline; gap: 8px; }
.ls-unit-l {
  flex: 1; min-width: 0; font-size: 11px; text-transform: uppercase; letter-spacing: 0.06em;
  color: var(--text-faint); overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.ls-unit-v {
  font-family: var(--font-mono); font-size: 15px; font-weight: 600; color: var(--text-heading);
  font-variant-numeric: tabular-nums;
}
.ls-unit-sub { font-size: 11px; color: var(--text-faint); font-variant-numeric: tabular-nums; }
.ls-bar { height: 3px; border-radius: 2px; background: var(--bg-hover); overflow: hidden; }
.ls-bar i { display: block; height: 100%; background: var(--accent); border-radius: 2px; }
.ls-extra { margin-top: 8px; border-top: 1px solid var(--border); padding-top: 6px; }

.wg-pom-phase { font-size: 11px; font-weight: 700; letter-spacing: 0.08em; text-transform: uppercase; color: var(--accent); }
.wg-pom-phase.wg-pom-break { color: var(--text-faint); }
.wg-pom-done { font-size: 11.5px; color: var(--text-faint); }

.wg-actions { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }
.wg-btn {
  border: 1px solid var(--border); background: var(--bg-secondary); color: var(--text-heading);
  font-family: var(--font-ui); font-size: 12px; padding: 4px 10px;
  border-radius: var(--radius-active); cursor: pointer;
}
.wg-btn:hover { background: var(--bg-hover); border-color: var(--accent); }
.wg-btn-quiet { background: transparent; color: var(--text-muted); }

.wg-input {
  width: 100%; resize: vertical; border: 1px solid var(--border); border-radius: 8px;
  background: var(--bg-primary); color: var(--text-normal);
  font-family: var(--font-ui); font-size: 13px; padding: 6px 8px;
}
.wg-input:focus { outline: none; border-color: var(--accent); }

.wg-note { font-size: 12.5px; line-height: 1.55; color: var(--text-muted); white-space: pre-wrap; cursor: pointer; }
.wg-note:hover { color: var(--text-normal); }

.wg-chips { display: flex; flex-wrap: wrap; gap: 5px; }
.wg-chip {
  border: 0; cursor: pointer; font-family: var(--font-ui); font-size: 11.5px;
  background: var(--tag-bg); color: var(--tag-text);
  padding: 2px 7px; border-radius: 999px; display: inline-flex; gap: 5px; align-items: center;
}
.wg-chip span { color: var(--text-faint); font-family: var(--font-mono); font-size: 10px; }
.wg-chip:hover { filter: brightness(0.96); }

/* A finished timer flashes, since this app has no OS notification surface. */
@keyframes wg-flash { 0%, 100% { box-shadow: var(--shadow-card); } 50% { box-shadow: 0 0 0 2px var(--accent); } }
.wg-flash { animation: wg-flash 0.5s ease-in-out 3; }
@media (prefers-reduced-motion: reduce) { .wg-flash { animation: none; box-shadow: 0 0 0 2px var(--accent); } }


/* ============================ Panel resizers ============================
   A drag strip living in the 10px flex gap between a sidebar and the note.
   Negative margins cancel the extra gap the element itself introduces, so
   adding it does not shift the layout. */
.panel-resizer {
  flex: 0 0 4px;
  margin: 0 -7px;
  position: relative;
  z-index: 5;
  cursor: col-resize;
  border-radius: 3px;
  background: transparent;
  transition: background 0.12s;
}
/* A wider invisible hit area than the visible line — 4px is hard to grab. */
.panel-resizer::before {
  content: '';
  position: absolute;
  inset: 0 -5px;
}
.panel-resizer:hover, .panel-resizer.dragging { background: var(--accent); }
/* While dragging, stop the pointer selecting note text as it sweeps across. */
body.resizing-panel { user-select: none; cursor: col-resize; }
body.resizing-panel * { cursor: col-resize !important; }
/* A collapsed sidebar takes its resizer with it. */
#left-sidebar.collapsed + .panel-resizer,
.panel-resizer:has(+ #right-sidebar.collapsed) { display: none; }
@media (prefers-reduced-motion: reduce) { .panel-resizer { transition: none; } }

/* Share dialog: the per-link look picker. */
.share-link-style { display: flex; align-items: center; gap: 8px; margin-top: 6px; }
.share-link-style > span { font-size: 12px; color: var(--text-faint); }
.share-link-style select { font-size: 12px; padding: 3px 6px; }
#share-style-row { display: flex; align-items: center; justify-content: space-between; gap: 10px; }

/* ============================ Note properties ============================
   The bar, the footer, the type icons, the widgets and the per-row delete are
   all DECORATIONS — stripped before the save gate sees the tree (see
   properties-ui.js). Collapsing never touches .properties itself; the class
   lives on the bar, so hiding your properties can never delete them. */
.prop-bar {
  display: flex; align-items: center; gap: 6px;
  margin: 0 0 2px; user-select: none;
}
.prop-toggle {
  display: inline-flex; align-items: center; gap: 6px;
  font-family: var(--font-ui); font-size: 11px; font-weight: 600;
  letter-spacing: 0.07em; text-transform: uppercase;
  color: var(--text-faint); padding: 3px 7px; border-radius: 6px; cursor: pointer;
}
.prop-toggle:hover { background: var(--bg-hover); color: var(--text-heading); }
.prop-chev { display: inline-block; transition: transform 0.14s ease; transform: rotate(90deg); font-size: 9px; }
.prop-bar.collapsed .prop-chev { transform: rotate(0deg); }
.prop-count {
  font-family: var(--font-mono); font-size: 10px; letter-spacing: 0;
  background: var(--chip-bg); color: var(--chip-text); border-radius: 999px; padding: 0 6px;
}
/* Collapsed: the block is hidden from the note, the bar stays so you can
   bring it back. The properties themselves are untouched on disk. */
.prop-bar.collapsed + .properties { display: none; }

.properties .prop-row { position: relative; align-items: flex-start; padding: 4px 0; }
.properties .prop-key { min-width: 116px; padding-top: 3px; }
/* order:-1 puts the type icon before the name while keeping it a SIBLING of
   the key span — inside it, its glyph would become part of the key's text. */
.prop-ic {
  order: -1; display: inline-flex; align-items: center; justify-content: center;
  width: 16px; height: 16px; flex: 0 0 16px; margin-top: 2px; cursor: pointer;
  font-family: var(--font-mono); font-size: 10px; font-weight: 700;
  border-radius: 4px; color: var(--text-faint); letter-spacing: 0;
}
.prop-ic:hover { background: var(--bg-hover); color: var(--accent); }
/* Reading view: the icon labels the type, it is not a button. */
.prop-ic.is-static { cursor: default; }
.prop-ic.is-static:hover { background: none; color: var(--text-faint); }
.prop-box:disabled, .prop-date:disabled { opacity: 1; cursor: default; }
.prop-date:disabled { color: var(--text-normal); -webkit-text-fill-color: var(--text-normal); }
.prop-date:disabled:hover { border-color: transparent; }

/* A row whose value is shown by a widget hides the raw text span — the span is
   still there, still the only thing that gets saved. */
.prop-row[data-type="multi"] > .prop-value,
.prop-row[data-type="select"] > .prop-value,
.prop-row[data-type="status"] > .prop-value,
.prop-row[data-type="checkbox"] > .prop-value,
.prop-row[data-type="date"] > .prop-value { display: none; }
.prop-widget { display: flex; flex-wrap: wrap; align-items: center; gap: 5px; min-height: 20px; }
.prop-chip {
  display: inline-flex; align-items: center; gap: 3px;
  background: var(--chip-bg); color: var(--chip-text);
  border-radius: 5px; padding: 1px 4px 1px 7px; font-size: 12.5px; line-height: 1.5;
}
/* Status reads as a state rather than a label, so it gets its own shape. */
.prop-chip.is-status {
  border-radius: 999px; padding-left: 9px; padding-right: 9px;
  background: transparent; box-shadow: inset 0 0 0 1px var(--border); color: var(--text-normal);
}
.prop-chip-x {
  font-size: 12px; line-height: 1; color: inherit; opacity: 0.45;
  padding: 0 2px; border-radius: 3px; cursor: pointer;
}
.prop-chip-x:hover { opacity: 1; background: var(--bg-hover); color: var(--danger); }
.prop-chip-add {
  font-size: 12px; line-height: 1.5; color: var(--text-faint);
  padding: 1px 6px; border-radius: 5px; cursor: pointer;
}
.prop-chip-add:hover { background: var(--bg-hover); color: var(--accent); }
.prop-box { width: 15px; height: 15px; accent-color: var(--accent); cursor: pointer; }
.prop-date {
  font-family: var(--font-ui); font-size: 12.5px; color: var(--text-normal);
  background: transparent; border: 1px solid transparent; border-radius: 5px;
  padding: 0 4px; cursor: pointer;
}
.prop-date:hover { border-color: var(--border); }

.prop-del {
  position: absolute; right: 2px; top: 4px;
  opacity: 0; font-size: 14px; line-height: 1; color: var(--text-faint);
  padding: 1px 6px; border-radius: 5px; cursor: pointer; transition: opacity 0.12s;
}
.prop-row:hover .prop-del { opacity: 1; }
.prop-del:hover { background: var(--bg-hover); color: var(--danger); }

.prop-foot { margin: 2px 0 1.1em; user-select: none; }
.prop-new {
  font-family: var(--font-ui); font-size: 12.5px; color: var(--text-faint);
  padding: 4px 8px; border-radius: 6px; cursor: pointer;
}
.prop-new:hover { background: var(--bg-hover); color: var(--accent); }
/* A verbatim block shows the file's real YAML instead of the rows we could
   only half-parse out of it — those rows are ignored on save anyway. The whole
   container goes, not just the rows, or it is drawn as an empty card. */
.markdown-body .properties[data-raw] { display: none; }
.prop-raw {
  font-family: var(--font-mono); font-size: 12.5px; line-height: 1.55;
  color: var(--text-normal); background: var(--bg-hover);
  border-radius: 8px; padding: 10px 12px; margin: 0 0 6px;
  overflow-x: auto; white-space: pre;
}
.prop-locked {
  font-size: 12px; line-height: 1.5; color: var(--text-faint);
  max-width: 62ch; padding: 4px 8px;
}
/* ---- database notes ----
   The rows are a list of wikilinks in the note body; this table is a view of
   that list, stripped before saving. The list itself is hidden while the view
   is up — the body class keeps that marker OUT of the editor, where any stray
   attribute risks islanding a block. */
body.is-database-note #editor > ul { display: none; }
/* Config properties are plumbing, not content — hidden on screen, untouched
   in the file, edited through View settings. */
.properties .prop-row[data-cfg="1"] { display: none; }
.markdown-body .properties[data-cfg="1"] { display: none; }

/* The database sits FLAT on the page — the bar names it, the hairlines shape
   it, and nothing boxes it in. (It used to be a card; the site's tour mock
   without one read cleaner, and the app now follows it.) */
.dbv { margin: 0.8em 0 1.4em; }
/* The database chrome follows the site's tour mock — the version everyone
   liked better: a quiet uppercase crumb, a soft serif count chip, airy rows
   with hairline dividers, and value-tinted pills. */
.dbv-bar { display: flex; align-items: center; gap: 12px; padding: 2px 2px 12px; }
.dbv-badge {
  font-size: 10px; font-weight: 700; letter-spacing: 0.14em; text-transform: uppercase;
  color: var(--text-faint);
}
.dbv-empty {
  font-size: 13px; color: var(--text-faint);
  padding: 14px 12px; text-align: center;
}
.dbv-count {
  font-family: "Iowan Old Style", "Literata", "Palatino Linotype", Georgia, serif;
  font-size: 15px; margin-right: auto; padding: 1px 12px 2px; border-radius: 9px;
  background: color-mix(in srgb, #57A85F 16%, transparent);
  color: color-mix(in srgb, #3E9048 55%, var(--text-heading));
}
.dbv-gear {
  font-family: var(--font-ui); font-size: 12.5px; color: var(--text-faint);
  padding: 4px 9px; border-radius: 6px; cursor: pointer;
}
.dbv-gear:hover { background: var(--bg-hover); color: var(--accent); }
.dbv-pop {
  position: fixed; z-index: 420; min-width: 250px; max-width: 320px;
  max-height: 70vh; overflow-y: auto; padding: 6px;
  background: var(--card-bg); border: 1px solid var(--border);
  border-radius: 10px; box-shadow: var(--shadow-panel);
}
.dbv-sec {
  font-size: 10px; font-weight: 700; letter-spacing: 0.08em; text-transform: uppercase;
  color: var(--text-faint); padding: 8px 8px 3px;
}
.dbv-opt {
  display: block; width: 100%; text-align: left;
  font-family: var(--font-mono); font-size: 12.5px; color: var(--text-normal);
  padding: 5px 8px; border-radius: 6px; cursor: pointer; white-space: pre;
}
.dbv-opt:hover { background: var(--bg-hover); }
.dbv-opt.is-on { color: var(--accent); }
.dbv-note { font-size: 12px; color: var(--text-faint); padding: 2px 8px 6px; line-height: 1.45; }
/* Layout picker: five names in a row, because they are one choice. */
.dbv-layouts { display: flex; flex-wrap: wrap; gap: 4px; padding: 2px 8px 6px; }
.dbv-layout {
  font-family: var(--font-ui); font-size: 11.5px; cursor: pointer;
  padding: 4px 9px; border-radius: 999px; border: 1px solid var(--border);
  background: transparent; color: var(--text-muted);
}
.dbv-layout:hover { color: var(--text-heading); border-color: var(--accent); }
.dbv-layout.is-on { background: var(--chip-bg); color: var(--chip-text); border-color: transparent; font-weight: 600; }
.dbv-filter { display: flex; gap: 6px; padding: 2px 8px 6px; }
.dbv-select {
  font-family: var(--font-ui); font-size: 12.5px; color: var(--text-normal);
  background: var(--bg-hover); border: 1px solid transparent; border-radius: 6px; padding: 4px 6px;
}
.dbv-table { border-collapse: collapse; width: 100%; font-size: 14.5px; }
.dbv-table th, .dbv-table td { text-align: left; }
/* The editor's generic table chrome (card, column separators, shaded header)
   is for Markdown tables IN prose; a database is a page of its own — flat,
   rows divide, columns breathe. */
.markdown-body .dbv-table {
  border: none; border-radius: 0; box-shadow: none; background: transparent; margin: 0;
}
.markdown-body .dbv-table td + td, .markdown-body .dbv-table th + th { border-left: none; }
.markdown-body .dbv-table th { background: transparent; }
.markdown-body .dbv-table tr:last-child td { border-bottom: 1px solid color-mix(in srgb, var(--border) 62%, transparent); }
.dbv-table td {
  padding: 12px 14px;
  border-bottom: 1px solid color-mix(in srgb, var(--border) 62%, transparent);
}
.dbv-table thead th {
  font-size: 10px; font-weight: 700; letter-spacing: 0.12em; text-transform: uppercase;
  color: var(--text-faint); padding: 8px 14px; border-bottom: 1px solid var(--border);
}
/* A column header is a control: it opens the column's menu and it drags. */
.dbv-table th.dbv-col { cursor: pointer; user-select: none; white-space: nowrap; }
.dbv-table th.dbv-col:hover { background: var(--bg-hover); }
.dbv-table th.dbv-col.is-dragging { opacity: 0.4; }
/* While a column is moving, nothing else should select or take a cursor. */
body.dbv-dragging { cursor: grabbing; user-select: none; }
.dbv-table th.dbv-col.is-over { box-shadow: inset 2px 0 0 var(--accent); }
.dbv-col-ic {
  display: inline-block; width: 14px; margin-right: 5px;
  font-family: var(--font-mono); font-size: 10px; color: var(--text-faint);
}
.dbv-colinput {
  width: 100%; min-width: 90px;
  font-family: var(--font-ui); font-size: 11px; font-weight: 700;
  letter-spacing: 0.06em; text-transform: uppercase; color: var(--text-normal);
  background: var(--bg-primary); border: 1px solid var(--accent);
  border-radius: 5px; padding: 2px 5px;
}
.dbv-addcol {
  width: 34px; text-align: center; cursor: pointer;
  color: var(--text-faint); font-size: 15px; user-select: none;
}
.dbv-addcol:hover { background: var(--bg-hover); color: var(--accent); }
/* Typed cells: a column looks like what it holds. */
.dbv-chip {
  display: inline-block; margin: 0 4px 2px 0; padding: 2px 10px;
  background: var(--bg-hover); color: var(--text-muted);
  border-radius: 999px; font-size: 12px; font-weight: 500;
}
.dbv-chip.is-status { color: var(--text-normal); }
/* Value tints — mixed against text-heading so they read in light AND dark. */
.dbv-chip.tone-done {
  background: color-mix(in srgb, #57A85F 18%, transparent);
  color: color-mix(in srgb, #3E9048 55%, var(--text-heading));
}
.dbv-chip.tone-doing {
  background: color-mix(in srgb, #4385BE 20%, transparent);
  color: color-mix(in srgb, #4385BE 55%, var(--text-heading));
}
.dbv-chip.tone-todo { background: var(--bg-hover); color: var(--text-muted); }
.dbv-chip.tone-hold {
  background: color-mix(in srgb, #D9822B 18%, transparent);
  color: color-mix(in srgb, #C4762A 55%, var(--text-heading));
}
.dbv-box { width: 15px; height: 15px; accent-color: var(--accent); cursor: pointer; }
.dbv-datein {
  font-family: var(--font-ui); font-size: 14px; color: var(--text-normal);
  background: transparent; border: 1px solid transparent; border-radius: 5px;
  padding: 1px 4px; cursor: pointer;
}
.dbv-datein::-webkit-calendar-picker-indicator { opacity: 0; transition: opacity 0.12s; }
.dbv-datein:hover { border-color: var(--border); }
.dbv-datein:hover::-webkit-calendar-picker-indicator { opacity: 0.55; }
.dbv-name { font-weight: 600; color: var(--text-heading); cursor: pointer; }
.dbv-name:hover { color: var(--accent); text-decoration: underline; }
.dbv-name.is-missing { color: var(--text-faint); font-style: italic; }
.dbv-cell { color: var(--text-muted, var(--text-normal)); cursor: text; }
.dbv-cell:hover { background: var(--bg-hover); }
.dbv-input {
  width: 100%; font-family: var(--font-ui); font-size: 14.5px; color: var(--text-normal);
  background: var(--bg-primary); border: 1px solid var(--accent);
  border-radius: 5px; padding: 3px 7px;
}
.dbv-new {
  display: block; width: 100%; text-align: left;
  font-family: var(--font-ui); font-size: 13.5px; color: var(--text-faint);
  padding: 10px 12px; border-radius: 8px; cursor: pointer;
}
.dbv-new:hover { background: var(--bg-hover); color: var(--accent); }

/* ---- database layouts: board · gallery · calendar · chart ----
   One card design across all of them, so a row looks like the same thing
   wherever it is standing. */
.dbl-card {
  background: var(--card-bg); border: 1px solid var(--border);
  border-radius: 10px; box-shadow: var(--shadow-card);
  padding: 9px 11px; display: flex; flex-direction: column; gap: 5px;
}
.dbl-card-title { font-size: 14px; font-weight: 600; color: var(--text-heading); cursor: pointer; }
.dbl-card-title:hover { color: var(--accent); }
.dbl-card-row { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; font-size: 12px; }
.dbl-card-k { color: var(--text-faint); }
.dbl-card-v { color: var(--text-muted); }

/* Board: columns scroll sideways as a set; each column scrolls its own cards. */
.dbl-board { display: flex; gap: 10px; overflow-x: auto; padding: 4px 2px 10px; align-items: flex-start; }
.dbl-col {
  flex: 0 0 224px; min-width: 224px;
  background: var(--bg-secondary); border-radius: 12px; padding: 8px;
  border: 1px solid transparent;
}
.dbl-col.is-over { border-color: var(--accent); background: var(--bg-hover); }
.dbl-col-head { display: flex; align-items: center; gap: 6px; padding: 2px 4px 8px; }
.dbl-col-name {
  font-size: 11px; font-weight: 700; letter-spacing: 0.06em; text-transform: uppercase;
  color: var(--text-faint); flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.dbl-col-count { font-family: var(--font-mono); font-size: 11px; color: var(--text-faint); }
.dbl-col-body { display: flex; flex-direction: column; gap: 7px; min-height: 34px; }
.dbl-card[data-drag] { cursor: grab; touch-action: none; }
.dbl-card.is-dragging { opacity: 0.4; }
body.dbl-dragging, body.dbl-dragging * { cursor: grabbing !important; user-select: none; }

/* Gallery */
.dbl-gallery {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(190px, 1fr));
  gap: 10px; padding: 4px 0 8px;
}

/* Calendar */
.dbl-cal { padding: 4px 0 8px; }
.dbl-cal-head { display: flex; align-items: center; justify-content: center; gap: 12px; padding-bottom: 8px; }
.dbl-cal-title { font-size: 14px; font-weight: 650; color: var(--text-heading); }
.dbl-cal-nav {
  font-size: 15px; color: var(--text-faint); cursor: pointer;
  padding: 1px 8px; border-radius: 6px; line-height: 1.2;
}
.dbl-cal-nav:hover { background: var(--bg-hover); color: var(--text-heading); }
.dbl-cal-grid { display: grid; grid-template-columns: repeat(7, minmax(0, 1fr)); gap: 4px; }
.dbl-cal-dow {
  font-size: 10px; font-weight: 700; letter-spacing: 0.06em; text-transform: uppercase;
  color: var(--text-faint); text-align: center; padding-bottom: 2px;
}
.dbl-cal-cell {
  min-height: 74px; border-radius: 9px; padding: 5px;
  background: var(--bg-secondary); display: flex; flex-direction: column; gap: 3px;
  position: relative;
}
/* The + shows on the day you're pointing at — creating a note THERE dates it
   there, so the affordance lives on the date, not in a toolbar. */
.dbl-cal-add {
  position: absolute; top: 3px; right: 3px; width: 20px; height: 20px;
  display: none; align-items: center; justify-content: center;
  border-radius: 6px; color: var(--text-faint); font-size: 14px; line-height: 1; cursor: pointer;
}
.dbl-cal-cell:hover .dbl-cal-add { display: flex; }
.dbl-cal-add:hover { background: var(--bg-hover); color: var(--accent); }
.dbl-cal-cell.is-blank { background: transparent; }
.dbl-cal-cell.is-today { box-shadow: inset 0 0 0 1.5px var(--accent); }
.dbl-cal-day { font-family: var(--font-mono); font-size: 11px; color: var(--text-faint); }
.dbl-cal-item {
  font-family: var(--font-ui); font-size: 11.5px; text-align: left; cursor: pointer;
  background: var(--chip-bg); color: var(--chip-text);
  border-radius: 6px; padding: 2px 6px;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.dbl-cal-item:hover { filter: brightness(0.96); }
.dbl-cal-foot { font-size: 12px; color: var(--text-faint); padding-top: 8px; }

.dbl-chart { padding: 6px 0 4px; }

.bt-new {
  display: block; width: 100%; text-align: left;
  font-family: var(--font-ui); font-size: 13px; color: var(--text-faint);
  padding: 9px 14px; margin-top: 2px; border-radius: 8px; cursor: pointer;
}
.bt-new:hover { background: var(--bg-hover); color: var(--accent); }

/* An editable property cell in a table view. */
.base-table td.bt-edit { cursor: text; }
.base-table td.bt-edit:hover { background: var(--bg-hover); }
.bt-input {
  width: 100%; font-family: var(--font-ui); font-size: inherit; color: var(--text-normal);
  background: var(--bg-primary); border: 1px solid var(--accent);
  border-radius: 5px; padding: 2px 6px;
}

/* ---- table formulas ----
   The formula is the cell's real text and stays editable; the value beside it
   is decoration, stripped before saving. Reading view drops the formula and
   shows only the number. */
/* A formula cell reads as its VALUE, like a spreadsheet. The formula text is
   in the document (it is what gets saved) but never shown — clicking into the
   cell swaps the whole cell for the plain formula instead. */
.tf-src { display: none; }
.tf-out { user-select: none; }
.tf-out.is-err { color: var(--danger); font-weight: 500; }
/* Being edited: monospace, so a formula reads like one. */
td.tf-editing, th.tf-editing {
  font-family: var(--font-mono); font-size: 0.94em;
  background: var(--bg-hover); box-shadow: inset 0 0 0 2px var(--accent);
}
/* Cells being pointed at while a reference is dragged out. */
td.tf-picked, th.tf-picked { background: var(--chip-bg); box-shadow: inset 0 0 0 1px var(--accent); }

/* The function list. On <body>, never inside the editor. */
.tf-ac {
  position: fixed; z-index: 420; min-width: 240px; max-height: 260px; overflow-y: auto;
  padding: 5px; background: var(--card-bg); border: 1px solid var(--border);
  border-radius: 10px; box-shadow: var(--shadow-panel);
}
.tf-ac-item {
  display: flex; align-items: baseline; gap: 10px; width: 100%; text-align: left;
  padding: 5px 8px; border-radius: 6px; cursor: pointer;
}
.tf-ac-item:hover, .tf-ac-item.is-on { background: var(--bg-hover); }
.tf-ac-name { font-family: var(--font-mono); font-size: 12.5px; font-weight: 700; color: var(--accent); }
.tf-ac-hint { font-size: 12px; color: var(--text-faint); }

.base-locked {
  font-size: 12.5px; line-height: 1.5; color: var(--text-faint);
  background: var(--bg-hover); border-radius: 8px;
  padding: 8px 12px; margin-bottom: 10px;
}

/* The menus. On <body>, never inside the editor — anything in there is a
   candidate for serialization and this chrome must never be. */
.prop-pop {
  position: fixed; z-index: 400; min-width: 232px; max-width: 300px;
  max-height: 60vh; overflow-y: auto; padding: 6px;
  background: var(--card-bg); border: 1px solid var(--border);
  border-radius: var(--radius-card); box-shadow: var(--shadow-panel);
}
.prop-pop-input {
  width: 100%; font-family: var(--font-ui); font-size: 13px; color: var(--text-normal);
  background: var(--bg-hover); border: 1px solid transparent; border-radius: 6px;
  padding: 5px 8px; margin-bottom: 4px;
}
.prop-pop-input:focus { border-color: var(--accent); outline: none; }
.prop-pop-head {
  font-size: 10px; font-weight: 700; letter-spacing: 0.08em; text-transform: uppercase;
  color: var(--text-faint); padding: 6px 8px 3px;
}
.prop-pop-head:empty { padding: 0; border-top: 1px solid var(--border); margin: 5px 0; }
.prop-pop-list { display: flex; flex-direction: column; }
.prop-pop-item {
  display: flex; align-items: center; gap: 8px; width: 100%; text-align: left;
  font-family: var(--font-ui); font-size: 13px; color: var(--text-normal);
  padding: 5px 8px; border-radius: 6px; cursor: pointer;
}
.prop-pop-item:hover { background: var(--bg-hover); }
.prop-pop-item .prop-ic { flex: 0 0 16px; }
.prop-pop-item .prop-ic:hover { background: none; }
.prop-pop-label { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.prop-pop-item.is-on { color: var(--accent); }
.prop-pop-item.is-new { color: var(--text-faint); }
.prop-pop-item.is-danger:hover { color: var(--danger); }
.prop-pop-err { font-size: 11.5px; color: var(--text-faint); padding: 3px 8px; }
.prop-pop-err:empty { display: none; }
@media (prefers-reduced-motion: reduce) { .prop-chev, .prop-del { transition: none; } }

/* ============ Ask your library (AI) ============
   A calm modal in the palette's family: question on top, the streaming
   answer as prose, sources as quiet chips — cited ones marked. */
#ask-modal, #cards-modal {
  position: fixed; inset: 0; z-index: 90;
  background: color-mix(in srgb, var(--bg-primary) 55%, transparent);
  display: flex; align-items: flex-start; justify-content: center;
  padding-top: 12vh;
}
#ask-modal.hidden, #cards-modal.hidden { display: none; }
.ask-card {
  width: min(680px, 92vw);
  max-height: 70vh;
  display: flex; flex-direction: column;
  background: var(--card-bg);
  border: 1px solid var(--panel-border);
  border-radius: 16px;
  box-shadow: var(--shadow-panel);
  overflow: hidden;
}
.ask-head { display: flex; align-items: center; padding: 14px 18px 0; }
.ask-title { font-family: var(--font-serif, Georgia, serif); font-size: 17px; font-weight: 600; color: var(--text-heading); }
.ask-close { margin-left: auto; border: 0; background: none; color: var(--text-faint); font-size: 18px; cursor: pointer; padding: 2px 6px; }
.ask-close:hover { color: var(--text-heading); }
.ask-consent { margin: 12px 18px 0; padding: 12px 14px; border: 1px dashed var(--border); border-radius: 10px; font-size: 13px; color: var(--text-muted); }
.ask-consent.hidden { display: none; }
.ask-allow { margin-top: 10px; border: 0; border-radius: 8px; background: var(--text-normal); color: var(--bg-primary); font: inherit; font-size: 12.5px; font-weight: 600; padding: 7px 14px; cursor: pointer; }
.ask-form { padding: 12px 18px; }
.ask-input {
  width: 100%; font: inherit; font-size: 14.5px; color: var(--text-normal);
  background: var(--bg-secondary); border: 1px solid var(--border); border-radius: 10px;
  padding: 10px 14px; outline: none;
}
.ask-input:focus { border-color: var(--accent); }
.ask-answer {
  padding: 2px 18px 8px; overflow-y: auto; font-size: 14px; line-height: 1.65;
  color: var(--text-normal); white-space: pre-wrap;
}
.ask-answer.hidden, .ask-sources.hidden { display: none; }
.ask-answer a.internal-link { color: var(--link); cursor: pointer; }
.ask-sources { display: flex; flex-wrap: wrap; gap: 6px; align-items: center; padding: 4px 18px 12px; }
.ask-src-label { font-size: 10.5px; font-weight: 650; letter-spacing: 0.08em; text-transform: uppercase; color: var(--text-faint); margin-right: 2px; }
.ask-src {
  font-size: 11.5px; padding: 3px 10px; border-radius: 999px; cursor: pointer;
  background: var(--bg-hover); color: var(--text-muted); border: 1px solid transparent;
}
.ask-src:hover { color: var(--text-heading); }
.ask-src.cited { background: var(--chip-bg); color: var(--chip-text); font-weight: 600; }
/* Shown BEFORE the request, so you can see what is about to be sent while it
   is still about to be sent. Dimmed because nothing has been cited yet — these
   are candidates, not evidence. */
.ask-sources.pending .ask-src { opacity: 0.5; }
.ask-sources.pending .ask-src-label { opacity: 0.7; }
.ask-foot { padding: 8px 18px 12px; font-size: 11px; color: var(--text-faint); border-top: 1px solid var(--border); }


/* Make cards: a checklist you read before anything is written. Every row is
   the card as it will appear in the note, so accepting is a decision about
   text you have actually seen. */
.cards-status { padding: 10px 18px 0; color: var(--text-muted); font-size: 13px; }
.cards-list { overflow: auto; padding: 8px 12px 4px; display: grid; gap: 2px; }
.cards-row {
  display: flex; gap: 10px; align-items: flex-start;
  padding: 9px 10px; border-radius: 10px; cursor: pointer;
}
.cards-row:hover { background: var(--bg-hover); }
.cards-row input { margin-top: 3px; flex: none; }
.cards-text { display: grid; gap: 2px; min-width: 0; }
.cards-front { font-weight: 600; font-size: 14px; line-height: 1.4; }
.cards-back { color: var(--text-muted); font-size: 13px; line-height: 1.45; }
.cards-badge {
  justify-self: start; margin-top: 2px;
  font-size: 10.5px; font-weight: 700; letter-spacing: .04em; text-transform: uppercase;
  color: var(--accent); background: color-mix(in srgb, var(--accent) 12%, transparent);
  border-radius: 5px; padding: 1px 6px;
}
#cards-modal .ask-foot { display: flex; align-items: center; gap: 12px; }
.cards-accept {
  font: inherit; font-size: 13px; font-weight: 600;
  padding: 7px 14px; border-radius: 9px; cursor: pointer;
  color: var(--bg-primary); background: var(--accent); border: 1px solid transparent;
}
.cards-accept:disabled { opacity: .45; cursor: default; }
.cards-foot-note { color: var(--text-faint); font-size: 12px; }


/* Typed answers. The box sits under the card and above the answer, because the
   point is to commit to something BEFORE seeing it. */
#study-typed { margin-top: 18px; display: grid; gap: 10px; }
#study-answer {
  font: inherit; font-size: 15px; width: 100%;
  padding: 10px 13px; border-radius: 10px;
  color: var(--text-primary); background: var(--input-bg, var(--card-bg));
  border: 1px solid var(--panel-border);
}
#study-answer:focus { outline: none; border-color: var(--accent); }
#study-answer:disabled { opacity: .6; }
#study-verdict {
  font-size: 13.5px; line-height: 1.5; padding: 9px 12px; border-radius: 9px;
  border: 1px solid transparent;
}
#study-verdict.checking, #study-verdict.unmarked { color: var(--text-muted); background: var(--bg-hover); }
#study-verdict.v-good  { color: #2f7d4f; background: color-mix(in srgb, #2f7d4f 10%, transparent); border-color: color-mix(in srgb, #2f7d4f 25%, transparent); }
#study-verdict.v-hard  { color: #8a6a2e; background: color-mix(in srgb, #8a6a2e 10%, transparent); border-color: color-mix(in srgb, #8a6a2e 25%, transparent); }
#study-verdict.v-again { color: #a4443a; background: color-mix(in srgb, #a4443a 10%, transparent); border-color: color-mix(in srgb, #a4443a 25%, transparent); }
/* The suggestion is a ring, not a fill: it must read as "this one" without
   looking like it has already been pressed. */
#study-grades button.suggested {
  box-shadow: 0 0 0 2px var(--accent), 0 0 0 5px color-mix(in srgb, var(--accent) 22%, transparent);
}

/* ---- the study coach: Hint before the answer, Why? after a miss ---- */
#study-hintbtn {
  font-size: 13px; padding: 9px 16px; border-radius: var(--radius-btn, 8px);
  background: transparent; border: 1px solid var(--border); color: var(--text-muted);
  cursor: pointer; margin-left: 8px;
}
#study-hintbtn:hover { color: var(--text-heading); border-color: var(--text-faint); }
#study-hintbtn.hidden { display: none; }
#study-hint-text {
  margin-top: 14px; font-size: 13.5px; line-height: 1.5; color: var(--text-muted);
  padding: 9px 12px; border-left: 3px solid var(--accent); background: var(--bg-hover);
  border-radius: 0 9px 9px 0; font-style: italic;
}
#study-hint-text.hidden { display: none; }
/* #study-why carries .study-pull, whose .hidden rule already exists. */
#study-why { margin-top: 8px; align-self: flex-start; }
#study-explain {
  margin-top: 10px; font-size: 13.5px; line-height: 1.6; color: var(--text-normal);
  padding: 10px 13px; border: 1px solid var(--border); border-radius: 9px;
  background: var(--bg-subtle, var(--code-bg));
}
#study-explain.hidden { display: none; }
#study-explain a.internal-link { color: var(--link); cursor: pointer; }
/* ---- the Chat panel: conversation, activity, and the tray ---- */
#chat-dock { display: flex; flex-direction: column; gap: 8px; min-height: 200px; height: 58vh; }
#chat-dock .chat-log, #chat-full .chat-log {
  flex: 1; min-height: 60px; overflow-y: auto; display: flex; flex-direction: column;
  gap: 7px; padding: 2px;
}
#chat-dock .chat-msg, #chat-full .chat-msg { font-size: 13px; line-height: 1.55; padding: 7px 10px; border-radius: 9px; white-space: pre-wrap; }
#chat-dock .chat-user, #chat-full .chat-user { background: var(--accent); color: #fff; align-self: flex-end; max-width: 92%; }
#chat-dock .chat-assistant, #chat-full .chat-assistant { background: var(--bg-hover); color: var(--text-normal); align-self: flex-start; max-width: 96%; }
#chat-dock .chat-activity, #chat-full .chat-activity { font-size: 11.5px; color: var(--text-faint); font-family: var(--font-mono); padding: 0 4px; overflow-wrap: break-word; line-height: 1.5; }
#chat-dock .chat-consent, #chat-full .chat-consent {
  display: flex; flex-direction: column; gap: 8px; font-size: 12.5px; color: var(--text-muted);
  border: 1px dashed var(--border); border-radius: 9px; padding: 9px 11px;
}
#chat-dock .chat-allow, #chat-full .chat-allow {
  align-self: flex-start; font-size: 12px; padding: 5px 11px; cursor: pointer;
  border: 1px solid var(--accent); border-radius: 7px; background: var(--accent); color: #fff;
}
#chat-dock .chat-tray, #chat-full .chat-tray { border-top: 1px solid var(--border); padding-top: 8px; display: flex; flex-direction: column; gap: 6px; max-height: 45%; overflow-y: auto; }
#chat-dock .chat-tray.hidden, #chat-full .chat-tray.hidden { display: none; }
#chat-dock .chat-tray-head, #chat-full .chat-tray-head { font-size: 11px; font-weight: 700; letter-spacing: .07em; text-transform: uppercase; color: var(--text-faint); display: flex; justify-content: space-between; }
#chat-dock .chat-tray-head span, #chat-full .chat-tray-head span { font-weight: 500; text-transform: none; letter-spacing: 0; margin-left: 10px; }
#chat-dock .chat-prop, #chat-full .chat-prop {
  font-size: 13px; display: flex; flex-direction: column; gap: 4px;
  border: 1px solid var(--border); border-radius: 9px; padding: 8px 10px;
}
#chat-dock .chat-prop label, #chat-full .chat-prop label { display: flex; gap: 8px; align-items: baseline; cursor: pointer; flex-wrap: wrap; }
#chat-dock .cp-kind, #chat-full .cp-kind {
  font-size: 10px; font-weight: 700; letter-spacing: .05em; text-transform: uppercase;
  padding: 1px 7px; border-radius: 20px; white-space: nowrap;
  background: var(--chip-bg, var(--bg-hover)); color: var(--chip-text, var(--text-muted));
}
#chat-dock .cp-kind-replace_note, #chat-full .cp-kind-replace_note { background: color-mix(in srgb, #8a6a2e 16%, transparent); color: #b08a3e; }
#chat-dock .cp-kind-create_note, #chat-full .cp-kind-create_note { background: color-mix(in srgb, #2f7d4f 14%, transparent); color: #3f9d67; }
#chat-dock .cp-label, #chat-full .cp-label {
  color: var(--text-normal); line-height: 1.45; overflow-wrap: anywhere; flex: 1; min-width: 120px;
}
#chat-dock .chat-prop-applied .cp-label, #chat-full .chat-prop-applied .cp-label { color: var(--text-faint); text-decoration: line-through; }
#chat-dock .chat-prop-conflict .cp-label, #chat-full .chat-prop-conflict .cp-label, #chat-dock .chat-prop-failed .cp-label, #chat-full .chat-prop-failed .cp-label { color: #a4443a; }
#chat-dock .cp-status, #chat-full .cp-status { font-size: 10.5px; color: var(--text-faint); margin-left: 22px; }
#chat-dock .cp-peek, #chat-full .cp-peek {
  align-self: flex-start; margin-left: 22px; font-size: 10.5px; padding: 1px 8px; cursor: pointer;
  border: 1px solid var(--border); border-radius: 6px; background: transparent; color: var(--text-muted);
}
#chat-dock .cp-body, #chat-full .cp-body {
  margin: 2px 0 2px 22px; font-family: var(--font-mono); font-size: 11px; line-height: 1.5;
  white-space: pre-wrap; word-break: break-word; max-height: 140px; overflow: auto;
  background: var(--code-bg); border: 1px solid var(--border); border-radius: 7px; padding: 7px 9px;
}
#chat-dock .cp-body.hidden, #chat-full .cp-body.hidden { display: none; }
#chat-dock .chat-tray-actions, #chat-full .chat-tray-actions { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; padding-top: 2px; }
#chat-dock .ct-apply, #chat-full .ct-apply { font-size: 12px; padding: 5px 13px; cursor: pointer; border-radius: 7px; border: 1px solid var(--accent); background: var(--accent); color: #fff; }
#chat-dock .ct-apply:disabled, #chat-full .ct-apply:disabled { opacity: .45; cursor: default; }
#chat-dock .ct-clear, #chat-full .ct-clear { font-size: 12px; padding: 5px 10px; cursor: pointer; border-radius: 7px; border: 1px solid var(--border); background: transparent; color: var(--text-muted); }
#chat-dock .ct-note, #chat-full .ct-note { font-size: 10.5px; color: var(--text-faint); flex-basis: 100%; }
#chat-dock .chat-inputrow, #chat-full .chat-inputrow { display: flex; gap: 6px; }
#chat-dock .chat-input, #chat-full .chat-input {
  flex: 1; font-size: 13px; padding: 7px 10px; border: 1px solid var(--border);
  border-radius: 8px; background: var(--bg-primary); color: var(--text-normal);
}
#chat-dock .chat-send, #chat-full .chat-send, #chat-dock .chat-stop, #chat-full .chat-stop {
  width: 34px; cursor: pointer; border-radius: 8px; font-size: 14px;
  border: 1px solid var(--accent); background: var(--accent); color: #fff;
}
#chat-dock .chat-stop, #chat-full .chat-stop { background: #a4443a; border-color: #a4443a; }
#chat-dock .chat-expand, #chat-full .chat-expand {
  width: 34px; cursor: pointer; border-radius: 8px; font-size: 14px;
  border: 1px solid var(--border); background: transparent; color: var(--text-muted);
}
#chat-dock .chat-expand:hover, #chat-full .chat-expand:hover { color: var(--text-heading); border-color: var(--text-faint); }
#chat-dock .chat-send.hidden, #chat-full .chat-send.hidden, #chat-dock .chat-stop.hidden, #chat-full .chat-stop.hidden { display: none; }
#chat-dock .chat-cost, #chat-full .chat-cost { font-size: 10.5px; color: var(--text-faint); text-align: right; }
#chat-dock .chat-assistant a.internal-link, #chat-full .chat-assistant a.internal-link {
  color: var(--link); cursor: pointer; font-weight: 600; text-decoration: none;
}
#chat-dock .chat-assistant a.internal-link:hover, #chat-full .chat-assistant a.internal-link:hover { text-decoration: underline; }
#chat-dock .chat-msg-notes, #chat-full .chat-msg-notes {
  display: flex; flex-wrap: wrap; gap: 5px; margin-top: 8px;
}
#chat-dock .chat-msg-notes button, #chat-full .chat-msg-notes button {
  font-size: 11px; padding: 2px 9px; cursor: pointer; border-radius: 20px;
  border: 1px solid var(--border); background: var(--bg-secondary); color: var(--link);
  max-width: 180px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
#chat-dock .chat-msg-notes button:hover, #chat-full .chat-msg-notes button:hover { border-color: var(--link); }

/* The recording pill: always visible while the microphone is live. */
#record-pill {
  position: fixed; right: 18px; bottom: 18px; z-index: 400;
  display: flex; align-items: center; gap: 10px; padding: 9px 14px;
  background: var(--bg-secondary); border: 1px solid var(--border);
  border-radius: 24px; box-shadow: 0 10px 30px rgba(0,0,0,.4);
}
#record-pill .rp-dot {
  width: 10px; height: 10px; border-radius: 50%; background: #d0524a;
  animation: rp-blink 1.2s ease-in-out infinite;
}
@keyframes rp-blink { 0%,100% { opacity: 1; } 50% { opacity: .35; } }
#record-pill .rp-clock { font-family: var(--font-mono); font-size: 13px; color: var(--text-heading); }
#record-pill .rp-stop {
  font-size: 12.5px; padding: 5px 14px; cursor: pointer; border-radius: 14px;
  border: 1px solid #d0524a; background: #d0524a; color: #fff;
}
#record-pill .rp-cancel {
  font-size: 13px; cursor: pointer; border: none; background: transparent; color: var(--text-faint);
}
#record-pill .rp-cancel:hover { color: var(--text-normal); }

/* The record mode menu, source chooser and which-meeting picker share one
   card language: real options, real buttons. */
#record-source, #record-event, #record-mode {
  position: fixed; inset: 0; z-index: 410; background: rgba(0,0,0,.5);
  display: flex; align-items: center; justify-content: center;
}
#record-source .rs-card, #record-event .rs-card, #record-mode .rs-card {
  width: min(430px, 92vw); background: var(--bg-secondary); border: 1px solid var(--border);
  border-radius: 14px; padding: 18px; display: flex; flex-direction: column; gap: 10px;
  box-shadow: 0 24px 70px rgba(0,0,0,.5);
}
#record-source .rs-title, #record-event .rs-title, #record-mode .rs-title { font-weight: 650; font-size: 15px; }
#record-source button[data-src], #record-event button[data-ev], #record-mode button[data-mode] {
  display: flex; flex-direction: column; gap: 3px; text-align: left; cursor: pointer;
  padding: 11px 14px; border: 1px solid var(--border); border-radius: 10px;
  background: transparent; color: var(--text-heading); font-size: 14px;
}
#record-source button[data-src]:hover, #record-event button[data-ev]:hover, #record-mode button[data-mode]:hover { border-color: var(--accent); }
#record-source button[data-src] span, #record-event button[data-ev] span, #record-mode button[data-mode] span { font-size: 11.5px; color: var(--text-faint); }
#record-source .rs-note { font-size: 11.5px; color: var(--text-faint); line-height: 1.5; }
/* The listen switch: a real choice about what leaves the machine, so it
   reads as a sentence rather than a toggle with a two-word label. */
#record-source .rs-listen {
  display: flex; gap: 9px; align-items: flex-start; cursor: pointer;
  padding: 10px 12px; border: 1px solid var(--border); border-radius: 10px;
}
#record-source .rs-listen:hover { border-color: var(--accent); }
#record-source .rs-listen input { margin-top: 2px; flex: none; }
#record-source .rs-listen span { font-size: 11.5px; color: var(--text-faint); line-height: 1.5; }
#record-source .rs-listen b { display: block; font-size: 13px; color: var(--text-heading); font-weight: 600; margin-bottom: 2px; }
#record-pill .rp-ear { font-size: 11px; }
/* Heard-you feedback: brief, out of the way, above the pill it belongs to. */
.capture-toast {
  position: fixed; right: 18px; bottom: 76px; z-index: 4001;
  max-width: 320px; display: flex; gap: 8px; align-items: baseline;
  padding: 9px 14px; border-radius: 12px;
  background: var(--panel-bg); border: 1px solid var(--panel-border);
  backdrop-filter: blur(var(--panel-blur, 18px));
  -webkit-backdrop-filter: blur(var(--panel-blur, 18px));
  box-shadow: var(--shadow-panel); color: var(--text-normal); font-size: 12.5px;
  opacity: 0; transform: translateY(8px); transition: opacity .2s ease, transform .2s ease;
}
.capture-toast.in { opacity: 1; transform: translateY(0); }
.capture-toast b {
  font-size: 10px; text-transform: uppercase; letter-spacing: .06em;
  color: var(--accent); flex: none;
}
#record-source .rs-cancel, #record-event .rs-cancel, #record-mode .rs-cancel {
  align-self: flex-end; font-size: 12.5px; padding: 5px 12px; cursor: pointer;
  border: 1px solid var(--border); border-radius: 8px; background: transparent; color: var(--text-muted);
}
#record-pill .rp-sys { font-size: 11px; color: var(--text-muted); }
#record-pill.rp-degraded { border-color: #a4443a; }
#record-pill.rp-degraded .rp-clock { color: #a4443a; }

/* Recording extras: pause state, the long-meeting amber, the transcribe wait. */
#record-pill .rp-pause {
  font-size: 11px; padding: 5px 10px; cursor: pointer; border-radius: 14px;
  border: 1px solid var(--border); background: transparent; color: var(--text-normal);
}
#record-pill.rp-paused .rp-dot { animation: none; opacity: .35; }
#record-pill.rp-long .rp-clock { color: #b08a3e; }
#record-pill.rp-long::after {
  content: 'long recording — transcription caps near 2h'; font-size: 10px; color: #b08a3e;
}
/* The recorder's "Saving…" notice is the same object as the transcriber's
   wait: same corner, same shape, one rule. */
#transcribe-wait, #record-saving {
  position: fixed; right: 18px; bottom: 18px; z-index: 400;
  padding: 10px 16px; font-size: 12.5px; color: var(--text-normal);
  background: var(--bg-secondary); border: 1px solid var(--border); border-radius: 22px;
  box-shadow: 0 10px 30px rgba(0,0,0,.4);
}

/* Suggestion chips in a fresh chat: the features, offering themselves. */
#chat-dock .chat-suggest, #chat-full .chat-suggest {
  display: flex; flex-wrap: wrap; gap: 6px; padding: 2px;
}
#chat-dock .chat-suggest button, #chat-full .chat-suggest button {
  font-size: 12px; padding: 5px 12px; cursor: pointer; border-radius: 16px;
  border: 1px solid var(--border); background: var(--bg-secondary); color: var(--text-normal);
  text-align: left;
}
#chat-dock .chat-suggest button:hover, #chat-full .chat-suggest button:hover {
  border-color: var(--accent); color: var(--text-heading);
}

/* The Transcribe row under an audio player. */
.tn-audio-ai { display: flex; align-items: center; gap: 10px; margin-top: 12px; }
.tn-audio-ai button {
  font-size: 13px; padding: 7px 16px; cursor: pointer; border-radius: 8px;
  border: 1px solid var(--accent); background: var(--accent); color: #fff;
}
.tn-audio-ai button:disabled { opacity: .6; cursor: default; }
.tn-audio-ai span { font-size: 11.5px; color: var(--text-faint); }

/* AI privacy: the ✨ menu's one-line refusal. */
#improve-menu .improve-menu-note {
  display: flex; flex-direction: column; gap: 3px; padding: 9px 12px;
  font-size: 13px; color: var(--text-normal);
}
#improve-menu .improve-menu-note span { font-size: 11.5px; color: var(--text-faint); }

/* The thinking graph: the user's own library, with a live camera. The whole
   sky first; then the frame glides into the corner the agent is working in.
   Labels exist only for touched notes — two hundred captions is not a sky. */
.chat-brain { padding: 4px 0; transition: opacity .8s; }
.chat-brain.cb-done { opacity: 0; }
.chat-brain svg { width: 100%; height: 150px; display: block; }
#chat-full .chat-brain svg { height: 280px; }
.chat-brain .cb-edges line { stroke: var(--text-faint); stroke-width: .6; stroke-opacity: .28; }
.chat-brain .cb-edges line.cb-newedge { stroke: #3f9d67; stroke-width: 1.1; stroke-opacity: .8; stroke-dasharray: 3 3; }
.chat-brain .cb-node circle { fill: var(--text-faint); opacity: .55; transition: fill .3s, opacity .3s; }
.chat-brain .cb-node text { display: none; fill: var(--text-muted); font-size: 7.5px; text-anchor: middle; paint-order: stroke; stroke: var(--bg-secondary); stroke-width: 2.5px; }
.chat-brain .cb-node.cb-seen circle { fill: var(--text-muted); opacity: .95; }
.chat-brain .cb-node.cb-seen text { display: block; opacity: .75; }
.chat-brain .cb-node.cb-read circle { fill: var(--accent); opacity: 1; animation: cb-pulse 1.6s ease-in-out infinite; transform-origin: center; transform-box: fill-box; }
.chat-brain .cb-node.cb-read text { display: block; fill: var(--text-normal); }
.chat-brain .cb-node.cb-staged circle { fill: #3f9d67; opacity: 1; stroke: #3f9d67; stroke-width: 3; stroke-opacity: .3; animation: none; }
.chat-brain .cb-node.cb-staged text { display: block; fill: #3f9d67; }
@keyframes cb-pulse { 0%,100% { transform: scale(1); } 50% { transform: scale(1.5); } }

/* Full-page chat: the panel's own elements, adopted into a bigger room. */
#chat-full {
  position: fixed; inset: 0; z-index: 320; background: rgba(0,0,0,.5);
  display: flex; align-items: center; justify-content: center;
}
#chat-full.hidden { display: none; }
#chat-full .chat-full-card {
  width: min(860px, 94vw); height: min(88vh, 900px); display: flex; flex-direction: column;
  background: var(--bg-secondary); border: 1px solid var(--border);
  border-radius: 16px; box-shadow: 0 28px 80px rgba(0,0,0,.55); overflow: hidden;
}
#chat-full .chat-full-head {
  display: flex; align-items: center; justify-content: space-between;
  padding: 14px 20px 10px; font-weight: 650; font-size: 15px;
}
#chat-full .chat-full-close { border: none; background: transparent; font-size: 16px; cursor: pointer; color: var(--text-muted); }
#chat-full .chat-full-body { flex: 1; min-height: 0; display: flex; flex-direction: column; gap: 10px; padding: 0 20px 16px; }
#chat-full .chat-log { flex: 1; min-height: 0; overflow-y: auto; display: flex; flex-direction: column; gap: 9px; }
#chat-full .chat-msg { font-size: 14px; max-width: 78%; }
#chat-full .chat-tray { border-top: 1px solid var(--border); padding-top: 10px; display: flex; flex-direction: column; gap: 7px; max-height: 38%; overflow-y: auto; }
#chat-full .chat-tray.hidden { display: none; }
#chat-full .chat-inputrow { display: flex; gap: 8px; }
#chat-full .chat-input { flex: 1; font-size: 14px; padding: 9px 12px; border: 1px solid var(--border); border-radius: 9px; background: var(--bg-primary); color: var(--text-normal); }
#chat-full .chat-send, #chat-full .chat-stop { width: 40px; cursor: pointer; border-radius: 9px; font-size: 15px; border: 1px solid var(--accent); background: var(--accent); color: #fff; }
#chat-full .chat-stop { background: #a4443a; border-color: #a4443a; }
#chat-full .chat-send.hidden, #chat-full .chat-stop.hidden { display: none; }
#chat-full .chat-expand { display: none; }   /* already here */
#chat-full .chat-cost { font-size: 11px; color: var(--text-faint); text-align: right; }
#chat-full .cp-body { max-height: 300px; }

/* The find bar's ask fallback: only ever visible when the search found 0. */
#find-ask {
  font-size: 12.5px; padding: 4px 11px; margin-left: 6px; cursor: pointer;
  border: 1px solid var(--border); border-radius: 7px;
  background: transparent; color: var(--accent); white-space: nowrap;
  overflow: hidden; text-overflow: ellipsis; max-width: 300px;
}
#find-ask:hover { border-color: var(--accent); }
#find-ask.hidden { display: none; }

/* Digest buttons under the docked calendar. */
.cal-digest-row { display: flex; gap: 6px; padding: 8px 2px 2px; }
.cal-digest-row button {
  flex: 1; font-size: 11.5px; padding: 5px 8px; cursor: pointer;
  border: 1px solid var(--border); border-radius: 7px;
  background: transparent; color: var(--text-muted);
}
.cal-digest-row button:hover { color: var(--text-heading); border-color: var(--text-faint); }
#improve-modal .improve-digest {
  font-size: 13.5px; line-height: 1.65; color: var(--text-normal); padding: 4px 0 10px;
}
#improve-modal .improve-digest a.internal-link { color: var(--link); cursor: pointer; }

/* ---- the ✨ Improve menu: chores on the open note, preview-first ---- */
#tb-improve.hidden { display: none; }
#improve-menu {
  position: fixed; z-index: 300; min-width: 260px; padding: 6px;
  background: var(--bg-secondary); border: 1px solid var(--border);
  border-radius: 10px; box-shadow: 0 12px 34px rgba(0,0,0,.35);
  display: flex; flex-direction: column; gap: 2px;
}
#improve-menu button {
  display: flex; flex-direction: column; gap: 2px; text-align: left;
  padding: 8px 11px; border: none; background: transparent; cursor: pointer;
  border-radius: 7px; font-size: 13.5px; color: var(--text-normal);
}
#improve-menu button:hover { background: var(--bg-hover); }
#improve-menu button span { font-size: 11.5px; color: var(--text-faint); }
/* Card-check: a findings report, not a pick-list — no checkboxes, and the
   kind headings carry the grouping. */
.improve-ask { display: block; margin: 10px 0 2px; }
.improve-ask > span { display: block; font-size: 11.5px; color: var(--text-faint); margin-bottom: 4px; }
.improve-ask textarea {
  width: 100%; resize: vertical; padding: 7px 9px; font: inherit; font-size: 13px;
  color: var(--text-normal); background: var(--bg-primary);
  border: 1px solid var(--border); border-radius: 7px;
}
.check-group {
  margin: 12px 0 4px; font-size: 10.5px; font-weight: 700; letter-spacing: .07em;
  text-transform: uppercase; color: var(--text-faint);
}
.improve-link-row.check-row { cursor: default; align-items: flex-start; }
.improve-link-row.check-row .ilr-ctx { white-space: normal; }

#improve-menu .improve-group {
  margin-top: 5px; padding: 5px 11px 2px; border-top: 1px solid var(--border);
  font-size: 10.5px; font-weight: 600; letter-spacing: .07em;
  text-transform: uppercase; color: var(--text-faint);
}
#improve-modal {
  position: fixed; inset: 0; z-index: 320; background: rgba(0,0,0,.45);
  display: flex; align-items: center; justify-content: center;
}
#improve-modal.hidden { display: none; }
#improve-modal .improve-card {
  width: min(980px, 92vw); max-height: 84vh; display: flex; flex-direction: column;
  background: var(--bg-secondary); border: 1px solid var(--border);
  border-radius: 14px; box-shadow: 0 24px 70px rgba(0,0,0,.5); overflow: hidden;
}
#improve-modal .improve-head {
  display: flex; align-items: center; justify-content: space-between;
  padding: 14px 18px 10px; font-weight: 650; font-size: 15px;
}
#improve-modal .improve-close {
  border: none; background: transparent; font-size: 20px; cursor: pointer;
  color: var(--text-muted); line-height: 1;
}
#improve-modal .improve-body { padding: 0 18px 8px; overflow: auto; }
#improve-modal .improve-status { color: var(--text-muted); font-size: 13.5px; padding: 8px 0 14px; }
#improve-modal .improve-warn {
  color: #a4443a; background: color-mix(in srgb, #a4443a 9%, transparent);
  border: 1px solid color-mix(in srgb, #a4443a 25%, transparent);
  font-size: 13px; padding: 8px 11px; border-radius: 8px; margin-bottom: 10px;
}
#improve-modal .improve-diff { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; }
#improve-modal .improve-pane { min-width: 0; }
#improve-modal .improve-pane-label {
  font-size: 10.5px; font-weight: 700; letter-spacing: .08em; text-transform: uppercase;
  color: var(--text-faint); margin-bottom: 5px;
}
#improve-modal .improve-pane pre {
  font-family: var(--font-mono); font-size: 12px; line-height: 1.55;
  white-space: pre-wrap; word-break: break-word; margin: 0; padding: 10px 12px;
  background: var(--code-bg); border: 1px solid var(--border); border-radius: 8px;
  max-height: 52vh; overflow: auto;
}
#improve-modal .improve-actions {
  display: flex; gap: 10px; align-items: center; padding: 12px 18px 16px; flex-wrap: wrap;
}
#improve-modal .improve-apply {
  border: 1px solid var(--accent); background: var(--accent); color: #fff;
  font-size: 13px; padding: 7px 18px; border-radius: var(--radius-btn, 8px); cursor: pointer;
}
#improve-modal .improve-cancel {
  border: 1px solid var(--border); background: transparent; color: var(--text-normal);
  font-size: 13px; padding: 7px 14px; border-radius: var(--radius-btn, 8px); cursor: pointer;
}
#improve-modal .improve-note { font-size: 11.5px; color: var(--text-faint); }
#improve-modal .improve-links { display: flex; flex-direction: column; gap: 7px; padding: 4px 0 10px; }
#improve-modal .improve-link-row {
  display: grid; grid-template-columns: auto auto 1fr; gap: 9px; align-items: baseline;
  cursor: pointer; font-size: 13px;
}
#improve-modal .ilr-name { color: var(--link); font-weight: 600; white-space: nowrap; }
#improve-modal .ilr-ctx {
  color: var(--text-muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
#improve-modal .improve-titles { display: flex; flex-direction: column; gap: 8px; padding: 6px 0 10px; }
#improve-modal .improve-title-pick {
  text-align: left; font-size: 14px; padding: 10px 14px; cursor: pointer;
  border: 1px solid var(--border); border-radius: 9px; background: transparent; color: var(--text-heading);
}
#improve-modal .improve-title-pick:hover { border-color: var(--accent); }

/* The leech banner: an offer, then a checklist, then gone. */
#study-recard {
  margin-top: 14px; padding: 11px 14px; border: 1px dashed var(--border);
  border-radius: 10px; font-size: 13.5px; line-height: 1.5;
  display: flex; flex-direction: column; gap: 9px;
}
#study-recard.hidden { display: none; }
#study-recard .recard-lead { color: var(--text-muted); }
#study-recard .recard-go, #study-recard .recard-cancel, #study-recard .recard-flag {
  align-self: flex-start; font-size: 12.5px; padding: 6px 12px; cursor: pointer;
  border: 1px solid var(--border); border-radius: var(--radius-btn, 7px);
  background: transparent; color: var(--text-normal);
}
#study-recard .recard-go:hover, #study-recard .recard-cancel:hover,
#study-recard .recard-flag:hover { border-color: var(--text-faint); }
#study-recard .recard-list { display: flex; flex-direction: column; gap: 6px; }
#study-recard .recard-row { display: flex; gap: 8px; align-items: baseline; cursor: pointer; }
#study-recard .recard-actions { display: flex; gap: 10px; align-items: center; flex-wrap: wrap; }
#study-recard .recard-accept {
  font-size: 12.5px; padding: 6px 14px; cursor: pointer; border-radius: var(--radius-btn, 7px);
  border: 1px solid var(--accent); background: var(--accent); color: #fff;
}
#study-recard .recard-note { font-size: 11.5px; color: var(--text-faint); }

/* The end-of-session debrief: a button first, paragraphs after. Created at
   runtime by renderDone(), so no .hidden pair — presence IS its visibility. */
#study-debrief-btn {
  margin-top: 16px; font-size: 13.5px; padding: 9px 18px;
  border-radius: var(--radius-btn, 8px); border: 1px solid var(--border);
  background: transparent; color: var(--text-normal); cursor: pointer;
}
#study-debrief-btn:hover { border-color: var(--text-faint); }
#study-debrief {
  margin-top: 12px; max-width: 560px; text-align: left; font-size: 13.5px;
  line-height: 1.6; color: var(--text-normal);
}
#study-debrief:empty { display: none; }
#study-debrief a.internal-link { color: var(--link); cursor: pointer; }

/* Connection state. Green means the provider answered — never merely that a
   key reached the disk, which is the distinction the whole check exists for. */
.ai-conn-ok { color: #2f7d4f; font-weight: 600; }
.ai-conn-bad { color: #a4443a; font-weight: 600; }

/* ---- the bell, its dot, and the notification panel ---- */

#hdr-notifs { position: relative; }
/* Never hidden — the button is permanent chrome, only the dot comes and goes.
   (A header button that disappears takes the user's aim with it.) */
.hdr-dot {
  position: absolute; top: 5px; right: 5px; width: 7px; height: 7px;
  border-radius: 50%; background: var(--danger, #e05561);
  box-shadow: 0 0 0 2px var(--bg-primary);
  pointer-events: none;
}
.hdr-dot.hidden { display: none; }

.nb-body { overflow-y: auto; flex: 1; min-height: 0; padding: 6px 8px 10px; }
.nb-group {
  font-size: 10.5px; font-weight: 700; letter-spacing: .08em; text-transform: uppercase;
  color: var(--text-faint); margin: 10px 6px 5px;
}
.nb-row {
  display: block; width: 100%; text-align: left; font: inherit;
  background: transparent; border: 0; border-radius: 8px;
  padding: 7px 9px; cursor: pointer; color: var(--text-normal);
}
.nb-row:hover { background: var(--bg-hover); }
.nb-row-text { display: block; font-size: 13px; line-height: 1.35; }
.nb-row-meta { display: flex; gap: 8px; align-items: baseline; margin-top: 2px; }
.nb-row-where {
  font-size: 11px; color: var(--text-faint); flex: 1;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.nb-row-when { font-size: 10.5px; font-family: var(--font-mono); color: var(--text-faint); white-space: nowrap; }
.nb-row.late .nb-row-when { color: var(--danger, #c2410c); font-weight: 600; }

.nb-empty { padding: 26px 12px; }
.nb-empty-title { font-size: 14px; font-weight: 650; color: var(--text-heading); margin-bottom: 5px; }
.nb-empty-body { font-size: 12px; line-height: 1.55; color: var(--text-faint); }
.nb-empty-body code { font-family: var(--font-mono); background: var(--code-bg); border-radius: 4px; padding: 0 4px; }

.nb-foot {
  border-top: 1px solid var(--border); padding: 9px 12px;
  display: flex; flex-direction: column; gap: 5px;
}
#nb-all {
  font: inherit; font-size: 12px; font-weight: 600; color: var(--accent);
  background: transparent; border: 0; padding: 0; cursor: pointer; text-align: left;
}
#nb-note { font-size: 10.5px; line-height: 1.45; color: var(--text-faint); }

/* ---- widget settings sheet ---- */

/* THE FIELDS SCROLL, THE FRAME DOES NOT. The Life Span settings carries
   sixteen rows, and a form that long needs the title to stay legible and Save
   to stay reachable while you move through it. overflow: hidden overrides the
   blunt scroll .vn-dialog sets, so there is only ever one scrolling box. */
.wg-cfg {
  min-width: 360px; max-width: 460px;
  display: flex; flex-direction: column;
  overflow: hidden;
}
.wg-cfg > .wg-cfg-form {
  overflow-y: auto;
  min-height: 0;                 /* or a flex child refuses to shrink and scroll */
  overscroll-behavior: contain;  /* and the page behind it stays put */
  padding-right: 4px;            /* room for the scrollbar, so nothing sits under it */
}
.wg-cfg > .prompt-btns { flex: none; }
.wg-cfg > .vn-dialog-title { flex: none; }
.wg-cfg-form { display: flex; flex-direction: column; gap: 12px; margin: 6px 0 14px; }
.wg-cfg-row {
  display: grid; grid-template-columns: 1fr auto; align-items: center;
  gap: 6px 12px; font-size: 13px; color: var(--text-normal);
}
.wg-cfg-input {
  font: inherit; font-size: 13px; color: var(--text-normal);
  background: var(--bg-tertiary); border: 1px solid var(--border);
  border-radius: 8px; padding: 6px 9px; min-width: 150px;
}
.wg-cfg-input:focus { outline: none; border-color: var(--accent); }
/* A switch, not a 16px system checkbox. These rows are scanned — "which of
   these are on?" should be answerable at a glance, and a tick box the size of
   a full stop is not. It is still a real <input type=checkbox> underneath:
   focus, keyboard and screen readers are untouched, only the paint changes. */
.wg-cfg-toggle .wg-cfg-input[type="checkbox"] {
  appearance: none; -webkit-appearance: none;
  min-width: 0; width: 38px; height: 22px; flex: none; justify-self: end;
  border-radius: 999px; border: 1px solid var(--border); background: var(--bg-tertiary);
  padding: 0; position: relative; cursor: pointer;
  transition: background 0.15s ease, border-color 0.15s ease;
}
.wg-cfg-toggle .wg-cfg-input[type="checkbox"]::after {
  content: ''; position: absolute; top: 2px; left: 2px; width: 16px; height: 16px;
  border-radius: 50%; background: var(--text-faint);
  transition: transform 0.15s ease, background 0.15s ease;
}
.wg-cfg-toggle .wg-cfg-input[type="checkbox"]:checked {
  background: var(--accent); border-color: var(--accent);
}
.wg-cfg-toggle .wg-cfg-input[type="checkbox"]:checked::after {
  transform: translateX(16px); background: #fff;
}
.wg-cfg-toggle .wg-cfg-input[type="checkbox"]:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.wg-cfg-input[type="checkbox"] { min-width: 0; width: 16px; height: 16px; justify-self: end; }
.wg-cfg-row select.wg-cfg-input { cursor: pointer; }
.wg-cfg-input[type="number"] { width: 90px; min-width: 0; }
/* The hint spans both columns so a sentence of explanation never squeezes the
   control it is explaining. */
.wg-cfg-hint { grid-column: 1 / -1; font-size: 11px; line-height: 1.45; color: var(--text-faint); }

/* ============================ Note lock ============================
   The lock dialog is the only surface in the app that is deliberately
   slower to get through than it needs to be: with no recovery, the
   password field IS the safety system, so it is given room and the
   warning is given weight rather than being a line of fine print. */
.vn-lock { width: 400px; max-width: 92vw; }
.vn-lock-warn {
  font-size: 12.5px; line-height: 1.55; color: var(--text-normal);
  background: color-mix(in srgb, var(--accent) 8%, transparent);
  border: 1px solid color-mix(in srgb, var(--accent) 28%, transparent);
  border-radius: 8px; padding: 9px 11px; margin-bottom: 12px;
}
.vn-lock-warn b { color: var(--text-heading); }
.vn-lock-row {
  display: flex; align-items: center; justify-content: space-between;
  gap: 12px; margin: 8px 0; font-size: 12.5px; color: var(--text-muted);
}
.vn-lock-row > span { flex: 0 0 auto; }
.vn-lock-row input[type="password"], .vn-lock-row input[type="text"] {
  flex: 1 1 auto; min-width: 0; padding: 7px 9px; font-size: 13px;
  background: var(--bg-primary); color: var(--text-normal);
  border: 1px solid var(--border); border-radius: 6px; outline: none;
}
.vn-lock-row input:focus { border-color: var(--accent); }
.vn-lock-showrow { justify-content: flex-start; }
.vn-lock-showrow input { flex: 0 0 auto; }
/* There is no global .hidden utility in this stylesheet — every use of it is
   scoped to its own element, so this one must be too. Without this rule the
   Caps Lock warning shows permanently, which is worse than not having it:
   a warning that is always on is a warning nobody reads. */
.vn-lock-caps {
  font-size: 12px; color: var(--accent-strong, var(--accent));
  margin: 2px 0 6px; font-weight: 600;
}
.vn-lock-caps.hidden { display: none; }
.vn-lock-note { font-size: 11.5px; color: var(--text-faint); margin-top: 10px; }

.note-locked {
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 10px; text-align: center; padding: 64px 24px; min-height: 320px;
}
.note-locked-icon { font-size: 34px; opacity: 0.85; }
.note-locked-title { font-size: 16px; font-weight: 700; color: var(--text-heading); }
.note-locked-body { font-size: 13px; line-height: 1.6; color: var(--text-muted); max-width: 380px; }
.note-locked-btn { margin-top: 8px; padding: 8px 18px; border-radius: 7px; cursor: pointer;
  border: 1px solid var(--accent); background: var(--accent); color: #fff; font-size: 13px; font-weight: 600; }
.note-locked-btn:hover { background: var(--accent-strong, var(--accent)); }

/* A locked note is marked in the tree, so "which of these is sealed" is a
   glance rather than a click. */
.tree-item.is-locked > .tree-label::after {
  content: '🔒'; font-size: 10px; margin-left: 5px; opacity: 0.7;
}
.vn-lock-busy {
  position: fixed; inset: 0; display: flex; align-items: center; justify-content: center;
  z-index: 3000; font-size: 13px; color: var(--text-heading); font-weight: 600;
  background: color-mix(in srgb, var(--bg-primary) 72%, transparent);
}
/* Nothing that writes is offered while a note is sealed. */
body.note-is-sealed #mode-toggle { opacity: 0.4; pointer-events: none; }

/* The due chip inside a Tasks block / To-dos widget. Same shape as the one on
   the To-dos page, but read-only here — this list is for looking at, and the
   note is one click away for changing anything. */
.tn-task-due {
  flex: none; margin-left: auto; align-self: flex-start; margin-top: 2px;
  font-size: 10.5px; font-weight: 600; font-family: var(--font-mono); white-space: nowrap;
  color: var(--text-muted, var(--text-normal)); background: var(--bg-tertiary);
  border: 1px solid var(--border); border-radius: 999px; padding: 1px 7px;
}
.tn-task-due.late { color: var(--danger, #c2410c); border-color: color-mix(in srgb, var(--danger, #c2410c) 40%, transparent); background: color-mix(in srgb, var(--danger, #c2410c) 10%, transparent); }
.tn-task-due.now  { color: var(--accent); border-color: color-mix(in srgb, var(--accent) 45%, transparent); }
.tn-task.done .tn-task-due { opacity: 0.5; }
.tn-tasks-more { font-size: 11.5px; color: var(--text-faint); padding: 6px 0 0 10px; }
/* A multi-line field needs the whole width, so its label sits above it rather
   than squeezing it into the right-hand column. */
.wg-cfg-row.wg-cfg-wide { grid-template-columns: 1fr; }
.wg-cfg-row.wg-cfg-wide textarea.wg-cfg-input {
  width: 100%; min-width: 0; resize: vertical; font-family: var(--font-mono); font-size: 12px; line-height: 1.5;
}

/* ============== "this block could not become Markdown" ==============
   Amber rather than red on purpose: nothing is lost, the note still works, and
   the block is being kept as HTML precisely so nothing changes. Red would
   overstate it, and an alarming badge nobody can act on is worse than none. */
.tree-frozen {
  flex: none; margin-left: 6px; min-width: 16px; height: 16px; padding: 0 4px;
  display: inline-flex; align-items: center; justify-content: center;
  font-family: var(--font-mono); font-size: 10px; font-weight: 700; line-height: 1;
  color: var(--warn-ink, #8A6A2E); background: var(--warn-bg, color-mix(in srgb, #C9A227 20%, var(--bg-primary)));
  border: 1px solid color-mix(in srgb, #C9A227 45%, transparent); border-radius: 999px;
}
.tree-item.active .tree-frozen { color: inherit; border-color: currentColor; background: transparent; }

/* The floating button on a note that has them. Sits out of the way, bottom
   right, and only exists when there is something to say. */
.nh-fab {
  position: absolute; right: 22px; bottom: 46px; z-index: 30;
  display: inline-flex; align-items: center; gap: 7px; cursor: pointer;
  padding: 8px 13px; border-radius: 999px; font-size: 12.5px; font-weight: 600;
  color: var(--warn-ink, #8A6A2E);
  background: color-mix(in srgb, #C9A227 16%, var(--bg-primary));
  border: 1px solid color-mix(in srgb, #C9A227 40%, transparent);
  box-shadow: 0 4px 14px rgba(0,0,0,.10);
}
.nh-fab:hover { background: color-mix(in srgb, #C9A227 26%, var(--bg-primary)); transform: translateY(-1px); }
.nh-fab-n {
  min-width: 17px; height: 17px; padding: 0 4px; border-radius: 999px;
  display: inline-flex; align-items: center; justify-content: center;
  font-family: var(--font-mono); font-size: 10px;
  background: color-mix(in srgb, #C9A227 55%, var(--bg-primary));
}

.nh-panel { width: 520px; max-width: 94vw; max-height: 76vh; overflow-y: auto; }
.nh-intro { font-size: 12.5px; line-height: 1.55; color: var(--text-muted); margin-bottom: 14px; }
.nh-item { border: 1px solid var(--border); border-radius: 10px; padding: 12px 14px; margin-bottom: 10px; }
.nh-item.is-ok { border-style: dashed; opacity: 0.85; }
.nh-head { display: flex; align-items: baseline; gap: 8px; margin-bottom: 7px; }
.nh-title { font-size: 13.5px; font-weight: 700; color: var(--text-heading); }
.nh-line {
  font-family: var(--font-mono); font-size: 10.5px; color: var(--text-faint);
  border: 1px solid var(--border); border-radius: 999px; padding: 1px 7px; flex: none;
}
.nh-why, .nh-fix { font-size: 12.5px; line-height: 1.6; color: var(--text-muted); margin-bottom: 6px; }
.nh-fix strong, .nh-why strong { color: var(--text-heading); }
.nh-code {
  font-family: var(--font-mono); font-size: 11px; line-height: 1.5; white-space: pre-wrap;
  word-break: break-all; background: var(--bg-tertiary); border: 1px solid var(--border);
  border-radius: 7px; padding: 8px 10px; margin-top: 8px; max-height: 120px; overflow: auto;
  color: var(--text-muted);
}
.nh-actions { display: flex; gap: 8px; margin-top: 9px; }
.nh-actions button {
  font: inherit; font-size: 12px; font-weight: 600; cursor: pointer; padding: 5px 11px;
  border-radius: 7px; border: 1px solid var(--border); background: var(--bg-tertiary); color: var(--text-normal);
}
.nh-actions button:hover { border-color: var(--accent); color: var(--accent); }

/* What "jump to it" lands on. */
@keyframes nh-flash { 0%,100% { background: transparent; } 25%,75% { background: color-mix(in srgb, #C9A227 22%, transparent); } }
.nh-target { animation: nh-flash 1.6s ease; border-radius: 6px; }

/* ============== the colour picker ==============
   Anchored to the button rather than centred, because picking a colour is an
   adjustment to text you are looking at — a modal in the middle of the screen
   would hide the thing being coloured. */
.tn-cp-overlay { background: transparent; }
.tn-cp {
  position: fixed; width: 264px; z-index: 2001;
  background: var(--bg-secondary); border: 1px solid var(--border-strong, var(--border));
  border-radius: 12px; padding: 12px; box-shadow: 0 18px 48px rgba(0,0,0,.22);
}
.tn-cp-title { font-size: 13px; font-weight: 700; color: var(--text-heading); margin-bottom: 9px; }
.tn-cp-label { font-size: 10.5px; font-weight: 700; letter-spacing: .06em; text-transform: uppercase;
  color: var(--text-faint); margin: 12px 0 6px; }
.tn-cp-grid { display: grid; grid-template-columns: repeat(6, 1fr); gap: 6px; }
.tn-cp-sw {
  aspect-ratio: 1; border-radius: 7px; cursor: pointer; padding: 0;
  border: 1px solid color-mix(in srgb, var(--text-normal) 22%, transparent);
}
.tn-cp-sw:hover { transform: scale(1.12); border-color: var(--accent); }
.tn-cp-custom { display: flex; gap: 6px; align-items: center; }
.tn-cp-input { width: 34px; height: 30px; padding: 0; border: 1px solid var(--border); border-radius: 7px;
  background: none; cursor: pointer; }
.tn-cp-hex {
  flex: 1; min-width: 0; font-family: var(--font-mono); font-size: 12px; padding: 6px 8px;
  border: 1px solid var(--border); border-radius: 7px; background: var(--bg-primary); color: var(--text-normal);
}
.tn-cp-hex:focus { outline: none; border-color: var(--accent); }
.tn-cp-use { font: inherit; font-size: 12px; font-weight: 600; padding: 6px 11px; border-radius: 7px;
  cursor: pointer; border: 1px solid var(--accent); background: var(--accent); color: #fff; }
.tn-cp-none {
  width: 100%; margin-top: 11px; font: inherit; font-size: 12px; font-weight: 600; cursor: pointer;
  padding: 7px; border-radius: 7px; border: 1px solid var(--border);
  background: var(--bg-tertiary); color: var(--text-muted);
}
.tn-cp-none:hover { border-color: var(--accent); color: var(--accent); }

/* A custom highlight carries its colour inline, so it needs the chip shape and
   nothing else — the colour itself is on the element. */
mark.tn-hl {
  color: inherit; border-radius: 3px; padding: 0 2px;
  box-decoration-break: clone; -webkit-box-decoration-break: clone;
}

/* The post-paste offer. Anchored bottom-centre over the note rather than in a
   corner: it is about the words that just landed, and it has to be noticed
   within the few seconds someone is still looking at them. */
.paste-offer {
  position: absolute; left: 50%; bottom: 22px; transform: translateX(-50%);
  z-index: 120; display: flex; align-items: center; gap: 10px;
  padding: 8px 10px 8px 14px; border-radius: 999px;
  background: var(--bg-secondary); border: 1px solid var(--border-strong, var(--border));
  box-shadow: 0 10px 30px rgba(0,0,0,.18);
  font-size: 12.5px; color: var(--text-muted); white-space: nowrap;
  animation: po-in .18s ease-out;
}
@keyframes po-in { from { opacity: 0; transform: translate(-50%, 6px); } }
.paste-offer button {
  font: inherit; font-weight: 600; cursor: pointer; border-radius: 999px;
  padding: 5px 11px; border: 1px solid var(--accent); background: var(--accent); color: #fff;
}
.paste-offer .po-x {
  padding: 4px 8px; border-color: transparent; background: none; color: var(--text-faint); font-weight: 400;
}
.paste-offer .po-x:hover { color: var(--text-normal); }

/* The header buttons that only apply to a note.

   shell.js has always toggled a `hidden` class on #hdr-share, and nothing ever
   acted on it: .icon-btn sets display:flex and no rule overrode it, so Share
   sat in the header on every view including the ones where clicking it does
   nothing. Found when the Download button copied the same pattern and was
   likewise visible everywhere. Scoped to this row rather than made a global
   .hidden rule, because plenty of other code uses that class name for its own
   purposes. */
.header-actions .icon-btn.hidden { display: none; }

/* ---- the web app's front door (js/app/web-gate.js) ----
   Covers the shell rather than replacing it: the app behind is real and will be
   usable the moment there is a session, and a covered app reads as "not yet"
   where a blank page reads as "broken". Uses the theme's own tokens, so it
   follows whichever theme is set instead of being a second palette to maintain. */
.web-gate {
  /* 9000 covers the app shell. #e2e-overlay deliberately sits ABOVE this at
     9500: the LOCKED gate's button opens it, and a modal underneath an opaque
     cover is indistinguishable from a dead button. */
  position: fixed; inset: 0; z-index: 9000;
  display: flex; align-items: center; justify-content: center;
  background: var(--bg-primary);
  /* Opaque, not translucent. A half-visible empty library behind the message
     looks like the app failed to load its content. */
  padding: 24px;
}
.web-gate-card {
  max-width: 380px; text-align: center;
  display: flex; flex-direction: column; align-items: center; gap: 14px;
}
.web-gate-card img { border-radius: 10px; opacity: 0.9; }
.web-gate-card h1 {
  margin: 0; font-size: 20px; font-weight: 600; color: var(--text-heading);
}
.web-gate-card p {
  margin: 0; font-size: 14px; line-height: 1.6; color: var(--text-muted);
}
.web-gate-btn {
  margin-top: 6px; padding: 9px 20px; border-radius: 8px; border: 0;
  background: var(--accent); color: #fff;
  font: inherit; font-size: 14px; font-weight: 500;
  text-decoration: none; cursor: pointer;
}

/* The gate's secondary action — "use a folder instead". Quiet on purpose: it is
   the way out for someone sealed behind the sign-in overlay in cloud-only mode,
   not a peer of the primary action. */
.web-gate-alt {
  display: block; margin-top: 14px; font-size: 12px;
  color: var(--dim, #8b90a0); text-decoration: none; cursor: pointer;
}
.web-gate-alt:hover { text-decoration: underline; }
.web-gate-alt.hidden { display: none; }
.web-gate-btn:hover { background: var(--accent-strong); }

/* ============================ Phones ============================
   The desktop shell is three columns — file tree, note, panels — held apart by
   draggable resizers. At 375px that arithmetic leaves the NOTE two pixels wide,
   which is not a cramped layout so much as an absent one.

   On a phone the note is the whole screen and the two side columns become
   drawers over it. Nothing new is introduced to open them: the header already
   has toggle-left and toggle-right, and `.collapsed` already means "not on
   screen" (display:none, line 155) — so a collapsed sidebar gives #main the
   full width for free, and the only work left is making an OPEN one overlay the
   note instead of squeezing it.

   760px rather than a device width: the point is not "is this an iPhone", it is
   "are three columns still honest here", and they stop being honest on a small
   tablet in portrait too. */
@media (max-width: 760px) {
  #left-sidebar, #right-sidebar {
    position: fixed;
    top: 0;
    bottom: 0;
    z-index: 60;
    /* !important because the panel resizer writes an INLINE width, and an
       inline style beats any stylesheet rule. Without this a sidebar dragged
       wide on a desktop follows the account to the phone — a 500px drawer on a
       375px screen, hanging off the edge with no way to reach the rest. The
       resizer is hidden here anyway (nothing to drag with a finger), so there
       is no width on a phone worth preserving. */
    width: min(86vw, 340px) !important;
    box-shadow: 0 0 40px rgba(0, 0, 0, 0.22);
  }
  #left-sidebar { left: 0; }
  #right-sidebar { right: 0; }

  /* Nothing to drag with a finger, and a 4px target is not a target. */
  .panel-resizer { display: none !important; }

  #main { flex: 1 1 100%; min-width: 0; }

  /* Tapping the note closes the drawer, so the drawer needs something to be
     tapped BESIDE. Only present while one is open. */
  .mobile-scrim {
    position: fixed;
    inset: 0;
    z-index: 55;
    background: rgba(0, 0, 0, 0.32);
    -webkit-tap-highlight-color: transparent;
  }

  /* Apple's own minimum is 44px, and every toolbar button here is smaller.
     Grown by padding rather than by size, so the icons do not change. */
  #view-header .icon-btn,
  .pane-actions .icon-btn,
  .sidebar-tab { min-width: 44px; min-height: 44px; }

  /* The notch and the home indicator. Without this the header sits under the
     status bar and the status line under the gesture bar. */
  #view-header { padding-top: max(8px, env(safe-area-inset-top)); }
  #status-bar { bottom: max(8px, env(safe-area-inset-bottom)); }
  #left-sidebar, #right-sidebar {
    padding-top: env(safe-area-inset-top);
    padding-bottom: env(safe-area-inset-bottom);
  }

  /* The header is one row of three groups — history arrows, the omnibox, and
     eight action buttons. At 375px that comes to 422px, so the last two
     buttons (settings among them) sit off the right edge with nothing to
     scroll: the header does not scroll, the PAGE does not scroll sideways, and
     they are simply unreachable. And the omnibox, being the flexible one, is
     squeezed to 30px — a search field too narrow to show a letter.

     So it becomes two rows: controls above, omnibox across the full width
     below, where it is the most useful control on a phone rather than the most
     crushed. The action group scrolls sideways on its own if it still does not
     fit, which keeps every button reachable without deciding for someone which
     ones matter. */
  /* height:auto is REQUIRED, not tidiness. The base rule pins #view-header to
     a fixed 46px (style.css:436) and `* { box-sizing: border-box }` makes that
     the OUTER box, so wrapping to a second row had nowhere to go: the omnibox
     row rendered outside the header's own box. Wrapping without releasing the
     height is not a layout, it is an overflow. */
  #view-header { flex-wrap: wrap; row-gap: 6px; height: auto; min-height: 46px; }
  #omnibox { order: 3; flex: 1 1 100%; min-width: 0; }
  #view-header .header-actions {
    margin-left: auto;
    /* overflow-x alone does nothing here. The base rule sets flex-shrink: 0
       (style.css:441), and a flex item that cannot shrink is laid out at its
       max-content width — so its content never exceeds its own box and there is
       never anything to scroll. Releasing the shrink, and min-width:0 so it may
       go below max-content, is what makes the overflow real. */
    flex-shrink: 1;
    min-width: 0;
    overflow-x: auto;
    scrollbar-width: none;
    -webkit-overflow-scrolling: touch;
  }
  #view-header .header-actions::-webkit-scrollbar { display: none; }

  /* iOS zooms the page when a focused input is under 16px. The editor is not an
     input, but the palette and every prompt are, and the zoom does not undo
     itself. */
  input, textarea, select { font-size: max(16px, 1em); }

  /* ---- Settings, as a phone screen ----

     The desktop box is a 208px nav beside the page, inside min(920px, 94vw).
     At 375px that is a 144px page guttered by a nav you cannot shrink — the
     one screen the owner named as unreachable. Same buttons, same ids (they
     are the deep-link vocabulary), different axis: the box takes the screen,
     the nav lies down as one scrolling row of chips, the page gets the rest. */
  #settings-box { width: 100vw; height: 100dvh; max-height: none; border-radius: 0; border: 0; flex-direction: column; }
  #settings-side {
    width: auto; flex-shrink: 0; flex-direction: column; gap: 8px;
    padding: max(10px, env(safe-area-inset-top)) 12px 10px;
    border-right: 0; border-bottom: 1px solid var(--border);
  }
  .settings-nav {
    flex-direction: row; align-items: center; gap: 4px;
    overflow-x: auto; overflow-y: hidden; scrollbar-width: none;
    -webkit-overflow-scrolling: touch; margin: 0 -12px; padding: 0 12px;
  }
  .settings-nav::-webkit-scrollbar { display: none; }
  /* A group heading in a horizontal row reads as a chip that does nothing —
     the grouping is a desktop luxury; the row keeps every page one flick away. */
  .settings-nav .settings-nav-group { margin: 0 2px 0 8px; white-space: nowrap; }
  .settings-nav .settings-nav-group:first-child { margin-left: 0; }
  .settings-nav-item { flex: none; white-space: nowrap; padding: 7px 11px; }
  #settings-main { padding-bottom: max(20px, env(safe-area-inset-bottom)); }

  /* ---- The study session, one-handed ----

     The card already fits; the furniture around it did not. The head wraps
     instead of shoving Back and Flag off the edge, and the four grades become
     a 2x2 of thumb-sized targets instead of a 4-across row of 76px slivers. */
  #study-head { flex-wrap: wrap; row-gap: 4px; padding: 10px 12px 6px; }
  #study-bar { margin: 0 12px 2px; }
  #study-card { width: calc(100% - 20px); margin: 8px auto; padding: 18px 16px; }
  #study-grades { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; width: 100%; }
  #study-grades button { min-height: 52px; width: 100%; }
  #study-actions { padding: 6px 10px 4px; }
  #study-reveal { width: 100%; min-height: 48px; }
  #study-cram-actions { width: 100%; }
  #study-cram-actions button { flex: 1; min-height: 48px; }
  /* The key legend is a desktop sentence — a phone has no Z, F or Space. */
  #study-hint { display: none; }
  #study-foot { padding: 4px 12px 10px; }

  /* The Study page itself: the dashboard gutters shrink to the screen. */
  #study-home.visible { padding: 8px 10px 0; }

  /* One sitting, opened: the paper takes the screen rather than floating. */
  #sitting-overlay { padding: 0; }
  #sitting-box { width: 100vw; max-height: 100dvh; height: 100dvh; border-radius: 0; border: 0; }
  #sitting-head { padding-top: max(12px, env(safe-area-inset-top)); }
  #sitting-body { padding-bottom: max(18px, env(safe-area-inset-bottom)); }

  /* ---- The formatting toolbar ----

     It wrapped into three colliding rows over the header's own icons. One row
     that scrolls keeps every button, decides for nobody, and matches how the
     header actions already behave here. */
  #toolbar { flex-wrap: nowrap; overflow-x: auto; scrollbar-width: none; -webkit-overflow-scrolling: touch; }
  #toolbar::-webkit-scrollbar { display: none; }

  /* The deck chooser and context menus: finger-sized rows. */
  #context-menu button, .cm-submenu button { min-height: 42px; }

  /* "type / for blocks · [[ for links" is advice about a keyboard this screen
     does not have, and it stretched the toolbar's scroll strip to 792px. */
  .tb-hint { display: none; }

  /* The to-do composer: the row's pieces fit the row, not a fixed sum. */
  .todo-add { flex-wrap: wrap; }
  .todo-add-target { min-width: 0; flex: 1 1 160px; }

  /* The canvas tools: one strip that scrolls, like every other strip here. */
  .cv-toolbar { max-width: calc(100vw - 60px); overflow-x: auto; scrollbar-width: none; }
  .cv-toolbar::-webkit-scrollbar { display: none; }
}

/* The hover name (tooltip.js) — shared by the dock's icons and by tree rows
   whose filename is cut off. On <body> because both live in a scroll box that
   would clip it, and with no transition because the delay is the whole point
   of it not being the operating system's own. */
#app-tip {
  position: fixed; z-index: 70; pointer-events: none;
  max-width: min(420px, 60vw);
  padding: 5px 9px; border-radius: 8px;
  background: var(--text-heading); color: var(--bg-primary);
  font-family: var(--font-ui); font-size: 12px; font-weight: 500; line-height: 1.35;
  white-space: pre-line; overflow-wrap: anywhere;
  box-shadow: 0 2px 10px rgba(0, 0, 0, 0.18);
}
#app-tip[hidden] { display: none; }

/* A multi-selected tree row. Distinct from .active — active is "this note is
   open", selected is "this row is part of the group you are about to drag" —
   and a row can be both, so this must not simply repaint the active fill. */
#file-tree .tree-item.tree-selected {
  background: color-mix(in srgb, var(--accent) 18%, transparent);
  box-shadow: inset 2px 0 0 var(--accent);
}
#file-tree .tree-item.tree-selected.active {
  box-shadow: inset 2px 0 0 var(--accent);
}

/* The bulk-operation progress line. Wears the update toast's shell so it reads
   as part of the app, but it is a status readout rather than a button — no
   pointer, no hover affordance, and it sits a little higher so the two can
   coexist if an update lands mid-import. */
/* VISIBLE WITHOUT AN ANIMATION HAVING TO RUN.

   .update-toast starts at opacity 0 and is faded in by adding .in. That is fine
   for a toast the user is looking at, and wrong for a progress line: a
   background tab runs neither requestAnimationFrame nor CSS transitions, so the
   opacity would sit at 0 forever and the one thing whose entire job is to say
   "still working" would be invisible in exactly the case where somebody has
   switched away to wait.

   So this is opaque in both states and only the slide is animated. Both
   selectors carry the same specificity as .update-toast.in and come later, so
   they win in both. */
.bulk-progress,
.bulk-progress.in {
  cursor: default;
  bottom: 148px;
  min-width: 240px;
  opacity: 1;
}
.bulk-progress:hover { border-color: var(--panel-border); }
.bulk-progress .bulk-text { font-size: 14px; }
.bulk-spinner {
  width: 14px; height: 14px; flex: 0 0 14px;
  border: 2px solid color-mix(in srgb, var(--text-heading) 25%, transparent);
  border-top-color: var(--accent);
  border-radius: 50%;
  animation: bulk-spin .7s linear infinite;
}
@keyframes bulk-spin { to { transform: rotate(360deg); } }
/* Respect a system preference for less motion: the spinner is decoration, and
   the text alone already says what is happening. */
@media (prefers-reduced-motion: reduce) {
  .bulk-spinner { animation: none; border-top-color: var(--accent); }
}

/* ---- Q&A page (settings) ---- */
/* A question is a row you can click; the answer unfolds under it. <details>
   rather than a JS accordion so keyboard and find-in-page work for free. */
.faq-item {
  border-bottom: 1px solid var(--border);
  padding: 2px 0;
}
.faq-item > summary {
  cursor: pointer;
  padding: 9px 4px;
  font-weight: 500;
  list-style: none;
  display: flex;
  align-items: flex-start;
  gap: 8px;
}
.faq-item > summary::-webkit-details-marker { display: none; }
.faq-item > summary::before {
  content: '›';
  color: var(--text-dim);
  transform: rotate(0deg);
  transition: transform .12s ease;
  line-height: 1.35;
}
.faq-item[open] > summary::before { transform: rotate(90deg); }
.faq-item > summary:hover { color: var(--accent); }
.faq-answer {
  padding: 0 4px 12px 20px;
  color: var(--text-dim);
  line-height: 1.55;
}
.faq-answer p { margin: 0 0 8px; }
.faq-answer p:last-child { margin-bottom: 0; }
.faq-answer ul { margin: 4px 0 8px; padding-left: 18px; }
.faq-answer li { margin: 2px 0; }

/* ============================ Home ============================
   Almost no styling of its own, on purpose: the head is the Library's, the
   section labels and task rows are the To-dos page's, the schedule is the
   Calendar's thread and the study button is the Study page's — see
   home-view.js. What is left here is only the layout that puts them side by
   side. */
#home-view { display: none; flex: 1; min-height: 0; }
#home-view.visible { display: block; }

/* The day on the left, the work on the right. Two plain columns rather than a
   grid of boxes: each column is a stack, so they can differ in height without
   leaving holes, and a task row gets the full width of its column. */
.home-cols {
  display: grid; gap: 34px; align-items: start; max-width: 1180px;
  grid-template-columns: minmax(0, 3fr) minmax(280px, 2fr);
}
/* Stacked, the groups' own spacing is the rhythm — adding the column gap on top
   left one hole twice the size of the rest, right above the second column. */
@media (max-width: 1100px) { .home-cols { grid-template-columns: minmax(0, 1fr); row-gap: 0; } }
.home-main, .home-side { min-width: 0; }

.home-quiet { padding: 4px 4px 2px; font-size: 13px; color: var(--text-faint); }
.home-more { display: inline-block; margin: 6px 0 0 30px; }

/* The schedule is the Calendar's thread (.cv-thread and its rows, unscoped,
   drawn by calendar-view.js's dayThread). Only the room around it is Home's. */
.home-main .cv-thread { margin-top: 4px; }

/* Study in the head: a count and the Study page's own button, pushed to the
   right the way the Library pushes its Sort button. */
.home-head { align-items: center; }
.home-study { margin-left: auto; display: flex; align-items: center; gap: 12px; }
.home-study-n { font-size: 12px; font-family: var(--font-mono); color: var(--text-faint); white-space: nowrap; }
.home-study-go { width: auto; padding: 7px 16px; white-space: nowrap; }
@media (max-width: 760px) { .home-head { flex-wrap: wrap; } .home-study { margin-left: 0; width: 100%; } }
.home-decks { display: flex; flex-direction: column; gap: 2px; margin-top: 8px; }

/* ON HOME A TASK'S NOTE IS A QUIET SECOND LINE, not a column beside it.

   The To-dos row puts the note name in its own column, which is right on a page
   that is nothing but rows. In Home's narrower column that column took a third
   of the width to say "ISYE 6501 - Week 1 - What t…", and every long task
   wrapped to make room for it. Same row, same element — only laid out as the
   task first and where it lives underneath, the way a reader takes it in. */
.home-cols .todo-row {
  display: grid; align-items: start; column-gap: 10px;
  grid-template-columns: auto minmax(0, 1fr) auto;
  grid-template-areas: "box text due" "box from .";
}
.home-cols .todo-row > .todo-box { grid-area: box; }
.home-cols .todo-row > .todo-text { grid-area: text; }
.home-cols .todo-row > .todo-due { grid-area: due; }
.home-cols .todo-row > .todo-from {
  grid-area: from; justify-self: start; max-width: 100%;
  padding: 0; margin-top: 1px; text-align: left;
}

/* Pinned: a row per note, the name and the folder it lives in, and a quiet ×
   that appears when you reach for it. */
.home-pin { padding: 0 4px 0 0; gap: 4px; }
.home-pin-open {
  flex: 1; min-width: 0; display: flex; align-items: baseline; gap: 10px;
  font: inherit; color: inherit; text-align: left;
  background: none; border: 0; padding: 7px 9px; cursor: pointer;
}
.home-pin-where {
  flex: none; max-width: 45%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  font-size: 11.5px; color: var(--text-faint);
}
.home-pin-x {
  flex: none; width: 24px; height: 24px; border-radius: 6px; border: 0;
  background: none; color: var(--text-faint); font-size: 15px; line-height: 1; cursor: pointer;
  opacity: 0; transition: opacity .12s ease;
}
.home-pin:hover .home-pin-x, .home-pin-x:focus-visible { opacity: 1; }
.home-pin-x:hover { color: var(--text-heading); background: var(--bg-hover); }
.home-side .home-more { margin-left: 9px; }


/* ============================ The boot curtain ============================
   Shown only when the wait is real (boot-loader.js holds it back for a
   quarter-second), so a fast load never flashes a splash. Painted from the
   theme's own variables, with literal fallbacks, because it has to look right
   BEFORE applySettings has run — at that moment :root carries only what this
   file declares. */
#boot-loader {
  position: fixed; inset: 0; z-index: 9999;
  display: grid; place-items: center;
  background: var(--app-bg, #17150F);
  opacity: 0; pointer-events: none;
  transition: opacity 0.22s ease;
}
#boot-loader.show { opacity: 1; pointer-events: auto; }
#boot-loader .bl-inner { display: flex; flex-direction: column; align-items: center; gap: 0; }

/* The mark, at a canter. Not a spinner: a spinner says "busy", and the thing
   worth saying here is whose app you are waiting for. */
#boot-loader .bl-mark {
  width: 76px; height: 76px;
  /* Transparent art: a drop-shadow FILTER follows the mark's own silhouette,
     where a box-shadow would square it off. */
  filter: drop-shadow(0 8px 18px rgba(0, 0, 0, 0.22));
  animation: bl-canter 1.6s ease-in-out infinite;
}
@keyframes bl-canter {
  0%, 100% { transform: translateY(0) rotate(-1.5deg); }
  50%      { transform: translateY(-9px) rotate(1.5deg); }
}

#boot-loader .bl-title {
  margin-top: 22px;
  font-family: var(--font-ui, system-ui, sans-serif);
  font-size: 15px; font-weight: 600; letter-spacing: 0.01em;
  color: var(--text-heading, #EDE7DC);
}

#boot-loader .bl-bar {
  position: relative; overflow: hidden;
  width: 232px; height: 4px; margin-top: 16px;
  border-radius: 999px;
  background: var(--bg-tertiary, rgba(255, 255, 255, 0.11));
}
#boot-loader .bl-fill {
  position: absolute; inset: 0 auto 0 0;
  width: 34%; border-radius: 999px;
  background: var(--accent, #3B6EF6);
}
/* Until the first count arrives there is nothing honest to show, so the bar
   sweeps instead of claiming a number. The moment real progress lands,
   .measured stops the sweep and the width takes over. */
#boot-loader:not(.measured) .bl-fill {
  animation: bl-sweep 1.15s ease-in-out infinite;
}
#boot-loader.measured .bl-fill { transition: width 0.28s ease; }
@keyframes bl-sweep {
  0%   { left: -36%; }
  100% { left: 100%; }
}

#boot-loader .bl-count {
  margin-top: 11px;
  font-family: var(--font-ui, system-ui, sans-serif);
  font-size: 12.5px; color: var(--text-faint, #9A9287);
  font-variant-numeric: tabular-nums;
}

@media (prefers-reduced-motion: reduce) {
  #boot-loader .bl-mark { animation: none; }
  #boot-loader:not(.measured) .bl-fill { animation: none; left: 0; width: 100%; opacity: 0.45; }
}

/* ---- Not created yet: the names linked but never written ---- */
/* The graph can show them; this is the form you can act on — every name with
   how many notes say it, and a click that opens the cleanup dialog. */
.gs-hint { font-size: 12px; color: var(--text-faint); margin-bottom: 6px; }
.uw-rows { display: flex; flex-direction: column; gap: 2px; max-height: 260px; overflow: auto; }
.uw-row {
  display: flex; align-items: center; gap: 8px; width: 100%;
  padding: 5px 8px; border: 0; border-radius: 7px;
  background: none; color: var(--text-normal);
  font: inherit; font-size: 13px; text-align: left; cursor: pointer;
}
.uw-row:hover { background: var(--bg-hover); }
.uw-row-name { flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.uw-row-count {
  flex: none; min-width: 20px; padding: 0 6px; border-radius: 999px;
  background: var(--bg-hover); color: var(--text-faint);
  font-size: 11px; font-variant-numeric: tabular-nums; text-align: center;
}

/* The dialog: which notes, and what to do about them. */
.vn-dialog.vn-unwritten { max-width: 560px; width: min(560px, 92vw); }
.vn-unwritten .uw-tools { display: flex; justify-content: flex-end; margin: 2px 0 6px; }
.vn-unwritten .uw-list {
  display: flex; flex-direction: column; gap: 2px;
  max-height: 46vh; overflow: auto;
  border: 1px solid var(--border); border-radius: 10px; padding: 6px;
}
.vn-unwritten .uw-item {
  display: flex; gap: 9px; align-items: flex-start;
  padding: 6px 7px; border-radius: 7px; cursor: pointer;
}
.vn-unwritten .uw-item:hover { background: var(--bg-hover); }
.vn-unwritten .uw-item input { margin-top: 3px; flex: none; }
.vn-unwritten .uw-item-body { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.vn-unwritten .uw-note { font-size: 13px; font-weight: 600; overflow-wrap: anywhere; }
/* The sentence the link sits in — the thing you are actually deciding about. */
.vn-unwritten .uw-line { font-size: 12px; color: var(--text-faint); overflow-wrap: anywhere; }

/* ---- Settings → Connector → AI prompts ---- */
/* Ten prompts open at once is a wall of text, so each is a title and a line
   until you want it. */
.ai-prompts { display: flex; flex-direction: column; gap: 6px; margin-top: 4px; }
.ai-prompt {
  border: 1px solid var(--border); border-radius: 10px;
  background: var(--card-bg); padding: 2px 2px 0;
}
.ai-prompt > summary {
  display: flex; flex-direction: column; gap: 2px;
  padding: 9px 11px; border-radius: 9px; cursor: pointer; list-style: none;
}
.ai-prompt > summary::-webkit-details-marker { display: none; }
.ai-prompt > summary:hover { background: var(--bg-hover); }
.ai-prompt-title { font-size: 13.5px; font-weight: 600; color: var(--text-normal); }
.ai-prompt-blurb { font-size: 12.5px; color: var(--text-muted); }
/* Why this exists rather than what it does — the bit that stops a prompt being
   used for the job it is wrong for. */
.ai-prompt-why {
  margin: 0 11px 8px; padding: 8px 10px;
  border-left: 2px solid var(--accent); border-radius: 0 7px 7px 0;
  background: var(--bg-hover);
  font-size: 12.5px; color: var(--text-muted);
}
.ai-prompt-text {
  margin: 0 11px; padding: 10px 12px;
  border: 1px solid var(--border); border-radius: 8px;
  background: var(--app-bg);
  font-family: var(--font-mono); font-size: 12px; line-height: 1.55;
  color: var(--text-normal);
  white-space: pre-wrap; overflow-wrap: anywhere;
  max-height: 340px; overflow: auto;
}
.ai-prompt-actions { display: flex; justify-content: flex-end; padding: 8px 11px; }

/* ---- "Find frozen blocks across the library" ---- */
/* The notes it CANNOT repair are the interesting ones — they are where a cause
   nobody has fixed yet shows up — so each is named with the reason the planner
   actually gave, rather than summed into "5 left alone". */
.vn-dialog.vn-frozen { max-width: 620px; width: min(620px, 94vw); }
.vn-frozen .fz-list {
  display: flex; flex-direction: column; gap: 1px;
  max-height: 48vh; overflow: auto;
  border: 1px solid var(--border); border-radius: 10px; padding: 6px;
}
.vn-frozen .fz-row {
  display: grid; grid-template-columns: 1fr auto; gap: 2px 10px;
  padding: 7px 9px; border-radius: 7px;
}
.vn-frozen .fz-row:hover { background: var(--bg-hover); }
.vn-frozen .fz-name { font-size: 13px; font-weight: 600; overflow-wrap: anywhere; }
.vn-frozen .fz-n {
  justify-self: end; min-width: 20px; padding: 0 6px; border-radius: 999px;
  background: var(--bg-hover); color: var(--text-faint);
  font-size: 11px; font-variant-numeric: tabular-nums; text-align: center;
}
.vn-frozen .fz-why { grid-column: 1 / -1; font-size: 12px; color: var(--text-muted); }
/* Left alone on purpose: quieter, not alarming. */
.vn-frozen .fz-stuck .fz-name { font-weight: 500; color: var(--text-muted); }

/* ---- Micro-breaks widget ---- */
/* What to do right now, under the timer. One line, quiet — it is an
   instruction to disengage, not something else to read. */
.wg-gap-what { font-size: 12px; color: var(--text-muted); margin: 2px 0 6px; line-height: 1.45; }
/* The countdown WHILE STUDYING is hidden on purpose: watching it tick is the
   predictability the random interval exists to remove. It comes back for the
   break, where the number is the thing you want. */
.wg-timer.wg-gap-hidden { opacity: 0; }


/* ---------- The ```quiz block (quiz-block.js) ----------

   A form inside the note, not a fence you type into. Styled as a card so it
   reads as one object you can move and delete, the way the person who inserted
   it thinks of it. Every control is inside .tn-quiz, which is what the
   dehydrator removes in one go. */
.tn-quiz {
  border: 1px solid var(--border); border-radius: var(--radius-panel, 14px);
  background: var(--bg-secondary, var(--bg-primary)); padding: 14px 15px 11px; margin: 14px 0;
}
.qz-head { display: flex; align-items: center; justify-content: space-between; gap: 10px; margin-bottom: 9px; }
.qz-tag { font-size: 11px; font-weight: 700; letter-spacing: .05em; text-transform: uppercase; color: var(--text-muted); }
/* ---- a block holds a SET of questions ----
   Separated by a rule rather than by cards-inside-a-card: the block already has
   a border, and nesting a second one around each question turns a set of six
   into six boxes inside a box. A line says "next question" with no new edges. */
.qz-block + .qz-block { margin-top: 16px; padding-top: 14px; border-top: 1px solid var(--border); }
/* The head is a flex row with the tag and the type pushed apart, so a third
   child would land in the middle — it is pinned to the end instead. */
.qz-del-question { margin-left: 0; order: 3; border: none; background: none; color: var(--text-faint);
  font-size: 17px; line-height: 1; cursor: pointer; padding: 0 2px; border-radius: 6px; }
.qz-del-question:hover { color: var(--danger); background: var(--bg-hover); }
.qz-add-question { display: block; width: 100%; margin-top: 14px; padding: 9px 10px;
  border: 1px dashed var(--border); border-radius: var(--radius-active); background: none;
  color: var(--text-muted); font: inherit; font-size: 13px; cursor: pointer; }
.qz-add-question:hover { border-color: var(--accent); color: var(--accent); }
.qz-type { font-size: 11.5px; font-weight: 600; color: var(--accent); }
.tn-quiz textarea {
  width: 100%; font: inherit; color: var(--text-normal); background: transparent;
  border: 0; border-radius: 8px; padding: 5px 6px; resize: none; overflow: hidden;
}
.tn-quiz textarea:focus { outline: none; background: var(--card-bg, var(--bg-primary)); box-shadow: 0 0 0 2px var(--accent); }
.tn-quiz textarea::placeholder { color: var(--text-muted); opacity: .75; }
.qz-q { font-size: 16px; font-weight: 600; margin-bottom: 4px; }
.qz-a, .qz-explain { font-size: 13.5px; color: var(--text-muted); }

.qz-options { display: flex; flex-direction: column; gap: 2px; margin: 6px 0 4px; }
.qz-opt { display: flex; align-items: flex-start; gap: 9px; padding: 4px 6px; border-radius: 8px; }
.qz-opt:hover { background: var(--bg-hover); }
/* A ticked answer is marked by its OWN row, not by the checkbox alone: on
   Daylight a checkbox is drawn as a toggle switch, and a row of switches is
   much harder to read at a glance than a row with the right one lit. */
.qz-opt.on { background: color-mix(in srgb, var(--accent) 12%, transparent); }
.qz-opt input[type="checkbox"] { margin-top: 7px; flex: none; }
.qz-opt-text { flex: 1; min-width: 0; }
/* The pictures a quiz field holds, under it. Capped in height so a full-size
   screenshot cannot push the answers off the screen while you are writing
   them; the card itself shows them at their own size. */
.qz-pics { display: flex; flex-wrap: wrap; gap: 6px; margin: 2px 0 6px; }
.qz-pics img { max-height: 120px; max-width: 100%; border-radius: 6px; border: 1px solid var(--bg-modifier-border); }
.qz-del { flex: none; margin-top: 3px; background: none; border: 0; color: var(--text-muted); font-size: 17px; line-height: 1; cursor: pointer; padding: 2px 5px; border-radius: 6px; opacity: 0; }
.qz-opt:hover .qz-del, .qz-del:focus { opacity: 1; }
.qz-del:hover { color: #d0524a; background: var(--bg-hover); }
.qz-add { align-self: flex-start; margin-top: 3px; background: none; border: 0; color: var(--accent); font: inherit; font-size: 13px; font-weight: 600; cursor: pointer; padding: 5px 6px; border-radius: 8px; }
.qz-add:hover { background: var(--bg-hover); }
.qz-foot { margin-top: 8px; padding-top: 8px; border-top: 1px solid var(--border); font-size: 11.5px; color: var(--text-muted); }


/* ---------- Sitting a practice exam (study-view.js, mode 'exam') ----------
   Built inside #study-front, so it inherits the card's own width and padding
   and adds no element the SRS path has to remember to hide. */
.ex-q { font-size: 20px; font-weight: 600; color: var(--text-heading); margin-bottom: 6px; }
.ex-note { font-size: 13px; color: var(--text-muted); margin-bottom: 12px; }
.ex-options { display: flex; flex-direction: column; gap: 7px; margin: 14px 0 18px; text-align: left; }
.ex-opt { display: flex; align-items: flex-start; gap: 11px; padding: 11px 13px; border: 1px solid var(--border); border-radius: var(--radius-active); cursor: pointer; font-size: 15px; }
.ex-opt:hover { border-color: var(--accent); background: var(--bg-hover); }
.ex-opt input { margin-top: 3px; flex: none; }
/* After marking: the right answer is always shown, and a wrong pick you made is
   marked as yours — showing only "correct/incorrect" teaches nothing. */
.ex-opt.ex-right { border-color: #2E7D46; background: color-mix(in srgb, #2E7D46 12%, transparent); }
.ex-opt.ex-wrong { border-color: #d0524a; background: color-mix(in srgb, #d0524a 12%, transparent); }
.ex-written { text-align: left; margin: 14px 0 18px; }
.ex-typed { width: 100%; font: inherit; font-size: 15px; padding: 11px 13px; border-radius: var(--radius-active); border: 1px solid var(--border); background: var(--bg-primary); color: var(--text-normal); resize: vertical; }
.ex-answer { margin-top: 10px; font-size: 15px; color: var(--text-normal); }
.ex-explain { text-align: left; font-size: 14px; line-height: 1.55; color: var(--text-muted); margin: 0 0 16px; padding: 11px 13px; background: var(--bg-secondary, var(--bg-primary)); border-radius: var(--radius-active); }
.ex-actions { display: flex; align-items: center; justify-content: center; gap: 14px; }
.ex-verdict { font-size: 14px; font-weight: 700; }
.ex-verdict.ok { color: #2E7D46; }
.ex-verdict.no { color: #d0524a; }
.ex-check, .ex-next { border: none; border-radius: var(--radius-active); padding: 11px 22px; font: inherit; font-weight: 600; font-size: 15px; cursor: pointer; background: var(--accent); color: #fff; box-shadow: var(--shadow-active); }
.ex-missed { text-align: left; margin: 12px auto 16px; max-width: 460px; padding-left: 20px; font-size: 14px; line-height: 1.7; color: var(--text-normal); }


/* ---------- who is in this note (share-live.js) ----------
   Top right of the note, the way Google Docs does it — which is where the owner
   expected it to be. A word ("Shared") rather than only the tinted button,
   because a tint speaks only to people who already know what it means. */
.note-people { display: inline-flex; align-items: center; gap: 8px; margin-right: 6px; }
.np-label {
  font-size: 12px; font-weight: 600; letter-spacing: 0.01em;
  color: var(--accent);
  background: color-mix(in srgb, var(--accent) 12%, transparent);
  padding: 3px 9px; border-radius: 999px; white-space: nowrap;
  /* A button now — the count is on it and the people are behind it. */
  border: none; font-family: inherit; line-height: inherit; cursor: pointer;
}
.np-label:hover { background: color-mix(in srgb, var(--accent) 20%, transparent); }
.np-label:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

/* The read-only list a MEMBER opens from that button (the owner gets the Share
   dialog, which can change access). Fixed to the viewport so it can sit over
   the editor without the note header clipping it. */
.np-popover {
  position: fixed; z-index: 1200; min-width: 230px; max-width: 320px;
  background: var(--card-bg, var(--bg-primary)); color: var(--text-normal);
  border: 1px solid var(--border); border-radius: 12px;
  box-shadow: 0 12px 32px rgba(0, 0, 0, 0.18); padding: 10px;
}
.np-popover-head { font-size: 11.5px; font-weight: 600; color: var(--text-muted); margin: 0 2px 8px; }
.np-popover-empty { font-size: 12.5px; color: var(--text-muted); padding: 2px; }
.np-popover-row { display: flex; align-items: center; gap: 8px; padding: 4px 2px; }
.np-popover-row .np-face, .share-person .np-face { margin-left: 0; flex: none; }
.np-popover-name { flex: 1; min-width: 0; font-size: 13px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.np-popover-role { font-size: 11.5px; color: var(--text-muted); white-space: nowrap; }
.np-faces { display: inline-flex; }
.np-faces:empty { display: none; }
/* Overlapped, like every collaborator stack: the faces are one group. The
   ring is the BACKGROUND colour, which is what makes the overlap legible. */
.np-face {
  width: 24px; height: 24px; border-radius: 50%;
  display: inline-flex; align-items: center; justify-content: center;
  font-size: 10px; font-weight: 700; color: var(--text-heading);
  background: var(--bg-hover, rgba(0,0,0,0.08));
  box-shadow: 0 0 0 2px var(--card-bg, #fff);
  margin-left: -6px; cursor: default;
}
/* A person's own colour (peer-block.js personColor), the one their mark in the
   margin wears — so a face can be matched to a paragraph at a glance. */
.np-face[style*="--face-color"] { background: var(--face-color); color: #fff; }
.np-face:first-child { margin-left: 0; }
/* TYPING, as opposed to looking: the accent ring. "It doesn't show that
   someone is editing" was the complaint, and reading vs writing is the
   difference worth knowing before you change the paragraph they are in. */
.np-face.editing { box-shadow: 0 0 0 2px var(--card-bg, #fff), 0 0 0 4px var(--face-color, var(--accent)); }
.np-face.more { font-size: 9.5px; color: var(--text-muted); }
/* AWAY — their window is hidden, or nothing has been touched for a few
   minutes. Still in the note, not looking at it; the banner leaves them out. */
.np-face.away { opacity: 0.4; filter: grayscale(0.4); }

/* ---------- the other person's cursor (peer-carets.js) ----------
   The Google Docs "|": a thin bar in their colour at the place they are (or
   are about to be) typing, with their name above it for a moment after it
   moves. In a fixed layer OVER the editor, never inside it, so it cannot reach
   a saved file, move your own caret or land in your undo history; and it never
   takes a click. */
.peer-caret-layer { position: fixed; inset: 0; pointer-events: none; z-index: 30; }
.peer-caret {
  position: fixed; width: 2px; margin-left: -1px; border-radius: 1px;
  background: var(--peer-color, var(--accent));
  box-shadow: 0 0 0 0.5px color-mix(in srgb, var(--peer-color, var(--accent)) 40%, transparent);
}
.peer-caret-flag {
  position: absolute; bottom: 100%; left: -1px; margin-bottom: 1px;
  font-size: 10.5px; font-weight: 600; line-height: 1.5; letter-spacing: 0.01em;
  color: #fff; background: var(--peer-color, var(--accent));
  padding: 0 5px; border-radius: 4px 4px 4px 0; white-space: nowrap;
  opacity: 0; transform: translateY(2px);
  transition: opacity 0.18s ease-out, transform 0.18s ease-out;
}
.peer-caret.recent .peer-caret-flag { opacity: 1; transform: none; }

/* ---------- somebody else is working here (sync-live.js) ----------
   A paragraph mark, not a cursor. We cannot honestly draw a caret — the two
   copies are a second or two apart, so a cursor from their offset would sit in
   the wrong place often enough to be a lie. A paragraph identified by its text
   is the same paragraph in both copies, and when it cannot be found nothing is
   drawn at all.

   A RULE IN THE MARGIN rather than a fill: the text must stay exactly as
   readable as it was, and a background wash on a paragraph somebody is reading
   is the kind of help that gets switched off. Positioned on the block, so the
   name can sit beside it. */
.peer-at { position: relative; }
.peer-at::before {
  content: ''; position: absolute; top: 0; bottom: 0; left: -14px;
  width: 2px; border-radius: 2px; background: var(--peer-color, var(--accent));
  opacity: 0.85;
}
/* WHO, as well as where: their initial in a small dot of their colour, beside
   the top of the rule — always shown, because a mark you have to hover to
   identify is one nobody identifies. In the margin, never above the block: a
   label pinned above it covered the line above (measured), and the text must
   stay exactly as readable as it was. Hover widens it to the full name. */
.peer-at::after {
  content: attr(data-peer-initial);
  position: absolute; top: 1px; left: -14px;
  transform: translateX(calc(-100% - 4px));
  min-width: 16px; height: 16px; line-height: 16px; box-sizing: border-box;
  text-align: center; padding: 0 4px;
  font-size: 10px; font-weight: 700; letter-spacing: 0.01em;
  color: #fff; background: var(--peer-color, var(--accent));
  border-radius: 8px;
  white-space: nowrap; pointer-events: none;
}
.peer-at:hover::after { content: attr(data-peer); padding: 0 6px; }
.peer-at:hover::before { opacity: 1; }

/* ---------- conflict copies (conflicts-view.js) ----------
   A list somebody reads once and then never again, so it is plain: the verdict
   does the work, and the only colour is on the ones that need a decision. */
.conflict-row { padding: 10px 0; border-bottom: 1px solid var(--border); }
.conflict-row:last-of-type { border-bottom: 0; }
.conflict-head { display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap; }
.conflict-name { font-size: 13.5px; color: var(--text-normal); word-break: break-word; }
.conflict-verdict { font-size: 12px; color: var(--text-faint); }
/* Amber, not red: a copy holding something is not an error, it is a thing to
   read. Red would say "you have a problem" about the app working correctly. */
.conflict-verdict.warn { color: var(--highlight-text); }
.conflict-extra {
  margin: 6px 0 0; padding: 8px 12px; list-style: none;
  background: var(--bg-secondary, var(--bg-hover)); border-radius: var(--radius-active);
  font-size: 12.5px; line-height: 1.6; color: var(--text-normal);
}
.conflict-extra li { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.conflict-extra li.more { color: var(--text-faint); }
.conflict-acts { display: flex; gap: 6px; margin-top: 8px; flex-wrap: wrap; }

/* ---------- Today → "No day yet" (home-view.js) ----------
   The pile, with the three buttons that empty it. Quiet until hovered, because
   a list of things you have not planned should not shout over the day you have. */
.home-unplanned { display: flex; flex-direction: column; gap: 2px; }
.home-unplanned-row { display: flex; align-items: center; gap: 12px; padding: 7px 9px; border-radius: var(--radius-active); }
.home-unplanned-row:hover { background: var(--bg-hover); }
.home-unplanned-text { flex: 1; min-width: 0; font-size: 14px; color: var(--text-normal); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* How long it has been sitting — the fact that makes the list worth reading. */
.home-unplanned-age { margin-left: 8px; font-size: 11.5px; font-weight: 600; color: var(--text-muted); }
.home-unplanned-acts { display: flex; gap: 4px; flex: none; opacity: 0; transition: opacity .12s ease; }
.home-unplanned-row:hover .home-unplanned-acts,
.home-unplanned-acts:focus-within { opacity: 1; }
.home-unplanned-btn { background: none; border: 1px solid var(--border); border-radius: 7px; color: var(--text-muted); font: inherit; font-size: 12px; padding: 3px 9px; cursor: pointer; }
.home-unplanned-btn:hover { border-color: var(--accent); color: var(--accent); }


/* ---------- Dragging a to-do onto another day (calendar-drag.js) ---------- */
/* The chip stays where it was, dimmed, so the day you are taking it FROM does
   not reflow under your hand mid-drag. */
.cv-chip.cv-dragging { opacity: .35; }
.cv-ghost {
  position: fixed; z-index: 10001; pointer-events: none;
  max-width: 220px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  padding: 5px 10px; border-radius: 8px; font-size: 12.5px; font-weight: 600;
  background: var(--accent); color: #fff; box-shadow: 0 8px 24px rgba(22, 28, 44, .28);
}
/* The day under the cursor. An inset ring rather than a border, so the grid
   does not shift by a pixel as the highlight moves from cell to cell. */
/* The day under the cursor, in whichever view drew it: a month cell, a week
   thread section, a week grid column. An inset ring rather than a border, so
   nothing shifts by a pixel as the highlight moves. */
.cv-drop-day.cv-drop { box-shadow: inset 0 0 0 2px var(--accent); border-radius: 8px; }
