/* Grain Decision System — the Compass shell.
   Ported from the shell the CEO briefing showed Jamie (CEO Presentation/build/shell_parts.py): same rail, same
   workspace chip, same palette, made live and responsive. Slide palette (grain.py) supplies the section styling. */
:root{
  --ink:#0a1a22; --ink9:#0f222b; --ink7:#203a45; --paper:#fcfbf8; --line:#d7dcd9; --lines:#e5e7e2;
  --text:#1c2b31; --body:#3f4f56; --muted:#596970; --onink:#f4f2ec; --oninkm:#a8b5b9;
  --grow:#205c51; --growS:#7db3a4; --blue:#2f6fb0; --amber:#c27d1e; --exec:#51487d; --pale:#eef4f1;
  --green:#10594A; --navy:#1A2B49; --coral:#FF8A66; --palegreen:#EBF8EE; --soft:#D2ECDB; --mid:#A6D4B9;
  --rule:#E2E5EC; --risk:#a1412e;
  --sans:Inter,-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,sans-serif;
  --mono:"JetBrains Mono",ui-monospace,SFMono-Regular,Menlo,monospace;
  --rail:214px; --top:38px; --wb:46px;
}
*{margin:0;padding:0;box-sizing:border-box}
html,body{height:100%}
body{background:var(--paper);font-family:var(--sans);color:var(--text);-webkit-font-smoothing:antialiased;font-size:14px}
.ng,.cnt,.lk,.pill,.crumbs,.mono,.eyebrow,.chip,.stat .l,th{font-family:var(--mono)}
.ic{flex:none;display:block}
a{color:inherit;text-decoration:none}

