: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;
  --violet: #6B4FC0;
  /* Two extra stat-tile tones so a 6-tile row (outreach campaign detail)
     can give every tile its own hue. Checked with the dataviz skill's
     validate_palette.js in the tile order green/blue/amber/teal/violet/rose
     (normal-vision and CVD separation pass; every tile carries a text label). */
  --teal: #008A9E;
  --rose: #C2477F;
  /* 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));
  /* Tint depth raised 14/16 -> 18/20 (2026-09-07): the old mixes were so
     pale that status chips, tiles and banners read as grey. Re-checked
     against the WCAG script - the *-text tokens still clear 4.5:1 on the
     new backgrounds in both themes. */
  --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));
  --violet-weak: color-mix(in srgb, var(--violet) 18%, var(--surface));
  --teal-weak: color-mix(in srgb, var(--teal) 20%, var(--surface));
  --rose-weak: color-mix(in srgb, var(--rose) 20%, var(--surface));
  /* Hairline in a status colour's own hue - for chips/tiles that need to
     read as a distinct pill/card without touching the fill/text contrast. */
  --brand-line: color-mix(in srgb, var(--brand) 42%, var(--surface));
  --success-line: color-mix(in srgb, var(--success) 42%, var(--surface));
  --warning-line: color-mix(in srgb, var(--warning) 42%, var(--surface));
  --danger-line: color-mix(in srgb, var(--danger) 42%, var(--surface));
  --info-line: color-mix(in srgb, var(--info) 42%, var(--surface));
  /* Text-on-tint variants for status chips/findings (e.g. .chip-active,
     .finding-warn) - NOT the same as --success/--warning/--danger/--info
     above, which stay untouched for icons/borders/solid fills. Measured with
     a WCAG contrast script: the plain status color on its own X-weak
     background is only 2.66-4.26:1 in light mode (fails the 4.5:1 AA floor
     for 13px chip text) and 3.91-4.12:1 in dark mode for 3 of the 4 colors -
     darkening (light) / lightening (dark) by a fixed 30% mix reliably clears
     4.5:1 for all four with room to spare, verified per-color, not guessed. */
  --success-text: color-mix(in srgb, var(--success) 70%, black);
  --warning-text: color-mix(in srgb, var(--warning) 70%, black);
  --danger-text: color-mix(in srgb, var(--danger) 70%, black);
  --info-text: color-mix(in srgb, var(--info) 70%, black);
  --brand-text: color-mix(in srgb, var(--brand) 72%, black);
  --violet-text: color-mix(in srgb, var(--violet) 72%, black);
  --teal-text: color-mix(in srgb, var(--teal) 70%, black);
  --rose-text: color-mix(in srgb, var(--rose) 70%, black);
  /* 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;

  /* =========================================================================
     Design-system token layer (admin-panel-table-view-guidelines.md).
     Three tiers: primitives (neutral ramp) -> semantic roles -> scales.
     The base tokens above (--text, --brand, --surface, --border, --success,
     ...) stay as-is and are treated as semantic roles too; the roles below
     are additive aliases/derivations so no existing rule breaks. Anything
     theme-dependent is redefined in both dark blocks further down; the
     scale tokens (space/radius/type/font) are theme-independent and live
     here only.
     ========================================================================= */

  /* Primitives - one neutral ramp, 11 stops (spec 2.1.1). ~90% of the UI. */
  --neutral-0:  #FFFFFF;
  --neutral-50: #F6F7F5;
  --neutral-100:#EDEFEB;
  --neutral-200:#E3E6E1;
  --neutral-300:#CFD4CD;
  --neutral-400:#A7AFA5;
  --neutral-500:#7C857A;
  --neutral-600:#5A6577;
  --neutral-700:#414B57;
  --neutral-800:#2A333F;
  --neutral-900:#1A2233;

  /* Semantic roles - surfaces (spec 2.2.1). Elevation = surface level + a
     hairline border, never a shadow (2.2.2). */
  --layer-0: var(--bg);          /* page canvas */
  --layer-1: var(--surface-2);   /* subtle fill, hover, metric cards */
  --layer-2: var(--surface);     /* cards, panels, table body */
  --layer-3: var(--surface);     /* popovers, menus, dropdowns (shadow-lifted) */

  /* Semantic roles - text (spec 2.4). Never dim text with opacity (2.4.3). */
  --text-primary: var(--text);
  --text-secondary: var(--text-muted);
  --text-faint: color-mix(in srgb, var(--text-muted) 60%, var(--surface));

  /* Semantic roles - boundaries. --border stays the decorative hairline;
     --border-strong is for boundaries that must carry meaning at >=3:1
     (input borders, toggles, chart keys - spec 2.4.2). */
  --border-strong: color-mix(in srgb, var(--border) 45%, var(--text-muted));

  /* Semantic roles - focus + selection (spec 2.5). */
  --focus-ring: var(--brand);
  --selected-bg: var(--brand-weak);

  /* Status triads - pale bg / readable text / hairline border (spec 2.1.3).
     Aliases over the existing *-weak / *-text tokens + the solid hue. */
  --bg-success: var(--success-weak);   --fg-success: var(--success-text);   --bd-success: var(--success);
  --bg-warning: var(--warning-weak);   --fg-warning: var(--warning-text);   --bd-warning: var(--warning);
  --bg-danger:  var(--danger-weak);    --fg-danger:  var(--danger-text);    --bd-danger:  var(--danger);
  --bg-info:    var(--info-weak);      --fg-info:    var(--info-text);       --bd-info:    var(--info);

  /* Spacing scale - base unit 4px, nothing between (spec 1.4 / 3.1). */
  --space-1: 4px;
  --space-2: 8px;
  --space-3: 12px;
  --space-4: 16px;
  --space-5: 24px;
  --space-6: 32px;
  --space-7: 48px;
  --space-8: 64px;

  /* Radii (spec 3.3.1). */
  --radius-control: 6px;   /* buttons, inputs, chips-as-controls */
  --radius-card: 10px;     /* cards, table containers */
  --radius-pill: 999px;    /* pills + status chips only */

  /* Shadows - floating layers only (spec 2.2.2). Single source of truth for
     the three raw rgba shadows the app is allowed to keep. */
  --shadow-popover: 0 4px 12px rgba(15, 20, 26, 0.12);
  --shadow-dialog:  0 8px 32px rgba(15, 20, 26, 0.28);
  --shadow-toast:   0 6px 20px rgba(15, 20, 26, 0.16);

  /* Type scale (spec 3.2). Two weights only: 400 and 500 (3.2.1). */
  --fs-caption: 11px;   /* column hints, dense timestamps */
  --fs-footnote: 12px;  /* badges, helper text, pagination meta, IDs */
  --fs-table: 13px;     /* table cell + header content */
  --fs-body: 14px;      /* form labels, buttons, sidebar items */
  --fs-prose: 16px;     /* descriptions, empty-state body */
  --fs-h3: 16px;
  --fs-h2: 20px;
  --fs-h1: 24px;

  --lh-tight: 1.4;   /* table cells */
  --lh-ui: 1.5;      /* UI text */
  --lh-prose: 1.65;  /* prose */

  --font-heading: "Space Grotesk", system-ui, sans-serif;
  --font-body: "Inter", system-ui, sans-serif;
  --font-mono: "JetBrains Mono", ui-monospace, monospace;

  /* Shell (spec 3.5.2 / 3.5.3). */
  --nav-width: 240px;
  --nav-width-collapsed: 64px;
  --topbar-height: 56px;
}

/* 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) 20%, var(--surface));
    --success-weak: color-mix(in srgb, var(--success) 22%, var(--surface));
    --warning-weak: color-mix(in srgb, var(--warning) 22%, var(--surface));
    --danger-weak: color-mix(in srgb, var(--danger) 22%, var(--surface));
    --info-weak: color-mix(in srgb, var(--info) 22%, var(--surface));
    --brand-line: color-mix(in srgb, var(--brand) 50%, var(--surface));
    --success-line: color-mix(in srgb, var(--success) 50%, var(--surface));
    --warning-line: color-mix(in srgb, var(--warning) 50%, var(--surface));
    --danger-line: color-mix(in srgb, var(--danger) 50%, var(--surface));
    --info-line: color-mix(in srgb, var(--info) 50%, var(--surface));
    /* Lightened (not darkened) here, unlike the light-theme block above -
       dark mode's weak background stays close to the dark surface, so the
       chip text needs to move further from --text toward white to keep
       4.5:1, the opposite direction from light mode. Same 30% mix depth,
       verified separately for dark. */
    --success-text: color-mix(in srgb, var(--success) 70%, white);
    --warning-text: color-mix(in srgb, var(--warning) 70%, white);
    --danger-text: color-mix(in srgb, var(--danger) 70%, white);
    --info-text: color-mix(in srgb, var(--info) 70%, white);
    --brand-text: color-mix(in srgb, var(--brand) 72%, white);
    --violet: #9D8BEA;
    --violet-weak: color-mix(in srgb, var(--violet) 22%, var(--surface));
    --violet-text: color-mix(in srgb, var(--violet) 70%, white);
    --teal: #1FA0B2;
    --teal-weak: color-mix(in srgb, var(--teal) 22%, var(--surface));
    --teal-text: color-mix(in srgb, var(--teal) 70%, white);
    --rose: #E36D9F;
    --rose-weak: color-mix(in srgb, var(--rose) 22%, var(--surface));
    --rose-text: color-mix(in srgb, var(--rose) 70%, white);
    --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;
    /* Neutral ramp inverted for dark (spec 2.1.1) - 0 = darkest. Every other
       role token below is derived via var()/color-mix() from tokens already
       redefined in this block, so only the ramp needs an explicit override. */
    --neutral-0:  #14181E;
    --neutral-50: #1A1F26;
    --neutral-100:#1E242C;
    --neutral-200:#2E3742;
    --neutral-300:#3C4654;
    --neutral-400:#566173;
    --neutral-500:#7C8695;
    --neutral-600:#9AA3AF;
    --neutral-700:#BEC5CE;
    --neutral-800:#DADEE3;
    --neutral-900:#E7E9EC;
  }
}

: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) 20%, var(--surface));
  --success-weak: color-mix(in srgb, var(--success) 22%, var(--surface));
  --warning-weak: color-mix(in srgb, var(--warning) 22%, var(--surface));
  --danger-weak: color-mix(in srgb, var(--danger) 22%, var(--surface));
  --info-weak: color-mix(in srgb, var(--info) 22%, var(--surface));
  --brand-line: color-mix(in srgb, var(--brand) 50%, var(--surface));
  --success-line: color-mix(in srgb, var(--success) 50%, var(--surface));
  --warning-line: color-mix(in srgb, var(--warning) 50%, var(--surface));
  --danger-line: color-mix(in srgb, var(--danger) 50%, var(--surface));
  --info-line: color-mix(in srgb, var(--info) 50%, var(--surface));
  --success-text: color-mix(in srgb, var(--success) 70%, white);
  --warning-text: color-mix(in srgb, var(--warning) 70%, white);
  --danger-text: color-mix(in srgb, var(--danger) 70%, white);
  --info-text: color-mix(in srgb, var(--info) 70%, white);
  --brand-text: color-mix(in srgb, var(--brand) 72%, white);
  --violet: #9D8BEA;
  --violet-weak: color-mix(in srgb, var(--violet) 22%, var(--surface));
  --violet-text: color-mix(in srgb, var(--violet) 70%, white);
  --teal: #1FA0B2;
  --teal-weak: color-mix(in srgb, var(--teal) 22%, var(--surface));
  --teal-text: color-mix(in srgb, var(--teal) 70%, white);
  --rose: #E36D9F;
  --rose-weak: color-mix(in srgb, var(--rose) 22%, var(--surface));
  --rose-text: color-mix(in srgb, var(--rose) 70%, white);
  --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;
  --neutral-0:  #14181E;
  --neutral-50: #1A1F26;
  --neutral-100:#1E242C;
  --neutral-200:#2E3742;
  --neutral-300:#3C4654;
  --neutral-400:#566173;
  --neutral-500:#7C8695;
  --neutral-600:#9AA3AF;
  --neutral-700:#BEC5CE;
  --neutral-800:#DADEE3;
  --neutral-900:#E7E9EC;
}

* {
  box-sizing: border-box;
}

body {
  margin: 0;
  background: var(--bg);
  color: var(--text);
  font-family: var(--font-body);
  font-size: var(--fs-body);
  line-height: var(--lh-ui);
}

/* Two weights only across the panel: 400 and 500. Headings and numeric
   displays get 500; heavy weights read as noise in dense UI (spec 3.2.1). */
h1, h2, h3 {
  font-family: var(--font-heading);
  font-weight: 500;
  line-height: var(--lh-ui);
  margin: 0 0 var(--space-4);
}

h1 { font-size: var(--fs-h1); }
h2 { font-size: var(--fs-h2); }
h3 { font-size: var(--fs-h3); }

/* 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: var(--font-mono);
  font-size: var(--fs-body);
}

/* Small secondary/meta text and inline form labels. Sentence case, no
   ALL-CAPS, no letter-spacing tricks (spec 3.2.3). */
.label {
  font-size: var(--fs-table);
  font-weight: 500;
  color: var(--text-secondary);
}

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

