:root{
  --ink:#1f2430;
  --sub:#6b7280;
  --line:#c7ccd4;
  --bg:#f5f6f8;
  --surface:#ffffff;
  --surface-alt:#f3f4f6;
  --chip-bg:#111827;
  --total:#1f2937;   --total-bg:#e7e9ec;
  --open:#2563eb;     --open-bg:#eaf1ff;
  --closed:#475569;   --closed-bg:#eef1f4;
  --eligible:#16a34a; --eligible-bg:#eaf7ee;
  --ineligible:#dc2626;--ineligible-bg:#fdecec;
  --invest:#d97706;   --invest-bg:#fef3e2;
  --outreach:#7c3aed; --outreach-bg:#f2ecfc;
  --letters:#0d9488;  --letters-bg:#e5f7f5;
  --leaf-bg:var(--surface);
  --accent:#2563eb;
  --shadow-1:rgba(0,0,0,.12);
  --shadow-2:rgba(0,0,0,.25);
  color-scheme:light;
}

/* Dark palette. Box "-bg" tints switch from solid pastels to translucent
   rgba() washes over the page background -- they automatically look
   harmonious on dark surfaces instead of reading as bright, jarring patches
   the way a direct light-mode-style pastel would. */
html[data-theme="dark"]{
  --ink:#e5e7eb;
  --sub:#94a3b8;
  --line:#2d3548;
  --bg:#0d1117;
  --surface:#161b26;
  --surface-alt:#1f2636;
  --chip-bg:#2a3245;
  --total:#cbd5e1;     --total-bg:rgba(203,213,225,.12);
  --open:#60a5fa;      --open-bg:rgba(96,165,250,.14);
  --closed:#94a3b8;    --closed-bg:rgba(148,163,184,.12);
  --eligible:#4ade80;  --eligible-bg:rgba(74,222,128,.14);
  --ineligible:#f87171;--ineligible-bg:rgba(248,113,113,.14);
  --invest:#fbbf24;    --invest-bg:rgba(251,191,36,.14);
  --outreach:#a78bfa;  --outreach-bg:rgba(167,139,250,.16);
  --letters:#2dd4bf;   --letters-bg:rgba(45,212,191,.14);
  --accent:#3b82f6;
  --shadow-1:rgba(0,0,0,.45);
  --shadow-2:rgba(0,0,0,.65);
  color-scheme:dark;
}

*{box-sizing:border-box;}
/* Smooth light/dark fade: every themed color property eases instead of
   snapping. Elements below with their own `transition` (buttons, hoverable
   boxes) list these same properties alongside their existing ones -- a more
   specific rule's `transition` value replaces the universal one entirely
   rather than merging with it, so the fade has to be repeated there too. */
*, *::before, *::after{
  transition:background-color .3s ease, border-color .3s ease, color .3s ease, box-shadow .3s ease;
}
body{
  margin:0; padding:32px 16px 64px;
  font-family:"Segoe UI",Roboto,Helvetica,Arial,sans-serif;
  background:var(--bg); color:var(--ink);
}
.page-head{ position:relative; text-align:center; margin-bottom:28px; }
h1{
  margin:0; font-size:32px; font-weight:800; letter-spacing:-.01em;
  color:var(--ink);
}
h1 .brand{ color:var(--accent); }
.page-head-actions{ position:absolute; top:4px; right:0; display:flex; align-items:center; gap:14px; }
.page-head-link{
  font-family:inherit; font-size:12px; font-weight:600;
  background:none; border:none; color:var(--sub); cursor:pointer; padding:4px 0;
  transition:color .3s ease;
}
.page-head-link:hover{ color:var(--accent); text-decoration:underline; }
.logout-link:hover{ color:var(--ineligible); }
.meta{ text-align:center; color:var(--sub); font-size:12px; margin-bottom:28px; }

/* control bar */
.control-bar{
  display:flex; align-items:center; justify-content:space-between; gap:14px;
  flex-wrap:wrap; max-width:1000px; margin:0 auto 20px;
}
.control-bar-left{ display:flex; align-items:center; gap:14px; flex-wrap:wrap; }
.control-bar-right{ display:flex; align-items:center; gap:14px; flex-wrap:wrap; margin-left:auto; }

