:root {
  color-scheme: light dark;
  --text: #1A2233;
  --text-muted: #5A6577;
  --brand: #2F6F5B;
  --brand-dark: #245546;
  --surface: #FFFFFF;
  --bg: #F6F7F5;
  --border: #E3E6E1;
  --success: #3B8C6E;
  --warning: #C9822E;
  --danger: #B4483C;
  --info: #2F7FD6;
  /* Layered surfaces + tinted status backgrounds — derived from the tokens
     above via color-mix() so they auto-adapt per theme instead of needing a
     hand-tuned hex in every theme block (same technique already used by the
     .wid-box diagram fills below). --surface-2 separates a section/table
     header from its surrounding --surface card; the -weak tokens are what
     status chips/banners tint their background with so the color reads as
     "this state" even before you read the text. */
  --surface-2: color-mix(in srgb, var(--border) 35%, var(--surface));
  --brand-weak: color-mix(in srgb, var(--brand) 14%, var(--surface));
  --success-weak: color-mix(in srgb, var(--success) 16%, var(--surface));
  --warning-weak: color-mix(in srgb, var(--warning) 16%, var(--surface));
  --danger-weak: color-mix(in srgb, var(--danger) 16%, var(--surface));
  --info-weak: color-mix(in srgb, var(--info) 16%, var(--surface));
  /* Chart-mark colors: distinct from the (more muted) chip colors above —
     validated with scripts/validate_palette.js from the dataviz skill for
     chroma-floor + CVD separation, which the muted chip hexes fail on fills. */
  --donut-valid: #1F9E6B;
  --donut-risky: #C9822E;
  --donut-invalid: #B4483C;
  --donut-unvalidated: #5A6577;
  --chart-scraped: #1BAF7A;
  --chart-sent: #4A3AA7;
  /* Dashboard benefit-card accents: a 6-slot categorical set (dataviz skill's
     validated default order — blue/green/magenta/yellow/aqua/orange), run
     through scripts/validate_palette.js for this exact 6-color subset in both
     modes (CVD + normal-vision adjacent-pair checks all pass). Decorative
     identity only — card titles/body text stay in --ink/--slate, never these. */
  --feature-1: #2A78D6;
  --feature-2: #008300;
  --feature-3: #E87BA4;
  --feature-4: #EDA100;
  --feature-5: #1BAF7A;
  --feature-6: #EB6834;
}

/* Explicit user choice (via the sidebar theme toggle) always wins over the OS
   preference — without this, color-scheme: light dark on :root still lets
   native form controls (select popups, checkboxes, scrollbars) follow a dark
   OS preference even after the user has explicitly picked light mode here. */
:root[data-theme="light"] {
  color-scheme: light;
}

@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    color-scheme: dark;
    --text: #E7E9EC;
    --text-muted: #9AA3AF;
    --brand: #4FAE8D;
    --brand-dark: #3E9078;
    --surface: #1E242C;
    --bg: #14181E;
    --border: #2E3742;
    --success: #4FAE8D;
    --warning: #E0A354;
    --danger: #E67469;
    --info: #5B9EE8;
    --surface-2: color-mix(in srgb, var(--border) 35%, var(--surface));
    --brand-weak: color-mix(in srgb, var(--brand) 18%, var(--surface));
    --success-weak: color-mix(in srgb, var(--success) 20%, var(--surface));
    --warning-weak: color-mix(in srgb, var(--warning) 20%, var(--surface));
    --danger-weak: color-mix(in srgb, var(--danger) 20%, var(--surface));
    --info-weak: color-mix(in srgb, var(--info) 20%, var(--surface));
    --donut-valid: #199E70;
    --donut-risky: #C98500;
    --donut-invalid: #E66767;
    --donut-unvalidated: #7C8695;
    --chart-scraped: #199E70;
    --chart-sent: #9085E9;
    --feature-1: #3987E5;
    --feature-2: #008300;
    --feature-3: #D55181;
    --feature-4: #C98500;
    --feature-5: #199E70;
    --feature-6: #D95926;
  }
}

:root[data-theme="dark"] {
  color-scheme: dark;
  --text: #E7E9EC;
  --text-muted: #9AA3AF;
  --brand: #4FAE8D;
  --brand-dark: #3E9078;
  --surface: #1E242C;
  --bg: #14181E;
  --border: #2E3742;
  --success: #4FAE8D;
  --warning: #E0A354;
  --danger: #E67469;
  --info: #5B9EE8;
  --surface-2: color-mix(in srgb, var(--border) 35%, var(--surface));
  --brand-weak: color-mix(in srgb, var(--brand) 18%, var(--surface));
  --success-weak: color-mix(in srgb, var(--success) 20%, var(--surface));
  --warning-weak: color-mix(in srgb, var(--warning) 20%, var(--surface));
  --danger-weak: color-mix(in srgb, var(--danger) 20%, var(--surface));
  --info-weak: color-mix(in srgb, var(--info) 20%, var(--surface));
  --donut-valid: #199E70;
  --donut-risky: #C98500;
  --donut-invalid: #E66767;
  --donut-unvalidated: #7C8695;
  --chart-scraped: #199E70;
  --chart-sent: #9085E9;
  --feature-1: #3987E5;
  --feature-2: #008300;
  --feature-3: #D55181;
  --feature-4: #C98500;
  --feature-5: #199E70;
  --feature-6: #D95926;
}

* {
  box-sizing: border-box;
}

body {
  margin: 0;
  background: var(--bg);
  color: var(--text);
  font-family: "Inter", system-ui, sans-serif;
  font-size: 15px;
  line-height: 1.5;
}

h1, h2, h3 {
  font-family: "Space Grotesk", system-ui, sans-serif;
  font-weight: 600;
  margin: 0 0 16px;
}

h1 { font-size: 28px; }
h2 { font-size: 22px; }
h3 { font-size: 18px; }

/* Base form-control theming: native inputs/selects don't pick up --ink/--surface
   on their own, so without this every text input and <select> across the app
   (not just one page) falls back to the browser's own light-mode rendering in
   dark mode — dark text on a dark card, or a stray light input box. Every
   component-specific input rule (.form-group, .search-row, .combobox, ...)
   layers padding/border on top of this; this is the single place background/
   color/placeholder/focus-ring are set so no page can drift out of sync. */
input[type="text"],
input[type="email"],
input[type="password"],
input[type="number"],
input[type="search"],
select,
textarea {
  background: var(--surface);
  color: var(--text);
}

input[type="text"]::placeholder,
input[type="email"]::placeholder,
input[type="password"]::placeholder,
input[type="number"]::placeholder,
input[type="search"]::placeholder,
textarea::placeholder {
  color: var(--text-muted);
  opacity: 1;
}

