/* VENDORED COPY for the marketing site's product-shot demos only.
   Copied verbatim from ../../sidepanel/sidepanel.css so the site can be
   deployed standalone (Hostinger) without depending on files outside the
   /website folder. Re-copy this file whenever the real stylesheet changes
   in a way that would visibly affect the demo screens in assets/panel-
   demo-list.html and assets/panel-demo-editor.html. Not used by the
   extension itself — the extension keeps loading its own sidepanel.css. */
/* ===================================================================
   Token defaults (Aurora / dark) — overridden below per [data-design]
   x [data-theme]. JS always resolves "system" to a concrete light/dark
   value and writes it to data-theme, so no @media duplication is
   needed here — every combination is one explicit, contrast-checked
   block, not a naive invert.
   =================================================================== */
:root {
  --bg: #0A0C18;
  --panel: #141728;
  --panel2: #1B1F35;
  --line: #242847;
  --line-soft: #20243D;
  --ink: #EEF0FA;
  --ink-dim: #C3C7E4;
  --muted: #8E94BC;
  --accent: #8B8BFA;
  --accent-ink: #0B0D1A;
  --accent-wash: #20204A;

  /* system-ui first so Windows 11 resolves to Segoe UI Variable Text, which
     is hinted for small sizes, instead of the legacy static Segoe UI that
     'Segoe UI' alone would pin us to. Emoji last: without it a 😀 in a note
     title falls back to whatever the renderer picks, which differs per OS. */
  --font-ui: system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI Variable Text',
             'Segoe UI', Roboto, 'Apple Color Emoji', 'Segoe UI Emoji', sans-serif;
  --font-display: var(--font-ui);
  --font-meta: var(--font-ui);
  /* Fixed across all three designs: code in a note is code, and a design
     theme changing its typeface would change what the code looks like. */
  --font-mono: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  --tracking-label: 0;
  --label-case: none;

  /* ---------- type scale ----------
     Seven steps, no half-pixels, nothing below 11px. Every font-size in
     this file resolves to one of these, so the scale cannot drift back
     into the fifteen ad-hoc sizes it replaced. Two deliberate literals
     remain: .welcome-icon (a glyph) and .acct-otp-input (a fixed-width
     code field whose 0.4em tracking would overflow at a larger step).
     --fs-read is the editor's own step: it is the one surface where
     paragraphs are actually read, so it sits above the UI base. */
  --fs-meta: 11px;    /* dates, counts, section labels, status bar */
  --fs-2: 12px;       /* note previews, hints, captions */
  --fs-sm: 13px;      /* menu items, toolbar, secondary controls */
  --fs-base: 14px;    /* body — inherited by everything unstyled */
  --fs-lg: 15px;      /* inputs, hero subtitles */
  --fs-title: 17px;   /* page and section titles */
  --fs-hero: 20px;    /* the welcome headline */
  --fs-read: 16px;    /* note editor body */
  /* Figures, not headings: the Account page's days-remaining count. Kept as
     its own step because at --fs-hero it reads as a title rather than a
     number, which is the whole reason that count was easy to miss before. */
  --fs-display: 34px;

  --row-radius: 12px;
  --row-shadow: 0 1px 2px rgba(0,0,0,.4), 0 8px 20px -10px rgba(0,0,0,.6);
  --row-border: 1px solid var(--line-soft);
  --row-gap: 6px;
  --row-bg: var(--panel);

  --tag-radius: 999px;
  --tag-case: none;
  --control-radius: 10px;
  --menu-radius: 14px;
  --header-bg: linear-gradient(180deg, #171B33 0%, #0A0C18 100%);

  color-scheme: dark;
}

/* Danger/delete semantic color is independent of each design's accent hue. */
:root[data-theme='dark'] { --danger: #F0728F; --danger-ink: #1a0f14; }
:root[data-theme='light'] { --danger: #C6395C; --danger-ink: #ffffff; }

/* ---------- semantic icon hues ----------
   Deliberately NOT applied to every icon. Navigation and formatting
   chrome (back, pager, the ⋯ menu, the B/I/H toolbar) stays neutral;
   colour is reserved for icons that name a *thing* — pinned, folder,
   tag, restore, export — so a hue carries meaning instead of decoration.
   Tuned per mode: the dark values would be muddy on white, the light
   values would glow on near-black. */
:root[data-theme='dark'] {
  --ic-pin: #F0B429; --ic-folder: #62A0FF; --ic-tag: #B98BFA; --ic-restore: #46C88A;
  --ic-export: #3BC7B6; --ic-import: #62A0FF; --ic-capture: #38BEDC; --ic-shield: #46C88A;
  --ic-sun: #F0B429; --ic-moon: #8E99F3; --ic-add: #46C88A; --ic-edit: #62A0FF;
}
:root[data-theme='light'] {
  --ic-pin: #96620A; --ic-folder: #2563C9; --ic-tag: #7A3FD0; --ic-restore: #12855A;
  --ic-export: #0F8478; --ic-import: #2563C9; --ic-capture: #0B7C93; --ic-shield: #12855A;
  --ic-sun: #96620A; --ic-moon: #4F57C4; --ic-add: #12855A; --ic-edit: #2563C9;
}

/* `.ic` strokes with currentColor, so an icon takes its own hue by setting
   `color` on the <svg> itself — that beats the colour the parent button
   sets, and survives the button's hover state. */
/* The pin is the exception: it earns its colour by being *on*, so an
   unpinned note's hover action stays neutral and "amber = pinned" holds. */
.ic-folder { color: var(--ic-folder); }
.ic-tag { color: var(--ic-tag); }
.ic-restore { color: var(--ic-restore); }
.ic-export { color: var(--ic-export); }
.ic-import { color: var(--ic-import); }
.ic-capture { color: var(--ic-capture); }
.ic-shield { color: var(--ic-shield); }
.ic-sun { color: var(--ic-sun); }
.ic-moon { color: var(--ic-moon); }
.ic-add { color: var(--ic-add); }
.ic-edit { color: var(--ic-edit); }

/* ---------- Slate: editorial dark, hairline rules, zero radius ---------- */
:root[data-design='slate'][data-theme='dark'] {
  --bg: #0C0D10; --panel: #16171B; --panel2: #1D1F24; --line: #24262D; --line-soft: #202228;
  --ink: #ECEEF1; --ink-dim: #C6C9D0; --muted: #878B94; --accent: #FF6B57; --accent-ink: #120D0B;
  --accent-wash: #2A1A16; --danger: #E2584A; --danger-ink: #1a0f0d;
  --font-meta: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  --tracking-label: 0.06em; --label-case: uppercase;
  --row-radius: 0px; --row-shadow: none; --row-border: 1px solid var(--line-soft); --row-bg: transparent; --row-gap: 0px;
  --tag-radius: 3px; --control-radius: 6px; --menu-radius: 10px;
  --header-bg: var(--bg);
  color-scheme: dark;
}
:root[data-design='slate'][data-theme='light'] {
  --bg: #F6F3EC; --panel: #FBF8F1; --panel2: #F1EDE3; --line: #E3DFD3; --line-soft: #E9E5D9;
  --ink: #14151A; --ink-dim: #3A3B44; --muted: #65666F; --accent: #D8452F; --accent-ink: #FFFFFF;
  --accent-wash: #FBE7E3; --danger: #B23A1E; --danger-ink: #ffffff;
  --font-meta: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  --tracking-label: 0.06em; --label-case: uppercase;
  --row-radius: 0px; --row-shadow: none; --row-border: 1px solid var(--line-soft); --row-bg: transparent; --row-gap: 0px;
  --tag-radius: 3px; --control-radius: 6px; --menu-radius: 10px;
  --header-bg: var(--panel);
  color-scheme: light;
}

/* ---------- Aurora: premium SaaS, soft depth, indigo, generous ---------- */
:root[data-design='aurora'][data-theme='dark'] {
  --bg: #0A0C18; --panel: #141728; --panel2: #1B1F35; --line: #242847; --line-soft: #20243D;
  --ink: #EEF0FA; --ink-dim: #C3C7E4; --muted: #8E94BC; --accent: #8B8BFA; --accent-ink: #0B0D1A;
  --accent-wash: #20204A; --danger: #F0728F; --danger-ink: #1a0f14;
  --row-radius: 12px; --row-shadow: 0 1px 2px rgba(0,0,0,.4), 0 8px 20px -10px rgba(0,0,0,.6);
  --row-border: 1px solid var(--line-soft); --row-bg: var(--panel); --row-gap: 6px;
  --tag-radius: 999px; --control-radius: 10px; --menu-radius: 14px;
  --header-bg: linear-gradient(180deg, #171B33 0%, #0A0C18 100%);
  color-scheme: dark;
}
:root[data-design='aurora'][data-theme='light'] {
  --bg: #F8F5EE; --panel: #FCFAF3; --panel2: #F2EFE6; --line: #E7E2D5; --line-soft: #EFEBE0;
  --ink: #161930; --ink-dim: #39406A; --muted: #5D6389; --accent: #5B5BD6; --accent-ink: #FFFFFF;
  --accent-wash: #ECECFD; --danger: #C6395C; --danger-ink: #ffffff;
  --row-radius: 12px; --row-shadow: 0 1px 2px rgba(22,25,48,.05), 0 6px 16px -8px rgba(22,25,48,.14);
  --row-border: 1px solid var(--line-soft); --row-bg: var(--panel); --row-gap: 6px;
  --tag-radius: 999px; --control-radius: 10px; --menu-radius: 14px;
  --header-bg: linear-gradient(180deg, #F2EEFB 0%, #F8F5EE 100%);
  color-scheme: light;
}

/* ---------- Focus: dense power-user, mono metadata, no ornament ---------- */
:root[data-design='focus'][data-theme='dark'] {
  --bg: #0F1114; --panel: #171A1F; --panel2: #1E2127; --line: #242830; --line-soft: #1F232A;
  --ink: #DCE1E8; --ink-dim: #B7BEC8; --muted: #7C8592; --accent: #E2A44F; --accent-ink: #14110A;
  --accent-wash: #2A2318; --danger: #DD6A55; --danger-ink: #1a0f0a;
  --font-meta: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  --label-case: lowercase;
  --row-radius: 6px; --row-shadow: none; --row-border: 1px dotted var(--line); --row-bg: transparent; --row-gap: 0px;
  --tag-radius: 4px; --control-radius: 5px; --menu-radius: 10px;
  --header-bg: var(--bg);
  color-scheme: dark;
}
:root[data-design='focus'][data-theme='light'] {
  --bg: #FAF7F0; --panel: #F3F0E7; --panel2: #ECE8DD; --line: #DDD8C9; --line-soft: #E5E0D3;
  --ink: #1A1D21; --ink-dim: #40454C; --muted: #5C646E; --accent: #8A5310; --accent-ink: #FFFFFF;
  --accent-wash: #F6EEE1; --danger: #A73C22; --danger-ink: #ffffff;
  --font-meta: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  --label-case: lowercase;
  --row-radius: 6px; --row-shadow: none; --row-border: 1px dotted var(--line); --row-bg: transparent; --row-gap: 0px;
  --tag-radius: 4px; --control-radius: 5px; --menu-radius: 10px;
  --header-bg: var(--panel);
  color-scheme: light;
}

* { box-sizing: border-box; }
html, body { height: 100%; margin: 0; }

/* Any element toggled via the `hidden` attribute must actually hide,
   regardless of what display value some other class rule sets on it.
   Without !important, a same-specificity class selector loaded later in
   the cascade (e.g. `.view{display:flex}`) silently wins over the
   browser's own `[hidden]{display:none}` and the element stays visible. */
[hidden] { display: none !important; }

body {
  font-family: var(--font-ui);
  font-size: var(--fs-base);
  /* Without this the whole UI inherited the browser default (~1.2), which
     is why anything that wrapped — note previews, hints, notices — read
     cramped. Rules that need tighter leading (single-line rows, titles)
     set their own; this is only the floor for text that wraps. */
  line-height: 1.45;
  background: var(--bg);
  color: var(--ink);
  display: flex;
  flex-direction: column;
}

.screen {
  display: flex;
  flex-direction: column;
  height: 100vh;
  overflow: hidden;
}

.welcome { margin: auto; max-width: 320px; padding: 24px; text-align: center; }
.welcome-icon { font-size: 40px; margin-bottom: 12px; }
.welcome h1 { font-family: var(--font-display); font-size: var(--fs-hero); margin: 0 0 8px; }
.welcome p { color: var(--muted); line-height: 1.5; margin: 0 0 16px; }
.fine-print { font-size: var(--fs-2); margin-top: 20px; color: var(--muted); }

.btn {
  display: inline-block; width: 100%; padding: 10px 14px; border-radius: var(--control-radius);
  border: 1px solid var(--line); background: var(--panel2); color: var(--ink);
  font: inherit; font-size: var(--fs-base); cursor: pointer; margin-bottom: 8px;
}
.btn:hover { filter: brightness(1.08); }
.btn-primary { background: var(--accent); color: var(--accent-ink); border-color: var(--accent); font-weight: 600; }
.btn-link { background: none; border: none; color: var(--accent); text-decoration: underline; }
.link-btn { background: none; border: none; color: var(--accent); text-decoration: underline; cursor: pointer; font: inherit; padding: 0; }

.app-header { display: flex; flex-direction: column; gap: 8px; padding: 10px 12px 8px; border-bottom: 1px solid var(--line); background: var(--header-bg); flex-shrink: 0; }
.app-header .page-title { font-family: var(--font-display); font-weight: 650; font-size: var(--fs-lg); }
.pagetitle-row { display: flex; align-items: center; gap: 4px; margin-left: -6px; }

.brand-row { display: flex; align-items: center; gap: 8px; }
.brandmark {
  width: 20px; height: 20px; border-radius: var(--control-radius); background: var(--accent);
  color: var(--accent-ink); font-size: var(--fs-meta); font-weight: 800; display: grid; place-items: center;
  flex-shrink: 0; font-family: var(--font-display); flex-shrink: 0;
}
.brand-name { font-family: var(--font-display); font-weight: 650; font-size: var(--fs-base); letter-spacing: -0.01em; flex: 1; }
.vault-pill {
  display: inline-flex; align-items: center; gap: 5px; font-size: var(--fs-meta); color: var(--muted);
  border: 1px solid var(--line); border-radius: var(--tag-radius); padding: 2px 9px 2px 7px; font-family: var(--font-meta);
  max-width: 150px; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; cursor: default;
}
.vault-pill .dot { width: 5px; height: 5px; border-radius: 50%; background: #45b37a; flex-shrink: 0; }
.vault-pill.fallback .dot { background: var(--muted); }
.vault-pill .txt { overflow: hidden; text-overflow: ellipsis; }

/* Help: a lightweight popover, not a whole page — the only thing anyone
   needs from it is the support address, so it doesn't deserve a drill-in
   view the way Account/Settings do. Reuses the same anchored-panel and
   copy-a-code-box grammar as the color pickers and the license key field,
   rather than inventing new visual language for a one-off. */
.help-menu { position: relative; flex-shrink: 0; }
.help-panel {
  position: absolute; left: 0; top: calc(100% + 4px); z-index: 20; width: 300px;
  background: var(--panel); border: 1px solid var(--line); border-radius: var(--menu-radius);
  box-shadow: 0 20px 44px rgba(0,0,0,0.32); padding: 12px;
}
.help-panel.align-right { left: auto; right: 0; }
.help-panel-caption {
  margin: 0 0 8px; font-size: var(--fs-meta); font-weight: 700; color: var(--muted);
  text-transform: var(--label-case); letter-spacing: var(--tracking-label);
}
.help-panel-hint { margin: 8px 0 0; font-size: var(--fs-meta); color: var(--muted); line-height: 1.4; }
.help-panel .acct-keyfield code { color: var(--ink); }

.searchrow { display: flex; align-items: center; gap: 6px; }

.tabbar { display: flex; border-bottom: 1px solid var(--line); flex-shrink: 0; }
.tabbar button {
  flex: 1; font: inherit; font-size: var(--fs-sm); font-weight: 600; color: var(--muted);
  background: none; border: none; cursor: pointer; padding: 9px 4px; border-bottom: 2px solid transparent;
  display: flex; align-items: center; justify-content: center; gap: 6px;
  text-transform: var(--label-case); letter-spacing: var(--tracking-label);
}
.tabbar button .tab-count { font-size: var(--fs-meta); color: var(--muted); font-weight: 500; font-variant-numeric: tabular-nums; }
.tabbar button.active { color: var(--ink); border-bottom-color: var(--accent); }
.tabbar button.active .tab-count { color: var(--accent); }
.tabbar button:hover { color: var(--ink); }

#search-input {
  flex: 1; padding: 7px 10px; border-radius: var(--control-radius); border: 1px solid var(--line);
  background: var(--panel); color: var(--ink); font: inherit; font-size: var(--fs-sm);
}
#search-input::placeholder { color: var(--muted); }

/* Narrows the search to one field. Sits right of the box and only exists
   while there's a query, so the resting layout is unchanged. Highlighted
   when it's set to anything other than "All", since a narrowed search that
   silently finds nothing is worse than no control at all. */
.search-scope {
  flex-shrink: 0; max-width: 94px; padding: 6px 4px; border-radius: var(--control-radius);
  border: 1px solid var(--line); background: var(--panel); color: var(--ink-dim);
  font: inherit; font-size: var(--fs-2); cursor: pointer;
}
.search-scope:hover { color: var(--ink); }
.search-scope.narrowed {
  border-color: var(--accent); color: var(--ink);
  background: color-mix(in srgb, var(--accent) 14%, var(--panel));
}

.ic { width: 17px; height: 17px; stroke: currentColor; stroke-width: 1.7; fill: none; stroke-linecap: round; stroke-linejoin: round; display: block; }

.icon-btn {
  border: none; background: none; cursor: pointer; padding: 6px; border-radius: var(--control-radius);
  color: var(--muted); line-height: 1; display: flex; align-items: center; justify-content: center;
  position: relative;
}
.icon-btn:hover { background: var(--panel2); color: var(--ink); }
.icon-btn-accent { background: var(--accent); color: var(--accent-ink); }
.icon-btn-accent:hover { filter: brightness(1.08); background: var(--accent); color: var(--accent-ink); }
.icon-btn:disabled { opacity: 0.4; cursor: default; }
.icon-btn:disabled:hover { background: none; }
.icon-btn.active, .icon-btn[aria-expanded="true"] { background: var(--accent-wash); color: var(--accent); }

/* Custom hover tooltip: replaces native `title` (default OS styling, ~1s
   delay, inconsistent across browsers) with one that matches the panel's
   own theme and appears instantly. Any element just needs `[data-tip]`
   plus `position: relative`; `data-tip-pos="bottom"` flips it below the
   element for controls that sit right at the top edge of the panel. */
[data-tip] { position: relative; }
[data-tip]::after {
  content: attr(data-tip);
  position: absolute;
  bottom: calc(100% + 7px);
  left: 50%;
  transform: translateX(-50%) translateY(3px);
  background: var(--ink);
  color: var(--bg);
  font: var(--fs-meta)/1.3 var(--font-ui);
  font-weight: 500;
  padding: 4px 8px;
  border-radius: 6px;
  white-space: nowrap;
  max-width: 220px;
  text-align: center;
  pointer-events: none;
  opacity: 0;
  visibility: hidden;
  transition: opacity .1s ease, transform .1s ease;
  transition-delay: 0s;
  z-index: 60;
  box-shadow: 0 4px 12px rgba(0,0,0,.28);
}
[data-tip]::before {
  content: '';
  position: absolute;
  bottom: calc(100% + 2px);
  left: 50%;
  transform: translateX(-50%);
  border: 5px solid transparent;
  border-top-color: var(--ink);
  pointer-events: none;
  opacity: 0;
  visibility: hidden;
  transition: opacity .1s ease;
  z-index: 60;
}
[data-tip]:hover::after, [data-tip]:hover::before,
[data-tip]:focus-visible::after, [data-tip]:focus-visible::before {
  opacity: 1;
  visibility: visible;
  transform: translateX(-50%) translateY(0);
  transition-delay: .25s;
}
[data-tip][data-tip-pos="bottom"]::after {
  bottom: auto; top: calc(100% + 7px); transform: translateX(-50%) translateY(-3px);
}
[data-tip][data-tip-pos="bottom"]::before {
  bottom: auto; top: calc(100% + 2px); transform: translateX(-50%);
  border-top-color: transparent; border-bottom-color: var(--ink);
}
[data-tip][data-tip-pos="bottom"]:hover::after, [data-tip][data-tip-pos="bottom"]:focus-visible::after {
  transform: translateX(-50%) translateY(0);
}
[data-tip]:disabled::after, [data-tip]:disabled::before { display: none; }

.banner { padding: 8px 12px; font-size: var(--fs-2); background: var(--panel); border-bottom: 1px solid var(--line); color: var(--muted); flex-shrink: 0; }
.banner-warn { background: color-mix(in srgb, var(--accent) 16%, var(--panel)); color: var(--ink); }

.find-bar {
  display: flex; flex-direction: column; gap: 6px; padding: 8px 10px;
  background: var(--panel); border-bottom: 1px solid var(--line); flex-shrink: 0;
}
.find-row { display: flex; align-items: center; gap: 6px; }
.find-input {
  flex: 1; min-width: 0; padding: 6px 9px; border-radius: var(--control-radius); border: 1px solid var(--line);
  background: var(--panel2); color: var(--ink); font: inherit; font-size: var(--fs-sm);
}
.find-input:focus { outline: none; border-color: var(--accent); }
.find-count {
  font-size: var(--fs-meta); color: var(--muted); font-variant-numeric: tabular-nums; font-family: var(--font-meta);
  white-space: nowrap; min-width: 34px; text-align: center;
}
.find-count--empty { color: var(--danger); }
.find-row .icon-btn { flex-shrink: 0; padding: 5px; }
.find-row .icon-btn .ic { width: 15px; height: 15px; }
.find-row .mini-btn { flex-shrink: 0; }

/* Find-match highlighting uses the CSS Custom Highlight API (see
   selectFindMatch/refreshFindMatches) instead of the real document
   Selection, so searching never moves the editable cursor into the note
   body while the user is still typing in the find/replace inputs. */
::highlight(find-match) { background-color: color-mix(in srgb, var(--accent) 30%, transparent); }
::highlight(find-match-active) { background-color: color-mix(in srgb, var(--accent) 65%, transparent); }

.view { flex: 1; display: flex; flex-direction: column; overflow: hidden; }

/* Folder / Tag / Sort share one row of equal-width dropdowns. A scrolling
   row of tag chips used to sit above this, costing a permanent row of
   vertical space that grew more useless the more tags existed — a select
   scales to any tag count for free and reads as a peer of the other two
   filters. `.filtering` marks a select whose value is narrowing the list,
   so an active filter is visible without opening it. */
.list-toolbar { display: flex; align-items: center; padding: 8px 12px 4px; flex-shrink: 0; gap: 6px; }
.list-toolbar select {
  flex: 1 1 0; min-width: 0; border: 1px solid var(--line); background: var(--panel); color: var(--ink);
  border-radius: var(--control-radius); padding: 4px 6px; font: inherit; font-size: var(--fs-2);
  text-overflow: ellipsis;
}
.list-toolbar select.filtering { border-color: var(--accent); color: var(--accent); }
.list-toolbar select:disabled { color: var(--muted); opacity: 0.7; }

/* The tag filter is the one control in this row that isn't a native
   <select>: a note has many tags, so it opens a checkbox popover instead.
   It's styled to sit flush with its two <select> neighbours — same height,
   same flex basis, same `.filtering` accent — so the difference in
   behaviour doesn't read as a difference in kind. */
.ms-btn {
  flex: 1 1 0; min-width: 0; display: flex; align-items: center; gap: 4px;
  border: 1px solid var(--line); background: var(--panel); color: var(--ink);
  border-radius: var(--control-radius); padding: 4px 6px; font: inherit; font-size: var(--fs-2);
  cursor: pointer; text-align: left;
}
.ms-btn > span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; flex: 1; }
.ms-btn .ms-caret { width: 12px; height: 12px; flex-shrink: 0; opacity: 0.7; }
.ms-btn.filtering { border-color: var(--accent); color: var(--accent); }
.ms-btn:disabled { color: var(--muted); opacity: 0.7; cursor: default; }

.tag-filter-menu {
  position: fixed; z-index: 50; min-width: 190px; max-width: 260px;
  background: var(--panel); border: 1px solid var(--line); border-radius: var(--menu-radius);
  box-shadow: 0 20px 44px rgba(0,0,0,0.32); padding: 6px; font-size: var(--fs-2);
}
.tag-menu-head { display: flex; align-items: center; gap: 8px; padding: 2px 4px 6px; border-bottom: 1px solid var(--line-soft); }
.tag-menu-head .link-btn { font-size: var(--fs-meta); margin-left: auto; }
.seg { display: inline-flex; border: 1px solid var(--line); border-radius: var(--control-radius); overflow: hidden; }
.seg-btn {
  font: inherit; font-size: var(--fs-meta); padding: 2px 8px; cursor: pointer;
  background: none; border: none; color: var(--muted);
}
.seg-btn.on { background: var(--accent-wash); color: var(--accent); font-weight: 650; }
.seg-btn:disabled { opacity: 0.45; cursor: default; }
/* Capped so a vault with dozens of tags scrolls the menu instead of
   growing it past the panel. */
.tag-menu-list { max-height: 240px; overflow-y: auto; margin-top: 4px; }
.tag-menu-row {
  display: flex; align-items: center; gap: 7px; padding: 5px 5px; border-radius: 7px; cursor: pointer;
}
.tag-menu-row:hover { background: var(--panel2); }
.tag-menu-row.on .tag-menu-name { color: var(--accent); font-weight: 650; }
.tag-menu-row input { accent-color: var(--accent); flex-shrink: 0; margin: 0; }
.tag-menu-name { flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.tag-menu-count { font-size: var(--fs-meta); color: var(--muted); font-variant-numeric: tabular-nums; }
.tag-menu-empty { color: var(--muted); padding: 8px 5px; margin: 0; }

.list-subbar { display: flex; align-items: center; gap: 8px; padding: 0 12px 6px; flex-shrink: 0; min-height: 16px; }
#trash-subbar { padding-top: 8px; }
.note-count { font-size: var(--fs-meta); color: var(--muted); text-transform: var(--label-case); letter-spacing: var(--tracking-label); white-space: nowrap; font-family: var(--font-meta); }
.subbar-spacer { flex: 1; }
.list-subbar .mini-btn { font-size: var(--fs-meta); padding: 4px 9px; }

/* Bulk action bar: replaces the subbar's row while selecting, so entering
   select mode costs no extra vertical space in an already narrow panel. */
.bulk-bar {
  display: flex; align-items: center; gap: 6px; flex-wrap: wrap;
  padding: 5px 12px 7px; flex-shrink: 0;
}
.bulk-all { display: flex; align-items: center; gap: 6px; font-size: var(--fs-meta); color: var(--muted); cursor: pointer; margin-right: auto; white-space: nowrap; }
.bulk-all input { accent-color: var(--accent); margin: 0; }
/* Aligned to the title line rather than centred in the row: rows vary a lot
   in height (tags, folder, progress bar), and a centred box drifts away
   from the thing it names. */
.row-check { accent-color: var(--accent); margin: 2px 2px 0 0; flex-shrink: 0; align-self: flex-start; }
.note-item.selected { border-color: var(--accent); box-shadow: 0 0 0 1px var(--accent) inset, var(--row-shadow); }
/* Pin/export/delete are single-note actions; hiding them while selecting
   keeps one row from offering two different destructive verbs at once. */
.note-item.selecting .note-item-actions { display: none; }

.notes-list { list-style: none; margin: 0; padding: 0 12px; overflow: hidden; flex: 1; display: flex; flex-direction: column; gap: var(--row-gap); }

.list-section-head {
  font-size: var(--fs-meta); text-transform: uppercase; letter-spacing: .06em; color: var(--muted);
  padding: 3px 2px; display: flex; align-items: center; gap: 6px; font-family: var(--font-meta); flex-shrink: 0;
}
.list-section-head::after { content: ''; flex: 1; height: 1px; background: var(--line); }

.note-item {
  padding: 9px 11px; cursor: pointer; position: relative; overflow: hidden; flex-shrink: 0;
  border-radius: var(--row-radius); box-shadow: var(--row-shadow); background: var(--row-bg);
  border: var(--row-border);
  transition: opacity .18s ease, max-height .2s ease, padding .2s ease;
}
:root[data-design='slate'] .note-item, :root[data-design='focus'] .note-item { border-width: 0 0 1px 0; border-radius: 0; padding: 9px 3px; }
.notes-list .note-item:last-child { border-bottom: none; }
.note-item:hover { background: var(--panel2); }
.note-item.sel { border-color: var(--accent); }
.note-item.removing { opacity: 0; max-height: 0; padding-top: 0; padding-bottom: 0; margin-bottom: 0; }
.note-item.confirming .note-item-actions { opacity: 0; pointer-events: none; }

.note-item-confirm { display: none; align-items: center; justify-content: space-between; gap: 8px; font-size: var(--fs-2); }
.note-item.confirming .note-item-row { display: none; }
.note-item.confirming .note-item-confirm { display: flex; }
.note-item-confirm .confirm-btns { display: flex; gap: 6px; flex-shrink: 0; }

.note-item-row { display: flex; align-items: flex-start; gap: 8px; }
.note-item-body { flex: 1; min-width: 0; }

.note-item-actions { flex-shrink: 0; display: flex; gap: 2px; opacity: 0; transition: opacity .12s ease; margin: -3px -4px 0 0; }
.note-item:hover .note-item-actions { opacity: 1; }
.note-item-action {
  border: none; background: none; color: var(--muted); cursor: pointer;
  width: 28px; height: 28px; border-radius: var(--control-radius); display: flex; align-items: center; justify-content: center;
  transition: opacity .12s ease;
}
.note-item-action:hover { background: var(--bg); color: var(--ink); }
.note-item-action.danger:hover { color: var(--danger); }
/* Was 14px — noticeably smaller than the 17px the rest of the app uses for
   the same icon set (see the base .ic rule). Bumped to sit closer to that
   norm; still a touch under it since three of these plus the date have to
   share one row without crowding. */
.note-item-action .ic { width: 16px; height: 16px; }

/* A pinned note's pin button stays visible after the hover-reveal group
   fades, so the row's pinned state is legible at rest — otherwise the only
   cue is a 6px dot that's easy to miss. */
.note-item .note-item-actions:has(.pin-action.on) { opacity: 1; }
.note-item .note-item-actions:has(.pin-action.on) .delete-action,
.note-item .note-item-actions:has(.pin-action.on) .export-action { opacity: 0; }
.note-item:hover .note-item-actions .delete-action,
.note-item:hover .note-item-actions .export-action { opacity: 1; }

/* Pinned = amber with a solid head; unpinned = the same outline in the
   neutral action colour. Two independent cues (hue and fill) so it still
   reads for anyone who can't separate the hues. */
.pin-action.on .ic-pin, .pin-btn.on .ic-pin { color: var(--ic-pin); }
.pin-action.on .pin-head, .pin-btn.on .pin-head { fill: currentColor; }
.pin-btn.on { background: color-mix(in srgb, var(--ic-pin) 15%, transparent); }
.pin-btn.on:hover { background: color-mix(in srgb, var(--ic-pin) 24%, transparent); }
.pin-action.on:hover { background: color-mix(in srgb, var(--ic-pin) 15%, transparent); }

.mini-btn {
  font: inherit; font-size: var(--fs-meta); border-radius: var(--control-radius); padding: 5px 9px; cursor: pointer;
  border: 1px solid var(--line); background: var(--panel); color: var(--ink);
}
.mini-btn.danger { background: var(--danger); border-color: var(--danger); color: var(--danger-ink); font-weight: 600; }

.note-item-title-row { display: flex; align-items: center; gap: 6px; font-family: var(--font-display); font-weight: 650; }
.note-item-title-row .t { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* The timestamp rides in the title row rather than on .note-item-meta below.
   A note with no tags or folder has nothing else to put down there, so the
   meta row isn't rendered at all (see buildNoteRow) and the card loses ~18px
   — the difference between four and five notes per page. `flex: 1` on .t
   above is what makes a long title truncate instead of shoving the time out
   of the row. */
.note-item-time {
  flex-shrink: 0; margin-left: auto; padding-left: 8px;
  font-size: var(--fs-meta); font-weight: 400; color: var(--muted);
  font-family: var(--font-meta); font-variant-numeric: tabular-nums;
}
/* Same amber as the pin icon on the far side of the row — one hue for one
   concept, rather than the dot saying "accent" and the icon saying "pin". */
.pinmark { width: 6px; height: 6px; border-radius: 50%; background: var(--ic-pin); flex-shrink: 0; }
:root[data-design='focus'] .pinmark { border-radius: 1px; }

.note-item-snippet {
  color: var(--muted); font-size: var(--fs-2); margin-top: 3px; line-height: 1.45;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
}
.note-item-snippet mark { background: var(--accent-wash); color: var(--ink); border-radius: 3px; padding: 0 1px; }
.note-item-meta { display: flex; align-items: center; gap: 6px; margin-top: 6px; font-size: var(--fs-meta); color: var(--muted); font-variant-numeric: tabular-nums; font-family: var(--font-meta); flex-wrap: wrap; }
.note-item-tags { display: flex; gap: 4px; flex-wrap: wrap; }

/*
 * Folder vs. tag distinction: a note has exactly one folder but any number
 * of tags, so they get two different visual grammars rather than two
 * colors of the same pill — that's what made them unreadable before (see
 * the design mockup this replaced). Folder is a solid filled badge (plus
 * its own icon); tags are light outline chips. The shape/weight difference
 * survives grayscale and color-vision deficiency on its own — hue and the
 * icon are a second, redundant cue on top, not the only one.
 */
.note-item-folder {
  display: inline-flex; align-items: center; gap: 3px; border-radius: var(--tag-radius);
  padding: 1px 8px 1px 6px; white-space: nowrap; font-weight: 650;
  text-transform: var(--label-case); letter-spacing: var(--tracking-label);
  background: var(--ic-folder); color: var(--accent-ink);
}
.note-item-folder .ic { width: 10px; height: 10px; flex-shrink: 0; }
/* Only rendered when the file name is why the row is in the results — see
   filenameHintFor(). Monospaced and unfilled so it reads as a path, not as
   another tag/folder chip. */
.note-item-filename {
  display: inline-flex; align-items: center; gap: 3px; min-width: 0; max-width: 100%;
  font-family: var(--font-mono); font-size: var(--fs-meta); color: var(--ink-dim);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.note-item-filename .ic { width: 10px; height: 10px; flex-shrink: 0; opacity: 0.7; }
.note-item-tag {
  border-radius: var(--tag-radius); padding: 1px 7px; white-space: nowrap;
  text-transform: var(--label-case); letter-spacing: var(--tracking-label);
  border: 1px solid color-mix(in srgb, var(--ic-tag) 40%, transparent); color: var(--ic-tag);
}
:root[data-design='slate'] .note-item-tag::before, :root[data-design='focus'] .note-item-tag::before { content: '#'; opacity: 0.75; }

.note-item-progress { display: inline-flex; align-items: center; gap: 5px; white-space: nowrap; }
.progbar { width: 30px; height: 3px; border-radius: 3px; background: var(--line); overflow: hidden; flex-shrink: 0; }
.progbar i { display: block; height: 100%; background: var(--accent); }

/* ===================================================================
   Note list layouts — user-chosen alternatives to the default card row.
   Every layout reuses buildNoteRow()'s existing markup (same title,
   snippet, meta, actions, checkbox), scoped to #notes-list so Trash
   always keeps the card layout regardless of this setting. The avatar
   letter and --row-accent custom property are populated by buildNoteRow
   for every row, every layout, and simply sit unused (display:none)
   except where a layout below asks for them.
   =================================================================== */
.note-item-avatar { display: none; }

/* ---------- two-line: flat row, one snippet line ---------- */
#notes-list[data-list-layout='two-line'] .note-item {
  background: none; border: none; border-bottom: 1px solid var(--line-soft);
  border-radius: 0; box-shadow: none; padding: 7px 3px;
}
#notes-list[data-list-layout='two-line'] .note-item-snippet { -webkit-line-clamp: 1; margin-top: 2px; }
#notes-list[data-list-layout='two-line'] .note-item-meta { margin-top: 3px; }

/* ---------- titles: single line, title + date only ---------- */
#notes-list[data-list-layout='titles'] .note-item {
  background: none; border: none; border-bottom: 1px solid var(--line-soft);
  border-radius: 0; box-shadow: none; padding: 6px 3px;
  display: flex; flex-direction: row; align-items: center; gap: 8px;
}
#notes-list[data-list-layout='titles'] .note-item-row { flex: 1; min-width: 0; }
#notes-list[data-list-layout='titles'] .note-item-snippet,
#notes-list[data-list-layout='titles'] .note-item-folder,
#notes-list[data-list-layout='titles'] .note-item-tags,
#notes-list[data-list-layout='titles'] .note-item-filename,
#notes-list[data-list-layout='titles'] .note-item-progress { display: none; }
/* Nothing is left for this row to hold in this layout — the date sits in the
   title row now, and every chip above is hidden — so it collapses to nothing
   rather than adding height to a deliberately single-line row. */
#notes-list[data-list-layout='titles'] .note-item-meta {
  margin: 0; flex-shrink: 0; gap: 0;
}

/* ---------- grid: two-column fixed-height tiles ---------- */
#notes-list[data-list-layout='grid'] { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; }
#notes-list[data-list-layout='grid'] .list-section-head { grid-column: 1 / -1; }
#notes-list[data-list-layout='grid'] .note-item {
  height: 116px; padding: 9px 10px; display: flex; flex-direction: column;
}
/* note-item-row keeps its normal flex-row layout (checkbox, body, actions
   side by side) — same as every other layout — it's just stretched to fill
   the tile's height instead of only its content's height, so body/snippet
   can flex to fill the remaining space. An earlier version pulled actions
   out with `display: contents` + absolute positioning to save width, but
   that removed them from flow entirely and left them overlapping the
   title text (nothing reserved the corner they sat in). Reserving their
   width in normal flow, like Card already does, is what actually avoids
   the overlap. */
#notes-list[data-list-layout='grid'] .note-item-row { flex: 1; min-height: 0; align-items: stretch; }
#notes-list[data-list-layout='grid'] .note-item-body {
  flex: 1; min-width: 0; min-height: 0; display: flex; flex-direction: column;
}
#notes-list[data-list-layout='grid'] .note-item-snippet { flex: 1; -webkit-line-clamp: 3; margin-top: 4px; }
#notes-list[data-list-layout='grid'] .note-item-meta { margin-top: auto; }
/* The meta row wraps everywhere else, which a variable-height row can absorb.
   A fixed 116px tile can't: a note with a folder, two tags and a checklist
   chip wrapped to three lines — 66px of the tile — and left the snippet 7px,
   the clipped tops of a single line. Held to one line here, with whatever
   doesn't fit cut off at the tile edge; losing the third chip costs less than
   losing the snippet. Chips keep their own width rather than being squeezed
   into unreadable slivers. */
#notes-list[data-list-layout='grid'] .note-item-meta,
#notes-list[data-list-layout='grid'] .note-item-tags { flex-wrap: nowrap; overflow: hidden; }
#notes-list[data-list-layout='grid'] .note-item-meta > * { flex-shrink: 0; }
/* Grid is the one layout that can't afford to reserve the action buttons'
   width in flow. Two tiles share the panel, so a tile is ~147px wide in a
   default panel and ~120px at the 320px minimum — and the three buttons are
   88px of that. Reserving them (which is right for Card at ~322px, and is
   what the comment above is about) left the title 11px wide, and 0px at a
   320px panel: the title simply wasn't rendered, and the snippet wrapped one
   word per line.

   They're `opacity: 0` until hover anyway, so here they leave the flow and
   are painted over the tile's top-right on hover, against the tile's own
   background so they stay legible over whatever text is beneath. */
#notes-list[data-list-layout='grid'] .note-item-actions {
  position: absolute; top: 6px; right: 6px; margin: 0;
  align-items: flex-start; border-radius: var(--control-radius);
}
#notes-list[data-list-layout='grid'] .note-item:hover .note-item-actions { background: var(--panel2); }
/* Toggled with `display`, not just opacity, so the resting box is only as
   wide as what's actually visible. Left at opacity the group would still
   occupy its full 88px while invisible, and the pin that stays on for a
   pinned note would be pushed ~88px in from the right edge — floating in the
   middle of the tile instead of sitting in its corner. */
#notes-list[data-list-layout='grid'] .note-item-actions .export-action,
#notes-list[data-list-layout='grid'] .note-item-actions .delete-action { display: none; }
#notes-list[data-list-layout='grid'] .note-item:hover .note-item-actions .export-action,
#notes-list[data-list-layout='grid'] .note-item:hover .note-item-actions .delete-action { display: flex; }
/* Only a pinned tile shows anything at rest, so only a pinned tile needs to
   keep its title clear of that corner. */
#notes-list[data-list-layout='grid'] .note-item:has(.pin-action.on) .note-item-title-row { padding-right: 24px; }

/* ---------- spine: compact row, coloured left edge ---------- */
#notes-list[data-list-layout='spine'] .note-item {
  border: none; border-radius: 8px; box-shadow: none; padding: 7px 11px 7px 14px;
}
#notes-list[data-list-layout='spine'] .note-item::before {
  content: ''; position: absolute; left: 0; top: 4px; bottom: 4px; width: 4px;
  border-radius: 3px; background: var(--row-accent, var(--line));
}
#notes-list[data-list-layout='spine'] .note-item-snippet { -webkit-line-clamp: 1; margin-top: 2px; }