.stat-box{
  display:flex; flex-direction:column; align-items:flex-end; gap:2px;
  padding:8px 14px; border:1px solid var(--line); border-radius:8px; background:var(--surface);
}
.stat-box .stat-label{ font-size:11px; font-weight:600; color:var(--sub); text-transform:uppercase; letter-spacing:.03em; }
.stat-box .stat-value{ font-size:18px; font-weight:700; color:var(--ink); }
.btn-refresh{
  display:inline-flex; align-items:center; gap:8px;
  font-family:inherit; font-size:13px; font-weight:600; padding:9px 18px;
  border:1px solid var(--accent); border-radius:8px; background:var(--accent); color:#fff;
  cursor:pointer;
  transition:opacity .15s, background-color .3s ease, border-color .3s ease, color .3s ease, box-shadow .3s ease;
}
.btn-refresh:hover{ opacity:.9; }
.btn-refresh:disabled{ opacity:.55; cursor:not-allowed; }
.spinner{
  width:13px; height:13px; border-radius:50%;
  border:2px solid rgba(255,255,255,.4); border-top-color:#fff;
  animation:spin .7s linear infinite;
}
.spinner[hidden]{ display:none; }
@keyframes spin{ to{ transform:rotate(360deg); } }
.status-row{ text-align:center; margin-bottom:20px; }
.last-refreshed{ font-size:12px; color:var(--sub); }
.last-refreshed.error{ color:var(--ineligible); font-weight:600; }

.date-range{ display:flex; align-items:center; gap:8px; }
.date-range label{ font-size:12px; font-weight:600; color:var(--ink); }
.date-range input[type="date"]{
  font-family:inherit; font-size:13px; padding:7px 8px; border:1px solid var(--line);
  border-radius:6px; background:var(--surface); color:var(--ink);
}
.date-range input.invalid{ border-color:var(--ineligible); }

/* Reusable "i in a circle" hover/focus tooltip -- CSS-only (no JS, no extra
   markup per instance) via attr(data-tooltip), so it looks and themes the
   same everywhere it's dropped in. tabindex="0" on the span makes it
   keyboard-focusable, same accessibility intent as the rest of the app. */
.info-icon{
  display:inline-flex; align-items:center; justify-content:center;
  width:14px; height:14px; border-radius:50%; flex-shrink:0;
  background:var(--sub); color:var(--surface);
  font-size:10px; font-weight:700; font-style:normal; line-height:1;
  text-transform:none; /* stays lowercase "i" even inside an uppercase label */
  cursor:help; position:relative; user-select:none;
}
.info-icon:hover, .info-icon:focus-visible{ background:var(--accent); outline:none; }
.info-icon:hover::after, .info-icon:focus-visible::after{
  content:attr(data-tooltip);
  position:absolute; bottom:calc(100% + 6px); left:50%; transform:translateX(-50%);
  background:var(--chip-bg); color:#fff; padding:7px 10px; border-radius:6px;
  font-size:11px; font-weight:500; white-space:normal; width:max-content; max-width:240px;
  box-shadow:0 4px 12px var(--shadow-2); z-index:60; text-align:left; line-height:1.4;
  pointer-events:none;
}
/* For an icon near the right edge of the page -- a centered tooltip would
   run off-screen, so anchor it to the icon's right edge instead. */
.info-icon.info-icon-right:hover::after, .info-icon.info-icon-right:focus-visible::after{
  left:auto; right:0; transform:none;
}
/* For an icon sitting at the top of a container that clips vertical
   overflow (e.g. the matrix modal's Total line, inside .matrix-wrap's
   overflow-x:auto -- which also computes overflow-y:auto per the CSS spec
   -- itself inside .modal-body's own overflow-y:auto) -- an upward tooltip
   gets clipped before it's ever visible. Pop it downward instead. */
.info-icon.info-icon-below:hover::after, .info-icon.info-icon-below:focus-visible::after{
  bottom:auto; top:calc(100% + 6px);
}
.date-range input[type="date"]:disabled{ opacity:.6; cursor:not-allowed; }

/* Pre-30BD mode toggle -- a checkbox visually rebuilt as a sliding switch,
   since this is a single on/off flip (unlike the two-button segmented
   Box Controlled/Action Item Based export mode toggle elsewhere). */
