/* ── Apps panels (Notes, Todo, Goals, Expenses) ──────────────────────────
   Loaded AFTER style.css — overrides and shared styles for the 4 custom panels.

   Reference the Hermes WebUI theme via CSS variables throughout.
   Never hardcode hex values.
*/

/* ── Fix: --panel was used extensively but never defined in style.css ── */
:root {
  --panel: var(--surface);
  /* Shared app-panel tokens */
  --app-bg-subtle: color-mix(in srgb, var(--surface) 60%, transparent);
  --app-hover: var(--hover-bg);
  /* Active row uses a stronger accent mix so it's distinguishable from
     the lighter --accent-bg tag chips that may sit on top of it. */
  --app-active: color-mix(in srgb, var(--accent) 14%, var(--surface));
  --app-tag-bg: var(--accent-bg);
  /* Use --text (not --accent-text) so chips stay readable on skins where
     --accent-text == --accent (gold-on-gold-tint problem). */
  --app-tag-text: var(--text);
  /* Stronger background for tag chips sitting on an active row so they
     don't blend into --app-active. */
  --app-tag-bg-strong: color-mix(in srgb, var(--accent) 22%, transparent);
  --app-tag-remove: var(--muted);
  --app-trash-bg: color-mix(in srgb, var(--error) 8%, transparent);
  --app-trash-border: color-mix(in srgb, var(--error) 20%, var(--border));
  --app-chip-radius: 6px;
  /* Note color tokens — derived from skin tokens so the palette tracks
     the active skin instead of clashing with it. */
  --note-color-red: color-mix(in srgb, var(--error) 80%, var(--surface));
  --note-color-teal: color-mix(in srgb, var(--success) 70%, var(--accent));
  --note-color-blue: var(--accent);
  --note-color-salmon: color-mix(in srgb, var(--warning) 80%, var(--text));
  --note-color-plum: color-mix(in srgb, var(--accent) 60%, var(--error));
  /* Heatmap tokens */
  --heatmap-empty: color-mix(in srgb, var(--border) 40%, transparent);
  --heatmap-fill-1: color-mix(in srgb, var(--cny-income) 25%, transparent);
  --heatmap-fill-2: color-mix(in srgb, var(--cny-income) 50%, var(--cny-income) 15%);
  --heatmap-fill-3: color-mix(in srgb, var(--cny-income) 75%, var(--cny-income) 30%);
  --heatmap-fill-4: var(--cny-income);
  /* Donut/sparkline tokens */
  --chart-accent: var(--accent);
  --chart-income: var(--cny-income);
  --chart-expense: var(--cny-expense);
  --chart-bg: color-mix(in srgb, var(--border) 30%, transparent);
}
:root.dark {
  --panel: var(--surface);
  --app-bg-subtle: color-mix(in srgb, var(--surface) 40%, transparent);
  --app-hover: var(--hover-bg);
  --app-active: color-mix(in srgb, var(--accent) 18%, var(--surface));
  --app-tag-bg-strong: color-mix(in srgb, var(--accent) 28%, transparent);
  --heatmap-empty: color-mix(in srgb, var(--border) 30%, transparent);
  /* Dark note colors — same derivations, lighter mixing for visibility
     against the dark surface. */
  --note-color-red: color-mix(in srgb, var(--error) 75%, var(--text));
  --note-color-teal: color-mix(in srgb, var(--success) 60%, var(--accent));
  --note-color-blue: var(--accent);
  --note-color-salmon: color-mix(in srgb, var(--warning) 70%, var(--text));
  --note-color-plum: color-mix(in srgb, var(--accent) 55%, var(--error));
}

/* ── Shared: tag chips ─────────────────────────────────────────────────── */
.apps-tag {
  display: inline-flex;
  align-items: center;
  gap: 3px;
  padding: 2px 8px;
  border-radius: var(--app-chip-radius);
  background: var(--app-tag-bg);
  color: var(--app-tag-text);
  font-size: var(--font-size-xs);
  line-height: 1.5;
  white-space: nowrap;
  cursor: default;
  transition: background .15s;
}
.apps-tag button {
  background: none;
  border: none;
  color: var(--app-tag-remove);
  cursor: pointer;
  font-size: 13px;
  line-height: 1;
  padding: 0 1px;
  opacity: .5;
  transition: opacity .15s;
}
.apps-tag button:hover { opacity: 1; }

/* When a tag chip sits inside an active/selected row (which is tinted with
   --app-active), bump its own background so it doesn't blend in. Each
   panel marks its active row container with a `.active` class that contains
   `.apps-tag` chips. */
.notes-list-item.active .apps-tag,
.todo-card.active .apps-tag,
.expense-row.active .apps-tag,
.goals-card.active .apps-tag {
  background: var(--app-tag-bg-strong);
}

.apps-tag-input-wrap {
  display: flex;
  flex-wrap: wrap;
  gap: 4px;
  padding: 6px 8px;
  border: 1px solid var(--border);
  /* Match the modal-input radius (8px) so the wrap visually aligns with
     the surrounding ``select`` / ``input`` rows; --radius-sm is 4px in
     the default theme which would look mismatched. */
  border-radius: var(--radius-md, 8px);
  background: var(--input-bg);
  min-height: 30px;
  align-items: center;
  box-sizing: border-box;
  transition: border-color .15s, box-shadow .15s;
}
/* Mirror the focus style of regular modal inputs so the whole wrap (not
   just the nested input) gets the accent ring on focus-within. */
.apps-tag-input-wrap:focus-within {
  border-color: var(--accent);
  box-shadow: 0 0 0 1px var(--accent);
}
.apps-tag-input-wrap input {
  border: none;
  background: none;
  color: var(--text);
  font-size: var(--font-size-sm);
  outline: none;
  min-width: 60px;
  flex: 1;
  padding: 2px 0;
}
/* Override the global ``.expense-modal-body input`` rule (style.css ~5114)
   which would otherwise re-apply a border, padding, and a focus accent
   ring around the nested text input — making the wrap look like a box
   inside a box on click. We need higher specificity and the focus
   variant to fully neutralise both the resting AND focus styles. */
.apps-tag-input-wrap input,
.apps-tag-input-wrap input:focus {
  width: auto;
  border: none;
  border-radius: 0;
  background: transparent;
  padding: 2px 0;
  box-shadow: none;
}
.apps-tag-input-wrap input::placeholder { color: var(--muted); font-size: var(--font-size-xs); }

.apps-tag-dropdown {
  position: absolute;
  top: 100%;
  left: 0;
  right: 0;
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  box-shadow: 0 4px 12px rgba(0,0,0,.12);
  max-height: 140px;
  overflow-y: auto;
  z-index: 100;
  display: none;
}
.apps-tag-dropdown.show { display: block; }
.apps-tag-dropdown div {
  padding: 6px 10px;
  font-size: var(--font-size-sm);
  color: var(--text);
  cursor: pointer;
  transition: background .1s;
}
.apps-tag-dropdown div:hover,
.apps-tag-dropdown div.highlighted { background: var(--app-hover); }

/* ── Shared: trash / restore ───────────────────────────────────────────── */
.apps-trash-btn {
  width: 28px; height: 28px;
  border-radius: var(--radius-sm);
  border: 1px solid var(--border);
  background: var(--panel);
  color: var(--muted);
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 13px;
  transition: background .15s, color .15s;
}
.apps-trash-btn:hover {
  background: var(--app-trash-bg);
  color: var(--error);
  border-color: var(--app-trash-border);
}
.apps-trash-btn.active {
  background: var(--app-trash-bg);
  color: var(--error);
  border-color: var(--error);
}

