/* ============================================================================
   app.css — Q-IF

   Dark product surface with the Quwa cyan. The marketing site is the white
   edition; this is a logged-in tool, and a dark canvas is what lets the map
   and the 3D buildings carry the screen. The brand hues used here are the
   DARK-theme values (#19c8e8 and friends) — the darkened set the white site
   uses would disappear against this background.

   Layout in one sentence: `.stages` is a two-column grid whose left column is
   the dock, and the map and the buildings are single DOM nodes that get moved
   between the stage and the dock, animated with FLIP.
   ========================================================================== */

/* ---------------------------------------------------------------- theme --
   Night is the default and light is opt-in, both driven by data-theme on
   <html>. Every colour below is a token: nothing downstream hard-codes a hex,
   which is what makes the switch a single attribute rather than a second
   stylesheet. The switch is instant and remembered per browser. */

:root {
  --bg:#0b0f16;
  --bg-1:#121825;
  --bg-2:#18202f;
  --bg-3:#1f2939;
  --line:rgba(150,175,205,.16);
  --line-2:rgba(150,175,205,.30);

  --ink:#f2f6fb;
  --ink-2:#b9c6d8;
  --ink-3:#8697ad;
  --ink-4:#6b7d94;

  --brand:#19c8e8;
  --brand-2:#4fdcf6;
  --brand-ink:#04222b;
  --teal:#2fd3a7;
  --warm:#f0a23c;
  --hot:#f2684a;
  --violet:#8e7bff;

  --ok:#2fd3a7;
  --warn:#f0a23c;
  --bad:#f2684a;

  /* The Quwa mark: the website's ring gradient and green arrow, plus the
     dollar. On night the ring is lightened from the site's #0b7592/#123a4a,
     which would disappear against this background. */
  --mark-1:#19c8e8;
  --mark-2:#0e6f8b;
  --mark-arrow:#2fd3a7;
  --mark-arrow-2:#7bf0c6;
  --mark-dollar:#f2f6fb;

  /* Map hotspot ramp — four tiers plus "nothing catalogued". */
  --t0:#1d2634;
  --t1:#27415c;
  --t2:#2f6a86;
  --t3:#2f9db4;
  --t4:#19c8e8;
  --map-bg-1:#151d2c;
  --map-bg-2:#0c111a;
  --map-stroke:rgba(150,175,205,.34);

  --shadow:0 2px 6px rgba(0,0,0,.30),0 22px 60px -22px rgba(0,0,0,.65);
  --glow:0 0 0 1px rgba(25,200,232,.35),0 18px 60px -22px rgba(25,200,232,.45);

  /* Surfaces and states that were previously pinned to the dark palette.
     The header was the visible one — it stayed dark in day mode because its
     background was a literal rgba() rather than a token. */
  --top-bg:rgba(11,15,22,.85);
  --btn-hover:#27334a;
  --scrim:rgba(4,7,12,.62);
  --ink-bad:#ffb4a1;
  --ink-warn:#f3cc94;
  --ink-ok:#9ff0d8;
  --ink-violet:#b3a6ff;
  --window-lit:#fff5cc;

  --r:14px;
  --r-lg:22px;
  --r-sm:9px;

  --sans:"Inter",-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Helvetica,Arial,sans-serif;
  --mono:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;

  --ease:cubic-bezier(.22,.61,.36,1);
  --ease-out:cubic-bezier(.16,1,.3,1);
  --spring:cubic-bezier(.34,1.46,.54,1);
}

/* Day. The brand cyan is only 3:1 on white, so text and small marks switch to
   the darkened brand the public site already uses; the bright cyan stays for
   large fills where contrast is not the constraint. */
:root[data-theme="light"] {
  --bg:#f4f7fa;
  --bg-1:#ffffff;
  --bg-2:#eef3f8;
  --bg-3:#e2eaf2;
  --line:rgba(11,20,33,.12);
  --line-2:rgba(11,20,33,.22);

  --ink:#0d1219;
  --ink-2:#425163;
  --ink-3:#5d6a7a;
  --ink-4:#707d8d;

  --brand:#0b7592;
  --brand-2:#085a71;
  --brand-ink:#ffffff;
  --teal:#0c8465;
  --warm:#b35c00;
  --hot:#b83a14;
  --violet:#5b4bd6;

  --ok:#0c8465;
  --warn:#9a6a00;
  --bad:#c62f1c;

  /* Day uses the website's own brand values unchanged. */
  --mark-1:#0b7592;
  --mark-2:#123a4a;
  --mark-arrow:#26994d;
  --mark-arrow-2:#34e08a;
  --mark-dollar:#0d1219;

  --t0:#dde5ee;
  --t1:#bcd4e4;
  --t2:#8fbdd4;
  --t3:#4f9cb8;
  --t4:#0b7592;
  --map-bg-1:#ffffff;
  --map-bg-2:#eef3f8;
  --map-stroke:rgba(11,20,33,.22);

  --shadow:0 1px 2px rgba(11,20,33,.05),0 14px 40px -16px rgba(11,20,33,.18);
  --glow:0 0 0 1px rgba(11,117,146,.25),0 18px 60px -22px rgba(11,117,146,.30);

  --top-bg:rgba(255,255,255,.88);
  --btn-hover:#d7e2ed;
  --scrim:rgba(11,20,33,.38);
  --ink-bad:#8f2414;
  --ink-warn:#6f4a00;
  --ink-ok:#065a45;
  --ink-violet:#3f33a8;
  --window-lit:#ffd75e;
}

*,*::before,*::after { box-sizing:border-box; }

/* Only the surfaces cross-fade. Transitioning every property on every element
   makes the switch feel like a page load rather than a light going on. */
body, .top, .side, .card, .modal, .mapwrap, .bld, .filters, .drawer, .side__body {
  transition:background-color .28s var(--ease), border-color .28s var(--ease),
             color .28s var(--ease);
}

.logo { width:30px; height:30px; flex:none; display:block; }
.logo--lg { width:44px; height:44px; }

/* The toggle shows the state you would move TO, which is the convention. */
.icon-sun { display:none; }
:root[data-theme="light"] .icon-sun { display:inline; }
:root[data-theme="light"] .icon-moon { display:none; }

html,body { height:100%; }

body {
  margin:0;
  font-family:var(--sans);
  background:var(--bg);
  color:var(--ink);
  -webkit-font-smoothing:antialiased;
  line-height:1.5;
}

[hidden] { display:none !important; }

button,input,select,textarea { font:inherit; color:inherit; }

/* ---------------------------------------------------------------- brand -- */

