/* ============================================================
   Ospaces — "Refined"   (loaded after redesign.css, before rtl.css)
   ------------------------------------------------------------
   WHY THIS EXISTS
   The identity layer (redesign.css) set the palette, type and the
   floating-pane idea. This layer is the CRAFT pass on top of it:
   the parts that were still reading as unfinished when the app was
   put on screen and audited surface by surface.

   What it fixes, and why each one mattered:

   1 · NATIVE CONTROLS.  Reminders shipped a raw `mm/dd/yyyy` date
       field, a raw time field and an unstyled <select> sitting
       beside otherwise custom controls — the single loudest "this
       is a hobby project" tell. `color-scheme` also wasn't set, so
       native pickers rendered WHITE in dark mode.
   2 · THE PANE STOPPED FLOATING IN DARK MODE. #1b1a20 on #131218
       is a 1.15:1 surface delta; the shadow does nothing that dark,
       so the whole "pane on a frame" concept collapsed into a flat
       screen. Fixed by deepening the frame and lifting the pane.
   3 · MOBILE TOPBAR COLLISION. mobile.css reserves `padding-left:
       54px` for the floating hamburger, but redesign.css re-declares
       `#topbar { padding: 0 14px }` LATER at equal specificity — so
       the reservation lost the cascade and the hamburger sat on top
       of the breadcrumbs. Re-asserted here, later still.
   4 · THE AI DRAWER BROKE THE PANE. It is body-fixed, so it squared
       off the pane's rounded corner, ran the full viewport height
       and dimmed the page it was writing about. It now docks inside
       the pane geometry and pushes content instead of hiding it.
   5 · GLASSMORPHISM REMOVED (deliberate — the house dislikes it).
       The scrolled topbar and the focus-mode pill were frosted
       translucent panels; both are now solid surfaces with a
       hairline and a real shadow. Modal scrims lose their blur too:
       a clean dim reads sharper and costs no compositing.
   6 · FOCUS.  Focus rings existed on <button>/<a> only, so the tree,
       menus, tabs, cells and contenteditables had no keyboard
       affordance at all.
   7 · DENSITY / ALIGNMENT nits found on screen: ragged home-card
       bottoms (`align-items: start` on the widget grid), a database
       summary band that read as a stray empty row, three unlabelled
       icons in the sidebar footer (`font-size: 0`), and a 56px mic
       FAB parked on top of page content in every single view.

   Nothing in the DOM is required to move for this file to work; the
   companion app.html edits are additive (labels, aria, one <link>).
   Fully reversible: delete the <link> and the app reverts.
   ============================================================ */

/* ============================================================
   1 · Tokens — motion, rings, control metrics, surface lift
   ============================================================ */
:root {
  /* one motion scale, so nothing animates at a random speed */
  --dur-1: 90ms;    /* state flips: hover, colour */
  --dur-2: 160ms;   /* small movement: press, reveal */
  --dur-3: 240ms;   /* entrances, drawers */
  --ease-out: cubic-bezier(0.22, 0.61, 0.36, 1);
  --ease-emph: cubic-bezier(0.2, 0.9, 0.25, 1);

  /* one focus ring, used by every interactive surface */
  --ring-w: 2px;
  --ring: 0 0 0 3px color-mix(in srgb, var(--accent) 22%, transparent);

  /* control metrics — buttons, inputs and selects share a rhythm */
  --ctl-h: 34px;
  --ctl-h-sm: 28px;

  /* radius scale (pane 18 / card 12 / control 9 already set upstream) */
  --radius-pill: 999px;
  --radius-xs: 6px;

  /* the pane's edge: a hairline that survives both themes */
  --pane-ring: inset 0 0 0 1px rgba(42, 40, 34, 0.06);
}

/* Native widgets (date pickers, selects, scrollbars, autofill) follow this
   — without it the dark theme rendered white calendar popups. */
html { color-scheme: light; }
html[data-theme="dark"] { color-scheme: dark; }

