/* Done — single-pane checklist sidebar + main todos pane. Mobile
   collapses to single-pane navigation (sidebar slides in over content).
   Sidebar visual language is matched verbatim to Noted's .notesPane
   so the suite reads as one family. */

body {
    display: flex;
    flex-direction: column;
    min-height: 100vh;
}

/* ── Layout ────────────────────────────────────────────────────────────── */
/* padding-top compensates for the fixed .appHeader (see header.css) so the
   sidebar + main pane sit below it instead of behind it. */
.appLayout {
    flex: 1;
    display: flex;
    min-height: 0;
    position: relative;
    padding-top: var(--header-height);
}

/* ── Sidebar (single pane) ──────────────────────────────────────────────
   The sidebar carries the .darkSidebar class — /common/css/theme.css
   maps that class to a dark variable scope so the children
   (search, checklist rows, "New list" button) inherit a dark surface
   without touching the main content pane. */
.sidebar {
    width: 320px;
    min-width: 260px;
    display: flex;
    flex-direction: row;
    overflow: hidden;
    position: relative;
    color: var(--text);
    border-right: 1px solid rgba(0, 0, 0, 0.12);
    transition: transform var(--transition), opacity var(--transition), margin-left var(--transition);
    flex-shrink: 0;
}
.sidebar.hidden {
    margin-left: calc(-1 * var(--sidebar-hidden-offset, 320px));
    opacity: 0;
    pointer-events: none;
}

.notesPane {
    flex: 1;
    min-width: 0;
    display: flex;
    flex-direction: column;
    overflow: hidden;
    background: var(--bg-sidebar);
}
.sidebarResizer {
    position: absolute;
    top: 0;
    right: -3px;
    width: 6px;
    height: 100%;
    cursor: col-resize;
    z-index: 20;
}

