/* ── ACT Development Screen: a slim, monochrome layer on Bootstrap 5 ───────
   Black and greys only, no accent hues. State is shown by contrast, not
   colour: darker = stronger signal. A tool that says "walk away" in red
   and "proceed" in green is making the decision for you; this one puts
   the numbers in a fixed-width face and lets them argue.

   Bootstrap's semantic utilities are remapped to greyscale here so the
   components keep working without per-template edits. */

:root{
  --ink:#1b1b1b; --g1:#3d3d3d; --g2:#6c6c6c; --g3:#9a9a9a;
  --g4:#cfcfcf; --g5:#e6e6e6; --g6:#f3f3f3;
  --bs-body-font-family:"Hanken Grotesk", system-ui, sans-serif;
  --bs-body-color:var(--ink);
  --bs-link-color-rgb:27,27,27;
  --bs-link-hover-color-rgb:0,0,0;
}
.mono, .figure-val, table.data td.num, table.data th.num, .grid-cell, input.form-control, .form-select{
  font-family:"Spline Sans Mono", ui-monospace, monospace;
  font-variant-numeric:tabular-nums;
}
[x-cloak]{display:none!important}
body{font-size:15px}
a{color:var(--ink)} a:hover{color:#000}
.fa-solid,.fa-regular{line-height:1; vertical-align:-.05em}

/* ── HTMX swap containers ─────────────────────────────────────────────
   Every keystroke in the calculators re-renders the whole container, and
   the answer changing adds or removes a panel, so the page gets taller or
   shorter mid-edit. Chrome's scroll anchoring then tries to hold whatever
   it had anchored on — but that node was just destroyed by the swap, so
   the correction it computes is garbage and the viewport lands at the very
   bottom of the document. The symptom is the input you are typing in
   apparently diving to the foot of the page.

   Anchoring has nothing to hold onto in a container that is replaced
   wholesale, so opt these out of it. Scroll position then simply stays
   where the user left it, which is what typing into a field should do. */
#model, #screen, #activity-stream, #results, #nav-results, #add-results{
  overflow-anchor:none;
}
/* The swap wrapper is not a panel, so `.panel + .panel` cannot reach
   across it and the panel after `#screen` sat flush against the Gate 2
   buttons. Give the container the page's own 1rem rhythm rather than
   putting a utility class on the div, so the rule travels with the
   reason for it. */
#screen{margin-bottom:1rem}

/* ── Primary / action = black ──────────────────────────────────────────*/
.btn-primary{
  --bs-btn-bg:var(--ink); --bs-btn-border-color:var(--ink);
  --bs-btn-hover-bg:#000; --bs-btn-hover-border-color:#000;
  --bs-btn-active-bg:#000; --bs-btn-active-border-color:#000;
  --bs-btn-disabled-bg:var(--g3); --bs-btn-disabled-border-color:var(--g3);
}
.btn-outline-primary,.btn-outline-warning{
  --bs-btn-color:var(--ink); --bs-btn-border-color:var(--g4);
  --bs-btn-hover-bg:var(--ink); --bs-btn-hover-color:#fff; --bs-btn-hover-border-color:var(--ink);
}
.btn-outline-secondary{
  --bs-btn-color:var(--g1); --bs-btn-border-color:var(--g4);
  --bs-btn-hover-bg:var(--g6); --bs-btn-hover-color:var(--ink); --bs-btn-hover-border-color:var(--g3);
}
.text-brand,.text-success,.text-primary{color:var(--ink)!important}
.text-danger{color:var(--g2)!important}
.brand-logo{width:30px; height:30px; border-radius:7px; background:var(--ink);
  color:#fff; display:grid; place-items:center; font-weight:700; flex:none;
  font-size:.85rem; letter-spacing:-.02em}