.pre30bd-toggle{ display:inline-flex; align-items:center; gap:7px; cursor:pointer; user-select:none; }
.pre30bd-toggle input[type="checkbox"]{
  position:absolute; opacity:0; width:1px; height:1px; overflow:hidden;
}
.pre30bd-toggle-track{
  position:relative; width:34px; height:19px; border-radius:999px;
  background:var(--line); flex-shrink:0;
  transition:background-color .15s ease;
}
.pre30bd-toggle-thumb{
  position:absolute; top:2px; left:2px; width:15px; height:15px; border-radius:50%;
  background:var(--surface); box-shadow:0 1px 2px var(--shadow-1);
  transition:transform .15s ease;
}
.pre30bd-toggle input[type="checkbox"]:checked + .pre30bd-toggle-track{ background:var(--accent); }
.pre30bd-toggle input[type="checkbox"]:checked + .pre30bd-toggle-track .pre30bd-toggle-thumb{ transform:translateX(15px); }
.pre30bd-toggle input[type="checkbox"]:focus-visible + .pre30bd-toggle-track{ box-shadow:0 0 0 2px var(--accent); }
.pre30bd-toggle input[type="checkbox"]:disabled + .pre30bd-toggle-track{ opacity:.55; }
.pre30bd-toggle:has(input:disabled){ cursor:not-allowed; }
.pre30bd-toggle-text{ font-size:12px; font-weight:600; color:var(--ink); }

/* legend */
.legend{
  display:flex; flex-wrap:wrap; gap:10px 18px; justify-content:center;
  margin:0 auto 10px; max-width:1000px; font-size:12px; color:var(--sub);
}
.legend span{ display:inline-flex; align-items:center; gap:6px; }
.swatch{ width:12px; height:12px; border-radius:3px; display:inline-block; }

.tree-controls{ display:flex; justify-content:center; gap:10px; margin:0 auto 14px; max-width:1000px; }

/* ---- tree ---- */
/* The tree is naturally wider than most viewports (many sibling boxes at the
   Closed/Letters Sent levels). fitTreeToView() in app.js zooms #caseTree
   down so the whole thing is visible by default -- zoom reflows layout for
   real, so this wrapper needs no overflow/scroll behavior of its own. */
.tree, .tree ul, .tree li{ list-style:none; margin:0; padding:0; position:relative; }
.tree{ display:table; margin:0 auto; text-align:center; }
.tree ul{ display:table; width:100%; padding-top:36px; }
.tree li{ display:table-cell; padding:36px 14px 0; vertical-align:top; }

.tree li::before{
  content:""; position:absolute; top:0; left:0; right:0;
  outline:1px solid var(--line);
}
.tree li:first-child::before{ left:50%; }
.tree li:last-child::before{ right:50%; }
.tree li:only-child::before{ display:none; }

.tree ul::before, .tree .box::before{
  content:""; position:absolute; top:-36px; left:50%;
  height:36px; outline:1px solid var(--line);
}
.tree ul::before{ display:none; }

.box{
  position:relative; display:inline-block; min-width:132px;
  border-radius:8px; padding:10px 14px; font-size:13px; font-weight:600;
  border:1px solid var(--line); background:var(--leaf-bg);
}
.box.clickable{
  cursor:pointer;
  transition:box-shadow .15s, transform .1s, background-color .3s ease, border-color .3s ease, color .3s ease;
}
.box.clickable:hover{ box-shadow:0 2px 10px var(--shadow-1); transform:translateY(-1px); }

/* Sits between the Payment Letters Sent box and its chevron-flow row --
   plain block, no flex/centering trick needed since .info-icon is
   inline-flex and .tree's inherited text-align:center already centers any
   inline-level child. */
.tree-flow-note{ margin-top:6px; }

/* Payment Letters Sent's 7-box row reads as a flow (1-7), so each box gets a
   small ">" chevron in the gutter to its right, purely decorative -- see
   .chevron-flow on that <ul> in index.html. Standard two-border+rotate
   trick (border-top + border-right rotated 45deg meet as a right-pointing
   corner), so it needs no image asset and follows the theme's line color
   automatically in both light and dark mode. Nothing about .box itself
   changes -- this is a sibling-scoped ::after, so every existing feature
   (checkboxes, click-to-open, matrix children, the Open Timeline button)
   is untouched. */
.chevron-flow > li:not(:last-child) > .box::after{
  content:""; position:absolute; top:50%; right:-17px;
  width:9px; height:9px;
  border-top:2px solid var(--sub); border-right:2px solid var(--sub);
  transform:translateY(-50%) rotate(45deg);
  pointer-events:none;
}

.mismatch-badge{
  position:absolute; top:-10px; right:-10px; font-size:16px; line-height:1;
  cursor:help; filter:drop-shadow(0 1px 1px rgba(0,0,0,.35));
}