/* Inline trash toggle (sidebar switch under Group filter) */
.apps-sidebar-toggle-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  padding: 6px 2px 2px;
  margin-top: 2px;
}
.apps-sidebar-toggle-label {
  font-size: 10px;
  font-weight: 600;
  color: var(--muted);
  text-transform: uppercase;
  letter-spacing: 0.05em;
  user-select: none;
}
.apps-toggle-switch {
  flex-shrink: 0;
  width: 30px;
  height: 16px;
  border-radius: 8px;
  border: 1px solid var(--border);
  background: var(--border);
  cursor: pointer;
  position: relative;
  transition: background .15s, border-color .15s;
  padding: 0;
}
.apps-toggle-switch::after {
  content: '';
  position: absolute;
  top: 1px;
  left: 1px;
  width: 12px;
  height: 12px;
  border-radius: 50%;
  background: var(--muted);
  transition: transform .15s, background .15s;
}
.apps-toggle-switch:hover { border-color: var(--muted); }
.apps-toggle-switch.on {
  background: var(--error, #e5484d);
  border-color: var(--error, #e5484d);
}
.apps-toggle-switch.on::after {
  transform: translateX(14px);
  background: var(--accent-text, #fff);
}

/* Inline "+" chip for adding new groups / categories from the sidebar */
.apps-add-chip {
  flex: 0 0 calc(33.33% - 3px);
  padding: 5px 0;
  border: 1px dashed var(--border);
  border-radius: 6px;
  background: transparent;
  color: var(--muted);
  font-size: 14px;
  font-weight: 600;
  line-height: 1;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  transition: background .15s, color .15s, border-color .15s;
}
.apps-add-chip:hover {
  background: var(--hover-bg, rgba(0,0,0,.03));
  color: var(--text);
  border-color: var(--muted);
  border-style: solid;
}

/* "More ▼" / "Less ▲" toggle for the expense Category filter — sits inline
   with the chip grid, uses the same shape as a regular chip but visually
   subdued so it reads as a control, not a category. */
.todo-group-grid button.apps-cat-more {
  flex: 0 0 calc(33.33% - 3px);
  color: var(--muted);
  font-style: italic;
  background: transparent;
}
.todo-group-grid button.apps-cat-more:hover {
  background: var(--hover-bg, rgba(0,0,0,.03));
  color: var(--text);
}

/* Expense category row: select + inline "+" button */
.apps-cat-row {
  display: flex;
  align-items: stretch;
  gap: 6px;
}
.apps-cat-row > select { flex: 1 1 auto; min-width: 0; }
.apps-cat-add {
  flex: 0 0 28px;
  width: 28px;
  padding: 0;
  font-size: 16px;
}

/* ── Sidebar filter label with inline settings button ──
   Used for sections that have an associated "manage / settings" panel
   (e.g. expense Category). The label keeps its monospace, muted look;
   the gear button sits inline at the end. */
.apps-filter-label-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 6px;
}
.apps-filter-settings-btn {
  background: transparent;
  border: none;
  color: var(--muted);
  cursor: pointer;
  padding: 2px 4px;
  border-radius: var(--radius-sm);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  transition: background .15s, color .15s;
}
.apps-filter-settings-btn:hover {
  color: var(--text);
  background: var(--app-hover, var(--hover-bg, rgba(0,0,0,.05)));
}

/* ── Settings modal: list of editable items (rename / delete) ── */
.apps-settings-list {
  display: flex;
  flex-direction: column;
  gap: 4px;
  max-height: 50vh;
  overflow-y: auto;
  padding: 4px 0;
}
.apps-settings-row {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 8px 10px;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm, 6px);
  background: var(--surface, var(--panel));
}
.apps-settings-name {
  flex: 1 1 auto;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  color: var(--text);
  font-size: var(--font-size-sm);
}
.apps-settings-tag {
  font-size: var(--font-size-xs, 11px);
  color: var(--muted);
  border: 1px solid var(--border);
  padding: 1px 6px;
  border-radius: 999px;
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: .04em;
}
.apps-settings-actions {
  display: flex;
  gap: 4px;
  flex: 0 0 auto;
}
.apps-settings-btn {
  background: transparent;
  border: 1px solid var(--border);
  color: var(--muted);
  cursor: pointer;
  padding: 4px 6px;
  border-radius: var(--radius-sm, 6px);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  transition: background .15s, color .15s, border-color .15s;
}
.apps-settings-btn:hover {
  background: var(--app-hover, var(--hover-bg, rgba(0,0,0,.05)));
  color: var(--text);
  border-color: var(--muted);
}
.apps-settings-btn.apps-settings-danger:hover {
  color: var(--danger, #d33);
  border-color: var(--danger, #d33);
}
/* Pin/star button — borderless variant; the row already has its own border.
   Filled star = pinned (warm accent); outline = unpinned. */
.apps-settings-btn.apps-settings-pin {
  border: none;
  padding: 4px;
  color: var(--muted);
}
.apps-settings-btn.apps-settings-pin:hover {
  background: var(--app-hover, var(--hover-bg, rgba(0,0,0,.05)));
  color: var(--text);
  border: none;
}
.apps-settings-btn.apps-settings-pin.is-pinned {
  color: var(--accent);
}
.apps-settings-btn.apps-settings-pin.is-pinned:hover {
  color: var(--accent);
}
.apps-settings-empty {
  color: var(--muted);
  font-size: var(--font-size-sm);
  text-align: center;
  padding: 24px 0;
}
/* Archived row (accounts settings only): faded so the user sees they're
   in the list but not active. Click the archive icon to restore. */
.apps-settings-row.is-archived {
  opacity: .55;
  background: transparent;
}
.apps-settings-row.is-archived:hover { opacity: .85; }
.apps-settings-btn.is-archived {
  color: var(--accent);
  border-color: var(--accent);
}
/* Inline meta inside the name span (currency + balance preview). */
.apps-settings-sub {
  font-size: var(--font-size-xs, 11px);
  color: var(--muted);
  font-weight: 400;
}


.apps-restore-btn,
.apps-perma-delete-btn {
  padding: 4px 10px;
  border-radius: var(--radius-sm);
  border: 1px solid var(--border);
  font-size: var(--font-size-xs);
  cursor: pointer;
  background: var(--panel);
  color: var(--text);
  transition: background .15s;
}
.apps-restore-btn { color: var(--accent); border-color: var(--accent); }
.apps-restore-btn:hover { background: var(--accent-bg); }
.apps-perma-delete-btn { color: var(--error); border-color: var(--error); }
.apps-perma-delete-btn:hover { background: color-mix(in srgb, var(--error) 10%, transparent); }

/* ── Shared: empty state ───────────────────────────────────────────────── */
.apps-empty {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 8px;
  padding: 48px 24px;
  color: var(--muted);
  text-align: center;
}
.apps-empty svg { opacity: .3; }
.apps-empty-title {
  font-size: var(--font-size-md);
  color: var(--muted);
  font-weight: 500;
}
.apps-empty-sub {
  font-size: var(--font-size-sm);
  color: var(--muted);
  opacity: .7;
  max-width: 280px;
}

/* ── Shared: inline edit ────────────────────────────────────────────────── */
.apps-inline-edit {
  border: 1px solid transparent;
  border-radius: var(--radius-sm);
  padding: 2px 4px;
  transition: border-color .15s, background .15s;
  cursor: text;
}
.apps-inline-edit:hover { border-color: var(--border); background: var(--input-bg); }
.apps-inline-edit:focus {
  outline: none;
  border-color: var(--accent);
  background: var(--input-bg);
  box-shadow: 0 0 0 2px var(--focus-glow);
}

/* ── Shared: sidebar filter label ──────────────────────────────────────── */
.apps-filter-label {
  font-size: var(--font-size-xs);
  color: var(--muted);
  text-transform: uppercase;
  letter-spacing: .5px;
  margin-top: 6px;
  display: none;
}
.apps-filter-label:first-child { margin-top: 0; }

/* ── Shared: chip filter grid ──────────────────────────────────────────── */
.apps-chip-grid {
  display: flex;
  flex-wrap: wrap;
  gap: 4px;
}
.apps-chip-grid button {
  padding: 3px 10px;
  border-radius: var(--app-chip-radius);
  border: 1px solid var(--border);
  background: var(--panel);
  color: var(--muted);
  font-size: var(--font-size-xs);
  cursor: pointer;
  transition: all .15s;
}
.apps-chip-grid button:hover { border-color: var(--accent); color: var(--accent); }
.apps-chip-grid button.active {
  background: var(--accent-bg);
  border-color: var(--accent);
  color: var(--accent-text);
}

/* ── Shared: tag filter in sidebar ─────────────────────────────────────── */
.apps-tag-filter {
  display: flex;
  flex-wrap: wrap;
  gap: 3px;
  margin-top: 4px;
}
.apps-tag-filter .apps-tag {
  cursor: pointer;
  opacity: .5;
  transition: opacity .15s, background .15s;
}
.apps-tag-filter .apps-tag.active { opacity: 1; background: var(--app-active); }
.apps-tag-filter .apps-tag:hover { opacity: .8; }

/* ── Notes panel ───────────────────────────────────────────────────────── */
.notes-notebook-tree { margin-bottom: 8px; }
.notes-notebook-item {
  display: flex;
  align-items: center;
  gap: 4px;
  padding: 5px 8px;
  border-radius: var(--radius-sm);
  cursor: pointer;
  font-size: var(--font-size-sm);
  color: var(--text);
  transition: background .15s;
}
.notes-notebook-item:hover { background: var(--accent-bg); }
.notes-notebook-item.active { background: var(--accent-bg); color: var(--accent-text); }
.notes-notebook-item .count {
  margin-left: auto;
  font-size: var(--font-size-xs);
  color: var(--muted);
}
.notes-notebook-item .icon { flex-shrink: 0; }

/* Notebook color dot — replaces the 📓/📔 emoji. The dot's background is
   set inline from the stored color value; if no color is set we render a
   neutral hollow ring so the layout stays consistent. */
.notes-notebook-dot {
  width: 10px;
  height: 10px;
  border-radius: 50%;
  flex-shrink: 0;
  margin-right: 4px;
  background: var(--muted);
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--text) 20%, transparent);
}
.notes-notebook-dot.is-empty {
  background: transparent;
  box-shadow: inset 0 0 0 1.5px var(--border);
}
.notes-notebook-dot.is-all {
  background: linear-gradient(135deg, var(--accent), color-mix(in srgb, var(--accent) 50%, var(--text)));
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--text) 15%, transparent);
}

/* Notebook modal — a small custom dialog with name input + color swatches.
   Reuses .expense-modal-overlay / .expense-modal classes for the chrome. */
.notebook-modal { width: 320px; max-width: 92vw; }
.notebook-modal-body { display: flex; flex-direction: column; gap: 12px; }
.notebook-modal-body label {
  font-size: var(--font-size-xs);
  font-weight: 600;
  color: var(--muted);
  text-transform: uppercase;
  letter-spacing: .04em;
}
.notebook-modal-body input[type="text"] {
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--input-bg);
  color: var(--text);
  padding: 8px 10px;
  font-size: var(--font-size-sm);
  outline: none;
}
.notebook-modal-body input[type="text"]:focus { border-color: var(--accent); }
.notebook-color-swatches {
  display: flex;
  gap: 8px;
  flex-wrap: wrap;
  align-items: center;
}
.notebook-color-swatch {
  width: 28px;
  height: 28px;
  border-radius: 50%;
  border: 2px solid transparent;
  cursor: pointer;
  background: var(--swatch-bg, var(--muted));
  transition: transform .12s ease, border-color .12s ease;
  position: relative;
  padding: 0;
}
.notebook-color-swatch:hover { transform: scale(1.1); }
.notebook-color-swatch.selected {
  border-color: var(--text);
}
.notebook-color-swatch.selected::after {
  content: '';
  position: absolute;
  inset: 4px;
  border-radius: 50%;
  background: transparent;
  box-shadow: 0 0 0 2px var(--bg) inset;
}
/* "No color" swatch — empty hollow ring */
.notebook-color-swatch.is-empty {
  background: transparent;
  border: 2px dashed var(--border);
}
.notebook-color-swatch.is-empty.selected { border: 2px solid var(--text); border-style: solid; }
.notebook-color-swatch.is-empty::after { display: none; }

/* "Custom color" swatch — rainbow conic gradient hint when no custom hex
   is selected; once a hex is picked, the inline style fills it solid and
   the gradient is hidden. Always opens the native picker on click. */