.brand {
  font-family: var(--font-heading);
  font-weight: 500;
  font-size: var(--fs-h3);
  color: var(--text);
  text-decoration: none;
  display: inline-flex;
  align-items: center;
}

/* Muhtelix logo lockup - two <img>s from _brand.html's brand_logo() macro,
   full-colour for light surfaces, all-white for dark. Toggled purely in CSS
   so it follows the same [data-theme] / prefers-color-scheme logic as every
   other token here. */
.brand-logo {
  height: 26px;
  width: auto;
  display: block;
}
.brand-logo-dark { display: none; }
:root[data-theme="dark"] .brand-logo-light { display: none; }
:root[data-theme="dark"] .brand-logo-dark { display: block; }
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .brand-logo-light { display: none; }
  :root:not([data-theme="light"]) .brand-logo-dark { display: block; }
}

.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: var(--nav-width);
  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;
  transition: width 0.15s ease;
}

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

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

/* Desktop-only collapse toggle (spec 3.5.2). Hidden on mobile, where the
   off-canvas drawer takes over instead. */
.sidebar-collapse-btn {
  display: none;
  min-height: 32px;
  padding: 4px 10px;
}
@media (min-width: 1101px) {
  .sidebar-collapse-btn { display: inline-flex; }
}

/* Collapsed rail: icons only, labels via native tooltip (the title attr on
   each link / the toggle button) - a group's sub-items become a hover/focus
   flyout instead (see .nav-flyout below). Scoped to desktop - the drawer
   owns the sub-1100px case. */
@media (min-width: 1101px) {
  :root[data-sidebar-collapsed] .sidebar { width: var(--nav-width-collapsed); }
  :root[data-sidebar-collapsed] .sidebar .brand { display: none; }
  :root[data-sidebar-collapsed] .sidebar-header { justify-content: center; padding-left: 0; padding-right: 0; }
  :root[data-sidebar-collapsed] .sidebar-nav { padding: 8px; }
  :root[data-sidebar-collapsed] .sidebar-nav a,
  :root[data-sidebar-collapsed] .nav-group-btn {
    justify-content: center;
    gap: 0;
    font-size: 0;
  }
  :root[data-sidebar-collapsed] .sidebar-nav a .nav-icon,
  :root[data-sidebar-collapsed] .nav-group-btn .nav-icon { font-size: 1rem; }
  :root[data-sidebar-collapsed] .sidebar-nav a .nav-status-chip,
  :root[data-sidebar-collapsed] .nav-chevron,
  :root[data-sidebar-collapsed] .nav-group-items,
  :root[data-sidebar-collapsed] .nav-group-dot,
  :root[data-sidebar-collapsed] .sidebar-footer-row .lang-switch,
  :root[data-sidebar-collapsed] #reveal-all-sender-emails-row,
  :root[data-sidebar-collapsed] .onboarding-checklist { display: none; }
  :root[data-sidebar-collapsed] .sidebar-logout { font-size: 0; text-align: center; }
  :root[data-sidebar-collapsed] .sidebar-logout::before { content: "\2192"; font-size: 1rem; }
  :root[data-sidebar-collapsed] .sidebar-footer { padding: 12px 8px; align-items: center; }
  :root[data-sidebar-collapsed] .sidebar-collapse-btn { transform: scaleX(-1); }

  /* A group's flyout is only ever reachable in rail mode - undo the
     font-size:0/centering above just for the menu that pops out of it. */
  :root[data-sidebar-collapsed] .nav-group:hover .nav-flyout,
  :root[data-sidebar-collapsed] .nav-group:focus-within .nav-flyout {
    display: flex;
  }
  :root[data-sidebar-collapsed] .nav-flyout a {
    font-size: 13.5px;
    justify-content: flex-start;
    gap: 8px;
  }
  :root[data-sidebar-collapsed] .nav-flyout a .nav-icon { font-size: 1rem; }
}

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

.sidebar-nav a,
.nav-group-btn {
  display: flex;
  align-items: center;
  gap: 10px;
  width: 100%;
  padding: 10px 12px;
  border: none;
  border-radius: 8px;
  background: none;
  color: var(--text-muted);
  text-decoration: none;
  font-size: 14px;
  font-weight: 500;
  font-family: inherit;
  text-align: left;
  cursor: pointer;
}

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

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

/* ---- Nav groups: an accordion of related pages under one row, so the
   sidebar gains a new sub-item instead of a new top-level icon as the
   product grows (see app/nav.py). ---- */

.nav-group {
  position: relative;
}

.nav-group-divider {
  margin-top: var(--space-2);
  padding-top: var(--space-2);
  border-top: 1px solid var(--border);
}

.nav-group-dot {
  position: absolute;
  left: 6px;
  top: 8px;
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--brand);
  display: none;
}

.nav-group.has-active-child:not(.open) .nav-group-dot {
  display: block;
}

.nav-chevron {
  width: 14px;
  height: 14px;
  flex-shrink: 0;
  margin-left: auto;
  color: var(--text-faint);
  transition: transform 0.16s ease;
}

.nav-group.open > .nav-group-btn .nav-chevron {
  transform: rotate(90deg);
}

/* grid-template-rows 0fr/1fr is the collapse trick that animates to a
   real "auto" height instead of a guessed max-height. */
.nav-group-items {
  display: grid;
  grid-template-rows: 0fr;
  transition: grid-template-rows 0.18s ease;
}

.nav-group.open .nav-group-items {
  grid-template-rows: 1fr;
}

.nav-group-items-inner {
  overflow: hidden;
  display: flex;
  flex-direction: column;
  gap: 1px;
}

/* Selector needs to be at least as specific as ".sidebar-nav a" above (one
   class + one type) for these overrides to actually win - a bare
   ".nav-subitem" class selector would lose the padding/border-radius/
   font-size cascade to that rule regardless of source order. */
a.nav-subitem {
  padding-left: 14px;
  margin-left: 23px;
  border-left: 1px solid var(--border);
  border-radius: 0 8px 8px 0;
  font-size: 13.5px;
}

a.nav-subitem.active {
  border-left-color: var(--brand);
}

.nav-subitem .nav-icon {
  width: 16px;
  height: 16px;
}

/* Rail-mode-only flyout menu for a group's sub-items - see the collapsed
   rail media query above for when this is actually shown. */
.nav-flyout {
  display: none;
  position: absolute;
  left: calc(100% + 8px);
  top: 0;
  min-width: 208px;
  flex-direction: column;
  gap: 1px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-card);
  box-shadow: var(--shadow-popover);
  padding: 6px;
  z-index: 30;
}

.nav-flyout-label {
  padding: 6px 10px 4px;
  font-size: var(--fs-footnote);
  font-weight: 600;
  letter-spacing: 0.03em;
  text-transform: uppercase;
  color: var(--text-faint);
}

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

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

.nav-status-chip {
  margin-left: auto;
}

.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;
}

.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-text);
}

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

.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: var(--space-3);
  height: var(--topbar-height);
  padding: 0 var(--space-4);
  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;
}

/* Form / settings pages read better capped narrow (spec 3.5.4). Table pages
   keep the full fluid width. */
.container-narrow {
  max-width: 720px;
}

.card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-card);
  /* Elevation is a surface level + a hairline border, not a shadow - shadows
     are reserved for floating layers (popover/dialog/toast), spec 2.2.2. */
  padding: var(--space-5);
  /* 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;
}

/* A .card hosting a toggle-opened popover (.multiselect-panel - see
   _template_multiselect.html / the Scans filter on outreach_campaign_new)
   must never establish its own scroll/clip context. Per the CSS overflow
   spec, an element with overflow-x:auto and no overflow-y set (or
   overflow-y explicitly 'visible') has its overflow-y silently promoted to
   'auto' too - the two axes can't disagree once one of them isn't
   'visible'. The open panel is position:absolute, so it still counts
   toward this card's *scrollable* height even though it never affects the
   card's own *auto* height (absolute children don't contribute to normal
   flow sizing) - the panel ends up visually cut off at the card's in-flow
   content height, with a second, confusing scrollbar to reach the rest of
   it stacked right next to the panel's own internal list scroll (a real
   bug: three stacked scrollbars on the outreach "İçerik" template picker).
   Setting both axes to 'visible' together sidesteps the mismatch that
   triggers the promotion. A card using this class gives up the .card
   horizontal safety-net above - wrap any wide table inside it with
   .table-scroll instead. */
/* Generic modal (outreach_step_modal.js) - lazy-loaded content injected into
   .modal-body on click, kept out of the initial page render entirely (see
   CLAUDE.md's Sequences Note addendum on the Takip Mailleri/Kayıtlar move).
   z-index above the mobile sidebar drawer's own 55/60 stack (see
   .sidebar-backdrop above) so it's never hidden behind an open drawer. */
.modal-overlay {
  position: fixed;
  inset: 0;
  background: rgba(15, 20, 26, 0.55);
  z-index: 200;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 24px;
}

.modal-overlay[hidden] {
  display: none;
}

.modal-dialog {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 8px;
  box-shadow: var(--shadow-dialog);
  width: 100%;
  max-width: 920px;
  max-height: 85vh;
  display: flex;
  flex-direction: column;
  overflow: hidden;
}

.modal-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 18px 20px;
  border-bottom: 1px solid var(--border);
  flex-shrink: 0;
}

.modal-header h3 {
  margin: 0;
}

.modal-body {
  padding: 20px;
  overflow-y: auto;
  /* A job/enrollment table (many columns) is wider than the dialog's own
     max-width on anything but a very wide viewport - scroll it within the
     modal instead of letting .modal-dialog's overflow:hidden (needed for
     its rounded corners) silently clip the trailing columns off-screen. */
  overflow-x: auto;
}

.modal-body table {
  margin: 0;
}

body.modal-open {
  overflow: hidden;
}

.link-button {
  background: none;
  border: none;
  padding: 0;
  font: inherit;
  color: var(--brand);
  cursor: pointer;
  text-align: left;
}

.link-button:hover {
  text-decoration: underline;
}

.card-overlay-safe {
  overflow: visible;
}

.table-scroll {
  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;
  }
}

/* Control sizes (spec 3.3): default 36, small 28. Radius 6 for controls. */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 36px;
  border-radius: var(--radius-control);
  padding: 0 var(--space-4);
  font-size: var(--fs-body);
  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;
}

.btn-small {
  min-height: 28px;
  padding: 0 var(--space-3);
  font-size: var(--fs-footnote);
}

/* 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;
}

/* =========================================================================
   Tables (admin-panel-table-view-guidelines.md §2.3, §3.4, §4, §5, §9, §13).
   Bare <table> keeps working (restyled) for pages not yet migrated to the
   _table.html macros; `.data-table` layers on density, a sticky header,
   sort-button headers, row selection and the <768px stacked-card fallback.
   ========================================================================= */

table {
  width: 100%;
  border-collapse: collapse;
  font-size: var(--fs-table);
  line-height: var(--lh-tight);
}

th {
  text-align: left;
  padding: var(--space-2) var(--space-3);
  font-size: var(--fs-table);
  font-weight: 500;
  /* Sentence case, no ALL-CAPS, no letter-spacing (spec 3.2.3). */
  color: var(--text-secondary);
  background: var(--layer-1);
  border-bottom: 1px solid var(--border);
  min-width: 90px;
}

td {
  padding: var(--space-3);
  border-bottom: 1px solid var(--border);
  overflow-wrap: anywhere;
  min-width: 90px;
  /* Center content up to ~3 lines (spec 4.2.1); rows with taller content
     opt into top alignment with `.align-top` (spec 4.2.2). */
  vertical-align: middle;
}

/* No zebra striping (spec 2.3.4): row separation is the hairline above.
   Row background is reserved for interaction state (spec 2.3.3). */
tbody tr:hover td {
  background: color-mix(in srgb, var(--brand) 5%, var(--layer-2));
}

/* ---- Alignment utilities (spec 4.1 / 5.1) - usable on bare tables too ---- */
.col-text  { text-align: left; }
.col-num   { text-align: right; font-variant-numeric: tabular-nums; }
.col-id    { text-align: left; font-family: var(--font-mono); font-size: var(--fs-footnote); color: var(--text-secondary); }
th.col-num { text-align: right; }
.align-top td, td.align-top { vertical-align: top; }
.cell-null { color: var(--text-faint); }

/* ---- .data-table: macro-driven table system ---- */
.data-table-wrap {
  overflow-x: auto;
  overflow-y: visible;
  border: 1px solid var(--border);
  border-radius: var(--radius-card);
  background: var(--layer-2);
}

.data-table {
  width: 100%;
  border-collapse: separate;
  border-spacing: 0;
  font-size: var(--fs-table);
  line-height: var(--lh-tight);
}

.sr-only,
table caption {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
  border: 0;
}
.data-table caption.caption-visible {
  position: static;
  width: auto;
  height: auto;
  margin: 0;
  clip: auto;
  text-align: left;
  padding: var(--space-3) var(--space-4);
  color: var(--text-secondary);
  font-size: var(--fs-footnote);
}

.data-table thead th {
  position: sticky;
  top: 0;
  z-index: 2;
  background: var(--layer-1);
  border-bottom: 1px solid var(--border-strong);
  text-align: left;
  font-weight: 500;
  color: var(--text-secondary);
  white-space: nowrap;
  padding: var(--space-2) var(--space-3);
}
.data-table thead th.col-num { text-align: right; }
.data-table thead th:first-child,
.data-table tbody td:first-child { padding-left: var(--space-4); }
.data-table thead th:last-child,
.data-table tbody td:last-child { padding-right: var(--space-4); }