html[data-theme="dark"] {
  /* deepen the frame + lift the pane so the pane reads as FLOATING.
     was frame #131218 / bg #1b1a20 — a 1.15:1 delta that read flat. */
  --frame:      #0e0d12;
  --frame-deep: #08080c;
  --bg:         #1c1b22;
  --bg-modal:   #23222a;   /* a modal must sit ABOVE the pane, not level */
  --bg-input:   #17161c;   /* an input must sit BELOW it */
  --bg-code:    #232128;
  --bg-callout: #211f27;
  --border:        #2f2d38;
  --border-strong: #45424f;
  --pane-ring: inset 0 0 0 1px rgba(255, 250, 235, 0.07);
  --ring: 0 0 0 3px color-mix(in srgb, var(--accent) 34%, transparent);
}

/* ============================================================
   2 · Foundations — selection, caret, scrollbars, motion
   ============================================================ */
body { text-rendering: optimizeLegibility; }

::selection { background: color-mix(in srgb, var(--accent) 24%, transparent); }
#page-title, .block-content, .db-name, [contenteditable="true"] { caret-color: var(--accent); }

/* scrollbars: present but quiet, and they stay out of the reading column */
* { scrollbar-width: thin; scrollbar-color: var(--border-strong) transparent; }
::-webkit-scrollbar { width: 11px; height: 11px; }
::-webkit-scrollbar-thumb {
  background: var(--border-strong); border-radius: var(--radius-pill);
  border: 3px solid transparent; background-clip: content-box;
}
::-webkit-scrollbar-thumb:hover { background: var(--text-faint); background-clip: content-box; }
::-webkit-scrollbar-corner { background: transparent; }

/* css/style.css:1559 already zeroes animation + transition durations under
   prefers-reduced-motion. The one thing it misses is programmatic smooth
   scrolling (.ai-thread and the outline rail both set scroll-behavior). */
@media (prefers-reduced-motion: reduce) {
  html, *, *::before, *::after { scroll-behavior: auto !important; }
}

/* ============================================================
   3 · Focus — one visible ring on EVERY interactive surface
   ------------------------------------------------------------
   :focus-visible only, so a mouse click never paints a ring and
   contenteditable surfaces are never boxed while you type.
   ============================================================ */
:where(button, a, input, select, textarea, summary, [tabindex]):focus-visible,
.sb-action:focus-visible, .tree-item:focus-visible, .menu-item:focus-visible,
.lib-tab:focus-visible, .lib-item:focus-visible, .db-tab:focus-visible,
.db-th:focus-visible, .db-td:focus-visible, .hh-chip:focus-visible,
.hh-card:focus-visible, .ob-step:focus-visible, .wg-item:focus-visible,
.result-item:focus-visible, .crumb:focus-visible, .ai-action:focus-visible {
  outline: var(--ring-w) solid var(--accent);
  outline-offset: 2px;
  /* NO border-radius here: `outline` already follows the element's own shape,
     and setting one squares off every pill-shaped control (.adm-pill,
     .wsearch-chip, .wg-cfg-toggle, …) for as long as it holds focus. */
}
/* inside the dark rail the iris ring is hard to see — use the soft tint,
   and go white on the iris-filled primary chip where even that fades out */
#sidebar :focus-visible { outline-color: var(--accent-soft); }
#sidebar .sb-action-primary:focus-visible { outline-color: #fff; }
/* fields get the ring as a glow instead, so they don't jump */
input:focus-visible, textarea:focus-visible, select:focus-visible {
  outline: none; border-color: var(--accent); box-shadow: var(--ring);
}
/* typing surfaces are never ringed */
[contenteditable]:focus, [contenteditable]:focus-visible { outline: none; }

/* ============================================================
   4 · Native controls — nothing may look like raw browser chrome
   ============================================================ */
input, textarea, select, button { font-family: inherit; font-size: inherit; }

/* text-ish fields share one look */
input[type="text"], input[type="email"], input[type="password"], input[type="search"],
input[type="url"], input[type="number"], input[type="date"], input[type="time"],
input[type="datetime-local"], input[type="month"], input[type="week"], textarea, select {
  color: var(--text);
  background: var(--bg-input);
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-ctl);
  transition: border-color var(--dur-1), box-shadow var(--dur-1), background var(--dur-1);
}
input[type="text"]:hover, input[type="email"]:hover, input[type="password"]:hover,
input[type="search"]:hover, input[type="number"]:hover, input[type="date"]:hover,
input[type="time"]:hover, textarea:hover, select:hover { border-color: var(--text-faint); }
::placeholder { color: var(--text-placeholder); opacity: 1; }

