/* Ascent Target client portal: dark navy theme with orange accents (matches ascent-target.com), Desktop first.
   This is also the DEFAULT/dark theme's variable values — every admin/client can switch to a lighter theme from
   their own Account page (see views.accountPage), which sets data-theme="light" on <body> (see layout()) and
   picks up the override block below instead. The header/nav bar and the sign-in screens keep this fixed dark
   navy look in both themes (brand chrome, not a content surface), so only vars used by content below the
   header ever change. */
:root{
  --navy:#16213C;--navy-deep:#0F1830;--orange:#FF6B0E;--orange-hi:#FF8236;--orange-soft:rgba(255,107,14,.14);
  --bg:#16213C;--card:#1E2B4D;--card-2:#263660;--line:rgba(255,255,255,.12);--line-2:rgba(255,255,255,.22);
  --ink:#FFFFFF;--text:#E4EAF6;--muted:#A6B3CF;--link:#FF8A3D;--placeholder:#6F7FA3;
  --field:#131D36;--field-line:rgba(255,255,255,.24);
  --red:#FF8B80;--red-bg:rgba(255,107,96,.14);--green:#4ADE80;--green-bg:rgba(74,222,128,.13);--blue:#8FB4FF;--blue-bg:rgba(143,180,255,.14);
  --purple:#B8B0FF;--purple-bg:rgba(160,150,255,.16);
  --shadow:0 10px 30px rgba(3,8,22,.35);
  --map-bg:#3A4258; /* HQ map backdrop colour, visible only for a moment while the dark basemap tiles load in */
  /* Generic "lighten the surface a bit" tints used for hover/empty/stacked states (buttons, table row hover,
     segmented controls, the swipe deck) — named by their dark-theme opacity so call sites read naturally;
     the light theme below redefines each as a matching dark-on-white tint instead of a lighten-white one. */
  --overlay-04:rgba(255,255,255,.04);--overlay-07:rgba(255,255,255,.07);--overlay-08:rgba(255,255,255,.08);
  --overlay-10:rgba(255,255,255,.1);--overlay-16:rgba(255,255,255,.16);--border-emphasis:rgba(255,255,255,.4);
  /* Swipe deck: the two cards stacked behind the top one (see .dcard.pos-1/pos-2) — a shade darker than
     --card-2 in dark theme; the light theme below uses a shade darker than its own light --card-2 instead. */
  --deck-2:#1C2A4C;--deck-3:#182444;
  /* Conversion funnel: one-hue ordinal ramp (position in a sequence, not identity), brand orange at the top
     (widest/earliest step) deepening toward the bottom (narrowest/latest) — reads as depth, stays orange throughout */
  --funnel-1:#FF6B0E;--funnel-2:#F56612;--funnel-3:#EA6017;--funnel-4:#DE5A1C;--funnel-5:#D05421;--funnel-6:#C14D26;--funnel-7:#B1462B;--funnel-8:#A03F30;
}
/* Light theme override: same component rules throughout this file (everything routes through the variables
   above), just a lighter palette for the vars that represent page/card surfaces and body text. --navy,
   --navy-deep, --orange/-hi/-soft and the funnel ramp are deliberately left out here — they're the fixed brand
   colours used by the header/nav/accents in both themes. Several colours below (--ink, --muted, --line,
   --line-2, --field-line, --link, --red, --placeholder) reuse the same light palette already shipped for the
   sign-in card (see body.auth .narrow further down), so both stay visually consistent. */
body[data-theme="light"]{
  --bg:#F3F5FA;--card:#FFFFFF;--card-2:#EEF1F7;--line:#E2E6EF;--line-2:#B9C2D2;
  --ink:#16213C;--text:#2B3652;--muted:#5D677C;--link:#C94E00;--placeholder:#97A1B5;
  --field:#FFFFFF;--field-line:#C7CEDB;
  --red:#B3261E;--red-bg:rgba(179,38,30,.10);--green:#1F9D4C;--green-bg:rgba(31,157,76,.12);--blue:#2F6BFF;--blue-bg:rgba(47,107,255,.10);
  --purple:#6B5CE0;--purple-bg:rgba(107,92,224,.12);
  --shadow:0 10px 30px rgba(16,33,71,.1);
  --map-bg:#E1E6EF;
  --overlay-04:rgba(22,33,60,.035);--overlay-07:rgba(22,33,60,.055);--overlay-08:rgba(22,33,60,.065);
  --overlay-10:rgba(22,33,60,.08);--overlay-16:rgba(22,33,60,.13);--border-emphasis:rgba(22,33,60,.35);
  --deck-2:#E9ECF3;--deck-3:#DEE3ED;
}
/* The HQ map's basemap tiles are inverted to look dark in dark theme (see .leaflet-tile-pane below) — in light
   theme the tiles are already light-coloured, so that filter is switched off instead of inverted again. */
body[data-theme="light"] .leaflet-tile-pane{filter:none}
*{box-sizing:border-box}[hidden]{display:none!important}
body{margin:0;font:16px/1.55 "DM Sans",system-ui,-apple-system,"Segoe UI",Roboto,sans-serif;color:var(--text);background:var(--bg);-webkit-font-smoothing:antialiased;min-height:100vh}
a{color:var(--link)}a:hover{color:var(--orange-hi)}
.muted{color:var(--muted)}.error{color:var(--red)}
h1{font-size:30px;line-height:1.2;margin:0 0 6px;font-weight:700;letter-spacing:-.01em;color:var(--ink)}h2{font-size:19px;margin:0 0 12px;font-weight:700;color:var(--ink)}h3{font-size:16px;margin:0 0 6px;font-weight:700;color:var(--ink)}