.data-table tbody td {
  padding: var(--space-3);
  border-bottom: 1px solid var(--border);
  vertical-align: middle;
  color: var(--text-primary);
}
.data-table tbody tr:last-child td { border-bottom: 0; }

/* Required row states, all visually distinct (spec 8.2). */
.data-table tbody tr:hover td { background: color-mix(in srgb, var(--brand) 5%, var(--layer-2)); }
.data-table tbody tr:focus-within td { background: color-mix(in srgb, var(--brand) 7%, var(--layer-2)); }
.data-table tbody tr[aria-selected="true"] td { background: var(--selected-bg); }
.data-table tbody tr[aria-selected="true"]:hover td { background: color-mix(in srgb, var(--brand) 24%, var(--layer-2)); }
.data-table tbody tr[aria-disabled="true"] td { color: var(--text-faint); }
.data-table tbody tr[data-row-link] { cursor: pointer; }
.data-table tbody tr.row-updated td { animation: row-flash 1.6s ease-out; }

/* Column alignment inside .data-table (spec 4.1). No centered data columns -
   only .col-utility (a lone checkbox or status dot) centers (spec 4.1.4). */
.data-table .col-num { text-align: right; font-variant-numeric: tabular-nums; }
.data-table .col-utility { text-align: center; width: 40px; padding-left: var(--space-2); padding-right: var(--space-2); }
.data-table .col-actions { width: 48px; }

/* Sort headers (spec 9.1/9.2): a real button filling the cell; the arrow
   pair sits inside the header's alignment and never breaks its edge (spec
   4.1.6). Shared by server-sorted (.data-table, ?sort=) and client-sorted
   (app/static/js/table_sort.js, any table) headers. Both arrows always show
   so a sortable column is recognizable; the active direction is the one in
   brand colour: up = ascending (A-Z, small to large, old to new), down =
   descending. */
th .sort-btn {
  display: inline-flex;
  align-items: center;
  gap: var(--space-1);
  width: 100%;
  background: none;
  border: 0;
  padding: 0;
  margin: 0;
  font: inherit;
  color: inherit;
  cursor: pointer;
  text-align: inherit;
}
th.col-num .sort-btn,
th .sort-btn.sort-btn-end { flex-direction: row-reverse; }
th .sort-btn:focus-visible { outline: 2px solid var(--focus-ring); outline-offset: 2px; border-radius: 2px; }
th .sort-btn:hover { color: var(--text-primary); }
th .sort-arrows {
  display: inline-flex;
  flex-shrink: 0;
  gap: 1px;
  font-size: 13px;
  line-height: 1;
  font-weight: 700;
  color: var(--text-secondary);
}
th .sort-arrow { opacity: 0.45; transition: opacity 0.12s ease, color 0.12s ease; }
th .sort-btn:hover .sort-arrow { opacity: 0.8; }
th[aria-sort="ascending"] .sort-arrow-up,
th[aria-sort="descending"] .sort-arrow-down { opacity: 1; color: var(--brand); }
th[aria-sort="ascending"] .sort-arrow-down,
th[aria-sort="descending"] .sort-arrow-up { opacity: 0.2; }
th[aria-sort="ascending"],
th[aria-sort="descending"] { color: var(--text-primary); }

/* Density (spec 3.4) - root attribute set pre-paint from localStorage. */
:root[data-table-density="compact"] .data-table tbody td,
:root[data-table-density="compact"] .data-table thead th {
  padding-top: var(--space-2);
  padding-bottom: var(--space-2);
}
:root[data-table-density="relaxed"] .data-table tbody td,
:root[data-table-density="relaxed"] .data-table thead th {
  padding-top: var(--space-4);
  padding-bottom: var(--space-4);
}

/* Freeze the identifying column in a horizontal-scroll table (spec 6.5). */
.data-table .col-freeze { position: sticky; left: 0; z-index: 1; background: var(--layer-2); }
.data-table thead .col-freeze { z-index: 3; background: var(--layer-1); }
.data-table-wrap.is-scrolled .col-freeze { box-shadow: 6px 0 8px -6px rgba(15, 20, 26, 0.25); }

/* ---- Shared dense table look for every .data-table: one type scale (13px
   body, 12px secondary, 12px/500 header), rows capped at ~2 lines, anything
   longer clamped and opened on click (.cell-clamp, app/static/js/cell_clamp.js;
   plain-text cells are wrapped automatically by expandable_text.js).
   `.fixed-cols` is added by the data_table macro when every column has a px
   width: fixed layout, min-width = the sum of those widths. ---- */
.data-table { font-size: 13px; line-height: 1.4; font-feature-settings: "tnum" 1; }
.data-table.fixed-cols { table-layout: fixed; }
.data-table thead th {
  font-size: 12px;
  font-weight: 500;
  color: var(--text-secondary);
  padding: 8px 12px;
  height: 40px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  min-width: 0;
}
.data-table thead th .sort-btn { width: auto; max-width: 100%; }
.data-table thead th .sort-btn > span:first-child { overflow: hidden; text-overflow: ellipsis; }
.data-table tbody td {
  padding: 8px 12px;
  min-width: 0;
  font-size: 13px;
  font-weight: 400;
  overflow-wrap: anywhere;
}
.data-table.fixed-cols tbody td { overflow: hidden; }
/* Empty-state row spans every column of a wide table: keep its message in view
   while the table scrolls sideways instead of centering it across the full width. */
.data-table.fixed-cols tbody td[colspan] { overflow: visible; }
.data-table td[colspan] > .table-empty { position: sticky; left: 0; width: min(100%, 720px); box-sizing: border-box; }
.data-table td.col-num { text-align: right; color: var(--text-secondary); }
.data-table th.col-num .sort-btn { justify-content: flex-end; }
.data-table .col-nowrap { white-space: nowrap; font-variant-numeric: tabular-nums; color: var(--text-secondary); }
.data-table .cell-null { color: var(--text-faint); }
.data-table tbody td .label,
.data-table .cell-meta {
  font-size: 12px;
  font-weight: 400;
  color: var(--text-secondary);
}
.data-table .cell-meta { margin: 2px 0 0; }
.data-table tbody td .chip {
  font-size: 11.5px;
  font-weight: 500;
  line-height: 1.5;
  padding: 1px 8px;
  border-radius: 6px;
}
.data-table .btn-icon { font-size: 12px; padding: 0 3px; }

/* Links in cells read as text until hovered; inline editors match the 13px scale. */
.data-table tbody td a:not(.btn):not(.chip) { text-decoration: none; }
.data-table tbody td a:not(.btn):not(.chip):hover { text-decoration: underline; }
.data-table tbody td select,
.data-table tbody td input[type="date"],
.data-table tbody td input[type="text"] {
  height: 28px;
  padding: 0 8px;
  font-size: 12px;
  border-radius: 6px;
  max-width: 100%;
  box-sizing: border-box;
}

/* Single-line value with ellipsis (full text in the title tooltip). */
.data-table .cell-ellipsis,
.data-table .cell-primary {
  display: block;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.data-table .cell-primary { font-size: 13px; font-weight: 500; color: var(--text-primary); }
.data-table .cell-badges { display: flex; flex-wrap: nowrap; gap: 4px; margin-top: 4px; overflow: hidden; }
.data-table .cell-badges:empty { display: none; }
.data-table .cell-badges .chip { flex: 0 0 auto; }
.data-table .cell-meta span + span::before { content: " · "; }
.data-table .cell-meta .lead-contact-line { display: inline; margin: 0; }

/* Clamp to N lines (data-clamp-lines 1 or 2, default 2); click opens it. */
.cell-clamp {
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
  overflow: hidden;
  white-space: normal;
  word-break: break-word;
}
.cell-clamp[data-clamp-lines="1"] { -webkit-line-clamp: 1; }
.cell-clamp.is-overflowing { cursor: pointer; }
.cell-clamp.is-overflowing:hover { color: var(--text-primary); }
.cell-clamp.is-open {
  display: block;
  -webkit-line-clamp: unset;
  overflow: visible;
  cursor: pointer;
}

/* /leads grid: top-aligned rows with a 56px floor. */
.leads-table tbody td { vertical-align: top; }
.leads-table tbody tr { height: 56px; }
.leads-table tbody tr:has(.cell-clamp.is-open) { height: auto; }
.leads-table td.col-utility,
.leads-table th.col-utility { vertical-align: top; padding-top: 12px; }
.leads-table td.col-num { padding-top: 10px; }
.leads-table td.lead-detail-cell { white-space: normal; max-width: none; }
@media (max-width: 768px) {
  .data-table-wrap.stack-cards .data-table { min-width: 0 !important; }
}

/* Table row action clusters: a horizontal, wrapping group of small buttons /
   inline forms with an even gap, so a row's actions never run together or
   spill past their cell. Applies everywhere .row-actions is used (list pages,
   _*_row.html partials, the alt-sources table). */
.row-actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-2);
}
.row-actions .form-inline { display: inline-flex; margin: 0; }
/* `.btn` / `.form-inline` set an explicit `display`, which beats the UA
   `[hidden] { display: none }` rule at equal specificity - so `el.hidden =
   true` on a button or an inline action form (source_run.html's Stop /
   "view leads" toggles) would silently do nothing without this. Same cascade
   pitfall already documented for .multiselect-option / .pagination-row. */
.btn[hidden],
.form-inline[hidden] { display: none !important; }

/* Alt-sources "run now" launcher: the per-run candidate-limit input sitting
   next to the run button (see _user_source_row.html). */
.source-run-launch { display: inline-flex; align-items: center; gap: var(--space-2); flex-wrap: wrap; }
.source-run-limit { display: inline-flex; align-items: center; gap: var(--space-1); }
.source-run-limit input { width: 76px; }

/* Fabrika Taraması "Brave limiti nedeniyle taranmadı" card: the count text
   on the left, "Devam et" / "Durdur" beside it (see fabrika_list.html). */
.search-retry-row { display: flex; align-items: center; justify-content: space-between; gap: var(--space-3); flex-wrap: wrap; }
.search-retry-text { flex: 1 1 320px; min-width: 0; }
.search-retry-text > p:first-child { margin-top: 0; color: var(--text); font-weight: 600; }
.search-retry-progress { margin-top: var(--space-2); }
.search-retry-progress .progress-bar { max-width: 360px; }

/* Campaign list "Kaynak" (discovery source) cell: a comma-joined provider
   list wraps between words, never mid-word (the blanket `td { overflow-wrap:
   anywhere }` would otherwise split "OpenStreetMap" as "OpenStree tMap"). */
.data-table td.campaign-source-cell { overflow-wrap: normal; word-break: normal; }

/* Hover-revealed row actions (spec 8.3) - always visible on touch. */
.data-table td.col-actions .row-actions { visibility: hidden; }
.data-table tbody tr:hover td.col-actions .row-actions,
.data-table tbody tr:focus-within td.col-actions .row-actions { visibility: visible; }
@media (hover: none) {
  .data-table td.col-actions .row-actions { visibility: visible; }
}

/* Stacked-card fallback below 768px (spec 12.1/12.3) - priority fields +
   detail. Row keeps table semantics via role overrides in the macro. */
@media (max-width: 768px) {
  .data-table-wrap.stack-cards {
    border: 0;
    background: transparent;
    overflow: visible;
  }
  .data-table-wrap.stack-cards table,
  .data-table-wrap.stack-cards tbody,
  .data-table-wrap.stack-cards tr,
  .data-table-wrap.stack-cards td { display: block; width: auto; }
  .data-table-wrap.stack-cards thead {
    position: absolute;
    width: 1px;
    height: 1px;
    overflow: hidden;
    clip: rect(0 0 0 0);
  }
  .data-table-wrap.stack-cards tbody tr {
    border: 1px solid var(--border);
    border-radius: var(--radius-card);
    background: var(--layer-2);
    margin-bottom: var(--space-3);
    padding: var(--space-1) 0;
  }
  .data-table-wrap.stack-cards tbody td {
    display: flex;
    justify-content: space-between;
    align-items: baseline;
    gap: var(--space-4);
    min-width: 0;
    border: 0;
    padding: var(--space-2) var(--space-4);
    text-align: right;
  }
  .data-table-wrap.stack-cards tbody td[data-label]::before {
    content: attr(data-label);
    flex-shrink: 0;
    font-weight: 500;
    color: var(--text-secondary);
    text-align: left;
  }
  .data-table-wrap.stack-cards tbody td:not([data-label])::before { content: none; }
  .data-table-wrap.stack-cards tbody td.col-actions .row-actions { visibility: visible; }
}

.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;
}

/* A chip used as a link (e.g. the alt-sources run-status chip → run detail):
   keep the chip look, drop the underline, hint interactivity on hover. */
a.chip { text-decoration: none; cursor: pointer; }
a.chip:hover { filter: brightness(0.95); text-decoration: underline; }

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

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

.chip-invalid,
.chip-disconnected,
.chip-unreachable {
  background: var(--danger-weak);
  color: var(--danger-text);
}

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

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

/* Text-like inputs only - never checkboxes/radios (which must keep their
   native box size; a min-height/width/border on them renders a giant
   misaligned control, e.g. the Copywriter Studio model pick-lists). */