/* ── Badges / alerts → greyscale ───────────────────────────────────────*/
.text-bg-success,.text-bg-danger{background-color:var(--ink)!important; color:#fff!important}
.text-bg-warning{background-color:var(--g5)!important; color:var(--ink)!important}
.text-bg-secondary,.text-bg-light{background-color:var(--g6)!important; color:var(--g2)!important;
  border:1px solid var(--g5)}
.alert-primary,.alert-success,.alert-warning,.alert-secondary,.alert-info,.alert-danger{
  --bs-alert-color:var(--ink); --bs-alert-bg:var(--g6); --bs-alert-border-color:var(--g5);
}
.form-control:focus,.form-select:focus{border-color:var(--g2); box-shadow:0 0 0 .18rem rgba(0,0,0,.08)}
.form-check-input:checked{background-color:var(--ink); border-color:var(--ink)}

/* ── Search ───────────────────────────────────────────────────────────*/
.search-shell{max-width:640px}
.search-input{font-size:1.15rem; padding:.85rem 1rem; border:1.5px solid var(--g4); border-radius:.6rem}
.search-input:focus{border-color:var(--ink)}
.results{border:1px solid var(--g5); border-radius:.6rem; overflow:hidden; background:#fff}
.results a{display:block; padding:.6rem .85rem; text-decoration:none; border-bottom:1px solid var(--g6)}
.results a:last-child{border-bottom:0}
.results a:hover,.results a:focus{background:var(--g6)}
.results .addr{font-weight:600}
.results .meta{font-size:.8rem; color:var(--g2)}
/* The suburb row in the dropdown. Tinted rather than bordered so it
   reads as a different kind of answer to the addresses under it — a
   destination, not a result. */
.results a.result-suburb{background:var(--g6); border-bottom:1px solid var(--g4)}
.results a.result-suburb:hover,.results a.result-suburb:focus{background:var(--g5)}
.results a.result-suburb .addr{display:flex; justify-content:space-between; gap:1rem}
.results .suburb-count{font-weight:400; font-size:.8rem; color:var(--g2);
  font-family:"Spline Sans Mono", ui-monospace, monospace; white-space:nowrap}
.htmx-request .spinner-hint{opacity:1}
.spinner-hint{opacity:0; transition:.15s; font-size:.8rem; color:var(--g3)}

/* ── Figures — the numbers are the product, so give them room ─────────*/
.figure-grid{display:grid; gap:.75rem; grid-template-columns:repeat(auto-fit,minmax(180px,1fr))}
.figure{border:1px solid var(--g5); border-radius:.5rem; padding:.7rem .85rem; background:#fff}
.figure-label{font-size:.72rem; text-transform:uppercase; letter-spacing:.06em; color:var(--g2)}
.figure-val{font-size:1.35rem; font-weight:600; line-height:1.25; margin-top:.15rem}
.figure-val.sm{font-size:1.05rem}
.figure-note{font-size:.76rem; color:var(--g2); margin-top:.15rem}
.figure.strong{border-color:var(--ink); border-width:1.5px}

/* ── Verdict panels: contrast, not colour ─────────────────────────────*/
.verdict{border:1.5px solid var(--g4); border-radius:.6rem; padding:1rem 1.15rem; background:#fff}
.verdict .label{font-size:.72rem; text-transform:uppercase; letter-spacing:.08em; color:var(--g2)}
.verdict .call{font-size:1.5rem; font-weight:700; letter-spacing:-.01em; margin:.15rem 0 .4rem}
.verdict p{margin:0; color:var(--g1); font-size:.9rem}
.verdict-stop{background:var(--ink); border-color:var(--ink); color:#fff}
.verdict-stop .label,.verdict-stop p{color:var(--g4)}
.verdict-warn{background:var(--g6); border-color:var(--g3)}
.verdict-go{background:#fff; border-color:var(--ink)}

/* ── Data tables ──────────────────────────────────────────────────────*/
table.data{width:100%; font-size:.88rem; border-collapse:collapse}
table.data th{font-size:.72rem; text-transform:uppercase; letter-spacing:.05em;
  color:var(--g2); font-weight:600; padding:.4rem .5rem; border-bottom:1px solid var(--g4);
  text-align:left; white-space:nowrap}
table.data td{padding:.4rem .5rem; border-bottom:1px solid var(--g6)}
table.data td.num,table.data th.num{text-align:right}
table.data tr.best td{background:var(--g6); font-weight:600}
table.data tr.best td:first-child{box-shadow:inset 3px 0 0 var(--ink)}
table.data tbody tr:hover td{background:var(--g6)}
table.data caption{caption-side:top; padding:0 0 .4rem; font-size:.8rem; color:var(--g2)}

/* ── Sensitivity grid — darker cell = more land you can pay for ───────*/
.grid-cell{text-align:right; padding:.35rem .5rem; font-size:.82rem; border:1px solid #fff}
.grid-cell.q0{background:#fff}
.grid-cell.q1{background:var(--g6)}
.grid-cell.q2{background:var(--g5)}
.grid-cell.q3{background:var(--g4)}
.grid-cell.q4{background:var(--g3); color:#fff}
.grid-cell.here{outline:2px solid var(--ink); outline-offset:-2px; font-weight:700}

/* ── Panels and section headings ──────────────────────────────────────*/
.panel{border:1px solid var(--g5); border-radius:.6rem; background:#fff; padding:1.1rem 1.25rem}
.panel + .panel{margin-top:1rem}
.panel-head{display:flex; align-items:baseline; justify-content:space-between; gap:1rem;
  margin:0 0 .85rem}
.panel-head h2{font-size:1rem; font-weight:700; margin:0; letter-spacing:-.01em}
.panel-head .hint{font-size:.8rem; color:var(--g2)}
.rule{border:0; border-top:1px solid var(--g5); margin:1rem 0}

/* ── Assumption fields ────────────────────────────────────────────────*/
.assump{display:grid; grid-template-columns:1fr 130px; gap:.5rem 1rem; align-items:center;
  padding:.3rem 0; border-bottom:1px solid var(--g6)}
.assump:last-child{border-bottom:0}
.assump label{font-size:.85rem; color:var(--g1); margin:0}
.assump .form-control{text-align:right; font-size:.85rem; padding:.25rem .5rem}
.assump .unit{font-size:.75rem; color:var(--g3)}

/* ── Flags: Mr Fluffy, missing schedule, deadline warnings ────────────*/
.flag{display:flex; gap:.6rem; align-items:flex-start; border:1px solid var(--g4);
  border-left-width:4px; border-left-color:var(--ink); border-radius:.4rem;
  padding:.6rem .8rem; background:#fff; font-size:.86rem}
.flag + .flag{margin-top:.5rem}
.flag.quiet{border-left-color:var(--g4); color:var(--g1)}
.flag .fa-solid{color:var(--g2); margin-top:.15rem}

/* ── Block overview: the signal grid ──────────────────────────────────
   Two columns of short rows rather than a table, because the reader is
   scanning for the one line that matters, not comparing a column.

   State is the left rule and the marker glyph, both greyscale: a
   constraint gets the full-contrast rule, something to check gets a
   mid-grey one, a clear result gets almost nothing. The alternative —
   red for bad, green for clear — would be the tool making the call, and
   a mapped bushfire band is a cost, not a verdict. */
.signal-grid{display:grid; gap:.4rem .9rem; grid-template-columns:repeat(auto-fit,minmax(300px,1fr))}
.signal{display:flex; gap:.55rem; align-items:baseline; font-size:.86rem;
  padding:.35rem .6rem; border-left:3px solid var(--g5); background:var(--g6);
  border-radius:.25rem}
.signal-state{font-family:"Spline Sans Mono", ui-monospace, monospace; font-weight:700;
  color:var(--g3); width:.9rem; flex:none; text-align:center}
.signal-detail{color:var(--g1)}
.signal-note{font-size:.75rem; color:var(--g2); margin-top:.1rem}
.signal.constraint{border-left-color:var(--ink); background:#fff}
.signal.constraint .signal-state{color:var(--ink)}
.signal.investigate{border-left-color:var(--g2); background:#fff}
.signal.investigate .signal-state{color:var(--g1)}
.signal.opportunity{border-left-color:var(--g3); background:#fff}
.signal.clear .signal-state{color:var(--g2)}
.signal.clear strong{font-weight:600}
.signal.informational{border-left-color:var(--g4)}
.signal.unknown{background:transparent; border-left-color:var(--g4)}
/* The unassessed list stays one line until asked for. It must be
   present — omitting it is the misreading this whole product guards
   against — but it is the least decision-relevant thing on the panel. */
.signal-unknown{font-size:.84rem; color:var(--g1)}
.signal-unknown summary{cursor:pointer; color:var(--g1); padding:.3rem 0}
.signal-unknown summary:hover{color:var(--ink)}
.signal-unknown[open] .signal{margin-top:.3rem}

/* ── Explainers ───────────────────────────────────────────────────────*/
.prose{max-width:44rem; font-size:.98rem; line-height:1.65}
.prose h2{font-size:1.15rem; font-weight:700; margin:1.8rem 0 .6rem}
.prose h3{font-size:1rem; font-weight:600; margin:1.4rem 0 .5rem}
.prose table{width:100%; font-size:.88rem; margin:1rem 0; border-collapse:collapse}
.prose th,.prose td{padding:.35rem .5rem; border-bottom:1px solid var(--g5); text-align:left}
.prose blockquote{border-left:3px solid var(--g4); padding-left:1rem; margin:1.2rem 0;
  color:var(--g1); font-style:normal}
.prose code{background:var(--g6); padding:.1rem .3rem; border-radius:.2rem; color:var(--ink)}
.prose .worked{background:var(--g6); border-radius:.5rem; padding:.9rem 1.1rem; margin:1.2rem 0;
  font-size:.9rem}

/* ── Disclaimer, footer ───────────────────────────────────────────────*/
.disclaimer{font-size:.78rem; color:var(--g2); border-top:1px solid var(--g5);
  padding-top:.85rem; margin-top:1.5rem}
.disclaimer p{margin:0 0 .4rem}
footer.site{border-top:1px solid var(--g5); margin-top:2.5rem; padding:1.25rem 0 2rem;
  font-size:.8rem; color:var(--g2)}
footer.site a{color:var(--g1)}

/* ── Landing ──────────────────────────────────────────────────────────*/
.hero h1{font-size:2rem; font-weight:700; letter-spacing:-.02em}
.hero .lede{font-size:1.05rem; color:var(--g1); max-width:34rem}
.pill{display:inline-block; border:1px solid var(--g4); border-radius:99px;
  padding:.15rem .6rem; font-size:.75rem; color:var(--g1)}
.step-num{width:26px; height:26px; border-radius:50%; background:var(--ink); color:#fff;
  display:grid; place-items:center; font-size:.75rem; font-weight:600; flex:none}

/* ── Activity strip ───────────────────────────────────────────────────
   A scrollable month-by-month bar chart. Two overlaid bars rather than a
   stack: the light bar is all applications, the dark one the subset that
   is development-related, so the ratio is readable at a glance without a
   legend lookup. */
.monthstrip{display:flex; gap:3px; overflow-x:auto; padding:.25rem 0 .5rem;
  scrollbar-width:thin; align-items:flex-end}
.monthstrip .month{flex:none; width:38px; text-decoration:none; text-align:center;
  padding:.2rem .1rem; border-radius:.3rem}
.monthstrip .month:hover{background:var(--g6)}
.monthstrip .bar-wrap{position:relative; height:86px; display:flex; align-items:flex-end;
  justify-content:center}
.monthstrip .bar{position:absolute; bottom:0; width:20px; background:var(--g4);
  border-radius:2px 2px 0 0; min-height:1px}
.monthstrip .bar.dev{width:20px; background:var(--ink)}
.monthstrip .mcount{font-size:.68rem; color:var(--g2); margin-top:.15rem}
.monthstrip .mlabel{font-size:.62rem; color:var(--g3); line-height:1.15; margin-top:.1rem}
.monthstrip .mlabel .yr{color:var(--g4)}
.swatch{display:inline-block; width:9px; height:9px; border-radius:2px; vertical-align:baseline}
.swatch.light{background:var(--g4)}
.swatch.dark{background:var(--ink)}

/* ── Optimism panel ───────────────────────────────────────────────────
   Deliberately not red. Nothing here is an error -- these are choices,
   and the panel exists to price them, not to forbid them. */
.panel.optimism{border-color:var(--g3); border-width:1.5px}
.panel.optimism .flag{border-left-color:var(--g3)}
.panel.optimism .flag:not(.quiet){border-left-color:var(--ink)}

/* An input whose value has been flagged. A left edge, not a red ring:
   the field is still perfectly valid. */
.assump.flagged .form-control{border-color:var(--g2); box-shadow:inset 3px 0 0 var(--ink)}
.assump .flagnote{grid-column:1 / -1; font-size:.74rem; color:var(--g2); margin-top:-.1rem}

/* The current month is always incomplete, so its bar is not comparable
   to the others. Hatched rather than hidden -- dropping it would make
   the strip look stale. */
.monthstrip .month.partial .bar{background:repeating-linear-gradient(
  135deg, var(--g4) 0 3px, #fff 3px 6px)}
.monthstrip .month.partial .bar.dev{background:repeating-linear-gradient(
  135deg, var(--ink) 0 3px, var(--g4) 3px 6px)}
.swatch.partial{background:repeating-linear-gradient(135deg, var(--ink) 0 2px, #fff 2px 4px)}

/* ── DA activity markers in search results ────────────────────────────
   A live application on the block is the one thing a searcher most needs
   to see before clicking, so it gets full contrast and everything else
   recedes. Still monochrome: urgency is weight, not hue. */
.da-strip{display:flex; flex-wrap:wrap; gap:.3rem; margin-top:.3rem}
.da-tag{font-size:.71rem; line-height:1.5; padding:.05rem .4rem; border-radius:.25rem;
  border:1px solid var(--g5); background:var(--g6); color:var(--g2); white-space:nowrap}
.da-tag.live{background:var(--ink); border-color:var(--ink); color:#fff; font-weight:600}
.da-tag.quiet{background:#fff; color:var(--g3)}

/* ── Neighbouring blocks ──────────────────────────────────────────────*/
.neighbour-dist{font-size:.72rem; color:var(--g3); white-space:nowrap}

/* ── Filter bars ──────────────────────────────────────────────────────*/
.filters{display:flex; flex-wrap:wrap; gap:.75rem; align-items:flex-end}
.filters .filter{flex:1 1 180px; min-width:150px}
.filters .form-select{font-size:.85rem}

/* ── Navigation ───────────────────────────────────────────────────────
   The dots button has to be indistinguishable from a nav link until you
   reach for it: it is a peer of the three destinations beside it, not a
   control. */
.nav-more{background:none; border:0; line-height:1}
.nav-more::after{display:none}          /* no Bootstrap caret next to the dots */
.nav-more[aria-expanded="true"]{color:var(--ink)}

/* Where you are. The same inset underline the comparison tables use to
   mark the best cell — weight and a rule, never colour, so it survives
   the monochrome palette and a black-and-white print. */
.navbar .nav-link.active{color:var(--ink); font-weight:600;
  box-shadow:inset 0 -2px 0 var(--ink)}
.navbar .dropdown-item.active{background:var(--g6); color:var(--ink); font-weight:600;
  box-shadow:inset 3px 0 0 var(--ink)}
.navbar .dropdown-menu{border-color:var(--g5); border-radius:.5rem; font-size:.9rem;
  box-shadow:0 6px 20px rgba(0,0,0,.08)}
.navbar .dropdown-item:active{background:var(--ink)}

/* `navbar-expand` never collapses, so the brand plus the links ran to
   1.8× the width of a 375px screen and the whole page scrolled
   sideways. Moving three items behind the dots fixed most of it; the
   nav still drops to its own row on a phone so the brand keeps its
   line. No overflow scrolling here — it would clip the dropdown. */
@media (max-width:575.98px){
  .navbar > .container-xl{flex-wrap:wrap; row-gap:.35rem}
  .navbar .navbar-nav{width:100%; margin-left:0!important;
    justify-content:space-between}
  .navbar .nav-link{white-space:nowrap}
}

/* ── Acquisition radar ────────────────────────────────────────────────
   A denser filter bar than the activity page: there are ten inputs and
   they have to sit above the fold, or the page reads as a form to fill
   in rather than a dial to turn. */
.radar-filters{display:grid; gap:1rem; align-items:start;
  grid-template-columns:repeat(auto-fit,minmax(190px,1fr))}
/* Two of the ten inputs need the room: the suburb list, and the row of
   constraint exclusions that would otherwise wrap one word per line. */
.radar-filters .rf-wide{grid-column:span 2}
.radar-filters .rf-actions{grid-column:1/-1; display:flex; align-items:center;
  gap:1rem; padding-top:.25rem; border-top:1px solid var(--g6); margin-top:.25rem}
.radar-filters .rf-pair{display:flex; gap:.5rem}
.radar-filters .form-select,.radar-filters .form-control{font-size:.85rem}
@media (max-width:640px){.radar-filters .rf-wide{grid-column:1/-1}}
.radar-filters select[multiple]{padding:.2rem}
.radar-filters select[multiple] option{padding:.15rem .35rem; border-radius:.2rem}
.rf-checks{display:flex; flex-wrap:wrap; gap:.15rem .85rem; padding-top:.15rem}
.rf-check{display:inline-flex; align-items:center; gap:.35rem; font-size:.85rem;
  color:var(--g1); cursor:pointer; white-space:nowrap}
.rf-check input{margin:0}

/* 250 rows and eight columns. The table scrolls inside its panel rather
   than pushing the page sideways. */
.table-scroll{overflow-x:auto; max-height:70vh; overflow-y:auto;
  border:1px solid var(--g6); border-radius:.4rem}
table.radar-table{margin:0}
table.radar-table thead th{position:sticky; top:0; background:#fff; z-index:1;
  box-shadow:inset 0 -1px 0 var(--g4)}
table.radar-table td{vertical-align:top}
table.radar-table .radar-sub{font-size:.72rem; color:var(--g3); margin-top:.1rem}
table.radar-table .shortlist-col{width:2.2rem; text-align:center}
table.radar-table .shortlist-col input{margin-top:.15rem; cursor:pointer}
table.radar-table .shortlist-col input:disabled{cursor:not-allowed; opacity:.35}

/* ── Shortlist bar ────────────────────────────────────────────────────
   Docked rather than floating: it is a working tray, and it should not
   cover the last row of the table it is filled from. */
.shortlist-bar{position:sticky; bottom:0; z-index:1020; background:#fff;
  border-top:1.5px solid var(--ink); box-shadow:0 -2px 12px rgba(0,0,0,.07)}
.shortlist-head{display:flex; flex-wrap:wrap; gap:.75rem; align-items:center;
  justify-content:space-between; padding:.6rem 0}
.shortlist-toggle{background:none; border:0; padding:0; font-size:.88rem;
  color:var(--ink); display:inline-flex; align-items:center; gap:.4rem}
.shortlist-toggle:hover{text-decoration:underline}
.shortlist-cap{font-size:.78rem; color:var(--g2)}
.shortlist-items{display:flex; flex-wrap:wrap; gap:.4rem; padding:0 0 .75rem}
.shortlist-chip{display:inline-flex; align-items:center; gap:.35rem; font-size:.8rem;
  border:1px solid var(--g4); border-radius:99px; padding:.1rem .3rem .1rem .7rem}
.shortlist-chip a{color:var(--g1); text-decoration:none}
.shortlist-chip a:hover{text-decoration:underline}
.shortlist-chip button{background:none; border:0; color:var(--g3); font-size:1rem;
  line-height:1; padding:0 .3rem}
.shortlist-chip button:hover{color:var(--ink)}
.shortlist-note{flex:1 1 100%; margin:.35rem 0 0; font-size:.74rem; color:var(--g3)}

/* ── Comparison tables ────────────────────────────────────────────────
   Rows are metrics and columns are subjects, which is the opposite of
   the usual orientation but the right one here: you read across a single
   metric to compare, and there are more metrics than subjects. */
table.compare{width:100%; font-size:.88rem; border-collapse:collapse}
table.compare th, table.compare td{padding:.45rem .6rem; border-bottom:1px solid var(--g6)}
table.compare thead th{border-bottom:1px solid var(--g4); font-size:.8rem; vertical-align:bottom}
table.compare tbody th{font-weight:400; color:var(--g1); text-align:left; width:26%}
table.compare tbody th .note{display:block; font-size:.73rem; color:var(--g3)}
table.compare td{text-align:right; font-family:"Spline Sans Mono", ui-monospace, monospace;
  font-variant-numeric:tabular-nums; white-space:nowrap}
table.compare td.best{font-weight:700; box-shadow:inset 0 -2px 0 var(--ink)}
table.compare tr.divider td, table.compare tr.divider th{border-bottom-color:var(--g4);
  padding-top:1rem; font-weight:600; color:var(--ink)}
table.compare tbody tr:hover td, table.compare tbody tr:hover th{background:var(--g6)}
.compare-head{font-weight:700}
.compare-head a{text-decoration:none}
.compare-sub{font-size:.74rem; color:var(--g2); font-weight:400}