/* ---------- badge: coloured initial, flat row ---------- */
#notes-list[data-list-layout='badge'] .note-item {
  background: none; border: none; border-bottom: 1px solid var(--line-soft);
  border-radius: 0; box-shadow: none; padding: 8px 3px;
}
#notes-list[data-list-layout='badge'] .note-item-row { align-items: center; }
#notes-list[data-list-layout='badge'] .note-item-snippet { -webkit-line-clamp: 1; margin-top: 2px; }
#notes-list[data-list-layout='badge'] .note-item-avatar {
  display: grid; place-items: center; width: 28px; height: 28px; border-radius: 9px;
  flex-shrink: 0; font-weight: 700; font-size: var(--fs-2);
  background: var(--row-accent, var(--accent)); color: var(--accent-ink);
}

.empty-state, .no-results-state { margin: auto; text-align: center; color: var(--muted); padding: 24px; }
.no-results-state .hint { font-size: var(--fs-2); margin-top: 6px; }

.trash-hint { margin: 0; font-size: var(--fs-meta); color: var(--muted); flex: 1; min-width: 0; }

.pager {
  display: flex; align-items: center; justify-content: center; gap: 12px;
  padding: 8px; border-top: 1px solid var(--line); flex-shrink: 0; background: var(--header-bg);
}
.pager-label { font-size: var(--fs-2); color: var(--muted); font-variant-numeric: tabular-nums; min-width: 70px; text-align: center; font-family: var(--font-meta); }
.pager-dots { display: flex; gap: 4px; align-items: center; }
.pager-dot { width: 5px; height: 5px; border-radius: 50%; background: var(--line); }
.pager-dot.on { background: var(--accent); }
:root[data-design='focus'] .pager-dot, :root[data-design='slate'] .pager-dot { border-radius: 1px; }