/* top bar */
.tb{position:fixed;left:0;top:0;right:0;height:var(--top);background:var(--ink);display:flex;align-items:center;
  padding:0 16px;border-bottom:1px solid #1b2c34;z-index:20}
.tl{display:flex;gap:8px;margin-right:22px}
.tl i{width:11px;height:11px;border-radius:50%;display:block}
.tb .nm{font-weight:600;font-size:14px;color:var(--onink)}.tb .nm span{color:#5f747b;margin:0 7px}
.tb .bc{font-family:var(--mono);font-size:12px;color:var(--oninkm);margin-left:18px;padding-left:18px;
  border-left:1px solid #26383f}
.tb .r{margin-left:auto;display:flex;gap:10px}
.pill{display:flex;align-items:center;gap:7px;font-size:11px;color:var(--oninkm);border:1px solid #2a3c44;
  border-radius:6px;padding:4px 10px;white-space:nowrap}
.pill i{width:7px;height:7px;border-radius:50%;display:block;flex:none}

/* rail */
.sb{position:fixed;left:0;top:var(--top);bottom:0;width:var(--rail);background:var(--ink9);padding:14px 12px;
  color:#c9d3d6;overflow-y:auto;z-index:15}
.brand{display:flex;align-items:center;gap:10px;margin-bottom:14px}
.bx{width:30px;height:30px;border-radius:8px;background:var(--grow);display:flex;align-items:center;
  justify-content:center;color:#e8f2ee;flex:none}
.brand b{display:block;font-size:14px;font-weight:600;color:var(--onink)}
.brand span{font-size:11px;color:var(--oninkm)}
.ws{display:flex;align-items:center;gap:8px;border:1px solid #22363f;border-radius:8px;padding:7px 9px;
  margin-bottom:6px;background:#11262f}
.ws .a{width:22px;height:22px;border-radius:5px;background:#00aa4f;color:#fff;font-weight:700;font-size:12px;
  display:flex;align-items:center;justify-content:center;flex:none}
.ws b{font-size:12.5px;font-weight:600;color:var(--onink);display:block;line-height:1.15}
.ws em{font-style:normal;font-size:10.5px;color:var(--oninkm)}
.ws .ic{margin-left:auto;color:var(--oninkm)}
.ng{font-size:10px;letter-spacing:.14em;text-transform:uppercase;color:#6f838a;margin:11px 0 3px 4px}
.ni{display:flex;align-items:center;gap:9px;white-space:nowrap;font-size:12.5px;font-weight:500;padding:5px 8px;
  border-radius:6px;color:#c3ced1;position:relative;cursor:pointer}
.ni .ic{color:#8ea0a5}
.ni .cnt{margin-left:auto;font-size:10px;color:var(--oninkm);background:#162e37;border-radius:4px;padding:1px 6px}
.ni.dim{color:#8c9ca1;cursor:default}
.lk{margin-left:auto;display:flex;align-items:center;gap:3px;font-size:9px;color:#d8b06a;border:1px solid #4a4128;
  border-radius:4px;padding:1px 5px}
.ni.live .cnt{background:#1b4034;color:#9fd6bf}
.ni:hover:not(.dim){background:#15303a}
.ni.on{background:#18343d;color:#fff}
.ni.on .ic{color:var(--growS)}
.ni.on:before{content:'';position:absolute;left:-12px;top:5px;bottom:5px;width:3px;border-radius:0 3px 3px 0;
  background:var(--growS)}

/* workspace bar */
.wb{position:fixed;left:var(--rail);right:0;top:var(--top);height:var(--wb);background:#fff;
  border-bottom:1px solid var(--lines);display:flex;align-items:center;padding:0 22px;font-size:13px;z-index:14}
.wb .a{width:22px;height:22px;border-radius:5px;background:#00aa4f;color:#fff;font-weight:700;font-size:12px;
  display:flex;align-items:center;justify-content:center;margin-right:9px;flex:none}
.wb b{font-weight:600}
.wb .crumbs{font-size:12px;color:var(--muted);margin-left:8px}
.wb .crumbs i{font-style:normal;color:#9aa6aa;margin:0 6px}
.wb .rt{margin-left:auto;display:flex;align-items:center;gap:14px;font-family:var(--mono);font-size:11.5px;
  color:var(--muted)}
.wb .rt i{display:inline-block;width:8px;height:8px;border-radius:50%;margin-right:5px}

/* page */
main{margin-left:var(--rail);padding:calc(var(--top) + var(--wb) + 26px) 30px 70px}
.eyebrow{font-size:11px;letter-spacing:.16em;text-transform:uppercase;color:var(--green);font-weight:700}
.hr{height:1px;background:var(--rule);margin:11px 0 20px}
h1{font-family:var(--sans);font-weight:800;font-size:31px;line-height:1.12;letter-spacing:-.02em;color:var(--navy)}
h2{font-weight:700;font-size:17px;color:var(--navy);margin-bottom:3px}
.lede{color:var(--body);font-size:15px;margin-top:9px;max-width:72ch;line-height:1.55}
section{margin-top:34px}
.note{font-size:12.5px;color:var(--muted);line-height:1.55}

/* stat tiles */
/* 142px could not fit four tiles in the workspace column, so a fourth dropped to its own row
   and sat alone beside a gap. */
.stats{display:grid;grid-template-columns:repeat(auto-fit,minmax(118px,1fr));gap:12px;margin-top:18px}
.stat{background:#fff;border:1px solid var(--rule);border-radius:7px;padding:13px 15px}
.stat .n{font-size:28px;font-weight:800;line-height:1.05;color:var(--navy);letter-spacing:-.02em}
.stat .l{font-size:10px;letter-spacing:.1em;text-transform:uppercase;color:var(--muted);margin-top:4px}
.stat.alert .n{color:var(--risk)}
.stat.good .n{color:var(--green)}

/* chips */
.chip{display:inline-flex;align-items:center;gap:5px;font-size:10px;letter-spacing:.07em;text-transform:uppercase;
  padding:2px 8px;border-radius:999px;white-space:nowrap;font-weight:500}
.chip.live{background:var(--palegreen);color:var(--green)}
.chip.build{background:#eef2f7;color:var(--navy)}
.chip.plan{background:#f4f4f2;color:var(--muted)}
.chip.crm{background:#fbf2e2;color:var(--amber)}
.chip.hot{background:#ffeee8;color:#9c4522}
.chip.bad{background:#f6e6e2;color:var(--risk)}
.chip.ok{background:var(--palegreen);color:var(--green)}

/* panels + tables */
.panel{background:#fff;border:1px solid var(--rule);border-radius:7px;overflow:hidden}
.panel > h2{padding:13px 16px;border-bottom:1px solid var(--rule);margin:0}
table{width:100%;border-collapse:collapse;font-size:13px}
th{text-align:left;font-size:10px;letter-spacing:.09em;text-transform:uppercase;color:var(--muted);
  padding:9px 14px;border-bottom:1px solid var(--rule);background:#fafbfa;font-weight:500}
td{padding:11px 14px;border-bottom:1px solid #f0f1ef;vertical-align:top}
tr.row{cursor:pointer}
tr.row:hover td{background:#f7faf8}
tr.row.on td{background:var(--palegreen)}
tr.dim td{color:var(--muted)}
.who{font-weight:600;color:var(--navy)}
.sub{font-size:11.5px;color:var(--muted);margin-top:2px}
.sla{font-family:var(--mono);font-size:12.5px;font-weight:500}
.sla.late{color:var(--risk)}
.empty{padding:34px 16px;color:var(--muted);text-align:center;font-size:13.5px}

/* the buyer journey strip — the CEO briefing's slide 5, made live */
.journey{margin-top:20px;border:1px solid var(--rule);border-radius:7px;overflow:hidden;background:#fff}
.jscroll{overflow-x:auto}
.jgrid{display:grid;grid-template-columns:132px repeat(7,minmax(146px,1fr));min-width:1140px}
.jband{grid-column:2 / -1;background:var(--palegreen);color:var(--green);font-family:var(--mono);font-size:10px;
  letter-spacing:.12em;text-transform:uppercase;text-align:center;padding:8px 6px;border-bottom:1px solid #fff}
.jband.wide{background:#eef2f7;color:var(--navy)}
.jhead{background:var(--navy);color:#fff;padding:12px 12px 13px;border-bottom:3px solid var(--coral)}
.jhead.stub{background:var(--navy);display:flex;align-items:flex-end}
.jhead .no{font-family:var(--mono);font-size:10.5px;color:#8fa0bd;display:block;margin-bottom:3px}
.jhead .ttl{font-size:13px;font-weight:600;line-height:1.25}
.jhead .lbl{font-family:var(--mono);font-size:10px;letter-spacing:.11em;text-transform:uppercase;color:#8fa0bd}
.jcell{padding:12px;border-right:1px solid #f0f1ef;border-bottom:1px solid #f0f1ef;font-size:12.5px;
  line-height:1.45;color:var(--body)}
.jcell:last-child{border-right:0}
.jrow-lbl{padding:12px;border-right:1px solid #f0f1ef;border-bottom:1px solid #f0f1ef;background:#fafbfa}
.jrow-lbl b{font-family:var(--mono);font-size:10px;letter-spacing:.11em;text-transform:uppercase;color:var(--navy);
  display:block}
.jrow-lbl span{font-size:11px;color:var(--muted);display:block;margin-top:3px;line-height:1.4}
.jcell.now{background:var(--palegreen)}
.jcell .n{font-size:21px;font-weight:800;color:var(--green);letter-spacing:-.02em;line-height:1}
.jloop{padding:9px 12px;text-align:center;font-family:var(--mono);font-size:10px;letter-spacing:.11em;
  text-transform:uppercase;color:var(--green);background:#fff;grid-column:1 / -1}
.split{display:grid;grid-template-columns:1fr 1fr;gap:16px;margin-top:18px}
@media (max-width:900px){.split{grid-template-columns:1fr}}
.chan{display:flex;align-items:center;gap:12px;padding:13px 16px;border-bottom:1px solid #f0f1ef}
.chan:last-child{border-bottom:0}
.chan .ico{width:34px;height:34px;border-radius:8px;background:var(--palegreen);color:var(--green);display:flex;
  align-items:center;justify-content:center;flex:none}
.chan .ico.web{background:#eef2f7;color:var(--navy)}
.chan b{display:block;font-size:13.5px;color:var(--navy)}
.chan span{font-size:11.5px;color:var(--muted)}
.chan .n{margin-left:auto;font-size:22px;font-weight:800;color:var(--navy);letter-spacing:-.02em}
.bar{height:6px;border-radius:3px;background:#eef0ee;overflow:hidden;margin-top:7px}
.bar i{display:block;height:100%;background:var(--grow)}

/* enquiry form */
.form{max-width:620px;background:#fff;border:1px solid var(--rule);border-radius:7px;padding:22px 24px 24px;
  margin-top:20px}
.form label{display:block;font-family:var(--mono);font-size:10px;letter-spacing:.1em;text-transform:uppercase;
  color:var(--muted);margin:16px 0 5px}
.form label:first-of-type{margin-top:0}
.form input,.form select,.form textarea{width:100%;font:inherit;font-size:14.5px;padding:10px 11px;
  border:1px solid var(--line);border-radius:5px;background:#fff;color:var(--text);font-family:var(--sans)}
.form textarea{min-height:88px;resize:vertical}
.form input:focus,.form select:focus,.form textarea:focus{outline:2px solid var(--growS);outline-offset:1px;
  border-color:var(--grow)}
.row2{display:grid;grid-template-columns:1fr 1fr;gap:14px}
@media (max-width:620px){.row2{grid-template-columns:1fr}}
.form button{margin-top:20px;border:0;border-radius:5px;padding:12px 22px;font:inherit;font-weight:600;
  font-size:14.5px;background:var(--grow);color:#fff;cursor:pointer}
.form button:hover{background:#17483f}
.form button:disabled{opacity:.55;cursor:progress}
.result{margin-top:16px;padding:14px 16px;border-radius:6px;background:var(--palegreen);border:1px solid var(--mid);
  font-size:13.5px;color:var(--green);line-height:1.5}
.result b{color:var(--navy)}
.result.bad{background:#f6e6e2;border-color:#e0b8ad;color:var(--risk)}

/* lead desk */
.deskgrid{display:grid;grid-template-columns:1.6fr 1fr;gap:16px;align-items:start;margin-top:18px}
@media (max-width:1100px){.deskgrid{grid-template-columns:1fr}}
.detail{padding:16px}
.detail .k{font-family:var(--mono);font-size:10px;letter-spacing:.1em;text-transform:uppercase;color:var(--muted);
  margin:15px 0 3px}
.detail .k:first-child{margin-top:0}
.detail .v{color:var(--text);font-size:13.5px;line-height:1.5}
.transcript{background:#fafbfa;border:1px solid var(--rule);border-radius:5px;padding:11px 13px;font-size:12.5px;
  line-height:1.6;white-space:pre-wrap;max-height:260px;overflow:auto;color:var(--body)}
ol.ev{list-style:none;margin:0;padding:0;font-size:12.5px}
ol.ev li{padding:7px 0 7px 15px;border-left:2px solid var(--rule);margin-left:3px;position:relative;
  color:var(--body);line-height:1.45}
ol.ev li:before{content:'';position:absolute;left:-5px;top:12px;width:8px;height:8px;border-radius:50%;
  background:var(--grow)}
ol.ev .when{color:var(--muted);font-size:11px;font-family:var(--mono);margin-top:2px}
button.act{border:0;border-radius:5px;padding:10px 16px;font:inherit;font-weight:600;font-size:13.5px;
  background:var(--grow);color:#fff;cursor:pointer;margin-top:16px}
button.act:hover{background:#17483f}
button.act:disabled{opacity:.5;cursor:default}
.chan-tag{display:inline-flex;align-items:center;gap:5px;font-size:11.5px;color:var(--muted)}

/* Compass landscape */
.mapwrap{display:grid;grid-template-columns:minmax(0,1fr) 352px;gap:16px;align-items:start;margin-top:18px}
@media (max-width:1180px){.mapwrap{grid-template-columns:1fr}}
.mapbox{background:#fff;border:1px solid var(--rule);border-radius:7px;padding:10px;position:relative}
.mapbox svg{display:block;width:100%;height:auto;max-height:76vh}
.cty{fill:#f3f5f3;stroke:#dfe4e0;stroke-width:.8;cursor:pointer}
.cty:hover{fill:#e7efe9}
.cty.on{fill:var(--palegreen);stroke:var(--grow);stroke-width:1.4}
.dot{cursor:pointer}
.dot.none{fill:#c3ccc6;opacity:.5}
.dot.bond{fill:var(--grow)}
.dot.project{fill:var(--coral)}
.dot.both{fill:var(--navy)}
.dot.sel{stroke:var(--navy);stroke-width:2}
.dot.hide{display:none}
.maplegend{display:flex;flex-wrap:wrap;gap:14px;align-items:center;margin-top:10px;padding-top:10px;
  border-top:1px solid var(--rule);font-family:var(--mono);font-size:10.5px;color:var(--muted)}
.maplegend b{display:inline-flex;align-items:center;gap:5px;font-weight:400}
.maplegend i{width:9px;height:9px;border-radius:50%;display:block}
.filters{display:flex;flex-wrap:wrap;gap:7px;margin-top:14px}
.fbtn{font-family:var(--mono);font-size:10.5px;letter-spacing:.06em;text-transform:uppercase;padding:5px 11px;
  border:1px solid var(--rule);border-radius:999px;background:#fff;color:var(--muted);cursor:pointer}
.fbtn.on{background:var(--navy);border-color:var(--navy);color:#fff}
.side{display:flex;flex-direction:column;gap:14px;position:sticky;top:112px}
.sidecard{background:#fff;border:1px solid var(--rule);border-radius:7px;padding:15px 16px}
.sidecard h3{font-size:13px;color:var(--navy);margin-bottom:9px;font-weight:700}
.kv{display:flex;justify-content:space-between;gap:12px;padding:5px 0;border-bottom:1px solid #f2f3f1;
  font-size:12.5px}
.kv:last-child{border-bottom:0}
.kv span{color:var(--muted)}
.kv b{color:var(--navy);font-weight:600;font-family:var(--mono);font-size:12px}
.ownerlist{max-height:330px;overflow:auto}
.owner{padding:9px 0;border-bottom:1px solid #f2f3f1;cursor:pointer}
.owner:last-child{border-bottom:0}
.owner:hover b{color:var(--grow)}
.owner b{display:block;font-size:12.5px;color:var(--navy);font-weight:600}
.owner span{font-size:11px;color:var(--muted)}
.statebar{display:flex;align-items:center;gap:10px;padding:8px 0;border-bottom:1px solid #f2f3f1;font-size:12.5px}
.statebar:last-child{border-bottom:0}
.statebar .ab{font-family:var(--mono);font-size:11px;color:var(--navy);width:28px;font-weight:500}
.statebar .nm{flex:1;color:var(--body)}
.statebar .tr{flex:2;height:7px;background:#eef0ee;border-radius:4px;overflow:hidden}
.statebar .tr i{display:block;height:100%;background:var(--grow)}
.statebar .vv{font-family:var(--mono);font-size:11.5px;color:var(--navy);width:52px;text-align:right}
.statebar.live{background:linear-gradient(90deg,var(--palegreen),transparent);border-radius:4px;padding-left:6px}
.statebar.live .nm{font-weight:600;color:var(--navy)}

/* Compass map — full bleed right of the rail, the way explorer.html lays it out */
body.map main{padding:0;margin-left:var(--rail);height:100vh}
#map{position:absolute;left:var(--rail);right:0;top:calc(var(--top) + var(--wb));bottom:0}
.maplibregl-ctrl-group{border:1px solid var(--rule)!important;box-shadow:none!important}
/* Cluster markers. MapLibre writes transform on .mkw to place it, so every hover effect lives on the
   SVG inside — otherwise the marker walks off its own coordinates the moment you point at it. */
.mkw{cursor:pointer;line-height:0}
.mk{display:block;transform-origin:50% 50%;
    transition:transform .17s cubic-bezier(.2,.7,.3,1);
    filter:drop-shadow(0 3px 7px rgba(10,26,34,.17))}
.mkw:hover .mk{transform:scale(1.13)}
.mkw:active .mk{transform:scale(1.03);transition-duration:.07s}
.mk .halo{transition:opacity .17s ease}
.mkw:hover .mk .halo{opacity:.85}
.mk .glow{transition:opacity .17s ease}
.mkw:hover .mk .glow{opacity:.2}
.mk .lbl{font-family:var(--mono);fill:var(--navy);letter-spacing:-.02em;pointer-events:none}
.mk .big{font-size:13px;font-weight:600}
.mk .sm2{font-size:11px;font-weight:500;fill:#8d9a9e}
.mk .tiny{font-size:8.5px;font-weight:500;fill:#8d9a9e;letter-spacing:.02em}
.mk .tiny.hot{fill:#d4612f;font-weight:600}
/* A market with no owner layer is present and quiet: it must not outshout the one with data. */
.mkw.ghost .mk{filter:none;opacity:.72}
.mkw.ghost:hover .mk{opacity:1;transform:scale(1.07)}
/* .odotw is what MapLibre positions; nothing here may transition transform, or the dot animates
   its own repositioning and lags the map on every pan. The dot inside it carries the hover. */
.odotw{line-height:0;cursor:pointer}
.odot{border-radius:50%;box-shadow:0 0 0 1.5px #fff;transform-origin:50% 50%;
      transition:transform .13s ease,box-shadow .13s ease}
.odotw:hover .odot{transform:scale(1.9);box-shadow:0 0 0 2px #fff,0 2px 7px rgba(10,26,34,.35)}
.odotw:hover{z-index:5}

/* The breadcrumb is navigation, not a label: each level takes you back to it. */
.crumb .lv{cursor:pointer;color:var(--navy3);font-weight:400;opacity:.5;
           border-bottom:1px solid transparent;transition:opacity .12s,border-color .12s}
.crumb .lv:hover{opacity:1;border-bottom-color:currentColor}
.crumb .lv.on{color:var(--navy);font-weight:600;opacity:1;cursor:default}
.crumb .lv.on:hover{border-bottom-color:transparent}
.pop .maplibregl-popup-content{font-family:var(--sans);font-size:12.5px;padding:9px 12px;border-radius:6px;
  box-shadow:0 6px 22px rgba(10,26,34,.18);border:1px solid var(--rule);line-height:1.45}
.pop b{display:block;color:var(--navy);font-size:13px;margin-bottom:2px}
.pop em{font-style:normal;color:var(--muted);font-family:var(--mono);font-size:11px}
.searchwrap{position:absolute;left:calc(var(--rail) + 16px);top:calc(var(--top) + var(--wb) + 16px);z-index:12;
  width:330px}
#q{width:100%;font:inherit;font-size:13.5px;padding:10px 13px 10px 32px;border:1px solid var(--rule);
  border-radius:7px;background:#fff;box-shadow:0 3px 14px rgba(10,26,34,.10)}
#q:focus{outline:2px solid var(--growS);outline-offset:1px}
.searchwrap .mag{position:absolute;left:11px;top:11px;color:var(--muted)}
#results{margin-top:6px;background:#fff;border:1px solid var(--rule);border-radius:7px;overflow:hidden;
  box-shadow:0 8px 26px rgba(10,26,34,.14);max-height:320px;overflow-y:auto}
#results div{padding:9px 13px;border-bottom:1px solid #f2f3f1;cursor:pointer}
#results div:last-child{border-bottom:0}
#results div:hover{background:var(--palegreen)}
#results b{display:block;font-size:12.5px;color:var(--navy)}
#results span{font-size:11px;color:var(--muted)}
/* The hint used to share the top row with the filter chips — same top, one anchored left and the
   other right — so on a laptop the sentence ran underneath the chips. It is a quiet caption, not a
   control, so it sits above the tiles where nothing competes for the space. */
/* clears the tile row: 92px tall, sitting 18px off the bottom, plus a 12px gap. */
.hint{position:absolute;left:calc(var(--rail) + 16px);bottom:calc(18px + 92px + 12px);z-index:11;
  background:var(--navy);color:#fff;font-family:var(--mono);font-size:10.5px;letter-spacing:.05em;
  padding:9px 14px;border-radius:7px;box-shadow:0 3px 14px rgba(10,26,34,.18)}
/* The readout is informational and has nothing to click, but it sat over the map at z-12 and
   swallowed any marker click that landed under it. */







.mfilters{position:absolute;right:18px;top:calc(var(--top) + var(--wb) + 16px);z-index:12;display:flex;gap:6px;
  transition:right .22s cubic-bezier(.2,.7,.3,1)}
.mfilters .fbtn{background:#fff;box-shadow:0 3px 12px rgba(10,26,34,.10)}
/* This rule comes after .fbtn.on and has equal specificity, so without restating it here the
   selected chip kept a white background while its text stayed white — the filter that is actually
   applied rendered as a blank pill. */
.mfilters .fbtn.on{background:var(--navy);border-color:var(--navy);color:#fff}
.mfilters .fbtn.on i{box-shadow:0 0 0 1px rgba(255,255,255,.55)}
/* The card and the filters both lived at right:18px and overlapped the moment a card opened.
   The filters step aside for it rather than the card having to start below two rows of chips. */
body.pane-open .mfilters{right:calc(396px + 30px)}
body.pane-open .hint,
body.pane-open .kpis{opacity:0;pointer-events:none}
.pane{position:absolute;right:18px;top:calc(var(--top) + var(--wb) + 16px);bottom:18px;width:396px;z-index:13;
  background:#fff;border:1px solid var(--rule);border-radius:7px;box-shadow:0 8px 28px rgba(10,26,34,.16);
  overflow-y:auto;padding:17px 18px}
.pane h3{font-size:15px;color:var(--navy);margin-bottom:3px;font-weight:700}
.pane .eyebrow{font-size:10px;margin-bottom:7px}
.pane .close{float:right;border:0;background:none;font-size:18px;color:var(--muted);cursor:pointer;
  line-height:1;padding:0 2px}
.crumb b{color:var(--navy);font-weight:600}
.crumb i{font-style:normal;color:#9aa6aa;margin:0 6px}

/* next best action, filters, markets */
.act{border:1px solid var(--rule);border-left:3px solid var(--grow);border-radius:0 6px 6px 0;
  padding:11px 13px;margin:12px 0 14px;background:var(--palegreen)}
.act.now{border-left-color:var(--coral);background:#fff3ee}
.act.high{border-left-color:var(--grow)}
.act.medium{border-left-color:var(--mid);background:#f6faf7}
.act.low{border-left-color:var(--rule);background:#fafbfa}
.act .l{font-family:var(--mono);font-size:9.5px;letter-spacing:.11em;text-transform:uppercase;
  color:var(--muted)}
.act b{display:block;font-size:14px;color:var(--navy);margin:3px 0 4px;line-height:1.3}
.act span{font-size:12px;color:var(--body);line-height:1.45}
.mfilters{flex-direction:column;align-items:flex-end;gap:7px}
.frow{display:flex;gap:6px;flex-wrap:wrap;justify-content:flex-end}
.fbtn i{width:8px;height:8px;border-radius:50%;display:inline-block;margin-right:5px;vertical-align:-1px}
.sheet{position:absolute;left:var(--rail);right:0;top:calc(var(--top) + var(--wb));bottom:0;z-index:30;
  background:var(--paper);overflow-y:auto;padding:24px 30px 60px}
.sheet .close{position:absolute;right:26px;top:20px;border:0;background:none;font-size:22px;
  color:var(--muted);cursor:pointer}
.sheet table{background:#fff;border:1px solid var(--rule);border-radius:7px;overflow:hidden}
.sheet td.n{font-family:var(--mono);text-align:right;font-size:12.5px}
.sheet tr.row td.cty{font-weight:600;color:var(--navy)}
.pbar{display:flex;height:7px;border-radius:4px;overflow:hidden;background:#eef0ee;min-width:90px}
.pbar i{display:block;height:100%}

/* Source and limit notes. Every page that serves a number says where it came from and what it
   cannot answer, in the same place, so the caveat is never a thing you have to go and find. */
.limits{list-style:none;margin-top:10px;border-left:2px solid var(--amber);padding-left:14px}
.limits li{font-size:13px;color:var(--body);line-height:1.55;margin-bottom:8px}
.limits li:last-child{margin-bottom:0}
.bar{height:7px;background:#eef0ee;border-radius:4px;overflow:hidden;min-width:60px}
.bar i{display:block;height:100%;border-radius:4px;background:var(--grow)}
.num{font-family:var(--mono);text-align:right;white-space:nowrap}
.tools{display:flex;gap:8px;flex-wrap:wrap;align-items:center;margin:14px 0 4px}
.tools input,.tools select{font-family:var(--sans);font-size:13px;padding:7px 11px;border:1px solid var(--rule);
  border-radius:6px;background:#fff;color:var(--text);min-width:150px}
.tools input:focus,.tools select:focus{outline:2px solid var(--soft);outline-offset:-1px}
.tag{font-family:var(--mono);font-size:10px;letter-spacing:.06em;text-transform:uppercase;
  padding:2px 7px;border-radius:999px;border:1px solid var(--rule);color:var(--muted);white-space:nowrap}
.tag.hot{border-color:var(--coral);color:#b4472b;background:#fff4f0}
.tag.go{border-color:var(--mid);color:var(--green);background:var(--palegreen)}
.scroll{max-height:620px;overflow:auto}
/* The header has to survive the scroll. These tables run to a few hundred rows, and once the
   column names had gone past you could not tell Principal from Unspent. th already carries its own
   background, which a sticky row needs or the rows show through it. */
.scroll thead th{position:sticky;top:0;z-index:2}
.scroll thead th::after{content:"";position:absolute;left:0;right:0;bottom:-1px;height:1px;
  background:var(--rule)}

/* ---- list toolbar ----------------------------------------------------------
   Search, facets and a live count above every table in the market workspace. */
.ltools{display:flex;align-items:center;gap:10px;flex-wrap:wrap;margin:14px 0 9px}
.lfind{position:relative;display:flex;align-items:center;flex:1 1 260px;max-width:380px;
  background:#fff;border:1px solid var(--rule);border-radius:999px;padding:0 13px;height:34px;
  color:var(--muted);transition:border-color .14s,box-shadow .14s}
.lfind:focus-within{border-color:var(--growS);box-shadow:0 0 0 3px rgba(32,92,81,.10)}
.lfind svg{flex:none;opacity:.6}
.lfind input{flex:1;border:0;outline:0;background:none;font-family:var(--sans);font-size:13px;
  color:var(--ink);padding:0 0 0 8px;min-width:0}
.lfind input::-webkit-search-cancel-button{cursor:pointer}
.lchips{display:flex;gap:6px;flex-wrap:wrap}
.lcount{margin-left:auto;font-family:var(--mono);font-size:10.5px;letter-spacing:.07em;
  text-transform:uppercase;color:var(--muted);white-space:nowrap}
.lempty{padding:18px 2px}

/* ---- source links ----------------------------------------------------------
   Every figure on a workspace tab or an account card is read from a public filing. The link is
   quiet until you want it: it carries the record's own name, not "click here", and opens the
   actual page so a claim can be checked in front of whoever is asking. */
.src{display:inline-flex;align-items:center;gap:4px;margin-left:8px;font-family:var(--mono);
  font-size:10.5px;letter-spacing:.05em;text-transform:uppercase;color:var(--grow);font-weight:500;
  text-decoration:none;border:1px solid var(--growS);border-radius:4px;padding:1px 6px;
  background:var(--pale);white-space:nowrap;vertical-align:1px;transition:background .12s}
.src:hover{background:var(--grow);color:#fff;border-color:var(--grow)}
.src:hover svg{opacity:1}
.src svg{opacity:.85;flex:none}
.who2 .src,.proj .src,.bnd .src{margin-left:0;margin-top:3px}

/* Sign-in. Deliberately plain: one card, no marketing, nothing that hints at what is behind it. */
body.signin{display:flex;align-items:center;justify-content:center;min-height:100vh;
  background:radial-gradient(1200px 600px at 50% -10%,#eef4f1 0%,var(--paper) 60%);padding:24px}
.signin .card{width:100%;max-width:392px;background:#fff;border:1px solid var(--rule);
  border-radius:12px;padding:30px 30px 24px;box-shadow:0 12px 40px rgba(10,26,34,.09)}
.signin .mark{display:flex;align-items:center;gap:10px;margin-bottom:22px}
.signin .mark b{display:block;font-size:13px;color:var(--ink);letter-spacing:-.01em}
.signin .mark span{font-family:var(--mono);font-size:10px;letter-spacing:.11em;
  text-transform:uppercase;color:var(--muted)}
.signin h1{font-size:23px;letter-spacing:-.02em;color:var(--ink);margin-bottom:6px}
.signin p{font-size:13px;color:var(--muted);line-height:1.5;margin-bottom:20px}
.signin label{display:block;font-family:var(--mono);font-size:10px;letter-spacing:.1em;
  text-transform:uppercase;color:var(--muted);margin:0 0 5px}
.signin input{width:100%;font-family:var(--sans);font-size:14px;padding:10px 12px;
  border:1px solid var(--rule);border-radius:7px;background:#fff;color:var(--text);margin-bottom:15px}
.signin input:focus{outline:2px solid var(--soft);outline-offset:-1px;border-color:var(--growS)}
.signin button{width:100%;font-family:var(--sans);font-size:14px;font-weight:600;padding:11px;
  border:0;border-radius:7px;background:var(--grow);color:#fff;cursor:pointer;margin-top:3px}
.signin button:hover{background:#19493f}
.signin button:disabled{background:#8fada5;cursor:default}
.signin .err{font-size:12.5px;color:var(--risk);background:#fdf3f1;border:1px solid #f0d6d0;
  border-radius:6px;padding:8px 11px;margin-bottom:12px}
.signin .foot{font-size:11px;color:var(--muted);margin-top:16px;text-align:center}

/* Who is signed in, and the way out. */
.pill.who{border:0;cursor:pointer;font-family:var(--mono);background:rgba(255,255,255,.08);
  color:var(--oninkm);transition:color .12s,background .12s}
.pill.who:hover{color:#fff;background:rgba(255,255,255,.16)}

/* ---- the account card ---------------------------------------------------- */
/* Section rules rather than boxes: the card is long and nested panels would make it a maze. */
.pane .sect{font-family:var(--mono);font-size:10px;letter-spacing:.11em;text-transform:uppercase;
  color:var(--muted);margin:17px 0 8px;padding-top:11px;border-top:1px solid var(--lines)}
.pane .more{display:inline-block;font-family:var(--mono);font-size:10.5px;color:var(--grow);
  margin-top:7px;border-bottom:1px solid transparent}
.pane .more:hover{border-bottom-color:var(--grow)}

/* The journey strip: five stages, the one they are on filled, the ones behind them ticked. */
.jrny{display:flex;align-items:flex-start;margin:13px 0 9px;gap:0}
.jrny .st{flex:1;text-align:center;position:relative}
.jrny .st i{display:block;width:9px;height:9px;border-radius:50%;margin:0 auto 6px;
  background:#fff;border:1.5px solid var(--line);position:relative;z-index:2}
.jrny .st.done i{background:var(--growS);border-color:var(--growS)}
.jrny .st.on i{background:var(--grow);border-color:var(--grow);box-shadow:0 0 0 3px var(--palegreen)}
.jrny .st:not(:last-child):after{content:"";position:absolute;top:4px;left:50%;right:-50%;
  height:1.5px;background:var(--lines);z-index:1}
.jrny .st.done:not(:last-child):after{background:var(--growS)}
.jrny .st span{font-family:var(--mono);font-size:9px;letter-spacing:.04em;color:var(--muted);
  display:block;line-height:1.25}
.jrny .st.on span{color:var(--grow);font-weight:500}

/* What already happened: a dated trail, with the losses marked as losses. */
.pane .trail{border-left:1.5px solid var(--lines);padding-left:13px;margin-left:3px}
.pane .trail .ev{position:relative;padding-bottom:11px}
.pane .trail .ev:last-child{padding-bottom:0}
.pane .trail .ev:before{content:"";position:absolute;left:-18px;top:5px;width:7px;height:7px;
  border-radius:50%;background:var(--growS);border:1.5px solid var(--paper)}
.pane .trail .ev.miss:before{background:var(--amber)}
.pane .trail .ev.lost:before{background:var(--risk)}
.pane .trail .ev.open:before{background:#fff;border:1.5px solid var(--grow)}
.pane .trail .ev b{display:block;font-family:var(--mono);font-size:10px;letter-spacing:.06em;
  text-transform:uppercase;color:var(--muted);margin-bottom:2px}
.pane .trail .ev.lost b{color:var(--risk)}
.pane .trail .ev.miss b{color:var(--amber)}
.pane .trail .ev span{font-size:12.5px;color:var(--body);line-height:1.45}
.pane .lesson{background:#fdf6ee;border:1px solid #f0e0cb;border-radius:6px;padding:10px 12px;
  margin-top:11px;font-size:12px;color:#7a5a24;line-height:1.5}

/* Sibling schools in the same district. */
.sibs{display:flex;flex-wrap:wrap;gap:5px;margin-top:9px}
.sib{font-family:var(--mono);font-size:10px;padding:3px 8px;border-radius:999px;
  border:1px solid var(--rule);color:var(--muted);background:#fff}
.sib.hot{border-color:var(--mid);color:var(--green);background:var(--palegreen)}
.pane .gaps{list-style:none;border-left:2px solid var(--amber);padding-left:12px;margin-top:4px}
.pane .gaps li{font-size:11.5px;color:var(--body);line-height:1.5;margin-bottom:7px}
.pane .gaps li:last-child{margin-bottom:0}


/* Three numbers in the hover, so you can compare markets without clicking into each one. */
.pop .facts{display:flex;gap:13px;margin:7px 0 2px}
.pop .facts i{display:block;font-style:normal;font-family:var(--mono);font-size:13px;
  font-weight:600;color:var(--navy);letter-spacing:-.02em}
.pop .facts u{display:block;text-decoration:none;font-family:var(--mono);font-size:9px;
  letter-spacing:.07em;text-transform:uppercase;color:var(--muted);margin-top:1px}
.pop .go{display:block;font-family:var(--mono);font-size:9.5px;letter-spacing:.07em;
  text-transform:uppercase;color:var(--grow);margin-top:6px;padding-top:6px;
  border-top:1px solid var(--rule)}


/* The hover card is informational only. Without this it covers the marker it describes — and the
   bigger the marker, the more of it the card covers — so clicking California did nothing. */
.pop{pointer-events:none}
.pop .maplibregl-popup-content{pointer-events:none}


/* Zoom controls. They were at top-right, underneath the filter chips and the account card, so
   with a card open there was no way to zoom out at all. Bottom-right is clear. */
.maplibregl-ctrl-bottom-right{z-index:14}
.maplibregl-ctrl-bottom-right .maplibregl-ctrl-group{margin:0 14px 30px 0;
  box-shadow:0 3px 14px rgba(10,26,34,.18)}
.maplibregl-ctrl-group button{width:30px;height:30px}

/* What you drilled into, beside what is on screen now. Drilling frames the next level rather than
   the whole parent, so the two differ — saying so is better than letting it look like bad maths. */




/* Per-account blocks. Each only renders when this buyer has something in it. */
.pane .bnd{display:flex;align-items:baseline;gap:7px;flex-wrap:wrap;padding:5px 0;
  border-bottom:1px solid #f2f3f1;font-size:12.5px}
.pane .bnd:last-child{border-bottom:0}
.pane .bnd b{color:var(--navy)}
.pane .bnd span{color:var(--muted);font-size:11.5px;flex:1}
.pane .bnd.bad b,.pane .bnd.bad span{color:#9a8f8c}
.pane .proj{padding:9px 0;border-bottom:1px solid #f2f3f1}
.pane .proj:last-child{border-bottom:0}
.pane .proj > b{display:block;color:var(--navy);font-size:12.5px;margin-bottom:4px}
.pane .proj .tag{margin-right:4px}
.pane .who2{background:var(--pale);border-radius:6px;padding:7px 10px;margin:5px 0}
.pane .who2 b{display:block;color:var(--navy);font-size:12.5px}
.pane .who2 span{display:block;color:var(--body);font-size:11.5px;line-height:1.45}
.pane .who2 em{font-style:normal;display:inline-block;margin-top:4px}
.pane .longnote{font-size:12px;color:var(--body);line-height:1.55;background:#fafbfa;
  border:1px solid var(--lines);border-radius:6px;padding:10px 12px}
.pane .longnote.warn{background:#fdf6ee;border-color:#f0e0cb;color:#7a5a24}

/* Nothing in the card may set its own width. One unwrapped pill dragged the panel sideways and
   left a screen of blank space beside it. */
.pane{overflow-x:hidden}
.pane *{min-width:0;max-width:100%}
.pane .sect,.pane .kv,.pane .note,.pane .longnote,.pane .proj,.pane .who2,.pane .gaps li,
.pane .trail .ev span,.pane .lesson{overflow-wrap:anywhere;word-break:break-word}
.pane .tag{white-space:normal;display:inline-block;max-width:100%}
.pane .kv{display:flex;gap:10px;align-items:baseline}
.pane .kv span{flex:none}
.pane .kv b{margin-left:auto;text-align:right}

/* Collapsible card sections. The head answers "what do I do" without scrolling; the rest opens
   on a click instead of running three screens deep. */
.pane .blk{border-top:1px solid var(--lines);margin-top:14px;padding-top:2px}
.pane .blk > summary{list-style:none;cursor:pointer;display:flex;align-items:center;gap:8px;
  font-family:var(--mono);font-size:10px;letter-spacing:.11em;text-transform:uppercase;
  color:var(--muted);padding:9px 0;user-select:none}
.pane .blk > summary::-webkit-details-marker{display:none}
.pane .blk > summary:before{content:"";width:7px;height:7px;flex:none;border-right:1.4px solid #9aa6aa;
  border-bottom:1.4px solid #9aa6aa;transform:rotate(-45deg);margin-left:1px;transition:transform .14s}
.pane .blk[open] > summary:before{transform:rotate(45deg)}
.pane .blk > summary:hover{color:var(--navy)}
.pane .blk .bdg{font-style:normal;margin-left:auto;font-size:10px;color:var(--grow);
  background:var(--palegreen);border-radius:999px;padding:2px 8px;letter-spacing:.04em}
.pane .blk > *:last-child{margin-bottom:10px}

/* ---- account workspace ---------------------------------------------------
   Once an account is open the map has answered its question. It shrinks to a strip that keeps
   you oriented, the column under it becomes the other accounts worth a call while you are here,
   and the account itself gets the room it needs instead of a 400px gutter. */
body.acct #map{right:auto;width:290px;bottom:auto;height:120px;border-radius:0 0 8px 0;
  overflow:hidden;box-shadow:0 6px 18px rgba(10,26,34,.10)}
body.acct .searchwrap{display:none}
/* These three belong to the full map and have no job once the map is a strip. The selector list
   below used to run off the end of its line and swallow the .pane rule that follows, so instead of
   being hidden they were handed the pane's geometry: left+right+top+bottom with width:auto made
   "All markets" stretch into a 918x740 white pill over the map and scattered the filter chips —
   and .pane, now behind the impossible selector "body.acct body.acct .pane", never widened. */
body.acct .hint,
body.acct .mfilters,
body.acct #mkbtn{display:none}
body.acct .pane{left:calc(var(--rail) + 306px);right:18px;width:auto;
  top:calc(var(--top) + var(--wb) + 16px);bottom:18px}

.nearby{position:absolute;left:var(--rail);width:290px;top:calc(var(--top) + var(--wb) + 136px);
  bottom:18px;z-index:12;background:#fff;border:1px solid var(--rule);border-radius:0 8px 8px 0;
  border-left:0;overflow-y:auto;padding:12px 0 8px}
.nearby h4{font-family:var(--mono);font-size:10px;letter-spacing:.11em;text-transform:uppercase;
  color:var(--muted);padding:0 14px 8px;font-weight:500}
.nearby .nb{display:flex;align-items:baseline;gap:7px;width:100%;text-align:left;border:0;
  background:none;cursor:pointer;padding:5px 14px 5px 11px;border-left:3px solid transparent}
.nearby .nb:hover{background:#f7faf8}
.nearby .nb.on{background:var(--palegreen);border-left-color:var(--grow)}
.nearby .nb.u-now,.nearby .nb.u-high{border-left-color:var(--coral)}
.nearby .nb b{font-size:12.5px;color:var(--navy);font-weight:600;line-height:1.5;
  white-space:nowrap;flex:none}
.nearby .nb span{font-size:11px;color:var(--muted);line-height:1.5;overflow:hidden;
  text-overflow:ellipsis;white-space:nowrap;min-width:0}


/* Tabs across the account, so nothing is three screens down. */
.pane .tabs{display:flex;gap:2px;border-bottom:1px solid var(--rule);margin:14px 0 0;
  overflow-x:auto;scrollbar-width:none}
.pane .tabs::-webkit-scrollbar{display:none}
/* flex:none — without it the buttons shrink into each other at a narrow pane instead of
   scrolling, and the row reads "PROFILESIGNALS10FUNDING". */
.pane .tab{flex:none;font-family:var(--mono);font-size:10.5px;letter-spacing:.07em;
  text-transform:uppercase;border:0;background:none;color:var(--muted);cursor:pointer;
  padding:9px 12px;white-space:nowrap;border-bottom:2px solid transparent;margin-bottom:-1px}
.pane .tab:hover{color:var(--navy)}
.pane .tab.on{color:var(--navy);border-bottom-color:var(--grow);font-weight:500}
.pane .tab em{font-style:normal;margin-left:5px;color:var(--grow);font-size:10px}
.pane .tabbody{padding-top:16px}

/* Two columns of facts when the account has the room. */
body.acct .pane .cols{display:grid;grid-template-columns:1fr 1fr;gap:0 28px;align-items:start}
body.acct .pane .cols > .wide{grid-column:1 / -1}

/* A row that says why it is on the screen. */
.pane .rel{font-size:11.5px;color:var(--grow);background:var(--palegreen);border-radius:4px;
  padding:4px 8px;margin-top:5px;line-height:1.45}
.pane .lead{font-size:12.5px;color:var(--body);line-height:1.55;margin-bottom:12px}
.pane .big{display:flex;gap:22px;flex-wrap:wrap;margin:4px 0 14px}
.pane .big div{min-width:96px}
.pane .big .n{font-size:23px;font-weight:800;color:var(--navy);letter-spacing:-.02em;line-height:1.1}
.pane .big .n.good{color:var(--grow)}
.pane .big .n.alert{color:var(--risk)}
.pane .big .l{font-family:var(--mono);font-size:9.5px;letter-spacing:.09em;text-transform:uppercase;
  color:var(--muted);margin-top:3px}
.pane .grp2{font-family:var(--mono);font-size:10px;letter-spacing:.08em;text-transform:uppercase;
  color:var(--grow);margin:14px 0 6px;padding-top:10px;border-top:1px solid var(--lines)}
.pane .grp2:first-of-type{border-top:0;padding-top:0;margin-top:4px}

/* ---- the front door ------------------------------------------------------- */
.mkts{display:grid;grid-template-columns:repeat(auto-fill,minmax(300px,1fr));gap:14px;margin-top:14px}
.mkts.thin{grid-template-columns:repeat(auto-fill,minmax(228px,1fr));gap:10px}
.mkt{display:block;background:#fff;border:1px solid var(--rule);border-radius:9px;padding:16px 18px;
  transition:border-color .14s,box-shadow .14s,transform .14s}
.mkt:hover{border-color:var(--growS);box-shadow:0 8px 24px rgba(10,26,34,.10);transform:translateY(-1px)}
.mkt.go{border-left:3px solid var(--grow)}
.mkt .hd{display:flex;align-items:center;gap:9px;margin-bottom:10px}
.mkt .hd b{font-size:16px;color:var(--navy);letter-spacing:-.01em}
.mkts.thin .mkt{padding:12px 14px}
.mkts.thin .mkt .hd b{font-size:13.5px}
.mkt .row{display:flex;gap:12px;flex-wrap:wrap;font-family:var(--mono);font-size:11px;
  color:var(--muted);margin-bottom:8px}
.mkt .big{display:flex;gap:18px;flex-wrap:wrap;margin-bottom:11px}
.mkt .big .n{font-size:20px;font-weight:800;color:var(--navy);letter-spacing:-.02em;line-height:1.1}
.mkt .big .n.good{color:var(--grow)}
.mkt .big .l{font-family:var(--mono);font-size:9px;letter-spacing:.09em;text-transform:uppercase;
  color:var(--muted);margin-top:2px}
.mkt .cta{display:inline-block;font-family:var(--mono);font-size:10.5px;letter-spacing:.07em;
  text-transform:uppercase;color:var(--grow);margin-top:11px}
/* What we hold here, at a glance: filled is "a seller can use this", hollow is "not collected". */
.pips{display:flex;gap:10px;flex-wrap:wrap;margin-bottom:8px}
.pip{font-family:var(--mono);font-size:9.5px;letter-spacing:.05em;text-transform:uppercase;
  color:#a9b3b6;display:inline-flex;align-items:center;gap:4px}
.pip i{width:7px;height:7px;border-radius:50%;border:1.4px solid #cfd6d8;display:block}
.pip.on{color:var(--grow)}
.pip.on i{background:var(--grow);border-color:var(--grow)}
/* Mapped but not researched: present, clickable, and visibly not the same thing. */
.odotw.ghost .odot{opacity:.55}
.odotw.ghost:hover .odot{opacity:1}
.mfilters .fbtn.rd{border-color:var(--mid);color:var(--green);background:var(--palegreen)}
.mfilters .fbtn.rd.on{background:var(--grow);border-color:var(--grow);color:#fff}

/* ---- profile, signals, outreach ------------------------------------------- */
.pane .facts2{display:grid;grid-template-columns:repeat(auto-fit,minmax(190px,1fr));gap:0 24px}
.pane .f2{display:flex;gap:10px;align-items:baseline;padding:7px 0;border-bottom:1px solid #f2f3f1}
.pane .f2 span{font-family:var(--mono);font-size:10px;letter-spacing:.08em;text-transform:uppercase;
  color:var(--muted);flex:none;width:86px}
.pane .f2 b{color:var(--navy);font-size:12.5px;font-weight:600}
.pane .lines{display:grid;grid-template-columns:repeat(auto-fit,minmax(190px,1fr));gap:10px;margin-top:10px}
.pane .line{border:1px solid var(--rule);border-left:3px solid var(--grow);border-radius:0 7px 7px 0;
  padding:10px 12px;background:#fff}
.pane .line b{display:block;color:var(--navy);font-size:13px}
.pane .line span{display:block;color:var(--muted);font-size:11.5px;margin-top:2px}
.pane .tiles{display:grid;grid-template-columns:repeat(auto-fit,minmax(118px,1fr));gap:10px;margin:12px 0 4px}
.pane .tl2{background:#fff;border:1px solid var(--rule);border-radius:7px;padding:11px 13px}
.pane .tl2 b{display:block;font-size:21px;font-weight:800;color:var(--navy);letter-spacing:-.02em;line-height:1.1}
.pane .tl2 span{display:block;font-family:var(--mono);font-size:9px;letter-spacing:.08em;
  text-transform:uppercase;color:var(--muted);margin-top:3px}
.pane .tl2.hot{border-color:var(--coral);background:#fff7f4}
.pane .tl2.hot b{color:#b4472b}
.pane .sub2{font-family:var(--mono);font-size:10px;letter-spacing:.11em;text-transform:uppercase;
  color:var(--navy);margin:16px 0 8px;font-weight:500}
/* A signal: headline and reason always, the quoted scope on hover. */
.pane .sig{border:1px solid var(--rule);border-radius:7px;padding:10px 12px;margin-bottom:8px;
  background:#fff;cursor:pointer;transition:border-color .13s,box-shadow .13s}
.pane .sig:hover,.pane .sig:focus-visible{border-color:var(--growS);
  box-shadow:0 4px 14px rgba(10,26,34,.07);outline:none}
.pane .sg-hd{display:flex;align-items:center;gap:7px;flex-wrap:wrap;margin-bottom:5px}
.pane .sg-hd b{color:var(--navy);font-size:12.5px}
.pane .sg-open{font-family:var(--mono);font-size:10px;letter-spacing:.07em;text-transform:uppercase;
  color:var(--grow);margin-top:7px}
.pane .sg-open::after{content:" →"}

/* The sheet a record opens into.
   First cut was a centred white card on a full-screen dark backdrop — a modal, which blanks the
   whole product to show one paragraph. A record is not that important. The sheet now covers the
   account card and only the account card: the map, the worklist and the rail stay exactly where
   they were, so you never lose your place. Clicking anywhere off the card closes it. */
.recsheet{position:absolute;right:18px;top:calc(var(--top) + var(--wb) + 16px);bottom:18px;
  width:396px;z-index:22;background:var(--paper);border:1px solid var(--line);border-radius:10px;
  box-shadow:0 10px 40px rgba(10,26,34,.16);overflow-y:auto;padding:24px 26px 26px;
  animation:shIn .16s ease-out}
body.acct .recsheet{left:calc(var(--rail) + 306px);right:18px;width:auto}
@keyframes shIn{from{opacity:0;transform:translateY(7px)}to{opacity:1;transform:none}}
.rs-catch{position:fixed;inset:0;z-index:21}
.rs-x{position:absolute;right:12px;top:10px;border:0;background:none;font-size:21px;line-height:1;
  color:var(--muted);cursor:pointer;padding:3px 8px;border-radius:6px;z-index:2}
.rs-x:hover{background:var(--lines);color:var(--ink)}
.rs-ttl{font-size:16px;font-weight:700;color:var(--navy);letter-spacing:-.01em;padding-right:28px;
  line-height:1.3}
.rs-meta{font-family:var(--mono);font-size:10.5px;letter-spacing:.05em;text-transform:uppercase;
  color:var(--muted);margin-top:6px}
.rs-body{font-size:13.5px;line-height:1.62;color:var(--body);margin-top:14px;white-space:pre-wrap;
  padding-top:14px;border-top:1px solid var(--lines)}
.pane .ocard{border:1px solid var(--rule);border-left:3px solid var(--grow);border-radius:0 7px 7px 0;
  padding:11px 13px;margin-bottom:9px;background:#fff}
.pane .ocard .ol{font-family:var(--mono);font-size:9.5px;letter-spacing:.1em;text-transform:uppercase;
  color:var(--muted);margin-bottom:3px}
.pane .ocard b{display:block;color:var(--navy);font-size:13.5px;line-height:1.35}
.pane .ocard span{display:block;color:var(--body);font-size:12px;line-height:1.5;margin-top:4px}
.pane .ocard.quiet{border-left-color:var(--mid)}
.pane .ocard.warn{border-left-color:var(--amber);background:#fdf9f3}
.pane .ocard.warn b{color:#7a5a24}
/* Which campus a district signal is actually about. Without it a bid two towns away and a filing
   naming this school read identically. */
.pane .sg-rel{font-family:var(--mono);font-size:9.5px;letter-spacing:.08em;text-transform:uppercase;
  color:var(--muted);margin-bottom:4px}
.pane .sg-rel.here{color:var(--grow);font-weight:500}
.pane .sg-rel.sibling{color:var(--blue)}
.pane .sig:has(.sg-rel.here){border-left:3px solid var(--grow)}
.pane .tl2.here b{color:var(--grow)}
.pane .tl2.here{border-color:var(--mid);background:var(--palegreen)}
/* Buyer segments, not "owners". A high school, a community college and a city parks department
   are three different sales, and the brief segments them. Click one to filter the map to it. */










/* Market workspace tabs — one market, its own views, no global rail items. */
.mtabs{display:flex;gap:2px;border-bottom:1px solid var(--rule);margin:22px 0 0;flex-wrap:wrap}
.mtab{flex:none;font-family:var(--mono);font-size:11px;letter-spacing:.08em;text-transform:uppercase;
  color:var(--muted);padding:11px 15px;border-bottom:2px solid transparent;margin-bottom:-1px}
.mtab:hover{color:var(--navy)}
.mtab.on{color:var(--navy);border-bottom-color:var(--grow);font-weight:500}
.mtab em{font-style:normal;margin-left:6px;color:var(--grow);font-size:10.5px}
#mbody{padding-top:22px}
.lead2{font-size:14px;color:var(--body);line-height:1.6;max-width:72ch}
.lead2 b{color:var(--ink)}
/* Who owns whom, as groups rather than a flat table. */
.owns{display:grid;grid-template-columns:repeat(auto-fill,minmax(270px,1fr));gap:12px}
.own{border:1px solid var(--rule);border-radius:9px;padding:14px 16px;background:#fff}
.own.rival{border-left:3px solid var(--coral);background:#fffaf8}
.own .oh{display:flex;align-items:center;gap:8px;margin-bottom:9px}
.own .oh b{font-size:14px;color:var(--navy);letter-spacing:-.01em}
.own .oh i{font-style:normal;margin-left:auto;font-family:var(--mono);font-size:16px;
  font-weight:700;color:var(--navy)}
.own.rival .oh i{color:#b4472b}
.own .ofirms{display:flex;flex-wrap:wrap;gap:5px}
.own .ofirms span{font-size:11px;color:var(--body);background:#f4f6f5;border-radius:4px;
  padding:3px 7px;line-height:1.35}
.own.rival .ofirms span{background:#fdeee8}
.msearch{margin:20px 0 4px}
.msearch input{width:100%;max-width:460px;font-family:var(--sans);font-size:15px;padding:13px 16px;
  border:1px solid var(--rule);border-radius:9px;background:#fff;color:var(--text);
  box-shadow:0 2px 10px rgba(10,26,34,.05)}
.msearch input:focus{outline:2px solid var(--soft);outline-offset:-1px;border-color:var(--growS)}
.own.ours{border-left:3px solid var(--grow);background:var(--palegreen)}
.own.ours .oh i{color:var(--grow)}
.own.ours .ofirms span{background:#dcefe3}
/* A named dot. Only drawn when few enough remain to read — otherwise the map is a word cloud. */
/* Not position:relative. MapLibre gives every marker position:absolute and then centres it with
   transform:translate(-50%,-50%). Overriding that to relative put the wrapper back in normal flow,
   where a block div takes its parent's full width — 631px — so -50% dragged each dot 315px left and
   all 81 accounts piled up against the left edge of the map, out over the ocean, while the basemap
   drew correctly behind them. The absolute position MapLibre sets is itself a containing block, so
   .olab still anchors to the dot without this. */
.olab{position:absolute;left:50%;top:100%;transform:translate(-50%,5px);white-space:nowrap;
  line-height:1.6;font-family:var(--sans);font-size:10.5px;font-weight:500;
  letter-spacing:-.005em;color:var(--ink7);
  pointer-events:none;max-width:140px;overflow:hidden;text-overflow:ellipsis;
  text-shadow:0 0 3px #fff,0 0 3px #fff,0 0 6px #fff,0 1px 2px #fff}
.olab.hot{color:#b4472b;font-weight:600}
.olab.q{opacity:0;transition:opacity .1s}
.odotw:hover .olab.q{opacity:1}
.odotw:hover .olab{background:#fff;border:1px solid var(--growS);border-radius:999px;
  padding:1px 8px;color:var(--grow);font-weight:600;max-width:200px;z-index:6;
  box-shadow:0 2px 8px rgba(10,26,34,.14);text-shadow:none}


/* ---- the readout -----------------------------------------------------------
   One tile shape everywhere: label, number, sub-line. The sub-line always renders, even empty,
   so every number sits on the same baseline. Segment tiles are pickable and carry an accent;
   the rest are a readout and stay quiet. */
.kpis{position:absolute;left:calc(var(--rail) + 16px);right:18px;bottom:18px;z-index:12;
  display:flex;gap:14px;align-items:stretch;justify-content:space-between;pointer-events:none}
.kgroup{display:flex;background:#fff;border:1px solid var(--rule);border-radius:9px;
  box-shadow:0 6px 22px rgba(10,26,34,.12);overflow:hidden;pointer-events:auto}
.kt{position:relative;padding:12px 18px 11px;border-right:1px solid var(--lines);min-width:124px;
  display:flex;flex-direction:column;justify-content:flex-start}
.kt:last-child{border-right:0}
.kl{font-family:var(--mono);font-size:9px;letter-spacing:.12em;text-transform:uppercase;
  color:var(--muted);line-height:1.2;min-height:22px}
.kn{font-size:24px;font-weight:800;color:var(--navy);letter-spacing:-.025em;line-height:1.08;
  font-variant-numeric:tabular-nums;margin-top:1px}
.kn small{font-size:13px;font-weight:600;color:var(--muted);letter-spacing:-.01em}
.ks{font-family:var(--mono);font-size:9.5px;letter-spacing:.03em;color:var(--muted);
  margin-top:5px;line-height:1.3;display:flex;align-items:center;gap:4px;min-height:13px}
.dotm{width:5px;height:5px;border-radius:50%;background:var(--grow);display:inline-block;flex:none}
.kt.pick{cursor:pointer}
.kt.pick:before{content:"";position:absolute;left:0;right:0;top:0;height:2px;background:transparent;
  transition:background .14s}
.kt.pick:hover{background:#f7faf8}
.kt.pick:hover:before{background:var(--mid)}
.kt.on{background:var(--palegreen)}
.kt.on:before{background:var(--grow)}
.kt.on .kn{color:var(--grow)}
.kt.muted .kn{color:#b4bcbe;font-weight:700}
.kt.muted{cursor:default}
.kt.muted:hover{background:none}
.kt.muted:hover:before{background:transparent}
.kt.ctx{background:var(--palegreen);border-right-color:var(--mid)}
.kt.ctx .kn{font-size:19px;color:var(--grow)}
.kt.warn .kn{color:var(--amber)}
@media (max-width: 1240px){ .kgroup.right .kt:nth-child(n+3){display:none} }


/* ---- whose system this is --------------------------------------------------
   The client's own wordmark at the top of the rail and in the workspace bar, in place of the
   initial chip. The text label stays in the markup for the tenant rewrite and for screen readers;
   the image carries it visually. */
.ws .lg,.wb .lg{height:15px;width:auto;display:block;flex:none}
.wb .lg{height:13px}
.ws .lg + div b,.wb .lg + b{position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0 0 0 0);
  clip-path:inset(50%);white-space:nowrap}
.ws{align-items:center;gap:9px}
.byline{margin-top:auto;padding:16px 14px 14px;border-top:1px solid rgba(255,255,255,.08);
  display:flex;flex-direction:column;gap:1px}
.byline .bl-mark{display:flex;align-items:center;gap:7px;color:var(--growS)}
.byline .bl-mark svg{flex:none}
.byline b{font-size:17px;color:#fff;font-weight:700;letter-spacing:-.02em;line-height:1}
.byline span{font-family:var(--mono);font-size:9px;letter-spacing:.14em;text-transform:uppercase;
  color:rgba(255,255,255,.46);line-height:1.35;margin-top:7px;padding-top:7px;
  border-top:1px solid rgba(255,255,255,.1)}
.byline em{font-family:var(--mono);font-size:9px;letter-spacing:.1em;text-transform:uppercase;
  color:rgba(255,255,255,.5);font-style:normal;margin-top:3px}
.byline em strong{color:rgba(255,255,255,.88);font-weight:500}
.sb{display:flex;flex-direction:column}
/* ---- the front door: one field, and the few places worth opening ---------- */
.door .hero{max-width:760px;margin-top:4px}
.door h1{font-size:30px;letter-spacing:-.025em}
.door .lede{font-size:14.5px;color:var(--muted);max-width:64ch}
.finder{position:relative;margin-top:26px;max-width:620px}
.finder .fic{position:absolute;left:17px;top:50%;transform:translateY(-50%);color:var(--muted);
  pointer-events:none}
.finder input{width:100%;box-sizing:border-box;height:54px;padding:0 18px 0 46px;font-size:16px;
  font-family:var(--sans);color:var(--text);background:#fff;border:1px solid var(--line);
  border-radius:11px;outline:none;transition:border-color .12s,box-shadow .12s}
.finder input::placeholder{color:#9aa7ad}
.finder input:focus{border-color:var(--growS);box-shadow:0 0 0 3px rgba(125,179,164,.22)}
.finder input::-webkit-search-cancel-button{-webkit-appearance:none}
.rlist{position:absolute;left:0;right:0;top:60px;z-index:30;background:#fff;
  border:1px solid var(--line);border-radius:11px;box-shadow:0 18px 44px rgba(10,26,34,.16);
  max-height:396px;overflow:auto;padding:6px}
.rgrp{font-family:var(--mono);font-size:9.5px;letter-spacing:.11em;text-transform:uppercase;
  color:var(--muted);padding:10px 12px 5px}
.ritem{display:flex;align-items:baseline;gap:10px;padding:8px 12px;border-radius:7px;
  text-decoration:none;color:inherit}
.ritem:hover,.ritem.on{background:var(--pale)}
.ritem .rn{font-size:14px;color:var(--navy);font-weight:500;white-space:nowrap}
.ritem .rn b{font-weight:800;color:var(--grow)}
.ritem .rm{font-size:11.5px;color:var(--muted);margin-left:auto;text-align:right;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.rnone{padding:18px 14px;font-size:13px;color:var(--muted);line-height:1.5}

.prows{margin-top:14px;border-top:1px solid var(--lines);max-width:860px}
.prow{display:flex;align-items:center;gap:14px;padding:15px 4px;text-decoration:none;color:inherit;
  border-bottom:1px solid var(--lines);transition:background .12s,padding-left .12s}
.prow:hover{background:var(--pale);padding-left:10px}
.prow .pk{font-family:var(--mono);font-size:9px;letter-spacing:.1em;text-transform:uppercase;
  color:var(--muted);width:62px;flex:none}
.prow .pn{font-size:15.5px;font-weight:600;color:var(--navy);letter-spacing:-.01em;flex:none}
.prow .pm{font-size:12px;color:var(--muted);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.prow .pa{font-family:var(--mono);font-size:11px;color:var(--grow);margin-left:auto;flex:none}
.prow .pg{color:var(--growS);flex:none}
@media (max-width:860px){.prow .pm{display:none}}

/* Caveats stay available, not shouted: closed by default, at the foot of the page. */
.method{margin-top:40px;border-top:1px solid var(--lines);padding-top:14px;max-width:80ch}
.method summary{font-family:var(--mono);font-size:10px;letter-spacing:.11em;text-transform:uppercase;
  color:var(--muted);cursor:pointer;list-style:none;outline:none}
.method summary::-webkit-details-marker{display:none}
.method summary::before{content:"+ ";color:var(--growS)}
.method[open] summary::before{content:"– "}
.method summary:hover{color:var(--grow)}
.method .note,.method .limits{margin-top:10px}

/* ---- where a district publishes, and what its money may buy -------------- */
.doors{margin-top:12px;border-top:1px solid var(--lines)}
.drow{display:flex;align-items:center;gap:10px;flex-wrap:wrap;padding:9px 2px;
  border-bottom:1px solid var(--lines)}
.drow b{font-size:13px;color:var(--navy);min-width:230px}
a.door{display:inline-flex;align-items:center;gap:4px;font-family:var(--mono);font-size:10.5px;
  letter-spacing:.04em;color:var(--grow);text-decoration:none;border:1px solid var(--lines);
  border-radius:999px;padding:3px 9px;background:#fff}
a.door:hover{border-color:var(--growS);background:var(--pale)}
.meas{display:grid;grid-template-columns:repeat(auto-fill,minmax(330px,1fr));gap:12px;margin-top:12px}
.meas1{background:#fff;border:1px solid var(--rule);border-left:3px solid var(--line);
  border-radius:9px;padding:13px 15px}
.meas1.yes{border-left-color:var(--grow)}
.meas1.no{border-left-color:var(--amber)}
.meas1 .mh{display:flex;align-items:center;gap:8px;flex-wrap:wrap}
.meas1 .mh b{font-size:13px;color:var(--navy)}
.meas1 .mh span{font-family:var(--mono);font-size:11px;color:var(--muted)}

/* ---- each section answers a different question, so each reads differently --
   Every tab was the same white with the same grey heading, so Profile, Signals and Funding were
   told apart only by reading them. The accent is carried on the tab and on the section headings
   inside it: enough to know where you are at a glance, not so much that the card turns into a
   paint chart. The coral "do this" band keeps working precisely because nothing else looks like
   it, so no section borrows coral. */
.pane .tab.on{color:var(--navy);border-bottom-color:var(--grow);font-weight:500}
.pane .tab.t-now.on{border-bottom-color:var(--grow)}
.pane .tab.t-work.on{border-bottom-color:var(--blue)}
.pane .tab.t-money.on{border-bottom-color:var(--grow)}
.pane .tab.t-people.on{border-bottom-color:var(--exec)}
.pane .tab.t-buying.on{border-bottom-color:var(--amber)}
.pane .tab.t-reach.on{border-bottom-color:var(--coral)}
.pane .tab.t-gaps.on{border-bottom-color:var(--muted)}

.pane .sub2{display:flex;align-items:center;gap:9px;font-family:var(--mono);font-size:10px;
  letter-spacing:.11em;text-transform:uppercase;color:var(--navy);margin:20px 0 9px;
  font-weight:500}
.pane .sub2::before{content:"";width:3px;height:13px;border-radius:2px;background:var(--line);
  flex:none}
.pane[data-tab="now"] .sub2::before{background:var(--grow)}
.pane[data-tab="work"] .sub2::before{background:var(--blue)}
.pane[data-tab="money"] .sub2::before{background:var(--grow)}
.pane[data-tab="people"] .sub2::before{background:var(--exec)}
.pane[data-tab="buying"] .sub2::before{background:var(--amber)}
.pane[data-tab="reach"] .sub2::before{background:var(--coral)}
.pane[data-tab="gaps"] .sub2::before{background:var(--muted)}

/* The Sport Group lines are the commercial point of the card. They were rendered in the same
   bordered box as a postcode. */
.pane .lines{display:grid;grid-template-columns:repeat(auto-fit,minmax(150px,1fr));gap:10px;
  margin-top:11px}
.pane .lines .ln{background:var(--pale);border:1px solid var(--growS);border-radius:9px;
  padding:12px 14px}
.pane .lines .ln b{display:block;color:var(--grow);font-size:13.5px;letter-spacing:-.01em}
.pane .lines .ln span{display:block;font-size:11.5px;color:var(--body);margin-top:3px;
  line-height:1.4}

/* ---- the shared-money box --------------------------------------------------
   Campuses in the same district share one measure and usually one contractor. That is a single
   fact about the group, not a repeated sentence under each school's name. */
.shared{margin:0 10px 14px;background:var(--pale);border:1px solid var(--growS);border-radius:9px;
  padding:12px 13px 11px}
.shared .sh-h{font-family:var(--mono);font-size:9px;letter-spacing:.12em;text-transform:uppercase;
  color:var(--grow);margin-bottom:4px}
.shared b{display:block;font-size:13px;color:var(--navy);line-height:1.3}
.shared .sh-n{font-size:11.5px;color:var(--body);margin-top:3px}
.shared .sh-m{font-family:var(--mono);font-size:10.5px;color:var(--grow);margin-top:5px}
.chips{display:flex;flex-wrap:wrap;gap:5px;margin-top:9px}
.chip2{display:inline-flex;align-items:center;gap:4px;border:1px solid var(--growS);background:#fff;
  border-radius:999px;padding:3px 9px;font-family:var(--sans);font-size:11px;color:var(--navy);
  cursor:pointer;line-height:1.5}
.chip2:hover{background:var(--grow);color:#fff;border-color:var(--grow)}
.chip2 i{font-style:normal;font-family:var(--mono);font-size:9px;color:var(--grow);
  background:var(--pale);border-radius:8px;padding:0 4px}
.chip2:hover i{background:rgba(255,255,255,.22);color:#fff}
.nearby h4{padding-top:4px}

/* The map credit is required by OpenStreetMap's licence and CARTO's terms, so it stays — but as
   a quiet marker in the corner, not a sentence across the bottom of the map. */
.maplibregl-ctrl-attrib.maplibregl-compact{min-height:22px;background:rgba(255,255,255,.88);
  border-radius:11px;box-shadow:0 1px 4px rgba(10,26,34,.12)}
.maplibregl-ctrl-attrib.maplibregl-compact:not(.maplibregl-compact-show){width:22px;height:22px}
.maplibregl-ctrl-attrib-button{opacity:.55}
.maplibregl-ctrl-attrib-button:hover{opacity:1}
.maplibregl-ctrl-attrib.maplibregl-compact-show{font-size:10.5px}

/* ---- the basemap comparison page ---------------------------------------- */
body.styles{margin:0;overflow:hidden}
body.styles #map{position:fixed;inset:0}
.stpick{position:fixed;left:18px;top:18px;z-index:20;background:#fff;border:1px solid var(--line);
  border-radius:11px;padding:10px;box-shadow:0 10px 34px rgba(10,26,34,.16);display:flex;
  flex-direction:column;gap:3px;width:216px}
.stp-h{font-family:var(--mono);font-size:9.5px;letter-spacing:.13em;text-transform:uppercase;
  color:var(--muted);padding:2px 8px 6px}
.stp{text-align:left;border:0;background:none;font-family:var(--sans);font-size:13.5px;
  color:var(--text);padding:8px 10px;border-radius:7px;cursor:pointer}
.stp:hover{background:var(--pale)}
.stp.on{background:var(--grow);color:#fff;font-weight:500}
.stp.back{margin-top:7px;padding-top:11px;border-top:1px solid var(--lines);border-radius:0;
  font-family:var(--mono);font-size:10.5px;letter-spacing:.06em;text-transform:uppercase;
  color:var(--grow);text-decoration:none}
.stnote{position:fixed;left:18px;bottom:18px;z-index:20;background:#fff;border:1px solid var(--line);
  border-radius:11px;padding:14px 16px;box-shadow:0 10px 34px rgba(10,26,34,.16);max-width:340px}
.stnote b{display:block;font-size:14px;color:var(--navy);letter-spacing:-.01em}
.stnote span{display:block;font-size:12.5px;color:var(--body);line-height:1.5;margin-top:4px}