.notebook-color-swatch.is-custom {
  background:
    conic-gradient(
      from 0deg,
      hsl(0, 80%, 60%),
      hsl(60, 80%, 60%),
      hsl(120, 80%, 55%),
      hsl(180, 70%, 55%),
      hsl(240, 80%, 65%),
      hsl(300, 70%, 60%),
      hsl(360, 80%, 60%)
    );
  position: relative;
}
.notebook-color-swatch.is-custom::before {
  content: '';
  position: absolute;
  inset: 6px;
  border-radius: 50%;
  background: var(--bg);
  pointer-events: none;
}
.notebook-color-swatch.is-custom.selected::before { display: none; }
.notebook-color-swatch.is-custom.selected::after {
  /* When a custom hex is active, override the rainbow with the inline-style
     solid color (set via element style attr) and show the standard ring. */
  content: '';
  position: absolute;
  inset: 4px;
  border-radius: 50%;
  background: transparent;
  box-shadow: 0 0 0 2px var(--bg) inset;
}

/* Hidden native color picker — sized 0×0 but kept in flow so .click() works
   reliably across browsers without layout shift. */
.notebook-color-hidden-input {
  position: absolute;
  width: 0;
  height: 0;
  opacity: 0;
  pointer-events: none;
  border: 0;
  padding: 0;
  margin: 0;
}

/* Editor.js mount — the WYSIWYG surface replaces the old textarea + preview.
   The editor manages its own DOM; we only size/scroll the holder and theme
   its blocks via the .codex-editor descendants below. */
.notes-editor-body {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
}
.notes-editor-body .codex-editor {
  padding: 12px 20px 80px;
}
/* Placeholder shown when the editor is empty or failed to load. */
.notes-preview-empty {
  color: var(--muted);
  font-size: var(--font-size-sm);
  font-style: italic;
  padding: 24px 12px;
  text-align: center;
}

/* ── Notes editor chrome: two header rows above the Editor.js surface ──
   Row 1: notebook select (left) · title (center) · tags (right)
   Row 2: save · pin · color (left) … status · delete (right) */

.notes-editor-row1,
.notes-editor-row2 {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 6px 12px;
  background: var(--surface);
  flex-shrink: 0;
}
.notes-editor-row1 { border-bottom: 1px solid var(--border-subtle); flex-wrap: nowrap; }
.notes-editor-row2 {
  border-bottom: 1px solid var(--border);
  justify-content: space-between;
  flex-wrap: wrap;
}

/* Row 1 children — shared height so all three line up on the same axis. */
.notes-editor-notebook,
.notes-editor-title,
.notes-editor-tags {
  box-sizing: border-box;
  min-height: 34px;
}
.notes-editor-notebook {
  padding: 3px 6px;
  margin-top:6px;
  border-radius: var(--radius-sm);
  border: 1px solid var(--border);
  background: var(--input-bg);
  color: var(--text);
  font-size: var(--font-size-xs);
  font-family: var(--font-ui);
  max-width: 20%;
  flex-shrink: 0;
}
.notes-editor-title {
  flex: 1 1 0;
  min-width: 80px;
  text-align: center;
  font-weight: 600;
  color: var(--text);
  font-size: 17px;
  letter-spacing: -.01em;
  line-height: 1.3;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  padding: 4px 8px;
  /* Styled as a bordered field matching the notebook select / tags wrap so
     all three row-1 items read as a consistent set. Click triggers inline
     editing via the .apps-inline-edit class. */
  border: 1px solid var(--border);
  background: var(--input-bg);
  border-radius: var(--radius-sm);
  cursor: text;
}
.notes-editor-title.apps-inline-edit:hover { border-color: var(--border); background: var(--input-bg); }
.notes-editor-title.apps-inline-edit:focus {
  outline: none;
  border-color: var(--accent);
  background: var(--input-bg);
  box-shadow: 0 0 0 2px var(--focus-glow);
}
.notes-editor-tags {
  flex: 0 1 auto;
  min-width: 0;
  max-width: 40%;
}
.notes-editor-tags .tag-input-field { min-width: 50px; }

/* Row 2 children */
.notes-editor-row2-left,
.notes-editor-row2-right {
  display: flex;
  align-items: center;
  gap: 6px;
}
.notes-editor-color { border-radius: 50%; }
.panel-head-btn.notes-save-btn {
  width: auto;
  height: auto;
  padding: 4px 12px;
  background: var(--accent);
  color: var(--bg);
  font-weight: 600;
  font-size: var(--font-size-xs);
  border-radius: var(--radius-sm);
}
.panel-head-btn.notes-save-btn:hover {
  background: var(--accent-hover);
  color: var(--bg);
}
.notes-editor-pin.is-pinned {
  background: var(--accent-bg);
  color: var(--accent);
  border-radius: var(--radius-sm);
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--accent) 30%, transparent);
}
.notes-editor-status {
  font-size: var(--font-size-xs);
  color: var(--muted);
  display: flex;
  gap: 10px;
  align-items: center;
}
.notes-editor-status .saving { color: var(--warning); }
.notes-editor-status .saved { color: var(--success); transition: opacity .4s ease; }
.notes-editor-status .saved.idle { opacity: .45; color: var(--muted); }

/* ── Editor.js block theming ────────────────────────────────────────────
   Editor.js ships no CSS; we theme its rendered blocks to match the app. */
/* Left-aligned (not centered) reading column. A 60px left gutter makes room
   for the per-block toolbar ("+" + drag handle), which sits at right:100%
   of the toolbar content — i.e. just outside the text's left edge. */
.notes-editor-body .codex-editor__redactor {
  padding-left: 60px;
}
.notes-editor-body .ce-block__content {
  max-width: none;
  margin: 0;
}
.notes-editor-body .ce-toolbar__content {
  max-width: none;
  margin: 0;
  margin-left: 60px;
}
/* Pin the per-block toolbar (the "+" + settings actions) to the LEFT of the
   block content, in the gutter created above. */
.notes-editor-body .ce-toolbar__content { position: relative; }
.notes-editor-body .ce-toolbar__actions,
.notes-editor-body .ce-toolbar__actions--opened {
  position: absolute;
  right: 100%;
  left: auto;
  margin-right: 2px;
}
/* The toolbox (tool picker, revealed by clicking "+") opens anchored under
   the "+" button; align it to the left edge, not the right. */
.notes-editor-body .ce-toolbox,
.notes-editor-body .ce-toolbox .ce-popover {
  left: 0;
  right: auto;
}
.notes-editor-body .ce-paragraph,
.notes-editor-body .ce-header,
.notes-editor-body .ce-list,
.notes-editor-body .ce-checklist,
.notes-editor-body .ce-quote,
.notes-editor-body .ce-code {
  color: var(--text);
}
.notes-editor-body h1.ce-header { font-size: 1.5em; font-weight: 700; margin: .4em 0; }
.notes-editor-body h2.ce-header { font-size: 1.3em; font-weight: 700; margin: .4em 0; }
.notes-editor-body h3.ce-header { font-size: 1.12em; font-weight: 600; margin: .4em 0; }
.notes-editor-body .ce-paragraph { line-height: 1.7; font-size: var(--font-size-sm); }
.notes-editor-body .ce-quote__text {
  border-left: 3px solid var(--accent);
  padding-left: 12px;
  color: var(--muted);
  font-style: italic;
}
.notes-editor-body .ce-code__textarea {
  background: var(--input-bg);
  color: var(--text);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  font-family: var(--font-mono, monospace);
  font-size: var(--font-size-xs);
  padding: 10px;
}
.notes-editor-body .ce-checklist__label { color: var(--text); }
.notes-editor-body .ce-checklist__checkbox { border-color: var(--border); }
.notes-editor-body .ce-checklist__checkbox-checked { background: var(--accent); border-color: var(--accent); }
.notes-editor-body .ce-delimiter { color: var(--muted); }
.notes-editor-body .ce-inline-toolbar,
.notes-editor-body .ce-toolbar__settings-btn,
.notes-editor-body .ce-toolbar__plus {
  color: var(--muted);
}
.notes-editor-body .ce-toolbar__settings-btn:hover,
.notes-editor-body .ce-toolbar__plus:hover { background: var(--app-hover); color: var(--text); }
/* Editor.js inline toolbar + toolbox popovers. */
.notes-editor-body .ce-popover,
.notes-editor-body .ce-inline-toolbar__dropdown,
.notes-editor-body .ce-inline-tool {
  background: var(--surface);
  color: var(--text);
  border-color: var(--border);
}

.notes-list-pane {
  width: 240px;
  min-width: 180px;
  border-right: 1px solid var(--border);
  overflow-y: auto;
  display: flex;
  flex-direction: column;
}
.notes-editor-pane {
  flex: 1;
  display: flex;
  flex-direction: column;
  min-width: 0;
}
.notes-editor-wrap {
  flex: 1;
  display: flex;
  flex-direction: column;
  min-height: 0;
}
.notes-list-pane-header {
  padding: 8px 10px;
  font-size: var(--font-size-xs);
  color: var(--muted);
  border-bottom: 1px solid var(--border);
  display: flex;
  justify-content: space-between;
  align-items: center;
}
.notes-list-pane-notes {
  flex: 1;
  overflow-y: auto;
}
.notes-list-item {
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding: 8px 10px;
  cursor: pointer;
  border-bottom: 1px solid var(--border-subtle);
  transition: background .15s;
  position: relative;
  margin-bottom: 2px
}
.notes-list-item:hover { background: var(--app-hover); }
.notes-list-item.active { background: var(--accent-bg); }
.notes-list-item-title {
  font-size: var(--font-size-sm);
  color: var(--text);
  font-weight: 500;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.notes-list-item-snippet {
  font-size: var(--font-size-xs);
  color: color-mix(in srgb, var(--text) 62%, var(--muted));
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  line-height: 1.4;
}
.notes-list-item-meta {
  display: flex;
  gap: 3px;
  flex-wrap: wrap;
  align-items: center;
  margin-top: 2px;
}
.notes-list-item .pin-icon {
  position: absolute;
  top: 4px; right: 6px;
  font-size: 9px;
  opacity: .4;
}
.notes-list-item.active .pin-icon { opacity: .7; }
/* Reserve space for the absolute-positioned pin so the title's ellipsis
   doesn't collide with it on narrow widths. */
.notes-list-item.is-pinned .notes-list-item-title { padding-right: 16px; }
/* Small notebook indicator on each list item — shown in `.notes-list-item-meta`
   so the user can tell which notebook each note belongs to in "All Notes". */
.notes-list-item .notebook-indicator {
  display: inline-flex;
  align-items: center;
  gap: 3px;
  color: var(--muted);
  font-size: var(--font-size-xs);
}
.notes-list-item .notebook-indicator .notes-notebook-dot {
  width: 6px;
  height: 6px;
  margin-right: 0;
}
.notes-list-item .color-dot {
  width: 6px; height: 6px;
  border-radius: 50%;
  flex-shrink: 0;
}
.notes-list-item .color-dot[data-note-color="red"]    { background: var(--note-color-red); }
.notes-list-item .color-dot[data-note-color="teal"]   { background: var(--note-color-teal); }
.notes-list-item .color-dot[data-note-color="blue"]   { background: var(--note-color-blue); }
.notes-list-item .color-dot[data-note-color="salmon"] { background: var(--note-color-salmon); }
.notes-list-item .color-dot[data-note-color="plum"]   { background: var(--note-color-plum); }

/* Note color swatch popover — anchored under the editor color button. */
.notes-color-popover {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-md, 8px);
  box-shadow: 0 4px 16px rgba(0,0,0,.25);
  padding: 8px;
}
.notes-color-popover .notebook-color-swatches {
  margin: 0;
}