/* header */
header{background:var(--navy-deep);color:#fff;display:flex;align-items:center;gap:36px;padding:0 32px;min-height:64px;flex-wrap:wrap;border-bottom:2px solid var(--orange)}
.brand{display:flex;align-items:center;gap:12px;text-decoration:none}.brand img{height:20px;width:auto;max-width:none;display:block}
.portal{color:var(--orange);font-size:13px;font-weight:700;letter-spacing:.22em;text-transform:uppercase;line-height:1;padding-top:1px}
nav{display:flex;align-items:center;gap:4px;flex:1;flex-wrap:wrap}
nav a{color:#C4CFE6;text-decoration:none;font-size:15px;font-weight:500;padding:8px 14px;border-radius:8px}
nav a:hover{color:#fff;background:rgba(255,255,255,.07)}nav a.on{color:#fff;background:rgba(255,255,255,.1);box-shadow:inset 0 -2px 0 var(--orange)}
nav .spacer{flex:1}nav form{margin:0}
/* The name drop-down (top right): Account & theme, Team, Activity, Settings, What's new, Sign out. */
.usermenu{position:relative}
.usermenu summary{list-style:none;cursor:pointer;display:flex;align-items:center;gap:8px;color:#C4CFE6;font-size:15px;font-weight:500;padding:8px 14px;border-radius:8px;user-select:none}
.usermenu summary::-webkit-details-marker{display:none}
.usermenu summary:hover,.usermenu[open] summary{color:#fff;background:rgba(255,255,255,.07)}
.usermenu summary.on{color:#fff;box-shadow:inset 0 -2px 0 var(--orange)}
.usermenu summary:focus-visible{outline:2px solid var(--orange);outline-offset:2px}
.who{max-width:220px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.caret{font-size:11px;opacity:.8}
.usermenu-list{position:absolute;right:0;top:calc(100% + 6px);min-width:220px;background:var(--navy-deep);border:1px solid rgba(255,255,255,.12);border-radius:12px;padding:6px;box-shadow:0 12px 32px rgba(0,0,0,.35);display:flex;flex-direction:column;gap:2px;z-index:50}
.usermenu-list a{display:block;padding:9px 12px}.usermenu-list a .muted{color:#8FA0C2;font-size:13px;margin-left:4px}
.usermenu-list form{border-top:1px solid rgba(255,255,255,.1);margin-top:4px;padding-top:4px}
.usermenu-list button.link{width:100%;text-align:left;padding:9px 12px;color:#C4CFE6;border-radius:8px}.usermenu-list button.link:hover{color:#fff;background:rgba(255,255,255,.07)}
/* Mid-width screens (e.g. a 13" laptop): tighten spacing rather than let the bar wrap onto a second line. */
@media (max-width:1600px){header{gap:20px;padding:0 24px}nav a{padding:8px 10px}}
@media (max-width:1400px) and (min-width:901px){header{gap:14px;padding:0 16px}nav{gap:0}nav a{padding:7px 8px;font-size:14px}}
.badge{background:var(--orange);color:var(--navy);border-radius:10px;padding:1px 8px;font-size:12px;font-weight:700}
main{max-width:1240px;margin:0 auto;padding:36px 32px 72px}
footer{text-align:center;color:var(--muted);font-size:13px;padding:24px}
.flash{background:var(--orange-soft);border:1px solid rgba(255,107,14,.45);color:var(--ink);padding:12px 16px;border-radius:10px;margin-bottom:22px}

/* "Preview as this client" banner (see auth.setPreviewClient): a full-width strip directly under the header,
   present on every page for as long as an Ascent admin is viewing a client's own Home/Targets/KPI pages instead
   of the admin area. Same dark tone as the header so it reads as one continuous top bar, not a one-off message
   like .flash — this is a mode, not a notification, so it needs to stay visibly "on" the whole time. */
.preview-bar{background:var(--navy-deep);border-bottom:2px solid var(--orange);color:#fff;display:flex;align-items:center;justify-content:center;gap:14px;flex-wrap:wrap;padding:10px 32px;font-size:14px}
.preview-bar b{color:var(--orange-hi)}
.preview-bar form{margin:0}
.preview-bar button{padding:6px 16px;font-size:13px}

/* cards and forms */
.card{background:var(--card);border:1px solid var(--line);border-radius:14px;padding:24px;margin:0 0 22px;box-shadow:var(--shadow)}
label{display:block;margin:0 0 14px;font-size:14px;color:var(--muted);font-weight:500}
/* :not([type=radio]) added alongside the existing :not([type=checkbox]) for the new Account theme picker (see
   views.accountPage) — the first radio buttons anywhere in this app; without it they'd pick up display:block;
   width:100% meant for text/email/etc fields, which stretches a radio to fill the row instead of a small dot
   sitting next to its label. */
input:not([type=checkbox]):not([type=radio]),textarea,select{display:block;width:100%;margin-top:6px;padding:10px 12px;font:inherit;color:var(--ink);border:1px solid var(--field-line);border-radius:9px;background:var(--field)}
input::placeholder,textarea::placeholder{color:var(--placeholder)}
input[type=checkbox],input[type=radio]{accent-color:var(--orange)}
input:focus,textarea:focus,select:focus,button:focus-visible,a:focus-visible{outline:3px solid rgba(255,107,14,.5);outline-offset:1px}
textarea{resize:vertical}.check{display:flex;gap:10px;align-items:flex-start;color:var(--text);font-size:15px;font-weight:400}.check input{margin-top:5px}
fieldset{border:1px solid var(--line);border-radius:9px;margin:0 0 12px}legend{font-size:14px;color:var(--muted)}
button,.button{font:inherit;font-weight:600;padding:10px 18px;border-radius:9px;border:1px solid var(--line-2);background:transparent;color:var(--ink);cursor:pointer;text-decoration:none;display:inline-block;line-height:1.3;transition:background .15s,border-color .15s}
button:hover,.button:hover{border-color:var(--ink);color:var(--ink)}
button.primary,.button.primary{background:var(--orange);border-color:var(--orange);color:var(--navy)}
button.primary:hover,.button.primary:hover{background:var(--orange-hi);border-color:var(--orange-hi);color:var(--navy)}
.button{background:var(--overlay-08);border-color:var(--line-2);color:var(--ink)}.button:hover{background:var(--overlay-16);color:var(--ink)}
button.success{background:#1F9D4C;border-color:#1F9D4C;color:#fff}button.success:hover{background:#26b559;border-color:#26b559}
button.success:disabled{background:transparent;border-color:var(--line);color:var(--muted);cursor:not-allowed}
button.danger{background:transparent;border-color:var(--red);color:var(--red)}
/* Fixed independent of --red on purpose: --red itself flips between a light pastel (dark theme, reads against
   navy) and a dark saturated red (light theme, reads against white) — but this hover state is a SOLID fill with
   its own white text, which needs a mid-dark red regardless of theme, not whichever shade --red currently is. */
button.danger:hover{background:#C0392B;border-color:#C0392B;color:#fff}
/* Per-row Approve/Reject in a table cell (e.g. the Contacts queue) — smaller than the full-size decision
   buttons used elsewhere, and stacked with a visible gap so they never read as one fused control. */
.rowactions{display:flex;flex-direction:column;gap:8px;align-items:flex-start}
.rowactions button{padding:6px 14px;font-size:13px}
/* Distinct from the small nav-count .badge above — a wider uppercase pill used inline next to a name. */
.tag-priority{display:inline-block;border-radius:999px;padding:2px 10px;font-size:11px;font-weight:700;letter-spacing:.02em;text-transform:uppercase;margin-top:6px;background:#eceff3;color:#4a5568}
.tag-priority.high{background:#fde2e2;color:#9b1c1c}
.tag-priority.medium{background:#fdf0d5;color:#8a5a00}
.tag-priority.none{background:transparent;border:1px dashed #9aa5b1;color:#9aa5b1}
.tag-rec{display:inline-block;border-radius:999px;padding:2px 10px;font-size:11px;font-weight:700;letter-spacing:.02em;text-transform:uppercase;margin-left:8px;vertical-align:middle;background:var(--orange);color:var(--navy)}
button.link{border:0;background:none;color:var(--muted);padding:8px 14px;font-weight:500;font-size:15px}button.link:hover{color:var(--ink)}
.card button.link{color:var(--link);padding:0}
table{width:100%;border-collapse:collapse}th,td{text-align:left;padding:12px 12px;border-bottom:1px solid var(--line);vertical-align:top}
th{font-size:12px;color:var(--muted);font-weight:700;letter-spacing:.06em;text-transform:uppercase}
tbody tr:last-child td{border-bottom:0}
.small{font-size:14px}tr.overdue td{background:rgba(255,107,96,.1)}.inline{display:flex;gap:8px;flex-wrap:wrap}.inline>*{width:auto;flex:1;min-width:140px}
.add-field{border-top:1px solid var(--line);margin:18px 0;padding-top:18px}.add-field h3{margin-bottom:4px}.add-field>p.muted{margin-top:0}
/* Contacts page: a target's candidates are already grouped visually by sharing one cell for target/client/found
   (see adminContacts), but with several rows per target the ordinary 1px row border wasn't enough to read as a
   break between two different targets (e.g. Dyke Yaxley vs Wellden Turnbull looked like one amalgamated block).
   The first row of each group after the first gets a distinctly heavier, brighter top border instead of the
   thin default one, so the eye catches the boundary at a glance. */
.contacts-table tbody tr.group-start:not(:first-child) td{border-top:3px solid var(--orange);padding-top:20px}
.reorder-cell{white-space:nowrap;width:1%}.reorder-btn{font-size:17px;padding:2px 6px!important;line-height:1}.reorder-btn-disabled{display:inline-block;padding:2px 6px;color:var(--muted);opacity:.35}
.msg{border-left:3px solid var(--line-2);padding:6px 12px;margin:0 0 12px}.msg.team{border-color:var(--orange);background:var(--orange-soft)}.meta{font-size:13px;color:var(--muted)}
code.key{font-size:18px;letter-spacing:.06em;background:var(--field);padding:2px 8px;border-radius:6px;color:var(--ink)}pre{white-space:pre-wrap;background:var(--field);padding:10px;border-radius:8px}
#geocheck .geo-results{margin:0 0 14px;display:flex;flex-direction:column;gap:6px}#geocheck .geo-result{width:100%;text-align:left;font-weight:400;font-size:14px;padding:8px 12px}
.card.admin{border-color:rgba(255,107,96,.4)}.admin-note{margin:0 0 16px}

/* sign-in screens: white card on the navy background */
body.auth{background-color:var(--navy);background-image:radial-gradient(1000px 500px at 85% -10%,rgba(47,107,255,.35),transparent 60%),radial-gradient(700px 400px at -10% 110%,rgba(255,107,14,.18),transparent 60%);min-height:100vh}
body.auth header{background:none;border:0;justify-content:center;padding-top:44px}body.auth .brand img{height:30px}body.auth .portal{font-size:17px}
body.auth main{padding-top:12px}body.auth footer{color:#8093b5}
.narrow{max-width:460px;margin:24px auto}
body.auth .narrow{--card:#fff;--ink:#16213C;--text:#16213C;--muted:#5d677c;--line:#e2e6ef;--line-2:#b9c2d2;--field:#fff;--field-line:#c7cedb;--link:#C94E00;--red:#b3261e;--shadow:none;box-shadow:0 20px 50px rgba(0,0,0,.35);border:0;padding:34px;color:var(--text)}
body.auth .narrow .button{background:var(--navy);color:#fff;border-color:var(--navy)}
body.auth .narrow button:not(.primary):not(.success):not(.danger){color:#16213C}
body.auth .narrow button:hover{border-color:var(--navy)}
body.auth .narrow code.key{background:#eef1f7;color:#16213C}body.auth .narrow input::placeholder{color:#97a1b5}
body.auth .narrow button.primary{width:100%;margin-top:4px}
.tagline{color:var(--orange);font-size:12px;font-weight:700;letter-spacing:.16em;text-transform:uppercase;margin:0 0 8px}

/* dashboard */
.pagehead{display:flex;justify-content:space-between;align-items:flex-end;gap:16px;flex-wrap:wrap;margin-bottom:24px}
.pagehead p{margin:0}
/* A client's own logo, pasted in by an Ascent admin (see adminClient), shown next to their name on Home —
   sits directly on the navy background, no white chip behind it, so a transparent-background logo blends in. */
.client-heading{display:flex;align-items:center;gap:14px}
.client-logo{height:40px;width:auto;max-width:180px;object-fit:contain}
/* The admin's upload preview is shown on the same navy the real Home page uses, so what they see while
   choosing a logo is what a client will actually see (not a white-card preview that hides poor contrast). */
.logo-preview{margin-bottom:14px;background:var(--bg);border-radius:8px;padding:10px 14px;display:inline-block}
.logo-preview img{height:56px;width:auto;max-width:240px;object-fit:contain}
.callout{display:flex;align-items:center;justify-content:space-between;gap:20px;flex-wrap:wrap;background:linear-gradient(90deg,var(--orange-soft),rgba(255,107,14,.03));border:1px solid rgba(255,107,14,.4);border-left:5px solid var(--orange);color:var(--ink);border-radius:14px;padding:18px 24px;margin-bottom:24px}
.callout b{font-size:19px}.callout span{color:var(--muted)}.callout .button{background:var(--orange);border-color:var(--orange);color:var(--navy)}.callout .button:hover{background:var(--orange-hi);border-color:var(--orange-hi);color:var(--navy)}
.searchbar-wrap{position:relative}
.searchbar{display:flex;gap:8px;align-items:center}
.searchbar input[type=search]{margin:0;width:220px;background:var(--field)}
.suggest{position:absolute;top:calc(100% + 4px);left:0;width:220px;background:var(--card);border:1px solid var(--line-2);border-radius:10px;box-shadow:0 14px 36px rgba(3,8,22,.5);overflow:hidden;z-index:30}
.suggest a{display:block;padding:8px 12px;color:var(--text);text-decoration:none;font-size:14px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.suggest a:hover,.suggest a.on{background:var(--orange);color:var(--navy)}
.toolbar{display:flex;justify-content:space-between;align-items:center;gap:12px;flex-wrap:wrap;margin-bottom:20px}
/* Groups the view switcher (.seg) and the "Download CSV" link together on the toolbar's right side, so the
   toolbar's own space-between only ever splits two things (chips vs. this group) instead of spreading three
   items apart with an oddly wide gap around the middle one. */
.toolbar-right{display:flex;align-items:center;gap:10px;flex-wrap:wrap}
/* "Download to Excel": small and quiet on purpose — muted text and a hairline, not a full button. */
.download-link{display:inline-flex;align-items:center;gap:6px;font-size:13px;font-weight:600;color:var(--muted);text-decoration:none;padding:5px 10px;border:1px solid var(--line);border-radius:8px;white-space:nowrap}
.download-link:hover{color:var(--ink);border-color:var(--line-2)}
.download-link svg{flex:none}
.chips{display:flex;flex-wrap:wrap;gap:8px}
.chip{background:transparent;border:1px solid var(--line-2);border-radius:999px;padding:6px 14px;text-decoration:none;color:var(--text);font-size:14px;font-weight:500}
.chip:hover{border-color:var(--ink);color:var(--ink)}.chip.on{background:var(--orange);color:var(--navy);border-color:var(--orange)}.chip b{margin-left:5px;opacity:.75}
/* Labels: a target's own tags (see portal.addLabel). Pills on cards/table/target page; a smaller second chip row
   under the status chips to filter by one. All colours from theme variables, so they work in dark and light. */
.labelbar{display:flex;flex-wrap:wrap;align-items:center;gap:6px;margin:-8px 0 20px}
.labelbar-title{font-size:12px;font-weight:700;letter-spacing:.06em;text-transform:uppercase;color:var(--muted);margin-right:4px}
.chip.lbl{padding:3px 11px;font-size:13px}
.tags{display:flex;flex-wrap:wrap;gap:5px;margin:2px 0 8px}
td .tags{margin:0}
.tag{display:inline-block;border:1px solid var(--line-2);background:var(--overlay-07);color:var(--text);border-radius:6px;padding:1px 8px;font-size:12px;font-weight:600;line-height:1.6;text-decoration:none;white-space:nowrap}
a.tag:hover{border-color:var(--orange);color:var(--ink)}
.label-list{display:flex;flex-wrap:wrap;gap:6px;margin-bottom:12px}
.label-chip{display:inline-flex;align-items:center;margin:0}
.label-chip .tag{border-radius:6px 0 0 6px;border-right:0}
.tag-x{border:1px solid var(--line-2);background:var(--overlay-07);color:var(--muted);border-radius:0 6px 6px 0;padding:1px 7px;font-size:13px;line-height:1.6;min-height:0;width:auto;margin:0;cursor:pointer}
.tag-x:hover{color:var(--ink);border-color:var(--orange)}
.label-add{display:flex;gap:8px;align-items:stretch;margin:0 0 8px}
.label-add input{flex:1;min-width:0;margin:0}
.label-add button{margin:0;width:auto}
.seg{display:inline-flex;border:1px solid var(--line-2);border-radius:9px;overflow:hidden}
/* CSS-only tooltip (no inline scripts under our CSP) — dotted underline, reveals data-tip on hover/keyboard focus. */
.tip{position:relative;cursor:help;border-bottom:1px dotted var(--muted)}
.tip:hover::after,.tip:focus::after{content:attr(data-tip);position:absolute;left:0;bottom:100%;margin-bottom:6px;background:#111;color:#fff;padding:8px 10px;border-radius:6px;font-size:12px;line-height:1.4;width:260px;white-space:normal;z-index:20;box-shadow:0 4px 16px rgba(0,0,0,.35)}
.tip:hover::before,.tip:focus::before{content:"";position:absolute;left:14px;bottom:100%;margin-bottom:1px;border:5px solid transparent;border-top-color:#111;z-index:20}
.seg a{padding:7px 16px;text-decoration:none;color:var(--text);font-size:14px;font-weight:600}.seg a:hover{background:var(--overlay-07)}.seg a.on{background:var(--orange);color:var(--navy)}
.grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(360px,1fr));gap:22px}
.target{margin:0;display:flex;flex-direction:column;gap:14px;padding:22px;border-top:4px solid var(--line-2)}
.target.needs{border-top-color:var(--orange)}
.target h2{margin:0;font-size:19px;line-height:1.25}.target h2 a{color:var(--ink);text-decoration:none}.target h2 a:hover{color:var(--orange)}
.row{display:flex;justify-content:space-between;align-items:flex-start;gap:12px}
.desc{color:var(--muted);font-size:14.5px;margin:0;display:-webkit-box;-webkit-line-clamp:3;-webkit-box-orient:vertical;overflow:hidden}
/* Dense financial-data-table styling for target data — small labels, hairline rules instead of individual
   boxes, figures right-aligned like a term sheet — but in the app's own navy/orange brand and DM Sans
   typeface throughout (an earlier pass tried a literal FT look: cream paper background, a serif typeface —
   Jack flagged that as off-brand, so this keeps the tightened/dense structure but stays on-brand). .metrics
   (grid card / swipe deck) and .hero-facts (target detail page) share this. On the detail page, facts() in
   views.ts groups fields into three sections instead of one uniform list of full-width rows (which read as
   too spread out): Website gets its own row (.metric-link); short facts (Employees, Financials, Revenue,
   EBITDA, Country, ...) are packed into .metric-chips, a wrapping row of compact label-value pairs, so
   related short facts sit together on the same line instead of each spanning the full width; Description
   (.metric-longtext) goes underneath everything else. */
.metrics,.hero-facts{display:block;margin:0;background:var(--field);border:1px solid var(--line);border-radius:8px;padding:0 14px}
.hero-facts>*:last-child{border-bottom:none}
.metric{display:flex;align-items:baseline;justify-content:space-between;gap:14px;padding:8px 0;border-bottom:1px solid var(--line)}
.metric:last-child{border-bottom:none}
.metric dt{flex-shrink:0;font-size:11px;font-weight:700;color:var(--muted);letter-spacing:.06em;text-transform:uppercase}
.metric dd{margin:0;font-weight:600;font-size:14.5px;color:var(--ink);text-align:right;overflow-wrap:anywhere}
.metric dd .muted{font-weight:400;font-size:13px}
.metric.metric-longtext,.metric.metric-link{flex-direction:column;align-items:flex-start}
.metric.metric-longtext dd,.metric.metric-link dd{text-align:left;font-weight:400;font-size:13.5px;line-height:1.55;white-space:pre-wrap}
/* A wrapping row of compact chips — label and value sit close together (gap:5px, not space-between across
   the full width), and several chips flow onto the same line whenever they fit, e.g. Financials/Revenue/
   EBITDA. No individual chip has its own border; one hairline runs under the whole row instead. */
.metric-chips{display:flex;flex-wrap:wrap;column-gap:26px;row-gap:9px;padding:9px 0;border-bottom:1px solid var(--line)}
.metric-chips .metric{display:inline-flex;flex:0 0 auto;align-items:baseline;gap:5px;padding:0;border-bottom:none}
.metric-chips .metric dd{text-align:left}
.card-foot{display:flex;justify-content:space-between;align-items:center;gap:10px;margin-top:auto}.card-foot .site{font-size:14px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.tablecard{padding:8px 14px;overflow-x:auto}.tablecard th a{color:var(--muted);text-decoration:none}.tablecard th a:hover{color:var(--ink)}.tablecard th a.on{color:var(--orange)}
.tablecard td{vertical-align:middle}.tablecard td.num{white-space:nowrap;color:var(--ink)}.tablecard tr.needs td:first-child{box-shadow:inset 4px 0 0 var(--orange)}
.tablecard tbody tr:hover td{background:var(--overlay-04)}
.tablecard td a.name{font-weight:700;color:var(--ink);text-decoration:none}.tablecard td a.name:hover{color:var(--orange)}
.tablecard td.site{max-width:220px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.empty{background:var(--overlay-04);border:1px dashed var(--line-2);border-radius:14px;padding:40px;text-align:center}


/* A card heading paired with a small (i) info toggle, e.g. on the KPI page — keeps the explanatory copy out
   of the way until someone actually wants it, instead of a permanent paragraph under every heading. */
.card-head{display:flex;align-items:center;gap:8px;margin-bottom:12px}.card-head h2{margin:0}
/* The (i) toggle itself: a native <details>/<summary>, not a hover-only tooltip — hover has no equivalent on
   a touchscreen, so this opens identically on tap (mobile) and click (desktop), and needs no script under
   our CSP. */
.info{position:relative;display:inline-flex}
.info>summary{list-style:none;display:flex;align-items:center;justify-content:center;width:20px;height:20px;border-radius:50%;background:var(--card-2);border:1px solid var(--line-2);color:var(--muted);font:italic 700 12px Georgia,serif;cursor:pointer}
.info>summary::-webkit-details-marker{display:none}
.info>summary:hover,.info>summary:focus-visible{color:var(--ink);border-color:var(--orange)}
.info[open]>summary{background:var(--orange);border-color:var(--orange);color:var(--navy)}
.info-body{position:absolute;top:calc(100% + 8px);left:0;z-index:20;width:300px;max-width:min(300px,80vw);background:#111;color:#fff;padding:12px 14px;border-radius:10px;font-size:13px;line-height:1.5;box-shadow:0 14px 36px rgba(0,0,0,.4)}

/* "Right now" stat tiles (live snapshot) */
/* Flexbox, not grid: a grid's column tracks are fixed across every row, so a trailing short row (say 2 tiles
   left over from 9 across 7 columns) leaves empty, un-stretched tracks — a visible gap on the right. Flex-wrap
   lets each row's actual tiles grow to fill whatever width that row has, so a short last row fills out evenly
   instead of leaving blank space. No max-width cap on the tile — capping growth is exactly what left a gap
   the first time round (2 leftover tiles capped well short of the 5+ columns' worth of space they had to
   fill); uncapped, tiles always consume every bit of free width in their row, so there is never a gap. */
.kpi-tiles{display:flex;flex-wrap:wrap;gap:10px;margin-top:4px}
.tile{background:var(--card-2);border:1px solid var(--line);border-radius:10px;padding:12px 14px;flex:1 1 150px}
.tile-label{color:var(--muted);font-size:13px;margin-bottom:4px}
.tile-value{color:var(--ink);font-size:22px;font-weight:700}

/* Conversion funnel: a stack of rounded trapezoid segments (SVG, path data computed server-side in
   views.ts), each stage's width the share of targets at that step or further along (so it only ever narrows) and tapering into the one below —
   so a later stage reads as visually INSIDE the one above it, not as its own separate bar. The label and
   count live OUTSIDE the shape, in a fixed-width text column, so a narrow bottom segment never has to clip
   or shrink its own text; the shape communicates proportion, the text column stays uniform and legible.
   Corners are rounded to match the softened points in the Ascent Target wordmark. */
/* Two renderings of the same funnel data ship in the page at once; only one is ever visible at a time (see the
   phone breakpoint below), because this app has no client-side JS to swap markup in after the fact. Desktop
   gets the tapering shape (reads proportion at a glance); phone gets the plain percentage bar-list instead,
   since the shape's fixed-width column has the least room to work with on a narrow screen. */
.funnel-bars{display:none}
.trap{width:100%;max-width:480px;margin-top:6px}
.trap-row{display:flex;align-items:center;gap:16px}
/* shape-col's width is set responsively below (see the phone breakpoint); the SVG inside scales to fill it
   (viewBox-based, not pixel-based), so the rounded corners stay correctly proportioned — round, not
   stretched — at any width. */
.shape-col{width:220px;flex:0 0 220px}
/* .fseg, not .seg — .seg is the Grid/Table/Map view switcher, whose bordered box used to wrap every funnel segment too (a name clash since v73, fixed v130). */
.fseg{margin:0 0 2px}
.fseg svg{display:block;width:100%;height:auto}
.seg-fill-1{fill:var(--funnel-1)}.seg-fill-2{fill:var(--funnel-2)}.seg-fill-3{fill:var(--funnel-3)}
.seg-fill-4{fill:var(--funnel-4)}.seg-fill-5{fill:var(--funnel-5)}.seg-fill-6{fill:var(--funnel-6)}.seg-fill-7{fill:var(--funnel-7)}.seg-fill-8{fill:var(--funnel-8)}
.text-col{flex:1;min-width:0;display:flex;align-items:baseline;gap:8px;font-size:14px}
.seg-label{color:var(--text)}
.seg-count{color:var(--text);white-space:nowrap}
/* "Not progressing" isn't part of the tapering shape above (it's a current-status count, not cumulative), so
   it's a plain note underneath instead of one more segment — a divider sets it apart, and the one figure
   that matters (the count) is the only bit that isn't muted. */
.funnel-note{margin:14px 0 0;padding-top:12px;border-top:1px solid var(--line);font-size:12.5px;line-height:1.5}
.funnel-note b{color:var(--text)}
.funnel-off{white-space:nowrap}
.stage-check{list-style:none;padding:0;margin:8px 0 0;display:grid;grid-template-columns:repeat(auto-fill,minmax(230px,1fr));gap:4px 16px}
.stage-check .ok{color:var(--text)}
.stage-check .missing{color:#e05252}
form.inline-link{display:inline;margin:0}
form.inline-link button.link{padding:0;margin:0 0 0 6px;width:auto;display:inline}
.choice-list{display:flex;flex-wrap:wrap;gap:6px;margin-top:8px}

/* An originator's background notes on a target (see views.formatNotes) — lightly formatted plain text
   (paragraphs and bullet lists only), styled close to the rest of the page's type rather than looking like a
   rich-text editor's output. */
.notes-body{font-size:15px;line-height:1.6;margin-bottom:10px}
.notes-body p{margin:0 0 12px}
.notes-body ul{margin:0 0 12px;padding-left:22px}
.notes-body li{margin:0 0 6px}
.notes-body>:last-child{margin-bottom:0}

/* Response-rate meter: a native <progress> element (value/max attributes, never an inline style="width:…%"
   — this page's CSP has no style-src 'unsafe-inline', which silently drops a hand-drawn bar sized that way) */
.meter{-webkit-appearance:none;appearance:none;display:inline-block;width:72px;height:8px;border:1px solid var(--line);border-radius:4px;background:var(--card-2);overflow:hidden;vertical-align:middle;margin-right:8px}
.meter::-webkit-progress-bar{background:var(--card-2);border-radius:3px}
.meter::-webkit-progress-value{background:var(--orange);border-radius:0 3px 3px 0}
.meter::-moz-progress-bar{background:var(--orange);border-radius:0 3px 3px 0}
/* Wider variant used under the Response rate hero figure below — same fill/track, just full width and a
   touch taller so it reads as this card's one supporting bar, not the small inline gauge .meter is elsewhere. */
.meter-wide{width:100%;height:10px;margin:0 0 16px}

/* Bar-list funnel rows (phone breakpoint): each stage is its own labelled <progress>, colored from the same
   one-hue ramp as the tapering shape's segments, so switching views at the breakpoint doesn't also change
   which color means which stage. */
.fbar-row{margin:0 0 14px}
.fbar-row:last-child{margin-bottom:0}
.fbar-head{display:flex;justify-content:space-between;align-items:baseline;gap:8px;font-size:14px;margin-bottom:4px}
.fbar-1::-webkit-progress-value{background:var(--funnel-1)}.fbar-1::-moz-progress-bar{background:var(--funnel-1)}
.fbar-2::-webkit-progress-value{background:var(--funnel-2)}.fbar-2::-moz-progress-bar{background:var(--funnel-2)}
.fbar-3::-webkit-progress-value{background:var(--funnel-3)}.fbar-3::-moz-progress-bar{background:var(--funnel-3)}
.fbar-4::-webkit-progress-value{background:var(--funnel-4)}.fbar-4::-moz-progress-bar{background:var(--funnel-4)}
.fbar-5::-webkit-progress-value{background:var(--funnel-5)}.fbar-5::-moz-progress-bar{background:var(--funnel-5)}
.fbar-6::-webkit-progress-value{background:var(--funnel-6)}.fbar-6::-moz-progress-bar{background:var(--funnel-6)}
.fbar-7::-webkit-progress-value{background:var(--funnel-7)}.fbar-7::-moz-progress-bar{background:var(--funnel-7)}
.fbar-8::-webkit-progress-value{background:var(--funnel-8)}.fbar-8::-moz-progress-bar{background:var(--funnel-8)}

/* Response rate hero figure: the one number this page leads with (per KPI-row layout below), set large
   enough to read at a glance rather than sitting inline in a sentence like the rest of the page's text. */
.kpi-hero{margin:2px 0 14px}
.kpi-hero-value{font-size:52px;line-height:1;font-weight:700;color:var(--ink);letter-spacing:-.01em}
.kpi-hero-label{color:var(--muted);font-size:14px;margin-top:4px}

/* KPI dashboard top row: Response rate and Conversion funnel side by side (Response rate first/left, since
   it's the headline number), Targets by current stage goes underneath on its own full-width row. */
.kpi-row{display:grid;grid-template-columns:1fr 1fr;gap:22px;align-items:start}
/* Left half of the KPIs page: response rate with the rejection reasons underneath, beside the funnel. */
.kpi-col{display:flex;flex-direction:column;gap:22px;min-width:0}.kpi-col>.card{margin:0}
@media(max-width:860px){.kpi-row{grid-template-columns:1fr}}

/* Portal home: large nav buttons through to Targets/KPIs/Team */
.home-tiles{display:grid;grid-template-columns:repeat(auto-fit,minmax(220px,1fr));gap:20px;margin-top:4px}
.home-tile{background:var(--card);border:1px solid var(--line);border-radius:14px;padding:24px;box-shadow:var(--shadow);text-decoration:none;display:block;transition:border-color .15s,background .15s}
.home-tile:hover{border-color:var(--orange);background:var(--card-2)}
.home-tile-head{display:flex;align-items:center;justify-content:space-between;gap:10px;margin-bottom:8px}
.home-tile-head h2{margin:0}
.home-tile p{margin:0;font-size:14px}

/* target page */
.back{display:inline-block;margin-bottom:16px;text-decoration:none;font-weight:500}
.tnavrow{display:flex;justify-content:space-between;align-items:center;gap:16px;flex-wrap:wrap;margin-bottom:0}
.tnav{display:flex;align-items:center;gap:10px;margin-bottom:16px}
.tnav span.button[aria-disabled]{opacity:.35;cursor:default;pointer-events:none}
.split{display:grid;grid-template-columns:minmax(0,1fr) 320px;gap:24px;align-items:start}
/* .hero-facts itself (the paper panel, hairline rows) is defined once, above, alongside .metrics — this just
   gives it a bottom margin so it doesn't sit flush against whatever card section follows it. */
.hero-facts{margin:0 0 20px}
.prose{white-space:pre-wrap}
.decide{border-top:4px solid var(--orange)}
.actions{display:grid;grid-template-columns:repeat(auto-fit,minmax(240px,1fr));gap:18px}
.box{border:1px solid var(--line);border-radius:12px;padding:18px;display:flex;flex-direction:column;gap:6px;background:var(--overlay-04)}
.box.approve{border-color:rgba(74,222,128,.45);background:var(--green-bg)}.box.reject{border-color:rgba(255,139,128,.45);background:var(--red-bg)}.box.park{background:var(--overlay-04)}
.box .check{margin-bottom:6px}.box button{margin-top:auto;width:100%}
.timeline{list-style:none;margin:0;padding:0}.timeline li{display:flex;justify-content:space-between;align-items:center;gap:8px;padding:10px 0;border-bottom:1px solid var(--line);font-size:14px}.timeline li:last-child{border:0}
.status{display:inline-block;white-space:nowrap;border-radius:999px;padding:3px 12px;font-size:12.5px;font-weight:700;background:var(--overlay-10);color:var(--text)}
.s-for-review{background:var(--orange-soft);color:var(--link);box-shadow:inset 0 0 0 1px rgba(255,107,14,.5)}.s-query-raised{background:rgba(255,160,90,.18);color:var(--link)}.s-approved{background:var(--green-bg);color:var(--green)}.s-rejected{background:var(--red-bg);color:var(--red)}.s-parked{background:var(--purple-bg);color:var(--purple)}.s-outreach,.s-in-conversation,.s-introduced,.s-under-offer,.s-under-hot,.s-due-diligence{background:var(--blue-bg);color:var(--blue)}.s-acquired{background:rgba(74,222,128,.22);color:var(--green)}.s-not-interested{background:var(--overlay-08);color:var(--muted)}
.s-strong{background:var(--green-bg);color:var(--green)}.s-average{background:var(--orange-soft);color:var(--link)}.s-weak{background:var(--overlay-08);color:var(--muted)}

/* swipe deck */
.deckview{max-width:560px;margin:0 auto}
.deck-head{display:flex;justify-content:space-between;align-items:baseline;gap:12px;flex-wrap:wrap;margin-bottom:12px;font-size:15px}.deck-head b{font-size:24px;color:var(--orange)}.deck-head .muted{font-size:13px}
.deck{position:relative;height:clamp(440px,calc(100dvh - 400px),560px);margin:0 0 16px}
.dcard{position:absolute;left:0;right:0;top:0;bottom:56px;background:var(--card-2);border:1px solid var(--line-2);border-radius:20px;padding:26px;display:flex;flex-direction:column;gap:16px;box-shadow:0 14px 36px rgba(3,8,22,.5);transform-origin:50% 100%;transition:transform .3s ease,opacity .3s ease;user-select:none;-webkit-user-select:none}
.dcard h2{font-size:24px;line-height:1.2;margin:0}
.dcard .desc{-webkit-line-clamp:4;font-size:15.5px;flex-shrink:0}
.dcard .metrics{margin-top:auto}
.dcard .metric dd{font-size:19px}
.dfoot{display:flex;justify-content:space-between;align-items:center;gap:10px;font-size:14px}.dfoot .site{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.dcard.pos-0{z-index:5;cursor:pointer;touch-action:none;border-top:5px solid var(--orange)}.dcard.pos-0:hover{border-color:var(--border-emphasis);border-top-color:var(--orange)}.dcard.pos-0:active{cursor:grabbing}
.dcard.pos-1{z-index:4;transform:translateY(24px) scale(.95);pointer-events:none;background:var(--deck-2);box-shadow:0 8px 22px rgba(3,8,22,.5)}
.dcard.pos-2{z-index:3;transform:translateY(48px) scale(.9);pointer-events:none;background:var(--deck-3);box-shadow:0 6px 16px rgba(3,8,22,.5)}
.dcard.pos-hide{z-index:1;transform:translateY(48px) scale(.9);opacity:0;pointer-events:none}
.dcard.pos-1>*,.dcard.pos-2>*{visibility:hidden}
.dcard.flying{z-index:9;pointer-events:none;border-top:5px solid var(--orange)}
.stamp{position:absolute;top:20px;padding:4px 12px;border:3px solid;border-radius:10px;font-weight:800;font-size:20px;letter-spacing:.08em;text-transform:uppercase;opacity:0;pointer-events:none;background:rgba(15,24,48,.85)}
/* Fixed colours, not the --green/--red/--purple variables: this chip's own background is always a dark navy
   tint regardless of theme, so its text needs to stay the light shades that read against THAT dark chip, not
   whichever shade those variables currently are for the page's theme (--red, for instance, turns into a dark
   saturated red in light theme — fine as body text on a white card, unreadable on this dark chip). */
.stamp.s-approve{left:20px;color:#4ADE80;transform:rotate(-10deg)}.stamp.s-reject{right:20px;color:#FF8B80;transform:rotate(10deg)}.stamp.s-park{left:50%;margin-left:-40px;color:#B8B0FF}
.deck-actions{display:flex;justify-content:center;gap:28px;margin:8px 0 14px}
.round{display:flex;flex-direction:column;align-items:center;gap:6px;border:0;background:none;padding:0;font-size:13px;color:var(--muted);font-weight:600}
.round:hover{color:var(--ink)}
.round .ic{width:64px;height:64px;border-radius:50%;display:flex;align-items:center;justify-content:center;font-size:26px;background:var(--card);border:2px solid;box-shadow:0 4px 14px rgba(3,8,22,.4);line-height:1}
.round.reject .ic{color:var(--red);border-color:var(--red)}.round.park .ic{color:var(--purple);border-color:var(--purple);font-size:20px;letter-spacing:-2px}.round.approve .ic{color:#fff;background:#1F9D4C;border-color:#1F9D4C}
.round:hover .ic{transform:scale(1.07)}.round .ic{transition:transform .15s}
.deck-note{text-align:center;font-size:13px;margin:0 0 10px}
.deckview .empty{margin-top:8px}
.toast{position:fixed;left:50%;top:84px;transform:translateX(-50%);z-index:50;min-width:min(340px,calc(100vw - 32px));justify-content:space-between;background:#fff;color:var(--navy);font-weight:600;border-radius:12px;padding:12px 16px 15px;display:flex;align-items:center;gap:16px;box-shadow:0 10px 30px rgba(0,0,0,.45);max-width:calc(100vw - 32px);overflow:hidden}
.toast[hidden]{display:none}.toast button{background:none;border:0;color:#C94E00;font-weight:800;padding:0;cursor:pointer}
.toast i{position:absolute;left:0;bottom:0;height:3px;background:var(--orange);width:100%;animation:drain 5s linear forwards}
.toast.error{background:#b3261e;color:#fff}@keyframes drain{to{width:0}}
dialog#rej{border:1px solid var(--line-2);border-radius:16px;padding:24px;max-width:460px;width:calc(100vw - 32px);box-shadow:0 20px 60px rgba(0,0,0,.6);background:var(--card);color:var(--text)}dialog#rej::backdrop{background:rgba(8,13,28,.7)}
.dlg-actions{display:flex;justify-content:flex-end;gap:10px}

/* HQ maps (Leaflet, Esri's free light-grey basemap tiles — see darkTiles in app.js — plus coloured pins).
   The tile service itself is light grey; inverting just the tile pane turns it dark to match the portal's
   theme, without affecting the pins/popups, which live in a separate Leaflet pane untouched by this filter. */
/* !important: Leaflet's own stylesheet loads after app.css and sets .leaflet-container{background:#ddd},
   which would otherwise win the cascade tie and show a flash of light grey while tiles are still loading in. */
.hqmap{height:220px;border-radius:12px;overflow:hidden;border:1px solid var(--line);background:var(--map-bg)!important}
.allmap{height:min(560px,70vh);border-radius:14px;overflow:hidden;border:1px solid var(--line);margin-bottom:14px;background:var(--map-bg)!important}
.leaflet-tile-pane{filter:invert(1) hue-rotate(180deg) brightness(.95) contrast(.9)}
.leaflet-popup-content-wrapper,.leaflet-popup-tip{background:var(--card);color:var(--text);box-shadow:0 10px 30px rgba(3,8,22,.5)}
.leaflet-popup-content a{color:var(--link)}.leaflet-popup-content{font:14px/1.5 "DM Sans",system-ui,sans-serif}
.leaflet-popup-close-button{color:var(--muted)!important}
.leaflet-control-zoom a{background:var(--card)!important;color:var(--ink)!important;border-color:var(--line-2)!important}
.leaflet-control-zoom a:hover{background:var(--overlay-10)!important}
/* Fixed light text, not var(--muted): this chip's own background is always a dark navy tint regardless of
   theme (it floats over the map tiles, not the page), so its text must stay the light shade that reads against
   THAT fixed dark chip rather than whichever shade --muted currently is for the page's theme. */
.leaflet-control-attribution{background:rgba(15,24,48,.72)!important;color:#B8C2DB!important;font-size:10px!important;padding:1px 6px!important}
.leaflet-control-attribution a{color:#B8C2DB!important}
.maplegend{display:flex;flex-wrap:wrap;align-items:center;gap:6px 18px;margin-bottom:14px}
.maplegend-all{background:none;border:0;padding:0;margin:0;font:inherit;font-size:14px;color:var(--link);text-decoration:underline;cursor:pointer}
.maplegend-all:hover{color:var(--orange-hi)}
.maplegend-item{display:flex;align-items:center;gap:7px;margin:0;font-size:14px;color:var(--text);cursor:pointer}
.maplegend-item input{margin:0}
.status-dot{width:10px;height:10px;border-radius:50%;flex:none;background:currentColor}
.maplegend-item.off{color:var(--muted);opacity:.55}
/* Cluster badges: nearby HQ pins collapse into one of these at low zoom (see renderClusters in app.js) —
   the portal's blue accent (--blue), a navy ring/border for definition against the map, bold white count.
   `.leaflet-marker-icon.cluster-pin` (two classes = higher specificity) is needed because leaflet.css loads
   after app.css and sets plain `.leaflet-marker-icon{display:block}`, which would otherwise beat our
   `display:flex` on cascade order alone and leave the number off-centre. */
.cluster-pin{display:flex;align-items:center;justify-content:center;border-radius:50%;background:var(--blue);border:2px solid var(--navy-deep);color:#fff;font-weight:700;cursor:pointer;box-shadow:0 0 0 4px rgba(143,180,255,.32),0 6px 14px rgba(3,8,22,.45)}
.leaflet-marker-icon.cluster-pin{display:flex}
.cluster-pin span{line-height:1;pointer-events:none;color:#fff;font-weight:700}
.cluster-pin.cluster-sm{font-size:13px}
.cluster-pin.cluster-md{font-size:14px}
.cluster-pin.cluster-lg{font-size:15px}
.cluster-pin:hover{background:#A9C4FF}

/* bulk approve (sits above the table) */
th.sel,td.sel{width:40px;padding-right:0}td.sel input,th.sel input{width:18px;height:18px;margin:0}
tr.picked td{background:rgba(74,222,128,.09)}
.bulkbar{display:flex;align-items:center;justify-content:space-between;gap:20px;flex-wrap:wrap;background:var(--card);border:1px solid var(--line-2);border-left:5px solid var(--orange);border-radius:14px;padding:14px 20px;margin-bottom:18px}
.bulk-what{display:flex;flex-direction:column;line-height:1.35}.bulk-what>b{color:var(--ink);font-size:16px}.bulk-what .muted{font-size:14px}.bulk-what .muted b{color:var(--orange)}
.bulkbar .check{color:var(--text);font-size:14px;flex:1;min-width:260px;margin:0}

@media(max-width:860px){.split{grid-template-columns:1fr}}
@media(max-width:600px){
  /* Signed-in header: logo on its own centred row, then the whole nav (links + sign out) as a second, centred,
     wrapping row underneath — instead of the desktop layout's flex spacer pushing "Sign out" off on its own,
     away from the links it belongs with, which is what made it look stranded in the corner on a phone. */
  header{flex-direction:column;align-items:stretch;gap:2px 0;padding:10px 16px}
  .brand{justify-content:center;padding:2px 0}.brand img{height:16px}.portal{font-size:11px}body.auth .brand img{height:22px}
  main{padding:22px 16px 48px}.grid{grid-template-columns:1fr}h1{font-size:24px}
  nav{flex:0 0 auto;width:100%;justify-content:center;gap:2px 4px}
  nav .spacer{flex:0 0 100%;height:0}
  nav a{padding:5px 10px}.usermenu summary{padding:5px 10px}.who{max-width:140px}
  .deck{height:clamp(380px,calc(100dvh - 360px),520px)}.dcard{padding:18px}.deck-actions{gap:18px}.round .ic{width:58px;height:58px}
  .pagehead.compact>div:first-child{display:none}.pagehead.compact{justify-content:center;margin-bottom:12px}
  /* Conversion funnel: swap the tapering shape for the plain percentage bar-list (see .funnel-shape/.funnel-bars
     above) — a fixed-width shape column has the least room to work with on a narrow screen, where the bar-list
     reads more clearly than a shrunk-down shape would. */
  .funnel-shape{display:none}
  .funnel-bars{display:block}
  /* The (i) info toggle: on a phone-width screen a floating card can run off the edge or sit under a thumb,
     so instead it drops inline right under the heading, pushing the rest of the card down — same tap to
     open, just no floating box to worry about clipping. */
  /* .info (the <details>) is unwrapped with display:contents so its <summary> and .info-body become direct
     flex items of .card-head alongside the <h2> — the icon still sits right next to the heading, and
     flex-basis:100% on .info-body then forces it onto its own full-width line underneath when open, instead
     of the fixed-width floating card it is on desktop. */
  .card-head{flex-wrap:wrap}
  .info{display:contents}
  .info-body{flex-basis:100%;position:static;width:auto;max-width:none;margin-top:8px;box-shadow:none;background:var(--card-2);color:var(--text)}
}

/* Tools area → Find contact details */
.lookup-form .inline label{margin-bottom:0}
.found{list-style:none;padding:0;margin:0 0 16px}
.found li{padding:8px 0;border-bottom:1px solid var(--line);display:flex;flex-wrap:wrap;align-items:center;gap:8px}
.found li:last-child{border-bottom:0}
.pill{display:inline-block;border-radius:999px;padding:1px 9px;font-size:12px;font-weight:700;background:var(--overlay-08);color:var(--muted)}
.pill.ok{background:var(--green-bg);color:var(--green)}
.pill.warn{background:var(--orange-soft);color:var(--link)}
.lookup-facts{display:flex;flex-wrap:wrap;gap:8px 28px;margin:0 0 18px}
.lookup-facts dt{font-size:12px;font-weight:700;letter-spacing:.06em;text-transform:uppercase;color:var(--muted)}
.lookup-facts dd{margin:2px 0 0;font-weight:600;color:var(--ink)}
.lookup-steps{margin-top:8px;color:var(--muted);font-size:14px}
.lookup-steps summary{cursor:pointer}
.inline-actions{display:flex;flex-wrap:wrap;gap:10px;align-items:center;margin:0 0 24px}
.inline-actions form{margin:0}

/* Management overview (MD): headline tiles, attention list, per-project table. Status flags always carry an icon
   and a word, never colour alone; arrows + numbers carry each change. */
.ov-tiles{margin:6px 0 22px}
.ov-tile .tile-value{font-size:30px;line-height:1.15}
.ov-change{margin-top:4px;font-size:14px;font-weight:600}
.ov-note{color:var(--muted);font-size:12px;margin-top:2px}
.delta{display:block;font-size:12px;font-weight:700;white-space:nowrap}
.ov-change .delta{font-size:14px;display:inline}
.delta.good{color:var(--green)}.delta.bad{color:var(--red)}.delta.flat{color:var(--muted);font-weight:500}
.ov-val{display:block;font-size:17px;font-weight:700;color:var(--ink)}
.ov-table td,.ov-table th{vertical-align:top}
.ov-table th{white-space:nowrap}
.ov-rank tfoot td{border-top:2px solid var(--line);font-weight:500}.ov-rank td.num,.ov-rank th.num{text-align:right}.ov-foot{margin:12px 0 0}
.ov-h{margin:26px 0 12px}
.flag{display:inline-block;border-radius:999px;padding:2px 10px;font-size:12px;font-weight:700;white-space:nowrap}
.flag.urgent{background:var(--red-bg);color:var(--red)}
.flag.watch{background:var(--orange-soft);color:var(--link)}
.flag.ok{background:var(--green-bg);color:var(--green)}
.ov-flags{list-style:none;margin:0;padding:0}
.ov-flags li{display:flex;align-items:center;gap:12px;padding:10px 0;border-bottom:1px solid var(--line)}
.ov-flags li:last-child{border-bottom:0}
.ov-flag-text{flex:1;min-width:0}
.ov-flags .button{padding:6px 12px;font-size:14px}
.ov-wins{list-style:none;margin:0;padding:0}
.ov-wins li{padding:8px 0;border-bottom:1px solid var(--line)}
.ov-wins li:last-child{border-bottom:0}
@media (max-width:700px){.ov-flags li{flex-wrap:wrap;gap:8px}.ov-flags .button{order:1;margin-left:auto;padding:4px 10px}.ov-flag-text{flex-basis:100%;order:2}}
/* Overview → week-by-week charts. One series colour, validated for contrast on each theme's card:
   #E8600A on the dark card, #C2410C on the light one. Axes/grid recessive; text in text colours only. */
:root{--chart-1:#E8600A}
body[data-theme="light"]{--chart-1:#C2410C}
.trend-filter{display:flex;flex-wrap:wrap;align-items:flex-end;gap:12px;margin:0 0 8px}
.trend-filter label{margin:0;font-size:13px}
.trend-filter select{margin-top:4px;min-width:180px}
.trend-filter button{margin:0}
.trend-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:16px;margin:12px 0 16px}
@media (max-width:900px){.trend-grid{grid-template-columns:1fr}}
.trend-chart{margin:0;background:var(--card);border:1px solid var(--line);border-radius:14px;padding:16px 16px 8px}
.trend-chart figcaption{display:flex;flex-direction:column;gap:2px;margin-bottom:8px}
.trend-chart figcaption b{color:var(--ink);font-size:16px}
.tc-wrap{position:relative;outline:none}
.tc-wrap:focus-visible{box-shadow:0 0 0 2px var(--orange);border-radius:6px}
.tc-wrap svg{display:block;width:100%;height:auto;overflow:visible}
.tc-grid{stroke:var(--line);stroke-width:1}
.tc-axis{fill:var(--muted);font-size:11px;font-variant-numeric:tabular-nums}
.tc-line{fill:none;stroke:var(--chart-1);stroke-width:2;stroke-linejoin:round;stroke-linecap:round}
.tc-dot{fill:var(--chart-1);stroke:var(--card);stroke-width:2}
.tc-bar{fill:var(--chart-1)}
.tc-end{fill:var(--ink);font-size:12px;font-weight:700}
.tc-cross{stroke:var(--muted);stroke-width:1}
.tc-tip{position:absolute;top:0;transform:translateX(-50%);background:var(--navy-deep);color:#fff;border-radius:8px;padding:6px 10px;font-size:12px;white-space:nowrap;pointer-events:none;box-shadow:var(--shadow)}
.tc-tip b{font-size:14px;display:block}
.trend-table{margin-top:4px}
.trend-table summary{cursor:pointer;font-weight:600}
.trend-table table{margin-top:12px}
.trend-h{margin:18px 0 0;font-size:15px;color:var(--muted);text-transform:uppercase;letter-spacing:.06em}

/* Rejection reasons (KPIs page and Overview): one bar per reason, longest first; the value sits after each bar
   in text colours. Widths are classes (see rejectionBars in views.ts) because inline styles are blocked. */
.rj-bars{display:flex;flex-direction:column;gap:10px;margin:6px 0 4px}
.rj-row{display:grid;grid-template-columns:minmax(120px,190px) 1fr auto;align-items:center;gap:12px}
.rj-label{color:var(--text);font-size:14px}
.rj-track{display:block;height:16px}
.rj-bar{display:block;height:16px;background:var(--chart-1);border-radius:0 4px 4px 0}
.rj-val{font-size:14px;white-space:nowrap;color:var(--ink)}
.rj-others{margin-top:14px;color:var(--text)}
.rj-others summary{cursor:pointer;font-weight:600}
.rj-others ul{margin:8px 0 0;padding-left:18px}
.rj-others li{margin:4px 0}
@media (max-width:600px){.rj-row{grid-template-columns:1fr auto}.rj-track{grid-column:1 / -1;order:3}}
.rj-bar.w0{width:0%}.rj-bar.w1{width:1%}.rj-bar.w2{width:2%}.rj-bar.w3{width:3%}.rj-bar.w4{width:4%}.rj-bar.w5{width:5%}.rj-bar.w6{width:6%}.rj-bar.w7{width:7%}.rj-bar.w8{width:8%}.rj-bar.w9{width:9%}.rj-bar.w10{width:10%}.rj-bar.w11{width:11%}.rj-bar.w12{width:12%}.rj-bar.w13{width:13%}.rj-bar.w14{width:14%}.rj-bar.w15{width:15%}.rj-bar.w16{width:16%}.rj-bar.w17{width:17%}.rj-bar.w18{width:18%}.rj-bar.w19{width:19%}.rj-bar.w20{width:20%}.rj-bar.w21{width:21%}.rj-bar.w22{width:22%}.rj-bar.w23{width:23%}.rj-bar.w24{width:24%}.rj-bar.w25{width:25%}.rj-bar.w26{width:26%}.rj-bar.w27{width:27%}.rj-bar.w28{width:28%}.rj-bar.w29{width:29%}.rj-bar.w30{width:30%}.rj-bar.w31{width:31%}.rj-bar.w32{width:32%}.rj-bar.w33{width:33%}.rj-bar.w34{width:34%}.rj-bar.w35{width:35%}.rj-bar.w36{width:36%}.rj-bar.w37{width:37%}.rj-bar.w38{width:38%}.rj-bar.w39{width:39%}.rj-bar.w40{width:40%}.rj-bar.w41{width:41%}.rj-bar.w42{width:42%}.rj-bar.w43{width:43%}.rj-bar.w44{width:44%}.rj-bar.w45{width:45%}.rj-bar.w46{width:46%}.rj-bar.w47{width:47%}.rj-bar.w48{width:48%}.rj-bar.w49{width:49%}.rj-bar.w50{width:50%}.rj-bar.w51{width:51%}.rj-bar.w52{width:52%}.rj-bar.w53{width:53%}.rj-bar.w54{width:54%}.rj-bar.w55{width:55%}.rj-bar.w56{width:56%}.rj-bar.w57{width:57%}.rj-bar.w58{width:58%}.rj-bar.w59{width:59%}.rj-bar.w60{width:60%}.rj-bar.w61{width:61%}.rj-bar.w62{width:62%}.rj-bar.w63{width:63%}.rj-bar.w64{width:64%}.rj-bar.w65{width:65%}.rj-bar.w66{width:66%}.rj-bar.w67{width:67%}.rj-bar.w68{width:68%}.rj-bar.w69{width:69%}.rj-bar.w70{width:70%}.rj-bar.w71{width:71%}.rj-bar.w72{width:72%}.rj-bar.w73{width:73%}.rj-bar.w74{width:74%}.rj-bar.w75{width:75%}.rj-bar.w76{width:76%}.rj-bar.w77{width:77%}.rj-bar.w78{width:78%}.rj-bar.w79{width:79%}.rj-bar.w80{width:80%}.rj-bar.w81{width:81%}.rj-bar.w82{width:82%}.rj-bar.w83{width:83%}.rj-bar.w84{width:84%}.rj-bar.w85{width:85%}.rj-bar.w86{width:86%}.rj-bar.w87{width:87%}.rj-bar.w88{width:88%}.rj-bar.w89{width:89%}.rj-bar.w90{width:90%}.rj-bar.w91{width:91%}.rj-bar.w92{width:92%}.rj-bar.w93{width:93%}.rj-bar.w94{width:94%}.rj-bar.w95{width:95%}.rj-bar.w96{width:96%}.rj-bar.w97{width:97%}.rj-bar.w98{width:98%}.rj-bar.w99{width:99%}.rj-bar.w100{width:100%}

/* BD Leads (Tools -> BD Leads): one card per lead, a coloured edge for its rating */
.s-strong{background:var(--green-bg);color:var(--green)}.s-average{background:var(--orange-soft);color:var(--link)}.s-weak{background:var(--red-bg);color:var(--red)}
.bd-cards{display:flex;flex-direction:column;gap:0}
.bd-card{border-left:6px solid var(--line-2)}.bd-card.bd-strong{border-left-color:var(--green)}.bd-card.bd-average{border-left-color:var(--orange)}.bd-card.bd-weak{border-left-color:var(--red)}
.bd-head{display:flex;justify-content:space-between;align-items:flex-start;gap:12px}.bd-head h3{margin:0}
.bd-card p{margin:8px 0}.bd-criteria{margin:10px 0}.bd-criteria .chip{font-size:12.5px;padding:4px 10px;cursor:default}
.bd-contact{border-top:1px solid var(--line);padding-top:10px}
.bd-warn{color:var(--link);font-size:14px}
.bd-flags{background:var(--orange-soft);border:1px solid rgba(255,107,14,.35);border-radius:10px;padding:10px 14px;margin:10px 0;font-size:14px}.bd-flags ul{margin:6px 0 0;padding-left:18px}
.bd-notes{margin:10px 0}.bd-notes ul{margin:0 0 6px;padding-left:18px;font-size:14px}
.bd-note-form{display:flex;gap:8px;align-items:center}.bd-note-form input{flex:1;margin:0}
.bd-article{margin:10px 0}.bd-article summary{cursor:pointer;color:var(--link);font-weight:600;font-size:14px}.bd-article .prose{max-height:280px;overflow:auto;white-space:pre-wrap;font-size:14px;margin-top:8px;padding:12px;border:1px solid var(--line);border-radius:8px}
.research-contact{border-top:1px solid var(--line);padding-top:10px;margin-top:10px}.research-contact:first-of-type{border-top:0;padding-top:0;margin-top:0}.research-contact p{margin:4px 0}
.bd-upload{display:flex;gap:10px;align-items:center;flex-wrap:wrap}.bd-upload input[type=file]{flex:1;min-width:220px;margin:0}
.bd-batch{margin-top:14px;font-size:14px}.bd-batch progress{display:block;width:100%;height:8px;margin-top:6px;accent-color:var(--orange)}
.error-text{color:var(--red)}
.bd-map{display:grid;grid-template-columns:repeat(auto-fill,minmax(220px,1fr));gap:4px 16px}
.bd-card .rowactions{display:flex;gap:10px;flex-wrap:wrap;margin-top:12px}.bd-card .rowactions form{margin:0}
.small-button{padding:6px 12px;font-size:13.5px;white-space:nowrap}
.form-actions{display:flex;gap:12px;align-items:center;flex-wrap:wrap;margin-top:6px}.form-actions .button{margin:0}
/* Knowledge area (/admin/knowledge): sections of article tiles, and the article page itself — an inline figure
   (the stage flow) that fills the card width, and a slightly narrower measure for the prose. */
.kn-section{margin:26px 0 10px}.kn-section h2{margin-bottom:4px}.kn-section>p.muted{margin-top:0}
.home-tile h3{margin:0;font-size:18px}
.kn-article h2{margin:26px 0 8px}.kn-article h2:first-child{margin-top:0}.kn-article p,.kn-article li{max-width:72ch}
.kn-article ul{padding-left:22px}.kn-article li{margin:6px 0}.kn-article table{margin:8px 0 12px}
.kn-figure{display:block;width:100%;height:auto;margin:6px 0 10px}
/* "Filter by details" (v123, slimmed v124): one compact strip under the status/label chips — a small toggle,
   then every field's from/to (or pick-list) inline on a single wrapping row with short inputs, and Apply/Clear
   tucked on the same row. Active filters repeat as chips with their own ×. Chip/labelbar styling matches the label
   filter, so the two rows read as one system. */
.filterrow{display:flex;justify-content:space-between;align-items:flex-start;gap:12px 18px;flex-wrap:wrap;margin:-8px 0 18px}
.filterpanel-wrap{flex:1 1 0;min-width:min(100%,520px)}
/* "Sort by": a small labelled drop-down on the right of the filter row (its Go button only shows without scripts). */
.sortbar{display:flex;align-items:center;gap:8px;margin:0}
.sortbar label{display:flex;align-items:center;gap:8px;margin:0;font-size:12.5px;font-weight:600;color:var(--muted);white-space:nowrap}
.sortbar select{margin:0;width:auto;padding:5px 8px;font-size:13px;border-radius:7px;max-width:260px}
.sortbar .button{padding:5px 12px;font-size:13px}
.filterpanel summary{cursor:pointer;display:inline-flex;align-items:center;gap:7px;padding:4px 10px 4px 8px;border:1px solid var(--line-2);border-radius:999px;font-size:12.5px;font-weight:600;color:var(--muted);list-style:none;user-select:none}
.filterpanel summary:hover{color:var(--ink);border-color:var(--ink)}
.filterpanel summary::-webkit-details-marker{display:none}
.filterpanel summary::before{content:"";display:inline-block;width:6px;height:6px;border-right:1.5px solid currentColor;border-bottom:1.5px solid currentColor;transform:rotate(-45deg);transition:transform .15s}
.filterpanel[open] summary::before{transform:rotate(45deg)}
.filterpanel summary b{background:var(--orange);color:var(--navy);border-radius:999px;padding:0 7px;font-size:11.5px;line-height:17px}
.facet-form{display:flex;flex-wrap:wrap;align-items:end;gap:8px 18px;padding:10px 0 2px}
.facet-grid{display:contents}
.facet{margin:0;padding:0;border:0;min-width:0;display:flex;align-items:center;gap:6px}
.facet>span,.facet legend{float:left;font-size:12px;font-weight:600;color:var(--muted);padding:0;margin:0 2px 0 0;white-space:nowrap}
.facet-form .facet select,.facet-form .facet input[type=text]{display:inline-block;margin:0;padding:5px 8px;font-size:13px;border-radius:7px;line-height:1.3;width:auto}
.facet-form .facet select{max-width:170px}
.facet-form .facet-range input[type=text]{width:72px;text-align:right}
.facet-form .facet-range input[type=text]::placeholder{text-align:center}
.facet-range .muted{font-size:12px}
.facet-actions{display:flex;align-items:center;gap:8px;flex-wrap:wrap}
.facet-actions .button{padding:5px 12px;font-size:13px}
.facet-actions .small{display:none}
.facet-active{margin:10px 0 0}
.facet-chip a{color:inherit;text-decoration:none;font-weight:700;margin-left:6px;opacity:.8}.facet-chip a:hover{opacity:1}
@media (max-width:640px){.facet-actions .small{display:inline}}
/* Team and project resourcing (v132, src/views-resourcing.ts). Capacity bars reuse the w0–w100 width classes
   (CSP: no inline style), trend bars use h0–h100 heights below. */
.rm-tabs{margin-right:6px}
.rm-tiles{margin:0 0 22px}
.rm-caps{display:grid;grid-template-columns:repeat(auto-fill,minmax(260px,1fr));gap:14px 22px}
.rm-cap-head{display:flex;justify-content:space-between;align-items:baseline;gap:10px;font-size:14px}
.rm-meter{margin:6px 0 4px}
.rm-cap.over .rm-meter::-webkit-progress-value{background:#e05252}.rm-cap.over .rm-meter::-moz-progress-bar{background:#e05252}
.rm-over{color:#e05252;font-weight:700;font-size:12px;text-transform:uppercase;letter-spacing:.04em}
.rm-filters{display:flex;flex-wrap:wrap;align-items:end;gap:10px 16px}
.rm-filters label{margin:0;font-size:12.5px;font-weight:600}.rm-filters select,.rm-filters input{margin-top:4px;width:auto;padding:5px 8px;font-size:13px;border-radius:7px}
.rm-filters label.check{display:flex;align-items:center;gap:6px;padding-bottom:8px}
.rm-filters .button{padding:6px 12px;font-size:13px}
.rm-table td,.rm-table th{vertical-align:top}
.rm-flag{border-color:var(--orange);color:var(--ink)}
.rm-sub{font-size:13px;font-weight:700;letter-spacing:.06em;text-transform:uppercase;color:var(--muted);margin:14px 0 8px}
.rm-notes,.rm-events{list-style:none;padding:0;margin:8px 0 0}.rm-notes li,.rm-events li{padding:8px 0;border-top:1px solid var(--line);font-size:14px}
.rm-end{display:flex;align-items:end;gap:10px;margin-top:14px;flex-wrap:wrap}.rm-end label{flex:1;min-width:200px;margin:0}
.rm-inline{display:flex;gap:6px;align-items:center;flex-wrap:wrap}.rm-inline input{margin:0;width:auto;padding:5px 8px;font-size:13px}.rm-inline input[name=max_units]{width:64px}
.rm-review-form{display:flex;flex-direction:column;gap:4px;min-width:170px}.rm-review-form select,.rm-review-form input{margin:0;padding:4px 6px;font-size:12.5px}
.rm-live td{color:var(--muted)}
.rm-trend{display:flex;flex-direction:column;gap:8px;margin:6px 0 16px}
.rm-trend-row{display:flex;align-items:end;gap:6px}.rm-trend-name{width:110px;font-size:13px;font-weight:600}
.rm-trend-cell{display:flex;flex-direction:column;align-items:center;gap:2px;width:34px}
.rm-trend-bar{width:22px;height:60px;background:var(--card-2);border:1px solid var(--line);border-radius:4px 4px 0 0;position:relative;overflow:hidden}
.rm-trend-bar::after{content:"";position:absolute;left:0;right:0;bottom:0;background:var(--orange);height:var(--h,0%)}
.rm-trend-bar.over::after{background:#e05252}
.h0::after{--h:0%}.h5::after{--h:5%}.h10::after{--h:10%}.h15::after{--h:15%}.h20::after{--h:20%}.h25::after{--h:25%}.h30::after{--h:30%}.h35::after{--h:35%}.h40::after{--h:40%}.h45::after{--h:45%}.h50::after{--h:50%}
.h55::after{--h:55%}.h60::after{--h:60%}.h65::after{--h:65%}.h70::after{--h:70%}.h75::after{--h:75%}.h80::after{--h:80%}.h85::after{--h:85%}.h90::after{--h:90%}.h95::after{--h:95%}.h100::after{--h:100%}
/* An (i) toggle inside a form label (Resourcing): sits on the label line, slightly smaller. */
.rm-label{display:inline-flex;align-items:center;gap:6px}
.rm-label .info>summary{width:17px;height:17px;font-size:11px}
label.check .info{margin-left:6px;vertical-align:middle}
.rm-sort{color:inherit;text-decoration:none}.rm-sort:hover{color:var(--orange)}.rm-sort.on{color:var(--orange)}