.form-group input:not([type="checkbox"]):not([type="radio"]) {
  width: 100%;
  min-height: 36px;
  padding: var(--space-2) var(--space-3);
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-control);
  font-family: inherit;
  font-size: var(--fs-body);
}

.form-group input:not([type="checkbox"]):not([type="radio"]):focus {
  outline: 2px solid var(--brand);
  outline-offset: 1px;
}

.form-group textarea {
  width: 100%;
  padding: var(--space-2) var(--space-3);
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-control);
  font-family: inherit;
  font-size: var(--fs-body);
  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);
}

/* Element-qualified (not just `.checkbox-inline`) so this ties
   `.form-group input`'s specificity instead of losing to it outright - a
   checkbox inside a .form-group (e.g. Settings' "Test modu") was rendering
   full-width from that stronger rule, forcing its label text onto its own
   line below an oversized empty box instead of sitting inline beside it. */
input.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: var(--space-2);
  flex-wrap: wrap;
  margin: 0 0 var(--space-4);
}

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

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

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

/* Centered "single message" card - the global 400/401/403/404/500 error
   page (errors/error.html). Roomier and more deliberate than an ordinary
   .card since a stray/broken link (a mistyped cold-outreach URL, in
   particular - recipients land on this app's own domain via the
   unsubscribe page) is one of the only pages a first-time, non-logged-in
   visitor might ever land on. */
.error-page {
  max-width: 480px;
  margin: 72px auto;
  padding: 48px 40px;
  text-align: center;
  border-radius: 20px;
  box-shadow: var(--shadow-dialog);
}

.error-page-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 64px;
  height: 64px;
  border-radius: 50%;
  background: var(--brand-weak);
  color: var(--brand);
  margin-bottom: 20px;
}

.error-page-icon svg {
  width: 28px;
  height: 28px;
}

.error-page-code {
  font-family: "Space Grotesk", sans-serif;
  font-size: 13px;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--text-muted);
  margin: 0 0 10px;
}

.error-page h2 {
  margin: 0 0 12px;
}

.error-page p {
  color: var(--text-muted);
  margin: 0 0 6px;
}

.error-page .label {
  font-size: 13px;
  margin: 4px 0 24px;
}

.error-page .btn {
  margin-top: 8px;
}

/* 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;
}

.auth-brand .brand-logo {
  height: 30px;
}

.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 sticky
   analytics toolbar (.analytics-filters) so it stacks 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;
  }
}

/* =========================================================================
   Table-page anatomy (admin-panel-table-view-guidelines.md §6).
   Vertical order: page header -> toolbar -> bulk bar -> table -> footer.
   ========================================================================= */

.page-header-lead {
  display: flex;
  align-items: baseline;
  gap: var(--space-3);
  flex-wrap: wrap;
  min-width: 0;
}
.page-header-count {
  font-size: var(--fs-footnote);
  color: var(--text-secondary);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
.page-header-actions {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  flex-shrink: 0;
}

/* Toolbar (spec 6.2): search (flex) -> filter chips -> spacer -> view controls.
   Sticks under the page header as one unit when it acts on visible rows. */
.table-toolbar {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  flex-wrap: wrap;
  margin-bottom: var(--space-3);
}
.table-toolbar .toolbar-search {
  flex: 1 1 260px;
  min-width: 180px;
}
.table-toolbar .toolbar-spacer { flex: 1 1 auto; }
.table-toolbar .toolbar-view {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  flex-shrink: 0;
}
/* A detailed GET filter form dropped into the toolbar: keep it compact and
   on one wrapping row rather than the tall stacked-label layout. */
.table-toolbar .filter-row {
  gap: var(--space-2);
  align-items: end;
  flex: 1 1 100%;
}
.table-toolbar .filter-row .form-group { margin-bottom: 0; }
.table-toolbar .filter-row .form-group label {
  margin-bottom: 2px;
  font-size: var(--fs-caption);
  color: var(--text-secondary);
}
.table-toolbar .filter-row .form-group input,
.table-toolbar .filter-row .form-group select {
  height: 32px;
  padding: 0 var(--space-2);
  font-size: var(--fs-footnote);
}
.table-toolbar .filter-row .btn { height: 32px; padding: 0 var(--space-3); font-size: var(--fs-footnote); }

/* Applied-filter chips with counts (spec 6.3). */
.filter-chips {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  flex-wrap: wrap;
}
.filter-chip {
  display: inline-flex;
  align-items: center;
  gap: var(--space-1);
  padding: 2px var(--space-1) 2px var(--space-2);
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-pill);
  background: var(--layer-1);
  font-size: var(--fs-footnote);
  color: var(--text-primary);
  white-space: nowrap;
}
.filter-chip .filter-chip-count {
  color: var(--text-secondary);
  font-variant-numeric: tabular-nums;
}
.filter-chip .filter-chip-remove {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 16px;
  height: 16px;
  border: 0;
  border-radius: var(--radius-pill);
  background: none;
  color: var(--text-secondary);
  cursor: pointer;
  font-size: 12px;
  line-height: 1;
  text-decoration: none;
}
.filter-chip .filter-chip-remove:hover { background: var(--danger-weak); color: var(--danger-text); }

/* Density switcher removed - tables are always compact ("dar"), set pre-paint
   in base.html. The `data-table-density="compact"` rules still live above. */

/* Bulk action bar (spec 8.5) - appears only on >=1 selection. */
.bulk-bar {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  flex-wrap: wrap;
  padding: var(--space-2) var(--space-4);
  margin-bottom: var(--space-3);
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-card);
  background: var(--selected-bg);
}
.bulk-bar[hidden] { display: none; }
.bulk-bar .bulk-count { font-weight: 500; font-variant-numeric: tabular-nums; }
.bulk-bar .bulk-spacer { flex: 1 1 auto; }
.bulk-bar .bulk-danger { margin-left: var(--space-3); padding-left: var(--space-3); border-left: 1px solid var(--border-strong); }

/* Table footer (spec 6.6): range meta + pagination. */
.table-footer {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
  flex-wrap: wrap;
  padding: var(--space-3) var(--space-1);
  font-size: var(--fs-footnote);
  color: var(--text-secondary);
}
.table-footer .pager {
  display: flex;
  align-items: center;
  gap: var(--space-1);
}
.table-footer .pager a,
.table-footer .pager span {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 32px;
  height: 32px;
  padding: 0 var(--space-2);
  border: 1px solid var(--border);
  border-radius: var(--radius-control);
  color: var(--text-primary);
  text-decoration: none;
  font-variant-numeric: tabular-nums;
}
.table-footer .pager a:hover { border-color: var(--brand); color: var(--brand); }
.table-footer .pager .is-current { background: var(--selected-bg); border-color: var(--brand); color: var(--brand); }
.table-footer .pager .is-disabled { opacity: 0.45; pointer-events: none; }
.table-footer .pager .pager-gap { border: 0; min-width: auto; }

/* Empty states (spec 11.2) - three distinct variants. */
.table-empty {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-3);
  padding: var(--space-7) var(--space-4);
  text-align: center;
}
.table-empty .empty-title { font-size: var(--fs-prose); font-weight: 500; color: var(--text-primary); }
.table-empty .empty-body { font-size: var(--fs-body); color: var(--text-secondary); max-width: 42ch; line-height: var(--lh-prose); }
.table-empty-inline {
  padding: var(--space-6) var(--space-4);
  text-align: center;
  color: var(--text-secondary);
  border: 1px solid var(--border);
  border-radius: var(--radius-card);
  background: var(--layer-2);
}
.table-empty-inline[hidden] { display: none; }

/* Error state with a retry (spec 11.3). */
.table-error {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  flex-wrap: wrap;
  padding: var(--space-4);
  border: 1px solid var(--bd-danger);
  border-radius: var(--radius-card);
  background: var(--bg-danger);
  color: var(--fg-danger);
}

/* Skeleton rows for a genuine load gap (spec 11.1) - only used where a table
   is fetched after first paint; a shimmer disabled under reduced motion. */
.skeleton-row td { padding: var(--space-3); }
.skeleton-bar {
  height: 12px;
  border-radius: var(--radius-pill);
  background: linear-gradient(90deg, var(--layer-1) 25%, var(--border) 37%, var(--layer-1) 63%);
  background-size: 400% 100%;
  animation: skeleton-shimmer 1.4s ease infinite;
}
@keyframes skeleton-shimmer { from { background-position: 100% 0; } to { background-position: 0 0; } }

/* One global focus style (spec 2.5.1): visible on every surface level. */
:focus-visible {
  outline: 2px solid var(--focus-ring);
  outline-offset: 1px;
}
@media (prefers-reduced-motion: reduce) {
  .skeleton-bar { animation: none; }
  .data-table tbody tr.row-updated td { animation: none; }
}

.chip-draft,
.chip-drafted,
.chip-new,
.chip-pending,
.chip-unusable,
.chip-unvalidated,
.chip-queued,
.chip-scheduled,
.chip-skipped,
.chip-suppressed,
.chip-canceled,
.chip-skipped_contacted,
.chip-skipped_confidence,
.chip-domain_unreachable,
.chip-empty,
.chip-unchecked {
  background: var(--surface-2);
  color: var(--text-muted);
}

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

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

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

/* 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);
}

/* "Sıcak Müşteri" tag on inbound lead mails/messages - a deliberate solid-red
   fill (not the weak tint the status chips use) so it reads as an attention
   flag on a reply, not just another status. */
.chip-hot-lead {
  background: var(--danger);
  color: #fff;
  font-weight: 600;
}

.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;
}

/* Phase 6.6: greeting-name quality indicator on /leads - a small dot rather
   than a full chip (the row already has a relevance chip; a second
   full-size chip per row would be visually heavy for what's meant to be a
   quick, secondary signal). Colors intentionally match the existing
   chip-relevant/chip-uncertain/chip-irrelevant palette so green/amber/red
   read consistently across both. */
.quality-dot {
  display: inline-block;
  width: 9px;
  height: 9px;
  border-radius: 50%;
  margin-right: 4px;
  vertical-align: middle;
}

.quality-dot-good {
  background: var(--success);
}

.quality-dot-uncertain {
  background: var(--warning);
}

.quality-dot-unusable {
  background: var(--danger);
}

.display-name-cell .display-name-text {
  vertical-align: middle;
}

.display-name-edit-form {
  display: flex;
  align-items: center;
  gap: 6px;
  flex-wrap: wrap;
}

.display-name-input {
  min-width: 160px;
}

.btn-link {
  background: none;
  border: none;
  padding: 0;
  color: var(--brand);
  cursor: pointer;
  font-size: inherit;
  text-decoration: underline;
}

.campaign-notes-cell {
  max-width: 220px;
}

/* A scan's background operations (_background_tasks.html): under the user's
   note on the Taramalarım list, and as a card on the scan's detail page. */
.campaign-bg-tasks {
  min-width: 190px; /* table-layout:auto would squeeze the Notlar column to ~80px */
  max-width: 260px;
  margin-top: var(--space-2);
  padding-top: var(--space-2);
  border-top: 1px dashed var(--border);
  font-size: 12px;
  white-space: normal;
}
.bg-task-list {
  list-style: none;
  margin: var(--space-1) 0;
  padding: 0;
  display: grid;
  gap: var(--space-2);
}
.bg-task-list li { line-height: 1.45; overflow-wrap: anywhere; }
.bg-task-list .chip { margin-right: var(--space-1); }
.bg-task-detail { display: block; color: var(--text-muted); }
.bg-task-done { margin: var(--space-1) 0; }
.bg-task-controls { display: flex; align-items: center; gap: var(--space-2); flex-wrap: wrap; margin-top: var(--space-1); }
.contact-crawl-state { margin: var(--space-2) 0; line-height: 1.45; }
.contact-crawl-state > .chip { margin-right: var(--space-1); }
.lead-contact-line { margin: 2px 0 0; font-family: var(--font-body); }

.lead-detail-cell {
  max-width: 220px;
  white-space: pre-wrap;
  word-break: break-word;
}

/* Generic truncate-with-toggle for any long free-text/JSON value (see
   _expandable_text.html / expandable_text.js) - a raw JSON opening-hours
   blob (Apify Google Maps discovery) or a long address was routinely
   blowing a single /leads row out to 800px+ tall before this existed. */
.expandable-text-full {
  display: none;
  white-space: pre-wrap;
  word-break: break-word;
}

.expandable-text.is-expanded .expandable-text-short {
  display: none;
}

.expandable-text.is-expanded .expandable-text-full {
  display: inline;
}

.expandable-text-toggle {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 18px;
  height: 18px;
  padding: 0;
  margin-left: 2px;
  border: none;
  background: transparent;
  color: var(--brand);
  cursor: pointer;
  font-weight: 700;
  border-radius: 4px;
  vertical-align: middle;
}

.expandable-text-toggle:hover {
  color: var(--brand-dark);
}

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

.expandable-text-toggle-icon {
  display: inline-block;
  transition: transform 0.1s ease;
}

.expandable-text.is-expanded .expandable-text-toggle-icon {
  transform: rotate(90deg);
}

.campaign-notes-cell .campaign-notes-text {
  vertical-align: middle;
  white-space: normal;
  word-break: break-word;
}

.campaign-notes-edit-form {
  display: flex;
  flex-direction: column;
  gap: 6px;
  min-width: 220px;
}