/* ── Todo panel ────────────────────────────────────────────────────────── */
.todo-smart-group {
  margin-bottom: 4px;
}
.todo-smart-group .todo-cards {
  display: flex;
  flex-direction: column;
  gap: 4px;
  min-height: 4px; /* keep an empty drop target visible after the last card moves out */
}
.todo-smart-group-header {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 6px 12px;
  font-size: var(--font-size-xs);
  color: var(--muted);
  text-transform: uppercase;
  letter-spacing: .5px;
  cursor: pointer;
  user-select: none;
}
.todo-smart-group-header:hover { color: var(--text); }
.todo-smart-group-header .count {
  margin-left: auto;
  background: var(--app-bg-subtle);
  padding: 1px 6px;
  border-radius: var(--radius-pill);
  font-size: 10px;
}
.todo-subtask {
  padding-left: 32px;
  border-left: 2px solid var(--border);
  margin-left: 16px;
  margin-top: 2px;
}
.todo-subtask .todo-card { background: var(--app-bg-subtle); }
.todo-add-subtask {
  font-size: var(--font-size-xs);
  color: var(--muted);
  padding: 4px 16px 4px 36px;
  cursor: pointer;
  transition: color .15s;
  display: none;
}
.todo-card:hover .todo-add-subtask,
.todo-card.expanded .todo-add-subtask { display: block; }
.todo-add-subtask:hover { color: var(--accent); }

.todo-card .sort-handle {
  cursor: grab;
  color: var(--text);
  font-size: 20px;
  padding: 4px;
  opacity: 0;
  transition: opacity .15s;
}
.todo-card:hover .sort-handle { opacity: .5; }
.todo-card .sort-handle:active { cursor: grabbing; }

.todo-inline-add {
  display: flex;
  gap: 6px;
  padding: 8px 12px;
  align-items: center;
}
.todo-inline-add input {
  flex: 1;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--input-bg);
  color: var(--text);
  padding: 6px 8px;
  font-size: var(--font-size-sm);
  outline: none;
}
.todo-inline-add input:focus { border-color: var(--accent); }

/* Override saturated full-card color-mix backgrounds from style.css */
.todo-card.prio-high,
.todo-card.prio-medium,
.todo-card.prio-low,
.dark .todo-card.prio-high,
.dark .todo-card.prio-medium,
.dark .todo-card.prio-low { background: var(--panel); }

/* Grid: handle | check | body (title+desc+tags) | meta (due) | edit */
.todo-card {
  display: grid !important;
  grid-template-columns: auto auto 1fr auto auto !important;
  align-items: start !important;
  gap: 8px 10px !important;
  padding: 10px 14px !important;
}

/* Card body layout */
.todo-card-body { display: flex; flex-direction: column; gap: 3px; min-width: 0; padding-top: 2px; }
.todo-card-title {
  font-size: 13px;
  font-weight: 550;
  color: var(--text);
  line-height: 1.35;
  text-align: left;
  cursor: pointer;
  overflow: hidden;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  word-break: break-word;
}
.todo-card.done .todo-card-title {
  text-decoration: line-through;
  text-decoration-thickness: 1.5px;
  text-decoration-color: var(--muted);
  color: var(--muted);
}
.todo-card-desc {
  font-size: 11px;
  color: var(--muted);
  line-height: 1.4;
  text-align: left;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
.todo-card-tags {
  display: flex;
  flex-wrap: wrap;
  gap: 3px;
  align-items: center;
  margin-top: 1px;
}
.todo-card-meta {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  justify-content: center;
  gap: 2px;
  flex-shrink: 0;
  align-self: center;
}
.todo-card-due {
  font-size: var(--font-size-xs);
  color: var(--muted);
  white-space: nowrap;
}
.todo-card-due.overdue { color: var(--error); font-weight: 500; }
.todo-card-due-iso {
  font-size: 10px;
  color: var(--muted);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
  opacity: .75;
}

/* Edit button — clean, appears on hover */
.todo-card-edit {
  background: none;
  border: none;
  cursor: pointer;
  font-size: 12px;
  color: var(--muted);
  padding: 4px;
  border-radius: var(--radius-sm);
  opacity: 0;
  transition: opacity .15s;
  flex-shrink: 0;
  align-self: center;
}
.todo-card:hover .todo-card-edit { opacity: .5; }
.todo-card-edit:hover { opacity: 1 !important; color: var(--accent); }

/* Done tasks fade to reduce visual weight */
.todo-card.done { opacity: .55; }
.todo-card.done:hover { opacity: .85; }

/* Relative date badge colors */
.todo-card-due.due-today { color: var(--accent); font-weight: 600; }
.todo-card-due.due-tomorrow { color: var(--warning); }
.todo-card-due.due-overdue { color: var(--error); font-weight: 600; }
.todo-card-due.due-soon { color: var(--text); }

/* Quick-add row per group — align icon with the check button column inside cards */
.todo-quick-add {
  display: flex;
  align-items: center;
  gap: 10px;
  /* card padding-left (14) + sort-handle width (~20) + gap (10) = 44px */
  padding: 8px 14px 8px 44px;
  margin: 2px 0;
  border-radius: var(--radius-md);
  cursor: pointer;
  color: var(--muted);
  font-size: var(--font-size-sm);
  transition: all .15s;
}
.todo-quick-add:hover {
  background: var(--app-bg-subtle);
  color: var(--text);
}
.todo-quick-add-icon {
  width: 20px;
  height: 20px;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 50%;
  border: 1.5px dashed var(--border);
  font-size: 15px;
  color: var(--muted);

  padding-bottom: 2px;
}
.todo-quick-add:hover .todo-quick-add-icon {
  border-color: var(--accent);
  color: var(--accent);
}

/* ── Goals panel ───────────────────────────────────────────────────────── */
.goals-heatmap {
  padding: 8px;
  overflow-x: auto;
}
.goals-heatmap svg text {
  font-size: 9px;
  fill: var(--muted);
}
.goals-heatmap svg rect.day { rx: 2; ry: 2; }
.goals-detail-card {
  padding: 16px;
}
.goals-milestones {
  display: flex;
  flex-direction: column;
  gap: 8px;
  margin-top: 8px;
}
.goals-milestone {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 6px 10px;
  border-radius: var(--radius-sm);
  background: var(--app-bg-subtle);
}
.goals-milestone-check { flex-shrink: 0; }
.goals-milestone-label { font-size: var(--font-size-sm); flex: 1; }
.goals-milestone-pct {
  font-size: var(--font-size-xs);
  color: var(--muted);
  flex-shrink: 0;
}
.goals-inline-add-progress {
  display: flex;
  gap: 4px;
  align-items: center;
  margin-top: 8px;
}
.goals-inline-add-progress input {
  width: 64px;
  padding: 3px 6px;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--input-bg);
  color: var(--text);
  font-size: var(--font-size-sm);
  text-align: center;
}
.goals-inline-add-progress button {
  padding: 3px 8px;
  border-radius: var(--radius-sm);
  border: 1px solid var(--accent);
  background: var(--accent-bg);
  color: var(--accent-text);
  font-size: var(--font-size-xs);
  cursor: pointer;
}

/* ── Expenses panel ────────────────────────────────────────────────────── */
.expense-accounts-bar {
  display: flex;
  gap: 6px;
  padding: 8px 12px;
  overflow-x: auto;
  flex-shrink: 0;
}
.expense-account-card {
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding: 8px 12px;
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  background: var(--panel);
  cursor: pointer;
  transition: all .15s;
  min-width: 110px;
  flex-shrink: 0;
}
.expense-account-card:hover { border-color: var(--accent); }
.expense-account-card.active { border-color: var(--accent); background: var(--accent-bg); }
.expense-account-card.archived { opacity: .4; }
.expense-account-card .name {
  font-size: var(--font-size-xs);
  color: var(--muted);
  white-space: nowrap;
}
.expense-account-card .balance {
  font-size: var(--font-size-sm);
  font-weight: 600;
  color: var(--text);
}
.expense-account-card .balance.pos { color: var(--cny-income); }
.expense-account-card .balance.neg { color: var(--cny-expense); }
.expense-account-card-add {
  display: flex;
  align-items: center;
  justify-content: center;
  min-width: 110px;
  border: 1px dashed var(--border);
  border-radius: var(--radius-md);
  background: none;
  color: var(--muted);
  cursor: pointer;
  font-size: 18px;
  transition: all .15s;
}
.expense-account-card-add:hover { border-color: var(--accent); color: var(--accent); }

