/* ── Variables ──────────────────────────────────────────────────────────── */
:root {
  --purple:      #241558;
  --purple-dark: #180e3a;
  --orange:      #ff6b3d;
  --orange-light:#ff9c7a;
  --success:     #2e7d52;
  --warning:     #e6a817;
  --danger:      #c0392b;
  --bg:          #f5f4f9;
  --surface:     #ffffff;
  --border:      #e2dff0;
  --text:        #1a1a2e;
  --text-muted:  #6b6b8a;
  --radius:      8px;
  --shadow:      0 1px 4px rgba(36,21,88,.08);
  --shadow-md:   0 4px 16px rgba(36,21,88,.12);
}

/* ── Reset ──────────────────────────────────────────────────────────────── */
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
body { font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
       font-size: 14px; color: var(--text); background: var(--bg); line-height: 1.5; }
a { color: var(--purple); text-decoration: none; }
a:hover { text-decoration: underline; }

/* ── Nav ────────────────────────────────────────────────────────────────── */
.nav {
  display: flex; align-items: center; gap: 1rem;
  background: var(--purple); color: #fff;
  padding: 0 1.5rem; height: 56px; position: sticky; top: 0; z-index: 100;
  box-shadow: 0 2px 8px rgba(0,0,0,.2);
}
.nav-brand { display: flex; align-items: center; gap: .6rem; margin-right: 1rem;
             color: #fff; text-decoration: none; }
.nav-brand:hover { text-decoration: none; opacity: .88; }
.nav-logo {
  width: 28px; height: 28px; border-radius: 6px;
  background: var(--orange); color: #fff; font-weight: 700; font-size: 15px;
  display: flex; align-items: center; justify-content: center;
}
.nav-logo-img { width: 30px; height: 30px; object-fit: contain; }
.nav-title { font-weight: 600; font-size: 15px; letter-spacing: .01em; }
.nav-links { display: flex; gap: .25rem; flex: 1; }
.nav-link {
  color: rgba(255,255,255,.75); padding: .4rem .75rem; border-radius: var(--radius);
  font-size: 13px; transition: background .15s, color .15s;
}
.nav-link:hover, .nav-link.active {
  background: rgba(255,255,255,.12); color: #fff; text-decoration: none;
}
.nav-divider {
  display: inline-block; width: 1px; height: 20px; background: rgba(255,255,255,.2);
  margin: 0 .35rem; vertical-align: middle;
}
.nav-user { display: flex; align-items: center; gap: .6rem; margin-left: auto; }
.nav-avatar { width: 28px; height: 28px; border-radius: 50%; border: 2px solid rgba(255,255,255,.3); }
.nav-username { font-size: 13px; color: rgba(255,255,255,.85); }
.nav-logout { font-size: 12px; color: rgba(255,255,255,.6); padding: .3rem .6rem;
              border: 1px solid rgba(255,255,255,.2); border-radius: var(--radius); }
.nav-logout:hover { background: rgba(255,255,255,.1); color: #fff; text-decoration: none; }

/* ── Main content ────────────────────────────────────────────────────────── */
.main-content { max-width: 1100px; margin: 0 auto; padding: 2rem 1.5rem; }

/* ── Flash messages ──────────────────────────────────────────────────────── */
.flash-container { margin-bottom: 1.5rem; display: flex; flex-direction: column; gap: .5rem; }
.flash { padding: .75rem 1rem; border-radius: var(--radius); font-size: 13px; font-weight: 500; }
.flash-success { background: #d4edda; color: #155724; border: 1px solid #c3e6cb; }
.flash-error   { background: #f8d7da; color: #721c24; border: 1px solid #f5c6cb; }
.flash-warning { background: #FFEB9C; color: #6b5300; border: 1px solid #f0d264; }
.flash-info    { background: #d1ecf1; color: #0c5460; border: 1px solid #bee5eb; }

/* ── Page header ─────────────────────────────────────────────────────────── */
.page-header {
  display: flex; align-items: center; justify-content: space-between;
  margin-bottom: 1.75rem; gap: 1rem;
}
.page-header h1 { font-size: 1.5rem; font-weight: 700; color: var(--purple); }
.page-subtitle  { color: var(--text-muted); font-size: 14px; margin-top: .25rem; }
.text-muted     { color: var(--text-muted); }

/* ── Buttons ─────────────────────────────────────────────────────────────── */
.btn {
  display: inline-flex; align-items: center; gap: .4rem;
  padding: .5rem 1rem; border-radius: var(--radius);
  font-size: 13px; font-weight: 500; cursor: pointer;
  border: 1px solid transparent; transition: all .15s; text-decoration: none;
}
.btn:hover { text-decoration: none; filter: brightness(.92); }
.btn-primary  { background: var(--purple); color: #fff; }
.btn-success  { background: var(--success); color: #fff; }
.btn-danger   { background: var(--danger);  color: #fff; }
.btn-warning  { background: var(--warning); color: #fff; }
.btn-ghost    { background: transparent; color: var(--purple); border-color: var(--border); }
.btn-ghost:hover { background: var(--bg); }
.btn-sm       { padding: .3rem .65rem; font-size: 12px; }
.btn-lg       { padding: .65rem 1.5rem; font-size: 14px; }
.btn-login    { width: 100%; justify-content: center; padding: .75rem 1rem; font-size: 15px; }

/* ── Login page ──────────────────────────────────────────────────────────── */
.login-body   { display: flex; align-items: center; justify-content: center;
                min-height: 100vh; background: var(--bg); }
.login-card   { background: var(--surface); border-radius: 12px; box-shadow: var(--shadow-md);
                padding: 2.5rem 2rem; width: 360px; text-align: center; }
.login-logo   { width: 48px; height: 48px; border-radius: 10px; background: var(--purple);
                color: #fff; font-size: 22px; font-weight: 700;
                display: flex; align-items: center; justify-content: center; margin: 0 auto 1rem; }
.login-logo-img { width: 64px; height: 64px; object-fit: contain; margin: 0 auto 1rem; display: block; }
.login-title  { font-size: 1.3rem; font-weight: 700; color: var(--purple); margin-bottom: .4rem; }
.login-subtitle { color: var(--text-muted); font-size: 13px; margin-bottom: 1.5rem; }
.login-note   { color: var(--text-muted); font-size: 12px; margin-top: 1rem; }

/* ── Dashboard action grid ───────────────────────────────────────────────── */
.action-grid  { display: grid; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); gap: 1rem; }
.action-section-title {
  font-size: 13px; font-weight: 700; text-transform: uppercase; letter-spacing: .04em;
  color: var(--text-muted); margin: 1.75rem 0 .75rem;
}
.action-section-title:first-of-type { margin-top: 0; }
/* Admin table's frozen Name column — same header/body background split
   as OB Pipeline's earlier sticky column fix: the header must stay the
   same purple as every other header cell, body cells need a solid
   light background so scrolled-under content doesn't show through. */
th.admin-frozen-col {
  position: sticky; left: 0; z-index: 2; background: var(--purple);
  box-shadow: 2px 0 4px rgba(0,0,0,.15);
}
td.admin-frozen-col {
  position: sticky; left: 0; z-index: 1; background: var(--surface);
  box-shadow: 2px 0 4px rgba(0,0,0,.06);
}
.data-table tr:hover td.admin-frozen-col { background: #f9f8fd; }

/* Admin Users table: filter bar above the table */
.admin-filter-bar {
  display: flex; align-items: center; gap: .75rem; flex-wrap: wrap;
  margin-bottom: .75rem;
}

/* Zebra striping — driven by JS (.row-stripe class), not nth-child.
   nth-child counts DOM position including hidden (filtered-out) rows, so
   striping would stop alternating correctly the moment any filter hides
   rows out of sequence — this class gets reassigned by restripe() in
   admin/index.html every time the filter or sort changes, so it always
   reflects visible order, not raw DOM order.
   Must set the frozen column's background too, or the sticky Name column
   shows a flat color while the rest of the row alternates, breaking the
   sticky-column illusion — same class of bug already fixed once on this
   table (see comment above admin-frozen-col). The hover rules below are
   declared AFTER the stripe rules so hover always wins regardless of
   stripe state, since both sets of selectors share the same specificity. */
.admin-users-table tbody tr.row-stripe td { background: #f7f6fb; }
.admin-users-table tbody tr.row-stripe td.admin-frozen-col { background: #efedf7; }
.admin-users-table tbody tr:hover td { background: #efeafa; }
.admin-users-table tbody tr:hover td.admin-frozen-col { background: #efeafa; }

.admin-sortable { cursor: pointer; user-select: none; white-space: nowrap; }
.admin-sortable:hover { background: var(--purple-dark); }
th.sortable:focus-visible, th.admin-sortable:focus-visible {
  outline: 2px solid var(--orange); outline-offset: -2px;
}
.action-card  {
  display: flex; align-items: center; gap: 1rem;
  background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius);
  padding: 1.25rem 1rem; text-decoration: none; color: var(--text);
  box-shadow: var(--shadow); transition: box-shadow .15s, border-color .15s;
}
.action-card:hover { box-shadow: var(--shadow-md); border-color: var(--purple); text-decoration: none; }
.action-icon  {
  width: 44px; height: 44px; border-radius: 10px; flex-shrink: 0;
  display: flex; align-items: center; justify-content: center; color: #fff;
}
.action-icon--pipeline { background: var(--purple); }
.action-icon--risk     { background: var(--warning); }
.action-icon--churn    { background: var(--danger); }
.action-icon--history  { background: #6b4fb5; }
.action-icon--intake   { background: var(--orange, #ff6b3d); }
.action-body  { flex: 1; }
.action-title { font-size: 14px; font-weight: 600; color: var(--purple); margin-bottom: .25rem; }
.action-desc  { font-size: 12px; color: var(--text-muted); }
.action-arrow { color: var(--text-muted); font-size: 18px; }

/* ── Table ───────────────────────────────────────────────────────────────── */
.table-wrapper { overflow-x: auto; background: var(--surface);
                 border: 1px solid var(--border); border-radius: var(--radius); }
.data-table   { width: 100%; border-collapse: collapse; font-size: 13px; min-width: 900px; }
/* A link inside a table header MUST inherit the header's white — the global
   `a { color: var(--purple) }` against `th { background: var(--purple) }` renders
   purple-on-purple, i.e. invisible. That's exactly what happened when the
   Implementation queue's headers became sort links (July 16 2026): the columns
   were sortable, but every header vanished except the one that wasn't a link. */
.data-table th a { color: inherit; text-decoration: none; }
.data-table th a:hover { text-decoration: underline; }
.data-table th {
  background: var(--purple); color: #fff;
  padding: .65rem .75rem; text-align: left; font-weight: 600; font-size: 12px;
  white-space: nowrap;
}
.data-table td { padding: .6rem .75rem; border-bottom: 1px solid var(--border); vertical-align: middle; }

/* ── A table that is BOTH wide and long ──────────────────────────────────────
   Set-Up Tracking is ~24 columns x ~200 rows, and a plain .table-wrapper puts
   the horizontal scrollbar at the very BOTTOM of the whole table. So to read the
   right-hand columns of the FIRST row you scroll to the bottom of the page, drag
   sideways, then scroll back up (Daniel, July 17 2026).

   The fix is to bound the box's height, which pins the horizontal scrollbar to
   the bottom of the viewport instead of the bottom of the data. That only works
   if the header stays put, so thead is sticky; and scrolling sideways is useless
   if you lose track of WHICH row you're on, so the first column is sticky too.

   Opt-in (--tall) rather than applied to .table-wrapper: every other list in the
   portal is narrow enough to read whole, and capping their height would add a
   scrollbar nobody asked for. */
.table-wrapper--tall { max-height: calc(100vh - 19rem); overflow: auto; }
.table-wrapper--tall thead th { position: sticky; top: 0; z-index: 2; }
/* The first column pins so a row stays identifiable when scrolled right.
   z-index 3 on the header's own first cell — it sits at BOTH intersections, and
   without it the sticky thead paints over it at the top-left corner. */
.table-wrapper--tall tbody td:first-child {
  position: sticky; left: 0; z-index: 1;
  background: var(--surface);
  /* The wrapper's own border can't show through a sticky cell, so the column
     needs its own right edge or the pinned name bleeds into the scrolled data. */
  box-shadow: 1px 0 0 var(--border);
}
.table-wrapper--tall thead th:first-child {
  position: sticky; left: 0; z-index: 3;
  box-shadow: 1px 0 0 var(--border);
}

/* Implementation task rows. A task's "detail" is free text that legitimately
   holds a pasted scheduling/retainer URL — one long unbroken string forces its
   column as wide as the URL and warps the whole table (reported July 15 2026).
   Cap the cell and let the detail wrap mid-string; `anywhere` rather than
   `break-word` because a URL has no break opportunities to prefer. */
.data-table td.task-cell { max-width: 24rem; }
.task-detail { overflow-wrap: anywhere; word-break: break-word; white-space: normal; }

/* "What's included" — the sub-steps folded into a task by the July 2026 trim.
   Collapsed by default so the checklist stays lean; a native <details> gives touch,
   keyboard and screen-reader support without JS. Palette is variable-driven so it
   themes with everything else. */
.task-includes { margin-top: .25rem; }
.task-includes > summary {
  cursor: pointer; font-size: .78rem; color: var(--text-muted);
  list-style: none; display: inline-flex; align-items: center; gap: .25rem;
  border-bottom: 1px dotted var(--border); width: fit-content;
}
.task-includes > summary::-webkit-details-marker { display: none; }
.task-includes > summary::before { content: "▸"; font-size: .7em; }
.task-includes[open] > summary::before { content: "▾"; }
.task-includes > summary:hover { color: var(--text); }
.task-includes > summary:focus-visible { outline: 2px solid var(--purple); outline-offset: 2px; }
.task-includes ul {
  margin: .3rem 0 0; padding-left: 1.1rem;
  font-size: .78rem; color: var(--text-muted); white-space: normal;
}
.task-includes li { margin: .1rem 0; overflow-wrap: anywhere; }

/* Nudge a Tech-pool task: an optional one-line note sits inline with the button, so
   a nudge can carry information ("client call is Thursday") instead of just nagging.
   The last-nudged stamp is the check on a deliberately repeatable action. */
.nudge-form { display: inline-flex; align-items: center; gap: .25rem; }
.nudge-note { width: 9rem; font-size: .78rem; padding: .15rem .35rem; }
.nudge-stamp { font-size: .72rem; color: var(--text-muted); white-space: nowrap; }
/* Inline assignee picker — sits in a table cell, so it must not inherit the
   full-width form-select sizing. */
.form-select-sm { padding: .25rem .4rem; font-size: .8rem; min-width: 9rem; width: auto; }
.data-table tr:last-child td { border-bottom: none; }
.data-table tr:hover td { background: #f9f8fd; }
.td-company   { min-width: 150px; max-width: 170px; }
/* THE ROW STANDARD (July 16 2026): the account name is how you open a record —
   every list does it this way, and the Actions column is reserved for genuine
   additional actions (Rectify, Resume, Churn), never for "open the thing".
   Adopted because the old Edit/View button forced a label choice that has no
   true answer once a detail page is a hybrid view+edit surface, which every
   Postgres-era module's is; the link makes no claim, and the page decides.
   A name with NO link is a real third state, not an oversight — it means the
   caller has no route to that record (see ob_pipeline/sales_takeover.html).
   The underline is load-bearing, not decoration: --purple (#241558) is all but
   identical to --text (#1a1a2e), so colour signals nothing here and weight
   doesn't either (these names were already bold). Without it the link is
   invisible as a link. */
.td-company a { font-weight: 600; text-decoration: underline;
                text-decoration-color: var(--text-muted); text-underline-offset: 2px; }
.td-company a:hover { text-decoration-color: var(--purple); }
.td-key       { display: block; font-size: 11px; color: var(--text-muted); font-family: monospace; }
.td-mrr       { white-space: nowrap; font-weight: 500; }
/* Total line at the foot of a list (OB Pipeline / Sales-Takeover MRR totals). */
.data-table tfoot td { border-top: 2px solid var(--border); border-bottom: none;
                       font-weight: 700; background: #f4f2fb; }
.td-date      { white-space: nowrap; color: var(--text-muted); font-size: 12px; }
.td-date--overdue { color: var(--danger); font-weight: 700; }
.td-date--soon { color: #856404; font-weight: 700; background: #FFF3CD; border-radius: 4px; padding: .1rem .4rem; }
.td-actions   { white-space: nowrap; padding-right: 1rem; vertical-align: middle; }
.td-actions a, .td-actions button, .td-actions form { display: inline-block; vertical-align: middle; margin-right: .35rem; }
.td-actions a:last-child, .td-actions button:last-child { margin-right: 0; }
/* Task progress — compact done/total bar for a list row (Implementation queue).
   All colours are variables, so it themes in dark mode for free. */
.task-progress { display: flex; align-items: center; gap: .5rem; min-width: 6rem; }
.task-progress__track { flex: 1 1 auto; height: 6px; min-width: 2.5rem;
                        background: var(--border); border-radius: 999px; overflow: hidden; }
.task-progress__fill  { height: 100%; background: var(--success); border-radius: 999px;
                        transition: width .2s ease; }
.task-progress__label { flex: 0 0 auto; font-size: 12px; color: var(--text-muted);
                        white-space: nowrap; font-variant-numeric: tabular-nums; }
/* The bar as a clickable button (opens the breakdown popover). Button chrome
   reset; the flex layout is inherited from .task-progress. */
.task-progress--btn { width: 100%; border: 0; background: transparent; padding: 0;
                      font: inherit; color: inherit; cursor: pointer; text-align: left; }
.task-progress--btn:hover .task-progress__track { box-shadow: 0 0 0 1px var(--purple) inset; }
.task-progress--btn:focus-visible { outline: 2px solid var(--purple); outline-offset: 2px;
                                    border-radius: var(--radius); }
/* Breakdown popover — done vs. remaining, grouped by phase. Positioned FIXED by
   main.js (so the table-wrapper's overflow can't clip it); scrolls if the
   checklist is long. Variable-driven, so it themes in dark mode. */
.task-popover { position: fixed; z-index: 200; width: 300px; max-width: 92vw;
                max-height: 60vh; overflow-y: auto;
                background: var(--surface); border: 1px solid var(--border);
                border-radius: var(--radius); box-shadow: var(--shadow-md);
                padding: .6rem .75rem; font-size: 12px; }
.task-popover[hidden] { display: none; }
.task-popover__head { font-weight: 700; color: var(--text); margin-bottom: .4rem;
                      padding-bottom: .35rem; border-bottom: 1px solid var(--border); }
.task-popover__phase { display: flex; justify-content: space-between; align-items: baseline;
                       font-weight: 600; color: var(--purple); margin: .5rem 0 .15rem; }
.task-popover__list { list-style: none; margin: 0; padding: 0; }
.task-popover__list li { display: flex; gap: .4rem; align-items: baseline; padding: .1rem 0;
                         color: var(--text); }
.task-popover__list li.is-open { color: var(--text-muted); }
.task-popover__list li.is-done .task-popover__mark { color: var(--success); }
.task-popover__mark { flex: 0 0 auto; width: .9rem; text-align: center; }
/* Completed section — collapsed one-liners so the remaining work leads. */
.task-popover__section { margin: .5rem 0 .1rem; padding-top: .35rem;
                         border-top: 1px solid var(--border);
                         text-transform: uppercase; letter-spacing: .04em;
                         font-size: 10px; font-weight: 700; color: var(--text-muted); }
.task-popover__alldone { display: flex; gap: .4rem; align-items: center;
                         color: var(--success); font-weight: 600; }
/* Two collapsible groupings: done tasks inside an ACTIVE phase (__done), and each
   fully-COMPLETED phase (__donephase). Both hide the native <details> marker (a
   flex/inline summary drops it anyway) and use a CSS caret that rotates when open. */
.task-popover__done { margin: .1rem 0 .2rem; }
.task-popover__done > summary,
.task-popover__donephase > summary { cursor: pointer; user-select: none; list-style: none; }
.task-popover__done > summary::-webkit-details-marker,
.task-popover__donephase > summary::-webkit-details-marker { display: none; }
.task-popover__done > summary::before,
.task-popover__donephase > summary > span:first-child::before {
  content: "\25B8"; display: inline-block; margin-right: .3rem; font-size: 9px;
  color: var(--text-muted); transition: transform .12s ease; }
.task-popover__done[open] > summary::before,
.task-popover__donephase[open] > summary > span:first-child::before { transform: rotate(90deg); }
/* Active-phase "N done" toggle. */
.task-popover__done > summary { color: var(--text-muted); font-size: 11px; padding: .05rem 0; }
.task-popover__done > summary:hover { color: var(--purple); }
/* Completed-phase toggle — looks like the phase rows above (ratio right-aligned). */
.task-popover__donephase > summary { display: flex; justify-content: space-between;
                                     align-items: baseline; color: var(--text-muted);
                                     font-weight: 500; padding: .1rem 0; }
.task-popover__donephase > summary:hover { color: var(--purple); }
.task-popover__donephase .task-popover__mark { color: var(--success); }
/* Deterministic collapse — don't rely on the UA <details> hiding, which a flex/
   block child can defeat. When closed, hide the list outright. */
.task-popover__done:not([open]) > .task-popover__list,
.task-popover__donephase:not([open]) > .task-popover__list { display: none; }
.task-popover__done .task-popover__list li.is-done,
.task-popover__donephase .task-popover__list li.is-done { color: var(--text-muted); }

/* Implementation "Links" table (artifacts). A raw render/Drive/Docs URL is a long
   unbreakable string; without help it wraps to several lines or shoves the Added
   column off-screen. Truncate the link to one line (full URL on hover), stack the
   Added name/date, and set the edit/replace row subordinate to its value. */
.artifact-what { white-space: nowrap; vertical-align: top; }
.artifact-what__sub { color: var(--text-muted); font-size: 12px; }
.artifact-link { display: inline-block; max-width: min(30rem, 46vw); vertical-align: bottom;
                 overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.artifact-added { white-space: nowrap; vertical-align: top; }
.artifact-added__date { display: block; font-size: 11px; color: var(--text-muted); }
.artifact-row--edit td { background: var(--bg); }
/* OB Pipeline-specific narrowing, scoped so it can't affect risks/pipeline.html,
   history/index.html, or intake/queue.html the way the earlier table-wide
   min-width change accidentally did. */
#ob-table .td-type { max-width: 60px; }
#ob-table .td-specialist { max-width: 85px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }

/* ── Badges ──────────────────────────────────────────────────────────────── */
.badge        { display: inline-block; padding: .2rem .5rem; border-radius: 4px;
                font-size: 11px; font-weight: 600; white-space: nowrap; }
.badge--risk  { background: #FFD4C2; color: #8B3000; }
.badge--notif { background: #D4CCE8; color: var(--purple); }
.badge--achieved { background: #C6EFCE; color: #1e5c33; }
.badge--open  { background: #E0E0E0; color: var(--text-muted); }
.badge--pending { background: #FFF3CD; color: #856404; }
.badge--active  { background: #CFE2FF; color: #084298; }
.badge--almost  { background: #D4F4DD; color: #1e5c33; }
.badge--stale   { background: #F0C9B8; color: #8B3000; }
/* Add-on marker (July 20 2026) — a base OB record that carries an appointment-
   scheduling / contract-signing add-on. Purple accent, its own dark override below. */
.badge--addon   { background: #E4DBF5; color: var(--purple); margin-left: .35rem; }

/* Go Live is the implementation team's headline deadline — kept prominent on the
   build queue so it stays top-of-mind while triaging (Implementation team, July 2026).
   Weight/size only (colour inherits var(--text)), so it's dark-mode-safe; the
   approaching/past states reuse the badge classes, which already theme. */
.th-go-live, .td-go-live { white-space: nowrap; }
.td-go-live .go-live-date { font-weight: 700; font-size: 1.05rem; }
.td-go-live .go-live-countdown { display: block; margin-top: 2px; }

/* Collapsed onboarding-questionnaire reference on the build detail page — the build
   spec, read-only, closed by default so it doesn't crowd the page. */
.detail-questionnaire > summary { cursor: pointer; }
.detail-questionnaire > summary .form-section-title { display: inline-block; margin: 0 .5rem 0 0; }
.detail-questionnaire > summary:hover { color: var(--purple); }

/* ── Forms ───────────────────────────────────────────────────────────────── */
.ops-form     { max-width: 860px; }
.form-section { background: var(--surface); border: 1px solid var(--border);
                border-radius: var(--radius); padding: 1.25rem 1.5rem; margin-bottom: 1.25rem; }
.form-section-title { font-size: 13px; font-weight: 700; color: var(--purple);
                      text-transform: uppercase; letter-spacing: .04em; margin-bottom: 1rem;
                      padding-bottom: .5rem; border-bottom: 1px solid var(--border); }
.form-grid    { display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: 1rem; }
.form-group   { display: flex; flex-direction: column; gap: .35rem; }
.form-label   { font-size: 12px; font-weight: 600; color: var(--text); }
.required     { color: var(--danger); }
.form-input, .form-select {
  padding: .5rem .65rem; border: 1px solid var(--border); border-radius: var(--radius);
  font-size: 13px; color: var(--text); background: var(--surface);
  transition: border-color .15s, box-shadow .15s;
}
.form-input:focus, .form-select:focus {
  outline: none; border-color: var(--purple);
  box-shadow: 0 0 0 3px rgba(36,21,88,.1);
}
.form-textarea { resize: vertical; min-height: 80px; }
.form-hint    { font-size: 11px; color: var(--text-muted); }
.radio-group  { display: flex; gap: 1rem; padding-top: .35rem; }
.checkbox-group { display: flex; flex-wrap: wrap; gap: .5rem 1.25rem; padding-top: .35rem; }
.radio-label  { display: flex; align-items: center; gap: .35rem; cursor: pointer; font-size: 13px; }
.form-actions { display: flex; gap: .75rem; align-items: center; margin-top: 1.5rem; }
.requirement-missing { background: rgba(192,57,43,.08); border: 1px solid var(--danger);
                        border-radius: var(--radius); padding: .35rem .6rem; }

/* ── Info banner ─────────────────────────────────────────────────────────── */
.info-banner  { background: #d1ecf1; color: #0c5460; border: 1px solid #bee5eb;
                border-radius: var(--radius); padding: .75rem 1rem;
                font-size: 13px; margin-bottom: 1.25rem;
                max-width: 860px; }

/* ── Notes history (neutral, not an alert — accumulating log, not a
   one-off instructional message like .info-banner) ────────────────────── */
.notes-history { background: var(--bg); border: 1px solid var(--border);
                 border-radius: var(--radius); padding: .75rem 1rem; }
.notes-entry  { font-size: 13px; margin: 0 0 .5rem 0; }
.notes-entry:last-child { margin-bottom: 0; }

/* ── Empty state ─────────────────────────────────────────────────────────── */
.empty-state  { background: var(--surface); border: 1px solid var(--border);
                border-radius: var(--radius); padding: 3rem; text-align: center;
                color: var(--text-muted); font-size: 15px; }

/* ── Pipeline search ─────────────────────────────────────────────────────── */
.pipeline-toolbar  { display: flex; align-items: center; gap: 1rem; margin-bottom: 1rem; }
.pipeline-search   { max-width: 320px; }
.pipeline-count    { font-size: 13px; color: var(--text-muted); }

/* ── History search ──────────────────────────────────────────────────────── */
.history-search-form  { margin-bottom: 1.5rem; }
.history-search-row   { display: flex; gap: .75rem; align-items: center; }
.history-search-input { max-width: 400px; }

/* ── Status pills ────────────────────────────────────────────────────────── */
.status-pill        { display: inline-block; padding: .2rem .55rem; border-radius: 4px;
                      font-size: 11px; font-weight: 600; white-space: nowrap; }
.status-open        { background: #d4edda; color: #155724; }
.status-rectified   { background: #d1ecf1; color: #0c5460; }
.status-churned     { background: #f8d7da; color: #721c24; }
.status-converted   { background: #fff3cd; color: #856404; }
.status-returned    { background: #e2e3e5; color: #383d41; }
.badge--churn       { background: #f8d7da; color: #721c24; }

/* ── History grouping ─────────────────────────────────────────────────────── */
.group-spacer td   { padding: 0; border: none; height: 10px; background: var(--bg); }
.group-start td    { border-top: 2px solid var(--purple); }

/* ── MRR lookup ───────────────────────────────────────────────────────────── */
.mrr-input-row { display: flex; gap: .5rem; align-items: center; flex-wrap: wrap; }
.mrr-input-row input { flex: 1 1 140px; min-width: 0; }
.mrr-input-row .btn { flex-shrink: 0; text-align: center; white-space: nowrap; }
.mrr-field-group { grid-column: span 2; }

/* Intake: per-service MRR rows (multi-service orders). The 130px cap keeps the
   amount column from stretching to absurd width next to a short service name;
   minmax lets it shrink on a phone without needing its own media query. */
.svc-mrr-rows  { display: flex; flex-direction: column; gap: .4rem; }
.svc-mrr-row   { display: grid; grid-template-columns: 1fr minmax(85px, 130px);
                 gap: .75rem; align-items: center; }
.svc-mrr-label { font-size: 13px; color: var(--text); }
.svc-mrr-total { display: flex; justify-content: space-between; gap: .75rem;
                 margin-top: .5rem; padding-top: .5rem; border-top: 1px solid var(--border);
                 font-size: 12px; font-weight: 600; color: var(--text); }

/* ── Power BI embed ──────────────────────────────────────────────────────── */
.powerbi-embed-wrapper { position: relative; width: 100%; padding-top: 56.25%;
                          border-radius: var(--radius); overflow: hidden;
                          box-shadow: var(--shadow); border: 1px solid var(--border); }
.powerbi-embed-frame   { position: absolute; top: 0; left: 0; width: 100%; height: 100%; border: none; }

.embed-placeholder { background: var(--surface); border: 1px dashed var(--border);
                      border-radius: var(--radius); padding: 4rem 2rem; text-align: center; }
.embed-placeholder-icon { color: var(--text-muted); margin-bottom: 1rem; display: flex; justify-content: center; }
.embed-placeholder h2 { font-size: 1.1rem; color: var(--purple); margin-bottom: .5rem; }
.embed-placeholder p  { color: var(--text-muted); font-size: 13px; margin-bottom: 1.5rem; max-width: 420px; margin-left: auto; margin-right: auto; }

/* ── Dashboard insights summary ──────────────────────────────────────────── */
.insights-summary-section { margin-top: 2rem; }
.insights-summary-header  { display: flex; align-items: center; justify-content: space-between; margin-bottom: .75rem; }
.section-title             { font-size: 1.1rem; font-weight: 700; color: var(--purple); }
.section-link               { font-size: 13px; }
.insights-summary-placeholder { background: var(--surface); border: 1px dashed var(--border);
                                 border-radius: var(--radius); padding: 2rem; text-align: center;
                                 color: var(--text-muted); font-size: 13px; }

/* ── Pipeline filter + sort ──────────────────────────────────────────────── */
.pipeline-csm-filter { max-width: 200px; }
th.sortable { cursor: pointer; user-select: none; }
th.sortable:hover { background: var(--purple-dark); }
.sort-arrow { font-size: 10px; margin-left: 4px; }

/* ── Company Key prominence ──────────────────────────────────────────────── */
.company-key-group   { margin-bottom: 1.25rem; max-width: 360px; }
.form-input-prominent{ font-size: 16px; font-weight: 600; padding: .65rem .85rem;
                       border: 2px solid var(--purple); }
.form-input-prominent:focus { box-shadow: 0 0 0 3px rgba(36,21,88,.15); }

/* ── Inline label hint ───────────────────────────────────────────────────── */
.form-hint-inline { font-size: 12px; font-weight: 400; color: var(--text-muted); margin-left: .25rem; }

/* ── BOB + Insights action card ─────────────────────────────────────────── */
.action-icon--insights { background: rgba(230, 168, 23, .12); color: #e6a817; }
.action-icon--bob { background: rgba(46, 125, 82, .12); color: #2e7d52; }
.action-icon--myweek { background: rgba(36, 21, 88, .12); color: var(--purple); }

/* ── Pipeline: Code Off Site reason as a domain link ─────────────────────── */
.reason-domain-link { color: var(--orange); font-weight: 600; text-decoration: none; }
.reason-domain-link:hover { text-decoration: underline; }

/* ── Mobile nav toggle (hamburger) ───────────────────────────────────────── */
/* Hidden on desktop; the media query below reveals it and collapses the
   link + user rows into a vertical dropdown panel. */
.nav-toggle {
  display: none; align-items: center; justify-content: center;
  width: 40px; height: 40px; margin-left: auto; flex-shrink: 0;
  background: transparent; color: #fff; border: 1px solid rgba(255,255,255,.2);
  border-radius: var(--radius); cursor: pointer; padding: 0;
}
.nav-toggle:hover { background: rgba(255,255,255,.12); }
.nav-toggle:focus-visible { outline: 2px solid var(--orange); outline-offset: 2px; }

/* ── Responsive: phones & small tablets ──────────────────────────────────── */
@media (max-width: 860px) {
  .nav {
    flex-wrap: wrap; height: auto; min-height: 56px;
    padding: 0 1rem; gap: .5rem 1rem;
  }
  .nav-brand { margin-right: 0; }
  .nav-toggle { display: flex; }

  /* Both the links and the user block become full-width stacked rows that
     only appear when the nav carries the .open class (toggled in main.js). */
  .nav-links, .nav-user {
    flex: 0 0 100%; flex-direction: column; align-items: stretch;
    gap: .15rem; display: none;
  }
  .nav.open { padding-bottom: .75rem; }
  .nav.open .nav-links, .nav.open .nav-user { display: flex; }

  /* Bigger tap targets, left-aligned like a menu. */
  .nav-link { padding: .7rem .75rem; font-size: 15px; }
  .nav-divider { display: none; }  /* dividers only read as separators horizontally */
  .nav-user {
    margin-left: 0; align-items: center; flex-direction: row; flex-wrap: wrap;
    gap: .6rem; padding-top: .6rem; margin-top: .35rem;
    border-top: 1px solid rgba(255,255,255,.15);
  }
  .nav-username { flex: 1; }
  .nav-logout { padding: .5rem .8rem; }

  /* Tighter page framing on small screens. */
  .main-content { padding: 1.25rem 1rem; }
  .page-header { flex-wrap: wrap; align-items: flex-start; margin-bottom: 1.25rem; }
  .page-header h1 { font-size: 1.3rem; }

  /* Let dense action / toolbar rows wrap instead of overflowing. */
  .form-actions, .pipeline-toolbar, .history-search-row,
  .mrr-input-row, .insights-summary-header { flex-wrap: wrap; }
  .form-actions .btn { flex: 1 1 auto; justify-content: center; }
  .pipeline-search, .history-search-input, .pipeline-csm-filter { max-width: 100%; }

  /* Forms: single column and full-width fields. */
  .form-section { padding: 1rem 1rem; }
  .form-grid { grid-template-columns: 1fr; }
  .mrr-field-group { grid-column: auto; }
  .ops-form, .info-banner { max-width: 100%; }
}

/* ── Responsive: narrow phones ───────────────────────────────────────────── */
@media (max-width: 480px) {
  .login-card { width: 100%; max-width: 360px; padding: 2rem 1.25rem; }
  .empty-state { padding: 2rem 1rem; }
  .radio-group { flex-wrap: wrap; gap: .5rem 1rem; }
}

/* ── Record navigation (Prev / Next, injected by main.js) ────────────────────
   Sits above the page header on a detail page opened from a list. Themed via
   variables, so it needs no dark-mode override. */
.record-nav { display: flex; align-items: center; gap: .5rem; margin-bottom: 1rem; }
.record-nav-btn {
  display: inline-flex; align-items: center; gap: .3rem;
  padding: .35rem .7rem; border-radius: var(--radius);
  font-size: 13px; font-weight: 500; text-decoration: none;
  background: var(--surface); color: var(--purple); border: 1px solid var(--border);
}
.record-nav-btn:hover { background: var(--bg); border-color: var(--purple); text-decoration: none; }
.record-nav-btn.is-disabled { color: var(--text-muted); opacity: .5; pointer-events: none; }
.record-nav-pos { font-size: 12px; color: var(--text-muted); }

/* ── Nav dropdowns (grouped mode — see app/nav.py) ───────────────────────────
   Rendered only for users with enough destinations to warrant grouping. The
   toggle is a <button> wearing .nav-link; the menu is a light surface popover
   against the purple bar. Themed via variables, so no dark-mode override. */
.nav-dropdown { position: relative; display: inline-flex; }
.nav-dropdown-toggle {
  font-family: inherit; background: transparent; border: 0; cursor: pointer;
  display: inline-flex; align-items: center; gap: .25rem;
}
.nav-dropdown.active > .nav-dropdown-toggle { background: rgba(255,255,255,.12); color: #fff; }
.nav-caret { font-size: 9px; transition: transform .15s; }
.nav-dropdown.open .nav-caret { transform: rotate(180deg); }
.nav-dropdown-menu {
  display: none; position: absolute; top: calc(100% + 4px); left: 0; z-index: 200;
  min-width: 190px; padding: .3rem;
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--radius); box-shadow: var(--shadow-md);
}
.nav-dropdown.open > .nav-dropdown-menu { display: block; }
.nav-dropdown-item {
  display: block; padding: .5rem .65rem; border-radius: 6px;
  font-size: 13px; color: var(--text); text-decoration: none; white-space: nowrap;
}
.nav-dropdown-item:hover { background: var(--bg); text-decoration: none; }
.nav-dropdown-item.active { background: var(--bg); color: var(--purple); font-weight: 600; }

/* Mobile: the menu drops the popover chrome and expands inline (accordion) as a
   light-on-purple indented list, matching the collapsed hamburger nav. */
@media (max-width: 860px) {
  .nav-dropdown { display: block; width: 100%; }
  .nav-dropdown-toggle { width: 100%; justify-content: space-between; }
  .nav-dropdown-menu {
    position: static; min-width: 0; padding: 0 0 .25rem .75rem;
    background: transparent; border: 0; box-shadow: none;
  }
  .nav-dropdown-item { color: rgba(255,255,255,.8); padding: .6rem .75rem; }
  .nav-dropdown-item:hover,
  .nav-dropdown-item.active { background: rgba(255,255,255,.12); color: #fff; }
}

/* ── Nav create control (prominent "log" action buttons, left of nav links) ── */
.nav-create { display: flex; align-items: center; gap: .4rem; flex-shrink: 0; margin-right: .25rem; }
.nav-create-btn {
  display: inline-flex; align-items: center; padding: .38rem .8rem;
  background: var(--orange); color: #fff; border-radius: var(--radius);
  font-size: 13px; font-weight: 600; text-decoration: none; white-space: nowrap;
}
.nav-create-btn:hover { filter: brightness(.93); text-decoration: none; color: #fff; }
.nav-create-overflow { display: inline-flex; }
/* The ▾ overflow toggle also carries .nav-dropdown-toggle, so main.js's dropdown
   handler and the .nav-dropdown-menu popover styling both apply for free. */
.nav-create-more {
  padding: .38rem .5rem; background: rgba(255,255,255,.14); color: #fff;
  border-radius: var(--radius);
}
.nav-create-more:hover { background: rgba(255,255,255,.22); }
.nav-create-more .nav-caret { font-size: 10px; margin-left: 0; }

/* ── Nav attention badge (overdue/urgent only — placed by main.js) ─────────── */
.nav-badge {
  display: inline-flex; align-items: center; justify-content: center;
  min-width: 16px; height: 16px; padding: 0 4px; margin-left: 5px;
  background: var(--danger); color: #fff; border-radius: 10px;
  font-size: 10px; font-weight: 700; line-height: 1; flex-shrink: 0;
}

/* ── Dashboard "needs attention" strip ───────────────────────────────────── */
.attention-strip {
  display: flex; align-items: center; flex-wrap: wrap; gap: .5rem;
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--radius); padding: .55rem .8rem; margin-bottom: 1.5rem;
}
.attention-label {
  font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: .04em;
  color: var(--text-muted); margin-right: .25rem;
}
.attention-pills { display: inline-flex; flex-wrap: wrap; gap: .5rem; }
.attention-pill {
  display: inline-flex; align-items: center; padding: .3rem .65rem;
  border-radius: 999px; font-size: 12px; font-weight: 600; text-decoration: none;
  background: var(--bg); color: var(--text); border: 1px solid var(--border);
}
.attention-pill:hover { border-color: var(--purple); text-decoration: none; }
.attention-pill--risk { background: #fdecea; color: #b93025; border-color: #f5c6cb; }

/* ── Theme toggle (sun / moon) ───────────────────────────────────────────────
   Lives in the nav, visible in both themes. Which icon shows is decided by CSS
   keyed on data-theme, not JS, so it's correct on first paint (no flicker): the
   moon means "switch to dark", the sun means "switch to light". */
.theme-toggle {
  display: inline-flex; align-items: center; justify-content: center;
  width: 32px; height: 32px; flex-shrink: 0; padding: 0;
  background: transparent; color: rgba(255,255,255,.75);
  border: 1px solid rgba(255,255,255,.2); border-radius: var(--radius);
  cursor: pointer;
}
.theme-toggle:hover { background: rgba(255,255,255,.12); color: #fff; }
.theme-toggle:focus-visible { outline: 2px solid var(--orange); outline-offset: 2px; }
.theme-toggle .icon-sun { display: none; }
:root[data-theme="dark"] .theme-toggle .icon-moon { display: none; }
:root[data-theme="dark"] .theme-toggle .icon-sun  { display: inline-flex; }

/* ── Dark mode ────────────────────────────────────────────────────────────────
   Toggled by data-theme="dark" on <html> (main.js flips it on click; a small
   no-flash inline script in each page's <head> applies the saved choice before
   first paint). Almost everything flips via the variable overrides below,
   because the structural palette (--bg / --surface / --border / --text /
   --text-muted) is already variable-driven.

   Two things need explicit help beyond the variables:
   (1) --purple does double duty — an accent FOREGROUND (headings, links,
       section titles) that must go LIGHT on dark, and a brand BACKGROUND (nav,
       primary buttons, table headers) that carries white text and must stay
       DARK. The variable flips to the light-accent role; the handful of
       surface-role selectors are given a fixed dark background here instead.
   (2) The pastel chips (flash / badges / status pills / info banner / date
       chips) are hardcoded light pairs; each gets a dark, legible override.

   This whole section is ADDITIVE — no light-mode rule is edited — so a dark-mode
   bug can never regress the default theme. */
:root[data-theme="dark"] {
  color-scheme: dark;              /* native selects, checkboxes, scrollbars, date pickers */
  --purple:      #b9a7ff;          /* accent foreground: headings, links, section titles */
  --purple-dark: #a892f5;
  --bg:          #15131f;
  --surface:     #201d30;
  --border:      #33304a;
  --text:        #e9e7f2;
  --text-muted:  #a3a0b8;
  --shadow:      0 1px 4px rgba(0,0,0,.45);
  --shadow-md:   0 4px 16px rgba(0,0,0,.55);
}

/* Brand-background surfaces: --purple now plays the light-accent role, so the
   selectors that use it as a background UNDER white text are repointed to a
   fixed dark purple. Higher specificity than the base rules, so order-independent. */
:root[data-theme="dark"] .nav,
:root[data-theme="dark"] .data-table th,
:root[data-theme="dark"] th.admin-frozen-col,
:root[data-theme="dark"] .btn-primary,
:root[data-theme="dark"] .action-icon--pipeline,
:root[data-theme="dark"] .login-logo { background: #241558; }
:root[data-theme="dark"] th.sortable:hover,
:root[data-theme="dark"] .admin-sortable:hover { background: #100a28; }

/* Row hover / zebra striping (the base rules use hardcoded light values). */
:root[data-theme="dark"] .data-table tr:hover td,
:root[data-theme="dark"] .data-table tr:hover td.admin-frozen-col { background: #2a2740; }
:root[data-theme="dark"] .data-table tfoot td { background: #26233a; }
:root[data-theme="dark"] .admin-users-table tbody tr.row-stripe td { background: #26233a; }
:root[data-theme="dark"] .admin-users-table tbody tr.row-stripe td.admin-frozen-col { background: #2b2842; }
:root[data-theme="dark"] .admin-users-table tbody tr:hover td,
:root[data-theme="dark"] .admin-users-table tbody tr:hover td.admin-frozen-col { background: #332e4c; }

/* Focus glow: the light-mode purple glow is invisible on dark. */
:root[data-theme="dark"] .form-input:focus,
:root[data-theme="dark"] .form-select:focus { box-shadow: 0 0 0 3px rgba(185,167,255,.20); }
:root[data-theme="dark"] .form-input-prominent:focus { box-shadow: 0 0 0 3px rgba(185,167,255,.25); }

/* Chips — each hardcoded pastel pair gets a dark, legible equivalent. */
:root[data-theme="dark"] .flash-success { background:#173328; color:#a3e0bf; border-color:#2c5241; }
:root[data-theme="dark"] .flash-error   { background:#361c20; color:#f0a9ae; border-color:#5a2e33; }
:root[data-theme="dark"] .flash-warning { background:#352d13; color:#e8cd7a; border-color:#544a1f; }
:root[data-theme="dark"] .flash-info    { background:#123037; color:#8fd3e0; border-color:#1e505b; }

:root[data-theme="dark"] .badge--risk     { background:#43241a; color:#ffb394; }
:root[data-theme="dark"] .badge--notif    { background:#2a2450; color:#c9b8ff; }
:root[data-theme="dark"] .badge--achieved { background:#173328; color:#9fe0bd; }
:root[data-theme="dark"] .badge--open     { background:#302e3d; color:var(--text-muted); }
:root[data-theme="dark"] .badge--pending  { background:#352d13; color:#e8cd7a; }
:root[data-theme="dark"] .badge--active   { background:#152d49; color:#9fc7f5; }
:root[data-theme="dark"] .badge--almost   { background:#173328; color:#9fe0bd; }
:root[data-theme="dark"] .badge--stale    { background:#43301f; color:#f0b394; }
:root[data-theme="dark"] .badge--addon    { background:#2a2450; color:#c9b8ff; }

:root[data-theme="dark"] .status-open      { background:#173328; color:#a3e0bf; }
:root[data-theme="dark"] .status-rectified { background:#123037; color:#8fd3e0; }
:root[data-theme="dark"] .status-churned   { background:#361c20; color:#f0a9ae; }
:root[data-theme="dark"] .status-converted { background:#352d13; color:#e8cd7a; }
:root[data-theme="dark"] .status-returned  { background:#2e2c3a; color:#c3c0d3; }
:root[data-theme="dark"] .badge--churn     { background:#361c20; color:#f0a9ae; }

:root[data-theme="dark"] .info-banner      { background:#123037; color:#8fd3e0; border-color:#1e505b; }
:root[data-theme="dark"] .td-date--soon    { background:#352d13; color:#e8cd7a; }
:root[data-theme="dark"] .td-date--overdue { color:#ef8078; }
:root[data-theme="dark"] .attention-pill--risk { background:#361c20; color:#f0a9ae; border-color:#5a2e33; }