.campaign-notes-edit-form textarea {
  min-width: 220px;
  resize: vertical;
}

.campaign-notes-edit-form .campaign-notes-edit-actions {
  display: flex;
  gap: 6px;
  align-items: center;
}

.account-limits-form {
  display: flex;
  flex-direction: column;
  gap: 10px;
  min-width: 210px;
}

/* The 24h/30-day fields sit side by side with a hairline divider between
   them ("split down the middle") rather than wrapping under each other -
   a fixed 1px middle column keeps the divider exactly centered regardless
   of how wide either field's content gets. */
.account-limits-grid {
  display: grid;
  grid-template-columns: 1fr 1px 1fr;
  gap: 14px;
  align-items: stretch;
}

.account-limits-divider {
  background: var(--border);
}

.account-limit-field {
  display: flex;
  flex-direction: column;
  gap: 5px;
  min-width: 0;
}

.account-limit-label {
  display: block;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.03em;
  text-transform: uppercase;
  color: var(--text-muted);
}

.account-limit-value-row {
  display: flex;
  align-items: center;
  gap: 5px;
}

.account-limit-used {
  color: var(--text);
  font-weight: 600;
  white-space: nowrap;
}

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

.account-limit-input {
  width: 100%;
  min-width: 0;
  padding: 5px 7px;
  border: 1px solid var(--border);
  border-radius: 6px;
  font-family: "JetBrains Mono", monospace;
  font-size: 13px;
}

/* Doubled-up selectors (rather than relying on source order) so these win
   over the base .progress-bar/.progress-bar-fill rules further down this
   file regardless of where either block moves later. */
.progress-bar.account-limit-bar {
  margin: 0;
  height: 4px;
}

.progress-bar-fill.progress-bar-fill-warn {
  background: var(--warning);
}

.account-limits-save {
  align-self: flex-start;
  display: inline-flex;
  align-items: center;
  gap: 6px;
}

.account-limits-save .icon-svg {
  width: 14px;
  height: 14px;
  display: inline-flex;
}

.account-limits-save .icon-svg svg {
  width: 100%;
  height: 100%;
}

/* Below this width the two-field split would force the whole table into
   horizontal scroll just to reveal the 30-day field - stack the fields
   instead (divider becomes a horizontal rule) so both stay reachable
   without scrolling the table sideways. */
@media (max-width: 640px) {
  .account-limits-form {
    min-width: 0;
  }

  .account-limits-grid {
    grid-template-columns: 1fr;
    gap: 10px;
  }

  .account-limits-divider {
    height: 1px;
  }
}

.display-name-error {
  flex-basis: 100%;
  margin: 2px 0 0;
}

.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;
}

/* Sender-account picker on /campaigns/new (outreach.new_campaign) - one row
   per account with its own daily/monthly "used / limit" columns, replacing
   the old .checkbox-grid-accounts checklist (a plain checkbox-grid overflows
   once a full email address is revealed - see _masked_email.html - and had
   no room for the usage figures this needed anyway). */
.sender-account-limits-table td {
  vertical-align: middle;
}

.sender-account-checkbox {
  display: flex;
  align-items: center;
  gap: 6px;
  font-weight: 400;
  min-width: 0;
}

.sender-account-checkbox input {
  width: auto;
}

.sender-account-checkbox .masked-email {
  min-width: 0;
}

/* "Hesapla" completion-date projection result (outreach_campaign_new.html) */
#campaign-estimate-stages {
  margin: 8px 0 0;
  padding-left: 20px;
}

#campaign-estimate-stages li {
  font-size: 14px;
  color: var(--text-muted);
  margin-bottom: 4px;
}

.form-group select {
  width: 100%;
  min-height: 36px;
  padding: var(--space-2) var(--space-3);
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-control);
  font-family: inherit;
  font-size: var(--fs-body);
  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: var(--shadow-popover);
}

.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: var(--shadow-popover);
  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;
}

/* The bare `[hidden]` attribute is UA-stylesheet `display: none` - an
   author-stylesheet `display: flex` of equal specificity above always wins
   the cascade regardless of source order, so `row.hidden = true` (search
   filtering, here and in template_multiselect.js) would otherwise silently
   do nothing. */
.multiselect-option[hidden] {
  display: none;
}

.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;
}

/* Copywriter Studio (see copywriter_studio.html / _studio_config_fields.html
   / copywriter_studio.js). A model picklist is the .multiselect visual
   language above, minus the popup/toggle mechanics - always visible, not
   hidden behind a button - since this same markup also renders inside
   Settings' plain-HTML-form mirror card with no JS guaranteed to run. */
.studio-zone + .studio-zone,
.studio-zone + .settings-panel,
.settings-panel + .studio-zone {
  margin-top: 20px;
}

.studio-stage-group {
  max-width: 280px;
}

/* Used by _studio_config_fields.html's model_picklist macro - still live on
   ICP Research's own advanced-settings panel (icp_review.html). */
.model-picklist {
  border: 1px solid var(--border);
  border-radius: 8px;
  background: var(--surface);
  overflow: hidden;
}

.model-picklist .multiselect-search {
  border-bottom: 1px solid var(--border);
}

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

.model-id-hint {
  color: var(--text-muted);
  font-size: 12px;
}

.model-picklist-empty {
  margin: 0;
}

.chip-model {
  background: var(--surface-2);
  color: var(--text-muted);
}

.chip-winner {
  background: var(--brand-weak);
  color: var(--brand);
  font-weight: 600;
}

.studio-candidate-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(340px, 1fr));
  gap: 16px;
  margin-top: 12px;
}

.studio-candidate {
  padding: 16px;
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.studio-candidate-winner {
  border-color: var(--brand);
  box-shadow: 0 0 0 1px var(--brand);
}

/* A guardrail-blocked draft stays visible (it can still be fixed by hand)
   but reads as secondary next to the passing ones. */
.studio-candidate-blocked {
  opacity: 0.85;
}

.studio-candidate-header {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px;
}

.studio-rank {
  font-weight: 700;
  color: var(--text-muted);
}

.studio-field-label {
  font-size: 12px;
  color: var(--text-muted);
  margin: 4px 0 -4px;
}

.studio-candidate-subject {
  font-weight: 600;
  width: 100%;
}

.studio-candidate-body {
  width: 100%;
  resize: vertical;
  line-height: 1.5;
}

.studio-preview {
  border: 1px dashed var(--border);
  border-radius: 8px;
  padding: 10px 12px;
  background: var(--surface-2);
}

.studio-preview-subject {
  font-weight: 600;
  margin: 0 0 6px;
}

.studio-preview-body {
  margin: 0;
  white-space: pre-wrap;
}

.studio-judge-note {
  border-left: 3px solid var(--brand);
  padding: 4px 0 4px 10px;
  font-size: 13px;
}

.studio-judge-note p {
  margin: 4px 0 0;
  white-space: pre-wrap;
}

.studio-reviews summary {
  cursor: pointer;
  font-size: 13px;
  color: var(--text-muted);
}

.studio-review {
  border-top: 1px solid var(--border);
  padding-top: 6px;
  margin-top: 6px;
  font-size: 13px;
}

.studio-review-head {
  margin: 0 0 4px;
}

.studio-review ul {
  margin: 0 0 4px;
  padding-left: 18px;
}

.studio-candidate-actions {
  margin-top: 4px;
}

/* "Save as template" is a <details> whose summary is styled as a button. */
.studio-save > summary {
  list-style: none;
  display: inline-flex;
  width: auto;
}

.studio-save > summary::-webkit-details-marker {
  display: none;
}

.studio-save-form {
  margin-top: 10px;
  border-top: 1px solid var(--border);
  padding-top: 10px;
}

.studio-result-head {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
}

.studio-result-tools {
  align-items: center;
  gap: 8px;
}

.studio-result-tools select {
  max-width: 320px;
}

.studio-progress {
  margin: 12px 0;
}

.studio-progress .help-text {
  margin-bottom: 6px;
}

.studio-run-meta {
  margin: 8px 0 0;
}

.studio-char-over {
  color: var(--warning-text);
}

/* System prompt editor: one expandable block per role. */
.studio-prompt-role {
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 10px 12px;
  margin-bottom: 12px;
  background: var(--surface);
}

.studio-prompt-summary {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px;
  cursor: pointer;
}

.studio-prompt-summary .help-text {
  margin: 0;
}

.studio-prompt-body {
  margin-top: 10px;
}

.studio-prompt-textarea {
  width: 100%;
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 13px;
  line-height: 1.5;
  resize: vertical;
}

.studio-prompt-tools {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  margin-top: 6px;
}

.studio-prompt-contract {
  margin-top: 8px;
}

.studio-prompt-contract summary {
  cursor: pointer;
}

.studio-prompt-contract pre {
  white-space: pre-wrap;
  font-size: 12px;
  background: var(--surface-2);
  border-radius: 6px;
  padding: 8px 10px;
  margin: 6px 0 0;
  color: var(--text-muted);
}

/* Prompt presets + per-role version history. */
.studio-presets {
  margin-bottom: 14px;
}

.studio-presets .form-inline {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  align-items: center;
}

.studio-prompt-versions {
  margin-top: 8px;
}

.studio-prompt-versions summary {
  cursor: pointer;
}

.studio-versions-table {
  margin-top: 6px;
  font-size: 13px;
}

/* Brief wizard: three numbered fields under the reference text. */
.studio-brief {
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 10px 12px 4px;
  margin: 0 0 14px;
}

.studio-brief legend {
  font-weight: 600;
  padding: 0 6px;
}

.studio-brief-steps {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
  gap: 12px;
}

.studio-brief-proof {
  grid-column: 1 / -1;
}

.studio-step-no {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 20px;
  height: 20px;
  border-radius: 50%;
  background: var(--brand-weak);
  color: var(--brand);
  font-size: 12px;
  font-weight: 700;
  margin-right: 4px;
}

.studio-profile-gaps {
  margin-bottom: 10px;
}

.studio-profile-gaps p {
  margin: 4px 0 0;
}

.studio-output-kind {
  display: flex;
  flex-wrap: wrap;
  gap: 16px;
}

/* Sequence cards: one block per step, so they need more width. */
.studio-sequence-grid {
  grid-template-columns: repeat(auto-fill, minmax(min(520px, 100%), 1fr));
}

.studio-steps {
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.studio-step {
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 10px;
  display: flex;
  flex-direction: column;
  gap: 6px;
  background: var(--surface);
}

.studio-step-head {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px;
}

.studio-delays {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  margin-top: 8px;
}

.studio-delay input {
  width: 90px;
}

.studio-saved-links {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  margin-top: 8px;
}

.studio-sequence-link {
  font-weight: 600;
}

/* Random-lead batch preview. */
.studio-batch {
  border: 1px dashed var(--border);
  border-radius: 8px;
  padding: 10px 12px;
  background: var(--surface-2);
}

.studio-batch-summary {
  margin: 0 0 6px;
}

.studio-batch-row {
  border-top: 1px solid var(--border);
  padding-top: 8px;
  margin-top: 8px;
}

.studio-batch-flagged {
  border-left: 3px solid var(--warning);
  padding-left: 8px;
}

.studio-batch-head {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 6px;
  margin-bottom: 4px;
}

/* Performance panels + template list rates. */
.studio-table-wrap {
  overflow-x: auto;
  margin-bottom: 12px;
}

.studio-recommendation ul {
  margin: 4px 0 0;
  padding-left: 18px;
}

.studio-model-hint .chip {
  margin-left: 4px;
}

.perf-low {
  color: var(--text-muted);
}

.perf-low-chip {
  font-size: 11px;
  margin-left: 4px;
}

.template-source {
  display: block;
  font-size: 12px;
  margin-top: 2px;
}

/* The template list gained five rate columns; keep the name readable. */
.template-name-cell {
  min-width: 200px;
}

/* 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;
}

/* Address + sender name (masked_email(email, name)): the name wraps onto
   its own line under the address and toggles with it. */
.masked-email.has-name {
  flex-wrap: wrap;
  row-gap: 2px;
}

.masked-email .masked-name {
  flex-basis: 100%;
  font-size: var(--fs-table);
  font-weight: 500;
  color: var(--text-secondary);
}

.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;
}

/* ---- Scrape run summary card (campaign_detail #campaign-status) ----
   The dense stack of "N x collected, Y skipped, Z ignored ..." label lines
   this replaced was hard to scan; the headline outcomes now read as a
   colored stat row and every diagnostic breakdown moved into the
   collapsible "Tarama ayrintilari" (<details class="scan-details">). */
.scan-summary-head {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 6px 14px;
  margin-bottom: 16px;
}

.scan-summary-head .scan-summary-meta {
  font-size: 13px;
}

.scan-stat-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(116px, 1fr));
  gap: 10px;
  margin-bottom: 14px;
}

.scan-stat {
  background: var(--bg);
  border: 1px solid var(--border);
  border-left: 3px solid var(--border);
  border-radius: 8px;
  padding: 10px 14px;
}

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

.scan-stat-label {
  display: block;
  font-size: 12px;
  color: var(--text-muted);
  margin-top: 2px;
}