.ana-trend { padding: 12px; }
.ana-trend svg { width: 100%; height: 60px; }
.ana-donut { padding: 12px; display: flex; gap: 12px; align-items: center; }
.ana-donut svg { flex-shrink: 0; }
.ana-donut-legend { display: flex; flex-direction: column; gap: 4px; flex: 1; }
.ana-donut-legend-item {
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: var(--font-size-xs);
  color: var(--muted);
}
.ana-donut-legend-item .dot {
  width: 8px; height: 8px;
  border-radius: 50%;
  flex-shrink: 0;
}
.ana-donut-legend-item .val {
  margin-left: auto;
  color: var(--text);
  font-weight: 500;
}
.ana-bars { padding: 12px; }
.ana-bars svg { width: 100%; height: 80px; }
.ana-bar-label {
  font-size: 7px;
  fill: var(--muted);
  text-anchor: middle;
}

/* ── Reusable flatpickr-backed date input (text input that opens flatpickr
   on click). Used in modals where the native date picker has poor dark-mode
   contrast (calendar glyph hard-coded near-black). No background icon —
   the field's label is enough; flatpickr opens on click. */
.apps-flatpickr-date {
  background: var(--input-bg);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  color: var(--text);
  padding: 7px 10px;
  font: inherit;
  font-size: var(--font-size-sm);
  cursor: pointer;
  font-variant-numeric: tabular-nums;
}
.apps-flatpickr-date:focus {
  outline: none;
  border-color: var(--accent);
  box-shadow: 0 0 0 2px var(--focus-glow, transparent);
}

/* ── Sidebar expense date-range picker (single flatpickr-bound text input).
   The `<input>` is the original element; flatpickr's altInput option auto-
   injects a sibling .form-control.input that the user actually sees. We
   style both so the visible field matches the other sidebar controls
   (rounded, themed, accent focus ring) regardless of which one renders. */
.expense-date-range-input,
.expense-date-range-input.flatpickr-input,
.expense-date-range-input ~ .flatpickr-input,
.expense-date-range-input + input.form-control {
  width: 100%;
  background: var(--input-bg);
  border: 1px solid var(--border);
  border-radius: 8px;
  color: var(--text);
  padding: 6px 10px;
  font: inherit;
  font-size: 11.5px;
  box-sizing: border-box;
  cursor: pointer;
  font-variant-numeric: tabular-nums;
}
.expense-date-range-input:focus,
.expense-date-range-input + input.form-control:focus {
  outline: none;
  border-color: var(--accent);
  box-shadow: 0 0 0 2px var(--focus-glow, transparent);
}

/* ── Flatpickr calendar popup — match WebUI tokens. Flatpickr defaults
   are light-themed and don't respect our skin/dark variables, so
   override the chrome here. */
.flatpickr-calendar {
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: var(--radius-md, 10px);
  box-shadow: 0 18px 40px -12px color-mix(in srgb, var(--text) 32%, transparent),
              0 6px 14px -4px color-mix(in srgb, var(--text) 20%, transparent);
  color: var(--text);
  font-family: var(--font-ui);
}
.flatpickr-calendar.arrowTop::before,
.flatpickr-calendar.arrowBottom::before { border-bottom-color: var(--border); border-top-color: var(--border); }
.flatpickr-calendar.arrowTop::after,
.flatpickr-calendar.arrowBottom::after  { border-bottom-color: var(--panel); border-top-color: var(--panel); }
.flatpickr-months,
.flatpickr-month,
.flatpickr-current-month,
.flatpickr-current-month input.cur-year,
.flatpickr-monthDropdown-months,
.flatpickr-weekday {
  color: var(--text);
  fill: var(--text);
}
.flatpickr-monthDropdown-months { background: var(--panel); }
.flatpickr-weekday { color: var(--muted); }
.flatpickr-prev-month, .flatpickr-next-month {
  fill: var(--muted);
  color: var(--muted);
}
.flatpickr-prev-month:hover, .flatpickr-next-month:hover {
  fill: var(--text);
  color: var(--text);
}
.flatpickr-prev-month svg, .flatpickr-next-month svg { fill: inherit; }
.flatpickr-day {
  color: var(--text);
  border-radius: var(--radius-sm, 6px);
}
.flatpickr-day:hover,
.flatpickr-day:focus {
  background: var(--app-hover);
  border-color: transparent;
}
.flatpickr-day.today {
  border-color: var(--accent);
  color: var(--accent);
}
.flatpickr-day.today:hover { background: var(--accent-bg); color: var(--accent-text); }
.flatpickr-day.flatpickr-disabled,
.flatpickr-day.prevMonthDay,
.flatpickr-day.nextMonthDay {
  color: color-mix(in srgb, var(--text) 35%, transparent);
}
/* Range styling — start, end, and middle days */
.flatpickr-day.startRange,
.flatpickr-day.endRange,
.flatpickr-day.selected {
  background: var(--accent);
  border-color: var(--accent);
  color: var(--accent-text);
}
.flatpickr-day.startRange:hover,
.flatpickr-day.endRange:hover,
.flatpickr-day.selected:hover {
  background: var(--accent);
  color: var(--accent-text);
}
.flatpickr-day.inRange {
  background: var(--accent-bg);
  border-color: transparent;
  color: var(--text);
  box-shadow: -5px 0 0 var(--accent-bg), 5px 0 0 var(--accent-bg);
}
.flatpickr-day.startRange.startRange + .endRange:not(:nth-child(7n+1)),
.flatpickr-day.endRange.endRange + .startRange:not(:nth-child(7n+1)) {
  box-shadow: -10px 0 0 var(--accent);
}
/* Number input arrows in the year selector */
.flatpickr-current-month .numInputWrapper:hover { background: var(--app-hover); }
.numInputWrapper span.arrowUp::after { border-bottom-color: var(--text); }
.numInputWrapper span.arrowDown::after { border-top-color: var(--text); }

/* Time picker (enableTime = true) — used by the Expense modal Date field. */
.flatpickr-time {
  background: var(--panel);
  border-top: 1px solid var(--border);
}
.flatpickr-time input,
.flatpickr-time .flatpickr-time-separator,
.flatpickr-time .flatpickr-am-pm {
  background: var(--panel);
  color: var(--text);
}
.flatpickr-time input:hover,
.flatpickr-time input:focus,
.flatpickr-time .flatpickr-am-pm:hover,
.flatpickr-time .flatpickr-am-pm:focus {
  background: var(--app-hover);
}

/* All in-modal date / datetime / date-range fields use flatpickr (see
   `.apps-flatpickr-date` and `.expense-date-range-input` above). The legacy
   `<input type="date" / datetime-local>` overrides that lived here have been
   removed — no remaining markup uses those native types. */


/* ── Todo Calendar (rebuilt) ────────────────────────────────────────────
   Override the previous quick-and-dirty grid in style.css with a real
   month calendar: full-width cells, day-of-week header, task pills inside
   cells, and a floating popover anchored to the clicked day for tasks.
*/
#todoCalendarWrap {
  /* Calendar fills the available view; day-list popover floats over it */
  padding: 0;
  position: relative;
  overflow: hidden;
}
#todoCalendarGrid {
  /* Fill the full available area — both width and height */
  padding: 12px 16px !important;
  display: flex !important;
  flex-direction: column !important;
  overflow: hidden !important;
  flex: 1 1 auto !important;
  min-height: 0 !important;
  width: 100%;
  box-sizing: border-box;
}
/* DOW header has its own height, the grid fills the rest */
#todoCalendarGrid .cal-dow-row { flex-shrink: 0; }
#todoCalendarGrid .cal-grid {
  flex: 1 1 auto;
  min-height: 0;
  grid-auto-rows: 1fr; /* equal-height rows */
}
/* Month-change animations — apply to the whole grid container */
#todoCalendarGrid.cal-anim-slide-left  { animation: calSlideInLeft  .28s cubic-bezier(.22, 1, .36, 1); }
#todoCalendarGrid.cal-anim-slide-right { animation: calSlideInRight .28s cubic-bezier(.22, 1, .36, 1); }
#todoCalendarGrid.cal-anim-fade        { animation: calFadeIn       .28s cubic-bezier(.22, 1, .36, 1); }
@keyframes calSlideInLeft {
  0%   { opacity: 0; transform: translateX(28px); }
  100% { opacity: 1; transform: translateX(0); }
}
@keyframes calSlideInRight {
  0%   { opacity: 0; transform: translateX(-28px); }
  100% { opacity: 1; transform: translateX(0); }
}
@keyframes calFadeIn {
  0%   { opacity: 0; transform: scale(.98); }
  100% { opacity: 1; transform: scale(1); }
}
.cal-dow-row {
  display: grid;
  grid-template-columns: repeat(7, 1fr);
  gap: 4px;
  padding: 6px 0 8px;
  border-bottom: 1px solid var(--border);
  margin-bottom: 8px;
}
.cal-dow {
  text-align: center;
  font-size: 11px;
  font-weight: 600;
  color: var(--muted);
  text-transform: uppercase;
  letter-spacing: .04em;
}
.cal-grid {
  display: grid;
  grid-template-columns: repeat(7, 1fr);
  gap: 4px;
  /* 6 rows of cells fit in the available height */
}
/* Priority legend — only shown on mobile (<=640px). On desktop the
   text pills inside each cell already convey priority via colored borders. */
