*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
html { height: -webkit-fill-available; }

:root {
  /* Checklist checkbox icons (theme-independent shapes; colored via
     background-color so every theme's accent still applies). Empty = Lucide
     `square` outline (a squircle); done = a filled squircle with a Lucide-style
     check knocked out (evenodd), so the accent fills the box and the tick shows
     through in the surface color. Generated in scratchpad/gen.mjs. */
  --check-empty: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect x='3' y='3' width='18' height='18' rx='5'/%3E%3C/svg%3E");
  --check-done: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath fill='%23000' fill-rule='evenodd' d='M8 3 h8 a5 5 0 0 1 5 5 v8 a5 5 0 0 1 -5 5 h-8 a5 5 0 0 1 -5 -5 v-8 a5 5 0 0 1 5 -5 z M6.88 13.02 L10.37 16.52 L17.19 8.25 L15.61 6.95 L10.23 13.48 L8.32 11.58 Z'/%3E%3C/svg%3E");

  --bg: #F5F5F5;
  --surface: #FFFFFF;
  --surface-2: #FAFAFA;
  --border: #E5E5E5;
  --border-mid: #D4D4D4;
  --divider: #F0F0F0;
  --text: #111111;
  --text-2: #444444;
  --text-muted: #656565;
  --text-faint: #949494;
  --accent: #111111;
  --accent-fg: #FFFFFF;
  --danger: #DC2626;
  --danger-bg: #FFF1F2;
  --link: #2563EB;
  --radius: 12px;
  --sidebar-w: 292px;
  --notes-w: 292px;

  /* Font-size scale — every literal font-size in this file should
     reference one of these instead of a bare px value, so a size can be
     adjusted in one place instead of grepping for every occurrence. */
  --fs-9: 9px;
  --fs-10: 10px;
  --fs-11: 11px;
  --fs-12: 12px;
  --fs-13: 13px;
  --fs-14: 14px;
  --fs-15: 15px;
  --fs-16: 16px;
  --fs-17: 17px;
  --fs-18: 18px;
  --fs-22: 22px;
  --fs-28: 28px;
}

[data-dark] {
  --bg: #1E2126;
  --surface: #24272E;
  --surface-2: #20232A;
  --border: #30353E;
  --border-mid: #3B414C;
  --divider: #2A2E36;
  --text: #B6C2D6;
  --text-2: #909BAF;
  --text-muted: #7A8492;
  --text-faint: #636B78;
  --accent: #C8CED8;
  --accent-fg: #1E2126;
  --danger: #F08C84;
  --danger-bg: #2E2125;
  --link: #7AA2F7;
}

body {
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
  background: var(--bg);
  color: var(--text);
  height: 100dvh;
  min-height: -webkit-fill-available;
  -webkit-font-smoothing: antialiased;
  overflow: hidden;
  touch-action: pan-x pan-y; /* allow scroll/swipe, block double-tap & pinch zoom */
}