/* single-line fields get the shared control height */
input[type="text"], input[type="email"], input[type="password"], input[type="search"],
input[type="url"], input[type="number"], input[type="date"], input[type="time"],
input[type="datetime-local"], select {
  min-height: var(--ctl-h);
  padding: 0 11px;
}

/* <select>: kill the platform arrow, draw our own chevron.
   The two class names ride along only for `padding-right`: both ARE selects,
   but their feature files set a `padding` shorthand through a class
   (`.tasks-rem-repeat` 7px 8px, `.ai-model` 6px 8px) which outranks a bare
   `select` rule — without them the label runs under the chevron. */
select, .tasks-rem-repeat, .ai-model {
  -webkit-appearance: none; -moz-appearance: none; appearance: none;
  padding-right: 30px; cursor: pointer;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%236b6558' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 9px center;
  background-size: 15px;
}
html[data-theme="dark"] select,
html[data-theme="dark"] .tasks-rem-repeat,
html[data-theme="dark"] .ai-model {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%23a8a396' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E");
}
select option { background: var(--bg-modal); color: var(--text); }

/* date / time: tint the picker button and make it a real affordance */
input[type="date"]::-webkit-calendar-picker-indicator,
input[type="time"]::-webkit-calendar-picker-indicator,
input[type="datetime-local"]::-webkit-calendar-picker-indicator {
  opacity: 0.45; cursor: pointer; border-radius: 4px; padding: 2px;
  transition: opacity var(--dur-1), background var(--dur-1);
}
input[type="date"]:hover::-webkit-calendar-picker-indicator,
input[type="time"]:hover::-webkit-calendar-picker-indicator,
input[type="datetime-local"]:hover::-webkit-calendar-picker-indicator { opacity: 0.9; background: var(--bg-hover); }
/* the empty "mm/dd/yyyy" mask should read as a placeholder, not as content */
/* (Nothing here targets the empty "mm/dd/yyyy" mask: an optional date input is
   not :invalid while blank, so CSS has no hook for it. The mask stays — what
   made it look unfinished was the mismatched height and border, not the text.) */
input[type="number"]::-webkit-outer-spin-button,
input[type="number"]::-webkit-inner-spin-button { opacity: 0.5; }
input[type="search"]::-webkit-search-cancel-button { cursor: pointer; opacity: 0.5; }

/* boxes and sliders inherit the brand instead of the platform blue */
input[type="checkbox"], input[type="radio"] { accent-color: var(--accent); cursor: pointer; }
input[type="range"] { accent-color: var(--accent); cursor: pointer; }
input[type="color"] { border-radius: var(--radius-xs); cursor: pointer; }
input:disabled, select:disabled, textarea:disabled, button:disabled { opacity: 0.55; cursor: not-allowed; }

/* Chrome's autofill paints its own yellow — repaint it in-theme */
input:-webkit-autofill, input:-webkit-autofill:hover, input:-webkit-autofill:focus {
  -webkit-text-fill-color: var(--text);
  -webkit-box-shadow: 0 0 0 1000px var(--bg-input) inset;
  caret-color: var(--text);
}

/* the reminder row in My Tasks is the place all three land together */
.tasks-rem-date, .tasks-rem-time, .tasks-rem-repeat { font-size: 13px; }
.tasks-rem-input { min-height: var(--ctl-h); }

/* ============================================================
   5 · The pane + the rail — make the floating pane real again
   ============================================================ */
#main {
  box-shadow: var(--shadow-pane), var(--pane-ring);
  /* the pane owns the scroll; nothing should bounce the frame behind it */
  overscroll-behavior: contain;
}

/* the rail's own edge, so the sidebar and the pane never merge in dark mode */
#sidebar { border-right: none; }
/* the last tree row was ending flush against the footer's hairline, which read
   as a clipped row rather than a scrollable list */
