/* ── Reset ── */
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }

/* ── Design tokens ──
   The palette is MyCal's, so the two apps read as one product: the five names
   MyNotes owns and MyCal re-exports — --fg, --muted, --primary, --link,
   --danger — carry the same values here, and the rest of the ramp is the same
   Tailwind grey/blue one MyCal derives from them.

   Below the ramp, MyMail's own long-standing token names (--topbar-bg,
   --list-item-hover, …) are resolved onto it rather than deleted: ~700 rules
   already reference them, and keeping them means a colour is still changed in
   exactly one place. Note --text-muted is MyMail's *faintest* step, one below
   --text-secondary; MyCal spells that step --text-faint.

   --link and --muted carry their shared values even though no rule here reads
   them yet: they are two of the canonical five, and the set is only useful as a
   set. */
:root {
  /* Tells the browser which palette to draw native widgets (form controls,
     scrollbars, date pickers) from; without it a dark theme still gets
     light-mode controls. */
  color-scheme: light;

  /* MyNotes' canonical five */
  --fg: #1f2937;
  --muted: #6b7280;
  --primary: #2563eb;
  --link: #2563eb;
  --danger: #dc2626;

  --primary-hover: #1d4ed8;

  --bg: #f3f4f6;
  --surface: #ffffff;
  --surface-alt: #f9fafb;
  --border: #e5e7eb;
  --border-light: #f3f4f6;
  --hover-bg: #f3f4f6;
  --hover-bg-light: #f9fafb;
  --accent-hover-bg: #eff6ff;
  --error-bg: #fee2e2;
  --success-bg: #dcfce7;
  --success-color: #16a34a;
  --text-subtle: #6b7280;
  --text-faint: #9ca3af;
  --text-disabled: #9ca3af;

  /* MyMail's names, resolved onto the ramp above */
  --sidebar-bg: var(--surface);
  --sidebar-text: var(--fg);
  --sidebar-muted: var(--text-subtle);
  --sidebar-hover: var(--hover-bg);
  --sidebar-active: var(--accent-hover-bg);
  --sidebar-active-border: var(--primary);
  --sidebar-badge: var(--primary);
  --sidebar-divider: var(--border-light);
  /* Deliberately a step darker than --sidebar-divider: this rule is the top of
     the footer, and the shared MySuite spec ties it to the same colour the two
     buttons below it are outlined in, not to the folder-list divider. */
  --sidebar-footer-border: var(--border);
  --topbar-bg: var(--surface);
  --topbar-border: var(--border);
  --list-bg: var(--bg);
  --list-border: var(--border);
  --list-item-hover: var(--hover-bg-light);
  --list-item-active-bg: var(--accent-hover-bg);
  --list-item-active-border: var(--primary);
  --btn-primary: var(--primary);
  --btn-primary-hover: var(--primary-hover);
  --btn-danger: var(--danger);
  --btn-danger-hover: #b91c1c;
  --btn-success: var(--success-color);
  --btn-success-hover: #15803d;
  --btn-disabled: var(--border);
  --btn-disabled-text: var(--text-disabled);
  --text-primary: var(--fg);
  --text-secondary: #4b5563;
  --text-muted: var(--text-faint);
  --unread-weight: 600;
  --border-radius: 6px;
  --field-border: var(--border);
  --focus-ring: 0 0 0 3px rgba(37,99,235,0.18);
  --app-bg: var(--bg);
  --status-error-bg: var(--error-bg);
  --status-error-text: var(--danger);
  --status-error-border: #fecaca;
  --status-success-bg: var(--success-bg);
  --status-success-border: #bbf7d0;
  --on-color-fg: #ffffff;
  /* Surface colors */
  --surface-bg: var(--surface);
  --surface-alt-bg: var(--surface-alt);
  --compose-actions-bg: var(--surface-alt);
  --field-row-border: var(--border-light);
  /* Warning / info highlight */
  --warning-bg: #fffbeb;
  --warning-border: #fde68a;
  --warning-text: #92400e;
  --highlight-bg: var(--accent-hover-bg);
  --highlight-border: #bfdbfe;
  --highlight-selected-hover: #dbeafe;
  /* Address tags */
  --tag-bg: #dbeafe;
  --tag-border: #bfdbfe;
  --tag-text: #1d4ed8;
  --tag-btn-color: #60a5fa;
  /* Search-snippet highlight */
  --mark-bg: #fef9c3;
  --mark-text: #78350f;
  --overlay-bg: rgba(255, 255, 255, 0.8);
}

/* ── Dark mode ──
   Same attribute MyCal switches on, so a saved preference reads the same in
   both apps and the two never disagree about which theme is showing. */
[data-theme="dark"] {
  color-scheme: dark;

  --fg: #f3f4f6;
  --muted: #9ca3af;
  --primary: #3b82f6;
  --link: #60a5fa;
  --danger: #ef4444;

  --primary-hover: #60a5fa;

  --bg: #111827;
  --surface: #1f2937;
  --surface-alt: #273549;
  --border: #374151;
  --border-light: #2b3644;
  --hover-bg: #374151;
  --hover-bg-light: #273549;
  --accent-hover-bg: #1e3a5f;
  --error-bg: #3f1d1d;
  --success-bg: #14321f;
  --success-color: #22c55e;
  --text-subtle: #9ca3af;
  --text-faint: #6b7280;
  --text-disabled: #6b7280;

  --text-secondary: #d1d5db;
  --btn-danger-hover: #f87171;
  --btn-success-hover: #4ade80;
  --status-error-text: #f87171;
  --status-error-border: #7f1d1d;
  --status-success-border: #14532d;
  --warning-bg: #2a1800;
  --warning-border: #4a2e00;
  --warning-text: #fbbf24;
  --highlight-border: #1e4080;
  --highlight-selected-hover: #1e3a5f;
  --tag-bg: #1e3a5f;
  --tag-border: #1e4080;
  --tag-text: #93c5fd;
  --tag-btn-color: #3b82f6;
  --focus-ring: 0 0 0 3px rgba(59,130,246,0.30);
  --mark-bg: #713f12;
  --mark-text: #fef9c3;
  --overlay-bg: rgba(31, 41, 55, 0.8);
}

/* ── Base ── */
html, body {
  font-family: system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif;
  line-height: 1.5;
  color: var(--text-primary);
  background: var(--app-bg);
}

/* Lucide icons are always either the whole content of an icon-only button or an
   inline run beside a label. Centring them keeps the SVG's baseline from
   leaving a descender gap under the glyph. */
.lucide {
  vertical-align: middle;
  flex-shrink: 0;
}

/* ── App Shell ──
   The sidebar track is in `rem`, not `px`: 13.75rem is 220px at the default
   16px root and identical to the literal it replaced, but it grows with the
   reader's browser font setting. The footer's two buttons are rem-sized by the
   shared MySuite spec, so a px column would have let them outgrow it — Chrome's
   "Large" (20px) and "Very Large" (24px) settings would push Settings over the
   content beside it, which is WCAG 1.4.4. The buttons do not scale purely — their
   padding, border and 16px icons are px — but their text does, and a px column
   would not have moved at all. */
.app {
  display: grid;
  grid-template-rows: auto 1fr auto;
  grid-template-columns: 13.75rem 1fr;
  grid-template-areas:
    "sidebar topbar"
    "sidebar content"
    "sidebar bottombar";
  height: 100vh;
}

/* ── Sidebar ──
   A --surface panel with a --border edge, like MyCal's .calendar-sidebar and
   .left-sidebar, rather than the dark slab this used to be: the whole chrome is
   now drawn from the one shared light/dark ramp. */
.sidebar {
  grid-area: sidebar;
  background: var(--sidebar-bg);
  color: var(--sidebar-text);
  border-right: 1px solid var(--border);
  display: flex;
  flex-direction: column;
  overflow-y: auto;
}