select option {
  background: var(--surface);
  color: var(--text);
}

input[type="text"]:focus,
input[type="email"]:focus,
input[type="password"]:focus,
input[type="number"]:focus,
input[type="search"]:focus,
select:focus,
textarea:focus {
  outline: 2px solid var(--brand);
  outline-offset: 1px;
}

.mono {
  font-family: "JetBrains Mono", monospace;
  font-size: 14px;
}

.label {
  font-size: 13px;
  font-weight: 500;
  letter-spacing: 0.02em;
  text-transform: uppercase;
  color: var(--text-muted);
}

a {
  color: var(--brand);
}

.brand {
  font-family: "Space Grotesk", system-ui, sans-serif;
  font-weight: 600;
  font-size: 18px;
  color: var(--text);
  text-decoration: none;
}

.icon-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 44px;
  padding: 5px 16px;
  background: transparent;
  border: 1px solid var(--border);
  border-radius: 999px;
  color: var(--text-muted);
  font-family: inherit;
  font-size: 13px;
  cursor: pointer;
}

.icon-btn:hover {
  border-color: var(--brand);
  color: var(--brand);
}

.theme-toggle-floating {
  position: fixed;
  top: 16px;
  right: 16px;
  z-index: 50;
  display: flex;
  align-items: center;
  gap: 12px;
}

.theme-toggle-floating .icon-btn {
  background: var(--surface);
}

.lang-switch {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  font-size: 13px;
}

.lang-switch a {
  color: var(--text-muted);
  text-decoration: none;
  padding: 2px 4px;
}

.lang-switch a.active {
  color: var(--brand);
  font-weight: 500;
}

.lang-switch a:hover {
  color: var(--brand);
}

/* ---- App shell: sidebar + main content ---- */

.app-shell {
  display: flex;
  align-items: stretch;
  min-height: 100vh;
}

.sidebar {
  width: 248px;
  flex-shrink: 0;
  background: var(--surface);
  border-right: 1px solid var(--border);
  display: flex;
  flex-direction: column;
  position: sticky;
  top: 0;
  height: 100vh;
  overflow-y: auto;
}

.sidebar-header {
  padding: 20px 20px 12px;
  display: flex;
  align-items: center;
  justify-content: space-between;
}

.sidebar-toggle-btn {
  display: none;
}

.sidebar-nav {
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding: 8px 12px;
  flex: 1;
}

.sidebar-nav a {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px 12px;
  border-radius: 8px;
  color: var(--text-muted);
  text-decoration: none;
  font-size: 14px;
  font-weight: 500;
}

.sidebar-nav a:hover {
  background: var(--bg);
  color: var(--text);
}

.sidebar-nav a.active {
  background: var(--brand-weak);
  color: var(--brand);
}

.nav-icon {
  width: 18px;
  height: 18px;
  flex-shrink: 0;
  display: inline-flex;
}

.nav-icon svg {
  width: 100%;
  height: 100%;
}

.sidebar-footer {
  padding: 16px 20px 20px;
  border-top: 1px solid var(--border);
  display: flex;
  flex-direction: column;
  gap: 12px;
}

.sidebar-footer-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
}

.sidebar-user-info {
  text-decoration: none;
  padding: 8px 10px;
  border-radius: 8px;
  background: var(--surface-alt, rgba(127, 127, 127, 0.08));
  gap: 8px;
}

.sidebar-user-info:hover {
  background: var(--surface);
}

.onboarding-checklist {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.onboarding-checklist li {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 14px;
}

.onboarding-check {
  color: var(--text-muted);
  width: 16px;
  text-align: center;
}

.onboarding-done .onboarding-check {
  color: var(--success);
}

.onboarding-done span {
  color: var(--text-muted);
  text-decoration: line-through;
}

.sidebar-user-email {
  color: var(--text);
  font-size: 13px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.sidebar-logout {
  color: var(--text-muted);
  text-decoration: none;
  font-size: 14px;
  font-weight: 500;
}

.sidebar-logout:hover {
  color: var(--danger);
}

.sidebar-backdrop {
  display: none;
}

.app-main {
  flex: 1;
  min-width: 0;
}

.topbar {
  display: none;
  align-items: center;
  gap: 14px;
  padding: 14px 20px;
  background: var(--surface);
  border-bottom: 1px solid var(--border);
  position: sticky;
  top: 0;
  z-index: 30;
}

.container {
  max-width: 1440px;
  margin: 0 auto;
  padding: 32px;
}

.card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 8px;
  box-shadow: 0 1px 3px rgba(26, 34, 51, 0.06);
  padding: 24px;
  /* Safety net: a wide table (many columns, long content) scrolls within its
     own card instead of overflowing the page on narrow viewports. */
  overflow-x: auto;
}

@media (max-width: 1100px) {
  .sidebar {
    position: fixed;
    top: 0;
    left: 0;
    z-index: 60;
    transform: translateX(-100%);
    transition: transform 0.2s ease;
    box-shadow: 0 0 32px rgba(0, 0, 0, 0.2);
  }

  .sidebar.open {
    transform: translateX(0);
  }

  .sidebar-toggle-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    padding: 6px 10px;
    font-size: 16px;
    line-height: 1;
  }

  .topbar {
    display: flex;
  }

  .sidebar-backdrop {
    display: none;
    position: fixed;
    inset: 0;
    background: rgba(15, 20, 26, 0.45);
    z-index: 55;
  }

  .sidebar-backdrop.open {
    display: block;
  }

  .container {
    padding: 20px;
  }
}

@media (max-width: 640px) {
  .container {
    padding: 16px;
  }

  h1 {
    font-size: 22px;
  }

  .page-header {
    flex-direction: column;
    align-items: flex-start;
    gap: 12px;
  }

  /* The desktop nowrap guard (above) exists to stop a wide action-button
     group from squeezing the title — moot once the header stacks into a
     column here, and a genuinely long title still needs to wrap normally
     within a 375px-wide screen instead of overflowing it. */
  .page-header h1 {
    white-space: normal;
  }

  .stat-grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }

  .theme-toggle-floating {
    top: 10px;
    right: 10px;
  }
}

.btn {
  display: inline-block;
  border-radius: 8px;
  padding: 10px 20px;
  font-size: 15px;
  font-weight: 500;
  text-decoration: none;
  border: none;
  cursor: pointer;
  font-family: inherit;
  /* A button's label must never wrap — this design has no multi-line
     buttons anywhere, so a wrap only ever means a table's action column got
     squeezed by a wider sibling column, which (combined with
     `td { overflow-wrap: anywhere }`) breaks the label character-by-character
     instead of just staying one line and letting the table scroll. */
  white-space: nowrap;
}