.cal-legend { display: none; }
.cal-cell {
  min-height: 60px;
  padding: 4px 5px 5px;
  border: 1px solid var(--border);
  border-radius: 8px;
  background: var(--panel);
  cursor: pointer;
  display: flex;
  flex-direction: column;
  gap: 3px;
  transition: background .15s ease, border-color .15s ease, transform .12s ease;
  overflow: hidden;
}
.cal-cell:hover { background: var(--app-hover); border-color: var(--text); }
/* Lift slightly + accent shadow on hover */
.cal-cell:not(.out):hover {
  transform: translateY(-1px);
  box-shadow: 0 4px 12px -6px color-mix(in srgb, var(--text) 25%, transparent);
}
/* Today pulse — subtle one-shot ring on initial render */
.cal-cell.today { animation: calTodayPulse 1.2s ease-out; }
@keyframes calTodayPulse {
  0%   { box-shadow: 0 0 0 0 color-mix(in srgb, var(--text) 35%, transparent), 0 0 0 1px var(--text) inset; }
  60%  { box-shadow: 0 0 0 6px transparent, 0 0 0 1px var(--text) inset; }
  100% { box-shadow: 0 0 0 0 transparent, 0 0 0 1px var(--text) inset; }
}
.cal-cell.out {
  opacity: .35;
  cursor: default;
  background: transparent;
  border-color: transparent;
}
.cal-cell.out:hover { background: transparent; border-color: transparent; }
.cal-cell.weekend { background: color-mix(in srgb, var(--panel) 70%, var(--bg) 30%); }
.cal-cell.today { border-color: var(--text); box-shadow: 0 0 0 1px var(--text) inset; }
.cal-cell.today .cal-cell-num { color: var(--text); font-weight: 700; }
.cal-cell.selected { background: color-mix(in srgb, var(--text) 8%, transparent); border-color: var(--text); }
.cal-cell-num {
  font-size: 12px;
  font-weight: 600;
  color: var(--text);
  line-height: 1;
  font-variant-numeric: tabular-nums;
  flex-shrink: 0;
}
.cal-cell.out .cal-cell-num { font-weight: 400; }
.cal-cell-pills {
  display: flex;
  flex-direction: column;
  gap: 2px;
  flex: 1;
  min-height: 0;
}
.cal-pill {
  font-size: 10px;
  line-height: 1.25;
  padding: 2px 5px;
  border-radius: 4px;
  background: color-mix(in srgb, var(--prio-medium) 18%, var(--panel) 82%);
  color: var(--text);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  border-left: 2px solid var(--prio-medium);
  animation: calPillIn .25s ease-out backwards;
}
.cal-pill:nth-child(1) { animation-delay: .04s; }
.cal-pill:nth-child(2) { animation-delay: .08s; }
.cal-pill:nth-child(3) { animation-delay: .12s; }
@keyframes calPillIn {
  0%   { opacity: 0; transform: translateY(-3px); }
  100% { opacity: 1; transform: translateY(0); }
}
.cal-pill.prio-high { background: color-mix(in srgb, var(--prio-high) 18%, var(--panel) 82%); border-left-color: var(--prio-high); }
.cal-pill.prio-low  { background: color-mix(in srgb, var(--prio-low) 18%, var(--panel) 82%);  border-left-color: var(--prio-low); }
.cal-pill.done { opacity: .5; text-decoration: line-through; }
.cal-pill-more {
  font-size: 9px;
  color: var(--muted);
  font-weight: 600;
  padding: 0 4px;
  line-height: 1.2;
}
/* Day list — floating popover anchored to the clicked day cell.
   Position is set inline by JS (top/left); CSS only handles sizing,
   styling, transition. Hidden until JS sets `.open`. */
