:root {
    /* Slate ink + neutrals */
    --ink: #0f172a;
    --ink-2: #334155;
    --muted: #64748b;
    --line: #e2e8f0;
    --line-2: #cbd5e1;
    --bg: #f1f5f9;
    --surface: #ffffff;
    --surface-2: #f8fafc;
    --white: #ffffff;

    /* Teal accent */
    --teal: #0d9488;
    --teal-dark: #0f766e;
    --teal-50: #f0fdfa;
    --teal-100: #ccfbf1;
    --teal-800: #115e59;

    /* Accent aliases (legacy var names map onto the teal accent) */
    --blue: #0d9488;
    --blue-dark: #115e59;

    /* Semantic */
    --green: #047857;
    --red: #b91c1c;
    --amber: #b45309;

    --radius: 10px;
    --radius-lg: 14px;
    --shadow-sm: 0 1px 2px rgba(15, 23, 42, .06);
    --shadow: 0 8px 28px rgba(15, 23, 42, .12);
    color-scheme: light;
}

/* ============================ Dark theme ============================ */
/* Set on <html data-theme="dark">. Almost everything is variable-driven, so re-defining the
   palette flips the whole UI; a handful of hardcoded light tints get dark equivalents below. */
[data-theme="dark"] {
    color-scheme: dark;                 /* dark native date-pickers, dropdowns, scrollbars */
    --ink: #e6eaf2;
    --ink-2: #c3ccda;
    --muted: #8b98ac;
    --line: #2a3547;
    --line-2: #3a4864;
    --bg: #0b111f;
    --surface: #151e30;
    --surface-2: #1c2740;
    --white: #151e30;

    --teal: #14b8a6;
    --teal-dark: #2dd4bf;               /* links + accents, bright enough on dark */
    --teal-50: #0e2b2a;
    --teal-100: #123f3a;
    --teal-800: #7ff0e0;
    --blue: #2dd4bf;
    --blue-dark: #7ff0e0;

    --green: #34d399;
    --red: #f87171;
    --amber: #fbbf24;

    --shadow-sm: 0 1px 2px rgba(0, 0, 0, .35);
    --shadow: 0 10px 30px rgba(0, 0, 0, .55);
}
[data-theme="dark"] .ico-blue { background: #16233b; color: #93c5fd; }
[data-theme="dark"] .ico-amber { background: #2a2413; color: #fcd34d; }
[data-theme="dark"] .ico-violet { background: #221c3a; color: #c4b5fd; }
[data-theme="dark"] .msg.success { background: #0f2a1f; border-color: #14532d; }
[data-theme="dark"] .msg.error { background: #2b1414; border-color: #7f1d1d; }
[data-theme="dark"] .msg.warning { background: #2a2210; border-color: #78350f; }
[data-theme="dark"] .note.pinned { background: #241d0f; }
[data-theme="dark"] .soon { background: #241d0f; border-color: #78350f; }
/* Elements that use --ink as a *background* (dark chips on the light UI) must stay dark. */
[data-theme="dark"] .avatar { background: #334155; }
[data-theme="dark"] .ob-bar { background: #10192a; }
/* OSM raster tiles are a bright white sheet — invert them so the map belongs to the dark shell
   instead of blinding a canvasser standing on a doorstep at 7pm. Popups follow the surface. */
[data-theme="dark"] #cmap { background: #0b1220; }
[data-theme="dark"] #cmap .leaflet-tile-pane { filter: invert(1) hue-rotate(180deg) brightness(.9) contrast(.92); }
[data-theme="dark"] .leaflet-popup-content-wrapper, [data-theme="dark"] .leaflet-popup-tip {
    background: var(--surface); color: var(--ink); }
[data-theme="dark"] .leaflet-bar a { background: var(--surface); color: var(--ink); border-color: var(--line); }

* { box-sizing: border-box; }

/* Global [hidden] override. The HTML5 `hidden` attribute is styled via the
   user-agent stylesheet as [hidden]{display:none}, but that has the same
   specificity as any .class{display:X} rule — so anywhere a `.btn` (which
   sets display:inline-flex) also has the `hidden` attribute, the class
   wins and the button stays visible. Bit us on the dialer's Hang up +
   Mute buttons, which start with `hidden` but rendered as solid teal
   pills next to Call until you actually made a call. !important here
   forces `hidden` to win over any component-level display rule without
   requiring every .btn/.d-primary/etc. to add its own [hidden] override. */
[hidden] { display: none !important; }

body {
    margin: 0;
    font-family: -apple-system, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
    color: var(--ink);
    background: var(--bg);
    line-height: 1.5;
}

a { color: var(--teal-dark); text-decoration: none; }
a:hover { text-decoration: underline; }

/* ============================ Top bar ============================ */
.topbar {
    position: sticky;
    top: 0;
    z-index: 50;
    display: flex;
    align-items: center;
    gap: 18px;
    background: var(--surface);
    border-bottom: 1px solid var(--line);
    box-shadow: var(--shadow-sm);
    padding: 0 22px;
    height: 60px;
}
.nav-cb { display: none; }

.brand {
    display: inline-flex; align-items: center; gap: 10px;
    font-weight: 700; font-size: 17px; color: var(--ink); white-space: nowrap;
}
.brand:hover { text-decoration: none; }
.brand-mark {
    display: inline-flex; align-items: center; justify-content: center;
    width: 30px; height: 30px; border-radius: 9px;
    background: var(--teal); color: #fff; font-size: 18px;
}

.nav-toggle {
    display: none; margin-left: auto; cursor: pointer;
    font-size: 24px; color: var(--ink-2); padding: 4px 6px; border-radius: 8px;
}
.nav-toggle:hover { background: var(--surface-2); }

/* min-width:0 — a flex item won't shrink below its content by default, so a long nav shoved the
   account menu past the right edge of the window and put a horizontal scrollbar on every page.
   The nav scrolls within itself instead. */
/* min-width:0 — a flex item won't shrink below its content by default, so a long nav shoved the
   account menu past the right edge of the window. */
.nav-collapse { display: flex; align-items: center; flex: 1; gap: 18px; min-width: 0; }
/* NO overflow here. `overflow-x: auto` forces overflow-y to compute to auto too, which turns this
   into a scroll container — and the dropdowns are absolutely positioned BELOW it, so they get
   clipped out of existence. Space is made by hiding this nav when the sidebar is docked (below)
   and by letting items compress, never by scrolling. */
.mainnav { display: flex; align-items: center; gap: 4px; min-width: 0; }
.mainnav .nav-link { white-space: nowrap; }
/* Nine sections plus the committee chip and account menu is a tight fit on a 1280 laptop — tighten
   the nav rather than let the last item slide under the account cluster. */
@media (max-width: 1439px) {
    .mainnav { gap: 1px; }
    .mainnav .nav-link { padding: 8px 8px; font-size: 14px; }
}

.nav-link {
    display: inline-flex; align-items: center; gap: 5px;
    color: var(--ink-2); font-weight: 500; font-size: 14.5px;
    padding: 8px 12px; border-radius: 8px; cursor: pointer; white-space: nowrap;
}
.nav-link:hover { background: var(--surface-2); text-decoration: none; color: var(--ink); }
.nav-link.active,
.nav-group.active > .nav-link { background: var(--teal-50); color: var(--teal-dark); }
.caret { font-size: 14px; opacity: .7; }

/* Dropdown groups (Lists, Canvassing) */
.nav-group { position: relative; }
.nav-group > summary { list-style: none; }
.nav-group > summary::-webkit-details-marker { display: none; }
.nav-menu {
    position: absolute; top: calc(100% + 6px); left: 0; z-index: 60;
    min-width: 210px; background: var(--surface);
    border: 1px solid var(--line); border-radius: 12px;
    box-shadow: var(--shadow); padding: 6px; display: flex; flex-direction: column; gap: 2px;
}
.nav-menu a {
    display: flex; align-items: center; gap: 10px;
    padding: 9px 12px; border-radius: 8px; color: var(--ink); font-size: 14px;
}
.nav-menu a:hover { background: var(--surface-2); text-decoration: none; }
.nav-menu a i { color: var(--muted); font-size: 18px; }

/* Right cluster */
.userbox { margin-left: auto; display: flex; align-items: center; gap: 12px; }
.campaign-chip {
    display: inline-flex; align-items: center; gap: 6px;
    background: var(--teal-50); border: 1px solid var(--teal-100); color: var(--teal-800);
    padding: 6px 12px; border-radius: 20px; font-size: 13px; font-weight: 600;
    max-width: 230px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.campaign-chip:hover { background: var(--teal-100); text-decoration: none; }
.campaign-chip i { font-size: 15px; }

.acct { position: relative; }
.acct > summary {
    list-style: none; cursor: pointer; display: inline-flex; align-items: center; gap: 8px;
    padding: 5px 8px 5px 5px; border-radius: 24px; border: 1px solid var(--line);
}
.acct > summary::-webkit-details-marker { display: none; }
.acct > summary:hover { background: var(--surface-2); }
.avatar {
    display: inline-flex; align-items: center; justify-content: center;
    width: 30px; height: 30px; border-radius: 50%;
    background: var(--ink); color: #fff; font-size: 12px; font-weight: 700;
}
.acct-name { font-size: 14px; color: var(--ink-2); font-weight: 500; max-width: 140px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.acct-menu {
    position: absolute; top: calc(100% + 6px); right: 0; z-index: 60;
    min-width: 220px; background: var(--surface);
    border: 1px solid var(--line); border-radius: 12px; box-shadow: var(--shadow);
    padding: 6px; display: flex; flex-direction: column; gap: 2px;
}
.acct-head { padding: 8px 12px 10px; border-bottom: 1px solid var(--line); margin-bottom: 4px; display: flex; flex-direction: column; }
.acct-head .muted { font-size: 12px; }
.acct-menu a, .acct-menu .logout button {
    display: flex; align-items: center; gap: 10px; width: 100%;
    padding: 9px 12px; border-radius: 8px; color: var(--ink); font-size: 14px;
    background: none; border: none; cursor: pointer; font: inherit; text-align: left;
}
.acct-menu a:hover, .acct-menu .logout button:hover { background: var(--surface-2); text-decoration: none; }
.acct-menu i { color: var(--muted); font-size: 18px; }
.logout { margin: 0; }

/* ============================ Content ============================ */
.content { max-width: 1180px; margin: 0 auto; padding: 28px 24px; }
h1 { font-size: 26px; margin: 0 0 6px; letter-spacing: -.01em; }
h2 { letter-spacing: -.01em; }

/* ====================== Dashboard launchpad ====================== */
.dash-head { margin-bottom: 6px; }
.dash-head h1 { margin-bottom: 2px; }
.dash-stats { display: flex; flex-wrap: wrap; gap: 10px; margin: 14px 0 6px; }
.dash-stat {
    display: inline-flex; align-items: center; gap: 8px;
    background: var(--surface); border: 1px solid var(--line); border-radius: 20px;
    padding: 7px 14px; font-size: 13px; color: var(--ink-2);
}
.dash-stat i { color: var(--muted); font-size: 16px; }
.dash-stat strong { color: var(--ink); }

.launch-group { font-size: 13px; font-weight: 600; letter-spacing: .03em; text-transform: uppercase;
    color: var(--muted); margin: 26px 0 12px; }
.launch-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(230px, 1fr)); gap: 14px; }
.launch-card {
    display: flex; gap: 14px; align-items: flex-start;
    background: var(--surface); border: 1px solid var(--line); border-radius: var(--radius-lg);
    padding: 16px 18px; color: var(--ink);
    transition: border-color .12s, box-shadow .12s, transform .12s;
}
.launch-card:hover { border-color: var(--line-2); box-shadow: var(--shadow-sm); text-decoration: none; transform: translateY(-1px); }
.launch-ico {
    flex: none; width: 40px; height: 40px; border-radius: 11px;
    display: inline-flex; align-items: center; justify-content: center; font-size: 21px;
}
.launch-card h3 { margin: 0 0 3px; font-size: 15px; }
.launch-card p { margin: 0; color: var(--muted); font-size: 13px; line-height: 1.45; }
.ico-teal { background: var(--teal-50); color: var(--teal-dark); }
.ico-blue { background: #eff6ff; color: #1d4ed8; }
.ico-amber { background: #fffbeb; color: #b45309; }
.ico-violet { background: #f5f3ff; color: #6d28d9; }
.ico-slate { background: var(--surface-2); color: var(--ink-2); }

/* ============================ Cards ============================ */
.cards { display: grid; grid-template-columns: repeat(auto-fill, minmax(240px, 1fr)); gap: 16px; margin-top: 20px; }
.card {
    display: block; background: var(--surface); border: 1px solid var(--line);
    border-radius: var(--radius-lg); padding: 18px 20px; color: var(--ink);
    transition: border-color .12s, box-shadow .12s, transform .12s;
}
.card:hover { border-color: var(--line-2); text-decoration: none; box-shadow: var(--shadow-sm); transform: translateY(-1px); }
.card h2 { margin: 0 0 6px; font-size: 17px; color: var(--ink); }
.card p { margin: 0; color: var(--muted); font-size: 14px; }

/* ============================ Messages ============================ */
.messages { list-style: none; padding: 0; margin: 0 0 18px; }
.msg { padding: 11px 14px; border-radius: var(--radius); margin-bottom: 8px; font-size: 14px; }
.msg.success { background: #ecfdf5; color: var(--green); border: 1px solid #a7f3d0; }
.msg.error { background: #fef2f2; color: var(--red); border: 1px solid #fecaca; }
.msg.warning { background: #fffbeb; color: var(--amber); border: 1px solid #fde68a; }
.msg.info { background: var(--teal-50); color: var(--teal-800); border: 1px solid var(--teal-100); }

/* ======================== Forms / tables ======================== */
input[type=text], input[type=password], input[type=number], input[type=email], input[type=date], select, textarea {
    width: 100%; padding: 9px 11px; border: 1px solid var(--line-2); border-radius: 8px; font: inherit; background: var(--surface); color: var(--ink);
}
input:focus, select:focus, textarea:focus { outline: none; border-color: var(--teal); box-shadow: 0 0 0 3px var(--teal-100); }

button.primary, .btn {
    background: var(--teal); color: #fff; border: none; border-radius: 8px;
    padding: 9px 16px; font: inherit; font-weight: 600; cursor: pointer; display: inline-flex;
    align-items: center; gap: 7px;
}
button.primary:hover, .btn:hover { background: var(--teal-dark); text-decoration: none; }
.btn.secondary { background: var(--surface); color: var(--ink); border: 1px solid var(--line-2); }
.btn.secondary:hover { background: var(--surface-2); }

table { width: 100%; border-collapse: collapse; background: var(--surface); border-radius: var(--radius-lg); overflow: hidden; }
th, td { text-align: left; padding: 10px 14px; border-bottom: 1px solid var(--line); font-size: 14px; }
th { background: var(--surface-2); font-weight: 600; color: var(--ink-2); }
tbody tr:last-child td { border-bottom: none; }
tbody tr:hover td { background: var(--surface-2); }

/* ============================ Login ============================ */
.login-wrap { max-width: 380px; margin: 9vh auto 0; background: var(--surface); padding: 34px; border: 1px solid var(--line); border-radius: 16px; box-shadow: var(--shadow-sm); }
.login-wrap h1 { color: var(--ink); text-align: center; }
.subtitle { text-align: center; color: var(--muted); margin-top: 0; }
.login-form { display: flex; flex-direction: column; gap: 6px; }
.login-form label { font-size: 13px; font-weight: 600; margin-top: 8px; }
.login-form button { margin-top: 16px; background: var(--teal); color: #fff; border: none; border-radius: 8px; padding: 11px; font-weight: 600; cursor: pointer; }
.login-form button:hover { background: var(--teal-dark); }
.error { color: var(--red); font-size: 14px; }

/* ====================== Utilities & chrome ====================== */
.muted { color: var(--muted); font-size: 14px; }
.page-head { display: flex; align-items: center; justify-content: space-between; gap: 16px; flex-wrap: wrap; }
.searchbar { display: flex; gap: 8px; margin: 14px 0; max-width: 520px; }
.searchbar input { flex: 1; }
.pager { display: flex; gap: 16px; align-items: center; margin-top: 16px; }
.scroll-x { overflow-x: auto; }
code { background: var(--surface-2); border: 1px solid var(--line); padding: 1px 5px; border-radius: 4px; font-size: 13px; }

td.actions a, td.actions { white-space: nowrap; }
td.actions a { margin-right: 12px; }
a.danger, .danger { color: var(--red); }
.danger-btn { background: var(--red); }
.danger-btn:hover { background: #991b1b; }

/* Stacked forms */
.stacked-form { max-width: 560px; }
.form-row { margin-bottom: 16px; display: flex; flex-direction: column; gap: 4px; }
.form-row label { font-weight: 600; font-size: 14px; }
.form-row .errorlist { color: var(--red); font-size: 13px; margin: 4px 0 0; padding-left: 18px; }
.form-actions { display: flex; gap: 10px; margin-top: 20px; flex-wrap: wrap; }

/* Column mapping */
.map-table { max-width: 640px; margin-bottom: 24px; }
.map-table select { width: 100%; }

/* Detail */
.detail-grid h2 { font-size: 16px; margin-top: 24px; }
.detail-grid th { width: 220px; }

/* Stat cards */
.stat-cards { display: flex; gap: 14px; flex-wrap: wrap; margin: 18px 0; }
.stat { background: var(--surface); border: 1px solid var(--line); border-radius: var(--radius-lg); padding: 16px 22px; min-width: 120px; text-align: center; }
.stat .num { display: block; font-size: 28px; font-weight: 700; color: var(--ink); letter-spacing: -.02em; }
.stat .lbl { color: var(--muted); font-size: 13px; }
.stat.ok .num { color: var(--green); }
.stat.bad .num { color: var(--red); }

/* Badges */
.badge { display: inline-block; background: var(--teal-100); color: var(--teal-800); font-size: 11px; font-weight: 600; padding: 2px 9px; border-radius: 10px; margin-left: 8px; vertical-align: middle; }
.nav-badge { background: var(--teal); color: #fff; border-radius: 10px; padding: 0 7px; font-size: 12px; font-weight: 700; }

/* Quick Look Up search form */
.lookup-form { background: var(--surface); border: 1px solid var(--line); border-radius: var(--radius-lg); padding: 20px; margin-bottom: 22px; }
.lookup-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(170px, 1fr)); gap: 14px; }
.lookup-grid .form-row { margin-bottom: 0; }
.lookup-form .form-actions { justify-content: flex-end; }

/* List builder */
.builder { display: grid; grid-template-columns: 1fr 330px; gap: 24px; align-items: start; }
.builder-main h3 { font-size: 15px; margin: 20px 0 8px; border-top: 1px solid var(--line); padding-top: 14px; }
.builder-main h3:first-of-type { border-top: none; padding-top: 0; }
.checkbox-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 6px; }
.chk { font-size: 13px; font-weight: 400; }
.builder-side { background: var(--surface); border: 1px solid var(--line); border-radius: var(--radius-lg); padding: 16px; position: sticky; top: 76px; }
.builder-side h3 { font-size: 15px; margin: 14px 0 8px; }
.step { border: 1px solid var(--line); border-radius: 8px; padding: 8px 10px; margin-bottom: 8px; font-size: 13px; }
.step ul { margin: 4px 0 0 16px; padding: 0; }
.link-btn { background: none; border: none; color: var(--teal-dark); cursor: pointer; padding: 0; font: inherit; font-size: 13px; text-decoration: underline; }
.preview-counts { display: grid; grid-template-columns: repeat(4, 1fr); gap: 8px; margin: 12px 0; }
.preview-counts > div { background: var(--surface-2); border: 1px solid var(--line); border-radius: 8px; padding: 8px; text-align: center; }
.preview-counts .num { display: block; font-size: 20px; font-weight: 700; color: var(--teal-dark); }
.preview-counts .lbl { font-size: 11px; color: var(--muted); }

/* Vertical criteria fields (VAN-style: label left, control right, stacked) */
.vfields { display: flex; flex-direction: column; gap: 12px; }
.vrow { display: flex; align-items: flex-start; gap: 14px; }
.vrow > label { flex: 0 0 130px; text-align: right; font-weight: 600; font-size: 14px; color: var(--ink-2); padding-top: 8px; }
.vrow > .vctl { flex: 1; min-width: 0; }
.vctl.inline2 { display: flex; gap: 8px; align-items: center; }
.vctl.inline2 > * { flex: 1; }

/* District field: clickable (blue) label toggles dropdown <-> multi-select checkboxes */
.dlabel {
    flex: 0 0 130px; text-align: right; font-weight: 600; font-size: 14px; padding-top: 8px;
    background: none; border: none; cursor: pointer; color: var(--teal-dark);
    text-decoration: underline; text-decoration-style: dotted; text-underline-offset: 3px;
    font-family: inherit;
}
.dlabel:hover { color: var(--teal); }
.district-field .dsingle[hidden] { display: none; }
.dmulti { border: 1px solid var(--line); border-radius: 8px; padding: 8px 10px; background: var(--surface-2); }
.dmulti-actions { font-size: 12px; margin-bottom: 6px; }
.dmulti-list { display: flex; flex-wrap: wrap; gap: 6px 16px; max-height: 180px; overflow-y: auto; }
@media (max-width: 700px) { .dlabel { text-align: left; flex-basis: auto; padding-top: 0; } }
.disabled-panel > summary { color: var(--muted); }
.soon { font-size: 11px; font-weight: 600; color: var(--amber); background: #fffbeb; border: 1px solid #fde68a; border-radius: 10px; padding: 1px 8px; margin-left: 8px; }
@media (max-width: 700px) {
  .vrow { flex-direction: column; gap: 4px; }
  .vrow > label { text-align: left; flex-basis: auto; padding-top: 0; }
  .vctl.inline2 { flex-direction: column; align-items: stretch; }
}

/* Accordion panels */
.panels { display: flex; flex-direction: column; gap: 10px; }
.panel { background: var(--surface); border: 1px solid var(--line); border-radius: var(--radius); }
.panel > summary { list-style: none; cursor: pointer; padding: 12px 16px; font-weight: 600; font-size: 15px; display: flex; align-items: center; }
.panel > summary::-webkit-details-marker { display: none; }
.panel > summary::before { content: "▸"; margin-right: 8px; color: var(--muted); }
.panel[open] > summary::before { content: "▾"; }
.panel .panel-body { padding: 0 16px 16px; }
.panel .lbl { display: block; font-size: 13px; color: var(--muted); margin-bottom: 4px; }
.star { margin-left: auto; background: none; border: none; cursor: pointer; font-size: 16px; color: var(--line-2); line-height: 1; }
.star.on { color: #f59e0b; }
.run-btn { background: var(--green); width: 100%; text-align: center; justify-content: center; }
.run-btn:hover { background: #065f46; }
.preview-btn { width: 100%; }
.preview-counts.big > div { padding: 14px; }
.preview-counts.big .num { font-size: 26px; }
.head-actions { display: flex; gap: 8px; }

/* My List toolbar */
/* ===================== Bounded, scrollable table =====================
   The house pattern for any list that can grow without limit. The page stays a fixed, readable
   height and the rows scroll inside it with the header pinned — so nothing is hidden (no
   truncation, no "show all") and no screen turns into an endless dump. */
.table-scroll { overflow: auto; max-height: 380px; border: 1px solid var(--line);
    border-radius: var(--radius-lg); background: var(--surface); }
.table-scroll table { border-collapse: separate; border-spacing: 0; overflow: visible;
    border-radius: 0; margin: 0; }
.table-scroll thead th { position: sticky; top: 0; z-index: 2; background: var(--surface-2);
    border-bottom: 0; box-shadow: inset 0 -1px 0 var(--line-2); }
.table-scroll.tall { max-height: 560px; }
.table-scroll.short { max-height: 240px; }

/* ===================== Filter bar =====================
   Scope before results. Range presets read as one segmented control; the narrowing selects sit
   underneath so the common choice is one click and the rare one is still there. */
.filterbar { display: flex; flex-direction: column; gap: 10px; background: var(--surface);
    border: 1px solid var(--line); border-radius: var(--radius-lg); padding: 12px 14px; margin: 14px 0 10px; }
.fb-ranges { display: inline-flex; flex-wrap: wrap; gap: 2px; background: var(--bg);
    border: 1px solid var(--line); border-radius: 999px; padding: 3px; align-self: flex-start; }
.fb-range { padding: 6px 14px; border-radius: 999px; font-size: 13px; font-weight: 600;
    color: var(--ink-2); white-space: nowrap; }
.fb-range:hover { color: var(--ink); text-decoration: none; background: var(--surface); }
.fb-range.on { background: var(--teal); color: #fff; }
.fb-range.on:hover { background: var(--teal); color: #fff; }
.fb-fields { display: flex; flex-wrap: wrap; gap: 10px 14px; align-items: flex-end; }
.fb-field { display: flex; flex-direction: column; gap: 3px; font-size: 12px; }
.fb-field > span { font-weight: 600; color: var(--muted); text-transform: uppercase;
    letter-spacing: .04em; font-size: 10.5px; }
.fb-field select, .fb-field input { min-width: 150px; padding: 7px 9px; font-size: 13.5px; }
.fb-clear { align-self: flex-end; font-size: 13px; padding-bottom: 8px; }
.fb-apply { align-self: flex-end; }

/* ===================== Multi-select facet =====================
   Tick more than one. Closed it reports the selection; open it's a checkbox list. */
.multi { position: relative; display: flex; flex-direction: column; gap: 3px; }
.multi-label { font-weight: 600; color: var(--muted); text-transform: uppercase;
    letter-spacing: .04em; font-size: 10.5px; }
.multi-btn { display: inline-flex; align-items: center; justify-content: space-between; gap: 8px;
    min-width: 168px; height: 36px; padding: 0 10px; font: inherit; font-size: 13.5px;
    background: var(--surface); color: var(--ink); border: 1px solid var(--line-2);
    border-radius: 8px; cursor: pointer; text-align: left; }
.multi-btn:hover { border-color: var(--teal); }
.multi-btn i { font-size: 15px; color: var(--muted); flex: none; }
.multi-summary { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.multi.has-sel .multi-btn { border-color: var(--teal); background: var(--teal-50); font-weight: 600; }
.multi-panel { position: absolute; top: calc(100% + 4px); left: 0; z-index: 40; min-width: 100%;
    max-width: 320px; background: var(--surface); border: 1px solid var(--line-2);
    border-radius: 10px; box-shadow: var(--shadow); padding: 8px; }
.multi-search { width: 100%; margin-bottom: 6px; padding: 6px 8px; font-size: 13px; }
.multi-opts { max-height: 240px; overflow-y: auto; display: flex; flex-direction: column; gap: 1px; }
.multi-opt { display: flex; align-items: center; gap: 8px; padding: 6px 7px; border-radius: 6px;
    font-size: 13.5px; cursor: pointer; white-space: nowrap; }
.multi-opt:hover { background: var(--teal-50); }
.multi-opt input { flex: none; }
.multi-none { margin: 4px 6px; font-size: 13px; }
.multi-clear { margin: 6px 0 0 6px; }
.scope-line { color: var(--muted); font-size: 13.5px; margin: 0 0 14px; }

/* Headline numbers for a report — bigger than .dash-stat, evenly sized. */
.result-stats { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
    gap: 12px; margin: 0 0 18px; }
.result-stats .stat { min-width: 0; }
.result-stats .num { font-variant-numeric: tabular-nums; }

/* Proportion bars — a count next to a bar reads instantly; a bare number in a table does not. */
.mini-bars { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 7px; }
.mini-bars li { display: grid; grid-template-columns: minmax(90px, 34%) 1fr auto; gap: 10px;
    align-items: center; font-size: 13.5px; }
.mb-label { color: var(--ink-2); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.mb-track { height: 8px; background: var(--bg); border: 1px solid var(--line); border-radius: 999px; overflow: hidden; }
.mb-fill { display: block; height: 100%; background: var(--teal); }
.mb-n { font-variant-numeric: tabular-nums; color: var(--muted); min-width: 42px; text-align: right; }

.report-block { margin-top: 22px; }
.rb-head { display: flex; align-items: baseline; gap: 12px; flex-wrap: wrap; margin-bottom: 8px; }
.rb-head h2 { margin: 0; font-size: 17px; }
.rb-head .muted { margin: 0; font-size: 13px; }
.rb-more { margin: 8px 0 0; font-size: 13px; }
.q-name { margin: 0 0 2px; font-size: 15px; }
.q-total { margin: 0 0 10px; font-size: 12.5px; }

/* One empty state everywhere, instead of a bare "No results." in a table cell. */
.empty-state { text-align: center; padding: 46px 24px; background: var(--surface);
    border: 1px solid var(--line); border-radius: var(--radius-lg); }
.empty-state > i { font-size: 34px; color: var(--line-2); display: block; margin-bottom: 10px; }
.empty-state h2 { margin: 0 0 6px; font-size: 18px; }
.empty-state .muted { margin: 0 0 16px; max-width: 46ch; margin-left: auto; margin-right: auto; }
.empty-state .btn + .btn { margin-left: 8px; }
/* Inside a table the state replaces the whole body, so drop the nested border and let the table's
   own frame hold it. */
.empty-row > td { padding: 0; border: 0; background: none; }
.empty-row .empty-state { border: 0; border-radius: 0; }

/* Call desk: the ask leads, then one-tap outcomes. A caller logs ~60 of these an hour. */
.ask-strip { display: flex; align-items: center; gap: 22px; flex-wrap: wrap;
    background: var(--surface); border: 1px solid var(--line); border-left: 3px solid var(--amber);
    border-radius: var(--radius-lg); padding: 14px 18px; margin-bottom: 12px; }
.ask-main { display: flex; flex-direction: column; }
.ask-label { font-size: 11px; font-weight: 700; letter-spacing: .05em; text-transform: uppercase; color: var(--muted); }
.ask-num { font-size: 34px; font-weight: 700; line-height: 1.05; letter-spacing: -.02em;
    color: var(--amber); font-variant-numeric: tabular-nums; }
.ask-side { display: flex; flex-direction: column; gap: 1px; }
.ask-side-lbl { font-size: 11px; color: var(--muted); text-transform: uppercase; letter-spacing: .04em; }
.ask-side-val { font-size: 16px; font-weight: 600; font-variant-numeric: tabular-nums; }
.ask-call { font-variant-numeric: tabular-nums; }
.ask-nophone { margin-left: auto; color: var(--muted); font-size: 13px; display: inline-flex; align-items: center; gap: 5px; }
/* Primary + alt phone stacked so the caller sees both without leaving the desk. */
.ask-phones { margin-left: auto; display: flex; flex-direction: column; align-items: stretch; gap: 4px; }
.ask-call-alt { font-size: 13px; font-variant-numeric: tabular-nums; padding: 5px 10px; text-align: center; }

/* All-reach contact card — every phone, email, and address surface visible during the call
   so the candidate never has to jump into the full donor record for a second number. */
.contact-card { padding: 12px 16px; margin-bottom: 12px; }
.contact-grid { display: grid; grid-template-columns: max-content 1fr; gap: 6px 18px;
    font-size: 14px; align-items: baseline; }
.cg-label { color: var(--muted); font-size: 11px; text-transform: uppercase; letter-spacing: .05em;
    font-weight: 600; padding-top: 2px; }
.cg-val { color: var(--ink); word-break: break-word; }
.cg-val a { color: var(--ink); text-decoration: none; border-bottom: 1px solid var(--line-strong, var(--line)); }
.cg-val a:hover { color: var(--amber); border-bottom-color: currentColor; }

/* Last call — the context you need before they pick up, above the form rather than under it. */
.last-call { display: flex; align-items: baseline; flex-wrap: wrap; gap: 10px; font-size: 13px;
    background: var(--bg); border: 1px solid var(--line); border-radius: var(--radius);
    padding: 9px 14px; margin-bottom: 12px; }
.lc-when { font-weight: 700; color: var(--ink-2); }
.lc-status { font-weight: 600; }
.lc-amt { color: var(--ink-2); }
.lc-amt.good { color: var(--green); font-weight: 600; }
.lc-note { color: var(--muted); font-style: italic; flex: 1; min-width: 200px; }

.oc-card h3 { margin-top: 0; }
.oc-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(160px, 1fr)); gap: 8px; }
.oc-btn { display: flex; align-items: center; justify-content: center; gap: 7px; min-height: 52px;
    padding: 10px 12px; font: inherit; font-size: 14px; font-weight: 600; cursor: pointer;
    background: var(--surface); color: var(--ink); border: 1px solid var(--line-2);
    border-radius: var(--radius); text-align: center; }
.oc-btn i { font-size: 17px; color: var(--muted); }
.oc-btn:hover { border-color: var(--teal); background: var(--teal-50); }
.oc-btn:hover i { color: var(--teal-dark); }
.oc-btn.good { border-color: var(--green); color: var(--green); }
.oc-btn.good i { color: var(--green); }
.oc-btn.good:hover { background: var(--teal-50); }
.oc-btn.bad:hover { border-color: var(--red); background: transparent; color: var(--red); }
.oc-btn.small { min-height: 42px; font-size: 13px; font-weight: 500; }
.oc-more, .oc-extra { margin-top: 10px; }
.oc-more > summary, .oc-extra > summary { cursor: pointer; font-size: 13px; color: var(--muted); padding: 6px 2px; }
.oc-more > summary:hover, .oc-extra > summary:hover { color: var(--teal-dark); }
.oc-more .oc-grid { margin-top: 6px; }
.oc-amount { margin-top: 12px; background: var(--bg); border: 1px solid var(--teal);
    border-radius: var(--radius); padding: 12px 14px; }
.oc-amount label { display: block; font-weight: 600; font-size: 14px; margin-bottom: 6px; }
.oc-amount-row { display: flex; gap: 8px; flex-wrap: wrap; }
.oc-amount-row input { flex: 1; min-width: 120px; font-size: 20px; font-weight: 600;
    font-variant-numeric: tabular-nums; }

/* Rarely-used search fields, tucked but one click away. */
.more-fields { margin-top: 12px; }
.more-fields > summary { cursor: pointer; font-size: 13px; font-weight: 600; color: var(--teal-dark);
    padding: 6px 2px; list-style: none; }
.more-fields > summary::-webkit-details-marker { display: none; }
.more-fields > summary::before { content: "\ea5f"; font-family: "tabler-icons"; font-weight: 400;
    margin-right: 5px; display: inline-block; transition: transform .12s; }
.more-fields[open] > summary::before { transform: rotate(90deg); }
.more-fields .lookup-grid { margin-top: 8px; }

/* Voter record identity strip — who this person is, before any panel is opened. */
.vr-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 20px;
    flex-wrap: wrap; background: var(--surface); border: 1px solid var(--line);
    border-radius: var(--radius-lg); padding: 18px 22px; margin-bottom: 16px; }
.vr-id { min-width: 0; }
.vr-id h1 { margin: 0 0 6px; font-size: 26px; line-height: 1.15; }
.vr-facts { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; margin: 0 0 8px;
    font-size: 14px; color: var(--ink-2); }
.vr-party { font-weight: 700; font-size: 12px; letter-spacing: .03em; text-transform: uppercase;
    border-radius: 999px; padding: 3px 10px; background: var(--bg); border: 1px solid var(--line-2); }
.vr-party.p-dem { color: #60a5fa; border-color: #1e3a8a; background: #131e33; }
.vr-party.p-rep { color: #f87171; border-color: #7f1d1d; background: #2b1414; }
.vr-party.p-non, .vr-party.p-npp { color: var(--ink-2); }
.vr-status { font-size: 12px; font-weight: 600; border-radius: 999px; padding: 2px 9px;
    background: var(--bg); border: 1px solid var(--line-2); color: var(--muted); }
.vr-status.s-a { color: var(--green); border-color: #14532d; }
.vr-reach { display: flex; flex-wrap: wrap; gap: 14px; margin: 0; font-size: 14px; }
.vr-reach a, .vr-reach span { display: inline-flex; align-items: center; gap: 5px; }
.vr-reach i { color: var(--muted); }
.vr-actions { text-align: right; }
.vr-last { font-size: 12.5px; color: var(--muted); margin: 8px 0 0; max-width: 280px; }
.panel-sub { font-size: 14px; margin: 18px 0 2px; }

/* Light theme keeps the party chips readable too. */
:root:not([data-theme="dark"]) .vr-party.p-dem { color: #1d4ed8; border-color: #bfdbfe; background: #eff6ff; }
:root:not([data-theme="dark"]) .vr-party.p-rep { color: #b91c1c; border-color: #fecaca; background: #fef2f2; }

/* Script builder: show the branching on the page instead of one click down. */
.el-q { display: flex; align-items: baseline; gap: 6px; margin: 2px 0 8px; font-size: 14px; }
.el-q i { color: var(--teal-dark); }
.branch-map { list-style: none; margin: 0 0 8px; padding: 0 0 0 2px; display: grid; gap: 3px; }
.branch-map li { display: flex; align-items: center; gap: 7px; font-size: 12.5px; }
.branch-map i { color: var(--line-2); font-size: 14px; }
.bm-ans { color: var(--ink-2); }
.bm-goes { color: var(--muted); }
.bm-goes.set { color: var(--teal-dark); font-weight: 600; }
hr.soft { border: 0; border-top: 1px solid var(--line); margin: 14px 0; }
.in-use { display: flex; align-items: baseline; gap: 7px; }

/* Script preview — reads as a sandbox, never mistakable for the live screen. */
.preview-note { background: var(--teal-50); border: 1px solid var(--teal); display: flex;
    align-items: baseline; gap: 8px; }
.preview-screen { border: 2px dashed var(--line-2); border-radius: var(--radius-lg);
    padding: 20px; margin-top: 14px; }
.preview-step { font-size: 11px; font-weight: 700; letter-spacing: .05em; text-transform: uppercase;
    color: var(--muted); margin: 0 0 8px; }
.preview-trail { font-size: 12px; color: var(--muted); margin: 12px 0 0; display: flex;
    align-items: center; gap: 6px; }

/* Dashboard status board — the 8am read. Numbers lead; the launchpad moves below. */
.board { display: grid; grid-template-columns: repeat(auto-fit, minmax(190px, 1fr)); gap: 12px;
    margin: 18px 0; }
.board-tile { display: flex; flex-direction: column; gap: 2px; background: var(--surface);
    border: 1px solid var(--line); border-radius: var(--radius-lg); padding: 16px 18px; color: var(--ink); }
a.board-tile:hover { border-color: var(--teal); text-decoration: none; }
.bt-num { font-size: 30px; font-weight: 700; letter-spacing: -.02em; line-height: 1.1;
    font-variant-numeric: tabular-nums; }
.bt-lbl { font-size: 13px; color: var(--ink-2); }
.bt-delta { font-size: 12px; color: var(--muted); display: inline-flex; align-items: center; gap: 3px; margin-top: 4px; }
.bt-delta.up { color: var(--green); }
.bt-delta.down { color: var(--red); }

.dash-split { display: grid; grid-template-columns: repeat(auto-fit, minmax(320px, 1fr)); gap: 14px; }
.card-head { display: flex; align-items: baseline; justify-content: space-between; gap: 10px; }
.card-head h2 { margin: 0; font-size: 16px; }
.card-head a { font-size: 12px; }
.card-sub { font-size: 12px; margin: 2px 0 12px; }
.live-list { list-style: none; margin: 0; padding: 0; }
.live-list li { padding: 9px 0; border-top: 1px solid var(--line); }
.live-list li:first-child { border-top: 0; }
.ll-top { display: flex; align-items: baseline; justify-content: space-between; gap: 10px; }
.ll-name { font-weight: 600; font-size: 14px; }
.ll-code { font-size: 12px; letter-spacing: .1em; font-weight: 700; color: var(--teal-dark);
    background: none; border: 0; padding: 0; }
.ll-bar { height: 5px; background: var(--bg); border-radius: 999px; overflow: hidden; margin: 6px 0 4px; }
.ll-bar span { display: block; height: 100%; background: var(--teal); }
.ll-meta { font-size: 12px; color: var(--muted); }
table.lean th, table.lean td { padding: 6px 0; border-bottom: 1px solid var(--line); font-size: 13px; }
table.lean tbody tr:last-child td { border-bottom: 0; }
table.lean { background: none; }

/* The launchpad is a destination list, not the morning read — it collapses under the board. */
.all-features { margin-top: 22px; border-top: 1px solid var(--line); padding-top: 8px; }
.all-features > summary { cursor: pointer; font-size: 13px; font-weight: 600; color: var(--ink-2);
    display: flex; align-items: center; gap: 7px; padding: 8px 2px; list-style: none; }
.all-features > summary::-webkit-details-marker { display: none; }
.all-features > summary:hover { color: var(--teal-dark); }

/* Right-align counts so a column of numbers reads as a column. */
.num-col { text-align: right; font-variant-numeric: tabular-nums; }
th.num-col { text-align: right; }

/* "+ New X" in a page head: the create form is the rarest action on a library screen, so it opens
   from a button instead of occupying the top of the page above the thing you came to see. */
.inline-new > summary { list-style: none; cursor: pointer; }
.inline-new > summary::-webkit-details-marker { display: none; }
.inline-new-form { display: flex; gap: 8px; margin-top: 10px; }
.inline-new-form input { min-width: 240px; }

/* A disabled control must never look clickable — .btn had no [disabled] rule at all, so a
   "Apply to 0 voters" button rendered in full primary teal. */
.btn[disabled], .btn.is-disabled, button.primary[disabled] {
    opacity: .5; cursor: not-allowed; pointer-events: none; box-shadow: none; }

/* Grouped by intent, with a quiet caption over each cluster — a flat row of identical chips makes
   the reader test every label to find the one they want. */
.toolbar { display: flex; flex-wrap: wrap; gap: 10px 22px; margin: 16px 0; align-items: flex-end; }
.tool-group { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; position: relative; }
.tool-group + .tool-group::before { content: ""; position: absolute; left: -11px; top: 4px; bottom: 4px;
    width: 1px; background: var(--line); }
.tool-label { flex-basis: 100%; font-size: 11px; font-weight: 700; letter-spacing: .05em;
    text-transform: uppercase; color: var(--muted); margin-bottom: 1px; }
/* One height for every chip in the row, whatever's inside it. */
.toolbar .tool { display: inline-flex; align-items: center; gap: 6px; height: 36px;
    border: 1px solid var(--line-2); background: var(--surface); border-radius: 8px;
    padding: 0 12px; font-size: 13px; color: var(--ink); cursor: pointer; white-space: nowrap; }
.toolbar .tool i { font-size: 15px; color: var(--muted); }
.toolbar a.tool:hover { border-color: var(--teal); text-decoration: none; }
.toolbar a.tool:hover i { color: var(--teal-dark); }
.toolbar .tool.disabled { color: var(--muted); opacity: .55; cursor: not-allowed; }

/* Notes */
.notes-block { background: var(--surface); border: 1px solid var(--line); border-radius: var(--radius-lg); padding: 16px 20px; margin-bottom: 22px; }
.notes-block h2 { margin-top: 0; font-size: 16px; }
.note { border-left: 3px solid var(--line); padding: 6px 12px; margin-bottom: 8px; }
.note.pinned { border-left-color: #f59e0b; background: #fffbeb; }
.note-meta { font-size: 12px; color: var(--muted); margin-bottom: 2px; }
.note-form { margin-top: 12px; }
.note-form textarea { width: 100%; padding: 8px 10px; border: 1px solid var(--line-2); border-radius: 8px; font: inherit; }
.note-form-actions { display: flex; align-items: center; gap: 14px; margin-top: 8px; }

/* Engagement chips */
.chips { display: flex; flex-wrap: wrap; gap: 6px; margin-bottom: 8px; }
.chip { display: inline-flex; align-items: center; gap: 6px; background: var(--teal-50); border: 1px solid var(--teal-100); color: var(--teal-800); border-radius: 14px; padding: 2px 6px 2px 10px; font-size: 13px; }
.chip-x { background: none; border: none; cursor: pointer; color: var(--teal-800); font-size: 15px; line-height: 1; padding: 0 2px; }
.chip-x:hover { color: var(--red); }
.inline-apply { display: flex; gap: 8px; align-items: center; max-width: 420px; }
.inline-apply select { flex: 1; }

/* Voter record */
.record-panels { max-width: 760px; }
.locked { font-size: 11px; color: var(--muted); border: 1px solid var(--line); border-radius: 10px; padding: 0 7px; margin-left: 6px; }
.add-row { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; margin-top: 10px; }
.add-row input, .add-row select { flex: 0 1 auto; }
.add-row input[name="full_line"], .add-row input[name="number"] { flex: 1 1 180px; }
.q-name { min-width: 170px; font-size: 14px; }
.edit-inline { display: inline-block; margin: 0 8px; }
.edit-inline > summary { cursor: pointer; color: var(--teal-dark); font-size: 13px; list-style: none; display: inline; }
.edit-inline > summary::-webkit-details-marker { display: none; }
.edit-inline .add-row { margin-top: 6px; }
.script-text { white-space: pre-wrap; font-size: 14px; margin-top: 6px; }
.script-block { background: var(--surface-2); border: 1px solid var(--line); border-radius: 8px; padding: 12px 14px; margin-bottom: 12px; }

/* Guided canvass run (mobile-first) */
/* margin auto — this had a max-width but no centring, so it sat 28px off-centre inside the
   outreach column and looked accidental on any wide screen. */
.canvass-screen { max-width: 620px; margin: 0 auto; }
.canvass-screen .form-row label { font-size: 15px; }
.canvass-screen select, .canvass-screen textarea { padding: 12px; font-size: 16px; }
.btn-big { width: 100%; justify-content: center; padding: 14px; font-size: 17px; }
.run-progress { margin: 8px 0 16px; }
.run-bar { height: 10px; background: var(--surface-2); border: 1px solid var(--line); border-radius: 999px; overflow: hidden; }
.run-bar span { display: block; height: 100%; background: var(--teal); }
.run-start { padding: 13px 22px; font-size: 16px; }
.src-row { display: flex; align-items: center; gap: 10px; background: var(--surface); border: 1px solid var(--line); border-radius: 10px; padding: 12px 14px; font-size: 15px; font-weight: 400; cursor: pointer; }
.src-row:hover { border-color: var(--line-2); }

/* Code-entry outreach launcher */
/* A card, like the sign-in screen — a single-task page floating on the raw background reads as
   an unfinished form rather than a deliberate destination. */
.code-launch { max-width: 420px; margin: 6vh auto 0; text-align: center; background: var(--surface);
    border: 1px solid var(--line); border-radius: var(--radius-lg); padding: 30px 26px 26px;
    box-shadow: var(--shadow-sm); }
.code-launch h1 { font-size: 24px; margin: 0 0 6px; }
.code-launch-ico { width: 52px; height: 52px; font-size: 28px; margin: 0 auto 14px; }
/* Input over button, both full width: the code is the task, and "Go" was a 80px chip next to a
   350px field — the one primary action shouldn't be the smallest thing on the page. */
.code-form { display: flex; flex-direction: column; gap: 10px; margin: 20px 0 8px; }
.code-form input { text-align: center; font-size: 26px; letter-spacing: .18em; text-transform: uppercase;
    padding: 16px 14px; font-weight: 700; }
/* The placeholder is a hint, not a value — shown in the same shouted, letter-spaced caps as a real
   code it looks like the field is already filled in. */
.code-form input::placeholder { text-transform: none; letter-spacing: normal; font-size: 16px;
    font-weight: 400; color: var(--muted); }
.code-form .btn { justify-content: center; padding: 14px; font-size: 17px; }
.code-manage { margin-top: 18px; font-size: 13px; }
/* The number IS the task on a call screen, so it gets the weight — and it's teal, not green,
   because green is semantic elsewhere in Foundry (success messages, healthy stats). */
.call-cta { margin: 0 0 18px; background: var(--teal); font-size: 20px; padding: 18px;
    box-shadow: var(--shadow-sm); font-variant-numeric: tabular-nums; }
.call-cta:hover { background: var(--teal-dark); }

/* Separate outreach shell (MiniVAN / phone-bank — no main app nav) */
.ob-body { margin: 0; background: var(--bg); }
.ob-bar { position: sticky; top: 0; z-index: 50; display: flex; align-items: center; justify-content: space-between;
    gap: 12px; background: var(--ink); color: #fff; padding: 0 16px; height: 54px; }
.ob-title { font-weight: 600; font-size: 16px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ob-exit { color: #fff; font-size: 14px; display: inline-flex; align-items: center; gap: 5px; white-space: nowrap; }
.ob-exit:hover { text-decoration: underline; color: #fff; }
.ob-main { max-width: 680px; margin: 0 auto; padding: 16px; }
/* Progress and the offline button share one row instead of the button sitting inside a paragraph
   with descriptive text wrapping raggedly around it. */
.walk-head { display: flex; align-items: center; justify-content: space-between; gap: 12px;
    flex-wrap: wrap; margin: 2px 0 12px; }
.ob-progress { font-size: 14px; color: var(--ink-2); margin: 0; }
.ob-progress strong { font-size: 17px; color: var(--ink); }
.offline-btn { white-space: nowrap; }
/* Roughly a third of the screen, never more — the walker returns to this page after every door
   and shouldn't have to scroll past a full-height map each time to reach the next name. */
#cmap { height: clamp(200px, 38vh, 340px); border: 1px solid var(--line); border-radius: var(--radius); }
.ob-list { margin-top: 12px; }

/* Households, not a flat list of people: one address header, then everyone behind that door. */
.ob-hh { background: var(--surface); border: 1px solid var(--line); border-radius: var(--radius-lg);
    margin-bottom: 10px; overflow: hidden; }
.ob-hh-addr { display: flex; align-items: center; gap: 6px; margin: 0; padding: 9px 14px;
    font-size: 12px; font-weight: 700; letter-spacing: .03em; text-transform: uppercase;
    color: var(--muted); background: var(--bg); border-bottom: 1px solid var(--line); }
.ob-row { display: flex; align-items: center; justify-content: space-between; gap: 12px;
    min-height: 56px; padding: 11px 14px; border-top: 1px solid var(--line);
    color: var(--ink); font-size: 16px; }
.ob-hh .ob-row:first-of-type { border-top: 0; }
.ob-row:hover { background: var(--teal-50); text-decoration: none; }
.ob-row.done { opacity: .55; }
/* Name on its own line, details beneath — a single run-on line of NAME · ADDRESS · AGE · PARTY
   wraps mid-address on a phone and is hard to scan door to door. */
.ob-who { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.ob-who strong { font-size: 16px; line-height: 1.25; font-weight: 600; }
.ob-sub { font-size: 13px; color: var(--muted); }
.ob-chev { flex: none; font-size: 18px; color: var(--line-2); }
.ob-chip { flex: none; display: inline-flex; align-items: center; gap: 4px; font-size: 12px;
    font-weight: 600; color: var(--green); background: var(--teal-50); border-radius: 999px;
    padding: 3px 9px; white-space: nowrap; }

/* Desktop: put the map beside the roster instead of stranding a phone-width column in the middle
   of a wide screen with the map pushing every name below the fold. */
@media (min-width: 900px) {
    .ob-main { max-width: 1040px; }
    .ob-split { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 20px; align-items: start; }
    .ob-split #cmap { height: calc(100vh - 190px); max-height: none; position: sticky; top: 70px; }
    .ob-split .ob-list { margin-top: 0; }
    .ob-split .ob-list-head { margin-top: 0; }
}
.pin-pop strong { display: block; margin-bottom: 6px; }
.pin-row { display: block; padding: 8px 4px; border-top: 1px solid var(--line); color: var(--teal-dark); font-size: 14px; }
.pin-row.done { color: var(--muted); }

/* Per-voter canvass screen: identity head, tabs, branching stepper, big tap targets.
   Built for a phone held one-handed outdoors: large type, generous targets, one clear next step. */
.cv-head { margin-bottom: 14px; }
.cv-head h1 { margin: 0 0 4px; font-size: 27px; line-height: 1.15; }
/* Separators are drawn by CSS, never typed into the template — so a voter with no age/sex can't
   render a stray leading "·". */
.cv-meta { margin: 0; font-size: 14px; color: var(--muted); display: flex; flex-wrap: wrap; align-items: center; }
.cv-meta > span + span::before { content: "·"; margin: 0 8px; color: var(--line-2); }
.cv-meta .cv-party { font-weight: 600; color: var(--ink-2); }
.cv-nophone { display: flex; align-items: center; gap: 8px; }

.cv-tabs { display: flex; gap: 2px; border-bottom: 1px solid var(--line); margin: 0 0 16px; overflow-x: auto; }
.cv-tab { background: none; border: none; border-bottom: 2px solid transparent; padding: 10px 14px;
    font: inherit; font-weight: 500; font-size: 15px; color: var(--muted); cursor: pointer; white-space: nowrap; }
.cv-tab:hover { color: var(--ink-2); }
.cv-tab.active { color: var(--teal-dark); border-bottom-color: var(--teal); }
.step-card { background: var(--surface); border: 1px solid var(--line); border-radius: var(--radius-lg); padding: 16px 18px; margin-bottom: 14px; }
.step-card h3 { margin: 0 0 6px; font-size: 17px; }
.bigbtns { display: flex; flex-direction: column; gap: 10px; }
.bigbtn { display: block; width: 100%; text-align: left; background: var(--surface); border: 1px solid var(--line-2);
    border-radius: 12px; padding: 16px 18px; font: inherit; font-size: 16px; font-weight: 500; color: var(--ink); cursor: pointer; }
.bigbtn:hover { border-color: var(--teal); background: var(--teal-50); }
/* Outlined, not solid — script navigation shouldn't compete with the call button or with Save
   for the eye. Only the one true commit action stays a solid slab. */
.bigbtn.next-btn { text-align: center; background: var(--surface); color: var(--teal-dark);
    border-color: var(--teal); font-weight: 600; }
.bigbtn.next-btn:hover { background: var(--teal-50); }
.bigbtn.good { border-color: #a7f3d0; color: var(--green); }
.bigbtn.ghost { border-style: dashed; color: var(--muted); }
.back-btn { background: none; border: none; color: var(--muted); font: inherit; cursor: pointer; padding: 4px 0; margin-bottom: 8px; }

/* Dispositions. A flat column of 15 identical full-width buttons is the thing that read as
   "computer-made" — a raw dump of the vocabulary. Now: the handful that cover most attempts sit
   in a compact grid, the long tail hides behind a disclosure, and both are visually quieter than
   the real primary action (Next / Save). */
.cantreach { margin-top: 18px; border-top: 1px solid var(--line); }
.cantreach > summary { cursor: pointer; font-weight: 600; font-size: 14px; color: var(--ink-2);
    padding: 12px 2px; list-style: none; display: flex; align-items: center; gap: 6px; }
.cantreach > summary::-webkit-details-marker { display: none; }
.cantreach > summary::before { content: "\ea5f"; font-family: "tabler-icons"; font-weight: 400;
    color: var(--muted); transition: transform .15s ease; }
.cantreach[open] > summary::before { transform: rotate(90deg); }
.cantreach > summary:hover { color: var(--teal-dark); }
.disp-wrap { padding-bottom: 4px; }
.disp-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(148px, 1fr)); gap: 8px; }
.disp-grid .bigbtn { text-align: center; padding: 14px 10px; font-size: 15px; }
.bigbtn.full { text-align: center; margin-top: 8px; display: flex; align-items: center;
    justify-content: center; gap: 8px; }
.more-disp { margin-top: 8px; }
.more-disp > summary { cursor: pointer; font-size: 13px; color: var(--muted); padding: 8px 2px; }
.more-disp > summary:hover { color: var(--teal-dark); }
/* Quieter than the primary four — otherwise opening the disclosure just restores the flat wall of
   identical buttons it was meant to defeat. */
.more-disp .disp-grid { margin-top: 6px; grid-template-columns: repeat(auto-fit, minmax(128px, 1fr)); }
.more-disp .disp-grid .bigbtn { padding: 10px 8px; font-size: 13.5px; color: var(--ink-2);
    border-color: var(--line); }
.kv { width: 100%; }
.kv td { padding: 9px 4px; border-bottom: 1px solid var(--line); font-size: 14px; }
.kv td:first-child { color: var(--muted); width: 38%; }
.linklike { background: none; border: 0; color: var(--teal-700, #0f766e); cursor: pointer; padding: 0 4px; vertical-align: middle; }
.linklike:hover { color: var(--teal, #14b8a6); }

/* Reports overview — dependency-free CSS charts */
.win-toggle{display:inline-flex; border:1px solid var(--line); border-radius:9px; overflow:hidden;}
.win-toggle a{padding:6px 12px; font-size:13px; color:var(--muted); text-decoration:none; border-right:1px solid var(--line);}
.win-toggle a:last-child{border-right:0;}
.win-toggle a.on{background:var(--teal); color:#fff; font-weight:600;}
.rep-grid{display:grid; grid-template-columns:1fr 1fr; gap:16px; margin-top:16px;}
@media(max-width:760px){.rep-grid{grid-template-columns:1fr;}}
.rep-card{padding:18px;}
.rep-card h2{font-size:16px; margin:0 0 14px;}
.hbar-row{display:grid; grid-template-columns:130px 1fr 44px; align-items:center; gap:10px; margin:7px 0; font-size:13.5px;}
.hbar-lbl{color:var(--ink); overflow:hidden; text-overflow:ellipsis; white-space:nowrap;}
.hbar-lbl small{display:block; font-size:11px; line-height:1;}
.hbar-track{background:var(--surface-2); border-radius:6px; height:16px; overflow:hidden;}
.hbar-fill{display:block; height:100%; background:var(--teal); border-radius:6px; min-width:2px;}
.hbar-fill.cov{background:var(--green);}
.hbar-n{text-align:right; font-weight:600; font-variant-numeric:tabular-nums; color:var(--ink);}
/* daily trend (vertical bars) */
.trend{display:flex; align-items:flex-end; gap:6px; height:120px; padding-top:6px;}
.trend-col{flex:1; display:flex; flex-direction:column; align-items:center; justify-content:flex-end; height:100%; gap:3px;}
.trend-bar{width:100%; max-width:26px; background:var(--teal); border-radius:4px 4px 0 0; min-height:2px; transition:height .2s;}
.trend-n{font-size:11px; color:var(--muted); font-variant-numeric:tabular-nums;}
.trend-dow{font-size:10px; color:var(--muted); text-transform:uppercase;}

/* Grid data entry */
.grid-actions{display:flex; align-items:center; gap:12px; margin:12px 0; flex-wrap:wrap;}
/* Save is always the rightmost thing, on every page — it used to jump to the left edge on page 2
   because the layout depended on how many buttons happened to be present. */
.grid-actions > .btn:not(.secondary){margin-left:auto;}
/* The scrollport. Sticky headers need a scrolling ancestor, and the global `table{overflow:hidden}`
   (there for border-radius) makes the table clip its own sticky cells — so the box lives here and
   the table opts out. */
.grid-scroll{overflow:auto; max-height:calc(100vh - 260px); border:1px solid var(--line);
  border-radius:var(--radius-lg); background:var(--surface);}
.grid-entry{border-collapse:separate; border-spacing:0; width:100%; min-width:520px; overflow:visible; border-radius:0;}
.grid-entry th{position:sticky; top:0; background:var(--surface-2); text-align:left; font-size:11px;
  text-transform:uppercase; letter-spacing:.05em; color:var(--muted); font-weight:700; padding:9px 10px;
  border-bottom:0; box-shadow:inset 0 -1px 0 var(--line-2); z-index:3;}
.grid-entry td{padding:7px 10px; border-bottom:1px solid var(--line); vertical-align:middle;}
.grid-entry tr:nth-child(even) td{background:var(--surface-2);}
/* Keep the name pinned while you scroll sideways through questions — otherwise you're answering
   Q3 for a row whose name left the screen. Sticky cells need an opaque background. */
.grid-entry .who{position:sticky; left:0; z-index:2; width:99%; min-width:190px;
  background:var(--surface); box-shadow:1px 0 0 var(--line);}
.grid-entry tr:nth-child(even) .who{background:var(--surface-2);}
.grid-entry th.who{z-index:4; background:var(--surface-2);}
.grid-entry .who strong{display:block; font-size:14px; line-height:1.2;}
.grid-entry .who .muted{font-size:12px;}
/* Let the name column absorb the slack so the dropdowns don't stretch to 600px on a wide screen. */
.grid-entry td:not(.who), .grid-entry th:not(.who){width:1%; white-space:nowrap;}
.grid-entry select{width:100%; min-width:150px; max-width:220px; min-height:40px; padding:8px 10px; font-size:15px;}
/* Light up the row you're working, and flag the ones that will actually save. */
.grid-entry tbody tr:hover td, .grid-entry tbody tr:focus-within td{background:var(--teal-50);}
.grid-entry tbody tr:focus-within .who, .grid-entry tbody tr:hover .who{background:var(--teal-50);}
.grid-entry tr.touched .who{box-shadow:inset 3px 0 0 var(--teal), 1px 0 0 var(--line);}
/* A save bar you can always reach — this screen runs ~2,600px tall with 50 rows on it. */
.grid-save-bar{position:sticky; bottom:0; z-index:4; background:var(--surface);
  border:1px solid var(--line); border-radius:var(--radius-lg); margin-top:12px;
  padding:10px 14px calc(10px + env(safe-area-inset-bottom)); box-shadow:0 -4px 14px rgba(15,23,42,.06);}
@media (max-width:700px){
  /* 16px is the exact threshold below which iOS zooms the whole page on focus. */
  .grid-entry select{font-size:16px; min-height:44px; min-width:130px;}
  .grid-entry td{padding:8px 10px;}
  .grid-scroll{max-height:calc(100vh - 300px);}
}

/* Single-task setup form on its own panel, sized to the form — a full-width heading over a 560px
   form with no surface under either reads as a fragment, not a page. */
.setup-card{max-width:620px; background:var(--surface); border:1px solid var(--line);
  border-radius:var(--radius-lg); padding:22px 24px 24px;}
.setup-card .page-head{margin-bottom:6px;}
.setup-card h1{font-size:22px; margin:0;}
.setup-card .stacked-form{max-width:none; margin-top:18px;}
/* The one line that says WHICH list you're about to freeze — not boilerplate. */
.setup-source{display:flex; align-items:center; gap:8px; margin:0 0 6px; font-size:15px;}
.setup-source i{color:var(--teal-dark);}
/* .muted hard-sets 14px, so <small class="muted"> wasn't small. */
.hint{display:block; margin-top:6px; font-size:12.5px; color:var(--muted); line-height:1.45;}

/* Script setup: which "couldn't reach them" outcomes volunteers may record. */
.disp-setup{background:var(--surface); border:1px solid var(--line); border-radius:var(--radius-lg);
  padding:20px 22px; margin-top:18px;}
.disp-setup h2{margin:0 0 4px; font-size:18px;}
.disp-groups{display:grid; grid-template-columns:repeat(auto-fit, minmax(230px, 1fr)); gap:14px; margin:16px 0;}
.disp-group{border:1px solid var(--line); border-radius:var(--radius); padding:12px 14px 10px; margin:0;}
.disp-group legend{font-size:13px; font-weight:700; padding:0 6px; color:var(--ink);}
.disp-help{font-size:12px; margin:0 0 8px;}
.disp-group .chk{display:flex; align-items:center; gap:7px; padding:4px 0; font-size:14px;}
.disp-star{font-size:10px; font-weight:700; text-transform:uppercase; letter-spacing:.04em;
  color:var(--teal-dark); background:var(--teal-50); border-radius:999px; padding:1px 7px;}
.disp-all{margin-top:6px;}
.disp-preview{background:var(--bg); border:1px solid var(--line); border-radius:var(--radius); padding:14px 16px;}
.disp-preview h3{margin:0 0 10px; font-size:14px;}
.disp-preview h4{margin:0 0 7px; font-size:13px; color:var(--muted); display:flex; align-items:center; gap:5px;}
.disp-preview-cols{display:grid; grid-template-columns:repeat(auto-fit, minmax(230px, 1fr)); gap:16px;}
.disp-tag{display:inline-block; font-size:12.5px; border:1px solid var(--line-2); border-radius:999px;
  padding:3px 10px; margin:0 5px 5px 0; color:var(--ink-2);}
.disp-tag.up{background:var(--teal); border-color:var(--teal); color:#fff; font-weight:600;}
.disp-legend{margin:12px 0 0; font-size:12px;}

/* Phone bank cards — the caller code is the hero, not a clipped table cell. */
.pb-grid{display:grid; grid-template-columns:repeat(auto-fill, minmax(320px, 1fr)); gap:14px; margin-top:16px;}
.pb-card{background:var(--surface); border:1px solid var(--line); border-radius:var(--radius-lg); padding:16px 18px;}
.pb-top{display:flex; align-items:flex-start; justify-content:space-between; gap:12px; flex-wrap:wrap;}
.pb-id h2{margin:0 0 2px; font-size:17px;}
.pb-id .muted{margin:0; font-size:13px;}
.pb-top .btn{flex:none;}
.pb-code{display:flex; align-items:center; gap:10px; flex-wrap:wrap; margin:14px 0 12px;
  background:var(--bg); border:1px dashed var(--line-2); border-radius:var(--radius); padding:10px 14px;}
.pb-code-label{font-size:11px; font-weight:700; text-transform:uppercase; letter-spacing:.05em; color:var(--muted);}
.pb-code code{font-size:22px; font-weight:700; letter-spacing:.16em; background:none; border:none;
  padding:0; color:var(--teal-dark); font-variant-numeric:tabular-nums;}
.pb-copy{margin-left:auto;}
.pb-actions{display:flex; gap:16px; flex-wrap:wrap; border-top:1px solid var(--line); padding-top:11px;}
.pb-actions form{margin:0;}

/* Crosstab / counts report table */
.crosstab { border-collapse: collapse; width: 100%; }
.crosstab th, .crosstab td { border: 1px solid var(--line); padding: 8px 12px; text-align: right; font-size: 14px; }
.crosstab thead th { background: var(--surface-2); text-align: right; color: var(--muted); font-weight: 600; }
.crosstab thead th:first-child, .crosstab .rowhdr { text-align: left; }
.crosstab .rowhdr { background: var(--surface-2); font-weight: 600; color: var(--ink); }
.crosstab .tot { font-weight: 700; background: var(--surface-2); }
.crosstab tfoot .tot { background: var(--teal-50); }
[data-theme="dark"] .crosstab tfoot .tot { background: rgba(13,148,136,.15); }

/* Bellows network tables: give each card a wider minimum (so it doesn't shrink to a squished
   ~250px), keep number columns on one line + right-aligned, and stack to one column when narrow. */
/* Roomier card grid: wider minimum so cards don't shrink to a squished ~250px, stacking to
   one column when narrow; wide tables scroll inside the card instead of cramming. */
.wide-cards, .net-cards { grid-template-columns: repeat(auto-fill, minmax(330px, 1fr)); }
.wide-cards .card, .net-cards .card { overflow-x: auto; }
/* Network tables also keep their number columns on one line + right-aligned. */
.net-cards th, .net-cards td:not(:first-child) { white-space: nowrap; }
.net-cards td:not(:first-child), .net-cards th:not(:first-child) { text-align: right; }

/* Candidate dashboard hero — leads the candidate straight to call time. */
.candidate-hero { display: flex; align-items: center; gap: 16px; text-decoration: none;
    background: var(--amber); color: #fff; border-radius: var(--radius-lg); padding: 18px 22px;
    margin: 4px 0 22px; box-shadow: var(--shadow-sm); }
.candidate-hero:hover { filter: brightness(1.05); }
.candidate-hero .ch-ico { font-size: 30px; display: flex; }
.candidate-hero .ch-text { flex: 1; }
.candidate-hero h2 { margin: 0; color: #fff; }
.candidate-hero p { margin: 2px 0 0; color: rgba(255,255,255,.9); font-size: 14px; }
.candidate-hero .ch-go { font-size: 24px; }

/* "View as" impersonation banner — shown on every page while a superadmin is impersonating. */
.impersonate-bar { display: flex; align-items: center; justify-content: space-between; gap: 14px;
    flex-wrap: wrap; margin: 0 0 16px; padding: 9px 14px; border-radius: var(--radius);
    background: var(--amber); color: #fff; font-size: 14px; }
.impersonate-bar .imp-real { opacity: .85; }
.impersonate-bar .btn { background: rgba(255,255,255,.18); border: 1px solid rgba(255,255,255,.4); color: #fff; }
.impersonate-bar .btn:hover { background: rgba(255,255,255,.3); }

/* Provider mode badge — rendered at the top of every texting page so the operator can
   tell at a glance whether they're on the fake carrier or hitting real Twilio. */
.tx-provider-badge { display: inline-flex; align-items: center; gap: 10px; margin: 0 0 14px;
    padding: 7px 14px; border-radius: 999px; font-size: 12px; line-height: 1.3;
    font-weight: 500; letter-spacing: .02em; border: 1px solid var(--line); }
.tx-provider-badge strong { font-weight: 700; letter-spacing: .06em; }
.tx-provider-badge .tx-badge-dot { width: 8px; height: 8px; border-radius: 50%; flex: 0 0 auto; }
.tx-provider-badge .tx-badge-sub { color: currentColor; opacity: .7; font-weight: 400; font-size: 11px; }
.tx-provider-badge.tx-sandbox { background: color-mix(in srgb, var(--amber) 12%, transparent);
    color: var(--amber, #b45309); border-color: color-mix(in srgb, var(--amber) 40%, transparent); }
.tx-provider-badge.tx-sandbox .tx-badge-dot { background: var(--amber, #b45309); }
.tx-provider-badge.tx-live { background: color-mix(in srgb, var(--red) 12%, transparent);
    color: var(--red, #b91c1c); border-color: color-mix(in srgb, var(--red) 45%, transparent); }
.tx-provider-badge.tx-live .tx-badge-dot { background: var(--red, #b91c1c);
    box-shadow: 0 0 0 3px color-mix(in srgb, var(--red) 20%, transparent); }

/* Bellows call desk — two-pane: persistent queue (left) + selected donor detail (right). */
.ct-layout { display: grid; grid-template-columns: 340px 1fr; gap: 18px; align-items: start; }
.ct-queue { background: var(--surface); border: 1px solid var(--line); border-radius: var(--radius);
    position: sticky; top: 74px; display: flex; flex-direction: column; max-height: calc(100vh - 96px); }
.ct-queue-head { display: flex; align-items: center; justify-content: space-between;
    padding: 12px 14px; border-bottom: 1px solid var(--line); }
.ct-progress { font-size: 12px; color: var(--muted); }
.ct-filter { padding: 10px 12px; border-bottom: 1px solid var(--line); }
.ct-filter select { width: 100%; }
.ct-list { overflow-y: auto; padding: 6px; }
.ct-item { display: flex; align-items: flex-start; gap: 8px; padding: 10px 11px; border-radius: 8px;
    text-decoration: none; color: var(--ink); border: 1px solid transparent; }
.ct-item:hover { background: var(--surface-2); }
.ct-item.active { background: var(--surface-2); border-color: var(--amber); }
.ct-item-main { flex: 1; min-width: 0; }
.ct-name { font-weight: 600; font-size: 14px; }
.ct-sub { font-size: 12px; color: var(--muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ct-pill { font-size: 10px; font-weight: 600; padding: 2px 8px; border-radius: 9px; flex: none;
    background: var(--line); color: var(--muted); white-space: nowrap; }
.ct-pill.done { background: var(--surface-2); color: var(--ink-2); border: 1px solid var(--line-2); }
.ct-pill.good { background: var(--teal-100); color: var(--teal-800); }
.ct-detail { min-width: 0; }
.research-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(180px, 1fr)); gap: 10px; }
.research-tile { background: var(--surface-2); border: 1px solid var(--line); border-radius: 10px; padding: 10px 12px; }
.rt-label { display: block; font-size: 11px; text-transform: uppercase; letter-spacing: .04em; color: var(--muted); }
.rt-val { display: block; font-size: 15px; margin-top: 3px; word-break: break-word; }
.ct-empty { text-align: center; padding: 60px 20px; }
@media (max-width: 800px) {
    .ct-layout { grid-template-columns: 1fr; }
    .ct-queue { position: static; max-height: 420px; }
}
[data-theme="dark"] .ct-pill.good { background: #0f2a1f; color: #6ee7b7; }

/* Bellows — the finance/fundraising sub-app identity (warm ember accent vs Foundry teal). */
.bellows-bar { display: flex; align-items: center; gap: 22px; flex-wrap: wrap;
    margin: -4px 0 20px; padding-bottom: 10px; border-bottom: 2px solid var(--amber); }
.bellows-brand { font-size: 20px; font-weight: 800; color: var(--amber); text-decoration: none;
    display: inline-flex; align-items: center; gap: 7px; letter-spacing: .2px; }
.bellows-nav { display: flex; gap: 4px; flex-wrap: wrap; }
.bellows-nav a { padding: 6px 12px; border-radius: 8px; color: var(--muted); text-decoration: none;
    font-size: 14px; font-weight: 600; }
.bellows-nav a:hover { background: var(--surface-2); color: var(--ink); }
.bellows-nav a.active { background: var(--amber); color: #fff; }

/* Feature launcher — the left hamburger + searchable feature list (VAN-style). */
.feat-btn { background: none; border: 0; color: var(--ink); cursor: pointer; font-size: 20px;
    padding: 6px 9px; margin-right: 4px; border-radius: 8px; display: inline-flex; align-items: center; }
.feat-btn:hover { background: var(--surface-2); color: var(--teal); }
.feat-drawer { position: fixed; inset: 0; z-index: 300; }
.feat-drawer[hidden] { display: none; }
.feat-backdrop { position: absolute; inset: 0; background: rgba(15, 23, 42, .45); }
.feat-panel { position: absolute; top: 0; left: 0; height: 100%; width: 350px; max-width: 88vw;
    background: var(--surface); border-right: 1px solid var(--line); box-shadow: var(--shadow);
    display: flex; flex-direction: column; animation: featIn .16s ease; }
@keyframes featIn { from { transform: translateX(-100%); } to { transform: none; } }
.feat-search { display: flex; align-items: center; gap: 9px; padding: 14px 14px; border-bottom: 1px solid var(--line); }
.feat-search > i { color: var(--muted); font-size: 18px; }
.feat-search input { flex: 1; border: 0; background: transparent; color: var(--ink); font-size: 16px; outline: none; }
.feat-esc { background: var(--surface-2); border: 1px solid var(--line); color: var(--muted);
    border-radius: 6px; font-size: 12px; padding: 3px 8px; cursor: pointer; }

/* Docked sidebar (wide screens). Open by default and remembered, the way VoteBuilder's left nav
   behaves — so it has to make room for itself rather than sit on top of the page like a modal.

   The breakpoint is set by arithmetic, not taste: the top bar needs ~1162px for the hamburger,
   brand, nine nav sections, committee chip and account menu. The top nav must stay visible at all
   times, so we only dock where BOTH fit — 1440px with a 260px rail and the committee chip capped.
   Narrower than that, the sidebar opens as an overlay instead and the page keeps its full width. */
@media (min-width: 1440px) {
    .nav-open .feat-drawer:not([hidden]) { position: fixed; inset: 0 auto 0 0; width: 260px; z-index: 200; }
    .nav-open .feat-drawer .feat-backdrop { display: none; }
    .nav-open .feat-panel { position: fixed; width: 260px; box-shadow: none; animation: none; }
    /* Push the chrome and the page over, rather than overlapping them. */
    .nav-open .topbar, .nav-open .content { margin-left: 260px; }
    .nav-open .feat-esc { display: none; }   /* Esc is a modal affordance; docked, it isn't one */
    /* The committee name is the most elastic thing up here — let it ellipsis rather than push the
       nav off the bar. Hovering still shows the full name via its title. */
    .nav-open .campaign-chip { max-width: 150px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
    /* Docking costs the bar 280px, so the nav needs its compact sizing here too — otherwise the
       items are wider than the box they were shrunk into and the last one spills out underneath
       the committee chip. (min-width:0 lets the box shrink; nothing stops the CONTENT overflowing,
       and we can't clip it without killing the dropdowns again — so it has to genuinely fit.) */
    .nav-open .mainnav { gap: 1px; }
    .nav-open .mainnav .nav-link { padding: 8px 8px; font-size: 14px; }
}
.feat-list { overflow-y: auto; padding: 6px 8px 16px; flex: 1; }
.cmd-sec { font-size: 11px; text-transform: uppercase; letter-spacing: .05em; color: var(--muted);
    margin: 14px 10px 3px; font-weight: 700; }
.cmd-item { display: flex; align-items: center; gap: 11px; padding: 10px 11px; border-radius: 8px;
    color: var(--ink); text-decoration: none; font-size: 15px; }
.cmd-item:hover, .cmd-item.hi { background: var(--surface-2); color: var(--teal-dark); }
.cmd-item > i { font-size: 18px; color: var(--muted); width: 20px; text-align: center; flex: none; }
.cmd-item:hover > i, .cmd-item.hi > i { color: var(--teal); }
.cmd-item .nav-badge { margin-left: auto; }
.feat-empty { color: var(--muted); padding: 24px; text-align: center; }
[data-theme="dark"] .cmd-item:hover, [data-theme="dark"] .cmd-item.hi { color: var(--teal-100); }
.row-done td { color: var(--muted); }

/* Walk packet (print) */
.packet-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 20px;
    border-bottom: 2px solid var(--line-2); padding-bottom: 12px; margin-bottom: 14px; }
.packet-head h1 { margin: 0 0 4px; font-size: 22px; }
.packet-meta { margin: 0; font-size: 13px; color: var(--ink-2); }
/* The code reads like a boarding pass — a volunteer types it into Outreach to walk this packet
   on a phone, so it has to survive a photocopy and be readable at arm's length. */
.packet-code { flex: none; text-align: center; border: 2px solid var(--line-2);
    border-radius: var(--radius); padding: 8px 16px; }
.packet-code-label { display: block; font-size: 9px; font-weight: 700; text-transform: uppercase;
    letter-spacing: .08em; color: var(--muted); }
.packet-code code { display: block; font-size: 26px; font-weight: 700; letter-spacing: .18em;
    background: none; border: none; padding: 2px 0; color: var(--ink); }
.packet-code-help { display: block; font-size: 9px; color: var(--muted); }
.packet-key { border: 1px solid var(--line); border-radius: var(--radius); padding: 8px 12px;
    margin-bottom: 12px; font-size: 12px; display: flex; gap: 10px; align-items: baseline; }
.packet-key strong { white-space: nowrap; }
.packet-table { width: 100%; border-collapse: collapse; }
.packet-table th, .packet-table td { font-size: 12px; padding: 5px 8px; border: 1px solid var(--line); }
.markcell { min-width: 70px; }
.packet-runfoot { display: none; }

/* Folders section */
.folder-card { background: var(--surface); border: 1px solid var(--line); border-radius: var(--radius-lg); padding: 18px 20px; margin-bottom: 16px; }
.folder-card > h2 { margin: 0 0 10px; font-size: 17px; display: flex; align-items: center; gap: 8px; }
.folder-card > h2 i { color: var(--teal); }
.folder-card.unfiled > h2 i { color: var(--muted); }
.folder-table { width: auto; min-width: 60%; background: none; border: none; }
.folder-table td { border-bottom: 1px solid var(--line); padding: 8px 14px 8px 0; }
.folder-table tr:last-child td { border-bottom: none; }
.folder-table tbody tr:hover td { background: none; }
.ftype { width: 92px; }
.type-tag { display: inline-block; font-size: 11px; font-weight: 600; padding: 2px 9px; border-radius: 10px; white-space: nowrap; }
.type-tag.type-0 { background: var(--teal-50); color: var(--teal-800); }
.type-tag.type-1 { background: #eff6ff; color: #1d4ed8; }
.type-tag.type-2 { background: #f5f3ff; color: #6d28d9; }

/* Save-as type chooser */
.save-type { display: flex; flex-direction: column; gap: 8px; }
.save-type .chk { font-weight: 400; }
.folder-picker .new-folder-input { width: 100%; }

/* Drag-and-drop script builder */
.sortable-el { transition: border-color .12s, opacity .12s; }
.sortable-head { display: flex; align-items: center; gap: 8px; }
.drag-handle { cursor: grab; color: var(--muted); font-size: 18px; line-height: 1; }
.drag-handle:active { cursor: grabbing; }
.sortable-el.dragging { opacity: .5; border-color: var(--teal); box-shadow: var(--shadow); }
details.addel > summary { cursor: pointer; font-weight: 600; padding: 12px 16px; list-style: none; }
details.addel > summary::-webkit-details-marker { display: none; }

/* Outreach roster heading */
.ob-list-head { font-size: 15px; margin: 16px 0 8px; }

/* My Turfs list */
.turf-table .folder-row td { background: var(--surface-2); font-weight: 600; color: var(--ink-2); border-top: 1px solid var(--line); }
.turf-table .folder-row td i { color: var(--muted); margin-right: 4px; }
.turf-table .turf-name { padding-left: 26px; }
.row-actions a { font-size: 18px; color: var(--ink-2); margin-right: 12px; }
.row-actions a:hover { color: var(--teal-dark); text-decoration: none; }

/* Turf cutting */
.turf-cut { display: grid; grid-template-columns: 1fr 280px; gap: 16px; align-items: start; }
#turfside { background: var(--surface); border: 1px solid var(--line); border-radius: var(--radius); padding: 14px; position: sticky; top: 76px; }
#turfside h3 { margin: 0 0 8px; font-size: 15px; }
.turf-row { padding: 6px 0; border-bottom: 1px solid var(--line); font-size: 14px; }
.turf-row.remaining { font-weight: 600; border-bottom: none; margin-top: 6px; color: var(--teal-dark); }
.swatch { display: inline-block; width: 12px; height: 12px; border-radius: 3px; margin-right: 6px; vertical-align: middle; }
.packet-script .script-block { font-size: 13px; }
.ck { display: inline-block; margin: 0 10px 2px 0; white-space: nowrap; font-size: 12px; }

@media print {
  /* Dark is the default theme and printers don't print page backgrounds — without this reset a
     walk packet comes out as near-white text on white paper. Force ink-on-paper regardless of
     which theme the director happens to be using on screen. */
  :root, [data-theme="dark"], [data-theme="light"] {
    --bg: #ffffff; --surface: #ffffff; --surface-2: #f2f4f7;
    --ink: #000000; --ink-2: #1a1a1a; --muted: #444444;
    --line: #bbbbbb; --line-2: #888888;
    --teal: #0f766e; --teal-dark: #0f766e; --teal-50: #ffffff; --teal-100: #e6fffb;
    --shadow: none; --shadow-sm: none;
  }
  body { background: #fff !important; color: #000 !important; }
  .topbar, .packet-controls, .feat-drawer, .impersonate-bar, .messages { display: none !important; }
  .content { max-width: none; padding: 0; }
  .script-block { background: none; border: 1px solid #999; }
  /* Never clip a printed page: scroll boxes exist for screens, paper has no scrollbar. */
  .table-scroll, .grid-scroll, .multi-opts { max-height: none !important; overflow: visible !important; }
  .table-scroll thead th, .grid-entry th, .grid-entry .who { position: static !important; box-shadow: none !important; }
  .card, .panel, .setup-card, .pb-card, .empty-state { box-shadow: none !important; border-color: #bbb !important; }
  a { color: #000 !important; text-decoration: none !important; }
  tr, .ob-hh, .pb-card, .card { break-inside: avoid; }

  /* Walk packet: leave room at the foot of every sheet and pin the code strip into it. A packet
     gets split between volunteers, so a loose page must still name its turf and its code. */
  @page { margin: 12mm 10mm 16mm; }
  .packet-runfoot { display: block; position: fixed; bottom: 0; left: 0; right: 0;
      border-top: 1px solid #999; padding-top: 3px; font-size: 10px; color: #333; }
  .packet-runfoot strong { letter-spacing: .12em; }
  .packet-head { break-after: avoid; }
  .packet-key { break-inside: avoid; }
  .packet-table thead { display: table-header-group; }  /* repeat column headers per page */
  .packet-table tfoot { display: table-footer-group; }
}

/* Builder side column (VAN-style) */
.builder-side-col { display: flex; flex-direction: column; gap: 12px; }
.step-indicator { margin: 16px 0 8px; }
.step-active { border-color: var(--teal); background: var(--teal-50); }
.preview-hint { text-align: center; margin: 10px 0; }
.side-actions { background: var(--surface); border: 1px solid var(--line); border-radius: var(--radius-lg); padding: 16px; }
.addstep-row { display: flex; gap: 8px; align-items: flex-start; margin-bottom: 12px; }
.addstep-row .run-btn { flex: 1; }
.addstep { position: relative; }
.addstep > summary { list-style: none; cursor: pointer; background: var(--surface); border: 1px solid var(--line-2); border-radius: 8px; padding: 9px 14px; font-weight: 600; font-size: 14px; white-space: nowrap; }
.addstep > summary::-webkit-details-marker { display: none; }
.addstep-menu { position: absolute; z-index: 20; top: 100%; left: 0; margin-top: 4px; background: var(--surface); border: 1px solid var(--line); border-radius: 8px; box-shadow: var(--shadow); padding: 6px; min-width: 170px; display: flex; flex-direction: column; }
.addstep-menu .link-btn { text-align: left; text-decoration: none; padding: 8px 10px; border-radius: 6px; color: var(--ink); }
.addstep-menu .link-btn:hover { background: var(--surface-2); }

/* ============================ Responsive ============================ */
@media (max-width: 980px) {
  .nav-toggle { display: inline-flex; }
  .brand { margin-right: auto; }
  .nav-collapse {
    display: none; position: absolute; top: 60px; left: 0; right: 0;
    flex-direction: column; align-items: stretch; gap: 0;
    background: var(--surface); border-bottom: 1px solid var(--line);
    box-shadow: var(--shadow); padding: 8px; max-height: calc(100vh - 60px); overflow-y: auto;
  }
  .nav-cb:checked ~ .nav-collapse { display: flex; }
  .mainnav { flex-direction: column; align-items: stretch; gap: 2px; }
  .nav-link { padding: 11px 12px; font-size: 15px; }
  .nav-group { position: static; }
  .nav-group > summary { justify-content: space-between; }
  .nav-menu { position: static; box-shadow: none; border: none; border-radius: 0;
    padding: 2px 0 6px 22px; min-width: 0; }
  .userbox { margin-left: 0; flex-direction: column; align-items: stretch; gap: 8px;
    margin-top: 8px; padding-top: 10px; border-top: 1px solid var(--line); }
  .campaign-chip { max-width: none; justify-content: center; }
  .acct { width: 100%; }
  .acct > summary { width: 100%; justify-content: flex-start; border: none; padding: 9px 12px; }
  .acct-menu { position: static; box-shadow: none; border: none; padding: 2px 0 0 22px; min-width: 0; }
}

@media (max-width: 800px) {
  .builder { grid-template-columns: 1fr; }
  .turf-cut { grid-template-columns: 1fr; }
  .builder-side, #turfside { position: static; }
  .content { padding: 20px 16px; }
  .preview-counts { grid-template-columns: repeat(2, 1fr); }
}

/* Bulk Upload hub */
.bulk-sec { margin-top: 16px; }
.bulk-sec .card { max-width: 640px; }
.bulk-sec h2 { font-size: 17px; margin: 0 0 12px; }
.src-choice { display: flex; flex-direction: column; gap: 6px; }
.src-choice .radio { display: flex; align-items: center; gap: 8px; font-weight: 400; cursor: pointer; }
.src-choice .radio input { width: auto; margin: 0; }

/* Coverage bar (canvass results) */
.cov-bar { display: inline-block; width: 90px; height: 8px; border-radius: 4px;
  background: var(--line); vertical-align: middle; overflow: hidden; margin-right: 6px; }
.cov-fill { display: block; height: 100%; background: var(--teal, #0d9488); border-radius: 4px; }

/* Login tagline (Foundry / Silver Basin Strategies) */
.login-wrap .tagline { margin-top: -6px; margin-bottom: 18px; font-style: italic;
  color: var(--muted, #64748b); font-size: 14px; }

/* Settings — theme picker */
.theme-choice { display: flex; gap: 12px; margin: 8px 0 4px; flex-wrap: wrap; }
.theme-opt { cursor: pointer; }
.theme-opt input { position: absolute; opacity: 0; width: 0; height: 0; }
.theme-swatch { display: inline-flex; align-items: center; gap: 8px; padding: 14px 20px;
  border-radius: var(--radius); border: 2px solid var(--line-2); font-weight: 600; }
.swatch-dark { background: #0b111f; color: #e6eaf2; }
.swatch-light { background: #f1f5f9; color: #0f172a; }
.theme-opt input:checked + .theme-swatch { border-color: var(--teal); box-shadow: 0 0 0 3px var(--teal-100); }

/* Version stamp in the account menu */
.acct-ver { padding: 8px 14px 10px; font-size: 12px; border-top: 1px solid var(--line); }

/* Donor database — filter panel + list meta */
.donor-filters { margin-bottom: 14px; display: flex; flex-direction: column; gap: 8px; }
.donor-filters .filter-row { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; }
.donor-filters input[type=text], .donor-filters select { padding: 7px 10px; }
.donor-filters .grow { flex: 1; min-width: 220px; }
.donor-filters .narrow { max-width: 120px; }
.donor-filters .chk { display: inline-flex; align-items: center; gap: 6px; font-size: 13px;
    color: var(--muted); white-space: nowrap; }
.list-meta { display: flex; align-items: center; justify-content: space-between; margin: 4px 0 10px; }
.btn.sm { padding: 5px 10px; font-size: 13px; }

/* Fundraising goal card (dashboard) */
.goal-card { background: var(--surface); border: 1px solid var(--line); border-radius: var(--radius-lg);
    padding: 16px 20px; margin: 18px 0; }
.goal-head { display: flex; justify-content: space-between; align-items: baseline; flex-wrap: wrap;
    gap: 6px; margin-bottom: 10px; }
.goal-label { font-weight: 600; color: var(--ink); }
.goal-figures { font-size: 15px; }
.goal-bar { height: 12px; background: var(--surface-2); border-radius: 999px; overflow: hidden; }
.goal-fill { height: 100%; background: var(--green); border-radius: 999px; transition: width .3s; }
.goal-pct { font-size: 12px; margin-top: 6px; }

/* Coordination (coordinated campaigns) */
.field { display: block; margin-bottom: 14px; }
.field > span:first-child { display: block; font-weight: 600; margin-bottom: 5px; font-size: 14px; }
.field input[type=text], .field select { width: 100%; padding: 8px 10px; }
.check-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); gap: 6px 14px; margin: 6px 0; }
.pill { display: inline-block; padding: 2px 10px; border-radius: 999px; font-size: 12px; font-weight: 600;
    background: var(--surface-2); color: var(--muted); border: 1px solid var(--line); }
.pill.ok { background: color-mix(in srgb, var(--green) 15%, transparent); color: var(--green);
    border-color: color-mix(in srgb, var(--green) 40%, transparent); }
ul.tidy { margin: 6px 0 0; padding-left: 18px; }
ul.tidy li { margin: 3px 0; }

/* --- Power dialer magic-link invites (R1b) --------------------------------
   Redemption page for volunteers (dial-redeem, dial-expired) + director's
   invite-management page (invite-card, invite-head, invite-actions, claimants).
   Uses the same tokens the rest of the app is on so a theme change flows
   through without a redeploy. */
.pill.good { background: color-mix(in srgb, var(--green) 15%, transparent); color: var(--green);
    border-color: color-mix(in srgb, var(--green) 40%, transparent); }
.btn.danger { background: var(--red); color: #fff; }
.btn.danger:hover { background: color-mix(in srgb, var(--red) 85%, black); }

.dial-redeem { max-width: 440px; margin: 24px auto; padding: 0 16px; }
.dial-redeem h1 { margin: 0 0 6px; }
.dial-redeem .stack { display: flex; flex-direction: column; gap: 14px; margin-top: 18px; }
.dial-redeem label { display: flex; flex-direction: column; gap: 4px; font-weight: 600; font-size: 14px; }
.dial-redeem input { padding: 12px 14px; font-size: 16px; border: 1px solid var(--line);
    border-radius: 10px; background: var(--surface); color: var(--ink); }
.dial-redeem .err { color: var(--red); font-size: 13px; font-weight: 400; }
.dial-redeem .fine { font-size: 13px; color: var(--muted); margin: 0; }

.dial-expired { max-width: 440px; margin: 60px auto 24px; padding: 0 16px; text-align: center; }
.dial-expired .empty-icon { font-size: 44px; color: var(--muted); margin-bottom: 12px; }
.dial-expired h1 { margin: 0 0 8px; font-size: 22px; }

.row-form { display: flex; gap: 12px; align-items: end; flex-wrap: wrap; margin-top: 12px; }
.row-form label { flex: 1 1 260px; display: flex; flex-direction: column; gap: 4px;
    font-weight: 600; font-size: 14px; }
.row-form input { padding: 8px 10px; border: 1px solid var(--line); border-radius: 8px;
    background: var(--surface); color: var(--ink); }
.row-form .fine, p.fine { font-size: 13px; color: var(--muted); }

.invite-card { margin-top: 14px; }
.invite-card.invite-dead { opacity: 0.65; }
.invite-head { display: flex; justify-content: space-between; gap: 12px; align-items: start;
    flex-wrap: wrap; }
.invite-actions { display: flex; gap: 8px; flex-wrap: wrap; }
.invite-url { margin-top: 12px; padding: 10px 12px; background: var(--surface-2);
    border: 1px solid var(--line); border-radius: 8px; overflow-x: auto; }
.invite-url code { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 13px; }

table.claimants { margin-top: 10px; }
table.claimants th, table.claimants td { padding: 6px 10px; font-size: 14px; }

/* --- Browser power dialer (R1c, redesigned v2.36.4) -------------------
   Volunteer-facing surface. Warm, generous whitespace, primary action
   dominant, disposition buttons color-coded by tone (positive / neutral /
   negative) so a caller isn't picking from a grid of look-alikes. */

.dialer { max-width: 640px; margin: 0 auto; padding: 20px 16px 40px; }

/* Ready screen — the first thing the volunteer sees. Feels like a warm
   welcome, not a HUD. */
.d-ready { text-align: center; padding: 32px 16px; }
.d-ready-icon { font-size: 56px; color: var(--teal); margin-bottom: 8px; }
.d-ready h1 { font-size: 28px; margin: 6px 0 8px; }
.d-ready-body { color: var(--muted); max-width: 440px; margin: 0 auto 24px;
    font-size: 15px; line-height: 1.5; }
.d-ready-fine { max-width: 380px; margin: 14px auto 0; }

/* The primary action button is BIG, teal, and unmistakable. */
.d-primary { width: 100%; max-width: 380px; padding: 16px 22px; font-size: 17px;
    box-shadow: 0 2px 8px color-mix(in srgb, var(--teal) 25%, transparent); }
.d-primary.danger { box-shadow: 0 2px 8px color-mix(in srgb, var(--red) 25%, transparent); }

/* Card layout: no boxes-inside-boxes. Each section breathes. */
.d-card { display: flex; flex-direction: column; gap: 22px; }

/* Small status crumbs — state + timer + progress on one quiet line, not a HUD. */
.d-crumbs { display: flex; align-items: baseline; gap: 12px; font-size: 13px;
    color: var(--muted); flex-wrap: wrap; }
.d-state { font-weight: 600; color: var(--ink-2); }
.d-timer { font-variant-numeric: tabular-nums; }
.d-progress { margin-left: auto; }

/* The person you're calling. Name is a proper headline. */
.d-person h1 { font-size: 28px; margin: 0 0 6px; line-height: 1.2; }

/* v2.38.6: highlight-and-fade cue that fires when a new voter loads. Even a
   volunteer scrolled below the fold catches the flash in their peripheral
   vision when they scroll back up. Pairs with a scrollIntoView() call in
   dialer.js so this is the second cue, not the only one. */
@keyframes dFlashPulse {
    0%   { background: color-mix(in srgb, var(--teal) 22%, transparent);
           box-shadow: 0 0 0 6px color-mix(in srgb, var(--teal) 22%, transparent); }
    60%  { background: color-mix(in srgb, var(--teal) 12%, transparent);
           box-shadow: 0 0 0 4px color-mix(in srgb, var(--teal) 10%, transparent); }
    100% { background: transparent; box-shadow: 0 0 0 0 transparent; }
}
.d-person.d-flash {
    animation: dFlashPulse 1.6s ease-out;
    border-radius: 10px; padding: 8px 10px; margin: -8px -10px 0;
}
@media (prefers-reduced-motion: reduce) {
    .d-person.d-flash { animation: none; }
}

.d-person-meta { color: var(--muted); font-size: 15px; margin: 0 0 8px; }
.d-person-meta span + span { margin-left: 10px; }
.d-person-phone { font-size: 20px; font-weight: 600; margin: 0;
    color: var(--ink); display: flex; align-items: center; gap: 8px; }
.d-person-phone .ti { color: var(--teal); font-size: 22px; }

/* Actions: primary call/hangup dominates; skip + mute sit modestly below. */
.d-actions { display: flex; flex-direction: column; align-items: center; gap: 10px; }
.d-actions-secondary { display: flex; gap: 10px; margin-top: 4px; }

/* Script section — labeled softly, no card border shouting at the volunteer. */
.d-script-label, .d-outcome-label { font-size: 13px; font-weight: 600;
    text-transform: uppercase; letter-spacing: 0.06em; color: var(--muted);
    margin-bottom: 6px; }
.d-script { padding-top: 6px; border-top: 1px solid var(--line); }

/* Disposition buttons — flow, not grid. Color-coded by what happened. */
.d-outcome { padding-top: 6px; border-top: 1px solid var(--line); }
.d-outcome-buttons { display: flex; flex-wrap: wrap; gap: 8px; margin: 4px 0 10px; }
.d-outcome-btn { padding: 12px 18px; font: inherit; font-size: 15px;
    border: 1.5px solid var(--line); border-radius: 999px;
    background: var(--surface); color: var(--ink); cursor: pointer;
    transition: background .12s, border-color .12s, transform .06s; }
.d-outcome-btn:hover { border-color: var(--line-2); background: var(--surface-2); }
.d-outcome-btn:active { transform: translateY(1px); }

/* Positive outcomes — green tint */
.d-outcome-btn.d-tone-canvassed,
.d-outcome-btn.d-tone-left-message {
    background: color-mix(in srgb, var(--green) 8%, var(--surface));
    border-color: color-mix(in srgb, var(--green) 40%, var(--line));
    color: var(--green);
}
.d-outcome-btn.d-tone-canvassed:hover,
.d-outcome-btn.d-tone-left-message:hover {
    background: color-mix(in srgb, var(--green) 16%, var(--surface));
}
/* Neutral outcomes stay default — no color, they're the vast majority */
/* Refusal / DNC — amber */
.d-outcome-btn.d-tone-refused,
.d-outcome-btn.d-tone-not-interested,
.d-outcome-btn.d-tone-do-not-call {
    background: color-mix(in srgb, var(--amber) 8%, var(--surface));
    border-color: color-mix(in srgb, var(--amber) 40%, var(--line));
    color: var(--amber);
}
/* Bad-number type — red-ish, quieter */
.d-outcome-btn.d-tone-wrong-number,
.d-outcome-btn.d-tone-disconnected,
.d-outcome-btn.d-tone-deceased {
    color: var(--red);
    border-color: color-mix(in srgb, var(--red) 30%, var(--line));
}

.d-outcome-more { margin-top: 6px; }
.d-outcome-more summary { color: var(--muted); font-size: 14px; cursor: pointer;
    padding: 4px 0; }
.d-outcome textarea#d-note { width: 100%; margin-top: 10px; padding: 10px 12px;
    border: 1px solid var(--line); border-radius: 8px;
    background: var(--surface); color: var(--ink); font: inherit; font-size: 15px;
    resize: vertical; }
.d-outcome textarea#d-note::placeholder { color: var(--muted); }

/* End of queue — celebratory, not clinical. */
.d-done { text-align: center; padding: 40px 20px; }
.d-done-icon { font-size: 60px; color: var(--amber); margin-bottom: 8px; }
.d-done h1 { font-size: 30px; margin: 6px 0 10px; }
.d-done-body { color: var(--muted); max-width: 460px; margin: 0 auto 24px;
    font-size: 16px; line-height: 1.5; }
.d-done-actions { display: flex; flex-direction: column; align-items: center; gap: 10px; }

/* Redemption page — warmer welcome, less form-y. */
.dial-redeem { max-width: 440px; margin: 40px auto 24px; padding: 0 20px; }
.dial-redeem .dr-eyebrow { font-size: 13px; text-transform: uppercase;
    letter-spacing: 0.08em; margin: 0 0 4px; }
.dial-redeem h1 { font-size: 30px; line-height: 1.2; margin: 0 0 10px; }
.dial-redeem .dr-intro { color: var(--ink-2); font-size: 16px; line-height: 1.5;
    margin: 0 0 24px; }
.dial-redeem .dr-form { display: flex; flex-direction: column; gap: 14px; }
.dial-redeem .dr-form label { display: flex; flex-direction: column; gap: 4px;
    font-weight: 600; font-size: 14px; }
.dial-redeem .dr-form input { padding: 12px 14px; font-size: 16px;
    border: 1px solid var(--line); border-radius: 10px;
    background: var(--surface); color: var(--ink); }
.dial-redeem .dr-form input:focus { outline: 2px solid var(--teal);
    outline-offset: 1px; border-color: var(--teal); }
.dial-redeem .dr-go { margin-top: 6px; padding: 14px 22px; font-size: 17px; }
.dial-redeem .dr-fine { margin: 8px 0 0; font-size: 13px; }
.dial-redeem .err { color: var(--red); font-size: 13px; font-weight: 400; }

/* Ghost button — quieter than secondary, for tertiary actions like Skip / End. */
.btn.ghost { background: transparent; color: var(--muted); border: 1px solid var(--line); }
.btn.ghost:hover { color: var(--ink); border-color: var(--line-2); background: var(--surface-2); }

/* Caller-ID pool table (R2). */
.calleridnum-table { width: 100%; margin-top: 12px; }
.calleridnum-table th, .calleridnum-table td { padding: 8px 10px; font-size: 14px; vertical-align: middle; }
.calleridnum-inactive { opacity: 0.55; }
.calleridnum-flagged { background: color-mix(in srgb, var(--red) 8%, transparent); }
.pool-bar { display: inline-block; width: 100px; height: 6px; background: var(--surface-2);
    border-radius: 4px; overflow: hidden; vertical-align: middle; margin-right: 6px; }
.pool-bar-fill { height: 100%; background: var(--green); transition: width .2s; }
.pool-bar-fill.pool-bar-warm { background: var(--amber); }
.pool-bar-fill.pool-bar-hot { background: var(--red); }

/* --- Call-time sticky-note messages + live manager (v2.35) ------------ */
.ct-msg-stack { display: flex; flex-direction: column; gap: 8px; margin-bottom: 14px; }
.ct-msg { display: flex; align-items: flex-start; gap: 10px; padding: 12px 14px;
    background: color-mix(in srgb, var(--teal) 12%, transparent);
    border: 1px solid color-mix(in srgb, var(--teal) 40%, transparent);
    border-radius: 10px; animation: ct-msg-in .18s ease-out; }
.ct-msg-urgent { background: color-mix(in srgb, var(--amber) 18%, transparent);
    border-color: color-mix(in srgb, var(--amber) 60%, transparent); }
.ct-msg-body { flex: 1; font-size: 15px; line-height: 1.35; }
.ct-msg-meta { font-size: 12px; margin-top: 4px; }
.ct-msg-dismiss { border: 0; background: transparent; color: var(--muted);
    cursor: pointer; padding: 6px 8px; border-radius: 6px; font-size: 18px; }
.ct-msg-dismiss:hover { background: color-mix(in srgb, var(--ink) 10%, transparent); color: var(--ink); }
@keyframes ct-msg-in { from { opacity: 0; transform: translateY(-6px); } to { opacity: 1; transform: none; } }

.live-row { margin-top: 12px; }
.live-row.live-slow { border-color: color-mix(in srgb, var(--amber) 45%, transparent); }
.live-head { display: flex; justify-content: space-between; gap: 16px; align-items: start;
    flex-wrap: wrap; }
.live-donor { text-align: right; min-width: 240px; }
.live-timer { margin-top: 4px; font-variant-numeric: tabular-nums; font-weight: 600; color: var(--muted); }
.live-timer-slow { color: var(--amber); }
.live-compose { display: flex; gap: 8px; align-items: center; margin-top: 12px; flex-wrap: wrap; }
.live-compose input[type=text] { flex: 1 1 300px; padding: 8px 10px;
    border: 1px solid var(--line); border-radius: 8px;
    background: var(--surface); color: var(--ink); }
.live-urgent { display: flex; align-items: center; gap: 6px; font-size: 13px;
    color: var(--muted); flex: 0 0 auto; }

/* v2.38.7: Call-time MANAGER pane. One pane per active caller — leads with
   the caller's identity + a timer, then the sticky-note compose (so the
   director never has to scroll to send one), then a two-column body:
   LEFT = the same donor pane the caller is looking at (reused partial in
   readonly mode); RIGHT = this session's activity log. Collapses to one
   column on narrow screens so it stays usable on a laptop half-screen. */
.ct-mgr { background: var(--surface); border: 1px solid var(--line);
    border-radius: var(--radius-lg); padding: 16px 18px; margin-top: 16px;
    box-shadow: var(--shadow-sm); }
.ct-mgr-slow { border-color: color-mix(in srgb, var(--amber) 45%, transparent); }
.ct-mgr-head { display: flex; justify-content: space-between; gap: 16px;
    align-items: flex-start; flex-wrap: wrap; margin-bottom: 12px; }
.ct-mgr-timer { text-align: right; min-width: 180px;
    font-variant-numeric: tabular-nums; color: var(--muted); }
.ct-mgr-timer-slow { color: var(--amber); }
.ct-mgr-compose { display: flex; gap: 8px; align-items: center;
    padding: 10px 12px; background: var(--surface-2); border: 1px solid var(--line);
    border-radius: 10px; margin-bottom: 14px; flex-wrap: wrap; }
.ct-mgr-compose input[type=text] { flex: 1 1 320px; padding: 9px 11px;
    border: 1px solid var(--line-2); border-radius: 8px;
    background: var(--surface); color: var(--ink); font-size: 14.5px; }
.ct-mgr-urgent { display: flex; align-items: center; gap: 6px; font-size: 13px;
    color: var(--muted); flex: 0 0 auto; }
.ct-mgr-body { display: grid; grid-template-columns: minmax(0, 3fr) minmax(0, 2fr);
    gap: 18px; margin-top: 8px; }
@media (max-width: 1100px) { .ct-mgr-body { grid-template-columns: 1fr; } }
.ct-mgr-section-lbl { font-size: 13px; text-transform: uppercase;
    letter-spacing: .04em; margin-bottom: 8px;
    display: inline-flex; align-items: center; gap: 6px; }
.ct-mgr-section-lbl .ti { color: var(--teal); }
.ct-mgr-donor, .ct-mgr-log { min-width: 0; }
.ct-mgr-log-list { list-style: none; padding: 0; margin: 0;
    max-height: 620px; overflow-y: auto;
    border: 1px solid var(--line); border-radius: 10px; background: var(--surface); }
.ct-mgr-log-item { display: grid; grid-template-columns: 84px 1fr; gap: 10px;
    padding: 10px 12px; border-bottom: 1px solid var(--line); }
.ct-mgr-log-item:last-child { border-bottom: 0; }
.ct-mgr-log-when { font-size: 12px; font-variant-numeric: tabular-nums;
    white-space: nowrap; padding-top: 2px; }
.ct-mgr-log-body strong { margin-right: 6px; }
.ct-mgr-log-amt { display: inline-block; margin-left: 8px; font-size: 13px;
    color: var(--muted); }
.ct-mgr-log-amt.good { color: var(--green); font-weight: 600; }
.ct-mgr-log-note { margin-top: 4px; font-size: 13px; color: var(--muted);
    font-style: italic; }
