/* Railway Alignment Designer — interface styling
   Dark, low-chroma surface so the drawing carries the colour. */

/* Design tokens and the base reset now live in tokens.css,
   which every page loads before this file. */
html,body{height:100%}
body{
  margin:0; background:var(--bg); color:var(--fg);
  font:13px/1.45 var(--ui); overflow:hidden;
  display:flex; flex-direction:column;
  -webkit-font-smoothing:antialiased;
}

/* The way past a locked sign-in gate. Quiet on purpose: whoever can sign in
   will, and this is for whoever cannot reach the host at all. */
.modal.account .acc-skip{
  display:block; margin:2px auto 14px; padding:6px 10px;
  background:none; border:none; cursor:pointer;
  color:var(--fg3); font:inherit; font-size:12px; text-decoration:underline;
}
.modal.account .acc-skip:hover{color:var(--accent)}
.modal.account .acc-skip:focus-visible{outline:2px solid var(--accent); outline-offset:2px}

/* Corridor reconnaissance: what is in the band, and which of it the line is
   obliged to serve. Nothing is ticked by default — an obligatory point moves
   the alignment, and that is the engineer's decision to make. */
.recon-card{
  margin-top:12px; padding:12px 14px; border-radius:10px;
  background:var(--bg2); border:1px solid var(--line2);
}
.recon-head{
  font-size:10.5px; font-weight:700; letter-spacing:.6px; text-transform:uppercase;
  color:var(--fg2); margin-bottom:6px;
}
.recon-lede{margin:0 0 10px; font-size:12px; line-height:1.55; color:var(--fg2)}
.recon-list{display:flex; flex-direction:column; gap:2px}
.recon-row{
  display:flex; gap:9px; align-items:flex-start; cursor:pointer;
  padding:7px 8px; border-radius:7px;
}
.recon-row:hover{background:var(--bg3)}
.recon-row input{margin-top:3px; flex:0 0 auto}
.recon-body{flex:1 1 auto; min-width:0}
.recon-name{display:flex; flex-wrap:wrap; align-items:baseline; gap:6px}
.recon-name b{font-size:13px; color:var(--fg)}
.recon-with{font-size:11.5px; color:var(--fg2)}
.recon-ch{margin-left:auto; font:10.5px var(--mono); color:var(--fg3); white-space:nowrap}
.recon-why{font-size:11.5px; line-height:1.5; color:var(--fg2); margin-top:2px}
.recon-more{margin-top:8px; font-size:11.5px; color:var(--fg2)}
.recon-more summary{cursor:pointer; color:var(--fg3); padding:4px 0}
.recon-more summary:hover{color:var(--accent)}
.recon-minor{padding:3px 0 3px 10px; line-height:1.5}
.recon-minor b{color:var(--fg2)}
.recon-acts{display:flex; gap:8px; justify-content:flex-end; margin-top:12px}

/* A cost that is not ready to be shown, shown as not ready rather than as a
   smaller number. */
.cost-readout.pending #costTotal{color:var(--fg3); font-style:italic}
.cost-readout.pending #costPerKm{color:var(--fg3)}
.est-pending{padding:14px 2px}
.est-pending h3{margin:0 0 6px; font-size:15px; color:var(--fg)}
.est-pending-list{margin:10px 0 0; padding-left:18px; color:var(--fg2); font-size:12.5px}
.est-pending-list li{margin-bottom:7px; line-height:1.55}
.est-pending-list b{color:var(--fg)}

/* ─────────────────── toolbar ─────────────────── */
/* The bar carries a lot — brand, project name, three settings and ten actions
 * — and at 1280 that wants around 2000px. It used to be one fixed-height row
 * with nowhere to overflow to, on a body that clips, so everything past the
 * right edge simply vanished. It now wraps onto a second row instead: a taller
 * header costs the drawing a few pixels, which is cheap next to a Save button
 * nobody can reach. */
.toolbar{
  display:flex; align-items:center; flex-wrap:wrap; gap:8px; row-gap:6px;
  padding:5px 12px; min-height:46px; flex:0 0 auto;
  background:var(--bg2); border-bottom:1px solid var(--line);
}
.tb-actions{
  display:flex; align-items:center; flex-wrap:wrap; gap:5px;
  justify-content:flex-end; margin-left:auto;
}
.tb-actions .btn.primary{margin-right:2px}
.brand{display:flex; align-items:center; flex:0 0 auto}
.brand img{display:block; height:30px; width:auto}
/* The project name is the title of the thing on screen, so at rest it is set
   as text: no box, no border, nothing to suggest a form. The box appears when
   it is hovered or being edited, which is the only time it is a control. The
   width ceiling is the side panel's own width, so a long name wraps within the
   panel below it rather than pushing the toolbar actions off the bar. */
.proj-name{
  background:transparent; border:1px solid transparent; color:var(--fg);
  border-radius:5px; padding:4px 8px; font:inherit; font-weight:600;
  line-height:1.25; letter-spacing:.1px;
  flex:0 0 var(--pn-w, 168px); width:var(--pn-w, 168px); min-width:110px; max-width:392px;
  resize:none; overflow:hidden; white-space:pre-wrap; word-break:break-word;
  cursor:text; transition:background .12s ease, border-color .12s ease;
}
.proj-name:hover{background:var(--bg3); border-color:var(--line)}
.proj-name:focus{
  background:var(--bg); border-color:var(--accent2); cursor:text;
}
/* Long names step down in size rather than truncate: a division wants to read
   "Nashik Road – Dahanu Road New BG Line" in full. Past three lines there is
   nothing left to give, so the last band clips. */
.proj-name.pn-2{font-size:11.5px}
.proj-name.pn-3{font-size:10.5px}
.proj-name.pn-clip{font-size:10px}
.tb-group{display:flex; align-items:center; gap:6px; color:var(--fg2); white-space:nowrap}
.tb-group label{font-size:12px}
.tb-group input{width:62px}
/* One standard's name — "Indian Railways — Broad Gauge (1676 mm)" — is wide
 * enough to push the actions off the bar on its own. The full text is there
 * when the list is open. */
#stdSel{max-width:230px}
/* The sprite itself is never drawn; only its symbols are, through <use>. */
.icon-defs{position:absolute; width:0; height:0; overflow:hidden}

/* A button that leads with an icon and then says what it does. The icon has
   to be sized explicitly: an inline <svg> with no width fills its container,
   which turns a gear into a billboard. */
.btn-lead{display:inline-flex; align-items:center; gap:6px; flex:0 0 auto}
.btn-lead .btn-i{
  width:14px; height:14px; display:block; flex:0 0 auto; pointer-events:none;
  fill:none; stroke:currentColor; stroke-width:1.5;
  stroke-linecap:round; stroke-linejoin:round;
}
/* The gear turns when you reach for it, and once round when the panel it
   opens is opening. A cog that span all the time would be a spinner, which
   means "wait" — the opposite of what this button is for. */
#btnRoute .btn-i{transform-origin:50% 50%; transition:transform .5s cubic-bezier(.34,.9,.4,1)}
#btnRoute:hover .btn-i{transform:rotate(60deg)}
#btnRoute.turning .btn-i{
  transform:rotate(405deg);
  transition:transform .75s cubic-bezier(.28,.9,.32,1);
}
@media (prefers-reduced-motion:reduce){
  #btnRoute .btn-i, #btnRoute:hover .btn-i, #btnRoute.turning .btn-i{
    transition:none; transform:none;
  }
}

/* Icon buttons. Square, so a row of them reads as a row rather than as words
   of different lengths, and the same height as the text buttons beside them so
   the bar keeps one baseline. */
.btn.icon{
  padding:0; width:30px; height:30px; display:inline-flex;
  align-items:center; justify-content:center; flex:0 0 auto;
}
.btn.icon svg{
  width:16px; height:16px; display:block; pointer-events:none;
  fill:none; stroke:currentColor; stroke-width:1.5;
  stroke-linecap:round; stroke-linejoin:round;
}
.btn.icon:disabled{opacity:.38; cursor:default}
.btn.icon:disabled:hover{background:var(--bg3); border-color:var(--line2)}

/* Groups the eye can land on without reading every button. */
.tb-sep{
  width:1px; height:18px; background:var(--line2); flex:0 0 auto;
  margin:0 1px; opacity:.75;
}