.btn-primary {
  background: var(--brand);
  color: #fff;
}

.btn-primary:hover {
  background: var(--brand-dark);
}

.btn-secondary {
  background: transparent;
  color: var(--text);
  border: 1px solid var(--border);
}

.btn-danger {
  background: transparent;
  color: var(--danger);
  border: none;
  padding: 4px 8px;
}

.btn-small {
  padding: 4px 10px;
  font-size: 13px;
}

/* Compact icon-only action buttons (table row delete/remove actions).
   Always icon, never the text label: a table's last unlabeled column
   shrinks to whatever the other columns leave it, and any wrapped text
   there looks broken regardless of the viewport breakpoint (the label
   still reaches assistive tech / hover via title+aria-label). */
.btn-compact {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  /* 44px — the minimum touch-target size this project targets, not 32px's
     visual icon size; a smaller icon inside a still-44px hit area would look
     odd here, so the whole button grows instead. */
  width: 44px;
  height: 44px;
  padding: 0;
  font-size: 16px;
  line-height: 1;
}

.btn-compact .btn-label {
  display: none;
}

/* Follow-up step builder (see _sequence_steps_builder.html) */
.sequence-step-row {
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 16px;
  margin-bottom: 12px;
}

.sequence-step-row-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  margin-bottom: 8px;
}

.sequence-step-row-header h4,
.sequence-step-row > h4 {
  margin: 0 0 8px;
}

.sequence-step-row-header h4 {
  margin-bottom: 0;
}

table {
  width: 100%;
  border-collapse: collapse;
}

th {
  text-align: left;
  padding: 8px 12px;
  font-size: 13px;
  font-weight: 500;
  letter-spacing: 0.02em;
  text-transform: uppercase;
  color: var(--text-muted);
  background: var(--surface-2);
  border-bottom: 1px solid var(--border);
  /* Same floor as td below, so a header cell can't be squeezed narrower
     than its own body column and force a mismatched layout. */
  min-width: 90px;
}

td {
  padding: 12px;
  border-bottom: 1px solid var(--border);
  /* A single long unbroken value (a long email address, a URL with no short
     domain) must wrap instead of stretching its column past the container —
     otherwise the table overflows its card and later columns get pushed off
     to the right, leaving a visual gap in the row. */
  overflow-wrap: anywhere;
  /* A table with many columns (10+) has no room left per column once
     `table { width: 100% }` tries to fit them all — every cell's text, even
     a short word or a plain link, breaks one character per line via
     overflow-wrap above. A floor per cell forces the whole table wider than
     its card instead, so `.card { overflow-x: auto }` scrolls it
     horizontally (the actual "wide tables scroll" behavior this app already
     documents) rather than squeezing every column unreadable — true at any
     viewport width, not just mobile's tighter case. */
  min-width: 90px;
}

/* Zebra striping rides on --surface-2 too, at half strength, so a header row
   and a striped body row read as the same "layered surface" language rather
   than two unrelated visual treatments. */
tbody tr:nth-child(even) td {
  background: color-mix(in srgb, var(--surface-2) 55%, transparent);
}

.chip {
  display: inline-block;
  border-radius: 8px;
  padding: 2px 10px;
  font-size: 13px;
  font-weight: 500;
  /* A status chip's text must never mid-word wrap inside a narrow table
     column — that reads as broken, not just tight. A table cell with a lone
     chip already wraps the row height fine without this. */
  white-space: nowrap;
}

.chip-active {
  background: var(--success-weak);
  color: var(--success);
}

.chip-limit_reached {
  background: var(--warning-weak);
  color: var(--warning);
}

.chip-invalid {
  background: var(--danger-weak);
  color: var(--danger);
}

.form-group {
  margin-bottom: 16px;
}

.form-group label {
  display: block;
  margin-bottom: 6px;
}

.form-group input {
  width: 100%;
  padding: 10px 12px;
  border: 1px solid var(--border);
  border-radius: 8px;
  font-family: inherit;
  font-size: 15px;
}

.form-group input:focus {
  outline: 2px solid var(--brand);
  outline-offset: 1px;
}

.form-group textarea {
  width: 100%;
  padding: 10px 12px;
  border: 1px solid var(--border);
  border-radius: 8px;
  font-family: inherit;
  font-size: 15px;
  resize: vertical;
}

.form-group textarea:focus {
  outline: 2px solid var(--brand);
  outline-offset: 1px;
}

.error {
  color: var(--danger);
  font-size: 14px;
  margin-bottom: 16px;
}

hr {
  border: none;
  border-top: 1px solid var(--border);
  margin: 20px 0;
}

.capacity-summary {
  margin-bottom: 24px;
}

/* Small layout utilities (phase 6.1 UI/UX audit) — replace one-off inline
   `style="..."` attributes that were repeating the same handful of
   declarations across many templates, so every page draws from the same
   token/spacing source instead of its own copy. */
.form-inline {
  display: inline;
}

/* Initial-hidden-until-JS-reveals state (an inline error message a script
   flips to visible on failure) — JS toggles the element's own inline style
   directly, which always wins over this class either way. */
.hidden {
  display: none;
}

.nowrap {
  white-space: nowrap;
}

.cell-muted {
  font-size: 13px;
  color: var(--text-muted);
}

.checkbox-inline {
  width: auto;
}

.form-group-tight {
  margin-bottom: 0;
}

.checkbox-label {
  font-weight: 400;
}

.details-inline {
  display: inline-block;
}

.details-summary-inline {
  display: inline;
  cursor: pointer;
}

.summary-clickable {
  cursor: pointer;
}

.card-section-gap {
  margin-bottom: 20px;
}

/* A small title+action header row INSIDE a card (e.g. the onboarding
   checklist's "Başlarken / Kapat" row) — deliberately not `.page-header`,
   which is `position: sticky` at desktop widths; nesting that inside a card
   would stick the inner row to the viewport top while scrolling past it. */
.card-header-row {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 8px;
}

.card-header-row h3 {
  margin: 0;
}

.status-strip {
  display: flex;
  gap: 24px;
  flex-wrap: wrap;
  margin-top: 8px;
}

.card-narrow {
  max-width: 480px;
}

.card-medium {
  max-width: 520px;
}

.card-wide {
  max-width: 760px;
  line-height: 1.6;
}

/* Centered "single message" card — error page, empty/blocking states. */
.card-message {
  max-width: 520px;
  margin: 60px auto;
  text-align: center;
}

.card-message .code {
  font-size: 56px;
  margin: 0;
  color: var(--text-muted);
}