#sidebar .sb-scroll { scrollbar-width: thin; padding-bottom: 10px; }
#sidebar ::-webkit-scrollbar-thumb { background: rgba(255, 250, 238, 0.14); background-clip: content-box; }
#sidebar ::-webkit-scrollbar-thumb:hover { background: rgba(255, 250, 238, 0.26); background-clip: content-box; }

/* ============================================================
   6 · Topbar — solid, not frosted; aligned; correct on phones
   ============================================================ */
/* GLASSMORPHISM OUT: the scrolled topbar was a translucent blur panel.
   A solid surface with a hairline and a shadow reads sharper and doesn't
   smear the text scrolling underneath it. */
#main.topbar-scrolled #topbar {
  background: var(--bg);
  -webkit-backdrop-filter: none; backdrop-filter: none;
  box-shadow: 0 1px 0 var(--border), 0 6px 16px -10px rgba(20, 16, 8, 0.28);
}
html[data-theme="dark"] #main.topbar-scrolled #topbar {
  box-shadow: 0 1px 0 var(--border), 0 8px 20px -10px rgba(0, 0, 0, 0.7);
}

#topbar { gap: 4px; }
.topbar-right { gap: 2px; }
#topbar .icon-btn { width: 30px; height: 30px; border-radius: 8px; }
.crumb { transition: background var(--dur-1), color var(--dur-1); }
.crumb-sep { opacity: 0.55; }

/* save state reads as a status chip rather than loose grey text */
#save-indicator {
  font-size: 11.5px; font-weight: 500; letter-spacing: 0.2px;
  padding: 3px 8px; border-radius: var(--radius-pill);
  color: var(--text-faint); margin-right: 4px; white-space: nowrap;
}
#save-indicator:not(:empty) { background: var(--bg-hover); }
#save-indicator.saving { color: var(--gold); }

#lock-badge {
  font-size: 11.5px; font-weight: 600; padding: 3px 9px; border-radius: var(--radius-pill);
  background: color-mix(in srgb, var(--gold) 16%, transparent);
  color: color-mix(in srgb, var(--gold) 80%, var(--text));
}

/* ============================================================
   7 · Sidebar — labelled footer, tidier rows, clearer state
   ============================================================ */
/* The footer was three unlabelled glyphs (`font-size: 0`). Tooltips are not
   discoverability. Three across truncates ("Settin…"), so Settings — the one
   people reach for — takes a full row and the other two share the next. */
.sb-footer-row { display: grid; grid-template-columns: 1fr 1fr; gap: 5px; }
.sb-footer-row #btn-settings { grid-column: 1 / -1; }
.sb-footer-row .sb-action {
  font-size: 12px; font-weight: 500; gap: 7px;
  padding: 7px 10px; min-width: 0; letter-spacing: 0.1px;
  justify-content: flex-start;
}
.sb-footer-row .sb-action > span:not(.sb-action-icon) {
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.sb-footer-row .sb-action .sb-action-icon { font-size: 14px; flex: 0 0 auto; }

/* the workspace chip should look pressable — it opens the switcher */
.sb-workspace {
  border-radius: 9px; padding: 4px 6px; margin: -4px -6px;
  transition: background var(--dur-1);
}
.sb-workspace:hover { background: rgba(255, 250, 238, 0.07); }

/* active row: a solid seat, not just a tinted background */
#sidebar .sb-action.active,
#sidebar .tree-item.active {
  background: rgba(255, 250, 238, 0.10);
  box-shadow: inset 2px 0 0 var(--accent-soft);
  color: var(--text);
}

/* count badges line up and read as one family */
#inbox-badge:not(.hidden), .sb-badge:not(.hidden) {
  min-width: 18px; height: 18px; padding: 0 5px;
  display: inline-flex; align-items: center; justify-content: center;
  font-size: 10.5px; font-weight: 700; line-height: 1;
  border-radius: var(--radius-pill);
  background: var(--accent); color: #fff;
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.35);
}