.editor-topbar { display: flex; align-items: center; gap: 6px; padding: 8px; border-bottom: 1px solid var(--line); flex-shrink: 0; position: relative; background: var(--header-bg); }
.title-input { flex: 1; border: none; background: none; color: var(--ink); font-family: var(--font-display); font-size: var(--fs-lg); font-weight: 650; padding: 6px 4px; }
.title-input::placeholder { color: var(--muted); }
.title-input:focus { outline: none; }

.dropdown-menu {
  position: absolute; right: 8px; top: 46px; background: var(--panel); border: 1px solid var(--line);
  border-radius: var(--menu-radius); box-shadow: 0 20px 44px rgba(0,0,0,0.32); z-index: 10;
  display: flex; flex-direction: column; min-width: 180px; padding: 4px; overflow: hidden;
}
.dropdown-menu button {
  display: flex; align-items: center; gap: 9px; border: none; background: none; text-align: left;
  padding: 9px 10px; cursor: pointer; color: var(--ink); font: inherit; font-size: var(--fs-sm); border-radius: var(--control-radius);
}
.dropdown-menu button:hover { background: var(--panel2); }
.dropdown-menu button.danger { color: var(--danger); }
.dropdown-menu hr { border: none; border-top: 1px solid var(--line); margin: 4px 2px; }