.beta-badge, .demo-badge {
  display: inline-block; margin-left: 8px;
  background: #f59e0b; color: #000;
  font-size: var(--fs-9); font-weight: 700; letter-spacing: 0.08em;
  padding: 4px 4px; border-radius: 8px;
  vertical-align: middle; position: relative; top: -1px;
}
.demo-badge { background: #10b981; color: #04241a; }

/* Demo-only UI is hidden everywhere except the demo instance (body.demo-mode) */
.demo-only { display: none; }
.demo-mode .demo-only { display: block; }
/* Inverse: hidden on the demo. The Markdown export is server-side, but demo
   data lives only in the browser, so it can't produce a real export there. */
.demo-mode .no-demo { display: none; }
.demo-reset-link {
  background: none; border: none; font-family: inherit; font-size: var(--fs-13);
  font-weight: 500; color: var(--danger); cursor: pointer; padding: 4px 4px;
}
.demo-reset-link:hover { text-decoration: underline; }

/* ── App shell ─────────────────────────────────────────────────────── */

.app {
  display: flex;
  height: 100dvh;
  overflow: hidden;
}

/* ── Shared ────────────────────────────────────────────────────────── */

.icon-btn {
  width: 30px; height: 30px;
  display: inline-flex; align-items: center; justify-content: center;
  background: none; border: none; border-radius: 8px;
  color: var(--text-muted); cursor: pointer;
  transition: background 0.1s, color 0.1s;
  flex-shrink: 0;
}
.icon-btn:hover { background: var(--border); color: var(--text); }
.icon-btn:active { opacity: 0.7; }

/* ── Sidebar ────────────────────────────────────────────────────────── */

.sidebar {
  width: var(--sidebar-w);
  flex-shrink: 0;
  background: var(--surface-2);
  display: flex; flex-direction: column;
  overflow: hidden;
}

.sidebar-header {
  min-height: 52px;
  padding: 8px 12px 8px 16px;
  display: flex; align-items: center; justify-content: space-between;
  flex-wrap: wrap; row-gap: 4px;
  flex-shrink: 0;
  border-bottom: 1px solid var(--divider);
}
/* Keep the title on one line and let the action row wrap under it when the
   fixed-width sidebar can't fit both — the title shrinking to wrap its own
   text (dropping BETA below "Journery") was the old, clipped behavior. */
.app-title { font-size: var(--fs-14); font-weight: 700; letter-spacing: -0.03em; white-space: nowrap; flex-shrink: 0; }
/* No border-radius — the logo SVG already has its own rounded corners (rx=4);
   adding CSS rounding on top over-rounded it vs the favicon/app icon. */
.app-logo { width: 20px; height: 20px; vertical-align: middle; margin-right: 8px; position: relative; top: -1px; user-select: none; }
.sidebar-header-actions { display: flex; align-items: center; gap: 4px; flex-shrink: 0; }

/* Primary "New note" action, labeled + in the theme accent, so the app's core
   verb is obvious from the sidebar header (desktop). Hidden on mobile, where the
   floating island owns New note. */
.sidebar-newnote-btn {
  display: inline-flex; align-items: center; gap: 5px;
  height: 30px; padding: 0 8px;
  background: none; color: var(--accent);
  border: none; border-radius: 8px; cursor: pointer;
  font-size: var(--fs-13); font-weight: 600; letter-spacing: -0.01em;
  transition: background 0.1s; flex-shrink: 0;
}
.sidebar-newnote-btn:hover { background: color-mix(in srgb, var(--accent) 12%, transparent); }
.sidebar-newnote-btn:active { opacity: 0.7; }
.sidebar-newnote-btn svg { width: 15px; height: 15px; }

.sidebar-search {
  padding: 12px 12px 8px 24px;
  display: flex; align-items: center; gap: 8px;
  border-bottom: 1px solid var(--divider);
  flex-shrink: 0;
}
.sidebar-search svg { color: var(--text-faint); flex-shrink: 0; }
.sidebar-search input {
  flex: 1; min-width: 0;
  background: none; border: none; outline: none;
  font-size: var(--fs-14); color: var(--text); font-family: inherit;
}
.sidebar-search input::placeholder { color: var(--text-muted); }
/* hide native search clear — we use a custom one */
.sidebar-search input::-webkit-search-cancel-button { -webkit-appearance: none; appearance: none; display: none; }

.search-clear {
  flex-shrink: 0; width: 20px; height: 20px;
  display: inline-flex; align-items: center; justify-content: center;
  background: none; border: none; border-radius: 50%;
  color: var(--text-faint); cursor: pointer; padding: 0;
  transition: color 0.1s, background 0.1s;
}
.search-clear svg { color: inherit; }
.search-clear:hover { color: var(--text); background: var(--border); }
.search-clear.hidden { display: none; }

/* overflow-x:hidden is deliberate — with only overflow-y set, CSS computes
   overflow-x to `auto`, so a sub-pixel-wide child triggered a phantom
   horizontal scrollbar even with nothing actually overflowing. */
.sidebar-nav { flex: 1; overflow-y: auto; overflow-x: hidden; padding: 8px 0 20px; }
.sidebar-nav::-webkit-scrollbar { width: 3px; }
.sidebar-nav::-webkit-scrollbar-thumb { background: var(--border); border-radius: 8px; }
.sidebar-nav.hidden { display: none; }

/* ── Live search results (in the sidebar, under the search bar) ─────────────── */
.sidebar-search-results {
  flex: 1 1 0; min-height: 0; overflow-y: auto;
  padding: 4px 8px 20px;
}
.sidebar-search-results.hidden { display: none; }
.search-result-item {
  display: block; width: 100%; text-align: left;
  padding: 8px 12px; margin-bottom: 4px;
  background: none; border: none; border-radius: 8px;
  font-family: inherit; cursor: pointer;
  transition: background 0.08s;
}
.search-result-item:hover  { background: var(--bg); }
.search-result-item:active { background: var(--border); }
.search-result-title {
  font-size: var(--fs-13); font-weight: 600; color: var(--text);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.search-result-title.untitled { color: var(--text-muted); font-weight: 500; }
.search-result-preview {
  font-size: var(--fs-12); color: var(--text-muted); margin-top: 4px;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.search-empty { padding: 20px 12px; font-size: var(--fs-13); color: var(--text-muted); text-align: center; }
@media (max-width: 768px) {
  .sidebar-search-results { padding: 8px 12px 24px; }
  .search-result-item { padding: 12px 12px; }
  .search-result-title { font-size: var(--fs-15); }
  .search-result-preview { font-size: var(--fs-13); }
}

/* Bottom-of-sidebar footer: profile (instance name + version) on the left,
   the focus/collapse toggle on the right. */
.sidebar-footer {
  flex-shrink: 0;
  display: flex; align-items: center; justify-content: space-between; gap: 8px;
  padding: 8px 8px max(8px, env(safe-area-inset-bottom)) 12px;
  border-top: 1px solid var(--divider);
}
/* Profile chip = avatar + name + a Settings gear pushed to the right end. No more
   dropdown menu: the gear opens Settings directly, and Feedback is a Settings
   section now. (Desktop only — hidden on mobile, where the header gear + island
   cover these.) */
.sidebar-profile-chip {
  display: flex; align-items: center; gap: 8px;
  width: 100%; min-width: 0; padding: 4px;
}
.profile-settings-btn { margin-left: auto; flex-shrink: 0; }
.profile-avatar {
  width: 28px; height: 28px; border-radius: 8px; flex-shrink: 0;
  display: inline-flex; align-items: center; justify-content: center;
  background: var(--accent); color: var(--accent-fg);
  font-size: var(--fs-12); font-weight: 700;
}
.profile-name {
  font-size: var(--fs-13); font-weight: 600; color: var(--text);
  min-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}

/* ── Mobile floating glass island (Search · New note · Profile) ──────────────
   Desktop keeps the sidebar-footer profile chip; the island is phones-only and
   lives inside .sidebar so it slides off with the sidebar when navigating. */
.mobile-island { display: none; }
@media (max-width: 768px) {
  .mobile-island {
    display: flex; align-items: center; gap: 32px;
    /* Fixed to the viewport, NOT absolute inside .sidebar — the sidebar is a
       transformed + scrolling layer, and having that between the glass and the
       page is what stopped iOS's standalone PWA webview from sampling the
       backdrop (blur went missing / opaque). As a fixed child of .app there's no
       transformed ancestor, so backdrop-filter can read the page behind it. */
    position: fixed; left: 50%;
    bottom: calc(env(safe-area-inset-bottom, 0px) + 16px);
    transform: translateX(-50%);
    z-index: 20;
    padding: 10px 22px;
    border-radius: 999px;
    /* SIMULATED glass — no backdrop-filter. Real backdrop blur is unreliable in the
       installed iOS PWA (the sidebar behind it is a separate GPU layer the standalone
       compositor won't feed into the backdrop), so the look is faked instead and reads
       identically everywhere. A top-lighter → bottom-darker translucent fill mimics
       light passing through glass; the specular rim, sheen (::before) and shadows do
       the rest. The gradient (not a flat fill) is what gives it dimensionality and
       lets the rim/sheen read — it's centered on ~75% opacity (68→82), so it stays as
       solid as a flat 75% but still looks like glass rather than a plain pill. */
    background: linear-gradient(180deg,
      color-mix(in srgb, var(--surface) 68%, transparent) 0%,
      color-mix(in srgb, var(--surface) 82%, transparent) 100%);
    /* Faint hairline edge + a bright specular rim along the top (light catching the
       glass) and a soft inner shadow at the bottom for depth — the classic glass read. */
    border: 1px solid color-mix(in srgb, var(--text) 10%, transparent);
    box-shadow:
      0 12px 34px rgba(0,0,0,0.28),
      0 2px 8px rgba(0,0,0,0.14),
      inset 0 1px 1.5px color-mix(in srgb, #fff 50%, transparent),    /* top rim — light on the upper curve */
      inset 0 -1.5px 2px color-mix(in srgb, #fff 24%, transparent),   /* bottom refractive edge — light bending through the lower curve */
      inset 0 -10px 22px color-mix(in srgb, #000 10%, transparent);   /* interior depth */
  }
  /* Faint inner ring that catches light all the way around — sells the "solid lens
     of glass" refractive edge (real content-distortion needs backdrop-filter, which
     the iOS PWA won't do; this is the reliable stand-in). */
  .mobile-island::after {
    content: '';
    position: absolute; inset: 1px;
    border-radius: inherit;
    pointer-events: none;
    box-shadow: inset 0 0 6px color-mix(in srgb, #fff 10%, transparent);
  }
  /* Glass sheen — a TOP-edge glow only. Vertical (180deg), not diagonal, so both
     sides match (no white-ish bleed down the left), and it fades out by ~40% so it
     stays a highlight under the top rim instead of washing the inner background.
     The crisp top edge itself is the box-shadow rim above; this is the soft glow. */
  .mobile-island::before {
    content: '';
    position: absolute; inset: 0;
    border-radius: inherit;
    pointer-events: none;
    background: linear-gradient(180deg,
      color-mix(in srgb, #fff 15%, transparent) 0%,
      transparent 42%);
  }
  /* It's a page-level fixed element now (not a child of the sliding sidebar), so
     hide it explicitly on the notes-list and editor views — only the sidebar
     (home) view shows it. */
  .app[data-view="notes"] #mobile-island,
  .app[data-view="editor"] #mobile-island { display: none; }

  /* The island now owns Search + New note, so the always-visible duplicates at the
     top are dropped on mobile. New note lives only in the island; the search field
     is revealed on demand (tap the island magnifier → .app.search-open) rather than
     sitting there permanently, reclaiming the top space. */
  #compose-btn { display: none; }
  .sidebar-search { display: none; }
  .app.search-open .sidebar-search { display: flex; }
  .app.search-open .search-clear { display: flex; }   /* doubles as the close/back control while searching */
  .app.search-open #mobile-island { display: none; }  /* keep the field + keyboard clear of the island */
  .island-btn {
    width: 40px; height: 40px; flex-shrink: 0;
    display: flex; align-items: center; justify-content: center;
    background: none; border: none; padding: 0;
    color: var(--text-2); cursor: pointer;
    -webkit-tap-highlight-color: transparent;
    transition: color 0.1s, opacity 0.1s;
  }
  .island-btn:active { opacity: 0.55; }
  .island-btn svg { width: 24px; height: 24px; }
  /* New note is the primary action — give it the accent so it reads as the CTA. */
  .island-btn-primary { color: var(--accent); }

  /* The desktop profile chip (avatar + name + person icon) is dropped on mobile —
     the island's person icon (Profile Settings) covers it. */
  .sidebar-footer { display: none; }

  /* Keep the last nav/folder rows scrollable clear of the floating island. */
  .sidebar-nav { padding-bottom: 96px; }
}

/* ── Sidebar nav items (Pinned, Recents, All Notes, Tags, Timeline, Trash) ─── */

.nav-item {
  position: relative;
  display: flex; align-items: center; gap: 8px;
  /* right padding reserves a fixed column for the chevron, so counts always
     right-align to the same x whether or not a chevron is present */
  width: calc(100% - 12px); min-height: 40px; padding: 8px 32px 8px 16px;
  background: none; border: none;
  font-size: var(--fs-14); font-family: inherit; color: var(--text-2);
  cursor: pointer; text-align: left;
  border-radius: 8px; margin: 4px 8px;
  transition: background 0.08s, color 0.08s;
  -webkit-tap-highlight-color: transparent;
  user-select: none; -webkit-user-select: none;
}
.nav-item:hover { background: var(--border); color: var(--text); }
.nav-item .nav-icon { flex-shrink: 0; color: var(--text-muted); width: 14px; }
/* The pin glyph carries its visual weight in the upper half (head at top, point
   at bottom), so a geometrically-centered box reads a touch high. Nudge just this
   icon down 1px to optically center it against the label. */
#pinned-tags-toggle .nav-icon { transform: translateY(1px); }

/* Currently-selected nav destination — a subtle accent-tinted background
   (not a solid fill, which read as too loud) plus bold text and an
   accent-colored icon, so "what's open" is clear without shouting. Works
   against any theme's accent hue via color-mix, no per-theme token needed. */
.nav-item.active,
.nav-item.active:hover {
  background: color-mix(in srgb, var(--accent) 14%, transparent);
  color: var(--text); font-weight: 600;
}
.nav-item.active .nav-icon { color: var(--accent); }

/* Count right-aligns to the reserved column edge — consistent across all rows */
.nav-count {
  margin-left: auto;
  font-size: var(--fs-11); color: var(--text-muted); font-weight: 400;
}

/* ── Sidebar collapsible sections ───────────────────────────────────── */

.sidebar-section { /* no divider — sections flow as one unified list */ }

/* Chevron sits in the reserved right column, absolutely positioned so it never
   shifts the count. */
.nav-item.nav-expandable .section-chev {
  position: absolute; right: 12px; top: 50%;
  transform: translateY(-50%);
  flex-shrink: 0; color: var(--text-faint);
  transition: transform 0.15s;
}
/* More specific than the base .nav-item.nav-expandable .section-chev rule above,
   so the rotation actually wins when the section is expanded. */
.nav-item.nav-expandable .section-chev.open { transform: translateY(-50%) rotate(90deg); }

/* An expanded section header reads a touch stronger than a collapsed one — its
   label brightens from the muted --text-2 to full --text and its icon/chevron
   lift a step too. Subtle weight/color only (no background chrome), so the open
   section is clearly the active one without shouting. Theme-token based. */
.nav-item.nav-expandable.expanded { color: var(--text); font-weight: 500; }
.nav-item.nav-expandable.expanded .nav-icon { color: var(--text-2); }
.nav-item.nav-expandable.expanded .section-chev { color: var(--text-muted); }

/* Folders gets a light divider since it's a different category */
#folders-section {
  border-top: 1px solid var(--divider);
  margin-top: 8px;
  padding-top: 8px;
}

/* Non-interactive section label (Folders) */
.sidebar-section-label {
  display: flex; align-items: center; justify-content: space-between;
  padding: 8px 8px 8px 16px;
  font-size: var(--fs-10); font-weight: 700; letter-spacing: 0.06em;
  text-transform: uppercase; color: var(--text-faint);
}
/* Contextual "new folder" action, tucked into the Folders section header. */
.folders-add-btn { width: 24px; height: 24px; }
.folders-add-btn svg { width: 14px; height: 14px; }

/* ── Timeline year items ─────────────────────────────────────────────── */

.year-nav-item {
  display: flex; align-items: center;
  width: calc(100% - 12px); margin: 4px 8px;
  padding: 4px 32px 4px 16px;
  background: none; border: none; border-radius: 8px;
  font-size: var(--fs-14); font-family: inherit; color: var(--text-2);
  cursor: pointer; text-align: left;
  transition: background 0.08s, color 0.08s;
  -webkit-tap-highlight-color: transparent;
  user-select: none; -webkit-user-select: none;
}
.year-nav-item:hover { background: var(--border); color: var(--text); }
.year-nav-item.active,
.year-nav-item.active:hover {
  background: color-mix(in srgb, var(--accent) 14%, transparent);
  color: var(--text); font-weight: 600;
}
.year-note-count {
  margin-left: auto;
  font-size: var(--fs-11); color: var(--text-muted);
}

/* ── Tag nav items (pinned + all tags) ──────────────────────────────── */

.tag-nav-item {
  display: flex; align-items: center; gap: 8px;
  width: calc(100% - 12px); margin: 4px 8px;
  padding: 4px 32px 4px 16px;
  background: none; border: none; border-radius: 8px;
  font-size: var(--fs-14); font-family: inherit; color: var(--text-2);
  cursor: pointer; text-align: left;
  transition: background 0.08s, color 0.08s;
  position: relative;
  -webkit-tap-highlight-color: transparent;
  user-select: none; -webkit-user-select: none;
}
.tag-nav-item:hover { background: var(--border); color: var(--text); }
.tag-nav-item.active,
.tag-nav-item.active:hover {
  background: color-mix(in srgb, var(--accent) 14%, transparent);
  color: var(--text); font-weight: 600;
}
.tag-nav-item.active .tag-hash { color: var(--accent); }
/* Wraps the "#" + tag name as a single flex item so the row's 8px flex gap sits
   only between the pin icon and the label — the hash hugs the tag text with no
   gap between them. */
.tag-label { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.tag-hash { color: var(--text-muted); font-size: var(--fs-12); margin-right: 2px; }
/* count right-aligns to the same reserved column as the section counts */
.tag-right { margin-left: auto; display: flex; align-items: center; gap: 4px; }
.tag-count { font-size: var(--fs-11); color: var(--text-muted); }

/* Pin button — appears on hover (desktop) / always (touch) */
.tag-pin-btn {
  width: 22px; height: 22px; flex-shrink: 0;
  display: inline-flex; align-items: center; justify-content: center;
  background: none; border: none; border-radius: 8px;
  color: var(--text-faint); cursor: pointer;
  opacity: 0;
  transition: opacity 0.1s, color 0.1s, background 0.1s;
}
.tag-nav-item:hover .tag-pin-btn { opacity: 1; }
.tag-pin-btn:hover { color: var(--text); background: var(--border-mid); }
.tag-pin-btn.pinned { opacity: 1; color: var(--text-muted); }

/* Pinned tags: pin sits to the LEFT of the hashtag (a tappable unpin target,
   away from the row's open-tag tap area). Width + zero margin match the section
   header's .nav-icon column (14px starting at the 16px padding edge) so the pin
   icons line up in the same vertical column as the "Pinned" header icon. */
.tag-pin-btn.tag-pin-left {
  width: 14px; height: 18px; margin-left: 0; opacity: 1;
  /* The pin's box is geometrically centered with the tag label at 0px; nudge 1px
     to optically center the top-heavy glyph (filled head up top, thin needle
     below). Measured against the label — larger values sit visibly low. */
  transform: translateY(1px);
}

/* Pinned tags section empty state */
.sidebar-empty {
  padding: 4px 16px 8px 16px;
  font-size: var(--fs-11); color: var(--text-faint); font-style: italic;
}

/* ── Folder tree ────────────────────────────────────────────────────── */

.folder-row {
  display: flex; align-items: center;
  width: calc(100% - 12px); margin: 4px 8px;
  border-radius: 8px;
  transition: background 0.08s;
}
.folder-row:hover { background: var(--border); }
.folder-row:hover .folder-kebab { opacity: 1; }
.folder-row.active,
.folder-row.active:hover {
  background: color-mix(in srgb, var(--accent) 14%, transparent);
}
.folder-row.active .folder-btn { color: var(--text); font-weight: 600; }
.folder-row.active .folder-btn svg { color: var(--accent); }

.folder-toggle {
  width: 20px; height: 28px; flex-shrink: 0;
  display: flex; align-items: center; justify-content: center;
  background: none; border: none; cursor: pointer; color: var(--text-faint);
  transition: transform 0.15s;
}
.folder-toggle.open { transform: rotate(90deg); }
.folder-toggle-spacer { width: 20px; flex-shrink: 0; }

.folder-btn {
  flex: 1; min-width: 0;
  display: flex; align-items: center; gap: 8px;
  padding: 4px 4px 4px 0;
  background: none; border: none; cursor: pointer;
  font-size: var(--fs-14); font-family: inherit; color: var(--text-2);
  text-align: left; overflow: hidden;
}
.folder-btn svg { flex-shrink: 0; color: var(--text-muted); }
.folder-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; flex: 1; }

.folder-kebab {
  display: inline-flex; align-items: center; justify-content: center;
  width: 26px; height: 26px; flex-shrink: 0; margin-right: 4px;
  background: none; border: none; border-radius: 8px; cursor: pointer;
  color: var(--text-muted); opacity: 0;
  transition: opacity 0.1s, background 0.1s;
}
.folder-kebab:hover { background: var(--border-mid); }

.folder-children { padding-left: 16px; }

/* ── Notes pane ─────────────────────────────────────────────────────── */

.notes-pane {
  width: var(--notes-w);
  flex-shrink: 0;
  background: var(--surface);
  display: flex; flex-direction: column;
  overflow: hidden;
}

.resize-handle {
  width: 1px;
  background: var(--border);
  cursor: col-resize;
  flex-shrink: 0;
  position: relative;
  z-index: 10;
  transition: background 0.15s;
}
.resize-handle::after {
  content: '';
  position: absolute;
  top: 0; bottom: 0;
  left: -4px; right: -4px;
}
.resize-handle:hover, .resize-handle.dragging { background: var(--border-mid); }

.notes-pane-header {
  height: 52px;
  padding: 0 8px 0 16px;
  display: flex; align-items: center; gap: 4px;
  flex-shrink: 0;
  border-bottom: 1px solid var(--divider);
}
.pane-title {
  flex: 1; font-size: var(--fs-15); font-weight: 600;
  letter-spacing: -0.02em; overflow: hidden;
  text-overflow: ellipsis; white-space: nowrap;
}
.back-btn { display: none; }
/* Up-one-level chevron: desktop only (mobile already has the drill-down
   back-btn above); JS toggles .hidden based on the current folder's
   parent_id, so a root-level folder shows no chevron. */
#folder-up-btn.hidden { display: none; }

.notes-header-actions { display: flex; align-items: center; gap: 0; flex-shrink: 0; }
.pane-dropdown-wrapper { position: relative; }

.pane-dropdown {
  position: absolute; top: calc(100% + 6px); right: 0;
  background: var(--surface);
  border: 1.5px solid var(--border);
  border-radius: 12px;
  padding: 4px;
  min-width: 160px;
  box-shadow: 0 4px 20px rgba(0,0,0,0.12);
  z-index: 100;
}
.pane-dropdown.hidden { display: none; }

/* Backdrop behind an open dropdown / context menu (below the menus at z 100+,
   above app content). Subtle, theme-aware dim. */
.menu-backdrop {
  position: fixed; inset: 0; z-index: 95;
  background: rgba(0, 0, 0, 0.10);
}
[data-dark] .menu-backdrop { background: rgba(0, 0, 0, 0.32); }
.menu-backdrop.hidden { display: none; }
.pane-dropdown button {
  display: block; width: 100%;
  padding: 8px 12px; text-align: left;
  background: none; border: none; border-radius: 8px;
  font-size: var(--fs-13); font-family: inherit; color: var(--text);
  cursor: pointer; transition: background 0.08s; white-space: nowrap;
}
.pane-dropdown button:hover { background: var(--surface-2); }
.pane-dropdown button.active-sort { font-weight: 600; }
.pane-dropdown-sep { height: 1px; background: var(--divider); margin: 4px 8px; }
.pane-dropdown-label { padding: 8px 12px 4px; font-size: var(--fs-11); font-weight: 600; color: var(--text-muted); text-transform: uppercase; letter-spacing: 0.04em; }
/* Tag-view overflow rows carry a leading icon, matching the note overflow menu. */
#notes-overflow-menu button { display: flex; align-items: center; gap: 12px; }
#notes-overflow-menu button svg { width: 15px; height: 15px; flex-shrink: 0; color: var(--text-muted); }
/* Tag view: collapse sort + select (+ share) into the overflow; keep "+" outside. */
.notes-overflow-wrap { display: none; }
.notes-pane.tag-view:not(.select-mode) .notes-overflow-wrap { display: block; }
.notes-pane.tag-view #sort-wrap,
.notes-pane.tag-view #select-mode-btn { display: none; }

.notes-pane-search {
  display: flex; align-items: center; gap: 8px;
  padding: 8px 12px;
  border-bottom: 1px solid var(--divider);
  flex-shrink: 0;
}
.notes-pane-search svg { color: var(--text-faint); flex-shrink: 0; }
.notes-pane-search input {
  flex: 1; background: none; border: none; outline: none;
  font-size: var(--fs-13); color: var(--text); font-family: inherit;
}
.notes-pane-search input::placeholder { color: var(--text-muted); }

.notes-section-label {
  padding: 12px 16px 4px;
  font-size: var(--fs-10); font-weight: 700; letter-spacing: 0.06em;
  text-transform: uppercase; color: var(--text-faint);
}
.note-item-trashed { opacity: 0.45; }
.note-item-trashed:hover { opacity: 0.7; background: var(--surface-2); }
.note-item-meta-trash { display: flex; align-items: center; justify-content: space-between; }
.tag-trash-restore-btn {
  font-size: var(--fs-11); padding: 4px 8px;
  background: none; border: 1px solid var(--border-mid);
  border-radius: 8px; color: var(--text-muted);
  cursor: pointer; font-family: inherit; flex-shrink: 0;
}
.tag-trash-restore-btn:hover { background: var(--surface-2); color: var(--text); }

.folder-list-item {
  padding: 12px 16px;
  border-bottom: 1px solid var(--divider);
  display: flex; align-items: center; gap: 12px;
  cursor: pointer; transition: background 0.08s;
}
.folder-list-item:hover { background: var(--surface-2); }
.folder-list-item svg { color: var(--text-muted); flex-shrink: 0; }
.folder-list-item-name {
  flex: 1; font-size: var(--fs-14); color: var(--text);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.folder-list-item-chev { color: var(--text-faint); flex-shrink: 0; }

.notes-list { flex: 1; overflow-y: auto; }
.notes-list::-webkit-scrollbar { width: 3px; }
.notes-list::-webkit-scrollbar-thumb { background: var(--border); border-radius: 8px; }

.note-item {
  padding: 12px 16px;
  border-bottom: 1px solid var(--divider);
  cursor: pointer; transition: background 0.08s;
  position: relative;
}
.note-item:hover { background: var(--surface-2); }
.note-item.active { background: var(--bg); }
.note-item-title {
  font-size: var(--fs-14); font-weight: 600; color: var(--text);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  margin-bottom: 4px;
}
.note-item-title.untitled { color: var(--text-faint); }
.note-item-meta {
  display: flex; align-items: center; gap: 8px;
  font-size: var(--fs-12); color: var(--text-muted);
  margin-top: 8px;
}
.note-item-preview {
  font-size: var(--fs-13); color: var(--text-muted); margin-bottom: 4px;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.note-item-tags { display: flex; flex-wrap: wrap; gap: 4px; margin-top: 4px; }
.note-tag-chip {
  font-size: var(--fs-11); color: var(--text-muted);
  background: var(--bg); border: 1px solid var(--border);
  border-radius: 8px; padding: 4px 4px;
}

.notes-empty {
  padding: 48px 20px; text-align: center;
  color: var(--text-faint); font-size: var(--fs-13); line-height: 1.8;
}

/* ── Editor pane ────────────────────────────────────────────────────── */

.editor-pane {
  flex: 1; min-width: 0;
  display: flex; flex-direction: column;
  overflow: hidden; position: relative;
}

.editor-toolbar {
  position: relative;
  height: 52px;
  padding: 0 12px 0 8px;
  display: flex; align-items: center; gap: 8px;   /* match the format bar's icon gap */
  flex-shrink: 0;
  border-bottom: 1px solid var(--divider);
}

/* Note title mirrored into the header, next to the back chevron. Hidden until
   the real title scrolls up out of the editor body (driven by an
   IntersectionObserver in app.js), then it cross-fades in as a scroll cue /
   scroll-to-top target. Takes the flex slot so it left-aligns after the back
   button and truncates before reaching the actions. */
.editor-header-title {
  flex: 1; min-width: 0;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  font-size: var(--fs-15); font-weight: 600; color: var(--text);
  padding-right: 8px;
  opacity: 0; pointer-events: none;
  transition: opacity 0.2s;
  cursor: pointer;
}
.editor-header-title.visible { opacity: 1; pointer-events: auto; }

.autosave-indicator {
  position: absolute; left: 50%; transform: translateX(-50%);
  font-size: var(--fs-11); color: var(--text-faint);
  text-align: center;
  pointer-events: none;
  transition: opacity 0.2s;
}
/* When the title is pinned in the header, drop the (usually empty) autosave
   text so they never overlap. */
.editor-toolbar.title-pinned .autosave-indicator { opacity: 0; }

/* Save button doubles as an autosave indicator: the checkmark swaps to a
   spinner while a save is in flight, then back to the check when it lands. */
.editor-save-btn .icon-spinner { display: none; }
.editor-save-btn.saving .icon-check { display: none; }
.editor-save-btn.saving .icon-spinner { display: inline-flex; animation: save-spin 0.7s linear infinite; }
@keyframes save-spin { to { transform: rotate(360deg); } }

.overflow-wrapper { position: relative; }
.overflow-menu {
  position: absolute; top: calc(100% + 6px); right: 0;
  background: var(--surface);
  border: 1.5px solid var(--border);
  border-radius: var(--radius);
  padding: 4px;
  min-width: 160px;
  box-shadow: 0 4px 20px rgba(0,0,0,0.12);
  z-index: 100;
}
.overflow-menu button {
  display: flex; align-items: center; gap: 12px; width: 100%;
  padding: 8px 12px; text-align: left; white-space: nowrap;
  background: none; border: none; border-radius: 8px;
  font-size: var(--fs-13); font-family: inherit; color: var(--text);
  cursor: pointer; transition: background 0.08s;
}
.overflow-menu button:hover { background: var(--surface-2); }
.overflow-menu button.danger { color: var(--danger); }
.overflow-menu button.danger:hover { background: var(--danger-bg); }
.overflow-menu button svg { width: 15px; height: 15px; flex-shrink: 0; color: var(--text-muted); }
.overflow-menu button.danger svg { color: var(--danger); }
.overflow-menu.hidden { display: none; }

.note-ctx-menu {
  position: fixed;
  background: var(--surface);
  border: 1.5px solid var(--border);
  border-radius: var(--radius);
  padding: 4px;
  min-width: 160px;
  box-shadow: 0 4px 20px rgba(0,0,0,0.18);
  z-index: 200;
}
.note-ctx-menu button {
  display: block; width: 100%;
  padding: 8px 12px; text-align: left;
  background: none; border: none; border-radius: 8px;
  font-size: var(--fs-13); font-family: inherit; color: var(--text);
  cursor: pointer; transition: background 0.08s;
}
.note-ctx-menu button:hover { background: var(--surface-2); }
.note-ctx-menu button.danger { color: var(--danger); }
.note-ctx-menu button.danger:hover { background: var(--danger-bg); }
.note-ctx-menu.hidden { display: none; }

.editor-body {
  flex: 1; display: flex; flex-direction: column;
  overflow-y: auto; min-height: 0;
}

.note-title-input {
  padding: 24px 28px 16px;
  font-size: var(--fs-28); font-weight: 700; letter-spacing: -0.03em;
  color: var(--text); background: none; border: none; outline: none;
  font-family: inherit; width: 100%; flex-shrink: 0;
  resize: none; overflow: hidden; line-height: 1.25;
}
.note-title-input::placeholder { color: var(--text-faint); font-weight: 600; }

.note-tags-row {
  display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
  padding: 0 28px 12px;
  flex-shrink: 0; min-height: 28px;
  position: relative;
}

.tag-suggestions {
  position: absolute;
  top: calc(100% - 4px); left: 28px;
  background: var(--surface);
  border: 1.5px solid var(--border);
  border-radius: 12px;
  padding: 4px;
  min-width: 180px; max-width: 280px;
  box-shadow: 0 4px 20px rgba(0,0,0,0.12);
  z-index: 50;
}
.tag-suggestions.hidden { display: none; }
.tag-suggestion-item {
  display: block; width: 100%;
  padding: 8px 12px; text-align: left;
  background: none; border: none; border-radius: 8px;
  font-size: var(--fs-13); font-family: inherit; color: var(--text);
  cursor: pointer; transition: background 0.08s; white-space: nowrap;
}
.tag-suggestion-item:hover,
.tag-suggestion-item.active { background: var(--bg); }

.note-dates {
  padding: 0 28px 12px;
  flex-shrink: 0;
  display: flex; gap: 32px;
}
.note-date-item {
  font-size: var(--fs-12); color: var(--text-muted);
  display: flex; flex-direction: column; gap: 4px;
}
.note-date-label {
  font-size: var(--fs-11); font-weight: 700; letter-spacing: 0.05em;
  text-transform: uppercase;
}
.note-dates.hidden { display: none; }

/* ── Floating format bar ─────────────────────────────────────────────── */

.floating-format-bar {
  position: fixed;
  z-index: 800;
  display: flex; align-items: center; gap: 4px;
  padding: 8px 8px;
  background: #1C1C1E;
  border-radius: 12px;
  box-shadow: 0 8px 32px rgba(0,0,0,0.3), 0 2px 8px rgba(0,0,0,0.2);
  transform: translateX(-50%);
  white-space: nowrap;
  pointer-events: all;
}
[data-dark] .floating-format-bar { background: #2C2C2E; }
.floating-format-bar.hidden { display: none; }
.floating-format-bar::after {
  content: '';
  position: absolute;
  top: 100%; left: var(--arrow-x, 50%);
  transform: translateX(-50%);
  border: 6px solid transparent;
  border-top-color: #1C1C1E;
  pointer-events: none;
}
[data-dark] .floating-format-bar::after { border-top-color: #2C2C2E; }
.floating-format-bar.below::after {
  top: auto; bottom: 100%;
  border-top-color: transparent;
  border-bottom-color: #1C1C1E;
}
[data-dark] .floating-format-bar.below::after { border-bottom-color: #2C2C2E; }

/* Touch-only formatting bar: sticky to the top of .editor-body (its
   scroll container), not floating/fixed/absolute at all — so it never
   needs to track the keyboard or visualViewport. It just stays at the top
   of whatever's currently scrolled into view, the same way any other
   position:sticky header would, regardless of the on-screen keyboard. */
.sticky-format-bar {
  position: sticky;
  top: 0;
  z-index: 5;
  display: flex;
  /* Anchor the controls to the bar's BOTTOM edge so, as max-height animates, they
     travel up/down WITH that edge (clipped by overflow:hidden) — a real slide. With
     align-items:center they'd instead unfold from the middle, and the old opacity
     fade made that read as a fade-out rather than a slide. (Separators re-center
     via align-self below.) */
  align-items: flex-end;
  flex-shrink: 0;
  gap: 4px;
  background: var(--surface);
  border-bottom: 1px solid var(--divider);
  overflow-x: auto;
  overflow-y: hidden;
  -webkit-overflow-scrolling: touch;
  scrollbar-width: none;      /* Firefox */
  -ms-overflow-style: none;   /* old Edge */
  /* Collapsed by default — the Formatting toggle drops it straight down. The
     height AND the vertical padding animate together (0 → full), so the controls
     travel with the bar's bottom edge the whole way — a clean slide, no fade
     (opacity never changes) and no dead first-half where only empty padding grows.
     Left/right padding stays STATIC (animating it drifted the bar diagonally, and
     desktop derives it from the writing column anyway). */
  max-height: 0;
  padding: 0 8px 0 12px;
  border-bottom-width: 0;
  pointer-events: none;
  transition: max-height 0.25s ease, padding-top 0.25s ease, padding-bottom 0.25s ease, border-bottom-width 0.25s ease;
}
.sticky-format-bar.open {
  max-height: 56px;
  padding-top: 12px;
  padding-bottom: 12px;
  border-bottom-width: 1px;
  pointer-events: auto;
}
.sticky-format-bar::-webkit-scrollbar { display: none; } /* Safari/Chrome */
.sticky-format-bar::after {
  /* Trailing spacer so the last button clears the screen edge with some
     breathing room once scrolled all the way, instead of sitting flush
     against it. */
  content: '';
  flex: none;
  width: 8px;
}
/* Desktop: full-width bar, but the controls spread edge-to-edge (space-between)
   across the same horizontal band as the note body — 28px in on each side, the
   note title/body's own padding — so the first and last controls line up with
   the text's left and right edges, symmetric on both sides. The trailing spacer
   is a mobile scroll-edge affordance; drop it here. */
@media (min-width: 769px) {
  .sticky-format-bar {
    gap: 8px;
    justify-content: space-between;
    /* Inset to the 750px writing column's text edges: half the leftover width
       plus the body's own 28px padding. Falls back to a flat 28px when the
       editor pane is narrower than the column (max() keeps padding ≥ 28px), so
       the first/last controls always line up with the note text on both sides. */
    padding-left: max(28px, (100% - 750px) / 2 + 28px);
    padding-right: max(28px, (100% - 750px) / 2 + 28px);
  }
  .sticky-format-bar::after { display: none; }
}
/* Header Formatting toggle — highlighted while the bar is open. */
#format-toggle-btn.active { color: var(--accent); background: var(--surface-2); }

.fmt-btn {
  display: inline-flex; align-items: center; justify-content: center;
  width: 34px; height: 32px;
  background: none; border: none; border-radius: 8px;
  color: rgba(255,255,255,0.75); cursor: pointer;
  transition: background 0.1s, color 0.1s;
  flex-shrink: 0;
}
.fmt-btn:hover { background: rgba(255,255,255,0.12); color: #fff; }
/* Active format: a soft persistent tint + brighter icon — enough to read as "on"
   without shouting. */
.fmt-btn.active, .fmt-btn.active:hover { background: rgba(255,255,255,0.16); color: #fff; }
/* Sticky (touch) bar sits on a themed surface: subtle fill + accent-tinted icon. */
.sticky-format-bar .icon-btn.active,
.sticky-format-bar .icon-btn.active:hover { background: var(--border); color: var(--accent); }
/* Match each bar's own icon size (15px desktop .fmt-btn svgs, 16px touch
   .icon-btn svgs in the sticky bar) so the text buttons (P/H1/H2/H3) read
   as the same visual weight as the icon buttons (B/I/U/S/etc.) next to them. */
.fmt-btn[data-fmt^="h"], .fmt-btn[data-fmt="p"] { font-size: var(--fs-15); font-weight: 700; }
.sticky-format-bar .icon-btn[data-fmt^="h"], .sticky-format-bar .icon-btn[data-fmt="p"] { font-size: var(--fs-16); font-weight: 700; }
.fmt-sep {
  width: 1px; height: 16px;
  background: rgba(255,255,255,0.15);
  margin: 0 4px;
  flex-shrink: 0;
}
/* The floating desktop bar is always dark regardless of theme, but the
   sticky touch bar uses the actual theme surface — needs a theme-aware
   separator instead of the white-based one above. */
/* The bar bottom-anchors its children (for the slide animation); keep the short
   separators optically centered against the taller icon buttons. */
.sticky-format-bar .fmt-sep { background: var(--border); align-self: center; }

.note-body-wrap { position: relative; }
.note-body-placeholder {
  position: absolute;
  /* Match .note-body-input's padding-top so the placeholder text shares the
     caret's line box (same font-size + 1.7 line-height) and the two align. */
  top: 16px; left: 28px; right: 28px;
  pointer-events: none;
  user-select: none;
  font-size: var(--fs-16); line-height: 1.7;
  color: var(--text-faint);
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
}
.note-body-placeholder.hidden { display: none; }
.note-body-input {
  flex: none;
  min-height: calc(100vh - 180px);
  padding: 16px 28px 20px;
  font-size: var(--fs-16); line-height: 1.7; color: var(--text-2);
  background: none; border-top: 1px solid var(--divider);
  outline: none;
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
  tab-size: 2;
  word-break: break-word; overflow-wrap: break-word;
}
/* Each Enter press creates a new top-level div (WebKit's default paragraph
   separator here) with zero margin, so consecutive lines stack at exactly
   1x line-height. Adding margin-bottom only to plain paragraphs (not
   line-height itself) makes the gap between paragraphs 1.5x while text
   wrapping within a single paragraph is untouched. 0.85em = half of the
   1.7 line-height above. */
.note-body-input > div { margin-bottom: 0.85em; }
/* Caret height on an EMPTY line (a bare <br>, i.e. what a fresh Enter creates)
   vs a line WITH text. WebKit sizes the caret on a text line to the glyph box
   (~1.18x font-size), but on an empty block there's no text to constrain it, so
   it draws the caret at the FULL 1.7 line box — ~10px taller. Result: the caret
   visibly "grows" the moment you Enter to a new line, and that oversized caret
   looms over the first glyph at the start of a sentence, reading as overlap.
   Fix: tighten line-height to ~glyph height on br-only lines ONLY, so their
   caret matches a text line. Text lines keep the 1.7 reading line-height (the
   :has guard means a line stops matching the instant you type into it). Verified
   in WebKit (iPhone): empty-vs-text caret gap 9.7px → 0.4px. */
.note-body-input > div:has(> br:only-child),
.note-body-input li:has(> br:only-child) { line-height: 1.2; }
/* A list belongs to the line directly above it — its intro, or a bold line used
   as a "heading". Pull it up tight against that line instead of inheriting the
   full 0.85em paragraph gap, so "title then bullets" reads as one unit rather
   than the title floating closer to the list ABOVE it than its own. (Real
   <h1/h2/h3> headings already hug their list via smaller margins, so this only
   affects paragraph→list.) */
.note-body-input > div + ul,
.note-body-input > div + ol { margin-top: -0.55em; }
/* Bottom margin is in REM, not EM, on purpose: em here is relative to each
   heading's own (larger) font-size, so a single em value would give h1/h2/h3
   three different gaps — and all were far tighter than a paragraph's 0.85em
   (13.6px) below-gap, leaving headings cramped against the text under them.
   0.85rem (= 0.85 × 16px root = 13.6px) gives every heading the SAME gap below
   as a regular paragraph. Top stays 0.5em so a heading still separates clearly
   from the content above it. */
.note-body-input h1, .note-body-input h2, .note-body-input h3 {
  color: var(--text); font-weight: 700; line-height: 1.3; margin: 0.5em 0 0.85rem;
}
.note-body-input h1 { font-size: 1.6em; }
.note-body-input h2 { font-size: 1.3em; }
.note-body-input h3 { font-size: 1.1em; font-weight: 600; }
.note-body-input b, .note-body-input strong { font-weight: 600; }
.note-body-input i, .note-body-input em { font-style: italic; }
.note-body-input u { text-decoration: underline; }
/* Struck text also dims to the muted token (same treatment as a done checklist
   item) so it's distinguishable at a glance, not just by the thin line. Uses a
   theme token, so it adapts to every theme. */
.note-body-input s, .note-body-input strike { text-decoration: line-through; color: var(--text-muted); }
.note-body-input ol { list-style: decimal; padding-left: 1.5em; margin: 0.3em 0; }
.note-body-input li { margin: 0.1em 0; font-weight: 400; }

/* Bullets: draw the marker ourselves (list-style:none + ::before) so we can use
   real shapes, not just the three native ones, and cycle them by nesting depth.
   The marker is an inline-block pulled left into the list padding via negative
   margin, so it hangs beside the text and stays baseline-aligned (wrapped lines
   align to the text, not the marker). `> li` scopes each rule to items at that
   exact depth; the deeper, more-specific chain wins the cascade. Cycle of four:
   • filled dot → ◦ hollow circle → ▪ square → ‣ arrow, then repeat. */
.note-body-input ul { list-style: none; padding-left: 1.6em; margin: 0.3em 0; }
.note-body-input ul > li { position: relative; }
.note-body-input ul > li::before {
  content: '\2022';                 /* • */
  /* Marker box == the full 1.6em gutter (border-box via the global reset),
     pulled left into the padding; glyph right-aligned with a fixed 0.45em gap
     to the text, so the spacing reads identical whatever shape the glyph is. */
  display: inline-block; width: 1.6em; margin-left: -1.6em;
  text-align: right; padding-right: 0.45em;
  color: var(--text-muted); font-weight: 700;
}
.note-body-input ul ul > li::before                      { content: '\25E6'; }  /* ◦ hollow circle */
.note-body-input ul ul ul > li::before                   { content: '\25AA'; font-size: 0.85em; }  /* ▪ square */
.note-body-input ul ul ul ul > li::before                { content: '\2023'; }  /* ‣ arrow */
.note-body-input ul ul ul ul ul > li::before             { content: '\2022'; }  /* • */
.note-body-input ul ul ul ul ul ul > li::before          { content: '\25E6'; }  /* ◦ */
.note-body-input ul ul ul ul ul ul ul > li::before       { content: '\25AA'; font-size: 0.85em; }  /* ▪ */
.note-body-input ul ul ul ul ul ul ul ul > li::before    { content: '\2023'; }  /* ‣ */

/* Numbers stay native (decimal→alpha→roman, cycling every 3 levels). */
.note-body-input ol ol                      { list-style-type: lower-alpha; }
.note-body-input ol ol ol                   { list-style-type: lower-roman; }
.note-body-input ol ol ol ol                { list-style-type: decimal; }
.note-body-input ol ol ol ol ol             { list-style-type: lower-alpha; }
.note-body-input ol ol ol ol ol ol          { list-style-type: lower-roman; }
.note-body-input ol ol ol ol ol ol ol       { list-style-type: decimal; }
.note-body-input ol ol ol ol ol ol ol ol    { list-style-type: lower-alpha; }
.note-body-input ol ol ol ol ol ol ol ol ol { list-style-type: lower-roman; }

/* Checklist: a <ul class="task-list"> whose marker is a tappable checkbox. The
   class selector outranks the bullet ::before rules above, so it wins even when
   nested. Explicit padding/text-align/width reset the bullet marker's geometry
   (which would otherwise leak through property-by-property). */
.note-body-input ul.task-list { padding-left: 1.7em; }
.note-body-input ul.task-list > li::before {
  content: '';
  display: inline-block;
  width: 1.2em; height: 1.2em;
  /* -1.7em pulls the box into the ul's left padding (the gutter); margins net to
     ~zero advance so the text still starts where a plain paragraph would. */
  margin-left: -1.7em; margin-right: 0.35em;
  /* `middle` targets the x-height midpoint, a touch below the line's visual
     center, so lift the box slightly to optically center it with the text. */
  vertical-align: middle; transform: translateY(-0.1em);
  background-color: var(--text-muted);
  -webkit-mask: var(--check-empty) center / contain no-repeat;
          mask: var(--check-empty) center / contain no-repeat;
  cursor: pointer;
  transition: background-color 0.12s;
}
.note-body-input ul.task-list > li.done::before {
  background-color: var(--accent);
  -webkit-mask-image: var(--check-done);
          mask-image: var(--check-done);
}
.note-body-input ul.task-list > li.done { color: var(--text-muted); text-decoration: line-through; }
/* Dark-mode selection readability: muted/struck (`.done`) text over the native
   translucent-blue highlight was nearly invisible in WebKit (iOS PWA). Force a
   brighter selected-text color so completed checklist items stay legible while
   selected. We MUST set an explicit `background` too — declaring a ::selection
   with only `color` makes WebKit drop the highlight background entirely. Scoped
   to [data-dark] so light mode keeps its native selection (which reads fine).
   ::selection and ::-moz-selection are separate rules on purpose — one selector
   list containing an unknown pseudo is dropped whole by both engines. */
[data-dark] .note-body-input ::selection {
  background: rgba(122, 162, 247, 0.40);
  color: var(--text);
  -webkit-text-fill-color: var(--text);
}
[data-dark] .note-body-input ::-moz-selection {
  background: rgba(122, 162, 247, 0.40);
  color: var(--text);
}
.note-body-input code {
  /* Menlo (not SF Mono) — SF Mono is San Francisco's monospace sibling, so it
     shares the system UI font's design language and reads as barely different
     from the body text. Menlo has real programmer-font character (dotted
     zero, distinct letterforms) and is preinstalled on every Apple device. */
  font-family: 'Menlo', 'Monaco', 'Consolas', 'Courier New', monospace;
  font-size: 0.875em; color: var(--text-2);
  /* Same light card treatment used for modals/dropdowns elsewhere in the app
     (surface + border), so the box reads as a deliberate, familiar shape
     rather than a loud highlight. */
  background: var(--surface); border: 1px solid var(--border);
  border-radius: 8px; padding: 0.1em 0.4em;
}
.note-body-input hr { border: none; border-top: 2px solid var(--border-mid); margin: 1em 0; cursor: default; }
.note-body-input pre {
  margin: 0.7em 0; padding: 12px 16px;
  background: var(--surface); border: 1px solid var(--border); border-radius: 8px;
  white-space: pre-wrap; word-break: break-word; overflow-x: auto;
}
/* Inside a block, the box is drawn by <pre> (which keeps its surface card, border,
   and padding above) — drop only the inline chip's own background/border/radius so
   it doesn't double up. NOTE: reset ONLY pre code here, never pre itself, or the
   block loses its card. */
.note-body-input pre code { background: none; border: none; border-radius: 0; padding: 0; }
/* Code BLOCKS use Monaco — chunkier and more rectangular ("slabbier") than the
   inline chip's Menlo, but with substantial strokes so it stays clearly readable
   (Courier was too thin/light). System fonts only (no CDN); for a truly slab
   webfont (Space Mono / IBM Plex Mono), self-host a woff2 + @font-face here. */
.note-body-input pre, .note-body-input pre code { font-family: 'Monaco', 'Consolas', 'Menlo', monospace; }
/* Copy buttons for code blocks. One per <pre>, held in a body-level layer (NOT
   inside the contenteditable — the note saves innerHTML verbatim, so an in-content
   button would be stored). Positioned over each block's top-right via JS.
   Desktop: a block's button fades in only while the cursor is over that block
   (.show, set by JS). Touch: every button carries .show so they're always visible. */
.code-copy-layer { position: fixed; inset: 0; z-index: 50; pointer-events: none; }
.code-copy-btn {
  position: fixed;
  display: inline-flex; align-items: center; justify-content: center;
  width: 26px; height: 26px; padding: 0;
  background: var(--surface); border: 1px solid var(--border); border-radius: 6px;
  color: var(--text-muted); cursor: pointer;
  opacity: 0; pointer-events: none;
  transition: opacity 0.12s, color 0.1s, background 0.1s;
}
.code-copy-btn.show { opacity: 1; pointer-events: auto; }
.code-copy-btn:hover { color: var(--text); background: var(--surface-2); }
.code-copy-btn.offscreen { display: none; }
.code-copy-btn .icon-check { display: none; }
.code-copy-btn.copied { color: var(--accent); }
.code-copy-btn.copied .icon-copy { display: none; }
.code-copy-btn.copied .icon-check { display: inline-flex; }
.note-body-input a { color: var(--link, #2563EB); text-decoration: underline; text-underline-offset: 2px; cursor: pointer; }
.note-body-input blockquote {
  margin: 0.7em 0; padding: 0.1em 0 0.1em 1em;
  border-left: 3px solid var(--border-mid);
  color: var(--text-2); font-size: 1.15em; font-style: italic; line-height: 1.5;
}

/* ── Share modal (balanced: labelled fields + full-width stacked buttons) ── */
.share-hint { font-size: var(--fs-13); color: var(--text-muted); margin: 0 0 20px; line-height: 1.5; }
.share-field { margin-bottom: 16px; }
.share-field-label { display: block; font-size: var(--fs-12); font-weight: 600; color: var(--text-2); margin-bottom: 8px; }
.share-field-control {
  width: 100%; padding: 12px 12px; border-radius: 8px;
  background: var(--bg); border: 1.5px solid var(--border);
  font-size: var(--fs-13); font-family: inherit; color: var(--text); outline: none;
}
.share-field-control:focus { border-color: var(--border-mid); }
/* Custom chevron (native one sat flush to the right edge with no gap). Positioned
   8px in from the right; padding-right keeps the value clear of it. */
select.share-field-control {
  cursor: pointer;
  -webkit-appearance: none; appearance: none;
  padding-right: 34px;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24' fill='none' stroke='%23888888' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 8px center;
}
input.share-field-control { color: var(--text-2); }
.share-expiry-note { font-size: var(--fs-12); color: var(--text-muted); margin: 8px 0 0; }
.share-expiry-note.hidden { display: none; }
.share-date-input { margin-top: 8px; color: var(--text-2); }
.share-password-note {
  display: flex; align-items: center; justify-content: space-between; gap: 8px;
  font-size: var(--fs-12); color: var(--text-muted); margin: 8px 0 0;
}
.share-date-input.hidden, .share-password-note.hidden { display: none; }

/* ── Connections (Claude / MCP access) ── */
/* No global `.hidden { display:none }` exists in this app — each element hidden
   via `.hidden` needs its own rule (same gotcha as the share controls). */
#mcp-details.hidden,
#mcp-token-reveal.hidden,
#mcp-add-form.hidden,
#mcp-add-cta.hidden { display: none; }
#mcp-token-reveal { margin-bottom: 14px; }   /* gap before the "Add another" CTA */
.mcp-field { margin-bottom: 18px; }
.mcp-field:last-child { margin-bottom: 0; }
.mcp-copy-row { display: flex; align-items: stretch; gap: 8px; }
.mcp-copy-row .share-field-control {
  flex: 1; min-width: 0;
  font-family: ui-monospace, Menlo, monospace; font-size: var(--fs-12);
  overflow-x: auto; white-space: nowrap;
}
.mcp-copy-row .settings-export-link {
  flex: none; align-self: stretch; white-space: nowrap;   /* match the field's height */
  display: inline-flex; align-items: center; justify-content: center;
}
.mcp-token-value { color: var(--text); font-weight: 600; }
.mcp-revoke-link {
  background: none; border: none; padding: 8px 0; cursor: pointer;
  font-size: var(--fs-13); font-weight: 600; color: var(--danger);
}
/* One-time-token warning — a banner so it's noticed, not a faint line of text. */
.mcp-warn-banner {
  display: flex; align-items: flex-start; gap: 9px;
  margin-top: 14px; padding: 11px 13px;
  background: var(--danger-bg); border-radius: var(--radius-sm, 8px);
  border: 1px solid color-mix(in srgb, var(--danger) 40%, transparent);
  font-size: var(--fs-13); line-height: 1.45; color: var(--text-2);
}
.mcp-warn-banner svg { flex: none; color: var(--danger); margin-top: 1px; }
.mcp-cli-label, #mcp-cli-label { margin-top: 14px; }
/* The trailing explainer under "Add a connection" is a direct child of the field;
   override .feedback-hint's negative top margin so it doesn't touch what's above. */
.mcp-field > .feedback-hint { margin-top: 16px; }
/* Connection rows — one per named MCP token. */
.mcp-conn-empty { font-size: var(--fs-13); color: var(--text-muted); margin: 0; }
.mcp-conn-row {
  display: flex; align-items: center; gap: 12px;
  padding: 12px 0; border-bottom: 1px solid var(--border);
}
.mcp-conn-row:first-child { border-top: 1px solid var(--border); }
.mcp-conn-main { flex: 1; min-width: 0; }
.mcp-conn-name {
  font-size: var(--fs-14); font-weight: 600; color: var(--text);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.mcp-conn-meta { font-size: var(--fs-12); color: var(--text-muted); margin-top: 2px; }
.mcp-conn-status { color: var(--text-muted); }
.mcp-conn-status.active { color: var(--buy, #16A34A); font-weight: 600; }
.mcp-conn-dot {
  display: inline-block; width: 7px; height: 7px; border-radius: 50%;
  background: var(--buy, #16A34A); margin-right: 5px; vertical-align: middle;
}
.mcp-conn-row .mcp-revoke-link { flex: none; padding: 4px 0; }
.share-inline-link {
  background: none; border: none; padding: 0; font-family: inherit;
  font-size: var(--fs-12); font-weight: 600; color: var(--danger); cursor: pointer;
}
.share-inline-link:hover { text-decoration: underline; }
.share-btn {
  width: 100%; padding: 12px; border-radius: 8px; margin-top: 8px;
  font-size: var(--fs-14); font-family: inherit; font-weight: 600; cursor: pointer;
  transition: background 0.1s, opacity 0.1s;
}
.share-btn-primary { background: var(--accent); color: var(--accent-fg); border: none; }
.share-btn-primary:hover { opacity: 0.9; }
.share-btn-danger { background: none; border: 1.5px solid var(--danger); color: var(--danger); }
.share-btn-danger:hover { background: var(--danger-bg); }
#share-active.hidden, #share-create-btn.hidden { display: none; }
/* No generic .hidden rule exists, and .icon-btn sets display — so hide explicitly. */
#share-tag-btn.hidden { display: none; }

/* Shared tag "collection" index on the public page */
.nv-tag-lg { font-size: var(--fs-16); font-weight: 600; color: var(--text-2); }
.note-view-back {
  display: inline-block; margin-bottom: 24px;
  font-size: var(--fs-13); color: var(--text-muted); text-decoration: none;
}
.note-view-back:hover { color: var(--text); }
.share-collection { display: flex; flex-direction: column; margin-top: 8px; }
.share-collection-item {
  display: block; padding: 16px 4px;
  border-bottom: 1px solid var(--divider);
  font-size: var(--fs-16); color: var(--text); text-decoration: none;
  transition: color 0.1s;
}
.share-collection-item:first-child { border-top: 1px solid var(--divider); }
.share-collection-item:hover { color: var(--accent); }

/* ── Standalone note view (share link) ─────────────────────────────────── */
.note-view {
  position: fixed; inset: 0; z-index: 300;
  background: var(--bg); overflow-y: auto;
  -webkit-overflow-scrolling: touch;
}
.note-view.hidden { display: none; }
body.note-view-mode .app { display: none; }
.note-view-header {
  position: sticky; top: 0; z-index: 1;
  display: flex; align-items: center; justify-content: space-between;
  padding: 12px 20px; height: 56px;
  background: var(--bg); border-bottom: 1px solid var(--divider);
}
.note-view-brand {
  display: flex; align-items: center; gap: 8px;
  font-size: var(--fs-15); font-weight: 700; letter-spacing: -0.02em;
  color: var(--text); text-decoration: none;
}
.note-view-brand img { border-radius: 8px; }
.note-view-copy {
  display: inline-flex; align-items: center; gap: 8px;
  padding: 8px 12px; border-radius: 8px;
  background: var(--surface); border: 1px solid var(--border);
  font-size: var(--fs-13); font-family: inherit; font-weight: 500; color: var(--text);
  cursor: pointer; transition: background 0.1s;
}
.note-view-copy:hover { background: var(--surface-2); }
.note-view-copy svg { color: var(--text-muted); }
/* Icon-only header buttons on the standalone share page (theme toggle + copy). */
.note-view-actions { display: flex; align-items: center; gap: 4px; }
.note-view-iconbtn {
  width: 36px; height: 36px; flex-shrink: 0;
  display: inline-flex; align-items: center; justify-content: center;
  background: none; border: none; border-radius: 8px;
  color: var(--text-2); cursor: pointer; transition: background 0.1s, color 0.1s;
}
.note-view-iconbtn:hover { background: var(--surface-2); color: var(--text); }
.note-view-iconbtn:active { opacity: 0.7; }
.note-view-iconbtn .icon-sun { display: none; }
[data-dark] .note-view-iconbtn .icon-sun { display: inline; }
[data-dark] .note-view-iconbtn .icon-moon { display: none; }
.note-view-article { max-width: 720px; margin: 0 auto; padding: 28px 24px 96px; }
.note-view-article h1 {
  font-size: var(--fs-28); font-weight: 700; letter-spacing: -0.03em;
  line-height: 1.25; color: var(--text); margin: 0 0 12px;
}
.note-view-tags { display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 16px; }
.note-view-tags.hidden { display: none; }
.note-view-tags .nv-tag { font-size: var(--fs-13); color: var(--text-muted); }
/* Reuse all the note rendering (lists, headings, code, hr, links…) but strip the
   editor-only sizing so it reads as a document, not a text field. */
.note-view .note-body-input { min-height: 0; padding: 0; border-top: none; }
.note-view-empty { color: var(--text-muted); font-size: var(--fs-15); }

/* Password gate for a protected share link */
.share-lock { max-width: 340px; margin: 8vh auto 0; text-align: center; }
.share-lock-icon { color: var(--text-muted); margin-bottom: 14px; }
.share-lock h1 { font-size: var(--fs-22); margin-bottom: 8px; }
.share-lock .note-view-empty { font-size: var(--fs-14); }
.share-lock-form { margin-top: 22px; display: flex; flex-direction: column; gap: 10px; }
.share-lock-input {
  width: 100%; padding: 12px 14px; border-radius: 8px;
  background: var(--surface); border: 1.5px solid var(--border);
  font-size: var(--fs-15); font-family: inherit; color: var(--text); outline: none;
}
.share-lock-input:focus { border-color: var(--border-mid); }
.share-lock-error { font-size: var(--fs-13); color: var(--danger); margin: 0; }
.share-lock-btn {
  width: 100%; padding: 12px; border-radius: 8px; border: none;
  background: var(--accent); color: var(--accent-fg);
  font-size: var(--fs-15); font-family: inherit; font-weight: 600; cursor: pointer;
}
.share-lock-btn:hover { opacity: 0.9; }

.tags-chips { display: flex; flex-wrap: wrap; gap: 4px; }
.editor-tag-chip {
  display: inline-flex; align-items: center; gap: 4px;
  font-size: var(--fs-13); color: var(--text-muted);
  background: var(--bg); border: 1px solid var(--border);
  border-radius: 8px; padding: 4px 8px 4px 8px;
}
.editor-tag-chip button {
  background: none; border: none; cursor: pointer;
  color: var(--text-faint); font-size: var(--fs-14); line-height: 1;
  padding: 0; display: flex; align-items: center;
  transition: color 0.1s;
}
.editor-tag-chip button:hover { color: var(--danger); }

.tag-input {
  flex: 1; min-width: 80px;
  background: none; border: none; outline: none;
  font-size: var(--fs-13); color: var(--text); font-family: inherit;
}
.tag-input::placeholder { color: var(--text-faint); }

.editor-empty-state {
  flex: 1; display: flex; flex-direction: column;
  align-items: center; justify-content: center; gap: 12px;
  color: var(--text-faint);
}
.editor-empty-state p { font-size: var(--fs-13); max-width: 280px; text-align: center; line-height: 1.6; }
.editor-empty-state.hidden { display: none; }
.editor-empty-cta {
  display: inline-flex; align-items: center; gap: 6px;
  margin-top: 4px; padding: 9px 16px 9px 13px;
  background: var(--accent); color: var(--accent-fg);
  border: none; border-radius: 9px; cursor: pointer;
  font-size: var(--fs-14); font-weight: 600; letter-spacing: -0.01em;
  transition: opacity 0.1s;
}
.editor-empty-cta:hover { opacity: 0.9; }
.editor-empty-cta:active { opacity: 0.75; }
.editor-empty-cta svg { width: 16px; height: 16px; }
.editor-body.hidden { display: none; }

/* ── Modals ──────────────────────────────────────────────────────────── */

.modal-overlay {
  position: fixed; inset: 0;
  background: rgba(0,0,0,0.3);
  display: flex; align-items: center; justify-content: center;
  z-index: 200;
  backdrop-filter: blur(2px);
}
.modal-overlay.hidden { display: none; }

.modal {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 16px;
  width: 340px; max-width: calc(100vw - 32px);
  box-shadow: 0 8px 40px rgba(0,0,0,0.18);
  overflow: hidden;
}

.modal-header {
  display: flex; align-items: center; justify-content: space-between;
  padding: 16px 16px 12px;
  font-size: var(--fs-14); font-weight: 600;
  border-bottom: 1px solid var(--divider);
}

.modal-body { padding: 12px 16px 16px; }

.modal-input {
  width: 100%; padding: 8px 12px;
  background: var(--bg); border: 1.5px solid var(--border);
  border-radius: 8px; outline: none;
  font-size: var(--fs-14); font-family: inherit; color: var(--text);
  margin-bottom: 12px;
  transition: border-color 0.15s;
}
.modal-input:focus { border-color: var(--border-mid); }
textarea.modal-input { resize: vertical; min-height: 88px; line-height: 1.5; }
.feedback-hint { font-size: var(--fs-12); color: var(--text-muted); margin: -4px 0 12px; }
/* Feedback panel: the global section-title has a 4px inset that only reads right
   above a bordered rows-card (General/Themes), not above the plain fields here —
   so drop the inset to line the title up with Message/inputs, and add breathing
   room before the first field (the default 8px felt cramped). */
#settings-panel-feedback .settings-group-title { padding-left: 0; margin-bottom: 18px; }

.modal-actions { display: flex; justify-content: flex-end; gap: 8px; }

.btn-secondary {
  padding: 8px 16px;
  background: none; border: 1.5px solid var(--border);
  border-radius: 8px; cursor: pointer;
  font-size: var(--fs-13); font-family: inherit; color: var(--text-2);
  transition: background 0.1s;
}
.btn-secondary:hover { background: var(--bg); }

.btn-primary {
  padding: 8px 16px;
  background: var(--accent); color: var(--accent-fg); border: none;
  border-radius: 8px; cursor: pointer;
  font-size: var(--fs-13); font-weight: 600; font-family: inherit;
  transition: opacity 0.1s;
}
.btn-primary:hover { opacity: 0.85; }

/* Move modal folder list */
/* A picker row is two separate buttons: the folder area ("move here") and a
   divided-off disclosure button ("show subfolders"). Splitting them makes the
   two actions distinct tap targets instead of a tiny chevron nested in the row. */
.move-folder-row {
  display: flex; align-items: stretch;
  border-radius: 8px; overflow: hidden;
}
.move-folder-select {
  flex: 1; min-width: 0;
  display: flex; align-items: center; gap: 8px;
  padding: 8px 8px;
  background: none; border: none; border-radius: 8px;
  font-size: var(--fs-13); font-family: inherit; color: var(--text);
  cursor: pointer; text-align: left;
  transition: background 0.08s;
}
.move-folder-select:hover:not(:disabled) { background: var(--bg); }
.move-folder-select:active:not(:disabled) { background: var(--border); }
.move-folder-select:disabled { cursor: default; }
.move-folder-row.current .move-folder-select { color: var(--text-faint); }
.move-folder-select svg { color: var(--text-muted); flex-shrink: 0; }
.move-folder-select small { color: var(--text-faint); flex-shrink: 0; }
.move-folder-name { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* Disclosure button — divided from the select area so it reads as its own tap
   target. Chevron points right when collapsed, rotates down when expanded. */
.move-folder-expand {
  flex-shrink: 0; width: 40px;
  display: flex; align-items: center; justify-content: center;
  background: none; border: none; border-left: 1px solid var(--divider);
  color: var(--text-muted); cursor: pointer;
  transition: background 0.08s, color 0.08s;
}
.move-folder-expand svg { transition: transform 0.15s; }
.move-folder-expand.open svg { transform: rotate(90deg); }
.move-folder-expand:hover { background: var(--bg); color: var(--text); }
.move-folder-expand:active { background: var(--border); }

/* Touch: taller rows + a wider disclosure zone so the two actions are easy to
   hit without overlapping (was the whole problem with the old tiny chevron). */
@media (max-width: 768px) {
  .move-folder-select { padding-top: 16px; padding-bottom: 16px; }
  .move-folder-expand { width: 56px; }
}
/* The list itself scrolls instead of growing past the modal / viewport. */
#move-folder-list { max-height: min(55vh, 380px); overflow-y: auto; }

/* Inline "New folder" control at the top of the move picker */
.move-folder-new { border-bottom: 1px solid var(--divider); margin-bottom: 4px; padding-bottom: 4px; }
/* The "New subfolder…" rows under an expanded folder are just list rows, not the
   top separator, so drop the divider/spacing the top-level control carries. */
.move-folder-new.nested { border-bottom: none; margin-bottom: 0; padding-bottom: 0; }
.move-folder-new.nested .move-folder-newbtn { color: var(--text-muted); font-size: var(--fs-13); }
.move-folder-new.nested .move-folder-newbtn:hover { color: var(--accent); }
.move-folder-newbtn {
  display: flex; align-items: center; gap: 8px; width: 100%;
  padding: 8px 8px; background: none; border: none; border-radius: 8px;
  font-size: var(--fs-13); font-family: inherit; color: var(--accent);
  cursor: pointer; text-align: left; transition: background 0.08s;
}
.move-folder-newbtn:hover { background: var(--bg); }
.move-folder-newbtn svg { flex-shrink: 0; }
.move-folder-newbtn.hidden { display: none; }
.move-folder-newform { display: flex; gap: 8px; padding: 4px; align-items: center; }
.move-folder-newform.hidden { display: none; }
.move-folder-newinput {
  flex: 1; min-width: 0; padding: 8px 12px;
  background: var(--bg); border: 1.5px solid var(--border); border-radius: 8px;
  font-size: var(--fs-13); font-family: inherit; color: var(--text); outline: none;
}
.move-folder-newinput:focus { border-color: var(--border-mid); }
.move-folder-newcreate { flex-shrink: 0; white-space: nowrap; padding: 8px 12px; font-size: var(--fs-13); }

/* ── Toast ───────────────────────────────────────────────────────────── */

.toast {
  position: fixed; bottom: 28px; left: 50%;
  transform: translateX(-50%) translateY(0);
  background: var(--text); color: var(--accent-fg);
  padding: 8px 20px; border-radius: 16px;
  font-size: var(--fs-13); font-weight: 500; white-space: nowrap;
  z-index: 900; pointer-events: none;
  opacity: 1; transition: opacity 0.25s, transform 0.25s;
}
.toast.hidden { opacity: 0; transform: translateX(-50%) translateY(6px); }
/* Action button (e.g. Undo) inside a toast — the toast itself is
   pointer-events:none, so re-enable events just on the button. */
.toast-action {
  margin-left: 14px; padding: 0; background: none; border: none;
  color: var(--accent-fg); font: inherit; font-weight: 700;
  text-decoration: underline; cursor: pointer; pointer-events: auto;
}

/* ── Drag & drop (desktop) ──────────────────────────────────────────────── */
/* The row left behind reads as a "lifted from here" placeholder — still
   legible (a light dim, not near-invisible — a 0.4 ghost failed contrast and
   was hard to see) with a dashed accent outline + faint accent wash marking
   its origin slot. The crisp "what am I dragging" cue is the cursor-following
   drag image. A valid drop target gets a stronger accent ring + tint so
   "drop here" reads clearly. All theme-token based. */
.dragging {
  opacity: 1;
  outline: 1.5px dashed var(--accent);
  outline-offset: -2px;
  border-radius: 8px;
  background: color-mix(in srgb, var(--accent) 8%, transparent);
}
/* The cursor-following drag image (via setDragImage) — a solid, fully opaque
   clone of the actual card/row, so it looks like the card you grabbed rather
   than the browser's translucent default snapshot (which CSS can't reach).
   Rendered off-screen only long enough for the browser to snapshot it. Given a
   solid surface + lifted shadow so it reads as picked up. Theme-token based. */
.drag-image {
  position: fixed; top: -1000px; left: 0; margin: 0;
  box-sizing: border-box;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 10px;
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.28);
  opacity: 1;
  pointer-events: none;
}
.folder-row.drop-target,
.tag-nav-item.drop-target {
  background: color-mix(in srgb, var(--accent) 18%, transparent) !important;
  box-shadow: inset 0 0 0 1.5px var(--accent);
}
/* Dropping a nested folder onto the Folders section (not a row) moves it to the
   top level. Ring the whole section rather than fill it, so it doesn't clash
   with the folder rows inside. */
#folders-section.drop-target {
  outline: 1.5px dashed var(--accent);
  outline-offset: -3px;
  border-radius: 8px;
  background: color-mix(in srgb, var(--accent) 6%, transparent);
}

/* Offline indicator — a small pill so it's clear edits won't save yet. */
.offline-pill {
  position: fixed; bottom: 28px; left: 50%; transform: translateX(-50%);
  display: flex; align-items: center; gap: 8px;
  background: var(--surface); color: var(--text-muted);
  border: 1px solid var(--border-mid); border-radius: 16px;
  padding: 8px 16px; font-size: var(--fs-12); font-weight: 500; white-space: nowrap;
  box-shadow: 0 2px 12px rgba(0,0,0,0.12);
  z-index: 890; pointer-events: none;
}
.offline-pill::before {
  content: ''; width: 7px; height: 7px; border-radius: 50%;
  background: var(--text-faint); flex-shrink: 0;
}
.offline-pill.hidden { display: none; }

/* ── Settings view ─────────────────────────────────────────────────────── */

/* Full-screen overlay. Body-level element with no transformed ancestors, so
   position:fixed resolves to the viewport — works identically on desktop and
   iOS Safari, independent of the sliding-pane layout underneath. */
.settings-view {
  position: fixed; inset: 0; z-index: 1000;
  display: flex; flex-direction: column;
  overflow: hidden;
  background: var(--bg);
  -webkit-font-smoothing: antialiased;
}
.settings-view.hidden { display: none; }

.settings-topbar {
  height: 52px; flex-shrink: 0;
  display: flex; align-items: center; justify-content: space-between;
  padding: 0 8px 0 16px;
  border-bottom: 1px solid var(--border);
  background: var(--surface);
}
.settings-topbar-title {
  font-size: var(--fs-14); font-weight: 700; letter-spacing: -0.01em; color: var(--text);
}
.settings-topbar-back {
  display: flex; align-items: center; gap: 4px;
  background: none; border: none; cursor: pointer;
  font-size: var(--fs-14); font-weight: 500; color: var(--text-2);
  font-family: inherit; padding: 4px 8px 4px 0;
  transition: color 0.1s; white-space: nowrap;
}
.settings-topbar-back:hover { color: var(--text); }
.settings-topbar-spacer { width: 60px; }

.settings-body {
  display: flex; flex: 1; overflow: hidden;
}

/* Category list — sidebar equivalent */
.settings-cat-pane {
  width: 180px; flex-shrink: 0;
  background: var(--surface-2);
  border-right: 1px solid var(--border);
  overflow-y: auto;
  padding: 12px 8px;
}
.settings-cat-nav { display: flex; flex-direction: column; gap: 4px; }
.settings-cat-item {
  display: flex; align-items: center; justify-content: space-between;
  width: 100%; padding: 8px 12px;
  background: none; border: none; border-radius: 8px;
  font-size: var(--fs-13); font-family: inherit; color: var(--text-2);
  cursor: pointer; text-align: left;
  transition: background 0.08s, color 0.08s;
}
.settings-cat-item:hover { background: var(--border); color: var(--text); }
.settings-cat-item.active,
.settings-cat-item.active:hover {
  background: color-mix(in srgb, var(--accent) 14%, transparent);
  color: var(--text); font-weight: 600;
}
.settings-cat-chev { color: var(--text-faint); flex-shrink: 0; display: none; }

/* Content pane — notes/editor pane equivalent. Full-width on purpose: this is
   the actual scroll container (overflow-y:auto), so it must span the whole
   pane or a scroll gesture over the gutter beside the capped content (below)
   would land on nothing and do nothing. The visual width cap lives one level
   down, on .settings-panel, not here. */
.settings-content-pane {
  flex: 1; overflow-y: auto;
  padding: 24px 28px 40px;
}
.settings-content-pane::-webkit-scrollbar { width: 3px; }
.settings-content-pane::-webkit-scrollbar-thumb { background: var(--border); border-radius: 8px; }

/* Panel (section content) — capped + centered so rows don't stretch
   edge-to-edge on wide desktop windows. (Tried anchor-left at a narrower
   720px cap first; on an actual wide/ultrawide monitor that read as too
   narrow AND unbalanced — centering only looked wrong at 720px because the
   box itself was too small for the leftover space it created. Wider cap +
   centered reads correctly instead.) Never binds on mobile — the viewport is
   already narrower than the cap. */
.settings-panel {
  display: flex;
  flex-direction: column;
  gap: 24px;
  max-width: 960px; margin: 0 auto;
}
.settings-panel.hidden { display: none; }

/* Subtle author credit, centered under the General panel. */
.settings-credit {
  text-align: center;
  font-size: var(--fs-13);
  color: var(--text-faint);
  margin-top: 8px;
}

/* iOS-style group */
.settings-group {}

.settings-group-title {
  font-size: var(--fs-11);
  font-weight: 700;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--text-muted);
  padding: 0 4px;
  margin-bottom: 8px;
}

/* Changelog / What's New */
.changelog-entry { padding: 16px 4px; border-bottom: 1px solid var(--divider); }
.changelog-entry:last-child { border-bottom: none; }
.changelog-head { display: flex; align-items: baseline; gap: 8px; margin-bottom: 8px; }
.changelog-version { font-size: var(--fs-14); font-weight: 600; color: var(--text); }
.changelog-date { font-size: var(--fs-12); color: var(--text-muted); }
.changelog-changes { list-style: none; display: flex; flex-direction: column; gap: 4px; }
.changelog-changes li {
  position: relative; padding-left: 16px;
  /* Matches .note-body-input's reading typography (size/line-height/family)
     so "What's New" reads like note content, not smaller UI chrome text. */
  font-size: var(--fs-16); color: var(--text-2); line-height: 1.7;
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
}
.changelog-changes li::before {
  content: '•'; position: absolute; left: 3px; top: -0.02em;
  color: var(--text-faint);
}

.settings-group-rows {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 12px;
  overflow: hidden;
}

/* Rows within a group */
.settings-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 16px 16px;
  gap: 16px;
  min-height: 52px;
}
.settings-row + .settings-row {
  border-top: 1px solid var(--divider);
}

.settings-row-label {
  font-size: var(--fs-16);
  color: var(--text);
  font-weight: 400;
}

.settings-row-desc {
  font-size: var(--fs-12);
  color: var(--text-muted);
  margin-top: 4px;
}

.settings-row-value {
  font-size: var(--fs-16);
  color: var(--text-muted);
}

/* Toggle switch */
.toggle-switch {
  position: relative; width: 44px; height: 26px; flex-shrink: 0;
  background: var(--border-mid); border: none; border-radius: 12px;
  cursor: pointer; transition: background 0.2s; padding: 0;
}
.toggle-switch.on { background: var(--accent); }
.toggle-switch::after {
  content: ''; position: absolute;
  width: 20px; height: 20px; background: #fff;
  border-radius: 50%; top: 3px; left: 3px;
  transition: transform 0.2s; box-shadow: 0 1px 3px rgba(0,0,0,0.2);
}
.toggle-switch.on::after { transform: translateX(18px); }

/* Tags list inside settings */
#settings-tags-list {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 12px;
  overflow: hidden;
}

.settings-tag-item {
  display: flex; align-items: center; gap: 8px;
  padding: 12px 16px;
  border-bottom: 1px solid var(--divider);
}
.settings-tag-item:last-child { border-bottom: none; }
.settings-tag-name { flex: 1; font-size: var(--fs-14); color: var(--text); }
.settings-tag-count { font-size: var(--fs-12); color: var(--text-muted); }
.settings-tag-delete {
  width: 28px; height: 28px;
  display: flex; align-items: center; justify-content: center;
  background: none; border: none; border-radius: 8px;
  color: var(--text-faint); cursor: pointer; flex-shrink: 0;
  transition: color 0.1s, background 0.1s;
}
.settings-tag-delete:hover { color: var(--danger); background: var(--danger-bg); }
.settings-tag-edit, .settings-tag-confirm-btn, .settings-tag-cancel-btn {
  width: 28px; height: 28px;
  display: flex; align-items: center; justify-content: center;
  background: none; border: none; border-radius: 8px;
  color: var(--text-faint); cursor: pointer; flex-shrink: 0;
  transition: color 0.1s, background 0.1s;
}
.settings-tag-edit:hover { color: var(--text); background: var(--border); }
.settings-tag-confirm-btn:hover { color: #16A34A; background: #F0FDF4; }
.settings-tag-cancel-btn:hover { color: var(--danger); background: var(--danger-bg); }
.settings-tag-rename-input {
  flex: 1; min-width: 0;
  font-size: var(--fs-14); font-family: inherit; color: var(--text);
  border: 1.5px solid var(--border-mid); border-radius: 8px;
  padding: 4px 8px; background: var(--bg); outline: none;
}
.settings-tag-rename-input:focus { border-color: var(--text-muted); }
.settings-empty { font-size: var(--fs-13); color: var(--text-faint); padding: 16px 16px; }

/* Segmented picker (list date, recents range, …) */
.segmented-picker {
  display: flex;
  border: 1.5px solid var(--border);
  border-radius: 8px;
  overflow: hidden;
  flex-shrink: 0;
}
.segmented-picker button {
  flex: 1; padding: 4px 12px;
  background: none; border: none;
  font-size: var(--fs-12); font-family: inherit; color: var(--text-muted);
  cursor: pointer; transition: background 0.1s, color 0.1s;
  white-space: nowrap;
}
.segmented-picker button + button { border-left: 1.5px solid var(--border); }
.segmented-picker button.active { background: var(--accent); color: var(--accent-fg); }

/* Export link */
.settings-export-link {
  font-size: var(--fs-13); font-weight: 500; color: var(--text);
  background: var(--bg); border: 1.5px solid var(--border);
  border-radius: 8px; padding: 8px 12px; text-decoration: none;
  transition: background 0.1s; white-space: nowrap; flex-shrink: 0;
}
.settings-export-link:hover { background: var(--border); }

/* ── Theme picker ────────────────────────────────────────────────────── */

.theme-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));
  gap: 12px;
  padding: 0 8px 8px;
}
.theme-card {
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 14px 16px;
  border-radius: 10px;
  border: 1.5px solid var(--border);
  cursor: pointer;
  transition: background 0.08s, border-color 0.08s;
  min-height: 44px;
}
.theme-card:hover { background: var(--surface-2); border-color: var(--border-mid); }
.theme-card.active {
  background: var(--surface-2);
  border-color: var(--accent);
}
.theme-swatch {
  display: flex;
  border-radius: 8px;
  overflow: hidden;
  width: 52px;
  height: 34px;
  flex-shrink: 0;
  border: 1px solid rgba(128,128,128,0.2);
}
.theme-swatch span { flex: 1; display: block; }
.theme-card-name {
  flex: 1;
  font-size: var(--fs-14);
  font-weight: 500;
  color: var(--text);
}
.theme-card-check {
  width: 16px; height: 16px;
  border-radius: 50%;
  background: var(--accent);
  display: none;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
}
.theme-card.active .theme-card-check { display: flex; }
.theme-card-check svg { display: block; }

/* ── Subfolder section toggle (notes pane) ──────────────────────────── */

.subfolder-section-toggle {
  display: flex; align-items: center; gap: 8px;
  width: 100%; padding: 12px 16px 8px;
  font-size: var(--fs-10); font-weight: 700; letter-spacing: 0.06em;
  text-transform: uppercase; color: var(--text-faint);
  cursor: pointer; user-select: none;
  background: none; border: none; font-family: inherit; text-align: left;
  transition: color 0.1s;
}
.subfolder-section-toggle:hover { color: var(--text-muted); }
.subfolder-toggle-chev { transition: transform 0.15s; flex-shrink: 0; }
.subfolder-toggle-chev.open { transform: rotate(90deg); }
.subfolder-section-count { margin-left: auto; font-weight: 400; }

/* ── Folder context menu ─────────────────────────────────────────────── */

.folder-ctx-menu {
  position: fixed;
  background: var(--surface);
  border: 1.5px solid var(--border);
  border-radius: 12px;
  padding: 4px;
  min-width: 172px;
  box-shadow: 0 4px 24px rgba(0,0,0,0.16);
  z-index: 500;
}
.folder-ctx-menu button {
  display: block; width: 100%;
  padding: 12px 16px; text-align: left;
  background: none; border: none; border-radius: 8px;
  font-size: var(--fs-15); font-family: inherit; color: var(--text);
  cursor: pointer; transition: background 0.08s;
}
.folder-ctx-menu button:active { background: var(--border); }
.folder-ctx-menu button.danger { color: var(--danger); }

/* ── Desktop overrides ───────────────────────────────────────────────── */

/* Focus-mode buttons: both hidden by default (turned on for desktop below).
   The enter button lives in the sidebar header; the reveal/exit button lives in
   the editor toolbar and only appears in focus mode (when the sidebar — and its
   enter button — are hidden). These come BEFORE the desktop media query so the
   media query's `display: inline-flex` wins by source order on wide screens —
   media queries add no specificity, so order is what decides. */
.focus-toggle-btn,
.focus-reveal-btn { display: none; }

@media (min-width: 769px) {
  .notes-pane-search { display: none; }

  /* ── Focus writing mode (desktop only) ─────────────────────────────── */
  .focus-toggle-btn { display: inline-flex; }               /* enter (sidebar header) */
  .app.focus-mode .focus-toggle-btn { display: none; }      /* sidebar's hidden anyway, but be explicit */
  .app.focus-mode .focus-reveal-btn { display: inline-flex; } /* exit (editor toolbar) */

  .app.focus-mode .sidebar,
  .app.focus-mode .notes-pane { display: none; }

  /* In focus mode "go back" would just land on a blank editor — hide the chevron
     (the panel/reveal button is the way out of focus). */
  .app.focus-mode #editor-back-btn { display: none; }

  /* Cap the writing column at 750px in BOTH modes (not just focus) — a
     comfortable reading measure whether the side panes are showing or not. The
     bar's own inset (below) is derived from this same width, so the controls
     stay aligned to the text. */
  .note-title-input,
  .note-tags-row,
  .note-dates,
  .note-body-wrap {
    max-width: 750px;
    margin-left: auto; margin-right: auto;
    width: 100%;
  }
}

/* ── Mobile ──────────────────────────────────────────────────────────── */

@media (max-width: 768px) {
  .app {
    display: block;
    position: relative;
    overflow: hidden;
    /* Height/offset are driven by the visualViewport API (see syncAppViewport
       in app.js) so the whole shell always exactly overlays the space *above*
       the on-screen keyboard. This is what stops iOS from window-scrolling to
       reveal the caret — with the editor already fitting the visible area, the
       caret is reachable via .editor-body's own scroll and the header/format
       bar never get dragged off-screen. Falls back to 100dvh where the API is
       unavailable. */
    height: var(--app-h, 100dvh);
    top: var(--app-top, 0px);
  }

  .sidebar,
  .notes-pane,
  .editor-pane {
    position: absolute; inset: 0;
    width: 100%; height: 100%;
    transition: transform 0.28s cubic-bezier(0.4, 0, 0.2, 1);
  }

  .sidebar    { transform: translateX(0);    z-index: 3; }
  .notes-pane { transform: translateX(100%); z-index: 2; }
  .editor-pane { transform: translateX(100%); z-index: 1; }

  /* The panes are transformed here (for the slide nav), so each is its own
     stacking context at z-index 1–3. That traps every floating menu inside a
     pane BELOW the full-screen backdrop (z-index 95), so on mobile the backdrop
     paints over the open menu and swallows the tap — nothing happens when you
     tap Delete/Share/etc. Drop the backdrop on mobile: the menus render crisp
     and tappable, and outsideMenuGuard (document-level) still dismisses them on
     an outside tap. Tradeoff: no dim overlay on mobile. */
  .menu-backdrop { display: none; }

  .app[data-view="notes"] .sidebar    { transform: translateX(-100%); }
  .app[data-view="notes"] .notes-pane { transform: translateX(0); }
  .app[data-view="notes"] .editor-pane { transform: translateX(100%); }

  .app[data-view="editor"] .sidebar    { transform: translateX(-100%); }
  .app[data-view="editor"] .notes-pane { transform: translateX(-100%); }
  .app[data-view="editor"] .editor-pane { transform: translateX(0); }

  .back-btn { display: inline-flex; }
  .notes-pane-header { padding: 0 8px; }

  .editor-pane { border-right: none; display: flex; flex-direction: column; }
  .editor-toolbar { flex-shrink: 0; position: sticky; top: 0; z-index: 10; background: var(--surface); }
  .editor-body { flex: 1; overflow-y: auto; -webkit-overflow-scrolling: touch; display: flex; flex-direction: column; }
  .note-title-input { flex-shrink: 0; padding: 20px 20px 12px; font-size: var(--fs-28); }
  .note-tags-row { padding: 0 20px 12px; }
  .note-body-input { flex: none; min-height: calc(100dvh - 210px); padding: 16px 20px max(env(safe-area-inset-bottom), 24px); font-size: var(--fs-17); line-height: 1.75; }
  .note-body-placeholder { top: 14px; left: 20px; right: 20px; font-size: var(--fs-17); line-height: 1.75; }

  /* Line the search icon up under the header's back chevron. The chevron glyph
     sits at 8px (header padding) + (44px tap target − 18px glyph)/2 = 21px in;
     the search bar's default 12px inset read as misaligned (icon too far left). */
  .notes-pane-search { padding-left: 21px; }
  .notes-pane-search input { font-size: var(--fs-16); }

  input, textarea, .modal-input { font-size: var(--fs-16); }

  .icon-btn { width: 44px; height: 44px; border-radius: 12px; }
  .icon-btn svg { width: 18px; height: 18px; }

  /* The icon buttons are 44px tall here (vs 30px on desktop), so the open bar
     must be tall enough to hold a 44px button plus its 12+12 vertical padding —
     otherwise flex-end anchoring clips the button's top. */
  .sticky-format-bar.open { max-height: 68px; }

  .sidebar-header { min-height: 64px; padding: 0 12px 0 20px; }
  .app-title { font-size: var(--fs-18); }
  .notes-pane-header { height: 64px; padding: 0 8px; }
  .editor-toolbar { height: 64px; }
  .sidebar-search { padding: 12px 16px 12px 24px; gap: 12px; }
  .search-clear { width: 32px; height: 32px; }
  .search-clear svg { width: 16px; height: 16px; }
  .sidebar-search input { font-size: var(--fs-16); }

  .nav-item     { min-height: 48px; font-size: var(--fs-16); padding: 0 36px 0 16px; gap: 12px; }
  .folder-row   { min-height: 48px; }
  .folder-btn   { padding: 12px 4px; font-size: var(--fs-16); gap: 12px; }
  .tag-nav-item { min-height: 48px; font-size: var(--fs-16); padding: 8px 36px 8px 16px; }
  .year-nav-item { min-height: 48px; font-size: var(--fs-16); padding: 8px 36px 8px 16px; }
  .tag-pin-btn  { opacity: 1; width: 32px; height: 32px; }

  /* No persistent "selected" highlight in the mobile sidebar. On mobile the
     sidebar is a drill-down view you navigate *away* from on tap, so a lingering
     accent-tinted active row is misleading (there's no split-pane showing the
     open destination alongside it). Selected state stays desktop-only. */
  .nav-item.active, .nav-item.active:hover,
  .tag-nav-item.active, .tag-nav-item.active:hover,
  .year-nav-item.active, .year-nav-item.active:hover,
  .folder-row.active, .folder-row.active:hover {
    background: none; color: var(--text-2); font-weight: 400;
  }
  .nav-item.active .nav-icon { color: var(--text-muted); }
  .tag-nav-item.active .tag-hash { color: var(--text-faint); }
  .year-nav-item.active { font-weight: 400; }
  .folder-row.active .folder-btn { color: var(--text-2); font-weight: 400; }
  .folder-row.active .folder-btn svg { color: var(--text-muted); }

  .note-item { padding: 16px 20px; }
  .note-item-title { font-size: var(--fs-15); }
  .note-item-preview { font-size: var(--fs-13); }
  .note-item-meta { font-size: var(--fs-12); }

  .folder-list-item { min-height: 52px; padding: 16px 20px; }
  .folder-list-item svg { width: 16px; height: 16px; }

  .subfolder-section-toggle { min-height: 44px; padding: 12px 20px 8px; font-size: var(--fs-11); }

  .pane-dropdown button { min-height: 44px; padding: 12px 16px; font-size: var(--fs-15); }
  .overflow-menu button { min-height: 44px; padding: 12px 16px; font-size: var(--fs-15); }

  .folder-kebab { opacity: 1; width: 44px; height: 44px; }

  .resize-handle { display: none; }

  .fmt-btn { width: 40px; height: 40px; }

  /* Settings view — mobile overrides (drill-down like notes navigation) */
  .settings-topbar {
    display: grid;
    grid-template-columns: 1fr auto 1fr;
    align-items: center;
    padding: 0 8px;
  }
  .settings-topbar-title { text-align: center; font-size: var(--fs-15); font-weight: 600; justify-self: center; }
  .settings-topbar-back { display: flex; justify-self: start; }
  .settings-topbar-spacer { justify-self: end; }

  /* Category pane becomes the full-screen list */
  .settings-cat-pane {
    width: 100%; border-right: none; background: var(--bg);
    padding: 20px 16px 40px;
  }
  .settings-cat-nav {
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: 12px;
    overflow: hidden;
    gap: 0;
  }
  .settings-cat-item {
    border-radius: 0; padding: 0 12px 0 16px;
    min-height: 48px; font-size: var(--fs-16);
    border-bottom: 1px solid var(--divider);
  }
  .settings-cat-item:last-child { border-bottom: none; }
  .settings-cat-item:hover { background: var(--surface); color: var(--text); }
  .settings-cat-chev { display: block; }

  /* Sliding drill-down — same pattern as the main app's three panes */
  .settings-body { position: relative; overflow: hidden; }
  .settings-cat-pane,
  .settings-content-pane {
    position: absolute; inset: 0;
    overflow-y: auto;
    transition: transform 0.28s cubic-bezier(0.4, 0, 0.2, 1);
  }
  /* Padding must be IDENTICAL in the list and detail states. If it only applies in
     one state (as it used to, in the detail rule below), it snaps at the instant
     you navigate — down 4px / right 12px — and that jump layered on the horizontal
     slide reads as diagonal motion. Set it here so both states share it → the slide
     is purely along the x-axis. */
  .settings-content-pane { padding: 20px 16px 40px; }
  .settings-view[data-pane="list"]   .settings-cat-pane     { transform: translateX(0); }
  .settings-view[data-pane="list"]   .settings-content-pane { transform: translateX(100%); }
  .settings-view[data-pane="detail"] .settings-cat-pane     { transform: translateX(-100%); }
  .settings-view[data-pane="detail"] .settings-content-pane { transform: translateX(0); }

  /* The section detail already shows its name in the top bar, so a panel heading
     that just repeats it (Report a bug / Send feedback / What's New) is redundant
     on mobile — hide it. Sub-group labels (General's Notes List/Editor/Sidebar,
     Themes' Built-in, etc.) are NOT tagged with this class, so they stay. */
  .settings-page-heading { display: none; }

  .settings-row { min-height: 48px; }
  .settings-row-label { font-size: var(--fs-16); }

  /* Centered modals. Sized to the visual viewport (same --app-h/--app-top vars
     the shell uses) rather than the full screen, so when a keyboard is open the
     modal centers in the space *above* it — a modal with an input (link, folder,
     new subfolder) stays fully visible and typable instead of being hidden
     behind the keyboard. Falls back to full height when no keyboard is up. */
  .modal-overlay {
    align-items: center;
    top: var(--app-top, 0px);
    height: var(--app-h, 100dvh);
    bottom: auto;
  }
}

/* ── Multi-select ─────────────────────────────────────────────────────── */

.select-btn {
  width: 30px; height: 30px; flex-shrink: 0;
  display: inline-flex; align-items: center; justify-content: center;
  color: var(--text-muted); background: none; border: none;
  border-radius: 8px; cursor: pointer;
  transition: background 0.1s, color 0.1s;
}
.select-btn:hover { background: var(--border); color: var(--text); }

.select-done-btn {
  display: none;
  padding: 4px 8px;
  font-size: var(--fs-12); font-weight: 600; font-family: inherit;
  color: var(--text); background: none; border: none;
  border-radius: 8px; cursor: pointer;
  white-space: nowrap;
}

.notes-pane.select-mode .pane-dropdown-wrapper { display: none; }
.notes-pane.select-mode .select-btn { display: none; }
.notes-pane.select-mode .select-done-btn { display: block; }

.note-checkbox {
  -webkit-appearance: none; appearance: none;
  position: absolute; left: 14px; top: 50%; transform: translateY(-50%);
  width: 20px; height: 20px; margin: 0; padding: 0; box-sizing: border-box;
  border: 1.5px solid var(--border-mid); border-radius: 50%;
  background: var(--surface);
  display: grid; place-content: center;
  pointer-events: none;
  transition: background 0.12s, border-color 0.12s;
}
.note-checkbox::before {
  content: '';
  width: 4px; height: 8px;
  border: 2px solid var(--accent-fg);
  border-top: none; border-left: none;
  transform: rotate(45deg) translateY(-1px);
  opacity: 0;
}
.note-checkbox:checked { background: var(--accent); border-color: var(--accent); }
.note-checkbox:checked::before { opacity: 1; }
.notes-pane.select-mode .note-item { padding-left: 48px; }
.note-item.selected { background: var(--surface-2); }

/* Bulk action bar */
.bulk-action-bar {
  display: flex; flex-direction: column; gap: 12px;
  padding: 12px 16px;
  border-top: 1px solid var(--border);
  background: var(--surface); flex-shrink: 0;
  position: relative;
}
.bulk-action-bar.hidden { display: none; }
.bulk-main { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
.bulk-main.hidden { display: none; }
.bulk-count { font-size: var(--fs-13); color: var(--text-muted); flex: 1; }
.bulk-actions { display: flex; gap: 8px; }
.bulk-action-btn {
  padding: 8px 12px;
  font-size: var(--fs-13); font-weight: 500; font-family: inherit;
  border: 1.5px solid var(--border-mid); border-radius: 8px;
  background: var(--surface); color: var(--text);
  cursor: pointer; transition: background 0.1s, opacity 0.1s;
  white-space: nowrap;
}
.bulk-action-btn:hover { background: var(--surface-2); }
.bulk-action-btn.danger { color: #DC2626; border-color: #DC2626; }
.bulk-action-btn.danger:hover { background: #fef2f2; }
.bulk-action-btn.primary { background: var(--accent); color: var(--accent-fg); border-color: var(--accent); }
.bulk-action-btn.primary:hover { opacity: 0.85; background: var(--accent); }

.bulk-tag-panel { display: flex; flex-direction: column; gap: 8px; }
.bulk-tag-panel.hidden { display: none; }
.bulk-tag-input-wrap {
  display: flex; flex-wrap: wrap; align-items: center; gap: 4px;
  background: var(--bg); border: 1.5px solid var(--border-mid);
  border-radius: 8px; padding: 8px 12px; min-height: 38px; cursor: text;
}
.bulk-tag-chip {
  display: inline-flex; align-items: center; gap: 4px;
  background: var(--border); border-radius: 8px;
  padding: 4px 8px; font-size: var(--fs-12); color: var(--text-2); white-space: nowrap;
}
.bulk-tag-chip button {
  background: none; border: none; padding: 0; margin: 0; line-height: 1;
  cursor: pointer; color: var(--text-faint); font-size: var(--fs-14); display: flex;
}
.bulk-tag-input {
  flex: 1; min-width: 80px; border: none; background: none; outline: none;
  font-size: var(--fs-13); color: var(--text); font-family: inherit;
}
.bulk-tag-suggestions {
  position: absolute; bottom: calc(100% + 4px); left: 0; right: 0;
  background: var(--surface); border: 1.5px solid var(--border);
  border-radius: 12px; padding: 4px; max-height: 160px; overflow-y: auto;
  box-shadow: 0 -4px 20px rgba(0,0,0,0.1); z-index: 200;
}
.bulk-tag-suggestions.hidden { display: none; }
.bulk-tag-suggestion-item {
  display: block; width: 100%; padding: 8px 12px; text-align: left;
  background: none; border: none; border-radius: 8px;
  font-size: var(--fs-13); color: var(--text); cursor: pointer; font-family: inherit;
}
.bulk-tag-suggestion-item:hover { background: var(--surface-2); }
.bulk-tag-panel-actions { display: flex; gap: 8px; justify-content: flex-end; }

@media (max-width: 768px) {
  .bulk-action-bar { padding: 12px 16px; }
  .bulk-action-btn { padding: 8px 12px; font-size: var(--fs-14); min-height: 44px; }
  .bulk-tag-input { font-size: var(--fs-16); }
  .note-checkbox { left: 16px; width: 22px; height: 22px; }
  .notes-pane.select-mode .note-item { padding-left: 52px; }
}

/* ── Touch devices: no persistent hover ─────────────────────────────── */
@media (hover: none) {
  /* Touch retains :hover after a tap, so hover must be a true no-op — reset to
     the element's RESTING color (--text-2), not --text-muted (which is lighter,
     and made tapped tags fade and stay faded). No intermediary state on touch:
     default at rest, :active only while the finger is down. */
  .nav-item:hover        { background: none; color: var(--text-2); }
  .tag-nav-item:hover    { background: none; color: var(--text-2); }
  .folder-row:hover      { background: none; }
  .folder-row:hover .folder-kebab { opacity: 0; }
  .note-item:hover       { background: none; }
  .note-item.active:hover { background: var(--bg); }
  .folder-list-item:hover { background: none; }
  .icon-btn:hover        { background: none; color: var(--text-muted); }
  .select-btn:hover      { color: var(--text-muted); }
  .bulk-action-btn:hover { background: none; }
  .bulk-action-btn.danger:hover  { background: none; }
  .bulk-action-btn.primary:hover { background: var(--accent); opacity: 1; }

  .nav-item:active       { background: var(--border); }
  .tag-nav-item:active   { background: var(--border); }
  .year-nav-item:active  { background: var(--border); }
  .folder-row:active     { background: var(--border); }
  .note-item:active      { background: var(--surface-2); }
  .folder-list-item:active { background: var(--surface-2); }
  .fmt-btn:active        { background: rgba(255,255,255,0.12); color: #fff; }
}

/* ── Trash ──────────────────────────────────────────────────────────── */

/* Sidebar trash nav item — slightly muted at rest; .nav-item.active handles
   the highlighted "currently open" state, same as every other nav row. */
.nav-trash { color: var(--text-muted); }

/* Notes pane in trash context */
.notes-pane[data-ctx="trash"] #sort-btn,
.notes-pane[data-ctx="trash"] #new-note-btn,
.notes-pane[data-ctx="trash"] .select-btn,
.notes-pane[data-ctx="trash"] .notes-pane-search { display: none; }
.notes-pane[data-ctx="trash"] .empty-trash-btn { display: inline-flex; }

/* Empty Trash button */
.empty-trash-btn {
  display: none; align-items: center;
  padding: 0 12px; height: 30px;
  font-size: var(--fs-12); font-weight: 500; font-family: inherit;
  color: var(--danger); border: 1.5px solid var(--danger);
  border-radius: 8px; background: none; cursor: pointer;
  white-space: nowrap; transition: background 0.1s;
}
.empty-trash-btn:hover { background: var(--danger-bg); }
.empty-trash-btn.hidden { display: none !important; }

/* Trash note items in list */
.trash-note-item { cursor: pointer; }
.trash-note-footer {
  display: flex; align-items: center; justify-content: space-between;
  gap: 8px; margin-top: 4px; flex-wrap: wrap;
}
.trash-note-time { font-size: var(--fs-11); color: var(--text-muted); flex-shrink: 0; }
.trash-note-actions { display: flex; gap: 4px; }
.trash-restore-btn, .trash-delete-btn {
  padding: 4px 8px; font-size: var(--fs-11); font-weight: 500; font-family: inherit;
  border-radius: 8px; border: 1.5px solid var(--border-mid);
  background: var(--surface); color: var(--text); cursor: pointer;
  transition: background 0.1s;
}
.trash-restore-btn:hover { background: var(--surface-2); }
.trash-delete-btn { color: var(--danger); border-color: var(--danger); }
.trash-delete-btn:hover { background: var(--danger-bg); }

/* Trash banner inside editor */
.trash-banner {
  display: flex; align-items: center; gap: 8px;
  padding: 8px 16px; margin: 0 0 12px;
  background: var(--danger-bg);
  border-bottom: 1px solid color-mix(in srgb, var(--danger) 20%, transparent);
  font-size: var(--fs-12); color: var(--danger);
}
.trash-banner.hidden { display: none; }
.trash-banner-label { font-weight: 500; flex: 1; }
.trash-banner-actions { display: flex; gap: 8px; }
.trash-banner-restore, .trash-banner-delete {
  padding: 4px 12px; font-size: var(--fs-12); font-weight: 500; font-family: inherit;
  border-radius: 8px; cursor: pointer; transition: opacity 0.1s;
}
.trash-banner-restore {
  background: var(--accent); color: var(--accent-fg); border: none;
}
.trash-banner-restore:hover { opacity: 0.85; }
.trash-banner-delete {
  background: none; border: 1.5px solid var(--danger); color: var(--danger);
}
.trash-banner-delete:hover { background: color-mix(in srgb, var(--danger) 10%, transparent); }

/* Note body readonly in trash */
.note-body-input[contenteditable="false"] { opacity: 0.7; cursor: default; }

/* ── iPad landscape ─────────────────────────────────────────────────── */
@media (hover: none) and (min-width: 769px) {
  .nav-item     { min-height: 44px; }
  .folder-row   { min-height: 44px; }
  .tag-nav-item { min-height: 44px; }
  .year-nav-item { min-height: 44px; }
  .note-item    { padding: 16px 16px; }
  .icon-btn     { width: 40px; height: 40px; }
  .bulk-action-btn { min-height: 44px; padding: 0 16px; }
}