.sidebar-header {
  padding: 14px 16px 12px;
  font-size: 1.1rem;
  font-weight: 600;
  color: var(--text-primary);
  border-bottom: 1px solid var(--border-light);
  display: flex;
  align-items: center;
  gap: 8px;
  flex-shrink: 0;
}

.logo-icon {
  width: 28px; height: 28px;
  background: var(--sidebar-badge);
  color: #fff;
  border-radius: 6px;
  display: flex; align-items: center; justify-content: center;
  flex-shrink: 0;
  /* Opts the badge out of .sidebar-header's own `align-items: center`, and it
     is load-bearing rather than tidy. Without it the badge is centred against
     whichever of it and the app-name label is taller, so its distance from the
     window's top edge is a *remainder* of the label's line box rather than the
     header's padding: it lands on the offset ../mysuite/spec/app-logo.md §4
     mandates only while the badge out-measures the label, and drifts at every
     root font size above that. Measured, not reasoned — see the badge-position
     items in web/AGENTS.md. MyCal and MyNotes each carry this declaration for
     the same reason; MyMail was the last of the three without it. */
  align-self: flex-start;
}

.sidebar-section-label {
  font-size: 0.65rem;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--sidebar-muted);
  padding: 14px 16px 4px;
  flex-shrink: 0;
}

.folder-list { list-style: none; padding: 0 8px 8px; flex-shrink: 0; }

.folder-item a {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 7px 10px;
  border-radius: var(--border-radius);
  color: var(--sidebar-text);
  text-decoration: none;
  font-size: 0.85rem;
  transition: background 0.12s;
  border-left: 3px solid transparent;
}
.folder-item a:hover { background: var(--sidebar-hover); }
.folder-item a:focus-visible { outline: none; box-shadow: var(--focus-ring); }
.folder-item.active a {
  background: var(--sidebar-active);
  border-left-color: var(--sidebar-active-border);
  color: var(--primary);
  font-weight: 600;
}

/* No width of its own: every Lucide icon is the same square, so the labels line
   up on the icons themselves. Colour is inherited, which is what tints the
   active row's icon along with its text. */
.folder-icon { opacity: 0.85; }

.folder-badge {
  margin-left: auto;
  background: var(--sidebar-badge);
  color: #fff;
  font-size: 0.7rem;
  font-weight: 700;
  min-width: 18px;
  height: 18px;
  border-radius: 9px;
  display: flex; align-items: center; justify-content: center;
  padding: 0 5px;
}

.sidebar-reload-btn {
  margin-left: auto;
  background: transparent;
  border: none;
  color: var(--sidebar-muted);
  cursor: pointer;
  line-height: 1;
  padding: 5px 6px;
  border-radius: var(--border-radius);
  transition: background 0.12s, color 0.12s;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
}
.sidebar-reload-btn:hover { background: var(--sidebar-hover); color: var(--text-primary); }
.sidebar-reload-btn:focus-visible { outline: none; box-shadow: var(--focus-ring); }

.sidebar-divider { height: 1px; background: var(--sidebar-divider); margin: 6px 8px; flex-shrink: 0; }

.sidebar-spacer { flex: 1; }

/* One line, always: nowrap plus one-word labels (see ThemeToggle) keeps both
   controls side by side, rather than dropping the wider of them onto a second
   row whenever the theme flips.

   Full-bleed by spec, in all three apps: the 8px the buttons sit in is this
   element's padding, never a margin, so the rule above them spans the whole
   sidebar rather than starting where the buttons start.

   Sticky, because .sidebar-spacer only holds this down while the sidebar fits.
   .sidebar scrolls, and once the folder list is taller than the panel the spacer
   collapses to nothing and this scrolls away with it — measured at 13 user
   folders in an 800px window, which put the buttons 44px below the fold, and at
   40 folders over 1000px below. The shared spec requires them 8px from the
   window's bottom edge in every state, so the footer has to leave the flow when
   the content overflows. `bottom: 0` and not `bottom: 8px`: this element's own
   padding is the 8px, and doubling it would put the buttons at 16.

   The background is not decoration either — without it the folder rows show
   through as they scroll underneath. It must stay equal to the sidebar's own, or
   the footer becomes a visible band. */
.sidebar-footer {
  position: sticky;
  bottom: 0;
  background: var(--sidebar-bg);
  padding: 8px;
  border-top: 1px solid var(--sidebar-footer-border);
  flex-shrink: 0;
  display: flex;
  flex-wrap: nowrap;
  gap: 6px;
}

/* Outlined, and geometrically identical to the same pair in MyCal and MyNotes:
   the three apps share one spec for this footer, so the buttons must measure the
   same in all of them. It is `spec/sidebar-footer.md` in the sibling `mysuite`
   repo (../mysuite), which is where a change to any of this has to start:
   changing any of this is a change in all three repositories, however local the
   edit looks from here. Every number below is that spec, not a local choice —
   including the trailing zero in `0.80rem`, which is the shared value written the
   way all three repos write it, so a grep finds them together. It is the only
   font size spelled that way here — `0.8rem`, the identical computed value in
   ordinary spelling, is what the rest of the file uses — so the distinction is a
   convention and nothing more. Any formatter would collapse it and no test here
   would notice.
   0.80rem over a 1.5 line-height is a 19.2px line box, and 4px of padding plus
   1px of border on each side makes the outer height exactly 29.2px at the
   default 16px root size. Only the text is rem-based; the padding and border are
   px, so at another root size the box does not scale proportionally — 29.2px is
   the agreed reference measurement, not a constant.
   line-height is stated rather than inherited so the height survives a change
   to `body`. The size was set by the narrowest of the three sidebars, not by
   this one: on MyMail's 13.75rem sidebar the pair measures 174px of the 203px
   available, at the default root and in the default UI font. Both scale
   together with the root font size, so that margin only grows. The sibling
   apps' budgets are in the shared spec and deliberately not repeated here — a
   copy of a number that lives in another repo is a copy that goes stale.
   Only this pair is outlined; .sidebar-reload-btn stays a ghost button, being an
   icon-only affordance in the header rather than one of the two the spec covers. */
.sidebar-settings-link {
  display: inline-flex;
  align-items: center;
  /* The pair must not shrink. `flex-wrap: nowrap` on the footer does not prevent
     that — a flex item shrinks before it overflows, and these are saved only by
     `min-width: auto` resolving to the nowrap content width. A `min-width: 0`
     reset reaching them would let the labels silently clip with no ellipsis, so
     overflow is made the only possible failure instead. It is not a local one:
     .sidebar has `overflow-y: auto`, which computes `overflow-x` to `auto` too,
     so the footer overflowing puts a horizontal scrollbar under the whole
     sidebar. Visible, which is the point. */
  flex-shrink: 0;
  gap: 6px;
  padding: 4px 8px;
  border: 1px solid var(--border);
  border-radius: var(--border-radius);
  background: none;
  color: var(--sidebar-muted);
  text-decoration: none;
  font-family: inherit;
  font-size: 0.80rem;
  line-height: 1.5;
  /* These three are no-ops today and pinned anyway: the two controls compute the
     same values from different places, so they match by luck rather than by
     contract. A <button> takes weight and style from the UA `font` shorthand and
     its alignment from a separate UA `text-align: center`, inheriting none of the
     three; the Settings <a> inherits all three from `body`. Anything that ever
     sets a base weight would move one and not the other, and the UA values differ
     between engines besides. text-align is
     `center` because that is what a <button> already computes — it reaches the
     toggle's stacked label, where `start` would shift the shorter word 1px. */
  font-weight: 400;
  font-style: normal;
  text-align: center;
  white-space: nowrap;
  cursor: pointer;
  transition: background 0.12s, color 0.12s, border-color 0.12s;
}
/* The hover border must be a token that differs from --hover-bg in *both*
   themes, or hovering erases the outline: in the dark theme --border and
   --hover-bg are the same #374151, so keeping --border here would fill the
   button with its own border colour. --text-faint is distinct in both. */