/*
 * A single shared element (see openRowExportMenuFor in sidepanel.js), not
 * one per row — positioned with `position: fixed` and JS-computed
 * left/top from the trigger button's own rect, since every ancestor a
 * per-row menu would otherwise live inside (.note-item, .notes-list,
 * .view, .screen) sets overflow:hidden for pagination or the delete
 * animation and would clip it.
 */
.row-export-menu {
  position: fixed; background: var(--panel); border: 1px solid var(--line);
  border-radius: var(--menu-radius); box-shadow: 0 20px 44px rgba(0,0,0,0.32); z-index: 50;
  display: flex; flex-direction: column; min-width: 150px; padding: 4px;
}
.row-export-menu button {
  border: none; background: none; text-align: left; padding: 8px 10px; cursor: pointer;
  color: var(--ink); font: inherit; font-size: var(--fs-sm); border-radius: var(--control-radius); width: 100%;
}
.row-export-menu button:hover { background: var(--panel2); }
.row-export-menu button.danger { color: var(--danger); }
.row-export-menu button:disabled { opacity: 0.4; cursor: default; }
.row-export-menu button:disabled:hover { background: none; }
.row-export-menu hr { border: none; border-top: 1px solid var(--line); margin: 4px 2px; }
.row-export-menu button.has-submenu { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
.row-export-menu .submenu-arrow { color: var(--muted); font-size: var(--fs-base); line-height: 1; }

.toolbar { display: flex; align-items: center; gap: 2px; padding: 6px 8px; border-bottom: 1px solid var(--line); flex-shrink: 0; flex-wrap: wrap; background: var(--panel); }
.toolbar button { border: none; background: none; padding: 6px 9px; border-radius: var(--control-radius); cursor: pointer; color: var(--ink-dim); font: inherit; font-size: var(--fs-sm); display: flex; align-items: center; line-height: 1; }
.toolbar button:hover { background: var(--panel2); color: var(--ink); }
/* Now that the editor is rich text, the toolbar is the only thing that can
   tell you the caret is inside bold/a list/a quote — the syntax that used
   to say so isn't on screen any more. */
.toolbar button.on {
  background: color-mix(in srgb, var(--accent) 20%, transparent);
  color: var(--ink); box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--accent) 40%, transparent);
}
.toolbar button sub, .toolbar button sup { font-size: 0.72em; }
/* Thin rules between logical groups (style / emphasis / lists / sub-sup /
   quote+code / link+image / clear) rather than one undifferentiated row of
   buttons — the reference toolbar this was modeled on groups the same way. */
.toolbar-divider { width: 1px; height: 18px; background: var(--line); margin: 0 3px; flex-shrink: 0; }
.toolbar-select {
  border: 1px solid var(--line); background: var(--panel2); color: var(--ink); border-radius: var(--control-radius);
  padding: 4px 6px; font: inherit; font-size: var(--fs-2); max-width: 108px; flex-shrink: 0;
}

/* Text/highlight color: a swatch grid instead of a <select>, so choosing a
   color means recognizing it, not reading its name off a dropdown row. Seven
   hue columns each running light-to-dark, same shape as the grids in
   Docs/Sheets-style editors, so the layout itself is already familiar. */
.color-picker { position: relative; flex-shrink: 0; }
.color-picker-btn {
  border: 1px solid var(--line); background: var(--panel2); color: var(--ink-dim); border-radius: var(--control-radius);
  padding: 5px 7px; cursor: pointer; display: flex; align-items: center; line-height: 1;
}
.color-picker-btn:hover, .color-picker-btn[aria-expanded="true"] { background: var(--panel); color: var(--ink); }
.color-swatch-panel {
  position: absolute; left: 0; top: calc(100% + 4px); z-index: 10; background: var(--panel);
  border: 1px solid var(--line); border-radius: var(--menu-radius); box-shadow: 0 20px 44px rgba(0,0,0,0.32);
  padding: 8px;
}
/* Set by JS once the panel is visible and its rect can be measured — swaps
   which edge it hangs from so it grows into free space instead of off the
   edge of the panel/window. */
.color-swatch-panel.align-right { left: auto; right: 0; }
.palette-grid { display: grid; grid-template-columns: repeat(7, 20px); grid-auto-rows: 20px; gap: 3px; }
.palette-grid .swatch {
  width: 20px; height: 20px; border-radius: 4px; border: 1px solid rgba(0,0,0,0.12); cursor: pointer; padding: 0;
}
.swatch-panel-footer {
  display: flex; gap: 6px; margin-top: 8px; padding-top: 8px; border-top: 1px solid var(--line);
}
.swatch-panel-footer .swatch { width: 26px; height: 26px; border-radius: 6px; }
.swatch:hover, .swatch:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
.swatch-clear {
  border: 1px solid rgba(0,0,0,0.12); background: var(--panel2); color: var(--ink-dim); cursor: pointer; padding: 0;
  display: flex; align-items: center; justify-content: center;
}
.swatch-clear .ic { width: 13px; height: 13px; }
/* The native colour input is the whole swatch: it's clipped to the same
   shape as the presets so the escape hatch reads as one more colour
   rather than a differently-shaped control. */