/* Save Badge displaying live save status and last saved timestamp */
.save-badge {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding: 3px 8px;
  border-radius: 12px;
  background: rgba(16, 185, 129, 0.12);
  border: 1px solid rgba(16, 185, 129, 0.25);
  color: var(--ok, #10b981);
  font-size: 11px;
  font-weight: 500;
  line-height: 1.2;
  cursor: default;
  user-select: none;
  transition: all 0.2s ease;
  white-space: nowrap;
}
.save-badge.dirty {
  background: rgba(245, 158, 11, 0.12);
  border-color: rgba(245, 158, 11, 0.25);
  color: var(--warn, #f59e0b);
}
.save-badge.saving {
  background: rgba(59, 130, 246, 0.12);
  border-color: rgba(59, 130, 246, 0.25);
  color: #60a5fa;
}
.save-badge-icon {
  font-size: 11px;
  line-height: 1;
}
.save-badge-text {
  font-size: 11px;
}

.save-mark{
  font-size:12px; line-height:1; color:var(--ok); width:12px; text-align:center;
  flex:0 0 auto; cursor:default; user-select:none;
}
.save-mark.dirty{color:var(--warn)}

.tb-spacer{flex:1}
.unit{color:var(--fg3); font-size:11px}

.mini{
  background:var(--bg3); border:1px solid var(--line2); color:var(--fg2);
  border-radius:4px; padding:3px 8px; cursor:pointer; font-size:11px;
}
.mini:hover{background:var(--bg4); color:var(--fg)}

/* ─────────────────── layout ─────────────────── */
.layout{flex:1; display:flex; min-height:0}
.side{
  --side-w:392px;
  width:var(--side-w); flex:0 0 var(--side-w); background:var(--bg2);
  border-right:1px solid var(--line); display:flex; flex-direction:column; min-height:0;
  transition:width .16s ease, flex-basis .16s ease;
}
.side-nav{
  display:flex; align-items:stretch; flex:0 0 auto;
  background:var(--bg2); border-bottom:1px solid var(--line);
}
/* Nine tabs are wider than the panel, and a tab will not shrink below its own
 * label. Left to itself the strip spills over the plan view and over the
 * collapse button with it, so it wraps onto a second row instead. */
.tabs{display:flex; flex-wrap:wrap; flex:1 1 auto; min-width:0}
.tab{
  flex:1; background:none; border:none; border-bottom:2px solid transparent;
  color:var(--fg3); padding:9px 4px; cursor:pointer; font:inherit; font-size:12px; position:relative;
  display:flex; align-items:center; justify-content:center;
}
/* Stages hide tabs with the hidden attribute, and a display of anything but
 * none beats the browser's rule for it. */
.tab[hidden]{display:none !important}
.tab:hover{color:var(--fg2)}
.tab.active{color:var(--accent); border-bottom-color:var(--accent)}
.tab-i{
  display:none; width:17px; height:17px; flex:0 0 auto; pointer-events:none;
  fill:none; stroke:currentColor; stroke-width:1.4; stroke-linecap:round; stroke-linejoin:round;
}

/* Collapse the panel to its tabs. What is given up is the tables; what is
 * kept is every way of getting back to them, so the rail is the tab strip
 * standing on its end rather than a new control to learn. */
.side-toggle{
  flex:0 0 auto; width:30px; background:none; border:none; border-bottom:2px solid transparent;
  color:var(--fg3); cursor:pointer; padding:0;
  display:flex; align-items:center; justify-content:center;
}
.side-toggle:hover{color:var(--fg2); background:var(--bg3)}
.side-toggle svg{
  width:15px; height:15px; pointer-events:none;
  fill:none; stroke:currentColor; stroke-width:1.4; stroke-linecap:round; stroke-linejoin:round;
}
.side.rail{--side-w:44px}
.side.rail .stages,
.side.rail .pane,
.side.rail .pane.active,
.side.rail .tab-t{display:none}
/* Nine tabs on a short screen are taller than the rail, so it scrolls rather
 * than putting the last of them out of reach. */
.side.rail .side-nav{
  flex-direction:column; border-bottom:none; flex:1 1 auto; min-height:0; overflow-y:auto;
}
.side.rail .tabs{flex:0 0 auto; flex-direction:column; flex-wrap:nowrap}
.side.rail .tab{
  flex:0 0 auto; padding:11px 0; border-bottom:none;
  border-left:2px solid transparent; border-right:2px solid transparent;
}
.side.rail .tab.active{background:var(--bg3); border-left-color:var(--accent)}
.side.rail .tab-i{display:block}
.side.rail .side-toggle{
  order:-1; width:auto; height:34px; border-bottom:1px solid var(--line);
}
.side.rail .side-toggle svg{transform:scaleX(-1)}

@media (prefers-reduced-motion:reduce){
  .side{transition:none}
}
.badge{
  display:none; position:absolute; top:3px; right:6px; min-width:15px; height:15px;
  border-radius:8px; background:var(--err); color:#fff; font-size:9px; line-height:15px;
  padding:0 4px; font-weight:700;
}
.badge.on{display:inline-block}
.badge.warn{background:var(--warn); color:#2a1d00}

.pane{display:none; padding:12px; overflow-y:auto; flex:1; min-height:0}
.pane.active{display:block}
.pane-head{display:flex; align-items:center; justify-content:space-between; margin-bottom:6px}
.pane-head h2{margin:0; font-size:12px; font-weight:600; color:var(--fg2); text-transform:uppercase; letter-spacing:.6px}
.pane-actions{display:flex; gap:5px}
.hint{margin:4px 0 10px; color:var(--fg3); font-size:11.5px; line-height:1.5}
.hint b{color:var(--fg2)}
.hint code{background:var(--bg3); padding:1px 4px; border-radius:3px; font-family:var(--mono); font-size:10.5px}
.field-row{display:flex; align-items:center; gap:8px; margin:8px 0; flex-wrap:wrap}
.field-row label{color:var(--fg2); font-size:12px}
.chk{display:flex; align-items:center; gap:4px; color:var(--fg2); font-size:11px; cursor:pointer}
.btn-col{display:flex; flex-direction:column}

/* ─────────────────── tables ─────────────────── */
.table-wrap{overflow:auto; border:1px solid var(--line); border-radius:6px; max-height:44vh}
.table-wrap.tall{max-height:52vh}
table.grid{border-collapse:separate; border-spacing:0; width:100%; font-size:11.5px}
table.grid th{
  position:sticky; top:0; z-index:2; background:var(--bg4); color:var(--fg2);
  font-weight:600; text-align:right; padding:6px 7px; white-space:nowrap;
  border-bottom:1px solid var(--line2); font-size:10.5px;
}
table.grid th:first-child,table.grid td:first-child{text-align:left}
table.grid td{
  padding:0; border-bottom:1px solid var(--line); text-align:right;
  font-family:var(--mono); font-size:11px; white-space:nowrap;
}
table.grid tr:last-child td{border-bottom:none}
table.grid tr.sel td{background:rgba(74,168,255,.13)}
table.grid tr.ends td{color:var(--fg3)}
table.grid input{
  width:100%; background:transparent; border:1px solid transparent; color:inherit;
  padding:5px 7px; text-align:right; font-family:var(--mono); font-size:11px; border-radius:0;
}
table.grid td:first-child input{text-align:left}
table.grid input:hover{background:var(--bg3)}
table.grid input:focus{background:var(--bg); border-color:var(--accent); position:relative; z-index:1}
table.grid input.auto{color:var(--spiral)}
table.grid input:disabled{color:var(--fg3); background:repeating-linear-gradient(45deg,transparent,transparent 4px,rgba(255,255,255,.02) 4px,rgba(255,255,255,.02) 8px)}
table.grid.compact td{padding:3px 7px}
.rowbtn{color:var(--fg3); cursor:pointer; padding:0 6px; user-select:none}
.rowbtn:hover{color:var(--err)}

/* ─────────────────── cards ─────────────────── */
.card{
  background:var(--bg3); border:1px solid var(--line); border-radius:7px;
  padding:9px 11px; margin-bottom:8px;
}
.card.bad{border-color:rgba(255,107,107,.5)}
.card.warnb{border-color:rgba(255,182,72,.45)}
.card h3{margin:0 0 7px; font-size:12.5px; display:flex; align-items:center; gap:7px}
.card h3 .tag{
  font-size:9.5px; font-weight:700; padding:2px 6px; border-radius:3px;
  background:var(--bg4); color:var(--fg2); letter-spacing:.4px;
}
.card h3 .tag.L{background:rgba(255,193,77,.18); color:var(--spiral)}
.card h3 .tag.R{background:rgba(122,180,255,.18); color:var(--accent)}
.kv{display:grid; grid-template-columns:auto 1fr auto 1fr; gap:2px 10px; font-size:11px}
.kv dt{color:var(--fg3); white-space:nowrap}
.kv dd{margin:0; font-family:var(--mono); text-align:right; color:var(--fg)}
.kv dd.warnv{color:var(--warn)}
.kv dd.errv{color:var(--err)}
.kv dd.okv{color:var(--ok)}
.card .note{margin:7px 0 0; font-size:10.5px; color:var(--fg3); border-top:1px solid var(--line); padding-top:6px}

/* ─────────────────── checks ─────────────────── */
.summary{display:flex; gap:8px; margin-bottom:10px}
.pill{
  flex:1; text-align:center; padding:8px 4px; border-radius:6px;
  background:var(--bg3); border:1px solid var(--line);
}
.pill b{display:block; font-size:19px; line-height:1.15; font-family:var(--mono)}
.pill span{font-size:10px; color:var(--fg3); text-transform:uppercase; letter-spacing:.5px}
.pill.e b{color:var(--err)} .pill.w b{color:var(--warn)}
.pill.i b{color:var(--info)} .pill.ok b{color:var(--ok)}

.issue{
  display:flex; gap:9px; padding:8px 10px; border-radius:6px; margin-bottom:6px;
  background:var(--bg3); border-left:3px solid var(--line2); cursor:pointer;
}
.issue:hover{background:var(--bg4)}
.issue.error{border-left-color:var(--err)}
.issue.warn{border-left-color:var(--warn)}
.issue.info{border-left-color:var(--info)}
.issue .ico{font-size:12px; line-height:1.3; flex:0 0 auto}
.issue.error .ico{color:var(--err)} .issue.warn .ico{color:var(--warn)} .issue.info .ico{color:var(--info)}
.issue .body{flex:1; min-width:0}
.issue .msg{font-size:11.5px; line-height:1.45}
.issue .meta{font-size:10px; color:var(--fg3); margin-top:3px; font-family:var(--mono)}
.empty{text-align:center; color:var(--fg3); padding:26px 10px; font-size:12px}
.empty .big{font-size:26px; display:block; margin-bottom:6px; color:var(--ok)}

/* ─────────────────── views ─────────────────── */
.views{flex:1; display:flex; flex-direction:column; min-width:0; min-height:0; background:var(--bg); position:relative}
.view{display:flex; flex-direction:column; min-height:0; position:relative; overflow:hidden}
#planWrap{flex:1 1 auto}
#profWrap{flex:0 0 210px}
#cantWrap{flex:0 0 150px}

/* ---- folding a drawing view away ----
 * The profile and the cant chart are reference, not workspace: much of the
 * time the plan is what is being worked on and the other two are two hundred
 * pixels of screen it cannot have. Folded, a view keeps its title bar — so it
 * is still named, and still one click from coming back — and gives every
 * other pixel to the plan. The height it had is remembered on the element, so
 * unfolding returns to the size that was dragged, not to the default. */
.views .view.folded{flex:0 0 auto !important}
.view.folded canvas,
.view.folded .legend,
.view.folded select,
.view.folded .chk{display:none}
/* The sprite's sizing lives on .btn.icon, and this is a .mini — so it states
   the same three things for itself rather than borrowing a button class that
   would also bring the padding and the 30px box. */
.view-fold{
  margin-left:8px; flex:0 0 auto; padding:0; width:22px; height:20px;
  display:inline-flex; align-items:center; justify-content:center;
}
.view-fold svg{
  width:14px; height:14px; display:block; pointer-events:none;
  fill:none; stroke:currentColor; stroke-width:1.6;
  stroke-linecap:round; stroke-linejoin:round;
  transition:transform .18s ease;
}
.view.folded .view-fold svg{transform:rotate(180deg)}
.view.folded .view-title{color:var(--fg3)}
/* A splitter cannot resize a pane that has no height to give. */
.splitter.idle{pointer-events:none; opacity:.25}
.view-head{
  display:flex; align-items:center; gap:14px; padding:0 11px; height:27px; flex:0 0 27px;
  background:var(--bg2); border-bottom:1px solid var(--line);
}
.view-title{font-size:11px; font-weight:600; color:var(--fg2); text-transform:uppercase; letter-spacing:.7px}
/* Vertical exaggeration is a property of the view, not of the ground data, so
   it sits with the view's other controls rather than under the VIP table. */
.vex{display:flex; align-items:center; gap:4px; color:var(--fg3); font-size:11px; white-space:nowrap}
.vex input{width:46px; padding:1px 4px; font-size:11px; text-align:right}
.view.folded .vex{display:none}

/* The chainage and georeference controls, while the Considerations panel is
   holding them. They were written for a 392 px side panel, so they are given
   room to breathe here rather than restyled. */
.dc-setup-card #projSetup{display:block}
.dc-setup-card .pane-head{margin-top:12px !important}
.dc-setup-card .pane-head:first-child{margin-top:0 !important}
.dc-setup-card .hint{margin:4px 0 8px}
.view-tools{display:flex; align-items:center; gap:11px; margin-left:auto; min-width:0}
.view-tools select{font-size:11px; padding:2px 5px}
/* The head is one fixed row. On a laptop the plan's dozen toggles no longer
   fit it, and letting them wrap broke each label across two lines and pushed
   the colour selector off the edge; they scroll sideways instead, whole and
   in order, and the row tightens up first so most widths never need to. */
.view-tools .chk, .view-tools .legend, .view-tools .vex{white-space:nowrap; flex-shrink:0}
.view-tools select, .view-tools .mini{flex-shrink:0}
.view-tools{overflow-x:auto; overflow-y:hidden; scrollbar-width:none}
.view-tools::-webkit-scrollbar{display:none}
@media (max-width:1440px){
  .view-tools{gap:8px}
  .view-tools .chk{font-size:10.5px}
}
.legend{display:flex; align-items:center; gap:4px; font-size:10.5px; color:var(--fg3)}
.sw{width:11px; height:3px; border-radius:2px; display:inline-block}
.sw.rail{background:var(--rail)} .sw.ground{background:var(--ground)}
.sw.cut{background:var(--cut)} .sw.fill{background:var(--fill)}
.sw.curv{background:var(--curv)} .sw.cant{background:var(--cantc)} .sw.cdef{background:var(--cdef)}

.splitter{
  height:5px; flex:0 0 5px; background:var(--bg2); border-top:1px solid var(--line);
  border-bottom:1px solid var(--line); cursor:row-resize;
}
.splitter:hover{background:var(--accent2)}

/* Basemap controls in the plan view head. */
.view-tools .slider{
  -webkit-appearance:none; appearance:none; width:70px; height:3px; border-radius:2px;
  background:var(--line2); border:none; padding:0; cursor:pointer;
}
.view-tools .slider::-webkit-slider-thumb{
  -webkit-appearance:none; width:11px; height:11px; border-radius:50%;
  background:var(--fg2); cursor:pointer;
}
.view-tools .slider::-moz-range-thumb{
  width:11px; height:11px; border:none; border-radius:50%; background:var(--fg2); cursor:pointer;
}
.view-tools .slider:disabled{opacity:.35; cursor:default}
.mini.icon{padding:2px 7px; font-size:13px; line-height:1.1}

/* ─────────────────── Google Maps style floating Map Type switcher ─────────────────── */
/* ---- the compliance orb ----
 *
 * Compliance used to be the fourth tab of nine. That put a running verdict on
 * the whole design behind a click, and hid it the moment the work moved to
 * another tab — which is most of the time, because the work is drawing, and
 * the verdict is about what is being drawn. So it leaves the rail and sits on
 * the drawing instead: a count that is always on screen, and a panel that
 * opens over the plan it is about.
 *
 * It sits at the workspace's bottom-right corner rather than the plan view's,
 * because the panel is a list to be read and the plan view is only as tall as
 * the profile and cant charts leave it. The map type switcher had that corner;
 * it moves one orb's width to the left, so the two sit side by side and can
 * never overlap however the views are folded. */
/* The wrap spans from the top of the view down to just above the map type
 * switcher, so that it has a definite height for the panel to be bounded
 * against — a percentage height against an auto-height parent is ignored, and
 * the panel grew to the length of its list. It is laid out from the bottom, so
 * the orb stays in the corner and the panel opens upward from it. Being a full
 * height strip it would otherwise swallow every press meant for the drawing
 * underneath, so the strip itself is transparent to the mouse and only its two
 * children are not. */
.check-orb-wrap{
  position:absolute; top:16px; bottom:16px; right:16px; z-index:26;
  display:flex; flex-direction:column; align-items:flex-end; justify-content:flex-end;
  gap:10px; pointer-events:none;
}
.check-orb-wrap > *{pointer-events:auto}
.check-orb{
  width:46px; height:46px; border-radius:50%; flex:0 0 auto;
  display:flex; align-items:center; justify-content:center; position:relative;
  background:var(--bg2); color:var(--fg2);
  border:1px solid var(--line2); cursor:pointer; padding:0;
  box-shadow:0 4px 14px rgba(0,0,0,.45);
  transition:transform .14s ease, border-color .14s ease, background .14s ease;
}
.check-orb:hover{transform:translateY(-2px); background:var(--bg3); color:var(--fg)}
.check-orb:active{transform:translateY(0)}
.check-orb.open{border-color:var(--accent); color:var(--accent)}
.check-orb-i{
  width:20px; height:20px; display:block; pointer-events:none;
  fill:none; stroke:currentColor; stroke-width:1.4; stroke-linecap:round; stroke-linejoin:round;
}
/* The count. Absent when the design is clean, so a quiet orb says "nothing to
   report" by carrying no number at all rather than by carrying a zero. */
/* Centred by flex, not by line-height. The box is border-box with a 2 px ring,
   so a 19 px line inside a 19 px box sat four pixels low — which is what put
   the number off centre. */
.check-orb-n{
  display:none; position:absolute; top:-3px; right:-3px; min-width:19px; height:19px;
  padding:0 5px; border-radius:10px; box-sizing:border-box;
  font:700 11px var(--mono); line-height:1;
  align-items:center; justify-content:center;
  background:var(--err); color:#fff; border:2px solid var(--bg);
}
.check-orb-n.on{display:flex}
.check-orb-n.warn{background:var(--warn); color:#2a1d00}
/* Clean: the ring goes green and stays quiet. */
.check-orb.clean{border-color:var(--ok); color:var(--ok)}

/* An error that has just appeared is worth one pulse and no more: a badge that
   throbs forever becomes furniture, and furniture is not read. */
.check-orb.alert{animation:orb-pulse .55s ease-out 2}
@keyframes orb-pulse{
  0%{box-shadow:0 4px 14px rgba(0,0,0,.45), 0 0 0 0 rgba(255,107,107,.55)}
  100%{box-shadow:0 4px 14px rgba(0,0,0,.45), 0 0 0 14px rgba(255,107,107,0)}
}
@media (prefers-reduced-motion:reduce){
  .check-orb{transition:none}
  .check-orb:hover{transform:none}
  .check-orb.alert{animation:none}
}

.orb-panel{
  width:min(392px, calc(100vw - 48px));
  max-height:min(540px, 100%);
  display:flex; flex-direction:column; flex:0 1 auto; min-height:0;
  background:var(--bg2); border:1px solid var(--line2); border-radius:10px;
  box-shadow:0 12px 40px rgba(0,0,0,.55);
  overflow:hidden;
}
.orb-panel[hidden]{display:none}
.orb-panel-head{
  display:flex; align-items:center; justify-content:space-between; gap:10px;
  padding:9px 11px; flex:0 0 auto;
  background:var(--bg3); border-bottom:1px solid var(--line);
}
.orb-panel-head h2{
  margin:0; font-size:12px; font-weight:600; color:var(--fg2);
  text-transform:uppercase; letter-spacing:.6px;
}
.orb-panel-x{
  background:none; border:0; color:var(--fg3); cursor:pointer;
  font-size:17px; line-height:1; padding:0 2px;
}
.orb-panel-x:hover{color:var(--fg)}
/* The body scrolls, so a project with two hundred findings opens a panel the
   size of the view rather than one the size of its list. */
.orb-panel-body{padding:12px; overflow-y:auto; flex:1 1 auto; min-height:0}

.map-layers-widget {
  position: absolute;
  bottom: 16px;
  /* Clear of the compliance orb, which holds the corner itself. */
  right: 76px;
  z-index: 25;
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 8px;
  user-select: none;
}

.map-layers-btn {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 5px 12px 5px 6px;
  background: rgba(18, 22, 28, 0.94);
  border: 1px solid rgba(255, 255, 255, 0.16);
  border-radius: 8px;
  box-shadow: 0 4px 18px rgba(0, 0, 0, 0.5);
  cursor: pointer;
  backdrop-filter: blur(10px);
  transition: all 0.2s ease;
  color: var(--fg);
}

.map-layers-btn:hover {
  background: rgba(28, 35, 46, 0.98);
  border-color: var(--accent);
  box-shadow: 0 6px 22px rgba(0, 0, 0, 0.65);
  transform: translateY(-1px);
}

.map-btn-thumb {
  width: 28px;
  height: 28px;
  border-radius: 6px;
  overflow: hidden;
  display: flex;
  align-items: center;
  justify-content: center;
  background: #0f172a;
}

.map-btn-label {
  font-size: 11.5px;
  font-weight: 600;
  letter-spacing: 0.3px;
  color: #f1f5f9;
}

/* Expanded Tray */
.map-layers-tray {
  background: rgba(18, 22, 28, 0.96);
  border: 1px solid rgba(255, 255, 255, 0.18);
  border-radius: 12px;
  padding: 12px 14px;
  box-shadow: 0 10px 36px rgba(0, 0, 0, 0.65);
  backdrop-filter: blur(14px);
  min-width: 320px;
  animation: trayFadeIn 0.18s ease-out;
}

@keyframes trayFadeIn {
  from { opacity: 0; transform: translateY(8px) scale(0.97); }
  to { opacity: 1; transform: translateY(0) scale(1); }
}

.map-layers-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 10px;
  font-size: 11px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.6px;
  color: var(--fg2);
}

.map-layers-close {
  background: transparent;
  border: none;
  color: var(--fg3);
  font-size: 18px;
  cursor: pointer;
  padding: 0 4px;
  line-height: 1;
  border-radius: 4px;
}
.map-layers-close:hover { color: #fff; background: rgba(255, 255, 255, 0.1); }

.map-layers-grid {
  display: grid;
  grid-template-columns: repeat(5, 1fr);
  gap: 8px;
}

.map-layer-card {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 6px;
  background: rgba(255, 255, 255, 0.04);
  border: 2px solid transparent;
  border-radius: 8px;
  padding: 6px 4px 5px;
  cursor: pointer;
  transition: all 0.15s ease;
  color: var(--fg2);
}

.map-layer-card:hover {
  background: rgba(255, 255, 255, 0.09);
  border-color: rgba(255, 255, 255, 0.35);
  transform: translateY(-2px);
}

.map-layer-card.active {
  background: rgba(56, 189, 248, 0.15);
  border-color: #38bdf8;
  color: #fff;
}

.map-card-thumb {
  width: 44px;
  height: 44px;
  border-radius: 6px;
  overflow: hidden;
  display: flex;
  align-items: center;
  justify-content: center;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.4);
}

.map-card-label {
  font-size: 10px;
  font-weight: 600;
  text-align: center;
  white-space: nowrap;
}

.map-layers-opacity {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-top: 12px;
  padding-top: 10px;
  border-top: 1px solid rgba(255, 255, 255, 0.1);
}

.map-layers-opacity .opacity-label {
  font-size: 10.5px;
  color: var(--fg3);
}

.map-layers-opacity .slider {
  flex: 1;
}

.map-layers-opacity .opacity-val {
  font-size: 10.5px;
  font-family: var(--mono);
  color: var(--fg2);
  min-width: 32px;
  text-align: right;
}

/* ── full-screen plan ──
   A CSS overlay rather than only the Fullscreen API, so the plan still fills
   the window where that API is unavailable (an embedded frame, say). When the
   API does work the two simply compose. */
body.plan-full #planWrap{
  position:fixed; inset:0; z-index:60; flex:1 1 auto;
  background:var(--bg); border:none;
}
body.plan-full #split1,body.plan-full #split2,
body.plan-full #profWrap,body.plan-full #cantWrap,
body.plan-full .side,body.plan-full .toolbar,body.plan-full .status{display:none}
body.plan-full #btnFull{background:var(--accent2); border-color:var(--accent); color:#fff}
#planWrap:fullscreen{background:var(--bg)}

/* ─────────────────── status ─────────────────── */
.status{
  display:flex; align-items:center; gap:18px; padding:0 12px; height:24px; flex:0 0 24px;
  background:var(--bg2); border-top:1px solid var(--line);
  font-family:var(--mono); font-size:10.5px; color:var(--fg3);
}
.status b{color:var(--fg2); font-weight:500}

/* ─────────────────── toast ─────────────────── */
.toast{
  position:fixed; bottom:38px; left:50%; transform:translateX(-50%) translateY(14px);
  background:var(--bg4); border:1px solid var(--line2); color:var(--fg);
  padding:9px 16px; border-radius:7px; font-size:12px; opacity:0; pointer-events:none;
  transition:opacity .18s, transform .18s; box-shadow:0 8px 26px rgba(0,0,0,.5); z-index:200;
  max-width:60vw;
}
.toast.show{opacity:1; transform:translateX(-50%) translateY(0)}
.toast.err{border-color:var(--err); color:#ffd7d7}


@media (max-width:1180px){
  .side{--side-w:330px}
  /* Shed the decoration, not the controls. This rule used to hide .tb-group
   * outright, which put the standard selector and both design speeds out of
   * reach altogether — they appear nowhere else in the interface. */
  .brand img{height:28px}
  #stdSel{max-width:170px}
}

/* The setting-out preview carries a lot of columns in a narrow panel. */
table.grid.compact td{font-size:10px; padding:3px 5px}
table.grid.compact th{font-size:9.5px; padding:5px 5px}

/* ═════════════════ new-route wizard, fixes, structures ═════════════════ */

.brand{text-decoration:none;color:inherit}
.samples{max-width:180px}

/* modal */
.modal-back{
  position:fixed; inset:0; background:rgba(8,10,13,.72); backdrop-filter:blur(3px);
  display:flex; align-items:center; justify-content:center; z-index:100; padding:22px;
}
.modal{
  background:var(--bg2); border:1px solid var(--line2); border-radius:12px;
  box-shadow:0 24px 70px rgba(0,0,0,.6); display:flex; flex-direction:column;
  max-height:92vh; overflow:hidden;
}
.modal.wizard{width:min(1120px,96vw); height:min(700px,92vh)}
.modal-head{
  display:flex; align-items:center; justify-content:space-between;
  padding:13px 17px; border-bottom:1px solid var(--line); flex:0 0 auto;
}
.modal-head h2{margin:0; font-size:14px; font-weight:600}
.modal-x{
  background:none; border:none; color:var(--fg3); font-size:22px; line-height:1;
  cursor:pointer; padding:0 4px;
}
.modal-x:hover{color:var(--fg)}

.wiz-body{display:flex; flex:1; min-height:0}
.wiz-map{flex:1; position:relative; min-width:0; background:var(--bg3)}
.wiz-map canvas{width:100%; height:100%; display:block; cursor:crosshair}

/* Map chrome. The layer switcher, the zoom controls and the hint each own a
 * corner of their own: they used to share the top left, where the hint sat
 * straight over the buttons and neither could be read. */
.wiz-layers{
  position:absolute; top:8px; left:8px; display:flex; flex-wrap:wrap; gap:4px;
  max-width:calc(100% - 68px); z-index:2;
}
.wiz-layer{
  background:rgba(18,21,26,.82); border:1px solid var(--line2); color:var(--fg2);
  border-radius:4px; padding:3px 8px; cursor:pointer; font:inherit; font-size:10.5px;
}
.wiz-layer:hover{color:var(--fg); border-color:var(--accent2)}
.wiz-layer.on{background:var(--accent2); border-color:var(--accent); color:#fff}

.wiz-tools{
  position:absolute; top:8px; right:8px; z-index:2;
  display:flex; flex-direction:column; align-items:stretch; gap:4px;
}
.wiz-tools button{
  background:rgba(18,21,26,.86); border:1px solid var(--line2); color:var(--fg2);
  border-radius:4px; width:26px; height:24px; cursor:pointer; font:inherit; font-size:13px;
  line-height:1; padding:0;
}
.wiz-tools button:hover{color:var(--fg); border-color:var(--accent2)}
.wiz-z{
  text-align:center; font:9.5px var(--mono); color:var(--fg3);
  background:rgba(18,21,26,.86); border-radius:3px; padding:2px 0;
}

.wiz-hint{
  position:absolute; left:10px; bottom:10px; background:rgba(18,21,26,.9);
  border:1px solid var(--line2); border-radius:7px; padding:7px 11px;
  font-size:11.5px; color:var(--fg2); max-width:calc(100% - 210px); line-height:1.45;
  pointer-events:none;
}
.wiz-hint b{color:var(--accent)}

/* Side panel */
.wiz-side{
  width:344px; flex:0 0 344px; border-left:1px solid var(--line);
  padding:14px; overflow-y:auto; display:flex; flex-direction:column; gap:2px;
}
.wiz-lab{display:block; font-size:10.5px; color:var(--fg3); text-transform:uppercase;
  letter-spacing:.6px; margin:10px 0 5px}
.wiz-head{display:flex; align-items:baseline; justify-content:space-between; gap:8px}
.wiz-head .wiz-lab{margin-bottom:4px}
.wiz-val{font:11.5px var(--mono); color:var(--fg)}
.link{
  background:none; border:none; color:var(--fg3); font:inherit; font-size:11px;
  cursor:pointer; padding:0;
}
.link:hover{color:var(--accent)}

/* Route points. Each row is a coordinate, a name or a station code — whichever
 * the user has to hand — so the box takes all three and the line under it says
 * where the pin ended up. */
.wiz-pts{display:flex; flex-direction:column; gap:7px; margin-bottom:8px}
.wiz-pt{display:flex; align-items:flex-start; gap:7px}
.wiz-pt .dot{width:9px; height:9px; border-radius:50%; flex:0 0 auto; margin-top:8px}
.wiz-pt-k{font-size:11px; color:var(--fg2); width:11px; font-weight:600; margin-top:6px; flex:0 0 auto}
.wiz-pt-in{position:relative; flex:1; min-width:0}
.wiz-pt-in input{width:100%; font-size:11.5px}
.wiz-pt-sub{
  font:10px var(--mono); color:var(--fg3); padding:2px 2px 0; min-height:12px;
  overflow:hidden; text-overflow:ellipsis; white-space:nowrap;
}
.wiz-pt-b{
  background:var(--bg3); border:1px solid var(--line); color:var(--fg3);
  border-radius:4px; width:22px; height:26px; flex:0 0 auto; cursor:pointer;
  font:inherit; font-size:12px; line-height:1; padding:0;
}
.wiz-pt-b:hover{color:var(--fg); border-color:var(--accent2)}
.wiz-pt-b.on{background:var(--accent2); border-color:var(--accent); color:#fff}
.wiz-pt-b.x:hover{color:var(--err); border-color:var(--err)}

.wiz-drop{
  position:absolute; left:0; right:0; top:calc(100% + 2px); z-index:5;
  background:var(--bg2); border:1px solid var(--line2); border-radius:6px;
  box-shadow:0 12px 30px rgba(0,0,0,.55); max-height:224px; overflow-y:auto;
}
.wiz-drop:empty{display:none}
.wiz-res{padding:6px 9px; cursor:pointer; border-bottom:1px solid var(--line)}
.wiz-res:last-child{border-bottom:none}
.wiz-res:hover{background:var(--bg3)}
.wiz-res-h{display:flex; align-items:baseline; gap:6px; font-size:11.5px; color:var(--fg)}
.wiz-res-h b{font-weight:600; overflow:hidden; text-overflow:ellipsis; white-space:nowrap}
.wiz-code{
  font:9.5px var(--mono); color:var(--accent); background:var(--bg3);
  border:1px solid var(--line2); border-radius:3px; padding:0 4px; flex:0 0 auto;
}
.wiz-kind{font-size:9.5px; color:var(--fg3); text-transform:uppercase; letter-spacing:.5px;
  margin-left:auto; flex:0 0 auto}
.wiz-kind.st{color:var(--ok)}
.wiz-res-d{font-size:10.5px; color:var(--fg3); margin-top:2px; line-height:1.35}
.wiz-note{padding:7px 9px; font-size:11px; color:var(--fg3)}
.wiz-note-sm{font-size:10.5px; color:var(--fg3); line-height:1.45; margin:6px 0 2px}

.mini.wide{width:100%; text-align:center}
.mini:disabled{opacity:.4; cursor:default}
.wiz-side .btn.wide{text-align:center; margin-top:12px}

.wiz-dist{margin-top:9px; font-size:12px; color:var(--fg2); font-family:var(--mono)}
.wiz-dist b{color:var(--fg); font-size:14px}

/* A slider for "about this fast" and a box for the figure off a drawing. */
.wiz-slide{display:flex; align-items:center; gap:9px}
.wiz-slide input[type=number]{width:58px; flex:0 0 auto; font-family:var(--mono); font-size:11.5px}
.wiz-slide input[type=range]{
  -webkit-appearance:none; appearance:none; background:transparent;
  flex:1; min-width:0; height:18px; margin:0; cursor:pointer;
}
.wiz-slide input[type=range]::-webkit-slider-runnable-track{
  height:4px; border-radius:2px; background:var(--bg4); border:1px solid var(--line);
}
.wiz-slide input[type=range]::-webkit-slider-thumb{
  -webkit-appearance:none; width:14px; height:14px; border-radius:50%;
  background:var(--accent); border:2px solid var(--bg2); margin-top:-6px;
}
.wiz-slide input[type=range]::-moz-range-track{
  height:4px; border-radius:2px; background:var(--bg4); border:1px solid var(--line);
}
.wiz-slide input[type=range]::-moz-range-thumb{
  width:12px; height:12px; border-radius:50%; background:var(--accent);
  border:2px solid var(--bg2);
}
.wiz-slide input[type=range]:focus{outline:none}
.wiz-slide input[type=range]:focus::-webkit-slider-thumb{box-shadow:0 0 0 3px rgba(74,168,255,.25)}
.wiz-slide input[type=range]:focus::-moz-range-thumb{box-shadow:0 0 0 3px rgba(74,168,255,.25)}

/* Segmented control — a handful of mutually exclusive choices small enough to
   show all of them at once, which a list cannot do without being opened. The
   icons are the thing being chosen: a coarser grid is literally fewer, larger
   cells. */
.seg{display:flex; gap:6px; margin-top:2px}
.seg-btn{
  flex:1; min-width:0; display:flex; flex-direction:column; align-items:center; gap:5px;
  padding:9px 4px 7px; cursor:pointer; font:inherit; color:var(--fg2);
  background:var(--bg3); border:1px solid var(--line2); border-radius:7px;
}
.seg-btn svg{width:20px; height:20px; fill:currentColor; opacity:.75; pointer-events:none}
.seg-btn span{font-size:10.5px; letter-spacing:.2px; pointer-events:none}
.seg-btn:hover{color:var(--fg); border-color:var(--accent2)}
.seg-btn.on{background:var(--accent2); border-color:var(--accent); color:#fff}
.seg-btn.on svg{opacity:1}

/* The suggested setting: marked, never pressed.
   A dashed ring says "this is what I would pick" without taking the decision
   away, and it survives being the selected one too — the two states have to be
   distinguishable, because "suggested and chosen" and "suggested but not
   chosen" are different things to look at. The dot is for anyone who cannot
   pick the ring out of the border. */
.seg-btn.sug{outline:1.5px dashed var(--accent); outline-offset:2px}
.seg-btn.sug::after{
  content:''; position:absolute; margin:-4px 0 0 26px;
  width:5px; height:5px; border-radius:50%; background:var(--accent);
}
.seg-btn{position:relative}
.seg-btn.on.sug::after{background:#fff}

/* The cost note under the buttons. Plain while the choice is the suggested
   one, tinted when it is not — in either direction, because choosing less
   detail than the corridor can carry is as much worth knowing as choosing
   more than it can. */
.wiz-note-sm.sug{color:var(--fg2)}
.wiz-note-sm.warn{color:var(--warn, #b8860b)}

#wizDivOther{margin-top:6px}

.wiz-warn{font-size:11px; color:var(--warn); margin:9px 0 0; line-height:1.5; display:none}
.wiz-warn.on{display:block}
.wiz-prog{margin-top:10px; font-size:11.5px; min-height:20px}
.wiz-step{color:var(--fg2); line-height:1.5}
.wiz-step b{color:var(--accent); font-family:var(--mono)}
.wiz-step.err{color:var(--err)}
.wiz-step.warn{color:var(--warn)}
.wiz-sub{color:var(--fg3); font-size:10.5px}

/* Below this the two halves stop fitting side by side. */
@media (max-width:820px){
  .wiz-body{flex-direction:column}
  .wiz-map{flex:0 0 46%; min-height:220px}
  .wiz-side{width:auto; flex:1 1 auto; border-left:none; border-top:1px solid var(--line)}
  .wiz-hint{max-width:calc(100% - 20px); bottom:6px}
}

/* repair affordances */
.issue .mini{align-self:flex-start; flex:0 0 auto}
.issue .mini.fix{border-color:var(--accent2); color:var(--accent)}
.issue .mini.fix:hover{background:var(--accent2); color:#fff}
.issue.banner{background:rgba(255,182,72,.08)}
.suggest{
  margin-top:7px; padding:7px 9px; background:var(--bg2); border-radius:5px;
  font-size:11px; color:var(--fg2); line-height:1.55; border-left:2px solid var(--warn);
}
.fixlog{
  background:var(--bg3); border:1px solid var(--line); border-radius:7px;
  padding:9px 11px; margin-bottom:9px;
}
.fixlog-head{display:flex; align-items:center; justify-content:space-between; margin-bottom:6px}
.fixlog-head b{font-size:11px; color:var(--ok)}
.fixlog-row{
  font-size:11px; color:var(--fg2); line-height:1.5; padding:3px 0 3px 12px;
  position:relative;
}
.fixlog-row:before{content:'✓'; position:absolute; left:0; color:var(--ok); font-size:9px; top:5px}
.fixlog-row.stalled{color:var(--fg3)}
.fixlog-row.stalled:before{content:'–'; color:var(--fg3)}

/* ── compliance report ── */
.check-controls{gap:6px}
.check-controls input[type=search]{
  flex:1; min-width:0; background:var(--bg3); border:1px solid var(--line);
  color:var(--fg); border-radius:5px; padding:4px 7px; font:inherit; font-size:11.5px;
}
.check-controls select{font-size:11px; padding:3px 5px; max-width:132px}
.chk-group{margin-bottom:12px}
.chk-group-head{
  display:flex; align-items:baseline; justify-content:space-between; gap:8px;
  padding:2px 2px 5px; border-bottom:1px solid var(--line); margin-bottom:6px;
}
.chk-group-head b{font-size:10.5px; color:var(--fg2); text-transform:uppercase; letter-spacing:.6px}
.chk-group-head span{font-size:10px; color:var(--fg3); font-family:var(--mono)}
.issue .ttl{font-size:11px; font-weight:600; color:var(--fg2); margin-bottom:2px}
.issue.muted{opacity:.72}
.issue-acts{display:flex; flex-direction:column; gap:4px; flex:0 0 auto}
.issue-acts .mini{width:100%; text-align:center}
.suggest p{margin:0 0 6px}
.suggest ul{margin:0 0 6px; padding-left:16px}
.suggest li{margin:2px 0}
.suggest .clause{color:var(--fg3); font-family:var(--mono); font-size:10px}
.overrides{
  border:1px solid var(--line); border-radius:6px; padding:8px 9px; margin-bottom:10px;
  background:rgba(90,176,255,.06);
}
.overrides-head{display:flex; align-items:center; justify-content:space-between; margin-bottom:6px}
.overrides-head b{font-size:11px; color:var(--info)}
.override-row{display:flex; align-items:center; gap:7px; margin:4px 0}
.override-row .code{font-family:var(--mono); font-size:10px; color:var(--fg3); flex:0 0 96px}
.override-row .ttl{font-size:11px; color:var(--fg2); flex:1; min-width:0;
  overflow:hidden; text-overflow:ellipsis; white-space:nowrap}
.override-row select{font-size:10.5px; padding:2px 4px}

/* structures */
.sbar{display:flex; height:9px; border-radius:5px; overflow:hidden; margin:10px 0 12px;
  background:var(--bg3); border:1px solid var(--line)}
.sbar i{display:block; height:100%}
.card.struct h3{gap:9px}

/* stage rail */
/* ---- the four stages ----
 *
 * Four buttons across a 392 px panel is about ninety pixels each, which holds
 * a number and a word and nothing else. They used to carry the stage's blurb
 * as well, so every one of them ended in an ellipsis — "where t…", "what it
 * ha…" — which is four truncations telling the reader nothing and reading as
 * clutter. The blurb is the button's title now: there in full on hover, absent
 * from the rail. And locked says so with a mark of its own rather than by
 * appending words to a label that has no room for them. */
.stages{display:flex; gap:6px; padding:9px 10px 0; flex:0 0 auto}
.stage{
  flex:1 1 0; min-width:0; cursor:pointer;
  background:var(--bg3); border:1px solid var(--line); border-radius:7px;
  padding:8px 3px; color:var(--fg3); font:inherit; font-size:11px;
  display:flex; align-items:center; justify-content:center; gap:5px;
  transition:border-color .13s ease, background .13s ease, opacity .13s ease;
}
.stage:hover{border-color:var(--line2); color:var(--fg2)}
.stage b{
  flex:0 0 auto; font-size:12px; font-weight:600;
  width:19px; height:19px; border-radius:50%;
  display:inline-flex; align-items:center; justify-content:center;
  background:var(--bg); color:var(--fg3);
}
.stage span{
  color:var(--fg2); font-weight:600; min-width:0;
  overflow:hidden; text-overflow:ellipsis; white-space:nowrap;
}
.stage.active{border-color:var(--accent); background:var(--bg2)}
.stage.active b{background:var(--accent); color:#08131f}
.stage.active span{color:var(--fg)}
/* A locked stage is dimmed, with its number in the warning colour. No padlock
   and no appended word: four buttons across this panel have room for a number
   and a label and nothing else, and anything more truncates the label — which
   is what "Cro…" and "Est…" were. The title says it is locked, and pressing it
   opens the checklist that says exactly what is missing, which is the answer
   anyone reading the padlock actually wanted. */
.stage.locked{opacity:.6}
.stage.locked b{background:var(--bg); color:var(--warn)}

/* stage gate checklist */
.gate-item{
  display:flex; gap:9px; align-items:flex-start; padding:8px 10px; margin-bottom:6px;
  background:var(--bg3); border:1px solid var(--line); border-radius:7px;
}
.gate-item .mark{flex:0 0 auto; width:15px; text-align:center; font-size:12px; line-height:1.5}
.gate-item.ok   .mark{color:var(--ok)}
.gate-item.no   .mark{color:var(--err)}
.gate-item.soft .mark{color:var(--warn)}
.gate-item.soft{border-color:rgba(255,193,77,.3)}
.gate-lab{font-size:12px; color:var(--fg)}
.gate-hint{font-size:10.5px; color:var(--fg3); margin-top:2px; line-height:1.5}

/* geometry is not editable outside stage 1 */
.view.locked canvas{cursor:default}
.view.locked .view-title::after{
  content:'locked'; margin-left:8px; font-size:9.5px; color:var(--warn);
  border:1px solid rgba(255,193,77,.35); border-radius:3px; padding:1px 4px; vertical-align:1px;
}

/* project library */
.modal.library{width:min(560px,94vw)}
.lib-body{padding:15px 17px 17px; overflow-y:auto; display:flex; flex-direction:column; gap:11px}
.lib-note{margin:0; font-size:11.5px; color:var(--fg3); line-height:1.6}
.lib-err{
  font-size:11.5px; color:var(--err); background:rgba(255,90,90,.09);
  border:1px solid rgba(255,90,90,.28); border-radius:6px; padding:8px 10px; line-height:1.5;
}
.lib-msg{
  font-size:11.5px; color:var(--ok); background:rgba(90,220,160,.08);
  border:1px solid rgba(90,220,160,.25); border-radius:6px; padding:8px 10px; line-height:1.5;
}
.lib-signin{display:flex; gap:7px}
.lib-signin input{flex:1; min-width:0}
.lib-head{
  display:flex; align-items:center; justify-content:space-between; gap:10px;
  padding-bottom:10px; border-bottom:1px solid var(--line);
}
.lib-who{flex:1; min-width:0; font-size:11.5px; color:var(--fg2); font-family:var(--mono);
  overflow:hidden; text-overflow:ellipsis; white-space:nowrap}
.lib-save{display:flex; gap:7px; align-items:center}
.lib-save .btn{flex:1; min-width:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap}
.lib-list{display:flex; flex-direction:column; gap:6px; max-height:46vh; overflow-y:auto}
.lib-item{
  display:flex; align-items:center; gap:10px; padding:9px 11px;
  background:var(--bg3); border:1px solid var(--line); border-radius:7px;
}
.lib-item.current{border-color:var(--accent)}
.lib-main{flex:1; min-width:0}
.lib-name{font-size:12.5px; color:var(--fg); overflow:hidden; text-overflow:ellipsis; white-space:nowrap}
.lib-meta{font-size:10.5px; color:var(--fg3); font-family:var(--mono); margin-top:3px;
  overflow:hidden; text-overflow:ellipsis; white-space:nowrap}
.lib-acts{display:flex; gap:5px; flex:0 0 auto}
.mini.danger:hover{color:var(--err); border-color:var(--err)}

/* crossing schedule */
.x-item{
  padding:8px 10px; margin-bottom:6px; background:var(--bg3);
  border:1px solid var(--line); border-left:3px solid var(--line2); border-radius:7px;
  cursor:pointer; transition:border-color .15s ease, background .15s ease;
}
.x-item:hover{background:var(--bg4); border-color:var(--line2)}
.x-item.selected{border-color:var(--accent); background:rgba(74,168,255,.08)}
.x-item.set{border-left-color:var(--accent)}
.x-item.unfit{border-left-color:var(--err)}
.x-head{display:flex; gap:9px; align-items:baseline}
.x-ch{font-family:var(--mono); font-size:11px; color:var(--fg3); flex:0 0 auto}
.x-name{font-size:12.5px; color:var(--fg); overflow:hidden; text-overflow:ellipsis; white-space:nowrap}
.x-meta{font-family:var(--mono); font-size:10px; color:var(--fg3); margin-top:3px}
.x-pick{margin-top:6px}
.x-pick select{width:100%; font-size:11.5px}
.x-why{font-size:10.5px; color:var(--fg3); margin-top:5px; line-height:1.5}
.x-item.unfit .x-why{color:var(--err)}
.x-size{font-size:10.5px; color:var(--fg2); margin-top:5px; line-height:1.5;
  padding:5px 7px; background:var(--bg); border-radius:5px}
.x-size.warn{color:var(--warn)}

/* Interactive Map Popup for Crossings & Structures */
.view#planWrap{position:relative}
.x-map-popup{
  position:absolute; z-index:40;
  background:var(--bg2); border:1px solid var(--line2);
  border-radius:9px; box-shadow:0 8px 24px rgba(0,0,0,.6);
  padding:12px 14px; width:300px; max-width:calc(100% - 24px);
  color:var(--fg); font-size:12px; pointer-events:auto;
}
.x-map-popup .pop-head{display:flex; align-items:center; justify-content:space-between; margin-bottom:6px; gap:8px}
.x-map-popup .pop-title{font-weight:600; font-size:13px; color:var(--fg); overflow:hidden; text-overflow:ellipsis; white-space:nowrap}
.x-map-popup .pop-close{background:none; border:none; color:var(--fg3); font-size:17px; cursor:pointer; padding:0 4px; line-height:1}
.x-map-popup .pop-close:hover{color:var(--fg)}
.x-map-popup .pop-meta{font-family:var(--mono); font-size:10.5px; color:var(--fg3); margin-bottom:6px}
.x-map-popup .pop-badge{display:inline-block; font-size:10px; font-weight:700; padding:2px 6px; border-radius:4px; margin-bottom:6px; text-transform:uppercase}
.x-map-popup .pop-badge.ok{background:rgba(94,214,154,.2); color:var(--ok)}
.x-map-popup .pop-badge.err{background:rgba(255,107,107,.2); color:var(--err)}
.x-map-popup .pop-badge.div{background:rgba(142,154,168,.2); color:#8e9aa8}
.x-map-popup .pop-desc{font-size:11px; color:var(--fg2); line-height:1.45; margin-bottom:8px}
.x-map-popup .pop-acts{display:flex; gap:6px; align-items:center; margin-top:8px; border-top:1px solid var(--line); padding-top:8px}
.x-map-popup select{flex:1; font-size:11px; padding:3px 5px}
.x-map-popup .btn-del{
  background:rgba(255,107,107,.12); border:1px solid rgba(255,107,107,.35);
  color:var(--err); border-radius:4px; padding:4px 8px; font-size:10.5px;
  cursor:pointer; white-space:nowrap;
}
.x-map-popup .btn-del:hover{background:var(--err); color:#fff}

/* ═════════════════════════ account and profile ═════════════════════════ */

/* The avatar appears in the toolbar, the library header and the profile
   panel, all from one function, so it is sized by its caller and styled once
   here. Initials sit underneath the picture and show through whenever there
   is none, or while one is loading, so the frame is never empty. */
.avatar{
  position:relative; display:inline-flex; align-items:center; justify-content:center;
  border-radius:50%; overflow:hidden; flex:0 0 auto;
  background:var(--accent2); color:#fff; font-weight:600; letter-spacing:.3px;
  line-height:1; user-select:none;
}
.avatar img{
  position:absolute; inset:0; width:100%; height:100%;
  object-fit:cover; display:block; z-index:1;
}
.avatar.big{box-shadow:0 3px 14px rgba(0,0,0,.35)}

/* The toolbar button shrinks to the picture once there is a session. */
.account-btn.has-avatar{padding:3px; border-radius:50%; line-height:0}
.account-btn.has-avatar:hover{border-color:var(--accent)}

.acc-missing{
  display:flex; flex-direction:column; gap:5px; margin:4px 0 12px;
  padding:11px 13px; border:1px solid var(--line2); border-left:3px solid var(--warn);
  border-radius:7px; background:var(--bg3); font-size:11.5px; line-height:1.55;
  color:var(--fg2);
}
.acc-missing strong{color:var(--fg); font-size:12.5px; font-weight:600}

.modal.choose{width:min(460px,94vw)}
.choose-body{padding:16px; display:flex; flex-direction:column; gap:10px}
.choose-lede{margin:0 0 2px; font-size:12px; color:var(--fg3); line-height:1.5}
/* A gate has nothing behind it worth seeing, and no way round it. */
.modal-back.locked{background:rgba(8,10,13,.9)}
.choose-card{
  display:flex; align-items:center; gap:13px; text-align:left; width:100%;
  background:var(--bg3); border:1px solid var(--line2); border-radius:9px;
  padding:14px 15px; cursor:pointer; color:var(--fg); font:inherit;
}
.choose-card:hover,.choose-card:focus{border-color:var(--accent); background:var(--bg4); outline:none}
.choose-icon{font-size:22px; line-height:1; flex:0 0 auto; filter:grayscale(.2)}
.choose-text{display:flex; flex-direction:column; gap:3px; min-width:0}
.choose-text strong{font-weight:600; font-size:13.5px}
.choose-note{font-size:11.5px; color:var(--fg3); line-height:1.45}

.modal.account{width:min(430px,94vw)}
.acc-body{padding:15px 17px 17px; overflow-y:auto; display:flex; flex-direction:column; gap:11px}
.acc-note{margin:0; font-size:11.5px; color:var(--fg3); line-height:1.6}
.acc-hint{margin:-4px 0 0; font-size:11px; color:var(--fg3)}

.acc-tabs{display:flex; gap:4px; background:var(--bg3); padding:3px; border-radius:7px}
.acc-tab{
  flex:1; background:none; border:none; color:var(--fg3); font:inherit; font-size:12.5px;
  padding:6px 8px; border-radius:5px; cursor:pointer;
}
.acc-tab:hover{color:var(--fg2)}
.acc-tab.on{background:var(--bg4); color:var(--fg)}

.acc-form{display:flex; flex-direction:column; gap:9px}
.acc-field{display:flex; flex-direction:column; gap:4px}
.acc-field span{font-size:11px; color:var(--fg2)}
.acc-field input{width:100%}
.acc-sep{border-top:1px solid var(--line); padding-top:13px; margin-top:2px}

.wide-btn{width:100%; text-align:center}

.acc-alt{display:flex; flex-direction:column; gap:5px; align-items:flex-start}
.acc-link{
  background:none; border:none; padding:0; font:inherit; font-size:11.5px;
  color:var(--fg2); cursor:pointer; text-decoration:underline; text-underline-offset:2px;
}
.acc-link:hover{color:var(--accent)}
.acc-link:disabled{opacity:.5; cursor:default}

.acc-head{display:flex; align-items:center; gap:13px}
.acc-who{min-width:0}
.acc-name{font-size:15px; font-weight:600; overflow:hidden; text-overflow:ellipsis; white-space:nowrap}
.acc-email{font-size:11.5px; color:var(--fg3); font-family:var(--mono);
  overflow:hidden; text-overflow:ellipsis; white-space:nowrap}
.acc-row{display:flex; gap:7px; align-items:center}
.acc-out{display:flex; justify-content:flex-end; border-top:1px solid var(--line); padding-top:12px}

/* ─────────────────── Stage 3: Stations & Yards ─────────────────── */
.stn-summary-pills{display:flex; gap:6px; flex-wrap:wrap; margin:10px 0 14px}
.stn-pill{
  flex:1; min-width:80px; background:var(--bg3); border:1px solid var(--line);
  border-radius:7px; padding:7px 9px; text-align:center;
}
.stn-pill b{display:block; font-size:16px; font-family:var(--mono); color:var(--fg); line-height:1.2}
.stn-pill span{font-size:9.5px; color:var(--fg3); text-transform:uppercase; letter-spacing:.5px}
.stn-pill.ok b{color:var(--ok)}
.stn-pill.warn b{color:var(--warn)}

.stn-card{
  background:var(--bg3); border:1px solid var(--line); border-radius:8px;
  padding:11px 13px; margin-bottom:8px; display:flex; flex-direction:column; gap:7px;
  transition:border-color .15s, background .15s; cursor:pointer;
}
.stn-card:hover{border-color:var(--line2); background:var(--bg4)}
.stn-card.selected{border-color:var(--accent); background:rgba(74,168,255,.08); box-shadow:0 0 0 1px var(--accent)}

.stn-head{display:flex; align-items:center; justify-content:space-between; gap:8px}
.stn-title-wrap{display:flex; align-items:center; gap:8px; min-width:0}
.stn-num{
  font-size:11px; font-family:var(--mono); font-weight:700; color:var(--accent);
  background:var(--bg2); border:1px solid var(--line); border-radius:4px; padding:1px 5px;
}
.stn-name{font-size:13px; font-weight:600; color:var(--fg); overflow:hidden; text-overflow:ellipsis; white-space:nowrap}
.stn-badge{
  font-size:9px; font-weight:700; text-transform:uppercase; letter-spacing:.5px;
  padding:2px 6px; border-radius:4px;
}
.stn-badge.village{background:rgba(94,214,154,.15); color:var(--ok)}
.stn-badge.halt{background:rgba(255,193,77,.15); color:var(--warn)}
.stn-badge.town{background:rgba(74,168,255,.15); color:var(--accent)}
.stn-badge.terminal{background:rgba(197,140,255,.15); color:var(--curv)}

.stn-meta-row{display:flex; gap:12px; font-size:11px; font-family:var(--mono); color:var(--fg3); flex-wrap:wrap}
.stn-meta-row b{color:var(--fg2); font-weight:600}

.stn-yard-specs{
  display:flex; gap:6px; flex-wrap:wrap; background:var(--bg2);
  border:1px solid var(--line); border-radius:5px; padding:5px 8px; font-size:10.5px;
}
.stn-yard-specs span{color:var(--fg3)}
.stn-yard-specs span b{color:var(--fg)}

.stn-compliance{font-size:10.5px; line-height:1.4}
.stn-compliance.ok{color:var(--ok)}
.stn-compliance.warn{color:var(--warn)}

.stn-actions{display:flex; gap:6px; margin-top:2px; justify-content:flex-end}
.stn-btn-edit{background:var(--accent); color:#fff; border:none; border-radius:4px; padding:3px 8px; font-size:10.5px; font-weight:600; cursor:pointer}
.stn-btn-edit:hover{opacity:0.9}

/* Station Yard Inspector / Drawer */
.stn-editor-drawer{
  background:var(--bg2); border:1px solid var(--accent); border-radius:8px;
  padding:12px; margin-bottom:14px; display:flex; flex-direction:column; gap:10px;
  box-shadow:0 4px 16px rgba(0,0,0,0.3); animation:fadeIn 0.15s ease-out;
}
.stn-editor-head{
  display:flex; align-items:center; justify-content:space-between;
  border-bottom:1px solid var(--line); padding-bottom:8px;
}
.stn-editor-title{font-size:13.5px; font-weight:700; color:var(--fg); display:flex; align-items:center; gap:6px}
.stn-editor-close{
  background:none; border:none; color:var(--fg3); font-size:18px; cursor:pointer; padding:0 4px;
}
.stn-editor-close:hover{color:var(--fg)}
.stn-editor-sec{
  background:var(--bg3); border:1px solid var(--line); border-radius:6px;
  padding:9px 10px; display:flex; flex-direction:column; gap:7px;
}
.stn-editor-sec-head{
  display:flex; align-items:center; justify-content:space-between;
  font-size:11.5px; font-weight:700; color:var(--fg2); text-transform:uppercase; letter-spacing:0.4px;
}
.stn-item-card{
  background:var(--bg2); border:1px solid var(--line); border-radius:5px;
  padding:7px 9px; display:flex; flex-direction:column; gap:5px;
}
.stn-item-row{display:flex; align-items:center; justify-content:space-between; gap:6px; font-size:11px}
.stn-item-name{font-weight:600; color:var(--fg)}
.stn-item-del{
  background:none; border:none; color:var(--warn); font-size:13px; cursor:pointer; padding:0 3px;
}
.stn-item-del:hover{color:#ff4d4d}
.stn-editor-grid{
  display:grid; grid-template-columns:repeat(auto-fit, minmax(110px, 1fr)); gap:6px;
}
.stn-field{display:flex; flex-direction:column; gap:2px}
.stn-field label{font-size:9.5px; color:var(--fg3); text-transform:uppercase; font-weight:600}
.stn-field input, .stn-field select{
  background:var(--bg); border:1px solid var(--line); border-radius:4px;
  color:var(--fg); font-size:11px; padding:3px 6px; font-family:var(--mono);
}
.stn-field input:focus, .stn-field select:focus{border-color:var(--accent); outline:none}
.stn-sod-checklist{
  display:flex; flex-direction:column; gap:4px; font-size:10.5px; font-family:var(--mono);
}
.stn-sod-item{display:flex; align-items:center; gap:6px; line-height:1.3}
.stn-sod-item.pass{color:var(--ok)}
.stn-sod-item.fail{color:var(--warn)}
.stn-sod-item.info{color:var(--accent)}
.stn-sod-item.err{color:var(--err); font-weight:600}
.stn-editor-actions{
  display:flex; gap:8px; justify-content:flex-end; margin-top:4px;
}

/* ─────────────────── Design Considerations Modal ─────────────────── */
.modal.considerations{
  /* Wider than the other modals: the Design Limits tab carries twenty-five
     figures in labelled rows, and at 780px they wrap to one cramped column. */
  width:min(940px, 96vw);
}
.dc-tabs{
  display:flex;
  gap:4px;
  background:var(--bg2);
  border-bottom:1px solid var(--line);
  padding:6px 12px 0 12px;
  overflow-x:auto;
}
.dc-tab-btn{
  background:none;
  border:none;
  border-bottom:2px solid transparent;
  color:var(--fg2);
  font-size:11.5px;
  font-weight:600;
  padding:8px 12px;
  cursor:pointer;
  white-space:nowrap;
  transition:all 0.15s ease;
  border-radius:4px 4px 0 0;
}
.dc-tab-btn:hover{
  color:var(--fg);
  background:rgba(255,255,255,0.03);
}
.dc-tab-btn.active{
  color:var(--accent);
  border-bottom-color:var(--accent);
  background:var(--bg3);
}
.dc-body{
  padding:16px 20px;
  overflow-y:auto;
  display:flex;
  flex-direction:column;
  gap:14px;
  max-height:calc(92vh - 150px);
}
.dc-tab-pane{
  display:flex;
  flex-direction:column;
  gap:14px;
}
.dc-card{
  background:var(--bg3);
  border:1px solid var(--line);
  border-radius:8px;
  padding:12px 14px;
  display:flex;
  flex-direction:column;
  gap:10px;
}
.dc-card-title{
  font-size:11.5px;
  font-weight:700;
  color:var(--fg2);
  text-transform:uppercase;
  letter-spacing:0.6px;
  border-bottom:1px solid var(--line);
  padding-bottom:6px;
  margin-bottom:2px;
}
.dc-grid-2{
  display:grid;
  grid-template-columns:repeat(auto-fit, minmax(280px, 1fr));
  gap:12px 16px;
  align-items:start;
}

.dc-field{
  display:flex;
  flex-direction:column;
  gap:4px;
}
.dc-lab-row{
  display:flex;
  align-items:baseline;
  justify-content:space-between;
  gap:8px;
}
.dc-lab{
  font-size:11px;
  font-weight:600;
  color:var(--fg2);
}
.dc-hint{
  font-size:10px;
  color:var(--fg3);
  line-height:1.35;
}
.dc-btn-link{
  background:none;
  border:none;
  color:var(--accent);
  font-size:11px;
  cursor:pointer;
  padding:0;
  text-decoration:underline;
}
.dc-btn-link:hover{
  color:var(--accent2);
}
.dc-inp, .dc-select{
  width:100%;
  background:var(--bg);
  border:1px solid var(--line2);
  color:var(--fg);
  border-radius:5px;
  padding:6px 10px;
  font-size:12px;
}
.dc-inp:focus, .dc-select:focus{
  border-color:var(--accent);
  outline:none;
}
.dc-slider-row{
  display:flex;
  align-items:center;
  gap:10px;
}
.dc-range{
  flex:1;
  accent-color:var(--accent);
  cursor:pointer;
}
.dc-num{
  width:80px;
  text-align:right;
  font-family:var(--mono);
  font-size:12px;
  background:var(--bg);
  border:1px solid var(--line2);
  border-radius:5px;
  padding:4px 8px;
  color:var(--fg);
}
.dc-val-badge{
  font-family:var(--mono);
  font-size:11.5px;
  font-weight:700;
  color:var(--accent);
}
.dc-limits-grid{
  display:grid;
  grid-template-columns:repeat(auto-fit, minmax(180px, 1fr));
  gap:8px;
}
.dc-pill{
  background:var(--bg2);
  border:1px solid var(--line);
  border-radius:6px;
  padding:8px 10px;
  display:flex;
  flex-direction:column;
  gap:2px;
}
.dc-pill-k{
  font-size:9.5px;
  color:var(--fg3);
  text-transform:uppercase;
  letter-spacing:0.4px;
}
.dc-pill-v{
  font-family:var(--mono);
  font-size:12px;
  color:var(--fg);
}
.dc-foot{
  display:flex;
  align-items:center;
  justify-content:space-between;
  padding:12px 18px;
  border-top:1px solid var(--line);
  background:var(--bg2);
}
.dc-foot-right{
  display:flex;
  align-items:center;
  gap:8px;
}

/* ── Design Limits tab ──
   The side panel's Limits table, moved into the modal. Everything that made
   it readable there is inherited from table.grid — the mono figures, the
   hatched disabled name column, the tight rows — so nothing is restated
   here. What is set below is only what the modal's own box needs: the
   table has to grow with the pane rather than scroll inside 44vh of it,
   because the pane already scrolls. */
.dc-lim-note{
  font-style:italic;
  padding:0 2px;
}
/* Design Limits holds five cards of two, four, six, six and eleven rows. On a
   grid each row is as tall as the tallest card in it, so the two-row Gauge
   card stood beside the eleven-row Cant card and left most of a screen empty
   beneath it. Columns pack by flow instead — a card starts where the last one
   ended — and the browser balances the two columns by height. */
.dc-lim-cards{
  column-count:2;
  column-gap:14px;
}
.dc-lim-cards > .dc-card{
  break-inside:avoid; -webkit-column-break-inside:avoid; page-break-inside:avoid;
  margin:0 0 14px;
}
@media (max-width:1000px){ .dc-lim-cards{column-count:1} }
.dc-limit-card .table-wrap{
  max-height:none;
  overflow:visible;
}
.dc-limit-card table.grid td:first-child{width:60%}
.dc-limit-unit{
  text-align:left !important;
  color:var(--fg3);
  padding:0 7px !important;
  font-size:10px;
  width:1%;
  white-space:nowrap;
}
.dc-lim-foot{
  flex-direction:row;
  align-items:center;
  gap:12px;
  flex-wrap:wrap;
}
.dc-lim-foot .dc-hint{flex:1; min-width:220px}

/* A sentence at the head of a pane, saying what the numbers below it mean.
   Avoidance and Inclusion both need one: a weight of 350 says nothing until
   you know it is measured in metres of track. */
.dc-pane-note{
  border-left:2px solid var(--line2);
  padding:2px 0 2px 10px;
  font-size:10.5px;
}

/* ─────────────────── Export Deliverables ─────────────────── */
.exp-details{border:none; margin-top:4px}
.exp-summary{
  cursor:pointer; font-size:10.5px; font-weight:700; letter-spacing:.5px;
  text-transform:uppercase; color:var(--fg3); padding:6px 0; list-style:none;
}
.exp-summary::-webkit-details-marker{display:none}
.exp-summary::before{content:'▾ '; color:var(--fg3)}
.exp-details:not([open]) .exp-summary::before{content:'▸ '}

.exp-sub-grid{display:flex; flex-direction:column; gap:10px; margin-top:4px}
.exp-group{display:flex; flex-direction:column; gap:5px}
.exp-group-name{
  font-size:9.5px; font-weight:700; letter-spacing:.5px; text-transform:uppercase;
  color:var(--fg3); border-bottom:1px solid var(--line); padding-bottom:3px;
}
.exp-group-row{display:flex; flex-wrap:wrap; gap:6px; align-items:center}
.exp-sub-btn{text-align:left; font-size:11px; padding:6px 10px; white-space:nowrap}

/* The setting-out interval belongs to the one export it cuts, so it travels
   with that button instead of heading the panel. */
.exp-with-int{display:inline-flex; align-items:center; gap:6px}
.exp-int-tag{display:inline-flex; align-items:center; gap:3px; color:var(--fg3); font-size:10px}
.exp-int-inp{width:58px; padding:3px 6px; font-size:11px; text-align:right}

/* ─────────────────── Stage 4: the abstract of cost ─────────────────── */
.est-lab{font-size:11px; color:var(--fg2); font-weight:600}
.est-select{
  flex:1; background:var(--bg); border:1px solid var(--line2); color:var(--fg);
  border-radius:5px; padding:5px 8px; font-size:11.5px;
}
.est-select:focus{border-color:var(--accent); outline:none}

.est-pills{display:grid; grid-template-columns:repeat(auto-fit,minmax(112px,1fr)); gap:7px; margin:10px 0}
.est-pill{
  background:var(--bg3); border:1px solid var(--line); border-radius:7px;
  padding:8px 10px; display:flex; flex-direction:column; gap:2px;
}
.est-pill b{font-family:var(--mono); font-size:12.5px; color:var(--fg)}
.est-pill span{font-size:9.5px; color:var(--fg3); text-transform:uppercase; letter-spacing:.4px}
.est-pill.total{border-color:var(--accent)}
.est-pill.total b{color:var(--accent)}

.est-card{
  background:var(--bg3); border:1px solid var(--line); border-radius:8px;
  margin-bottom:9px; overflow:hidden;
}
.est-card.empty{opacity:.55}
.est-card-head{
  display:flex; align-items:baseline; gap:9px;
  padding:8px 11px; border-bottom:1px solid var(--line); background:var(--bg2);
}
.est-code{font-family:var(--mono); font-size:11px; color:var(--accent); font-weight:700}
.est-name{font-size:11px; font-weight:600; color:var(--fg2); flex:1}
.est-amt{font-family:var(--mono); font-size:11.5px; color:var(--fg)}
.est-none{padding:8px 11px; font-size:10px; color:var(--fg3)}
/* Where a quantity came from, under the item it prices. It used to be a
   tooltip, which is to say invisible: an abstract that cannot show which of
   its lines are measured and which are assumed reads as though all of them
   were measured. */
.est-basis{display:block; font-size:9.5px; line-height:1.35; color:var(--fg3); margin-top:1px; font-weight:400}
.est-basis.assumed{color:var(--warn, #d9a441)}
.est-card .table-wrap{max-height:none; overflow:visible; border:none; border-radius:0}
.est-card table.grid td:first-child{width:46%}

/* The cascade under the sub-heads: what is levied on the works, on what base,
   and at what rate. Each line states its own rule, because "why is it that
   number" is answered here rather than by any one sub-head. */
.est-casc{
  display:flex; align-items:baseline; justify-content:space-between; gap:12px;
  padding:7px 13px; font-size:11.5px; color:var(--fg3);
  border-bottom:1px solid rgba(255,255,255,.04);
}
.est-casc b{font-family:var(--mono); font-size:12px; color:var(--fg2); flex:0 0 auto}
.est-casc.strong{color:var(--fg2)}
.est-casc.strong b{color:var(--fg)}

.est-total{
  display:flex; align-items:center; justify-content:space-between; gap:12px;
  padding:11px 13px; margin-top:4px;
  background:var(--bg4); border:1px solid var(--accent); border-radius:8px;
}
.est-total span{font-size:10.5px; font-weight:700; letter-spacing:.5px; text-transform:uppercase; color:var(--fg2)}
.est-total b{font-family:var(--mono); font-size:14px; color:var(--accent)}

/* ─────────────────── Export Deliverables Buttons ─────────────────── */
.export-main-btns{
  display:flex;
  flex-direction:column;
  gap:8px;
  margin-top:6px;
}
.export-main-btn{
  width:100%;
  font-size:12.5px;
  font-weight:700 !important;
  letter-spacing:0.2px;
  padding:10px 16px;
  border-radius:6px;
  text-align:center;
  background:var(--bg3);
  border:1px solid var(--line2);
  color:var(--fg);
  cursor:pointer;
  transition:all 0.15s ease;
  box-shadow:0 1px 3px rgba(0,0,0,0.2);
}
.export-main-btn:hover{
  background:var(--line);
  border-color:var(--accent);
  color:#ffffff;
  box-shadow:0 2px 6px rgba(56,189,248,0.15);
}

/* ─────────────────── Export Deliverables Modal ─────────────────── */
.modal.export-modal{
  width:min(640px, 94vw);
}
.exp-body{
  padding:16px 20px;
  overflow-y:auto;
  display:flex;
  flex-direction:column;
  gap:14px;
  max-height:calc(92vh - 120px);
}
.exp-main-col{
  display:flex;
  flex-direction:column;
  gap:8px;
}
.exp-foot{
  display:flex;
  justify-content:flex-end;
}

/* ═════════════════════ 5 km Sheets Modal Viewer ═════════════════════ */
.modal.sheets-modal {
  width: min(1300px, 96vw);
  height: min(880px, 94vh);
  display: flex;
  flex-direction: column;
  background: var(--bg2);
}
.sheets-head-title {
  display: flex;
  flex-direction: column;
  gap: 2px;
}
.sheets-subhead {
  font-size: 11px;
  color: var(--fg3);
  font-weight: 500;
}
.sheets-toolbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 8px 16px;
  background: var(--bg3);
  border-bottom: 1px solid var(--line2);
  flex-wrap: wrap;
}
.sheets-nav-group,
.sheets-zoom-group,
.sheets-exp-group {
  display: flex;
  align-items: center;
  gap: 6px;
}
.sheets-label {
  font-size: 11.5px;
  font-weight: 600;
  color: var(--fg2);
}
.sheets-select {
  font-size: 12px;
  padding: 4px 8px;
  background: var(--bg);
  border: 1px solid var(--line2);
  border-radius: 4px;
  color: var(--fg);
}
.sheets-canvas-wrap {
  flex: 1;
  position: relative;
  overflow: hidden;
  background: #0b0e14;
  cursor: grab;
}
.sheets-canvas-wrap.grabbing {
  cursor: grabbing;
}
.sheets-canvas {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  display: block;
}




/* ---- Yard editor overlay --------------------------------------------- */
.yard-back{align-items:stretch; justify-content:stretch; padding:24px}
.yard-win{display:flex; flex-direction:column; width:100%; height:100%;
  background:var(--bg1); border:1px solid var(--line); border-radius:10px; overflow:hidden}
.yard-head{display:flex; align-items:center; justify-content:space-between; gap:12px;
  padding:10px 14px; border-bottom:1px solid var(--line); background:var(--bg2)}
.yard-title{display:flex; align-items:baseline; gap:12px; min-width:0}
.yard-title b{font-size:14px}
.yard-sub{color:var(--fg3); font-size:11px; font-family:var(--mono); white-space:nowrap;
  overflow:hidden; text-overflow:ellipsis}
.yard-palette{display:flex; align-items:center; gap:6px; padding:8px 12px; overflow-x:auto;
  border-bottom:1px solid var(--line); background:var(--bg2)}
.yard-pal-label{color:var(--fg3); font-size:11px; text-transform:uppercase;
  letter-spacing:.06em; margin-right:6px; white-space:nowrap}
.yard-chip{display:flex; align-items:center; gap:6px; padding:6px 10px; cursor:grab;
  background:var(--bg3); color:var(--fg1); border:1px solid var(--line); border-radius:6px;
  font-size:12px; white-space:nowrap}
.yard-chip:hover{border-color:var(--accent); color:var(--accent)}
.yard-chip:active{cursor:grabbing}
.yard-chip.dragging{opacity:.5; border-color:var(--accent)}
.yard-chip-glyph{font-size:14px; line-height:1}
.yard-body{display:flex; flex:1; min-height:0}
.yard-rail{display:flex; flex-direction:column; gap:4px; padding:8px 6px; width:44px;
  border-right:1px solid var(--line); background:var(--bg2)}
.yard-rail-gap{flex:1}
.yard-tool{width:32px; height:32px; display:flex; align-items:center; justify-content:center;
  background:var(--bg3); color:var(--fg2); border:1px solid var(--line); border-radius:6px;
  cursor:pointer; font-size:14px}
.yard-tool:hover{color:var(--accent); border-color:var(--accent)}
.yard-tool.on{background:var(--accent); color:#08121d; border-color:var(--accent)}
.yard-canvas-wrap{flex:1; position:relative; min-width:0; overflow:hidden; cursor:default}
.yard-canvas-wrap.grabbing{cursor:grabbing}
.yard-canvas-wrap.dropping{outline:2px dashed var(--accent); outline-offset:-6px}
.yard-canvas{display:block; position:absolute; inset:0}
.yard-inspector{width:290px; padding:12px; overflow-y:auto; border-left:1px solid var(--line);
  background:var(--bg2)}
.yard-insp-head{font-weight:600; font-size:13px; margin-bottom:8px}
.yard-insp-hint,.yard-insp-note{color:var(--fg3); font-size:11px; line-height:1.5; margin-bottom:10px}
.yard-insp-note{font-family:var(--mono); color:var(--accent)}
.yard-field{margin-bottom:9px}
.yard-field label{display:block; color:var(--fg3); font-size:11px; margin-bottom:3px}
.yard-field input,.yard-field select{width:100%; padding:5px 7px; font-size:12px;
  background:var(--bg1); color:var(--fg1); border:1px solid var(--line); border-radius:5px}
.yard-status{padding:7px 14px; font-size:11px; border-top:1px solid var(--line);
  background:var(--bg2); max-height:64px; overflow-y:auto; line-height:1.5}
.yard-status.ok{color:var(--ok)}
.yard-status.bad{color:var(--err)}
.yard-status-line.ok{color:var(--ok)}
.yard-status-line.bad{color:var(--err)}
.yard-suggest-row{display:flex; align-items:center; gap:6px; margin-top:6px;
  flex-wrap:wrap}
.yard-suggest-label{color:var(--fg3); font-size:10px; text-transform:uppercase;
  letter-spacing:.06em; margin-right:2px}
.yard-suggest{display:inline-flex; align-items:center; gap:5px; padding:3px 9px;
  background:transparent; color:var(--accent); border:1px dashed var(--accent);
  border-radius:11px; font-size:11px; cursor:pointer}
.yard-suggest:hover{background:var(--accent); color:#08121d; border-style:solid}
.yard-suggest-plus{font-weight:700}
.yard-head-acts{display:flex; align-items:center; gap:6px; margin-left:auto}
.yard-hbtn{padding:5px 11px; font-size:12px; border-radius:6px; cursor:pointer;
  background:var(--bg3); color:var(--fg1); border:1px solid var(--line)}
.yard-hbtn:hover:not(:disabled){border-color:var(--accent); color:var(--accent)}
.yard-hbtn:disabled{opacity:.4; cursor:default}
.yard-hbtn.primary{background:var(--accent); color:#08121d; border-color:var(--accent)}
.yard-hbtn.primary:disabled{background:var(--bg3); color:var(--fg3); border-color:var(--line)}
.yard-hbtn.primary.dirty{box-shadow:0 0 0 2px rgba(74,168,255,.28)}
.yard-dims{position:absolute; padding:3px 7px; font-family:var(--mono); font-size:11px;
  background:rgba(12,16,22,.92); color:var(--accent); border:1px solid var(--accent);
  border-radius:4px; pointer-events:none; white-space:nowrap; z-index:5}
.yard-palette .yard-pal-label:not(:first-child){margin-left:10px;
  padding-left:10px; border-left:1px solid var(--line)}
.yard-rail-sep{height:1px; background:var(--line); margin:4px 2px}
.yard-tool.layer{font-size:11px; height:26px; opacity:.5}
.yard-tool.layer.on{opacity:1; background:var(--bg1); color:var(--accent);
  border-color:var(--accent)}
.yard-hsel{padding:5px 8px; font-size:12px; border-radius:6px; max-width:190px;
  background:var(--bg3); color:var(--fg1); border:1px solid var(--line)}


/* ---- the mark, catching the light now and then ----
 *
 * The lockup is a raster, so there is nothing inside it to animate. Instead a
 * highlight is swept across a copy of it, masked to the artwork's own alpha so
 * the light travels over the letterforms rather than over a rectangle around
 * them. The sweep occupies the first sixth of the cycle and the rest is still,
 * which is what makes it occasional rather than a thing that flickers in the
 * corner of the eye all day. */
.brand{position:relative; overflow:hidden}
.brand::after{
  content:''; position:absolute; inset:0; pointer-events:none;
  /* The band is kept narrower than the box on purpose: a background image
     wider than its element makes percentage positions count against a
     negative remainder, and the sweep simply never crosses. */
  background-image:linear-gradient(100deg,
    transparent 0%, rgba(255,255,255,.72) 50%, transparent 100%);
  background-size:52% 100%; background-repeat:no-repeat;
  background-position:-70% 0;
  -webkit-mask-image:url(../assets/rad-lockup-dark.png);
  mask-image:url(../assets/rad-lockup-dark.png);
  -webkit-mask-size:contain; mask-size:contain;
  -webkit-mask-repeat:no-repeat; mask-repeat:no-repeat;
  -webkit-mask-position:left center; mask-position:left center;
  animation:markSheen 14s ease-in-out infinite;
}
@keyframes markSheen{
  0%{background-position:-70% 0}
  15%{background-position:175% 0}
  100%{background-position:175% 0}
}
/* A logo glinting at someone is decoration, and a poor trade for anybody who
   asked the browser to stop things moving. */
@media (prefers-reduced-motion:reduce){
  .brand::after{animation:none; opacity:0}
}

/* ─────────────────── the station proposal report ───────────────────
   A set of recommendations with the reasoning attached, rather than a
   list of chainages to accept on trust. */
.modal.report{max-width:760px; width:calc(100vw - 48px)}
.report-body{padding:16px 18px 18px; max-height:min(70vh,660px); overflow-y:auto}
.report-warn{
  margin:0 0 10px; padding:10px 12px; border-radius:8px; font-size:12.5px;
  line-height:1.55; color:var(--warn);
  background:rgba(255,182,72,.09); border:1px solid rgba(255,182,72,.3);
}
.report-row{
  padding:12px 14px; margin-bottom:8px; border-radius:9px;
  background:var(--bg3); border:1px solid var(--line);
}
.report-row.over{border-color:rgba(255,182,72,.4)}
.report-row-head{display:flex; align-items:baseline; gap:9px; flex-wrap:wrap}
.report-row-head b{font-size:14px; color:var(--fg)}
.report-type{
  font:600 9.5px var(--mono); letter-spacing:.6px; text-transform:uppercase;
  color:var(--accent); background:rgba(74,168,255,.1);
  border:1px solid rgba(74,168,255,.2); padding:2px 7px; border-radius:4px;
}
.report-ch{margin-left:auto; font:12px var(--mono); color:var(--fg2)}
.report-facts{display:flex; flex-wrap:wrap; gap:16px; margin-top:8px}
.report-fact{display:flex; gap:6px; font-size:11.5px; align-items:baseline}
.report-fact em{
  font-style:normal; color:var(--fg3); text-transform:uppercase;
  letter-spacing:.5px; font-size:9.5px; font-weight:600;
}
.report-fact span{color:var(--fg2); font-family:var(--mono); font-size:11px}
.report-why{
  margin:9px 0 0; font-size:12.5px; line-height:1.6; color:var(--fg2);
  padding-top:9px; border-top:1px solid rgba(255,255,255,.05);
}
/* What the map calls the watercourse, beside what the design proposes to carry
   it on. Quieter than the structure class, because the structure is the
   decision and this is the ground it was taken on. */
.report-klass{
  font:600 9.5px var(--mono); letter-spacing:.6px; text-transform:uppercase;
  color:var(--fg3); background:rgba(255,255,255,.04);
  border:1px solid rgba(255,255,255,.08); padding:2px 7px; border-radius:4px;
}
/* A figure that cannot be believed, said on the row it belongs to. */
.report-doubt{
  margin:9px 0 0; padding:9px 11px; border-radius:7px; font-size:12px;
  line-height:1.55; color:var(--warn);
  background:rgba(255,182,72,.08); border:1px solid rgba(255,182,72,.25);
}

/* A judgement made against cost wants a slider, not a number box. */
.dc-inp.slider{
  width:100%; height:6px; -webkit-appearance:none; appearance:none; padding:0;
  background:linear-gradient(90deg,var(--accent),var(--bg4));
  border-radius:3px; border:none; cursor:pointer; margin:8px 0 2px;
}
.dc-inp.slider::-webkit-slider-thumb{
  -webkit-appearance:none; width:16px; height:16px; border-radius:50%;
  background:var(--accent); border:3px solid var(--bg2); cursor:grab;
}
.dc-inp.slider::-moz-range-thumb{
  width:12px; height:12px; border-radius:50%; background:var(--accent);
  border:3px solid var(--bg2); cursor:grab;
}
.dc-out{
  float:right; font:600 11.5px var(--mono); color:var(--accent);
}

/* ─────────── the hydrology behind one crossing ─────────── */
.hyd-btn{
  margin-top:10px; width:100%; text-align:left; cursor:pointer;
  background:var(--bg4); border:1px solid var(--line2); color:var(--fg2);
  border-radius:7px; padding:7px 11px; font:inherit; font-size:12px;
  display:flex; align-items:center; gap:8px;
  transition:border-color .18s, color .18s, background .18s;
}
.hyd-btn:hover{border-color:var(--accent2); color:var(--fg)}
.hyd-btn.open{border-color:var(--accent); color:var(--accent)}
.hyd-ico{
  font-size:14px; line-height:1; color:var(--accent);
  width:20px; height:20px; border-radius:5px; flex:0 0 auto;
  background:rgba(74,168,255,.12); border:1px solid rgba(74,168,255,.28);
  display:inline-flex; align-items:center; justify-content:center;
}
.hyd-panel{margin-top:9px}
.hyd-report{
  background:var(--bg); border:1px solid var(--line); border-radius:8px; padding:13px 15px;
}
.hyd-step{padding:8px 0; border-top:1px solid rgba(255,255,255,.05)}
.hyd-step:first-child{border-top:none; padding-top:0}
.hyd-step-head{display:flex; align-items:baseline; gap:10px}
.hyd-step-name{font-size:11px; color:var(--fg3); text-transform:uppercase; letter-spacing:.6px}
.hyd-step-val{margin-left:auto; font:700 13px var(--mono); color:var(--accent)}
.hyd-step-work{
  margin-top:4px; font:11px/1.6 var(--mono); color:var(--fg2);
}
.hyd-diagram{
  margin:12px 0; background:var(--bg2); border:1px solid var(--line);
  border-radius:7px; padding:6px;
}
.hyd-diagram svg{display:block; width:100%; height:auto}
.hyd-bed{fill:none; stroke:var(--ground); stroke-width:2}
.hyd-water{fill:rgba(74,168,255,.22); stroke:rgba(74,168,255,.5); stroke-width:1}
.hyd-deck{fill:var(--bg4); stroke:var(--accent); stroke-width:1.4}
.hyd-pier{fill:var(--bg3); stroke:var(--fg3); stroke-width:1.2}
.hyd-barrel{fill:rgba(74,168,255,.1); stroke:var(--accent2); stroke-width:1.2}
.hyd-dim{stroke:var(--spiral); stroke-width:1.2; fill:none}
.hyd-lab{fill:var(--fg2); font:9.5px var(--mono)}
.hyd-alts{margin-top:10px}
.hyd-alts-title{
  font-size:9.5px; text-transform:uppercase; letter-spacing:.7px;
  color:var(--fg3); font-weight:600; margin-bottom:5px;
}
.hyd-alt{
  display:flex; justify-content:space-between; padding:4px 8px; border-radius:5px;
  font:11px var(--mono); color:var(--fg3); background:var(--bg2); margin-bottom:3px;
}
.hyd-alt.won{color:var(--ok); background:rgba(94,214,154,.08)}
.hyd-alt em{font-style:normal; opacity:.8}
.hyd-warn{
  margin-top:10px; padding:9px 11px; border-radius:7px; font-size:11.5px; line-height:1.55;
  color:var(--warn); background:rgba(255,182,72,.09); border:1px solid rgba(255,182,72,.28);
}
.hyd-basis{margin-top:9px; font:10.5px var(--mono); color:var(--fg3); opacity:.85}
.hyd-none{color:var(--fg3); font-size:12.5px; line-height:1.6}

/* ═══════════════ the cost, in the toolbar ═══════════════ */
.cost-readout{
  display:flex; align-items:stretch; gap:1px; margin-right:8px; flex:0 0 auto;
  background:var(--bg3); border:1px solid var(--line2); border-radius:7px; overflow:hidden;
}
.cost-readout[hidden]{display:none}
.cost-figures{
  display:flex; flex-direction:column; align-items:flex-end; gap:1px;
  padding:4px 9px; background:none; border:0; cursor:pointer; font:inherit;
  transition:background .12s ease;
}
.cost-figures:hover{background:var(--bg4)}
/* The figure follows the alignment, so it says when it has moved. */
.cost-readout.moved{animation:cost-moved .75s ease-out}
@keyframes cost-moved{
  0%{border-color:var(--accent); box-shadow:0 0 0 3px rgba(74,168,255,.22)}
  100%{border-color:var(--line2); box-shadow:0 0 0 0 rgba(74,168,255,0)}
}
@media (prefers-reduced-motion:reduce){ .cost-readout.moved{animation:none} }
.cost-figures b{font-family:var(--mono); font-size:12.5px; color:var(--accent); line-height:1.15}
.cost-figures span{font-family:var(--mono); font-size:9.5px; color:var(--fg3); line-height:1.1}
.cost-why{
  width:20px; flex:0 0 auto; background:none; border:0; border-left:1px solid var(--line);
  color:var(--fg3); cursor:pointer; font:italic 700 11px Georgia,serif;
  transition:color .12s ease, background .12s ease;
}
.cost-why:hover{color:var(--accent); background:var(--bg4)}

/* Why the figure is the figure. */
.cost-pop{
  position:fixed; z-index:60; width:430px; max-width:calc(100vw - 16px);
  background:var(--bg2); border:1px solid var(--line2); border-radius:10px;
  box-shadow:0 16px 48px rgba(0,0,0,.6); padding:13px 15px 12px;
}
.cost-pop-head{font-size:12px; font-weight:700; color:var(--fg); text-transform:uppercase; letter-spacing:.5px}
.cost-pop-sub{font-size:11px; color:var(--fg3); margin:3px 0 9px}
.cost-pop-tbl{width:100%; border-collapse:collapse; font-size:11.5px}
.cost-pop-tbl td{padding:3px 5px; vertical-align:middle}
.cost-pop-tbl td.c{font-family:var(--mono); color:var(--fg3); font-size:10.5px; width:1%}
.cost-pop-tbl td.m{font-family:var(--mono); color:var(--fg); text-align:right; white-space:nowrap}
.cost-pop-tbl td.p{font-family:var(--mono); color:var(--fg3); text-align:right; font-size:10.5px; width:1%}
.cost-pop-tbl td.bar{width:70px}
.cost-pop-tbl td.bar i{display:block; height:5px; border-radius:3px; background:var(--accent); opacity:.65}
.cost-pop-levies{margin-top:9px; padding-top:8px; border-top:1px solid var(--line)}
.cost-pop-levies > div{display:flex; justify-content:space-between; gap:10px; font-size:11.5px;
  color:var(--fg2); padding:2px 5px}
.cost-pop-levies b{font-family:var(--mono); color:var(--fg)}
.cost-pop-levies .note{display:block; color:var(--fg3); font-size:10.5px; line-height:1.5; margin-top:5px}
.cost-pop-warn{
  margin-top:10px; padding:8px 10px; border-radius:7px; font-size:11px; line-height:1.5;
  color:var(--warn); background:rgba(255,182,72,.08); border:1px solid rgba(255,182,72,.25);
}
.cost-pop-foot{display:flex; gap:7px; margin-top:10px; justify-content:flex-end}

/* ═══════════════ the estimate, in full ═══════════════ */
.modal.est-console{
  width:min(1180px, calc(100vw - 40px)); height:min(820px, calc(100vh - 60px));
  display:flex; flex-direction:column;
}
.est-con-tabs{
  display:flex; gap:4px; padding:9px 14px 0; flex:0 0 auto;
  border-bottom:1px solid var(--line); overflow-x:auto; scrollbar-width:thin;
}
.est-con-tab{
  flex:0 0 auto; display:flex; flex-direction:column; align-items:flex-start; gap:1px;
  padding:6px 11px 7px; background:none; border:0; border-bottom:2px solid transparent;
  color:var(--fg3); cursor:pointer; font:inherit; white-space:nowrap;
}
.est-con-tab em{font:600 9.5px var(--mono); font-style:normal; letter-spacing:.5px; opacity:.8}
.est-con-tab span{font-size:12px; font-weight:600}
.est-con-tab:hover{color:var(--fg2)}
.est-con-tab.active{color:var(--accent); border-bottom-color:var(--accent)}
.est-con-tab.empty{opacity:.45}
.est-con-body{flex:1 1 auto; min-height:0; overflow:hidden; display:flex; padding:0}
.est-con-wrap{flex:1 1 auto; min-height:0; overflow:auto; padding:12px 14px}
.est-con-grid{width:100%; border-collapse:collapse; font-size:11.5px}
.est-con-grid th{
  position:sticky; top:0; z-index:1; background:var(--bg2);
  text-align:right; padding:6px 8px; font-size:9.5px; letter-spacing:.5px;
  text-transform:uppercase; color:var(--fg3); border-bottom:1px solid var(--line2);
}
/* The code column is a code and the one beside it is a name: both read left,
   and every money column reads right. Sizing the code column keeps the name
   next to it rather than adrift across half the sheet. */
.est-con-grid th:first-child,
.est-con-grid th:nth-child(2){text-align:left}
.est-con-grid tr > *:first-child{width:1%; white-space:nowrap}
.est-con-grid td.lft[colspan]{width:auto}
.est-con-grid td{padding:5px 8px; text-align:right; border-bottom:1px solid rgba(255,255,255,.04)}
.est-con-grid td.lft{text-align:left; color:var(--fg2)}
.est-con-grid td.ind{padding-left:22px}
.est-con-grid td.mono{font-family:var(--mono); color:var(--fg2); white-space:nowrap}
/* The unit sits just off the quantity it belongs to, not jammed against it. */
.est-con-grid td.unit{text-align:left; color:var(--fg3); font-size:10.5px; padding-left:4px; width:1%}
.est-con-grid th:nth-child(3){text-align:left; padding-left:4px}
.est-con-grid td.b{color:var(--fg); font-weight:600}
.est-con-head-row td{background:var(--bg3); color:var(--fg); font-weight:600}
.est-con-part-row td{background:rgba(255,255,255,.02); color:var(--fg2)}
.est-con-levy td{background:var(--bg3)}
.est-con-levy.strong td{background:var(--bg4); color:var(--fg); font-weight:600}
.est-con-levy.grand td{
  background:var(--bg4); color:var(--accent); font-weight:700;
  border-top:1px solid var(--accent); border-bottom:1px solid var(--accent);
}
.est-con-foot{padding:9px 14px; border-top:1px solid var(--line); flex:0 0 auto}
.est-con-sum{display:flex; gap:20px; flex-wrap:wrap; align-items:baseline}
.est-con-sum span{display:flex; flex-direction:column; gap:1px}
.est-con-sum em{
  font-style:normal; font-size:9.5px; letter-spacing:.5px; text-transform:uppercase;
  color:var(--fg3); font-weight:600;
}
.est-con-sum b{font-family:var(--mono); font-size:13px; color:var(--fg2)}
.est-con-sum .grand b{color:var(--accent); font-size:15px}
@media (max-width:820px){
  .modal.est-console{width:calc(100vw - 16px); height:calc(100vh - 24px)}
  .est-con-sum{gap:12px}
}


/* The flow, for work that runs outside a modal. Bottom left, clear of the
   compliance orb and the map type switcher on the other side. */
.work-card{
  /* Above the modal layer at 100: this reports work that is running, and a
     dialog opening over it does not stop that work or the need to see it. */
  position:fixed; left:16px; bottom:38px; z-index:120; width:min(400px, calc(100vw - 32px));
  background:var(--bg2); border:1px solid var(--line2); border-radius:10px;
  box-shadow:0 12px 40px rgba(0,0,0,.55); padding:12px 14px 8px;
}
.work-head{
  font-size:10.5px; font-weight:700; letter-spacing:.6px; text-transform:uppercase;
  color:var(--fg2); margin-bottom:6px;
}


/* ---- the tool drawer beside the plan ----
 *
 * A rail of tools down the left, a layer panel that opens top right, a strip
 * of colours that appears only with the colour tool in hand, and one line at
 * the foot saying what the tool is waiting for. All of it floats over the
 * drawing rather than taking width from it, because the drawing is the work
 * and the tools are only how it is reached. */
.plan-rail{position:absolute; left:12px; top:46px; z-index:6;
  /* Two columns rather than one long strip: fourteen tools in a column is
     taller than the plan view on a laptop, and a rail that scrolls hides the
     last few tools behind a scrollbar nobody notices is there. */
  display:grid; grid-template-columns:repeat(2, 30px); gap:3px; padding:5px;
  background:rgba(18,21,26,.86); border:1px solid var(--line); border-radius:9px;
  backdrop-filter:blur(6px); box-shadow:0 6px 20px rgba(0,0,0,.35);
  /* And on a window short enough that even two columns will not fit, it
     scrolls rather than running off the bottom of the drawing. */
  max-height:calc(100% - 58px); overflow-y:auto}
.plan-rail-sep{grid-column:1 / -1}
.plan-tool{width:30px; height:30px; flex:0 0 auto;
  display:flex; align-items:center; justify-content:center;
  background:var(--bg3); color:var(--fg2); border:1px solid var(--line);
  border-radius:6px; cursor:pointer; font-size:14px; line-height:1; padding:0}
.plan-tool:hover:not(:disabled){color:var(--accent); border-color:var(--accent)}
.plan-tool.on{background:var(--accent); color:#08121d; border-color:var(--accent)}
.plan-tool:disabled{opacity:.35; cursor:default}
.plan-rail-sep{height:1px; background:var(--line); margin:3px 1px; flex:0 0 auto}

.plan-swatches{position:absolute; left:90px; top:46px; z-index:6;
  display:flex; flex-wrap:wrap; gap:4px; max-width:196px; padding:6px;
  background:rgba(18,21,26,.9); border:1px solid var(--line); border-radius:9px;
  box-shadow:0 6px 20px rgba(0,0,0,.35)}
.plan-swatch{width:18px; height:18px; border-radius:4px; cursor:pointer; padding:0;
  border:1px solid rgba(255,255,255,.16); background:var(--bg3)}
.plan-swatch.bylayer{color:var(--fg3); font-size:11px; line-height:16px; text-align:center}
.plan-swatch:hover{border-color:var(--fg)}
.plan-swatch.on{box-shadow:0 0 0 2px var(--accent); border-color:var(--accent)}
.plan-swatches[hidden]{display:none}
.plan-swatches.turnouts{max-width:none; gap:5px}
.plan-turnout{padding:4px 9px; border-radius:5px; cursor:pointer;
  font-family:var(--mono); font-size:11px; line-height:1;
  background:var(--bg3); color:var(--fg2); border:1px solid var(--line)}
.plan-turnout:hover{color:var(--accent); border-color:var(--accent)}
.plan-turnout.on{background:var(--accent); color:#08121d; border-color:var(--accent)}

.plan-hint{position:absolute; left:50%; transform:translateX(-50%); bottom:14px; z-index:6;
  max-width:min(560px,72%); padding:5px 12px; font-size:11.5px; color:var(--fg2);
  background:rgba(18,21,26,.9); border:1px solid var(--line); border-radius:20px;
  white-space:nowrap; overflow:hidden; text-overflow:ellipsis; pointer-events:none}

.plan-layers{position:absolute; right:14px; top:46px; z-index:7; width:262px;
  max-height:calc(100% - 92px); overflow-y:auto; padding:8px;
  background:rgba(18,21,26,.94); border:1px solid var(--line); border-radius:10px;
  box-shadow:0 10px 30px rgba(0,0,0,.45)}
.plan-layers-head{display:flex; align-items:center; justify-content:space-between;
  font-size:11px; letter-spacing:.07em; text-transform:uppercase; color:var(--fg3);
  padding:0 2px 7px}
.plan-layers-close{background:none; border:0; color:var(--fg3); font-size:15px;
  cursor:pointer; line-height:1; padding:0 2px}
.plan-layers-close:hover{color:var(--fg)}
.plan-layer-row{display:flex; align-items:center; gap:5px; flex-wrap:wrap;
  padding:3px 2px; border-radius:5px}
.plan-layer-row:hover{background:var(--bg3)}
.plan-layer-row.routing .plan-layer-name{color:var(--fg)}
.plan-layer-btn{width:20px; height:20px; flex:0 0 auto; padding:0; cursor:pointer;
  background:none; border:0; color:var(--fg3); font-size:12px; line-height:1}
.plan-layer-btn.on{color:var(--accent)}
.plan-layer-btn.locked{color:var(--warn,#ffc14d)}
.plan-layer-colour{width:16px; height:16px; flex:0 0 auto; padding:0; cursor:pointer;
  border:1px solid rgba(255,255,255,.2); border-radius:3px}
.plan-layer-name{flex:1 1 auto; font-size:12px; color:var(--fg2);
  overflow:hidden; text-overflow:ellipsis; white-space:nowrap}
.plan-layer-count{font-family:var(--mono); font-size:10.5px; color:var(--fg3)}
.plan-layer-palette{flex:1 0 100%; display:flex; flex-wrap:wrap; gap:4px;
  padding:5px 0 3px 26px}
.plan-layers-foot{margin-top:7px; padding-top:7px; border-top:1px solid var(--line);
  font-size:10.5px; color:var(--fg3); line-height:1.5}

.plan-text-input{position:absolute; z-index:8; width:190px; padding:4px 7px;
  font-size:12px; background:rgba(18,21,26,.96); color:var(--fg);
  border:1px solid var(--accent); border-radius:5px; outline:none}

#plan.drawing{cursor:crosshair}