/* keycap hints: real keycaps, aligned right, quiet until the row is hovered */
.sb-kbd {
  margin-left: auto; font-family: var(--font); font-size: 10px; font-weight: 600;
  letter-spacing: 0.4px; padding: 2px 6px; border-radius: 5px;
  opacity: 0.55; transition: opacity var(--dur-1);
}
.sb-action:hover .sb-kbd { opacity: 1; }

/* tree rows: hover actions must not shove the title around */
.tree-item .ti-actions { opacity: 0; display: flex; transition: opacity var(--dur-1); }
.tree-item:hover .ti-actions, .tree-item:focus-within .ti-actions { opacity: 1; }

/* ============================================================
   8 · Home — an even grid, a compact checklist, aligned actions
   ============================================================ */
.hh-top { align-items: center; margin-bottom: 22px; }
.hh-actions { gap: 7px; }
.hh-chip { border-radius: var(--radius-ctl); min-height: var(--ctl-h); }

/* `align-items: start` left every card a different height and the row
   bottom ragged. Stretch makes each ROW square without forcing tall cards. */
.wg-grid { align-items: stretch; gap: 14px; }
.wg-card {
  display: flex; flex-direction: column;
  background: var(--bg);
  box-shadow: var(--pane-ring);
  transition: border-color var(--dur-2), box-shadow var(--dur-2);
}
.wg-card:hover { border-color: var(--border-strong); }
/* a stretched card must not leave its empty state stranded at the top edge */
.wg-body { flex: 1; display: flex; flex-direction: column; }
.wg-body > .ht-tasks, .wg-body > .wg-list { flex: 1; }
.ht-empty, .wg-empty { flex: 1; justify-content: center; }

/* "Customize" sat orphaned between two blocks — tie it to the grid it edits */
.wg-bar { margin-bottom: 10px; }
.wg-customize { min-height: var(--ctl-h-sm); border-radius: var(--radius-ctl); }

/* Getting started: it was ~370px of the first screen for five one-line steps.
   Two columns on desktop, tighter rows, and the wash turned down. */
.ob-card { padding: 16px 18px 14px; margin-bottom: 20px; background: var(--bg); }
.ob-bar { height: 4px; margin: 11px 0 12px; }
.ob-steps { gap: 2px; }
.ob-step { padding: 8px 10px; }
@media (min-width: 900px) {
  .ob-steps { display: grid; grid-template-columns: 1fr 1fr; gap: 2px 10px; }
}
/* on a phone there is no second column to escape into — wrap, don't truncate */
@media (max-width: 620px) {
  .ob-step-hint { white-space: normal; overflow: visible; line-height: 1.4; }
}

/* ============================================================
   9 · Library / list views — sticky head, calmer rows
   ============================================================ */
.lib-colhead {
  position: sticky; top: 0; z-index: 2;
  background: var(--bg); border-bottom: 1px solid var(--border);
}
.lib-search { min-height: var(--ctl-h-sm); }
.lib-newpage, .lib-templates-btn, .lib-sort { min-height: var(--ctl-h); }

/* ============================================================
   10 · Databases — a footer that reads as a footer, real controls
   ============================================================ */
/* The aggregation band rendered as an empty table row directly under
   "+ New" — it looked like a rendering bug. Give it a footer identity. */
.db-root .db-summary {
  background: var(--bg-hover);
  border-top: 1px solid var(--db-border);
  min-height: 32px;
}
.db-root .db-summary .db-sum-cell {
  font-size: 11.5px; color: var(--db-text-faint);
  border-right: none; transition: color var(--dur-1);
}
.db-root .db-summary .db-sum-cell:hover { color: var(--db-text); }
/* database.css repaints the frozen first column with --db-bg to keep it opaque
   while scrolling; inside the new footer band that leaves a visible seam. */
.db-root .db-summary .db-col-frozen { background: var(--bg-hover); }
.db-root .db-add-row { transition: background var(--dur-1), color var(--dur-1); }
.db-root .db-add-row:hover { background: var(--db-hover); color: var(--db-text); }