/* Filter/search forms built from stacked label+input .form-group pairs
   (admin log filters, ...) laid out in a row, submit button aligned to the
   bottom of the inputs rather than their vertical center. */
.filter-row {
  display: flex;
  gap: 12px;
  flex-wrap: wrap;
  align-items: flex-end;
}

.filter-row .form-group {
  margin-bottom: 0;
}

/* Two-column stretch layout (plan/feature comparison cards, ...). */
.compare-columns {
  display: flex;
  gap: 24px;
  flex-wrap: wrap;
  align-items: stretch;
}

.compare-column {
  flex: 1;
  min-width: 220px;
}

.feature-list {
  padding-left: 18px;
  line-height: 1.8;
}

.usage-row {
  margin-bottom: 10px;
}

.usage-row:last-child {
  margin-bottom: 0;
}

/* Auth pages (login/register/forgot-password/reset-password) render inside
   their own full-bleed container instead of the sidebar shell's `.container`
   (max-width 1440px + padding) — see base.html's <main> class — so
   .login-wrap's flex centering is always centered on the real viewport, not
   inside an already-centered, narrower box. */
.auth-page-container {
  width: 100%;
  min-height: 100vh;
}

.login-wrap {
  min-height: 100vh;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 24px;
}

.auth-stack {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 20px;
  width: 100%;
  max-width: 400px;
}

.auth-brand {
  font-size: 22px;
}

.login-card {
  width: 100%;
  max-width: 400px;
}

.auth-links {
  text-align: center;
  font-size: 14px;
  color: var(--text-muted);
  margin-top: 12px;
}

.auth-links a {
  color: var(--brand);
  text-decoration: none;
  font-weight: 500;
}

.auth-links a:hover {
  text-decoration: underline;
}

.page-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  flex-wrap: wrap;
  gap: 12px;
  margin-bottom: 24px;
}

/* The title must never be the thing that breaks mid-word when a page's
   action-button group is wide (several buttons, a busy toolbar) — it should
   keep its natural width and let the action group wrap onto its own line
   instead (already flex-wrap-friendly, since every action group here is a
   plain block of inline-block buttons). */
.page-header h1 {
  flex-shrink: 0;
  white-space: nowrap;
  margin: 0;
}

/* Sticky page header is a desktop-only enhancement (>1100px): below that the
   mobile topbar is already a persistent sticky header of its own, and
   stacking a second sticky element under it (plus the .page-header column
   layout kicking in at <640px) isn't worth the added complexity for the
   value it buys. --sticky-header-offset is reused below by the two
   pre-existing sticky toolbars (.analytics-filters, .sticky-send-bar) so
   they stack cleanly beneath this instead of overlapping it. */
:root {
  --sticky-header-offset: 68px;
}

@media (min-width: 1101px) {
  .page-header {
    position: sticky;
    top: 0;
    z-index: 25;
    background: var(--bg);
    padding: 14px 0;
    margin-top: -14px;
  }
}

.chip-draft,
.chip-drafted,
.chip-new,
.chip-unvalidated,
.chip-queued,
.chip-suppressed,
.chip-canceled,
.chip-unchecked {
  background: var(--surface-2);
  color: var(--text-muted);
}

.chip-running,
.chip-warm,
.chip-risky,
.chip-stopped,
.chip-paused,
.chip-pending_approval,
.chip-awaiting_approval,
.chip-uncertain {
  background: var(--warning-weak);
  color: var(--warning);
}

.chip-done,
.chip-hot,
.chip-valid,
.chip-sent,
.chip-opened,
.chip-replied,
.chip-relevant {
  background: var(--success-weak);
  color: var(--success);
}

.chip-failed,
.chip-cold,
.chip-bounced,
.chip-irrelevant,
.chip-error {
  background: var(--danger-weak);
  color: var(--danger);
}

/* Admin log viewer only (phase 5.12) — 'critical' is a step above the
   ordinary 'error' chip above, so it gets a solid (not weak-tint) fill to
   stand out in a list that's mostly 'error' rows. */
.chip-critical {
  background: var(--danger);
  color: var(--surface);
}

.error-detail-pre {
  white-space: pre-wrap;
  word-break: break-word;
  font-family: "JetBrains Mono", monospace;
  font-size: 12px;
  max-height: 320px;
  overflow-y: auto;
  background: var(--surface-2);
  border-radius: 8px;
  padding: 12px;
}

.progress-bar {
  background: var(--border);
  border-radius: 999px;
  height: 8px;
  overflow: hidden;
  margin: 8px 0 20px;
}

/* Fixed-width variant for a compact quota/usage bar inside a table cell
   (search keys, warm-up ramp) rather than stretching to the cell's width. */
.progress-bar-compact {
  width: 140px;
}

.progress-bar-fill {
  background: var(--brand);
  height: 100%;
  transition: width 0.3s ease;
}

.social-badge {
  display: inline-block;
  padding: 2px 8px;
  margin: 2px 4px 2px 0;
  border-radius: 6px;
  background: var(--bg);
  border: 1px solid var(--border);
  font-size: 12px;
  color: var(--text);
  text-decoration: none;
}

.social-badge:hover {
  border-color: var(--brand);
  color: var(--brand);
}

details > summary {
  cursor: pointer;
  list-style: revert;
}

.email-list {
  margin: 8px 0 0;
  padding-left: 18px;
  font-size: 13px;
}

.email-list li {
  margin-bottom: 4px;
}

.help-text {
  font-size: 13px;
  color: var(--text-muted);
  margin-top: 4px;
}

.checkbox-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(140px, 1fr));
  gap: 6px 12px;
  max-height: 260px;
  overflow-y: auto;
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 12px;
}

.checkbox-grid label {
  display: flex;
  align-items: center;
  gap: 6px;
  font-weight: 400;
  font-size: 14px;
  margin-bottom: 0;
}

.checkbox-grid input {
  width: auto;
}

.form-group select {
  width: 100%;
  padding: 10px 12px;
  border: 1px solid var(--border);
  border-radius: 8px;
  font-family: inherit;
  font-size: 15px;
  background: var(--surface);
}

.combobox {
  position: relative;
}

.combobox input[type="text"] {
  width: 100%;
  padding: 10px 12px;
  border: 1px solid var(--border);
  border-radius: 8px;
  font-family: inherit;
  font-size: 15px;
}

.combobox input[type="text"]:focus {
  outline: 2px solid var(--brand);
  outline-offset: 1px;
}

.combobox-options {
  position: absolute;
  z-index: 10;
  top: calc(100% + 4px);
  left: 0;
  right: 0;
  max-height: 240px;
  overflow-y: auto;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 8px;
  box-shadow: 0 4px 12px rgba(26, 34, 51, 0.12);
}

