/* =================================================================
   cloud notes — modern UI
   Layout uses an explicit flex chain so every container has a
   definite height. Viewer panes use absolute fill — never flex+100%.
   ================================================================= */

:root {
  /* surfaces */
  --bg-canvas:    #f6f5f1;
  --bg-card:      #ffffff;
  --bg-topbar:    rgba(255, 255, 255, 0.85);
  --bg-sidebar:   #0f0f11;
  --bg-sidebar-2: #18181b;

  /* text */
  --fg:           #18181b;
  --fg-2:         #3f3f46;
  --fg-muted:     #71717a;
  --fg-on-dark:   #f4f4f5;
  --fg-on-dark-2: #a1a1aa;
  --fg-on-dark-3: #52525b;

  /* lines */
  --line:         #ebe9e3;
  --line-strong:  #d8d4cc;
  --line-dark:    #27272a;

  /* accent */
  --accent:       #6366f1;
  --accent-hover: #4f46e5;
  --accent-soft:  #eef2ff;
  --accent-dark:  #c7d2fe;

  /* states */
  --danger:       #ef4444;
  --warning:      #f59e0b;
  --success:      #10b981;

  /* dot grid */
  --dot:          #e7e4dc;

  /* elevations */
  --shadow-xs:    0 1px 1px rgba(24, 24, 27, .04);
  --shadow-sm:    0 1px 2px rgba(24, 24, 27, .05), 0 1px 1px rgba(24, 24, 27, .04);
  --shadow:       0 1px 2px rgba(24, 24, 27, .04), 0 4px 14px rgba(24, 24, 27, .07);
  --shadow-md:    0 4px 8px -2px rgba(24, 24, 27, .08), 0 12px 24px -8px rgba(24, 24, 27, .12);
  --shadow-lg:    0 12px 24px -8px rgba(24, 24, 27, .10), 0 24px 48px -12px rgba(24, 24, 27, .16);

  /* type */
  --font-ui:   -apple-system, BlinkMacSystemFont, "Inter", "Segoe UI Variable", "Segoe UI", system-ui, Roboto, "Helvetica Neue", Arial, sans-serif;
  --font-note: -apple-system, BlinkMacSystemFont, "Inter", "Segoe UI Variable", "Segoe UI", system-ui, Roboto, sans-serif;
  --font-mono: "JetBrains Mono", "SF Mono", ui-monospace, Menlo, Consolas, "Liberation Mono", monospace;

  /* timing */
  --t-fast:   120ms;
  --t-base:   180ms;
  --t-slow:   280ms;
  --ease:     cubic-bezier(.22, .61, .36, 1);

  /* radii */
  --r-xs: 4px;
  --r-sm: 6px;
  --r:    8px;
  --r-lg: 12px;
}

* { box-sizing: border-box; }
html, body { height: 100%; margin: 0; }
body {
  font-family: var(--font-ui);
  font-size: 14px;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  color: var(--fg);
  background: var(--bg-canvas);
  display: flex;
  overflow: hidden;
}

/* Embedded mode: app loaded via /?embed=<path> into an iframe.
   Hide every piece of chrome, let the viewer take the whole window. */
body.embedded { display: block; }
body.embedded #sidebar,
body.embedded #topbar,
body.embedded #format-toolbar,
body.embedded #empty-hint,
body.embedded #ctx-menu,
body.embedded #modal-overlay { display: none !important; }
body.embedded #main { width: 100%; height: 100vh; }

/* ============================== Sidebar ============================== */
#sidebar {
  width: 248px;
  flex-shrink: 0;
  background: var(--bg-sidebar);
  color: var(--fg-on-dark);
  display: flex;
  flex-direction: column;
  border-right: 1px solid #000;
  user-select: none;
  transition: width var(--t-base) var(--ease);
}
.sidebar-actions { display: inline-flex; align-items: center; gap: 2px; }

/* Collapsible folder panel (desktop). On mobile the sidebar is already a drawer
   (☰), so the collapse button is hidden there and the collapse class is scoped
   to desktop so a lingering class can't break the mobile drawer layout. */
@media (min-width: 769px) {
  body.sidebar-collapsed #sidebar {
    width: 0;
    min-width: 0;
    border-right: 0;
    overflow: hidden;
  }
  /* When collapsed, the topbar ☰ becomes the "show folders again" button. */
  body.sidebar-collapsed #sidebar-toggle {
    display: inline-flex;
    align-items: center;
    justify-content: center;
  }
}
@media (max-width: 768px) { #sidebar-collapse { display: none !important; } }

#sidebar-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 14px 16px 12px;
  font-size: 12px;
  letter-spacing: .04em;
  text-transform: uppercase;
  color: var(--fg-on-dark-2);
}

.brand {
  color: #fff;
  font-weight: 600;
  font-size: 13px;
  letter-spacing: .02em;
  text-transform: none;
  display: flex;
  align-items: center;
  gap: 8px;
}
.brand::before {
  content: "";
  width: 8px; height: 8px;
  background: var(--accent);
  border-radius: 50%;
  box-shadow: 0 0 0 3px rgba(99, 102, 241, .18);
}

.icon-btn {
  background: transparent;
  color: var(--fg-on-dark-2);
  border: 0;
  border-radius: var(--r-xs);
  width: 26px; height: 26px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  font-size: 14px;
  transition: background var(--t-fast) var(--ease), color var(--t-fast) var(--ease);
}
.icon-btn:hover { background: rgba(255,255,255,.06); color: #fff; }
.icon-btn:active { background: rgba(255,255,255,.10); }

#tree {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  overflow-x: hidden;
  padding: 4px 0 16px;
  font-size: 13px;
  outline: none;
}
#tree::-webkit-scrollbar { width: 8px; }
#tree::-webkit-scrollbar-thumb { background: rgba(255,255,255,.08); border-radius: 4px; }
#tree::-webkit-scrollbar-thumb:hover { background: rgba(255,255,255,.14); }
#tree::-webkit-scrollbar-track { background: transparent; }

.tree-node { display: block; }
.tree-row {
  position: relative;
  display: flex;
  align-items: center;
  gap: 4px;
  padding: 4px 12px 4px 6px;
  margin: 0 6px;
  cursor: pointer;
  white-space: nowrap;
  border-radius: var(--r-xs);
  color: var(--fg-on-dark);
  transition: background var(--t-fast) var(--ease), color var(--t-fast) var(--ease);
}
.tree-row:hover { background: rgba(255,255,255,.05); }
.tree-row.nav-focus {
  background: rgba(99,102,241,.10);
  box-shadow: inset 2px 0 0 var(--accent);
}
.tree-row.active {
  background: rgba(99,102,241,.16);
  color: #fff;
}
.tree-row.active.nav-focus { background: rgba(99,102,241,.26); }
.tree-row.drop-target {
  background: rgba(99,102,241,.28);
  outline: 1.5px dashed var(--accent);
  outline-offset: -2px;
}
/* Drag-to-reorder insertion indicators: a 2px accent line on top/bottom of
   the row the cursor is currently above. Positioned relative so the
   pseudo-element can sit at the row edge. */
.tree-row { position: relative; }
.tree-row.drop-before::before,
.tree-row.drop-after::after {
  content: "";
  position: absolute;
  left: 4px;
  right: 4px;
  height: 2px;
  background: var(--accent);
  border-radius: 1px;
  pointer-events: none;
  z-index: 2;
}
.tree-row.drop-before::before { top: -1px; }
.tree-row.drop-after::after   { bottom: -1px; }
.tree-row.multi-selected {
  background: rgba(99,102,241,.22);
  color: #fff;
}
.tree-row.multi-selected.active     { background: rgba(99,102,241,.32); }
.tree-row.multi-selected.nav-focus  { box-shadow: inset 2px 0 0 var(--accent); }
.tree-row.dragging-source           { opacity: .45; }
.tree-row.clip-cut                   { opacity: .55; font-style: italic; }
.tree-row.clip-cut .label            { text-decoration: line-through dotted; }
#tree.drop-target-root {
  background: rgba(99,102,241,.06);
  box-shadow: inset 0 0 0 2px var(--accent);
}
.tree-row.active::before {
  content: "";
  position: absolute;
  left: -6px; top: 6px; bottom: 6px;
  width: 2px;
  background: var(--accent);
  border-radius: 2px;
}

.tree-row .twist {
  width: 14px;
  flex-shrink: 0;
  text-align: center;
  color: var(--fg-on-dark-3);
  font-size: 9px;
  transition: transform var(--t-fast) var(--ease);
}
.tree-row.dir > .twist::before { content: "▶"; display: inline-block; transition: transform var(--t-fast) var(--ease); }
.tree-row.dir.open > .twist::before { transform: rotate(90deg); }
.tree-row.file > .twist { visibility: hidden; }

.tree-row .icon {
  width: 16px;
  flex-shrink: 0;
  text-align: center;
  font-size: 11px;
  color: var(--fg-on-dark-3);
}
.tree-row.dir .icon::before { content: ""; display: inline-block; width: 12px; height: 10px; background: var(--fg-on-dark-3); border-radius: 1px 3px 3px 3px; opacity: .55; vertical-align: middle; }
.tree-row.dir.open .icon::before { background: var(--accent); opacity: .85; }
.tree-row.file .icon::before { content: ""; display: inline-block; width: 9px; height: 11px; background: var(--fg-on-dark-3); border-radius: 1px; opacity: .45; vertical-align: middle; }
.tree-row.file.note .icon::before { background: var(--fg-on-dark); opacity: .85; }

/* Per-folder color overrides. Closed = muted (.6), open = full (.95). The
   palette here mirrors FOLDER_COLOR_PALETTE in src/tree/folder-colors.js. */
.tree-row.dir[data-color="red"]    .icon::before { background: #ef4444; opacity: .60; }
.tree-row.dir[data-color="red"].open    .icon::before { opacity: .95; }
.tree-row.dir[data-color="orange"] .icon::before { background: #f59e0b; opacity: .60; }
.tree-row.dir[data-color="orange"].open .icon::before { opacity: .95; }
.tree-row.dir[data-color="yellow"] .icon::before { background: #eab308; opacity: .60; }
.tree-row.dir[data-color="yellow"].open .icon::before { opacity: .95; }
.tree-row.dir[data-color="green"]  .icon::before { background: #10b981; opacity: .60; }
.tree-row.dir[data-color="green"].open  .icon::before { opacity: .95; }
.tree-row.dir[data-color="teal"]   .icon::before { background: #14b8a6; opacity: .60; }
.tree-row.dir[data-color="teal"].open   .icon::before { opacity: .95; }
.tree-row.dir[data-color="blue"]   .icon::before { background: #3b82f6; opacity: .60; }
.tree-row.dir[data-color="blue"].open   .icon::before { opacity: .95; }
.tree-row.dir[data-color="purple"] .icon::before { background: #a855f7; opacity: .60; }
.tree-row.dir[data-color="purple"].open .icon::before { opacity: .95; }
.tree-row.dir[data-color="pink"]   .icon::before { background: #ec4899; opacity: .60; }
.tree-row.dir[data-color="pink"].open   .icon::before { opacity: .95; }
.tree-row.dir[data-color="gray"]   .icon::before { background: #71717a; opacity: .60; }
.tree-row.dir[data-color="gray"].open   .icon::before { opacity: .95; }

/* Color picker popup. */
.folder-color-popup {
  position: fixed;
  z-index: 1100;
  background: var(--bg-card);
  border: 1px solid var(--line);
  border-radius: var(--r);
  box-shadow: var(--shadow-lg);
  padding: 8px;
  display: grid;
  grid-template-columns: repeat(5, 22px);
  gap: 6px;
  animation: ctx-in 120ms var(--ease);
}
.folder-color-popup .fc-swatch {
  width: 22px;
  height: 22px;
  border-radius: 50%;
  border: 2px solid transparent;
  background: var(--fc-color, #6366f1);
  cursor: pointer;
  padding: 0;
  transition: transform var(--t-fast), border-color var(--t-fast);
}
.folder-color-popup .fc-swatch:hover  { transform: scale(1.12); }
.folder-color-popup .fc-swatch.active { border-color: var(--fg); }
.folder-color-popup .fc-swatch-default {
  background: var(--bg-card);
  border: 2px dashed var(--line-strong);
  position: relative;
}
.folder-color-popup .fc-swatch-default::after {
  content: "";
  position: absolute; left: 3px; right: 3px; top: 50%;
  height: 2px; background: var(--line-strong);
  transform: rotate(-45deg);
}
.folder-color-popup .fc-swatch-default.active { border-style: solid; border-color: var(--fg); }

.tree-row .label {
  overflow: hidden;
  text-overflow: ellipsis;
  flex: 1;
  font-weight: 400;
}
.tree-row.dir > .label { font-weight: 500; }
.tree-row.active .label { color: #fff; }

.tree-row .label-edit {
  flex: 1;
  min-width: 0;
  font: inherit;
  color: var(--fg-on-dark);
  background: var(--bg-sidebar-2);
  border: 1px solid var(--accent);
  border-radius: 3px;
  padding: 1px 4px;
  margin: -2px 0;
  outline: none;
  caret-color: var(--fg-on-dark);
}
.tree-row .label-edit::selection {
  background: var(--accent);
  color: #fff;
}

/* ============================== Share Pickup ============================== */
.share-pickup-panel {
  background: var(--bg-card);
  border-radius: var(--r-lg);
  box-shadow: var(--shadow-lg);
  width: min(560px, 92vw);
  max-height: 88vh;
  display: flex;
  flex-direction: column;
  overflow: hidden;
}
.share-pickup-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 14px 18px;
  border-bottom: 1px solid var(--line);
}
.share-pickup-title { font-size: 15px; font-weight: 600; }
.share-pickup-body {
  flex: 1;
  overflow: auto;
  padding: 14px 18px;
  display: flex;
  flex-direction: column;
  gap: 16px;
}
.sp-section-label {
  font-size: 11px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: .04em;
  color: var(--fg-muted);
  margin-bottom: 6px;
}
.sp-files-list {
  list-style: none;
  padding: 0;
  margin: 0;
  border: 1px solid var(--line);
  border-radius: var(--r);
  max-height: 180px;
  overflow: auto;
}
.sp-files-list li {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 8px 12px;
  border-bottom: 1px solid var(--line);
  font-size: 13px;
}
.sp-files-list li:last-child { border-bottom: 0; }
.sp-file-icon { flex-shrink: 0; }
.sp-file-name { flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.sp-file-size { color: var(--fg-muted); font-size: 11px; font-variant-numeric: tabular-nums; }
.sp-file-empty { color: var(--fg-muted); font-style: italic; }
.sp-current-target {
  font-size: 13px;
  padding: 8px 12px;
  background: var(--accent-soft);
  border: 1px solid var(--accent-dark);
  border-radius: var(--r-sm);
  color: var(--accent-hover);
  font-weight: 500;
  margin-bottom: 8px;
  word-break: break-all;
}
.sp-pins { margin-bottom: 8px; }
.sp-pins[hidden] { display: none; }
.sp-pins-head {
  font-size: 11px;
  font-weight: 500;
  color: var(--fg-muted);
  text-transform: uppercase;
  letter-spacing: .04em;
  margin-bottom: 4px;
}
.sp-pins-strip {
  display: flex;
  gap: 6px;
  overflow-x: auto;
  padding: 2px 0 6px;
  -webkit-overflow-scrolling: touch;
}
.sp-pin-chip {
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 6px 10px;
  background: var(--bg-canvas);
  border: 1px solid var(--line);
  border-radius: 999px;
  cursor: pointer;
  font: inherit;
  color: var(--fg);
  max-width: 220px;
}
.sp-pin-chip:hover  { border-color: var(--accent); background: var(--accent-soft); }
.sp-pin-chip:active { transform: scale(.97); }
.sp-pin-icon { font-size: 14px; line-height: 1; }
.sp-pin-labels {
  display: flex;
  flex-direction: column;
  gap: 1px;
  overflow: hidden;
  min-width: 0;
}
.sp-pin-name {
  font-size: 13px;
  font-weight: 500;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.sp-pin-parent {
  font-size: 10px;
  color: var(--fg-muted);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.sp-tree {
  border: 1px solid var(--line);
  border-radius: var(--r);
  max-height: 280px;
  overflow: auto;
  padding: 4px 0;
}
.sp-tree-row {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 6px 8px;
  cursor: pointer;
  font-size: 13px;
  user-select: none;
  border-radius: var(--r-xs);
  margin: 0 4px;
}
.sp-tree-row:hover { background: var(--bg-canvas); }
.sp-tree-row.selected { background: var(--accent-soft); color: var(--accent-hover); font-weight: 500; }
.sp-twist { width: 12px; text-align: center; font-size: 9px; color: var(--fg-muted); cursor: pointer; }
.sp-icon { font-size: 14px; }
.sp-label { flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.sp-actions {
  display: flex;
  justify-content: flex-end;
  gap: 8px;
  padding: 12px 18px;
  border-top: 1px solid var(--line);
}

/* Hidden folders/files shown via the Settings toggle — dimmed + italic so it's
   clear they're hidden from the normal sidebar view. */
.tree-row.hidden-dir, .tree-row.hidden-file { opacity: .5; }
.tree-row.hidden-dir .label, .tree-row.hidden-file .label { font-style: italic; }

/* Background mirror sync (mirror-sync.js): a file still downloading is locked —
   dimmed with a small spinner at the right edge. A folder containing locked
   files gets a subtle spinning badge but stays clickable. */
.tree-row.sync-locked { opacity: .55; }
.tree-row.sync-locked::after {
  content: ''; flex: 0 0 auto; margin-left: auto;
  width: 11px; height: 11px;
  border: 2px solid currentColor; border-right-color: transparent;
  border-radius: 50%; opacity: .55;
  animation: si-spin .8s linear infinite;
}
.tree-row.sync-pending .label::after {
  content: '⟳'; margin-left: 6px; opacity: .5; font-size: .85em;
  display: inline-block; animation: si-spin 1.2s linear infinite;
}
@keyframes si-spin { to { transform: rotate(360deg); } }

/* ── Top-right transfer indicators (download/sync ↓ + upload ↑) ───────────────
   Upload and download are a matched pair, so they share ALL chrome: the same
   pill button, the same progress bar, the same dropdown panel and row design.
   Only the direction icon and the listed content differ. */
.topbar-ind { position: relative; display: inline-flex; align-items: center; }
.ind-btn {
  display: inline-flex; align-items: center; gap: 7px;
  padding: 3px 9px 3px 8px;
  border: 1px solid var(--line-strong); border-radius: 999px;
  background: var(--bg-card); color: var(--fg-2);
  font-size: 12px; font-weight: 600; cursor: pointer;
  box-shadow: var(--shadow-xs);
  transition: background var(--t-fast), border-color var(--t-fast), color var(--t-fast);
}
.ind-btn:hover { background: var(--accent-soft); }
.ind-icon { font-size: 13px; line-height: 1; }
.ind-bar {
  width: 56px; height: 6px; border-radius: 999px;
  background: var(--line); overflow: hidden; flex-shrink: 0;
}
.ind-fill {
  display: block; height: 100%; width: 2%;
  background: var(--accent); border-radius: 999px;
  transition: width .2s var(--ease), background .2s var(--ease);
}
.ind-val { min-width: 30px; text-align: right; font-variant-numeric: tabular-nums; }

/* Draining: accent + pulsing icon. Offline (uploads parked): amber. Done: green. */
.topbar-ind.syncing  .ind-btn  { border-color: var(--accent); color: var(--accent); }
.topbar-ind.syncing  .ind-icon { animation: oq-pulse 1.1s ease-in-out infinite; }
.topbar-ind.offline  .ind-btn  { border-color: var(--warning); color: var(--warning); }
.topbar-ind.offline  .ind-fill { background: var(--warning); }
.topbar-ind.complete .ind-fill { background: var(--success); }
.topbar-ind.complete .ind-val  { color: var(--success); }

.ind-panel {
  position: absolute; top: calc(100% + 8px); right: 0;
  width: 300px; max-height: 60vh; overflow-y: auto;
  background: var(--bg-card);
  border: 1px solid var(--line-strong); border-radius: var(--r-lg);
  box-shadow: var(--shadow-md); z-index: 60; padding: 6px;
}

/* "Als PDF speichern"-Dialog: Dateiname-Feld (reuses the share-pickup panel). */
.savepdf-name {
  width: 100%;
  box-sizing: border-box;
  padding: 8px 12px;
  font: inherit;
  font-size: 13px;
  border: 1px solid var(--line);
  border-radius: var(--r-sm);
  background: var(--bg-canvas);
  color: var(--fg);
}
.savepdf-name:focus { outline: none; border-color: var(--accent); }

.tree-row .trash-countdown {
  flex-shrink: 0;
  margin-left: 6px;
  padding: 0 5px;
  font-size: 10px;
  line-height: 14px;
  border-radius: 7px;
  color: var(--fg-on-dark-2);
  background: rgba(239, 68, 68, .14);
  border: 1px solid rgba(239, 68, 68, .26);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
.tree-row.active .trash-countdown,
.tree-row:hover .trash-countdown { color: var(--fg-on-dark); }

.tree-children { overflow: hidden; }

.tree-empty { padding: 18px 16px; color: var(--fg-on-dark-3); font-size: 12px; }

.focus-pill {
  display: flex;
  align-items: center;
  gap: 6px;
  margin: 6px 8px 6px;
  padding: 5px 6px 5px 9px;
  background: rgba(99,102,241,.16);
  border: 1px solid rgba(99,102,241,.32);
  border-radius: var(--r-xs);
  font-size: 12px;
  color: var(--fg-on-dark);
}
.focus-pill .focus-icon { color: var(--accent); font-size: 9px; flex-shrink: 0; }
.focus-pill .focus-label {
  flex: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-weight: 500;
  cursor: pointer;
}
.focus-pill .focus-label:hover { color: #fff; }
.focus-pill .focus-clear {
  background: transparent;
  border: 0;
  color: var(--fg-on-dark-2);
  cursor: pointer;
  font-size: 11px;
  padding: 2px 5px;
  border-radius: 3px;
  flex-shrink: 0;
}
.focus-pill .focus-clear:hover { background: rgba(255,255,255,.12); color: #fff; }

/* ============================== Main ============================== */
#main {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  background: var(--bg-canvas);
}

#topbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0 18px;
  height: 46px;
  background: var(--bg-topbar);
  backdrop-filter: saturate(180%) blur(12px);
  -webkit-backdrop-filter: saturate(180%) blur(12px);
  border-bottom: 1px solid var(--line);
  flex-shrink: 0;
  font-size: 13px;
  z-index: 5;
}

#breadcrumb {
  font-weight: 500;
  color: var(--fg);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  min-width: 0;
}
#breadcrumb b { font-weight: 600; }
#breadcrumb .dim { color: var(--fg-muted); font-weight: 400; }
#breadcrumb .sep { color: var(--fg-muted); margin: 0 6px; opacity: .6; }

#breadcrumb .bc-seg {
  font: inherit;
  background: transparent;
  border: 0;
  padding: 0 2px;
  margin: 0;
  cursor: pointer;
  border-radius: 3px;
  color: var(--fg-muted);
}
#breadcrumb .bc-seg:hover {
  background: var(--accent-soft);
  color: var(--accent);
}
#breadcrumb .bc-seg.last {
  color: var(--fg);
  font-weight: 600;
}

#topbar-right {
  display: inline-flex;
  align-items: center;
  gap: 12px;
}

#tab-strip {
  display: flex;
  background: var(--bg-canvas);
  border-bottom: 1px solid var(--line);
  flex-shrink: 0;
  align-items: stretch;
}
#tabs-list {
  display: flex;
  flex: 1;
  min-width: 0;
  overflow-x: auto;
  scrollbar-width: thin;
}
#tab-add {
  flex-shrink: 0;
  height: 32px;
  width: 32px;
  font-size: 18px;
  background: transparent;
  border: 0;
  border-left: 1px solid var(--line);
  color: var(--fg-2);
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
}
#tab-add:hover { background: var(--bg-card); color: var(--fg); }
.tab {
  display: inline-flex;
  align-items: center;
  height: 32px;
  padding: 0 4px 0 12px;
  gap: 6px;
  border-right: 1px solid var(--line);
  font-size: 13px;
  color: var(--fg-2);
  cursor: pointer;
  user-select: none;
  white-space: nowrap;
  flex-shrink: 0;
  max-width: 240px;
}
.tab:hover { background: var(--bg-card); }
.tab.active {
  background: var(--bg-card);
  color: var(--fg);
  box-shadow: inset 0 -2px 0 var(--accent);
}
.tab .tab-label {
  overflow: hidden;
  text-overflow: ellipsis;
}
.tab .tab-close {
  background: transparent;
  border: 0;
  padding: 0 5px;
  margin: 0;
  border-radius: 3px;
  color: var(--fg-muted);
  cursor: pointer;
  font-size: 16px;
  line-height: 1;
  height: 20px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
}
.tab .tab-close:hover { background: var(--line); color: var(--fg); }
.tab.drop-before { box-shadow: inset 2px 0 0 var(--accent); }
.tab.drop-after  { box-shadow: inset -2px 0 0 var(--accent); }

#hover-preview {
  position: fixed;
  z-index: 100;
  width: 420px;
  height: 300px;
  overflow: hidden;
  background: var(--bg-card);
  color: var(--fg);
  border: 1px solid var(--line);
  border-radius: 8px;
  box-shadow: var(--shadow-lg, 0 6px 24px rgba(0,0,0,.25));
  padding: 0;
  font-size: 12px;
  line-height: 1.4;
  pointer-events: none;
}
#hover-preview > * {
  width: 100%;
  height: 100%;
}
#hover-preview .hp-meta {
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--fg-muted);
  font-style: italic;
  font-size: 14px;
}
#hover-preview .hp-pre {
  margin: 0;
  padding: 10px 14px;
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 11px;
  white-space: pre-wrap;
  word-break: break-word;
  overflow: hidden;
  color: var(--fg-2);
  background: var(--bg-canvas);
}
#hover-preview .hp-rendered {
  padding: 12px 16px;
  overflow: hidden;
  font-size: 12px;
  line-height: 1.5;
  color: #18181b;
  background: #fff;
}
#hover-preview .hp-rendered p { margin: 0 0 6px; }
#hover-preview .hp-rendered h1,
#hover-preview .hp-rendered h2,
#hover-preview .hp-rendered h3 { margin: 8px 0 4px; font-size: 13px; }
#hover-preview .hp-rendered img { max-width: 100%; }
#hover-preview .hp-img {
  object-fit: contain;
  background: var(--bg-canvas);
}
#hover-preview .hp-pdf {
  border: 0;
  background: var(--bg-canvas);
}
#hover-preview .hp-sheet {
  overflow: hidden;
  background: #fff;
  color: #18181b;
  padding: 4px;
}
#hover-preview .hp-sheet table {
  border-collapse: collapse;
  font-size: 10px;
}
#hover-preview .hp-sheet td,
#hover-preview .hp-sheet th {
  border: 1px solid #d4d4d8;
  padding: 2px 5px;
  white-space: nowrap;
}
#hover-preview .hp-load { color: var(--fg-muted); }