.scan-stat-success { border-left-color: var(--success); }
.scan-stat-success .scan-stat-value { color: var(--success-text); }
.scan-stat-warning { border-left-color: var(--warning); }
.scan-stat-warning .scan-stat-value { color: var(--warning-text); }
.scan-stat-danger { border-left-color: var(--danger); }
.scan-stat-danger .scan-stat-value { color: var(--danger-text); }
.scan-stat-muted .scan-stat-value { color: var(--text-muted); }

.scan-details {
  margin-top: 12px;
  border-top: 1px solid var(--border);
  padding-top: 10px;
}

.scan-details > summary {
  list-style: none;
  cursor: pointer;
  font-size: 13px;
  font-weight: 500;
  color: var(--text-muted);
}

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

.scan-details > summary::before {
  content: "\25B8";
  display: inline-block;
  margin-right: 6px;
  transition: transform 0.15s ease;
}

.scan-details[open] > summary::before { transform: rotate(90deg); }

.scan-details-body {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(230px, 1fr));
  gap: 14px 24px;
  margin-top: 12px;
}

.scan-details-group h3 {
  margin: 0 0 4px;
  font-size: 12px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--text-muted);
}

.scan-details-group p {
  margin: 0 0 4px;
  font-size: 13px;
}

.scan-reason-list {
  display: flex;
  flex-wrap: wrap;
  gap: 4px 6px;
}

.scan-reason {
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: 4px;
  padding: 1px 6px;
  font-size: 12px;
  color: var(--text-muted);
}

.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;
}

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

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

.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 system health check panel ---- */

.syscheck-summary {
  display: flex;
  align-items: center;
  gap: 10px;
  margin: 0 0 16px;
}

.syscheck-timestamp {
  margin: 0;
}

.syscheck-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
  gap: 12px;
}

.syscheck-tile {
  display: flex;
  gap: 12px;
  background: var(--bg);
  border: 1px solid var(--border);
  border-left: 3px solid var(--border);
  border-radius: 8px;
  padding: 12px 14px;
}

.syscheck-tile-ok {
  border-left-color: var(--success);
}

.syscheck-tile-warn {
  border-left-color: var(--warning);
}

.syscheck-tile-error {
  border-left-color: var(--danger);
}

.syscheck-tile-off {
  border-left-color: var(--border);
}

.syscheck-tile-icon {
  color: var(--text-muted);
  flex-shrink: 0;
  margin-top: 1px;
}

.syscheck-tile-icon .icon-svg,
.syscheck-tile-icon svg {
  width: 20px;
  height: 20px;
  display: block;
}

.syscheck-tile-body {
  min-width: 0;
  flex: 1;
}

.syscheck-tile-top {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
}

.syscheck-tile-label {
  font-weight: 600;
  font-size: 14px;
}

.syscheck-tile-detail {
  font-size: 13px;
  color: var(--text-muted);
  margin: 4px 0 0;
  line-height: 1.4;
}

.syscheck-tile-link {
  display: inline-block;
  font-size: 13px;
  margin-top: 6px;
}

@media (max-width: 480px) {
  .syscheck-tile-top {
    flex-wrap: wrap;
  }
}

/* ---- 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 0 12px;
}

.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;
}

.howitworks-steps {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 18px;
}

.howitworks-steps li {
  display: flex;
  gap: 14px;
  align-items: flex-start;
}

.howitworks-step-num {
  flex: 0 0 auto;
  width: 28px;
  height: 28px;
  border-radius: 50%;
  background: var(--brand);
  color: #fff;
  display: flex;
  align-items: center;
  justify-content: center;
  font-weight: 600;
  font-size: 13px;
}

.howitworks-step-body h4 {
  margin: 0 0 4px;
  font-size: 15px;
}

.howitworks-step-body p {
  margin: 0;
  color: var(--text-muted);
  font-size: 13.5px;
  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: var(--shadow-popover);
  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;
}

/* Phase 6.10 - HTML email editor (HTML/Plain/Preview tabs) + shared
   lint/composition-guard findings list, reused by both the template editor
   and the Outbox approval queue (a blocked pending_approval row). */
.mailhtml-tab-nav {
  display: flex;
  gap: 4px;
  border-bottom: 1px solid var(--border);
  margin-bottom: 12px;
}

.mailhtml-tab-btn {
  background: none;
  border: none;
  border-bottom: 2px solid transparent;
  padding: 8px 14px;
  font-size: 14px;
  font-weight: 500;
  color: var(--text-muted);
  cursor: pointer;
}

.mailhtml-tab-btn:hover {
  color: var(--text);
}

.mailhtml-tab-btn.active {
  color: var(--brand);
  border-bottom-color: var(--brand);
}

.mailhtml-tab-panel.hidden {
  display: none;
}

.mailhtml-preview-frames {
  display: flex;
  flex-wrap: wrap;
  gap: 16px;
  margin: 12px 0;
}

.mailhtml-preview-col {
  flex: 0 0 auto;
}

.mailhtml-preview-frame {
  display: block;
  border: 1px solid var(--border);
  border-radius: 8px;
  background: #ffffff;
  height: 480px;
}

.mailhtml-preview-frame-desktop {
  width: 660px;
  max-width: 100%;
}

.mailhtml-preview-frame-mobile {
  width: 395px;
  max-width: 100%;
}

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

/* Plain tab: text editor + live-generated-HTML preview side by side. */
.mailhtml-plain-layout {
  display: flex;
  flex-wrap: wrap;
  gap: 16px;
}

.mailhtml-plain-editor,
.mailhtml-plain-live {
  flex: 1 1 320px;
  min-width: 280px;
}

.mailhtml-live-html-frame {
  display: block;
  width: 100%;
  height: 320px;
  border: 1px solid var(--border);
  border-radius: 8px;
  background: #ffffff;
  margin-bottom: 8px;
}

/* Always-available live preview, pinned to the bottom of the viewport
   (not just the Preview tab) - collapsed to a slim header bar by default so
   it doesn't eat screen space, expandable on click. */
.mailhtml-live-dock {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 50;
  background: var(--surface);
  border-top: 1px solid var(--border);
  box-shadow: var(--shadow-toast);
}

.mailhtml-live-dock-toggle {
  width: 100%;
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 8px;
  padding: 10px 20px;
  background: none;
  border: none;
  cursor: pointer;
  font-weight: 600;
  font-size: 14px;
  color: var(--text);
  font-family: inherit;
}

.mailhtml-live-dock-chevron {
  display: inline-block;
  transition: transform 0.15s ease;
}

.mailhtml-live-dock.collapsed .mailhtml-live-dock-chevron {
  transform: rotate(180deg);
}

.mailhtml-live-dock-body {
  display: flex;
  flex-wrap: wrap;
  gap: 16px;
  padding: 0 20px 16px;
  max-height: 42vh;
  overflow-y: auto;
}

.mailhtml-live-dock.collapsed .mailhtml-live-dock-body {
  display: none;
}

.mailhtml-live-dock-col {
  flex: 1 1 300px;
  min-width: 260px;
}

.mailhtml-live-dock-frame {
  display: block;
  width: 100%;
  height: 240px;
  border: 1px solid var(--border);
  border-radius: 8px;
  background: #ffffff;
}

.findings-list {
  display: flex;
  flex-direction: column;
  gap: 6px;
  margin: 8px 0;
}

.finding {
  border-radius: 8px;
  padding: 8px 12px;
  font-size: 13px;
}

.finding-warn {
  background: var(--warning-weak);
  color: var(--warning-text);
}

.finding-block {
  background: var(--danger-weak);
  color: var(--danger-text);
}

/* Settings' HTML email style fields (font/size/colors/width) - a compact
   grid rather than one control per row, since these are short inputs that
   read fine side by side and this keeps the AI & Sender panel from growing
   too tall. */
.html-style-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
  gap: 12px;
}

.html-style-grid select,
.html-style-grid input[type="number"] {
  width: 100%;
  padding: 8px 10px;
  border: 1px solid var(--border);
  border-radius: 8px;
  font-family: inherit;
  font-size: 14px;
  background: var(--surface);
  color: var(--text);
}

.html-style-grid input[type="color"] {
  width: 100%;
  height: 38px;
  padding: 2px;
  border: 1px solid var(--border);
  border-radius: 8px;
  background: var(--surface);
  cursor: pointer;
}

.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;
  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;
}
th .info-dot, .label .info-dot {
  margin-left: 4px;
  vertical-align: middle;
}

.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;
}

.collapsible-table-controls {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 10px;
  margin-top: 12px;
}

.collapsible-table-controls .pagination-row {
  margin-top: 0;
}

/* Same `[hidden]`-vs-`display:flex` cascade pitfall documented above for
   .multiselect-option - collapsible_table.js toggles this row's `hidden`
   property, which .pagination-row's own `display: flex` would otherwise
   silently override. */
.collapsible-table-controls .pagination-row[hidden] {
  display: none;
}

/* Same fix for the toggle button itself - hidden outright (rows.length <=
   data-default-rows, nothing to collapse/paginate), which .btn's own
   display: inline-block would otherwise override the same way. */
[data-table-toggle][hidden] {
  display: none;
}

@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;
  }
}

/* Manual "mark irrelevant" removal on /leads (see lead_relevance.js) - a
   quick fade so the row doesn't just vanish, not a layout-shifting collapse. */
.row-removing {
  opacity: 0;
  transition: opacity 0.25s ease;
}

.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);
  border-color: color-mix(in srgb, var(--warning) 30%, var(--border));
  background: var(--warning-weak);
}

.banner-danger {
  border-left-color: var(--danger);
  border-color: color-mix(in srgb, var(--danger) 30%, var(--border));
  background: var(--danger-weak);
}

.banner-info {
  border-left-color: var(--info);
  border-color: color-mix(in srgb, var(--info) 30%, var(--border));
  background: var(--info-weak);
}

/* 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: var(--shadow-toast);
  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) {
  *,
  *::before,
  *::after {
    transition: none !important;
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    scroll-behavior: auto !important;
  }
}

.default-filter-row {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 10px;
}

.default-filter-row .search-row {
  margin-top: 0;
}

.default-filter-row form {
  display: inline-flex;
  margin: 0;
}

.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.
   The nav is its own elevated card (not bare text floating on --bg) and each
   link carries the same icon as its panel's badge below - that repeated
   icon/label pairing is what makes the 9-section list scannable instead of
   a flat stack of same-weight text links. */
.settings-shell {
  display: flex;
  align-items: flex-start;
  gap: 24px;
}

.settings-nav {
  position: sticky;
  top: 20px;
  width: 240px;
  flex-shrink: 0;
  display: flex;
  flex-direction: column;
  gap: 2px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 12px;
  padding: 10px;
}

.settings-nav a {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 9px 12px;
  border-radius: 8px;
  color: var(--text-muted);
  text-decoration: none;
  font-size: 14px;
  font-weight: 500;
  border-left: 3px solid transparent;
  transition: background 0.12s ease, color 0.12s ease, border-color 0.12s ease;
}

.settings-nav a .nav-icon {
  opacity: 0.75;
}

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

.settings-nav a:hover .nav-icon {
  opacity: 1;
}

.settings-nav a.active {
  background: var(--brand-weak);
  color: var(--brand);
  border-left-color: var(--brand);
  font-weight: 600;
}

.settings-nav a.active .nav-icon {
  opacity: 1;
}

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

/* Each panel is its own elevated card, and gets a stronger border + shadow
   once open - the resting (collapsed) state stays quiet so the open section
   is unambiguous at a glance instead of every card reading as equally
   "loud." */
.settings-panel {
  border: 1px solid var(--border);
  border-radius: 12px;
  background: var(--surface);
  transition: border-color 0.15s ease, box-shadow 0.15s ease;
}

.settings-panel[open] {
  border-color: var(--brand-weak);
}

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

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

.settings-panel-heading {
  display: flex;
  align-items: center;
  gap: 14px;
  min-width: 0;
}

/* A colored icon badge per section - the same icon repeats in the nav link
   above, so the two stay visually linked without needing matching text. */
.settings-panel-icon {
  width: 38px;
  height: 38px;
  border-radius: 10px;
  background: var(--brand-weak);
  color: var(--brand);
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
}

.settings-panel-icon .icon-svg,
.settings-panel-icon svg {
  width: 19px;
  height: 19px;
}

.settings-panel-heading-text {
  min-width: 0;
}

.settings-panel-heading-text h2 {
  margin: 0 0 2px;
  font-size: 17px;
}

.settings-panel-heading-text 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, color 0.15s ease;
}

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

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

/* A hairline under the header, inside the open body - without it the header
   row and the first subcard sit at the same visual weight with nothing
   marking where "title" ends and "content" begins. */
.settings-panel-body::before {
  content: "";
  display: block;
  border-top: 1px solid var(--border);
  margin: 0 0 2px;
}

/* Subcards get a brand-tinted left rail (not just a same-tone border) so a
   panel with several stacked subcards (AI & Sender, Search & Scraping) reads
   as a set of distinct, clickable-feeling groups instead of one long
   undifferentiated block of the same flat --surface-2 tone. */
.settings-subcard {
  border: 1px solid var(--border);
  border-left: 3px solid var(--brand-weak);
  border-radius: 10px;
  background: var(--surface-2);
  padding: 16px 18px;
}

.settings-subcard h3 {
  margin-top: 0;
}

.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;
}

/* A panel whose fields save together as one POST but read better split
   into several .settings-subcard groups (e.g. Search & Scraping) wraps them
   all in one <form> - display: contents removes the form's own box from
   layout so .settings-panel-body's flex gap applies directly to the
   subcards (and the trailing Save button) inside it, same rhythm as every
   other panel's subcard-per-form pattern. */