.sidebar-settings-link:hover {
  background: var(--sidebar-hover);
  border-color: var(--text-faint);
  color: var(--text-primary);
}
/* A real outline, not this file's usual `outline: none` + --focus-ring shadow.
   That ring composites to 1.288:1 in light and 1.501:1 in dark against the panel
   it sits on, where WCAG 1.4.11 (Non-text Contrast, AA) wants 3:1 of a focus
   indicator — so it replaced a compliant browser outline with a nearly invisible
   one. Raising its alpha cannot fix it: a `box-shadow` with no offset is painted
   directly against the button's own 1px --border, and in dark that border caps
   the achievable contrast at 2.803:1 even with the ring fully opaque.

   `outline-offset` is what does the work. It lifts the outline clear of the
   border, so both of the outline's neighbours are the panel background instead:
   --primary measures 5.169:1 on white and 3.991:1 on #1f2937. 2px also meets
   the minimum indicator area of 2.4.13 (Focus Appearance, AAA) — a 2px
   perimeter — exactly, so do not thin it. The offset plus the outline extend 4px
   outside the border box and .sidebar is a scroll container in both axes, so
   .sidebar-footer's 8px of padding is what keeps them from being cropped: a
   footer padding below 4px would silently start truncating the indicator.

   An outline is painted under forced colours, where a box-shadow is not, so no
   `forced-colors` fallback is needed here — and one that reverted the outline
   would undo this rule rather than help it.

   --focus-ring itself stays: many other rules in this file still use it, and
   they have the same problem — including .folder-item a and .sidebar-reload-btn,
   in this same sidebar, so tabbing down it watches the indicator come and go.
   (Count them when you need the number; a figure written here is one no test
   can hold to.) This
   pair is what the shared MySuite spec covers; fixing the rest is not a
   find-replace, since several of those are inputs in tight containers where a 4px
   outward outline needs the same clearance check this rule got. */
.sidebar-settings-link:focus-visible {
  outline: 2px solid var(--primary);
  outline-offset: 2px;
}

/* ── Top bar ── */
.topbar {
  grid-area: topbar;
  background: var(--topbar-bg);
  border-bottom: 1px solid var(--topbar-border);
  padding: 0 16px;
  display: flex;
  align-items: center;
  gap: 10px;
  height: 48px;
}

.topbar-title {
  font-weight: 600;
  font-size: 0.95rem;
  color: var(--text-primary);
}

/* ── Content ── */
.content {
  grid-area: content;
  overflow: hidden;
  background: var(--list-bg);
}

.placeholder-view {
  display: flex;
  align-items: center;
  justify-content: center;
  height: 100%;
  color: var(--text-muted);
  font-size: 0.95rem;
}

/* ── Bottom bar ── */
.bottombar {
  grid-area: bottombar;
  background: var(--topbar-bg);
  border-top: 1px solid var(--topbar-border);
  padding: 8px 16px;
  display: flex;
  align-items: center;
  gap: 10px;
}

.compose-btn {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 6px 14px;
  background: var(--btn-primary);
  color: #fff;
  border: 1px solid var(--btn-primary);
  border-radius: var(--border-radius);
  font-size: 0.9rem;
  font-family: inherit;
  font-weight: 500;
  cursor: pointer;
  transition: background 0.12s, border-color 0.12s;
  white-space: nowrap;
}
.compose-btn:hover { background: var(--btn-primary-hover); border-color: var(--btn-primary-hover); }
.compose-btn:focus-visible { outline: none; box-shadow: var(--focus-ring); }

.search-bar {
  flex: 1;
  position: relative;
  max-width: 480px;
}
.search-bar input {
  width: 100%;
  padding: 6px 12px 6px 32px;
  border: 1px solid var(--border);
  border-radius: var(--border-radius);
  font-size: 0.9rem;
  font-family: inherit;
  background: var(--surface-bg);
  color: var(--text-primary);
  outline: none;
  transition: border-color 0.15s, box-shadow 0.15s;
}
.search-bar input:focus-visible {
  border-color: var(--btn-primary);
  box-shadow: var(--focus-ring);
}
.search-bar .search-icon {
  position: absolute; left: 10px; top: 50%; transform: translateY(-50%);
  color: var(--text-faint); pointer-events: none;
}

/* ── Folder view ── */
.folder-view {
  display: flex;
  flex-direction: column;
  height: 100%;
  overflow: hidden;
}

.folder-toolbar {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 6px 12px;
  background: var(--topbar-bg);
  border-bottom: 1px solid var(--list-border);
  flex-shrink: 0;
}

.pagination-info {
  font-size: 0.75rem;
  color: var(--text-secondary);
  white-space: nowrap;
}

.bulk-toolbar {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 5px 12px;
  background: var(--highlight-bg);
  border-bottom: 1px solid var(--list-border);
  flex-shrink: 0;
}

.bulk-count {
  font-size: 0.8rem;
  font-weight: 600;
  color: var(--text-secondary);
  white-space: nowrap;
}

.move-select {
  padding: 4px 8px;
  border: 1px solid var(--field-border);
  border-radius: var(--border-radius);
  font-size: 0.8rem;
  color: var(--text-primary);
  background: var(--surface-bg);
  cursor: pointer;
}
.move-select:focus { outline: none; box-shadow: var(--focus-ring); }

.folder-error {
  padding: 8px 16px;
  background: var(--status-error-bg);
  color: var(--status-error-text);
  font-size: 0.8rem;
  border-bottom: 1px solid var(--status-error-border);
  flex-shrink: 0;
}

.folder-status {
  display: flex;
  align-items: center;
  justify-content: center;
  flex: 1;
  color: var(--text-muted);
  font-size: 0.9rem;
}

.folder-empty { font-style: italic; }

/* ── Message list ── */
.msg-list-wrap {
  flex: 1;
  overflow-y: auto;
  background: var(--surface-bg);
}

.msg-table {
  width: 100%;
  border-collapse: collapse;
  table-layout: fixed;
}

.msg-table thead th {
  position: sticky;
  top: 0;
  background: var(--list-bg);
  font-size: 0.7rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--text-muted);
  padding: 6px 8px;
  border-bottom: 1px solid var(--list-border);
  text-align: left;
  z-index: 1;
}

.col-check {
  width: 36px;
  padding-left: 12px !important;
  text-align: center !important;
}
.col-from { width: 200px; }
.col-subject { /* takes remaining space */ }
.col-folder {
  width: 120px;
  white-space: nowrap;
}
/* Scheduled send / snooze expiry — the Scheduled and Snoozed folders only. */
.col-schedule {
  width: 140px;
  white-space: nowrap;
}
.col-date {
  width: 120px;
  text-align: right;
  white-space: nowrap;
}

.msg-row {
  cursor: pointer;
  border-bottom: 1px solid var(--list-border);
  transition: background 0.08s;
}
.msg-row:hover { background: var(--list-item-hover); }
.msg-row:focus-visible { outline: 2px solid var(--primary); outline-offset: -2px; }
.msg-row.selected { background: var(--list-item-active-bg); }
.msg-row.selected:hover { background: var(--highlight-selected-hover); }