#progress-bar {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  height: 2px;
  background: transparent;
  z-index: 1000;
  pointer-events: none;
  overflow: hidden;
}
#progress-bar .pb-fill {
  height: 100%;
  background: var(--accent);
  width: 0;
  transition: width .15s ease-out;
}
#progress-bar.indeterminate .pb-fill {
  width: 33% !important;
  animation: pb-slide 1.1s ease-in-out infinite;
}
@keyframes pb-slide {
  0%   { transform: translateX(-110%); }
  100% { transform: translateX(310%); }
}

/* ===================== Per-file upload panel ===================== */
#upload-progress {
  position: fixed;
  right: 16px;
  bottom: 16px;
  z-index: 1100;
  width: 320px;
  max-width: calc(100vw - 32px);
  background: var(--bg-card);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  box-shadow: var(--shadow-lg);
  overflow: hidden;
  font-family: var(--font-ui);
}
#upload-progress .up-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  padding: 7px 8px 7px 12px;
  font-size: 12px;
  font-weight: 600;
  color: var(--fg-2);
  border-bottom: 1px solid var(--line);
}
#upload-progress .up-close {
  flex: 0 0 auto;
  border: 0;
  background: transparent;
  color: var(--fg-muted);
  font-size: 18px;
  line-height: 1;
  padding: 2px 6px;
  border-radius: var(--r-sm);
  cursor: pointer;
}
#upload-progress .up-close:hover { background: var(--bg-canvas); color: var(--fg); }
#upload-progress .up-list {
  max-height: 40vh;
  overflow-y: auto;
  padding: 6px 0;
}
.up-row {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 5px 12px;
}
.up-row .up-name {
  flex: 1 1 auto;
  min-width: 0;
  font-size: 12px;
  color: var(--fg);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.up-row .up-bar {
  flex: 0 0 70px;
  height: 4px;
  border-radius: 2px;
  background: var(--line);
  overflow: hidden;
}
.up-row .up-fill {
  display: block;
  height: 100%;
  width: 0;
  background: var(--accent);
  transition: width .15s ease-out;
}
.up-row.up-indet .up-fill {
  width: 40% !important;
  animation: pb-slide 1.1s ease-in-out infinite;
}
.up-row.up-done .up-fill { background: var(--success); }
.up-row.up-fail .up-fill { background: var(--danger); width: 100% !important; }
.up-row .up-pct {
  flex: 0 0 34px;
  text-align: right;
  font-size: 11px;
  font-variant-numeric: tabular-nums;
  color: var(--fg-muted);
}
.up-row.up-done .up-pct { color: var(--success); }
.up-row.up-fail .up-pct { color: var(--danger); }

/* ============================== Sidebar footer ============================== */
#sidebar-footer {
  flex-shrink: 0;
  border-top: 1px solid rgba(255,255,255,.06);
  padding: 6px;
  background: var(--bg-sidebar);
}
#settings-btn {
  width: 100%;
  text-align: left;
  background: transparent;
  border: 0;
  padding: 7px 10px;
  border-radius: 6px;
  color: var(--fg-on-dark-2);
  cursor: pointer;
  font-size: 12px;
  font: inherit;
}
#settings-btn:hover { background: rgba(255,255,255,.05); color: var(--fg-on-dark); }

/* Make sure the tree scrolls and the footer stays pinned. */
#sidebar { display: flex; flex-direction: column; }
#tree { flex: 1; min-height: 0; overflow-y: auto; }

/* ============================== Settings overlay ============================== */
#settings-overlay.overlay {
  position: fixed; inset: 0; z-index: 200;
  background: rgba(0,0,0,.45);
  display: flex; align-items: center; justify-content: center;
}
#settings-overlay[hidden] { display: none; }
.settings-panel {
  width: min(560px, 92vw);
  max-height: 80vh;
  background: var(--bg-card);
  color: var(--fg);
  border-radius: 12px;
  box-shadow: 0 16px 48px rgba(0,0,0,.45);
  display: flex; flex-direction: column;
  overflow: hidden;
}
.settings-head {
  display: flex; align-items: center; justify-content: space-between;
  padding: 14px 18px;
  border-bottom: 1px solid var(--line);
}
.settings-title { font-weight: 600; font-size: 15px; }
.settings-close {
  background: transparent; border: 0; cursor: pointer;
  font-size: 22px; line-height: 1; color: var(--fg-muted);
  width: 28px; height: 28px; border-radius: 6px;
}
.settings-close:hover { background: var(--bg-canvas); color: var(--fg); }
.settings-body { padding: 14px 18px 18px; overflow-y: auto; }
.settings-section h3 { font-size: 13px; margin: 0 0 4px; }
.settings-section p  { font-size: 13px; color: var(--fg-muted); margin: 0 0 10px; line-height: 1.5; }
.settings-actions-row { display: flex; gap: 10px; flex-wrap: wrap; align-items: center; margin-bottom: 10px; }
.settings-hint { font-size: 13px; color: var(--fg-muted); }
.settings-meta { font-size: 11px; color: var(--fg-muted); margin-top: 8px; }
.cache-stat-total { font-weight: 600; }
.cache-stat-list { margin-top: 6px; display: flex; flex-direction: column; gap: 3px; }
.cache-stat-row { display: flex; justify-content: space-between; gap: 12px; }
.cache-stat-row em { font-style: normal; opacity: 0.7; }
#purge-failed-uploads { margin-top: 8px; }
.settings-toggle { display: inline-flex; align-items: center; gap: 8px; font-size: 13px; cursor: pointer; user-select: none; }
.settings-toggle input { width: 16px; height: 16px; cursor: pointer; }

#sync-progress { margin-top: 8px; }
.settings-pb {
  height: 6px;
  background: var(--line);
  border-radius: 999px;
  overflow: hidden;
  position: relative;
}
.settings-pb-fill {
  height: 100%;
  width: 0%;
  background: var(--accent);
  transition: width .2s ease-out;
}
/* Sliding stripe shown while sync is active. The actual fill stays at 0%
   until "finished" sets it to 100%; the stripe gives the user visible
   activity even when the byte-progress hasn't moved yet (server still
   warming up, gzip buffer filling, big file in flight). */
.settings-pb.indeterminate::before {
  content: '';
  position: absolute;
  top: 0; bottom: 0; left: 0;
  width: 30%;
  background: linear-gradient(90deg, transparent, var(--accent), transparent);
  animation: settings-pb-slide 1.4s linear infinite;
  pointer-events: none;
}
@keyframes settings-pb-slide {
  from { transform: translateX(-100%); }
  to   { transform: translateX(450%); }
}
.sync-row {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-top: 6px;
}
.sync-status {
  flex: 1;
  font-size: 11px;
  color: var(--fg-muted);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
#sync-cancel-btn {
  flex-shrink: 0;
  font: inherit;
  font-size: 11px;
  background: transparent;
  border: 1px solid var(--line);
  color: var(--fg-2);
  padding: 3px 10px;
  border-radius: 4px;
  cursor: pointer;
}
#sync-cancel-btn:hover:not(:disabled) { background: var(--bg-canvas); color: var(--danger); border-color: var(--danger); }
#sync-cancel-btn:disabled { opacity: .5; cursor: default; }
.sync-meta {
  margin-top: 4px;
  font-size: 11px;
  color: var(--fg-muted);
  font-variant-numeric: tabular-nums;
}

#sync-failures {
  margin-top: 10px;
  max-height: 180px;
  overflow-y: auto;
  border: 1px solid var(--line);
  border-radius: 6px;
  padding: 8px 10px;
  background: var(--bg-canvas);
  font-size: 11px;
}
#sync-failures .ff-title { font-weight: 600; color: var(--danger); margin-bottom: 4px; }
#sync-failures .ff-list  { list-style: none; padding: 0; margin: 0; }
#sync-failures .ff-list li {
  padding: 2px 0;
  border-bottom: 1px dashed var(--line);
  word-break: break-all;
}
#sync-failures .ff-list li:last-child { border-bottom: 0; }
#sync-failures .ff-path   { color: var(--fg); }
#sync-failures .ff-reason { color: var(--fg-muted); margin-left: 6px; }
#sync-failures .ff-more   { color: var(--fg-muted); margin-top: 4px; }
#hover-preview .hp-note hr {
  border: 0;
  border-top: 1px dashed var(--line);
  margin: 8px 0;
}
#hover-preview .hp-audio {
  width: 100%;
  height: auto;
  padding: 80px 16px;
  background: var(--bg-canvas);
  box-sizing: border-box;
}
#mode-toggle,
#canvas-view-toggle,
#canvas-fullscreen-toggle,
#canvas-reset-view {
  font: inherit;
  font-size: 12px;
  padding: 4px 10px;
  background: var(--bg-canvas);
  color: var(--fg);
  border: 1px solid var(--line);
  border-radius: var(--r-sm);
  cursor: pointer;
  white-space: nowrap;
}
#mode-toggle:hover,
#canvas-view-toggle:hover,
#canvas-fullscreen-toggle:hover,
#canvas-reset-view:hover { background: var(--accent-soft); border-color: var(--accent); }
#mode-toggle.view-mode,
#canvas-view-toggle.view-mode,
#canvas-fullscreen-toggle.view-mode {
  background: var(--accent);
  color: #fff;
  border-color: var(--accent);
}
#mode-toggle.view-mode:hover,
#canvas-view-toggle.view-mode:hover,
#canvas-fullscreen-toggle.view-mode:hover { filter: brightness(1.08); }

/* Im Vollbild Platz sparen: komplette Kopfzeile UND die Seiten-Tabs ausblenden.
   Der Vollbild-Beenden-Button wandert stattdessen ganz nach rechts in die
   Werkzeugleiste (siehe unten). */
body.app-fullscreen #topbar,
body.app-fullscreen #tab-strip { display: none !important; }

/* Vollbild-Beenden-Button in der Werkzeugleiste: standardmäßig versteckt, im
   Vollbild ganz rechts und durch eine Trennlinie abgegrenzt. */
#ft-fullscreen-exit { display: none; }
body.app-fullscreen #ft-fullscreen-exit {
  display: inline-flex;
  align-items: center;
  margin-left: auto;                 /* schiebt den Button ganz nach rechts */
  padding: 4px 12px;
  font: inherit;
  font-size: 12px;
  white-space: nowrap;
  cursor: pointer;
  color: #fff;
  background: var(--accent);
  border: 1px solid var(--accent);
  border-radius: var(--r-sm);
}
body.app-fullscreen #ft-fullscreen-exit:hover { filter: brightness(1.08); }

/* CSS fallback when the native Fullscreen API is unavailable (e.g. iPhone
   Safari): reclaim space for the canvas while keeping the topbar (and thus the
   exit button) reachable. */
body.canvas-maxed #tab-strip { display: none; }
body.canvas-maxed #sidebar   { display: none; }
body.canvas-maxed #main      { width: 100%; }

/* Canvas observation (read-only) mode: hide every editing affordance so the
   note can only be viewed. Toggled via #canvas-view-toggle. */
body.canvas-readonly #format-toolbar { display: none !important; }
body.canvas-readonly .box .toolbar,
body.canvas-readonly .box .handle,
body.canvas-readonly .box .resize,
body.canvas-readonly .box .resize-edge,
body.canvas-readonly .box .port { display: none !important; }
body.canvas-readonly .box,
body.canvas-readonly .box .body { cursor: default; }

#status {
  color: var(--fg-muted);
  font-size: 12px;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  white-space: nowrap;
}
#status::before { content: ""; width: 6px; height: 6px; border-radius: 50%; background: transparent; transition: background var(--t-base); }
#status.saving::before { background: var(--warning); }
#status.saved::before  { background: var(--success); }
#status.error::before  { background: var(--danger);  }
#status.up-clickable { cursor: pointer; text-decoration: underline; text-underline-offset: 2px; }
#status.saving { color: var(--warning); }
#status.saved  { color: var(--success); }
#status.error  { color: var(--danger);  }

/* ===================== Offline write queue (top-right) ===================== */
/* Upload/download pill chrome + states live in the shared .topbar-ind / .ind-*
   rules above. Only the dropdown list internals are queue-specific below. */
@keyframes oq-pulse { 0%,100% { opacity: 1; } 50% { opacity: .35; } }