.todo-calendar-day-list {
  position: absolute !important;
  margin-top: 0 !important;
  width: 320px !important;
  max-width: calc(100% - 32px) !important;
  max-height: min(60vh, 440px) !important;
  border: 1px solid var(--border) !important;
  border-radius: 12px !important;
  padding: 12px 16px 14px !important;
  background: var(--panel) !important;
  box-shadow: 0 18px 36px -10px color-mix(in srgb, var(--text) 30%, transparent),
              0 6px 12px -4px color-mix(in srgb, var(--text) 18%, transparent) !important;
  overflow-y: auto !important;
  z-index: 10 !important;
  display: none;
  /* JS sets top/left to anchor next to the clicked day cell */
}
.todo-calendar-day-list.open {
  display: block;
  animation: calPopoverIn .22s cubic-bezier(.22, 1.2, .36, 1);
  transform-origin: top left;
}
@keyframes calPopoverIn {
  0%   { opacity: 0; transform: scale(.92) translateY(-4px); }
  100% { opacity: 1; transform: scale(1) translateY(0); }
}
/* Close button shown inside the floating list */
.cal-list-close {
  position: absolute;
  top: 6px;
  right: 8px;
  background: transparent;
  border: none;
  color: var(--muted);
  font-size: 18px;
  line-height: 1;
  width: 24px;
  height: 24px;
  border-radius: 6px;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
}
.cal-list-close:hover { color: var(--text); background: var(--app-hover); }
.cal-list-head {
  font-size: 12px;
  font-weight: 650;
  color: var(--text);
  padding: 0 4px 8px;
  display: flex;
  align-items: center;
  gap: 8px;
}
.cal-list-count {
  font-size: 12px;
  font-weight: 500;
  color: var(--muted);
  background: transparent;
  padding: 0;
  border-radius: 0;
  margin-left: 4px;
  font-variant-numeric: tabular-nums;
}
.cal-list-empty {
  text-align: center;
  color: var(--muted);
  padding: 16px 8px;
  font-size: 12px;
}
.cal-list-item {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  padding: 7px 10px;
  border-radius: 6px;
  cursor: pointer;
  border-left: 3px solid var(--prio-medium);
  background: var(--panel);
  margin-bottom: 3px;
  transition: background .12s ease;
}
.cal-list-item:hover { background: var(--app-hover); }
.cal-list-item.prio-high { border-left-color: var(--prio-high); }
.cal-list-item.prio-low  { border-left-color: var(--prio-low); }
.cal-list-item.done .cal-list-title { opacity: .55; text-decoration: line-through; }
.cal-list-check {
  width: 14px;
  height: 14px;
  border-radius: 50%;
  border: 1.5px solid var(--border);
  flex-shrink: 0;
  cursor: pointer;
  margin-top: 2px;
  background: transparent;
  transition: border-color .15s ease, background .15s ease, color .15s ease;
}
/* Pending → hover blue (next: in_progress) */
.cal-list-check:hover { border-color: var(--blue); }
/* In progress: blue dot */
.cal-list-item.in-progress .cal-list-check {
  border-color: var(--blue);
  background: radial-gradient(circle, var(--blue) 0 3px, transparent 4px);
}
/* In progress hover → fill green (next: done) */
.cal-list-item.in-progress .cal-list-check:hover {
  border-color: var(--success);
  background: var(--success);
}
/* Done: green fill */
.cal-list-item.done .cal-list-check {
  background: var(--success);
  border-color: var(--success);
}
/* Done hover → red empty (next: pending reset) */
.cal-list-item.done .cal-list-check:hover {
  background: transparent;
  border-color: var(--error);
}
.cal-list-body {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 2px;
}
.cal-list-title {
  font-size: 13px;
  color: var(--text);
  font-weight: 500;
  line-height: 1.35;
  word-break: break-word;
}
.cal-list-desc {
  font-size: 11.5px;
  color: var(--muted);
  line-height: 1.4;
  word-break: break-word;
  /* 3-line clamp */
  display: -webkit-box;
  -webkit-line-clamp: 3;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
.cal-list-status {
  font-size: 9.5px;
  text-transform: uppercase;
  font-weight: 650;
  color: var(--muted);
  letter-spacing: .04em;
  flex-shrink: 0;
  margin-top: 2px;
}

/* ── Todo Board (rebuilt cards) ─────────────────────────────────────── */
.todo-board-card {
  display: grid;
  grid-template-columns: 1fr auto;
  align-items: start;
  column-gap: 10px;
  row-gap: 4px;
  background: var(--panel);
  border: 1px solid var(--border);
  border-left-width: 3px;
  border-radius: 8px;
  padding: 8px 10px 9px;
  cursor: grab;
  transition: border-color .15s ease, transform .15s ease, box-shadow .15s ease, background .15s ease;
  position: relative;
  overflow: visible;
  font-size: 12.5px;
}
/* Body holds title + desc + tags stacked; sits in column 1 */
.todo-board-card-body {
  display: flex;
  flex-direction: column;
  gap: 3px;
  min-width: 0;
}
/* Date meta sits in column 2, top-aligned to the title.
   Stack relative ("3 days ago") + ISO ("2026-06-21") vertically,
   right-aligned, never shrinks below content width. */
.todo-board-card > .todo-board-card-meta {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  justify-content: flex-start;
  gap: 2px;
  margin-top: 0;
  flex-wrap: nowrap;
  white-space: nowrap;
  flex-shrink: 0;
  min-width: max-content;
}
.todo-board-card-due-iso {
  font-size: 9.5px;
  color: var(--muted);
  font-variant-numeric: tabular-nums;
  opacity: .75;
}
/* Replace the old ::before stripe with a plain left border for crispness */
.todo-board-card::before { display: none !important; }
.todo-board-card.prio-high   { border-left-color: var(--prio-high); }
.todo-board-card.prio-medium { border-left-color: var(--prio-medium); }
.todo-board-card.prio-low    { border-left-color: var(--prio-low); }
.todo-board-card:hover {
  border-color: var(--text);
  border-left-color: var(--text);
  transform: translateY(-1px);
  box-shadow: 0 4px 12px -4px color-mix(in srgb, var(--text) 25%, transparent);
}
.todo-board-card.done { opacity: .55; }
.todo-board-card.done .todo-board-card-title { text-decoration: line-through; }
.todo-board-card-title {
  font-weight: 550;
  color: var(--text);
  line-height: 1.35;
  font-size: 12.5px;
  /* 2-line clamp */
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
  word-break: break-word;
}
.todo-board-card-desc {
  font-size: 10.5px;
  color: var(--muted);
  line-height: 1.35;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
.todo-board-card-meta {
  display: flex;
  align-items: center;
  gap: 6px;
  flex-wrap: wrap;
  margin-top: 2px;
}
.todo-board-card-due {
  font-size: 10px;
  color: var(--muted);
  font-weight: 500;
  font-variant-numeric: tabular-nums;
}
.todo-board-card-due.due-today { color: var(--accent); font-weight: 600; }
.todo-board-card-due.due-tomorrow { color: var(--warning); }
.todo-board-card-due.due-overdue { color: var(--error); font-weight: 600; }
.todo-board-card-tags { display: flex; gap: 3px; flex-wrap: wrap; }
.todo-board-card-tags .apps-tag { font-size: 9.5px; padding: 1px 6px; }
.todo-board-col-empty {
  color: var(--muted);
  font-size: 11.5px;
  text-align: center;
  padding: 24px 8px;
  font-style: italic;
  opacity: .7;
}
.todo-board-card.just-moved {
  animation: todoCardLanded .35s cubic-bezier(.22, 1, .36, 1);
}
@keyframes todoCardLanded {
  0%   { background: color-mix(in srgb, var(--text) 8%, var(--panel)); transform: scale(1.02); }
  100% { background: var(--panel); transform: scale(1); }
}

/* ── Drag animation polish (list + board) ─────────────────────────────
   SortableJS classes: ghost = placeholder hole, chosen = element while
   pressed, drag = the floating clone shown by forceFallback.
*/
.todo-card-ghost,
.todo-board-card-ghost {
  opacity: .25;
  background: color-mix(in srgb, var(--text) 6%, var(--panel)) !important;
  border-style: dashed !important;
  filter: grayscale(.4);
}
.todo-card-chosen,
.todo-board-card-chosen {
  cursor: grabbing !important;
}
.todo-card-drag,
.todo-board-card-drag {
  cursor: grabbing !important;
  transform: scale(1.02);
  box-shadow: 0 12px 24px -8px color-mix(in srgb, var(--text) 40%, transparent),
              0 4px 8px -2px color-mix(in srgb, var(--text) 20%, transparent);
  border-color: var(--text) !important;
  opacity: .96;
  transition: none !important;
}

/* ── Mobile (<=640px) — Todo panel ──────────────────────────────────────
   The custom-panel sidebar is already moved into the slide-in drawer by
   the core mobile rules in style.css (.sidebar .panel-view{margin-left:52px}).
   Below are main-view (#mainTodolist) adjustments only.
*/
@media (max-width: 640px) {

  /* ── View tabs: equal-width pills with high-contrast active state.
     The desktop look (subtle muted text + accent on active) doesn't read
     as a "tab bar" on mobile — make the active tab a solid pill so the
     current view is unmistakable. */
  .todo-view-tabs {
    padding: 8px 10px 6px !important;
    gap: 4px;
    margin-bottom: 0;
    overflow: visible;
    background: transparent;
    border-bottom: 1px solid var(--border);
  }
  .todo-view-tab {
    flex: 1 1 0;
    min-width: 0;
    padding: 9px 6px !important;
    font-size: 12.5px !important;
    white-space: nowrap;
    text-align: center;
    border-radius: 8px !important;
  }
  .todo-view-tab.active {
    background: color-mix(in srgb, var(--accent) 16%, var(--panel)) !important;
    color: var(--accent) !important;
    box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--accent) 35%, transparent);
  }

  /* ── Calendar header: bigger touch targets for nav arrows + Today.
     Default 30×30 arrows are below the 44×44 iOS guideline; bump them
     and pad the row a bit more. */
  .todo-calendar-header {
    padding: 8px 12px 4px !important;
    gap: 8px !important;
  }
  .todo-calendar-nav {
    width: 40px !important;
    height: 40px !important;
    font-size: 22px !important;
    flex-shrink: 0;
  }
  .todo-calendar-month {
    font-size: 15px !important;
    padding: 0 4px;
  }
  .todo-calendar-today {
    padding: 8px 14px !important;
    min-height: 36px;
    font-size: 12px !important;
  }

  /* ── List view: tighter cards. Sort-handle and edit-button are
     hidden on mobile (display:none below); grid drops their columns.
     Columns: check | title-body | due-meta */
  .todo-card {
    grid-template-columns: auto 1fr auto !important;
    padding: 10px 12px !important;
    gap: 6px 10px !important;
  }
  /* Sort handle — drag-to-reorder isn't great on touch; hide it.
     Mobile users still get drag via long-press inside the card. */
  .todo-card .sort-handle { display: none !important; }
  /* Edit button hidden on mobile — use long-press OR swipe-left to open
     the edit modal. The card itself is translated by JS during swipe;
     the wrapper here paints a subtle "Edit" hint beneath it that the
     drag reveals. */
  .todo-card-edit { display: none !important; }
  .todo-smart-group .todo-cards .todo-card {
    will-change: transform;
    touch-action: pan-y; /* allow vertical scroll, capture horizontal swipe */
  }

  .todo-card-title { font-size: 14px; -webkit-line-clamp: 3; }
  .todo-card-desc  { font-size: 12px; }

  /* Smart-group headers sticky so user always knows the section.
     Background must be fully opaque (matches #todoBoard's bg) so cards
     scrolling underneath are hidden, not bleeding through. top:0 pins
     it directly under the tabs row (since #todoBoard has padding-top:0). */
  .todo-smart-group-header {
    position: sticky;
    top: 0;
    background: var(--bg);
    z-index: 5;
    padding: 12px 12px 8px;
    margin: 0 -12px 6px;  /* extend bg to viewport edges so items don't show in corners */
    padding-left: 24px;   /* compensate for negative margin */
    padding-right: 24px;
    border-bottom: 1px solid var(--border);
  }
  /* Add a bit of space between groups */
  .todo-smart-group { margin-bottom: 12px; }

  /* Quick-add row: realign icon column with the (now narrower) card padding */
  .todo-quick-add { padding: 10px 12px 10px 12px; gap: 10px; }

  /* List view scroll body should fill remaining height.
     padding-top MUST be 0 — any top padding creates a gap above the
     sticky group header where todo items briefly bleed through during
     scroll. The sticky header's own internal padding handles spacing. */
  #todoBoard {
    overflow-y: auto;
    -webkit-overflow-scrolling: touch;
    padding: 0 12px 16px !important;
  }

  /* ── Calendar grid: SHORT rows + always-visible day list below ──
     The desktop layout (tall cells filling the viewport with task pills
     inside) looks cramped on a 390-wide screen — cells become tall thin
     boxes and pills truncate to "Mee…". Replace with a calendar that
     occupies just the top half of the screen (~auto-height rows), and
     a permanent day-detail list below. Mirrors iOS/Android calendar UX. */
  /* Calendar wrap layout (column: calendar on top, day-list below)
     comes from the base rule in style.css — no mobile override needed.
     Crucially: do NOT use display:flex !important here, since that
     would clobber the inline `display:none` set by switchTodoView()
     and make the calendar leak into the list / board tabs. */
  #todoCalendarGrid {
    padding: 0 8px 4px !important;
    flex: 0 0 auto !important;        /* don't stretch — keep cells short */
  }
  #todoCalendarGrid .cal-grid {
    grid-auto-rows: 46px !important;   /* taller — gives breathing room
                                          between number and dot row so
                                          the two never overlap (was 38) */
    flex: 0 0 auto;
  }
  .cal-dow-row {
    grid-template-columns: repeat(7, 1fr) !important;
    gap: 2px !important;
    padding: 4px 0 6px !important;
    margin-bottom: 4px !important;
  }
  .cal-dow {
    font-size: 10.5px !important;
    text-align: center;
    letter-spacing: 0;       /* prevent visual drift vs cells below */
  }
  .cal-grid { gap: 2px; grid-template-columns: repeat(7, 1fr) !important; }
  .cal-cell {
    min-height: 0;             /* let row sizing decide */
    height: 46px;
    padding: 0 !important;
    border-radius: 8px;
    gap: 0 !important;
    border-color: transparent !important;  /* remove every-cell box look */
    background: transparent !important;
    align-items: center;
    justify-content: flex-start;
    position: relative;
  }
  .cal-cell:hover { background: transparent !important; }
  .cal-cell-num {
    font-size: 13px !important;
    font-weight: 500;
    line-height: 1;
    margin: 6px auto 0;        /* number top, dot row directly below */
    display: flex;
    align-items: center;
    justify-content: center;
    width: 24px;
    height: 24px;
    border-radius: 50%;
    flex-shrink: 0;
    box-sizing: border-box;
  }
  /* Out-of-month — dimmed but legible (was 55% — too faint, almost
     invisible against dark bg). 75% reads as clearly inactive
     while still being readable. */
  .cal-cell.out {
    opacity: 1 !important;
    background: transparent !important;
  }
  .cal-cell.out .cal-cell-num {
    color: color-mix(in srgb, var(--text) 36%, transparent);
    font-weight: 400;
  }
  /* Weekend tint removed on mobile — adds noise, hurts day-of-week scan */
  .cal-cell.weekend { background: transparent !important; }
  /* Today — HOLLOW accent ring (not solid fill) so the number stays
     legible AND the priority dot below remains visible. */
  .cal-cell.today {
    background: transparent !important;
    border: 0 !important;
    box-shadow: none !important;
  }
  .cal-cell.today .cal-cell-num {
    background: transparent;
    color: var(--accent);
    font-weight: 700;
    border: 1.5px solid var(--accent);
  }
  /* Selected — solid filled circle on the number */
  .cal-cell.selected {
    background: transparent !important;
    border: 0 !important;
  }
  .cal-cell.selected .cal-cell-num {
    background: color-mix(in srgb, var(--text) 88%, transparent);
    color: var(--bg);
    font-weight: 700;
    border: 0;
  }
  /* Selected + today — keep the accent identity but as a solid pill
     with high-contrast text. accent-text is the on-accent foreground
     defined per skin (white on default, dark on light skins). */
  .cal-cell.selected.today .cal-cell-num {
    background: var(--accent);
    border: 1.5px solid var(--accent);
  }
  /* Dots row — fixed position directly below the 24px number circle.
     With 6px top margin + 24px circle = 30px from cell top. Cell is
     46px, so 30..42 is the dots band. Pin to bottom:6px so dots sit
     in a stable strip ~10px below the number, never overlapping it. */
  .cal-cell-pills {
    position: absolute;
    bottom: 6px;
    left: 0;
    right: 0;
    display: flex;
    flex-direction: row !important;
    flex-wrap: nowrap !important;
    gap: 3px !important;
    justify-content: center;
    align-items: center;
    height: 5px;
    overflow: hidden;
    pointer-events: none;
  }
  .cal-pill {
    width: 4px !important;
    height: 4px !important;
    padding: 0 !important;
    border-radius: 50% !important;
    border-left: 0 !important;
    background: var(--prio-medium) !important;
    text-indent: -9999px;
    overflow: hidden;
    flex: 0 0 auto;
    line-height: 0;
  }
  .cal-pill.prio-high { background: var(--prio-high) !important; }
  .cal-pill.prio-low  { background: var(--prio-low) !important; }
  .cal-pill.done      { opacity: .35; }
  .cal-pill-more {
    display: none !important;   /* dots row caps at ~4 visible; "+N" not needed */
  }
  .cal-cell:not(.out):hover { transform: none !important; box-shadow: none !important; }
  .cal-cell:not(.out):active .cal-cell-num {
    background: color-mix(in srgb, var(--text) 12%, transparent);
  }
  /* Dot legend below the calendar */
  #todoCalendarGrid::after {
    content: '';
    display: block;
    height: 4px;
  }
  .cal-legend {
    display: flex !important;
    justify-content: center;
    gap: 18px;
    padding: 8px 12px 6px;
    font-size: 11px;
    color: var(--muted);
    border-top: 1px solid var(--border);
    text-align: center;
  }
  .cal-legend-item {
    display: inline-flex;
    align-items: center;
    gap: 7px;
    line-height: 1;
  }
  .cal-legend-dot {
    width: 6px;
    height: 6px;
    border-radius: 50%;
    background: var(--prio-medium);
    flex-shrink: 0;
  }
  .cal-legend-dot.prio-high { background: var(--prio-high); }
  .cal-legend-dot.prio-low  { background: var(--prio-low); }

  /* Day list — permanent inline panel below the calendar (not a sheet).
     The calendar above is short and stable; the rest of the viewport
     scrolls through that day's todos. Mirrors iOS/Android calendar UX
     where day-detail is always visible, not gated behind a tap.
     We still override the inline left/top from _positionCalendarDayList. */
  .todo-calendar-day-list {
    position: relative !important;
    top: auto !important;
    left: auto !important;
    right: auto !important;
    bottom: auto !important;
    width: auto !important;
    max-width: 100% !important;
    max-height: none !important;
    margin: 4px 12px 0 !important;
    padding: 12px 14px 16px !important;
    border-radius: 12px !important;
    border: 1px solid var(--border) !important;
    background: var(--panel) !important;
    box-shadow: none !important;
    z-index: auto !important;
    flex: 1 1 auto;
    overflow-y: auto !important;
    -webkit-overflow-scrolling: touch;
    /* The list is shown by JS when a date is selected (default: today) */
  }
  .todo-calendar-day-list.open {
    animation: none !important;
  }
  /* No drag handle (no sheet) */
  .todo-calendar-day-list::before { content: none !important; }
  .cal-list-close {
    display: none !important;   /* permanent panel — no close needed */
  }
  .cal-list-item {
    padding: 9px 10px;
    border-left-width: 2px !important;   /* thinner stripe matches the
                                             refined calendar aesthetic
                                             (was 3px — felt chunky) */
  }
  .cal-list-title { font-size: 14px; }
  .cal-list-desc  { font-size: 12px; }
  .cal-list-check {
    width: 18px;
    height: 18px;
    /* Brighter outline so the checkbox reads as interactive on the
       dark card background. Was var(--border) which is near-invisible. */
    border-color: color-mix(in srgb, var(--text) 55%, transparent) !important;
    border-width: 1.5px !important;
  }

  /* ── Board: vertical stack on mobile (horizontal swipe is awkward,
     fights browser back-gesture, and hides 2/3 of the board off-screen).
     Stack columns top-to-bottom; each column header is sticky so the
     status label stays visible as the user scrolls through its cards. */
  .todo-board-columns {
    display: flex;
    flex-direction: column;
    gap: 0;
    padding: 0 12px 16px;
    overflow-x: hidden;
    overflow-y: auto;
    scroll-snap-type: none;
  }
  .todo-board-col {
    flex: 0 0 auto;
    min-width: 0;
    max-width: 100%;
    width: 100%;
    background: transparent;
    border: 0;
    border-radius: 0;
    border-bottom: 1px solid var(--border);
    margin-bottom: 4px;
    scroll-snap-align: none;
  }
  .todo-board-col:last-child { border-bottom: 0; }
  /* Sticky status header — same look-and-feel as list view's smart-group
     headers so the two views feel consistent. */
  .todo-board-col-header {
    position: sticky;
    top: 0;
    z-index: 5;
    background: var(--bg);
    padding: 12px 4px 8px;
    font-size: 11px;
    font-weight: 700;
    color: var(--text);
    border-bottom: 1px solid var(--border);
  }
  .todo-board-col-body {
    overflow: visible;
    padding: 8px 0 12px;
    gap: 6px;
    min-height: 40px;
  }
  /* Empty-state placeholder shouldn't take a whole column; tighten it. */
  .todo-board-col-empty { padding: 14px 8px; font-size: 12px; }
  .todo-board-card {
    padding: 10px 12px;
    font-size: 13px;
    will-change: transform;
    touch-action: pan-y; /* allow vertical scroll, capture horizontal swipe */
  }
  .todo-board-card-title { font-size: 13px; }
  .todo-board-card-desc  { font-size: 11.5px; }

  /* ── Modal: full-width on mobile, scrollable body ──────────────── */
  /* #todoModal inherits .expense-modal which is already 92vw on <=768px;
     just give it more vertical room and tighter inside padding. */
  #todoModal {
    width: 94vw !important;
    max-width: 94vw !important;
    max-height: 88vh !important;
    padding: 14px !important;
  }
  #todoModal .expense-modal-actions {
    flex-wrap: wrap;
    gap: 8px;
  }
  #todoModal .expense-modal-actions .btn {
    flex: 1 1 calc(50% - 4px);
    min-height: 40px;
    padding: 10px 12px;
  }
}