/* export checkbox, injected into every tree box by app.js */
.box-select{
  position:absolute; bottom:-8px; right:-8px; width:20px; height:20px;
  display:flex; align-items:center; justify-content:center;
  background:var(--surface); border:1px solid var(--line); border-radius:5px;
  box-shadow:0 1px 3px var(--shadow-1); cursor:pointer;
}
.box-select input{ width:14px; height:14px; margin:0; cursor:pointer; accent-color:var(--accent); }

/* expand/collapse toggle, injected into every tree box that has children --
   bottom-left is the one corner not already used by .serial (top-left),
   .mismatch-badge (top-right), or .box-select (bottom-right). */
.collapse-toggle{
  position:absolute; bottom:-8px; left:-8px; width:20px; height:20px; padding:0;
  display:flex; align-items:center; justify-content:center;
  background:var(--surface); border:1px solid var(--line); border-radius:50%;
  font-size:11px; line-height:1; color:var(--sub); cursor:pointer;
  box-shadow:0 1px 3px var(--shadow-1); font-family:inherit;
}
.collapse-toggle:hover{ background:var(--surface-alt); color:var(--ink); }

/* "Open Timeline" button -- one only, on Active Timeline for Submission
   (it covers both that box and In F&O Buffer Period, so a second button on
   the other box would be redundant). Absolutely positioned hanging off the
   box's edge (like the four corner badges above), rather than a sibling in
   the flow or a wrapper around .box, so it doesn't affect .box's own
   size/centering (the parent-to-child connector line is centered on
   .box's own width) or break the collapse-toggle injection's
   `:scope > .box` lookup. Opens a separate popup from the box's own
   click-to-matrix behavior -- its own click handler stops propagation so
   it never also triggers that. */
.open-timeline-btn{
  position:absolute; top:50%; right:100%; transform:translateY(-50%);
  margin-right:8px; white-space:nowrap;
  font-family:inherit; font-size:10px; font-weight:600; padding:5px 8px;
  border:1px solid var(--line); border-radius:6px; background:var(--surface); color:var(--ink);
  cursor:pointer;
}
.open-timeline-btn:hover{ background:var(--surface-alt); }

/* speech-bubble remark on a box or matrix cell -- deliberately always a dark
   chip regardless of theme (a fixed near-black in light mode reads as a
   strong callout; --chip-bg lightens it a step above the dark surface below
   so it doesn't just blend into the page in dark mode). */
.bubble{
  display:block; margin-top:8px; padding:5px 8px; font-size:10px; font-weight:600;
  background:var(--chip-bg); color:#fff; border-radius:6px; position:relative; text-align:center; line-height:1.3;
}
.bubble::before{
  content:""; position:absolute; top:-5px; left:50%; transform:translateX(-50%);
  border-left:5px solid transparent; border-right:5px solid transparent; border-bottom:5px solid var(--chip-bg);
}
.matrix-bubble{ margin-top:6px; }
.bubble.bubble-chase{ background:var(--invest); }
.bubble.bubble-chase::before{ border-bottom-color:var(--invest); }

.serial{
  position:absolute; top:-9px; left:-9px; width:20px; height:20px;
  border-radius:50%; background:var(--chip-bg); color:#fff;
  font-size:11px; font-weight:700; line-height:20px; text-align:center;
  box-shadow:0 1px 3px var(--shadow-1);
}
.box .name{ display:block; line-height:1.25; }
.box .count{
  display:inline-block; margin-top:4px; font-size:16px; font-weight:700;
}
/* Sits right after .count on the same line (see .count's own switch to
   inline-block above -- .name is still display:block, so this pair still
   starts on its own new line below the name, just no longer stacked
   vertically from each other). Populated generically by app.js's
   applyBoxes() off data-percent-of-total="<box_id>" -- blank whenever
   there's nothing to show (total is 0/missing), not "(0%)". */
.box .count-percent{
  display:inline-block; margin-top:4px; margin-left:4px;
  font-size:11px; font-weight:600; color:var(--sub);
}
.box .tag{ display:block; margin-top:2px; font-size:10px; font-weight:500; color:var(--sub); text-transform:uppercase; letter-spacing:.03em; }