.oq-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  padding: 6px 8px 8px;
  border-bottom: 1px solid var(--line);
  margin-bottom: 4px;
}
.oq-title { font-size: 13px; font-weight: 700; color: var(--fg); }
.oq-sub   { font-size: 11px; color: var(--fg-muted); }
.oq-list  { display: flex; flex-direction: column; gap: 2px; }
.oq-item {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 7px 8px;
  border-radius: var(--r-sm);
}
.oq-item:hover { background: var(--bg-canvas); }
.oq-dot { width: 8px; height: 8px; border-radius: 50%; flex-shrink: 0; background: var(--fg-muted); }
.oq-offline .oq-dot { background: var(--warning); }
.oq-pending .oq-dot { background: var(--accent); }
.oq-sending .oq-dot { background: var(--accent); animation: oq-pulse 1s ease-in-out infinite; }
.oq-error   .oq-dot { background: var(--danger); }
.oq-info { display: flex; flex-direction: column; min-width: 0; flex: 1; }
.oq-name { font-size: 13px; color: var(--fg); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.oq-path { font-size: 11px; color: var(--fg-muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.oq-meta { font-size: 11px; color: var(--fg-muted); white-space: nowrap; flex-shrink: 0; }
.oq-error .oq-meta { color: var(--danger); }
.oq-del {
  flex-shrink: 0; width: 22px; height: 22px; padding: 0; margin-left: 2px;
  display: flex; align-items: center; justify-content: center;
  border: none; border-radius: var(--r-sm); cursor: pointer;
  background: transparent; color: var(--fg-muted); font-size: 13px; line-height: 1;
  opacity: 0; transition: opacity var(--t-fast) var(--ease), background var(--t-fast) var(--ease), color var(--t-fast) var(--ease);
}
.oq-item:hover .oq-del { opacity: 1; }
.oq-del:hover { background: var(--danger); color: #fff; }
@media (pointer: coarse) { .oq-del { opacity: 1; } }

/* ============================== Format Toolbar ============================== */
#format-toolbar {
  display: flex;
  align-items: center;
  gap: 2px;
  padding: 6px 12px;
  background: var(--bg-card);
  border-bottom: 1px solid var(--line);
  flex-shrink: 0;
  flex-wrap: wrap;
  font-size: 13px;
  z-index: 4;
  position: relative;
  user-select: none;
}
#format-toolbar[hidden] { display: none; }
/* Page-switch button: only used on touch devices (see @media pointer:coarse). */
#ft-page-switch { display: none; font-size: 12px; font-weight: 700; }
#ft-page-switch #ft-page-ind { line-height: 1; }

.ft-group { display: inline-flex; gap: 1px; }
.ft-sep   { width: 1px; height: 22px; background: var(--line); margin: 0 4px; }

.ft-btn {
  min-width: 30px;
  height: 30px;
  padding: 0 8px;
  background: transparent;
  border: 1px solid transparent;
  border-radius: var(--r-xs);
  color: var(--fg-2);
  cursor: pointer;
  font-family: inherit;
  font-size: 13px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 4px;
  transition: background var(--t-fast), border-color var(--t-fast), color var(--t-fast);
}
.ft-btn b, .ft-btn i, .ft-btn u, .ft-btn s { font-weight: 600; font-size: 14px; }
.ft-btn svg { width: 17px; height: 17px; flex-shrink: 0; }
.ft-btn:hover { background: var(--bg-canvas); color: var(--fg); }
.ft-btn:active { background: var(--accent-soft); }
.ft-btn.on { background: var(--accent-soft); color: var(--accent-hover); border-color: rgba(99,102,241,.2); }

.ft-select {
  height: 30px;
  padding: 0 26px 0 10px;
  border: 1px solid var(--line-strong);
  border-radius: var(--r-xs);
  background: var(--bg-card);
  background-image: linear-gradient(45deg, transparent 50%, var(--fg-muted) 50%),
                    linear-gradient(135deg, var(--fg-muted) 50%, transparent 50%);
  background-position: calc(100% - 14px) 50%, calc(100% - 10px) 50%;
  background-size: 4px 4px;
  background-repeat: no-repeat;
  font-family: inherit;
  font-size: 13px;
  color: var(--fg);
  cursor: pointer;
  appearance: none;
  -webkit-appearance: none;
  transition: border-color var(--t-fast);
}
.ft-select:hover { border-color: var(--fg-muted); }
.ft-select:focus { outline: none; border-color: var(--accent); box-shadow: 0 0 0 3px rgba(99,102,241,.15); }

.ft-color-btn { padding: 0 6px; flex-direction: column; gap: 0; line-height: 1; min-width: 32px; }
.ft-color-letter { font-size: 12px; font-weight: 600; height: 16px; display: flex; align-items: center; }
.ft-color-letter svg { width: 14px; height: 14px; }
.ft-color-bar    { display: block; width: 18px; height: 4px; border-radius: 2px; margin-top: 1px; }

.ft-color-popup {
  /* fixed (not absolute): the toolbar becomes overflow:hidden on narrow / PWA
     windows (≤768px), which would otherwise clip these dropdowns. fixed escapes
     the toolbar's overflow and matches the viewport coords JS sets from
     getBoundingClientRect(). Placement is clamped to the viewport in JS. */
  position: fixed;
  z-index: 100;
  background: var(--bg-card);
  border: 1px solid var(--line);
  border-radius: var(--r);
  box-shadow: var(--shadow-lg);
  padding: 10px;
  display: grid;
  grid-template-columns: repeat(8, 24px);
  gap: 4px;
}
.ft-color-popup[hidden] { display: none; }
.ft-color-popup button {
  width: 24px; height: 24px;
  border: 1px solid rgba(0,0,0,.10);
  border-radius: 4px;
  cursor: pointer;
  padding: 0;
  transition: transform var(--t-fast);
}
.ft-color-popup button:hover { transform: scale(1.15); }
.ft-color-popup .ft-color-clear {
  grid-column: span 8;
  width: auto; height: 26px;
  background: var(--bg-canvas);
  border: 1px solid var(--line-strong);
  margin-top: 4px;
  font-size: 12px;
}

.ft-table-popup {
  position: fixed;   /* see .ft-color-popup — escapes the toolbar's overflow clip */
  z-index: 100;
  background: var(--bg-card);
  border: 1px solid var(--line);
  border-radius: var(--r);
  box-shadow: var(--shadow-lg);
  padding: 12px;
}
.ft-table-popup[hidden] { display: none; }
.ft-table-grid {
  display: grid;
  grid-template-columns: repeat(10, 22px);
  gap: 2px;
}
.ft-table-grid .cell {
  width: 22px; height: 22px;
  background: var(--bg-canvas);
  border: 1px solid var(--line-strong);
  border-radius: 2px;
  cursor: pointer;
  transition: background var(--t-fast);
}
.ft-table-grid .cell.hot { background: var(--accent-soft); border-color: var(--accent); }
.ft-table-label {
  font-size: 12px;
  color: var(--fg-muted);
  margin-top: 8px;
  font-variant-numeric: tabular-nums;
  text-align: center;
}

.ft-form-popup {
  position: fixed;   /* see .ft-color-popup — escapes the toolbar's overflow clip */
  z-index: 100;
  background: var(--bg-card);
  border: 1px solid var(--line);
  border-radius: var(--r);
  box-shadow: var(--shadow-lg);
  padding: 6px;
  min-width: 240px;
  display: flex;
  flex-direction: column;
  gap: 2px;
}
.ft-form-popup[hidden] { display: none; }
.ft-form-popup .ft-form-item {
  text-align: left;
  background: transparent;
  border: 0;
  padding: 6px 10px;
  border-radius: 4px;
  font-size: 13px;
  cursor: pointer;
  color: var(--fg);
}
.ft-form-popup .ft-form-item:hover { background: var(--accent-soft); }

/* ============================== Canvas-Wrap ============================== */
#canvas-wrap {
  flex: 1;
  min-height: 0;
  position: relative;
  overflow: hidden;
  background: var(--bg-canvas);
}

/* Split-layout: replaces the single canvas-wrap with a grid of iframes,
   each pinned to a different file via /?pane=<path>. Stays out of the layout
   entirely unless `body.split-active` is set — important because `flex: 1`
   would otherwise still occupy half the main area even with `hidden`. */
#split-grid {
  display: none;
  flex: 1;
  min-height: 0;
  gap: 6px;
  padding: 6px;
  background: var(--bg-canvas);
  position: relative;
}

/* Draggable splitter between grid tracks. Sits absolutely over the gap;
   transparent at rest, accent-tinted on hover/drag. */
.split-divider {
  position: absolute;
  z-index: 100;
  background: transparent;
  transition: background 120ms;
}
.split-divider:hover,
.split-divider.dragging { background: var(--accent); opacity: .35; }
.split-divider.dragging { opacity: .55; }
.split-divider-v { width: 8px; cursor: col-resize; }
.split-divider-h { height: 8px; cursor: row-resize; }

/* Full-viewport overlay placed during a drag so the pointer keeps tracking
   the splitter even when it passes over a pane iframe. The cursor matches
   the axis so users see they're still in a resize gesture. */
.split-divider-cover {
  position: fixed;
  inset: 0;
  z-index: 1000;
  background: transparent;
}
.split-divider-cover.col { cursor: col-resize; }
.split-divider-cover.row { cursor: row-resize; }
/* Grid template (areas/cols/rows) is set per-formation via inline style by
   split.js (window.openSplitFormation). The class only enables the grid. */
body.split-active #split-grid           { display: grid; }
body.split-active #canvas-wrap,
body.split-active #empty-hint,
body.split-active #format-toolbar       { display: none !important; }

.split-pane {
  display: flex;
  flex-direction: column;
  background: var(--bg-card);
  border: 1px solid var(--line-strong);
  border-radius: 8px;
  overflow: hidden;
  min-width: 0;
  min-height: 0;
}
.split-pane-head {
  display: flex;
  align-items: center;
  padding: 4px 8px;
  background: var(--bg-canvas);
  border-bottom: 1px solid var(--line);
  flex-shrink: 0;
}
.split-pane-pick {
  flex: 1;
  min-width: 0;
  font: inherit;
  font-size: 12px;
  background: transparent;
  border: 0;
  color: var(--fg);
  cursor: pointer;
  padding: 2px 4px;
}
.split-pane-pick:focus { outline: 1px solid var(--accent); border-radius: 4px; }
.split-pane-close {
  background: transparent;
  border: 0;
  color: var(--fg-muted);
  cursor: pointer;
  font-size: 16px;
  line-height: 1;
  padding: 2px 8px;
  margin-left: 4px;
  border-radius: 4px;
  flex-shrink: 0;
}
.split-pane-close:hover { background: var(--line); color: var(--fg); }
.split-pane-frame {
  border: 0;
  width: 100%;
  flex: 1;
  background: var(--bg-card);
}

/* Formation picker — visual builder for split layouts. The user drags
   rectangles across a 3×3 grid; each rectangle becomes one pane in the
   resulting CSS grid. Drag preview is dashed; committed panes get one of
   the PANE_COLORS as background. */
.formation-picker-modal { width: 420px; }
.formation-picker-help {
  font-size: 12px;
  color: var(--fg-muted);
  margin-bottom: 14px;
  line-height: 1.45;
}
.formation-picker-grid {
  display: grid;
  gap: 5px;
  width: 320px;
  height: 320px;
  margin: 0 auto 16px;
  padding: 6px;
  background: var(--bg-canvas);
  border: 1px solid var(--line);
  border-radius: 8px;
  touch-action: none;
  user-select: none;
}
.formation-picker-cell {
  background: var(--bg-card);
  border: 1px dashed var(--line-strong);
  border-radius: 4px;
  cursor: crosshair;
  transition: background var(--t-fast) var(--ease), border-color var(--t-fast) var(--ease);
}
.formation-picker-cell.preview {
  border: 2px dashed var(--accent);
  background: var(--accent-soft);
}
.formation-picker-cell.filled {
  border: 0;
  cursor: pointer;
  /* background set inline by JS to one of the PANE_COLORS */
}
.formation-picker-cell.filled:hover {
  outline: 2px solid rgba(0, 0, 0, .15);
  outline-offset: -2px;
}

/* Pane-mode: the iframe variant of the app. Sidebar / tab-strip / split-btn
   are noise inside a pane (the parent window manages those). */
body.pane-mode #sidebar,
body.pane-mode #sidebar-backdrop,
body.pane-mode #tab-strip { display: none !important; }
body.pane-mode #topbar { padding: 0 10px; height: 34px; }
body.pane-mode #breadcrumb { font-size: 12px; }

#canvas {
  position: absolute;
  inset: 0;
  display: none;
  /* Infinite canvas: no native scroll — pan/zoom is a CSS transform on the
     surface (see zoom.js). overflow:hidden clips the transformed surface to the
     viewport; touch-action:none stops the browser hijacking finger gestures. */
  overflow: hidden;
  touch-action: none;
  /* The dot grid lives here (not on the surface) so it tiles infinitely in
     every direction. JS (applyZoom) drives background-position/size from the
     current pan + zoom so dots stay aligned with snapped boxes. */
  background-image:
    radial-gradient(circle at 1px 1px, var(--dot) 1px, transparent 1.5px);
  background-size: 14px 14px;
}
#canvas.active { display: block; }
#canvas::-webkit-scrollbar { width: 10px; height: 10px; }
#canvas::-webkit-scrollbar-thumb { background: rgba(0,0,0,.10); border-radius: 5px; border: 2px solid var(--bg-canvas); }
#canvas::-webkit-scrollbar-thumb:hover { background: rgba(0,0,0,.18); }
#canvas::-webkit-scrollbar-track { background: transparent; }

#canvas-surface {
  position: relative;
  /* Transparent positioning layer for the boxes/ink (the grid is on #canvas).
     Large so click-to-create works across the whole practical pan range; its
     own size is invisible. pan+zoom are applied as a transform from origin 0,0. */
  width: 20000px;
  height: 20000px;
  transform-origin: 0 0;
  will-change: transform;
}

/* Crosshair marking the canvas origin (logical 0,0) — the reference centre of
   the infinite canvas. Sized in logical px (scales with zoom). Two thin bars
   built from the pseudo-elements, centred exactly on (0,0). Purely decorative. */
#canvas-center-cross {
  position: absolute;
  left: 0;
  top: 0;
  width: 0;
  height: 0;
  pointer-events: none;
}
#canvas-center-cross::before,
#canvas-center-cross::after {
  content: "";
  position: absolute;
  background: var(--accent);
  opacity: .55;
}
#canvas-center-cross::before {   /* horizontal bar */
  left: -15px;
  top: -1px;
  width: 30px;
  height: 2px;
}
#canvas-center-cross::after {    /* vertical bar */
  left: -1px;
  top: -15px;
  width: 2px;
  height: 30px;
}

/* ============================== Empty Hint ============================== */
#empty-hint {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  gap: 18px;
  color: var(--fg-muted);
  text-align: center;
  padding: 32px;
  pointer-events: none;
  z-index: 0;
  overflow: auto;
}
#empty-hint .big { font-size: 17px; color: var(--fg-2); font-weight: 500; }
#empty-hint .small { font-size: 13px; max-width: 480px; line-height: 1.6; color: var(--fg-muted); }
#empty-hint .small b { color: var(--fg-2); font-weight: 600; }
#empty-hint .empty-tips {
  pointer-events: auto;
  max-width: 600px;
  text-align: left;
  background: rgba(0,0,0,.02);
  border: 1px solid var(--line);
  border-radius: var(--r);
  padding: 6px 14px 12px;
}
#empty-hint .empty-tips summary {
  cursor: pointer;
  list-style: none;
  font-size: 13px;
  font-weight: 500;
  color: var(--fg-2);
  padding: 8px 0;
  user-select: none;
}
#empty-hint .empty-tips summary::-webkit-details-marker { display: none; }
#empty-hint .empty-tips summary::before {
  content: "▸ ";
  display: inline-block;
  transition: transform var(--t-fast);
  font-size: 10px;
  color: var(--fg-muted);
}
#empty-hint .empty-tips[open] summary::before { content: "▾ "; }
#empty-hint .empty-tips .small { margin-top: 4px; text-align: left; }
#canvas.active ~ #empty-hint,
#viewer.active ~ #empty-hint { display: none; }