.settings-panel-body > form {
  display: contents;
}

/* Without this, the Save button above (now a direct flex item of
   .settings-panel-body via display: contents on its <form> parent) gets
   stretched to the full column width by that flex container's default
   align-items: stretch - every other Save button in this file is a plain
   inline-block sized to its label, so this keeps this one consistent. */
.settings-panel-body > form > .btn {
  align-self: flex-start;
}

@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: 8px;
  }

  .settings-nav a {
    white-space: nowrap;
    flex-shrink: 0;
    border-left: none;
    border-bottom: 3px solid transparent;
    border-radius: 8px;
  }

  .settings-nav a.active {
    border-left-color: transparent;
    border-bottom-color: var(--brand);
  }

  .settings-panel-icon {
    width: 34px;
    height: 34px;
  }
}

/* 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;
}

/* =========================================================================
   Form-page legibility pass (2026-09-07).
   The scan-start ("Mail Topla") and settings forms were reading as one
   flat white sheet - field labels, help text, section groupings and the
   advanced-settings disclosure all sat at the same visual weight, so it
   was hard to tell one part from the next. This block adds hierarchy and
   colour anchors using the existing token palette only: every value is a
   --brand / --surface-2 / *-weak derivation, so both the light and dark
   themes pick it up with no new dark-block overrides.
   ========================================================================= */

/* Field labels back above their help text: primary ink, medium weight.
   Scoped to real field labels - the interactive-row labels (toggle rows,
   "select all", inline checkboxes) keep their own weight. */
.form-group > label:not(.switch-row):not(.select-all-row):not(.checkbox-label) {
  color: var(--text-primary);
  font-weight: 500;
}

/* Every in-card section heading carries a short brand rule so each card
   visibly announces itself instead of blending into the one above it. */
.card h2 {
  padding-left: var(--space-3);
  border-left: 3px solid var(--brand);
  line-height: 1.3;
}

/* Grouped-control panels: a nested .card (e.g. "Keşif kaynakları") and the
   advanced-settings <details> sit on a tinted surface with a clearer
   border, so a cluster of related toggles reads as one bounded unit
   against the plain white parent card. */
.form-group.card,
details.form-group {
  background: var(--surface-2);
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-card);
}

details.form-group {
  padding: var(--space-4);
}

/* <summary> as a real control: hover feedback, no default triangle, a
   brand caret that rotates on open - mirrors .scan-details > summary. */
details.form-group > summary {
  list-style: none;
  cursor: pointer;
  font-weight: 500;
  color: var(--text-primary);
  padding: var(--space-1) 0;
  user-select: none;
}

details.form-group > summary::-webkit-details-marker { display: none; }

details.form-group > summary::before {
  content: "\25B8";
  display: inline-block;
  margin-right: var(--space-2);
  color: var(--brand);
  transition: transform 0.15s ease;
}

details.form-group[open] > summary::before { transform: rotate(90deg); }

details.form-group[open] > summary {
  margin-bottom: var(--space-4);
  padding-bottom: var(--space-3);
  border-bottom: 1px solid var(--border);
}

/* Focus: a soft brand ring on top of the a11y outline, so the active
   field stands out on a page full of identical grey boxes. */
.form-group input:not([type="checkbox"]):not([type="radio"]):focus,
.form-group textarea:focus,
.form-group select:focus,
.combobox input[type="text"]:focus {
  border-color: var(--brand);
  box-shadow: 0 0 0 3px var(--brand-weak);
}

/* A nested .card acting as a titled sub-panel: its <label class="label">
   heading reads as a heading (the .card h2 accent rule can't reach it). */
.form-group.card > label.label:first-child {
  display: block;
  font-size: var(--fs-body);
  color: var(--text-primary);
  padding-left: var(--space-3);
  border-left: 3px solid var(--brand);
  margin-bottom: var(--space-1);
}

/* Form-page shell: wide enough to breathe on a large screen but capped so
   full-width inputs don't stretch to a hard-to-scan line length; collapses
   fluidly on smaller viewports. Pairs with .field-row for side-by-side
   short fields. */
.form-page {
  max-width: 1120px;
  margin-inline: auto;
}

.field-row {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
  gap: 0 var(--space-5);
}

/* =========================================================================
   Colour pass (2026-09-07) - part 2: status chips + stat tiles.
   The palette itself (sage-green brand + WCAG-tuned status triads) is
   sound; it was just applied too timidly. Chips now carry a hairline in
   their own hue, and stat tiles gain semantic modifiers (a coloured edge
   + coloured number) so a wall of counts reads at a glance.
   ========================================================================= */

.chip {
  border: 1px solid transparent;
}

.chip-draft, .chip-drafted, .chip-new, .chip-pending, .chip-unusable,
.chip-unvalidated, .chip-queued, .chip-scheduled, .chip-skipped,
.chip-suppressed, .chip-canceled,
.chip-skipped_contacted, .chip-skipped_confidence, .chip-domain_unreachable, .chip-empty, .chip-unchecked {
  border-color: var(--border-strong);
}

.chip-running, .chip-warm, .chip-risky, .chip-stopped, .chip-paused, .chip-waiting,
.chip-pending_approval, .chip-awaiting_approval, .chip-question,
.chip-uncertain, .chip-limit_reached, .chip-qr_pending {
  border-color: var(--warning-line);
}

.chip-done, .chip-hot, .chip-valid, .chip-sent, .chip-delivered, .chip-read,
.chip-opened, .chip-replied, .chip-relevant, .chip-active, .chip-connected {
  border-color: var(--success-line);
}

.chip-failed, .chip-cold, .chip-not_interested, .chip-bounced,
.chip-irrelevant, .chip-error, .chip-invalid, .chip-disconnected,
.chip-unreachable {
  border-color: var(--danger-line);
}

/* .stat-row / .stat-value: an older grid shape (fabrika results) that had
   no CSS at all - give it the same layout/type as .stat-grid / .value. */
.stat-row {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(120px, 1fr));
  gap: 12px;
  margin-bottom: 16px;
}
.stat-value {
  font-family: var(--font-heading);
  font-size: 24px;
  font-weight: 600;
  line-height: 1.2;
  color: var(--text);
}

/* Stat-tile semantic modifiers - a coloured left edge, a faint hue wash and
   a coloured value. Neutral tiles stay exactly as before. Mirrors the
   .scan-stat-{success,warning,danger} pattern already used on campaign
   detail, just as reusable classes for any .stat-tile grid. */
.stat-tile--brand,
.stat-tile--success,
.stat-tile--warning,
.stat-tile--danger,
.stat-tile--info,
.stat-tile--violet,
.stat-tile--teal,
.stat-tile--rose,
.stat-tile--neutral {
  border-left-width: 3px;
}

/* .value is the number class on most grids; .stat-value on a few (fabrika,
   scan summary) - colour both so the modifier works regardless. */
.stat-tile--brand   { border-left-color: var(--brand);   background: var(--brand-weak); }
.stat-tile--success { border-left-color: var(--success); background: var(--success-weak); }
.stat-tile--warning { border-left-color: var(--warning); background: var(--warning-weak); }
.stat-tile--danger  { border-left-color: var(--danger);  background: var(--danger-weak); }
.stat-tile--info    { border-left-color: var(--info);    background: var(--info-weak); }
.stat-tile--violet  { border-left-color: var(--violet);  background: var(--violet-weak); }
.stat-tile--teal    { border-left-color: var(--teal);    background: var(--teal-weak); }
.stat-tile--rose    { border-left-color: var(--rose);    background: var(--rose-weak); }
.stat-tile--neutral { border-left-color: var(--border-strong); }

.stat-tile--brand   .value, .stat-tile--brand   .stat-value { color: var(--brand-text); }
.stat-tile--success .value, .stat-tile--success .stat-value { color: var(--success-text); }
.stat-tile--warning .value, .stat-tile--warning .stat-value { color: var(--warning-text); }
.stat-tile--danger  .value, .stat-tile--danger  .stat-value { color: var(--danger-text); }
.stat-tile--info    .value, .stat-tile--info    .stat-value { color: var(--info-text); }
.stat-tile--violet  .value, .stat-tile--violet  .stat-value { color: var(--violet-text); }
.stat-tile--teal    .value, .stat-tile--teal    .stat-value { color: var(--teal-text); }
.stat-tile--rose    .value, .stat-tile--rose    .stat-value { color: var(--rose-text); }

/* is-link tiles: keep the hover cue, but don't let it wipe the coloured
   left edge (the generic rule sets border-color on all four sides). */
.stat-tile--brand.is-link:hover   { border-color: var(--brand); }
.stat-tile--success.is-link:hover { border-color: var(--success); }
.stat-tile--warning.is-link:hover { border-color: var(--warning); }
.stat-tile--danger.is-link:hover  { border-color: var(--danger); }
.stat-tile--info.is-link:hover    { border-color: var(--info); }
.stat-tile--violet.is-link:hover  { border-color: var(--violet); }
.stat-tile--teal.is-link:hover    { border-color: var(--teal); }
.stat-tile--rose.is-link:hover    { border-color: var(--rose); }

/* .stat-extra: the secondary counts under a 4-tile .stat-grid (outbox,
   leads) as one compact line of filter links, grouped by axis, instead of
   a wall of equally-weighted tiles. */
.stat-extra {
  display: flex;
  flex-wrap: wrap;
  gap: 6px 24px;
  margin: -8px 0 20px;
  font-size: 13px;
  color: var(--text-muted);
}
.stat-extra-group {
  display: inline-flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 4px 14px;
}
.stat-extra-label {
  font-weight: 600;
  color: var(--text);
}
.stat-extra a {
  color: var(--text-muted);
  text-decoration: none;
  white-space: nowrap;
}
.stat-extra a:hover {
  color: var(--brand);
  text-decoration: underline;
}
.stat-extra a b {
  font-weight: 600;
  color: var(--text);
  font-variant-numeric: tabular-nums;
}

/* ---- KPI cards (dashboard): the same semantic edge, so the metrics row
   isn't a flat white strip. ---- */
.kpi-card--success { border-left: 3px solid var(--success); }
.kpi-card--warning { border-left: 3px solid var(--warning); }
.kpi-card--danger  { border-left: 3px solid var(--danger); }
.kpi-card--info    { border-left: 3px solid var(--info); }
.kpi-card--brand   { border-left: 3px solid var(--brand); }

/* =========================================================================
   Outreach campaign settings (/campaigns/<id>/settings,
   outreach_campaign_settings.html): editable sections on the left, a
   read-only "fixed at creation" summary on the right (stacks below 1100px).
   ========================================================================= */
.campaign-settings-subtitle {
  margin-top: calc(-1 * var(--space-4));
  margin-bottom: var(--space-5);
}

.campaign-settings-layout {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 340px;
  gap: var(--space-5);
  align-items: start;
}

.campaign-settings-main,
.campaign-settings-aside {
  display: flex;
  flex-direction: column;
  gap: var(--space-5);
  min-width: 0;
}

.campaign-settings-main .card,
.campaign-settings-aside .card {
  margin-bottom: 0;
}

@media (min-width: 1101px) {
  .campaign-settings-aside {
    position: sticky;
    top: var(--sticky-header-offset);
  }
}

@media (max-width: 1100px) {
  .campaign-settings-layout {
    grid-template-columns: minmax(0, 1fr);
  }
}

.settings-section-head {
  margin-bottom: var(--space-4);
  padding-bottom: var(--space-3);
  border-bottom: 1px solid var(--border);
}

.settings-section-head h2,
.campaign-settings-aside h2 {
  font-size: var(--fs-h3);
  margin: 0 0 var(--space-1);
}

.settings-section-head .help-text {
  margin: 0;
}

.settings-fieldset {
  border: none;
  padding: 0;
  margin-left: 0;
  margin-right: 0;
  min-width: 0;
}

.settings-fieldset legend {
  padding: 0;
  margin-bottom: 6px;
}

.settings-fieldset .card-header-row legend {
  margin-bottom: 0;
}

.field-meta {
  display: flex;
  justify-content: space-between;
  gap: var(--space-3);
}

.settings-interval-row {
  display: flex;
  align-items: flex-end;
  gap: var(--space-3);
  flex-wrap: wrap;
}

.settings-interval-row > div {
  flex: 1 1 160px;
  max-width: 240px;
}

.settings-interval-row label {
  display: block;
  font-size: var(--fs-footnote);
  color: var(--text-secondary);
  margin-bottom: 4px;
}

.settings-interval-sep {
  padding-bottom: 8px;
  color: var(--text-muted);
}

.input-suffix {
  position: relative;
}

.form-group .input-suffix input:not([type="checkbox"]):not([type="radio"]) {
  padding-right: 44px;
}

.input-suffix span {
  position: absolute;
  right: 12px;
  top: 50%;
  transform: translateY(-50%);
  font-size: var(--fs-footnote);
  color: var(--text-muted);
  pointer-events: none;
}

.settings-fieldset input[aria-invalid="true"] {
  border-color: var(--danger);
}

.settings-callout {
  margin: var(--space-3) 0 var(--space-2);
  padding: var(--space-3) var(--space-4);
  background: var(--brand-weak);
  border-left: 3px solid var(--brand);
  border-radius: var(--radius-control);
  font-size: var(--fs-footnote);
  color: var(--text);
}

