/* AmWatt Transmission Planner — page stylesheet.
 * Extracted from the former monolith public/app.html so the UX is readable and
 * cacheable under the Next.js app (see scripts/app-version.mjs for ?v= stamps).
 */
  /* ================================================================
     AmWatt Transmission Planner — professional light theme
     Visual language modeled on the MapBiomas platform: white rounded
     cards on a cool-gray canvas, petrol-teal accent, green circular
     check toggles, pill buttons/segments, soft layered shadows.
     Every selector from the previous (dark) sheet is preserved so the
     app's JS — which only toggles classes — is untouched.
     ================================================================ */
  @import url('https://fonts.googleapis.com/css2?family=Lato:wght@400;700;900&display=swap');
  /* American Terawatt brand face kept as fallback */
  @font-face{font-family:"Untitled Sans";src:url(fonts/untitled-sans/Light.woff2) format("woff2");font-weight:300;font-display:swap}
  @font-face{font-family:"Untitled Sans";src:url(fonts/untitled-sans/Regular.woff2) format("woff2");font-weight:400;font-display:swap}
  @font-face{font-family:"Untitled Sans";src:url(fonts/untitled-sans/Medium.woff2) format("woff2");font-weight:500;font-display:swap}
  @font-face{font-family:"Untitled Sans";src:url(fonts/untitled-sans/Bold.woff2) format("woff2");font-weight:700;font-display:swap}
  :root { --bg:#EDF1F4; --surface:#FFFFFF; --panel:#F3F6F9; --hover:#EBF2F6; --line:#DFE6EC; --divider:#E7EDF1;
    --text:#1D2936; --muted:#556474; --muted2:#8794A4; --accent:#2A5674; --accent-deep:#152F47; --accent-soft:#E1E9F1;
    --on-accent:#FFFFFF; --green:#3AA66F; --green-soft:#E1F3E9;
    --supply:#39B252; --load:#111827; --pro:#2E9E63; --con:#D96856; --con-soft:#FBE9E5;
    --shadow-sm:0 1px 3px rgba(28,48,64,.08); --shadow:0 4px 18px rgba(28,48,64,.12); --shadow-lg:0 14px 40px rgba(28,48,64,.18);
    --btnbd:#CFDAE2; --btnbd2:#B9C9D4; --ckbd:#B7C4CF; --track:#E7EDF1; --scroll:#C7D2DC;
    --glass:rgba(255,255,255,.96); --glass2:rgba(255,255,255,.95); --selbg:#F1F6FB;
    --toastbg:rgba(0,0,0,.80); --toastbg-solid:#000000; --toasttx:#FFFFFF; --chipoff:#E7EBEF;
    --hitint:rgba(42,86,116,.10); --hitint2:rgba(42,86,116,.16);
    --route-ink:#27272A; --route-outline-opacity:.5; --risk-high:#C2413B; --risk-medium:#B7791F;
    /* Route and infrastructure palette. */
    --color-blue-60:rgba(79,163,247,1); --color-blue-50:rgba(0,98,235,1); --color-cyan-60:rgba(6,182,212,1);
    --color-green-60:rgba(57,178,82,1); --color-green-35:rgba(47,107,60,1); --color-red-55:rgba(192,57,43,1);
    --color-orange-35:rgba(176,86,7,1); --color-orange-48:rgba(223,114,19,1); --color-orange-59:rgba(231,145,70,1);
    --color-orange-70:rgba(232,176,127,1); --color-orange-82:rgba(238,207,181,1); --color-teal-36:rgba(24,158,144,1);
    --color-yellow-62:rgba(239,211,79,1); --color-ochre-45:rgba(201,162,39,1); --color-orchid-55:rgba(190,92,180,1);
    --color-gray-71:rgba(181,181,181,1); --color-slate-35:rgba(74,85,96,1); --color-hover:rgba(17,24,39,1);
    --color-blue-alt-1:rgba(55,119,230,1); --color-blue-alt-2:rgba(94,142,225,1); --color-blue-alt-3:rgba(129,163,222,1);
    --color-blue-alt-4:rgba(161,183,223,1); --color-blue-alt-5:rgba(189,203,227,1); --color-blue-alt-6:rgba(215,222,234,1);
    --color-moss-38:rgba(110,139,61,1); --color-terracotta-47:rgba(181,83,58,1); --color-earthyellow-38:rgba(158,133,36,1);
    --color-bronze-43:rgba(154,107,63,1); --color-sage-56:rgba(143,163,122,1);
    /* right column width. Its collapse handle is pinned to the same value, so widening the
       column without this would leave the handle floating over the panel. */
    --rbw:413px;
    /* left column width — same deal as --rbw: #lbtoggle is pinned to it, so a hard-coded 276px here
       would leave the collapse handle stranded mid-panel the moment the bar is dragged. */
    --lbw:276px;
    --r:12px; --r-sm:8px; --r-round:9999px; --r-none:0;
    --font-ui:"Lato","Untitled Sans",system-ui,sans-serif;
    --font-2xs:10px; --font-xs:11.5px; --font-sm:12.5px; --font-md:14px; --font-lg:16px; --font-display:40px;
    --space-1:4px; --space-2:8px; --space-3:12px; --space-4:16px; --space-5:20px; --space-6:24px;
    --ease-out:cubic-bezier(.23,1,.32,1);
    --dur-press:120ms; --dur-ui:200ms; --control-h:36px; }
  /* ── accent options — the white canvas stays; buttons & chrome recolour ── */
  /* true black chrome on the white canvas (2026-07): buttons/active chips go black */
  html[data-accent="black"] { --accent:#15181C; --accent-deep:#000000; --accent-soft:#ECEEF0; --hitint:rgba(20,24,28,.10); --hitint2:rgba(20,24,28,.16); }
  html[data-accent="teal"]  { --accent:#1E7E9E; --accent-deep:#135E77; --accent-soft:#DDEEF5; --hitint:rgba(30,126,158,.10); --hitint2:rgba(30,126,158,.16); }
  html[data-accent="green"] { --accent:#1F7A46; --accent-deep:#14532D; --accent-soft:#DFF0E7; --hitint:rgba(31,122,70,.10); --hitint2:rgba(31,122,70,.16); }
  .accrow { display:flex; align-items:center; gap:8px; }
  .accrow .acclab { font-size:10px; font-weight:700; letter-spacing:.08em; text-transform:uppercase; color:var(--muted2); margin-right:2px; }
  .accdot { width:20px; height:20px; border-radius:50%; border:2px solid #fff; box-shadow:0 0 0 1.5px var(--line); cursor:pointer; padding:0; transition:box-shadow .12s, transform .12s; }
  .accdot:hover { box-shadow:0 0 0 2px var(--muted2); }
  .accdot.on { box-shadow:0 0 0 2.5px var(--accent); transform:scale(1.1); }
  * { box-sizing:border-box; }
  html,body { margin:0; height:100%; font-family:var(--font-ui); color:var(--text); background:var(--bg); -webkit-font-smoothing:antialiased; }
  body:focus { outline:none; }
  #app { display:flex; height:100%; }
  /* scrollbar-gutter:stable — THE SIDEBAR MUST NOT CHANGE WIDTH (Shubh 2026-07-30: "when i click
     'use' on the table, the table increases a bit in size - that should not happen, it should be
     static"). This panel is overflow-y:auto, so its scrollbar appeared and disappeared as content
     grew and shrank — and pressing Edit does exactly that, because it clears the selection and the
     detail panel under the table goes away. Every percentage-width child then re-laid-out against a
     content box ~9px wider. The compare table made it obvious (its columns are 1fr), but the shift
     was always there for everything in here. Reserving the gutter always costs 9px of a 413px panel
     and buys a width that never moves. */
  .bar { flex:none; display:flex; flex-direction:column; overflow-y:auto; scrollbar-gutter:stable;
    background:var(--bg); position:relative; }
  .bar > * { flex:none; }               /* children keep natural height — the BAR scrolls (was: flex-shrink squashed + clipped "Map data layers") */
  #leftbar > :last-child { margin-bottom:12px; }
  #leftbar { width:var(--lbw); border-right:1px solid var(--line); }
  /* --rbw is 344 × 1.2 (Shubh 2026-07-28). The candidate cards live in here at 88% of its width,
     so this is also what gives the ROW-followed rows and the stat boxes room to sit unwrapped. */
  #rightbar { width:var(--rbw); border-left:1px solid var(--line); background:var(--surface); }
  /* DRAG THE PANEL WIDER OR NARROWER (Shubh 2026-08-01: "i want to be able to drag the right
     sidebar in and out"). A 6px grab strip on the panel's left edge — wider than the 1px border it
     sits on, because a 1px target is not draggable in practice. position:fixed rather than absolute
     inside the panel: #rightbar scrolls, and an absolutely-positioned child would scroll away from
     the edge it is supposed to be pinned to.
     Everything else follows for free — the width is already the --rbw custom property, so the
     collapse handle (#rbtoggle, right:var(--rbw)) and the panel's own layout track it with no extra
     wiring. That is why this is a variable write and not a style write. */
  #rbdrag { position:fixed; top:0; bottom:0; right:var(--rbw); width:6px; margin-right:-3px;
    z-index:7; cursor:col-resize; }
  body.rb-collapsed #rbdrag { display:none; }
  #rbdrag::after { content:""; position:absolute; inset:0 2px; background:transparent; transition:background .12s; }
  #rbdrag:hover::after, body.rb-dragging #rbdrag::after { background:var(--accent); }
  /* THE LEFT BAR STRETCHES TOO (Shubh 2026-08-04: "same way right bar stretches, can we also make
     the left bar able to stretch"). Deliberately the same mechanism rather than a second one: one
     custom property, one 6px fixed strip on the bar's outer edge, one class while dragging. The
     three states that hide or unpin the bar hide the strip with it — dragging the width of a
     collapsed rail, or of a viewer's absent panel, would move a number nothing is reading. */
  #lbdrag { position:fixed; top:0; bottom:0; left:var(--lbw); width:6px; margin-left:-3px;
    z-index:7; cursor:col-resize; }
  body.lb-collapsed #lbdrag, body.lb-min #lbdrag, body.viewonly #lbdrag { display:none; }
  #lbdrag::after { content:""; position:absolute; inset:0 2px; background:transparent; transition:background .12s; }
  #lbdrag:hover::after, body.lb-dragging #lbdrag::after { background:var(--accent); }
  /* While dragging, nothing else should take the pointer or start selecting text. */
  body.rb-dragging, body.lb-dragging { cursor:col-resize; user-select:none; }
  body.rb-dragging #map, body.rb-dragging iframe,
  body.lb-dragging #map, body.lb-dragging iframe { pointer-events:none; }
  body.rb-collapsed #rightbar { display:none; }
  /* VIEW-ONLY (Shubh 2026-07-27). The server resolved this caller's role on the open design to
     "viewer", so every affordance that would WRITE leaves the page. Declarative on purpose:
     the panels re-render constantly (candidate cards, pair list, imported-route panel), and a
     JS sweep would have to chase every re-render — a descendant selector cannot be outrun.
     Reading stays whole: pan/zoom, search, hover cards, candidate cards and their ROW/parcel
     breakdowns, Measure, the 3D flythrough, the feasibility report. Only applyRoleUI() sets
     this class, and only when the server EXPLICITLY says viewer — see its fail-open note. */
  body.viewonly #leftbar, body.viewonly #lbtoggle, body.viewonly #addpoints,
  /* Import WRITES (it registers points and forms pairs), so it leaves for a viewer — unlike Export
     and Share next to it, which only read. */
  body.viewonly #importbtn, body.viewonly #importmenu,
  body.viewonly #mapclear, body.viewonly #getstarted, body.viewonly .bp-lede,
  body.viewonly #ed-edit, body.viewonly #ed-undo,
  body.viewonly #ed-reset, body.viewonly #ed-savefelt,
  body.viewonly #rd-edit, body.viewonly #rd-save,
  body.viewonly #pareto-run, body.viewonly #pp-runsec,
  body.viewonly [data-paadopt], body.viewonly [data-bpadopt],
  body.viewonly #imp-panel .imp-list, body.viewonly #imp-panel .imp-btns { display:none !important; }
  /* BOOKMARKS are the one thing here a viewer keeps in full: the panel, the rows, the notes and
     the pulsing markers all stay, because that is what a shared design is FOR. Only the controls
     that write leave — every one of them carries .bm-mut. (bmControlHtml and bmRender also refuse
     to emit them for a viewer; this class is the declarative backstop, for the same reason the
     rest of this block is declarative: these panels re-render constantly.) */
  body.viewonly .bm-mut { display:none !important; }
  /* the design title is click-to-rename; dtBeginEdit refuses too, this kills the affordance */
  body.viewonly #dtitle { cursor:default; pointer-events:none; }
  .dt-state.viewer { color:var(--muted2); border:1px solid var(--line); border-radius:999px; padding:2px 7px; }
  /* lb-min (Shubh 2026-07-27): generating candidate routes collapses the left column to JUST
     the floating AmWatt logo — no panel behind it — so the map gets the room. Distinct from
     lb-collapsed, which hides the logo too. The bar goes position:absolute so it leaves the
     flex flow and the map fills the freed width; only .brand stays, transparent and clickable.
     #lbtoggle stays as the way back (its handler clears lb-min). */
  body.lb-min #leftbar, body.lb-collapsed #leftbar { position:absolute; top:0; left:0; z-index:20; width:auto;
    background:transparent; border-right:none; overflow:visible; pointer-events:none; }
  body.lb-min #leftbar > *:not(.brand), body.lb-collapsed #leftbar > *:not(.brand) { display:none; }
  body.lb-min #leftbar .brand, body.lb-collapsed #leftbar .brand { border-bottom:none; background:transparent; pointer-events:auto; }
  /* JUST the logo mark — the "AMERICAN TERAWATT / TRANSMISSION PLANNER" wordmark was still
     rendering and landing on top of the search field, which is unreadable and was never the
     intent ("only a logo should be visible in top left"). */
  body.lb-min #leftbar .brand .wm, body.lb-collapsed #leftbar .brand .wm { display:none; }
  /* ...and the top-left map control stack moves DOWN so it sits UNDER the floating logo rather than
     behind it (Shubh 2026-07-27: "lat long should go under"). The whole column shifts: the
     lat/lng search first, then "Add a point…", which lives in #addpoints and so keeps stacking
     under it as it always did. ("Upload edges" used to sit here too — removed 2026-08-03.) */
  body.lb-min #mapsearch, body.lb-collapsed #mapsearch { top:54px; }
  body.lb-min #addpoints, body.lb-collapsed #addpoints { top:98px; }
  body.lb-min #lbtoggle { left:0; }
  /* collapse toggles: circles straddling the sidebar/map boundary, vertically centred */
  .edgetog { position:fixed; top:50%; z-index:21; width:32px; height:32px; border-radius:50%;
    border:1px solid var(--line); background:var(--surface); color:var(--muted); font:inherit; font-size:15px;
    font-weight:700; line-height:1; cursor:pointer; box-shadow:var(--shadow);
    display:flex; align-items:center; justify-content:center; padding:0 0 2px; }
  .edgetog:hover { background:var(--hover); color:var(--accent-deep); }
  #lbtoggle { left:var(--lbw); transform:translate(-50%,-50%); }
  #rbtoggle { right:var(--rbw); transform:translate(50%,-50%); }
  body.lb-collapsed #lbtoggle { left:0; }
  body.rb-collapsed #rbtoggle { right:0; }
  #userbar { display:flex; flex-direction:column; align-items:flex-end; gap:7px; padding:9px 14px 10px;
    border-bottom:1px solid var(--line); font-size:11px; color:var(--muted); background:var(--surface); }
  #userbar .ub-row { display:flex; align-items:center; gap:10px; max-width:100%; }
  #userbar #useremail { overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
  #userbar #logout { color:var(--accent); text-decoration:underline; cursor:pointer; flex:none; }
  #userbar #opendesigns { padding:6px 12px; font-size:11.5px; }

  #mapwrap { flex:1; min-width:0; position:relative; background:var(--bg); }
  #coordhud { position:absolute; bottom:44px; left:12px; z-index:6; display:flex; align-items:center; gap:8px;  /* lifted above Felt's scale bar / zoom badge */
    border:1px solid var(--line); background:var(--surface); color:var(--text); font:inherit; font-size:11.5px;
    font-variant-numeric:tabular-nums; padding:6px 12px; border-radius:999px; cursor:pointer; box-shadow:var(--shadow); }
  #coordhud:hover { background:var(--hover); }
  #coordhud .cc { font-size:9.5px; font-weight:700; text-transform:uppercase; letter-spacing:.04em; color:var(--muted2); }
  body.routing #coordhud { bottom:132px; }   /* lift clear of the taller route toolbar */
  /* route toolkit — fixed bottom toolbar over the map; wraps so every control stays visible */
  #edbar { position:absolute; left:0; right:0; bottom:0; z-index:8; display:flex; flex-direction:column; align-items:stretch; gap:12px;
    padding:14px 18px 18px; background:var(--glass); border-top:1px solid var(--line);
    box-shadow:0 -6px 24px rgba(28,48,64,.10); backdrop-filter:blur(6px); }
  #edbar.hide { display:none; }
  /* the toggle straddles the top edge of the bar so it is reachable in BOTH states */
  #edbar-tog { position:absolute; top:-15px; left:50%; transform:translateX(-50%); height:26px;
    display:flex; align-items:center; gap:8px; padding:0 12px; border:1px solid var(--line);
    border-radius:999px; background:var(--surface); color:var(--text); font:inherit; font-size:11px;
    font-weight:600; cursor:pointer; box-shadow:var(--shadow-sm); z-index:2; white-space:nowrap; }
  #edbar-tog:hover { border-color:var(--accent); }
  #edbar-tog .ebt-c { color:var(--muted); font-size:12px; line-height:1; }
  /* collapsed: everything but the handle goes, and the bar stops reserving height */
  #edbar.ebmin { padding:0; background:transparent; border-top:0; box-shadow:none;
    backdrop-filter:none; pointer-events:none; }
  #edbar.ebmin > * { display:none !important; }
  #edbar.ebmin > #edbar-tog { display:flex !important; pointer-events:auto; top:auto; bottom:12px; }
  #edbar.ebmin > #edbar-tog .ebt-c { transform:rotate(180deg); }
  #edbar .eb-hint { font-size:11px; color:var(--muted); line-height:1.4; margin-bottom:-4px; }
  #edbar .eb-main { display:flex; align-items:center; gap:14px 18px; flex-wrap:wrap; }
  /* rights-of-way composition bar — each stretch coloured by the ROW it follows, width ∝ miles */
  #rowbar { display:flex; flex-direction:column; gap:5px; }
  #rowbar.hide { display:none; }
  #rowbar .rb-bar { display:flex; height:14px; width:100%; border-radius:7px; overflow:hidden; border:1px solid var(--line); }
  #rowbar .rb-seg { min-width:2px; height:100%; }
  #rowbar .rb-legend { display:flex; flex-wrap:wrap; gap:3px 14px; font-size:10.5px; color:var(--muted); }
  #rowbar .rb-chip { display:inline-flex; align-items:center; gap:5px; white-space:nowrap; }
  #rowbar .rb-chip i { width:10px; height:10px; border-radius:3px; flex:none; }
  #rowbar .rb-chip b { color:var(--text); font-weight:700; }
  #edbar .eb-stats { display:flex; gap:20px; flex:none; }
  #edbar .eb-stat { display:flex; flex-direction:column; line-height:1.05; white-space:nowrap; }
  #edbar .eb-stat .k { font-size:8.5px; font-weight:700; text-transform:uppercase; letter-spacing:.06em; color:var(--muted2); }
  #edbar .eb-stat b { font-size:17px; font-weight:800; letter-spacing:-.02em; color:var(--text); }
  #edbar .eb-cp { cursor:pointer; } #edbar .eb-cp:hover .k { color:var(--accent-deep); }
  #cp-break { align-self:center; display:flex; flex-wrap:wrap; gap:2px 14px; max-width:44%; font-size:11px; color:var(--muted2); }
  #cp-break .cpi { white-space:nowrap; } #cp-break .cpi b { color:var(--muted); font-weight:800; }
  #edbar .eb-actions { display:flex; gap:7px; align-items:center; flex:1 1 auto; flex-wrap:wrap; }
  #edbar .eb-actions .btn { white-space:nowrap; padding:7px 13px; }
  /* density warnings along the WORKING route (POST api/density) — one ⚠ chip per warned
     stretch, in the toolkit beside the stats it annotates. high = --con (the .pabad red),
     med = the #pareto-confwarn amber, so the severity colours match the rest of the app. */
  #densrow { display:flex; flex-wrap:wrap; align-items:center; gap:6px; }
  #densrow.hide { display:none; }
  .denschip { display:inline-flex; align-items:center; gap:6px; max-width:460px; border-radius:999px;
    border:1px solid var(--line); background:var(--panel); color:var(--muted); padding:4px 11px;
    font:inherit; font-size:11px; line-height:1.35; text-align:left; }
  button.denschip { cursor:pointer; }
  button.denschip:hover { box-shadow:var(--shadow-sm); }
  .denschip.high { border-color:var(--con); background:rgba(217,104,86,.10); color:var(--con); font-weight:700; }
  .denschip.med  { border-color:#f59e0b88; background:#f59e0b12; color:#92400e; font-weight:700; }
  #map, #overlay { position:absolute; inset:0; }
  #map { overflow:hidden; }
  #map iframe { position:relative; z-index:0; width:100%; height:100%; border:0; }
  #overlay { pointer-events:none; }
  .pad { padding:9px 14px; } .bd { border-bottom:1px solid var(--line); }
  h1 { font-size:13.5px; margin:0; letter-spacing:-.02em; color:var(--accent-deep); } .sub { font-size:10.5px; color:var(--muted); margin-top:2px; line-height:1.45; }
  /* editable design title + save state */
  .dt-row { display:flex; align-items:center; gap:8px; min-width:0; }
  /* The design's name is the panel's title, so it outranks the generic h1 size (Shubh 2026-07-30:
     "make the design name a bit bigger in the top right"). #dtitle-input carries the SAME size —
     the rename field replaces the h1 in place, and a size change there makes the text jump the
     moment you click to rename it. It still ellipsizes rather than wrapping the row. */
  #dtitle { flex:0 1 auto; min-width:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap;
    font-size:16px; cursor:text; border-radius:5px; padding:1px 4px; margin:-1px -4px; outline:none; }
  #dtitle:hover { background:var(--chipbg); }
  #dtitle:focus-visible { box-shadow:0 0 0 2px var(--accent); }
  #dtitle.untitled { color:var(--muted); }
  #dtitle-input { flex:1 1 auto; min-width:0; font:inherit; font-size:16px; font-weight:700; letter-spacing:-.02em;
    color:var(--accent-deep); border:1px solid var(--accent); border-radius:5px; padding:1px 4px; margin:-1px -4px; outline:none; }
  #dtitle-input.hide { display:none; }
  .dt-state { flex:none; font-size:10px; font-weight:700; color:var(--muted2); white-space:nowrap; }
  .dt-state.saving { color:var(--accent-deep); }
  .dt-state.saved { color:var(--pro); }
  .dt-state.dirty { color:var(--fix); }
  .dt-state.err { color:var(--con); }
  /* clickable save states (see dtSaveFromChip) — a word that does something has to look like it */
  .dt-state.can-save { cursor:pointer; border:1px solid var(--btnbd); border-radius:999px;
    padding:2px 8px; background:var(--surface); }
  .dt-state.can-save:hover { border-color:var(--accent); color:var(--accent-deep); background:var(--hover); }
  .dt-state.can-save:focus-visible { outline:2px solid var(--accent); outline-offset:1px; }

  /* MapBiomas-style circular check toggles — every checkbox in the app */
  input[type=checkbox] { -webkit-appearance:none; appearance:none; width:15px; height:15px; border-radius:50%;
    border:1.6px solid var(--ckbd); background:var(--surface); display:inline-grid; place-content:center;
    cursor:pointer; margin:0; flex:none; transition:background .12s,border-color .12s; }
  /* checkmark drawn as a rotated border (not a font glyph) → crisp + perfectly centred at any size */
  input[type=checkbox]::after { content:""; width:4px; height:8px; margin-top:-1px; border:solid #fff; border-width:0 2px 2px 0; border-radius:.5px; box-sizing:border-box; transform:rotate(45deg) scale(0); transition:transform .1s; }
  input[type=checkbox]:checked { background:var(--green); border-color:var(--green); }
  input[type=checkbox]:checked::after { transform:rotate(45deg) scale(1); }
  input[type=checkbox]:indeterminate { background:var(--green); border-color:var(--green); }
  input[type=checkbox]:indeterminate::after { width:8px; height:0; margin-top:0; border-width:0 0 2px 0; border-radius:0; transform:rotate(0) scale(1); }
  input[type=checkbox]:hover { border-color:var(--green); }
  #sitemodal input[type=checkbox]:checked,
  #sitemodal input[type=checkbox]:indeterminate { background:#111827; border-color:#111827; }
  #sitemodal input[type=checkbox]:hover { border-color:#111827; }

  /* home screen — designs gallery (shown on open; New Design enters the planner) */
  #homescreen { position:fixed; inset:0; z-index:60; background:var(--bg); display:flex; }
  .hs-spin { width:34px; height:34px; flex:none; border:3px solid var(--line); border-top-color:var(--accent);
    border-radius:50%; animation:hsspin .8s linear infinite; }
  @keyframes hsspin { to { transform:rotate(360deg); } }
  #hs-busy { position:fixed; inset:0; z-index:120; background:rgba(24,42,56,.45);
    display:flex; flex-direction:column; gap:14px; align-items:center; justify-content:center; }
  #hs-busy.hide { display:none; }
  #hs-busy .msg { font-size:12.5px; color:#fff; font-weight:700; }
  .hs-side { width:236px; flex:none; background:var(--surface); border-right:1px solid var(--line);
    display:flex; flex-direction:column; padding:16px 0 14px; }
  .hs-side .brand { padding:0 16px 14px; border-bottom:1px solid var(--line); cursor:pointer; transition:opacity .12s; }
  .hs-side .brand:hover { opacity:.8; }
  .hs-nav { display:flex; flex-direction:column; padding:10px 10px; gap:2px; }
  .hs-nav .nlab { font-size:10px; font-weight:700; letter-spacing:.14em; text-transform:uppercase;
    color:var(--muted2); padding:12px 10px 5px; }
  .hs-nav a, .hs-nav .nitem { display:flex; align-items:center; gap:9px; padding:8px 11px; font-size:12.5px;
    color:var(--muted); text-decoration:none; cursor:pointer; border:1px solid transparent; border-radius:999px; }
  .hs-nav .nitem.on { background:var(--accent-soft); color:var(--accent-deep); border-color:transparent; font-weight:700; }
  .hs-nav a:hover, .hs-nav .nitem:hover { color:var(--accent-deep); background:var(--hover); border-radius:999px; }
  .hs-nav .nico { width:14px; text-align:center; color:var(--accent); flex:none; }
  /* "Shared With Me" is a collapsible GROUP HEADER, not a view. It styles like a .nitem but
     is deliberately NOT one, so the blanket `.hs-nav .nitem` selectors that clear and set the
     active `.on` class never touch it — its own open/closed state is `.open` on the header
     plus `.hide` on the children. The arrow sits on the LEFT of the label (Shubh 2026-07-27). */
  .hs-nav .ngroup { display:flex; align-items:center; gap:9px; padding:8px 11px; font-size:12.5px;
    color:var(--muted); cursor:pointer; border:1px solid transparent; border-radius:999px;
    -webkit-user-select:none; user-select:none; }
  .hs-nav .ngroup:hover { color:var(--accent-deep); background:var(--hover); }
  /* The caret carries the whole affordance for this group, so it is sized and coloured to be
     read as a control rather than punctuation (Shubh 2026-07-27): full text colour, not the
     faintest grey in the palette. */
  /* DRAWN, not typed (Shubh 2026-07-27: "should be bigger, or use a diff arrow"). The ▸ glyph
     renders at the mercy of whatever font resolves it — thin and small in the system UI face,
     and on some machines it promotes to an emoji. A CSS triangle is a solid filled wedge at a
     size we actually control, identical everywhere. font-size:0 suppresses the ▸ still in the
     markup, which stays as the no-CSS fallback. */
  .hs-nav .ngroup .narrow { width:14px; height:14px; flex:none; position:relative; font-size:0;
    color:var(--muted); transition:transform .14s ease, color .12s; }
  .hs-nav .ngroup .narrow::before { content:""; position:absolute; top:50%; left:50%;
    transform:translate(-50%,-50%);
    border-style:solid; border-width:5px 0 5px 8px;
    border-color:transparent transparent transparent currentColor; }
  .hs-nav .ngroup:hover .narrow, .hs-nav .ngroup.open .narrow { color:var(--accent); }
  .hs-nav .ngroup.open .narrow { transform:rotate(90deg); }
  .hs-nav .nkids { display:flex; flex-direction:column; gap:2px; }
  /* Children sit INSIDE the parent, so they indent past the parent's LABEL (which starts at
     11px padding + 14px caret + 9px gap = 34px) rather than merely level with it. */
  /* 56px, not 46: the parent's LABEL starts at 34px (11 padding + 14 caret + 9 gap), so 46
     read as a nudge rather than nesting. This is a clear step in, and a hairline rail makes
     the grouping legible without a full tree connector. */
  .hs-nav .nitem.nsub { padding-left:56px; font-size:12px; position:relative; }
  .hs-nav .nitem.nsub::before { content:""; position:absolute; left:34px; top:6px; bottom:6px;
    width:1px; background:var(--line); }
  .hs-nav .nitem.nsub.on::before { background:var(--accent); }
  /* A selected child reads with the SAME accent-soft pill as a top-level selection — no extra
     marker. An inset left bar was tried and removed: against the 999px radius it follows the
     rounded edge and renders as a crescent, which reads as a glitch rather than an indicator. */
  .hs-nav .nitem.nsub.on { background:var(--accent-soft); color:var(--accent-deep); font-weight:700; }
  .hs-nav .nsep { height:1px; background:var(--line); margin:10px 12px; }
  .hs-user { margin-top:auto; border-top:1px solid var(--line); padding:11px 16px 0; font-size:11px; color:var(--muted);
    display:flex; align-items:baseline; gap:10px; }
  .hs-user .em { overflow:hidden; text-overflow:ellipsis; white-space:nowrap; flex:1; color:var(--text); font-weight:700; }
  .hs-user a { color:var(--accent); text-decoration:underline; cursor:pointer; }
  #homescreen .hs-wrap { flex:1; overflow-y:auto; padding:26px 34px 60px; }
  /* title + caption stack vertically in their own block (the caption used to sit
     INLINE between the title and the search box and wrapped into a skinny column) */
  .hs-top { display:flex; align-items:center; gap:16px; flex-wrap:wrap; }
  /* 240px basis, not 340: the row now carries search + sort + two buttons, and the wider basis
     made the head claim space it did not need, wrapping "+ Multi-terminal" onto its own line */
  .hs-top .hs-head { flex:1 1 240px; min-width:0; }
  .hs-top .hs-sub { display:block; margin-top:3px; max-width:760px; line-height:1.5; }
  .hs-top .btn.primary { margin-left:0; padding:10px 18px; font-size:13px; white-space:nowrap; flex:none; }
  /* 200px, not 260: the sort control shares this row, and at 1280px the extra width pushed
     "+ Multi-terminal" onto a second line */
  #hs-search { margin-left:auto; width:200px; min-width:130px; background:var(--surface); border:1px solid var(--line); border-radius:999px;
    color:var(--text); font:inherit; font-size:12.5px; padding:9px 15px; outline:none; box-shadow:var(--shadow-sm); }
  #hs-search:focus { border-color:var(--accent); box-shadow:0 0 0 3px rgba(20,24,28,.12); }
  #hs-search::placeholder { color:var(--muted2); }
  /* THE CHEVRON SITS NEXT TO THE WORDS, not off at the pill's edge (Shubh 2026-08-04: "move the
     down arrow so its not off on the side"). This is the share-page role select all over again —
     see #accessmodal select below: a native select parks its own indicator against the element's
     right edge and sizes the box past its text, so "Sort: most recent" left an obvious gap before
     the caret, and padding-right only ever pushed the two further apart. appearance:none drops the
     platform arrow and shrinks the box to its content; the caret comes back as a background image
     10px in, so the gap is ours rather than the platform's. background-COLOR, not the background
     shorthand — the shorthand would wipe the caret image out. */
  #hs-sort { appearance:none; -webkit-appearance:none; background-color:var(--surface);
    border:1px solid var(--line); border-radius:999px;
    color:var(--text); font:inherit; font-size:12.5px; padding:9px 26px 9px 14px; outline:none;
    box-shadow:var(--shadow-sm); cursor:pointer;
    background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='9' height='6'%3E%3Cpath d='M0 0h9L4.5 6z' fill='%23556474'/%3E%3C/svg%3E");
    background-repeat:no-repeat; background-position:right 10px center; }
  #hs-sort:focus { border-color:var(--accent); box-shadow:0 0 0 3px rgba(20,24,28,.12); }
  .hs-top .btn.primary { margin-left:0; }
  .hs-card { position:relative; }
  /* owner avatar: the owner's Google photo if we have one, otherwise their initials. The
     initials are ALWAYS in the DOM underneath the photo, so a broken or expired lh3 URL (they
     rotate) degrades to them instead of a hole.
     It lives in the card BODY, right-hand side, level with the name (Shubh 2026-07-27) — over
     the thumbnail it had to carry a shadow and a border to stay legible against arbitrary
     satellite imagery; in the body's whitespace it just sits there. */
  .hs-own { flex:none; width:28px; height:28px; border-radius:999px; position:relative;
    display:flex; align-items:center; justify-content:center; overflow:hidden; cursor:default;
    background:var(--accent-soft); color:var(--accent-deep); border:1px solid var(--line);
    font-size:10.5px; font-weight:800; line-height:1; letter-spacing:.02em; }
  .hs-own img { position:absolute; inset:0; width:100%; height:100%; object-fit:cover; }
  /* the avatar has left this corner, so ⋯ takes it back */
  .hs-menu-btn { position:absolute; top:8px; right:8px; z-index:2; width:26px; height:26px; display:none;
    align-items:center; justify-content:center; background:var(--glass2); border:1px solid var(--line);
    border-radius:8px; color:var(--muted); cursor:pointer; font-size:16px; line-height:1; box-shadow:var(--shadow-sm); }
  .hs-card:hover .hs-menu-btn, .hs-menu-btn.open { display:flex; }
  .hs-menu-btn:hover, .hs-menu-btn.open { color:var(--accent-deep); border-color:var(--accent); }
  .hs-menu { position:absolute; top:38px; right:8px; z-index:3; min-width:170px; font-size:12px;
    background:var(--surface); border:1px solid var(--line); border-radius:10px; overflow:hidden; box-shadow:var(--shadow-lg); }
  .hs-menu div { padding:9px 13px; cursor:pointer; color:var(--text); }
  .hs-menu div:hover { background:var(--hover); }
  .hs-menu div.danger:hover { color:var(--con); }
  .hs-del { position:absolute; top:8px; left:8px; z-index:2; width:26px; height:26px; display:none;
    align-items:center; justify-content:center; background:var(--glass2); border:1px solid var(--line);
    border-radius:8px; color:var(--muted); font-size:13px; cursor:pointer; }
  .hs-card:hover .hs-del { display:flex; }
  .hs-del:hover { color:var(--con); border-color:var(--con); }
  .hs-card.blank { border-style:dashed; background:transparent; box-shadow:none; }
  .hs-card.blank .hs-prev { display:flex; align-items:center; justify-content:center; background:transparent; }
  .hs-card.blank .plus { font-size:34px; font-weight:300; color:var(--muted2); line-height:1; }
  .hs-card.blank:hover .plus { color:var(--accent); }
  .hs-title-row { display:flex; align-items:baseline; gap:14px; margin:28px 0 16px; }
  .hs-title { font-size:24px; font-weight:800; letter-spacing:-.03em; color:var(--accent-deep); }
  .hs-sub { color:var(--muted2); font-size:12.5px; }
  .hs-grid { display:grid; grid-template-columns:repeat(auto-fill,minmax(300px,1fr)); gap:18px; }
  /* column flex so .hs-body can absorb the slack: the grid stretches every card in a row to
     the tallest one, and a content-sized body would leave dead space BELOW itself on the
     short-text cards — which left the bottom-aligned owner avatars sitting at ragged heights
     (41px / 27px / 13px off the card bottom across one row). */
  .hs-card { border:1px solid var(--line); background:var(--surface); border-radius:var(--r); overflow:hidden;
    display:flex; flex-direction:column;
    cursor:pointer; box-shadow:var(--shadow-sm); transition:border-color .12s, box-shadow .15s, transform .15s; }
  .hs-card:hover { border-color:var(--accent); box-shadow:var(--shadow); transform:translateY(-1px); }
  .hs-prev { display:block; width:100%; aspect-ratio:16/10; background:var(--track); }
  /* PENDING thumbnail — a design with no usable meta.preview, whose real geometry is still being
     lazy-filled (see _hsRenderGallery). Deliberately says NOTHING: #161616 is the exact colour
     paintCardMap fills before its first tile lands, so the canvas that replaces this does not
     jump in brightness. The US-outline card must not be used here — it looks like a finished
     answer ("this design has no route"), and four of Shubh's sixty designs wore it for the best
     part of a second before their satellite thumbnail arrived (2026-07-28). */
  .hs-prev.hs-pending { background:#161616; position:relative; overflow:hidden; }
  .hs-prev.hs-pending::after { content:""; position:absolute; inset:0;
    background:linear-gradient(100deg, transparent 25%, rgba(255,255,255,.05) 50%, transparent 75%);
    transform:translateX(-100%); animation:hsPend 1.6s ease-in-out infinite; }
  @keyframes hsPend { to { transform:translateX(100%); } }
  /* name + meta stack on the left and take the slack; the owner avatar is the fixed right
     column, bottom-aligned (Shubh 2026-07-27). flex-end, NOT flex-start: cards carry two to
     four lines of meta, and the avatar has to sit at the bottom-right corner of the card
     rather than riding up beside the name on the tall ones. */
  .hs-body { padding:10px 13px 12px; border-top:1px solid var(--line);
    flex:1; display:flex; align-items:flex-end; gap:10px; }
  .hs-body > .hs-txt { flex:1; min-width:0; }
  .hs-name { font-weight:700; font-size:13.5px; letter-spacing:-.01em; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
  .hs-meta { color:var(--muted); font-size:11.5px; margin-top:3px; }
  .hs-foot { margin-top:34px; border-top:1px solid var(--line); padding-top:12px; display:flex; gap:8px;
    font-size:11.5px; color:var(--muted2); }
  .hs-foot a { color:var(--accent); text-decoration:underline; }
  #homescreen .empty { color:var(--muted2); font-size:13px; }

  /* brand wordmark */
  .brand { display:flex; align-items:center; gap:10px; cursor:pointer; }
  .brand .logo { flex:none; border-radius:6px; display:block; }
  .brand .wm { font-size:13px; font-weight:800; letter-spacing:-.02em; text-transform:uppercase; line-height:1.05; color:var(--text); }
  .brand .wm small { display:block; font-size:9px; font-weight:600; letter-spacing:.05em; color:var(--muted); text-transform:uppercase; margin-top:1px; }
  /* pill segmented control (MapBiomas "Coverage / Natural and Anthropic use") */
  .seg { display:flex; border:1px solid var(--line); border-radius:999px; overflow:hidden; margin-top:9px; background:var(--surface); padding:3px; gap:3px; }
  .seg button { flex:1; border:none; background:transparent; padding:5px 10px; font:inherit; font-size:11px; font-weight:700;
    color:var(--muted); cursor:pointer; border-radius:999px; white-space:nowrap; }
  .seg button:first-child { border-left:none; }
  .seg button.on { background:var(--accent-soft); color:var(--accent-deep); }
  .seg button:not(.on):hover { background:var(--hover); color:var(--text); }
  .t3-seg { margin-top:0; flex:none; }
  .t3-seg button { padding:6px 12px; white-space:nowrap; }
  /* left-bar sections as floating cards (MapBiomas theme cards) */
  .sect { margin:10px 10px 0; padding:11px 13px 12px; background:var(--surface); border:1px solid var(--line);
    border-radius:var(--r); box-shadow:var(--shadow-sm); }
  .sect-title { display:flex; align-items:center; gap:8px; font-size:12.5px; font-weight:700; letter-spacing:-.01em; }
  .sect-title input { width:15px; height:15px; cursor:pointer; }
  .sect-title .sw { width:11px; height:11px; border-radius:50%; border:2px solid #fff; box-shadow:0 0 0 1px rgba(28,48,64,.35); }
  .sect-title.supply .sw { background:var(--supply); } .sect-title.load .sw { background:var(--load); }
  /* supply / load sections collapse like the Map-data-layers section */
  details.sect > summary { list-style:none; cursor:pointer; }
  details.sect > summary::-webkit-details-marker { display:none; }
  details.sect > summary.sect-title::before { content:"\25B8"; color:var(--muted2); font-weight:800; }
  details.sect[open] > summary.sect-title::before { content:"\25BE"; }
  .filthdr { margin:6px 0 1px; }
  .filthdr .lab { font-size:9.5px; font-weight:700; text-transform:uppercase; letter-spacing:.08em; color:var(--muted2); }
  .tlist { display:grid; grid-template-columns:repeat(2,minmax(0,1fr)); gap:0 10px; }
  /* supply panel: master map-toggle + Operating/Planned sub-sections (Will 2026-07-21) */
  .sect-vis { width:15px; height:15px; flex:none; cursor:pointer; accent-color:var(--accent); }
  .subsec { margin-top:9px; padding-top:8px; border-top:1px solid var(--divider); }
  .subsec .subhead { font-size:12px; font-weight:700; }
  .subsec .subhead b { font-weight:800; }
  .subsec .subhead .subnote { color:var(--muted2); font-size:10px; font-weight:500; margin-left:6px; }
  /* a section toggle (Operating/Planned) must stay readable when OFF — don't fade it like a
     de-selected filter row (the checkbox's checked/unchecked state is the on/off cue). */
  .subsec .subhead input:not(:checked) ~ * { opacity:1; }
  .pfilters { margin:6px 0 2px 22px; }
  .pfilters.hide { display:none; }
  .isolist { display:grid; grid-template-columns:repeat(2,minmax(0,1fr)); gap:0 10px; }
  .mktscroll { display:grid; grid-template-columns:repeat(2,minmax(0,1fr)); gap:0 10px; max-height:150px; overflow-y:auto; margin-top:2px; padding-right:2px; }
  /* per-layer Felt attribute filters (Map data layers) */
  /* TRUNK LINES ONLY — the default view, stated rather than assumed. Sits OUTSIDE .lfilt so it
     is visible while the filter block is collapsed: this toggle is ON at boot, and a map that
     hides gathering systems with no visible sign of it is worse than a busy one. Indented to
     26px to sit under the layer's own checkbox, matching .lfilt. */
  /* Label above, note below — a deliberate two-line stack rather than one line left to wrap.
     The row is ~199px at this indent, and "Trunk lines only" plus "hides gathering systems" does
     not fit; allowed to wrap freely it broke mid-phrase ("Trunk lines / only"), which reads as a
     layout bug. */
  .lf-trunk { display:flex; align-items:flex-start; gap:6px; margin:4px 0 0 26px; cursor:pointer;
    font-size:11px; color:var(--muted); }
  .lf-trunk input { flex:none; margin:1px 0 0; accent-color:var(--accent); cursor:pointer; }
  .lf-trunk .lf-tx { display:flex; flex-direction:column; gap:1px; min-width:0; }
  .lf-trunk .lf-tk { color:var(--text); white-space:nowrap; }
  .lf-trunk .lf-tn { font-size:10px; line-height:1.25; color:var(--muted2); }
  .lf-trunk:hover .lf-tk { color:var(--accent); }
  .lfilt { margin:8px 0 6px 26px; }
  .lfilt > summary { list-style:none; cursor:pointer; font-size:10.5px; font-weight:700; letter-spacing:.03em;
    text-transform:uppercase; color:var(--muted2); padding:2px 0; display:flex; align-items:center; gap:5px; }
  .lfilt > summary::-webkit-details-marker { display:none; }
  .lfilt > summary::before { content:"\25B8"; font-size:8px; color:var(--muted2); }
  .lfilt[open] > summary::before { content:"\25BE"; }
  .lfilt > summary:hover { color:var(--text); }
  .lfbody { padding:3px 0 6px; }
  .lf-row { margin:4px 0; }
  .lf-lab { display:block; font-size:11px; color:var(--muted); margin-bottom:2px; }
  .lf-lab b { color:var(--text); font-variant-numeric:tabular-nums; }
  .lf-cats { display:flex; flex-wrap:wrap; gap:4px 12px; }
  .lf-catlab { display:flex; align-items:center; gap:5px; font-size:11px; cursor:pointer; white-space:nowrap; }
  .lf-catlab input { width:13px; height:13px; }
  .stagetext { width:100%; box-sizing:border-box; margin-top:3px; padding:6px 9px; border:1px solid var(--line);
    border-radius:7px; background:var(--panel); color:var(--text); font:inherit; font-size:11.5px; outline:none; }
  .stagetext:focus { border-color:var(--accent); }
  .trow { display:flex; align-items:center; gap:7px; padding:2px 2px; font-size:11.5px; cursor:pointer; user-select:none; border-radius:6px; }
  .trow:hover { background:var(--hover); }
  .trow input { width:14px; height:14px; cursor:pointer; flex:none; }
  .trow .dot { width:9px; height:9px; border-radius:50%; flex:none; }
  .trow.allrow { grid-column:1 / -1; font-weight:700; border-bottom:1px solid var(--line); padding-bottom:5px; margin-bottom:3px; }
  .mwrow { margin-top:6px; }
  .mwrow .mwlab { font-size:10.5px; color:var(--muted); white-space:nowrap; }
  .mwrow .mwlab b { color:var(--text); }
  /* dual-handle range (two overlaid inputs on one track) */
  .rng2 { position:relative; height:20px; margin-top:3px; }
  .rng2::before { content:""; position:absolute; left:2px; right:2px; top:9px; height:3px; background:var(--track); border-radius:2px; }
  .rng2 input[type=range] { position:absolute; left:0; top:0; width:100%; height:20px; margin:0; background:none; pointer-events:none; -webkit-appearance:none; appearance:none; }
  .rng2 input[type=range]::-webkit-slider-thumb { pointer-events:auto; -webkit-appearance:none; width:14px; height:14px; border-radius:50%; background:var(--accent); border:2px solid #fff; box-shadow:0 1px 4px rgba(28,48,64,.35); cursor:pointer; margin-top:0; }
  .rng2 input[type=range]::-moz-range-thumb { pointer-events:auto; width:14px; height:14px; border-radius:50%; background:var(--accent); border:2px solid #fff; cursor:pointer; }
  .rng2 input[type=range]::-webkit-slider-runnable-track { background:none; height:20px; }
  .rng2 input[type=range]::-moz-range-track { background:none; }
  .ictog { margin-top:6px; font-weight:700; }   /* part of its section — no divider above */
  .trow input:not(:checked) ~ * { opacity:.45; }
  .gis .lyr { display:flex; align-items:center; gap:7px; font-size:11.5px; padding:3px 0; cursor:pointer; }
  .gis .lyr input { width:14px; height:14px; flex:none; }
  .st { font-size:9px; color:var(--muted2); } .st.up{color:var(--accent);} .st.done{color:var(--muted);}
  .ctl { font-size:9.5px; color:var(--muted2); margin:0 0 4px; font-weight:700; text-transform:uppercase; letter-spacing:.08em; }
  a.maplink { font-size:11px; color:var(--accent); }
  /* Private transmission laws overlay */
  #ptlaw-legend { position:absolute; left:12px; bottom:14px; z-index:6; background:rgba(255,255,255,.95);
    border:1px solid var(--line); border-radius:var(--r); padding:10px 12px; font-size:11.5px; color:var(--text);
    box-shadow:var(--shadow); backdrop-filter:blur(4px); }
  #ptlaw-legend.hide { display:none; }
  #ptlaw-legend .ptl-h { font-size:10px; text-transform:uppercase; letter-spacing:.06em; color:var(--muted2); margin-bottom:5px; font-weight:700; }
  #ptlaw-legend .ptl-r { display:flex; align-items:center; gap:7px; padding:1.5px 0; }
  #ptlaw-legend .ptl-sw { width:13px; height:13px; border-radius:4px; flex:none; border:1px solid rgba(28,48,64,.18); }
  #ptlaw-legend .ptl-note { margin-top:6px; font-size:10px; color:var(--muted); max-width:170px; line-height:1.3; }
  #ptlaw-detail { position:absolute; right:12px; top:56px; z-index:7; width:330px; max-width:calc(100% - 24px);
    max-height:calc(100% - 130px); overflow-y:auto; background:var(--glass2); border:1px solid var(--line);
    border-radius:var(--r); padding:13px 15px; box-shadow:var(--shadow-lg); backdrop-filter:blur(4px); }
  #ptlaw-detail.hide { display:none; }
  #ptlaw-detail .ptd-hd { display:flex; align-items:center; gap:8px; }
  #ptlaw-detail .ptd-hd b { font-size:15px; flex:none; }
  #ptlaw-detail .ptd-dot { width:12px; height:12px; border-radius:50%; flex:none; border:2px solid rgba(28,48,64,.25); }
  #ptlaw-detail .ptd-badge { font-size:10px; font-weight:700; text-transform:uppercase; letter-spacing:.04em;
    border:1px solid; border-radius:999px; padding:1px 8px; }
  #ptlaw-detail .ptd-x { margin-left:auto; cursor:pointer; color:var(--muted2); font-size:14px; padding:0 2px; }
  #ptlaw-detail .ptd-x:hover { color:var(--text); }
  #ptlaw-detail .ptd-sum { font-size:12.5px; line-height:1.5; color:var(--text); margin:9px 0 4px; }
  #ptlaw-detail .ptd-h { font-size:10px; text-transform:uppercase; letter-spacing:.06em; color:var(--muted2); margin:11px 0 4px; font-weight:700; }
  #ptlaw-detail .ptd-ul { margin:0; padding-left:16px; font-size:11.5px; line-height:1.5; color:var(--muted); }
  #ptlaw-detail .ptd-ul li { margin-bottom:4px; }
  #ptlaw-detail .ptd-src { font-size:11px; line-height:1.6; }
  #ptlaw-detail .ptd-src a { color:var(--accent); text-decoration:none; }
  #ptlaw-detail .ptd-src a:hover { text-decoration:underline; }
  /* plain-English topic blocks, each with its own "verify" source links */
  #ptlaw-detail .ptd-topic { font-size:11.5px; line-height:1.5; color:var(--muted); margin-bottom:8px; }
  #ptlaw-detail .ptd-topic b { display:block; color:var(--text); font-size:11px; text-transform:uppercase; letter-spacing:.04em; margin-bottom:2px; }
  #ptlaw-detail .ptd-vs { color:var(--muted2); font-size:10.5px; }
  #ptlaw-detail .ptd-ul li b { color:var(--text); font-weight:700; }
  #ptlaw-detail .ptd-more { margin-top:9px; font-size:11px; font-weight:700; color:var(--accent); cursor:pointer; }
  #ptlaw-detail .ptd-more:hover { text-decoration:underline; }
  #ptlaw-detail .ptd-vs a { color:var(--accent); text-decoration:none; }
  #ptlaw-detail .ptd-vs a:hover { text-decoration:underline; }
  #ptlaw-detail .ptd-meta { margin-top:10px; padding-top:8px; border-top:1px solid var(--line); font-size:10px; color:var(--muted2); }
  /* map legend */
  .lgc { border:1px solid var(--line); margin-top:7px; background:var(--panel); border-radius:var(--r-sm); }
  .lgc > summary { list-style:none; cursor:pointer; padding:8px 10px; font-size:11px; font-weight:700; color:var(--muted); text-transform:uppercase; letter-spacing:.04em; }
  .lgc > summary::-webkit-details-marker { display:none; }
  .lgc > summary::before { content:"▸ "; color:var(--muted2); }
  .lgc[open] > summary::before { content:"▾ "; }
  .lgc > *:not(summary) { margin-left:10px; margin-right:10px; }
  .lgc > *:last-child { margin-bottom:9px; }
  /* collapsible sidebar sections as cards */
  .lg { border:1px solid var(--line); border-radius:var(--r); background:var(--surface); margin:10px 10px 0; box-shadow:var(--shadow-sm); overflow:hidden; }
  .lg > summary { list-style:none; cursor:pointer; padding:11px 14px; font-size:11px; font-weight:800; color:var(--accent-deep); text-transform:uppercase; letter-spacing:.05em; }
  .lg > summary::-webkit-details-marker { display:none; }
  .lg > summary::before { content:"▸ "; color:var(--muted2); }
  /* Map-data-layers body: same gutter as #legendbody, so its group headers / checkbox
     rows align with every other sidebar section instead of sitting flush at x=0 */
  #infrabody { padding:0 14px 12px; }
  .lg[open] > summary::before { content:"▾ "; }
  #legendbody { padding:0 14px 12px; }
  .lgh { font-size:9.5px; font-weight:700; text-transform:uppercase; letter-spacing:.08em; color:var(--muted2); margin:9px 0 3px; }
  .lgrow { display:flex; align-items:center; gap:8px; font-size:11.5px; padding:2px 0; color:var(--text); }
  .lgsw { width:12px; height:12px; border-radius:3px; flex:none; }
  .lgsw.line { height:4px; border-radius:2px; }
  .lgsw.ring { border-radius:50%; border:2px solid #fff; box-shadow:0 0 0 1px rgba(28,48,64,.3); }
  .lgsw.dot { border-radius:50%; }
  /* checkable legend rows — the colour swatch is the checkbox; row dims when off */
  .lgck { cursor:pointer; user-select:none; border-radius:6px; margin:0 -4px; padding:2.5px 4px; }
  .lgck:hover { background:var(--hover); }
  /* candidate-route cards (Pareto panel) */
  #pp-runsec { margin-top:14px; }
  #pp-run.primed { animation:ppRunPulse 1.9s ease-out infinite; }
  @keyframes ppRunPulse {
    0%   { box-shadow:0 0 0 0 rgba(42,86,116,.55); }
    70%  { box-shadow:0 0 0 9px rgba(42,86,116,0); }
    100% { box-shadow:0 0 0 0 rgba(42,86,116,0); }
  }
  @media (prefers-reduced-motion:reduce) {
    #pp-run.primed { animation:none; box-shadow:0 0 0 3px rgba(42,86,116,.35); }
  }
  #pareto-cards { display:flex; flex-direction:row; gap:9px; overflow-x:auto; overflow-y:hidden;
    scroll-snap-type:x mandatory; align-items:stretch;
    /* LEFT GUTTER for the ‹ arrow, taken from the PANEL's own 14px padding (margin-left pulls the
       track box out, padding-left puts the space back inside it) so the cards keep their width —
       the arrow used to sit on top of the first stat box and clip "COST INDEX". It stops 12px short
       of where card text begins, and -12px lands on #rightbar's content edge, so an overflow:auto
       ancestor gets nothing to scroll. scroll-padding-left matches the padding, keeping a card's
       snap position at scrollLeft = i × width — the relationship paIndex() reads. */
    scroll-padding:0 var(--pa-bleed-r,2px) 0 var(--pa-bleed-l,12px);
    /* the row is the scroller, so its own padding must not clip a card's focus ring.
       --pa-gut is ON TOP of the bleed and does the centring: see the note below. */
    padding:2px calc(var(--pa-bleed-r,2px) + var(--pa-gut,9%)) 8px calc(var(--pa-bleed-l,12px) + var(--pa-gut,9%));
    margin:0 calc(-1 * var(--pa-bleed-r,2px)) 0 calc(-1 * var(--pa-bleed-l,12px));
    -webkit-overflow-scrolling:touch; scrollbar-width:thin; }
  /* CENTRED, with a hint of BOTH neighbours (Shubh 2026-07-28: "card design should be such that
     this should be centered, and should see a left and right arrow to switch to the next cards
     on either side, with just hints of each of the adjacent cards (a little bit less than the
     sneak peek right now)"). It used to be scroll-snap-align:start at 88%, so the card sat 18 px
     left of centre with a 39 px peek on the right and a 3 px sliver on the left.
     The card is 100% of the CONTENT box, and --pa-gut is the track's own horizontal padding, so
     the card width is whatever is left: 100% - 2 x gut. Writing it that way rather than as an
     82% flex-basis is what makes the arithmetic close.
       · A snapped card's centre lands on the snapport's centre automatically, at EVERY index —
         including the first and the last, which is where centred carousels normally break. The
         padding is what gives the end cards room to reach the middle; without it the scroller
         simply runs out (today the last card cannot even reach its own start position:
         scrollWidth allows 995 px and it wants 1041).
       · scrollLeft == i x (card + gap) STILL HOLDS, which paIndex() and paSlide() both depend
         on. It holds precisely because the padding is half the leftover on each side; the
         asymmetric scroll-padding above cancels the asymmetric bleed, so the two effects
         subtract out exactly. Change one of these three numbers without the others and the
         arrows will start skipping cards. */
  /* CENTRED (Shubh 2026-07-30, restoring the 2026-07-28 intent). b04a00f flipped exactly two things
     — this alignment, and the LEFT --pa-gut out of the track's padding — while leaving the rest of
     the centring apparatus in place: the comment above, the cancelling scroll-padding, and the ‹
     arrow's own offset, which still reads --pa-gut and so assumed a left gutter that was no longer
     there. Both are restored together, because either alone is wrong: with the alignment centred and
     the left gutter missing, the card measured 17.3px left of the column's centre. */
  #pareto-cards > .pacard { flex:0 0 100%; scroll-snap-align:center; }
  /* uniform height: the card is a column so its footer/sections sit at the bottom of the tallest */
  #pareto-cards > .pacard { display:flex; flex-direction:column; }
  /* Carousel chrome. The arrows FLANK the track rather than sitting under it (Shubh
     2026-07-28: "arrows should be between them"), so they overlay the seam between the current
     card and its neighbour — the gesture and the gap it acts on are in the same place.
     Now that the gutters are symmetric the arrows are too: each sits --pa-arrow-gap from its
     own edge of the CARD, which is the symmetry the eye actually reads. Their distances from
     the TRACK edge still differ by the bleed, because the panel has 12 px of usable padding on
     the left and 2 px on the right — that is the panel's asymmetry, not the carousel's. */
  /* --pa-bleed-* is how far the track's box extends past the wrapper on each side (it borrows the
     panel's padding for the arrow gutter). The track's margin/padding and this overlay both derive
     from it, so the arrows stay pinned to the scrollport rather than drifting off it.
     --pa-gut is the centring gutter: half the space left over by the card, on each side. The
     visible hint of each neighbour is (gut - gap). 9% of the panel gives ~26 px, against the
     39 px one-sided peek it replaces. */
  #pa-wrap { position:relative; --pa-gut:9%; --pa-arrow-gap:4px; --pa-bleed-l:12px; --pa-bleed-r:2px; }
  .pa-arrows { position:absolute; top:2px; bottom:26px;
    left:calc(-1 * var(--pa-bleed-l)); right:calc(-1 * var(--pa-bleed-r));
    /* the overlay spans the cards, so it must not eat clicks meant for a card */
    pointer-events:none; display:flex; align-items:center; }
  .pa-nav { display:flex; align-items:center; justify-content:center; height:18px; margin:2px 0 4px; }
  #pa-wrap.pa-solo .pa-arrows, #pa-wrap.pa-solo .pa-nav { display:none; }
  .pa-nav-b { position:absolute; pointer-events:auto;
    width:26px; height:26px; border-radius:999px; border:1px solid var(--line); background:var(--surface);
    color:var(--accent-deep); font:inherit; font-size:15px; line-height:1; cursor:pointer; display:flex;
    align-items:center; justify-content:center; box-shadow:var(--shadow); }
  /* 22px, not 0: #rbtoggle (.edgetog) is position:fixed, 32px wide, z-index 21 and centred ON the
     sidebar's left edge, so it painted straight over an arrow sitting at the left edge — the arrow was
     there the whole time, underneath the collapse handle (Shubh 2026-07-28: "make sure the arrows to
     scroll through the candidate routes horizontally are visible on the screen"). z-index lifts it
     above the handle too, so neither position nor stacking can hide it again. */
  .pa-nav-b[data-pan="-1"] { left:max(16px, calc(var(--pa-bleed-l) + var(--pa-gut) - 26px - var(--pa-arrow-gap))); }
  .pa-nav-b { z-index:22; }
  .pa-nav-b[data-pan="1"]  { right:max(3px, calc(var(--pa-bleed-r) + var(--pa-gut) - 26px - var(--pa-arrow-gap))); }
  .pa-nav-b:hover:not(:disabled) { border-color:var(--accent); background:var(--selbg); }
  /* at an end the arrow would do nothing: fade it out of the way of the card underneath */
  .pa-nav-b:disabled { opacity:.22; cursor:default; box-shadow:none; }
  .pa-nav-i { font-size:11px; font-weight:700; color:var(--muted); min-width:34px; text-align:center; }
  /* ---- COMPARE TABLE (Shubh 2026-07-30) -------------------------------------------------------
     "keep in mind i'd have at most 4 different routes here. would have to make sure this table
     fits laterally in, or keep those row names but just make the cards be able to move left and
     right. i think this last choice is the best approach" — then "sidebar makes most sense here".
     So: the row names are a STICKY RAIL and the route columns scroll under it. Same surface as the
     carousel, a second way of reading the same paretoRoutes — no second data path.
     Why this and not a 3-across table: at the real sidebar width (--rbw:413px, ~385px of content)
     four columns plus a rail cannot fit without shrinking numbers to unreadable, and dropping the
     4th candidate from a compare view is the one thing a compare view may not do. */
  /* THE TABLE IS THE ONLY VIEW (Shubh 2026-07-30: "get rid of the cards, we will just use this
     henceforth"). The card carousel and its chrome — arrows, the i/n indicator, the Cards|Compare
     toggle — are all gone: the table carries every number they carried, for every candidate at once,
     which is what made the carousel redundant.
     WHAT THE CARDS STILL DO, and why #pareto-cards is not deleted outright: the collapsible detail
     sections (ROW sequence, counterparties, crossings, density flags, parcels & landowners) and the
     pros/cons lines live in the card, and their hover/click handlers are bound against #pareto-cards
     in paCards. So the node stays as a DETAIL PANEL under the table, showing only the selected
     candidate, with everything the table already says suppressed. Deleting it would have quietly
     taken the drill-down with it. */
  #pa-wrap .pa-arrows, #pa-wrap .pa-nav { display:none; }
  /* not a scroller any more: one card, stacked under the table */
  #pareto-cards { display:block; overflow:visible; scroll-snap-type:none; padding:0; margin-top:10px; }
  #pareto-cards .pacard { display:none; }
  #pareto-cards .pacard.sel { display:block; border-left-width:4px !important; animation:none;
    box-shadow:var(--shadow-sm) !important; }
  /* every part the table already shows, so the detail panel is detail and not a second opinion */
  #pareto-cards .pacard .pastats, #pareto-cards .pacard .pabar, #pareto-cards .pacard .padet,
  #pareto-cards .pacard .paopt, #pareto-cards .pacard .pafollow, #pareto-cards .pacard .paeye,
  #pareto-cards .pacard .pause, #pareto-cards .pacard .parec { display:none; }
  #pareto-cards .pacard .pahd { margin-bottom:2px; }
  #pareto-compare { margin-top:9px; }
  /* Keep the labels and route headers readable at every candidate count. The sticky metric rail and
     each candidate own a real minimum width; the table scrolls inside the sidebar when those tracks
     need more room than the panel provides. */
  .pctab { --pc-rail:120px; --pc-col:84px; overflow-x:auto; overflow-y:hidden;
    display:grid; align-content:start; scroll-padding-left:var(--pc-rail);
    border:1px solid var(--line); border-radius:var(--r); background:var(--surface); box-shadow:var(--shadow-sm); }
  /* Four-route tables remain compact vertically, but no longer shrink their column tracks. */
  .pctab.n4 .pcc { padding:5px 4px; }
  .pctab.n4 .pcv { font-size:11px; }
  .pctab.n4 .pcr { font-size:10px; }
  .pctab.n4 .pch { padding:7px 6px 6px; }
  .pctab.n4 .pchlbl { font-size:10px; }
  /* 6.5px was past legible — at four columns the pill was a green smear. The star moved to a bare
     glyph and the dot no longer shares its row with the label, so the width is there to spend.
     Both status labels may wrap instead of clipping in a narrow candidate column. */
  .pctab.n4 :is(.pcrec,.pcrefined) { font-size:7px; letter-spacing:.02em; padding:2px 4px; white-space:normal; line-height:1.25; }
  .pctab.n4 .pchtop { gap:4px; }
  .pctab.n4 .pcact { font-size:9.5px; padding:5px 1px; }
  .pctab.n3 .pcc { padding:5px 6px; }
  /* two candidates have room to spare, so the numbers get it */
  .pctab.n2 .pcv { font-size:12.5px; }
  .pctab::-webkit-scrollbar { height:8px; }
  .pctab::-webkit-scrollbar-thumb { background:var(--line); border-radius:99px; }
  .pctab::-webkit-scrollbar-track { background:transparent; }
  .pcc { border-bottom:1px solid var(--line); padding:5px 7px; font-size:11.5px; min-width:0; }
  /* THE RAIL. sticky+left:0 keeps the row names in place while the columns move; the background is
     opaque and z-index beats the cells, or scrolled numbers would show through the labels. */
  .pcr { position:sticky; left:0; z-index:2; background:var(--surface); color:var(--muted);
    font-size:10.5px; line-height:1.25; border-right:1px solid var(--line); display:flex; align-items:center; }
  /* nowrap so the parenthetical never splits: "Greenfield (mi ↓)" was breaking after "(mi" and
     dropping the arrow onto a line of its own, which read as a stray glyph rather than a unit note.
     The LABEL still wraps — it just wraps before the bracket instead of inside it. */
  .pcr .u { color:var(--muted2); font-weight:400; white-space:nowrap; }
  /* WHICH WAY IS BETTER, said on the row itself (Shubh 2026-07-30: "indicate which variables we want
     to minimie, which we want to maximize"). Folded INTO the existing unit parenthetical — "(mi ↓)",
     "(% ↑)" — rather than given its own leading gutter: the rail is 92px and "Near protected land"
     already wraps to three lines there, so a column of arrows would have cost a column of candidates.
     Reads as "miles, lower is better", which is the sentence anyway. */
  .pcdir { font-weight:700; color:var(--accent); }
  /* THE ROW MIX AS A PIE (Shubh 2026-07-30: "maybe make the right of way a pie chart as opposed to a
     line segment, and hovering over particular parts tells us what each part is, or have a key as
     well") — so: both, a pie with a per-slice tooltip AND the key below the table.
     Drawn as stroked circles rather than arc paths: r=9 with stroke-width=18 makes the stroke run from
     the centre to radius 18, which fills the 36-unit viewBox exactly, and each slice is its OWN
     element so it can carry a <title> that the browser shows on hover. Arc `path` d-strings would be
     one blob of generated geometry with no natural hover target per slice.
     Worth knowing: for judging "which candidate is mostly road", side-by-side bar LENGTHS are easier
     to compare than pie ANGLES — the key below is what makes the pie legible at 44px. */
  .pcmix { padding:6px 4px; display:flex; justify-content:center; }
  .pcpie { width:44px; height:44px; display:block; overflow:visible; }
  .pctab.n4 .pcpie { width:38px; height:38px; }
  .pcpie circle { transition:opacity .12s; }
  .pcpie:hover circle { opacity:.45; }          /* hovering the pie fades the rest… */
  .pcpie circle:hover { opacity:1; }            /* …and restores the slice under the cursor */
  .pcleg { display:flex; flex-wrap:wrap; gap:3px 9px; margin:7px 2px 0; }
  .pclegi { display:inline-flex; align-items:center; gap:4px; font-size:10.5px; color:var(--muted); white-space:nowrap; }
  .pclegsw { width:9px; height:9px; border-radius:2px; flex:none; }
  /* tabular-nums so a column of figures lines up on the digit, which is the entire point of a table */
  .pcv { text-align:right; font-variant-numeric:tabular-nums; font-weight:600; color:var(--text); }
  .pcv.none { color:var(--muted2); font-weight:400; }
  /* the placeholder that replaced "…": a bar, not text, so it cannot be mistaken for a value */
  .pcwait { display:inline-block; width:22px; height:8px; border-radius:2px; background:var(--line);
    vertical-align:middle; animation:pc-wait 1.3s ease-in-out infinite; }
  @keyframes pc-wait { 0%,100% { opacity:.45; } 50% { opacity:.85; } }
  @media (prefers-reduced-motion:reduce) { .pcwait { animation:none; } }
  /* BEST IN ROW. Marked only when there is something to win: an all-equal row gets no marker,
     because highlighting four identical numbers says nothing. Ties both get it. */
  .pcv.best { color:var(--accent-deep); font-weight:800; background:var(--selbg); }
  .pch { position:sticky; top:0; z-index:1; background:var(--surface); border-bottom:1px solid var(--line);
    padding:7px 7px 6px; cursor:pointer; min-width:0; }
  .pch.rail { left:0; z-index:3; border-right:1px solid var(--line); cursor:default; }
  /* THREE THINGS, THREE JOBS, VISIBLY APART (Will 2026-08-01: "fix the formatting of the stars and
     names of the routes so that it's not clumped together"). The dot identifies the route, the star
     chooses it, the eye shows/hides it. They used to run dot-star together on the left with the eye
     shoved to the far right by margin-left:auto — so the star read as decoration attached to the
     dot, and in a 96 px column the 26 px star pill left the name nowhere to go. The dot now sits
     alone on the left and the two CONTROLS group on the right, which is also what makes them read
     as buttons rather than as part of the label. */
  .pchtop { display:flex; align-items:center; gap:6px; min-height:24px; }
  .pch .padot { width:9px; height:9px; border-radius:50%; flex:none; box-shadow:0 0 0 2px rgba(28,48,64,.12); }
  .pch .pastar { margin-left:auto; }
  .pch .paeye { font-size:11px; }
  /* Both controls are pills on the CARD, where there is room for them. In the table they share a
     ~61px row with a coloured dot, and at 4 candidates that row was OVER-full (9 + 19 + 26 + gaps =
     62px into 61px) — which is why margin-left:auto above resolved to 0 and everything stayed
     jammed against the dot. Dropping both to bare glyphs buys the slack back, and lets the name
     underneath have the column to itself. Same colours, same states, no chrome. */
  .pch .pastar, .pch .paeye { width:19px; height:19px; background:none; border:0; padding:0; }
  .pch .pastar svg, .pch .paeye svg { width:15px; height:15px; }
  .pch .pastar:hover, .pch .pastar.on, .pch .paeye:hover { background:none; }
  /* Candidate statuses share one compact pill shape; their fill communicates who assigned them. */
  :is(.pcrec,.pcrefined) { display:block; margin-top:4px; padding:2px 5px; border:0; border-radius:var(--r-round);
    color:#fff; font-size:7.5px; font-weight:800; letter-spacing:.04em; text-align:center;
    white-space:nowrap; }
  .pcrec { background:var(--green); }
  .pcrefined { background:#000; }
  /* HIDDEN MEANS BLURRED, NOT DIMMED (Shubh 2026-07-30: "want the eye to blur out a column"). Dimming
     to opacity .45 still read as data you were meant to compare; a blur says "out of play" without
     pretending the column is gone. The blur is on the LABEL and the value cells only — never on
     .pchtop, because the eye that turns it back on lives there and has to stay sharp and clickable. */
  .pchid .pchlbl, .pcc.pchid { filter:blur(1.7px); opacity:.55; }
  @media (prefers-reduced-motion:reduce) { .pchid .pchlbl, .pcc.pchid { filter:none; opacity:.4; } }
  /* 2 lines then ellipsis: "Follows existing transmission" must not set the column's height.
     THE NAME IS THE "SHOW ME THIS ONE" CONTROL (Shubh 2026-07-30: "can either click on the name
     (balanced, follow existing ROW, etc), to highlight the line and zoom into it, or edit to actually
     start editing it") — so it has to look like something you can click. Underline on hover rather
     than always, or twelve underlined strings would compete with the numbers for attention. */
  /* THREE lines, not two: "Fewest counterparties" and "Follow existing ROW" are the names this app
     actually generates, and at 10px in a 73px column both need a third line. Clamping at two ate a
     whole word ("Fewest counterparti…"), which is the clumped, half-shown look being fixed here. */
  .pchlbl { margin-top:5px; font-size:11px; font-weight:700; line-height:1.3; color:var(--accent-deep);
    display:-webkit-box; -webkit-line-clamp:3; -webkit-box-orient:vertical; overflow:hidden;
    cursor:pointer; text-underline-offset:2px;
    /* the names are two and three words ("Fewest counterparties", "Follow existing ROW") and the
       column is narrow. break-word rather than `anywhere`: only split a word that genuinely cannot
       fit, and hyphenate it when we do — `anywhere` chopped at the raw column edge and produced
       "counterparti / es", where this gives "counterpar- / ties". */
    overflow-wrap:break-word; hyphens:auto; }
  .pchlbl:hover { text-decoration:underline; color:var(--accent); }
  /* the selected column is capped in its own route colour — the same signal the card's left border
     carries, rotated 90°, so card view and table view agree about what is selected */
  /* A BORDER AROUND THE COLUMN, NOT A TINT ACROSS IT (Shubh 2026-07-30: "when i select on a column, it
     highlights the whole, but then i can no longer see if any of the elements of that column were the
     least in the row … so instead, do a border / pop around the column").
     The tint was var(--selbg) — the SAME background .pcv.best uses to mark a winning number. Selecting
     a column therefore painted over exactly the marks you were selecting it to read. Drawn as inset
     shadows per cell rather than a real border, because each cell is its own grid item: left+right on
     every cell make the column's sides, the header adds the top cap, and the action cell closes the
     bottom. No background, so .best shows through unchanged. */
  .pcsel { box-shadow:inset 1.5px 0 0 0 var(--pc-c,var(--accent)), inset -1.5px 0 0 0 var(--pc-c,var(--accent)); }
  .pch.pcsel { box-shadow:inset 1.5px 0 0 0 var(--pc-c,var(--accent)), inset -1.5px 0 0 0 var(--pc-c,var(--accent)),
    inset 0 3px 0 0 var(--pc-c,var(--accent)); }
  .pcend.pcsel { box-shadow:inset 1.5px 0 0 0 var(--pc-c,var(--accent)), inset -1.5px 0 0 0 var(--pc-c,var(--accent)),
    inset 0 -1.5px 0 0 var(--pc-c,var(--accent)); }
  /* HOVERED FROM THE MAP (Shubh 2026-08-01: "if i hover over a route option on the map, should
     highlight it on the table … and vice versa"). Table→map already worked; this is the return
     leg. A TINT, not a border: selection owns the coloured rails above, and hover has to be
     legible on top of a selected column without being mistaken for one. */
  .pchov { background:var(--hitint); }
  .pch.pchov, .pcend.pchov { background:var(--hitint2); }
  .pcact { border:1px solid var(--accent); background:var(--surface); color:var(--accent-deep); font:inherit;
    font-size:10.5px; font-weight:700; width:100%; padding:5px 2px; border-radius:6px; cursor:pointer; white-space:nowrap; }
  .pcact:hover { background:var(--accent); color:#fff; }
  /* ✓ DONE IS THE ONE THING TO CLICK, SO IT LOOKS LIKE IT (Shubh 2026-07-31: "when editing one of
     the columns of the table, done button should be a bit more pronounced to click"). It carried
     .primary but nothing styled `.pcact.primary`, so it rendered identically to the ✎ Edit buttons
     it replaces — the same outline in the same cell, at a moment when every OTHER Edit is disabled
     and this is the only live control in the row. Filled, a size up, and ringed so the eye lands on
     it; the ring rather than a bigger box because the cell width is fixed by the column. */
  .pcact.primary { background:var(--accent-deep); border-color:var(--accent-deep); color:#fff;
    font-size:11.5px; padding:6px 2px; box-shadow:0 0 0 2px var(--accent-soft); }
  .pcact.primary:hover { filter:brightness(1.12); background:var(--accent-deep); color:#fff; }
  /* …and it keeps its size when four candidates squeeze the row (see .pctab.n4 .pcact) — shrinking
     the only actionable control to 9.5px is exactly the thing being complained about. */
  .pctab.n4 .pcact.primary { font-size:10.5px; padding:6px 1px; }
  /* REVERT AND ✓ DONE SHARE ✓ DONE'S CELL (Shubh 2026-08-02: "get rid of undo, just keep revert
     or done" — it was a trio for one commit).
     IT WRAPS RATHER THAN TRUNCATES, and the candidate count decides which it does. Measured in
     the real panel: a cell is ~127px at two candidates and ~65px at four, and each button needs
     ~37px. Two fit side by side down to ~77px, so the pair is a row at n2/n3 and stacks at n4 —
     which is the whole reason this is flex-wrap with a real min-width rather than a fixed layout:
     the cell answers for itself, with no viewport media query (the viewport is the wrong axis —
     the panel is a fixed-width sidebar; it is the CANDIDATE COUNT that squeezes these).
     37px is the widest label ("Revert", 32.1px at 9.5/700) plus its padding and border. */
  .pcacts { display:flex; flex-wrap:wrap; gap:3px; width:100%; }
  .pcacts .pcact { width:auto; flex:1 1 auto; min-width:37px; }
  .pcmini { font-size:9.5px; padding:5px 2px; border-radius:5px; letter-spacing:-.1px; }
  /* ✓ Done stays the pronounced one, but the 2px ring it earned on 2026-07-31 is dropped inside
     the group — at these widths the ring reads as a fourth border and costs the row a wrap. */
  .pcacts .pcact.primary { font-size:9.5px; padding:5px 2px; box-shadow:none; }
  /* No glyphs in the group: a leading "⤺ " costs 11px of a 37px button, which is the difference
     between a row and a wrap — and the word is the part that has to be read. */
  /* ↩ Revert sits beside ✎ IN USE — an action, so bordered rather than filled like the chip */
  .parev { margin-left:5px; border:1px solid var(--line); background:var(--surface); color:var(--accent-deep);
    font:inherit; font-size:9.5px; font-weight:800; letter-spacing:.04em; text-transform:uppercase;
    padding:2px 6px; border-radius:999px; cursor:pointer; white-space:nowrap; }
  .parev:hover { border-color:var(--accent); background:var(--selbg); }
  #pareto-cards::-webkit-scrollbar { height:8px; }
  #pareto-cards::-webkit-scrollbar-thumb { background:var(--line); border-radius:99px; }
  #pareto-cards::-webkit-scrollbar-track { background:transparent; }
  .pacard { border:1px solid var(--line); border-radius:var(--r); padding:11px 12px 10px; cursor:pointer;
            background:var(--surface); box-shadow:var(--shadow-sm); transition:background .12s,border-color .12s,box-shadow .15s; }
  .pacard:hover { border-color:#BFD4DE; box-shadow:var(--shadow); }
  .pacard.sel { background:var(--selbg); border-color:var(--accent); }
  /* ✕ legend: one chip per crossing type this route actually has, coloured to match the markers */
  .paxlegend { display:flex; flex-wrap:wrap; gap:4px 8px; margin:7px 0 2px; }
  .paxleg { display:inline-flex; align-items:center; gap:3px; font-size:10px; color:var(--muted);
    line-height:1.2; white-space:nowrap; }
  .paxlegx { font-size:11px; font-weight:800; }
  .paxlegn { font-weight:700; color:var(--text); }
  /* THE SELECTED CARD PULSES (Shubh 2026-07-28: "when i select a card and it's the one that's on,
     should be a bit more pulsing so it's easier to tell thats the route im referring to"). A static
     ring is easy to lose among four cards of similar shape; motion is the one channel nothing else
     in this panel uses. The colour comes from --pa-ring, set inline per card, so the pulse is the
     SAME colour as that route's outline on the map — the card, its ring and its line all agree.
     A CSS animation outranks the inline box-shadow in the cascade, which is why this works without
     touching the inline style. */
  @keyframes pa-sel-pulse {
    0%,100% { box-shadow:0 0 0 3px var(--pa-ring), var(--shadow); }
    50%     { box-shadow:0 0 0 10px var(--pa-ring-far), var(--shadow); }
  }
  .pacard.sel { animation:pa-sel-pulse 1.9s ease-in-out infinite; }
  @media (prefers-reduced-motion:reduce) {
    .pacard.sel { animation:none; box-shadow:0 0 0 3px var(--pa-ring), var(--shadow); }
  }
  /* THE CENTRED CARD IS LIVE WITHOUT A CLICK (Will 2026-07-31: "when on slider, should be able to
     highlight automatically and show the edit button without clicking on it").
     Two different things were both spelled `.sel`:
       · the real SELECTION — redraws the map layers, dims every other candidate, refits the
         viewport and lazily fetches that route's parcels and density over the network. That has to
         stay a settle-time action (paSettleSelect), and auto-selecting one on arrival is exactly
         what was rejected in 2026-07-17 for dimming the alternatives to near-invisible.
       · the HIGHLIGHT and the "Use & edit this route" button — pure presentation, and the two
         things you need in front of you before you have decided anything.
     `.pa-focus` is that second half, split out: a class toggle on whichever card the carousel is
     resting on, applied on every scroll event (paSyncNav) and on render, touching nothing else.
     So a freshly generated set arrives with card 1 highlighted and editable while all candidates
     stay at full strength on the map, and dragging the slider highlights as it goes instead of
     170 ms after you let go. */
  .pacard.pa-focus:not(.sel) { border-color:var(--accent);
    box-shadow:0 0 0 3px var(--pa-ring,rgba(28,48,64,.10)), var(--shadow); }
  .pacard .pause { display:none; }
  .pacard.sel .pause, .pacard.pa-focus .pause { display:block; }
  /* header: dot + verdict + title on the left, RECOMMENDED + HIDE pinned top-right.
     top-aligned so the pills don't float against a wrapped 2-line title. */
  .pacard .pahd { display:flex; align-items:flex-start; gap:7px; }
  .pacard .padot { width:11px; height:11px; border-radius:50%; flex:none; margin-top:3px; box-shadow:0 0 0 2.5px rgba(28,48,64,.12); }
  /* per-card risk verdict badge: ✓ low · ⚠ moderate · ✕ higher risk */
  .pacard .paverdict { width:17px; height:17px; flex:none; margin-top:1px; border-radius:50%; display:flex; align-items:center;
                   justify-content:center; font-size:11px; font-weight:800; line-height:1; }
  .pacard .paverdict.good { background:#dcfce7; color:#15803d; }
  .pacard .paverdict.warn { background:#fef9c3; color:#a16207; }
  .pacard .paverdict.bad  { background:#fee2e2; color:#b91c1c; }
  .pacard .patit { flex:1; min-width:0; font-size:12.5px; font-weight:700; line-height:1.3; padding-top:1px; }
  /* selected candidate: per-ROW mileage breakdown (colour swatches match the map core) */
  .pacard .pafollow { margin-top:8px; border-top:1px solid var(--divider); padding-top:7px; }
  .pacard .pafh { font-size:9px; font-weight:800; text-transform:uppercase; letter-spacing:.07em; color:var(--muted2); margin-bottom:4px; }
  .pacard .pafr { display:flex; align-items:center; gap:7px; font-size:11.5px; padding:1.5px 0; }
  .pacard .pafr .sw { width:16px; height:4px; border-radius:2px; flex:none; }
  .pacard .pafr .lbl { flex:1; color:var(--text); }
  .pacard .pafr b { font-variant-numeric:tabular-nums; }
  .pacard .pafr .pct { width:34px; text-align:right; color:var(--muted2); font-size:10.5px; }
  /* selected candidate: collapsible crossings & risks list (rows zoom to the crossing) */
  .pacard .paxing { margin-top:8px; border-top:1px solid var(--divider); padding-top:6px; }
  .pacard .paxing > summary { cursor:pointer; list-style:none; font-size:11px; font-weight:800;
                   text-transform:uppercase; letter-spacing:.04em; color:var(--muted2); }
  .pacard .paxing > summary::-webkit-details-marker { display:none; }
  .pacard .paxing[open] > summary { color:var(--text); margin-bottom:5px; }
  .pacard .paxlist { display:flex; flex-direction:column; gap:1px; max-height:230px; overflow:auto; }
  .pacard .paxk { display:flex; align-items:center; gap:6px; font-size:10.5px; margin:5px 0 1px; color:var(--muted2); }
  .pacard .paxk .paxsw { width:9px; height:9px; border-radius:50%; flex:none; }
  .pacard .paxk .paxn { margin-left:auto; font-variant-numeric:tabular-nums; }
  .pacard .paxrow { display:flex; align-items:center; gap:7px; width:100%; text-align:left; cursor:pointer;
                   background:transparent; border:0; border-radius:6px; padding:3px 6px; font-size:11.5px; color:var(--text); }
  .pacard .paxrow:hover { background:var(--selbg); }
  .pacard .paxrow .paxpin { width:7px; height:7px; border-radius:50%; flex:none; box-shadow:0 0 0 2px rgba(28,48,64,.12); }
  .pacard .paxhint { font-size:10.5px; color:var(--muted2); margin-top:5px; }
  /* ordered right-of-way sequence rows */
  .pacard .paseqlist { display:flex; flex-direction:column; gap:1px; max-height:260px; overflow:auto; }
  .pacard .paseqr { display:flex; align-items:center; gap:7px; width:100%; text-align:left; font-size:11.5px;
                   padding:3px 5px; cursor:pointer; background:transparent; border:0; border-radius:6px; color:var(--text); }
  .pacard .paseqr:hover { background:var(--selbg); }
  .pacard .paseqr.on { background:var(--selbg); box-shadow:inset 2px 0 0 var(--accent); }
  .pacard .paseqr .paseqn { width:16px; height:16px; flex:none; border-radius:50%; background:var(--divider);
                   color:var(--muted2); font-size:9.5px; font-weight:700; display:flex; align-items:center; justify-content:center; }
  .pacard .paseqr .paseqsw { width:14px; height:4px; border-radius:2px; flex:none; }
  .pacard .paseqr .paseql { flex:1; line-height:1.25; min-width:0; }
  .pacard .paseqr .paseqsub { color:var(--muted2); font-size:10.5px; }
  .pacard .paseqr .paseqmi { font-variant-numeric:tabular-nums; color:var(--text); font-size:11px; }
  /* grouped inspection sub-sections (counterparties-by-type · crossings-by-operator · landowners) */
  .pacard .paxsub { margin:2px 0 2px 2px; }
  .pacard .paxsub > summary { list-style:none; cursor:pointer; display:flex; align-items:center; gap:7px; font-size:11.5px;
                   padding:3px 6px; border-radius:6px; }
  .pacard .paxsub > summary::-webkit-details-marker { display:none; }
  .pacard .paxsub > summary::before { content:"\25B8"; color:var(--muted2); font-weight:800; font-size:9px; flex:none; }
  .pacard .paxsub[open] > summary::before { content:"\25BE"; }
  .pacard .paxsub > summary:hover { background:var(--selbg); }
  .pacard .paxsub > summary.pahi-on { background:var(--selbg); box-shadow:inset 2px 0 0 var(--accent); }
  .pacard .paxsub .paxsw { width:11px; height:4px; border-radius:2px; flex:none; }
  .pacard .paxsub .paxn { margin-left:auto; color:var(--muted2); font-variant-numeric:tabular-nums; font-size:10.5px; }
  .pacard .paxsub .paxsubkind { color:var(--muted2); font-size:10px; }
  .pacard .pacp { display:flex; align-items:center; gap:7px; width:100%; text-align:left; font-size:11px;
                   padding:3px 6px 3px 18px; cursor:pointer; background:transparent; border:0; border-radius:6px; color:var(--text); }
  .pacard .pacp:hover { background:var(--selbg); }
  .pacard .pacp .paseqsw { width:12px; height:4px; border-radius:2px; flex:none; }
  .pacard .pacp .paseql { flex:1; min-width:0; }
  .pacard .pacp.pahi-on, .pacard .paseqr.pahi-on { background:var(--selbg); box-shadow:inset 2px 0 0 var(--accent); }
  .pacard .paxitem { display:flex; align-items:center; gap:7px; font-size:11px; padding:2px 6px 2px 18px; color:var(--text); border-radius:6px; cursor:pointer; }
  .pacard .paxitem:hover { background:var(--selbg); }
  .pacard .paxitem .paxil { flex:1; min-width:0; }
  .pacard .paxrow .paxseqn { width:15px; flex:none; color:var(--muted2); font-size:9.5px; font-variant-numeric:tabular-nums; text-align:right; }
  .pacard .paxrow .paxil { flex:1; min-width:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
  /* landowner row loading spinner (while parcel geometry fetches) */
  .pacard .paxsubh.pa-loading::after { content:""; width:11px; height:11px; margin-left:6px; flex:none; border-radius:50%;
    border:2px solid var(--divider); border-top-color:var(--accent); animation:apspin .7s linear infinite; }
  /* custom "Add a point" dropdown (replaces the native <select>) */
  .apdd { position:relative; width:100%; }
  .apdd-btn { width:100%; display:flex; align-items:center; gap:8px; padding:9px 12px; border:1px solid var(--line);
    border-radius:9px; background:var(--surface); color:var(--text); font:inherit; font-size:12.5px; font-weight:600;
    cursor:pointer; text-align:left; box-shadow:var(--shadow); transition:border-color .12s; }
  .apdd-btn:hover { border-color:var(--accent); }
  .apdd-btn .apdd-ico { font-weight:800; color:var(--accent); font-size:14px; line-height:1; }
  .apdd-btn .apdd-lbl { flex:1; min-width:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
  .apdd-btn .apdd-car { color:var(--muted2); font-size:10px; transition:transform .15s; }
  .apdd.open .apdd-btn { border-color:var(--accent); box-shadow:0 0 0 3px rgba(28,48,64,.06); }
  .apdd.open .apdd-btn .apdd-car { transform:rotate(180deg); }
  .apdd-menu { position:absolute; left:0; right:0; top:calc(100% + 5px); z-index:40; background:var(--surface);
    border:1px solid var(--line); border-radius:11px; box-shadow:var(--shadow-lg); overflow:hidden; }
  .apdd-menu.hide { display:none; }
  .apdd-search { width:100%; box-sizing:border-box; padding:9px 12px; border:0; border-bottom:1px solid var(--line);
    background:var(--panel); color:var(--text); font:inherit; font-size:12px; outline:none; }
  .apdd-list { max-height:280px; overflow-y:auto; padding:5px; }
  .apdd-grp { font-size:9.5px; font-weight:800; letter-spacing:.07em; text-transform:uppercase; color:var(--muted2); padding:8px 8px 3px; }
  .apdd-item { display:flex; align-items:center; gap:8px; width:100%; text-align:left; padding:7px 8px; border:0;
    background:none; color:var(--text); font:inherit; font-size:12px; cursor:pointer; border-radius:8px; }
  .apdd-item:hover { background:var(--selbg); }
  .apdd-item .apdd-dot { width:9px; height:9px; border-radius:50%; flex:none; border:1.5px solid #fff; box-shadow:0 0 0 1px rgba(28,48,64,.25); }
  .apdd-item .apdd-nm { flex:1; min-width:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
  .apdd-item .apdd-sub { color:var(--muted2); font-size:10.5px; }
  .apdd-item .apdd-tag { font-size:9px; font-weight:800; letter-spacing:.04em; padding:2px 7px; border-radius:999px; color:#fff; flex:none; }
  .apdd-empty { padding:14px; text-align:center; color:var(--muted2); font-size:11.5px; }
  .pacard .in-kv { display:flex; gap:8px; font-size:11.5px; padding:2px 2px; }
  .pacard .in-kv .k { flex:1; color:var(--text); min-width:0; }
  .pacard .in-kv .v { color:var(--muted2); font-variant-numeric:tabular-nums; white-space:nowrap; }
  .pacard .parec { flex:none; align-self:flex-start; font-size:9px; font-weight:800; letter-spacing:.06em; color:#fff;
                   background:var(--green); border-radius:999px; padding:3px 9px; white-space:nowrap; }
  /* Map-visibility toggle: an EYE (Shubh 2026-07-30). It was the words HIDE / SHOW in a fixed-width
     pill — the width was there so the label swap could not shift the layout, which an icon makes
     moot. The struck-through state is drawn with a rotated pseudo-element rather than a second glyph,
     so both states are the same SVG and can never disagree in size or alignment. */
  /* UNSCOPED FROM .pacard (Shubh 2026-07-30: "i also don't see the eye to disappear it"). Every rule
     here was written when the eye existed only on a candidate CARD, so in the compare table the
     glyph inherited no width/height and rendered at zero size — an invisible control. The eye is
     the same control in both surfaces and now has one definition; nothing here was card-specific. */
  .paeye { flex:none; align-self:flex-start; cursor:pointer; box-sizing:border-box;
                   position:relative; width:26px; height:22px; display:flex; align-items:center; justify-content:center;
                   background:var(--panel); border:1px solid var(--line); border-radius:999px;
                   color:var(--muted); user-select:none; }
  .paeye svg { width:14px; height:14px; display:block; }
  .paeye:hover { color:var(--accent-deep); border-color:var(--accent); background:var(--selbg); }
  .paeye:focus-visible { outline:2px solid var(--accent); outline-offset:1px; }
  /* OFF: dimmed, plus the slash. The line is inset 3px so it reads as crossing the eye rather than
     the button, and it carries a light outline so it stays visible over the glyph's own strokes. */
  .paeye.off { color:var(--muted2); }
  .paeye.off::after { content:""; position:absolute; left:3px; right:3px; top:50%;
                              border-top:1.5px solid currentColor; transform:rotate(-45deg);
                              box-shadow:0 -1.5px 0 var(--panel); }
  /* THE STAR — "the route you want to be visible" (Shubh 2026-08-01). Same pill as the eye so the
     two controls read as one pair, and deliberately NOT the accent colour: amber is the one hue on
     this panel that is never a route colour, so a lit star can never be mistaken for a candidate's
     own swatch. Unstarred is an outline at the eye's own muted weight — present, but not competing
     with the numbers underneath. */
  .pastar { flex:none; align-self:flex-start; cursor:pointer; box-sizing:border-box; position:relative;
    width:26px; height:22px; display:flex; align-items:center; justify-content:center;
    background:var(--panel); border:1px solid var(--line); border-radius:999px;
    color:var(--muted); user-select:none; }
  .pastar svg { width:14px; height:14px; display:block; }
  .pastar:hover { color:#B45309; border-color:#F59E0B; background:#FFFBEB; }
  .pastar:focus-visible { outline:2px solid var(--accent); outline-offset:1px; }
  .pastar.on { color:#D97706; border-color:#F59E0B; background:#FFFBEB; }
  .pch .pastar { font-size:11px; }
  .pacard .paopt { font-size:9.5px; font-weight:700; text-transform:uppercase; letter-spacing:.06em; margin:5px 0 0; }
  .pacard .pasum { font-size:11px; color:var(--muted); margin:4px 0 8px; line-height:1.45; }
  .pacard .pastats { display:grid; grid-template-columns:repeat(3,1fr); gap:6px; margin:0 0 7px; }
  .pacard .pastat { background:var(--panel); border:1px solid var(--line); border-radius:var(--r-sm); padding:5px 8px 4px; min-width:0; }
  .pacard .pastat .k { display:block; font-size:8.5px; text-transform:uppercase; letter-spacing:.05em; color:var(--muted2); margin-bottom:1px; }
  .pacard .pastat .v { font-size:13px; font-weight:800; font-variant-numeric:tabular-nums; }
  .pacard .pastat .u { font-size:9.5px; color:var(--muted); font-weight:600; }
  .pacard .pabar { height:4px; background:var(--track); border-radius:2px; margin:0 0 8px; overflow:hidden; }
  .pacard .pabar i { display:block; height:100%; border-radius:2px; }
  .pacard .padet { font-size:11px; line-height:1.6; }
  .pacard .padet .parow { display:flex; justify-content:space-between; gap:10px; }
  .pacard .padet .parow span { color:var(--muted2); }
  .pacard .padet .parow b { font-weight:700; font-variant-numeric:tabular-nums; text-align:right; }
  .pacard .pagood { font-size:11px; margin-top:7px; color:var(--pro); line-height:1.5; }
  .pacard .pabad  { font-size:11px; margin-top:3px; color:var(--con); line-height:1.5; }
  /* density-flag rows in the expanded candidate card — severity colours match the ⚠ chips */
  .pacard .padr { display:flex; align-items:flex-start; gap:6px; width:100%; text-align:left; font-size:11px; line-height:1.4;
    padding:3px 6px; cursor:pointer; background:transparent; border:0; border-radius:6px; }
  .pacard .padr:hover, .pacard .padr.pahi-on { background:var(--selbg); }
  .pacard .padr.high { color:var(--con); font-weight:700; }
  .pacard .padr.med  { color:#92400e; }
  .lgck > input { flex:none; width:15px; height:15px; margin:0; cursor:pointer; }
  .lgck.off { opacity:.68; }
  .lgck.off .lgtx { text-decoration:none; color:var(--muted2); }
  .lgck.lgall { font-weight:700; }
  .lgsw.sel { position:relative; background:transparent; border:1.6px solid var(--ckbd); border-radius:50%; }
  .lgall:not(.off) .lgsw.sel { background:var(--green); border-color:var(--green); }
  .lgall:not(.off) .lgsw.sel::after { content:"✓"; position:absolute; inset:0; font-size:8.5px; line-height:12px; text-align:center; color:#fff; font-weight:900; }
  /* right bar planner — stepper as pill segments */
  .stepper { display:flex; gap:6px; padding:12px 14px; }
  .step { flex:1; text-align:center; font-size:12.5px; font-weight:700; padding:10px 4px; background:var(--panel);
    color:var(--muted); letter-spacing:-.01em; border-radius:999px; border:1px solid transparent; }
  .step.active { background:var(--accent); color:#fff; } .step.done { background:var(--green-soft); color:var(--pro); }
  .step.next { background:var(--accent-soft); color:var(--accent-deep); border-color:var(--accent); animation:atpulse 1.9s ease-out infinite; }
  /* "look here" pulse to guide the user to the first step + start button */
  @keyframes atpulse { 0%{ box-shadow:0 0 0 0 rgba(42,86,116,.45);} 70%{ box-shadow:0 0 0 9px rgba(30,126,158,0);} 100%{ box-shadow:0 0 0 0 rgba(30,126,158,0);} }
  /* numbered "get started" guide */
  .startsteps { margin:2px 0 4px; }
  .ss { display:flex; gap:10px; align-items:flex-start; padding:9px 2px; border-bottom:1px solid var(--divider); }
  .ss:last-child { border-bottom:none; }
  .ss.on .ssn { background:var(--accent); color:#fff; animation:atpulse 1.9s ease-out infinite; }
  .ssn { flex:none; width:22px; height:22px; border-radius:50%; background:var(--panel); color:var(--muted); font-size:12px; font-weight:700; display:flex; align-items:center; justify-content:center; }
  .ss b { font-size:12.5px; } .ssd { font-size:11px; color:var(--muted); margin-top:2px; line-height:1.4; }
  .swi { display:inline-block; width:9px; height:9px; border:1px solid var(--ckbd); vertical-align:middle; margin:0 2px; }
  @keyframes pulse { 0%,100%{ box-shadow:0 0 0 0 rgba(21,47,71,.45);} 50%{ box-shadow:0 0 0 6px rgba(21,47,71,0);} }
  .btn.primary.pulse { animation:pulse 1.8s ease-in-out infinite; }
  .prompt { font-size:12.5px; line-height:1.5; } .prompt b { background:var(--accent-soft); color:var(--accent-deep); padding:1px 7px; border-radius:4px; }
  .prompt b.hi-supply { background:var(--supply); color:#fff; } .prompt b.hi-load { background:var(--load); color:#fff; }
  button.btn.primary { background:var(--accent-deep); color:#fff; border-color:var(--accent-deep); font-weight:700; }
  button.btn.primary:hover { filter:brightness(1.1); background:var(--accent-deep); }
  #getstarted { animation:atpulse 1.9s ease-out infinite; }
  .card { border:1px solid var(--line); padding:9px 11px; margin:7px 0; background:var(--surface); border-radius:var(--r-sm); box-shadow:var(--shadow-sm); }
  .card .t { font-weight:700; font-size:12.5px; display:flex; align-items:center; gap:8px; cursor:pointer; }
  .card .t:hover .cardname { color:var(--accent-deep); }
  .card .cardhd { display:flex; flex-direction:column; min-width:0; flex:1; }
  .card .cardname { font-weight:700; letter-spacing:-.01em; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
  .card .cardsub { font-size:10.5px; font-weight:500; color:var(--muted); white-space:nowrap; overflow:hidden; text-overflow:ellipsis; margin-top:1px; }
  .card .caret { color:var(--muted2); font-size:11px; flex:none; }
  .card .cardbody { display:none; margin-top:8px; padding-top:8px; border-top:1px solid var(--divider); }
  .card.open .cardbody { display:block; }
  .card .m { color:var(--muted); font-size:11px; margin-top:3px; }
  .card .dr { display:flex; justify-content:space-between; gap:12px; font-size:11px; margin:2.5px 0; }
  .card .dr .dk { color:var(--muted); flex:none; } .card .dr .dv { color:var(--text); font-weight:700; text-align:right; }
  .card .drs { margin-top:6px; }
  .card .chg { font-size:10.5px; color:var(--accent); cursor:pointer; flex:none; font-weight:700; }
  .pin { display:inline-flex; width:17px; height:17px; color:#fff; font-size:10px; font-weight:700; align-items:center; justify-content:center; border:2px solid #fff; border-radius:50%; box-sizing:border-box; box-shadow:0 0 0 1px rgba(28,48,64,.25); }
  .stats { display:flex; border-top:1px solid var(--line); border-bottom:1px solid var(--line); background:var(--panel); }
  .stat { flex:1; padding:9px 12px; border-right:1px solid var(--line); } .stat:last-child{border-right:none;}
  .stat .k { font-size:9.5px; color:var(--muted2); text-transform:uppercase; letter-spacing:.05em; font-weight:700; }
  .stat .v { font-size:18px; font-weight:800; letter-spacing:-.03em; color:var(--accent-deep); }
  .row { display:flex; gap:6px; padding:10px 14px 4px; flex-wrap:wrap; }
  button.btn { font:inherit; font-size:12px; padding:6px 13px; border:1px solid var(--btnbd); background:var(--surface);
    color:var(--text); cursor:pointer; border-radius:999px; font-weight:600; transition:background .12s,border-color .12s,box-shadow .12s; }
  button.btn:hover{background:var(--hover); border-color:var(--btnbd2);} button.btn:disabled{opacity:.4;cursor:default;}
  button.btn.back:not(:disabled) { border-color:var(--accent); color:var(--accent-deep); font-weight:700; }
  .sect-h { font-size:10.5px; font-weight:700; letter-spacing:.06em; text-transform:uppercase; margin:0 0 6px; color:var(--muted); }
  .sect-h.pro{color:var(--pro);} .sect-h.con{color:var(--con);}
  .finding { border-left:3px solid; padding:7px 9px; margin:4px 0; font-size:11.5px; line-height:1.4; background:var(--panel); border-radius:0 var(--r-sm) var(--r-sm) 0; }
  .finding.pro{border-color:var(--pro);} .finding.con{border-color:var(--con);}
  .aibox { margin-top:8px; padding:9px 11px; border-left:3px solid var(--accent); background:var(--panel); font-size:11.5px; line-height:1.45; border-radius:0 var(--r-sm) var(--r-sm) 0; }
  #movetip { position:absolute; top:56px; right:12px; z-index:6; width:250px; max-height:calc(100% - 135px); overflow-y:auto;
    background:var(--glass2); border:1px solid var(--line); border-left:3px solid var(--accent); padding:10px 13px;
    font-size:11.5px; line-height:1.4; border-radius:var(--r-sm); box-shadow:var(--shadow); pointer-events:none; backdrop-filter:blur(4px); }
  #movetip .mv-h { font-size:9.5px; font-weight:700; text-transform:uppercase; letter-spacing:.06em; color:var(--muted2); margin-bottom:4px; }
  #movetip .mv-v { font-weight:700; font-size:12.5px; margin-bottom:4px; }
  #movetip .mv-ok{color:var(--pro);} #movetip .mv-warn{color:#C08A1C;} #movetip .mv-bad{color:var(--con);}
  #movetip .mv-r { color:var(--muted); margin:2px 0; }
  /* segment inspector — top-right box shown when a route stretch is clicked on the map */
  #seginfo { position:absolute; top:56px; right:12px; z-index:8; width:290px; max-height:calc(100% - 135px); overflow-y:auto;
    background:var(--surface); border:1px solid var(--line); border-left:3px solid var(--accent); padding:12px 14px;
    font-size:12px; line-height:1.4; color:var(--text); border-radius:var(--r-sm); box-shadow:var(--shadow-lg); }
  #seginfo .si-h { display:flex; align-items:center; font-weight:800; font-size:13.5px; color:var(--text); letter-spacing:-.01em; margin-bottom:7px; }
  #seginfo .si-h .si-sw { display:inline-flex; margin-right:6px; }
  #seginfo .si-x { margin-left:auto; background:none; border:0; color:var(--muted2); cursor:pointer; font-size:13px; padding:0 2px; }
  #seginfo .si-x:hover { color:var(--text); }
  #seginfo .si-r { display:flex; gap:14px; justify-content:space-between; margin:3px 0; }
  #seginfo .si-k { color:var(--muted); } #seginfo .si-v { color:var(--text); text-align:right; font-weight:700; }
  #seginfo .si-sec { font-size:9.5px; font-weight:700; text-transform:uppercase; letter-spacing:.06em; color:var(--muted2); margin:9px 0 3px; }
  #seginfo .si-note { color:var(--muted); margin:2px 0; font-size:11.5px; }
  #seginfo .si-drop { width:100%; text-align:left; background:var(--panel); border:1px solid var(--line);
    color:var(--text); border-radius:var(--r-sm); padding:8px 11px; font:inherit; font-size:12.5px; font-weight:600; cursor:pointer; }
  #seginfo .si-drop:hover { background:var(--hover); border-color:var(--btnbd2); }
  #seginfo .si-droplist { margin-top:5px; display:flex; flex-direction:column; gap:2px; }
  #seginfo .si-droplist.hide { display:none; }
  #seginfo .si-opt { display:flex; align-items:center; gap:8px; padding:6px 9px; border-radius:var(--r-sm); cursor:pointer; }
  #seginfo .si-opt:hover { background:var(--hover); }
  #seginfo .si-opt.empty { color:var(--muted2); cursor:default; padding:6px 2px; } #seginfo .si-opt.empty:hover { background:none; }
  #seginfo .si-osw { flex:none; display:inline-flex; }
  #seginfo .si-ol { flex:1; min-width:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; } #seginfo .si-ol b { color:var(--text); font-weight:700; }
  #seginfo .si-om { color:var(--muted2); font-size:11px; }
  #seginfo .si-od { flex:none; color:var(--muted2); font-size:11px; font-variant-numeric:tabular-nums; }
  #seginfo .si-gf { border-top:1px solid var(--line); margin-top:3px; padding-top:7px; }
  .rowdot{width:9px;height:9px;border-radius:2px;flex:none;display:inline-block;vertical-align:middle;margin-right:5px;}
  /* "rights of way followed" rows — compact, same font family as the rest of the UI */
  .sug { font-size:11px; line-height:1.4; padding:2px 0; color:var(--text); }
  .sug .sugsw { display:inline-block; width:38px; vertical-align:middle; }   /* fixed swatch column → numbers always align */
  .sug .sugsw svg, .sug .sugsw .rowdot { vertical-align:middle; margin:0; }
  .sug b { font-weight:700; }
  /* inspection lists (parcels / landowners / counterparties) — collapsed items, expand for detail */
  #inspect { border-top:1px solid var(--line); }
  #inspect .in-h { display:flex; align-items:center; justify-content:space-between; font-size:11px; font-weight:700;
    text-transform:uppercase; letter-spacing:.05em; color:var(--muted); margin-bottom:6px; }
  #inspect .in-h button { border:none; background:none; color:var(--accent); font:inherit; cursor:pointer; font-weight:700; }
  details.insp { border:1px solid var(--line); background:var(--surface); margin-bottom:4px; border-radius:var(--r-sm); }
  details.insp > summary { list-style:none; cursor:pointer; padding:7px 10px; font-size:11.5px; display:flex; gap:6px; align-items:center; }
  details.insp > summary::-webkit-details-marker { display:none; }
  details.insp > summary::before { content:"▸"; color:var(--muted2); flex:none; }
  details.insp[open] > summary::before { content:"▾"; }
  details.insp .in-body { padding:2px 10px 8px 23px; font-size:11px; }
  details.insp .in-kv { display:flex; justify-content:space-between; gap:12px; padding:1.5px 0; }
  details.insp .in-kv .k { color:var(--muted); flex:none; }
  details.insp .in-kv .v { text-align:right; font-weight:700; }
  .hiclk { cursor:pointer; border-radius:6px; }
  .hiclk:hover { background:var(--hitint); }
  .hiclk.hion { background:var(--hitint2); box-shadow:inset 2px 0 0 var(--accent); }   /* currently highlighted on the map */
  .sug .sugmeta { display:block; margin-left:38px; font-size:10px; color:var(--muted2); line-height:1.35; }
  .rowtbl{width:100%;border-collapse:collapse;font-size:11px;margin-top:3px;}
  .rowtbl td{padding:5px 5px;border-bottom:1px solid var(--divider);vertical-align:top;cursor:pointer;}
  .rowtbl tr:hover td{background:var(--hover);}
  .rowtbl td.num{text-align:right;color:var(--muted);white-space:nowrap;}
  .rowtbl .sub2{color:var(--muted);font-size:10px;margin-top:1px;}
  .card .lnk { display:flex; flex-wrap:wrap; gap:8px; margin-top:6px; }
  .card .lnk a { font-size:11px; color:var(--accent); text-decoration:none; border:1px solid var(--line); padding:2.5px 9px; border-radius:999px; font-weight:600; }
  .card .lnk a:hover { background:var(--hover); border-color:var(--accent); }
  .empty { color:var(--muted2); font-size:11.5px; font-style:italic; }
  .conn { border:1px solid var(--line); padding:8px 10px; margin:5px 0; font-size:11.5px; background:var(--surface); border-radius:var(--r-sm); }
  .conn .t { font-weight:700; } .conn .m { color:var(--muted); margin-top:2px; }
  /* ABOVE #addpoints (z 12) and #measurebtn (z 11) (Shubh 2026-07-28: "when i search stuff up, it
     sometimes gets covered"). #searchsugs drops DOWN from the box straight across both of those
     controls, and at z 5 the results rendered underneath them — the first two hits were unreadable
     and unclickable. 15 clears them both while staying under the panels at 20/30 and the modals at
     60, so nothing that should sit above the map chrome is now behind the search. */
  /* Anchored LEFT but also bounded RIGHT so the pill SHRINKS on a narrow map instead of
     sliding under the basemap switcher (Will 2026-08-11: "search gen,load covers the basic
     satellite and sharpest map overlay"). 624px = the switcher's right offset (302) plus its
     own ~310px width and a 12px gap; max-width restores the classic 270px whenever there is
     room, and min-width on the input keeps it usable at the squeeze point. */
  #mapsearch { position:absolute; top:12px; left:12px; right:624px; max-width:270px; z-index:15; }
  #mapsearch input { width:100%; min-width:150px; padding:9px 16px; border:1px solid var(--line); border-radius:999px; background:var(--surface);
    color:var(--text); font:inherit; font-size:12.5px; box-shadow:var(--shadow); outline:none; }
  #mapsearch input:focus { border-color:var(--accent); box-shadow:0 0 0 3px rgba(42,86,116,.16), var(--shadow); }
  #mapsearch input::placeholder { color:var(--muted2); }
  #searchsugs { position:absolute; top:42px; left:0; width:340px; background:var(--surface);
    border:1px solid var(--line); border-radius:var(--r); overflow:hidden; box-shadow:var(--shadow-lg); max-height:320px; overflow-y:auto; }
  #searchsugs .ss { display:flex; align-items:center; gap:8px; padding:8px 12px; font-size:12px; cursor:pointer; }
  #searchsugs .ss:hover, #searchsugs .ss.sel { background:var(--hover); }
  #searchsugs .ss .dot { width:9px; height:9px; border-radius:50%; flex:none; border:1.5px solid #fff; box-shadow:0 0 0 1px rgba(28,48,64,.25); }
  #searchsugs .ss .nm { overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
  #searchsugs .ss .kd { margin-left:auto; flex:none; font-size:10.5px; color:var(--muted2); }
  /* why a hit with no name match is in the list — "· via operator EdgeConneX" */
  #searchsugs .ss .ssvia { color:var(--accent); }
  /* STICKY, because it answers "is that all of them?" and the list above it scrolls: a footer
     that scrolled away would be invisible exactly when the list is long enough to need it. */
  #searchsugs .ssmore { position:sticky; bottom:0; background:var(--panel); border-top:1px solid var(--line);
    padding:6px 12px; font-size:10.5px; color:var(--muted); }
  #maptools { position:absolute; top:54px; left:12px; z-index:5; display:flex; gap:3px; background:var(--surface); border:1px solid var(--line);
    padding:3px; border-radius:999px; box-shadow:var(--shadow); }
  #maptools button { border:none; background:transparent; font:inherit; font-size:11.5px; padding:5px 12px; cursor:pointer; color:var(--muted); border-radius:999px; font-weight:600; }
  #maptools button:hover { background:var(--hover); color:var(--text); }
  #maptools button.on { background:var(--accent-soft); color:var(--accent-deep); }
  /* SHARE (Shubh 2026-07-27) — top-right corner pill; the basemap switcher slides left to make
     room for it, so both share the top row and nothing had to move down. */
  /* while candidates generate: the map goes soft and says so (Shubh 2026-07-27). The blur is on
     #map, NOT on the overlay's parent, so the text stays perfectly sharp on top of it. */
  #genveil { position:absolute; inset:0; z-index:30; display:flex; align-items:center; justify-content:center;
    background:rgba(246,248,250,.35); pointer-events:none; }
  #genveil.hide { display:none; }
  #genveil .gv-box { display:flex; align-items:center; gap:11px; background:var(--surface);
    border:1px solid var(--line); border-radius:999px; padding:11px 20px; box-shadow:var(--shadow-lg);
    font-size:13px; font-weight:700; color:var(--accent-deep); letter-spacing:-.01em; }
  #genveil .gv-spin { width:15px; height:15px; border:2px solid var(--accent-soft);
    border-top-color:var(--accent-deep); border-radius:50%; animation:gvspin .8s linear infinite; flex:none; }
  @keyframes gvspin { to { transform:rotate(360deg); } }
  body.generating #map { filter:blur(3px) saturate(.85); transition:filter .25s ease; }
  #sharebtn { position:absolute; top:12px; right:12px; z-index:6; display:flex; align-items:center; gap:7px;
    background:var(--accent-soft); color:var(--accent-deep); border:1px solid transparent; border-radius:999px;
    font:inherit; font-size:12px; font-weight:800; padding:7px 14px; cursor:pointer; box-shadow:var(--shadow); }
  #sharebtn:hover { border-color:var(--accent); }
  #sharebtn.hide { display:none; }
  /* Export: the same pill as Share, immediately left of it. right:112px would collide with
     #basemap, so this sits at the gap Share leaves — measured against Share's own padding
     rather than guessed, so the two read as a single group. */
  #exportbtn { position:absolute; top:12px; right:108px; z-index:6; display:flex; align-items:center; gap:7px;
    background:var(--surface); border:1px solid var(--line); border-radius:99px; color:var(--text);
    font:inherit; font-size:12px; font-weight:800; padding:7px 14px; cursor:pointer; box-shadow:var(--shadow); }
  #exportbtn:hover { border-color:var(--accent); }
  #exportmenu { position:absolute; top:48px; right:108px; z-index:8; width:236px; padding:5px;
    background:var(--surface); border:1px solid var(--line); border-radius:12px; box-shadow:var(--shadow-lg); }
  #exportmenu.hide { display:none !important; }
  #exportmenu button { display:block; width:100%; text-align:left; font:inherit; font-size:12.5px;
    font-weight:700; color:var(--text); background:none; border:0; border-radius:8px; padding:8px 10px;
    cursor:pointer; }
  #exportmenu button:hover { background:var(--hover); }
  #exportmenu button[disabled] { opacity:.5; cursor:progress; }
  #exportmenu small { display:block; font-weight:500; font-size:10.5px; color:var(--muted); margin-top:1px; }
  #exportbtn.hide { display:none; }
  #exportbtn[disabled] { opacity:.55; cursor:progress; }
  /* IMPORT: third in the row — Share (12), Export (108), Import (212) — taking the gutter the
     commented-out PDF pill left free. #basemap steps out to 316 to clear it (see its own note).
     Deliberately the SAME pill as Export rather than a variant: both are "move this design across a
     boundary", and giving one its own look would imply they are different kinds of thing. The menu
     restates Export's rules instead of sharing a class, because that is how #exportmenu is written
     and one selector list covering both would make either one hard to change alone. */
  /* 212 → 200: Import and Export read as ONE pair (Shubh 2026-08-03: "import/export button should be
     closer to each other"). Export occupies [108,194] from the right, so 200 leaves a 6px gap between
     them against the ~16px that separates Export from Share — which is the point, the two imports/exports
     group together and the group sits apart from Share. #basemap follows them in (316 → 302) so the space
     it left behind does not just move to the other side of Import. */
  #importbtn { position:absolute; top:12px; right:200px; z-index:6; display:flex; align-items:center; gap:7px;
    background:var(--surface); border:1px solid var(--line); border-radius:99px; color:var(--text);
    font:inherit; font-size:12px; font-weight:800; padding:7px 14px; cursor:pointer; box-shadow:var(--shadow); }
  #importbtn:hover { border-color:var(--accent); }
  /* PRESSED WHILE THE MENU IS OPEN, so it is obvious the thing is a toggle you have to click again.
     Keyed on aria-expanded — the same attribute the wiring already maintains for assistive tech, so
     the look and the announced state cannot drift apart. Share gets it too: its dialog is modal, but
     the pill behind the backdrop should still read as the one that is active. */
  #importbtn[aria-expanded="true"], #exportbtn[aria-expanded="true"] {
    background:var(--accent); border-color:var(--accent); color:var(--on-accent); box-shadow:var(--shadow-sm); }
  #sharebtn[aria-expanded="true"] { background:var(--accent); color:var(--on-accent); border-color:var(--accent); }
  #importbtn.hide { display:none; }
  #importbtn[disabled] { opacity:.55; cursor:progress; }
  #importmenu { position:absolute; top:48px; right:200px; z-index:8; width:250px; padding:5px;
    background:var(--surface); border:1px solid var(--line); border-radius:12px; box-shadow:var(--shadow-lg); }
  #importmenu.hide { display:none !important; }
  #importmenu button { display:block; width:100%; text-align:left; font:inherit; font-size:12.5px;
    font-weight:700; color:var(--text); background:none; border:0; border-radius:8px; padding:8px 10px;
    cursor:pointer; }
  #importmenu button:hover { background:var(--hover); }
  #importmenu button[disabled] { opacity:.5; cursor:progress; }
  #importmenu small { display:block; font-weight:500; font-size:10.5px; color:var(--muted); margin-top:1px; }
  /* PDF sits third in the same row — Share, Export, PDF — so the basemap switcher steps left again
     (right:212 → 296). Same pill as Export rather than a variant: they are the same KIND of action,
     "take this design somewhere else", and giving one of them its own look would imply otherwise.
     HEADS UP: #importbtn above now holds right:212 too. That is not a live collision — #pdfbtn's
     markup is commented out, so only one of them is ever in the DOM — but whoever un-comments the
     PDF pill has to give it the NEXT free gutter (right:316, where #basemap now sits) and step
     #basemap out again to ~412, or PDF will stack on Import and the switcher will land on PDF. */
  #pdfbtn { position:absolute; top:12px; right:212px; z-index:6; display:flex; align-items:center; gap:7px;
    background:var(--surface); border:1px solid var(--line); border-radius:99px; color:var(--text);
    font:inherit; font-size:12px; font-weight:800; padding:7px 14px; cursor:pointer; box-shadow:var(--shadow); }
  #pdfbtn:hover { border-color:var(--accent); }
  #pdfbtn.hide { display:none; }
  #pdfbtn[disabled] { opacity:.55; cursor:progress; }
  /* …and the basemap switcher steps left to make room, the same way it already does for Share */

  /* 296 → 316 when Import joined the row (2026-08-03). The switcher is ~317px wide (five basemaps),
     so at 296 its right edge landed on Import's left edge with a 1px overlap — verified in the
     browser, not eyeballed. The row is right-anchored and each pill clears the one before it by
     ~16-18px: Share [12,92] · Export [108,194] · Import [200,285] · basemap from 302. */
  #basemap { position:absolute; top:12px; right:302px; z-index:5; margin:0; box-shadow:var(--shadow); }
  /* SWITCHING SHOWS ITS WORK. The segment repaints the instant you click — that part is local —
     but the tiles behind it are a network fetch (Topographic especially: OpenTopoMap is a slow,
     rate-limited public tile server). Without this the map sat unchanged for a beat and the click
     read as dropped, so people clicked again, which is how three quick clicks and a race got
     discovered in the first place. A hairline sweep under the pill, nothing that shifts layout. */
  #basemap.bm-busy { position:absolute; }   /* keep the stacking context for ::after */
  #basemap.bm-busy::after { content:""; position:absolute; left:6px; right:6px; bottom:1px; height:2px;
    border-radius:2px; background:linear-gradient(90deg,transparent,var(--accent),transparent);
    background-size:60% 100%; background-repeat:no-repeat; animation:bmsweep .9s linear infinite; }
  @keyframes bmsweep { 0% { background-position:-60% 0; } 100% { background-position:160% 0; } }
  @media (prefers-reduced-motion:reduce) { #basemap.bm-busy::after { animation:none; opacity:.5; } }
  #basemap button:focus-visible { outline:2px solid var(--accent); outline-offset:1px; }
  /* share dialog — same shadowed-backdrop shape as #savemodal */
  /* THE BACKDROP SCROLLS, NOT THE CARD. The card used to be overflow-y:auto for tall rosters, which
     made it a clipping context — so the General-access menu, absolutely positioned inside it, was cut
     off at the card's bottom edge exactly where "Anyone with the link" sits (seen in the browser). Its
     menus are meant to overhang the card, as they do in the dialog this copies. margin:auto keeps a
     short card centred while a tall one scrolls instead of overflowing off-screen. */
  #accessmodal { position:fixed; inset:0; z-index:80; background:rgba(24,42,56,.44); display:flex; align-items:center; justify-content:center; padding:24px; overflow-y:auto; }
  #accessmodal.hide { display:none; }
  /* SHARE DIALOG, restyled after Google Drive's (Shubh 2026-08-03: "can you copy this share style.
     although we dont need the question mark or settings icon in top right"). Drive's LAYOUT and
     interaction are what is copied — the roomy card, the outlined add-people field, avatar rows with
     the role on the right, the globe chip, and checkmark menus instead of native selects.
     Its BLUE is not: every accent here is var(--accent), which the accent switcher repaints
     (navy/black/teal/green), so a literal #1a73e8 would be the one thing in the app that ignores it.
     No ? or ⚙ — asked for explicitly. The ✕ stays: Drive has none, but it is this app's escape hatch
     on every other modal and dropping it would make this the one dialog you cannot dismiss by symbol. */
  #accessmodal .ax-card { width:100%; max-width:512px; margin:auto; background:var(--surface); border:1px solid var(--line);
    border-radius:16px; box-shadow:var(--shadow-lg); padding:22px 24px 18px; }
  #accessmodal .ax-head { font-size:21px; font-weight:700; letter-spacing:-.02em; margin-bottom:18px; line-height:1.3; }
  #accessmodal .ax-sec { font-size:13.5px; font-weight:700; color:var(--text); letter-spacing:0;
    text-transform:none; margin:20px 0 6px; }
  /* OUTLINED FIELD with the label sitting on the border, Drive's text-field shape. It is a <label>
     wrapper rather than a placeholder so the field still says what it wants once you are typing in it. */
  #accessmodal .ax-add { display:flex; gap:8px; align-items:stretch; }
  #accessmodal .ax-field { position:relative; flex:1; min-width:0; display:block; }
  #accessmodal .ax-field .ax-flab { position:absolute; top:-6px; left:10px; padding:0 5px; background:var(--surface);
    font-size:11px; font-weight:600; color:var(--muted); line-height:1; pointer-events:none; transition:color .12s; }
  #accessmodal .ax-field:focus-within .ax-flab { color:var(--accent); }
  #accessmodal .ax-add input { width:100%; padding:13px 12px 11px; border:1px solid var(--btnbd); border-radius:8px;
    font:inherit; font-size:13px; background:var(--surface); color:var(--text); outline:none; transition:border-color .12s, box-shadow .12s; }
  #accessmodal .ax-field:focus-within input { border-color:var(--accent); box-shadow:0 0 0 1px var(--accent); }
  #accessmodal .ax-row { display:flex; align-items:center; gap:12px; padding:8px 0; }
  #accessmodal .ax-av { flex:none; width:34px; height:34px; border-radius:999px; background:var(--accent-soft); color:var(--accent-deep);
    display:flex; align-items:center; justify-content:center; font-size:12px; font-weight:800; }
  #accessmodal .ax-who { flex:1; min-width:0; font-size:13.5px; }
  #accessmodal .ax-who small { display:block; color:var(--muted); font-size:11.5px; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
  #accessmodal .ax-rolestatic { font-size:13px; color:var(--muted); flex:none; }
  #accessmodal .ax-gen { display:flex; align-items:flex-start; gap:12px; }
  /* the green globe puck, and it keeps its own colour: it reads as "public", not as chrome */
  #accessmodal .ax-gen .ax-av { background:var(--green-soft); color:var(--pro); font-size:15px; margin-top:1px; }
  #accessmodal .ax-gen .ax-who { padding-top:2px; }
  #accessmodal .ax-gen .ax-who small { margin-top:3px; white-space:normal; }
  /* The two pickers. A real <select> stays underneath as the source of truth (see axWireMenus) — this
     is only its trigger, so it must not be focusable-but-inert or the keyboard would reach two things. */
  #accessmodal .ax-hidden { position:absolute; width:1px; height:1px; opacity:0; pointer-events:none; }
  #accessmodal .ax-drop { display:inline-flex; align-items:center; gap:5px; max-width:100%; border:0; border-radius:6px;
    background:none; color:var(--text); font:inherit; font-size:13.5px; font-weight:600; padding:5px 8px;
    margin-left:-8px; cursor:pointer; transition:background .12s; }
  #accessmodal .ax-drop:hover { background:var(--hover); }
  #accessmodal .ax-drop[disabled] { cursor:default; color:var(--muted); }
  #accessmodal .ax-drop[disabled]:hover { background:none; }
  /* A DRAWN triangle, not the ▾ glyph. At the size Drive uses it, ▾ renders in Lato as a faint 4px
     smudge that does not read as "this opens" at all — verified in the browser. font-size:0 hides the
     character in the markup while the borders draw the arrow, so it stays crisp at any zoom. */
  #accessmodal .ax-drop .ax-car { flex:none; width:0; height:0; font-size:0; margin-top:2px;
    border-left:4.5px solid transparent; border-right:4.5px solid transparent; border-top:5px solid var(--muted); }
  #accessmodal .ax-drop[disabled] .ax-car { border-top-color:var(--muted2); }
  #accessmodal .ax-dropwrap { position:relative; flex:none; }
  #accessmodal .ax-menu { position:absolute; z-index:9; min-width:216px; padding:6px 0; background:var(--surface);
    border:1px solid var(--line); border-radius:10px; box-shadow:var(--shadow-lg); }
  #accessmodal .ax-who .ax-menu { left:-8px; top:calc(100% + 2px); }
  #accessmodal .ax-dropwrap .ax-menu { right:0; top:calc(100% + 4px); }
  #accessmodal .ax-menu.hide { display:none; }
  #accessmodal .ax-mhead { font-size:10px; font-weight:800; letter-spacing:.08em; text-transform:uppercase;
    color:var(--muted2); padding:5px 14px 6px; }
  #accessmodal .ax-mitem { display:flex; align-items:center; gap:10px; width:100%; text-align:left; border:0;
    background:none; color:var(--text); font:inherit; font-size:13.5px; padding:9px 14px; cursor:pointer; }
  #accessmodal .ax-mitem:hover { background:var(--hover); }
  /* Commenter is shown because the roles it sits between are real, and greyed because it does nothing
     yet (Shubh: "commenter can be unclickable for now"). Not hidden: a Viewer→Editor menu would imply
     no middle role exists. */
  #accessmodal .ax-mitem.off { color:var(--muted2); cursor:default; }
  #accessmodal .ax-mitem.off:hover { background:none; }
  #accessmodal .ax-mck { flex:none; width:16px; color:var(--accent); font-weight:800; font-size:12px; }
  /* the rule between the roles and the actions below them, as in the dialog this copies */
  #accessmodal .ax-msep { height:1px; background:var(--divider); margin:6px 0; }
  /* Remove access is destructive, so it says so on hover rather than looking like a fourth role */
  #accessmodal .ax-mitem.ax-mdanger:hover { background:#FDECEC; color:var(--con); }
  /* a person's row menu is wider than the role words alone — "Add expiration" sets the floor */
  #accessmodal #ax-people .ax-menu { min-width:196px; }
  /* the row itself lights up while its menu is open, so it is clear WHOSE access you are editing */
  #accessmodal .ax-row:has(.ax-drop[aria-expanded="true"]) { background:var(--hover); border-radius:8px; }
  /* THE ARROW SITS NEXT TO THE WORD, not at the far edge (Shubh 2026-08-03: "fix the arrow near
     'viewer' on the share page, its' too far to the right"). A native select puts its own arrow against
     the element's right edge and sizes the element well past its text, so "Viewer" left ~60px of empty
     box before the chevron. appearance:none drops Chrome's arrow and shrinks the box to content, and the
     caret comes back as a background image positioned 10px in — so the gap is fixed rather than whatever
     the platform chose. width:auto because .ax-add is a flex row and a stretched select would undo it.
     The arrow is #556474 = --muted, hardcoded because a data-URI cannot read a custom property; safe
     because the accent themes only repaint --accent*, never --muted. */
  #accessmodal select:not(.ax-hidden) { appearance:none; -webkit-appearance:none; width:auto;
    padding:9px 26px 9px 11px; border:1px solid var(--btnbd); border-radius:8px; font:inherit; font-size:13px;
    color:var(--text); background-color:var(--surface); cursor:pointer;
    background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='9' height='6'%3E%3Cpath d='M0 0h9L4.5 6z' fill='%23556474'/%3E%3C/svg%3E");
    background-repeat:no-repeat; background-position:right 10px center; }
  #accessmodal select:not(.ax-hidden):hover { border-color:var(--accent); }
  #accessmodal select:not(.ax-hidden)[disabled] { opacity:.55; cursor:default; }
  /* the per-person role selects in the people list are the same control, just smaller */
  #accessmodal #ax-people select { font-size:12.5px; padding:6px 24px 6px 9px; }
  #accessmodal .ax-foot { display:flex; align-items:center; justify-content:space-between; gap:10px; margin-top:22px; }
  /* Drive's footer pair: an outlined pill that reads as secondary, and a solid one that reads as done */
  #accessmodal .ax-foot .ax-copy { border:1px solid var(--btnbd); border-radius:999px; background:var(--surface);
    color:var(--accent); font-weight:700; font-size:13px; padding:9px 18px; }
  #accessmodal .ax-foot .ax-copy:hover { background:var(--accent-soft); border-color:var(--accent); }
  #accessmodal .ax-foot .ax-done { border-radius:999px; font-weight:700; font-size:13px; padding:9px 26px; }
  #accessmodal .ax-note { font-size:11.5px; color:var(--muted2); margin-top:8px; }
  #accessmodal .ax-x { background:none; border:none; font-size:15px; color:var(--muted2); cursor:pointer; padding:2px 6px; }
  #accessmodal .ax-x:hover { color:var(--con); }
  /* ── YOU NEED ACCESS ─────────────────────────────────────────────────────────────────────
     A PAGE, not an overlay: opaque, z above everything, and it owns the viewport. There is nothing
     behind it worth seeing — the design did not load — and a translucent scrim over an empty map is
     what made the old failure read as "something went wrong" instead of "you weren't invited". */
  #needaccess { position:fixed; inset:0; z-index:120; background:var(--surface); overflow-y:auto;
    display:flex; align-items:flex-start; justify-content:center; padding:64px 32px; }
  #needaccess.hide { display:none; }
  #needaccess .na-wrap { display:flex; gap:56px; align-items:flex-start; width:100%; max-width:960px; }
  #needaccess .na-col { flex:1; min-width:0; max-width:520px; }
  #needaccess .na-brand { display:block; height:31px; width:auto; margin-bottom:34px; }
  #needaccess .na-h { font-size:32px; font-weight:400; letter-spacing:-.02em; color:var(--text);
    margin:0 0 10px; line-height:1.2; }
  #needaccess .na-sub { font-size:14px; color:var(--muted); margin:0 0 22px; line-height:1.5; }
  #needaccess .na-roles { display:flex; flex-direction:column; gap:2px; margin-bottom:22px; }
  #needaccess .na-radio { display:flex; align-items:center; gap:14px; padding:8px 6px; border-radius:8px;
    font-size:15px; color:var(--text); cursor:pointer; }
  #needaccess .na-radio:hover { background:var(--hover); }
  #needaccess .na-radio input { width:18px; height:18px; margin:0; accent-color:var(--accent); cursor:pointer; }
  /* Commenter is offered nowhere yet — greyed here exactly as in the share dialog, so the three roles
     read as one consistent set across the product rather than differing by screen. */
  #needaccess .na-radio.na-off { color:var(--muted2); cursor:default; }
  #needaccess .na-radio.na-off:hover { background:none; }
  #needaccess .na-radio.na-off input { cursor:default; }
  #needaccess .na-msg { width:100%; box-sizing:border-box; padding:13px 14px; border:1px solid var(--btnbd);
    border-radius:8px; font:inherit; font-size:14px; color:var(--text); background:var(--surface);
    outline:none; resize:vertical; transition:border-color .12s, box-shadow .12s; }
  #needaccess .na-msg:focus { border-color:var(--accent); box-shadow:0 0 0 1px var(--accent); }
  #needaccess .na-act { display:flex; align-items:center; gap:14px; margin:22px 0 46px; }
  #needaccess .na-go { border-radius:999px; font-size:14px; font-weight:700; padding:11px 26px; }
  #needaccess .na-state { font-size:13px; color:var(--muted); }
  #needaccess .na-signed { font-size:13px; color:var(--muted); text-align:center; margin-bottom:8px; }
  #needaccess .na-chip { display:inline-flex; align-items:center; gap:9px; margin:0 auto; padding:7px 16px 7px 12px;
    border:1px solid var(--line); border-radius:999px; font-size:13.5px; color:var(--text);
    max-width:100%; overflow:hidden; }
  /* the chip is centred under the centred label, which a plain inline-flex will not do on its own */
  #needaccess .na-col > .na-chip { display:flex; width:fit-content; }
  #needaccess .na-dot { color:var(--accent); font-size:15px; line-height:1; }
  /* mark.svg, not favicon.svg — the favicon carries a dark tile behind the mark (it must read against
     both tab strips) and at low opacity that tile shows as a grey box. See the build script. */
  #needaccess .na-art { flex:none; width:240px; opacity:.09; padding-top:56px; }
  #needaccess .na-art img { display:block; width:100%; height:auto; }
  /* the art is decoration; it is the first thing to go when there is no room for it */
  @media (max-width:820px){ #needaccess .na-art { display:none; }
    #needaccess { padding:40px 22px; } #needaccess .na-h { font-size:27px; } }
  #basemap button { flex:0 0 auto; }
  /* BOOKMARKS panel — directly UNDER the Basic/Satellite/Topographic switcher and on its gutter
     (right:112px), so it reads as part of that stack rather than as a fourth floating control.
     z-index 13 puts it over #hovertip (7): the hover card starts at top:56px on the same side, so
     an open bookmark list has to win the overlap or the list you just opened is behind a card. */
  #bookmarks { position:absolute; top:52px; right:112px; z-index:13; width:208px; }
  #bookmarks.hide { display:none; }
  #bm-btn { background:var(--surface); box-shadow:var(--shadow); }
  #bookmarks .bm-count { font-size:10px; font-weight:800; color:var(--muted2); flex:none; }
  .bm-item { display:flex; align-items:flex-start; gap:8px; width:100%; text-align:left; padding:7px 8px;
    border:0; background:none; font:inherit; font-size:11.5px; color:var(--text); cursor:pointer; border-radius:8px; }
  .bm-item:hover { background:var(--selbg); }
  /* .apdd-dot is styled only as a descendant of .apdd-item, so a bookmark row has to restate it —
     the rows are the same visual language but not the same element. */
  .bm-item .apdd-dot { width:9px; height:9px; border-radius:50%; flex:none; border:1.5px solid #fff;
    box-shadow:0 0 0 1px rgba(28,48,64,.25); margin-top:4px; }
  .bm-main { flex:1; min-width:0; }
  .bm-main > span { display:block; }
  .bm-nm { font-weight:700; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
  .bm-note { color:var(--muted2); font-size:10.5px; line-height:1.35; overflow-wrap:anywhere; }
  .bm-x { flex:none; background:none; border:0; font:inherit; font-size:12px; font-weight:800;
    color:var(--muted2); cursor:pointer; padding:0 2px; line-height:1.4; }
  .bm-x:hover { color:var(--con); }
  /* the star + note control, shared by the top-right map card and the sidebar point card */
  .bmrow { display:flex; align-items:center; gap:6px; flex-wrap:wrap; margin-top:8px; }
  .bmstar { display:inline-flex; align-items:center; gap:5px; background:var(--surface); border:1px solid var(--line);
    border-radius:999px; font:inherit; font-size:11px; font-weight:800; padding:3px 10px; cursor:pointer; color:var(--text); }
  .bmstar:hover { border-color:var(--accent); }
  .bmstar.on { background:#FEF3C7; border-color:#F59E0B; color:#92400E; }
  span.bmstar { cursor:default; }
  .bmnote { font-size:10.5px; color:var(--muted2); line-height:1.4; margin-top:5px; overflow-wrap:anywhere; }
  /* THE STAR RIDES THE CARD'S TOP RIGHT (Shubh 2026-07-30: "bookmark is at the bottom, it should
     be at the top right of the card"). On a load card the provenance rows push the bottom of the
     card past the fold, so the card's primary action was the one thing you had to scroll to reach.
     It sits in the header ROW rather than absolutely positioned, so a long kicker squeezes the
     kicker and never collides with the star — and `.selfold summary`'s 18px right padding already
     reserves the ▾'s lane, so the two cannot overlap either. */
  #hovertip .hrow { display:flex; align-items:flex-start; justify-content:space-between; gap:8px; }
  #hovertip .hrow .th { flex:1 1 auto; min-width:0; }
  /* THE NAME AND THE ☆ STAY PUT WHILE THE CARD SCROLLS (Shubh 2026-07-30: "the name and bookmark
     should stay there even when i scroll down"). #hovertip is the scrollport, so the header sticks
     to it: .hhead on a plain hover card, and the <summary> itself on a foldable one — the ▾ is
     positioned against the summary, so sticking an inner wrapper would leave it behind.
     top:-12px with the padding/margin pair is what keeps rows from showing through #hovertip's own
     12px top padding as they pass under a header parked at the very top. The background must be
     opaque for the same reason. */
  #hovertip .hhead, #hovertip .selfold > summary {
    position:sticky; top:-12px; z-index:3; background:var(--surface);
    padding-top:12px; margin-top:-12px; }
  /* the card head's action cluster: Ask AI + Bookmark + Lists sit on ONE row, right-aligned,
     wrapping as a row when the card is narrow (they used to stack — unstyled block divs) */
  .hact { display:flex; align-items:center; justify-content:flex-end; flex-wrap:wrap; gap:4px; flex:none; }
  .hact .dossbtn { margin:0; }
  .bmhd { flex:none; display:flex; align-items:center; gap:4px; margin-top:0; }
  .bmhd .bmstar { font-size:10px; padding:2px 7px; gap:4px; }
  /* shared-lists control + its inline picker on the point card (explore-lists.mjs) */
  .xlbtn.on { background:#E1E9F1; border-color:#2A5674; color:#152F47; }
  .xlpane { margin-top:7px; border:1px solid var(--line); border-radius:8px; background:var(--surface); padding:7px 9px; }
  .xlt { font-size:9px; font-weight:700; letter-spacing:.06em; text-transform:uppercase; color:var(--muted); margin-bottom:4px; }
  .xlrow { display:flex; align-items:center; gap:6px; font-size:11.5px; padding:2px 3px; border-radius:5px; cursor:pointer; }
  .xlrow:hover { background:rgba(42,86,116,.07); }
  .xlnm { white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
  .xlc { margin-left:auto; flex:none; color:var(--muted); font-size:10px; }
  .xle { font-size:11px; color:var(--muted); padding:2px 0 3px; line-height:1.4; }
  .xlnew { display:flex; gap:5px; margin-top:6px; }
  .xlnew input { flex:1; min-width:0; font:inherit; font-size:11.5px; padding:3px 7px; border:1px solid var(--line); border-radius:6px; }
  /* operator filter (Power Supply / Power Load sections) */
  .opfilter { padding:2px 10px 6px; }
  .opfilter .opq { width:100%; font:inherit; font-size:11.5px; padding:5px 9px; border:1px solid var(--line);
    border-radius:8px; background:var(--surface); color:var(--text); }
  .opfilter .opq:focus { border-color:var(--accent); outline:none; }
  .opfilter .oplist { max-height:170px; overflow-y:auto; margin-top:4px; }
  .opfilter .trow { display:flex; align-items:center; gap:7px; font-size:11.5px; padding:2.5px 2px; }
  .opfilter .trow.opsel { font-weight:700; }
  .opfilter .opn { margin-left:auto; color:var(--muted2); font-size:10px; flex:none; }
  .opfilter .ophint { font-size:10.5px; color:var(--muted2); padding:4px 2px; line-height:1.35; }
  /* the note button loses its label up here — the row is 300px wide and shared with the kicker,
     so ✎ alone keeps "★ Bookmarked" readable. title/aria-label carry the meaning. */
  .bmhd .bmstar-i { padding:2px 5px; font-size:11px; }
  /* distance-measure control (uses Felt's native line tool; miles readout).
     TOP-RIGHT, directly under the Basic/Satellite/Topographic switcher (Shubh 2026-07-27):
     it is a map-viewing tool, so it belongs with the other map-viewing controls rather than
     heading the point-building stack on the left. right:12px matches #basemap's gutter, and
     top:52px clears it. */
  /* Moved bottom-left, above the Felt attribution (Shubh 2026-07-27) — it was top-right under
     the basemap switcher, and the top-right corner now belongs to Share. */
  #measurebtn { position:absolute; bottom:34px; left:12px; z-index:11; background:var(--surface); color:var(--text);
    border:1px solid var(--line); font:inherit; font-size:12px; font-weight:700; padding:7px 12px; border-radius:999px;
    cursor:pointer; box-shadow:var(--shadow); }
  #measurebtn:hover { border-color:var(--accent); }
  #measurebtn.on { background:var(--accent-deep); color:#fff; border-color:var(--accent-deep); }
  /* …which frees the left column: "Add a point" moves up into the slot Measure vacated, and
     "Upload edges" follows it, so the two point-building controls start at the top. */
  #addpoints { position:absolute; top:56px; left:12px; z-index:12; width:216px; }
  /* the measure readout follows the button to the right so it appears beside its own tool */
  #measureout { position:absolute; bottom:72px; left:12px; z-index:11; background:rgba(16,22,28,.9); color:#fff;
    border:1px solid rgba(255,255,255,.16); border-radius:10px; padding:7px 12px; font-size:12.5px; font-weight:700;
    box-shadow:var(--shadow-lg); max-width:230px; line-height:1.4; }
  #measureout.hide { display:none; }
  /* Will 2026-07-21: removed the top-left generation/load legend + the bottom-left coordinate HUD */
  #maplegend { display:none !important; }
  #coordhud { display:none !important; }
  #measureout .mo-sub { font-size:10.5px; font-weight:600; color:#9AA8B6; }
  #measureout .mo-total { font-size:13px; font-weight:800; margin:2px 0 4px; }
  #measureout .mo-row { display:flex; align-items:center; justify-content:space-between; gap:10px; padding:2px 0; font-weight:600; }
  #measureout .mo-x { background:none; border:none; color:#ff9a9a; cursor:pointer; font-size:13px; font-weight:800; padding:0 4px; line-height:1; }
  #measureout .mo-x:hover { color:#ff4d4d; }
  #measureout .mo-clear { cursor:pointer; text-decoration:underline; }
  /* interactive hover card (pointer-events:auto + the hover-hold in hideTipSoon)
     so the provenance/source links inside it are clickable */
  /* .atpoint switches the card from the fixed top-right slot to cursor-anchored
     placement; `right:auto` is required or the right anchor keeps overriding left. */
  /* A CARD THAT FOLLOWS THE CURSOR MUST NOT CATCH IT. #hovertip is pointer-events:auto so the
     ☆ and the groundwork button are clickable — harmless while the card lived in a fixed
     top-right slot, but .atpoint parks it right beside the pointer. It then swallowed the
     mouse: the felt.com iframe stopped receiving moves, so the dot kept its ring and the card
     never updated, and escaping meant moving off the card — "only when im a bit above the
     point". Transparent while it follows; a PINNED card (clicked open) holds still, so it
     keeps pointer-events and everything in it stays clickable. */
  #hovertip.atpoint:not(.pinned) { pointer-events:none; }
  #hovertip.atpoint { right:auto; bottom:auto; max-height:min(60vh, 420px); }
  #hovertip { position:absolute; top:112px; right:12px; z-index:7; width:300px; max-width:300px; max-height:calc(100% - 190px); overflow-y:auto;
    background:var(--surface); border:1px solid var(--line); border-radius:var(--r); padding:12px 14px; font-size:12px; line-height:1.35;
    color:var(--text); box-shadow:var(--shadow-lg); pointer-events:auto; }
  #hovertip a { color:var(--accent); text-decoration:underline; }
  #hovertip .hsec + .hsec { border-top:1px solid var(--divider); margin-top:9px; padding-top:9px; }
  #hovertip .th { font-size:9.5px; font-weight:800; text-transform:uppercase; letter-spacing:.07em; color:var(--accent); }
  #hovertip .nm { font-size:13.5px; font-weight:800; color:var(--text); letter-spacing:-.01em; margin:1px 0 8px; }
  #hovertip .tr { display:flex; gap:14px; justify-content:space-between; margin:3px 0; }
  #hovertip .hdr { border-top:1px solid var(--divider); margin:9px 0 4px; padding-top:8px; font-size:9px; font-weight:800; text-transform:uppercase; letter-spacing:.07em; color:var(--accent); }
  #hovertip .tr .k { color:var(--muted); flex:none; } #hovertip .tr .v { text-align:right; font-weight:700; color:var(--text); }
  /* LONG PROSE ROWS (Shubh 2026-08-04: the Finding section "too verbose/unstructured"). Not a value in
     a right-aligned column — a paragraph. Label above, text left-aligned at normal weight and a
     readable measure, collapsed behind its first clause so one research write-up cannot own the card.
     The <summary> keeps the row's own geometry so a collapsed long row still scans as a row. */
  /* display:block overrides the .tr flex it deliberately still carries — see the note at the renderer:
     the class is the contract every card reader selects on, the layout here is the disclosure's. */
  #hovertip .trlong { display:block; margin:3px 0; }
  #hovertip .trlong > summary { display:flex; gap:14px; justify-content:space-between; cursor:pointer;
    list-style:none; align-items:baseline; }
  #hovertip .trlong > summary::-webkit-details-marker { display:none; }
  #hovertip .trlong > summary .k { color:var(--muted); flex:none; }
  #hovertip .trlong > summary .peek { text-align:right; color:var(--muted2); font-style:italic;
    overflow:hidden; display:-webkit-box; -webkit-line-clamp:2; -webkit-box-orient:vertical; }
  /* the chevron says there is more, on the same side every other disclosure in this card uses */
  #hovertip .trlong > summary::after { content:"▾"; color:var(--muted2); flex:none; font-size:10px;
    transition:transform .12s; }
  #hovertip .trlong[open] > summary::after { transform:rotate(180deg); }
  #hovertip .trlong[open] > summary .peek { display:none; }
  #hovertip .trlong .longbody { margin:5px 0 8px; text-align:left; font-weight:400; color:var(--text);
    line-height:1.5; max-height:210px; overflow-y:auto; padding-right:4px;
    border-left:2px solid var(--divider); padding-left:9px; }
  #hovertip.pinned { pointer-events:auto; }
  #maplegend { position:absolute; top:56px; left:12px; z-index:5; width:216px; max-height:calc(100% - 140px);
    display:flex; flex-direction:column; background:var(--glass2); border:1px solid var(--line);
    border-radius:var(--r); box-shadow:var(--shadow); backdrop-filter:blur(5px); overflow:hidden; }
  #maplegend .mlhead { display:flex; align-items:center; justify-content:space-between; gap:6px; cursor:pointer;
    padding:9px 12px; font-size:10.5px; font-weight:800; text-transform:uppercase; letter-spacing:.05em; color:var(--accent-deep); flex:none; }
  #maplegend.collapsed { width:auto; }
  #maplegend.collapsed #maplegendbody { display:none; }
  #maplegend.collapsed .mlcaret { transform:rotate(-90deg); }
  #maplegendbody { overflow-y:auto; padding:0 12px 10px; }
  /* site-preset rows (Fervo NM leases) */
  #sitepresets summary::-webkit-details-marker { display:none; }
  #sitepresets[open] summary { color:var(--text); }
  .sp-row { display:flex; align-items:center; gap:8px; padding:4px 0; border-bottom:1px solid var(--divider); }
  .sp-row:last-child { border-bottom:0; }
  .sp-main { flex:1; min-width:0; }
  .sp-main b { display:block; font-size:11.5px; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
  .sp-main span { display:block; font-size:10px; color:var(--muted2); overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
  .sp-row .btn { flex:none; font-size:10.5px; padding:3px 10px; }
  #drawtog { width:88px; border:1px solid transparent; font:inherit; font-size:13px; font-weight:800; letter-spacing:-.01em;
    padding:8px 0; border-radius:999px; cursor:pointer; box-shadow:var(--shadow-sm); }
  #drawtog.go { background:var(--accent-deep); color:#fff; }   /* black theme: action buttons are black (was green) */
  #drawtog.stop { background:var(--surface); color:var(--text); border-color:var(--btnbd); }
  #drawtog:hover { filter:brightness(1.06); }
  /* Clear + Local infra ride together at the bottom centre, as a FLEX ROW rather than two
     separately anchored buttons (Shubh 2026-07-30: "should have the nearby infra button next to the
     clear as well"). #mapinfra had NO CSS whatsoever, so it was position:static in normal flow near
     the top of the map, nowhere near the Clear it is meant to sit beside. A fixed left offset would
     not have fixed it either: Clear's label changes width ("✕ Clear" vs "✕ Clear route"), so the
     pair has to be laid out by flex to stay together. The wrapper takes no pointer events of its
     own, so the empty space around the buttons never swallows a map click.
     NOT #maptools, which is already taken: an orphaned rule for a top-left pill toolbar (top:54px,
     left:12px, padding, border, radius, box-shadow) whose element is long gone. Reusing that id
     inherited all of it — a 640px-tall white capsule down the middle of the map — and its
     `#maptools button` rule out-specifies `#mapclear`, so Clear lost its dark pill too. */
  #mapactions { position:absolute; bottom:26px; left:50%; transform:translateX(-50%); z-index:6;
    display:flex; align-items:center; gap:8px; pointer-events:none; }
  #mapactions > * { pointer-events:auto; }
  #mapclear { background:var(--accent-deep); color:#fff; border:none; font:inherit; font-size:14px; font-weight:700;
    letter-spacing:-.01em; padding:12px 24px; border-radius:999px; cursor:pointer; box-shadow:var(--shadow-lg); }
  #mapclear:hover { filter:brightness(1.1); }
  #mapclear.hide, #mapinfra.hide { display:none; }
  /* Secondary to Clear: Clear is the destructive one and keeps the solid dark pill, so infra is the
     quiet surface chip — and it goes solid when the layers are ON, which is what .primary means
     here (toggleNearbyInfra syncs that class across #ctx-infra / #mt-ctx-infra / #mapinfra, so the
     edit-bar button and this one can never disagree about the state). */
  #mapinfra { background:var(--surface); color:var(--text); border:1px solid var(--line); font:inherit;
    font-size:13.5px; font-weight:700; letter-spacing:-.01em; padding:11px 18px; border-radius:999px;
    cursor:pointer; box-shadow:var(--shadow); white-space:nowrap; }
  #mapinfra:hover { background:var(--hover); }
  #mapinfra.primary { background:var(--accent-deep); color:#fff; border-color:var(--accent-deep); }
  #mapinfra:active { transform:scale(.97); }
  /* Browse | Design (Shubh 2026-07-28: "underneath basic/satellite/topographic, and then when the
     cards for specific points come up, those cards should be underneath that"). Same right edge as
     #basemap (right:112px, top:12 + 32 high + 8 gap = top:52), and #hovertip drops from top:56 to
     top:96 so the card stack reads switcher -> mode -> card. */
  #mapdraw { position:absolute; top:52px; right:112px; z-index:6;
    display:flex; gap:2px; background:var(--surface); border:1px solid var(--line); border-radius:999px;
    padding:4px; box-shadow:var(--shadow); white-space:nowrap; }
  #mapdraw button { border:none; background:transparent; color:var(--text); font:inherit; font-size:13.5px;
    font-weight:700; letter-spacing:-.01em; padding:8px 16px; border-radius:999px; cursor:pointer; }
  #mapdraw button.on { background:var(--accent-deep); color:#fff; }
  #mapdraw button:not(.on):hover { background:var(--hover); }
  #mapdraw.hide { display:none; }
  /* "select the point on the map": while armed the New-point form is hidden, so this pill is
     the only thing telling you the app is waiting for a click. Persistent, not a toast — a
     toast fades after 2.4 s and the wait is open-ended. */
  /* top:56px, not 18 — centred at 18 its left edge clipped the right end of the search box,
     which is the widest thing in the left-hand map toolbar. At 56 it sits level with Measure
     (much narrower) and above "Add a point…", so it clears the whole column. */
  #st-pickhint { position:absolute; top:56px; left:50%; transform:translateX(-50%); z-index:86;
    background:var(--accent-deep); color:#fff; font:inherit; font-size:12.5px; font-weight:700;
    letter-spacing:-.01em; padding:10px 18px; border-radius:999px; box-shadow:var(--shadow-lg);
    display:flex; align-items:center; gap:12px; pointer-events:auto; }
  #st-pickhint.hide { display:none; }
  #st-pickhint .sph-x { font-size:11px; font-weight:600; opacity:.8; cursor:pointer;
    border-left:1px solid rgba(255,255,255,.3); padding-left:12px; }
  #st-pickhint .sph-x:hover { opacity:1; }
  #mapclear:active { transform:scale(.97); }   /* the centring transform moved to #mapactions */
  /* geometry-editor: invisible drag surface OVER the Felt iframe. The cross-origin embed
     reports clicks and hovers but NEVER mousedown/mouseup, so a press-and-hold cannot happen
     inside it — this pad catches the native mouse gesture on top. It is pointer-events:none
     (completely inert, the map pans and zooms straight through it) until evArmPad turns it on,
     which only happens over an existing node or a bare stretch where a node can be added. */
  #evdragpad { position:absolute; inset:0; z-index:5; display:grid; place-items:center; pointer-events:none; }
  #evdragpad.armed { pointer-events:auto; cursor:grab; }
  #evdragpad.armed.add { cursor:pointer; }   /* over a bare stretch: this click ADDS a point */
  #evdragpad.armed.add:not(.dragging)::after {
    content:""; box-sizing:border-box; inline-size:12px; aspect-ratio:1;
    border:2px dotted var(--accent); border-radius:50%; background:var(--surface); pointer-events:none;
  }
  /* Ephemeral moved-span preview. It exists only while a node is actively moving, above the
     Felt iframe and below editor popovers. The black casing + attributed core mirror the route
     that Felt receives on drop without sending pointer-rate updates across the iframe bridge. */
  #evmove-preview { position:absolute; inset:0; width:100%; height:100%; z-index:6;
    pointer-events:none; overflow:hidden; }
  #evmove-preview polyline { fill:none; stroke-linecap:round; stroke-linejoin:round; vector-effect:non-scaling-stroke; }
  .evmove-preview-casing { stroke:var(--route-ink); stroke-width:8; }
  .evmove-preview-core { stroke-width:5; stroke-opacity:.95; }
  /* Delete-point popup, anchored beside the clicked picking point */
  #evdel { position:absolute; z-index:7; transform:translate(-50%,-140%); }
  #evdel.hide { display:none !important; }
  #evdel .rf-delete-action { color:var(--con); border-color:var(--line); box-shadow:var(--shadow-lg); }
  #evdel .rf-delete-action:hover { background:var(--con-soft); border-color:var(--con); }
  #evtargettip { position:absolute; z-index:9; max-width:260px; padding:var(--space-2) var(--space-3); transform:translate(-50%,calc(-100% - 12px));
    border:1px solid var(--line); border-radius:var(--r-sm); color:var(--text); background:var(--surface); box-shadow:var(--shadow-lg);
    font-size:var(--font-xs); line-height:1.35; pointer-events:none; }
  #evtargettip.hide { display:none !important; }
  #evtargettip b, #evtargettip small { display:block; }
  #evtargettip small { margin-top:2px; color:var(--muted); font-size:var(--font-2xs); }
  /* Focused route refinement reuses the existing editor, map, sidebar width, buttons and design
     tokens. Only the task-specific shell is new. The original candidate set stays untouched until
     Done creates a sibling variant. */
  body.refine-route #leftbar, body.refine-route #lbtoggle, body.refine-route #lbdrag,
  body.refine-route #rbtoggle, body.refine-route #rbdrag, body.refine-route #mapsearch,
  body.refine-route #addpoints, body.refine-route #importbtn, body.refine-route #importmenu,
  body.refine-route #exportbtn, body.refine-route #exportmenu, body.refine-route #sharebtn,
  body.refine-route #mapdraw, body.refine-route #mapactions, body.refine-route #measurebtn,
  body.refine-route #measureout, body.refine-route #coordhud, body.refine-route #edbar,
  body.refine-route #maplegend, body.refine-route #hovertip,
  body.refine-route #movetip, body.refine-route #seginfo, body.refine-route #ptlaw-legend,
  body.refine-route #ptlaw-detail, body.refine-route #st-pickhint { display:none !important; }
  body.refine-route #leftbar { position:absolute; }
  body.refine-route #rightbar > *:not(#refine-panel) { display:none !important; }
  body.refine-route #rightbar { overflow:hidden; }
  body.refine-route #basemap { top:var(--space-3); right:var(--space-3); }
  #refine-header { position:absolute; bottom:var(--space-4); left:50%; z-index:8; transform:translate(-50%,8px);
    width:min(800px,calc(100% - 184px)); min-height:52px; display:flex; align-items:center; justify-content:space-between;
    gap:var(--space-4); padding:var(--space-2) var(--space-2) var(--space-2) var(--space-4); border:1px solid var(--line); border-radius:var(--r);
    background:var(--glass); box-shadow:var(--shadow-lg); opacity:0; backdrop-filter:blur(20px) saturate(150%);
    transition:opacity var(--dur-ui) var(--ease-out),transform var(--dur-ui) var(--ease-out); will-change:transform,opacity; }
  body.refine-route #refine-header { opacity:1; transform:translate(-50%,0); }
  #refine-header.hide { display:none !important; }
  .rf-title { min-width:0; display:flex; align-items:baseline; gap:var(--space-2); white-space:nowrap; }
  .rf-title span { color:var(--muted2); font-size:var(--font-2xs); font-weight:900; letter-spacing:.08em; text-transform:uppercase; }
  .rf-title strong { overflow:hidden; color:var(--accent-deep); font-size:var(--font-md); text-overflow:ellipsis; }
  .rf-actions { display:flex; align-items:center; gap:var(--space-1); }
  .rf-actions .btn { min-height:var(--control-h); padding:var(--space-2) var(--space-3); font-size:var(--font-xs); white-space:nowrap;
    transition:transform var(--dur-press) var(--ease-out),background var(--dur-press) ease,border-color var(--dur-press) ease,box-shadow var(--dur-press) ease; }
  .rf-actions .btn:not(:disabled):active { transform:scale(.97); }
  .rf-icon-action { display:inline-flex; align-items:center; justify-content:center; gap:var(--space-1); }
  #rf-reset { margin-left:var(--space-1); border-left-color:var(--btnbd2); }
  body.refine-route #toast { top:auto; bottom:calc(var(--control-h) + var(--space-6) + var(--space-4)); max-width:min(520px,calc(100% - var(--space-6))); text-align:center; white-space:normal; }
  #refine-panel { height:100%; min-height:0; display:flex; flex-direction:column; overflow:hidden;
    background:var(--surface); opacity:0; transform:translateX(var(--space-4));
    transition:opacity var(--dur-ui) var(--ease-out),transform var(--dur-ui) var(--ease-out); will-change:transform,opacity; }
  body.refine-route #refine-panel { opacity:1; transform:translateX(0); }
  #refine-panel.hide { display:none !important; }
  .rf-tabs { flex:none; display:flex; gap:var(--space-1); padding:var(--space-2); border-bottom:1px solid var(--divider); background:var(--panel); }
  .rf-tab { min-width:0; min-height:var(--control-h); flex:1; display:inline-flex; align-items:center; justify-content:center; gap:var(--space-2); padding:var(--space-2) var(--space-3);
    border:0; border-radius:var(--r-sm); color:var(--muted); background:transparent; font:800 var(--font-xs)/1.2 var(--font-ui); cursor:pointer;
    transition:transform var(--dur-press) var(--ease-out),color var(--dur-press) ease,background var(--dur-press) ease; }
  .rf-tab[aria-selected="true"] { color:var(--on-accent); background:var(--accent); box-shadow:var(--shadow-sm); }
  .rf-tab:focus-visible { outline:2px solid var(--accent); outline-offset:2px; }
  .rf-tab:active { transform:scale(.98); }
  .rf-tab-count { min-width:18px; padding:2px 5px; border-radius:var(--r-round); color:var(--muted); background:var(--surface); font-size:var(--font-2xs); font-variant-numeric:tabular-nums; line-height:1.2; }
  .rf-tab[aria-selected="true"] .rf-tab-count { color:var(--accent-deep); }
  .rf-tab-panel { min-height:0; flex:1; overflow-y:auto; scrollbar-gutter:stable; }
  .rf-tab-panel[hidden] { display:none; }
  .rf-panel-head, .rf-section { padding:var(--space-5); border-bottom:1px solid var(--divider); }
  .rf-panel-head { background:var(--surface); }
  .rf-impact-heading { display:flex; align-items:center; justify-content:space-between; gap:var(--space-3); margin-bottom:var(--space-3); }
  .rf-kicker { display:block; color:var(--muted2); font-size:var(--font-2xs); font-weight:900; letter-spacing:.08em; text-transform:uppercase; }
  .rf-impact-heading > span:last-child { color:var(--muted2); font-size:var(--font-2xs); }
  .rf-impact-stack { display:grid; gap:var(--space-2); padding:var(--space-2); border-radius:var(--r); background:var(--panel); }
  .rf-impact-primary, .rf-impact-table { background:var(--surface); border-radius:var(--r); box-shadow:var(--shadow-sm); }
  .rf-impact-primary { overflow:hidden; }
  .rf-primary-metric { padding:var(--space-5); }
  .rf-primary-label { display:block; color:var(--muted); font-size:var(--font-sm); font-weight:800; }
  .rf-primary-value { display:flex; align-items:baseline; gap:var(--space-2); min-height:46px; margin-top:var(--space-2); }
  .rf-primary-value strong { color:var(--accent-deep); font-size:var(--font-display); font-weight:900; font-variant-numeric:tabular-nums; letter-spacing:-.04em; line-height:1; }
  .rf-primary-value > span { color:var(--muted); font-size:var(--font-md); font-weight:800; }
  .rf-primary-value .pcwait { width:44px; height:14px; }
  .rf-primary-change { display:block; min-height:14px; margin-top:var(--space-2); color:var(--muted2); font-size:var(--font-2xs); font-weight:800; font-variant-numeric:tabular-nums; }
  .rf-primary-change.good { color:var(--pro); }
  .rf-primary-change.bad { color:var(--con); }
  .rf-primary-change .context { color:var(--muted2); font-weight:600; }
  .rf-primary-rowmix { padding:var(--space-4) var(--space-5) var(--space-5); border-top:1px solid var(--divider); }
  .rf-rowmix-head { display:flex; align-items:baseline; justify-content:space-between; gap:var(--space-3); margin-bottom:var(--space-3); }
  .rf-rowmix-head span { color:var(--muted); font-size:var(--font-xs); font-weight:800; }
  .rf-impact-table { overflow:hidden; }
  .rf-section h2 { margin:0; color:var(--accent-deep); font-size:var(--font-sm); font-weight:900; letter-spacing:-.01em; }
  .rf-section-title { display:flex; align-items:center; justify-content:space-between; gap:var(--space-3); margin-bottom:var(--space-3); }
  .rf-section-title > span { color:var(--muted2); font-size:var(--font-2xs); }
  .rf-impact-table-head, .rf-comparison-row { display:grid; grid-template-columns:minmax(0,1fr) 70px 70px; align-items:center; column-gap:var(--space-2); }
  .rf-impact-table-head { min-height:32px; padding:var(--space-2) var(--space-3); color:var(--muted2); background:var(--surface); border-bottom:1px solid var(--divider);
    font-size:var(--font-2xs); font-weight:900; letter-spacing:.06em; text-transform:uppercase; }
  .rf-impact-table-head span:not(:first-child) { text-align:right; }
  .rf-comparison { background:var(--surface); }
  .rf-comparison-row { min-height:40px; padding:var(--space-2) var(--space-3); border-bottom:1px solid var(--divider); }
  .rf-comparison-row:last-child { border-bottom:0; }
  .rf-comp-label { min-width:0; display:flex; align-items:baseline; flex-wrap:wrap; column-gap:var(--space-1); color:var(--muted); font-size:var(--font-xs); font-weight:700; line-height:1.25; }
  .rf-comp-label small { color:var(--muted2); font-size:var(--font-2xs); font-weight:500; white-space:nowrap; }
  .rf-comp-current, .rf-comp-delta { text-align:right; font-size:var(--font-xs); font-weight:900; font-variant-numeric:tabular-nums; }
  .rf-comp-current { color:var(--text); }
  .rf-comp-delta { color:var(--muted2); }
  .rf-comp-delta.good { color:var(--pro); }
  .rf-comp-delta.bad { color:var(--con); }
  .rf-comparison-row.stale .rf-comp-delta { color:var(--muted2); font-weight:700; }
  .rf-rowbar { display:flex; height:12px; overflow:hidden; border-radius:var(--r-sm); background:var(--track); }
  .rf-rowbar span { min-width:2px; }
  .rf-rowlegend { display:flex; flex-wrap:wrap; gap:var(--space-2) var(--space-3); margin-top:var(--space-3); }
  .rf-rowlegend span { display:flex; align-items:center; gap:var(--space-1); color:var(--muted); font-size:var(--font-2xs); }
  .rf-rowlegend i { width:8px; height:8px; border-radius:var(--r-round); }
  .rf-risk-section .rf-section-title { align-items:flex-start; }
  .rf-risk-section .rf-section-title > span { min-width:0; }
  .rf-risk-section .rf-section-title small { display:block; margin-top:var(--space-1); color:var(--muted2); font-size:var(--font-2xs); }
  .rf-risk-switch { position:relative; display:inline-flex; align-items:center; gap:var(--space-2); flex:none; color:var(--muted); font-size:var(--font-2xs); font-weight:800; cursor:pointer; }
  .rf-risk-switch input { position:absolute; width:1px; height:1px; margin:-1px; overflow:hidden; opacity:0; pointer-events:none; }
  .rf-risk-switch-track { position:relative; width:32px; height:18px; flex:none; border:1px solid var(--btnbd2); border-radius:var(--r-round); background:var(--track);
    transition:background var(--dur-press) ease,border-color var(--dur-press) ease; }
  .rf-risk-switch-track::after { content:""; position:absolute; top:2px; left:2px; width:12px; height:12px; border-radius:var(--r-round); background:var(--surface); box-shadow:var(--shadow-sm);
    transition:transform var(--dur-press) var(--ease-out); }
  .rf-risk-switch input:checked + .rf-risk-switch-track { border-color:var(--accent); background:var(--accent); }
  .rf-risk-switch input:checked + .rf-risk-switch-track::after { transform:translateX(14px); }
  .rf-risk-switch input:focus-visible + .rf-risk-switch-track { outline:2px solid var(--accent); outline-offset:2px; }
  .rf-risk-filters { display:flex; flex-wrap:wrap; gap:var(--space-1); margin-bottom:var(--space-3); }
  .rf-risk-filters button { min-height:30px; display:inline-flex; align-items:center; gap:6px; padding:5px 9px; border:1px solid var(--line); border-radius:var(--r-round);
    color:var(--muted); background:var(--surface); font:800 var(--font-2xs)/1 var(--font-ui); cursor:pointer;
    transition:color var(--dur-press) ease,background var(--dur-press) ease,border-color var(--dur-press) ease; }
  .rf-risk-filters button[aria-pressed="true"] { color:var(--on-accent); border-color:var(--accent); background:var(--accent); }
  .rf-risk-filters button:focus-visible { outline:2px solid var(--accent); outline-offset:2px; }
  .rf-risk-filters button span { min-width:16px; padding:2px 4px; border-radius:var(--r-round); color:var(--muted2); background:var(--panel); font-variant-numeric:tabular-nums; text-align:center; }
  .rf-risk-filters button[aria-pressed="true"] span { color:var(--accent-deep); background:var(--surface); }
  .rf-risks { display:block; }
  .rf-risk-empty { margin:0; padding:var(--space-3); border:1px solid var(--line); border-radius:var(--r-sm); color:var(--muted); background:var(--panel); font-size:var(--font-xs); line-height:1.45; }
  .rf-risk-list { margin:0; padding:0; overflow:hidden; border:1px solid var(--line); border-radius:var(--r-sm); background:var(--surface); list-style:none; }
  .rf-risk-row + .rf-risk-row { border-top:1px solid var(--divider); }
  .rf-risk-item { width:100%; min-height:64px; display:grid; grid-template-columns:28px minmax(0,1fr); align-items:start; gap:var(--space-3); padding:var(--space-3);
    border:0; color:var(--text); background:var(--surface); font:600 var(--font-xs)/1.35 var(--font-ui); text-align:left; cursor:zoom-in;
    transition:background var(--dur-press) ease; }
  .rf-risk-item:focus-visible { outline:2px solid var(--accent); outline-offset:-2px; }
  .rf-risk-number { width:26px; height:26px; display:flex; align-items:center; justify-content:center; border:1px solid var(--line); border-radius:var(--r-round);
    color:var(--accent-deep); background:var(--panel); font-size:var(--font-2xs); font-weight:900; font-variant-numeric:tabular-nums; }
  .rf-risk-copy { min-width:0; display:block; }
  .rf-risk-type { display:block; margin-bottom:2px; color:var(--muted2); font-size:var(--font-2xs); font-weight:900; letter-spacing:.06em; text-transform:uppercase; }
  .rf-risk-copy strong { display:block; overflow-wrap:anywhere; color:var(--text); font-size:var(--font-xs); font-weight:800; }
  .rf-risk-copy small { display:block; margin-top:3px; color:var(--muted2); font-size:var(--font-2xs); font-weight:500; }
  .rf-validation { margin-top:var(--space-3); padding:var(--space-3); border:1px solid var(--con); border-radius:var(--r-sm);
    color:var(--con); background:var(--panel); font-size:var(--font-xs); font-weight:700; line-height:1.45; }
  .rf-validation.warning { color:var(--muted); border-color:var(--line); }
  .rf-validation.hide { display:none !important; }
  @media (max-width:980px) {
    #refine-header { left:var(--space-3); right:var(--space-3); width:auto; transform:translateY(8px); }
    body.refine-route #refine-header { transform:translateY(0); }
    .rf-title { display:none; }
    .rf-actions { width:100%; justify-content:flex-end; }
  }
  @media (hover:hover) and (pointer:fine) {
    .rf-tab:not([aria-selected="true"]):hover { color:var(--text); background:var(--hover); }
    .rf-risk-filters button:not([aria-pressed="true"]):hover, .rf-risk-item:hover { color:var(--text); border-color:var(--btnbd2); background:var(--hover); }
  }
  @media (max-width:720px) {
    body.refine-route #app { position:relative; display:block; }
    body.refine-route #mapwrap { position:absolute; inset:0; }
    body.refine-route #rightbar { position:absolute; left:0; right:0; bottom:0; z-index:8; width:100%; height:min(48vh,420px);
      border-top:1px solid var(--line); border-left:0; border-radius:var(--r) var(--r) var(--r-none) var(--r-none); box-shadow:var(--shadow-lg); }
    #refine-header { bottom:calc(min(48vh,420px) + var(--space-3)); padding-left:var(--space-2); }
    .rf-actions { justify-content:space-between; }
    .rf-actions .btn { padding-inline:var(--space-2); }
    .rf-icon-action .rf-action-label { display:none; }
  }
  @media (prefers-reduced-motion:reduce) {
    #refine-header, #refine-panel { transform:none; transition:opacity var(--dur-ui) ease; }
    body.refine-route #refine-header { transform:none; }
    #map::after { transition:none; transform:none; }
    .rf-actions .btn:not(:disabled):active, .rf-tab:active, .rf-risk-switch-track, .rf-risk-switch-track::after { transform:none; transition:none; }
  }
  @media (prefers-reduced-transparency:reduce) {
    #refine-header { background:var(--surface); backdrop-filter:none; }
  }
  @media (prefers-contrast:more) {
    #refine-header, .rf-impact-primary, .rf-impact-table, .rf-risk-list { outline:1px solid var(--text); }
  }
  /* A DRAG owns the whole map: once a point is held the pointer has to stay trackable wherever it
     goes, so this overrides the small armed box evPadBox sets inline (see evArmPad). */
  #evdragpad.dragging { pointer-events:auto; cursor:grabbing;
    left:0 !important; top:0 !important; width:auto !important; height:auto !important; inset:0 !important; }
  /* BOOT SHADE (2026-07-27): an OPAQUE cover over the map, up only between "embed connected"
     and "hosted-layer visibility sweep landed". #maploading can't do this job — it is
     pointer-events:none with a translucent centre card, so the map shows straight through it,
     which is exactly how the transmission/GIS flash was visible. Fades out; capped by a timer
     in bootShadeOn so it can never strand the map behind a grey rectangle. */
  #mapshade { position:absolute; inset:0; z-index:7; background:var(--surface); opacity:1;
    transition:opacity .18s ease-out; pointer-events:none; }
  #mapshade.hide { opacity:0; }
  #maploading { position:absolute; inset:0; z-index:8; display:flex; align-items:center; justify-content:center; pointer-events:none; }
  #maploading .lcard { display:flex; flex-direction:column; align-items:center; gap:13px; background:var(--glass2);
    border:1px solid var(--line); border-radius:var(--r); padding:24px 34px; box-shadow:var(--shadow-lg); backdrop-filter:blur(4px); }
  #maploading .spinner { width:36px; height:36px; border:3px solid var(--line); border-top-color:var(--accent); border-radius:var(--r-round); animation:spin .8s linear infinite; }
  @keyframes spin { to { transform:rotate(360deg); } }
  #maploading .lmsg { font-size:var(--font-sm); color:var(--text); font-weight:700; max-width:260px; text-align:center; line-height:1.4; white-space:pre-line; }
  /* System feedback follows the editor-canvas pattern used by design tools: a compact floating
     message in a dedicated lane, visually separate from the controls it describes. */
  #toast { position:absolute; left:50%; top:var(--space-3); max-width:min(520px,calc(100% - var(--space-6))); transform:translateX(-50%);
    background:var(--toastbg); color:var(--toasttx); padding:var(--space-2) var(--space-4); font-family:var(--font-ui);
    font-size:var(--font-sm); font-weight:600; line-height:1.4; text-align:center; white-space:normal; border-radius:var(--r-sm);
    box-shadow:var(--shadow-lg); opacity:0; -webkit-backdrop-filter:blur(8px); backdrop-filter:blur(8px);
    transition:opacity var(--dur-ui) var(--ease-out); pointer-events:none; z-index:9; }
  #toast.show { opacity:1; }
  @media (prefers-reduced-transparency:reduce) {
    #toast { background:var(--toastbg-solid); -webkit-backdrop-filter:none; backdrop-filter:none; }
  }
  .grad { height:8px; margin:5px 0 3px; border-radius:4px; background:linear-gradient(90deg,#15803d,#86efac,#dcfce7,var(--track)); }
  .gradlbl { display:flex; justify-content:space-between; font-size:10px; color:var(--muted2); }
  .hide { display:none !important; }
  ::-webkit-scrollbar{width:9px;height:9px} ::-webkit-scrollbar-thumb{background:var(--scroll);border-radius:5px;border:2px solid transparent;background-clip:content-box} ::-webkit-scrollbar-track{background:transparent}
  /* save-design dialog (centred name + description) */
  #confirmmodal { position:fixed; inset:0; z-index:90; background:rgba(24,42,56,.30); display:flex; align-items:center; justify-content:center; padding:24px; }
  #confirmmodal.hide { display:none; }
  #confirmmodal .sm-card { width:100%; max-width:400px; background:var(--surface); border:1px solid var(--line); border-radius:14px; box-shadow:var(--shadow-lg); padding:20px; }
  #confirmmodal .cm-msg { font-size:14px; line-height:1.45; }
  /* only appPrompt shows this; appConfirm re-hides it. `.hide` must win over the display
     below, so it is stated after. */
  #confirmmodal #cm-input { display:block; width:100%; margin-top:12px; padding:9px 11px; font:inherit;
    font-size:13.5px; color:var(--text); background:var(--surface); border:1px solid var(--line);
    border-radius:9px; outline:none; }
  #confirmmodal #cm-input:focus { border-color:var(--accent); }
  #confirmmodal #cm-input.hide { display:none; }
  #confirmmodal .sm-act { display:flex; justify-content:flex-end; gap:8px; margin-top:16px; }
  #savemodal { position:fixed; inset:0; z-index:75; background:rgba(24,42,56,.40); display:flex; align-items:center; justify-content:center; padding:24px; }
  #savemodal.hide { display:none; }
  #savemodal .sm-card { width:100%; max-width:440px; background:var(--surface); border:1px solid var(--line); border-radius:14px; box-shadow:var(--shadow-lg); padding:20px 20px 18px; }
  #savemodal .sm-head { font-size:15px; font-weight:800; letter-spacing:-.02em; margin-bottom:12px; color:var(--accent-deep); }
  #savemodal .sm-lab { display:block; font-size:10px; font-weight:700; text-transform:uppercase; letter-spacing:.06em; color:var(--muted2); margin:10px 0 4px; }
  #savemodal .sm-opt { color:var(--muted2); font-weight:500; text-transform:none; letter-spacing:0; }
  #savemodal input, #savemodal textarea { width:100%; box-sizing:border-box; padding:9px 12px; border:1px solid var(--line); border-radius:var(--r-sm);
    background:var(--panel); color:var(--text); font:inherit; font-size:13px; outline:none; resize:vertical; }
  #savemodal input:focus, #savemodal textarea:focus { border-color:var(--accent); background:var(--surface); box-shadow:0 0 0 3px rgba(42,86,116,.14); }
  #savemodal .sm-act { display:flex; justify-content:flex-end; gap:8px; margin-top:16px; }
  /* share-link dialog — shows the URL, auto-copies, works even when clipboard perms fail */
  /* opportunities tab — CRM-style scored table */
  #hs-opps .opp-filters { display:flex; flex-wrap:wrap; gap:10px 14px; align-items:center; padding:11px 13px;
    border:1px solid var(--line); border-radius:var(--r); background:var(--surface); box-shadow:var(--shadow-sm); font-size:11.5px; color:var(--muted); margin-bottom:12px; }
  #hs-opps .opp-filters label { display:flex; align-items:center; gap:6px; cursor:pointer; white-space:nowrap; }
  #hs-opps .opp-filters input[type=number], #hs-opps .opp-filters select { background:var(--panel); color:var(--text);
    border:1px solid var(--line); border-radius:6px; font:inherit; font-size:11.5px; padding:3px 7px; width:70px; }
  #hs-opps .opp-filters select { width:auto; }
  #hs-opps .opp-count { margin-left:auto; color:var(--muted2); }
  .opp-row { border:1px solid var(--line); background:var(--surface); border-radius:var(--r); margin-bottom:9px; box-shadow:var(--shadow-sm); overflow:hidden; }
  /* narrow left pane: score chip on the left, everything else STACKED in a body column
     (name → load → actions) so nothing gets crushed into an ellipsis-fight */
  .opp-main { display:flex; align-items:flex-start; gap:11px; padding:10px 12px; cursor:pointer; }
  .opp-main:hover { background:var(--hover); }
  .opp-score { flex:none; width:34px; height:28px; display:flex; align-items:center; justify-content:center;
    font-weight:800; font-size:13.5px; background:var(--accent-deep); color:#fff; border-radius:var(--r-sm); margin-top:1px; }
  .opp-score.mid { background:#E5B94E; color:#4A3A08; } .opp-score.low { background:var(--chipoff); color:var(--muted); }
  .opp-body { flex:1; min-width:0; display:flex; flex-direction:column; gap:4px; }
  .opp-name { min-width:0; }
  .opp-name b { font-size:12.5px; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; display:inline-block; max-width:100%; vertical-align:bottom; }
  .opp-name span, .opp-load span { font-size:11px; color:var(--muted); display:block; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
  .opp-load { min-width:0; font-size:11.5px; }
  .opp-load .ll { overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
  /* "why this score" breakdown (detail pane) — ranking transparency */
  .ws-prov { font-size:9px; font-weight:800; letter-spacing:.06em; color:#b45309; border:1px solid #f59e0b55;
    background:#f59e0b12; border-radius:999px; padding:1px 7px; margin-left:6px; text-transform:uppercase; vertical-align:1px; }
  .whyscore { border:1px solid var(--line); border-radius:8px; padding:6px 9px; background:var(--surface); }
  .whyscore .ws-r { display:flex; justify-content:space-between; gap:10px; font-size:11.5px; padding:2px 0; }
  .whyscore .ws-r i { color:var(--muted2); font-style:normal; }
  .whyscore .ws-r b { font-variant-numeric:tabular-nums; color:#15803d; }
  .whyscore .ws-t { border-top:1px solid var(--divider); margin-top:3px; padding-top:4px; }
  .whyscore .ws-t b { color:var(--text); }
  /* interconnection-milestone chips (IA/FIS/SIS/COD) on each row */
  .opp-ms { display:flex; flex-wrap:wrap; gap:4px; margin-top:3px; }
  .opp-ms .ms { font-size:9.5px; font-weight:700; letter-spacing:.02em; padding:1px 6px; border-radius:999px;
    border:1px solid var(--line); color:var(--muted); background:var(--panel); white-space:nowrap; }
  .opp-ms .ms.on { color:#15803d; border-color:#15803d40; background:#15803d12; }
  .opp-actions { display:flex; align-items:center; gap:8px; margin-top:2px; }
  .opp-status { flex:none; background:var(--panel); color:var(--text); border:1px solid var(--line); border-radius:999px; font:inherit; font-size:11px; padding:4px 9px; }
  .opp-go { flex:none; width:30px; height:30px; border:1px solid var(--line); border-radius:50%; background:var(--surface); color:var(--accent);
    font-size:15px; cursor:pointer; }
  .opp-go:hover { border-color:var(--accent); background:var(--accent-soft); }
  /* labeled action pills — explicit verbs beat mystery arrows (dogfooding 2026-07) */
  .opp-go.lbl { width:auto; height:28px; border-radius:999px; padding:0 12px; font-size:11px; font-weight:700; white-space:nowrap; }
  .opp-go.lbl.go { background:var(--accent); color:var(--on-accent); border-color:var(--accent); margin-left:auto; }
  .opp-go.lbl.go:hover { opacity:.88; }
  .opp-det { border-top:1px solid var(--line); padding:12px 15px; display:flex; gap:18px; flex-wrap:wrap; background:var(--panel); }
  .opp-det .chips { display:flex; gap:6px; flex-wrap:wrap; margin-bottom:8px; }
  .opp-det .chip { font-size:10.5px; padding:2.5px 9px; border:1px solid var(--line); border-radius:999px; color:var(--muted); background:var(--surface); }
  .opp-det .chip.on { border-color:var(--accent); color:var(--accent-deep); background:var(--accent-soft); }
  .opp-det .col { flex:1; min-width:260px; }
  .opp-det h5 { margin:0 0 6px; font-size:11px; color:var(--muted); font-weight:700; text-transform:uppercase; letter-spacing:.05em; }
  .opp-lds { width:100%; border-collapse:collapse; font-size:11.5px; table-layout:auto; }
  .opp-lds td { padding:5px 8px; border-top:1px solid var(--line); vertical-align:middle; }
  .opp-lds td:last-child { width:1%; white-space:nowrap; text-align:right; }   /* shrink the action column so the pill never gets squeezed */
  .opp-lds .lgo { display:inline-flex; align-items:center; justify-content:center; height:22px; padding:0 10px;
    border:1px solid var(--accent); border-radius:999px; background:var(--accent); color:var(--on-accent);
    font:inherit; font-size:10.5px; font-weight:700; white-space:nowrap; cursor:pointer; }
  .opp-lds .lgo:hover { opacity:.88; }
  .opp-lds .lgo[data-seeall] { background:var(--surface); color:var(--accent); border-color:var(--line); font-weight:600; }
  .opp-det textarea { width:100%; box-sizing:border-box; min-height:56px; background:var(--surface); color:var(--text);
    border:1px solid var(--line); border-radius:var(--r-sm); font:inherit; font-size:11.5px; padding:7px 9px; resize:vertical; }
  .opp-det .roweval { font-size:11px; color:var(--muted); margin-top:6px; }
  .opp-det .btn.sm { font-size:11px; padding:4px 11px; }
  #hs-opps .opp-viewtog { display:flex; gap:4px; }
  #hs-opps .opp-viewtog .btn { font-size:11px; padding:4px 12px; }
  /* (List/Map tabs removed 2026-07-17 — the split layout shows both at once) */
  /* location-confidence chip (opportunities rows, A/B cards, route panel) —
     the .opp-name span/.opp-load span block rules must not stretch it */
  .confb, .opp-name span.confb, .opp-load span.confb, .opp-lds span.confb {
    display:inline-block; width:auto; vertical-align:1px; font-size:9.5px; font-weight:700; letter-spacing:.03em;
    border:1px solid; border-radius:999px; padding:0.5px 7px; white-space:nowrap; cursor:default; }
  /* firm / all / non-firm segmented control (primary filter bar) */
  .opp-seg { display:inline-flex; border:1px solid var(--line); border-radius:999px; overflow:hidden; }
  .opp-seg button { background:var(--panel); border:0; color:var(--muted); font:inherit; font-size:11px;
    font-weight:600; padding:4px 11px; cursor:pointer; }
  .opp-seg button+button { border-left:1px solid var(--line); }
  .opp-seg button.on { background:var(--accent); color:var(--on-accent); font-weight:700; }
  /* one-line default-behavior explainer + reset, under the filter bar */
  .opp-note { display:flex; align-items:center; gap:10px; font-size:11px; color:var(--muted); margin:-4px 0 10px; padding:0 2px; }
  .opp-note .btn.sm { font-size:10.5px; padding:2.5px 10px; }
  /* lightweight workflow strip: where you are in opportunity → candidate → route → design */
  .opp-steps { display:flex; align-items:center; gap:7px; flex-wrap:wrap; font-size:11px; color:var(--muted);
    margin:0 0 10px; }
  .opp-steps b { color:var(--text); font-weight:700; }
  .opp-steps .sep { color:var(--muted2); }
  .opp-steps .stn { display:inline-flex; align-items:center; justify-content:center; width:15px; height:15px;
    border-radius:50%; border:1px solid var(--line); font-size:9.5px; font-weight:700; margin-right:4px; color:var(--muted); }
  .opp-steps .cur .stn { background:var(--accent); border-color:var(--accent); color:var(--on-accent); }
  .opp-dd { position:relative; }
  .opp-dd summary { list-style:none; cursor:pointer; border:1px solid var(--line); background:var(--panel);
    padding:3px 8px; font-size:11.5px; white-space:nowrap; }
  .opp-dd summary::-webkit-details-marker { display:none; }
  .opp-dd[open] summary { border-color:var(--accent); }
  .opp-dd .ddbody { position:absolute; top:26px; left:0; z-index:20; background:var(--surface);
    border:1px solid var(--line); box-shadow:var(--shadow-lg); padding:8px 10px; min-width:150px;
    display:grid; grid-template-columns:1fr 1fr; gap:3px 12px; }
  .opp-dd .ddbody label { display:flex; gap:5px; align-items:center; white-space:nowrap; font-size:11.5px; cursor:pointer; }
  .opp-dd .ddbody .ddall { grid-column:1/-1; border-bottom:1px solid var(--line); padding-bottom:4px; margin-bottom:2px; }
  /* SPLIT layout (dogfooding 2026-07): list + filters on the LEFT, map ALWAYS visible on
     the right — no more List/Map tabs. Clicking a list row focuses that candidate on the map. */
  .opp-split { display:flex; gap:14px; align-items:stretch; height:calc(100vh - 230px); min-height:480px; }
  .opp-left { flex:0 0 46%; min-width:400px; display:flex; flex-direction:column; min-height:0; }
  .opp-left #opp-list { flex:1; overflow-y:auto; min-height:0; padding-right:4px; }
  .opp-split #opp-map { flex:1; height:auto; min-height:0; }
  @media (max-width:1100px){ .opp-split { flex-direction:column; height:auto; }
    .opp-left { flex:none; width:100%; min-width:0; } .opp-left #opp-list { max-height:50vh; }
    .opp-split #opp-map { flex:none; height:60vh; } }   /* flex:none — a 0% flex-basis would zero the height */
  #opp-map { min-height:420px; border:1px solid var(--line); border-radius:var(--r); overflow:hidden; position:relative; }
  .opp-row.focused { border-color:var(--accent); box-shadow:0 0 0 1px var(--accent); }
  /* designer map legend: what each dot colour means (top-left, under the search box) */
  #maplegend { position:absolute; top:54px; left:10px; z-index:6; display:flex; align-items:center; gap:10px;
    background:rgba(16,22,28,.82); border:1px solid rgba(255,255,255,.14); border-radius:999px;
    padding:4px 12px; font-size:10px; color:#E5EAEF; pointer-events:none; }
  #maplegend span { display:flex; align-items:center; gap:4px; white-space:nowrap; }
  #maplegend i { width:8px; height:8px; border-radius:50%; border:1.5px solid #fff; flex:none; }
  body.routing #maplegend { display:none; }   /* route stage: the ROW bar + route colours own the story */
  /* score legend + hover hint (bottom-left, over the satellite) */
  #opp-map-legend { position:absolute; bottom:10px; left:10px; z-index:5; display:flex; align-items:center; gap:11px;
    background:rgba(16,22,28,.82); border:1px solid rgba(255,255,255,.14); border-radius:999px;
    padding:5px 13px; font-size:10.5px; color:#E5EAEF; pointer-events:none; }
  #opp-map-legend span { display:flex; align-items:center; gap:5px; white-space:nowrap; }
  #opp-map-legend i { width:9px; height:9px; border-radius:50%; border:1.5px solid #fff; flex:none; }
  #opp-map-legend .hint { color:#9AA8B6; }
  #opp-map.hide { display:none; }
  #opp-map .maplibregl-popup-content { background:var(--surface); color:var(--text); border:1px solid var(--line);
    border-radius:var(--r-sm); box-shadow:var(--shadow-lg); font:12px/1.45 inherit; }
  #opp-map .maplibregl-popup-anchor-bottom .maplibregl-popup-tip { border-top-color:var(--surface); }
  #opp-map .maplibregl-popup-anchor-top .maplibregl-popup-tip { border-bottom-color:var(--surface); }
  #opp-map .maplibregl-popup-close-button { color:var(--muted); font-size:16px; }
  #sitemodal { position:fixed; inset:0; z-index:85; background:rgba(24,42,56,.40); display:flex; align-items:center; justify-content:center; padding:24px; }
  #sitemodal.hide { display:none; }
  #sitemodal .sm-card { width:100%; max-width:600px; max-height:92vh; overflow-y:auto; background:var(--surface); border:1px solid var(--line); border-radius:14px; box-shadow:var(--shadow-lg); padding:18px; }
  #sitemodal .sm-head { font-size:15px; font-weight:800; letter-spacing:-.02em; margin-bottom:4px; color:var(--accent-deep);
    display:flex; align-items:center; gap:8px; }
  /* the × is pushed right by margin-left:auto rather than by a spacer, so the MANUAL ENTRY tag keeps
     sitting next to the title in db mode instead of being flung across the header */
  #sitemodal .sm-x { margin-left:auto; flex:none; width:26px; height:26px; display:flex; align-items:center;
    justify-content:center; border:1px solid var(--line); border-radius:999px; background:var(--surface);
    color:var(--muted); font:inherit; font-size:13px; font-weight:700; cursor:pointer; }
  #sitemodal .sm-x:hover { border-color:var(--accent); color:var(--accent-deep); background:var(--selbg); }
  #sitemodal .sm-x:focus-visible { outline:2px solid var(--accent); outline-offset:1px; }
  #sitemodal .sh-note { font-size:11.5px; color:var(--muted); margin-bottom:12px; line-height:1.45; }
  #sitemodal .frow { display:flex; gap:8px; margin-top:8px; }
  #sitemodal label.f, #sitemodal div.f { flex:1; font-size:11px; color:var(--muted); display:flex; flex-direction:column; gap:3px; }
  #sitemodal label.f b, #sitemodal div.f b { color:var(--text); font-weight:600; }
  /* REQUIRED vs OPTIONAL, said out loud (Shubh 2026-07-30: "make clear what is required what is
     not with an asterick"). The asterisks were already there but rendered as ordinary bold text, so
     they read as punctuation rather than as a rule; and the optional fields said nothing at all, so
     a blank one looked equally unfinished. Red * on the required, a muted "optional" on the rest,
     and one legend at the top so the convention does not have to be inferred. */
  #sitemodal .req { color:#ef4444; font-style:normal; font-weight:800; margin-left:1px; }
  #sitemodal .opt { color:var(--muted2); font-weight:500; font-style:italic; margin-left:4px; }
  #sitemodal .sh-legend { font-size:11px; color:var(--muted); margin:2px 0 10px; }
  #sitemodal .sh-legend .req { margin-right:3px; }
  /* MW UNKNOWN is a real control now (Shubh 2026-07-30: "make the check box under MW unknown a bit
     more prominent"). It was a 10.5px span with a default checkbox tucked under the input — easy to
     miss, and it is the one thing that makes the required MW field skippable. :has() rather than a
     class toggle, so nothing has to remember to sync it. */
  #sitemodal .mwunk { display:flex; align-items:center; gap:7px; margin-top:5px; padding:6px 9px;
    border:1px solid var(--line); border-radius:var(--r-sm); background:var(--panel);
    font-size:11.5px; font-weight:700; color:var(--text); cursor:pointer; user-select:none; }
  #sitemodal .mwunk:hover { border-color:var(--accent); background:var(--hover); }
  #sitemodal .mwunk input[type=checkbox] { width:15px; height:15px; margin:0; flex:none; cursor:pointer;
    accent-color:var(--accent-deep); }
  #sitemodal .mwunk:has(input:checked) { border-color:var(--accent-deep); background:var(--accent-soft); color:var(--accent-deep); }
  #sitemodal input, #sitemodal select, #sitemodal textarea { width:100%; box-sizing:border-box; padding:7px 9px;
    border:1px solid var(--line); border-radius:var(--r-sm); background:var(--panel); color:var(--text); font:inherit; font-size:12.5px; outline:none; }
  #sitemodal .req-miss { border-color:#ef4444 !important; }
  /* Upload-edges modal (Shubh 2026-07-27) */
  #uploadmodal { position:fixed; inset:0; z-index:86; background:rgba(24,42,56,.40); display:flex; align-items:center; justify-content:center; padding:24px; }
  #uploadmodal.hide { display:none; }
  #uploadmodal .sm-card { width:100%; max-width:600px; background:var(--surface); border:1px solid var(--line); border-radius:16px; box-shadow:var(--shadow-lg); padding:24px 26px; max-height:92vh; overflow-y:auto; }
  #uploadmodal .sm-head { font-size:19px; font-weight:800; letter-spacing:-.02em; color:var(--text); margin-bottom:7px; }
  #uploadmodal .sh-note { font-size:13.5px; line-height:1.55; color:var(--muted); margin-bottom:0; }
  #uploadmodal .sh-note b { color:var(--text); font-weight:700; }
  #uploadmodal .un-schema { background:var(--panel); border:1px solid var(--line); border-radius:11px; padding:14px 15px; margin:16px 0 14px; }
  #uploadmodal .un-schema-h { font-size:10px; font-weight:800; letter-spacing:.09em; color:var(--muted2); text-transform:uppercase; margin-bottom:7px; }
  #uploadmodal .un-schema code { display:block; white-space:pre; overflow-x:auto; font-family:ui-monospace,SFMono-Regular,Menlo,monospace; font-size:11.5px; line-height:1.75; color:var(--text); }
  #uploadmodal .un-pipe { color:var(--muted2); }
  #uploadmodal .un-arr { color:var(--accent); font-weight:800; padding:0 1px; }
  #uploadmodal .un-req { color:var(--accent-deep); font-weight:800; background:var(--accent-soft); border-radius:4px; padding:1px 5px; }
  #uploadmodal .un-reqline { font-size:11.5px; line-height:1.5; color:var(--muted); margin-top:9px; }
  #uploadmodal .un-reqline b { color:var(--text); font-weight:700; }
  #uploadmodal .un-reqline .un-opt { color:var(--muted); font-style:italic; }
  #uploadmodal #bp-paste { width:100%; box-sizing:border-box; font-size:12.5px; line-height:1.5; padding:11px 12px; border-radius:10px; }
  #uploadmodal .un-actions { display:flex; align-items:center; gap:10px; margin-top:14px; flex-wrap:wrap; }
  #uploadmodal .un-dl { font-size:11.5px; color:var(--accent); text-decoration:underline; cursor:pointer; }
  #sitemodal .pastezone { border:1.5px dashed var(--line); padding:14px; text-align:center; font-size:11.5px;
    color:var(--muted); cursor:pointer; margin-top:8px; }
  #sitemodal .pastezone.has { border-color:var(--accent); }
  #sitemodal .pastezone.drag { border-color:var(--accent); background:var(--accent-soft); }
  #sitemodal .pastezone .zspin { width:16px; height:16px; display:inline-block; vertical-align:-3px; margin-right:7px;
    border:2.5px solid var(--line); border-top-color:var(--accent); border-radius:50%; animation:hsspin .8s linear infinite; }
  #sitemodal .pastezone img { max-width:100%; max-height:150px; display:block; margin:8px auto 0; }
  #sitemodal .manualtag { display:inline-block; background:#f59e0b22; color:#b45309; border:1px solid #f59e0b;
    font-size:10px; font-weight:700; padding:1.5px 7px; letter-spacing:.05em; }
  /* mode switches for the shared add-site / new-point modal (see openPointModal) */
  #sitemodal.ptmode .st-dbonly { display:none !important; }
  /* the "also add to the AmWatt DB" opt-in: a row, not a stacked label like the other fields */
  #sitemodal .stdb-row { margin-top:12px; padding-top:11px; border-top:1px solid var(--line); gap:2px; }
  #sitemodal .stdb-row span { display:flex; align-items:center; gap:7px; color:var(--text); font-size:12px; font-weight:600; }
  #sitemodal .stdb-row input[type=checkbox] { width:auto; margin:0; }
  /* !important because the enclosing .f label sets a bold weight on its spans, which won on
     specificity and made this read as a second label rather than as the caption under one */
  #sitemodal .stdb-hint { display:block; color:var(--muted); font-size:10.5px; font-weight:400 !important;
    padding-left:21px; line-height:1.4; }
  #sitemodal:not(.ptmode) .st-ptonly { display:none !important; }
  #sitemodal #st-kind { width:100%; }
  #sitemodal #st-kind button { flex:1; }
  #sitemodal .sm-act { display:flex; gap:8px; justify-content:flex-end; margin-top:14px; }
  #importmodal { position:fixed; inset:0; z-index:80; background:rgba(24,42,56,.40); display:flex; align-items:center; justify-content:center; padding:24px; }
  #importmodal.hide { display:none; }
  #importmodal .sm-card { width:100%; max-width:520px; background:var(--surface); border:1px solid var(--line); border-radius:14px; box-shadow:var(--shadow-lg); padding:20px; }
  #importmodal .sm-head { font-size:15px; font-weight:800; letter-spacing:-.02em; margin-bottom:6px; color:var(--accent-deep); }
  #importmodal .sh-note { font-size:11.5px; color:var(--muted); margin-bottom:12px; line-height:1.45; }
  #importmodal input { width:100%; box-sizing:border-box; padding:9px 12px; border:1px solid var(--line); border-radius:var(--r-sm); background:var(--panel); color:var(--text); font:inherit; font-size:12.5px; outline:none; }
  #importmodal .im-or { text-align:center; color:var(--muted2); font-size:11px; margin:12px 0; }
  #importmodal .sm-act { display:flex; gap:8px; justify-content:flex-end; margin-top:12px; }
  #sharemodal { position:fixed; inset:0; z-index:80; background:rgba(24,42,56,.40); display:flex; align-items:center; justify-content:center; padding:24px; }
  #sharemodal.hide { display:none; }
  #sharemodal .sm-card { width:100%; max-width:540px; background:var(--surface); border:1px solid var(--line); border-radius:14px; box-shadow:var(--shadow-lg); padding:20px; }
  #sharemodal .sm-head { font-size:15px; font-weight:800; letter-spacing:-.02em; margin-bottom:6px; color:var(--accent-deep); }
  #sharemodal .sh-note { font-size:11.5px; color:var(--muted); margin-bottom:10px; line-height:1.45; }
  #sharemodal input { width:100%; box-sizing:border-box; padding:9px 12px; border:1px solid var(--line); border-radius:var(--r-sm); background:var(--panel); color:var(--text); font:inherit; font-size:12.5px; outline:none; }
  #sharemodal input:focus { border-color:var(--accent); }
  #sharemodal .sm-act { display:flex; justify-content:flex-end; gap:8px; margin-top:14px; }
  .btn.copied, #sharemodal .btn.copied { background:#16a34a !important; border-color:#16a34a !important; color:#fff !important; }
  /* ---- groundwork dossier: the research behind a load point's coordinate ---------
     A reading surface, not a data grid. The dossiers run to ~6 KB of prose, so this is
     a wide centred sheet with a fixed header (what was decided) over a scrolling body
     (how it was decided) — the verdict must stay on screen while you read the evidence. */
  #dossiermodal { position:fixed; inset:0; z-index:82; background:rgba(24,42,56,.46); display:flex; align-items:center; justify-content:center; padding:28px; }
  #dossiermodal.hide { display:none; }
  #dossiermodal .dm-card { width:100%; max-width:760px; max-height:88vh; display:flex; flex-direction:column;
    background:var(--surface); border:1px solid var(--line); border-radius:14px; box-shadow:var(--shadow-lg); overflow:hidden; }
  #dossiermodal .dm-head { padding:16px 20px 12px; border-bottom:1px solid var(--line); flex:0 0 auto; }
  #dossiermodal .dm-eyebrow { font-size:10.5px; font-weight:800; letter-spacing:.08em; text-transform:uppercase; color:var(--muted); }
  #dossiermodal .dm-title { font-size:17px; font-weight:800; letter-spacing:-.02em; color:var(--accent-deep); margin-top:3px; line-height:1.25; }
  #dossiermodal .dm-sub { font-size:11.5px; color:var(--muted); margin-top:3px; }
  #dossiermodal .dm-verdict { display:flex; flex-wrap:wrap; gap:6px; margin-top:10px; }
  #dossiermodal .dm-chip { font-size:11px; font-weight:700; padding:3px 8px; border-radius:999px; border:1px solid var(--line); background:var(--panel); color:var(--text); }
  #dossiermodal .dm-chip.ok { color:#15803d; border-color:#15803d33; background:#15803d14; }
  #dossiermodal .dm-chip.warn { color:#b45309; border-color:#f59e0b44; background:#f59e0b14; }
  #dossiermodal .dm-chip.bad { color:#b91c1c; border-color:#ef444444; background:#ef444414; }
  #dossiermodal .dm-body { padding:14px 20px 18px; overflow:auto; flex:1 1 auto; }
  #dossiermodal .dm-sec { margin-top:16px; }
  #dossiermodal .dm-sec:first-child { margin-top:0; }
  #dossiermodal .dm-h { font-size:11px; font-weight:800; letter-spacing:.06em; text-transform:uppercase; color:var(--muted); margin-bottom:7px; }
  #dossiermodal .dm-kv { display:grid; grid-template-columns:150px 1fr; gap:3px 12px; font-size:12.5px; line-height:1.5; }
  #dossiermodal .dm-kv .k { color:var(--muted); }
  #dossiermodal .dm-src { font-size:12.5px; line-height:1.55; }
  #dossiermodal .dm-src li { margin:0 0 7px; padding-left:2px; }
  #dossiermodal .dm-cls { font-weight:700; color:var(--accent-deep); }
  #dossiermodal .dm-note { color:var(--muted); }
  #dossiermodal .dm-md { font-size:12.5px; line-height:1.6; color:var(--text); }
  #dossiermodal .dm-md h1, #dossiermodal .dm-md h2, #dossiermodal .dm-md h3 { font-size:12.5px; font-weight:800; margin:14px 0 5px; color:var(--accent-deep); }
  #dossiermodal .dm-md p { margin:0 0 9px; }
  #dossiermodal .dm-md ul, #dossiermodal .dm-md ol { margin:0 0 9px; padding-left:20px; }
  #dossiermodal .dm-md li { margin:0 0 3px; }
  #dossiermodal .dm-md code { font-family:ui-monospace,SFMono-Regular,Menlo,monospace; font-size:11.5px; background:var(--panel); padding:1px 4px; border-radius:4px; }
  #dossiermodal .dm-md a { color:var(--accent); }
  #dossiermodal .dm-md hr { border:0; border-top:1px solid var(--line); margin:12px 0; }
  #dossiermodal .dm-act { padding:11px 20px; border-top:1px solid var(--line); display:flex; justify-content:space-between; align-items:center; gap:8px; flex:0 0 auto; }
  #dossiermodal .dm-key { font-size:11px; color:var(--muted2); font-family:ui-monospace,SFMono-Regular,Menlo,monospace; }
  #dossiermodal .dm-empty { font-size:12.5px; color:var(--muted); line-height:1.55; }
  /* the card's own affordance into all of the above */
  .dossbtn { display:inline-flex; align-items:center; gap:5px; margin-top:8px; padding:5px 10px; font:inherit; font-size:11.5px; font-weight:700;
    border:1px solid var(--line); border-radius:999px; background:var(--panel); color:var(--accent-deep); cursor:pointer; }
  .dossbtn:hover { border-color:var(--accent); color:var(--accent); }
  /* ---- Ask AI ------------------------------------------------------------------
     The button borrows .dossbtn wholesale (Shubh 2026-07-31: "a button that says Ask AI at the
     top that looks like our open the groundwork button") and only overrides its position: it sits
     in the card HEADER rather than in a row, so the top margin goes and the type drops a touch to
     sit on the title's baseline. */
  .askai { margin:6px 0 0; padding:4px 9px; font-size:11px; }
  .askai:hover { background:var(--accent-soft); }
  /* The panel is deliberately SMALL and fixed bottom-right ("the pop up easy and not huge"):
     it is a side conversation about a point, not a workspace. Height is capped in vh so it never
     grows past the map, and the message list is the only thing that scrolls. */
  #askai { position:fixed; right:18px; bottom:18px; z-index:60; width:330px; max-height:min(58vh,460px);
    display:none; flex-direction:column; background:var(--surface); border:1px solid var(--line);
    border-radius:var(--r); box-shadow:var(--shadow); overflow:hidden; }
  #askai.up { display:flex; }
  #askai .ai-h { display:flex; align-items:center; gap:8px; padding:9px 11px; border-bottom:1px solid var(--line); flex:0 0 auto; }
  #askai .ai-t { font-weight:800; font-size:12px; flex:1; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
  #askai .ai-x { border:0; background:none; font:inherit; font-size:15px; line-height:1; color:var(--muted); cursor:pointer; padding:2px 4px; }
  #askai .ai-x:hover { color:var(--text); }
  #askai .ai-body { overflow-y:auto; padding:10px 11px; display:flex; flex-direction:column; gap:9px; font-size:12px; line-height:1.5; }
  #askai .ai-msg.user { align-self:flex-end; max-width:88%; background:var(--accent-soft); color:var(--text);
    padding:6px 9px; border-radius:10px 10px 2px 10px; white-space:pre-wrap; }
  #askai .ai-msg.bot { color:var(--text); }
  #askai .ai-msg.bot ul { margin:0; padding-left:16px; }
  #askai .ai-msg.bot li { margin:2px 0; }
  #askai .ai-msg.err { color:var(--con); font-size:11.5px; }
  #askai .ai-wait { color:var(--muted); font-size:11.5px; font-style:italic; }
  /* The panel's resting state, since opening it no longer asks anything (Shubh 2026-08-04). Centred
     in the body so an empty popup reads as a prompt rather than as a failed load. */
  #askai .ai-empty { margin:auto; padding:18px 6px; text-align:center; color:var(--text);
    font-size:13px; font-weight:600; }
  #askai .ai-empty span { display:block; margin-top:6px; font-size:11.5px; font-weight:400;
    line-height:1.5; color:var(--muted); }
  /* Sources under an answer: quiet, and each on its own line — these are URLs, and wrapping them
     mid-domain to save a row makes them unreadable. */
  #askai .ai-src { margin-top:8px; padding-top:7px; border-top:1px solid var(--divider);
    display:flex; flex-direction:column; gap:3px; }
  #askai .ai-src span { font-size:10px; font-weight:700; letter-spacing:.06em; text-transform:uppercase;
    color:var(--muted2); }
  #askai .ai-src a { font-size:11.5px; color:var(--accent); text-decoration:none;
    overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
  #askai .ai-src a:hover { text-decoration:underline; }
  #askai .ai-f { display:flex; gap:6px; padding:9px 11px; border-top:1px solid var(--line); flex:0 0 auto; }
  #askai .ai-f input { flex:1; min-width:0; font:inherit; font-size:12px; padding:6px 9px;
    border:1px solid var(--line); border-radius:8px; background:var(--panel); color:var(--text); }
  #askai .ai-f input:focus { outline:none; border-color:var(--accent); }
  #askai .ai-f button { font:inherit; font-size:11.5px; font-weight:700; padding:6px 11px; border:1px solid var(--line);
    border-radius:8px; background:var(--panel); color:var(--accent-deep); cursor:pointer; }
  #askai .ai-f button:hover:not(:disabled) { border-color:var(--accent); color:var(--accent); }
  #askai .ai-f button:disabled { opacity:.5; cursor:default; }
  /* autonomous router panel */
  #autopanel { border-bottom:1px solid var(--line); }
  #autopanel .ap-h { font-weight:800; font-size:13px; display:flex; align-items:center; gap:7px; }
  #ap-toggle { border-color:var(--accent) !important; color:var(--accent-deep); font-weight:800; box-shadow:0 0 0 1px rgba(20,24,28,.18); }
  #ap-toggle:hover { background:var(--accent-soft); }
  #autopanel .ap-beta { background:var(--accent); color:#fff; font-size:9px; font-weight:800; letter-spacing:.08em; padding:1.5px 7px; border-radius:999px; }
  #autopanel .ap-sub { color:var(--muted); font-size:11.5px; margin:4px 0 2px; }
  #autopanel .ap-sec { font-size:10px; letter-spacing:.1em; text-transform:uppercase; color:var(--muted); margin:11px 0 5px; font-weight:700; }
  .ap-chips { display:flex; flex-wrap:wrap; gap:5px; }
  .ap-chip { display:flex; align-items:center; gap:5px; border:1px solid var(--line); padding:3.5px 10px; border-radius:999px; cursor:pointer; font-size:11.5px; color:var(--muted); user-select:none; background:var(--surface); }
  .ap-chip .sw { width:9px; height:9px; border-radius:50%; background:#9AA8B5; flex:none; }
  .ap-chip.on { color:var(--accent-deep); border-color:var(--accent); background:var(--accent-soft); }
  .ap-ck { display:flex; gap:8px; align-items:flex-start; font-size:12px; margin-top:9px; cursor:pointer; }
  .ap-ck input { margin-top:2px; }
  #ap-status { font-size:11.5px; color:var(--muted); margin-top:7px; min-height:15px; }
  #ap-status.err { color:var(--con); }
  @keyframes apspin { to { transform:rotate(360deg); } }
  #ap-status .apspin, #mt-status .apspin, #pareto-status .apspin, #bp-status .apspin, #densrow .apspin, .pacard .paxhint .apspin { display:inline-block; width:11px; height:11px; margin-right:7px; vertical-align:-1px;
    border:2px solid var(--line); border-top-color:var(--accent); border-radius:50%; animation:apspin .7s linear infinite; }
  /* batch A→B routing panel — borrows autopanel's section/sub typography so the two
     collapsibles read as one family (they are: batch reads autopanel's chips per pair) */
  #batch-panel { border-bottom:1px solid var(--line); }
  #bp-toggle { border-color:var(--accent) !important; color:var(--accent-deep); font-weight:800; box-shadow:0 0 0 1px rgba(20,24,28,.18); }
  #bp-toggle:hover { background:var(--accent-soft); }
  #batch-panel .ap-sub { color:var(--muted); font-size:11.5px; margin:4px 0 2px; line-height:1.45; }
  /* the one instruction line in the pair panel — "a bit more bold" (Shubh 2026-07-27): full
     text colour and weight 600. Deliberately NOT a heading: same size, same .ap-sub metrics. */
  #batch-panel .bp-lede { color:var(--text); font-weight:600; }
  #batch-panel .ap-sec { font-size:10px; letter-spacing:.1em; text-transform:uppercase; color:var(--muted); margin:12px 0 5px; font-weight:700; }
  #batch-panel .seg { margin-top:0; }
  .bpn { font-size:9px; font-weight:800; letter-spacing:.05em; color:#fff; background:var(--accent); border-radius:999px; padding:2px 8px; }
  .bprow { display:flex; gap:6px; align-items:center; margin-top:6px; }
  .bplab { font-size:10.5px; color:var(--muted2); font-weight:700; text-transform:uppercase; letter-spacing:.06em; flex:none; }
  .bpin, .bpta { flex:1; min-width:0; box-sizing:border-box; padding:7px 10px; border:1px solid var(--line); border-radius:8px;
    background:var(--surface); color:var(--text); font:inherit; font-size:12px; outline:none; }
  .bpin:focus, .bpta:focus { border-color:var(--accent); }
  .bpin.req-miss, .bpta.req-miss { border-color:var(--con); background:#fef2f2; }
  /* the placeholder is a worked EXAMPLE of the line format now (item 6), so it needs room.
     Deliberately WRAPS rather than scrolling horizontally: a placeholder can't be scrolled,
     so a clipped example is an example nobody can read. */
  .bpta { width:100%; margin-top:6px; min-height:136px; resize:vertical; font-variant-numeric:tabular-nums; line-height:1.45; }
  .bpta::placeholder { color:var(--muted2); opacity:1; font-size:10px; line-height:1.5; }
  #batch-panel .bpbtn { flex:none; padding:7px 11px; font-size:11.5px; }
  /* one list, two provenances: LOCAL rows are dashed (private scratch), TEAM rows solid */
  .bppt { display:flex; align-items:center; gap:7px; font-size:11.5px; padding:4px 6px; border-radius:8px; cursor:pointer;
    border:1px solid var(--line); background:var(--surface); margin-top:4px; }
  .bppt.loc { border-style:dashed; background:var(--panel); }
  .bppt:hover { background:var(--selbg); border-color:var(--accent); }
  .bppt.inA { box-shadow:inset 3px 0 0 var(--supply); }
  .bppt.inB { box-shadow:inset 3px 0 0 var(--load); }
  .bppt .bpdot { width:9px; height:9px; border-radius:50%; flex:none; border:1.5px solid #fff; box-shadow:0 0 0 1px rgba(28,48,64,.25); }
  .bppt .bpnm { flex:1; min-width:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
  .bppt .bpco { color:var(--muted2); font-size:10px; font-variant-numeric:tabular-nums; flex:none; }
  .bppt .bptag { font-size:8.5px; font-weight:800; letter-spacing:.05em; padding:2px 6px; border-radius:999px; flex:none;
    border:1px solid var(--line); color:var(--muted); background:var(--surface); }
  .bppt .bpx, .bppt .bpup { flex:none; cursor:pointer; color:var(--muted2); padding:0 3px; font-size:11px; }
  .bppt .bpx:hover { color:var(--con); } .bppt .bpup:hover { color:var(--accent-deep); }
  .bpslots { display:flex; gap:6px; }
  .bpslot { flex:1; min-width:0; border:1px dashed var(--line); border-radius:8px; padding:5px 8px; background:var(--panel); }
  .bpslot.on { border-style:solid; border-color:var(--accent); background:var(--selbg); cursor:pointer; }
  .bpslot .k { display:block; font-size:8.5px; font-weight:800; letter-spacing:.07em; text-transform:uppercase; color:var(--muted2); }
  .bpslot .v { font-size:11.5px; font-weight:700; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; display:block; }
  .bpslot .v.em { font-weight:400; color:var(--muted2); }
  /* P2P redesign: slot internals — the kind dot beside a filled slot's label, and the
     per-slot "lat, lng" entry an EMPTY slot accepts (ppSlotCoords) */
  .bpslot .v .bpdot { display:inline-block; width:8px; height:8px; border-radius:50%; margin-right:5px;
    border:1.5px solid #fff; box-shadow:0 0 0 1px rgba(28,48,64,.25); vertical-align:baseline; }
  .bpslot .ppco { width:100%; box-sizing:border-box; border:0; background:transparent; outline:none;
    font:inherit; font-size:11px; color:var(--text); padding:1px 0 0; }
  .bpslot .ppco::placeholder { color:var(--muted2); font-size:10.5px; }
  .bpslot .ppco.req-miss { color:var(--con); }
  .bpslot .k .ppcaret { float:right; color:var(--muted2); font-size:9px; }
  #bp-slotcards .ppslotcard { margin:6px 0 0; }
  #bp-slotcards .ppslotcard .cardbody { display:block; }
  /* photo attached to a declared point (New-point modal) — session-only, shown on its slot card */
  .ppslotimg { display:block; width:100%; max-height:150px; object-fit:cover; margin-top:7px;
    border:1px solid var(--line); border-radius:8px; }
  /* pair switcher above the candidate cards — one chip per pair's candidate set */
  #pair-switcher { margin-bottom:9px; }
  #pair-switcher .ppsw-h { font-size:10px; font-weight:800; letter-spacing:.08em; text-transform:uppercase;
    color:var(--muted2); margin-bottom:5px; }
  #pair-switcher .ppsw { display:flex; align-items:center; gap:7px; width:100%; text-align:left; font:inherit;
    font-size:11.5px; padding:5px 8px; border:1px solid var(--line); border-radius:8px; background:var(--surface);
    color:var(--text); cursor:pointer; margin-top:4px; }
  #pair-switcher .ppsw:hover { border-color:var(--accent); background:var(--selbg); }
  #pair-switcher .ppsw.on { border-color:var(--accent); background:var(--selbg); font-weight:700; }
  #pair-switcher .ppsw .bpsw { width:14px; height:4px; border-radius:2px; flex:none; }
  #pair-switcher .ppsw .ppswnm { flex:1; min-width:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
  #pair-switcher .ppsw .ppswn { flex:none; font-size:9px; font-weight:800; color:var(--accent-deep);
    background:var(--accent-soft); border-radius:999px; padding:2px 7px; }
  #pair-switcher .ppsw .bpst { font-size:8.5px; font-weight:800; letter-spacing:.05em; padding:2px 6px; border-radius:999px; flex:none; }
  #pair-switcher .ppsw .bpst.queued { background:var(--chipoff); color:var(--muted); }
  #pair-switcher .ppsw .bpst.routing { background:var(--accent-soft); color:var(--accent-deep); }
  #pair-switcher .ppsw .bpst.failed { background:#fee2e2; color:#b91c1c; }
  .bperr { font-size:11px; color:var(--con); line-height:1.5; margin-top:5px; }
  .bppair { display:flex; align-items:center; gap:7px; font-size:11.5px; padding:4px 6px; border:1px solid var(--line);
    border-radius:8px; background:var(--surface); margin-top:4px; }
  /* Pointed at on the MAP. Deliberately the same treatment the row gives its own :hover, so
     "my cursor is on the line" and "my cursor is on the row" look identical — they are the same
     state, and showing them differently would invite reading a difference into it. */
  .bppair.pphov { border-color:#111827; background:var(--hover); }
  .bppair .bpsw { width:14px; height:4px; border-radius:2px; flex:none; }
  /* the planned-edge glyph: a black dashed segment that mirrors the map's planned-pair line
     (PP_PLANNED_COLOR #111827, dashArray [3,2]) rather than a per-pair colour. The colour
     swatch it replaces keyed off bpColor(i), which disagreed with the map's ordering; this
     one carries no per-pair identity, so it cannot go stale. */
  /* secondary and tabular; margin-left:auto pushes it to sit just before the chevron, and nowrap
     keeps it off a second line when the pair name is long */
  .bpl2 { flex:none; margin-left:auto; padding-left:8px; font-size:10.5px; font-weight:600;
    color:var(--muted); font-variant-numeric:tabular-nums; white-space:nowrap; }
  /* matches the gold circle the bookmark wears on the map, so the row and the marker read as one */
  .bmdot { width:9px; height:9px; flex:none; border-radius:999px; background:#F59E0B;
    box-shadow:0 0 0 2px rgba(245,158,11,.28); }
  /* The Custom Points row's kind dot. Same 9px disc as .bmdot but the colour comes from the point's
     own kind (cpRenderSide), so the row's dot is the colour the map is drawing it in; the dark ring
     is the black ring every user-placed point wears out there (PP_USER_RING_STYLE). */
  .bppair .bpdot { width:9px; height:9px; flex:none; border-radius:999px;
    box-shadow:0 0 0 2px rgba(17,24,39,.22); }
  /* A row's own controls (✎ ✕). .bpx had only ever been styled inside .bppt — the RETIRED points
     list — so the bookmark row's ✕ has been rendering as plain body text this whole time. A row now
     carries two of them, and muted-until-hovered is what says "control" and stops the destructive one
     from shouting over the note; the two hover colours keep ✎ from looking like it deletes. Scoped to
     .bppair, which is the one row shape both these lists and the route list use. */
  .bppair .bpx { flex:none; cursor:pointer; color:var(--muted2); padding:0 2px; font-size:11px; }
  .bppair .bpx:hover { color:var(--con); }
  /* the ✎ on EITHER list must not hover like the ✕ next to it. data-cpnote is the custom-point row's
     own note attribute (bmWire's coordinate contract does not fit a registry id — see cpRenderSide),
     so both selectors are named here rather than the rule being loosened to every .bpx. */
  .bppair .bpx[data-bmact="note"]:hover,
  .bppair .bpx[data-cpnote]:hover { color:var(--accent-deep); }
  /* CUSTOM POINTS rows hover like the bookmark rows above, in their own tint: a bookmark's colour
     out on the map is gold, and a user-placed point's is the heavy black ring behind it — see the
     halo note in cpRenderSide for the whole argument. */
  .bppair[data-cphov] { cursor:pointer; }
  .bppair[data-cphov]:hover { border-color:#111827; background:var(--hover); }
  .provfold { margin-top:4px; }
  .provfold summary { list-style:none; cursor:pointer; font-size:10px; font-weight:800;
    letter-spacing:.04em; text-transform:uppercase; color:var(--muted); padding:3px 0; }
  .provfold summary::-webkit-details-marker { display:none; }
  .provfold .pf-c { display:inline-block; transition:transform .12s; }
  .provfold[open] .pf-c { transform:rotate(180deg); }
  /* The SELECTED point's card folds as a whole, so collapsing leaves the name and a chevron
     rather than removing the card. The summary keeps the ordinary card's two-line head —
     kicker above name, both full width — with the chevron parked in the corner; a flex row
     put them side by side and a long facility name then fought the header for space. */
  .selfold summary { list-style:none; cursor:pointer; position:relative; padding-right:18px; }
  .selfold summary::-webkit-details-marker { display:none; }
  .selfold summary .nm { margin-bottom:0; }
  .selfold .sf-c { position:absolute; right:0; top:-1px; color:var(--muted); font-size:11px;
    line-height:1; display:inline-block; transition:transform .12s; }
  .selfold[open] .sf-c { transform:rotate(180deg); }
  .selfold[open] summary { margin-bottom:7px; }
  .bppair .bpdash { width:16px; height:0; flex:none; border-top:2px dashed #111827; }
  /* the pair's candidate cards, inline under its row */
  .bpcards { padding:2px 0 4px; }
  .bpcards:empty { display:none; }
  /* routed pair: the dash becomes a solid swatch in the route's colour, and it's a button */
  .bppair .bpcol { width:16px; height:6px; border-radius:2px; cursor:pointer; box-shadow:0 0 0 1px rgba(0,0,0,.18) inset; }
  .bppair .bpcol:hover { box-shadow:0 0 0 2px var(--accent); }
  .ppcolbox { position:fixed; z-index:60; background:var(--surface); border:1px solid var(--line);
    border-radius:10px; box-shadow:0 10px 30px rgba(0,0,0,.18); padding:9px; width:184px; }
  .ppcolh { font-size:10px; font-weight:800; letter-spacing:.06em; text-transform:uppercase; color:var(--muted); margin-bottom:7px; }
  .ppcolgrid { display:grid; grid-template-columns:repeat(4,1fr); gap:6px; }
  .ppcolsw { height:22px; border:1px solid rgba(0,0,0,.15); border-radius:5px; cursor:pointer; padding:0; }
  .ppcolsw.on { box-shadow:0 0 0 2px var(--accent); }
  .ppcolrow { display:flex; align-items:center; gap:8px; margin-top:9px; }
  .ppcolcustom { flex:1; display:flex; align-items:center; gap:6px; font-size:11px; color:var(--muted); }
  .ppcolcustom input[type=color] { width:30px; height:22px; padding:0; border:1px solid var(--line); border-radius:5px; background:none; cursor:pointer; }
  .ppcolreset { font-size:11px; padding:3px 8px; border:1px solid var(--line); border-radius:6px; background:var(--surface); cursor:pointer; }
  .ppcolreset:disabled { opacity:.45; cursor:default; }
  .bppair .bpnm { flex:1; min-width:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
  .bppair .bpst { font-size:8.5px; font-weight:800; letter-spacing:.05em; padding:2px 6px; border-radius:999px; flex:none; }
  .bppair .bpst.queued { background:var(--chipoff); color:var(--muted); }
  .bppair .bpst.routing { background:var(--accent-soft); color:var(--accent-deep); }
  .bppair .bpst.done { background:var(--green-soft); color:var(--pro); }
  .bppair .bpst.failed { background:#fee2e2; color:#b91c1c; }
  .bppair .bpdw { color:var(--con); font-weight:800; font-size:10px; flex:none; }   /* ⚠ density count on the adopted pair */
  /* a GENERATED pair's row is the disclosure for its route options (Shubh 2026-07-27, item 4) */
  .bppair.hasopt { cursor:pointer; }
  .bppair.hasopt:hover { border-color:var(--accent); background:var(--selbg); }
  /* bookmark rows light the same way route rows do (Shubh 2026-07-28: "same way i hover over routes
     and the box fills... i want the same when i hover over / click a bookmark") — gold-tinted,
     because gold is the bookmark's identity on the map, so row, halo and marker read as one thing */
  .bppair[data-bmhov] { cursor:pointer; }
  .bppair[data-bmhov]:hover { border-color:#F59E0B; background:#FFF8E8; }
  .bppair.open { border-color:var(--accent); background:var(--selbg); border-bottom-left-radius:0; border-bottom-right-radius:0; }
  .bppair .bpopt { font-size:9.5px; font-weight:800; color:var(--accent-deep); background:var(--accent-soft);
    padding:2px 6px; border-radius:999px; flex:none; letter-spacing:.03em; }
  /* expanded pair body: the two endpoints, always available (the row itself has to elide
     both names to fit, so this is where they're legible) */
  .bpbody { border:1px solid var(--accent); border-top:0; background:var(--surface); padding:5px 6px 6px; }
  .bppair.open + .bpbody:last-child { border-radius:0 0 8px 8px; margin-bottom:4px; }
  /* A GRID, NOT A FLEX ROW (Shubh 2026-07-28: "can we make sure columns line up, ie gen*wind here is
     not at same line as load * operating"). As flex the middle column started wherever the name
     happened to end, so a long name pushed its type/MW far right while a short one left it far left,
     and the two endpoint rows of the SAME route did not line up — which is exactly the comparison
     these two rows exist to support. Explicit tracks make the four columns real:
       A/B letter | name (flexible) | type · status · MW (fixed) | coordinates (fixed)
     minmax(0,1fr) on the name so a long name WRAPS inside its own column instead of widening the
     track and shoving the others out of alignment. */
  .bpend { display:grid; grid-template-columns:11px minmax(0,1fr) 8.2em 8.4em;
    align-items:baseline; gap:6px; padding:3px 2px; font-size:10.5px; line-height:1.35; }
  .bpend + .bpend { border-top:1px dashed var(--line); }
  .bpendw { font-size:9px; font-weight:800; letter-spacing:.06em; color:var(--muted2); }
  .bpendn { font-weight:700; color:var(--text); overflow-wrap:anywhere; min-width:0; }
  .bpendm { color:var(--muted); min-width:0; overflow-wrap:anywhere; }
  /* right-aligned so the two rows' coordinates stack digit over digit; tabular figures keep the
     columns from shifting as the digits change */
  .bpendc { color:var(--muted2); font-variant-numeric:tabular-nums; text-align:right; }
  .bpendhint { font-size:10px; color:var(--muted2); padding:5px 2px 1px; line-height:1.4; border-top:1px dashed var(--line); margin-top:3px; }
  .bpopts { border:1px solid var(--accent); border-top:0; border-radius:0 0 8px 8px; background:var(--surface);
    padding:3px; margin-bottom:4px; }
  .bpopt-r { display:flex; align-items:center; gap:6px; font-size:10.5px; padding:4px 5px; border-radius:6px; cursor:pointer; }
  .bpopt-r:hover { background:var(--selbg); }
  .bpopt-r.on { background:var(--accent-soft); font-weight:600; }
  .bpopt-r .sw { width:10px; height:10px; border-radius:50%; flex:none; }
  .bpopt-r .lb { flex:1; min-width:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
  .bpopt-r .lb .rec { color:var(--pro); font-size:9px; letter-spacing:.04em; }
  .bpopt-r .mx { flex:none; color:var(--muted); font-variant-numeric:tabular-nums; min-width:44px; text-align:right; }
  /* undo the last generation — sits inline in the run status line */
  .ppundo { margin-left:6px; font-size:10.5px; font-weight:700; padding:2px 8px; border-radius:999px; cursor:pointer;
    border:1px solid var(--line); background:var(--surface); color:var(--text); }
  .ppundo:hover { border-color:var(--accent); background:var(--accent-soft); color:var(--accent-deep); }
  .bpres { border:1px solid var(--line); border-radius:var(--r-sm); background:var(--surface); padding:7px 9px; margin-top:5px;
    cursor:pointer; font-size:11.5px; }
  .bpres:hover { border-color:var(--accent); background:var(--selbg); }
  .bpres.used { border-color:var(--accent); background:var(--selbg); }
  .bpres .bprh { display:flex; align-items:center; gap:7px; }
  .bpres .bprh .bpnm { font-weight:700; }
  .bpres .bpsw { width:14px; height:4px; border-radius:2px; flex:none; }
  .bpres .bpst { font-size:8.5px; font-weight:800; letter-spacing:.05em; padding:2px 6px; border-radius:999px; flex:none; }
  .bpres .bpst.queued { background:var(--chipoff); color:var(--muted); }
  .bpres .bpst.routing { background:var(--accent-soft); color:var(--accent-deep); }
  .bpres .bpst.done { background:var(--green-soft); color:var(--pro); }
  .bpres .bpst.failed { background:#fee2e2; color:#b91c1c; }
  .bpres .bprm { display:flex; gap:12px; margin-top:3px; font-size:10.5px; color:var(--muted); font-variant-numeric:tabular-nums; }
  .bpres .bprm b { color:var(--text); font-weight:800; }
  .bpres .bprm .bpdw { color:var(--con); font-weight:800; }   /* ⚠ density count on the adopted pair */
  .bpres .bprerr { font-size:10.5px; color:var(--con); margin-top:3px; line-height:1.45; word-break:break-word; }
  #bp-status { font-size:11.5px; color:var(--muted); margin-top:7px; min-height:15px; line-height:1.45; }
  /* "＋ add the place I just searched as a routing point" — appears under the map search box */
  #searchadd { margin-top:5px; display:flex; align-items:center; gap:7px; padding:6px 10px; border:1px solid var(--accent);
    border-radius:9px; background:var(--surface); color:var(--accent-deep); font:inherit; font-size:11.5px; font-weight:700;
    cursor:pointer; box-shadow:var(--shadow); text-align:left; width:100%; }
  #searchadd:hover { background:var(--accent-soft); }
  #searchsugs .ssadd { flex:none; cursor:pointer; color:var(--muted2); font-weight:800; font-size:13px; padding:0 4px; border-radius:5px; }
  #searchsugs .ssadd:hover { color:var(--accent-deep); background:var(--accent-soft); }
  /* "keep this custom map point" offer, under the A/B endpoint cards */
  .fpsaves { margin-top:8px; border-top:1px dashed var(--line); padding-top:8px; }
  .fpsave { display:flex; align-items:center; gap:6px; margin-top:5px; }
  .fpsave .fpw { width:17px; height:17px; flex:none; border-radius:50%; font-size:9.5px; font-weight:800;
    display:flex; align-items:center; justify-content:center; }
  .fpsave .fpin { flex:1; min-width:0; padding:6px 9px; border:1px solid var(--line); border-radius:8px;
    background:var(--surface); color:var(--text); font:inherit; font-size:11.5px; outline:none; }
  .fpsave .fpin:focus { border-color:var(--accent); }
  .fpsave .fpin.req-miss { border-color:var(--con); background:#fef2f2; }
  .fpsave .btn { flex:none; padding:6px 10px; font-size:11px; }
  .fphint { font-size:10px; color:var(--muted2); line-height:1.45; margin-top:6px; }
  /* manual line drawing behind a disclosure (Shubh 2026-07-26) — see drawGroupSet */
  #drawgroup { display:flex; flex-direction:column; gap:9px; border-top:1px solid var(--line); padding-top:11px; }
  #draw-toggle .dtarrow { color:var(--muted2); font-size:10px; margin-left:2px; }
  #draw-toggle.primary .dtarrow { color:inherit; }
  /* multi-terminal results panel */
  #mt-result .mt-hd { font-size:11px; text-transform:uppercase; letter-spacing:.06em; color:var(--muted2); margin:11px 0 5px; font-weight:700; }
  #mt-result .mt-stat { display:flex; justify-content:space-between; gap:8px; font-size:12px; padding:2px 0; }
  #mt-result .mt-stat b { font-variant-numeric:tabular-nums; color:var(--text); }
  #mt-result .mt-bar { height:7px; border-radius:4px; overflow:hidden; display:flex; margin:5px 0 8px; background:var(--track); }
  #mt-result .mt-comp { display:flex; align-items:center; gap:7px; font-size:12px; padding:2px 0; }
  #mt-result .mt-sw { width:9px; height:9px; border-radius:2px; flex:none; }
  /* saved designs modal */
  #designsmodal { position:fixed; inset:0; z-index:70; background:rgba(24,42,56,.40); display:flex; align-items:center; justify-content:center; padding:24px; }
  #designsmodal .dm-card { width:100%; max-width:520px; max-height:80vh; display:flex; flex-direction:column; background:var(--surface); border:1px solid var(--line); border-radius:14px; box-shadow:var(--shadow-lg); overflow:hidden; }
  .dm-head { display:flex; align-items:center; justify-content:space-between; padding:13px 18px; border-bottom:1px solid var(--line); font-size:14px; font-weight:800; letter-spacing:-.02em; color:var(--accent-deep); }
  .dm-save { padding:12px 18px; border-bottom:1px solid var(--line); display:flex; gap:8px; }
  .dm-save input { flex:1; padding:8px 12px; border:1px solid var(--line); border-radius:var(--r-sm); background:var(--panel); color:var(--text); font:inherit; font-size:12.5px; outline:none; }
  .dm-list { overflow-y:auto; padding:8px 18px 14px; }
  .dm-item { display:flex; align-items:center; gap:10px; padding:10px 0; border-bottom:1px solid var(--divider); font-size:12.5px; }
  .dm-item .di-main { flex:1; min-width:0; }
  .dm-item .di-name { font-weight:700; }
  .dm-item .di-meta { color:var(--muted); font-size:11px; margin-top:2px; }
  .dm-item .di-desc { color:var(--muted2); font-size:11.5px; margin-top:3px; line-height:1.35; }
  .dm-item .di-act { display:flex; gap:6px; flex:none; }
  /* 3D terrain modal — immersive view keeps dark glass over the terrain */
  #terrain3d { position:fixed; inset:0; z-index:60; background:#10161C; display:flex; flex-direction:column; }
  .t3-head { flex:none; display:flex; align-items:center; gap:16px; padding:10px 16px; border-bottom:1px solid var(--line); background:var(--surface); }
  .t3-title { font-size:14px; font-weight:800; letter-spacing:-.02em; flex:0 1 auto; min-width:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; color:var(--accent-deep); }
  .t3-brand { flex:none; padding-right:14px; border-right:1px solid var(--line); }
  .t3-stats { font-size:11.5px; color:var(--muted); flex:1 0 auto; min-width:0; white-space:nowrap; line-height:1.35; overflow:hidden; }
  .t3-stats > div { overflow:hidden; text-overflow:ellipsis; }
  .t3-head .btn { flex:none; white-space:nowrap; }   /* controls stay one line so the header keeps a fixed, compact height */
  /* sky fallback: above-horizon pixels are transparent when the GL sky layer is unsupported,
     so this gradient shows through — the frame is never a black void */
  #tmap { flex:1; min-height:0; background:linear-gradient(#87b3e2 0%, #cfe0ee 45%, #6b6f5e 75%, #3a3d33 100%); }
  /* loading veil over the 3D map until terrain + elevation are ready (no black screen / no early start) */
  #t3-loading { position:absolute; left:0; right:0; top:53px; bottom:150px; z-index:5; display:flex; flex-direction:column;
    align-items:center; justify-content:center; gap:14px; background:#10161C; color:#B7C4CF; font-size:13px; }
  #t3-loading.hide { display:none; }
  #t3-prof { flex:none; height:150px; border-top:1px solid #232B33; background:#141a20; cursor:ew-resize; touch-action:none; }
  #t3-svg { width:100%; height:150px; display:block; pointer-events:none; }
  /* live annotation while flying/scrubbing: corridor being followed + soils at this point */
  #t3-hud { position:absolute; top:64px; left:14px; z-index:6; max-width:400px; pointer-events:none;
    background:rgba(16,22,28,.85); border:1px solid rgba(255,255,255,.14); border-radius:10px; padding:9px 12px; font-size:12.5px; color:#F2F6F9; }
  #t3-hud.hide { display:none; }
  #t3-hud .t3h-row { display:flex; align-items:center; gap:7px; line-height:1.4; }
  #t3-hud .t3h-sw { width:16px; height:4px; border-radius:2px; flex:none; }
  #t3-hud .t3h-soil { color:#B7C4CF; font-size:11px; margin-top:4px; }
  #t3-hud .t3h-mi { font-size:14px; font-weight:800; letter-spacing:-.01em; font-variant-numeric:tabular-nums; margin-bottom:4px; }
  #t3-hud .t3h-mi span { color:#8B99A8; font-weight:600; font-size:11px; }
  /* horizontal rotate controls (right edge, under the nav stack) */
  #t3-rot { position:absolute; right:10px; top:170px; z-index:6; display:flex; flex-direction:column; gap:4px; }
  #t3-rot button { width:30px; height:30px; border:1px solid rgba(255,255,255,.18); background:rgba(16,22,28,.85); color:#F2F6F9;
    font-size:15px; line-height:1; cursor:pointer; border-radius:8px; }
  #t3-rot button:hover { background:rgba(30,40,50,.95); }
  /* hover-inspect tooltip in the 3D view */
  #t3-tip { position:absolute; z-index:7; pointer-events:none; max-width:340px;
    background:rgba(16,22,28,.92); border:1px solid rgba(255,255,255,.14); border-left:3px solid var(--accent);
    border-radius:8px; padding:7px 10px; font-size:11.5px; line-height:1.45; color:#F2F6F9; }
  #t3-tip.hide { display:none; }
  #t3-tip div+div { margin-top:3px; border-top:1px solid rgba(255,255,255,.10); padding-top:3px; }
  /* filmic vignette over the 3D map (edges darken subtly — pure chrome, no interaction) */
  #t3-vig { position:absolute; left:0; right:0; top:53px; bottom:150px; z-index:4; pointer-events:none;
    background:radial-gradient(ellipse 120% 105% at 50% 42%, transparent 62%, rgba(0,0,0,.38) 100%); }
  /* 3D info panel — ROWs followed + negotiation stats (bottom-right, above the profile) */
  #t3-info { position:absolute; right:14px; bottom:164px; z-index:6; max-width:330px; pointer-events:auto;
    max-height:calc(100% - 330px); overflow-y:auto;
    background:rgba(16,22,28,.85); border:1px solid rgba(255,255,255,.14); border-radius:10px; padding:9px 12px; font-size:11px; color:#F2F6F9; }
  #t3-info .t3l-h { font-size:9.5px; font-weight:700; text-transform:uppercase; letter-spacing:.06em; color:#8B99A8; margin-bottom:5px; }
  #t3-info .t3i-r { display:flex; align-items:flex-start; gap:6px; padding:1.5px 0; line-height:1.4; }
  #t3-info .t3l-sw { width:18px; height:5px; border-radius:2px; flex:none; }
  #t3-info .t3i-stats { display:flex; gap:14px; margin-top:7px; padding-top:7px; border-top:1px solid rgba(255,255,255,.10); }
  #t3-info .t3i-stat b { display:block; font-size:14px; font-weight:800; }
  #t3-info .t3i-stat span { font-size:8.5px; font-weight:700; text-transform:uppercase; letter-spacing:.04em; color:#8B99A8; }
  /* 3D legend — what the colours mean (bottom-left, above the elevation profile) */
  #t3-legend { position:absolute; left:14px; bottom:164px; z-index:6; max-width:300px; pointer-events:auto;
    max-height:calc(100% - 330px); overflow-y:auto;
    background:rgba(16,22,28,.85); border:1px solid rgba(255,255,255,.14); border-radius:10px; padding:9px 12px; font-size:11px; color:#F2F6F9; }
  #t3-legend .t3l-h { font-size:9.5px; font-weight:700; text-transform:uppercase; letter-spacing:.06em; color:#8B99A8; margin-bottom:5px; }
  #t3-legend .t3l-r { display:flex; align-items:center; gap:7px; padding:1.5px 0; line-height:1.35; }
  #t3-legend .t3l-sw { width:18px; height:5px; border-radius:2px; flex:none; }
  #t3-legend .t3l-dot { width:10px; height:10px; border-radius:50%; border:2px solid #fff; flex:none; }

/* The gallery's "there are more than we're showing" line (2026-08-04, #10 of the multi-user list).
   grid-column:1/-1 so it sits on its own row under the cards instead of becoming a card-shaped cell
   in the grid. Muted on purpose — it is a fact about the list, not a warning about the designs. */
#hs-grid .hs-capnote, .hs-grid .hs-capnote {
  grid-column: 1 / -1; padding: 14px 2px 4px; text-align: center;
  color: var(--muted2); font-size: 12.5px; font-style: italic;
}