/* ---- Pinned quick-access tiles ---- */
.pinned-section {
  pointer-events: auto;
  width: min(720px, 100%);
  text-align: left;
}
.pinned-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px;
  margin-bottom: 10px;
  padding: 0 4px;
}
.pinned-title {
  font-size: 13px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: .06em;
  color: var(--fg-2);
}
.pinned-hint { font-size: 11px; color: var(--fg-muted); }
.pinned-empty {
  padding: 24px;
  text-align: center;
  color: var(--fg-muted);
  font-size: 13px;
  border: 1px dashed var(--line-strong);
  border-radius: var(--r);
  background: var(--bg-card);
}
.pinned-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(180px, 1fr));
  gap: 10px;
}
.pinned-tile {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 12px 14px;
  background: var(--bg-card);
  border: 1px solid var(--line);
  border-radius: var(--r);
  cursor: pointer;
  text-align: left;
  font: inherit;
  color: var(--fg);
  transition: border-color var(--t-fast), box-shadow var(--t-fast), transform var(--t-fast);
  overflow: hidden;
}
.pinned-tile:hover { border-color: var(--accent); box-shadow: var(--shadow-sm); transform: translateY(-1px); }
.pinned-tile:active { transform: translateY(0); }
.pinned-tile.missing { opacity: .55; cursor: default; }
.pinned-tile.missing:hover { transform: none; border-color: var(--line); box-shadow: none; }
.pinned-icon {
  flex-shrink: 0;
  width: 32px; height: 32px;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 18px;
  border-radius: var(--r-sm);
  background: var(--bg-canvas);
}
.pinned-icon.dir  { background: var(--accent-soft); }
.pinned-labels {
  display: flex;
  flex-direction: column;
  min-width: 0;
  flex: 1;
}
.pinned-name {
  font-size: 13px;
  font-weight: 500;
  color: var(--fg);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.pinned-parent {
  font-size: 11px;
  color: var(--fg-muted);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.pinned-missing-tag {
  font-size: 10px;
  color: var(--danger);
  margin-top: 2px;
}

/* ============================== Boxes ============================== */
.box {
  position: absolute;
  min-width: 100px;
  min-height: 50px;
  background: var(--bg-card);
  border: 1px solid transparent;
  border-radius: var(--r-sm);
  box-shadow: var(--shadow-sm);
  /* No overflow:hidden here — the toolbar (top: -32px) and the edge ports
     (translate(±50%, ±50%)) deliberately overhang the box. The .body child
     handles scrolling its own content via overflow:auto. */
  display: flex;
  flex-direction: column;
  font-family: var(--font-note);
  font-size: 14px;
  line-height: 1.55;
  color: var(--fg);
  transition: border-color var(--t-fast) var(--ease),
              box-shadow var(--t-fast) var(--ease),
              transform var(--t-fast) var(--ease);
}
.box:hover {
  border-color: var(--line-strong);
  box-shadow: var(--shadow);
}
.box.selected {
  border-color: var(--accent);
  box-shadow: 0 0 0 3px rgba(99,102,241,.15), var(--shadow);
}
.box.editing {
  border-color: var(--accent);
  box-shadow: 0 0 0 3px rgba(99,102,241,.18), var(--shadow-md);
}
.box.dragging { opacity: .94; cursor: grabbing; }

/* Rahmenlose "überall-tippen"-Box (Einfachklick, OneNote-Gefühl): in JEDEM
   Zustand ohne Hintergrund/Rahmen/Schatten — der Text liegt direkt auf der
   Canvas, auch beim Tippen und Auswählen. Greifen/Vergrößern geht weiter über
   die Hover-Griffe (Handle/Ports/Resize sind eigene Elemente). */
.box.frameless,
.box.frameless:hover,
.box.frameless.selected,
.box.frameless.editing {
  background: transparent;
  border-color: transparent;
  box-shadow: none;
}

/* Stift-Tinte-Overlay je Box: liegt über dem Inhalt, fängt aber keine Klicks
   (Text bleibt bearbeitbar; der Stift wird per pointerdown auf .body erkannt). */
.box .ink-layer {
  position: absolute;
  inset: 0;
  z-index: 1;
  pointer-events: none;
  border-radius: inherit;
}

/* Freihand-Tinte der ganzen Fläche: unterste Ebene hinter den Boxen. */
#canvas-ink-svg {
  position: absolute;
  left: 0;
  top: 0;
  /* Stift-Tinte liegt ÜBER allen Elementen (Boxen z-index 1, Verbindungen 2),
     damit man mit dem Stift über Text, Bilder und alles zeichnen kann "als wäre
     dort nichts". pointer-events:none → Finger-Bedienung der Elemente bleibt
     unberührt. (Unter dem Kontextmenü z-index 60.) */
  z-index: 5;
  pointer-events: none;
  overflow: visible;
}

/* Schwebende Stift-Werkzeugleiste (erscheint beim ersten Stift-Strich). */
.ink-toolbar {
  position: fixed;
  left: 50%;
  bottom: 18px;
  transform: translateX(-50%);
  display: none;
  gap: 10px;
  align-items: center;
  padding: 8px 14px;
  background: var(--bg-card, #fff);
  border: 1px solid var(--line-strong, #d4d4d8);
  border-radius: 999px;
  box-shadow: var(--shadow-md, 0 6px 24px rgba(0,0,0,.18));
  z-index: 9999;
}
.ink-toolbar.on { display: flex; }
.ink-toolbar input[type="color"] {
  width: 28px; height: 28px;
  border: none; background: none; padding: 0; cursor: pointer;
}
.ink-toolbar input[type="range"] { width: 96px; }
.ink-toolbar button {
  border: none; background: transparent; cursor: pointer;
  width: 30px; height: 30px; border-radius: 8px; font-size: 16px;
  color: var(--fg, #18181b);
}
.ink-toolbar button:hover { background: rgba(0,0,0,.06); }
.ink-toolbar button.on { background: #dbeafe; }

/* --- JSON Canvas 1.0 node types --- */
/* Per-node accent color: thin left bar in the chosen hue. The variable is
   set by makeBoxEl when box.color is present (resolved from preset 1-6 or
   #hex). Keeps the rest of the box's styling intact. */
.box.has-color {
  box-shadow: inset 4px 0 0 0 var(--node-color, transparent), var(--shadow-sm);
}
.box.has-color.selected,
.box.has-color.editing {
  box-shadow: inset 4px 0 0 0 var(--node-color, transparent),
              0 0 0 3px rgba(99,102,241,.15), var(--shadow);
}

/* file/link nodes share a compact card layout — fixed, never editable. */
.box-file .body, .box-link .body { padding: 10px 12px; cursor: pointer; }
.node-file, .node-link {
  display: flex; align-items: center; gap: 10px;
  min-height: 100%;
}
.node-file-icon, .node-link-icon {
  font-size: 22px; flex: 0 0 auto;
  width: 24px; height: 24px;
  display: inline-flex; align-items: center; justify-content: center;
}
img.node-link-icon { width: 18px; height: 18px; border-radius: 3px; }
.node-file-name, .node-link-host {
  font-weight: 600;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.node-file-sub, .node-link-url {
  font-size: 12px;
  color: var(--fg-muted);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  margin-left: 6px;
}
.node-file-sub::before { content: "▸"; margin-right: 4px; opacity: .6; }

/* group node: labelled rectangle, lowest z-index so it sits behind its
   members. Border is dashed so it reads as a container, not a regular box. */
.box-group {
  background: rgba(99,102,241,.05);
  border: 1px dashed var(--line-strong);
  z-index: 0;
}
.box-group:hover { background: rgba(99,102,241,.08); }
.box-group.editing, .box-group.selected {
  border-style: dashed;
}
.box-group .body {
  padding: 6px 10px;
  align-items: flex-start !important;
  justify-content: flex-start !important;
  overflow: hidden;
}
.node-group-label {
  font-size: 13px; font-weight: 600;
  color: var(--fg-muted);
  text-transform: uppercase;
  letter-spacing: .04em;
  user-select: none;
}
/* Other boxes float above groups so they can be selected/dragged on top. */
.box:not(.box-group) { z-index: 1; }
/* "Memorized" template box: pressing M tags one box as the source for the
   next click-to-paste. Green outline sits outside the border so it stays
   visible on top of the selected/editing accent border. */
.box.memorized {
  outline: 2px solid #22c55e;
  outline-offset: 2px;
}
.box.memorized.selected,
.box.memorized.editing {
  /* Keep the green halo above the accent shadow so it remains obvious. */
  outline-color: #22c55e;
}

.box .handle {
  height: 10px;
  flex-shrink: 0;
  cursor: grab;
  position: relative;
}
.box .handle::after {
  content: "";
  position: absolute;
  left: 50%; top: 4px;
  width: 24px; height: 2px;
  background: var(--line-strong);
  border-radius: 1px;
  transform: translateX(-50%);
  opacity: 0;
  transition: opacity var(--t-fast) var(--ease);
}
.box:hover .handle::after,
.box.selected .handle::after,
.box.editing .handle::after { opacity: .65; }

.box .body {
  flex: 1;
  padding: 10px 14px 12px;
  overflow: auto;
  cursor: text;
  word-wrap: break-word;
  scrollbar-width: thin;
  outline: none;
}
.box .body::-webkit-scrollbar { width: 6px; }
.box .body::-webkit-scrollbar-thumb { background: var(--line-strong); border-radius: 3px; }
.box .body:empty::before {
  content: "Tippen für Inhalt …";
  color: var(--fg-muted);
  pointer-events: none;
}
.box .body[contenteditable=true]:focus { cursor: text; }

/* Maximales Schreiberlebnis: Stift/Finger dürfen beim Zeichnen/Pannen niemals
   Box-Text markieren oder eine Auswahl über die Canvas ziehen. Text ist nur in
   der gerade BEARBEITETEN Box selektierbar. */
#canvas-surface, .box, .box .body {
  -webkit-user-select: none;
  user-select: none;
}
.box.editing .body {
  -webkit-user-select: text;
  user-select: text;
}
/* Während eines Stiftstrichs jegliche Selektion hart unterbinden. */
body.ink-drawing, body.ink-drawing * {
  -webkit-user-select: none !important;
  user-select: none !important;
}

/* Stift zeichnet über ALLEM: solange (und kurz nachdem) der Stift schreibt,
   ignorieren Canvas-Boxen sämtliche Zeiger-Eingaben. So trifft der Stift (und
   der synthetische Klick danach) keine Box, keinen Link und kein PDF/Video-
   Embed — es wird einfach darüber gezeichnet. Der Finger bedient die Elemente
   wieder, sobald der Stift weg ist. */
body.pen-active #canvas-surface .box { pointer-events: none !important; }

/* Frei platziertes Medium (Bild/Datei): rahmenlos auf der Canvas, per Finger
   verschieb-/skalierbar. Bei Auswahl ein dezenter Rahmen, damit die Grenzen und
   der Eck-Griff zum Größe-Ändern sichtbar sind. Der Cursor bleibt ein Move-
   Cursor (kein Text-Cursor), weil es kein Text-Container ist. */
/* "Tippen zum Platzieren": Fadenkreuz, solange ein Foto auf seine Position
   wartet. */
body.placing-media #canvas-surface,
body.placing-media #canvas-surface * { cursor: crosshair !important; }

.box.media .body { cursor: move; padding: 0; overflow: hidden; }
.box.media.selected { outline: 2px solid var(--accent); outline-offset: 1px; }
.box.media .body img { display: block; width: 100%; height: 100%; object-fit: contain; }

/* Inline AI ghost-text suggestion. Shown inside an editing box at the caret;
   user accepts with Tab, dismisses with Esc / typing. Visually distinct from
   real content (muted + italic) but renders inline so the user can preview
   exactly how their text will read with the suggestion applied. */
.box .body .ai-ghost {
  color: var(--fg-muted, #8a8a8a);
  opacity: .68;
  font-style: italic;
  user-select: none;
  -webkit-user-select: none;
  caret-color: transparent;
  white-space: pre-wrap;
  background: linear-gradient(180deg, transparent 0%, transparent 90%, var(--fg-muted, #8a8a8a) 90%, var(--fg-muted, #8a8a8a) 100%);
  background-size: 4px 100%;
  background-repeat: repeat-x;
  background-position: bottom;
  padding-bottom: 1px;
}
.box .body .ai-ghost::after {
  /* Tiny "Tab" hint after the ghost so first-time users know what to press. */
  content: " ⇥";
  font-style: normal;
  font-size: .75em;
  opacity: .8;
  margin-left: 2px;
  vertical-align: baseline;
}

/* Horizontal centering: body-level text-align center (decoupled from vertical
   so each axis can be set independently). */
.box.centered .body { text-align: center; }
.box.centered .body > img,
.box.centered .body > video,
.box.centered .body > iframe,
.box.centered .body p > img,
.box.centered .body p > video { display: block; margin: 0 auto; }
.box.centered .body ul,
.box.centered .body ol { list-style-position: inside; padding-left: 0; }
.box.centered .body table { margin-left: auto; margin-right: auto; }

/* Vertical alignment: flex column with the right justify-content. Top is the
   default (no class needed → plain block layout). */
.box.valign-middle .body {
  display: flex;
  flex-direction: column;
  justify-content: center;
}
.box.valign-bottom .body {
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
}

/* prose elements inside boxes */
.box .body > :first-child { margin-top: 0; }
.box .body > :last-child  { margin-bottom: 0; }
.box .body h1 { font-size: 1.55em; font-weight: 650; margin: .4em 0 .3em; letter-spacing: -.01em; }
.box .body h2 { font-size: 1.3em;  font-weight: 650; margin: .4em 0 .3em; letter-spacing: -.01em; }
.box .body h3 { font-size: 1.12em; font-weight: 650; margin: .4em 0 .25em; }
.box .body p  { margin: .3em 0; }
.box .body ul, .box .body ol { margin: 0 0 .3em; padding-left: 1.6em; }
.box .body li { margin: .12em 0; }
/* Inline field — modern token/chip look. No visible border by default; the
   field reads as a subtle filled token embedded in the text. Hover lifts the
   fill slightly, focus swaps to a clean white surface with an accent ring
   (the ring lives on the wrapper so it doesn't get clipped by the wrapper's
   overflow:hidden, which is required for the resize handle). */
.box .body input.inline-field,
.box .body textarea.inline-field,
.box .body select.inline-field {
  display: inline-block;
  padding: 2px 10px;
  margin: 0 2px;
  border: 1px solid transparent;
  border-radius: 7px;
  font: inherit;
  color: inherit;
  background: var(--line);
  min-width: 80px;
  vertical-align: baseline;
  transition: background var(--t-fast) var(--ease),
              border-color var(--t-fast) var(--ease);
}
.box .body input.inline-field:hover,
.box .body textarea.inline-field:hover,
.box .body select.inline-field:hover {
  background: var(--line-strong);
}
.box .body input.inline-field::placeholder,
.box .body textarea.inline-field::placeholder {
  color: var(--fg-muted);
  opacity: .55;
}
.box .body input.inline-field:focus,
.box .body textarea.inline-field:focus,
.box .body select.inline-field:focus {
  outline: none;
  background: var(--bg-card);
  border-color: var(--accent);
}

/* Wrap around inline single-line text fields. Provides a native
   resize-horizontal grab handle so users can drag the field wider/narrower.
   `inline-flex` + `align-items: stretch` keeps the input the same height as
   the wrap. `vertical-align: middle` avoids the `overflow:hidden` baseline-
   drop that otherwise lifts the wrap above the surrounding text. The accent
   focus ring lives here (via :focus-within) so it sits outside the wrapper's
   clipped interior. */
.box .body .inline-field-wrap {
  display: inline-flex;
  align-items: stretch;
  vertical-align: middle;
  overflow: hidden;
  resize: horizontal;
  min-width: 80px;
  max-width: 100%;
  height: auto;
  margin: 0 2px;
  border-radius: 7px;
  transition: box-shadow var(--t-fast) var(--ease);
}
.box .body .inline-field-wrap:focus-within {
  box-shadow: 0 0 0 3px rgba(99, 102, 241, .2);
}
.box .body .inline-field-wrap > input.inline-field {
  flex: 1 1 auto;
  width: 100%;
  margin: 0;
  min-width: 0;
  box-sizing: border-box;
}
.box .body textarea.inline-field {
  display: block;
  width: 100%;
  resize: vertical;
  padding: 6px 10px;
  border-radius: 8px;
}
.box .body .inline-form {
  display: block;
  margin: .5em 0;
  padding: 10px 12px;
  border: 1px solid var(--line);
  border-radius: 8px;
  background: var(--bg-canvas);
}
.box .body .inline-form-title {
  font-weight: 600;
  font-size: 1.02em;
  padding: 2px 4px;
  margin: 0 -4px 8px;
  border-radius: 4px;
  outline: none;
  min-height: 1.2em;
}
.box.editing .body .inline-form-title:hover,
.box.editing .body .inline-form-title:focus {
  background: var(--bg-card);
}
.box .body .inline-form-options {
  list-style: none;
  margin: 0;
  padding: 0;
}
.box .body .inline-form-option {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 3px 4px;
  margin: 0 -4px;
  border-radius: 4px;
}
.box.editing .body .inline-form-option:hover { background: var(--bg-card); }
.box .body .inline-form-option > input {
  flex: 0 0 auto;
  margin: 0;
  vertical-align: middle;
}
.box .body .inline-form-label {
  flex: 1 1 auto;
  padding: 2px 4px;
  border-radius: 4px;
  outline: none;
  min-height: 1.2em;
}
.box.editing .body .inline-form-label:focus {
  background: var(--bg-card);
  box-shadow: inset 0 -1px 0 var(--accent);
}
.box .body .inline-form-remove {
  flex: 0 0 auto;
  background: transparent;
  border: 0;
  color: var(--fg-muted);
  cursor: pointer;
  font-size: 18px;
  line-height: 1;
  padding: 0 6px;
  border-radius: 4px;
  opacity: 0;
  transition: opacity var(--t-fast), color var(--t-fast), background var(--t-fast);
}
.box.editing .body .inline-form-option:hover .inline-form-remove { opacity: 1; }
.box .body .inline-form-remove:hover { color: var(--fg); background: var(--bg-canvas); }
.box .body .inline-form-add {
  display: inline-block;
  background: transparent;
  border: 0;
  color: var(--accent);
  cursor: pointer;
  padding: 6px 4px 2px;
  font-size: 13px;
  font-weight: 500;
}
.box .body .inline-form-add:hover { text-decoration: underline; }

/* Filler view (box not in edit mode): hide build-mode affordances so it
   looks like a clean, fillable form. */
.box:not(.editing) .body .inline-form-add,
.box:not(.editing) .body .inline-form-remove { display: none; }
/* Arrow list — bullet list whose marker is a "🡪" (created by "->" at the line
   start or the toolbar's Pfeil-Aufzählung button). Uses the browser's NATIVE
   list marker (the same layout path as the working "•" bullet), so the arrow
   is baseline-aligned with its line automatically. Inherits the base ul
   padding so it indents like the other lists. */
.box .body ul.arrow { list-style-type: "🡪\00a0"; }
.box .body ul.arrow > li::marker { color: var(--fg-2); }

.box .body ul.todo { list-style: none; padding-left: 1.4em; }
.box .body ul.todo > li { position: relative; padding-left: 4px; }
.box .body ul.todo > li::before {
  content: "";
  position: absolute;
  left: -1.3em;
  top: .35em;
  width: 14px; height: 14px;
  border: 1.5px solid var(--line-strong);
  border-radius: 3px;
  background: var(--bg-card);
  cursor: pointer;
}
.box .body ul.todo > li.done { color: var(--fg-muted); text-decoration: line-through; }
.box .body ul.todo > li.done::before {
  background: var(--accent);
  border-color: var(--accent);
}
.box .body ul.todo > li.done::after {
  content: "";
  position: absolute;
  left: -1em;
  top: .55em;
  width: 6px; height: 3px;
  border-left: 2px solid #fff;
  border-bottom: 2px solid #fff;
  transform: rotate(-45deg);
}
.box .body a {
  color: var(--accent);
  text-decoration: none;
  border-bottom: 1px solid rgba(99,102,241,.3);
}
.box .body a:hover { color: var(--accent-hover); }
.box .body code {
  font-family: var(--font-mono);
  font-size: .9em;
  background: var(--bg-canvas);
  padding: 1px 6px;
  border-radius: var(--r-xs);
}
.box .body pre {
  background: #1a1a1c;
  color: #e4e4e7;
  padding: 12px 14px;
  border-radius: var(--r-sm);
  overflow-x: auto;
  font-family: var(--font-mono);
  font-size: 12.5px;
  margin: .5em 0;
}
.box .body pre code { background: transparent; color: inherit; padding: 0; }
.box .body blockquote {
  margin: .5em 0;
  padding: 2px 0 2px 12px;
  border-left: 3px solid var(--accent-dark);
  color: var(--fg-2);
}
.box .body hr { border: 0; border-top: 1px solid var(--line); margin: .8em 0; }
.box .body table {
  border-collapse: collapse;
  margin: .5em 0;
  font-size: .95em;
}
.box .body th, .box .body td {
  border: 1px solid var(--line-strong);
  padding: 5px 9px;
  min-width: 40px;
}
.box .body th { background: var(--bg-canvas); font-weight: 600; }

/* Marked row/column (right-click → „Zeile/Spalte markieren"). Transient visual
   selection only — serialize.js strips `.tbl-mark` so it never persists. The
   box-shadow inset tints the cell without disturbing the collapsed borders. */
.box .body td.tbl-mark, .box .body th.tbl-mark {
  background: var(--accent-soft);
  box-shadow: inset 0 0 0 9999px var(--accent-soft);
}

/* Columns-layout table: same alignment as a real table, but the borders are
   invisible by default. Faint dashed guides appear when hovering the table
   or while the box is in edit mode so the user can still see the column
   structure they're filling in. */
.box .body table.cloud-columns {
  margin: .35em 0;
}
.box .body table.cloud-columns td {
  border: 1px dashed transparent;
  padding: 2px 8px;
  min-width: 40px;
  vertical-align: middle;
}
.box .body table.cloud-columns:hover td,
.box.editing .body table.cloud-columns td {
  border-color: var(--line);
}
.box .body img {
  max-width: 100%;
  height: auto;
  display: inline-block;
  vertical-align: middle;
  border-radius: var(--r-xs);
}
.box .body .file-link {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 4px 10px;
  background: var(--bg-canvas);
  border: 1px solid var(--line);
  border-radius: var(--r-sm);
  text-decoration: none !important;
  border-bottom: 1px solid var(--line) !important;
  color: var(--fg) !important;
  font-size: 13px;
  margin: 2px 0;
}
.box .body .file-link:hover { background: var(--accent-soft); border-color: var(--accent); }
.box .body .file-link::before {
  content: "📎";
  font-size: 11px;
}

/* Inline embed references inserted via tree drag-drop. They fill the box body
   on width and stretch to use any remaining vertical space (with a min-height
   so they're always usable, even in small boxes). Alt+wheel grows/shrinks
   them dynamically. */
.box .body iframe.cloud-ref {
  display: block;
  width: 100%;
  height: 100%;
  min-height: 220px;
  margin: 0;
  border: 1px solid var(--line);
  border-radius: var(--r-sm);
  background: #fff;
  box-shadow: var(--shadow-xs);
}

/* While the user is dragging/resizing a box, or holding Alt to scroll-resize,
   we let mouse/wheel events pass through any iframe inside boxes. Otherwise
   the iframe (PDF viewer, embedded Word, etc.) eats the events and the
   parent's mousemove/mouseup or wheel handler never fires → laggy resize and
   broken Alt+Wheel. */
body.box-dragging iframe.cloud-ref,
body.box-resizing iframe.cloud-ref,
body.alt-pressed iframe.cloud-ref { pointer-events: none; }
body.alt-pressed .box .body iframe.cloud-ref { cursor: ns-resize; }
.box .body img.cloud-ref-img,
.box .body video.cloud-ref-video {
  display: block;
  max-width: 100%;
  margin: 0 auto;
  border-radius: var(--r-xs);
}
.box .body audio.cloud-ref-audio { width: 100%; margin: 4px 0; }
/* Layout: when an embed is the dominant child of the body, let it fill. */
.box .body > iframe.cloud-ref:only-child,
.box .body > img.cloud-ref-img:only-child,
.box .body > video.cloud-ref-video:only-child {
  height: 100%;
}
.box.drag-over {
  border-color: var(--accent);
  box-shadow: 0 0 0 3px rgba(99,102,241,.22), var(--shadow-md);
}
.tree-row[draggable=true]:active { opacity: .6; }

.box .resize-edge {
  position: absolute;
  opacity: 0;
  transition: opacity var(--t-fast) var(--ease);
  background: var(--fg-muted);
}
.box .resize-e {
  top: 8px; bottom: 22px; right: 0;
  width: 4px;
  cursor: ew-resize;
  border-radius: 2px 0 0 2px;
}
.box .resize-s {
  left: 8px; right: 22px; bottom: 0;
  height: 4px;
  cursor: ns-resize;
  border-radius: 2px 2px 0 0;
}
.box:hover .resize-edge,
.box.selected .resize-edge,
.box.editing .resize-edge { opacity: .35; }
.box .resize-edge:hover { opacity: .8 !important; }

.box .resize {
  position: absolute;
  right: 0; bottom: 0;
  width: 20px; height: 20px;
  cursor: nwse-resize;
  opacity: 0;
  transition: opacity var(--t-fast) var(--ease);
}
.box .resize::after {
  content: "";
  position: absolute;
  right: 3px; bottom: 3px;
  width: 11px; height: 11px;
  background:
    linear-gradient(135deg, transparent 0 35%, var(--fg-muted) 35% 50%, transparent 50% 65%, var(--fg-muted) 65% 80%, transparent 80%);
  border-radius: 0 0 var(--r-xs) 0;
}
.box.selected .resize, .box.editing .resize { opacity: .9; }

.box .toolbar {
  position: absolute;
  top: -32px;
  right: 0;
  display: none;
  gap: 2px;
  background: var(--bg-card);
  border: 1px solid var(--line);
  border-radius: var(--r-sm);
  padding: 2px;
  box-shadow: var(--shadow);
}
.box:hover .toolbar, .box.selected .toolbar, .box.editing .toolbar { display: inline-flex; }
.box .toolbar button {
  background: transparent;
  border: 0;
  cursor: pointer;
  padding: 4px 8px;
  font-size: 14px;
  line-height: 1;
  color: var(--fg-muted);
  border-radius: var(--r-xs);
  transition: background var(--t-fast), color var(--t-fast);
}
.box .toolbar button:hover { background: var(--bg-canvas); color: var(--fg); }
.box .toolbar button.del:hover { background: #fee2e2; color: var(--danger); }

/* ====== Connection arrows between boxes ====== */
/* Ports — 4 small dots at the edge midpoints. Hidden by default; shown on
   box hover/selection, and shown on every box while an arrow drag is in
   progress (so the user can see where they can drop). */
.box .port {
  position: absolute;
  width: 12px; height: 12px;
  background: var(--accent);
  border: 2px solid var(--bg-card);
  border-radius: 50%;
  cursor: crosshair;
  opacity: 0;
  pointer-events: none;
  z-index: 3;
  transition: opacity var(--t-fast) var(--ease), transform var(--t-fast) var(--ease);
  box-shadow: 0 1px 3px rgba(0,0,0,.18);
}
.box:hover .port, .box.selected .port,
body.arrow-dragging .box .port { opacity: 1; pointer-events: auto; }
.box .port.top    { left: 50%; top: 0;       transform: translate(-50%, -50%); }
.box .port.right  { right: 0;  top: 50%;     transform: translate(50%, -50%); }
.box .port.bottom { left: 50%; bottom: 0;    transform: translate(-50%, 50%); }
.box .port.left   { left: 0;   top: 50%;     transform: translate(-50%, -50%); }
.box .port.top:hover    { transform: translate(-50%, -50%) scale(1.35); }
.box .port.right:hover  { transform: translate(50%, -50%)  scale(1.35); }
.box .port.bottom:hover { transform: translate(-50%, 50%)  scale(1.35); }
.box .port.left:hover   { transform: translate(-50%, -50%) scale(1.35); }

/* Highlight the box currently under the cursor while an arrow drag is live. */
.box.arrow-target {
  border-color: var(--accent);
  box-shadow: 0 0 0 3px rgba(99,102,241,.22), var(--shadow);
}

/* SVG overlay carrying the arrows. Sits above boxes so arrows are visible
   across the canvas; only the <path>s opt back into pointer events. */
#canvas-svg {
  position: absolute;
  inset: 0;
  width: 100%; height: 100%;
  pointer-events: none;
  overflow: visible;
  z-index: 2;
}
#canvas-svg defs #arrow-head path          { fill: rgba(63,63,70,.7); }
#canvas-svg defs #arrow-head-selected path { fill: var(--accent); }
#canvas-svg path.connection {
  fill: none;
  stroke: rgba(63,63,70,.7);
  stroke-width: 2;
  stroke-linecap: round;
  pointer-events: stroke;
  cursor: pointer;
  transition: stroke var(--t-fast) var(--ease), stroke-width var(--t-fast) var(--ease);
}
#canvas-svg path.connection:hover   { stroke: var(--accent); stroke-width: 2.5; }
#canvas-svg path.connection.selected{ stroke: var(--accent); stroke-width: 2.5; }
#canvas-svg path.connection.pending {
  stroke: var(--accent);
  stroke-width: 2;
  stroke-dasharray: 6 5;
  pointer-events: none;
}

/* Label that floats at the midpoint of each arrow. */
.conn-label {
  position: absolute;
  transform: translate(-50%, -50%);
  z-index: 3;
  padding: 2px 8px;
  font-family: var(--font-note);
  font-size: 12px;
  line-height: 1.35;
  color: var(--fg);
  background: var(--bg-card);
  border: 1px solid var(--line);
  border-radius: var(--r-xs);
  box-shadow: 0 1px 2px rgba(0,0,0,.08);
  max-width: 260px;
  white-space: pre-wrap;
  word-break: break-word;
  cursor: text;
  user-select: text;
  transition: opacity var(--t-fast) var(--ease);
}
.conn-label.empty {
  width: 16px;
  height: 16px;
  padding: 0;
  font-size: 12px;
  line-height: 14px;
  text-align: center;
  color: var(--fg-muted);
  border-style: dashed;
  border-color: var(--line-strong);
  opacity: .3;
}
.conn-label.empty::after { content: "+"; }
.conn-label.empty:hover, .conn-label.empty.selected { opacity: 1; }
.conn-label.selected:not(.empty) {
  border-color: var(--accent);
  box-shadow: 0 0 0 2px rgba(99,102,241,.15);
}
.conn-label.editing {
  border-style: solid;
  border-color: var(--accent);
  box-shadow: 0 0 0 2px rgba(99,102,241,.25);
  outline: none;
  opacity: 1;
  width: auto;
  height: auto;
  min-width: 30px;
  padding: 2px 8px;
  font-size: 12px;
  line-height: 1.35;
  text-align: left;
  color: var(--fg);
}
.conn-label.editing::after { content: none; }

/* While dragging an arrow: crosshair cursor on the canvas, and box internals
   stop swallowing events so document.elementFromPoint can hit the target
   box itself. */
body.arrow-dragging,
body.arrow-dragging #canvas-surface { cursor: crosshair; }
body.arrow-dragging #canvas-surface .box .body,
body.arrow-dragging #canvas-surface .box .handle,
body.arrow-dragging #canvas-surface .box .resize,
body.arrow-dragging #canvas-surface .box .toolbar,
body.arrow-dragging #canvas-surface .conn-label,
body.arrow-dragging #canvas-svg path.connection { pointer-events: none; }

/* Rubber-band: dashed accent rectangle drawn on canvas-surface while the user
   drags from empty canvas. Pointer-events: none so the rectangle never
   intercepts the in-flight gesture. */
#rubber-band {
  position: absolute;
  border: 1px dashed var(--accent);
  background: rgba(99, 102, 241, .10);
  border-radius: 2px;
  pointer-events: none;
  z-index: 4;
}
body.rubber-banding { cursor: crosshair; }
/* Hide ports while rubber-banding so they don't visually clutter the
   selection rectangle as the cursor passes over boxes. */
body.rubber-banding #canvas-surface .box .port { display: none; }
/* While selecting/moving/resizing boxes, kill native text selection inside
   box bodies — otherwise the browser highlights whatever paragraphs the
   cursor crosses, leaving stray blue text selections after the gesture. */
body.rubber-banding #canvas-surface .box .body,
body.box-dragging   #canvas-surface .box .body,
body.box-resizing   #canvas-surface .box .body {
  user-select: none;
  -webkit-user-select: none;
}

/* Paint / drawing canvas inside a box. Replaces text body content. */
.paint-canvas {
  position: absolute;
  inset: 0;
  background: #fff;
  cursor: crosshair;
  overflow: hidden;
}
.paint-canvas canvas {
  display: block;
  width: 100%;
  height: 100%;
  touch-action: none;
}
.paint-canvas .paint-tools {
  position: absolute;
  top: 4px;
  right: 4px;
  display: flex;
  gap: 4px;
  align-items: center;
  background: rgba(255, 255, 255, 0.92);
  border: 1px solid #d1d5db;
  border-radius: 6px;
  padding: 2px 4px;
  box-shadow: 0 1px 2px rgba(0, 0, 0, 0.06);
  z-index: 2;
}
.paint-canvas .paint-tools input[type="color"] {
  width: 22px; height: 22px;
  padding: 0; border: none; background: none; cursor: pointer;
}
.paint-canvas .paint-tools input[type="range"] {
  width: 70px;
}
.paint-canvas .paint-tools button {
  width: 24px; height: 22px;
  border: 1px solid #d1d5db;
  background: #fff;
  border-radius: 4px;
  cursor: pointer;
  font-size: 13px;
  line-height: 1;
  padding: 0;
}
.paint-canvas .paint-tools button.on { background: #dbeafe; }
.paint-canvas.erasing { cursor: cell; }

/* Hidden boxes: removed from layout by default. The reveal-hidden toggle
   shows them ghosted with a dashed outline so the user can right-click them
   to bring them back. */
.box.is-hidden { display: none; }
body.reveal-hidden .box.is-hidden {
  display: flex;
  opacity: 0.35;
  outline: 1px dashed #9ca3af;
  outline-offset: -1px;
  filter: grayscale(0.5);
}

/* Rendered markdown inside .box */
.md > :first-child { margin-top: 0; }
.md > :last-child  { margin-bottom: 0; }
.md h1, .md h2, .md h3, .md h4 {
  font-family: var(--font-note);
  font-weight: 650;
  line-height: 1.25;
  margin: .55em 0 .3em;
  letter-spacing: -.01em;
}
.md h1 { font-size: 1.55em; }
.md h2 { font-size: 1.3em; }
.md h3 { font-size: 1.1em; }
.md h4 { font-size: 1em; color: var(--fg-2); }
.md p { margin: .35em 0; }
.md ul, .md ol { margin: .35em 0; padding-left: 1.6em; }
.md li { margin: .12em 0; }
.md a { color: var(--accent); text-decoration: none; border-bottom: 1px solid rgba(99,102,241,.3); }
.md a:hover { color: var(--accent-hover); border-bottom-color: var(--accent-hover); }
.md code {
  font-family: var(--font-mono);
  font-size: .9em;
  background: var(--bg-canvas);
  padding: 1px 6px;
  border-radius: var(--r-xs);
  border: 1px solid var(--line);
}
.md pre {
  background: #1a1a1c;
  color: #e4e4e7;
  padding: 12px 14px;
  border-radius: var(--r-sm);
  overflow-x: auto;
  font-size: 12.5px;
  line-height: 1.5;
  margin: .5em 0;
}
.md pre code { background: transparent; color: inherit; padding: 0; border: 0; }
.md blockquote {
  margin: .5em 0;
  padding: 2px 0 2px 14px;
  border-left: 3px solid var(--accent-dark);
  color: var(--fg-2);
}
.md hr { border: 0; border-top: 1px solid var(--line); margin: .8em 0; }
.md table { border-collapse: collapse; margin: .5em 0; font-size: .95em; }
.md th, .md td { border: 1px solid var(--line); padding: 5px 10px; }
.md th { background: var(--bg-canvas); font-weight: 600; }
.md input[type=checkbox] { margin-right: 6px; }

/* ============================== Viewer ============================== */
#viewer {
  position: absolute;
  inset: 0;
  display: none;
  background: var(--bg-canvas);
  z-index: 1;
}
#viewer.active { display: block; }

/* Every direct child fills the viewer absolutely — no flex+100% headaches. */
#viewer > * {
  position: absolute;
  inset: 0;
}

/* One panel per open tab, stacked in the #viewer host. Only the active tab's
   panel is shown; the others stay in the DOM (display:none) so their content —
   including live iframes — survives a tab switch without reloading. */
.viewer-panel { display: none; }
.viewer-panel.active { display: block; }
.viewer-panel > * { position: absolute; inset: 0; }

#viewer .v-frame {
  width: 100%;
  height: 100%;
  border: 0;
  display: block;
  background: #fff;
}

/* HTML-Viewer: Wrapper füllt das Panel (inset:0 via .viewer-panel > *) und
   ist Verankerung für den schwebenden "Als PDF speichern"-Button. */
#viewer .v-html { background: #fff; }

#viewer .v-office {
  background: #fff;
  overflow: hidden;
}
#viewer .v-office iframe {
  width: 100% !important;
  height: 100% !important;
  border: 0;
}