.swatch-custom {
  padding: 0; overflow: hidden; display: block; border-radius: 6px;
  background: conic-gradient(#E5484D, #F76B15, #D4A72C, #30A46C, #12A594, #3B82F6, #8B5CF6, #E93D82, #E5484D);
}
.swatch-custom input[type='color'] {
  width: 200%; height: 200%; margin: -50% 0 0 -50%; border: none; padding: 0;
  background: none; opacity: 0; cursor: pointer;
}

/* Table size picker: the same panel shell as the colour swatches, so the two
   dropdowns in the toolbar behave and read as one family. Size is chosen by
   sweeping the grid — the shape you want is the shape you point at. */
.table-picker-panel {
  position: absolute; left: 0; top: calc(100% + 4px); z-index: 10; background: var(--panel);
  border: 1px solid var(--line); border-radius: var(--menu-radius); box-shadow: 0 20px 44px rgba(0,0,0,0.32);
  padding: 8px;
}
.table-picker-panel.align-right { left: auto; right: 0; }
.table-grid { display: grid; grid-template-columns: repeat(8, 16px); grid-auto-rows: 16px; gap: 2px; }
/* Descendant-qualified so these beat `.toolbar button`, which zeroes out
   background/border for every button in the toolbar — the same reason the
   colour swatches are written as `.palette-grid .swatch`. */
.table-grid .table-grid-cell {
  width: 16px; height: 16px; padding: 0; cursor: pointer; box-sizing: border-box;
  border: 1px solid var(--line); border-radius: 2px;
  background: color-mix(in srgb, var(--ink) 8%, transparent);
}
.table-grid .table-grid-cell.on { background: var(--accent); border-color: var(--accent); }
.table-grid-label {
  margin-top: 8px; padding-top: 8px; border-top: 1px solid var(--line);
  font-size: var(--fs-2); color: var(--ink-dim); text-align: center; font-variant-numeric: tabular-nums;
}

/* Change-case menu: the same panel shell as the colour swatches and table
   picker, but a plain vertical list of actions rather than a grid — there's
   nothing here to preview or sweep across, just three things to click. */
.text-case-panel {
  position: absolute; left: 0; top: calc(100% + 4px); z-index: 10; background: var(--panel);
  border: 1px solid var(--line); border-radius: var(--menu-radius); box-shadow: 0 20px 44px rgba(0,0,0,0.32);
  padding: 4px; display: flex; flex-direction: column; min-width: 160px;
}
.text-case-panel.align-right { left: auto; right: 0; }
/* Descendant-qualified for the same reason as .palette-grid .swatch above:
   a bare `.text-case-panel button` ties .toolbar button on specificity and
   would only win by source order, which the next edit to this file could
   quietly break. */
.text-case-panel .text-case-item {
  text-align: left; padding: 6px 10px; border-radius: 6px; border: none; background: none;
  color: var(--ink); cursor: pointer; font-size: var(--fs-2); width: 100%; display: block;
}
.text-case-panel .text-case-item:hover, .text-case-panel .text-case-item:focus-visible { background: var(--panel2); }

/* Small caret next to a picker trigger's own icon — the trigger already
   shows the current state (alignment) or a generic glyph (insert), so this
   is only the "there's a menu here" affordance, not a control of its own. */
.chevron-ic { width: 11px; height: 11px; stroke-width: 2.2; margin-left: 2px; opacity: 0.65; flex-shrink: 0; }

/* Alignment picker: same panel shell as the table/case pickers above, but a
   plain horizontal row of the original four buttons — nothing new needed
   here since they keep their own data-align wiring, only their container
   changed. */
.align-picker-panel {
  position: absolute; left: 0; top: calc(100% + 4px); z-index: 10; background: var(--panel);
  border: 1px solid var(--line); border-radius: var(--menu-radius); box-shadow: 0 20px 44px rgba(0,0,0,0.32);
  padding: 4px; display: flex; gap: 2px;
}
.align-picker-panel.align-right { left: auto; right: 0; }

/* Insert menu: icon + label rows, wider than the change-case list since
   "Horizontal rule" is the longest thing any menu in this toolbar has to
   say. */
.insert-menu-panel {
  position: absolute; left: 0; top: calc(100% + 4px); z-index: 10; background: var(--panel);
  border: 1px solid var(--line); border-radius: var(--menu-radius); box-shadow: 0 20px 44px rgba(0,0,0,0.32);
  padding: 4px; display: flex; flex-direction: column; min-width: 180px;
}
.insert-menu-panel.align-right { left: auto; right: 0; }
.insert-menu-panel .insert-item {
  display: flex; align-items: center; gap: 10px; text-align: left; padding: 7px 9px; border-radius: 8px;
  border: none; background: none; color: var(--ink); cursor: pointer; font: inherit; font-size: var(--fs-2);
  width: 100%;
}
.insert-menu-panel .insert-item:hover, .insert-menu-panel .insert-item:focus-visible { background: var(--panel2); }
.insert-menu-panel .insert-item .ic { width: 16px; height: 16px; color: var(--ink-dim); flex-shrink: 0; }

/* Row/column actions live in their own bar that only exists while the caret
   is in a table, rather than as seven permanently-greyed buttons in the
   main toolbar. */
.table-toolbar { border-top: 1px dashed var(--line); }
.table-toolbar-label {
  font-size: var(--fs-meta); color: var(--muted); text-transform: uppercase; letter-spacing: 0.04em;
  margin-right: 2px; flex-shrink: 0;
}
.note-editor thead th { background: var(--panel2); font-weight: 600; text-align: left; }

/* Folder + tags as a footer strip above the save status, rather than a band
   between the toolbar and the first line of text: they're set-once metadata,
   so they shouldn't be the first thing the eye lands on when writing. The
   row scrolls sideways rather than wrapping, so a heavily-tagged note can't
   eat the writing area. */
.meta-bar {
  display: flex; align-items: center; gap: 6px; padding: 6px 10px; flex-shrink: 0;
  border-top: 1px solid var(--line); background: var(--panel);
  overflow-x: auto; overflow-y: hidden; scrollbar-width: none;
}
.meta-bar::-webkit-scrollbar { display: none; }
#note-folder-select {
  flex-shrink: 0; max-width: 45%; border: 1px solid var(--line); background: var(--panel2); color: var(--ink-dim);
  border-radius: var(--control-radius); padding: 3px 6px; font: inherit; font-size: var(--fs-2); text-overflow: ellipsis;
}
#note-folder-select:disabled { opacity: 0.6; }

.meta-ic { flex-shrink: 0; }
.tag-chips { display: flex; align-items: center; gap: 4px; flex-shrink: 0; }
/* Tinted with the tag hue rather than the app accent, so a tag chip and a
   folder chip stay tellable apart at a glance in a dense row. */
.tag-chip-editable {
  display: inline-flex; align-items: center; gap: 3px; flex-shrink: 0; white-space: nowrap;
  background: color-mix(in srgb, var(--ic-tag) 15%, transparent);
  border: 1px solid color-mix(in srgb, var(--ic-tag) 26%, transparent); color: var(--ink);
  border-radius: var(--tag-radius); padding: 2px 4px 2px 8px; font-size: var(--fs-meta);
  text-transform: var(--label-case); letter-spacing: var(--tracking-label);
}
:root[data-design='slate'] .tag-chip-editable::before,
:root[data-design='focus'] .tag-chip-editable::before { content: '#'; opacity: 0.6; margin-right: -1px; }
.tag-chip-x {
  border: none; background: none; color: var(--muted); cursor: pointer; font: inherit; font-size: var(--fs-sm);
  line-height: 1; padding: 0 2px; border-radius: 3px;
}
.tag-chip-x:hover { color: var(--danger); background: var(--panel); }

.tag-add-btn {
  display: inline-flex; align-items: center; gap: 4px;
  flex-shrink: 0; white-space: nowrap; border: 1px dashed var(--line); background: none; color: var(--muted);
  border-radius: var(--tag-radius); padding: 2px 9px 2px 7px; font: inherit; font-size: var(--fs-meta); cursor: pointer;
}
.tag-add-btn .ic { width: 12px; height: 12px; }
.tag-add-btn:hover { border-color: var(--ic-tag); color: var(--ink); border-style: solid; }
.tag-add-btn:disabled { opacity: 0.5; cursor: default; }
.tag-input {
  flex: 0 0 110px; min-width: 90px; border: 1px solid var(--ic-tag); background: var(--panel2); color: var(--ink);
  border-radius: var(--tag-radius); padding: 2px 9px; font: inherit; font-size: var(--fs-meta);
}
.tag-input:focus { outline: none; }
.meta-bar.readonly { opacity: 0.75; }

/*
 * The note body is a rich-text surface, not a Markdown source view: the
 * styles below are what "bold" or "Heading 2" actually look like while you
 * type. They're kept close to the rendered defaults of the rest of the app
 * so a note reads the same in the editor as it does in an export.
 */
.editor-body { flex: 1; display: flex; overflow: hidden; }
.note-editor {
  flex: 1; padding: 14px; overflow-y: auto; overflow-x: auto; font-family: var(--font-ui);
  font-size: var(--fs-read); line-height: 1.7; background: var(--bg); color: var(--ink);
  outline: none; word-wrap: break-word; overflow-wrap: anywhere; position: relative;
}
/* CSS can't reliably tell "empty" here: Chrome leaves a stray <p><br></p>
   behind once you delete everything, which :empty doesn't match. The JS
   toggles .is-empty instead, off the same text it counts words from. */
.note-editor.is-empty::before {
  content: attr(data-placeholder); color: var(--muted); pointer-events: none;
  position: absolute; /* out of flow, so the caret still sits on line one */
}

.note-editor > :first-child { margin-top: 0; }
.note-editor p { margin: 0 0 0.75em; }
.note-editor h1, .note-editor h2, .note-editor h3, .note-editor h4 {
  font-family: var(--font-display); color: var(--ink); margin: 1em 0 0.4em; line-height: 1.3;
}
.note-editor h1 { font-size: 1.7em; }
.note-editor h2 { font-size: 1.38em; }
.note-editor h3 { font-size: 1.16em; }
.note-editor h4 { font-size: 1.04em; }
.note-editor ul, .note-editor ol { margin: 0 0 0.75em; padding-left: 1.5em; }
.note-editor li { margin: 0.15em 0; }
.note-editor blockquote {
  margin: 0 0 0.75em; padding: 2px 0 2px 12px; border-left: 3px solid var(--accent);
  color: var(--ink-dim); font-style: italic;
}
.note-editor code {
  background: var(--panel2); padding: 1px 4px; border-radius: 4px;
  font-family: var(--font-mono); font-size: 0.92em;
}
.note-editor pre {
  background: var(--panel2); padding: 10px 12px; border-radius: var(--control-radius);
  overflow-x: auto; margin: 0 0 0.75em;
}
.note-editor pre code { background: none; padding: 0; }
.note-editor a { color: var(--accent); text-decoration: underline; }
.note-editor img { max-width: 100%; height: auto; border-radius: var(--control-radius); }
.note-editor hr { border: none; border-top: 1px solid var(--line); margin: 1em 0; }
/* No width by default: a table with real content sizes to that content, like
   any ordinary table, rather than being stretched edge to edge regardless of
   how little is in it. .table-empty (toggled in sidepanel.js, based on
   whether any cell has text) is the one exception — a table with nothing in
   it yet has no content to size to, and the same auto layout would shrink
   every column to its floor instead, which is the cramped look this whole
   rule exists to avoid. See refreshTableWidthMode() in sidepanel.js for
   when that class is added and removed — including why it backs off the
   moment a manual drag-resize (also sidepanel.js) is in play.
   table-layout stays `auto`, not `fixed` — tempting, since `fixed` is the
   usual "make columns behave" fix, but measured here it ignores the cells'
   min-width entirely and just divides its width evenly regardless, so a
   many-column table gets squeezed below its floor instead of growing past
   it. `auto` does honour min-width as real column content, so instead a wide
   table grows past its container — which is what lets .note-editor's own
   overflow-x: auto (below) put a scrollbar under it, with no wrapper <div>
   needed around the <table> itself. */
.note-editor table { border-collapse: collapse; margin: 0 0 0.75em; table-layout: auto; }
.note-editor table.table-empty { width: 100%; }
.note-editor th, .note-editor td {
  border: 1px solid var(--line); padding: 6px 10px; min-width: 72px; overflow-wrap: break-word;
}

/* Column-resize handles for a table in the editor (sidepanel.js). position:
   fixed and parented to <body>, not the table — see the comment above their
   construction for why. A thin hit target (10px) centred on a near-invisible
   1px line, widening to an accent bar only on hover/drag so the table
   doesn't look busy the rest of the time. */
.table-col-handle {
  position: fixed; width: 10px; margin-left: -5px; cursor: col-resize; z-index: 40;
}
.table-col-handle::after {
  content: ''; display: block; width: 1px; height: 100%; margin: 0 auto; background: transparent;
}
.table-col-handle:hover::after, .table-col-handle.active::after { width: 2px; background: var(--accent); }

/* Checklists: the marker column is the checkbox itself, so the default
   list bullet has to go or every item shows two markers. */
.note-editor ul.task-list { list-style: none; padding-left: 0.25em; }
/* The checkbox rides in the text flow rather than in a flex column: a
   nested list inside a checklist item has to fall *below* its parent, and
   a flex row puts it alongside instead. */
.note-editor li.task-item { list-style: none; }
.note-editor .task-check {
  margin: 0 8px 0 0; vertical-align: -0.1em; accent-color: var(--accent); cursor: pointer;
}
.note-editor li.task-item:has(.task-check:checked) { color: var(--muted); text-decoration: line-through; }

/* Trashed notes open here too, read-only — same rendering, no caret. */
.editor-body.mode-preview .note-editor { color: var(--ink-dim); }

/*
 * Wraps rather than truncates: at a realistic side-panel width (as narrow
 * as ~320px) "Ln 1, Col 73 · 15 words · 72 chars (58 no spaces) · 1 line"
 * doesn't fit next to the save status on one line. flex-wrap lets the
 * stats drop to their own row as a whole, unbroken chunk instead of
 * clipping mid-number behind an ellipsis.
 */
.status-bar { display: flex; align-items: center; flex-wrap: wrap; gap: 2px 8px; padding: 6px 10px; font-size: var(--fs-meta); color: var(--muted); border-top: 1px solid var(--line); flex-shrink: 0; font-variant-numeric: tabular-nums; font-family: var(--font-meta); background: var(--header-bg); }
.status-bar .spacer { flex: 1 1 auto; min-width: 8px; }

/*
 * The file name gets its own row above the counts, sharing it with the
 * save status: the two together answer "which file am I editing, and is
 * it written yet" — the pair of questions a folder-backed editor has to
 * keep visible. Monospaced, since it's a path, not prose.
 */