/* the toolbar was a row of bare words; give the controls edges on hover */
.db-root .db-tool-btn {
  min-height: var(--ctl-h-sm); display: inline-flex; align-items: center; gap: 6px;
  border-radius: var(--radius-ctl); transition: background var(--dur-1), color var(--dur-1), border-color var(--dur-1);
}
.db-root .db-tool-btn:hover { border-color: var(--db-border); }
.db-root .db-new-btn, .db-root .db-new-caret { min-height: var(--ctl-h-sm); }
.db-root .db-new-btn { border-radius: var(--radius-ctl) 0 0 var(--radius-ctl); font-weight: 600; }
.db-root .db-new-caret { border-radius: 0 var(--radius-ctl) var(--radius-ctl) 0; }
.db-root .db-table { border-radius: var(--radius-card); }
.db-root .db-thead { background: var(--db-bg); }
.db-root .db-tr { transition: background var(--dur-1); }

/* ============================================================
   11 · AI drawer — dock it in the pane, stop hiding the page
   ------------------------------------------------------------
   It was body-fixed and full-bleed, so it clipped the pane's corner,
   sat over the content it was editing, and dimmed it grey. Now it
   aligns to the pane (8px inset — #app's padding) and, on a wide
   screen, the pane shrinks to sit beside it.
   ============================================================ */
/* The click-through has to be switched off on the ROOT, not the backdrop:
   .ai-root is `position: fixed; inset: 0`, so it covers the viewport itself
   and swallowed every click aimed at the page even with the backdrop
   neutralised. With the root transparent to pointers the page stays fully
   usable while the assistant is open — which also means click-outside no
   longer closes the drawer. That is the intended trade for a DOCKED panel:
   Esc and the × close it, and clicking the page now edits the page. */
.ai-panel-root { pointer-events: none; }
.ai-panel-root .ai-backdrop { background: transparent; }
.ai-panel-root .ai-panel {
  top: 8px; bottom: 8px; right: 8px;
  border-radius: var(--radius-pane);
  border: none;                       /* the ring + shadow draw the edge */
  box-shadow: var(--shadow-pane), var(--pane-ring);
  pointer-events: auto;
}
/* ai.css ships `html[data-theme="dark"] .ai-backdrop/.ai-panel` rules, which
   outrank a plain `.ai-panel-root …` — so dark mode kept both the dim and the
   old side shadow until these matched their specificity. */
html[data-theme="dark"] .ai-panel-root .ai-backdrop { background: transparent; }
html[data-theme="dark"] .ai-panel-root .ai-panel { box-shadow: var(--shadow-pane), var(--pane-ring); }
/* wide screens: push the pane aside instead of covering it */
@media (min-width: 1100px) {
  #main { transition: margin-right var(--dur-3) var(--ease-emph); }
  html.ai-panel-open #main { margin-right: calc(440px + 8px); }
}
/* the model picker is the one <select> in the drawer */
.ai-model { min-height: var(--ctl-h-sm); max-width: 210px; }
/* the emoji tiles read calmer next to the app's line icons */
.ai-action-emoji { filter: saturate(0.9); }
.ai-action { min-height: 38px; }

@media (max-width: 760px) {
  .ai-panel-root .ai-panel { top: 0; bottom: 0; right: 0; border-radius: 0; }
}

/* ============================================================
   12 · Voice dock — present, not parked on the content
   ------------------------------------------------------------
   A 56px saturated circle sat over the bottom-right of every view.
   Smaller, calmer at rest, full presence on hover or when live.
   The .vdock rules are injected at runtime from ai.js, so they land in <head>
   AFTER this file — but they are single-class selectors, and specificity beats
   source order, so the `body .vdock…` prefix is all that is needed. Do NOT add
   !important here: it would outrank the global prefers-reduced-motion guard
   and freeze the "speaking" bob animation whenever the cursor is over the FAB.
   ============================================================ */
body .vdock { right: 18px; bottom: 18px; }
body .vdock-fab {
  width: 46px; height: 46px;
  opacity: 0.9;
  box-shadow: 0 6px 18px -6px rgba(20, 16, 8, 0.5), inset 0 1px 0 rgba(255, 255, 255, 0.2);
  transition: transform var(--dur-2) var(--ease-out), opacity var(--dur-1), background var(--dur-2);
}
body .vdock-fab:hover { opacity: 1; transform: translateY(-1px) scale(1.04); }