/* Inline read-only previews inside canvas boxes — drag a .docx/.md/.xlsx
   onto the canvas to insert one. Content is re-rendered from the source on
   every box mount; only the placeholder shell lives in the note JSON. */
.box .body .cloud-inline {
  display: block;
  background: #fff;
  color: #18181b;
  border: 1px solid var(--line);
  border-radius: var(--r-sm);
  overflow: auto;
  max-height: 100%;
}
.box .body .cloud-inline-head {
  padding: 6px 10px;
  background: var(--bg-canvas);
  border-bottom: 1px solid var(--line);
  font-size: 12px;
  position: sticky;
  top: 0;
}
.box .body .cloud-inline-head a {
  color: var(--accent);
  text-decoration: none;
}
.box .body .cloud-inline-head a:hover { text-decoration: underline; }
.box .body .cloud-inline-body {
  padding: 12px 16px;
  font-size: 14px;
  line-height: 1.55;
}
.box .body .cloud-inline-loading { color: var(--fg-muted); font-size: 13px; }
.box .body .cloud-inline-err     { color: var(--danger);   font-size: 13px; }
.box .body .cloud-inline-body p           { margin: 0 0 8px; }
.box .body .cloud-inline-body h1,
.box .body .cloud-inline-body h2,
.box .body .cloud-inline-body h3          { margin: 12px 0 6px; }
.box .body .cloud-inline-body img         { max-width: 100%; }
.box .body .cloud-inline-body table       { border-collapse: collapse; font-size: 12px; }
.box .body .cloud-inline-body td,
.box .body .cloud-inline-body th          { border: 1px solid #d4d4d8; padding: 3px 6px; }


#viewer .v-img-wrap {
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 28px;
  overflow: auto;
}
#viewer .v-img-wrap img {
  max-width: 100%;
  max-height: 100%;
  background: #fff;
  box-shadow: var(--shadow-lg);
  border-radius: var(--r-sm);
}

#viewer .v-center {
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 24px;
}

#viewer .v-card {
  background: var(--bg-card);
  border: 1px solid var(--line);
  border-radius: var(--r);
  padding: 32px 32px;
  box-shadow: var(--shadow);
  text-align: center;
  max-width: 460px;
}
#viewer .v-card-title { font-weight: 600; margin-bottom: 6px; word-break: break-all; font-size: 15px; }
#viewer .v-card-sub   { color: var(--fg-muted); font-size: 13px; margin-bottom: 20px; }

#viewer .v-loading { display: flex; align-items: center; justify-content: center; color: var(--fg-muted); font-size: 14px; }
#viewer .v-error   { padding: 32px; color: var(--danger); }

/* ============================== Forms viewer (.form) ============================== */
#viewer .form-view {
  position: absolute;
  inset: 0;
  overflow: auto;
  background: var(--bg-canvas);
}
#viewer .form-tabs {
  position: sticky;
  top: 0;
  z-index: 5;
  display: flex;
  gap: 2px;
  padding: 10px 16px 0;
  background: var(--bg-canvas);
  border-bottom: 1px solid var(--line);
}
#viewer .form-tab {
  background: transparent;
  border: 0;
  padding: 8px 14px;
  border-radius: 6px 6px 0 0;
  font-size: 13px;
  color: var(--fg-muted);
  cursor: pointer;
}
#viewer .form-tab:hover { background: var(--bg-card); color: var(--fg); }
#viewer .form-tab.active {
  background: var(--bg-card);
  color: var(--fg);
  font-weight: 600;
  box-shadow: inset 0 -2px 0 var(--accent);
}

/* ----- Builder ----- */
#viewer .form-builder {
  max-width: 760px;
  margin: 0 auto;
  padding: 24px 16px 80px;
  display: flex;
  flex-direction: column;
  gap: 14px;
}
#viewer .form-title {
  font-size: 22px;
  font-weight: 600;
  padding: 10px 12px;
  border: 1px solid transparent;
  border-radius: 8px;
  background: var(--bg-card);
  color: var(--fg);
  width: 100%;
}
#viewer .form-title:hover, #viewer .form-title:focus {
  border-color: var(--line-strong);
  outline: none;
}
#viewer .form-description {
  font: inherit;
  padding: 8px 12px;
  border: 1px solid transparent;
  border-radius: 8px;
  background: var(--bg-card);
  color: var(--fg);
  resize: vertical;
  width: 100%;
}
#viewer .form-description:hover, #viewer .form-description:focus {
  border-color: var(--line-strong);
  outline: none;
}
#viewer .form-fields {
  display: flex;
  flex-direction: column;
  gap: 12px;
}
#viewer .form-field-card {
  background: var(--bg-card);
  border: 1px solid var(--line);
  border-radius: 10px;
  padding: 14px 16px;
  display: flex;
  flex-direction: column;
  gap: 10px;
  box-shadow: 0 1px 2px rgba(0,0,0,.04);
}
#viewer .form-field-head {
  display: flex;
  align-items: center;
  gap: 10px;
}
#viewer .form-field-drag {
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 22px;
  height: 22px;
  color: var(--fg-muted);
  cursor: grab;
  user-select: none;
  border-radius: 4px;
  font-size: 16px;
  line-height: 1;
}
#viewer .form-field-drag:hover { color: var(--fg); background: var(--bg-canvas); }
#viewer .form-field-drag:active { cursor: grabbing; }
#viewer .form-field-card.form-field-dragging { opacity: .45; }
#viewer .form-field-card.form-field-drop {
  border-color: var(--accent);
  box-shadow: 0 0 0 2px var(--accent-soft);
}
#viewer .form-field-label {
  flex: 1 1 auto;
  font: inherit;
  font-weight: 500;
  padding: 6px 8px;
  border: 1px solid var(--line);
  border-radius: 6px;
  background: var(--bg-canvas);
  color: var(--fg);
}
#viewer .form-field-type {
  flex: 0 0 auto;
  padding: 6px 8px;
  border: 1px solid var(--line);
  border-radius: 6px;
  background: var(--bg-canvas);
  color: var(--fg);
  font: inherit;
}
#viewer .form-field-delete {
  flex: 0 0 auto;
  background: transparent;
  border: 0;
  color: var(--fg-muted);
  cursor: pointer;
  font-size: 20px;
  line-height: 1;
  padding: 2px 8px;
  border-radius: 4px;
}
#viewer .form-field-delete:hover { color: var(--danger); background: var(--bg-canvas); }
#viewer .form-field-stub {
  color: var(--fg-muted);
  font-size: 13px;
  border-bottom: 1px dashed var(--line-strong);
  padding-bottom: 4px;
}
#viewer .form-field-placeholder {
  font: inherit;
  font-style: italic;
  color: var(--fg-muted);
  padding: 6px 8px;
  border: 1px dashed var(--line-strong);
  border-radius: 6px;
  background: var(--bg-canvas);
}
#viewer .form-field-placeholder:focus {
  border-style: solid;
  border-color: var(--accent);
  color: var(--fg);
  outline: none;
}
#viewer .form-field-options {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 4px;
}
#viewer .form-field-option {
  display: flex;
  align-items: center;
  gap: 8px;
}
#viewer .form-field-option > input[type="radio"],
#viewer .form-field-option > input[type="checkbox"] {
  flex: 0 0 auto;
}
#viewer .form-field-option-label {
  flex: 1 1 auto;
  font: inherit;
  padding: 4px 8px;
  border: 1px solid transparent;
  border-radius: 4px;
  background: transparent;
  color: var(--fg);
}
#viewer .form-field-option-label:hover, #viewer .form-field-option-label:focus {
  border-color: var(--line);
  background: var(--bg-canvas);
  outline: none;
}
#viewer .form-field-option-remove {
  background: transparent;
  border: 0;
  color: var(--fg-muted);
  cursor: pointer;
  font-size: 16px;
  padding: 0 6px;
  border-radius: 4px;
  opacity: 0;
}
#viewer .form-field-option:hover .form-field-option-remove { opacity: 1; }
#viewer .form-field-option-remove:hover { color: var(--danger); background: var(--bg-canvas); }
#viewer .form-field-option-add {
  align-self: flex-start;
  background: transparent;
  border: 0;
  color: var(--accent);
  cursor: pointer;
  font-size: 13px;
  padding: 4px 0;
}
#viewer .form-field-option-add:hover { text-decoration: underline; }
#viewer .form-field-required {
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: 13px;
  color: var(--fg-muted);
}
#viewer .form-add-field {
  display: flex;
  gap: 8px;
  flex-wrap: wrap;
  margin-top: 4px;
}
#viewer .form-add-field-btn {
  background: var(--bg-card);
  border: 1px dashed var(--line-strong);
  color: var(--accent);
  padding: 8px 12px;
  border-radius: 8px;
  cursor: pointer;
  font: inherit;
  font-size: 13px;
}
#viewer .form-add-field-btn:hover { background: var(--accent-soft); border-color: var(--accent); }

/* ----- Preview / fill ----- */
#viewer .form-preview {
  max-width: 720px;
  margin: 0 auto;
  padding: 24px 16px 80px;
  display: flex;
  flex-direction: column;
  gap: 16px;
}
#viewer .form-preview-title {
  font-size: 24px;
  font-weight: 600;
  margin: 0;
}
#viewer .form-preview-desc {
  color: var(--fg-muted);
  margin: 0;
  white-space: pre-wrap;
}
#viewer .form-preview-empty { color: var(--fg-muted); }
#viewer .form-preview-field {
  background: var(--bg-card);
  border: 1px solid var(--line);
  border-radius: 10px;
  padding: 14px 16px;
  display: flex;
  flex-direction: column;
  gap: 8px;
}
#viewer .form-preview-label {
  font-weight: 500;
}
#viewer .form-preview-label .req { color: var(--danger); }
#viewer .form-preview-field input[type="text"],
#viewer .form-preview-field textarea {
  font: inherit;
  padding: 8px 10px;
  border: 1px solid var(--line);
  border-radius: 6px;
  background: var(--bg-canvas);
  color: var(--fg);
  width: 100%;
}
#viewer .form-preview-field textarea { resize: vertical; }
#viewer .form-preview-option {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 4px 0;
  cursor: pointer;
}
#viewer .form-preview-actions {
  display: flex;
  align-items: center;
  gap: 12px;
  margin-top: 4px;
}
#viewer .form-submit-btn {
  background: var(--accent);
  color: white;
  border: 0;
  padding: 10px 22px;
  border-radius: 8px;
  font: inherit;
  font-weight: 500;
  cursor: pointer;
}
#viewer .form-submit-btn:hover { filter: brightness(1.06); }
#viewer .form-submit-btn:disabled { background: var(--line-strong); cursor: not-allowed; }
#viewer .form-submit-status { color: var(--ok, #16a34a); font-size: 13px; }

/* ----- Answers ----- */
#viewer .form-answers {
  max-width: 880px;
  margin: 0 auto;
  padding: 24px 16px 80px;
  display: flex;
  flex-direction: column;
  gap: 12px;
}
#viewer .form-answers-empty {
  max-width: 720px;
  margin: 60px auto;
  text-align: center;
  color: var(--fg-muted);
}
#viewer .form-answers-actions {
  display: flex;
  gap: 8px;
  justify-content: flex-end;
}
#viewer .form-export-csv {
  background: transparent;
  border: 1px solid var(--line);
  color: var(--fg);
  padding: 6px 12px;
  border-radius: 6px;
  font: inherit;
  font-size: 13px;
  cursor: pointer;
}
#viewer .form-export-csv:hover { background: var(--bg-card); border-color: var(--line-strong); }
#viewer .form-answer-card {
  background: var(--bg-card);
  border: 1px solid var(--line);
  border-radius: 10px;
  padding: 12px 16px;
}
#viewer .form-answer-head {
  display: flex;
  align-items: center;
  gap: 10px;
  padding-bottom: 8px;
  border-bottom: 1px solid var(--line);
  margin-bottom: 8px;
}
#viewer .form-answer-num { font-weight: 600; }
#viewer .form-answer-date { color: var(--fg-muted); font-size: 13px; flex: 1; }
#viewer .form-answer-delete {
  background: transparent;
  border: 0;
  color: var(--fg-muted);
  cursor: pointer;
  font-size: 18px;
  padding: 0 6px;
  border-radius: 4px;
}
#viewer .form-answer-delete:hover { color: var(--danger); background: var(--bg-canvas); }
#viewer .form-answer-card dl {
  display: grid;
  grid-template-columns: minmax(120px, 200px) 1fr;
  gap: 6px 12px;
  margin: 0;
}
#viewer .form-answer-card dt { color: var(--fg-muted); font-size: 13px; }
#viewer .form-answer-card dd { margin: 0; word-break: break-word; }

#viewer .v-sheet { /* inherits absolute-fill from #viewer > * */ }
#viewer .v-tabs {
  position: absolute;
  top: 0; left: 0; right: 0;
  height: 44px;
  display: flex; gap: 2px;
  padding: 8px 12px;
  background: var(--bg-card);
  border-bottom: 1px solid var(--line);
  overflow-x: auto;
  z-index: 1;
}
#viewer .v-tabs button {
  background: transparent;
  border: 1px solid transparent;
  padding: 5px 12px;
  border-radius: var(--r-xs);
  font-size: 12px;
  color: var(--fg-muted);
  cursor: pointer;
  white-space: nowrap;
  transition: background var(--t-fast), color var(--t-fast), border-color var(--t-fast);
}
#viewer .v-tabs button:hover { background: var(--bg-canvas); color: var(--fg); }
#viewer .v-tabs button.on {
  background: var(--accent-soft);
  color: var(--accent-hover);
  border-color: rgba(99,102,241,.2);
  font-weight: 500;
}

#viewer .v-sheet-body {
  position: absolute;
  top: 44px; left: 0; right: 0; bottom: 0;
  overflow: auto;
  padding: 16px;
}
#viewer .v-sheet.no-tabs .v-sheet-body { top: 0; }

#viewer .v-table-wrap {
  overflow: auto;
  padding: 16px;
}
#viewer .v-table-wrap table {
  border-collapse: collapse;
  background: var(--bg-card);
  font-size: 13px;
  box-shadow: var(--shadow);
  border-radius: var(--r-sm);
  overflow: hidden;
}
#viewer .v-table-wrap th,
#viewer .v-table-wrap td,
#viewer .v-sheet-body th,
#viewer .v-sheet-body td {
  border: 1px solid var(--line);
  padding: 6px 12px;
  max-width: 360px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-family: var(--font-ui);
}
#viewer .v-table-wrap th,
#viewer .v-sheet-body th {
  background: var(--bg-canvas);
  font-weight: 600;
  position: sticky; top: 0;
  z-index: 1;
}
#viewer .v-sheet-body table {
  border-collapse: collapse;
  background: var(--bg-card);
  font-size: 13px;
  box-shadow: var(--shadow-sm);
}

#viewer .v-media {
  display: flex;
  align-items: center;
  justify-content: center;
  background: #0a0a0c;
  padding: 24px;
}
#viewer .v-media audio { width: min(560px, 100%); }
#viewer .v-media video { max-width: 100%; max-height: 100%; border-radius: var(--r-sm); box-shadow: var(--shadow-lg); }

/* DOCX viewer — paper metaphor, centered max-width column */
#viewer .v-doc {
  overflow: auto;
  padding: 28px 24px 96px;
  background: var(--bg-canvas);
}
#viewer .v-doc-paper {
  max-width: 780px;
  margin: 0 auto;
  background: var(--bg-card);
  padding: 64px 80px;
  box-shadow: var(--shadow-md);
  border-radius: var(--r-sm);
  font-family: var(--font-note);
  font-size: 14.5px;
  line-height: 1.7;
  color: var(--fg);
}
#viewer .v-doc-paper img { max-width: 100%; height: auto; display: block; margin: 1em auto; }
#viewer .v-doc-paper table { border-collapse: collapse; margin: 1em 0; }
#viewer .v-doc-paper th, #viewer .v-doc-paper td { border: 1px solid var(--line); padding: 6px 10px; }
#viewer .v-doc-paper h1 { font-size: 1.8em; margin: 0 0 .4em; }
#viewer .v-doc-paper h2 { font-size: 1.45em; margin: 1em 0 .35em; }
#viewer .v-doc-paper h3 { font-size: 1.2em; margin: .85em 0 .3em; }
#viewer .v-doc-paper p  { margin: .55em 0; }

/* Code viewer — line numbers + monospace pane */
#viewer .v-code {
  display: flex;
  flex-direction: column;
  background: var(--bg-card);
}
#viewer .v-code-header {
  flex-shrink: 0;
  display: flex;
  align-items: center;
  justify-content: space-between;
  height: 36px;
  padding: 0 14px;
  background: var(--bg-card);
  border-bottom: 1px solid var(--line);
  font-size: 12px;
  color: var(--fg-muted);
}
#viewer .v-code-lang {
  font-family: var(--font-mono);
  font-size: 11px;
  color: var(--accent-hover);
  background: var(--accent-soft);
  padding: 2px 8px;
  border-radius: 999px;
  text-transform: uppercase;
  letter-spacing: .04em;
  font-weight: 600;
}
#viewer .v-code-stats { font-variant-numeric: tabular-nums; }
#viewer .v-code-body {
  position: absolute;
  top: 36px; left: 0; right: 0; bottom: 0;
  display: flex;
  overflow: auto;
  background: var(--bg-card);
}
#viewer .v-code-ln,
#viewer .v-code-src {
  margin: 0;
  padding: 14px 0;
  font-family: var(--font-mono);
  font-size: 12.5px;
  line-height: 1.6;
  white-space: pre;
  tab-size: 4;
}
#viewer .v-code-ln {
  padding-left: 14px;
  padding-right: 14px;
  color: var(--fg-muted);
  text-align: right;
  user-select: none;
  border-right: 1px solid var(--line);
  background: var(--bg-canvas);
  position: sticky;
  left: 0;
  z-index: 1;
}
#viewer .v-code-src {
  padding-left: 16px;
  padding-right: 24px;
  color: var(--fg);
  flex: 1;
  min-width: 0;
}

#viewer .v-card-actions {
  display: flex;
  gap: 8px;
  justify-content: center;
  flex-wrap: wrap;
}
#viewer .v-card-actions .btn-primary,
#viewer .v-card-actions .btn-secondary {
  text-decoration: none;
  display: inline-block;
}

/* ---------- Font preview ---------- */
#viewer .v-font {
  overflow: auto;
  background: var(--bg-card);
}
#viewer .v-font-header {
  padding: 28px 36px 18px;
  border-bottom: 1px solid var(--line);
  background: var(--bg-canvas);
  font-family: var(--font-ui);
}
#viewer .v-font-title { font-size: 20px; font-weight: 600; }
#viewer .v-font-sub   { font-size: 13px; color: var(--fg-muted); margin-top: 4px; }
#viewer .v-font-body  { padding: 28px 36px 80px; }
#viewer .v-font-line  { margin: 4px 0 18px; line-height: 1.15; color: var(--fg); word-break: break-word; }
#viewer .v-font-pangram {
  margin-top: 24px;
  padding: 22px 26px;
  background: var(--bg-canvas);
  border-radius: var(--r-sm);
  border: 1px solid var(--line);
  white-space: pre-wrap;
  font-size: 22px;
  line-height: 1.5;
  outline: none;
}
#viewer .v-font-pangram:focus { border-color: var(--accent); box-shadow: 0 0 0 3px rgba(99,102,241,.15); }

/* ---------- Data tables (ICS / VCF / GPX / archive) ---------- */
#viewer .v-data {
  overflow: auto;
  padding: 28px 36px 80px;
  background: var(--bg-canvas);
  font-family: var(--font-ui);
}
#viewer .v-data > h2 { margin: 0 0 4px; font-size: 19px; font-weight: 600; }
#viewer .v-data > h3 { margin: 28px 0 10px; font-size: 14px; font-weight: 600; color: var(--fg-2); text-transform: uppercase; letter-spacing: .04em; }
#viewer .v-data-sub { font-size: 13px; color: var(--fg-muted); margin-bottom: 16px; }
#viewer .v-data-table {
  border-collapse: collapse;
  width: 100%;
  background: var(--bg-card);
  font-size: 13px;
  box-shadow: var(--shadow-sm);
  border-radius: var(--r-sm);
  overflow: hidden;
}
#viewer .v-data-table th {
  background: var(--bg-canvas);
  padding: 8px 14px;
  text-align: left;
  font-weight: 600;
  border-bottom: 1px solid var(--line);
  position: sticky; top: 0;
  z-index: 1;
}
#viewer .v-data-table td {
  padding: 7px 14px;
  border-top: 1px solid var(--line);
  max-width: 380px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-variant-numeric: tabular-nums;
}
#viewer .v-data-table tbody tr:hover td { background: var(--bg-canvas); }

/* ---------- Hex dump (binary fallback) ---------- */
#viewer .v-binary {
  overflow: auto;
  padding: 28px 36px 80px;
  background: var(--bg-canvas);
}
#viewer .v-bin-card {
  background: var(--bg-card);
  border: 1px solid var(--line);
  border-radius: var(--r);
  padding: 22px 26px;
  box-shadow: var(--shadow-sm);
  margin-bottom: 18px;
}
#viewer .v-bin-title { font-size: 16px; font-weight: 600; margin-bottom: 4px; word-break: break-all; }
#viewer .v-bin-sub   { font-size: 13px; color: var(--fg-muted); margin-bottom: 14px; }
#viewer .v-bin-sub b { color: var(--fg); font-weight: 600; }
#viewer .v-bin-actions { display: flex; gap: 8px; flex-wrap: wrap; }
#viewer .v-bin-actions a { text-decoration: none; }
#viewer .v-hex {
  background: var(--bg-card);
  border: 1px solid var(--line);
  border-radius: var(--r);
  padding: 16px 18px;
  box-shadow: var(--shadow-sm);
}
#viewer .v-hex-meta {
  display: flex;
  gap: 24px;
  font-size: 12px;
  margin-bottom: 12px;
  padding-bottom: 10px;
  border-bottom: 1px solid var(--line);
  color: var(--fg-muted);
}
#viewer .v-hex-meta b { color: var(--fg); font-weight: 600; }
#viewer .v-hex pre {
  margin: 0;
  font-family: var(--font-mono);
  font-size: 12px;
  line-height: 1.55;
  color: var(--fg-2);
  white-space: pre;
  overflow-x: auto;
}
#viewer .v-hex pre .off { color: var(--fg-muted); }
#viewer .v-hex pre .asc { color: var(--accent); }