.combobox-option {
  padding: 8px 12px;
  cursor: pointer;
  font-size: 14px;
}

.combobox-option:hover {
  background: var(--bg);
}

.combobox-empty {
  padding: 8px 12px;
  font-size: 14px;
  color: var(--text-muted);
}

/* Filterable + checkable multi-select dropdown (see outreach_campaign_new.js) —
   same visual language as .combobox above, but a persistent checkbox panel
   instead of a single-pick option list. */
.multiselect {
  position: relative;
}

.multiselect-toggle {
  width: 100%;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  padding: 10px 12px;
  border: 1px solid var(--border);
  border-radius: 8px;
  font-family: inherit;
  font-size: 15px;
  background: var(--surface);
  color: var(--text);
  cursor: pointer;
  text-align: left;
}

.multiselect-toggle:focus {
  outline: 2px solid var(--brand);
  outline-offset: 1px;
}

.multiselect-caret {
  color: var(--text-muted);
  font-size: 12px;
}

.multiselect-panel {
  position: absolute;
  z-index: 10;
  top: calc(100% + 4px);
  left: 0;
  right: 0;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 8px;
  box-shadow: 0 4px 12px rgba(26, 34, 51, 0.12);
  overflow: hidden;
}

.multiselect-search {
  width: 100%;
  padding: 10px 12px;
  border: none;
  border-bottom: 1px solid var(--border);
  font-family: inherit;
  font-size: 14px;
  background: transparent;
  color: var(--text);
}

/* A visible focus indicator, not the browser default outline (which would
   clip against this input's own bottom border) — still WCAG-visible, unlike
   suppressing it outright. */
.multiselect-search:focus {
  outline: none;
  box-shadow: inset 0 -2px 0 var(--brand);
}

.multiselect-options {
  max-height: 240px;
  overflow-y: auto;
}

.multiselect-option {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 8px 12px;
  font-size: 14px;
  font-weight: 400;
  cursor: pointer;
}

.multiselect-option:hover {
  background: var(--bg);
}

.multiselect-option-all {
  border-bottom: 1px solid var(--border);
  font-weight: 500;
}

.select-all-row {
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: 14px;
  font-weight: 400;
  margin-bottom: 8px;
}

/* Grouped template multi-select (see _template_multiselect.html /
   template_multiselect.js) — group header + "select all in group" row on
   top of the base .multiselect-option list. */
.multiselect-group + .multiselect-group {
  border-top: 1px solid var(--border);
}

.multiselect-group-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  padding: 8px 12px;
  background: var(--surface-2, var(--bg));
  font-size: 13px;
  font-weight: 600;
  color: var(--text-muted);
}

.multiselect-group-select-all {
  border: none;
  background: none;
  color: var(--brand);
  font-size: 12px;
  font-weight: 600;
  cursor: pointer;
  padding: 2px 4px;
}

.multiselect-group-select-all:hover {
  text-decoration: underline;
}

.tmpl-multiselect .multiselect-options {
  max-height: 320px;
}

.template-preview-item {
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 10px 12px;
  margin-bottom: 8px;
}

.template-preview-item strong {
  display: block;
  margin-bottom: 4px;
}

/* Masked sender-email display + eye toggle (see _masked_email.html /
   masked_email.js) — the user's OWN connected Gmail addresses only, never
   lead/recipient emails. */
.masked-email {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  /* A masked address ("**\*@**\*.com") is short and must read as one token —
     without this it inherits the table's overflow-wrap:anywhere and breaks
     character-by-character the moment a narrow mobile column squeezes it,
     instead of the table just scrolling horizontally (its actual safety net,
     see .card { overflow-x: auto }). */
  white-space: nowrap;
}

.masked-email-toggle {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 22px;
  height: 22px;
  padding: 0;
  border: none;
  background: transparent;
  color: var(--text-muted);
  cursor: pointer;
  border-radius: 4px;
}

.masked-email-toggle:hover {
  color: var(--brand);
}

.masked-email-toggle:focus-visible {
  outline: 2px solid var(--brand);
  outline-offset: 1px;
}

.masked-email-toggle .icon-svg svg {
  width: 16px;
  height: 16px;
}

.masked-email-icon-hide {
  display: none;
}

.masked-email-toggle.is-revealed .masked-email-icon-show {
  display: none;
}

.masked-email-toggle.is-revealed .masked-email-icon-hide {
  display: inline-flex;
}

#reveal-all-sender-emails-row {
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: 12px;
  color: var(--text-muted);
}

.how-it-works {
  margin: 8px 0 0;
  padding-left: 20px;
}

.how-it-works li {
  margin-bottom: 8px;
  line-height: 1.5;
}

.stat-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(110px, 1fr));
  gap: 12px;
  margin-bottom: 20px;
}

.stat-tile {
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 14px 16px;
}

.stat-tile .value {
  font-family: "Space Grotesk", system-ui, sans-serif;
  font-size: 26px;
  font-weight: 600;
  color: var(--text);
  line-height: 1.2;
}

.stat-tile .stat-label {
  font-size: 13px;
  color: var(--text-muted);
  margin-top: 2px;
}

.status-fill-draft {
  background: var(--text-muted);
}

.status-fill-running {
  background: var(--warning);
}

.status-fill-done {
  background: var(--success);
}

.status-fill-failed {
  background: var(--danger);
}

.stacked-bar {
  display: flex;
  height: 20px;
  border-radius: 10px;
  overflow: hidden;
  background: var(--bg);
  gap: 2px;
}

.stacked-bar-segment {
  height: 100%;
}

.stacked-bar-legend {
  list-style: none;
  padding: 0;
  margin: 12px 0 0;
  display: flex;
  flex-wrap: wrap;
  gap: 16px;
}

.stacked-bar-legend li a {
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: 14px;
  color: var(--text);
  text-decoration: none;
}

.stacked-bar-legend li a:hover {
  color: var(--brand);
}

.legend-swatch {
  width: 10px;
  height: 10px;
  border-radius: 3px;
  display: inline-block;
}

.send-panel {
  margin-top: 16px;
}

.sticky-send-bar {
  position: sticky;
  top: 0;
  z-index: 20;
  margin-bottom: 16px;
}

@media (min-width: 1101px) {
  .sticky-send-bar {
    top: var(--sticky-header-offset);
  }
}

@media (max-width: 1100px) {
  .sticky-send-bar {
    top: 60px;
  }
}

.repeatable-row {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-top: 8px;
}

.repeatable-row input {
  flex: 1 1 240px;
}