.brandmark {
  width:30px; height:30px; border-radius:9px; flex:none;
  background:linear-gradient(140deg,var(--brand),#0e7fa0);
  box-shadow:0 6px 18px -6px rgba(25,200,232,.7);
  position:relative;
}
.brandmark::after {
  content:""; position:absolute; inset:0;
  background:linear-gradient(180deg,transparent 52%,rgba(255,255,255,.22));
  border-radius:inherit;
}
.brandmark__eyebrow {
  margin:0; font-size:11px; letter-spacing:.16em; text-transform:uppercase;
  color:var(--brand); font-weight:600;
}
.brandmark__name { margin:0; font-size:26px; letter-spacing:-.02em; }

/* ------------------------------------------------------------- buttons -- */

.btn {
  display:inline-flex; align-items:center; justify-content:center; gap:8px;
  padding:11px 18px; border-radius:var(--r-sm); border:1px solid transparent;
  background:var(--bg-3); color:var(--ink);
  font-weight:600; font-size:14px; cursor:pointer;
  transition:background .18s var(--ease), border-color .18s var(--ease),
             transform .12s var(--ease), opacity .18s var(--ease);
}
.btn:hover { background:var(--btn-hover); }
.btn:active { transform:translateY(1px); }
.btn:focus-visible { outline:2px solid var(--brand); outline-offset:2px; }
.btn[disabled] { opacity:.42; cursor:not-allowed; }
.btn[disabled]:hover { background:var(--bg-3); }

.btn--primary { background:var(--brand); color:var(--brand-ink); }
.btn--primary:hover { background:var(--brand-2); }
.btn--primary[disabled]:hover { background:var(--brand); }

.btn--ghost { background:transparent; border-color:var(--line-2); }
.btn--ghost:hover { background:var(--bg-2); }

.btn--quiet { background:transparent; color:var(--ink-3); padding:11px 12px; }
.btn--quiet:hover { background:var(--bg-2); color:var(--ink); }

.btn--block { width:100%; }

.icon-btn {
  width:34px; height:34px; border-radius:50%; border:1px solid var(--line);
  background:transparent; color:var(--ink-2); cursor:pointer; font-size:20px;
  line-height:1; display:grid; place-items:center;
}
.icon-btn:hover { background:var(--bg-2); color:var(--ink); }

.pill {
  display:inline-grid; place-items:center; min-width:20px; height:20px;
  padding:0 6px; border-radius:10px; background:var(--brand);
  color:var(--brand-ink); font-size:12px; font-weight:700;
}

/* ---------------------------------------------------------------- gate -- */

.gate {
  min-height:100dvh; display:grid; grid-template-columns:minmax(0,1fr) minmax(0,.85fr);
}
.gate--narrow { grid-template-columns:minmax(0,1fr); place-items:center; }

.gate__panel {
  align-self:center; width:min(440px,100%); margin:0 auto; padding:48px 32px;
}
.gate__brand { display:flex; align-items:center; gap:14px; margin-bottom:22px; }
.gate__title { margin:0 0 10px; font-size:26px; letter-spacing:-.02em; }
.gate__lede { margin:0 0 26px; color:var(--ink-2); font-size:15px; }

.gate__aside {
  position:relative; overflow:hidden; display:grid; align-content:center;
  padding:48px; background:var(--bg-1); border-left:1px solid var(--line);
}
.gate__glow {
  position:absolute; inset:-40% -20% auto auto; width:520px; height:520px;
  background:radial-gradient(circle at 50% 50%,rgba(25,200,232,.30),transparent 65%);
  filter:blur(8px);
  animation:drift 18s var(--ease) infinite alternate;
}
@keyframes drift {
  from { transform:translate3d(0,0,0) scale(1); }
  to   { transform:translate3d(-60px,50px,0) scale(1.15); }
}
.gate__stat { position:relative; margin:0; font-size:15px; color:var(--ink-2); }
.gate__stat strong {
  display:block; font-size:64px; line-height:1; letter-spacing:-.03em;
  color:var(--ink); font-variant-numeric:tabular-nums;
}
.gate__stat-sub { position:relative; margin:8px 0 0; color:var(--ink-3); font-size:14px; }

@media (max-width:820px) {
  .gate { grid-template-columns:1fr; }
  .gate__aside { display:none; }
}

/* --------------------------------------------------------------- forms -- */

.form { display:grid; gap:16px; }
.field { display:grid; gap:6px; }
.field__label { font-size:13px; font-weight:600; color:var(--ink-2); }
.field__optional { color:var(--ink-4); font-weight:400; }
.field__hint { font-size:12px; color:var(--ink-3); min-height:1em; }
.field__input {
  width:100%; padding:11px 13px; border-radius:var(--r-sm);
  border:1px solid var(--line-2); background:var(--bg-1); color:var(--ink);
  transition:border-color .16s var(--ease), box-shadow .16s var(--ease);
}
.field__input:focus {
  outline:none; border-color:var(--brand);
  box-shadow:0 0 0 3px rgba(25,200,232,.20);
}
textarea.field__input { resize:vertical; min-height:72px; }

.form__error {
  margin:0; padding:10px 12px; border-radius:var(--r-sm); font-size:14px;
  background:rgba(242,104,74,.12); color:var(--ink-bad);
  border:1px solid rgba(242,104,74,.32);
}

/* ----------------------------------------------------------------- app -- */

.app { min-height:100dvh; display:flex; flex-direction:column; }

.top {
  display:flex; align-items:center; gap:22px; padding:12px 22px;
  border-bottom:1px solid var(--line); background:var(--top-bg);
  backdrop-filter:blur(12px); position:sticky; top:0; z-index:40;
}
.top__brand {
  display:flex; align-items:center; gap:10px; text-decoration:none; color:inherit;
}
.top__name { font-size:19px; font-weight:700; letter-spacing:-.01em; }
.top__sub { font-size:13px; color:var(--ink-3); }
.top__actions { margin-left:auto; display:flex; align-items:center; gap:10px; }

.steps {
  display:flex; align-items:center; gap:6px; margin:0; padding:0; list-style:none;
}
.steps__item {
  display:flex; align-items:center; gap:7px; padding:5px 12px 5px 6px;
  border-radius:999px; font-size:13px; color:var(--ink-4);
  transition:color .2s var(--ease), background .2s var(--ease);
}
.steps__item span {
  display:grid; place-items:center; width:21px; height:21px; border-radius:50%;
  background:var(--bg-3); color:var(--ink-3); font-size:12px; font-weight:700;
  transition:background .2s var(--ease), color .2s var(--ease);
}
.steps__item.is-done { color:var(--ink-2); }
.steps__item.is-done span { background:rgba(47,211,167,.22); color:var(--ok); }
.steps__item.is-current { color:var(--ink); background:var(--bg-2); }
.steps__item.is-current span { background:var(--brand); color:var(--brand-ink); }

@media (max-width:900px) { .steps { display:none; } }

/* --------------------------------------------------------------- menus -- */

.menu { position:relative; }
.menu__button {
  list-style:none; cursor:pointer; padding:7px 13px; border-radius:999px;
  border:1px solid var(--line-2); font-size:13px; font-weight:600;
}
.menu__button::-webkit-details-marker { display:none; }
.menu__button:hover { background:var(--bg-2); }
.menu__panel {
  position:absolute; right:0; top:calc(100% + 8px); min-width:210px; z-index:50;
  background:var(--bg-1); border:1px solid var(--line); border-radius:var(--r);
  box-shadow:var(--shadow); padding:8px; display:grid; gap:2px;
}
.menu__who {
  margin:0; padding:8px 10px 10px; font-size:13px; color:var(--ink-3);
  border-bottom:1px solid var(--line); word-break:break-all;
}
.menu__item {
  text-align:left; padding:9px 10px; border-radius:var(--r-sm);
  background:transparent; border:0; cursor:pointer; font-size:14px;
}
.menu__item:hover { background:var(--bg-2); }

/* -------------------------------------------------------------- stages -- */

.stages {
  flex:1; display:grid; grid-template-columns:270px minmax(0,1fr);
  gap:24px; padding:22px 22px 40px; align-content:start;
  transition:grid-template-columns .5s var(--ease-out);
}
/* The building panel is a third column, and only at step 3. */
.app[data-stage="results"] .stages { grid-template-columns:270px minmax(0,1fr) 320px; }
@media (max-width:1280px) {
  .app[data-stage="results"] .stages { grid-template-columns:270px minmax(0,1fr); }
}

/* All three columns are pinned to row 1 explicitly.
   Grid auto-placement walks the DOM in order and never moves BACKWARDS to an
   earlier column in the same row, so a definite-column item that appears
   after a later column gets pushed to the next row. The building panel sits
   before the results section in the markup and is column 3, which silently
   dropped the results into row 2 — 767px down the page, below an empty
   screen. Explicit rows remove the dependency on markup order entirely. */
.stage { grid-column:2; grid-row:1; min-width:0; }
.stage--region, .stage--buildings, .stage--results { display:none; }
.app[data-stage="region"]    .stage--region,
.app[data-stage="buildings"] .stage--buildings,
.app[data-stage="results"]   .stage--results { display:block; }

.stage__head { margin-bottom:18px; }
.stage__step {
  margin:0 0 4px; font-size:12px; letter-spacing:.14em; text-transform:uppercase;
  color:var(--brand); font-weight:600;
}
.stage__title { margin:0; font-size:27px; letter-spacing:-.02em; }
.stage__hint { margin:6px 0 0; color:var(--ink-3); font-size:14px; }

.stage__slot { min-height:0; }

.stage__foot {
  display:flex; align-items:center; gap:14px; flex-wrap:wrap; margin-top:20px;
}
.stage__foot .btn:last-child { margin-left:auto; }

/* ---------------------------------------------------------------- dock -- */

.dock {
  display:grid; gap:12px; align-content:start; margin-top:4px;
  opacity:0; pointer-events:none; height:0; overflow:hidden;
  transition:opacity .4s var(--ease-out) .15s;
}
.app[data-stage="buildings"] .dock,
.app[data-stage="results"] .dock { opacity:1; pointer-events:auto; height:auto; }

.dock__slot {
  display:grid; gap:9px; padding:12px; text-align:left; cursor:pointer;
  background:var(--bg-1); border:1px solid var(--line); border-radius:var(--r);
  transition:border-color .2s var(--ease), background .2s var(--ease),
             transform .2s var(--ease);
}
.dock__slot:hover {
  border-color:var(--brand); background:var(--bg-2); transform:translateY(-2px);
}
.dock__slot:focus-visible { outline:2px solid var(--brand); outline-offset:2px; }
.dock__hold { display:block; }
.dock__label {
  display:block; font-size:11px; letter-spacing:.12em; text-transform:uppercase;
  color:var(--ink-4); font-weight:600;
}
.dock__value { display:block; font-size:13px; color:var(--ink-2); font-weight:600; }

@media (max-width:1000px) {
  .stages { grid-template-columns:minmax(0,1fr); }
  .side {
    grid-column:1; grid-row:auto; position:static; max-height:none;
    display:grid; grid-template-columns:repeat(auto-fit,minmax(210px,1fr));
  }
  .side__body { max-height:none; }
  .stage { grid-column:1; grid-row:auto; }
  .dock { grid-auto-flow:column; grid-column:1/-1; }
  .dock .mapwrap { max-width:190px; }
}

@media (max-width:640px) {
  .filters { flex-direction:column; align-items:stretch; }
  .filter, .filter--search { flex:1 1 auto; min-width:0; width:100%; }
  .side { grid-template-columns:minmax(0,1fr); }
  .dock { grid-auto-flow:row; }
  .results__actions { width:100%; }
  .results__actions .btn { flex:1 1 auto; }
}

/* -------------------------------------------------------------- sidebar -- */

/* Flex, NOT grid. A grid with a max-height distributes its auto rows within
   that height and shrinks them rather than overflowing, so the sidebar
   reported scrollHeight === clientHeight with twenty buildings in it and the
   list simply could not be scrolled — the rows past the fold were clipped by
   `.side__block{overflow:hidden}` and unreachable. Flex children with
   `flex:0 0 auto` keep their natural height and overflow properly. */
.side {
  grid-column:1; grid-row:1; display:flex; flex-direction:column; gap:10px;
  position:sticky; top:74px; max-height:calc(100dvh - 92px); overflow-y:auto;
  padding-right:4px; scrollbar-width:thin;
}
.side__block { flex:0 0 auto; }

/* A long panel scrolls inside itself too, so opening My buildings does not
   push the saved searches out of reach. */
.side__body {
  max-height:46vh; overflow-y:auto; scrollbar-width:thin;
}

/* Visible scrollbars: an invisible one on a list that must be scrolled is
   the same bug again, just harder to see. */
.side::-webkit-scrollbar, .side__body::-webkit-scrollbar { width:8px; }
.side::-webkit-scrollbar-thumb, .side__body::-webkit-scrollbar-thumb {
  background:var(--line-2); border-radius:4px;
}
.side::-webkit-scrollbar-track, .side__body::-webkit-scrollbar-track { background:transparent; }
.side__block {
  background:var(--bg-1); border:1px solid var(--line); border-radius:var(--r);
  overflow:hidden;
}
.side__head {
  width:100%; display:flex; align-items:center; gap:9px; padding:11px 13px;
  background:transparent; border:0; cursor:pointer; text-align:left;
  font-size:13.5px; font-weight:700; color:var(--ink);
}
.side__head:hover { background:var(--bg-2); }
.side__icon { color:var(--brand); font-size:13px; }
.side__title { flex:1; }
.side__count {
  min-width:21px; height:21px; padding:0 6px; border-radius:11px;
  background:var(--bg-3); color:var(--ink-3);
  display:grid; place-items:center; font-size:11.5px; font-weight:700;
  transition:background .25s var(--ease), color .25s var(--ease), transform .3s var(--spring);
}
.side__count.is-bumped {
  background:var(--brand); color:var(--brand-ink); transform:scale(1.35);
}
.side__body {
  padding:4px 11px 12px; display:grid; gap:8px; align-content:start;
  border-top:1px solid var(--line);
}
.side__empty { margin:6px 0; font-size:12.5px; color:var(--ink-4); line-height:1.5; }
.side__add {
  width:100%; padding:8px; border-radius:var(--r-sm); cursor:pointer;
  background:transparent; border:1px dashed var(--line-2); color:var(--ink-3);
  font-size:12.5px; font-weight:600;
}
.side__add:hover { border-color:var(--brand); color:var(--brand); }

.srow {
  display:grid; gap:3px; padding:9px 10px; border-radius:var(--r-sm);
  background:var(--bg-2); border:1px solid transparent; cursor:pointer;
  text-align:left; width:100%;
}
.srow:hover { border-color:var(--line-2); }
.srow.is-active { border-color:var(--brand); background:var(--bg-3); }
.srow__top { display:flex; align-items:center; gap:7px; }
.srow__name {
  font-size:12.8px; font-weight:700; color:var(--ink);
  overflow:hidden; text-overflow:ellipsis; white-space:nowrap;
}
.srow__n { margin-left:auto; font-size:11px; color:var(--ink-4); flex:none; }
.srow__meta {
  font-size:11.5px; color:var(--ink-4);
  overflow:hidden; text-overflow:ellipsis; white-space:nowrap;
}
.srow__acts { display:flex; gap:4px; margin-top:4px; flex-wrap:wrap; }
.srow__act {
  padding:3px 7px; border-radius:6px; font-size:10.5px; font-weight:600;
  background:var(--bg-3); border:1px solid transparent; color:var(--ink-3);
  cursor:pointer; white-space:nowrap;
}
.srow__act:hover { border-color:var(--brand); color:var(--brand); }
.srow__act--bad:hover { border-color:var(--bad); color:var(--bad); }

/* The token that flies from a result card into the sidebar when something is
   added. It is a fixed-position clone, so it is unaffected by scrolling
   containers and cannot disturb the layout it passes over. */
.flyer {
  position:fixed; z-index:90; pointer-events:none;
  border-radius:50%; background:var(--brand); color:var(--brand-ink);
  display:grid; place-items:center; font-weight:800; font-size:13px;
  box-shadow:0 8px 24px -6px rgba(25,200,232,.7);
}

/* ----------------------------------------------------------------- map -- */

.mapwrap {
  position:relative; border-radius:var(--r-lg); overflow:hidden;
  background:radial-gradient(120% 120% at 50% 0%,var(--map-bg-1),var(--map-bg-2) 70%);
  border:1px solid var(--line);
}
.mapwrap .map { display:block; }

/* The map is drawn 960x640 but must never be taller than the space left
   between the header and the Continue button, or the button that the whole
   step leads to sits below the fold. Fixing the height and letting the SVG
   letterbox inside it (preserveAspectRatio centres by default) keeps the
   whole step on one screen at any window size. */
/* The drawing is 3:2. Sizing the WRAPPER to that ratio rather than letting a
   full-width box letterbox it removes the dead margins either side — the
   panel is then the map, not a frame around it.
   
   The width is derived from the height left over, not from a flat vh
   fraction. Everything around the map — header, heading, the small-region
   bar, the Continue button and the padding — is a constant 365px measured
   across four window sizes, and it does NOT scale with the viewport. A plain
   `90vh` therefore fits a 1080p screen and pushes the Continue button off a
   768px laptop by 58px. Subtracting the chrome first keeps the whole step on
   one screen at every size; the 420px floor stops it collapsing to nothing
   on a very short window, which scrolls instead. */
.stage--region .mapwrap {
  max-width:min(100%, max(420px, calc((100dvh - 380px) * 1.5)));
  margin-inline:auto;
}
.mapwrap .map { aspect-ratio:3 / 2; }
.mapwrap svg { display:block; width:100%; height:100%; }
.dock .mapwrap .map { height:auto; }
.dock .mapwrap svg { height:auto; }

/* Clicking a region focuses it, and Chrome draws a box round the path's
   bounding box for that. Keyboard focus still needs a ring, so only the
   pointer case is suppressed. */
.region:focus { outline:none; }
.region:focus-visible { outline:2px solid var(--brand-2); outline-offset:2px; }

/* Regions lift toward the pointer. transform-box + transform-origin make the
   scale happen about each shape's own centre rather than the SVG's origin,
   which is the difference between a state growing in place and it flying off
   to the corner. */
.region {
  fill:var(--t0); stroke:var(--map-stroke); stroke-width:.6; cursor:pointer;
  transform-box:fill-box; transform-origin:center;
  transition:fill .22s var(--ease), transform .28s var(--spring),
             filter .28s var(--ease), stroke .22s var(--ease);
}
/* Hotspots. Four tiers by how much funding is catalogued, so coverage reads
   at a glance. Every region stays clickable, including tier 0 — a province
   with nothing catalogued still has federal routes, and making it inert told
   the user the map was broken. */
.region--t0 { fill:var(--t0); }
.region--t1 { fill:var(--t1); }
.region--t2 { fill:var(--t2); }
.region--t3 { fill:var(--t3); }
.region--t4 { fill:var(--t4); }

.mapwrap:not(.is-locked) .region:hover {
  transform:scale(1.14); filter:drop-shadow(0 10px 18px rgba(0,0,0,.45));
  stroke:var(--brand-2); stroke-width:1;
}
.region.is-selected {
  fill:var(--brand); stroke:#bff1fb; stroke-width:.9;
  filter:drop-shadow(0 8px 20px rgba(25,200,232,.45));
}
.mapwrap:not(.is-locked) .region.is-selected:hover { fill:var(--brand-2); }

.maplegend {
  display:flex; align-items:center; gap:13px; flex-wrap:wrap;
  margin-top:10px; font-size:12px; color:var(--ink-4);
}
.maplegend__label { font-weight:600; letter-spacing:.06em; text-transform:uppercase; }
.maplegend__key { display:inline-flex; align-items:center; gap:5px; }
.sw { width:13px; height:13px; border-radius:3px; border:1px solid var(--map-stroke); }
.sw--t0 { background:var(--t0); } .sw--t1 { background:var(--t1); }
.sw--t2 { background:var(--t2); } .sw--t3 { background:var(--t3); }
.sw--t4 { background:var(--t4); }

.map__small-btn--t0 { opacity:.72; }
.map__small-btn--t3, .map__small-btn--t4 { border-color:var(--brand); color:var(--ink); }

.map__tip {
  position:absolute; pointer-events:none; z-index:5; transform:translate(-50%,-140%);
  background:var(--bg-1); border:1px solid var(--line-2); border-radius:var(--r-sm);
  padding:7px 11px; font-size:13px; white-space:nowrap; box-shadow:var(--shadow);
}
.map__tip strong { display:block; font-size:14px; }
.map__tip span { color:var(--ink-3); }

/* The small regions — DC, PE, RI, DE — are a few pixels across at this scale.
   They stay on the map, but they also get a real target here. */
.map__small {
  display:flex; flex-wrap:wrap; gap:7px; padding:12px 14px;
  border-top:1px solid var(--line); background:rgba(0,0,0,.22);
}
.map__small-btn {
  padding:5px 11px; border-radius:999px; cursor:pointer; font-size:12.5px;
  font-weight:600; background:var(--bg-3); border:1px solid var(--line);
  color:var(--ink-2);
  transition:background .18s var(--ease), color .18s var(--ease),
             border-color .18s var(--ease), transform .18s var(--spring);
}
.map__small-btn:hover { transform:translateY(-2px) scale(1.05); border-color:var(--brand); }
.map__small-btn.is-selected {
  background:var(--brand); color:var(--brand-ink); border-color:var(--brand);
}

/* Docked, the map is a static thumbnail: no hover growth, no clicks. */
.dock .mapwrap { border-radius:var(--r-sm); }
.dock .map__small { display:none; }
.is-locked .region { pointer-events:none; }

/* --------------------------------------------------------------- chips -- */

.chips { display:flex; flex-wrap:wrap; gap:8px; }
.chip {
  display:inline-flex; align-items:center; gap:8px; padding:6px 8px 6px 13px;
  border-radius:999px; background:var(--bg-2); border:1px solid var(--line);
  font-size:13px; font-weight:600;
  animation:chip-in .32s var(--spring) both;
}
@keyframes chip-in {
  from { opacity:0; transform:scale(.7) translateY(6px); }
  to   { opacity:1; transform:none; }
}
.chip__x {
  width:19px; height:19px; border-radius:50%; border:0; cursor:pointer;
  background:var(--bg-3); color:var(--ink-3); line-height:1; font-size:14px;
  display:grid; place-items:center;
}
.chip__x:hover { background:var(--bad); color:#fff; }

/* ----------------------------------------------------------- buildings -- */

.buildings {
  display:grid; gap:16px; perspective:1200px;
  grid-template-columns:repeat(auto-fill,minmax(178px,1fr));
}

.bld {
  position:relative; display:grid; gap:0; padding:18px 14px 14px; cursor:pointer;
  background:linear-gradient(180deg,var(--bg-1),#0e1420);
  border:1px solid var(--line); border-radius:var(--r);
  transform-style:preserve-3d;
  transition:border-color .25s var(--ease), transform .4s var(--spring),
             box-shadow .3s var(--ease), background .25s var(--ease);
  animation:bld-in .5s var(--ease-out) both;
}
@keyframes bld-in {
  from { opacity:0; transform:translateY(22px) rotateX(-12deg); }
  to   { opacity:1; transform:none; }
}
.bld:hover {
  border-color:var(--brand); transform:translateY(-6px) rotateX(6deg) scale(1.03);
  box-shadow:var(--glow);
}
.bld:focus-visible { outline:2px solid var(--brand); outline-offset:3px; }
.bld.is-selected {
  border-color:var(--brand); background:linear-gradient(180deg,#123141,#0d1a24);
  box-shadow:var(--glow);
}
.bld.is-empty { opacity:.4; cursor:not-allowed; }
.bld.is-empty:hover { transform:none; border-color:var(--line); box-shadow:none; }

.bld__stage {
  height:150px; display:grid; place-items:center; margin-bottom:10px;
  perspective:620px;
}

/* The leading translateY is screen-space, applied before the rotations, and
   it exists because the masses grow UPWARD from z = 0. A tall model's
   projected body therefore sits well above its footprint box, and without
   this nudge the towers climb out of the top of the card. */
.bld__model {
  transform-style:preserve-3d;
  transform:translateY(26px) rotateX(58deg) rotateZ(-38deg);
  transition:transform .55s var(--spring);
}
.bld:hover .bld__model, .bld.is-selected .bld__model {
  transform:translateY(22px) rotateX(52deg) rotateZ(-22deg) translateZ(10px);
}

/* Each mass is a real box: four sides and a roof, positioned in 3D. The
   faces are shaded by hand rather than lit, because a CSS 3D scene has no
   light source — the constant hues are what read as solid. */
.mass { position:absolute; transform-style:preserve-3d; }

/* No backface culling. Each pair of opposite walls is built with the SAME
   rotation, so the pair shares a facing — culling therefore removes the near
   wall along with the far one and leaves the model open at the corner
   nearest the camera. The far walls need no culling anyway: the depth sort
   puts them behind the near ones, which is what makes the mass read solid. */
.mass__face { position:absolute; inset:0; }
.mass__face--top   { background:var(--roof,#3f5673); }
.mass__face--front { background:var(--front,#2c3c53); }
.mass__face--side  { background:var(--side,#1f2c3e); }

.bld.is-selected .mass__face--top   { background:var(--roof-on,#54e3ff); }
.bld.is-selected .mass__face--front { background:var(--front-on,#1892b1); }
.bld.is-selected .mass__face--side  { background:var(--side-on,#10697f); }

.bld__name { margin:0; font-size:14.5px; font-weight:700; letter-spacing:-.01em; }
.bld__count { margin:3px 0 0; font-size:12.5px; color:var(--ink-3); }
.bld__tick {
  position:absolute; top:11px; right:11px; width:21px; height:21px;
  border-radius:50%; background:var(--brand); color:var(--brand-ink);
  display:grid; place-items:center; font-size:13px; font-weight:800;
  transform:scale(0); transition:transform .3s var(--spring);
}
.bld.is-selected .bld__tick { transform:scale(1); }

/* Docked, the models shrink and sit shoulder to shoulder. */
.dock .buildings {
  display:flex; gap:6px; perspective:520px; flex-wrap:wrap;
}
.dock .bld {
  padding:7px; border-radius:var(--r-sm); pointer-events:none; animation:none;
  background:var(--bg-2);
}
.dock .bld:hover { transform:none; box-shadow:none; }
.dock .bld__stage { height:56px; margin-bottom:0; perspective:260px; }
.dock .bld__model { width:64px !important; height:56px !important; }

/* Both selectors are needed and the second is not redundant: the docked
   model is always a selected one, and `.bld.is-selected .bld__model` carries
   three classes to this rule's two, so without matching that specificity the
   full-size selected transform wins and the thumbnail renders at full size. */
.dock .bld__model,
.dock .bld.is-selected .bld__model {
  transform:scale(.46) translateY(24px) rotateX(58deg) rotateZ(-38deg);
  transform-origin:center bottom;
}
.dock .bld__name, .dock .bld__count, .dock .bld__tick { display:none; }

/* ------------------------------------------------------------- results -- */

.results__head {
  display:flex; align-items:flex-end; gap:18px; flex-wrap:wrap; margin-bottom:18px;
}
.results__actions { margin-left:auto; display:flex; gap:10px; flex-wrap:wrap; }

.filters {
  display:flex; gap:12px; flex-wrap:wrap; align-items:end; margin-bottom:20px;
  padding:14px; background:var(--bg-1); border:1px solid var(--line);
  border-radius:var(--r);
}
/* A <select> sizes to its widest option unless told otherwise, and the
   administrator list holds names like "NYSERDA + Downstate Joint Utilities".
   That one control was 467px wide inside a 390px screen and took the whole
   page sideways with it. min-width:0 is the part that actually matters —
   without it a grid or flex item refuses to shrink below its content. */
.filter { display:grid; gap:5px; min-width:150px; max-width:100%; }
.filter--search { flex:1 1 230px; }
.filter__input { width:100%; max-width:100%; min-width:0; }
select.filter__input { text-overflow:ellipsis; }
.filter__label {
  font-size:11px; letter-spacing:.11em; text-transform:uppercase;
  color:var(--ink-4); font-weight:600;
}
.filter__input {
  padding:9px 11px; border-radius:var(--r-sm); border:1px solid var(--line-2);
  background:var(--bg); color:var(--ink);
}
.filter__input:focus {
  outline:none; border-color:var(--brand); box-shadow:0 0 0 3px rgba(25,200,232,.18);
}

.cards { display:grid; gap:14px; grid-template-columns:repeat(auto-fill,minmax(330px,1fr)); }

.card {
  display:grid; gap:10px; padding:18px; background:var(--bg-1);
  border:1px solid var(--line); border-radius:var(--r);
  animation:card-in .42s var(--ease-out) both;
  transition:border-color .2s var(--ease), transform .2s var(--ease);
}
@keyframes card-in {
  from { opacity:0; transform:translateY(14px); }
  to   { opacity:1; transform:none; }
}
.card:hover { border-color:var(--line-2); transform:translateY(-2px); }

.card__top { display:flex; align-items:start; gap:10px; }
.card__name { margin:0; font-size:16px; line-height:1.35; letter-spacing:-.01em; }
.card__meta { margin:0; font-size:12.5px; color:var(--ink-3); }
.card__incentive { margin:0; font-size:13.5px; color:var(--ink-2); }

.status {
  flex:none; padding:4px 9px; border-radius:999px; font-size:11px; font-weight:700;
  letter-spacing:.03em; white-space:nowrap;
}
.status--open      { background:rgba(47,211,167,.16); color:var(--ok); }
.status--limited   { background:rgba(240,162,60,.16); color:var(--warn); }
.status--financing { background:rgba(142,123,255,.18); color:var(--ink-violet); }
.status--costs     { background:rgba(240,162,60,.13); color:var(--warn); }
.status--paused    { background:rgba(134,151,173,.16); color:var(--ink-3); }
.status--closed    { background:rgba(242,104,74,.14); color:var(--bad); }
.status--upcoming  { background:rgba(25,200,232,.14); color:var(--brand); }

.tags { display:flex; flex-wrap:wrap; gap:6px; }
.tag {
  padding:3px 9px; border-radius:999px; font-size:11.5px;
  background:var(--bg-3); color:var(--ink-3);
}

.card__foot { display:flex; align-items:center; gap:10px; margin-top:2px; }
.card__foot .btn { padding:8px 13px; font-size:13px; }
.card__link { color:var(--brand); font-size:13px; font-weight:600; text-decoration:none; }
.card__link:hover { text-decoration:underline; }

.card__caution {
  margin:0; padding:9px 11px; border-radius:var(--r-sm); font-size:12.5px;
  background:rgba(240,162,60,.09); border:1px solid rgba(240,162,60,.22);
  color:var(--ink-warn);
}

details.card__more { font-size:13px; color:var(--ink-2); }
details.card__more summary { cursor:pointer; color:var(--brand); font-weight:600; }
details.card__more ul { margin:8px 0 0; padding-left:18px; display:grid; gap:6px; }

.empty {
  padding:36px; text-align:center; color:var(--ink-3);
  background:var(--bg-1); border:1px dashed var(--line-2); border-radius:var(--r);
}

/* -------------------------------------------------------------- drawer -- */

.drawer {
  position:fixed; top:0; right:0; bottom:0; width:min(430px,100%); z-index:60;
  background:var(--bg-1); border-left:1px solid var(--line);
  display:flex; flex-direction:column;
  animation:drawer-in .34s var(--ease-out) both;
}
@keyframes drawer-in { from { transform:translateX(100%); } to { transform:none; } }
.drawer__head {
  display:flex; align-items:center; gap:12px; padding:16px 18px;
  border-bottom:1px solid var(--line);
}
.drawer__title { margin:0; font-size:18px; }
.drawer__head .icon-btn { margin-left:auto; }
.drawer__body { flex:1; overflow-y:auto; padding:16px 18px 30px; display:grid; gap:14px; align-content:start; }

.scrim {
  position:fixed; inset:0; z-index:55; background:var(--scrim);
  backdrop-filter:blur(2px); animation:fade .3s var(--ease) both;
}
@keyframes fade { from { opacity:0; } to { opacity:1; } }

.list {
  border:1px solid var(--line); border-radius:var(--r); background:var(--bg-2);
  padding:14px; display:grid; gap:10px;
}
.list.is-active { border-color:var(--brand); }
.list__top { display:flex; align-items:center; gap:10px; }
.list__name { margin:0; font-size:15px; font-weight:700; }
.list__count { margin-left:auto; font-size:12px; color:var(--ink-3); }
.list__items { display:grid; gap:8px; margin:0; padding:0; list-style:none; }

.li {
  display:grid; gap:6px; padding:10px; border-radius:var(--r-sm);
  background:var(--bg-1); border:1px solid var(--line);
}
.li__top { display:flex; gap:8px; align-items:start; }
.li__name { margin:0; font-size:13.5px; font-weight:600; line-height:1.35; }
.li__meta { margin:0; font-size:11.5px; color:var(--ink-4); }
.li__row { display:flex; gap:8px; align-items:center; }
.li__state {
  padding:5px 8px; border-radius:var(--r-sm); border:1px solid var(--line-2);
  background:var(--bg); font-size:12px;
}
.li__note {
  width:100%; padding:7px 9px; border-radius:var(--r-sm); font-size:12.5px;
  border:1px solid var(--line); background:var(--bg); resize:vertical; min-height:34px;
}
.li__x {
  margin-left:auto; border:0; background:transparent; color:var(--ink-4);
  cursor:pointer; font-size:17px; line-height:1; padding:2px 5px; border-radius:6px;
}
.li__x:hover { background:rgba(242,104,74,.16); color:var(--bad); }

/* --------------------------------------------------------------- modal -- */

.modal {
  width:min(660px,94vw); border:1px solid var(--line); border-radius:var(--r-lg);
  background:var(--bg-1); color:var(--ink); padding:26px; box-shadow:var(--shadow);
}
.modal::backdrop { background:var(--scrim); backdrop-filter:blur(3px); }
.modal[open] { animation:modal-in .3s var(--ease-out) both; }
@keyframes modal-in {
  from { opacity:0; transform:translateY(14px) scale(.98); }
  to   { opacity:1; transform:none; }
}
.modal__close-form { float:right; margin:-8px -8px 0 0; }
.modal__title { margin:0 0 6px; font-size:21px; }
.modal__lede { margin:0 0 18px; color:var(--ink-3); font-size:14px; }
.modal__actions { display:flex; gap:10px; margin-top:18px; flex-wrap:wrap; }
.modal .field { margin-bottom:14px; }

.share__result { margin-top:20px; border-top:1px solid var(--line); padding-top:18px; }
.share__status {
  margin:0 0 12px; padding:10px 12px; border-radius:var(--r-sm); font-size:13.5px;
  background:rgba(47,211,167,.12); border:1px solid rgba(47,211,167,.3); color:var(--ink-ok);
}
.share__status.is-warn {
  background:rgba(240,162,60,.12); border-color:rgba(240,162,60,.3); color:var(--ink-warn);
}
.share__status.is-bad {
  background:rgba(242,104,74,.12); border-color:rgba(242,104,74,.3); color:var(--ink-bad);
}
.share__tabs { display:flex; gap:6px; margin-bottom:10px; }
.share__tab {
  padding:6px 12px; border-radius:999px; border:1px solid var(--line);
  background:transparent; cursor:pointer; font-size:12.5px; color:var(--ink-3);
}
.share__tab.is-active { background:var(--bg-3); color:var(--ink); border-color:var(--line-2); }
.share__preview {
  max-height:280px; overflow:auto; margin:0; padding:14px; border-radius:var(--r-sm);
  background:var(--bg); border:1px solid var(--line); font-family:var(--mono);
  font-size:12px; line-height:1.6; white-space:pre-wrap; word-break:break-word;
  color:var(--ink-2);
}

/* --------------------------------------------------------------- toast -- */

.toast {
  position:fixed; left:50%; bottom:28px; transform:translateX(-50%); z-index:80;
  padding:12px 20px; border-radius:999px; background:var(--bg-3);
  border:1px solid var(--line-2); box-shadow:var(--shadow); font-size:14px;
  animation:toast-in .3s var(--spring) both;
}
@keyframes toast-in {
  from { opacity:0; transform:translate(-50%,16px); }
  to   { opacity:1; transform:translate(-50%,0); }
}
.toast.is-bad { background:rgba(242,104,74,.18); border-color:rgba(242,104,74,.4); }

/* ------------------------------------------------------------- motion -- */

@media (prefers-reduced-motion:reduce) {
  *,*::before,*::after {
    animation-duration:.01ms !important; animation-iteration-count:1 !important;
    transition-duration:.01ms !important;
  }
  .region:hover { transform:none !important; }
}

/* ------------------------------------------------------- modal extras -- */

.modal--wide { width:min(880px,95vw); }

.grid2 {
  display:grid; gap:12px; grid-template-columns:repeat(auto-fit,minmax(190px,1fr));
  margin-bottom:14px;
}
.grid2 .field { margin-bottom:0; }

.measures { border:1px solid var(--line); border-radius:var(--r); padding:12px 14px; margin:0 0 14px; }
.measures legend { padding:0 6px; }
.measures__grid {
  display:grid; gap:7px; grid-template-columns:repeat(auto-fill,minmax(190px,1fr));
}
.mcheck {
  display:flex; align-items:center; gap:8px; padding:7px 9px; cursor:pointer;
  border-radius:var(--r-sm); background:var(--bg-2); border:1px solid transparent;
  font-size:12.8px;
}
.mcheck:hover { border-color:var(--line-2); }
.mcheck input { accent-color:var(--brand); width:15px; height:15px; }
.mcheck.is-on { border-color:var(--brand); background:var(--bg-3); }

/* ---------------------------------------------------------- estimate -- */

.estimate { margin-top:20px; border-top:1px solid var(--line); padding-top:18px; }
.estimate__headline {
  padding:18px; border-radius:var(--r);
  background:linear-gradient(135deg,var(--bg-2),var(--bg-3));
  border:1px solid var(--line); margin-bottom:14px;
}
.estimate__label {
  margin:0; font-size:11.5px; letter-spacing:.12em; text-transform:uppercase;
  color:var(--ink-4); font-weight:700;
}
.estimate__figure {
  margin:6px 0 0; font-size:34px; font-weight:800; letter-spacing:-.02em;
  color:var(--brand); font-variant-numeric:tabular-nums; line-height:1.1;
}
.estimate__sub { margin:8px 0 0; font-size:13px; color:var(--ink-3); }

.estimate__rows { display:grid; gap:8px; max-height:330px; overflow-y:auto; margin-bottom:14px; }
.erow {
  display:grid; gap:4px; padding:11px 13px; border-radius:var(--r-sm);
  background:var(--bg-1); border:1px solid var(--line);
}
.erow__top { display:flex; align-items:baseline; gap:10px; }
.erow__name { font-size:13.5px; font-weight:700; }
.erow__amt {
  margin-left:auto; font-size:13.5px; font-weight:800; color:var(--brand);
  font-variant-numeric:tabular-nums; white-space:nowrap;
}
.erow__meta { font-size:11.5px; color:var(--ink-4); }
.erow__basis { font-size:11.5px; color:var(--ink-3); font-family:var(--mono); }
.erow--none { opacity:.75; }
.erow--none .erow__amt { color:var(--ink-4); font-weight:600; }

#estimate-caveats { margin:8px 0 0; padding-left:18px; display:grid; gap:6px; }
#estimate-caveats li { font-size:12.5px; color:var(--ink-3); }

/* ---------------------------------------------------- building panel -- */
/* The right-hand column. It answers "what does this mean for MY building?"
   while the middle of the screen is still a catalogue. It only appears at
   step 3, where a building is actually in play. */

.bpanel {
  grid-column:3; grid-row:1; display:none; gap:0; align-content:start;
  position:sticky; top:74px; max-height:calc(100dvh - 92px); overflow-y:auto;
  padding:16px; border-radius:var(--r); border:1px solid var(--line);
  background:linear-gradient(180deg,var(--bg-1),var(--bg));
}
.app[data-stage="results"] .bpanel { display:grid; }

.bpanel__eyebrow {
  margin:0; font-size:11px; letter-spacing:.14em; text-transform:uppercase;
  color:var(--brand); font-weight:700;
}
.bpanel__name { margin:5px 0 0; font-size:16.5px; letter-spacing:-.01em; line-height:1.3; }
.bpanel__addr { margin:3px 0 0; font-size:12.5px; color:var(--ink-3); }

/* ---- the charge ---------------------------------------------------------
   A building silhouette that fills from the bottom as routes are added, with
   windows lighting up on the way. `--fill` is 0..1 and drives the clip
   rectangle; the windows switch on in sequence above it.
   It is a PROGRESS indicator, not a metric, and the caption says so — the
   money is reported as a number underneath, where it cannot be misread as a
   proportion of anything. */

.charge { position:relative; margin:14px 0 4px; display:grid; justify-items:center; }
.charge__svg { width:118px; height:148px; display:block; }

.charge__shape rect { fill:var(--bg-3); stroke:var(--line-2); stroke-width:1; }

/* The clip rect is animated by its y position: at --fill 0 it sits entirely
   below the building, at 1 it covers it. */
.charge__level {
  transform:translateY(calc((1 - var(--fill)) * 150px));
  transition:transform 1s var(--ease-out);
}
.charge__fill { filter:drop-shadow(0 0 14px rgba(25,200,232,.55)); }

.charge__windows rect {
  fill:var(--bg-1); opacity:.25;
  transition:opacity .5s var(--ease), fill .5s var(--ease);
}
.charge__windows rect.is-lit {
  fill:var(--window-lit); opacity:.95;
  animation:flicker 2.6s var(--ease) infinite alternate;
}
@keyframes flicker { from { opacity:.78; } to { opacity:1; } }

.charge__caption {
  margin:8px 0 0; font-size:11.5px; color:var(--ink-4); text-align:center;
}

.bpanel__stats {
  margin:14px 0 0; padding:12px 0 0; display:grid; gap:8px;
  border-top:1px solid var(--line);
}
.bpanel__stats div { display:flex; align-items:baseline; gap:8px; }
.bpanel__stats dt { font-size:11.5px; color:var(--ink-4); }
.bpanel__stats dd {
  margin:0 0 0 auto; font-size:12.5px; font-weight:700; color:var(--ink-2);
  font-variant-numeric:tabular-nums;
}

.bpanel__figure {
  margin-top:12px; padding:11px 13px; border-radius:var(--r-sm);
  background:var(--bg-2); border:1px solid var(--line);
}
.bpanel__flabel {
  margin:0; font-size:10.5px; letter-spacing:.11em; text-transform:uppercase;
  color:var(--ink-4); font-weight:700;
}
.bpanel__fvalue {
  margin:5px 0 0; font-size:19px; font-weight:800; color:var(--brand);
  font-variant-numeric:tabular-nums; letter-spacing:-.01em; line-height:1.2;
}
.bpanel__fvalue--sm { font-size:13.5px; color:var(--ink-2); font-weight:700; }

.bpanel__note {
  margin:10px 0 0; padding:9px 11px; border-radius:var(--r-sm); font-size:11.5px;
  line-height:1.5; background:rgba(240,162,60,.10);
  border:1px solid rgba(240,162,60,.28); color:var(--ink-warn);
}

.bpanel__cta {
  margin-top:16px; padding-top:14px; border-top:1px solid var(--line);
}
.bpanel__ctatext { margin:0 0 9px; font-size:12.5px; color:var(--ink-3); }
#bp-contact { font-size:13px; padding:10px 12px; text-decoration:none; text-align:center; }

@media (max-width:1280px) {
  .app[data-stage="results"] .bpanel {
    grid-column:1/-1; grid-row:auto; position:static; max-height:none;
  }
}

/* ------------------------------------------------------- panel metrics -- */
/* A number on its own tells nobody whether it is good. Every metric here is
   a value, a track showing where typical sits, and a one-word verdict. The
   shaded band IS the typical range — the pin's position relative to it is
   the whole message, readable without reading any of the figures. */

.bpanel__chip {
  margin:8px 0 0; display:inline-block; padding:3px 9px; border-radius:999px;
  background:var(--bg-3); color:var(--ink-3); font-size:11px; font-weight:600;
}

.metrics { display:grid; gap:13px; margin:14px 0 4px; padding-top:13px;
  border-top:1px solid var(--line); }

.metric { display:grid; gap:6px; }
.metric__top { display:flex; align-items:baseline; gap:8px; }
.metric__label {
  font-size:10.5px; letter-spacing:.1em; text-transform:uppercase;
  color:var(--ink-4); font-weight:700;
}
.metric__value {
  margin-left:auto; font-size:15px; font-weight:800; color:var(--ink);
  font-variant-numeric:tabular-nums; white-space:nowrap;
}
.metric__value--sm { font-size:12.5px; font-weight:700; color:var(--ink-2); }

.track {
  position:relative; height:8px; border-radius:4px; background:var(--bg-3);
  overflow:visible;
}
.track__band {
  position:absolute; top:0; bottom:0; border-radius:4px;
  background:linear-gradient(90deg,rgba(47,211,167,.55),rgba(240,162,60,.55));
}
.track__pin {
  position:absolute; top:50%; width:12px; height:12px; border-radius:50%;
  transform:translate(-50%,-50%);
  background:var(--ink); border:2px solid var(--bg-1);
  box-shadow:0 1px 4px rgba(0,0,0,.4);
  transition:left .7s var(--ease-out), background .3s var(--ease);
}
.track__pin.is-strong  { background:var(--ok); }
.track__pin.is-good    { background:var(--teal); }
.track__pin.is-onmark  { background:var(--brand); }
.track__pin.is-average { background:var(--warn); }
.track__pin.is-poor    { background:var(--bad); }

.metric__foot { display:flex; align-items:baseline; gap:8px; }
.metric__verdict { font-size:11.5px; font-weight:700; }
.metric__verdict.is-strong  { color:var(--ok); }
.metric__verdict.is-good    { color:var(--teal); }
.metric__verdict.is-onmark  { color:var(--brand); }
.metric__verdict.is-average { color:var(--warn); }
.metric__verdict.is-poor    { color:var(--bad); }
.metric__alt { margin-left:auto; font-size:11px; color:var(--ink-4);
  font-variant-numeric:tabular-nums; }

.split { display:flex; height:10px; border-radius:5px; overflow:hidden; background:var(--bg-3); }
.split__elec { background:var(--brand); transition:width .7s var(--ease-out); }
.split__gas  { background:var(--warm); transition:width .7s var(--ease-out); }

.metric__key { display:inline-flex; align-items:center; gap:5px;
  font-size:11px; color:var(--ink-3); font-variant-numeric:tabular-nums; }
.metric__key + .metric__key { margin-left:auto; }
.dot { width:8px; height:8px; border-radius:2px; flex:none; }
.dot--elec { background:var(--brand); }
.dot--gas  { background:var(--warm); }

.bpanel__more { font-size:11.5px; }
.bpanel__more summary { font-size:11.5px; }
.bpanel__more ul { margin:7px 0 0; padding-left:16px; display:grid; gap:5px; }
.bpanel__more li { font-size:11px; color:var(--ink-4); line-height:1.5; }

.bpanel__size {
  display:flex; align-items:center; gap:7px; margin-top:10px;
  font-size:11.5px; color:var(--ink-4);
}
.bpanel__size input {
  width:88px; padding:5px 8px; border-radius:var(--r-sm); font-size:12px;
  border:1px solid var(--line-2); background:var(--bg); color:var(--ink);
  font-variant-numeric:tabular-nums;
}
.bpanel__size input:focus {
  outline:none; border-color:var(--brand); box-shadow:0 0 0 3px rgba(25,200,232,.18);
}

/* Portfolio grouping and building thumbnails in the sidebar. */
.side__group {
  margin:10px 0 2px; font-size:10.5px; letter-spacing:.1em; text-transform:uppercase;
  color:var(--brand); font-weight:700;
}
.side__group:first-child { margin-top:2px; }

.srow--photo { grid-template-columns:52px minmax(0,1fr); display:grid; gap:9px; align-items:start; }
.srow__thumb {
  width:52px; height:52px; object-fit:cover; border-radius:7px; display:block;
  background:var(--bg-3); border:1px solid var(--line);
}
.srow__body { display:grid; gap:3px; min-width:0; }

.bpanel__photo {
  width:100%; height:130px; object-fit:cover; border-radius:var(--r-sm);
  display:block; margin-bottom:12px; background:var(--bg-3);
  border:1px solid var(--line);
}
.metric__src { font-size:10.5px; color:var(--ink-4); }

/* Twenty buildings, each with four action buttons, is four-fifths buttons.
   The actions belong to the row you are pointing at or the one in the panel;
   the rest just need a name and a photograph. Keeping them in the flow
   (rather than display:none) would still leave a mis-click target, so they
   collapse to zero height until wanted. */
.srow--photo .srow__acts {
  max-height:0; overflow:hidden; margin-top:0; opacity:0;
  transition:max-height .18s var(--ease), opacity .18s var(--ease), margin-top .18s var(--ease);
}
.srow--photo:hover .srow__acts,
.srow--photo:focus-within .srow__acts,
.srow--photo.is-active .srow__acts {
  max-height:40px; opacity:1; margin-top:4px;
}
.srow--photo { cursor:pointer; }