.filename-bar {
  display: flex; align-items: center; gap: 6px; padding: 5px 10px; flex-shrink: 0;
  border-top: 1px solid var(--line); background: var(--header-bg); font-size: var(--fs-meta); min-width: 0;
}
.filename-bar .spacer { flex: 1 1 auto; min-width: 8px; }
.filename-bar .ic-file { width: 13px; height: 13px; color: var(--muted); flex-shrink: 0; }
.filename-btn {
  border: none; background: none; padding: 2px 5px; border-radius: var(--control-radius);
  color: var(--ink-dim); font-family: var(--font-mono); font-size: var(--fs-meta); cursor: pointer;
  min-width: 0; max-width: 62%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.filename-btn:hover:not(:disabled) { background: var(--panel2); color: var(--ink); text-decoration: underline; }
.filename-btn:disabled { cursor: default; color: var(--muted); }
.save-status { color: var(--muted); font-family: var(--font-meta); white-space: nowrap; }
#save-status { flex-shrink: 0; white-space: nowrap; }
.editor-stats { white-space: nowrap; }

/* ===================================================================
   Settings — built to fit a side panel without scrolling.
   Section captions sit *outside* their card so each card contains
   nothing but uniform rows; every row is one fixed-height line with its
   control landing on a shared right edge.
   =================================================================== */
.settings-body {
  flex: 1; min-height: 0; padding: 10px 12px 6px; overflow-y: auto;
  display: flex; flex-direction: column; gap: 7px; scrollbar-width: thin;
}
/* Every group is rigid. Without this, a body taller than the panel squeezes
   the groups instead of scrolling, and each card's fixed-height rows spill
   out over the caption below it. The folder list is the one deliberate
   exception (see .settings-group-folders). */
.settings-group { display: flex; flex-direction: column; gap: 4px; flex-shrink: 0; min-height: 0; }
.settings-caption {
  font-size: var(--fs-meta); line-height: 1.2; text-transform: uppercase; letter-spacing: 0.06em;
  color: var(--muted); margin: 0 0 0 2px; font-family: var(--font-meta); font-weight: 700;
}
.settings-card {
  border: 1px solid var(--line); border-radius: var(--row-radius); background: var(--panel);
  box-shadow: var(--row-shadow); padding: 0 12px; display: flex; flex-direction: column;
  flex-shrink: 0; min-height: 0;
}
:root[data-design='slate'] .settings-card,
:root[data-design='focus'] .settings-card { border-radius: var(--control-radius); box-shadow: none; }

.settings-row {
  display: flex; align-items: center; justify-content: space-between; gap: 10px;
  flex-shrink: 0; min-height: 36px; padding: 5px 0; font-size: var(--fs-sm); color: var(--ink);
}
.settings-row + .settings-row,
.folder-manage-list + .add-row,
.settings-empty + .add-row { border-top: 1px solid var(--line-soft); }
.settings-row-stack { display: block; padding: 8px 0; }
/* A row whose only child is its button — space-between would strand it left. */
.settings-row-action { justify-content: flex-end; }
.row-label { min-width: 0; line-height: 1.35; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.row-text { display: flex; flex-direction: column; gap: 1px; min-width: 0; }
.row-text .row-label { color: var(--ink); }
.row-sub {
  font-size: var(--fs-meta); line-height: 1.35; color: var(--muted); font-family: var(--font-meta);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.muted { color: var(--muted); font-size: var(--fs-sm); }
.settings-empty { color: var(--muted); font-size: var(--fs-2); margin: 0; padding: 10px 0; }

/* One height and one border treatment for every control on the page, so
   buttons and selects line up on the right edge instead of each bringing
   its own metrics. */
.btn-compact, .control-select {
  width: auto; margin: 0; flex-shrink: 0; height: 28px; padding: 0 10px;
  border: 1px solid var(--line); border-radius: var(--control-radius);
  background: var(--panel2); color: var(--ink); font: inherit; font-size: var(--fs-2); cursor: pointer;
}
.btn-compact:hover, .control-select:hover { border-color: var(--accent); color: var(--accent); }
.control-select { padding-right: 4px; }

/* Segmented controls replace the old design thumbnails and the light/dark
   <select>: same information, one row of height, and the current value is
   readable without opening anything. */
.segmented {
  display: flex; width: 100%; gap: 2px; padding: 2px; border: 1px solid var(--line);
  border-radius: var(--control-radius); background: var(--panel2);
}
.segmented-compact { width: auto; flex-shrink: 0; }
/* The full-width picker above splits its row evenly, but a compact one sits at
   the right edge of a settings row and has no row width to divide — its
   buttons have to size to their own labels instead. `flex: 1` + `min-width: 0`
   would let the longest one shrink below its text and clip it, which English
   ("Auto/Light/Dark") hides and German ("Auto/Hell/Dunkel") does not. */
.segmented-compact .seg { flex: 0 0 auto; min-width: max-content; }
.seg {
  flex: 1; display: flex; align-items: center; justify-content: center; gap: 6px; min-width: 0;
  border: none; background: none; color: var(--muted); cursor: pointer; font: inherit; font-size: var(--fs-2);
  padding: 5px 8px; border-radius: calc(var(--control-radius) - 2px); white-space: nowrap;
  transition: background .12s ease, color .12s ease;
}
.seg:hover { color: var(--ink); }
.seg.active { background: var(--panel); color: var(--ink); font-weight: 600; box-shadow: var(--row-shadow); }
/* All three designs paint the active segment as a flat accent fill. Aurora
   was missing from this selector, so it fell through to the generic
   `.seg.active` rule above (panel bg, ink text — no accent color at all) —
   that's the "highlight color is missing on Aurora" bug: next to Slate's
   and Focus's solid, punchy fill, Aurora's segmented controls (design
   picker, light/dark, floating-icon toggle) showed no color whatsoever.
   Adding Aurora here matches it to the same crisp, consistent treatment
   the other two designs already use. */
:root[data-design='slate'] .seg.active,
:root[data-design='aurora'] .seg.active,
:root[data-design='focus'] .seg.active { background: var(--accent); color: var(--accent-ink); box-shadow: none; }
.seg-swatch {
  width: 13px; height: 13px; border-radius: 4px; flex-shrink: 0;
  border: 1px solid rgba(128, 128, 128, 0.35);
}
:root[data-design='slate'] .seg-swatch, :root[data-design='focus'] .seg-swatch { border-radius: 2px; }
/* Each design's own accent over its own surface — the identity of a theme
   in 13px, which is all the old 40px mockups actually conveyed. */
.sw-slate { background: linear-gradient(135deg, #FF6B57 50%, #16171B 50%); }
.sw-aurora { background: linear-gradient(135deg, #5B5BD6 50%, #EFEFFE 50%); }
.sw-focus { background: linear-gradient(135deg, #E2A44F 50%, #171A1F 50%); }

/* Folders: a grid of icon+name cards instead of a list of rows — a list of
   ten folders left two-thirds of the row empty on every line, while a grid
   reuses that width for more folders per screenful. Rename/delete stay
   visible (not hover-reveal): this is a side panel, so "hover" often means
   "tapped a trackpad" and a hidden action is a missed action.
   Columns are `auto-fit`, not a fixed count: a fixed 3-column grid leaves a
   phantom empty column whenever there are fewer than 3 folders (or one
   short on the last row) — auto-fit collapses columns nothing landed in
   and lets the real cards stretch to fill the freed width instead. */
/* The only elastic group: folders are the one section whose height depends
   on the user's data, so it gives back whatever the page is short of and
   scrolls internally instead — every other group is rigid. Both floors are
   stated in pixels rather than left to min-content, which either collapses
   to nothing (clipping "New folder") or refuses to shrink at all: the card
   is one card row (60) + the New folder row (36) + padding/borders, and the
   group is that plus its caption. */
.settings-group-folders { flex: 0 1 auto; min-height: 120px; }
.settings-group-folders .settings-card { flex-shrink: 1; min-height: 100px; overflow: hidden; }
.folder-manage-list {
  list-style: none; margin: 0; padding: 10px 0; display: grid;
  grid-template-columns: repeat(auto-fit, minmax(140px, 1fr)); gap: 8px;
  overflow-y: auto; overflow-x: hidden; min-height: 0; max-height: 148px; scrollbar-width: thin;
}
/* Never shrink past one row of cards — below that it reads as a sliver
   rather than a grid, and a page scroll is the better trade. */
.folder-manage-list:not(:empty) { min-height: 60px; }

/* Chrome ignores scrollbar-width on these, and the default 15px track sits
   on top of the row's action buttons. */
.settings-body::-webkit-scrollbar, .folder-manage-list::-webkit-scrollbar { width: 6px; }
.settings-body::-webkit-scrollbar-track, .folder-manage-list::-webkit-scrollbar-track { background: transparent; }
.settings-body::-webkit-scrollbar-thumb, .folder-manage-list::-webkit-scrollbar-thumb {
  background: var(--line); border-radius: 3px;
}
.settings-body::-webkit-scrollbar-thumb:hover, .folder-manage-list::-webkit-scrollbar-thumb:hover {
  background: var(--muted);
}
/* One line for icon + name + actions, one line for the count — instead of
   three stacked lines (icon / name / count) each with its own breathing
   room. The count is indented to sit under the name, past the icon, so it
   reads as "this card's detail" rather than a new column of its own. */
.folder-manage-item {
  display: flex; flex-direction: column; gap: 3px; min-width: 0;
  padding: 7px 7px 8px; border: 1px solid var(--line); border-radius: var(--control-radius);
  background: var(--panel2); font-size: var(--fs-sm);
}
.folder-manage-head { display: flex; align-items: center; gap: 6px; min-width: 0; }
.folder-manage-icon { width: 16px; height: 16px; flex-shrink: 0; }
.folder-manage-icon .ic { width: 100%; height: 100%; }
.folder-manage-name {
  flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  color: var(--ink); font-weight: 600;
}
.folder-manage-count {
  padding-left: 22px; color: var(--muted); font-size: var(--fs-meta); font-family: var(--font-meta);
  white-space: nowrap; font-variant-numeric: tabular-nums;
}
.folder-actions { display: flex; gap: 1px; flex-shrink: 0; margin-left: auto; }
.folder-action {
  width: 26px; height: 26px; display: flex; align-items: center; justify-content: center;
  border: none; background: none; color: var(--muted); cursor: pointer;
  border-radius: var(--control-radius); transition: background .12s ease, color .12s ease;
}
.folder-action .ic { width: 16px; height: 16px; }
.folder-action:hover { background: var(--panel); color: var(--accent); }
.folder-action.danger:hover { background: var(--panel); color: var(--danger); }

/* Reads as the last row of the list rather than a button parked under it. */
.add-row {
  display: flex; align-items: center; gap: 7px; flex-shrink: 0; min-height: 36px; padding: 4px 0;
  border: none; background: none; color: var(--accent); font: inherit; font-size: var(--fs-sm);
  cursor: pointer; text-align: left; width: calc(100% + 24px); margin: 0 -12px; padding-left: 12px;
  border-radius: 0 0 var(--row-radius) var(--row-radius);
}
.add-row .ic { width: 14px; height: 14px; }
.add-row:hover { background: var(--panel2); }

.settings-footnote {
  display: flex; align-items: flex-start; gap: 6px; margin: 2px 2px 0; flex-shrink: 0;
  font-size: var(--fs-meta); line-height: 1.45; color: var(--muted);
}
.settings-footnote .ic { width: 13px; height: 13px; flex-shrink: 0; margin-top: 1px; }

/* ---------- Account / License page ----------
   One hero card carries identity, the countdown, and the note counts as a
   single object; everything below it is a plain settings surface. The page
   previously opened with four visually identical grey cards, which gave a
   reader no idea which of them mattered.

   Every colour here resolves through --accent / --danger / --ic-*, so all
   three designs x light/dark re-skin without a hardcoded value. */
.acct-hero {
  border-radius: var(--menu-radius); overflow: hidden;
  border: 1px solid color-mix(in srgb, var(--accent) 30%, var(--line));
}

/* .settings-body is a flex column, so any child that doesn't opt out gets
   squeezed once the page is taller than the panel — and on the hero that is
   invisible damage rather than a squeeze, because overflow: hidden (needed
   for the rounded band) simply cuts the counts strip off mid-digit. The
   settings page solves this per-component on .settings-group/.settings-card;
   this page has plain divs, buttons and paragraphs at the top level too, so
   the whole column opts out at once. */
#account-view .settings-body > * { flex-shrink: 0; }

/* --- the coloured band ---
   `data-tone` is set in paintAccount: accent = healthy, warn = expiring or
   renewal due, flat = paused/expired. Only the paint changes between them,
   never the layout, so a state change can't reflow the page. */
.acct-band {
  padding: 14px;
  /* White, always — deliberately not --accent-ink (dark, calibrated for text
     on *flat* --accent) and not switched per theme. A dark-theme accent is
     usually a light pastel and a light-theme accent is usually more
     saturated, so no single fixed mix-and-ink pairing serves both — UNLESS
     the mix is dark enough that white clears AA on every combination, which
     is what these percentages are: measured as the darkest requirement
     across all 3 designs x 2 themes (the binding case was Focus/dark, which
     tolerated at most 63% accent before white dropped under 5:1), with a
     few points of margin. Re-check with a contrast tool if --accent or
     --ic-pin changes in any design. */
  color: #fff;
  /* Three stops instead of two: a flat dark-to-darker wash of one hue reads as
     muddy (this was the "ugly" flat purple in Aurora/dark). Adding a mid stop
     that swings back up in accent share, on a steeper diagonal, gives the
     band actual gradient motion instead of a single dimming ramp — while the
     brightest stop (58%) stays under the 60%(ish)/63% white-contrast ceiling
     documented above, so AA still holds everywhere this reskins to. */
  background: linear-gradient(125deg,
    color-mix(in srgb, var(--accent) 58%, #000) 0%,
    color-mix(in srgb, var(--accent) 40%, #000) 45%,
    color-mix(in srgb, var(--accent) 22%, #000) 100%);
}
/* Aurora only: a hand-picked "Royal indigo" gradient (chosen from mockups),
   richer and more saturated than what --accent's own color-mix formula above
   can produce — Aurora's accent (#8B8BFA) is a soft, fairly desaturated
   periwinkle, so mixing it with black just dims it rather than deepening it
   into something jewel-toned. Slate and Focus keep the generic accent-driven
   gradient above, since their accents (a warm red-orange, an amber) already
   read fine that way and the "faded/muddy" complaint was Aurora-specific.
   All three stops checked >=4.5:1 against the band's fixed white text. */
:root[data-design='aurora'] .acct-band:not([data-tone='warn']):not([data-tone='flat']) {
  background: linear-gradient(135deg, #34279E 0%, #5B3FD6 55%, #7C4DE0 100%);
}
/* .acct-avatar/.acct-badge normally use --accent-ink (dark) on their light
   translucent chip, on the assumption the band behind them is dark enough
   that a light chip reads as the bright element in the corner. Royal indigo
   is saturated enough — especially its darkest, top-left stop, right where
   the avatar sits — that --accent-ink (near-black in Aurora/dark) landed
   dark-on-dark instead: the "K" and "PRO" the user flagged as unreadable.
   Force white here rather than editing the shared rule, since Slate/Focus's
   accent-mix bands don't have this problem. */
:root[data-design='aurora'] .acct-band:not([data-tone='warn']):not([data-tone='flat']) .acct-avatar,
:root[data-design='aurora'] .acct-band:not([data-tone='warn']):not([data-tone='flat']) .acct-badge {
  color: #fff;
}
.acct-band[data-tone='warn'] {
  /* --ic-pin's binding case (Aurora/Slate/Focus dark all share one bright
     amber, #F0B429) tolerated at most 59% before white dropped under 5:1. */
  background: linear-gradient(140deg,
    color-mix(in srgb, var(--ic-pin) 55%, #000),
    color-mix(in srgb, var(--ic-pin) 30%, #000));
}
.acct-hero:has(.acct-band[data-tone='warn']) { border-color: color-mix(in srgb, var(--ic-pin) 40%, var(--line)); }
/* Nothing good is happening, so nothing is painted as though it were. */
.acct-band[data-tone='flat'] { background: var(--panel2); color: var(--ink); }
.acct-hero:has(.acct-band[data-tone='flat']) { border-color: color-mix(in srgb, var(--danger) 34%, var(--line)); }

.acct-band-top { display: flex; align-items: center; gap: 11px; }

/* A letter avatar once there's an email to draw it from; a plain account
   icon before that (no key on file yet) — either way the hero always has
   a face, instead of an icon-plus-caption row that reads as an afterthought.
   On the band it's a translucent well rather than an accent fill, since the
   band is already the accent. */
.acct-avatar {
  width: 42px; height: 42px; border-radius: 50%; flex-shrink: 0;
  background: color-mix(in srgb, #fff 26%, transparent);
  border: 1px solid color-mix(in srgb, #fff 30%, transparent);
  /* Dark, not inherited: this sits on its own light translucent chip, not
     directly on the gradient, so it needs the opposite ink from the band
     text around it. */
  color: var(--accent-ink);
  display: flex; align-items: center; justify-content: center;
}
.acct-band[data-tone='flat'] .acct-avatar {
  background: var(--panel); border-color: var(--line); color: var(--ink-dim);
}
.acct-avatar-icon { width: 18px; height: 18px; }
.acct-avatar-letter { font-size: var(--fs-title); font-weight: 800; font-family: var(--font-display); }

.acct-band-who { min-width: 0; flex: 1; }
/* Normally the email (the answer to "which account am I on?"), or the
   trial pitch when there's no account yet to describe. */
.acct-band-headline {
  font-size: var(--fs-lg); font-weight: 750; font-family: var(--font-display);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.acct-band-sub { font-size: var(--fs-2); opacity: .92; margin-top: 1px; }

/* The badge fills are tuned for a dark panel — accent-wash on accent, a
   danger tint on amber — so on the coloured band they lose nearly all their
   contrast ("Expiring soon" read as pink-on-amber). Inside the band it
   becomes a neutral translucent chip and lets the band's own tone carry the
   severity. The flat tone keeps the semantic colours, since it sits on
   --panel2 like the original. */
.acct-band:not([data-tone='flat']) .acct-badge {
  background: color-mix(in srgb, #fff 24%, transparent);
  border: 1px solid color-mix(in srgb, #fff 30%, transparent);
  /* Same reasoning as .acct-avatar just above: a light chip needs a dark
     ink of its own, regardless of what colour the band text around it is. */
  color: var(--accent-ink);
}
.acct-band[data-tone='flat'] .acct-band-sub { opacity: 1; color: var(--muted); }

/* --- the countdown --- */
.acct-count { margin-top: 13px; }
.acct-count-top { display: flex; align-items: flex-end; justify-content: space-between; gap: 10px; }
.acct-count-num { line-height: 1; }
/* Above the type scale's ceiling on purpose: this is the one number the page
   exists to show, and --fs-hero (20px) reads as a heading, not a figure. */
.acct-count-num .n {
  display: block; font-size: var(--fs-display); font-weight: 800; font-family: var(--font-display);
  font-variant-numeric: tabular-nums; letter-spacing: -0.025em;
}
.acct-count-num .u { display: block; font-size: var(--fs-2); font-weight: 650; opacity: .95; margin-top: 4px; }
.acct-count-state { font-size: var(--fs-2); opacity: .95; text-align: right; padding-bottom: 2px; }

.acct-progress { height: 8px; border-radius: 999px; overflow: hidden; margin-top: 12px;
  background: color-mix(in srgb, #000 26%, transparent); }
.acct-progress > i { display: block; height: 100%; border-radius: 999px;
  background: color-mix(in srgb, #fff 90%, transparent); }
.acct-band[data-tone='flat'] .acct-progress { background: var(--line-soft); }
.acct-band[data-tone='flat'] .acct-progress > i { background: var(--accent); }
.acct-progress-foot {
  display: flex; align-items: baseline; justify-content: space-between; gap: 8px;
  font-size: var(--fs-meta); opacity: .93; margin-top: 5px;
}

/* --- note counts, fused to the band ---
   1px gaps show the card background through as hairline dividers, same
   trick the old stats card used. */
.acct-strip { display: flex; gap: 1px; background: var(--line-soft); }
.acct-cell {
  flex: 1 1 0; min-width: 0; background: var(--panel); padding: 9px 11px;
  display: flex; flex-direction: column; align-items: center; gap: 1px;
  text-align: center;
}
.acct-cell .v {
  font-size: var(--fs-title); font-weight: 700; font-family: var(--font-display);
  line-height: 1.15; color: var(--ink); font-variant-numeric: tabular-nums; letter-spacing: -0.01em;
}
.acct-cell.zero .v { color: var(--muted); }
/* Wrapping rather than ellipsing: a longer translation grows the cell by a
   line instead of truncating a word. */
.acct-cell .k {
  font-size: var(--fs-meta); color: var(--muted); font-weight: 650;
  text-transform: var(--label-case); letter-spacing: var(--tracking-label);
  white-space: normal; overflow-wrap: anywhere;
}
.acct-where {
  display: flex; align-items: center; justify-content: space-between; gap: 10px;
  padding: 9px 11px; background: var(--panel); border-top: 1px solid var(--line-soft);
  font-size: var(--fs-2);
}
.acct-where .k { color: var(--muted); }
.acct-where .v {
  color: var(--ink-dim); min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  /* Ellipsise from the front: on a long path the folder name is the tail,
     and that is the part worth keeping. */
  direction: rtl; text-align: right;
}

/* --- footer --- */
/* Real buttons, not underlined links: these two are the only actions on the
   page that change account state, and a link reads as navigation. They use
   the same .btn-compact metrics as every other secondary control here (the
   stale notice's "Check again", the device rows), so the page has one
   button treatment rather than one per block. */
.acct-footer { display: flex; align-items: center; justify-content: space-between; gap: 8px; padding: 2px 2px 0; }
/* Keeps Sign out on the right edge when Restore purchase is hidden. */
.acct-footer .btn-compact:last-child { margin-left: auto; }
/* Sign out isn't destructive to the notes — they're plain files and stay put
   — but it is the one control here you can't undo with the same click, so
   the hover states diverge: accent for Restore, danger for Sign out. */
.acct-signout:hover { border-color: color-mix(in srgb, var(--danger) 55%, var(--line)); color: var(--danger); }
.acct-verified { display: flex; gap: 6px; }
/* Seats-used, sitting next to the "Devices" caption. */
.acct-cap-count {
  margin-left: 6px; color: var(--ink-dim); font-weight: 650;
  font-variant-numeric: tabular-nums; text-transform: none; letter-spacing: 0;
}

/* Warning-weight, not danger-weight: the license may well be fine and this
   is asking for a retry, not announcing a loss. */
.acct-notice {
  display: flex; align-items: flex-start; gap: 10px; padding: 10px 12px;
  border-radius: var(--control-radius); background: color-mix(in srgb, var(--danger) 10%, transparent);
  border: 1px solid color-mix(in srgb, var(--danger) 28%, transparent);
}
.acct-notice p { margin: 0; flex: 1; font-size: var(--fs-2); line-height: 1.45; color: var(--ink-dim); }
.acct-notice .btn { flex-shrink: 0; }

.acct-badge {
  display: inline-flex; align-items: center; gap: 5px; font-size: var(--fs-meta); font-weight: 700;
  padding: 3px 9px; border-radius: 999px; text-transform: var(--label-case); letter-spacing: var(--tracking-label);
  flex-shrink: 0;
}
.acct-badge.free { background: var(--panel2); color: var(--muted); }
.acct-badge.pro { background: var(--accent-wash); color: var(--accent); }
.acct-badge.trial { background: color-mix(in srgb, var(--ic-restore) 18%, transparent); color: var(--ic-restore); }
.acct-badge.expiring, .acct-badge.expired { background: color-mix(in srgb, var(--danger) 16%, transparent); color: var(--danger); }
/* Paused is a "we couldn't reach the server" state, not a loss — warning
   weight rather than danger weight, same reasoning as .acct-notice. */
.acct-badge.paused { background: color-mix(in srgb, var(--ic-pin) 20%, transparent); color: var(--ic-pin); }

.acct-trial-cta { display: flex; flex-direction: column; gap: 6px; }
.acct-trial-input {
  width: 100%; padding: 8px 10px; border-radius: var(--control-radius); border: 1px solid var(--line);
  background: var(--panel2); color: var(--ink); font: inherit; font-size: var(--fs-sm);
}
.acct-trial-input:focus { outline: none; border-color: var(--accent); }

/* Code entry reads as digits, not prose — the wide tracking makes a
   six-digit string easy to check against the email at a glance. */
.acct-otp-sent { font-size: var(--fs-meta); color: var(--muted); margin: 0 2px 2px; line-height: 1.45; }
.acct-otp-input {
  text-align: center; font-size: 18px; letter-spacing: 0.4em; text-indent: 0.4em;
  font-variant-numeric: tabular-nums;
}
.acct-otp-input::placeholder { letter-spacing: 0.4em; color: var(--line); }
.acct-otp-actions { display: flex; justify-content: space-between; gap: 8px; }
.acct-otp-actions .btn-link { font-size: var(--fs-meta); padding: 2px 0; }

.acct-hint { font-size: var(--fs-meta); color: var(--muted); margin: 6px 2px 0; line-height: 1.45; }

.acct-key-label { display: block; margin-bottom: 6px; }
.acct-keyfield {
  display: flex; align-items: center; gap: 4px; border: 1px solid var(--line); border-radius: var(--control-radius);
  padding: 7px 8px; background: var(--panel2);
}
.acct-keyfield code {
  flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  font-family: var(--font-mono); font-size: var(--fs-2); color: var(--ink-dim); letter-spacing: 0.02em;
}
.acct-iconbtn {
  width: 24px; height: 24px; border-radius: 7px; border: none; background: transparent; color: var(--muted);
  display: flex; align-items: center; justify-content: center; cursor: pointer; flex-shrink: 0; padding: 0;
}
.acct-iconbtn:hover { background: var(--panel); color: var(--ink); }
.acct-iconbtn[aria-pressed='true'] { color: var(--accent); }
.acct-iconbtn .ic { width: 14px; height: 14px; }

/* One row per activated install. The current row trades its timestamp for
   a Deactivate button — a seat can only be released from the machine
   holding it, so that's the only row Deactivate could ever act on, and
   "when did this device last check in" is already answered by "Last
   verified" a few rows down. Other rows keep the timestamp: for those it's
   the only signal of whether a seat is still in use. */
.acct-device { display: flex; align-items: center; gap: 8px; padding: 9px 0; font-size: var(--fs-sm); }
.acct-device + .acct-device { border-top: 1px solid var(--line-soft); }
.acct-device .dot {
  width: 7px; height: 7px; border-radius: 50%; flex-shrink: 0; background: var(--line);
}
.acct-device.current .dot { background: var(--ic-restore); }
.acct-device .name { flex: 1; color: var(--ink-dim); min-width: 0; }
.acct-device.current .name { color: var(--ink); font-weight: 600; }
.acct-device .when { color: var(--muted); font-size: var(--fs-2); flex-shrink: 0; }
/* Outline, not filled. A filled danger button was the brightest thing on the
   whole page — a secondary, reversible-by-re-entering-the-key action
   outranking the licence it belongs to. The colour still marks it as
   destructive; it just stops shouting. */
.acct-device-deactivate-btn {
  background: transparent; color: var(--danger);
  border: 1px solid color-mix(in srgb, var(--danger) 42%, transparent);
}
.acct-device-deactivate-btn:hover {
  background: color-mix(in srgb, var(--danger) 12%, transparent);
  border-color: var(--danger); color: var(--danger);
}

/* ---------- in-panel modals ----------
   window.prompt()/confirm() either get suppressed in a side panel or are
   drawn as a browser-level dialog on the *window*, which reads as "the
   extension opened a Chrome window". These are rendered in-document. */
.modal-overlay {
  position: fixed; inset: 0; z-index: 200; display: grid; place-items: center; padding: 16px;
  background: rgba(0, 0, 0, 0.45); animation: modal-in .12s ease;
}
.modal-overlay.closing { opacity: 0; transition: opacity .12s ease; }
@keyframes modal-in { from { opacity: 0; } to { opacity: 1; } }
.modal-box {
  width: 100%; max-width: 320px; background: var(--panel); color: var(--ink);
  border: 1px solid var(--line); border-radius: var(--menu-radius);
  box-shadow: 0 24px 60px rgba(0,0,0,0.45); padding: 16px;
}
.modal-title { font-family: var(--font-display); font-size: var(--fs-lg); font-weight: 650; margin: 0 0 8px; }
.modal-label-row { display: flex; align-items: baseline; justify-content: space-between; gap: 8px; margin-bottom: 5px; }
.modal-label { display: block; font-size: var(--fs-meta); color: var(--muted); text-transform: var(--label-case); letter-spacing: var(--tracking-label); }
.modal-label-row .modal-label { margin-bottom: 0; }
.modal-counter { font-size: var(--fs-meta); color: var(--muted); font-variant-numeric: tabular-nums; font-family: var(--font-meta); flex-shrink: 0; }
.modal-message { font-size: var(--fs-sm); color: var(--ink-dim); line-height: 1.5; margin: 0 0 14px; }
.modal-input {
  width: 100%; padding: 8px 10px; border-radius: var(--control-radius); border: 1px solid var(--line);
  background: var(--panel2); color: var(--ink); font: inherit; font-size: var(--fs-sm);
}
.modal-input:focus { outline: none; border-color: var(--accent); }
.modal-error { font-size: var(--fs-2); color: var(--danger); margin: 6px 0 0; }
.modal-actions { display: flex; gap: 8px; justify-content: flex-end; margin-top: 14px; }
.modal-actions .btn { width: auto; margin: 0; padding: 8px 14px; }
.btn-danger { background: var(--danger); border-color: var(--danger); color: var(--danger-ink); font-weight: 600; }

/*
 * Candidate D from mockups/toast-redesign.html: --panel on a --line border
 * measured at 1.04–1.10:1 contrast against the page background in every
 * design/theme — close enough to identical that the toast was reported as
 * invisible. Fixed by elevation instead of by changing hue, to stay the
 * closest of the four candidates to the app's existing look: a translucent,
 * blurred surface plus a hard --accent ring (never near-identical to the
 * page, in any design, because it's a saturated color rather than another
 * near-black/near-white neutral) and a heavier shadow to sell the float.
 */
.toast {
  position: fixed; left: 12px; right: 12px; top: 12px; margin: 0 auto; max-width: 340px;
  display: flex; align-items: center; gap: 10px;
  background: color-mix(in srgb, var(--panel) 88%, transparent);
  backdrop-filter: blur(8px) saturate(1.4);
  -webkit-backdrop-filter: blur(8px) saturate(1.4);
  color: var(--ink);
  padding: 9px 11px; border-radius: var(--row-radius);
  box-shadow: 0 0 0 1.5px var(--accent), 0 16px 36px rgba(0,0,0,.4);
  font-size: var(--fs-sm); z-index: 100;
}
.toast .toast-msg { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.toast .toast-undo { color: var(--accent); font-weight: 650; cursor: pointer; background: none; border: none; font: inherit; padding: 0; flex-shrink: 0; }

/* --- review-ask celebration: a richer, one-time toast + a confetti burst
   across the whole panel, not just the toast card. Separate component from
   the plain .toast above (which is reused constantly for undo/status
   messages and needs to stay terse) because this one carries a title,
   sub-line and two real actions.

   #review-toast-dock's `top` is set from JS (maybeShowReviewCelebration),
   not fixed here, because the space above it isn't constant: the main
   header (brand row + search row + tabbar on Notes, a shorter page-title
   row on Trash/Settings/Account) and the editor's own topbar are different
   heights, and either can be the thing on screen when the milestone fires. */
#review-confetti {
  position: fixed; inset: 0; z-index: 150; pointer-events: none;
}
.review-toast-dock {
  position: fixed; left: 10px; right: 10px; top: 54px; z-index: 151;
  display: flex; justify-content: center; pointer-events: none;
}
.review-toast {
  pointer-events: auto; width: 100%; max-width: 360px;
  background: var(--panel2); border: 1px solid var(--line); border-radius: var(--menu-radius);
  box-shadow: 0 16px 40px -12px rgba(0,0,0,.5), 0 2px 8px rgba(0,0,0,.28);
  padding: 12px 12px 11px; display: flex; flex-direction: column; gap: 9px;
  animation: review-toast-drop .4s cubic-bezier(.2,.8,.25,1);
}
@keyframes review-toast-drop { from { transform: translateY(-16px); opacity: 0; } to { transform: translateY(0); opacity: 1; } }
.review-toast-row1 { display: flex; align-items: flex-start; gap: 10px; }
.review-toast-icon {
  width: 30px; height: 30px; border-radius: var(--control-radius); flex-shrink: 0;
  background: var(--accent-wash); color: var(--ic-pin);
  display: grid; place-items: center; font-size: 15px;
  animation: review-toast-pop .5s cubic-bezier(.34,1.56,.64,1);
}
@keyframes review-toast-pop { 0% { transform: scale(.4); } 60% { transform: scale(1.14); } 100% { transform: scale(1); } }
.review-toast-body { flex: 1; min-width: 0; }
.review-toast-title { font-size: var(--fs-sm); font-weight: 700; line-height: 1.35; }
.review-toast-sub { font-size: var(--fs-2); color: var(--muted); line-height: 1.4; margin-top: 2px; }
.review-toast-close {
  flex-shrink: 0; width: 22px; height: 22px; border-radius: 6px; border: none;
  background: transparent; color: var(--muted); cursor: pointer; font-size: 15px;
  display: grid; place-items: center; margin: -2px -3px 0 0;
}
.review-toast-close:hover { background: var(--line-soft); color: var(--ink); }
.review-toast-actions { display: flex; align-items: center; gap: 8px; padding-left: 40px; }
.review-toast-btn {
  font: inherit; font-size: var(--fs-2); font-weight: 650; cursor: pointer;
  border-radius: var(--control-radius); padding: 6px 12px; border: 1px solid transparent;
}
.review-toast-btn.primary { background: var(--accent); color: var(--accent-ink); }
.review-toast-btn.ghost { background: none; color: var(--muted); padding: 6px; }
.review-toast-btn.ghost:hover { color: var(--ink); }

@media (prefers-reduced-motion: reduce) {
  .review-toast, .review-toast-icon { animation: none; }
}

/* --- engagement celebrations: five buckets, one shared shell (.review-toast
   itself, via engage-toast-dock) but a distinct icon treatment per variant so
   the icon alone signals which kind of moment this is before the text is
   even read. No action row — these carry a single × only, unlike the
   review-ask, which is the one toast in the app allowed a real CTA. */
.engage-toast:not(.variant-recap) .review-toast-body { padding-top: 1px; }

/* 1 — adoption milestone (10/25/50/…): the number itself, restrained,
   since this is the variant most likely to repeat often. */
.review-toast-icon.variant-tick {
  background: var(--accent-wash); color: var(--ink); font-weight: 800;
  font-variant-numeric: tabular-nums; font-family: var(--font-display);
  animation: engage-tick-in .5s ease-out;
}
@keyframes engage-tick-in { 0% { transform: scale(.7); opacity: 0; } 60% { transform: scale(1.18); opacity: 1; } 100% { transform: scale(1); } }

/* 2 — usage streak: a flickering flame, reserved only for streaks so it
   becomes recognizable shorthand on its own. Built on --danger rather than a
   new hardcoded hue — the only warm/red token the palette already defines
   per design, and every design's --danger reads plausibly flame-like. */
.review-toast-icon.variant-flame {
  color: var(--danger); background: color-mix(in srgb, var(--danger) 16%, var(--accent-wash));
  position: relative;
}
.review-toast-icon.variant-flame::after {
  content: ''; position: absolute; inset: -5px; border-radius: calc(var(--control-radius) + 2px);
  background: radial-gradient(circle, color-mix(in srgb, var(--danger) 45%, transparent), transparent 70%);
  animation: engage-flicker 1.6s ease-in-out infinite; z-index: -1;
}
@keyframes engage-flicker { 0%, 100% { opacity: .5; transform: scale(1); } 50% { opacity: .9; transform: scale(1.12); } }

/* 3 — feature discovery: a badge with two calm expanding rings, once per
   feature ever. --ic-pin (amber) doubles as the review-ask trophy's color —
   both read as "achievement," which is the point. */
.review-toast-icon.variant-unlock { color: var(--ic-pin); background: var(--accent-wash); position: relative; overflow: visible; }
.engage-ring { position: absolute; inset: 0; border-radius: var(--control-radius); border: 1.5px solid var(--ic-pin); opacity: 0; pointer-events: none; }
.engage-ring.r1 { animation: engage-ring 1.1s ease-out .05s; }
.engage-ring.r2 { animation: engage-ring 1.1s ease-out .3s; }
@keyframes engage-ring { 0% { opacity: .55; transform: scale(1); } 100% { opacity: 0; transform: scale(2.1); } }

/* 4 — anniversary: rare and meant to feel warm rather than gamey, so the
   whole card gets a soft amber tint instead of just the icon, plus a
   single glow pulse rather than a repeating animation. */
.engage-toast.variant-anniv {
  background: linear-gradient(135deg, color-mix(in srgb, var(--ic-pin) 12%, var(--panel2)), var(--panel2) 65%);
  border-color: color-mix(in srgb, var(--ic-pin) 28%, var(--line));
}
.review-toast-icon.variant-anniv { color: var(--ic-pin); background: color-mix(in srgb, var(--ic-pin) 20%, var(--accent-wash)); position: relative; }
.review-toast-icon.variant-anniv::after {
  content: ''; position: absolute; inset: -6px; border-radius: calc(var(--control-radius) + 3px);
  background: radial-gradient(circle, color-mix(in srgb, var(--ic-pin) 40%, transparent), transparent 72%);
  animation: engage-glow 2.2s ease-in-out 1;
}
@keyframes engage-glow { 0% { opacity: 0; transform: scale(.7); } 35% { opacity: 1; transform: scale(1.15); } 100% { opacity: 0; transform: scale(1.3); } }

/* 5 — quiet weekly recap: deliberately un-badged and unanimated, a plain
   stats row instead of an icon+copy pair — this one isn't trying to be a
   celebration, just a mirror. */
.engage-toast.variant-recap { padding-bottom: 10px; }
.engage-recap-head { display: flex; align-items: center; justify-content: space-between; }
.engage-recap-head .review-toast-title {
  font-size: var(--fs-meta); font-weight: 700; color: var(--muted);
  text-transform: var(--label-case); letter-spacing: var(--tracking-label);
}
.engage-recap-stats { display: flex; border-top: 1px solid var(--line-soft); padding-top: 8px; margin-top: 8px; }
.engage-recap-stat { flex: 1; text-align: center; }
.engage-recap-stat .n {
  font-size: var(--fs-title); font-weight: 800; font-family: var(--font-display);
  font-variant-numeric: tabular-nums; color: var(--ink);
}
.engage-recap-stat .k { font-size: var(--fs-meta); color: var(--muted); text-transform: var(--label-case); letter-spacing: var(--tracking-label); margin-top: 1px; }

@media (prefers-reduced-motion: reduce) {
  .engage-toast, .review-toast-icon.variant-tick, .review-toast-icon.variant-flame::after,
  .review-toast-icon.variant-anniv::after, .engage-ring { animation: none; }
}