.send-panel .search-row {
  margin-top: 8px;
}

.select-all-row input {
  width: auto;
}

.search-row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px;
  margin-top: 16px;
}

.search-row input[type="text"] {
  flex: 1 1 240px;
  padding: 10px 12px;
  border: 1px solid var(--border);
  border-radius: 8px;
  font-family: inherit;
  font-size: 15px;
}

.search-row select {
  padding: 10px 12px;
  border: 1px solid var(--border);
  border-radius: 8px;
  font-family: inherit;
  font-size: 15px;
  background: var(--surface);
}

/* "How it works" diagram (inline SVG, not a raster image — see dashboard.html):
   transparent by design so it sits directly on the card's own background in
   both themes, no separate white plate. Capped well below full card width so
   it reads as a compact figure, not a full-bleed banner. */
.wid-diagram {
  display: block;
  width: 100%;
  height: auto;
  margin: 12px auto 4px;
}

.wid-box {
  fill: color-mix(in srgb, var(--brand) 12%, var(--bg));
  stroke: var(--brand);
  stroke-width: 1;
}

.wid-box-accent {
  fill: color-mix(in srgb, var(--chart-sent) 14%, var(--bg));
  stroke: var(--chart-sent);
  stroke-width: 1;
}

.wid-num {
  fill: color-mix(in srgb, var(--brand) 12%, var(--bg));
  stroke: var(--brand);
  stroke-width: 1;
}

.wid-num-accent {
  fill: color-mix(in srgb, var(--chart-sent) 14%, var(--bg));
  stroke: var(--chart-sent);
  stroke-width: 1;
}

.wid-num-text {
  fill: var(--brand-dark);
  font: 600 14px "Space Grotesk", system-ui, sans-serif;
  text-anchor: middle;
  dominant-baseline: central;
}

.wid-num-text-accent {
  fill: var(--chart-sent);
}

.wid-title {
  fill: var(--brand-dark);
  font: 600 14px system-ui, sans-serif;
  text-anchor: middle;
  dominant-baseline: central;
}

.wid-title-accent {
  fill: var(--chart-sent);
}

.wid-desc {
  fill: var(--brand);
  font: 400 12px system-ui, sans-serif;
  text-anchor: middle;
  dominant-baseline: central;
}

.wid-desc-accent {
  fill: var(--chart-sent);
}

.wid-arrow {
  fill: none;
  stroke: var(--border);
  stroke-width: 1.5px;
}

.wid-arrow-head {
  fill: none;
  stroke: var(--border);
  stroke-width: 1.5px;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.wid-caption {
  fill: var(--text-muted);
  font: 400 12px system-ui, sans-serif;
  text-anchor: middle;
}

.stat-tile.is-link {
  display: block;
  text-decoration: none;
  transition: border-color 0.15s ease;
}

.stat-tile.is-link:hover {
  border-color: var(--brand);
}

.stacked-bar-segment.is-link {
  cursor: pointer;
}

/* ---- Dashboard hero + benefits ---- */

.hero-card {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 24px;
}

.hero-copy {
  flex: 1 1 360px;
}

.hero-copy h2 {
  margin-bottom: 8px;
}

.hero-copy p {
  color: var(--text-muted);
  margin: 0;
}

.hero-stat {
  flex: 0 0 auto;
  text-align: center;
  padding: 12px 28px;
  border-left: 1px solid var(--border);
}

.hero-stat-value {
  font-family: "Space Grotesk", system-ui, sans-serif;
  font-size: 40px;
  font-weight: 600;
  color: var(--brand);
  line-height: 1.1;
}

.hero-stat-label {
  font-size: 13px;
  color: var(--text-muted);
  margin-top: 4px;
  max-width: 160px;
}

.how-it-works-label {
  margin-top: 28px;
}

.benefits-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 16px;
}

.benefit-card {
  padding: 16px;
  border: 1px solid var(--border);
  border-top: 3px solid var(--accent, var(--brand));
  border-radius: 8px;
  background: color-mix(in srgb, var(--accent, var(--brand)) 7%, var(--bg));
}

/* Six-slot categorical accent (see --feature-1.. in :root) — one per card, in
   fixed order, never cycled per-instance (dataviz skill's categorical rule). */
.benefit-card:nth-child(1) { --accent: var(--feature-1); }
.benefit-card:nth-child(2) { --accent: var(--feature-2); }
.benefit-card:nth-child(3) { --accent: var(--feature-3); }
.benefit-card:nth-child(4) { --accent: var(--feature-4); }
.benefit-card:nth-child(5) { --accent: var(--feature-5); }
.benefit-card:nth-child(6) { --accent: var(--feature-6); }

.benefit-icon {
  width: 32px;
  height: 32px;
  color: var(--accent, var(--brand));
  margin-bottom: 10px;
}

.benefit-icon .icon-svg,
.benefit-icon svg {
  width: 100%;
  height: 100%;
}

.benefit-card h3 {
  font-size: 15px;
  margin: 0 0 6px;
}

.benefit-card p {
  font-size: 13px;
  color: var(--text-muted);
  margin: 0;
  line-height: 1.5;
}

/* ---- Dashboard charts ---- */

.charts-row {
  display: grid;
  grid-template-columns: minmax(260px, 1fr) minmax(0, 2fr);
  gap: 20px;
  align-items: stretch;
}

.chart-card {
  display: flex;
  flex-direction: column;
}

.chart-card-wide {
  min-width: 0;
}

.chart-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 12px;
  margin-bottom: 4px;
}

.chart-header h3 {
  margin: 0;
}

.chart-toggle {
  display: inline-flex;
  border: 1px solid var(--border);
  border-radius: 999px;
  padding: 2px;
}

.chart-toggle-btn {
  border: none;
  background: transparent;
  color: var(--text-muted);
  font-family: inherit;
  font-size: 13px;
  font-weight: 500;
  padding: 5px 14px;
  border-radius: 999px;
  cursor: pointer;
}

.chart-toggle-btn.active {
  background: var(--brand);
  color: #fff;
}

.donut-svg {
  width: 100%;
  max-width: 220px;
  margin: 4px auto 8px;
  display: block;
}

.donut-center-value {
  font-family: "Space Grotesk", system-ui, sans-serif;
  font-size: 20px;
  font-weight: 600;
  fill: var(--text);
}

.donut-center-label {
  font-size: 8px;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  fill: var(--text-muted);
}

.donut-legend {
  list-style: none;
  padding: 0;
  margin: 8px 0 0;
  display: flex;
  flex-direction: column;
  gap: 6px;
  font-size: 13px;
}

.donut-legend li {
  display: flex;
  align-items: center;
  gap: 8px;
}