/* ---------- EPUB reader ---------- */
#viewer .v-epub {
  background: var(--bg-canvas);
}
#viewer .v-epub-toolbar {
  position: absolute;
  top: 0; left: 0; right: 0;
  height: 44px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0 16px;
  background: var(--bg-card);
  border-bottom: 1px solid var(--line);
  font-size: 13px;
  color: var(--fg-2);
}
#viewer .v-epub-title { font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; margin-right: 16px; }
#viewer .v-epub-nav   { display: flex; gap: 6px; flex-shrink: 0; }
#viewer .v-epub-nav .btn-secondary { padding: 5px 12px; font-size: 12px; }
#viewer .v-epub-reader {
  position: absolute;
  top: 44px; left: 0; right: 0; bottom: 0;
  overflow: hidden;
  background: var(--bg-card);
}

/* ============================== Graph View ============================== */
.v-graph {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  background: var(--bg-canvas);
}
.v-graph-head {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 8px 14px;
  border-bottom: 1px solid var(--line);
  background: var(--bg-card);
}
.v-graph-title { font-weight: 600; font-size: 13px; color: var(--fg); }
.v-graph-crumbs {
  font-weight: 600;
  font-size: 13px;
  color: var(--fg);
  display: flex;
  align-items: center;
  gap: 6px;
  flex-wrap: wrap;
  min-width: 0;
}
.v-graph-crumb {
  cursor: pointer;
  color: var(--accent);
  text-decoration: none;
}
.v-graph-crumb:hover { text-decoration: underline; }
.v-graph-crumb.is-current { cursor: default; color: var(--fg); }
.v-graph-crumb.is-current:hover { text-decoration: none; }
.v-graph-sep { color: var(--fg-muted); font-weight: normal; }
.v-graph-stats { font-size: 12px; color: var(--fg-muted); }
.v-graph-depth {
  margin-left: auto;
  font-size: 12px;
  color: var(--fg-muted);
  display: flex;
  align-items: center;
  gap: 6px;
}
.v-graph-conn {
  font-size: 12px;
  color: var(--fg-muted);
  display: flex;
  align-items: center;
  gap: 4px;
  cursor: pointer;
  user-select: none;
}
.v-graph-conn input { margin: 0; }
.v-graph-depth-sel {
  font: inherit;
  font-size: 12px;
  padding: 3px 6px;
  border: 1px solid var(--line-strong);
  border-radius: var(--r-sm);
  background: var(--bg-canvas);
  color: var(--fg-2);
  cursor: pointer;
}
.v-graph-reset {
  font: inherit;
  font-size: 12px;
  padding: 4px 10px;
  background: var(--bg-canvas);
  border: 1px solid var(--line-strong);
  border-radius: var(--r-sm);
  color: var(--fg-2);
  cursor: pointer;
}
.v-graph-reset:hover { background: var(--accent-soft); color: var(--accent-hover); border-color: var(--accent-dark); }
.v-graph-canvas-wrap {
  position: relative;
  flex: 1;
  overflow: hidden;
  cursor: grab;
}
.v-graph-canvas-wrap:active { cursor: grabbing; }
.v-graph-canvas-wrap canvas {
  display: block;
  width: 100%;
  height: 100%;
}
.v-graph-tooltip {
  position: absolute;
  pointer-events: none;
  background: var(--bg-sidebar);
  color: var(--fg-on-dark);
  padding: 6px 10px;
  border-radius: var(--r-sm);
  font-size: 12px;
  max-width: 260px;
  box-shadow: var(--shadow-md);
  z-index: 10;
}
.v-graph-tooltip .tip-sub { color: var(--fg-on-dark-2); font-size: 11px; margin-top: 2px; word-break: break-all; }
.v-graph-tooltip { max-width: 380px; }
.v-graph-tooltip .tip-snips {
  margin-top: 6px;
  padding-top: 6px;
  border-top: 1px solid rgba(255,255,255,.08);
  display: flex;
  flex-direction: column;
  gap: 4px;
}
.v-graph-tooltip .tip-snip {
  font-size: 11px;
  color: var(--fg-on-dark-2);
  line-height: 1.4;
  word-break: break-word;
  display: flex;
  gap: 6px;
}
.v-graph-tooltip .tip-ln {
  color: var(--fg-on-dark-3);
  font-family: ui-monospace, Menlo, Consolas, monospace;
  flex-shrink: 0;
}
.v-graph-tooltip .tip-text { display: inline-block; }
.v-graph-tooltip .tip-snip mark {
  background: var(--accent);
  color: white;
  padding: 0 2px;
  border-radius: 2px;
}
.v-graph-tooltip .tip-more { color: var(--fg-on-dark-3); font-style: italic; }

/* ============================== Context Menu ============================== */
.ctx {
  position: fixed;
  z-index: 1000;
  background: var(--bg-card);
  border: 1px solid var(--line);
  border-radius: var(--r);
  box-shadow: var(--shadow-lg);
  padding: 5px;
  min-width: 192px;
  font-size: 13px;
  animation: ctx-in 120ms var(--ease);
}
@keyframes ctx-in {
  from { opacity: 0; transform: translateY(-3px) scale(.98); }
  to   { opacity: 1; transform: translateY(0)   scale(1); }
}
.ctx button {
  display: block;
  width: 100%;
  text-align: left;
  background: transparent;
  border: 0;
  padding: 7px 12px;
  cursor: pointer;
  border-radius: var(--r-xs);
  color: var(--fg);
  font-size: 13px;
  font-family: inherit;
  transition: background var(--t-fast);
}
.ctx button:hover { background: var(--bg-canvas); }
.ctx button:disabled { opacity: .4; cursor: default; }
.ctx button:disabled:hover { background: transparent; }
.ctx button.danger { color: var(--danger); }
.ctx button.danger:hover { background: #fef2f2; }
.ctx .sep { height: 1px; background: var(--line); margin: 4px 4px; }

/* ============================== Modal ============================== */
.overlay {
  position: fixed;
  inset: 0;
  background: rgba(15, 15, 17, .42);
  backdrop-filter: blur(4px);
  -webkit-backdrop-filter: blur(4px);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 2000;
  animation: overlay-in 160ms var(--ease);
}
.overlay[hidden] { display: none; }
@keyframes overlay-in { from { opacity: 0; } to { opacity: 1; } }

.modal {
  background: var(--bg-card);
  border-radius: var(--r);
  padding: 22px 24px 20px;
  width: 400px;
  max-width: calc(100vw - 32px);
  box-shadow: var(--shadow-lg);
  animation: modal-in 200ms var(--ease);
}
@keyframes modal-in {
  from { opacity: 0; transform: translateY(8px) scale(.98); }
  to   { opacity: 1; transform: translateY(0)   scale(1); }
}
.modal-title { font-weight: 600; margin-bottom: 12px; font-size: 14px; }

/* Link dialog: stacks fields vertically, includes a "new tab" checkbox. */
.link-modal { width: 460px; }
.link-modal .link-modal-field {
  display: flex;
  flex-direction: column;
  gap: 4px;
  margin-bottom: 10px;
}
.link-modal .link-modal-label {
  font-size: 11px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: .04em;
  color: var(--fg-muted);
}
.link-modal-check {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 13px;
  color: var(--fg-2);
  margin: 6px 0 10px;
  cursor: pointer;
  user-select: none;
}
.link-modal-check input[type="checkbox"] { margin: 0; }
.modal-input {
  width: 100%;
  padding: 9px 12px;
  border: 1px solid var(--line-strong);
  border-radius: var(--r-sm);
  font-size: 14px;
  font-family: var(--font-ui);
  color: var(--fg);
  background: var(--bg-canvas);
  outline: none;
  transition: border-color var(--t-fast), background var(--t-fast), box-shadow var(--t-fast);
}
.modal-input:focus {
  border-color: var(--accent);
  background: var(--bg-card);
  box-shadow: 0 0 0 3px rgba(99,102,241,.15);
}
.modal-msg { font-size: 12px; color: var(--fg-muted); margin-top: 10px; min-height: 1em; }
.modal-msg.error { color: var(--danger); }
.modal-actions { display: flex; justify-content: flex-end; gap: 8px; margin-top: 16px; }

.btn-primary, .btn-secondary {
  border: 1px solid transparent;
  border-radius: var(--r-sm);
  padding: 7px 16px;
  font-size: 13px;
  font-family: inherit;
  font-weight: 500;
  cursor: pointer;
  transition: background var(--t-fast), border-color var(--t-fast), color var(--t-fast), box-shadow var(--t-fast);
}
.btn-primary {
  background: var(--accent);
  color: white;
  box-shadow: 0 1px 2px rgba(99,102,241,.3), inset 0 1px 0 rgba(255,255,255,.16);
}
.btn-primary:hover { background: var(--accent-hover); }
.btn-primary:active { transform: translateY(.5px); }

.btn-secondary {
  background: var(--bg-card);
  border-color: var(--line-strong);
  color: var(--fg-2);
}
.btn-secondary:hover { background: var(--bg-canvas); border-color: var(--fg-muted); color: var(--fg); }

/* ============================== Sidebar drawer ============================== */
/* Hamburger lives in the topbar, hidden on desktop. Backdrop is the dark
   overlay shown behind the sidebar drawer on mobile. */
#sidebar-toggle {
  display: none;
  background: transparent;
  border: 0;
  width: 36px;
  height: 36px;
  font-size: 22px;
  line-height: 1;
  color: var(--fg-2);
  border-radius: var(--r-xs);
  cursor: pointer;
  margin-right: 4px;
  flex-shrink: 0;
}
#sidebar-toggle:hover { background: var(--accent-soft); color: var(--accent); }
#sidebar-toggle:active { background: var(--accent-dark); }

#sidebar-backdrop {
  position: fixed;
  inset: 0;
  background: rgba(15, 15, 17, .55);
  z-index: 19;
  opacity: 0;
  transition: opacity var(--t-base) var(--ease);
  pointer-events: none;
}
#sidebar-backdrop[hidden] { display: none; }
body.sidebar-open #sidebar-backdrop {
  opacity: 1;
  pointer-events: auto;
}

/* ============================== Mobile (≤ 768px) ============================== */
@media (max-width: 768px) {
  body { font-size: 15px; }

  /* Hamburger visible on mobile, dim until pressed. Hide reload-btn (sidebar
     header has its own that the user reaches via the drawer). */
  #sidebar-toggle { display: inline-flex; align-items: center; justify-content: center; }

  /* Sidebar becomes an off-canvas drawer. transform is GPU-accelerated, so
     the slide stays smooth even with a long file tree mounted. */
  #sidebar {
    position: fixed;
    top: 0; left: 0; bottom: 0;
    width: min(82vw, 320px);
    z-index: 20;
    transform: translateX(-100%);
    transition: transform var(--t-base) var(--ease);
    box-shadow: var(--shadow-lg);
  }
  body.sidebar-open #sidebar { transform: translateX(0); }

  /* Body uses the full width — sidebar is overlaid, not pushed. */
  body { display: block; }
  #main { width: 100%; height: 100vh; height: 100dvh; }

  /* Topbar: tighter padding, smaller breadcrumb, hamburger gets the room. */
  #topbar {
    padding: 0 8px 0 6px;
    height: 50px;
    gap: 6px;
  }
  #breadcrumb {
    font-size: 14px;
    flex: 1;
    min-width: 0;
  }
  #topbar-right { gap: 6px; }
  #mode-toggle {
    font-size: 12px;
    padding: 4px 8px;
  }
  #status { font-size: 11px; }

  /* Tab strip: scroll horizontally instead of squashing tabs. */
  #tab-strip { overflow: hidden; }
  #tabs-list {
    overflow-x: auto;
    overflow-y: hidden;
    scrollbar-width: none;
    -webkit-overflow-scrolling: touch;
  }
  #tabs-list::-webkit-scrollbar { display: none; }
  #tab-add {
    flex-shrink: 0;
    min-width: 44px;
    min-height: 44px;
  }

  /* Format toolbar: same horizontal-scroll trick. Buttons get bigger touch
     targets so fat fingers actually hit one. */
  #format-toolbar {
    overflow-x: auto;
    overflow-y: hidden;
    flex-wrap: nowrap;
    scrollbar-width: none;
    -webkit-overflow-scrolling: touch;
    padding: 6px 8px;
    gap: 4px;
  }
  #format-toolbar::-webkit-scrollbar { display: none; }
  .ft-group { flex-shrink: 0; }
  .ft-btn {
    min-width: 38px;
    min-height: 38px;
  }
  .ft-select {
    min-height: 38px;
    font-size: 13px;
  }

  /* Settings overlay full-screen — the desktop centered card is too small
     for portrait screens, and the failures list scrolls forever. */
  #settings-overlay.overlay { padding: 0; align-items: stretch; }
  .settings-panel {
    max-width: none;
    width: 100%;
    height: 100%;
    height: 100dvh;
    border-radius: 0;
    max-height: none;
  }

  /* Modal sits a bit lower so the on-screen keyboard doesn't push it off. */
  #modal-overlay.overlay { align-items: flex-start; padding-top: 18vh; }
  .modal { width: calc(100vw - 24px); max-width: 460px; }

  /* Context menu wider so finger-tap-targets are reasonable. */
  #ctx-menu { min-width: 220px; font-size: 14px; }
  #ctx-menu .ctx-item { padding: 12px 14px; }

  /* Hover-preview is a desktop-only tooltip — no place for it on touch. */
  #hover-preview { display: none !important; }

  /* Tree rows: bigger tap targets, closer to native list rows. */
  .tree-row {
    min-height: 36px;
    padding-top: 6px;
    padding-bottom: 6px;
  }

  /* Empty hint reads better on narrow screens. */
  #empty-hint { padding: 24px 18px; }
  #empty-hint .big { font-size: 16px; }
  #empty-hint .small { font-size: 13px; }
}

/* ============================== Tiny phones (≤ 380px) ============================== */
@media (max-width: 380px) {
  #breadcrumb { font-size: 13px; }
  #mode-toggle { font-size: 11px; padding: 3px 6px; }
  #status { display: none; }   /* re-appears as part of the sync UI when it matters */
}

/* ===== Touch: keep the format toolbar on ONE row, page through tools ===== */
/* Instead of wrapping to two rows (landscape) or relying on side-scroll, the
   toolbar shows one "page" of tool groups at a time; #ft-page-switch cycles
   pages. Placed after the ≤768px block so it wins the overflow rules. */
@media (pointer: coarse) {
  #format-toolbar {
    flex-wrap: nowrap;
    overflow-x: auto;          /* safety net so nothing is ever clipped */
    overflow-y: hidden;
  }
  #format-toolbar .ft-sep { display: none; }
  #format-toolbar .ft-group.ft-page-off { display: none; }
  #ft-page-switch {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
    position: sticky;          /* stays reachable even if a dense page scrolls */
    left: 0;
    z-index: 1;
    background: var(--bg-card);
  }
}

/* =================================================================
   Full-text search (sidebar)
   ================================================================= */
#sidebar-search {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 4px;
  padding: 6px 10px 4px;
  border-bottom: 1px solid rgba(255,255,255,.05);
}
#search-input {
  flex: 1 1 120px;
  min-width: 120px;
  padding: 6px 10px;
  background: rgba(255,255,255,.04);
  color: var(--fg-on-dark);
  border: 1px solid rgba(255,255,255,.08);
  border-radius: 6px;
  font: inherit;
  font-size: 13px;
  outline: none;
  transition: border-color .12s;
}
#search-input::placeholder { color: var(--fg-on-dark-3); }
#search-input:focus {
  border-color: var(--accent);
  background: rgba(255,255,255,.06);
}
#search-clear {
  background: transparent;
  border: 0;
  color: var(--fg-on-dark-2);
  font-size: 18px;
  cursor: pointer;
  padding: 0 6px;
  line-height: 1;
}
#search-clear:hover { color: var(--fg-on-dark); }

/* AND-search chips: pinned terms in front of the input. Enter promotes the
   typed text into a chip; × removes one; Backspace on empty input pops the
   rightmost. Visually a small blue pill — distinguishes pinned filters from
   the live-typed term in the input. */
.search-chip {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  max-width: 100%;
  padding: 2px 4px 2px 8px;
  background: rgba(59, 130, 246, .25);
  color: var(--fg-on-dark);
  border: 1px solid rgba(96, 165, 250, .55);
  border-radius: 999px;
  font-size: 12px;
  line-height: 1.3;
  white-space: nowrap;
}
.search-chip .sc-text {
  overflow: hidden;
  text-overflow: ellipsis;
  max-width: 140px;
}
.search-chip .sc-remove {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 16px;
  height: 16px;
  padding: 0;
  margin: 0;
  background: transparent;
  border: 0;
  color: var(--fg-on-dark-2);
  font-size: 14px;
  line-height: 1;
  cursor: pointer;
  border-radius: 50%;
}
.search-chip .sc-remove:hover {
  background: rgba(255, 255, 255, .12);
  color: var(--fg-on-dark);
}

#search-results {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  padding: 4px 0 8px;
  color: var(--fg-on-dark-2);
}
#search-results::-webkit-scrollbar { width: 8px; }
#search-results::-webkit-scrollbar-thumb { background: rgba(255,255,255,.08); border-radius: 4px; }
#search-results::-webkit-scrollbar-thumb:hover { background: rgba(255,255,255,.14); }