.box.total{ border-color:var(--total); background:var(--total-bg); color:var(--total); }
.box.open{ border-color:var(--open); background:var(--open-bg); color:var(--open); }
.box.closed{ border-color:var(--closed); background:var(--closed-bg); color:var(--closed); }
.box.eligible{ border-color:var(--eligible); background:var(--eligible-bg); color:var(--eligible); }
.box.ineligible{ border-color:var(--ineligible); background:var(--ineligible-bg); color:var(--ineligible); }
.box.invest{ border-color:var(--invest); background:var(--invest-bg); color:var(--invest); }
.box.outreach{ border-color:var(--outreach); background:var(--outreach-bg); color:var(--outreach); }
.box.letters{ border-color:var(--letters); background:var(--letters-bg); color:var(--letters); }
.box.leaf{ font-weight:500; color:var(--ink); }
.box.leaf .count{ color:var(--ink); }

.note{
  max-width:760px; margin:40px auto 0; font-size:12px; color:var(--sub);
  background:var(--surface); border:1px solid var(--line); border-radius:8px; padding:14px 16px;
}

/* ---- export panel ---- */
.export-panel{
  width:95%; max-width:1400px; margin:28px auto 0; background:var(--surface); border:1px solid var(--line);
  border-radius:12px; padding:20px 24px; box-shadow:0 2px 10px rgba(0,0,0,.04);
}
.export-head{
  display:flex; align-items:flex-start; justify-content:space-between; gap:16px; flex-wrap:wrap;
}
.export-panel h2{ margin:0 0 2px; font-size:17px; }
.export-sub{ margin:0; font-size:12px; color:var(--sub); }
.export-mode-toggle{ display:flex; gap:8px; margin:14px 0; }
.export-actions{ display:flex; align-items:center; gap:10px; flex-wrap:wrap; }
.export-selected-count{ font-size:12px; font-weight:600; color:var(--sub); white-space:nowrap; }

/* Action item multi-select -- a button that opens a checkbox-list panel,
   instead of a native <select multiple> (no visible checkboxes, needs
   ctrl/cmd-click to pick more than one -- not discoverable enough for an
   internal tool most people use occasionally). */
.multi-select{ position:relative; display:inline-block; }
/* .multi-select's own display:inline-block ties the [hidden] attribute
   selector on specificity, and author CSS always beats the browser's
   default [hidden]{display:none} -- without this override, setting the
   hidden attribute (see app.js's setExportMode) stopped actually hiding
   the action-item dropdown in Box Controlled mode. */
.multi-select[hidden]{ display:none; }
.multi-select .btn-secondary{ min-width:220px; text-align:left; }
.multi-select-panel{
  position:absolute; top:calc(100% + 4px); left:0; z-index:40;
  min-width:280px; max-height:280px; overflow-y:auto;
  background:var(--surface); border:1px solid var(--line); border-radius:8px;
  box-shadow:0 8px 24px var(--shadow-2); padding:6px;
}
.multi-select-option{
  display:flex; align-items:center; gap:8px; padding:6px 8px; border-radius:6px;
  font-size:13px; color:var(--ink); cursor:pointer; white-space:nowrap;
}
.multi-select-option:hover{ background:var(--surface-alt); }
.multi-select-option input[type="checkbox"]{ flex-shrink:0; cursor:pointer; }
/* Shared "pressed" state for a segmented btn-secondary toggle (e.g. the
   export panel's Box Controlled/Action Item Based mode toggle). */