.donut-legend .mono {
  margin-left: auto;
  color: var(--text-muted);
}

.donut-swatch-valid { background: var(--donut-valid); }
.donut-swatch-risky { background: var(--donut-risky); }
.donut-swatch-invalid { background: var(--donut-invalid); }
.donut-swatch-unvalidated { background: var(--donut-unvalidated); }

.chart-legend {
  list-style: none;
  padding: 0;
  margin: 4px 0 8px;
  display: flex;
  gap: 16px;
  font-size: 13px;
  color: var(--text);
}

.chart-legend li {
  display: flex;
  align-items: center;
  gap: 6px;
}

.legend-swatch-scraped { background: var(--chart-scraped); }
.legend-swatch-sent { background: var(--chart-sent); }

#activity-chart {
  position: relative;
  flex: 1;
  min-height: 260px;
}

.chart-tooltip {
  position: absolute;
  transform: translateX(-50%);
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 8px;
  box-shadow: 0 4px 12px rgba(26, 34, 51, 0.14);
  padding: 8px 10px;
  font-size: 12px;
  pointer-events: none;
  white-space: nowrap;
  z-index: 5;
}

.chart-tooltip-title {
  font-weight: 600;
  margin-bottom: 4px;
  color: var(--text);
}

.chart-tooltip-row {
  display: flex;
  align-items: center;
  gap: 6px;
  color: var(--text-muted);
}

.chart-tooltip-key {
  width: 8px;
  height: 8px;
  border-radius: 2px;
  display: inline-block;
}

.switch-row {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  cursor: pointer;
}

/* A vertical list of toggles (e.g. the blocklist category switches) —
   .switch-row is inline-flex so a single toggle sits naturally alongside
   other inline content elsewhere, but several of them as bare siblings wrap
   like words in a paragraph instead of stacking one per line. */
.switch-row-list {
  display: flex;
  flex-direction: column;
  gap: 12px;
  margin-bottom: 16px;
}

.switch {
  position: relative;
  display: inline-block;
  width: 42px;
  height: 24px;
  flex-shrink: 0;
}

.switch input {
  position: absolute;
  opacity: 0;
  width: 100%;
  height: 100%;
  margin: 0;
  cursor: pointer;
}

.switch-track {
  position: absolute;
  inset: 0;
  background: var(--border);
  border-radius: 999px;
  transition: background 0.15s ease;
  pointer-events: none;
}

.switch-track::before {
  content: "";
  position: absolute;
  width: 18px;
  height: 18px;
  left: 3px;
  top: 3px;
  background: #fff;
  border-radius: 50%;
  transition: transform 0.15s ease;
  box-shadow: 0 1px 2px rgba(0, 0, 0, 0.25);
}

.switch input:checked + .switch-track {
  background: var(--brand);
}

.switch input:checked + .switch-track::before {
  transform: translateX(18px);
}

.switch input:focus-visible + .switch-track {
  outline: 2px solid var(--brand);
  outline-offset: 2px;
}

.placeholder-chips {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin-bottom: 8px;
}

.placeholder-chip {
  border: 1px dashed var(--border);
  background: var(--bg);
  color: var(--brand);
  border-radius: 6px;
  padding: 3px 9px;
  font-size: 13px;
  cursor: grab;
}

.placeholder-chip:hover {
  border-color: var(--brand);
  background: var(--brand-weak);
}

.placeholder-chip:active {
  cursor: grabbing;
}

.analytics-heading {
  margin-top: 8px;
}

.analytics-filters {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  gap: 20px;
  position: sticky;
  top: 0;
  z-index: 20;
  background: var(--bg);
  padding: 8px 0;
}

@media (min-width: 1101px) {
  .analytics-filters {
    top: var(--sticky-header-offset);
  }
}

.analytics-filters select {
  padding: 8px 12px;
  border: 1px solid var(--border);
  border-radius: 8px;
  font-family: inherit;
  font-size: 14px;
  background: var(--surface);
  min-width: 200px;
}

.analytics-loading {
  font-size: 13px;
  color: var(--brand);
  font-weight: 500;
}

.kpi-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
  gap: 16px;
  margin-bottom: 20px;
}

.kpi-card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 8px;
  box-shadow: 0 1px 3px rgba(26, 34, 51, 0.06);
  padding: 16px;
}

.kpi-card-primary {
  border-color: var(--brand);
}

.kpi-value {
  font-family: "JetBrains Mono", monospace;
  font-size: 28px;
  font-weight: 600;
  color: var(--text);
  line-height: 1.2;
}

.kpi-label {
  font-size: 12px;
  font-weight: 500;
  letter-spacing: 0.02em;
  text-transform: uppercase;
  color: var(--text-muted);
  margin-top: 4px;
  display: flex;
  align-items: center;
  gap: 6px;
}

.kpi-secondary {
  font-size: 12px;
  color: var(--text-muted);
  margin-top: 4px;
}

.info-dot {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 14px;
  height: 14px;
  border-radius: 50%;
  border: 1px solid var(--text-muted);
  color: var(--text-muted);
  font-size: 10px;
  cursor: help;
  text-transform: none;
}

.analytics-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
  gap: 20px;
  margin-bottom: 20px;
  align-items: start;
}

.funnel-legend {
  list-style: none;
  padding: 0;
  margin: 8px 0 0;
  font-size: 13px;
}

.funnel-legend li {
  display: flex;
  justify-content: space-between;
  padding: 6px 0;
  border-bottom: 1px solid var(--border);
}

.funnel-legend li:last-child {
  border-bottom: none;
}

.account-health-row {
  margin-bottom: 14px;
}

.account-health-top {
  display: flex;
  justify-content: space-between;
  font-size: 13px;
  margin-bottom: 4px;
}

.campaign-row-link {
  cursor: pointer;
}

.campaign-row-link:hover {
  background: var(--bg);
}

.empty-state {
  text-align: center;
  padding: 32px;
}

.empty-state p {
  margin-bottom: 16px;
  color: var(--text-muted);
}

select:focus-visible,
button:focus-visible,
.campaign-row-link:focus-visible {
  outline: 2px solid var(--brand);
  outline-offset: 1px;
}

@media (max-width: 900px) {
  .analytics-grid {
    grid-template-columns: 1fr;
  }

  .benefits-grid {
    grid-template-columns: repeat(2, 1fr);
  }
}

@media (max-width: 640px) {
  .kpi-grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }

  .analytics-filters {
    position: static;
  }

  .benefits-grid {
    grid-template-columns: 1fr;
  }
}

.pagination-row {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 16px;
}