/* ── Expense columns — match ab80638c look: transparent panels on page bg
       (--panel was undefined back then, resolving to transparent) ────── */
#mainExpenses .expense-column {
  background: transparent;
}
#mainExpenses .expense-column-head,
#mainExpenses .expense-column-foot {
  background: var(--surface-subtle, rgba(0,0,0,.02));
}

/* ── Analytics hero: CNY-specific colors (mirror HKD overrides) ──────── */
.ana-hero[data-currency="CNY"] .ana-hero-item.in .ana-hero-dot{background:var(--cny-income);box-shadow:0 0 6px var(--cny-income);}
.ana-hero[data-currency="CNY"] .ana-hero-item.out .ana-hero-dot{background:var(--cny-expense);box-shadow:0 0 6px var(--cny-expense);}
.ana-hero[data-currency="CNY"] .ana-hero-bar-fill.in{background:linear-gradient(90deg, var(--cny-income), color-mix(in srgb, var(--cny-income) 70%, #fff));}
.ana-hero[data-currency="CNY"] .ana-hero-bar-fill.out{background:linear-gradient(90deg, var(--cny-expense), color-mix(in srgb, var(--cny-expense) 70%, #fff));}
.ana-hero[data-currency="CNY"].pos .ana-hero-net{color:var(--cny-income);}
.ana-hero[data-currency="CNY"].neg .ana-hero-net{color:var(--cny-expense);}
/* Top-border accent on neg cards: use currency-specific expense color */
.ana-hero[data-currency="CNY"].neg{border-top-color:var(--cny-expense);}
.ana-hero[data-currency="HKD"].neg{border-top-color:var(--hkd-expense);}
.ana-hero[data-currency="CNY"].pos{border-top-color:var(--cny-income);}
.ana-hero[data-currency="HKD"].pos{border-top-color:var(--hkd-income);}

/* ── Expense rows — keep style.css base layout, just style new chips ─── */
.expense-row .expense-row-tags {
  display: inline-flex;
  gap: 4px;
  flex-wrap: wrap;
}
.expense-row .apps-tag-inline {
  font-size: 10px;
  padding: 1px 6px;
  line-height: 1.4;
}
.expense-row .expense-row-transfer {
  font-size: 11px;
  color: var(--muted);
  white-space: nowrap;
}

/* ── Scroll-fade on summary bar (mobile) so users see the affordance ── */
@media (max-width: 768px) {
  .expense-summary-row {
    -webkit-mask-image: linear-gradient(90deg, #000 0, #000 calc(100% - 24px), transparent 100%);
            mask-image: linear-gradient(90deg, #000 0, #000 calc(100% - 24px), transparent 100%);
  }
}

/* ── Analytics hero: responsive — sub-cards stack on narrow widths ──── */
@media (max-width: 1200px) {
  #mainExpenses .ana-hero-sub { flex-direction: column; gap: 6px; }
  #mainExpenses .ana-hero-sub .ana-hero { padding: 8px 12px; }
  #mainExpenses .ana-hero-sub .ana-hero-net { font-size: 18px; margin-bottom: 4px; }
}

/* ── Right-click context menu (shared lightweight popup) ─────────────── */
.apps-context-menu {
  position: fixed;
  z-index: 1200;
  min-width: 160px;
  background: var(--panel, var(--surface));
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 4px;
  box-shadow: 0 8px 24px rgba(0, 0, 0, .18);
  font-size: 13px;
  color: var(--text);
  user-select: none;
}
.apps-context-menu .apps-ctx-item {
  display: flex; align-items: center; gap: 8px;
  padding: 7px 12px;
  border-radius: 5px;
  cursor: pointer;
  white-space: nowrap;
}
.apps-context-menu .apps-ctx-item:hover { background: var(--hover-bg, rgba(0, 0, 0, .05)); }
.apps-context-menu .apps-ctx-item.danger { color: var(--error, #F87171); }
.apps-context-menu .apps-ctx-sep {
  height: 1px; background: var(--border); margin: 4px 0;
}

/* ── Inline edit on amount/category ───────────────────────────────────── */
.expense-row .expense-row-cat-text.editing,
.expense-row .expense-row-amt.editing {
  outline: 1px solid var(--accent);
  background: var(--panel, var(--surface));
  border-radius: 3px;
}
.expense-row input.apps-inline-edit {
  width: 100%;
  font: inherit;
  color: inherit;
  text-align: inherit;
  background: var(--input-bg, var(--bg));
  border: 1px solid var(--accent);
  border-radius: 4px;
  padding: 1px 4px;
  box-sizing: border-box;
}