.search-head {
  padding: 6px 12px;
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: .06em;
  color: var(--fg-on-dark-3);
  border-bottom: 1px solid rgba(255,255,255,.04);
  margin-bottom: 4px;
}
.search-file { margin: 0 4px 8px; }
.search-folders { margin: 0 4px 8px; border-bottom: 1px solid rgba(255,255,255,.04); padding-bottom: 6px; }
.search-folder {
  display: flex;
  align-items: baseline;
  gap: 8px;
  padding: 4px 8px;
  border-radius: 6px;
  color: var(--fg-on-dark);
  font-size: 13px;
  cursor: pointer;
}
.search-folder:hover { background: rgba(255,255,255,.06); }
/* Highlighter-pen marker used by the in-content search highlight (mark.js). */
mark.s-mark {
  background: #fde047;
  color: #422006;
  padding: 0 1px;
  border-radius: 2px;
  box-shadow: 0 0 0 1px rgba(202, 138, 4, 0.35);
}
.search-folder::before {
  content: '▸';
  color: var(--accent);
  font-size: 11px;
  margin-right: 2px;
}
.sf-header {
  display: flex;
  align-items: baseline;
  gap: 8px;
  padding: 4px 8px;
  border-radius: 6px;
  cursor: pointer;
  color: var(--fg-on-dark);
  font-size: 13px;
}
.sf-header:hover { background: rgba(255,255,255,.06); }
.sf-name { font-weight: 500; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.sf-dir  { font-size: 11px; color: var(--fg-on-dark-3); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.sf-line {
  display: flex;
  align-items: baseline;
  gap: 8px;
  padding: 2px 8px 2px 16px;
  font-family: ui-monospace, "SF Mono", Menlo, Consolas, monospace;
  font-size: 11px;
  color: var(--fg-on-dark-2);
  cursor: pointer;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.sf-line:hover { background: rgba(255,255,255,.04); color: var(--fg-on-dark); }
.sf-ln {
  display: inline-block;
  min-width: 28px;
  text-align: right;
  color: var(--fg-on-dark-3);
  flex-shrink: 0;
}
.sf-text {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.sf-text mark {
  background: var(--accent);
  color: white;
  padding: 0 2px;
  border-radius: 2px;
}
.search-loading, .search-empty, .search-err {
  padding: 24px 16px;
  text-align: center;
  font-size: 12px;
  color: var(--fg-on-dark-3);
}
.search-err { color: var(--danger); }

/* ---------- Share modal ---------- */
.share-panel {
  background: var(--bg-card);
  color: var(--fg);
  border-radius: 12px;
  width: min(620px, 92vw);
  max-height: 90vh;
  overflow: auto;
  box-shadow: 0 18px 48px rgba(0,0,0,.35);
  padding: 0;
}
.share-head {
  display: flex; align-items: center; justify-content: space-between;
  padding: 18px 22px 4px;
}
.share-title { font-size: 17px; font-weight: 600; }
.share-target {
  margin: 0 22px 8px;
  font-size: 13px; color: var(--fg-muted);
  word-break: break-all;
}
.share-stage { padding: 8px 22px 18px; }
#share-overlay[data-stage="create"] .share-stage-done { display: none; }
#share-overlay[data-stage="done"]   .share-stage-create { display: none; }

.share-tiles {
  display: grid; grid-template-columns: 1fr 1fr 1fr;
  gap: 10px; margin: 8px 0 16px;
}
@media (max-width: 540px) { .share-tiles { grid-template-columns: 1fr; } }
.share-tile {
  background: var(--bg-canvas);
  border: 2px solid transparent;
  border-radius: 10px;
  padding: 14px 12px;
  cursor: pointer;
  text-align: center;
  transition: border-color .12s, background .12s;
  display: flex; flex-direction: column; align-items: center; gap: 4px;
}
.share-tile:hover { background: #efeee9; }
.share-tile.selected {
  border-color: var(--accent);
  background: var(--accent-soft);
}
.share-tile-ico  { font-size: 26px; line-height: 1; }
.share-tile-name { font-weight: 600; font-size: 14px; }
.share-tile-desc { font-size: 12px; color: var(--fg-muted); line-height: 1.3; }

.share-form { display: flex; flex-direction: column; gap: 10px; }
.share-row {
  display: flex; flex-direction: column; gap: 4px;
}
.share-label  { font-size: 13px; color: var(--fg-2); font-weight: 500; }
.share-hint   { font-weight: 400; color: var(--fg-muted); font-size: 12px; }
.share-form input[type=text],
.share-form input[type=password],
.share-form input[type=number],
.share-form select {
  padding: 8px 10px; font-size: 14px;
  background: white; border: 1px solid #e5e5ea; color: var(--fg);
  border-radius: 6px; outline: none;
}
.share-form input:focus, .share-form select:focus { border-color: var(--accent); }
.share-err { color: var(--danger); font-size: 13px; min-height: 18px; }

.share-actions {
  display: flex; justify-content: flex-end; gap: 8px;
  margin-top: 16px;
}

.share-url-row {
  display: flex; gap: 8px; margin: 10px 0;
}
.share-url-row input {
  flex: 1; padding: 9px 10px; font-size: 13px;
  border: 1px solid #e5e5ea; border-radius: 6px;
  background: var(--bg-canvas); font-family: ui-monospace, SFMono-Regular, monospace;
}
.share-meta {
  font-size: 12px; color: var(--fg-muted);
  line-height: 1.5; padding: 8px 0 0;
}
.share-meta b { color: var(--fg-2); font-weight: 600; }

/* ---------- Shares list in settings ---------- */
.shares-list { display: flex; flex-direction: column; gap: 10px; margin-top: 8px; }
.shares-loading, .shares-empty {
  color: var(--fg-on-dark-2); font-size: 13px; padding: 12px 0;
}
.shares-list .share-row {
  /* override the modal form's column .share-row to a horizontal card */
  flex-direction: row;
  align-items: flex-start; justify-content: space-between; gap: 10px;
  padding: 12px;
  background: rgba(255,255,255,.04);
  border-radius: 8px;
  border: 1px solid rgba(255,255,255,.06);
}
.shares-list .share-row-dead { opacity: .55; }
.share-row-main { flex: 1; min-width: 0; }
.share-row-path {
  font-family: ui-monospace, SFMono-Regular, monospace;
  font-size: 13px; color: var(--fg-on-dark);
  word-break: break-all; margin-bottom: 4px;
}
.share-row-meta { font-size: 12px; color: var(--fg-on-dark-2); margin-bottom: 6px; }
.share-row-meta b { color: var(--fg-on-dark); font-weight: 600; }
.share-row-pills { display: flex; gap: 6px; flex-wrap: wrap; margin-bottom: 8px; }
.share-pill {
  display: inline-block;
  padding: 2px 8px;
  border-radius: 999px;
  font-size: 11px;
  background: rgba(255,255,255,.07);
  color: var(--fg-on-dark);
}
.share-pill-rw   { background: #4f46e5; color: white; }
.share-pill-ro   { background: #2563eb; color: white; }
.share-pill-dl   { background: #16a34a; color: white; }
.share-pill-warn { background: #b45309; color: white; }
.share-row-url { display: flex; gap: 6px; align-items: center; }
.share-row-url-input {
  flex: 1;
  font-family: ui-monospace, SFMono-Regular, monospace;
  font-size: 11px;
  padding: 5px 8px;
  background: rgba(0,0,0,.3);
  border: 1px solid rgba(255,255,255,.08);
  color: var(--fg-on-dark);
  border-radius: 4px;
  min-width: 0;
}
.share-row-copy, .share-row-revoke { white-space: nowrap; font-size: 12px; padding: 5px 10px; }
.share-row-actions { display: flex; flex-direction: column; gap: 6px; }

/* ---------- Share session styling ---------- */
/* Only read-only shares strip the editing affordances. RW share recipients
   keep the format toolbar, tab-add, and mode-toggle so they can edit canvas
   notes and join the OnlyOffice collab editor. */
body.readonly #format-toolbar,
body.readonly #tab-add,
body.readonly #settings-btn,
body.readonly #canvas-view-toggle,
body.readonly #mode-toggle { display: none !important; }
body.share-mode .brand::after {
  content: ' · geteilt';
  font-size: 11px;
  color: var(--fg-on-dark-2);
  font-weight: normal;
}

/* ---------- Wiki-links ---------- */
a.wikilink {
  color: var(--accent);
  text-decoration: none;
  border-bottom: 1px dashed var(--accent);
  padding: 0 2px;
  cursor: pointer;
}
a.wikilink:hover { background: var(--accent-soft); border-bottom-style: solid; }
/* dark sidebar variant */
#sidebar a.wikilink { color: var(--accent-dark); border-bottom-color: var(--accent-dark); }

/* ---------- Wiki-link autocomplete ---------- */
.wikilink-ac {
  position: fixed;
  z-index: 1100;
  background: var(--bg-card);
  border: 1px solid var(--line);
  border-radius: var(--r);
  box-shadow: var(--shadow-lg);
  padding: 4px;
  width: 340px;
  max-height: 280px;
  overflow-y: auto;
  font-size: 13px;
  animation: ctx-in 100ms var(--ease);
}
.wikilink-ac-item {
  display: flex;
  align-items: baseline;
  gap: 6px;
  padding: 6px 10px;
  border-radius: var(--r-xs);
  cursor: pointer;
  overflow: hidden;
}
.wikilink-ac-item .wal-name {
  color: var(--fg);
  font-weight: 500;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  flex-shrink: 0;
  max-width: 60%;
}
.wikilink-ac-item .wal-dir {
  color: var(--fg-muted);
  font-size: 11px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  direction: rtl;
  flex: 1;
  min-width: 0;
}
.wikilink-ac-item.selected,
.wikilink-ac-item:hover { background: var(--accent-soft); }
.wikilink-ac-item.selected .wal-name { color: var(--accent-hover); }
.wikilink-ac-empty {
  padding: 10px 12px;
  color: var(--fg-muted);
  font-style: italic;
  text-align: center;
}

/* ---------- Backlinks panel ---------- */
#backlinks-panel {
  border-top: 1px solid rgba(255,255,255,.06);
  max-height: 35vh;
  overflow-y: auto;
  padding: 6px 8px 8px;
}
#backlinks-panel .bl-head {
  display: flex; align-items: center; gap: 6px;
  font-size: 11px; text-transform: uppercase;
  letter-spacing: .04em;
  color: var(--fg-on-dark-2);
  padding: 6px 4px 4px;
}
#backlinks-panel .bl-title { font-weight: 600; }
#backlinks-panel .bl-count { color: var(--fg-on-dark-3); }
#backlinks-panel .bl-empty { color: var(--fg-on-dark-3); font-size: 12px; padding: 4px; }
#backlinks-panel .bl-row {
  display: flex; flex-direction: column; align-items: stretch;
  width: 100%;
  background: transparent;
  border: none;
  color: var(--fg-on-dark);
  padding: 4px 6px;
  text-align: left;
  cursor: pointer;
  border-radius: 4px;
  font-size: 12px;
  line-height: 1.3;
  gap: 1px;
}
#backlinks-panel .bl-row:hover { background: rgba(255,255,255,.05); }
#backlinks-panel .bl-name   { color: var(--fg-on-dark); font-weight: 500; }
#backlinks-panel .bl-folder { color: var(--fg-on-dark-3); font-size: 11px; font-family: ui-monospace, monospace; }
#backlinks-panel .bl-row-out { color: var(--accent-dark); }
#backlinks-panel .bl-outgoing { margin-top: 8px; }

/* ---------- Canvas: search-hit flash ---------- */
.box.search-hit-flash {
  animation: hit-flash 1.7s ease-out;
  outline: 2px solid var(--accent);
  outline-offset: 3px;
}
@keyframes hit-flash {
  0%   { box-shadow: 0 0 0 0 var(--accent); }
  20%  { box-shadow: 0 0 0 12px rgba(99,102,241,.35); }
  100% { box-shadow: 0 0 0 0 rgba(99,102,241,0); }
}

/* =================================================================
   Intelligent (LLM) search — modal + result section
   ================================================================= */
#search-ai-btn {
  background: transparent;
  border: 0;
  color: var(--fg-on-dark-2);
  font-size: 14px;
  cursor: pointer;
  padding: 0 6px;
  line-height: 1;
}
#search-ai-btn:hover { color: var(--fg-on-dark); }

.ai-search-panel {
  background: var(--bg-card);
  border-radius: var(--r);
  padding: 18px 20px 16px;
  width: 520px;
  max-width: calc(100vw - 32px);
  box-shadow: var(--shadow-lg);
  animation: modal-in 200ms var(--ease);
}
.ai-search-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 10px;
}
.ai-search-title { font-weight: 600; font-size: 14px; }
.ai-search-hint { font-size: 12px; color: var(--fg-muted); margin: 0 0 10px; line-height: 1.5; }
#ai-search-input {
  width: 100%;
  padding: 10px 12px;
  border: 1px solid var(--line-strong);
  border-radius: var(--r-sm);
  font-size: 13px;
  font-family: var(--font-ui);
  color: var(--fg);
  background: var(--bg-canvas);
  outline: none;
  resize: vertical;
  min-height: 64px;
  transition: border-color var(--t-fast), background var(--t-fast), box-shadow var(--t-fast);
}
#ai-search-input:focus {
  border-color: var(--accent);
  background: var(--bg-card);
  box-shadow: 0 0 0 3px rgba(99,102,241,.15);
}
.ai-search-actions { display: flex; justify-content: flex-end; gap: 8px; margin-top: 12px; }
.ai-search-status {
  margin-top: 12px;
  font-size: 12px;
  color: var(--fg-muted);
  padding: 8px 10px;
  background: rgba(99,102,241,.08);
  border-left: 3px solid var(--accent);
  border-radius: var(--r-sm);
}
.ai-search-status a { color: var(--accent); text-decoration: underline; cursor: pointer; }
.ai-search-err {
  margin-top: 10px;
  padding: 8px 10px;
  background: rgba(220, 38, 38, .12);
  border-left: 3px solid #dc2626;
  color: var(--fg);
  border-radius: var(--r-sm);
  font-size: 12px;
}

/* Results section rendered inside #search-results when an AI query resolves. */
.ai-results {
  margin: 0 4px 12px;
  padding: 6px 4px 4px;
  border-radius: 8px;
  background: rgba(99,102,241,.06);
  border: 1px solid rgba(99,102,241,.18);
}
.ai-results-head {
  padding: 6px 10px 4px;
  display: flex;
  flex-direction: column;
  gap: 2px;
}
.ai-results-title {
  font-size: 12px;
  color: var(--fg-on-dark);
  font-weight: 500;
}
.ai-results-title i {
  color: var(--accent);
  font-style: normal;
  font-weight: 400;
}
.ai-results-meta {
  font-size: 10px;
  text-transform: uppercase;
  letter-spacing: .05em;
  color: var(--fg-on-dark-3);
}
.ai-results-summary {
  margin: 4px 8px 8px;
  padding: 8px 10px;
  background: rgba(255,255,255,.04);
  border-radius: 6px;
  font-size: 12px;
  color: var(--fg-on-dark);
  line-height: 1.5;
  white-space: pre-wrap;
}
.ai-results-empty {
  padding: 10px;
  color: var(--fg-on-dark-3);
  font-size: 12px;
  text-align: center;
}
.ai-result {
  margin: 4px 4px;
  padding: 6px 8px;
  border-radius: 6px;
  cursor: pointer;
  transition: background var(--t-fast);
}
.ai-result:hover { background: rgba(255,255,255,.06); }
.ai-result-head {
  display: flex;
  align-items: baseline;
  gap: 8px;
}
.ai-result-name {
  font-size: 13px;
  font-weight: 500;
  color: var(--fg-on-dark);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.ai-result-dir {
  font-size: 11px;
  color: var(--fg-on-dark-3);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.ai-result-reason {
  margin-top: 2px;
  font-size: 11px;
  color: var(--fg-on-dark-2);
  line-height: 1.4;
}
.ai-result-snippet {
  margin-top: 4px;
  padding: 4px 6px;
  background: rgba(0,0,0,.18);
  border-radius: 4px;
  font-family: ui-monospace, "SF Mono", Menlo, Consolas, monospace;
  font-size: 11px;
  color: var(--fg-on-dark-2);
  line-height: 1.4;
  white-space: pre-wrap;
  max-height: 60px;
  overflow: hidden;
}

/* AI search history — rendered inside the modal under the input. */
#ai-search-history-wrap {
  margin-top: 14px;
  padding-top: 10px;
  border-top: 1px solid var(--line);
}
.ai-history-head {
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: .06em;
  color: var(--fg-muted);
  margin-bottom: 6px;
}
.ai-history-list {
  max-height: 220px;
  overflow-y: auto;
  display: flex;
  flex-direction: column;
  gap: 2px;
}
.ai-history-item {
  display: grid;
  grid-template-columns: 1fr auto auto;
  align-items: center;
  gap: 8px;
  padding: 6px 8px;
  border-radius: 6px;
  cursor: pointer;
  transition: background var(--t-fast);
}
.ai-history-item:hover { background: var(--bg-canvas); }
.ai-history-q {
  font-size: 12px;
  color: var(--fg);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.ai-history-meta {
  font-size: 10px;
  color: var(--fg-muted);
  white-space: nowrap;
}
.ai-history-del {
  width: 18px;
  height: 18px;
  padding: 0;
  background: transparent;
  border: 0;
  color: var(--fg-muted);
  font-size: 14px;
  line-height: 1;
  border-radius: 50%;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  justify-content: center;
}
.ai-history-del:hover {
  background: rgba(220, 38, 38, .15);
  color: #dc2626;
}

/* =================================================================
   Tags — per-file/-folder labels with autocomplete
   ================================================================= */
.tree-row { position: relative; }
.tag-badge {
  margin-left: auto;
  margin-right: 4px;
  padding: 1px 6px;
  font-size: 10px;
  line-height: 1.4;
  color: var(--fg-on-dark-2);
  background: rgba(99, 102, 241, .18);
  border: 1px solid rgba(129, 140, 248, .35);
  border-radius: 999px;
  white-space: nowrap;
  pointer-events: none;
}

.tags-panel {
  background: var(--bg-card);
  border-radius: var(--r);
  padding: 18px 20px 16px;
  width: 460px;
  max-width: calc(100vw - 32px);
  box-shadow: var(--shadow-lg);
  animation: modal-in 200ms var(--ease);
}
.tags-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 8px;
}
.tags-title { font-weight: 600; font-size: 14px; }
.tags-target {
  font-size: 12px;
  color: var(--fg-muted);
  padding: 6px 8px;
  background: var(--bg-canvas);
  border-radius: var(--r-sm);
  word-break: break-all;
  margin-bottom: 12px;
}
.tags-input-wrap { position: relative; }
.tags-chips {
  display: flex;
  flex-wrap: wrap;
  gap: 4px;
  margin-bottom: 4px;
  min-height: 4px;
}
.tag-chip {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 2px 4px 2px 8px;
  background: rgba(99, 102, 241, .22);
  color: var(--fg);
  border: 1px solid rgba(99, 102, 241, .5);
  border-radius: 999px;
  font-size: 12px;
  line-height: 1.3;
}
.tag-chip-text { max-width: 180px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.tag-chip-remove {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 16px;
  height: 16px;
  padding: 0;
  background: transparent;
  border: 0;
  color: var(--fg-muted);
  font-size: 14px;
  line-height: 1;
  border-radius: 50%;
  cursor: pointer;
}
.tag-chip-remove:hover {
  background: rgba(220, 38, 38, .15);
  color: #dc2626;
}
#tags-input {
  width: 100%;
  padding: 8px 10px;
  border: 1px solid var(--line-strong);
  border-radius: var(--r-sm);
  font-size: 13px;
  font-family: var(--font-ui);
  color: var(--fg);
  background: var(--bg-canvas);
  outline: none;
  transition: border-color var(--t-fast), background var(--t-fast), box-shadow var(--t-fast);
}
#tags-input:focus {
  border-color: var(--accent);
  background: var(--bg-card);
  box-shadow: 0 0 0 3px rgba(99,102,241,.15);
}
.tags-suggest {
  position: absolute;
  left: 0;
  right: 0;
  top: 100%;
  margin-top: 4px;
  z-index: 10;
  max-height: 240px;
  overflow-y: auto;
  background: var(--bg-card);
  border: 1px solid var(--line-strong);
  border-radius: var(--r-sm);
  box-shadow: var(--shadow-lg);
}
.tag-suggest-row {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 6px 10px;
  cursor: pointer;
  font-size: 13px;
}
.tag-suggest-row:hover,
.tag-suggest-row.active { background: var(--bg-canvas); }
.tag-suggest-text { color: var(--fg); }
.tag-suggest-count {
  font-size: 10px;
  color: var(--fg-muted);
  background: rgba(0,0,0,.06);
  padding: 1px 6px;
  border-radius: 999px;
}
.tags-hint {
  margin-top: 6px;
  font-size: 11px;
  color: var(--fg-muted);
}
.tags-actions {
  display: flex;
  justify-content: flex-end;
  gap: 8px;
  margin-top: 14px;
}
.tags-err {
  margin-top: 10px;
  padding: 8px 10px;
  background: rgba(220,38,38,.12);
  border-left: 3px solid #dc2626;
  border-radius: var(--r-sm);
  font-size: 12px;
  color: var(--fg);
}

/* Top section in search results: items whose TAGS satisfy the AND filter.
   Rendered above the regular folder-/file-name hits because tags are an
   explicit curation signal. */
.search-tagged {
  margin: 0 4px 10px;
  padding-bottom: 6px;
  border-bottom: 1px solid rgba(255,255,255,.06);
}
.search-section-label {
  padding: 4px 8px;
  font-size: 10px;
  text-transform: uppercase;
  letter-spacing: .07em;
  color: var(--fg-on-dark-3);
}
.search-tagged-row {
  padding: 4px 8px;
  border-radius: 6px;
  cursor: pointer;
}
.search-tagged-row:hover { background: rgba(255,255,255,.06); }
.search-tagged-row .st-head {
  display: flex;
  align-items: baseline;
  gap: 6px;
}
.search-tagged-row .st-ico { font-size: 12px; }
.search-tagged-row .st-name {
  font-size: 13px;
  font-weight: 500;
  color: var(--fg-on-dark);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.search-tagged-row .st-dir {
  font-size: 11px;
  color: var(--fg-on-dark-3);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.search-tagged-row .st-tags {
  display: flex;
  flex-wrap: wrap;
  gap: 3px;
  margin-top: 3px;
  padding-left: 18px;
}
.search-tag-pill {
  font-size: 10px;
  line-height: 1.4;
  padding: 1px 6px;
  border-radius: 999px;
  background: rgba(99,102,241,.22);
  color: var(--fg-on-dark);
  border: 1px solid rgba(129,140,248,.4);
  white-space: nowrap;
}

/* ==================================================================
   Touch / mobile parity
   Pointer-event handlers in box/drag.js, box/resize.js, connections/
   drag.js, canvas/rubber-band.js drive the canvas on touch. CSS here
   stops the browser from hijacking the gesture (scroll/zoom) before
   the JS sees it, and lays out the new mobile-only UI controls
   (FAB, back/forward) the JS toggles in src/ui/mobile-tools.js.
   ================================================================== */

/* Anything draggable on the canvas must opt out of native pan/zoom so
   pointermove keeps firing instead of the browser scrolling/zooming. */
#canvas-surface, .box .handle, .box .resize, .box .resize-edge, .box .port {
  touch-action: none;
}
/* iOS Safari shows its own callout (text-select / "open in new tab") on
   long-press of draggable elements, which steals the gesture from our
   long-press → context-menu shim. Suppress it on the tree, pinned tiles,
   and box chrome. */
.tree-row, .pinned-tile, .box, .conn-label, #canvas-surface {
  -webkit-touch-callout: none;
  -webkit-tap-highlight-color: transparent;
}
.tree-row, .pinned-tile {
  -webkit-user-select: none;
  user-select: none;
}
/* The body of a text box stays scrollable when its content overflows,
   but pinch-zoom is disabled to keep the canvas zoom authoritative. */
.box .body { touch-action: pan-y; }
.box.editing .body { touch-action: auto; }

/* Generous touch targets for the small canvas affordances. The visual
   hit-area stays the same on desktop — only the invisible padding grows
   on coarse-pointer devices. */
@media (pointer: coarse) {
  /* Keep the visible dots/bars near their desktop size; grow only the
     invisible tap target via a transparent ::before so touch stays easy
     without the affordances looking oversized. */
  .box .port {
    width: 15px;
    height: 15px;
  }
  .box .port::before {
    content: "";
    position: absolute;
    inset: -8px;
  }
  .box .resize {
    width: 26px;
    height: 26px;
  }
  .box .resize-e { width: 5px; }
  .box .resize-s { height: 5px; }
  .box .resize-e::before {
    content: "";
    position: absolute;
    inset: -12px -11px;
  }
  .box .resize-s::before {
    content: "";
    position: absolute;
    inset: -11px -12px;
  }
  .box .handle {
    min-height: 22px;
  }
  /* Bigger tap target for the per-box delete chip. */
  .box .toolbar .del {
    width: 28px;
    height: 28px;
    font-size: 18px;
  }
}

/* Safe-area-inset support — keeps content clear of iPhone notch /
   home-indicator and Android gesture-bar. viewport-fit=cover in
   index.html is what enables env(safe-area-inset-*) values. */
#topbar {
  padding-top: env(safe-area-inset-top);
  padding-left: max(env(safe-area-inset-left), 6px);
  padding-right: max(env(safe-area-inset-right), 8px);
  box-sizing: content-box;
}
#sidebar {
  padding-top: env(safe-area-inset-top);
  padding-left: env(safe-area-inset-left);
}
#sidebar-footer {
  padding-bottom: max(env(safe-area-inset-bottom), 8px);
}

/* Mobile bottom toolbar (back/forward + FAB) — hidden on desktop. */
#mobile-tools {
  display: none;
  position: fixed;
  bottom: max(env(safe-area-inset-bottom), 12px);
  right: 14px;
  z-index: 18;
  flex-direction: column;
  gap: 10px;
  align-items: flex-end;
  pointer-events: none;
}
#mobile-tools > * { pointer-events: auto; }
.mobile-fab {
  width: 56px;
  height: 56px;
  border-radius: 50%;
  border: 0;
  background: var(--accent);
  color: #fff;
  font-size: 30px;
  line-height: 1;
  box-shadow: 0 6px 18px rgba(0,0,0,.35);
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
}
.mobile-fab:active { transform: scale(.96); }

/* Bottom-sheet action menu (opens from the FAB on mobile). */
.mobile-sheet-overlay {
  position: fixed;
  inset: 0;
  background: rgba(0,0,0,.5);
  z-index: 1000;
  display: flex;
  align-items: flex-end;
  justify-content: center;
  animation: mobile-sheet-fade .15s ease-out;
}
@keyframes mobile-sheet-fade { from { background: rgba(0,0,0,0); } to { background: rgba(0,0,0,.5); } }
.mobile-sheet {
  width: min(520px, 100%);
  background: var(--bg-card, var(--bg-elev));
  border-radius: 14px 14px 0 0;
  padding: 8px 8px max(env(safe-area-inset-bottom), 12px);
  display: flex;
  flex-direction: column;
  gap: 4px;
  animation: mobile-sheet-slide .2s ease-out;
}
@keyframes mobile-sheet-slide { from { transform: translateY(100%); } to { transform: translateY(0); } }
.mobile-sheet-folder {
  padding: 12px 16px 6px;
  font-size: 12px;
  color: var(--fg-muted);
  word-break: break-all;
}
.mobile-sheet-item {
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 14px 16px;
  border: 0;
  background: transparent;
  text-align: left;
  border-radius: 10px;
  color: var(--fg);
  font: inherit;
  cursor: pointer;
}
.mobile-sheet-item:active { background: var(--bg-canvas, var(--bg-elev)); }
.mobile-sheet-icon {
  flex: 0 0 auto;
  width: 36px;
  height: 36px;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 22px;
  background: var(--bg-canvas, var(--bg-elev));
  border-radius: 50%;
}
.mobile-sheet-text { display: flex; flex-direction: column; gap: 2px; }
.mobile-sheet-title { font-weight: 500; font-size: 15px; }
.mobile-sheet-sub   { font-size: 12px; color: var(--fg-muted); }
.mobile-sheet-cancel {
  margin-top: 8px;
  padding: 14px;
  border: 0;
  background: var(--bg-canvas, var(--bg-elev));
  border-radius: 10px;
  font: inherit;
  font-weight: 500;
  color: var(--fg);
  cursor: pointer;
}
.mobile-sheet-cancel:active { background: var(--line-strong, var(--border)); }