/* ai.js already steps the dock aside for its own panel (`.ai-panel-open
   .vdock`) but nothing did it for the COMMENTS drawer, which is also pinned
   right — the FAB landed squarely on top of the drawer's Send button and ate
   the click. The drawer is a body-level sibling that precedes the runtime-
   appended dock, so `~` reaches it without needing :has(). 360px is the width
   openCommentsDrawer() sets inline (js/app.js). */
#comments-drawer:not(.hidden) ~ .vdock { right: calc(min(360px, 92vw) + 18px); }
body .vdock[data-state="listening"] .vdock-fab,
body .vdock[data-state="thinking"] .vdock-fab,
body .vdock[data-state="speaking"] .vdock-fab { opacity: 1; }
/* and give scrollable views room so nothing ever ends up under it */
#page-scroll { scroll-padding-bottom: 80px; }
#tasks-view, #inbox-view, #daily-view, #database-view, #library-view { padding-bottom: 72px; }

/* ============================================================
   13 · Modals, popovers, toast — solid scrims, one radius family
   ============================================================ */
/* GLASSMORPHISM OUT: blurred scrims smear the app into mush. A clean,
   slightly warm dim keeps the page behind legible as context. */
#modal-layer {
  background: rgba(24, 19, 10, 0.52);
  -webkit-backdrop-filter: none; backdrop-filter: none;
}
html[data-theme="dark"] #modal-layer { background: rgba(6, 5, 9, 0.66); }
.link-modal-back { -webkit-backdrop-filter: none; backdrop-filter: none; }

.modal { box-shadow: var(--shadow-popover), var(--pane-ring); }
.menu-item { border-radius: var(--radius-ctl); transition: background var(--dur-1); }

/* command palette: a permanent key legend on the left, query actions right */
.palette-foot {
  justify-content: space-between; align-items: center;
  padding: 8px 12px; margin-top: 0;
  background: var(--bg-callout);
}
.palette-foot-acts { display: flex; align-items: center; gap: 8px; }
.palette-hints {
  display: inline-flex; align-items: center; gap: 5px;
  font-size: 11.5px; color: var(--text-faint); white-space: nowrap;
}
.palette-hints kbd {
  display: inline-flex; align-items: center; justify-content: center;
  font-family: var(--font); font-size: 10.5px; font-weight: 600; line-height: 1;
  min-width: 19px; height: 19px; padding: 0 5px; border-radius: 5px;
  color: var(--text-light); background: var(--bg);
  border: 1px solid var(--border-strong); box-shadow: 0 1px 0 var(--border-strong);
}
.palette-hints kbd .ic { stroke-width: 2.2; }
@media (max-width: 620px) { .palette-hints { display: none; } }

/* toast: a solid pill with a defined edge */
#toast { border-radius: 12px; }

/* focus-mode pill: was a frosted panel; now a solid one */
#focus-exit {
  background: var(--frame-deep);
  -webkit-backdrop-filter: none; backdrop-filter: none;
  box-shadow: 0 8px 24px -8px rgba(0, 0, 0, 0.7), inset 0 0 0 1px rgba(255, 255, 255, 0.1);
}

/* ============================================================
   14 · Page — a calmer head, a real empty state
   ============================================================ */
#page-head { padding-top: 46px; }
#page-title { letter-spacing: -1px; }

#empty-state .empty-inner { display: flex; flex-direction: column; align-items: center; gap: 14px; }
#empty-state .empty-logo { width: 56px; height: 56px; border-radius: 16px; }
#empty-state p { font-size: 15px; }

/* the trash banner is a warning bar, not a red block with pill buttons */
#trash-banner { font-weight: 500; }
#trash-banner button { min-height: var(--ctl-h-sm); border-radius: var(--radius-ctl); font-weight: 600; }

/* ============================================================
   15 · Phones — the topbar collision, safe areas, touch targets
   ============================================================ */