.settings-callout[hidden] {
  display: none;
}

.settings-inline-actions {
  display: flex;
  gap: var(--space-2);
}

#sender-accounts-table {
  width: 100%;
}

#sender-accounts-table .row-muted td {
  color: var(--text-muted);
}

.settings-savebar {
  display: flex;
  justify-content: flex-end;
  align-items: center;
  gap: var(--space-2);
  position: sticky;
  bottom: 0;
  z-index: 5;
  padding: var(--space-3) 0;
  background: var(--bg);
  border-top: 1px solid var(--border);
}

.settings-savebar .help-text {
  margin: 0 auto 0 0;
  color: var(--warning-text);
}

.settings-savebar .help-text[hidden] {
  display: none;
}

.settings-mini-stats {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--space-2);
  margin: var(--space-3) 0 var(--space-4);
}

.settings-mini-stats > div {
  display: flex;
  flex-direction: column;
  padding: var(--space-2) var(--space-3);
  background: var(--surface-2);
  border-radius: var(--radius-control);
}

.settings-mini-stats .value {
  font-size: var(--fs-h3);
  font-weight: 600;
  font-variant-numeric: tabular-nums;
}

.settings-mini-stats .stat-label {
  font-size: var(--fs-caption);
  color: var(--text-secondary);
}

.settings-dl {
  margin: 0;
}

.settings-dl dt {
  font-size: var(--fs-caption);
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--text-secondary);
  margin-top: var(--space-3);
}

.settings-dl dt:first-child {
  margin-top: 0;
}

.settings-dl dd {
  margin: 4px 0 0;
  overflow-wrap: anywhere;
}

.settings-dl dd .help-text {
  margin: 4px 0;
}

.settings-filter-list {
  margin: 0;
  padding-left: 18px;
}

/* The settings form is its own flex column inside .campaign-settings-main,
   followed by the campaign-management card (separate forms). */
.campaign-settings-form {
  display: flex;
  flex-direction: column;
  gap: var(--space-5);
  min-width: 0;
}

/* Templates section: current set (keep/remove checkbox) + pending adds. */
.settings-template-table {
  width: 100%;
}

.settings-template-table tr.is-removed td:not(.col-num) {
  color: var(--text-muted);
  text-decoration: line-through;
}

.settings-template-table tr.is-removed .chip {
  text-decoration: none;
}

.settings-template-state {
  margin-left: var(--space-2);
}

.settings-template-state[hidden] {
  display: none;
}

.settings-template-keep {
  display: inline-flex;
  justify-content: flex-end;
}

.settings-template-add {
  margin-top: var(--space-4);
}

.settings-schedule-current {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-2);
  margin: 0;
}

/* Campaign management (pause / cancel / archive / delete). */
.lifecycle-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-4);
  padding: var(--space-3) 0;
  border-top: 1px solid var(--border);
}

.settings-section-head + .lifecycle-row {
  border-top: none;
  padding-top: 0;
}

.lifecycle-text {
  min-width: 0;
}

.lifecycle-text .help-text {
  margin: 4px 0 0;
}

.lifecycle-row form {
  flex-shrink: 0;
}

.lifecycle-delete-form {
  display: flex;
  flex-direction: column;
  align-items: stretch;
  gap: var(--space-2);
  width: 260px;
}

.lifecycle-delete-form .form-group {
  margin: 0;
}

/* Paused-campaign banner on outreach_campaign_detail.html: message + Resume. */
.campaign-paused-banner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: var(--space-3);
}

.campaign-paused-banner p {
  margin: 0;
}

.btn-danger-outline {
  border: 1px solid color-mix(in srgb, var(--danger) 45%, var(--border));
}

.btn-danger-outline:disabled {
  opacity: 0.5;
  cursor: not-allowed;
}

@media (max-width: 640px) {
  .lifecycle-row {
    flex-direction: column;
    align-items: stretch;
  }
  .lifecycle-delete-form {
    width: auto;
  }
}

/* Secondary figure under a stat grid (e.g. the undelivered count on
   outreach_campaign_detail.html) - plain text, not another colored tile. */
.stat-footnote {
  margin: var(--space-3) 0 0;
}

/* Desktop already has Save/Cancel in the sticky .page-header, so the bottom
   bar only needs to follow the viewport on narrower screens. */
@media (min-width: 1101px) {
  .settings-savebar {
    position: static;
    border-top: none;
  }
}

@media (max-width: 520px) {
  .settings-interval-sep {
    display: none;
  }
  .settings-interval-row > div {
    max-width: none;
  }
}

/* ---- Tüm Mailler (unified mailbox, app/mailbox/) ------------------------ */
.chip-mail-in {
  background: var(--info-weak);
  color: var(--info-text);
  border-color: var(--info-line);
}
.chip-mail-out {
  background: var(--brand-weak);
  color: var(--brand-text);
  border-color: var(--brand-line);
}
.stat-tile.is-selected {
  box-shadow: inset 0 0 0 2px var(--brand);
}
.mailbox-accounts-summary {
  cursor: pointer;
  list-style-position: inside;
}
.mailbox-accounts-summary h3 {
  display: inline;
  margin: 0;
}
.mailbox-account-table tr.is-selected td {
  background: var(--brand-weak);
}
.mailbox-active-account {
  margin: 0 0 var(--space-3);
}
.mailbox-subject {
  font-weight: 600;
}
.mailbox-snippet {
  margin: 2px 0 0;
  color: var(--text-muted);
  font-size: var(--fs-footnote);
  overflow: hidden;
  text-overflow: ellipsis;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
}
.mailbox-counterparty {
  word-break: break-all;
}
.mailbox-convo-facts {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-3) var(--space-6);
  margin: 0 0 var(--space-2);
}
.mailbox-convo-facts dt,
.mail-message-meta dt {
  color: var(--text-muted);
  font-size: var(--fs-footnote);
}
.mailbox-convo-facts dd,
.mail-message-meta dd {
  margin: 0;
}
.mailbox-live-status {
  margin: 0;
}
.mailbox-live-status--error,
.mailbox-live-status--inactive {
  color: var(--warning-text);
}
.mail-thread {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
}
.mail-message {
  border: 1px solid var(--border);
  border-left: 3px solid var(--info);
  border-radius: var(--radius-card);
  background: var(--surface);
  padding: var(--space-3) var(--space-4);
  max-width: 920px;
}
.mail-message--out {
  border-left-color: var(--brand);
  margin-left: auto;
  background: color-mix(in srgb, var(--brand-weak) 35%, var(--surface));
}
.mail-message.is-focused {
  box-shadow: 0 0 0 2px var(--brand);
}
.mail-message-head {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-2);
}
.mail-message-time {
  margin-left: auto;
  color: var(--text-muted);
  font-size: var(--fs-footnote);
}
.mail-message-meta {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  gap: var(--space-2) var(--space-4);
  margin: var(--space-2) 0;
}
.mail-message-meta dd {
  word-break: break-word;
}
.mail-message-body {
  white-space: pre-wrap;
  word-break: break-word;
  font-size: var(--fs-body);
  line-height: 1.55;
  max-height: 520px;
  overflow-y: auto;
  border-top: 1px solid var(--border);
  padding-top: var(--space-2);
}
@media (max-width: 720px) {
  .mail-message--out {
    margin-left: 0;
  }
}

/* =========================================================================
   WhatsApp settings page (2026-10-15): sectioned cards, radio cards for the
   auto mode, chip checkboxes for reply categories.
   ========================================================================= */

.wa-settings {
  max-width: 760px;
  display: flex;
  flex-direction: column;
  gap: var(--space-4, 16px);
}

.wa-form {
  display: flex;
  flex-direction: column;
  gap: var(--space-4, 16px);
}

.wa-section-head {
  margin-bottom: 16px;
}

.wa-section-head h2 {
  margin: 0 0 4px;
  font-size: 1.05rem;
}

.wa-section-head .help-text {
  margin: 0;
}

.wa-mode-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  gap: 10px;
}

.wa-mode-card {
  display: block;
  cursor: pointer;
  position: relative;
}

.wa-mode-card input {
  position: absolute;
  opacity: 0;
  inset: 0;
  margin: 0;
  cursor: pointer;
}

.wa-mode-body {
  display: flex;
  flex-direction: column;
  gap: 4px;
  height: 100%;
  padding: 12px 14px;
  border: 1px solid var(--border);
  border-radius: 10px;
  background: var(--surface);
  transition: border-color 0.15s ease, box-shadow 0.15s ease;
}

.wa-mode-body span {
  font-size: 0.85rem;
  color: var(--text-muted, inherit);
  opacity: 0.85;
}

.wa-mode-card:hover .wa-mode-body {
  border-color: var(--brand);
}

.wa-mode-card input:checked + .wa-mode-body {
  border-color: var(--brand);
  box-shadow: 0 0 0 2px var(--brand);
}

.wa-mode-card input:focus-visible + .wa-mode-body {
  outline: 2px solid var(--brand);
  outline-offset: 2px;
}

.wa-auto-warning {
  display: none;
  margin: 14px 0 0;
}

.wa-form:has(#wa-mode-auto:checked) .wa-auto-warning {
  display: block;
}

.wa-chip-group {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}

.wa-chip-check {
  position: relative;
  cursor: pointer;
}

.wa-chip-check input {
  position: absolute;
  opacity: 0;
  inset: 0;
  margin: 0;
  cursor: pointer;
}

.wa-chip-check span {
  display: inline-block;
  padding: 6px 14px;
  border: 1px solid var(--border);
  border-radius: 999px;
  background: var(--surface);
  font-size: 0.9rem;
  transition: background 0.15s ease, border-color 0.15s ease;
}

.wa-chip-check:hover span {
  border-color: var(--brand);
}

.wa-chip-check input:checked + span {
  background: var(--brand);
  border-color: var(--brand);
  color: #fff;
}

.wa-chip-check input:focus-visible + span {
  outline: 2px solid var(--brand);
  outline-offset: 2px;
}

.wa-narrow {
  max-width: 220px;
}

.wa-switches {
  margin: 4px 0 0;
}

.wa-switches .switch-row {
  align-items: flex-start;
}

.wa-switches .switch {
  margin-top: 2px;
}

.wa-switch-text {
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.wa-switch-text .help-text {
  margin: 0;
}

.wa-actions {
  display: flex;
  justify-content: flex-end;
}

.wa-inline-form {
  display: flex;
  align-items: flex-end;
  gap: 12px;
  flex-wrap: wrap;
}

.wa-inline-form .form-group {
  flex: 1 1 220px;
  margin-bottom: 0;
}

/* WhatsApp add-number page (2026-10-15) */
.wa-actions-start {
  justify-content: flex-start;
  gap: 10px;
  margin-top: 8px;
}

.wa-advanced {
  margin: 4px 0 16px;
  padding: 12px 14px;
  border: 1px dashed var(--border);
  border-radius: 10px;
}

.wa-advanced summary {
  cursor: pointer;
  font-weight: 600;
}

.wa-steps {
  margin: 0 0 16px;
  padding-left: 22px;
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.wa-form input:not([type="checkbox"]):not([type="radio"]),
.wa-section .form-group input:not([type="checkbox"]):not([type="radio"]) {
  width: 100%;
}

/* Compact multi-choice filter dropdown (_multi_filter.html, /leads filter row).
   The panel is as wide as its longest choice (never a narrow scrolling strip),
   options stay on one line, and type is filter-bar sized. */
.multi-filter {
  min-width: 140px;
}

.multi-filter .multiselect-toggle {
  height: 32px;
  padding: 0 10px;
  font-size: 13px;
  border-radius: 6px;
}

.multi-filter .multiselect-toggle-label {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  max-width: 180px;
}

.multi-filter .multiselect-panel {
  right: auto;
  min-width: 100%;
  width: max-content;
  max-width: 280px;
  padding: 4px;
  border-radius: 8px;
}

.multi-filter .multiselect-options {
  max-height: 260px;
  overflow-x: hidden;
}

.multi-filter .multiselect-option {
  gap: 8px;
  padding: 6px 8px;
  font-size: 13px;
  line-height: 1.3;
  white-space: nowrap;
  border-radius: 4px;
}

.multi-filter .multiselect-option span {
  overflow: hidden;
  text-overflow: ellipsis;
}

.multi-filter .multiselect-option input[type="checkbox"] {
  width: 14px;
  height: 14px;
  margin: 0;
  flex: none;
  accent-color: var(--brand);
}

/* /leads filter row: every control (text input, native select, multi-choice
   toggle, buttons) shares one height and type size. */
#leads-filter-form {
  gap: 10px 12px;
}

#leads-filter-form .form-group label {
  margin-bottom: 4px;
  font-size: 13px;
}

#leads-filter-form .form-group input[type="text"],
#leads-filter-form select,
#leads-filter-form .multiselect-toggle {
  box-sizing: border-box;
  height: 32px;
  min-height: 32px;
  padding: 0 10px;
  font-size: 13px;
  line-height: 30px;
  border-radius: 6px;
}

#leads-filter-form select {
  padding-right: 24px;
}

#leads-filter-form .btn {
  height: 32px;
  min-height: 32px;
  padding: 0 14px;
  font-size: 13px;
  display: inline-flex;
  align-items: center;
}