@media (max-width: 768px) {
  #mobile-tools { display: flex; }
  /* Doc-viewer paper has 64×80 padding on desktop — way too much on a
     phone. Halve it and let the column fill the viewport. */
  #viewer .v-doc-paper {
    padding: 18px 14px;
    max-width: none;
  }
  /* Modal sit-just-above-keyboard is already handled (see line 2727);
     also use dvh so iOS doesn't crop the bottom buttons when the on-
     screen keyboard appears. */
  .modal, .settings-panel, .share-panel, .ai-search-panel, .tags-panel,
  .share-pickup-panel {
    max-height: 100dvh;
  }
}
/* Hide mobile FAB when an overlay is active so it doesn't sit on top of
   modal buttons. */
body:has(.overlay:not([hidden])) #mobile-tools { display: none !important; }

/* ==================================================================
   Plain-text editor (viewers/text.js) — ruled-notebook page look for
   .txt and .md. Full-viewport white sheet, slim line-number gutter at
   the left edge, light ruled writing lines, floating Vorschau toggle.
   ================================================================== */
.v-text {
  position: relative;
  display: flex;
  flex-direction: column;
  width: 100%;
  height: 100%;
  background: #e9ecef;            /* "desk" surface around the paper */
  font-family: 'Iowan Old Style', 'Palatino Linotype', Palatino, Georgia, 'Times New Roman', serif;
  --rule-line-height: 32px;
  --rule-color: #dbe7f3;
  --gutter-w: 56px;
  --page-w:   820px;              /* total paper width incl. gutter */
}
.v-text-scroll {
  flex: 1;
  min-height: 0;
  overflow: auto;
  background: transparent;        /* desk shows through */
  display: flex;
  justify-content: center;
  padding: 24px 16px;             /* gap between desk edge and paper */
  box-sizing: border-box;
}
.v-text-page {
  position: relative;
  display: block;
  width: 100%;
  max-width: var(--page-w);
  min-height: 100%;
  background:
    linear-gradient(to right, transparent var(--gutter-w), #f1aeae var(--gutter-w), #f1aeae calc(var(--gutter-w) + 1px), transparent calc(var(--gutter-w) + 1px)),
    repeating-linear-gradient(
      to bottom,
      transparent 0,
      transparent calc(var(--rule-line-height) - 1px),
      var(--rule-color) calc(var(--rule-line-height) - 1px),
      var(--rule-color) var(--rule-line-height)
    ),
    #ffffff;
  background-position: 0 0, 0 12px, 0 0;
  background-repeat: no-repeat, repeat-y, no-repeat;
  box-shadow: 0 1px 3px rgba(0,0,0,.12), 0 8px 24px rgba(0,0,0,.08);
  border-radius: 2px;
}
.v-text-gutter {
  position: absolute;
  top: 12px;
  left: 0;
  width: var(--gutter-w);
  bottom: 80px;                 /* matches textarea padding-bottom */
  padding: 0 14px 0 0;
  color: #bfc7d0;
  font-family: ui-monospace, 'SF Mono', Menlo, Consolas, monospace;
  font-size: 13px;
  line-height: var(--rule-line-height);
  text-align: right;
  white-space: pre;
  user-select: none;
  pointer-events: none;
  overflow: hidden;
}
.v-text-area {
  display: block;
  width: 100%;
  border: 0;
  outline: 0;
  resize: none;
  /* The .v-text-page above is max-width 820, so the textarea wraps at
     the page edge automatically — no explicit text-width calc needed. */
  padding: 12px 32px 80px calc(var(--gutter-w) + 16px);
  margin: 0;
  font-family: inherit;
  font-size: 17px;
  line-height: var(--rule-line-height);
  background: transparent;
  color: #1a1a1a;
  tab-size: 4;
  overflow: hidden;
  caret-color: #2563eb;
  box-sizing: border-box;
  min-height: 100%;
  /* Unbreakable strings (URLs, code) wrap at the page edge instead of
     pushing the textarea past it. */
  overflow-wrap: break-word;
  word-break: break-word;
}
.v-text-area::selection { background: rgba(37, 99, 235, .22); }
.v-text-area[readonly]  { background: transparent; }

/* Floating preview toggle — only present for .md, top-right corner. */
.v-text-mode {
  position: absolute;
  top: 12px;
  right: 14px;
  z-index: 2;
  border: 1px solid #d1d5db;
  background: rgba(255, 255, 255, .92);
  color: #1a1a1a;
  border-radius: 999px;
  padding: 5px 14px;
  font-size: 12px;
  font-family: ui-sans-serif, system-ui, -apple-system, sans-serif;
  cursor: pointer;
  box-shadow: 0 1px 3px rgba(0,0,0,.08);
}
.v-text-mode:hover { background: #ffffff; border-color: #9ca3af; }

/* Markdown preview — same centred sheet as source, no gutter rules. */
.v-text-preview {
  flex: 1;
  min-height: 0;
  overflow: auto;
  background: #e9ecef;
  display: flex;
  justify-content: center;
  padding: 24px 16px;
  box-sizing: border-box;
  --gutter-w: 56px;
  --page-w:   820px;
}
.v-text-preview-paper {
  width: 100%;
  max-width: var(--page-w);
  min-height: 100%;
  background: #ffffff;
  color: #1a1a1a;
  padding: 32px 32px 80px calc(var(--gutter-w) + 16px);
  font-family: 'Iowan Old Style', 'Palatino Linotype', Palatino, Georgia, 'Times New Roman', serif;
  font-size: 17px;
  line-height: 1.7;
  box-sizing: border-box;
  border-radius: 2px;
  box-shadow: 0 1px 3px rgba(0,0,0,.12), 0 8px 24px rgba(0,0,0,.08);
  overflow-wrap: break-word;
  word-break: break-word;
}
.v-text-preview-paper pre,
.v-text-preview-paper code { white-space: pre-wrap; word-break: break-word; }
.v-text-preview-paper > :first-child { margin-top: 0; }
.v-text-preview-paper h1,
.v-text-preview-paper h2,
.v-text-preview-paper h3 { margin-top: 1.4em; color: #111; }
.v-text-preview-paper pre  { background: #f6f7f9; padding: 12px; border-radius: 4px; overflow-x: auto; }
.v-text-preview-paper code { background: #f6f7f9; padding: 1px 5px; border-radius: 3px; font-size: 0.92em; }
.v-text-preview-paper pre code { background: transparent; padding: 0; }
.v-text-preview-paper blockquote { border-left: 3px solid #2563eb; margin: 0; padding: 4px 14px; color: #4b5563; }
.v-text-preview-paper img { max-width: 100%; height: auto; }
.v-text-preview-paper a { color: #2563eb; }

@media (max-width: 768px) {
  /* On phones the paper fills the screen — no desk gap, no shadow. */
  .v-text         { --gutter-w: 40px; --rule-line-height: 30px; background: #ffffff; }
  .v-text-preview { --gutter-w: 40px; background: #ffffff; }
  .v-text-scroll, .v-text-preview { padding: 0; }
  .v-text-page, .v-text-preview-paper { box-shadow: none; border-radius: 0; }
  .v-text-gutter  { font-size: 12px; padding-right: 8px; }
  .v-text-area    { font-size: 16px; padding-right: 16px; padding-left: calc(var(--gutter-w) + 10px); }
  .v-text-preview-paper { font-size: 16px; padding: 24px 16px 60px calc(var(--gutter-w) + 10px); }
  .v-text-mode    { top: 8px; right: 8px; }
}

/* ============================== Properties / Eigenschaften ============================== */
/* Ubuntu-style Properties dialog: large icon + name on top, then a stack of
   rounded "cards" for info rows and per-folder settings (color, autosync,
   pin, tags), then an action row at the bottom. The whole thing fits in the
   same .overlay container the rest of the app uses, so it inherits the
   backdrop blur + fade-in. */
.props-panel {
  background: var(--bg-card);
  color: var(--fg);
  border-radius: 14px;
  width: min(460px, 92vw);
  max-height: 90vh;
  overflow: auto;
  box-shadow: 0 18px 48px rgba(0,0,0,.35);
  padding: 0 0 18px;
}
.props-head {
  display: flex; justify-content: flex-end;
  padding: 10px 10px 0;
}
.props-hero {
  display: flex; flex-direction: column; align-items: center;
  padding: 4px 24px 18px;
  text-align: center;
  gap: 6px;
}
.props-icon {
  width: 84px; height: 64px;
  border-radius: 8px 12px 8px 8px;
  background: var(--accent);
  position: relative;
  opacity: .9;
  margin-bottom: 4px;
}
.props-icon::before {
  /* Folder "tab" — the small lip on the top-left. */
  content: ""; position: absolute;
  left: 0; top: -7px;
  width: 32px; height: 10px;
  border-radius: 4px 4px 0 0;
  background: inherit;
}
.props-icon[data-type="file"] {
  width: 56px; height: 70px;
  border-radius: 4px;
  background: var(--accent);
}
.props-icon[data-type="file"]::before {
  display: none;
}
.props-name { font-size: 19px; font-weight: 600; line-height: 1.2; word-break: break-word; }
.props-sub  { font-size: 13px; color: var(--fg-muted); }
.props-disk { font-size: 12px; color: var(--fg-muted); }

.props-body {
  display: flex; flex-direction: column; gap: 8px;
  padding: 0 18px;
}
.props-card {
  background: var(--bg-canvas);
  border: 1px solid var(--line);
  border-radius: 10px;
  padding: 10px 14px;
  display: flex; align-items: center; justify-content: space-between;
  gap: 12px;
  min-height: 44px;
}
.props-card.is-button {
  cursor: pointer;
  transition: background var(--t-fast);
}
.props-card.is-button:hover { background: var(--accent-soft, rgba(99,102,241,.08)); }
.props-card .props-label {
  font-size: 11px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: .04em;
  color: var(--fg-muted);
  margin-bottom: 2px;
}
.props-card-text {
  display: flex; flex-direction: column; min-width: 0; flex: 1;
}
.props-card-text > .props-value {
  font-size: 14px; color: var(--fg);
  word-break: break-word;
}
.props-chev { color: var(--fg-muted); font-size: 18px; flex-shrink: 0; }

/* Color swatch row inside the props-card. */
.props-swatches {
  display: flex; gap: 6px; flex-wrap: wrap;
}
.props-swatch {
  width: 22px; height: 22px;
  border-radius: 50%;
  border: 2px solid transparent;
  cursor: pointer;
  background: var(--sw, #6366f1);
  transition: transform var(--t-fast), border-color var(--t-fast);
}
.props-swatch:hover { transform: scale(1.1); }
.props-swatch.is-active { border-color: var(--fg); }
/* "Keine Farbe" — dashed outline + diagonal slash, mirrors the small folder-
   color-popup so the affordance is consistent. */
.props-swatch[data-key="default"] {
  background: var(--bg-card);
  border-style: dashed;
  border-color: var(--line-strong);
  position: relative;
}
.props-swatch[data-key="default"]::after {
  content: "";
  position: absolute;
  left: 2px; right: 2px; top: 50%;
  height: 2px;
  background: var(--line-strong);
  transform: translateY(-1px) rotate(-45deg);
}
.props-swatch[data-key="default"].is-active {
  border-style: solid;
  border-color: var(--fg);
}

/* Toggle switch used for the pin toggle. */
.props-toggle {
  position: relative; display: inline-block;
  width: 38px; height: 22px; flex-shrink: 0;
}
.props-toggle input { opacity: 0; width: 0; height: 0; }
.props-toggle .props-toggle-slider {
  position: absolute; inset: 0;
  background: var(--line-strong);
  border-radius: 22px;
  cursor: pointer;
  transition: background var(--t-fast);
}
.props-toggle .props-toggle-slider::before {
  content: ""; position: absolute;
  left: 2px; top: 2px;
  width: 18px; height: 18px;
  background: white;
  border-radius: 50%;
  transition: transform var(--t-fast);
  box-shadow: 0 1px 2px rgba(0,0,0,.18);
}
.props-toggle input:checked + .props-toggle-slider { background: var(--accent); }
.props-toggle input:checked + .props-toggle-slider::before { transform: translateX(16px); }

/* Tags row: chip list + edit button. */
.props-tags {
  display: flex; gap: 4px; flex-wrap: wrap; align-items: center;
  justify-content: flex-end;
}
.props-tag-chip {
  font-size: 12px;
  background: var(--accent-soft, rgba(99,102,241,.12));
  color: var(--accent);
  padding: 2px 8px;
  border-radius: 10px;
}
.props-tags-empty { font-size: 13px; color: var(--fg-muted); }

/* Action row at the bottom: secondary buttons that perform one-shot actions. */
.props-actions {
  display: flex; flex-wrap: wrap; gap: 8px;
  padding: 10px 18px 0;
}
.props-actions .btn-secondary { flex: 1 1 auto; min-width: 120px; }
.props-actions .btn-danger {
  flex: 1 1 auto; min-width: 120px;
  background: transparent; color: var(--danger);
  border: 1px solid var(--line-strong);
  border-radius: var(--r-sm);
  padding: 7px 16px;
  font-size: 13px; font-weight: 500;
  cursor: pointer;
  transition: background var(--t-fast), border-color var(--t-fast);
}
.props-actions .btn-danger:hover { background: rgba(239,68,68,.08); border-color: var(--danger); }

/* ============================================================
   Markdown Notes — CM6 Live Preview editor (src/note/*)
   ============================================================ */
.v-note { display: flex; flex-direction: column; height: 100%; background: var(--bg-canvas); }
.v-note-bar {
  display: flex; align-items: center; justify-content: space-between;
  gap: 8px; padding: 6px 12px; border-bottom: 1px solid var(--line);
  background: var(--bg-topbar); backdrop-filter: blur(8px); flex: 0 0 auto;
}
.v-note-modes { display: inline-flex; background: var(--bg-canvas); border: 1px solid var(--line); border-radius: var(--r-sm); padding: 2px; }
.v-note-mode {
  border: 0; background: transparent; color: var(--fg-muted);
  font: 500 12.5px/1 var(--font-ui); padding: 6px 12px; border-radius: 4px; cursor: pointer;
}
.v-note-mode:hover { color: var(--fg); }
.v-note-mode.is-active { background: var(--bg-card); color: var(--accent-hover); box-shadow: var(--shadow-sm, 0 1px 2px rgba(0,0,0,.06)); }
.v-note-outline-toggle { border: 1px solid var(--line); background: var(--bg-card); border-radius: var(--r-sm); width: 30px; height: 30px; cursor: pointer; color: var(--fg-2); }
.v-note-outline-toggle:hover { border-color: var(--accent); color: var(--accent-hover); }

.v-note-main { position: relative; flex: 1 1 auto; min-height: 0; display: flex; }
.v-note-editor { flex: 1 1 auto; min-width: 0; overflow: hidden; }
.v-note-reading { flex: 1 1 auto; min-width: 0; overflow: auto; }

/* CodeMirror surface — give it a centered "paper" column */
.v-note .cm-editor { height: 100%; background: transparent; }
.v-note .cm-editor.cm-focused { outline: none; }
.v-note .cm-scroller { overflow: auto; padding: 28px 0 30vh; font-family: var(--font-note); }
.v-note .cm-content {
  max-width: 780px; margin: 0 auto; padding: 0 28px;
  font-size: 15.5px; line-height: 1.75; color: var(--fg); caret-color: var(--accent);
}
.v-note .cm-line { padding: 0; }
.v-note .cm-selectionBackground, .v-note .cm-content ::selection { background: var(--accent-soft) !important; }
.v-note.is-source .cm-content { font-family: var(--font-mono); font-size: 13.5px; }

/* Headings (Live Preview line styling) */
.v-note .cm-heading { font-weight: 700; line-height: 1.3; }
.v-note .cm-headline-1 { font-size: 1.9em; }
.v-note .cm-headline-2 { font-size: 1.55em; }
.v-note .cm-headline-3 { font-size: 1.3em; }
.v-note .cm-headline-4 { font-size: 1.12em; }
.v-note .cm-headline-5 { font-size: 1em; }
.v-note .cm-headline-6 { font-size: .92em; color: var(--fg-muted); }
.v-note .cm-h1, .v-note .cm-h2, .v-note .cm-h3,
.v-note .cm-h4, .v-note .cm-h5, .v-note .cm-h6 { font-weight: 700; }

/* Inline + block code */
.v-note .cm-inline-code, .v-note .cm-md-code {
  font-family: var(--font-mono); font-size: .88em;
  background: var(--bg-canvas); border: 1px solid var(--line); border-radius: 4px; padding: 1px 4px;
}
.v-note .cm-codeblock-line { background: #faf9f6; border-left: 2px solid var(--line-strong); }
.v-note .cm-codeblock-line .cm-md-code { background: transparent; border: 0; padding: 0; }

/* Blockquote / callout bar */
.v-note .cm-quote-line { border-left: 3px solid var(--accent-dark); padding-left: 12px; color: var(--fg-2); background: var(--accent-soft); }

/* List bullets + task checkboxes */
.v-note .cm-bullet { color: var(--accent); padding-right: 2px; }
.v-note .cm-task-box, #viewer .v-doc-paper input[type=checkbox] { width: 15px; height: 15px; vertical-align: -2px; margin-right: 4px; cursor: pointer; accent-color: var(--accent); }

/* Links */
.v-note .cm-md-link, .v-note .cm-rendered-link, #viewer .v-doc-paper a { color: var(--accent-hover); text-decoration: none; border-bottom: 1px solid var(--accent-dark); cursor: pointer; }
.v-note .cm-rendered-link:hover, #viewer .v-doc-paper a:hover { background: var(--accent-soft); }
.v-note .cm-md-url { color: var(--fg-muted); }

/* Rendered block widgets in Live Preview */
.v-note .cm-render-hr { display: block; height: 0; border-top: 2px solid var(--line-strong); margin: 10px 0; }
.v-note .cm-render-img-wrap, .v-note .cm-render-table, .v-note .cm-render-mermaid,
.v-note .cm-render-embed, .v-note .cm-math-block { display: block; margin: 6px 0; }
.v-note .cm-render-img { max-width: 100%; height: auto; border-radius: var(--r-sm); }
.v-note .cm-render-table table { border-collapse: collapse; }
.v-note .cm-render-table th, .v-note .cm-render-table td { border: 1px solid var(--line); padding: 6px 10px; }
.v-note .cm-math-error, .mermaid-error { color: #c0392b; font-family: var(--font-mono); font-size: .85em; }

/* Outline panel */
.v-note-outline { flex: 0 0 220px; border-left: 1px solid var(--line); background: var(--bg-card); overflow: auto; padding: 14px 6px; }
.v-note-outline-empty { color: var(--fg-muted); font-size: 12.5px; padding: 6px 10px; }
.v-note-ol { display: block; padding: 4px 10px; border-radius: 4px; color: var(--fg-2); font-size: 13px; text-decoration: none; cursor: pointer; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.v-note-ol:hover { background: var(--accent-soft); color: var(--accent-hover); }
.v-note-ol-2 { padding-left: 22px; } .v-note-ol-3 { padding-left: 34px; }
.v-note-ol-4 { padding-left: 46px; } .v-note-ol-5, .v-note-ol-6 { padding-left: 58px; }

/* Callouts (reading view + hydrated widgets) */
.callout { border: 1px solid var(--line); border-left: 4px solid var(--accent); border-radius: var(--r-sm); padding: 10px 14px; margin: 1em 0; background: var(--accent-soft); }
.callout-title { font-weight: 700; margin-bottom: 4px; color: var(--accent-hover); }
.callout-warning, .callout-caution { border-left-color: #e0a800; background: #fff8e6; } .callout-warning .callout-title { color: #9a6b00; }
.callout-danger, .callout-error, .callout-bug { border-left-color: #d64545; background: #fdecec; } .callout-danger .callout-title { color: #a32020; }
.callout-tip, .callout-success, .callout-info { border-left-color: #2f9e6b; background: #e9f8f0; } .callout-tip .callout-title { color: #1d7a4f; }

/* Embeds */
.note-embed { border: 1px solid var(--line); border-radius: var(--r-sm); background: var(--bg-card); margin: 8px 0; overflow: hidden; }
.note-embed-head { font-size: 12px; padding: 6px 12px; border-bottom: 1px solid var(--line); background: var(--bg-canvas); }
.note-embed-body { padding: 12px 18px; max-height: 360px; overflow: auto; }
.note-embed-img { display: block; max-width: 100%; height: auto; }
.note-embed-frame { width: 100%; height: 420px; border: 0; }
.note-embed-link { display: inline-block; padding: 10px 14px; color: var(--accent-hover); }
.note-embed-missing { padding: 10px 14px; color: var(--fg-muted); font-size: 13px; }

/* Frontmatter properties */
.note-properties { max-width: 780px; margin: 0 auto 1.5em; padding: 12px 0; border-bottom: 1px solid var(--line); display: grid; gap: 6px; }
.note-prop { display: flex; gap: 12px; font-size: 13.5px; }
.note-prop-k { flex: 0 0 120px; color: var(--fg-muted); }
.note-tag { color: var(--accent-hover); cursor: pointer; }

/* highlight.js — compact light theme */
.hljs { display: block; overflow-x: auto; }
#viewer .v-doc-paper pre.hljs, .v-note .cm-render-table pre.hljs { background: #faf9f6; border: 1px solid var(--line); border-radius: var(--r-sm); padding: 12px 14px; font-family: var(--font-mono); font-size: 13px; }
.hljs-comment, .hljs-quote { color: #8a8f98; font-style: italic; }
.hljs-keyword, .hljs-selector-tag, .hljs-built_in, .hljs-name { color: #8250df; }
.hljs-string, .hljs-attr, .hljs-template-tag { color: #1d7a4f; }
.hljs-number, .hljs-literal, .hljs-type { color: #b8860b; }
.hljs-title, .hljs-section, .hljs-function .hljs-title { color: #0550ae; }
.hljs-attribute, .hljs-variable, .hljs-tag { color: #c0392b; }
.v-note .cm-frontmatter { font-family: var(--font-mono); font-size: .82em; color: var(--fg-muted); background: #faf9f6; }