.msg-row td {
  padding: 8px 8px;
  font-size: 0.8rem;
  color: var(--text-primary);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.msg-row.unread td { font-weight: var(--unread-weight); }

.msg-row .col-check { text-align: center; }
.msg-row .col-date {
  color: var(--text-secondary);
  text-align: right;
  font-size: 0.75rem;
}
.msg-row.unread .col-date { color: var(--text-primary); }

.col-subject {
  display: table-cell;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.subject-text { margin-right: 4px; }

.msg-badge {
  margin-left: 4px;
  vertical-align: middle;
  color: var(--text-faint);
}

.msg-badge-fail {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 16px;
  height: 16px;
  background: var(--btn-danger);
  color: #fff;
  border-radius: 50%;
  font-size: 0.7rem;
  font-weight: 700;
  vertical-align: middle;
}

/* ── Shared utilities ── */
.btn {
  display: inline-flex; align-items: center; gap: 5px;
  padding: 6px 12px;
  border: 1px solid transparent;
  border-radius: var(--border-radius);
  font-size: 0.85rem;
  font-family: inherit;
  font-weight: 500;
  cursor: pointer;
  transition: background 0.12s, border-color 0.12s, box-shadow 0.12s;
  text-decoration: none;
}
.btn:focus-visible { outline: none; box-shadow: var(--focus-ring); }
.btn-ghost { background: var(--surface); color: var(--text-primary); border-color: var(--border); }
.btn-ghost:hover:not(:disabled) { background: var(--hover-bg); }
.btn-primary { background: var(--btn-primary); color: #fff; border-color: var(--btn-primary); }
.btn-primary:hover:not(:disabled) { background: var(--btn-primary-hover); border-color: var(--btn-primary-hover); }
.btn-danger { background: var(--btn-danger); color: #fff; border-color: var(--btn-danger); }
.btn-danger:hover:not(:disabled) { background: var(--btn-danger-hover); border-color: var(--btn-danger-hover); }
.btn-success { background: var(--btn-success); color: #fff; border-color: var(--btn-success); }
.btn-success:hover:not(:disabled) { background: var(--btn-success-hover); border-color: var(--btn-success-hover); }
/* Grey for every variant, so a button that cannot be pressed reads as such
   without being hovered — the Send buttons in compose and on a draft spend
   most of their life disabled. Comes after the variants so it wins over their
   background, and the :not(:disabled) above keeps hover from lighting it up. */
.btn:disabled {
  background: var(--btn-disabled);
  color: var(--btn-disabled-text);
  border-color: var(--btn-disabled);
  cursor: not-allowed;
}
.btn-sm { padding: 4px 9px; font-size: 0.8rem; }
.btn-icon { padding: 5px 7px; }

.msg-back-to-list { margin-left: -8px; border: none; background: transparent; }

.toolbar-sep { width: 1px; height: 20px; background: var(--list-border); margin: 0 4px; }
.ml-auto { margin-left: auto; }

/* ── Message detail ── */
.msg-detail {
  display: flex;
  flex-direction: column;
  height: 100%;
  overflow-y: auto;
  background: var(--surface-bg);
}

.msg-detail-status {
  display: flex;
  align-items: center;
  justify-content: center;
  flex: 1;
  height: 100%;
  color: var(--text-muted);
  font-size: 0.9rem;
}

.msg-detail-error { color: var(--btn-danger); }
.msg-detail-not-found { color: var(--text-muted); font-style: italic; }

.msg-detail-actions {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 8px 16px;
  background: var(--topbar-bg);
  border-bottom: 1px solid var(--list-border);
  flex-shrink: 0;
  flex-wrap: wrap;
}

.msg-folder-indicator {
  font-size: 0.75rem;
  color: var(--text-muted);
  white-space: nowrap;
}

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

.snooze-panel {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 8px 16px;
  background: var(--highlight-bg);
  border-bottom: 1px solid var(--list-border);
  flex-shrink: 0;
}

.snooze-label {
  font-size: 0.8rem;
  color: var(--text-secondary);
  white-space: nowrap;
}

.snooze-input {
  padding: 4px 8px;
  border: 1px solid var(--field-border);
  border-radius: var(--border-radius);
  font-size: 0.8rem;
  color: var(--text-primary);
}
.snooze-input:focus { outline: none; box-shadow: var(--focus-ring); }

.snooze-until-display {
  font-size: 0.8rem;
  color: var(--text-secondary);
  white-space: nowrap;
}

.msg-detail-header {
  padding: 12px 16px 8px;
  border-bottom: 1px solid var(--list-border);
  flex-shrink: 0;
}

.msg-detail-field {
  display: flex;
  align-items: baseline;
  gap: 8px;
  padding: 3px 0;
  font-size: 0.85rem;
}

.msg-detail-label {
  font-weight: 600;
  color: var(--text-muted);
  font-size: 0.7rem;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  min-width: 56px;
  flex-shrink: 0;
}

.msg-detail-value {
  color: var(--text-primary);
  word-break: break-word;
  display: flex;
  align-items: center;
  gap: 6px;
}

.msg-detail-subject {
  font-weight: 600;
  font-size: 0.95rem;
}

.msg-detail-attachments {
  align-items: flex-start;
  margin-top: 4px;
}

.attachment-list {
  list-style: none;
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  padding: 0;
}

.attachment-link {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 4px 10px;
  background: var(--list-bg);
  border: 1px solid var(--list-border);
  border-radius: var(--border-radius);
  color: var(--text-primary);
  text-decoration: none;
  font-size: 0.8rem;
  transition: background 0.1s;
}
.attachment-link:hover { background: var(--list-item-hover); }

.attachment-size {
  color: var(--text-muted);
  font-size: 0.7rem;
}

.import-cal-btn {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 4px 10px;
  background: var(--list-bg);
  border: 1px solid var(--list-border);
  border-radius: var(--border-radius);
  color: var(--text-primary);
  font-size: 0.8rem;
  cursor: pointer;
  transition: background 0.1s;
  margin-left: 4px;
}
.import-cal-btn:hover:not(:disabled) { background: var(--list-item-hover); }
.import-cal-btn:disabled { opacity: 0.7; cursor: default; }

/* A calendar link found in the body wears .attachment-link's chrome without
   being one — it is a URL to read, not to follow — so the hover the real
   download links carry is undone here.

   Stacked rather than side by side: the URL is shown in full and never
   truncated (its query commonly carries the ids the endpoint needs, and the
   point of showing it is to be read before clicking), so it is routinely long
   enough to wrap over several lines. */
.attachment-link-static {
  cursor: default;
  flex-direction: column;
  align-items: flex-start;
  gap: 2px;
  max-width: 60ch;
}
.attachment-link-static:hover { background: var(--list-bg); }

.calendar-link-row {
  display: flex;
  align-items: flex-start;
  flex-wrap: wrap;
  gap: 4px;
}

/* Both halves are sender-controlled and can be arbitrarily long, so they break
   rather than widening the row. */
.calendar-link-label,
.calendar-link-url {
  overflow-wrap: anywhere;
  max-width: 100%;
}

.import-cal-error {
  color: var(--danger);
  font-size: 0.75rem;
  margin-left: 4px;
}

.msg-headers-panel {
  border-bottom: 1px solid var(--list-border);
  background: var(--list-bg);
  flex-shrink: 0;
  max-height: 300px;
  overflow-y: auto;
}

.msg-headers-loading {
  padding: 8px 16px;
  font-size: 0.8rem;
  color: var(--text-muted);
}

.msg-headers-pre {
  margin: 0;
  padding: 8px 16px;
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 0.75rem;
  line-height: 1.5;
  color: var(--text-primary);
  white-space: pre-wrap;
  word-break: break-all;
}

.body-toggle {
  position: relative;
  display: flex;
  align-items: center;
  gap: 6px;
  flex-shrink: 0;
  font-size: 0.8rem;
}

.body-toggle-control {
  display: flex;
  position: relative;
  cursor: pointer;
}

.body-toggle input {
  z-index: 1;
  cursor: pointer;
  position: absolute;
  width: 36px;
  height: 22px;
  left: 0;
  top: 0;
  opacity: 0;
  margin: 0;
}

.body-toggle-track {
  width: 36px;
  height: 22px;
  border: 1px solid var(--text-secondary);
  border-radius: 11px;
  background: var(--surface);
  position: relative;
}

.body-toggle-track::before {
  content: '';
  position: absolute;
  width: 16px;
  height: 16px;
  top: 2px;
  left: 2px;
  border-radius: 50%;
  background: var(--text-primary);
  transition: transform 120ms;
}

.body-toggle input:checked + .body-toggle-track::before {
  transform: translateX(14px);
}

.body-toggle input:focus-visible + .body-toggle-track {
  box-shadow: var(--focus-ring);
}

.btn.active {
  background: var(--list-item-active-bg);
  border-color: var(--sidebar-active-border);
  color: var(--btn-primary);
  font-weight: 600;
}

.external-images-bar {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 6px 16px;
  background: var(--warning-bg);
  border-bottom: 1px solid var(--warning-border);
  font-size: 0.8rem;
  color: var(--text-secondary);
  flex-shrink: 0;
}

.msg-detail-body {
  flex: 1;
  display: flex;
  flex-direction: column;
  min-height: 0;
  max-width: 900px;
  /* Warnings and the body must scroll above the thread, even when the divider
     leaves less room than the warnings or the iframe's minimum height. */
  overflow: auto;
}

.body-iframe {
  width: 100%;
  min-height: 200px;
  border: none;
  flex: 1;
  display: block;
}

.body-text {
  flex: 1;
  padding: 16px;
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 0.8rem;
  line-height: 1.6;
  color: var(--text-primary);
  white-space: pre-wrap;
  word-break: break-word;
  overflow-y: auto;
  background: var(--surface-bg);
}

/* Keep a usable text viewport when the warnings need the body's outer scroller. */
.msg-detail-body > .body-text { min-height: 200px; }

/* ── Thread strip ── */
.thread-resizing .body-iframe { pointer-events: none; }

.thread-resize-handle {
  height: 5px;
  background: var(--list-border);
  cursor: ns-resize;
  flex-shrink: 0;
  transition: background 0.15s;
}
.thread-resize-handle:hover,
.thread-resize-handle:active {
  background: var(--btn-primary);
}

.thread-strip {
  background: var(--list-bg);
  flex-shrink: 0;
  max-height: 40%;
  display: flex;
  flex-direction: column;
  overflow: hidden;
}

.thread-strip-header {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 8px 16px 6px;
  font-size: 0.75rem;
  font-weight: 600;
  color: var(--text-muted);
  text-transform: uppercase;
  letter-spacing: 0.04em;
  border-bottom: 1px solid var(--list-border);
}

.thread-truncated {
  color: var(--btn-danger);
  font-weight: 400;
  text-transform: none;
  letter-spacing: 0;
}

.thread-list {
  list-style: none;
  padding: 0;
  margin: 0;
  overflow-y: auto;
  flex: 1;
}

.thread-entry {
  border-bottom: 1px solid var(--list-border);
}
.thread-entry:last-child { border-bottom: none; }

.thread-entry-row {
  display: flex;
  align-items: stretch;
}

.thread-entry-btn {
  display: flex;
  align-items: center;
  gap: 10px;
  flex: 1;
  min-width: 0;
  padding: 8px 16px;
  background: transparent;
  border: none;
  cursor: pointer;
  text-align: left;
  font-size: 0.8rem;
  color: var(--text-primary);
  transition: background 0.08s;
}
.thread-entry-btn:hover:not(:disabled) { background: var(--list-item-hover); }
.thread-entry-btn:focus-visible { outline: none; box-shadow: var(--focus-ring); }

.thread-open-btn {
  align-self: center;
  flex-shrink: 0;
  margin-right: 16px;
  visibility: hidden;
}
/* Revealed on hover, and on focus so it stays keyboard-reachable. */
.thread-entry-row:hover .thread-open-btn,
.thread-entry-row:focus-within .thread-open-btn { visibility: visible; }
/* Nothing hovers on a touch screen, so there it is always shown. */
@media (hover: none) {
  .thread-open-btn { visibility: visible; }
}
/* The current message is already open, so its button never shows — it is there
   only to reserve the column. Last, and specific enough to beat both above. */
.thread-current .thread-entry-row .thread-open-btn { visibility: hidden; }

.thread-current .thread-entry-btn {
  background: var(--list-item-active-bg);
  border-left: 3px solid var(--sidebar-active-border);
  cursor: default;
}

/* Keep Junk/Trash visibly distinct without dimming their warning labels or bodies. */
.thread-excluded-folder .thread-from {
  font-weight: 400;
  color: var(--text-secondary);
}

.thread-folder-label {
  flex-shrink: 0;
  padding: 1px 6px;
  border: 1px solid currentColor;
  border-radius: 4px;
  font-weight: 600;
}

.thread-from {
  font-weight: 600;
  min-width: 140px;
  max-width: 200px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  flex-shrink: 0;
}

.thread-subject {
  flex: 1;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  color: var(--text-secondary);
}

.thread-date {
  font-size: 0.75rem;
  color: var(--text-muted);
  white-space: nowrap;
  flex-shrink: 0;
}

.thread-unread-dot {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--btn-primary);
  flex-shrink: 0;
}

.thread-expanded {
  padding: 0 16px 12px;
  background: var(--surface-bg);
  border-top: 1px solid var(--list-border);
}

.thread-expanded-meta {
  display: flex;
  align-items: baseline;
  gap: 8px;
  padding: 8px 0 6px;
  font-size: 0.8rem;
  flex-wrap: wrap;
}

.thread-expanded-sep {
  width: 1px;
  height: 14px;
  background: var(--list-border);
  margin: 0 4px;
  align-self: center;
}

.thread-expanded-status {
  padding: 12px 0;
  color: var(--text-muted);
  font-size: 0.8rem;
}

/* ── Compose Form ── */
.compose-loading {
  display: flex; align-items: center; justify-content: center;
  flex: 1; height: 100%; color: var(--text-muted); font-size: 0.9rem;
}

.compose-loading-overlay {
  position: absolute; inset: 0; background: var(--overlay-bg);
  display: flex; align-items: center; justify-content: center;
  color: var(--text-muted); font-size: 0.9rem; z-index: 10;
}

.compose-form {
  display: flex; flex-direction: column; height: 100%; overflow: hidden;
  background: var(--surface-bg); position: relative;
}

.compose-fields {
  flex-shrink: 0;
  border-bottom: 1px solid var(--list-border);
}

.cf-field-row {
  display: grid;
  grid-template-columns: 80px 1fr auto;
  align-items: flex-start;
  border-bottom: 1px solid var(--field-row-border);
  min-height: 40px;
}
.cf-field-row:last-child { border-bottom: none; }

.cf-field-label {
  font-size: 0.7rem; font-weight: 600; color: var(--text-muted);
  text-transform: uppercase; letter-spacing: 0.04em;
  padding: 11px 8px 0 16px; text-align: right; white-space: nowrap; flex-shrink: 0;
}

.cf-field-input {
  padding: 8px 0; align-self: center;
}
.cf-field-input select {
  border: none; background: transparent; font-size: 0.85rem;
  color: var(--text-primary); outline: none; cursor: pointer; width: 100%; padding: 0;
}

.cf-field-actions {
  padding: 6px 10px; display: flex; gap: 4px; align-items: center; flex-shrink: 0;
}

.cf-toggle-btn {
  font-size: 0.75rem; color: var(--btn-primary); cursor: pointer;
  padding: 3px 6px; border-radius: var(--border-radius); border: none; background: none;
  transition: background 0.1s;
}
.cf-toggle-btn:hover { background: var(--highlight-bg); }

/* Address field / autocomplete */
.cf-autocomplete-wrap { position: relative; flex: 1; }

.cf-tags-input {
  display: flex; flex-wrap: wrap; gap: 4px; align-items: center;
  padding: 6px 0; min-height: 40px; cursor: text;
}
.cf-tags-input input {
  border: none; outline: none; font-size: 0.85rem; min-width: 120px;
  flex: 1; background: transparent; padding: 2px 0;
}

.cf-addr-tag {
  display: inline-flex; align-items: center; gap: 4px;
  background: var(--tag-bg); border: 1px solid var(--tag-border); border-radius: 4px;
  padding: 2px 6px 2px 8px; font-size: 0.8rem; color: var(--tag-text);
}
.cf-addr-tag button {
  background: none; border: none; cursor: pointer; color: var(--tag-btn-color);
  font-size: 0.9rem; line-height: 1; padding: 0;
}
.cf-addr-tag button:hover { color: var(--tag-text); }

.cf-autocomplete-dropdown {
  position: absolute; top: calc(100% + 2px); left: 0; right: 0;
  background: var(--surface-bg); border: 1px solid var(--list-border); border-radius: var(--border-radius);
  box-shadow: 0 4px 16px rgba(0,0,0,0.12); z-index: 100; overflow: hidden;
}

.cf-ac-item {
  display: flex; align-items: center; gap: 8px; padding: 8px 12px;
  cursor: pointer; font-size: 0.8rem; transition: background 0.1s;
}
.cf-ac-item:hover, .cf-ac-item.selected { background: var(--list-item-hover); }
.cf-ac-name { font-weight: 500; color: var(--text-primary); }
.cf-ac-addr { font-size: 0.75rem; color: var(--text-muted); margin-left: 4px; }
.cf-ac-hint { padding: 6px 12px; font-size: 0.75rem; color: var(--text-muted); font-style: italic; }

.cf-subject-input {
  padding: 9px 0; font-size: 0.95rem; font-weight: 600; color: var(--text-primary);
  border: none; outline: none; width: 100%; background: transparent;
}
.cf-subject-input::placeholder { color: var(--text-muted); font-weight: 400; }

/* Quill editor area */
.compose-editor-wrap {
  flex: 1; overflow: hidden; display: flex; flex-direction: column; min-height: 0;
}
.compose-editor-wrap .ql-container {
  flex: 1; overflow-y: auto; font-family: inherit; font-size: 0.9rem;
  line-height: 1.7; border: none;
}
.compose-editor-wrap .ql-toolbar {
  border-left: none; border-right: none; border-top: none;
  background: var(--surface-alt-bg); flex-shrink: 0;
}
.compose-editor-wrap .ql-editor {
  padding: 16px 20px; min-height: 180px;
}

/* Quoted material (read-only, held outside the editor) */
.compose-quote {
  border-top: 1px solid var(--list-border);
  background: var(--surface-alt-bg); flex-shrink: 0;
  max-height: 40%; overflow-y: auto;
}
.compose-quote-bar {
  display: flex; align-items: center; gap: 8px;
  padding: 4px 12px; position: sticky; top: 0;
  background: var(--surface-alt-bg);
}
.compose-quote-note {
  flex: 1; font-size: 0.75rem; color: var(--text-muted);
}
.compose-quote-preview {
  margin: 0; padding: 0 20px 12px;
  font-size: 0.8rem; line-height: 1.6; color: var(--text-secondary);
  white-space: pre-wrap; overflow-wrap: anywhere;
}

/* Attachments */
.compose-attachments {
  display: flex; flex-wrap: wrap; gap: 6px;
  padding: 8px 16px; border-top: 1px solid var(--list-border);
  background: var(--surface-alt-bg); flex-shrink: 0;
}
.cf-attached-file {
  display: inline-flex; align-items: center; gap: 5px;
  background: var(--surface-bg); border: 1px solid var(--list-border);
  border-radius: var(--border-radius); padding: 4px 8px;
  font-size: 0.75rem; color: var(--text-secondary);
}
.cf-attached-file button {
  background: none; border: none; color: var(--text-muted);
  cursor: pointer; font-size: 0.9rem; padding: 0; line-height: 1;
}
.cf-attached-file button:hover { color: var(--btn-danger); }
.cf-new-attach { border-color: var(--tag-border); background: var(--tag-bg); color: var(--tag-text); }
.cf-attach-size { color: var(--text-muted); font-size: 0.7rem; }

/* Send later panel */
.compose-send-later {
  display: flex; align-items: center; gap: 12px;
  padding: 10px 16px; border-top: 1px solid var(--list-border);
  background: var(--warning-bg); flex-shrink: 0; font-size: 0.8rem;
}
.compose-send-later label { font-weight: 500; color: var(--warning-text); }
.compose-send-later input[type="datetime-local"] {
  padding: 5px 8px; border: 1px solid var(--warning-border); border-radius: var(--border-radius);
  font-size: 0.8rem; background: var(--surface-bg); color: var(--text-primary); outline: none;
}

/* Send error */
.compose-send-error {
  padding: 8px 16px; background: var(--status-error-bg); color: var(--status-error-text);
  font-size: 0.8rem; border-top: 1px solid var(--status-error-border); flex-shrink: 0;
}

/* Bottom actions bar */
.compose-actions {
  display: flex; align-items: center; gap: 8px;
  padding: 10px 16px; border-top: 1px solid var(--list-border);
  background: var(--compose-actions-bg); flex-shrink: 0;
}
.compose-save-status {
  font-size: 0.75rem; color: var(--text-muted); font-style: italic; margin-left: 4px;
}
.cf-attach-btn { cursor: pointer; }

/* ── Search view ── */
.search-view {
  display: flex;
  flex-direction: column;
  height: 100%;
  overflow: hidden;
}

.search-form {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 8px 12px;
  background: var(--topbar-bg);
  border-bottom: 1px solid var(--list-border);
  flex-shrink: 0;
  flex-wrap: wrap;
}

.search-query-input {
  flex: 1;
  min-width: 160px;
  padding: 6px 10px;
  border: 1px solid var(--field-border);
  border-radius: var(--border-radius);
  font-size: 0.8rem;
  color: var(--text-primary);
  background: var(--surface-bg);
}
.search-query-input:focus { outline: none; box-shadow: var(--focus-ring); border-color: var(--btn-primary); }

/* .search-sort-select sits in the results toolbar rather than the form — it
   orders the result set instead of narrowing it — but is the same control.
   Padding is the one thing they do not share, so it is set per selector below
   rather than here and overridden: an override would work only as long as
   nothing reorders the two rules. */
.search-folder-select,
.search-sort-select {
  border: 1px solid var(--field-border);
  border-radius: var(--border-radius);
  font-size: 0.8rem;
  background: var(--surface-bg);
  color: var(--text-primary);
  cursor: pointer;
}
.search-folder-select { padding: 5px 8px; }
/* Tighter: the toolbar is sized for buttons, not for form fields. */
.search-sort-select { padding: 3px 6px; }

.search-folder-select:focus,
.search-sort-select:focus { outline: none; box-shadow: var(--focus-ring); }

/* Label + control, kept on one line so .search-form's wrap never separates them. */
.search-field {
  display: flex;
  align-items: center;
  gap: 6px;
}

.search-field-label {
  font-size: 0.75rem;
  color: var(--text-muted);
  white-space: nowrap;
}

.search-date-input,
.search-addr-input {
  padding: 5px 8px;
  border: 1px solid var(--field-border);
  border-radius: var(--border-radius);
  font-size: 0.8rem;
  background: var(--surface-bg);
  color: var(--text-primary);
}
.search-date-input:focus,
.search-addr-input:focus { outline: none; box-shadow: var(--focus-ring); }

/* Narrower than the query box, and allowed to shrink first when the row wraps. */
.search-addr-input {
  flex: 0 1 150px;
  min-width: 110px;
}

.search-blank { flex: 1; }

/* ── Snippet display ── */
.has-snippets .msg-row .col-subject {
  white-space: normal;
  overflow: visible;
  text-overflow: initial;
}

.msg-row .subject-line {
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.msg-snippet {
  display: block;
  white-space: normal;
  font-size: 0.75rem;
  color: var(--text-muted);
  font-weight: 400;
  margin-top: 2px;
  overflow: hidden;
  max-height: 2.8em;
  line-height: 1.4;
}

.msg-row.unread .msg-snippet { font-weight: 400; }

.snippet-mark {
  background: var(--mark-bg);
  color: var(--mark-text);
  border-radius: 2px;
  padding: 0 1px;
}

/* ── Global toast ── */
.toast-container {
  position: fixed;
  bottom: 16px;
  right: 16px;
  display: flex;
  flex-direction: column;
  gap: 8px;
  z-index: 9000;
  max-width: 360px;
  pointer-events: none;
}

.toast-item {
  display: flex;
  align-items: center;
  gap: 10px;
  background: var(--fg);
  color: var(--bg);
  padding: 10px 12px;
  border-radius: var(--border-radius);
  font-size: 0.8rem;
  box-shadow: 0 4px 16px rgba(0,0,0,0.25);
  pointer-events: all;
  animation: toast-in 0.18s ease;
}

.toast-persistent {
  border-left: 3px solid var(--btn-danger);
}

@keyframes toast-in {
  from { opacity: 0; transform: translateY(8px); }
  to   { opacity: 1; transform: translateY(0); }
}

.toast-message { flex: 1; line-height: 1.4; }

.toast-btns {
  display: flex;
  align-items: center;
  gap: 6px;
  flex-shrink: 0;
}

.toast-retry-btn {
  padding: 3px 9px;
  background: var(--btn-primary);
  color: #fff;
  border: none;
  border-radius: var(--border-radius);
  font-size: 0.75rem;
  font-weight: 600;
  cursor: pointer;
  transition: background 0.12s;
}
.toast-retry-btn:hover { background: var(--btn-primary-hover); }

/* The toast paints its own inverted surface, so these follow the toast's text
   colour rather than the page's. */
.toast-close-btn {
  display: inline-flex;
  align-items: center;
  background: none;
  border: none;
  color: inherit;
  opacity: 0.65;
  cursor: pointer;
  line-height: 1;
  padding: 2px 4px;
  transition: opacity 0.12s;
}
.toast-close-btn:hover { opacity: 1; }

/* ── Settings Page ── */
.settings-page {
  display: flex;
  flex-direction: column;
  height: 100%;
  overflow: hidden;
  background: var(--list-bg);
}

.settings-tabs {
  display: flex;
  background: var(--topbar-bg);
  border-bottom: 1px solid var(--list-border);
  padding: 0 16px;
  flex-shrink: 0;
  overflow-x: auto;
}

.settings-tab {
  padding: 10px 16px;
  border: none;
  background: none;
  border-bottom: 2px solid transparent;
  font-size: 0.85rem;
  font-weight: 500;
  color: var(--text-secondary);
  cursor: pointer;
  margin-bottom: -1px;
  white-space: nowrap;
  transition: color 0.12s, border-color 0.12s;
}
.settings-tab:hover { color: var(--text-primary); }
.settings-tab:focus-visible { outline: none; box-shadow: var(--focus-ring); }
.settings-tab.active {
  color: var(--btn-primary);
  border-bottom-color: var(--btn-primary);
  font-weight: 600;
}

.settings-content {
  flex: 1;
  overflow-y: auto;
  padding: 20px 24px;
  max-width: 700px;
}

.settings-toolbar {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-bottom: 12px;
  flex-wrap: wrap;
}

.settings-search-form {
  display: flex;
  align-items: center;
  gap: 6px;
  flex: 1;
  min-width: 180px;
}

.settings-search-input {
  flex: 1;
  padding: 5px 10px;
  border: 1px solid var(--field-border);
  border-radius: var(--border-radius);
  font-size: 0.8rem;
  color: var(--text-primary);
  background: var(--topbar-bg);
  min-width: 0;
}
.settings-search-input:focus { outline: none; box-shadow: var(--focus-ring); border-color: var(--btn-primary); }

.settings-item {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 10px 12px;
  border: 1px solid var(--list-border);
  border-radius: var(--border-radius);
  background: var(--topbar-bg);
  margin-bottom: 6px;
  transition: border-color 0.1s, background 0.1s;
}
.settings-item:last-child { margin-bottom: 0; }
.settings-item.drag-over {
  border-color: var(--btn-primary);
  background: var(--list-item-active-bg);
}

.settings-drag-handle {
  color: var(--text-muted);
  cursor: grab;
  flex-shrink: 0;
  user-select: none;
}
.settings-drag-handle:active { cursor: grabbing; }

.settings-item-info {
  flex: 1;
  min-width: 0;
}

.settings-item-name {
  font-weight: 600;
  font-size: 0.85rem;
  color: var(--text-primary);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.settings-item-meta {
  font-size: 0.8rem;
  color: var(--text-secondary);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  margin-top: 1px;
}

.contact-provenance {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex: 0 0 16px;
  height: 16px;
  color: var(--text-secondary);
}

.settings-badge {
  display: inline-flex;
  align-items: center;
  font-size: 0.7rem;
  font-weight: 600;
  padding: 2px 7px;
  border-radius: 10px;
  background: var(--sidebar-badge);
  color: var(--on-color-fg);
  flex-shrink: 0;
}

.settings-form {
  border: 1px solid var(--list-border);
  border-radius: var(--border-radius);
  padding: 16px;
  background: var(--surface-bg);
  margin-bottom: 8px;
}

.settings-field {
  margin-bottom: 12px;
}
.settings-field:last-of-type { margin-bottom: 0; }

.settings-field > label {
  display: block;
  font-size: 0.7rem;
  font-weight: 600;
  color: var(--text-muted);
  text-transform: uppercase;
  letter-spacing: 0.04em;
  margin-bottom: 4px;
}

.settings-field input[type="text"],
.settings-field input[type="email"],
.settings-field input[type="number"],
.settings-field select,
.settings-field textarea {
  width: 100%;
  padding: 7px 10px;
  border: 1px solid var(--field-border);
  border-radius: var(--border-radius);
  font-size: 0.85rem;
  color: var(--text-primary);
  background: var(--topbar-bg);
  font-family: inherit;
}
.settings-field input:focus,
.settings-field select:focus,
.settings-field textarea:focus {
  outline: none;
  box-shadow: var(--focus-ring);
  border-color: var(--btn-primary);
}
.settings-field textarea {
  resize: vertical;
  min-height: 80px;
  line-height: 1.5;
  font-size: 0.8rem;
}

.settings-field-check {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-bottom: 12px;
}
.settings-field-check label {
  font-size: 0.85rem;
  color: var(--text-primary);
  cursor: pointer;
}
.settings-field-check input[type="checkbox"] {
  width: 15px;
  height: 15px;
  cursor: pointer;
  flex-shrink: 0;
}

.settings-form-actions {
  display: flex;
  gap: 8px;
  margin-top: 14px;
}

.settings-error {
  padding: 8px 12px;
  background: var(--status-error-bg);
  color: var(--status-error-text);
  font-size: 0.8rem;
  border-radius: var(--border-radius);
  margin-bottom: 12px;
  border: 1px solid var(--status-error-border);
}

.settings-success {
  padding: 8px 12px;
  background: var(--status-success-bg);
  color: var(--btn-success);
  font-size: 0.8rem;
  border-radius: var(--border-radius);
  margin-bottom: 12px;
  border: 1px solid var(--status-success-border);
}

.settings-empty {
  padding: 24px;
  text-align: center;
  color: var(--text-muted);
  font-size: 0.8rem;
  font-style: italic;
}

.settings-loading {
  padding: 24px;
  text-align: center;
  color: var(--text-muted);
  font-size: 0.8rem;
}

.settings-pagination {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-top: 12px;
}

.settings-pagination-info {
  flex: 1;
  font-size: 0.75rem;
  color: var(--text-muted);
  text-align: center;
}

/* Spam filter */
.spam-filter-form {
  background: var(--topbar-bg);
  border: 1px solid var(--list-border);
  border-radius: var(--border-radius);
  padding: 20px;
}

.settings-meta-arrow {
  color: var(--text-faint);
  margin: 0 1px;
}

/* Filter with broken folder reference */
.filter-folder-missing {
  color: var(--btn-danger);
  font-weight: 600;
}

/* Preferences */
.pref-row {
  display: flex;
  align-items: center;
  gap: 16px;
  padding: 14px 0;
  border-bottom: 1px solid var(--list-border);
}
.pref-row:last-child { border-bottom: none; }

.pref-row-info { flex: 1; }

.pref-label {
  font-size: 0.85rem;
  font-weight: 500;
  color: var(--text-primary);
}

.pref-description {
  font-size: 0.75rem;
  color: var(--text-muted);
  margin-top: 2px;
}

.pref-toggle {
  position: relative;
  width: 40px;
  height: 22px;
  flex-shrink: 0;
}
.pref-toggle input {
  opacity: 0;
  width: 0;
  height: 0;
  position: absolute;
}
.pref-toggle-track {
  position: absolute;
  inset: 0;
  border-radius: 11px;
  background: var(--field-border);
  cursor: pointer;
  transition: background 0.2s;
}
.pref-toggle input:checked + .pref-toggle-track { background: var(--btn-primary); }
.pref-toggle-track::after {
  content: '';
  position: absolute;
  top: 3px; left: 3px;
  width: 16px; height: 16px;
  border-radius: 50%;
  background: var(--on-color-fg);
  transition: transform 0.2s;
  box-shadow: 0 1px 3px rgba(0,0,0,0.2);
}
.pref-toggle input:checked + .pref-toggle-track::after { transform: translateX(18px); }
.pref-toggle input:focus-visible + .pref-toggle-track { box-shadow: var(--focus-ring); }

.pref-radio-group {
  display: flex;
  gap: 6px;
  flex-wrap: wrap;
}

.pref-radio-btn {
  padding: 5px 12px;
  border: 1px solid var(--field-border);
  border-radius: var(--border-radius);
  font-size: 0.8rem;
  background: var(--topbar-bg);
  color: var(--text-secondary);
  cursor: pointer;
  transition: border-color 0.1s, background 0.1s, color 0.1s;
}
.pref-radio-btn:hover { background: var(--list-item-hover); }
.pref-radio-btn:focus-visible { outline: none; box-shadow: var(--focus-ring); }
.pref-radio-btn.active {
  border-color: var(--btn-primary);
  background: var(--list-item-active-bg);
  color: var(--btn-primary);
  font-weight: 600;
}

.pref-text-input {
  padding: 6px 10px;
  border: 1px solid var(--field-border);
  border-radius: var(--border-radius);
  font-size: 0.8rem;
  color: var(--text-primary);
  background: var(--topbar-bg);
  font-family: inherit;
  min-width: 220px;
}
.pref-text-input:focus {
  outline: none;
  box-shadow: var(--focus-ring);
  border-color: var(--btn-primary);
}
/* A column number needs three digits, not the width of a URL. */
.pref-number-input {
  min-width: 0;
  width: 90px;
}

/* ── Demo mode ── */
/* Shown only in a backend-less demo build (mymail -demo-server / -demo-bundle),
   so that nothing here can be mistaken for a real mailbox. */
.demo-badge {
  margin-left: auto;
  font-size: 0.75rem;
  color: var(--text-secondary);
  background: var(--list-item-active-bg);
  border: 1px solid var(--list-item-active-border);
  border-radius: var(--border-radius);
  padding: 3px 8px;
  white-space: nowrap;
}

/* ── Dialogs ── */
/* One overlay and one card for every modal in the app: the demo notice, and the
   confirmations that replaced window.confirm. Their buttons are ordinary .btn
   variants, so a dialog's Delete looks like Delete everywhere else. */
.dialog-overlay {
  position: fixed;
  inset: 0;
  /* Above .toast-container (9000), which sets pointer-events on its buttons —
     otherwise a persistent network-error toast's Retry stays clickable behind
     a dialog that claims aria-modal="true". */
  z-index: 9500;
  background: rgba(0, 0, 0, 0.4);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 16px;
}

.dialog {
  background: var(--topbar-bg);
  border: 1px solid var(--topbar-border);
  border-radius: var(--border-radius);
  box-shadow: 0 10px 30px rgba(15, 23, 42, 0.35);
  max-width: 460px;
  /* The demo notice is three paragraphs; on a short viewport it scrolls rather
     than running off the card. */
  max-height: calc(100vh - 32px);
  overflow-y: auto;
  padding: 20px;
}

.dialog-title {
  font-size: 1rem;
  color: var(--text-primary);
  margin-bottom: 12px;
}

.dialog-body p {
  font-size: 0.8rem;
  line-height: 1.5;
  color: var(--text-secondary);
  margin-bottom: 10px;
}

.dialog-actions {
  display: flex;
  justify-content: flex-end;
  gap: 8px;
  margin-top: 16px;
}

/* Device consent must keep requester details readable on narrow screens. */
.device-approval { margin-top: 1.5rem; }
.device-approval label { display: block; margin: 0.5rem 0; }
.device-approval input[type="checkbox"] { width: auto; margin-right: 0.5rem; }
.device-requester { overflow-wrap: anywhere; }
.device-actions { display: flex; gap: 0.5rem; margin-top: 0.75rem; }

.device-approval input[type="text"] { box-sizing: border-box; width: 100%; max-width: 100%; }
.device-approval fieldset { min-width: 0; }
.device-approval dd { margin-left: 0; margin-bottom: 0.5rem; overflow-wrap: anywhere; }
.device-approval dt { font-weight: 600; }

/* The dedicated device page shares the palette, without the app layout. */
.device-page { min-height: 100vh; height: auto; overflow: auto; }
.device-page-content { max-width: 42rem; margin: 2rem auto; padding: 1.5rem; background: var(--surface); border: 1px solid var(--border); border-radius: 0.5rem; }
.device-page-content h1 { font-size: 1.4rem; }
.device-page-content .device-approval > p { margin: 0.75rem 0; }
.device-page-content input[type="text"] { padding: 0.5rem; border: 1px solid var(--border); border-radius: 0.375rem; background: var(--surface); color: var(--fg); }
@media (max-width: 600px) { .device-page-content { margin: 0.75rem; padding: 1rem; } }
.device-page-content .device-approval h2 { font-size: 1.15rem; }

/* Long attacker-controlled link text must fit the confirmation pane. */
.link-confirmation {
  padding: 1rem;
  max-width: 52rem;
  overflow-wrap: anywhere;
}

/* Message-local phishing signals; never style sender authentication as approval. */
.phishing-warnings, .compose-reply-warning {
  padding: 10px 16px;
  background: var(--warning-bg);
  border: 1px solid var(--warning-border);
  color: var(--text-primary);
  flex-shrink: 0;
  border-radius: 4px;
  margin: 8px 0;
  overflow-wrap: anywhere;
}
.phishing-warnings ul { margin: 0; padding-left: 20px; }
.phishing-warnings li + li { margin-top: 6px; }
.phishing-link-warning { display: flex; align-items: baseline; gap: 0.25em; white-space: nowrap; }
.phishing-link-warning > span { flex-shrink: 0; }
.phishing-link-warning:focus-visible { outline: 2px solid var(--btn-primary); outline-offset: 2px; }
.phishing-warning-url { flex: 1 1 0; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.phishing-warning-host { flex: 0 1 auto; max-width: 25%; }
/* Fixed positioning escapes the body/thread scrollers. Full values wrap and can
   be selected or scrolled without following the suspicious link. */
.phishing-link-tooltip {
  position: fixed;
  right: 16px;
  z-index: 100;
  max-width: 52rem;
  padding: 10px 12px;
  border: 1px solid var(--warning-border);
  border-radius: 4px;
  background: var(--warning-bg);
  color: var(--text-primary);
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2);
  white-space: normal;
  overflow-wrap: anywhere;
  overflow: auto;
}
.phishing-link-tooltip > span { display: block; }
.phishing-link-tooltip > span + span { margin-top: 6px; }
/* First-time sender sits beside the From address: a signal, not an alarm. */
.sender-first-time {
  padding: 1px 8px;
  background: var(--warning-bg);
  border: 1px solid var(--warning-border);
  border-radius: 4px;
  color: var(--text-primary);
  font-size: 12px;
}
.phishing-warning-strong { font-weight: 700; border-left: 4px solid currentColor; padding-left: 8px; }
.sender-display { display: inline-flex; flex-wrap: wrap; gap: 0 8px; max-width: 100%; overflow-wrap: anywhere; }
.sender-address, .sender-idn { font-weight: 400; }
.thread-from { white-space: normal; overflow: visible; }
.attachment-risk { font-weight: 700; }
.attachment-link[role="button"] { cursor: pointer; }