@media (max-width: 900px) {
  .charts-row {
    grid-template-columns: 1fr;
  }

  .hero-stat {
    border-left: none;
    border-top: 1px solid var(--border);
    padding: 16px 0 0;
    width: 100%;
  }
}

.row-highlight-new {
  animation: row-flash 1.6s ease-out;
}

@keyframes row-flash {
  from {
    background: color-mix(in srgb, var(--brand) 18%, transparent);
  }
  to {
    background: transparent;
  }
}

.banner {
  border-radius: 10px;
  border: 1px solid var(--border);
  border-left-width: 4px;
  padding: 12px 16px;
  margin-bottom: 16px;
  background: var(--bg);
}

.banner p {
  margin: 6px 0 0;
  font-size: 14px;
  color: var(--text-muted);
}

.banner-warning {
  border-left-color: var(--warning);
}

.banner-danger {
  border-left-color: var(--danger);
}

.banner-info {
  border-left-color: var(--info);
}

/* Freemium plan gating (phase 5.15) — the upgrade callout mixes a message
   and a CTA button on one row, unlike the plain text-only banners above. */
.gated-banner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  flex-wrap: wrap;
}

.toast-stack {
  position: fixed;
  top: 16px;
  right: 16px;
  z-index: 1000;
  display: flex;
  flex-direction: column;
  gap: 8px;
  max-width: min(360px, calc(100vw - 32px));
}

.toast {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  padding: 12px 14px;
  border-radius: 10px;
  border: 1px solid var(--border);
  background: var(--surface);
  color: var(--text);
  box-shadow: 0 6px 20px rgba(0, 0, 0, 0.12);
  font-size: 14px;
  animation: toast-in 0.18s ease-out;
}

.toast-success {
  border-left: 3px solid var(--success);
}

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

.toast-message {
  flex: 1;
}

.toast-close {
  background: none;
  border: none;
  color: var(--text-muted);
  cursor: pointer;
  font-size: 14px;
  line-height: 1;
  padding: 0;
}

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

.btn[data-submitting] {
  opacity: 0.7;
  pointer-events: none;
  position: relative;
}

/* Freemium plan gating (phase 5.15) — a disabled action button/span for a
   free-plan user (see app/templates/_gating.html's gate_attrs() macro). */
.btn:disabled,
.btn[disabled],
.btn-disabled {
  opacity: 0.55;
  cursor: not-allowed;
}

.btn[data-submitting]::after {
  content: "";
  display: inline-block;
  width: 12px;
  height: 12px;
  margin-left: 8px;
  border: 2px solid currentColor;
  border-right-color: transparent;
  border-radius: 50%;
  vertical-align: -2px;
  animation: btn-spin 0.6s linear infinite;
}

@keyframes btn-spin {
  to {
    transform: rotate(360deg);
  }
}

@media (prefers-reduced-motion: reduce) {
  * {
    transition: none !important;
  }
}

.saved-lists {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 10px;
  margin-top: 8px;
}

.saved-list-item {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 4px 6px 4px 10px;
  border: 1px solid var(--border);
  border-radius: 999px;
  background: var(--surface-alt, transparent);
}

.saved-list-item form {
  display: inline-flex;
  margin: 0;
}

.btn-icon {
  border: none;
  background: none;
  color: var(--text-muted);
  cursor: pointer;
  font-size: 12px;
  line-height: 1;
  padding: 2px 4px;
  border-radius: 50%;
}

.btn-icon:hover {
  color: var(--danger);
}

/* ---- Settings: two-pane sticky nav (desktop) / accordion (everywhere,
   including no-JS) — see settings_nav.js for the desktop single-open
   enhancement. Each section is a native <details> so it works with zero JS
   as a plain accordion; the nav is just anchor links into that same markup. */
.settings-shell {
  display: flex;
  align-items: flex-start;
  gap: 24px;
}

.settings-nav {
  position: sticky;
  top: 20px;
  width: 232px;
  flex-shrink: 0;
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.settings-nav a {
  display: block;
  padding: 10px 14px;
  border-radius: 8px;
  color: var(--text-muted);
  text-decoration: none;
  font-size: 14px;
  font-weight: 500;
}

.settings-nav a:hover {
  background: var(--surface-2);
  color: var(--text);
}

.settings-nav a.active {
  background: var(--brand-weak);
  color: var(--brand);
}

.settings-panels {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 20px;
}

.settings-panel {
  border: 1px solid var(--border);
  border-radius: 8px;
  background: var(--surface);
}

.settings-panel > summary {
  list-style: none;
  cursor: pointer;
  padding: 20px 24px;
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px;
}

.settings-panel > summary::-webkit-details-marker {
  display: none;
}

.settings-panel-heading h2 {
  margin: 0 0 4px;
  font-size: 18px;
}

.settings-panel-heading p {
  margin: 0;
  font-size: 13px;
  color: var(--text-muted);
}

.settings-panel-caret {
  color: var(--text-muted);
  font-size: 13px;
  flex-shrink: 0;
  transition: transform 0.15s ease;
}

.settings-panel[open] > summary .settings-panel-caret {
  transform: rotate(180deg);
}

.settings-panel-body {
  padding: 0 24px 24px;
  display: flex;
  flex-direction: column;
  gap: 20px;
}

.settings-subcard {
  border: 1px solid var(--border);
  border-radius: 8px;
  background: var(--surface-2);
  padding: 16px 18px;
}

.settings-flow-step {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 13px;
  font-weight: 600;
  color: var(--brand);
  text-transform: uppercase;
  letter-spacing: 0.02em;
  margin-bottom: 4px;
}

@media (max-width: 900px) {
  .settings-shell {
    display: block;
  }

  /* A horizontally-scrollable single-row tab strip, not a wrapped pill
     grid — 8 nav items of very different label lengths wrap unevenly across
     lines at this width, which reads as messy rather than "clean and
     scannable" (the actual per-section content is already a native
     <details> accordion regardless of how this nav is laid out). */
  .settings-nav {
    position: static;
    width: 100%;
    flex-direction: row;
    flex-wrap: nowrap;
    overflow-x: auto;
    margin-bottom: 20px;
    padding-bottom: 4px;
  }

  .settings-nav a {
    white-space: nowrap;
    flex-shrink: 0;
  }
}

/* Sending schedule (phase 5.11) */
.schedule-day-checkboxes {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
}

.schedule-day-checkbox {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-weight: 400;
  cursor: pointer;
}

.schedule-day-checkbox input {
  width: auto;
}

.schedule-time-row {
  display: flex;
  gap: 16px;
  flex-wrap: wrap;
}

.schedule-time-row > div {
  flex: 1;
  min-width: 140px;
}