/* ── Pane header — height + padding match Noted exactly ───────────────── */
.notesPaneHeader {
    display: flex;
    align-items: center;
    gap: 8px;
    height: 48px;
    padding: 0 12px;
    flex-shrink: 0;
}
.notesPaneTitle {
    flex: 1;
    min-width: 0;
    font-size: 13px;
    font-weight: 600;
    color: var(--text);
    letter-spacing: -0.01em;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.sidebarPaneToggle {
    display: none;
    align-items: center;
    justify-content: center;
    gap: 6px;
    height: 30px;
    padding: 0 10px;
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    background: transparent;
    color: var(--text-secondary);
    font-size: 13px;
    font-weight: 500;
    letter-spacing: -0.005em;
    transition: background var(--transition), color var(--transition),
                border-color var(--transition);
    flex-shrink: 0;
}
.sidebarPaneToggle .fa-table-columns { font-size: 14px; }
.sidebarPaneToggle:hover {
    background: var(--bg-hover);
    color: var(--text);
    border-color: var(--border-strong);
}

/* Shared with .editorToolbarToggle. */
.sidebarToggleLabel { display: inline; }

/* ── Pane search — verbatim from Noted's .sidebarSearch ───────────────── */
.sidebarSearch {
    padding: 0px 10px 10px 10px;
    display: flex;
    align-items: center;
    gap: 6px;
    flex-shrink: 0;
}
.sidebarSearchField {
    flex: 1;
    min-width: 0;
    position: relative;
    display: flex;
}
.sidebarSearch input {
    flex: 1;
    min-width: 0;
    padding: 8px 30px 8px 12px;
    border-radius: var(--radius-sm);
    background: var(--bg);
    border: 1px solid var(--border);
    font-size: 13px;
    transition: border-color var(--transition);
}
.sidebarSearch input:focus { border-color: var(--border-strong); }
.sidebarSearch input::placeholder { color: var(--text-tertiary); }

.sidebarSearchClear {
    display: none;
    position: absolute;
    top: 50%;
    right: 6px;
    transform: translateY(-50%);
    width: 22px;
    height: 22px;
    align-items: center;
    justify-content: center;
    border: 0;
    background: transparent;
    border-radius: 999px;
    color: var(--text-tertiary);
    font-size: 11px;
    cursor: pointer;
    transition: background var(--transition), color var(--transition);
}
.sidebarSearchClear:hover { background: var(--bg-hover); color: var(--text); }
.sidebarSearchField:has(input:not(:placeholder-shown)) .sidebarSearchClear { display: flex; }

/* Resize cursor lock during drag (only the whole-sidebar resizer left). */
body.isResizing,
body.isResizing * { cursor: col-resize !important; user-select: none !important; }

/* Desktop: hide the kebab icon on list rows entirely — right-click opens
   the same menu, so the hover-reveal kebab is redundant. Selectors are
   matched against the hover rule below so they win the specificity tie
   inside the media query. Mobile keeps the kebab persistent (no
   right-click on touch). */
@media (min-width: 769px) {
    .noteItem .noteItemActions,
    .noteItem:hover .noteItemActions { display: none; }
}

/* ── Shared overflow menu (#actionsMenu) — list + folder ──────────────── */
.folderActionsMenu {
    position: fixed;
    z-index: 200;
    min-width: 220px;
    padding: 5px;
    background: var(--bg);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    box-shadow: 0 6px 24px rgba(0, 0, 0, 0.10), 0 1px 4px rgba(0, 0, 0, 0.04);
    display: none;
}
.folderActionsMenu.open { display: block; }
.folderActionsItem {
    display: flex;
    align-items: center;
    gap: 10px;
    width: 100%;
    padding: 9px 10px;
    background: transparent;
    border: 0;
    border-radius: var(--radius-sm);
    color: var(--text);
    font-size: 13.5px;
    text-align: left;
    cursor: pointer;
    transition: background var(--transition);
}
.folderActionsItem:hover { background: var(--bg-hover); }
.folderActionsItem i { width: 16px; text-align: center; font-size: 12px; color: var(--text-secondary); }
.folderActionsItem--danger { color: #c33; }
.folderActionsItem--danger i { color: #c33; }
.folderActionsItem--danger:hover { background: rgba(220, 50, 50, 0.08); }
.folderActionsDivider {
    height: 1px;
    background: var(--border);
    margin: 4px 6px;
}

/* Mobile: bigger menu items + drop hover-bg flash on touch. */
@media (max-width: 768px) {
    .folderActionsMenu { min-width: 240px; padding: 8px; }
    .folderActionsItem { gap: 14px; padding: 14px; font-size: 16px; }
    .folderActionsItem i { width: 20px; font-size: 16px; }
    .folderActionsItem:hover,
    .folderActionsItem:focus,
    .folderActionsItem--danger:hover,
    .folderActionsItem--danger:focus { background: transparent; }
}


/* ── Lists list — values match Noted's .notesList / .noteItem / .noteItemTitle
   / .noteItemDate verbatim so the two sidebars feel identical. */
.notesList {
    flex: 1;
    overflow-y: auto;
    padding: 0 8px 12px;
}
.noteItem {
    display: block;
    width: 100%;
    text-align: left;
    padding: 10px 12px;
    border-radius: var(--radius-sm);
    margin-bottom: 2px;
    transition: background var(--transition);
    position: relative;
    background: transparent;
    cursor: pointer;
}
.noteItem:hover { background: var(--bg-hover); }

/* Drag-to-reorder feedback — the source row dims so it's clear which
   row is in flight; the target paints a mint inset stripe on the half
   the cursor is in. Only rows rendered with draggable="true" qualify
   (Inbox + filtered-search rows are excluded). */
.noteItem[draggable="true"]:hover { cursor: grab; }
.noteItem[draggable="true"]:active { cursor: grabbing; }
.noteItem.dragging { opacity: 0.4; }
.noteItem.dropAbove { box-shadow: inset 0 2px 0 var(--mint); }
.noteItem.dropBelow { box-shadow: inset 0 -2px 0 var(--mint); }
/* Different highlight for cross-pane todo→list drops so the user
   can tell at a glance whether they're reordering checklists
   (top/bottom edge stripe) vs. dropping a todo into one (the
   whole row tints + outlines). */
.noteItem.dropTodoTarget {
    background: var(--accent-soft);
    box-shadow: inset 0 0 0 2px var(--mint);
}
/* Decorative grip handle to surface that checklists can be
   reordered. Floats absolutely inside an enlarged left gutter on
   the row, with the title pushed in via `:has()` so the icon
   doesn't crowd the checklist name. Subtle on hover only on
   desktop; stays low-opacity on touch where there's no hover. */
.listDragHandle {
    position: absolute;
    left: 8px;
    top: 50%;
    transform: translateY(-50%);
    width: 12px;
    text-align: center;
    color: var(--text-tertiary);
    font-size: 12px;
    opacity: 0;
    transition: opacity 120ms ease;
    pointer-events: none;
}
/* Bump the row's left padding only for rows that carry a handle
   so the Inbox / filtered rows keep their original geometry. The
   title now starts ~14px past the icon's right edge instead of
   tucked right behind it. */
.noteItem:has(.listDragHandle) { padding-left: 32px; }
.noteItem:hover .listDragHandle { opacity: 0.55; }
@media (hover: none) {
    .listDragHandle { opacity: 0.4; }
}
.noteItem.active { background: var(--bg-active); }
.noteItemTitle {
    font-size: 13.5px;
    font-weight: 500;
    line-height: 1.3;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    color: var(--text);
    margin-right: 60px;
    display: flex;
    align-items: center;
    gap: 8px;
}
/* Synthetic-list icon (Today's sun, Inbox's tray) prefixed inside
   .noteItemTitle so the row reads like the others while still
   distinguishing the special entries. */
.listRowIcon {
    flex-shrink: 0;
    width: 16px;
    text-align: center;
    color: var(--text-secondary);
    font-size: 12px;
}
.listRowName {
    flex: 1;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
}
/* Count badge on Today — small pill on the row's right edge.
   Today has no kebab, so the title's 60px right-reservation
   isn't needed; collapse it back so the badge can sit flush
   with the row's right padding. */
.listRowBadge {
    flex-shrink: 0;
    margin-left: auto;
    padding: 1px 8px;
    border-radius: 999px;
    background: var(--accent);
    color: var(--bg-sidebar);
    font-size: 10.5px;
    font-weight: 600;
    font-variant-numeric: tabular-nums;
    line-height: 1.6;
}
.noteItem:has(.listRowBadge) .noteItemTitle { margin-right: 12px; }
.noteItemDate {
    font-size: 11px;
    color: var(--text-tertiary);
    font-variant-numeric: tabular-nums;
    margin-top: 3px;
}
/* Subtitle preview shown in place of .noteItemDate when a checklist
   has a subtitle. Mirrors Noted's .noteItemPreview line so the two
   sidebars feel identical. */
.noteItemPreview {
    font-size: 12px;
    color: var(--text-tertiary);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    margin-top: 5px;
    margin-right: 60px;
}
.noteItemActions {
    position: absolute;
    top: 8px;
    right: 8px;
    width: 28px;
    height: 28px;
    display: none;
    align-items: center;
    justify-content: center;
    border-radius: var(--radius-sm);
    color: var(--text-tertiary);
    font-size: 13px;
    cursor: pointer;
}
.noteItem:hover .noteItemActions { display: flex; }
.noteItemActions:hover { background: var(--bg-hover); color: var(--text); }

/* ── Main content (todos pane) ────────────────────────────────────────── */
.mainContent {
    flex: 1;
    min-width: 0;
    display: flex;
    flex-direction: column;
    overflow: hidden;
    background: var(--bg);
}
.editorToolbar {
    display: flex;
    align-items: center;
    gap: 8px;
    height: 48px;
    padding: 0 10px;
    border-bottom: 1px solid var(--border);
    flex-shrink: 0;
}
/* Title + optional subtitle, rendered above the add-todo row as a page
   header. Mirrors the placement Noted uses for its .titleInput — large,
   prominent, sets the page identity before the working area starts. */
.todosTitleStack {
    display: flex;
    flex-direction: column;
    gap: 6px;
    padding: 24px 28px 12px;
    flex-shrink: 0;
}
.editorToolbarToggle {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 6px;
    height: 30px;
    padding: 0 10px;
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    background: transparent;
    color: var(--text-secondary);
    font-size: 13px;
    font-weight: 500;
    letter-spacing: -0.005em;
    cursor: pointer;
    transition: background var(--transition), color var(--transition),
                border-color var(--transition);
    flex-shrink: 0;
}
.editorToolbarToggle .fa-table-columns { font-size: 14px; }
.editorToolbarToggle:hover {
    background: var(--bg-hover);
    color: var(--text);
    border-color: var(--border-strong);
}
.todosTitle {
    font-size: 28px;
    font-weight: 700;
    color: var(--text);
    letter-spacing: -0.02em;
    line-height: 1.2;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.todosSubtitle {
    font-size: 15px;
    font-weight: 400;
    color: var(--text-secondary);
    letter-spacing: -0.005em;
    line-height: 1.4;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.todosView {
    flex: 1;
    display: flex;
    flex-direction: column;
    /* Single scroll container for the whole pane below the editor
       toolbar. Earlier the title + add row + filter chips were all
       pinned and only the .todosList scrolled; with overflow up
       here, the title scrolls away with everything else, so the
       page reads like one continuous document. */
    overflow-y: auto;
    overflow-x: hidden;
}
.todosEmpty {
    flex: 1;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    color: var(--text-tertiary);
    text-align: center;
    padding: 40px;
}
.todosEmpty i { font-size: 32px; margin-bottom: 12px; opacity: 0.4; }
.todosEmpty p { font-size: 14px; margin: 2px 0; }
.todosEmptyHint { font-size: 12.5px; color: var(--text-tertiary); }

/* ── Filter chips ─────────────────────────────────────────────────────── */
.todoFilterBar {
    display: flex;
    gap: 6px;
    padding: 5px 20px;
    overflow-x: auto;
    scrollbar-width: none;
    /* Pin its natural height inside the column-flex .todosView. The
       default flex-shrink:1 was letting the column-flex parent
       (now the scroll container) squeeze the chip row to nothing
       when other children claimed space. The chips already manage
       their own horizontal overflow; vertical-wise we just want
       the bar to occupy exactly its content height. */
    flex-shrink: 0;
}
.todoFilterBar::-webkit-scrollbar { display: none; }
.todoFilterChip {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 5px 12px;
    border-radius: 999px;
    background: var(--bg-sidebar);
    border: 1px solid var(--border);
    color: var(--text-secondary);
    font-size: 12.5px;
    font-weight: 500;
    cursor: pointer;
    flex-shrink: 0;
    transition: background var(--transition), color var(--transition), border-color var(--transition);
}
.todoFilterChip:hover { color: var(--text); border-color: var(--border-strong); }
.todoFilterChip.active {
    background: var(--accent);
    color: var(--bg-sidebar);
    border-color: var(--accent);
}
.todoFilterChipCount {
    font-variant-numeric: tabular-nums;
    font-size: 11.5px;
    opacity: 0.7;
}
/* ── Todos list ───────────────────────────────────────────────────────── */
/* No longer the scroll container — the parent .todosView now owns
   the vertical scroll so the title + add row + chips scroll with
   the rows. The list grows to its natural content height and the
   parent handles overflow. */
.todosList {
    padding: 12px 12px;
}
.todosListEmpty {
    padding: 40px 20px;
    text-align: center;
    color: var(--text-tertiary);
    font-size: 13px;
}
/* "Show N completed" / "Hide N completed" toggle that appears at the
   bottom of the todos list when the All view has done items. Inline,
   muted — it's a secondary action that yields to the active items
   above. */
/* Single row at the bottom of the todos list: "Show/Hide N
   completed" toggle on the left + a subtle "Clear" link on the
   right (only shown once the completed block is expanded so the
   action's scope is unambiguous). */
.todoCompletedRow {
    display: flex;
    align-items: center;
    gap: 8px;
    margin: 12px 4px 4px;
}
.todoCompletedToggle {
    flex: 1;
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 8px 12px;
    border: 0;
    border-radius: var(--radius-sm);
    background: transparent;
    color: var(--text-tertiary);
    font-size: 12.5px;
    font-weight: 500;
    cursor: pointer;
    transition: background var(--transition), color var(--transition);
    text-align: left;
}
.todoCompletedToggle:hover {
    background: var(--bg-hover);
    color: var(--text-secondary);
}
.todoCompletedToggle i {
    font-size: 11px;
    width: 12px;
    text-align: center;
}
/* "Clear" — quiet by design. Reads as a text link until hovered;
   on hover it tints red so the destructive nature is obvious
   right before the click. */
.todoCompletedClear {
    flex-shrink: 0;
    padding: 6px 10px;
    border: 0;
    border-radius: var(--radius-sm);
    background: transparent;
    color: var(--text-tertiary);
    font-size: 12px;
    font-weight: 500;
    cursor: pointer;
    transition: background var(--transition), color var(--transition);
}
.todoCompletedClear:hover {
    color: #c33;
    background: rgba(195, 50, 50, 0.08);
}
.todoRow {
    display: flex;
    align-items: flex-start;
    gap: 12px;
    padding: 10px 12px;
    /* Reserve a transparent 1px border on every row so the active
       row's visible border doesn't push neighbouring content
       around when it appears. Same idea applies to padding +
       margin: kept identical between collapsed and expanded
       states so the title's screen position is anchored. */
    border: 1px solid transparent;
    border-radius: var(--radius-sm);
    cursor: pointer;
    transition: background var(--transition), border-color var(--transition), box-shadow var(--transition);
    margin-bottom: 1px;
}
.todoRow:hover { background: var(--bg-hover); }
.todoRow.active { background: var(--bg-active); }
.todoRow.done .todoText { color: var(--text-tertiary); text-decoration: line-through; }

/* Drag-to-reorder visual feedback. Mint inset stripe at the top or
   bottom edge of the hover-target row tells the user where the
   dropped item will land; the source row dims so it's clear which
   row is in flight. Only shown on rows whose markup carried
   draggable="true" — completed/active/smart-view rows can't drag. */
.todoRow.dragging { opacity: 0.4; }
.todoRow.dropAbove { box-shadow: inset 0 2px 0 var(--mint); }
.todoRow.dropBelow { box-shadow: inset 0 -2px 0 var(--mint); }

.todoCheckbox {
    flex-shrink: 0;
    width: 18px;
    height: 18px;
    border: 1.5px solid var(--border-strong);
    border-radius: 4px;
    cursor: pointer;
    transition: all var(--transition);
    display: inline-flex;
    align-items: center;
    justify-content: center;
}
.todoCheckbox.checked {
    background: var(--accent);
    border-color: var(--accent);
}
.todoCheckbox.checked::after {
    content: "";
    width: 10px;
    height: 6px;
    border-left: 1.5px solid var(--bg-sidebar);
    border-bottom: 1.5px solid var(--bg-sidebar);
    transform: rotate(-45deg) translate(0, -1px);
}

/* Briefly added by the click handler when the user checks an item, so
   the box pops and the tick draws in before the row re-renders (and
   often disappears from filtered views). The class is purely visual —
   no rendering depends on its presence. */
.todoCheckbox.todoCheckboxAnimating {
    animation: todoCheckboxPop 0.32s ease;
}
.todoCheckbox.todoCheckboxAnimating::after {
    animation: todoCheckmarkDraw 0.3s ease;
}
@keyframes todoCheckboxPop {
    0%   { transform: scale(1); }
    45%  { transform: scale(1.18); }
    100% { transform: scale(1); }
}
@keyframes todoCheckmarkDraw {
    0%   { opacity: 0; transform: rotate(-45deg) translate(0, -1px) scale(0); }
    55%  { opacity: 1; transform: rotate(-45deg) translate(0, -1px) scale(1.25); }
    100% { opacity: 1; transform: rotate(-45deg) translate(0, -1px) scale(1); }
}
.todoMain {
    flex: 1;
    min-width: 0;
    display: flex;
    flex-direction: column;
    gap: 0px;
}
.todoText {
    font-size: 14px;
    color: var(--text);
    line-height: 1.4;
    outline: none;
    border-radius: 3px;
    word-break: break-word;
}
/* Editable affordance — only when the row is the active one (the
   detail card is open). Mirrors .todosTitle's hover/focus cues so the
   "click to edit" gesture reads the same in both places. */
.todoText[contenteditable] {
    cursor: text;
    padding: 2px 6px;
    margin: -2px -6px;
    transition: background var(--transition);
}
.todoText[contenteditable]:hover { background: var(--bg-hover); }
.todoText[contenteditable]:focus { background: var(--accent-soft); }
.todoText[contenteditable]:empty::before {
    content: attr(data-placeholder);
    color: var(--text-tertiary);
    font-style: italic;
    font-weight: 500;
}
/* One-line note preview shown below the todo title when the row is
   collapsed and the todo has a note. Replaces the old "has a note"
   icon with the actual content so the user can see what the note says
   without expanding the detail card. */
.todoNotePreview {
    font-size: 12.5px;
    color: var(--text-secondary);
    line-height: 1.35;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    /* Trim the .todoMain gap above this preview a touch — the title +
       preview should read as one stacked unit, distinct from the meta
       strip below. */
    margin-top: -2px;
}
.todoRow.done .todoNotePreview { color: var(--text-tertiary); }

/* Quick "Today" pill — only stamped on collapsed, undone, due-
   less rows. Lives at the row's right edge as a subtle nudge
   for one-tap triage. Hidden by default, fades in on row hover;
   on coarse-pointer / touch where hover is unreliable, it stays
   visible at a low opacity so the affordance is reachable. */
.todoQuickToday {
    flex-shrink: 0;
    align-self: center;
    display: inline-flex;
    align-items: center;
    gap: 5px;
    height: 24px;
    padding: 0 10px;
    border-radius: 999px;
    border: 1px solid var(--border);
    background: var(--bg);
    color: var(--text-secondary);
    font: inherit;
    font-size: 11.5px;
    font-weight: 500;
    cursor: pointer;
    opacity: 0;
    transition: opacity 120ms ease, background var(--transition),
                border-color var(--transition), color var(--transition),
                transform var(--transition);
}
.todoQuickToday i { font-size: 10.5px; }
.todoQuickToday:hover {
    background: var(--accent-soft);
    border-color: var(--border-strong);
    color: var(--text);
}
.todoQuickToday:active { transform: translateY(0.5px); }
.todoRow:hover .todoQuickToday { opacity: 1; }
@media (hover: none) {
    .todoQuickToday { opacity: 0.7; }
    .todoQuickToday span { display: none; }
    .todoQuickToday { padding: 0 8px; }
}

.todoMeta {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
    align-items: center;
}
/* Push the meta strip slightly off the title only when it actually
   carries something (due chip / attachment count). Uses :has(*)
   over :not(:empty) — :empty fails when the markup contains
   whitespace text nodes (newlines / indentation), which was
   inflating every row by 10px for no visible reason. :has(*)
   ignores text nodes and only matches a real element child. */
.todoMeta:has(*) { margin-top: 10px; }
.todoDueChip {
    display: inline-flex;
    align-items: center;
    padding: 2px 8px;
    border-radius: 999px;
    background: var(--bg-sidebar);
    border: 1px solid var(--border);
    color: var(--text-secondary);
    font-size: 11.5px;
    font-weight: 500;
    font-variant-numeric: tabular-nums;
}
.todoDueChip.overdue {
    background: rgba(220, 50, 50, 0.08);
    border-color: rgba(220, 50, 50, 0.25);
    color: #b33;
}
.todoMetaIcon {
    display: inline-flex;
    align-items: center;
    gap: 3px;
    color: var(--text-tertiary);
    font-size: 11.5px;
}

/* ── Add-todo row (prominent card, sits below the filter chips) ──────── */
.todoAddRow {
    display: flex;
    align-items: center;
    gap: 12px;
    /* Left-aligned to match the .todosTitleStack's left padding so the
       page header, the add-todo row, and (visually) the todos beneath
       all share the same left rail. max-width keeps the row from
       stretching into a runway on wide screens. */
    width: auto;
    max-width: 640px;
    margin: 12px 20px 14px 20px;
    padding: 4px 6px 4px 14px;
    background: var(--bg);
    border: 1px solid var(--border-strong);
    border-radius: 999px;
    box-shadow: 0 1px 3px rgba(0, 0, 0, 0.04),
                0 4px 14px rgba(0, 0, 0, 0.04);
    transition: border-color var(--transition), box-shadow var(--transition);
    flex-shrink: 0;
}
.todoAddRow:focus-within {
    border-color: var(--accent);
    box-shadow: 0 1px 3px rgba(0, 0, 0, 0.06),
                0 6px 18px rgba(0, 0, 0, 0.06);
}
.todoAddRow .doneAddItemPlus {
    border: 0;
    background: var(--accent-soft);
    color: var(--accent);
    font-size: 13px;
    width: 24px;
    height: 24px;
}
.todoAddRow .doneAddItemInput {
    padding: 10px 0;
    font-size: 15px;
    font-weight: 500;
}
.todoAddRow .doneAddItemBtn {
    height: 36px;
    padding: 0 18px;
    border-radius: 999px;
}
.doneAddItemPlus {
    width: 18px;
    height: 18px;
    flex-shrink: 0;
    color: var(--text-tertiary);
    font-size: 11px;
    display: flex;
    align-items: center;
    justify-content: center;
    border: 1.5px dashed var(--border);
    border-radius: var(--radius-sm);
}
.doneAddItemInput {
    flex: 1;
    /* min-width: 0 lets the input shrink below its intrinsic ~150px size
       attribute width — without this, narrow viewports push the Add
       button past the container's right edge. */
    min-width: 0;
    padding: 6px 2px;
    font-size: 14px;
    color: var(--text);
    background: transparent;
    border: 0;
    outline: none;
}
.doneAddItemInput::placeholder { color: var(--text-tertiary); }
.doneAddItemBtn {
    flex-shrink: 0;
    height: 30px;
    padding: 0 14px;
    border: 0;
    border-radius: 999px;
    background: var(--text);
    color: var(--bg);
    font-size: 13px;
    font-weight: 600;
    letter-spacing: -0.005em;
    cursor: pointer;
    transition: opacity 120ms ease, transform 120ms ease;
}
.doneAddItemBtn:hover { opacity: 0.88; }
.doneAddItemBtn:active { transform: translateY(0.5px); }
.todoAddRow:has(.doneAddItemInput:placeholder-shown) .doneAddItemBtn {
    opacity: 0.35;
    pointer-events: none;
}

/* ── Todo inline detail (expands within the row, not a drawer) ────────── */

/* Inner row containing checkbox + main + close button. */
.todoRowLine {
    display: flex;
    align-items: flex-start;
    gap: 12px;
    width: 100%;
}
/* When a row is expanded, switch to column so the detail card sits below
   the line and uses the FULL pane width — earlier the .todoRow's
   default flex-row layout squeezed the detail into a narrow second column.
   Padding / margin / border GEOMETRY is intentionally identical to the
   collapsed state so the title stays anchored to the same on-screen
   position when the row expands; only color + shadow change to mark
   the active row visually. */
.todoRow.active {
    flex-direction: column;
    align-items: stretch;
    gap: 0;
    background: var(--bg);
    border-color: var(--border-strong);
    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.04),
                0 8px 22px rgba(0, 0, 0, 0.05);
}
.todoRowCloseBtn {
    flex-shrink: 0;
    width: 18px;
    height: 18px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border-radius: var(--radius-sm);
    color: var(--text-tertiary);
    background: transparent;
    border: 0;
    font-size: 12px;
    cursor: pointer;
    transition: background var(--transition), color var(--transition);
}
.todoRowCloseBtn:hover { background: var(--bg-hover); color: var(--text); }

.todoRowDetail {
    margin-top: 14px;
    padding-top: 16px;
    border-top: 1px solid var(--border);
    /* 2-column grid for the field stack so wide panes don't show a thin
       column with lots of empty space. Long fields (note, attachments,
       reminders) span the full width via .todoDetailField--wide. */
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    column-gap: 20px;
    row-gap: 0;
    /* Tiny fade-in so the body feels like it's expanding out of the
       row, not just popping in. The row line above stays where it
       is — only this body grows in. */
    animation: todoRowDetailExpand 180ms ease;
}
@keyframes todoRowDetailExpand {
    from { opacity: 0; transform: translateY(-4px); }
    to   { opacity: 1; transform: translateY(0); }
}
.todoDetailField--wide { grid-column: 1 / -1; }

/* On narrower main panes, fall back to a single column. The threshold
   is the inner width of the active row, not the viewport — but since we
   can't query that in CSS, we approximate with a viewport rule that
   matches the typical sidebar(320) + breakpoint headroom. */
@media (max-width: 900px) {
    .todoRowDetail { grid-template-columns: minmax(0, 1fr); column-gap: 0; }
}

.todoDetailFooter {
    display: flex;
    justify-content: flex-end;
    margin-top: 10px;
    padding-top: 10px;
    border-top: 1px solid var(--border);
}
.todoDetailFooter .todoDetailDelete {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 6px 12px;
    border-radius: var(--radius-sm);
    background: transparent;
    border: 0;
    color: #c33;
    font-size: 13px;
    cursor: pointer;
    transition: background var(--transition);
}
.todoDetailFooter .todoDetailDelete:hover { background: rgba(220, 50, 50, 0.10); }

/* Editable list title + subtitle as a page header above the add-todo row. */
.todosTitle[contenteditable],
.todosSubtitle[contenteditable] {
    cursor: text;
    padding: 4px 8px;
    margin-left: -8px;
    border-radius: var(--radius-sm);
    transition: background var(--transition);
}
.todosTitle[contenteditable]:hover,
.todosSubtitle[contenteditable]:hover { background: var(--bg-hover); }
.todosTitle[contenteditable]:focus,
.todosSubtitle[contenteditable]:focus { background: var(--accent-soft); outline: none; }
.todosTitle[contenteditable]:empty::before,
.todosSubtitle[contenteditable]:empty::before {
    content: attr(data-placeholder);
    color: var(--text-tertiary);
    font-weight: 400;
}

.todoDetailField {
    margin-bottom: 18px;
}
.todoDetailLabel {
    display: block;
    font-size: 11.5px;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: var(--text-tertiary);
    margin-bottom: 6px;
}
.todoDetailInput,
.todoDetailTextarea {
    width: 100%;
    padding: 8px 10px;
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    background: var(--bg);
    color: var(--text);
    font-size: 14px;
    font-family: inherit;
    transition: border-color var(--transition);
}
.todoDetailInput:focus,
.todoDetailTextarea:focus {
    outline: none;
    border-color: var(--accent);
}
.todoDetailTextarea {
    resize: vertical;
    min-height: 88px;
    line-height: 1.5;
}
/* Custom-styled select for the "Checklist" picker. The native
   <select> is hidden behind a styled wrapper so the field reads
   the same as the other detail inputs (icon + label + chevron),
   while the browser still owns the dropdown widget. */
.todoDetailListPicker {
    position: relative;
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 10px 12px;
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    background: var(--bg);
    color: var(--text);
    font-size: 13.5px;
    line-height: 1.2;
    cursor: pointer;
    transition: border-color var(--transition);
}
.todoDetailListPicker:focus-within { border-color: var(--accent); }
.todoDetailListPickerIcon {
    flex-shrink: 0;
    width: 16px;
    text-align: center;
    color: var(--text-tertiary);
    font-size: 13px;
}
.todoDetailListPickerChevron {
    flex-shrink: 0;
    color: var(--text-tertiary);
    font-size: 11px;
    pointer-events: none;
}
.todoDetailListPickerSelect {
    flex: 1;
    min-width: 0;
    border: 0;
    background: transparent;
    color: inherit;
    font: inherit;
    padding: 0;
    cursor: pointer;
    appearance: none;
    -webkit-appearance: none;
    -moz-appearance: none;
    outline: none;
}
/* ── Due-date component ───────────────────────────────────────────────
   A single-column stack: state-aware preview pill on top, quick-pick
   chip row in the middle, native datetime picker tucked into a "Custom"
   row at the bottom. Replaces the old text input + Clear button row,
   which forced users to think in YYYY-MM-DD when most due dates are
   "today" or "tomorrow". */
.todoDueComponent {
    display: flex;
    flex-direction: column;
    gap: 10px;
}
.todoDuePreview {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 7.5px 12px;
    border-radius: var(--radius-sm);
    border: 1px solid var(--border);
    background: var(--bg-sidebar);
    color: var(--text-secondary);
    font-size: 13.5px;
    line-height: 1.2;
    /* Pin a stable inner row height (≥ the clear-X button) so the
       pill renders at exactly the same outer dimensions whether
       it's "No due date" (no button), "Tomorrow at 9 AM" (button
       present), or "Yesterday at 5 PM" (overdue + button). Empty
       and set states no longer jump in height. */
    min-height: 22px;
    transition: background var(--transition), color var(--transition),
                border-color var(--transition);
}
.todoDuePreviewIcon {
    font-size: 14px;
    width: 16px;
    text-align: center;
    flex-shrink: 0;
}
.todoDuePreviewText {
    flex: 1;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.todoDuePreview--empty {
    color: var(--text-tertiary);
    background: var(--bg-sidebar);
    border-style: dashed;
}
.todoDuePreview--set {
    color: #1f4d7a;
    background: rgba(45, 102, 175, 0.08);
    border-color: rgba(45, 102, 175, 0.22);
}
.todoDuePreview--overdue {
    color: #a32424;
    background: rgba(195, 50, 50, 0.08);
    border-color: rgba(195, 50, 50, 0.25);
}
.todoDueClearBtn {
    flex-shrink: 0;
    width: 22px;
    height: 22px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border: 0;
    border-radius: 999px;
    background: transparent;
    color: inherit;
    opacity: 0.55;
    cursor: pointer;
    font-size: 11px;
    transition: background var(--transition), opacity var(--transition);
}
.todoDueClearBtn:hover { opacity: 1; background: rgba(0, 0, 0, 0.06); }
.todoDueClearBtn[hidden] { display: none; }

/* Quick-pick chip row of preset dates. */
.todoDueQuickRow {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
}
.todoDueQuickBtn {
    padding: 6px 12px;
    border-radius: 999px;
    border: 1px solid var(--border);
    background: var(--bg);
    color: var(--text-secondary);
    font-size: 12.5px;
    font-weight: 500;
    cursor: pointer;
    transition: background var(--transition), color var(--transition),
                border-color var(--transition);
}
.todoDueQuickBtn:hover {
    background: var(--bg-hover);
    color: var(--text);
    border-color: var(--border-strong);
}
.todoDueQuickBtn:active { transform: translateY(0.5px); }

.todoDueCustomRow {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 8px 10px;
    border: 1px dashed var(--border);
    border-radius: var(--radius-sm);
    background: var(--bg);
    cursor: text;
}
.todoDueCustomLabel {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    font-size: 12px;
    color: var(--text-tertiary);
    font-weight: 500;
    white-space: nowrap;
    flex-shrink: 0;
}
.todoDueInput {
    flex: 1;
    min-width: 0;
    border: 0;
    background: transparent;
    color: var(--text);
    font-size: 13.5px;
    font-family: inherit;
    padding: 2px 0;
    outline: none;
}
.todoDueInput::-webkit-calendar-picker-indicator {
    cursor: pointer;
    opacity: 0.6;
}
.todoDueInput::-webkit-calendar-picker-indicator:hover { opacity: 1; }

.todoDetailPlaceholder {
    padding: 10px 14px;
    background: var(--bg-sidebar);
    border: 1px dashed var(--border);
    border-radius: var(--radius-sm);
    color: var(--text-tertiary);
    font-size: 12.5px;
    line-height: 1.4;
}

/* ── Detail-card pills row ───────────────────────────────────────────
   Below the Note textarea, every component (checklist, due date, each
   reminder, each attachment, plus + Add affordances) renders as a
   single pill. Filled (--set) when the value is present, dashed
   (--add) when the pill is an "add this" prompt. Clicking an
   editable pill expands the editor in #detailExpander; the inline ×
   on a set pill clears its value without opening anything. */
.todoDetailPills {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 6px;
    margin-top: 4px;
}
.detailPill {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    padding: 6px 14px;
    border-radius: 999px;
    border: 1px solid var(--border);
    background: var(--bg);
    color: var(--text-secondary);
    font-size: 12.5px;
    font-weight: 500;
    line-height: 1.2;
    cursor: pointer;
    transition: background var(--transition), color var(--transition),
                border-color var(--transition), box-shadow var(--transition);
    max-width: 100%;
}
.detailPill:hover {
    background: var(--bg-hover);
    color: var(--text);
    border-color: var(--border-strong);
}
.detailPill > i {
    font-size: 12px;
    flex-shrink: 0;
}
.detailPillText {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    max-width: 240px;
}
.detailPill--add {
    border-style: dashed;
    color: var(--text-tertiary);
}
.detailPill--add:hover {
    border-color: var(--accent);
    color: var(--text);
}
.detailPill--set {
    background: rgba(45, 102, 175, 0.08);
    border-color: rgba(45, 102, 175, 0.25);
    color: #1f4d7a;
}
.detailPill--set:hover {
    background: rgba(45, 102, 175, 0.14);
    border-color: rgba(45, 102, 175, 0.35);
    color: #1f4d7a;
}
.detailPill--overdue {
    background: rgba(195, 50, 50, 0.08);
    border-color: rgba(195, 50, 50, 0.28);
    color: #a32424;
}
.detailPill--overdue:hover {
    background: rgba(195, 50, 50, 0.14);
    border-color: rgba(195, 50, 50, 0.4);
    color: #a32424;
}
.detailPill--active {
    box-shadow: 0 0 0 2px rgba(45, 102, 175, 0.16);
    border-color: rgba(45, 102, 175, 0.55);
}

.detailPillClear {
    margin-right: -6px;
    margin-left: -2px;
    width: 18px;
    height: 18px;
    border-radius: 999px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    opacity: 0.55;
    transition: opacity var(--transition), background var(--transition);
    cursor: pointer;
}
.detailPillClear i { font-size: 9.5px; }
.detailPillClear:hover {
    opacity: 1;
    background: rgba(0, 0, 0, 0.10);
}

/* Inline editor that opens beneath the pills row when an editable
   pill is active. The list / due / reminder-new editors render
   their existing primitives (.todoDetailListPicker /
   .todoDueComponent / .todoReminderAddRow) inside this slot. */
.todoDetailExpander {
    margin-top: 10px;
    padding: 12px;
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    background: var(--bg-sidebar);
    display: flex;
    flex-direction: column;
    gap: 10px;
}
.todoDetailExpander[hidden] { display: none; }

.todoDetailFootMsg {
    margin-top: 8px;
    font-size: 12px;
    color: var(--text-tertiary);
    min-height: 1em;
}
.todoDetailFootMsg--ok    { color: #1f6b3d; }
.todoDetailFootMsg--error { color: #c33; }

/* Reminder add row — kept (the +Reminder pill renders this inside
   the expander). Same .todoDueCustomRow shape, with an Add button
   tacked on the end. */
.todoReminderAddRow {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 8px 10px;
    border: 1px dashed var(--border);
    border-radius: var(--radius-sm);
    background: var(--bg);
    flex-wrap: wrap;
}
.todoReminderAddRow .todoDueCustomField {
    flex: 1;
    min-width: 140px;
    display: flex;
    align-items: center;
    gap: 8px;
}
.todoReminderAddBtn {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 6px 14px;
    border-radius: 999px;
    border: 1px solid var(--accent);
    background: var(--accent);
    color: var(--bg-sidebar);
    font-size: 12.5px;
    font-weight: 500;
    cursor: pointer;
    transition: opacity var(--transition);
    flex-shrink: 0;
}
.todoReminderAddBtn:hover  { opacity: 0.92; }
.todoReminderAddBtn:active { transform: translateY(0.5px); }
.todoReminderAddBtn:disabled { opacity: 0.5; cursor: not-allowed; }

.todoReminderMsg {
    font-size: 12px;
    color: var(--text-tertiary);
    min-height: 1em;
}
.todoReminderMsg--ok    { color: #1f6b3d; }
.todoReminderMsg--error { color: #c33; }

/* ── Attachment upload zone + list (todo detail drawer) ───────────────── */
/* Box dimensions / chrome match .todoDuePreview — same padding,
   border weight, radius, background, font-size — so the two
   neighbouring detail-card slots read as the same component. The
   .dragover state still lights up the border so the drop-target
   affordance survives. */
.todoAttachZone {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 10px 12px;
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    background: var(--bg-sidebar);
    color: var(--text-secondary);
    font-size: 13.5px;
    line-height: 1.2;
    /* Same inner-row floor as .todoDuePreview so the two boxes
       render at identical heights — and stay that way whether the
       list below is empty or full of attachments (the list grows
       in its own block, the zone itself never resizes). */
    min-height: 22px;
    cursor: pointer;
    transition: border-color var(--transition), background var(--transition), color var(--transition);
}
.todoAttachZone:hover,
.todoAttachZone:focus-visible,
.todoAttachZone.dragover {
    border-color: var(--accent);
    color: var(--text);
    outline: none;
}
.todoAttachZone i {
    font-size: 14px;
    width: 16px;
    text-align: center;
    color: var(--text-tertiary);
    flex-shrink: 0;
}
.todoAttachZoneLink { color: var(--accent); font-weight: 600; }

.todoAttachList { margin-top: 10px; display: flex; flex-direction: column; gap: 8px; }
.todoAttachItem {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 8px 10px;
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    background: var(--bg);
}
.todoAttachThumb,
.todoAttachIcon {
    flex-shrink: 0;
    width: 36px;
    height: 36px;
    display: flex;
    align-items: center;
    justify-content: center;
    border-radius: var(--radius-sm);
    background: var(--bg-sidebar);
    color: var(--text-tertiary);
    font-size: 14px;
    overflow: hidden;
    text-decoration: none;
}
.todoAttachThumb img { width: 100%; height: 100%; object-fit: cover; }
.todoAttachMeta {
    flex: 1;
    min-width: 0;
    display: flex;
    flex-direction: column;
    gap: 1px;
}
.todoAttachName {
    font-size: 13px;
    color: var(--text);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    text-decoration: none;
}
.todoAttachName:hover { text-decoration: underline; }
.todoAttachSize {
    font-size: 11px;
    color: var(--text-tertiary);
    font-variant-numeric: tabular-nums;
}
.todoAttachDelete {
    flex-shrink: 0;
    width: 26px;
    height: 26px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border-radius: var(--radius-sm);
    color: var(--text-tertiary);
    background: transparent;
    border: 0;
    cursor: pointer;
    transition: background var(--transition), color var(--transition);
}
.todoAttachDelete:hover { background: rgba(220, 50, 50, 0.10); color: #c33; }

.todoAttachStatus {
    margin-top: 8px;
    font-size: 12px;
    color: var(--text-tertiary);
    min-height: 1em;
}
.todoAttachStatus.uploading { color: var(--text-secondary); }
.todoAttachStatus.error { color: #c33; }

/* ── Header primary CTA ".notesPaneNewBtn" (kept from earlier) ────────── */
.notesPaneNewBtn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 6px;
    min-width: 30px;
    min-height: 30px;
    padding: 0 10px;
    border-radius: var(--radius-sm);
    background: var(--accent);
    color: var(--bg-sidebar);
    font-size: 15px;
    font-weight: 500;
    box-shadow: 0 1px 2px rgba(0, 0, 0, 0.10),
                inset 0 1px 0 rgba(255, 255, 255, 0.08);
    transition: background 120ms ease, color 120ms ease,
                box-shadow 160ms ease, transform 120ms ease;
    flex-shrink: 0;
}
.notesPaneNewBtn:not(:has(.notesPaneNewBtnLabel)) {
    padding: 0;
    width: 30px;
}
.notesPaneNewBtnLabel {
    font-size: 13.5px;
    font-weight: 500;
    letter-spacing: -0.005em;
    white-space: nowrap;
}
.notesPaneNewBtn:hover {
    box-shadow: 0 3px 8px rgba(0, 0, 0, 0.16),
                inset 0 1px 0 rgba(255, 255, 255, 0.12);
    transform: translateY(-0.5px);
}
.notesPaneNewBtn:active {
    transform: translateY(0);
    box-shadow: 0 1px 2px rgba(0, 0, 0, 0.10),
                inset 0 1px 0 rgba(255, 255, 255, 0.08);
}

/* ── Export popover ───────────────────────────────────────────────────── */
.doneExportPopover {
    position: fixed;
    top: calc(var(--header-height) + 6px);
    right: 58px;
    min-width: 220px;
    padding: 6px;
    background: var(--bg);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    box-shadow: 0 6px 24px rgba(0, 0, 0, 0.10), 0 1px 4px rgba(0, 0, 0, 0.04);
    z-index: 200;
    display: none;
}
.doneExportPopover[data-open="true"] { display: block; }
.doneExportItem {
    display: flex;
    align-items: center;
    gap: 10px;
    width: 100%;
    padding: 8px 10px;
    border-radius: var(--radius-sm);
    font-size: 13px;
    color: var(--text);
    text-align: left;
    transition: background var(--transition);
    cursor: pointer;
}
.doneExportItem:hover { background: var(--bg-hover); }
.doneExportItem i { color: var(--text-tertiary); font-size: 12px; width: 14px; text-align: center; }
.doneExportItemSub { display: block; font-size: 11px; color: var(--text-tertiary); }
.doneExportItemMain { flex: 1; }

/* ── Undo toast ───────────────────────────────────────────────────────── */
.doneToast {
    position: fixed;
    bottom: 60px;
    right: 20px;
    display: none;
    align-items: center;
    gap: 12px;
    padding: 10px 14px;
    background: var(--text);
    color: #fff;
    border-radius: var(--radius);
    font-size: 13px;
    box-shadow: 0 6px 20px rgba(0, 0, 0, 0.22);
    z-index: 150;
    max-width: 360px;
}
.doneToast[data-open="true"] { display: flex; }
.doneToastMsg { flex: 1; }
.doneToastUndo {
    padding: 4px 10px;
    border-radius: var(--radius-sm);
    font-size: 13px;
    font-weight: 600;
    color: var(--mint);
    background: transparent;
    border: 0;
    cursor: pointer;
    transition: opacity var(--transition);
}
.doneToastUndo:hover { opacity: 0.8; }

/* Info variant - no action button, sits a row above the undo slot so
   a passive confirmation that happens during an active undo never
   covers the Undo affordance. */
.doneToast--info { bottom: 110px; }

/* ── Sync status chip (header) ────────────────────────────────────────────
   Minimal bordered chip with three states: checkmark (synced), spinning
   arrow (syncing), x-mark (offline). Sized to harmonize with the header
   buttons — same height, same hairline border. Background is transparent
   at rest; only the icon + border carry the state color. */
.syncStatus {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 6px;
    height: 32px;
    padding: 0 12px;
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    background: transparent;
    color: var(--text-secondary);
    font-size: 13px;
    font-weight: 500;
    letter-spacing: -0.005em;
    margin-right: 4px;
    white-space: nowrap;
    transition: color 200ms ease, border-color 200ms ease;
}
.syncStatusIcon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 14px;
    font-size: 12px;
    line-height: 1;
}
.syncStatus.syncStatus--ok {
    color: #1f6b3d;
    border-color: rgba(45, 122, 74, 0.30);
}
.syncStatus.syncStatus--syncing {
    color: var(--text-secondary);
    border-color: var(--border-strong);
}
.syncStatus.syncStatus--offline {
    color: #a32424;
    border-color: rgba(160, 38, 38, 0.30);
}
.syncStatusLabel {
    /* Wrapper so the label collapses on narrow viewports while the icon
       stays as a quiet status indicator. */
    display: inline;
}

/* ── Mobile responsive ────────────────────────────────────────────────── */
@media (max-width: 768px) {
    .sidebar {
        position: fixed;
        top: var(--header-height);
        left: 0;
        right: 0;
        bottom: 0;
        width: auto !important;
        min-width: 0 !important;
        border-right: 0;
        z-index: 50;
        box-shadow: 2px 0 12px rgba(0, 0, 0, 0.08);
    }
    .sidebar.hidden { margin-left: -100vw; }
    .notesPane {
        width: 100% !important;
        min-width: 0 !important;
        flex-shrink: 0;
    }

    .sidebarPaneToggle { display: inline-flex; }
    .sidebarResizer { display: none; }

    /* Desktop hides the kebab entirely (right-click opens the same menu),
       but touch has neither hover nor right-click — keep the dots visible
       so users can reach Rename / Delete. Sized to match Noted's
       .folderItemAction kebab so the two sidebars feel identical:
       20px wide, 14px glyph. */
    .noteItemActions {
        display: flex;
        width: 20px;
        height: 20px;
        font-size: 14px;
    }

    /* Pane buttons + new buttons + filter chips: bumped touch targets.
       On mobile the sidebar toggle keeps its label ("Checklists" — set
       in the markup) so the user knows what tapping it opens. */
    .notesPaneHeader { height: 56px; }
    .sidebarPaneToggle,
    .editorToolbarToggle {
        height: 40px;
        padding: 0 12px;
        font-size: 14px;
    }
    .sidebarPaneToggle .fa-table-columns,
    .editorToolbarToggle .fa-table-columns { font-size: 16px; }
    .editorToolbar { height: 56px; padding: 0 12px; }
    .todosTitleStack { padding: 20px 16px 10px; gap: 4px; }
    .todosTitle { font-size: 24px; }
    .todosSubtitle { font-size: 14px; }
    /* Match the title stack's 16px left padding so the add row hugs the
       same left rail on phones. */
    .todoAddRow { margin: 12px 16px 14px; }
    .notesPaneNewBtn { min-height: 35px; min-width: 40px; }
    .notesPaneNewBtn:not(:has(.notesPaneNewBtnLabel)) { width: 40px; }

    .doneAddItemBtn { height: 38px; padding: 0 18px; font-size: 14px; }

    /* List rows get more breathing room. */
    .noteItem { padding: 12px; }
    .noteItemTitle { font-size: 15.5px; }

    .todoFilterChip { font-size: 13px; padding: 7px 14px; }
    .todoText { font-size: 15px; }

    /* iOS Safari auto-zooms when a focused input has font-size < 16px.
       Floor every editable control at 16px on mobile so tapping the
       add-todo input, the search box, the inline detail fields, etc.
       doesn't shift the viewport. */
    .doneAddItemInput,
    .todoAddRow .doneAddItemInput,
    .sidebarSearch input,
    .todoDetailInput,
    .todoDetailTextarea,
    .todoDueInput {
        font-size: 16px;
    }

    /* Mobile: collapse the chip to an icon-only square so the right-side
       cluster never pushes into the Done wordmark. The colored border +
       icon still convey state at a glance. */
    .syncStatus {
        width: 35px;
        height: 35px;
        padding: 0;
        gap: 0;
        margin-right: 0;
    }
    .syncStatusLabel { display: none; }
}

/* ── Toothpaste-style picker modal (due-date / reminder) ────────────
   Sits on top of the .confirmModal scaffold below. Header with title
   + close, body with stacked .tpModalField rows (date and time on
   their own lines), footer with Cancel / Save. Rounded corners and
   blur backdrop come from the scaffold; what's added here is the
   layout of the body itself. */
.tpModalContent {
    width: 380px;
    max-width: calc(100% - 32px);
    border-radius: 18px;
    padding: 22px 24px 18px;
}
.tpModalHeader {
    display: flex;
    align-items: center;
    gap: 10px;
    margin-bottom: 16px;
}
.tpModalTitle {
    flex: 1;
    margin: 0;
    font-size: 15px;
    font-weight: 600;
    color: var(--text);
    letter-spacing: -0.005em;
}
.tpModalClose {
    width: 28px;
    height: 28px;
    border-radius: 999px;
    border: 0;
    background: transparent;
    color: var(--text-tertiary);
    cursor: pointer;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    transition: background var(--transition), color var(--transition);
}
.tpModalClose:hover { background: var(--bg-hover); color: var(--text); }
.tpModalBody {
    display: flex;
    flex-direction: column;
    gap: 12px;
}
.tpModalField {
    display: flex;
    flex-direction: column;
    gap: 6px;
}
.tpModalFieldLabel {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    font-size: 12px;
    font-weight: 500;
    color: var(--text-secondary);
    letter-spacing: 0.01em;
}
.tpModalInput {
    width: 100%;
    padding: 9px 12px;
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    background: var(--bg);
    color: var(--text);
    font-size: 14px;
    font-family: inherit;
    outline: none;
    transition: border-color var(--transition), box-shadow var(--transition);
}
.tpModalInput:focus {
    border-color: var(--accent);
    box-shadow: 0 0 0 3px rgba(45, 102, 175, 0.16);
}
.tpModalQuickRow {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
    margin-top: 2px;
}
.tpModalMsg {
    font-size: 12px;
    color: var(--text-tertiary);
    min-height: 1em;
}
.tpModalMsg--error { color: #c33; }
.tpModalFooter {
    display: flex;
    justify-content: flex-end;
    gap: 8px;
    margin-top: 18px;
}
.confirmModalBtnCancel {
    background: transparent;
    color: var(--text-secondary);
    border: 1px solid var(--border);
}
.confirmModalBtnCancel:hover { background: var(--bg-hover); color: var(--text); border-color: var(--border-strong); }

/* ── Confirm modal scaffold (used by the onboarding modal). Verbatim
   from Noted's confirmModal so the visual language matches across the
   suite. ─────────────────────────────────────────────────────────────── */
.confirmModal {
    display: none;
    position: fixed;
    inset: 0;
    z-index: 300;
    align-items: center;
    justify-content: center;
}
.confirmModal.open { display: flex; }
.confirmModalBackdrop {
    position: absolute;
    inset: 0;
    background: rgba(20, 20, 20, 0.32);
    backdrop-filter: blur(2px);
    -webkit-backdrop-filter: blur(2px);
}
.confirmModalContent {
    position: relative;
    background: var(--bg);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    box-shadow: 0 12px 40px rgba(0, 0, 0, 0.15), 0 2px 8px rgba(0, 0, 0, 0.06);
    padding: 22px 22px 18px;
    width: 380px;
    max-width: calc(100% - 32px);
}
.confirmModalBtn {
    padding: 7px 14px;
    border-radius: var(--radius-sm);
    font-size: 13px;
    font-weight: 500;
    transition: background var(--transition), color var(--transition), border-color var(--transition), opacity var(--transition);
    border: 1px solid transparent;
    cursor: pointer;
}
.confirmModalBtnPrimary {
    color: #fff;
    background: var(--accent);
}

/* ── First-visit onboarding modal — verbatim from Noted ───────────────── */
.onboardingModalContent {
    width: 380px;
    max-width: calc(100% - 32px);
    padding: 32px 28px 24px;
    text-align: center;
    border-radius: 18px;
    max-height: calc(100vh - 32px);
    max-height: calc(100dvh - 32px);
    overflow-y: auto;
    -webkit-overflow-scrolling: touch;
}
.onboardingHero { margin-bottom: 24px; }
.onboardingAppIcon {
    width: 72px;
    height: 72px;
    margin: 0 auto 18px;
    display: flex;
    align-items: center;
    justify-content: center;
    background: linear-gradient(135deg, #2D2D2D 0%, #4A4A4A 100%);
    color: #fff;
    border-radius: 18px;
    font-size: 30px;
    box-shadow: 0 8px 24px rgba(0, 0, 0, 0.18), 0 1px 2px rgba(0, 0, 0, 0.06);
}
.onboardingTitle {
    font-size: 24px;
    font-weight: 700;
    letter-spacing: -0.02em;
    margin: 0 0 6px;
    color: var(--text);
}
.onboardingSubtitle {
    font-size: 13.5px;
    color: var(--text-secondary);
    line-height: 1.4;
    margin: 0;
}
.onboardingFeatures {
    display: flex;
    flex-direction: column;
    gap: 18px;
    margin: 0 0 24px;
    padding: 0;
    list-style: none;
    text-align: left;
}
.onboardingFeature { display: flex; align-items: flex-start; gap: 14px; }
.onboardingFeatureIcon {
    flex-shrink: 0;
    width: 32px;
    height: 32px;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 22px;
    margin-top: 2px;
}
.onboardingFeatureIcon--pink   { color: #e84c6b; }
.onboardingFeatureIcon--green  { color: #2d9b5a; }
.onboardingFeatureIcon--purple { color: #7758c4; }
.onboardingFeatureIcon--blue   { color: #2563eb; }
.onboardingFeatureBody { flex: 1; min-width: 0; }
.onboardingFeatureTitle {
    font-size: 14.5px;
    font-weight: 600;
    color: var(--text);
    margin-bottom: 2px;
    letter-spacing: -0.01em;
}
.onboardingFeatureDesc {
    font-size: 12.5px;
    color: var(--text-secondary);
    line-height: 1.45;
}
.onboardingContinueBtn {
    width: 100%;
    padding: 12px 14px;
    font-size: 14px;
    font-weight: 600;
    border-radius: var(--radius);
}

@media (max-width: 600px), (max-height: 700px) {
    .onboardingModalContent {
        padding: 22px 20px 16px;
        max-width: calc(100% - 24px);
        max-height: calc(100vh - 16px);
        max-height: calc(100dvh - 16px);
    }
    .onboardingHero { margin-bottom: 16px; }
    .onboardingAppIcon {
        width: 56px;
        height: 56px;
        margin-bottom: 12px;
        font-size: 24px;
        border-radius: 14px;
    }
    .onboardingTitle { font-size: 20px; }
    .onboardingSubtitle { font-size: 13px; }
    .onboardingFeatures { gap: 12px; margin-bottom: 16px; }
    .onboardingFeatureIcon { width: 28px; height: 28px; font-size: 18px; }
    .onboardingFeatureTitle { font-size: 14px; }
    .onboardingFeatureDesc  { font-size: 12px; }
    .onboardingContinueBtn {
        position: sticky;
        bottom: 0;
        box-shadow: 0 -16px 16px -8px var(--bg);
    }
}