@media (max-width: 760px) {
  /* THE FIX: mobile.css reserved this room, redesign.css took it back.
     Declared here, after both, so the hamburger and the crumbs coexist. */
  #topbar { padding-left: 56px; padding-right: 8px; }
  body.sb-open #topbar { padding-left: 14px; }

  /* the pane goes full-bleed here (style.css drops its radius), so the drop
     shadow and hairline ring must come off with it or they hug the screen edge */
  #main { box-shadow: none; }

  /* notch / home-indicator safety for the installed PWA */
  #sidebar { padding-top: env(safe-area-inset-top, 0px); }
  .sb-footer { padding-bottom: calc(8px + env(safe-area-inset-bottom, 0px)); }
  #page-scroll { padding-bottom: env(safe-area-inset-bottom, 0px); }
  body .vdock { right: 14px; bottom: calc(14px + env(safe-area-inset-bottom, 0px)); }
  /* the drawer goes full-width here, so there is nowhere to step aside to */
  #comments-drawer:not(.hidden) ~ .vdock { display: none; }

  /* Comfortable targets without making the rail feel loose. The tree rows are
     spelled out per container because redesign.css sizes them through
     `#sb-tree .tree-item` — an id selector a bare `.tree-item` cannot beat,
     media query or not. Same story for the database toolbar, which this file
     tightens to 28px on desktop and must hand back here. */
  .sb-footer-row .sb-action { min-height: 44px; }
  .menu-item, .lib-item { min-height: 40px; }
  #sb-tree .tree-item, #sb-databases .tree-item, #sb-teams .tree-item,
  #sb-favorites .tree-item, #sb-shared .tree-item { min-height: 40px; }
  .db-root .db-tool-btn, .db-root .db-new-btn, .db-root .db-new-caret { min-height: 40px; }
  .icon-btn { min-width: 38px; min-height: 38px; }

  /* modals sit as sheets against the bottom edge */
  #modal-layer { padding-top: 56px; }
  .modal { border-radius: 16px; }
}

/* ============================================================
   16 · Print — the reading column only
   ============================================================ */
@media print {
  .vdock, #focus-exit, #toast, .mnav-btn { display: none !important; }
  #main { box-shadow: none; }
}

/* ============================================================
   17 · Backlinks 2.0 & Unlinked Mentions
   ============================================================ */
.backlinks-head {
  display: flex; align-items: center; justify-content: space-between;
  font-size: 11.5px; font-weight: 600; text-transform: uppercase; letter-spacing: .04em;
  color: var(--text-faint); margin: 28px 0 10px; padding-bottom: 5px; border-bottom: 1px solid var(--border);
}
.backlinks-link-all-btn {
  font-size: 11.5px; font-weight: 600; font-family: var(--font); color: var(--accent);
  background: var(--bg-hover); border: 1px solid var(--border); border-radius: 6px;
  padding: 3px 9px; cursor: pointer; text-transform: none; letter-spacing: normal;
  transition: background var(--dur-1), color var(--dur-1), border-color var(--dur-1);
}
.backlinks-link-all-btn:hover {
  background: var(--accent); color: #fff; border-color: var(--accent);
}
.backlink-item {
  display: flex; align-items: center; justify-content: space-between; gap: 8px;
  width: 100%; text-align: left; padding: 7px 10px; margin: 3px 0; border-radius: var(--radius-ctl);
  background: var(--bg-hover); border: 1px solid transparent; font-family: var(--font);
  font-size: 13.5px; color: var(--text); cursor: pointer; transition: background var(--dur-1), border-color var(--dur-1);
}
.backlink-item:hover { background: var(--bg-active); border-color: var(--border); }
.backlink-src { font-weight: 600; color: var(--text); white-space: nowrap; }
.backlink-snip { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--text-light); }
.backlink-snip mark { background: rgba(99, 102, 241, 0.18); color: var(--accent); border-radius: 3px; padding: 0 3px; font-weight: 600; }
.backlink-linkbtn {
  font-size: 11.5px; font-weight: 600; color: var(--accent); background: var(--bg);
  border: 1px solid var(--border); border-radius: 6px; padding: 3px 8px; cursor: pointer;
  transition: background var(--dur-1), color var(--dur-1);
}
.backlink-linkbtn:hover { background: var(--accent); color: #fff; border-color: var(--accent); }