.btn-secondary.active{ background:var(--accent); border-color:var(--accent); color:#fff; }
.btn-secondary{
  font-family:inherit; font-size:13px; font-weight:600; padding:8px 14px;
  border:1px solid var(--line); border-radius:8px; background:var(--surface); color:var(--ink);
  cursor:pointer;
  transition:background-color .15s, border-color .3s ease, color .3s ease, box-shadow .3s ease;
}
.btn-secondary:hover{ background:var(--surface-alt); }
.btn-secondary:disabled{ opacity:.5; cursor:not-allowed; background:var(--surface); }
.export-status{ margin:14px 0 0; font-size:12px; color:var(--sub); }
.cooldown-timer{ font-size:12px; font-weight:600; color:var(--sub); white-space:nowrap; font-variant-numeric:tabular-nums; }
.export-status.error{ color:var(--ineligible); font-weight:600; }
.export-table-wrap{ margin-top:14px; max-height:480px; overflow:auto; border-radius:8px; }
.export-table-wrap .empty-state{ color:var(--sub); font-size:13px; padding:16px 4px; }
.export-table{ width:100%; border-collapse:collapse; font-size:13px; }
.export-table thead th{
  position:sticky; top:0; text-align:left; padding:9px 14px; background:var(--surface-alt);
  border-bottom:1px solid var(--line); color:var(--sub); font-weight:600; font-size:11px;
  text-transform:uppercase; letter-spacing:.03em;
}
.export-table tbody td{ padding:8px 14px; border-top:1px solid var(--line); }
.export-table tbody tr:hover{ background:var(--surface-alt); }
.export-more-notice{
  text-align:center; padding:12px 8px; font-size:12px; color:var(--sub);
  background:var(--surface-alt); border-top:1px solid var(--line);
}

/* ---- toast notifications ---- */
.toast-container{
  position:fixed; top:20px; right:20px; z-index:1100;
  display:flex; flex-direction:column; gap:10px; pointer-events:none;
  max-width:320px;
}
.toast{
  background:var(--chip-bg); color:#fff; font-size:13px; font-weight:500; line-height:1.4;
  padding:12px 16px; border-radius:8px; box-shadow:0 8px 24px var(--shadow-2);
  pointer-events:auto; animation:toast-in .2s ease-out;
}
.toast.toast-out{ animation:toast-out .2s ease-in forwards; }
@keyframes toast-in{ from{ opacity:0; transform:translateX(24px); } to{ opacity:1; transform:translateX(0); } }
@keyframes toast-out{ from{ opacity:1; transform:translateX(0); } to{ opacity:0; transform:translateX(24px); } }

/* ---- dark mode toggle ---- */
/* Fixed top-left -- top-right is already the toast container's corner. Both
   icons are always in the DOM, stacked on top of each other; only their
   opacity/rotation/scale differ by theme, so switching is a genuine
   crossfade+spin rather than an instant glyph swap. */
.theme-toggle{
  position:fixed; top:20px; left:20px; z-index:1100;
  width:40px; height:40px; padding:0; border-radius:50%;
  display:flex; align-items:center; justify-content:center;
  background:var(--surface); border:1px solid var(--line); color:var(--ink);
  cursor:pointer; box-shadow:0 2px 8px var(--shadow-1);
  transition:background-color .3s ease, border-color .3s ease, color .3s ease, box-shadow .3s ease, transform .2s ease;
}
.theme-toggle:hover{ transform:scale(1.08); }
.theme-toggle svg{
  position:absolute; width:20px; height:20px;
  transition:opacity .35s ease, transform .45s ease;
}
.theme-toggle .icon-sun{ opacity:1; transform:rotate(0deg) scale(1); }
.theme-toggle .icon-moon{ opacity:0; transform:rotate(90deg) scale(.4); }
html[data-theme="dark"] .theme-toggle .icon-sun{ opacity:0; transform:rotate(-90deg) scale(.4); }
html[data-theme="dark"] .theme-toggle .icon-moon{ opacity:1; transform:rotate(0deg) scale(1); }

/* ---- login page ---- */
.login-body{ min-height:100vh; display:flex; align-items:center; justify-content:center; }
.login-shell{ width:100%; max-width:420px; }
.login-card{
  background:var(--surface); border:1px solid var(--line); border-radius:16px;
  padding:44px 36px; text-align:center; box-shadow:0 12px 48px var(--shadow-1);
}
.login-title{ margin:0 0 8px; font-size:23px; font-weight:800; letter-spacing:-.01em; color:var(--ink); }
.login-title .brand{ color:var(--accent); }
.login-subtitle{ margin:0 0 28px; font-size:13px; color:var(--sub); line-height:1.5; }
.google-signin-container{ display:flex; justify-content:center; min-height:44px; }
.login-status{ margin:16px 0 0; font-size:12px; color:var(--sub); }
.login-status.error{ color:var(--ineligible); font-weight:600; }
.login-divider{
  display:flex; align-items:center; gap:12px; margin:24px 0 16px;
  color:var(--sub); font-size:11px; text-transform:uppercase; letter-spacing:.05em;
}
.login-divider::before, .login-divider::after{ content:""; flex:1; height:1px; background:var(--line); }
.login-local-btn{ width:100%; justify-content:center; }

/* ---- modal ---- */
.modal-overlay{
  position:fixed; inset:0; background:rgba(15,18,25,.55);
  display:flex; align-items:center; justify-content:center; z-index:1000; padding:20px;
}
.modal-overlay[hidden]{ display:none; }
.modal{
  background:var(--surface); border-radius:12px; width:min(640px, 100%); max-height:82vh;
  overflow:hidden; display:flex; flex-direction:column;
  box-shadow:0 12px 48px var(--shadow-2);
}
.modal.modal-wide{ width:min(900px, 96vw); }
.modal-head{
  display:flex; align-items:center; justify-content:space-between;
  padding:16px 20px; border-bottom:1px solid var(--line);
}
.modal-head h2{ font-size:15px; margin:0; }
.modal-close{
  border:none; background:none; font-size:22px; line-height:1; cursor:pointer;
  color:var(--sub); padding:0 4px;
}
.modal-close:hover{ color:var(--ink); }
.modal-body{ padding:16px 20px; overflow-y:auto; font-size:13px; }
.modal-body .empty-state{ color:var(--sub); font-size:13px; padding:8px 0; }

/* flat data tables rendered inside the modal (e.g. Closed Cases closures list) */
.modal-body table{ width:100%; border-collapse:collapse; font-size:12px; }
.modal-body table th, .modal-body table td{ text-align:left; padding:7px 14px; border-top:1px solid var(--line); }
.modal-body table th{ color:var(--sub); font-weight:600; background:var(--surface-alt); }

/* usage guide popup */
.usage-guide h3{ margin:16px 0 6px; font-size:13px; color:var(--ink); }
.usage-guide h3:first-child{ margin-top:0; }
.usage-guide ul{ margin:0 0 4px; padding-left:20px; }
.usage-guide li{ margin:4px 0; color:var(--sub); line-height:1.5; }
.usage-guide strong{ color:var(--ink); }
.modal-body table td.reason{ color:var(--closed); }

/* Shared "BD gradient" popup component -- opened by clicking a box (see
   app.js's renderInvestigationAgingView/renderOutreachBdLeftView), same
   .matrix-wrap/.matrix-total shell as the offer/payment matrix modals.
   Each segment's fill color is fixed by position (a severity/urgency
   gradient independent of the actual counts, which are the numbers printed
   inside each segment) via a color modifier class (see
   .bd-gradient-fill-ok below; the base color is set per-widget). Horizontally
   scrollable (like .matrix-wrap) rather than compressed, so many segments
   stay legible at a readable size instead of being squeezed to fit. */
.bd-gradient-scroll{ overflow-x:auto; padding-bottom:4px; }
.bd-gradient-slider{ display:flex; gap:3px; width:max-content; }
.bd-gradient-segment{
  position:relative; width:34px; height:56px; flex-shrink:0;
  border-radius:6px; overflow:hidden;
}
.bd-gradient-segment.bd-gradient-boundary{
  box-shadow:inset 2px 0 0 var(--ink);
}
.bd-gradient-fill{ position:absolute; inset:0; background:var(--ineligible); }
/* Modifiers for the parts of a gradient that aren't the default red --
   Investigation's "still compliant" (0-5 BD) zone, Outreach Sent's single
   all-blue gradient (there's no compliant/non-compliant split there, just
   "more or fewer business days left"), and the F&O Due Date Timeline's
   "already overdue" (negative bd_to_due) zone. */
.bd-gradient-fill.bd-gradient-fill-ok{ background:var(--eligible); }
.bd-gradient-fill.bd-gradient-fill-blue{ background:var(--open); }
.bd-gradient-fill.bd-gradient-fill-yellow{ background:var(--invest); }
.bd-gradient-count{
  position:relative; z-index:1; display:flex; align-items:center; justify-content:center;
  height:100%; font-size:14px; font-weight:700; color:var(--ink);
}
.bd-gradient-labels{
  display:flex; justify-content:space-between; margin-top:8px;
  font-size:11px; font-weight:600; color:var(--sub);
}
.bd-gradient-labels-mid{ text-align:center; flex:1; }
/* Outreach Sent's right-edge label -- 0 BD is the queue's front, the next
   batch an outreach reprocessing run picks up, so it gets an explicit
   arrow+caption instead of leaving that implicit in a bare "0 BD". */
.bd-gradient-reprocess-label{ color:var(--open); font-weight:700; }
.bd-gradient-reprocess-arrow{ font-weight:700; }
/* Fluid variant -- for a small, fixed number of segments (Outreach Sent's
   6) that should stretch to fill the modal end-to-end, unlike the default
   fixed-width-plus-horizontal-scroll shape (Investigation's 31 segments),
   which only makes sense once there are enough of them that shrinking all
   to fit would make the numbers illegible. Without this, .bd-gradient-labels
   (which spans the modal's full width via space-between) visibly
   disagreed with the segments' own much narrower width-content sizing. */
.bd-gradient-slider.bd-gradient-slider-fluid{ width:100%; }
.bd-gradient-slider.bd-gradient-slider-fluid .bd-gradient-segment{
  flex:1; width:auto; min-width:0; height:72px;
}
/* F&O Due Date Timeline wraps each segment with a tick label underneath
   (see .bd-gradient-tick) -- the flex-fill target shifts from the segment
   itself to this wrapper so the label stays put below its own segment
   instead of stretching independently. */
.bd-gradient-col{ position:relative; display:flex; flex-direction:column; align-items:stretch; flex-shrink:0; }
.bd-gradient-slider.bd-gradient-slider-fluid .bd-gradient-col{ flex:1; min-width:0; }
.bd-gradient-slider.bd-gradient-slider-fluid .bd-gradient-col .bd-gradient-segment{
  flex:none; width:auto; min-width:0; height:72px;
}
.bd-gradient-tick{
  margin-top:3px; text-align:center; font-size:10px; font-weight:600; color:var(--sub);
}
/* Outreach Sent popup only -- a heading above the strip naming what the BD
   count actually means (there's no other title on this view besides the
   bare "Total:" line), and a ">" connector in the gap between each pair of
   day-blocks so the strip reads as a countdown sequence. Same border+rotate
   chevron technique as .chevron-flow in the tree (see that rule's own
   comment) -- widens the shared .bd-gradient-slider's default 3px gap
   just enough to fit it, scoped to this modifier class so Investigation's
   31-segment strip and the F&O Due Date Timeline's fluid strip (which
   don't get this class) keep their own tighter spacing. */
.bd-gradient-heading{
  margin:2px 0 10px; font-size:12px; font-weight:700; color:var(--sub); text-align:center;
}
.bd-gradient-slider.bd-gradient-slider-chevron{ gap:22px; }
.bd-gradient-slider-chevron > .bd-gradient-col:not(:last-child)::after{
  content:""; position:absolute; top:36px; right:-15px;
  width:9px; height:9px;
  border-top:2px solid var(--sub); border-right:2px solid var(--sub);
  transform:translateY(-50%) rotate(45deg);
  pointer-events:none;
}

/* IP x NIP offer/payment matrix (Offers & Payments Received view) */
.matrix-wrap{ overflow-x:auto; }
.matrix-total{
  text-align:center; font-size:15px; font-weight:700; color:var(--ink);
  margin:0 0 14px;
}
.matrix-table{ border-collapse:collapse; min-width:700px; width:100%; }
.matrix-table th, .matrix-table td{ border:1px solid var(--line); padding:10px; vertical-align:middle; }
.matrix-corner{ background:var(--surface-alt); min-width:130px; text-align:left; font-size:11px; color:var(--sub); }
.matrix-corner .corner-ip{ display:block; font-weight:600; }
.matrix-corner .corner-nip{ display:block; margin-top:14px; text-align:right; font-weight:600; }
.matrix-axis-head{ background:var(--surface-alt); }
.axis-badges{ display:flex; flex-direction:column; align-items:center; gap:4px; }
.axis-party{ font-size:10px; font-weight:700; color:var(--sub); text-transform:uppercase; letter-spacing:.03em; }
.badge-row{ display:flex; gap:4px; }
.badge{ font-size:10px; font-weight:600; padding:2px 6px; border-radius:10px; white-space:nowrap; }
.badge-no{ background:var(--surface-alt); color:var(--sub); }
.badge-yes{ background:var(--eligible-bg); color:var(--eligible); }
.matrix-cell{ position:relative; text-align:center; min-width:120px; }
/* Table cells sit flush against each other (no gap like the tree boxes have)
   and are densely packed with outcome/count/bubble text, so the default
   .box-select's absolute bottom-right overlay would spill into the row below
   and cover cell content. Flow it in normally instead, as one more centered
   line under everything else in the cell. */
.matrix-cell .box-select{ position:static; margin:8px auto 0; box-shadow:none; border-color:var(--line); }
.matrix-outcome{ font-size:11px; font-weight:600; line-height:1.3; }
.matrix-count{ margin-top:4px; font-size:15px; font-weight:700; }
.matrix-cell.outcome-fees{ background:var(--surface-alt); color:var(--sub); }
.matrix-cell.outcome-admin{ background:var(--invest-bg); color:var(--invest); }
.matrix-cell.outcome-nip{ background:var(--open-bg); color:var(--open); }
.matrix-cell.outcome-ip{ background:var(--eligible-bg); color:var(--eligible); }
.matrix-cell.outcome-arb{ background:var(--outreach-bg); color:var(--outreach); border:2px dashed var(--outreach); }
