/* Intake interface. Two columns: the conversation, and the constraints it fires. */

:root {
  --ink: #17191c;
  --ink-soft: #565d66;
  --ink-faint: #868e99;
  --paper: #f6f5f2;
  --card: #ffffff;
  --line: #e2e0da;
  --line-strong: #cbc8bf;
  --accent: #1f5f4f;
  --accent-soft: #e8f1ee;
  --blocker: #9b2c2c;
  --blocker-soft: #fbeceb;
  --warn: #9a6b12;
  --warn-soft: #fdf4e3;
  --unknown: #3f5b8b;
  --unknown-soft: #eaeff8;
  --info-soft: #eef0f1;
  --radius: 10px;
  --shadow: 0 1px 2px rgba(23, 25, 28, .06), 0 8px 24px rgba(23, 25, 28, .05);
  --arrow-left: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M5 12h14'/%3E%3Cpath d='M5 12l4 4'/%3E%3Cpath d='M5 12l4 -4'/%3E%3C/svg%3E");
}

* { box-sizing: border-box; }
[x-cloak] { display: none !important; }

body {
  margin: 0;
  background: var(--paper);
  color: var(--ink);
  font: 16px/1.55 ui-sans-serif, -apple-system, "Segoe UI", Roboto, sans-serif;
  -webkit-font-smoothing: antialiased;
}

h1, h2, h3 { line-height: 1.25; letter-spacing: -.011em; }
h1 { font-size: 1.5rem; margin: 0 0 .5rem; }
h2 { font-size: 1.15rem; margin: 0 0 .5rem; }

/* --- chrome ------------------------------------------------------------ */

.masthead {
  display: flex; align-items: baseline; gap: .6rem 1.5rem; flex-wrap: wrap;
  padding: .9rem 1.75rem;
  background: var(--card);
  border-bottom: 1px solid var(--line);
}
.wordmark {
  font-weight: 650; letter-spacing: -.02em; text-decoration: none; color: var(--ink);
  white-space: nowrap;
}
.wordmark span { color: var(--ink-faint); font-weight: 450; }
.masthead-meta {
  display: flex; gap: .4rem 1rem; align-items: baseline; flex-wrap: wrap;
  font-size: .9rem; margin-left: auto;
}
/* Below the point where it all fits on one line, the meta drops onto its own
   full-width row rather than being pushed off the right edge and clipped.
   Matches the app's other panels, which wrap rather than overflow. */
@media (max-width: 640px) {
  .masthead { padding: .7rem 1rem; }
  .masthead-meta { flex-basis: 100%; margin-left: 0; font-size: .85rem; }
}

/* Editable address in the masthead: a plain button that drops a small form. */
.mast-address { position: relative; }
.mast-address-show {
  background: none; border: 0; padding: 0; font: inherit; color: inherit;
  cursor: pointer; display: inline-flex; align-items: baseline; gap: .35rem;
}
.mast-address-show:hover { color: var(--accent); }
.mast-address-cue {
  font-size: .66rem; text-transform: uppercase; letter-spacing: .05em;
  color: var(--accent); opacity: 0; transition: opacity .12s ease;
}
.mast-address-show:hover .mast-address-cue,
.mast-address-show[aria-expanded="true"] .mast-address-cue { opacity: 1; }
.mast-address-form {
  position: absolute; top: calc(100% + .55rem); right: 0; z-index: 30;
  display: flex; flex-direction: column; gap: .45rem; width: 260px;
  padding: .85rem; text-align: left;
  background: var(--card); border: 1px solid var(--line-strong);
  border-radius: 10px; box-shadow: var(--shadow);
}
.mast-address-form input { margin-top: 0; }
.mast-address-actions { display: flex; gap: .8rem; align-items: center; }
.mast-address-actions .primary { padding: .45rem .9rem; font-size: .88rem; }
.mast-address-note { margin: 0; font-size: .74rem; color: var(--ink-faint); }
/* On a narrow masthead the meta is full-width; drop the form below-left. */
@media (max-width: 640px) {
  .mast-address-form { right: auto; left: 0; }
}

.mainnav { display: flex; gap: .35rem; }
.mainnav-item {
  font-size: .88rem; text-decoration: none; color: var(--ink-soft);
  padding: .3rem .7rem; border-radius: 999px;
}
.mainnav-item:hover { background: var(--paper); color: var(--ink); }
.mainnav-item--active { background: var(--ink); color: #fff; }
.mainnav-item--active:hover { background: var(--ink); color: #fff; }

.page--list { max-width: 900px; margin: 0 auto; }
.list-header {
  display: flex; justify-content: space-between; align-items: center;
  gap: 1rem; flex-wrap: wrap; margin-bottom: .9rem;
}
.list-header h1 { margin: 0; }
.search { display: flex; gap: .4rem; align-items: center; }
.search input {
  margin-top: 0; width: 260px; padding: .45rem .65rem; font-size: .9rem;
}
/* The search button is a solid black action, not a ghost - it is the one
   affirmative control on the caseload header. */
.search .ghost {
  padding: .45rem .8rem; font-size: .9rem;
  background: var(--ink); color: #fff; border-color: var(--ink);
}
.search .ghost:hover { background: #000; border-color: #000; color: #fff; }

.pagination {
  display: flex; align-items: center; justify-content: center; gap: 1.4rem;
  margin: 1.3rem 0 .2rem; font-size: .9rem;
}
.pagination .page-edge { opacity: .45; }

.tabs {
  display: flex; gap: .3rem; flex-wrap: wrap; margin-bottom: 1rem;
  /* 2px in ink-faint, not a 1px hairline in the line colour: thick and dark
     enough to read as a divider over the background doodles. */
  border-bottom: 2px solid var(--ink-faint); padding-bottom: .6rem;
}
.tab {
  display: inline-flex; align-items: center; gap: .4rem;
  /* Full ink and the active weight, so an inactive filter still reads cleanly
     over the doodles; the active one is set apart by its pill, not by being the
     only dark or bold one. */
  font-size: .88rem; text-decoration: none; color: var(--ink); font-weight: 600;
  padding: .35rem .75rem; border-radius: 999px;
  border: 1px solid transparent; background: none;  /* works as <a> or <button> */
}
.tab:hover { background: var(--card); border-color: var(--line-strong); color: var(--ink); }
.tab--active {
  background: var(--card); border-color: var(--line-strong);
  color: var(--ink); font-weight: 600;
}
.tab-count {
  font-size: .74rem; background: var(--paper); color: var(--ink-faint);
  border-radius: 999px; padding: .05rem .4rem; min-width: 1.3em; text-align: center;
}
.tab--active .tab-count { background: var(--ink); color: #fff; }

/* --- brief technical: horizontal section rail ------------------------- */
/* A row of section tabs across the top with an underline active indicator,
   content below. Deliberately its own classes, not .tab, so the caseload's
   pill filters are left untouched. */
.section-layout { display: flex; flex-direction: column; gap: 1rem; }
/* The rail sits on a plain translucent panel - a 50% white tint, no blur.
   A frosted (backdrop-filter) version was tried and abandoned: the background
   doodles are thin, faint lines that any blur dissolves entirely, so there was
   nothing to "see through". A straight tint keeps them showing faintly beneath
   the tabs, muted rather than erased. No border, so it has no hard edge. */
.section-tabs {
  background: rgba(255, 255, 255, .3);
  border-radius: var(--radius);
  padding: .7rem .5rem .35rem;
  box-shadow: 0 1px 2px rgba(23, 25, 28, .05), 0 8px 22px rgba(23, 25, 28, .07);
}
.section-rail {
  display: flex; flex-direction: row; flex-wrap: wrap;
}
.section-tab {
  cursor: pointer; font: inherit; font-size: .92rem;
  color: var(--ink-soft); background: none; border: 0;
  border-bottom: 2px solid transparent; margin-bottom: -1px;
  padding: .5rem .85rem; border-radius: 0;
  transition: color .15s ease, background .15s ease;
}
.section-tab:hover { color: var(--ink); background: rgba(23, 25, 28, .04); }
.section-tab--active {
  color: var(--ink); font-weight: 600;
  border-bottom-color: var(--ink);
}
/* min-width:0 lets the wide tables scroll inside their own box rather than
   forcing the whole layout wider. */
.section-content { min-width: 0; }

.empty { color: var(--ink-soft); margin: 0; padding: .5rem 0; }

main { padding: 1.5rem; }
.page { max-width: 1180px; margin: 0 auto; }
.page--narrow { max-width: 660px; }

.panel {
  background: var(--card);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 1.5rem;
  margin-bottom: 1.25rem;
  box-shadow: var(--shadow);
}

.lede { color: var(--ink-soft); margin-top: 0; }
.hint { color: var(--ink-faint); font-size: .82rem; }

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

.stack { display: grid; gap: 1rem; }
label { display: block; font-weight: 550; font-size: .92rem; }
input[type=text], input[type=number], textarea, select {
  width: 100%; margin-top: .35rem;
  padding: .6rem .7rem;
  font: inherit; color: inherit;
  background: var(--card);
  border: 1px solid var(--line-strong);
  border-radius: 8px;
}
input:focus-visible, textarea:focus-visible, select:focus-visible {
  /* A soft accent ring instead of a hard 2px outline. The transparent outline
     keeps a visible focus indicator under forced-colors / high-contrast. */
  outline: 2px solid transparent;
  border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-soft);
}
label .hint { display: block; font-weight: 400; margin-top: .3rem; }

button { font: inherit; cursor: pointer; }
button.primary {
  background: var(--accent); color: #fff; border: 1px solid var(--accent);
  padding: .55rem 1.1rem; border-radius: 8px; font-weight: 550;
}
button.primary:hover { background: #19503f; }

/* Loading state for HTMX buttons that reach the network (emit). While the
   request is in flight HTMX puts `.htmx-request` on the triggering element - the
   form or the button - so the label/spinner (descendants of either) swap. The
   button is disabled by `hx-disabled-elt`, which also prevents a double submit. */
.btn-loading { display: none; align-items: center; gap: .45rem; }
.htmx-request .btn-label { display: none; }
.htmx-request .btn-loading { display: inline-flex; }
.spinner {
  width: .9em; height: .9em; border-radius: 50%;
  border: 2px solid currentColor; border-top-color: transparent;
  animation: spin .6s linear infinite;
}
@keyframes spin { to { transform: rotate(360deg); } }
button:disabled { cursor: default; opacity: .8; }
@media (prefers-reduced-motion: reduce) { .spinner { animation: none; } }
button.ghost {
  background: var(--card); color: var(--ink-soft);
  border: 1px solid var(--line-strong); padding: .55rem 1rem; border-radius: 8px;
}
button.ghost:hover { border-color: var(--ink-faint); color: var(--ink); }
button.link, .link {
  background: none; border: 0; padding: 0; cursor: pointer;
  color: var(--accent); font: inherit; font-size: .85rem;
  /* A faint underline that solidifies on hover, sat well clear of the text -
     modern and quiet, rather than a hard browser-default rule tight to the
     baseline. color-mix degrades to a plain accent underline where unsupported. */
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-decoration-color: color-mix(in srgb, var(--accent) 32%, transparent);
  text-underline-offset: 3px;
  transition: text-decoration-color .15s ease, color .15s ease;
}
button.link:hover, .link:hover {
  color: #19503f;
  text-decoration-color: currentColor;
}

/* A "back" link with a thin long left-arrow. The arrow is a masked pseudo-element
   so it takes the link's own colour and needs no per-link SVG; it nudges left on
   hover. */
.back-link {
  display: inline-flex; align-items: center; gap: .4rem;
  color: var(--accent); text-decoration: none; font-size: .85rem;
}
.back-link::before {
  content: ""; width: 17px; height: 15px; flex: none;
  background: currentColor;
  -webkit-mask: var(--arrow-left) center / contain no-repeat;
          mask: var(--arrow-left) center / contain no-repeat;
  transition: transform .15s ease;
}
.back-link:hover { text-decoration: underline; text-underline-offset: 2px; }
.back-link:hover::before { transform: translateX(-2px); }
/* A row of header links (back link + peers) with a little breathing room, set
   apart by a small haloed dot rather than a plain bullet. */
.header-links { display: flex; gap: 1.1rem; align-items: center; }
.header-dot {
  width: 5px; height: 5px; flex: none; border-radius: 50%;
  background: #000; box-shadow: 0 0 0 3px var(--paper);
}

.error {
  background: var(--blocker-soft); border: 1px solid #f0c9c6;
  color: var(--blocker); padding: .75rem 1rem; border-radius: 8px;
  margin-bottom: 1rem; font-size: .9rem; white-space: pre-wrap;
}

/* --- scheme list ------------------------------------------------------- */

/* Doodle pane: faint architectural sketches behind the whole app, fixed so the
   content scrolls over them, and masked to fade at the edges. Decorative only. */
body::before {
  content: ""; position: fixed; inset: 0; z-index: 0; pointer-events: none;
  background-image: url("../img/doodles.svg");
  background-size: 340px 340px;
  opacity: .25;
  -webkit-mask-image: radial-gradient(120% 90% at 50% 20%, #000 30%, transparent 78%);
          mask-image: radial-gradient(120% 90% at 50% 20%, #000 30%, transparent 78%);
}
/* The masthead sits above main so its address dropdown escapes over the page
   content; without the higher z-index, main (later in the DOM, same z-index)
   paints over the popover and hides it. */
.masthead { position: relative; z-index: 20; }
main { position: relative; z-index: 1; }

.pill {
  display: inline-block; padding: .12rem .55rem; border-radius: 999px;
  background: var(--info-soft); color: var(--ink-soft);
  font-size: .72rem; font-weight: 600; letter-spacing: .01em;
}
.pill--complete { background: var(--accent-soft); color: var(--accent); }
/* State pills - after the base so their colours win the cascade. */
.pill--asking { background: var(--info-soft); color: var(--ink-soft); }
.pill--ready  { background: var(--warn-soft); color: var(--warn); }
.pill--issued { background: var(--accent-soft); color: var(--accent); }

.scheme-list { list-style: none; margin: 0; padding: 0; display: grid; gap: .8rem; }

.scheme-card {
  position: relative; overflow: hidden;
  display: flex; align-items: center; justify-content: space-between; gap: 1rem;
  padding: .95rem 1.1rem;
  background: var(--card);
  border: 1px solid var(--line);
  border-radius: 14px;
  box-shadow: var(--shadow);
  transition: transform .18s ease, box-shadow .18s ease, border-color .18s ease;
  animation: card-in .5s cubic-bezier(.2,.7,.2,1) both;
  animation-delay: calc(var(--i, 0) * 45ms);
}
.scheme-card:hover {
  transform: translateY(-2px);
  border-color: var(--line-strong);
  box-shadow: 0 2px 4px rgba(23, 25, 28, .06), 0 16px 36px rgba(23, 25, 28, .11);
}
/* htmx adds this class while the card is being removed after a delete. */
.scheme-card.htmx-swapping {
  opacity: 0; transform: translateX(14px) scale(.98);
  transition: opacity .28s ease, transform .28s ease;
}

@keyframes card-in {
  from { opacity: 0; transform: translateY(10px); }
  to   { opacity: 1; transform: translateY(0); }
}

.scheme-main { min-width: 0; }
.scheme-title {
  font-weight: 650; color: var(--ink); text-decoration: none; letter-spacing: -.01em;
}
.scheme-title:hover { color: var(--accent); }
.scheme-address { color: var(--ink-faint); font-size: .82rem; margin-top: .1rem; }
.scheme-meta {
  display: flex; gap: .45rem .6rem; align-items: center; flex-wrap: wrap; margin-top: .55rem;
}
.scheme-progress { width: 120px; flex-shrink: 0; }

.scheme-aside { display: flex; align-items: center; gap: .75rem; flex-shrink: 0; }
.scheme-links { display: flex; align-items: center; gap: .9rem; }

/* Round icon buttons for row actions. */
.icon-btn {
  display: inline-flex; align-items: center; justify-content: center;
  width: 34px; height: 34px; padding: 0; border: 0; border-radius: 10px;
  background: none; color: var(--ink-faint); cursor: pointer;
  transition: background .15s ease, color .15s ease, transform .12s ease;
}
.icon-btn svg { width: 17px; height: 17px; display: block; }
.icon-btn:hover { background: var(--paper); color: var(--ink); }
.icon-btn:active { transform: scale(.88); }
.scheme-delete:hover { background: var(--blocker-soft); color: var(--blocker); }

/* The in-page confirmation that stands in for the native confirm() (see
   base.html), so a delete is confirmed without the browser stamping the page
   origin across the top of a system dialog. */
.confirm-dialog {
  border: 1px solid var(--line-strong); border-radius: var(--radius);
  padding: 1.3rem; width: min(92vw, 400px);
  background: var(--card); color: var(--ink); box-shadow: var(--shadow);
}
.confirm-dialog::backdrop { background: rgba(23, 25, 28, .38); }
.confirm-message { margin: 0 0 1.2rem; font-size: .95rem; line-height: 1.5; }
.confirm-actions { display: flex; gap: .6rem; justify-content: flex-end; }
.confirm-dialog .danger {
  background: var(--blocker); color: #fff; border: 1px solid var(--blocker);
  padding: .55rem 1.1rem; border-radius: 8px; font-weight: 550;
}
.confirm-dialog .danger:hover { background: #872626; }

/* --- header meters ----------------------------------------------------- */

.workspace-header {
  display: flex; justify-content: space-between; align-items: center;
  gap: 1.5rem; flex-wrap: wrap; margin: 0;
  background: var(--card); border: 1px solid var(--line);
  border-radius: var(--radius); padding: .85rem 1.1rem; box-shadow: var(--shadow);
}
.badges { display: flex; gap: .5rem; flex-wrap: wrap; align-items: center; }
/* The objective, as plain text - the thing the rest of the header is about. */
.objective {
  font-weight: 700; font-size: 1rem; color: var(--ink);
  letter-spacing: -.01em; margin-right: .3rem;
}
.badge {
  font-size: .82rem; padding: .28rem .6rem; border-radius: 999px;
  border: 1px solid var(--line-strong); background: var(--paper);
}
.badge--route { background: var(--accent-soft); border-color: #c7ded6; color: var(--accent); }
.badge--route em { font-style: normal; color: var(--ink-faint); margin-left: .35rem; }
/* Replaces the questions donut once a brief exists: plain black, underlined,
   with its arrow - a clear way through to the brief rather than a soft accent. */
.header-brief-link {
  flex: none; font-size: .92rem; font-weight: 600; color: var(--ink);
  text-decoration: underline; text-underline-offset: 3px;
}
.header-brief-link:hover { text-decoration-thickness: 2px; }

/* Question progress as an inline donut. `pathLength="100"` lets the arc be set
   straight from the percentage; the count lives in the title for hover/a11y. */
.progress-donut { display: flex; align-items: center; gap: .45rem; flex: none; }
.progress-donut svg { width: 22px; height: 22px; }
.donut-track { stroke: var(--line); }
.donut-value { stroke: var(--ink); stroke-linecap: round; transition: stroke-dasharray .3s ease; }
.donut-label {
  font-size: .7rem; text-transform: uppercase; letter-spacing: .04em;
  color: var(--ink-faint);
}

/* Shared progress bar for the caseload rows (the header no longer uses it). */
.meter-track { display: block; height: 5px; background: var(--line); border-radius: 999px; overflow: hidden; }
.meter-fill { display: block; height: 100%; background: var(--ink); border-radius: 999px; }

/* --- workspace --------------------------------------------------------- */

.workspace {
  display: grid; grid-template-columns: minmax(0, 1fr) 340px; gap: 1.25rem;
  grid-template-areas: "head head" "main rail";
  max-width: 1180px; margin: 0 auto; align-items: start;
}
/* Once anything has been answered, a quiet log column opens on the left so the
   answered questions no longer stack above and push the live card down. */
.workspace--has-log {
  grid-template-columns: 232px minmax(0, 1fr) 340px;
  grid-template-areas: "head head head" "log main rail";
  max-width: 1260px;
}
.column-main { grid-area: main; }
/* The rail's sticky wrapper takes the grid slot; the panel scrolls inside it so
   the custom scroll handle can be pinned to the panel edge (see .rail-wrap). */
.rail-wrap { grid-area: rail; position: sticky; top: 1rem; }
.workspace-log { grid-area: log; }
/* The header spans every column, so its width runs from the left panel to the
   right whatever the column count. */
.workspace-header { grid-area: head; }
@media (max-width: 940px) {
  /* Stacked: header, live card first, constraints, then the log last - least
     in the way on a narrow screen. */
  .workspace, .workspace--has-log {
    grid-template-columns: 1fr;
    grid-template-areas: "head" "main" "rail" "log";
  }
}

.out-of-scope {
  background: var(--blocker-soft); border: 1px solid #f0c9c6;
  border-left: 4px solid var(--blocker);
  border-radius: var(--radius); padding: .85rem 1rem; margin-bottom: 1.25rem;
  font-size: .88rem; color: var(--ink-soft);
}
.out-of-scope strong { color: var(--blocker); }

.track-note {
  background: var(--unknown-soft); border: 1px solid #ccd8ec;
  border-radius: var(--radius); padding: .85rem 1rem; margin-bottom: 1.25rem;
  font-size: .88rem; color: var(--ink-soft);
}
.track-note strong { color: var(--unknown); }
.track-note .link { margin-left: .35rem; }

.handoff {
  display: flex; gap: 1rem; align-items: center; justify-content: space-between;
  background: var(--unknown-soft); border: 1px dashed #ccd8ec;
  border-radius: var(--radius); padding: .85rem 1rem; margin-bottom: 1rem;
}
.handoff p { margin: .25rem 0 0; }
.ghost-link {
  white-space: nowrap; text-decoration: none; font-size: .88rem; font-weight: 550;
  border: 1px solid var(--unknown); color: var(--unknown);
  padding: .5rem .9rem; border-radius: 8px; background: var(--card);
}
.ghost-link:hover { background: var(--unknown); color: #fff; }
.pill--survey { background: var(--unknown-soft); color: var(--unknown); }

/* The answered-questions log. On its own panel, matching the constraints rail
   on the right, so the two side columns read as a matched pair around the live
   card. Muted type inside keeps it a record to glance at, not a second thing
   to attend to. */
.workspace-log {
  background: var(--card); border: 1px solid var(--line);
  border-radius: var(--radius); padding: 1.1rem; box-shadow: var(--shadow);
  position: sticky; top: 1rem;
  max-height: calc(100vh - 2rem); overflow-y: auto;
}

/* The answered-column log keeps a slim native scrollbar - a rounded thumb inset
   from the edge, darkening on hover. (The constraints rail has its own custom
   rail-and-handle instead; see .rail-wrap.) Firefox uses the two properties on
   the panel; WebKit the pseudo-elements. */
.workspace-log {
  scrollbar-width: thin;
  scrollbar-color: var(--line-strong) transparent;
}
.workspace-log::-webkit-scrollbar { width: 10px; }
.workspace-log::-webkit-scrollbar-track { background: transparent; }
.workspace-log::-webkit-scrollbar-thumb {
  background: var(--line-strong);
  border-radius: 999px;
  border: 3px solid var(--card);   /* inset from the edge, so the thumb reads slim */
}
.workspace-log:hover::-webkit-scrollbar-thumb { background: var(--ink-faint); }

.log-title {
  font-size: .8rem; text-transform: uppercase; letter-spacing: .06em;
  color: var(--ink-faint); display: flex; align-items: center; gap: .4rem;
  margin: 0 0 .55rem;
}
.log-groups { display: grid; gap: .1rem; }

/* A stage header: the topic run it folds, with a rotating caret and a count.
   The whole row is the toggle. */
.log-group-head {
  width: 100%; display: flex; align-items: center; justify-content: space-between;
  gap: .5rem; background: none; border: 0; cursor: pointer;
  padding: .35rem .4rem; border-radius: 6px; color: var(--ink);
}
.log-group-head:hover, .log-group-head:focus-visible { background: var(--paper); outline: none; }
.log-group-name {
  display: flex; align-items: center; gap: .45rem;
  font-size: .82rem; font-weight: 500;
}
/* A right-pointing caret that turns to point down when the stage is open. */
.log-chevron {
  width: 0; height: 0; flex: none;
  border-left: 4px solid var(--ink-faint);
  border-top: 3.5px solid transparent; border-bottom: 3.5px solid transparent;
  transition: transform .18s ease;
}
.log-chevron.is-open { transform: rotate(90deg); }
/* A single-question stage has no fold, so its row carries an invisible caret
   in the same place - keeping its label lined up with the stages that do. */
.log-chevron--none { visibility: hidden; }

/* The fold: an animatable 0fr -> 1fr grid row, so height glides on open and
   close with no measuring. The single child clips and can shrink to nothing.
   visibility flips to hidden only after the close finishes (and back to visible
   at once on open), so a folded stage's rows leave the tab order and the screen
   reader rather than sitting clipped-but-focusable. */
.log-group-body {
  display: grid; grid-template-rows: 0fr; visibility: hidden;
  transition: grid-template-rows .22s ease, visibility 0s linear .22s;
}
.log-group-body.is-open {
  grid-template-rows: 1fr; visibility: visible;
  transition: grid-template-rows .22s ease, visibility 0s;
}
.log-group-body > .log-list { overflow: hidden; min-height: 0; }

.log-list { list-style: none; margin: 0; padding: 0; display: grid; gap: .05rem; }
.log-edit {
  width: 100%; text-align: left; cursor: pointer;
  background: none; border: 0;
  padding: .28rem .5rem .28rem 1.05rem; border-radius: 6px;
}
.log-edit:hover, .log-edit:focus-visible { background: var(--paper); outline: none; }
.log-q {
  font-size: .78rem; color: var(--ink-soft); line-height: 1.3;
  display: block; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.log-edit:hover .log-q, .log-edit:focus-visible .log-q { color: var(--ink); }

/* The question open in the card right now, marked with an accent left edge so
   it is clear which row the card belongs to. Every row carries a transparent
   edge of the same width, so lighting one up shifts nothing. */
.log-edit, .log-group-head { border-left: 2px solid transparent; }
.log-edit.is-active, .log-group-head.log-solo.is-active {
  border-left-color: var(--accent);
  border-radius: 0 6px 6px 0;
}
.log-edit.is-active .log-q { color: var(--accent); font-weight: 500; }
.log-group-head.log-solo.is-active .log-group-name { color: var(--accent); }

.slot-type {
  font-size: .62rem; letter-spacing: .06em; padding: .1rem .38rem;
  border-radius: 4px; background: var(--info-soft); color: var(--ink-soft);
  white-space: nowrap;
}
.slot-type--preferred { background: var(--accent-soft); color: var(--accent); }
.slot-type--defaulted { background: var(--warn-soft); color: var(--warn); }
.slot-type--professional { background: var(--unknown-soft); color: var(--unknown); }

/* --- cards ------------------------------------------------------------- */

.card {
  background: var(--card); border: 1px solid var(--line-strong);
  border-radius: var(--radius); padding: 1.4rem; box-shadow: var(--shadow);
}
.card-head { margin-bottom: 1.1rem; }
.card-stage {
  display: inline-block; font-size: .68rem; text-transform: uppercase;
  letter-spacing: .07em; color: var(--ink-faint); margin-bottom: .4rem;
}
.card-stage--professional { color: var(--unknown); font-weight: 600; }
.card-help { color: var(--ink-soft); font-size: .9rem; margin: .4rem 0 0; }

/* The floor-plan upload card. The whole dashed panel is the file control - the
   label wraps the input, so a click anywhere opens the picker; the native input
   is tucked away but kept focusable, and focus lands on the panel. */
.upload-drop {
  display: flex; align-items: center; gap: .9rem; margin-top: 1rem;
  border: 1.5px dashed var(--line-strong); border-radius: 10px;
  padding: 1.1rem 1.2rem; cursor: pointer; background: var(--paper);
  transition: border-color .15s ease, background .15s ease;
}
.upload-drop:hover { border-color: var(--accent); background: var(--accent-soft); }
.upload-drop:focus-within {
  border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-soft);
}
.upload-drop input[type=file] { position: absolute; width: 1px; height: 1px; opacity: 0; }
.upload-drop-plus {
  flex: none; width: 34px; height: 34px; border-radius: 8px;
  background: var(--card); border: 1px solid var(--line-strong);
  display: grid; place-items: center; font-size: 1.35rem; color: var(--ink-faint);
}
.upload-drop-text { display: grid; gap: .1rem; font-weight: 500; font-size: .92rem; }
.upload-drop-text .hint { font-weight: 400; }
.upload-current { font-size: .84rem; color: var(--ink-soft); margin: .65rem 0 0; }

.postcode-row { display: flex; gap: .5rem; }
.postcode-found, .postcode-manual { display: grid; gap: .85rem; }
.postcode-summary {
  display: flex; gap: .5rem; align-items: baseline; flex-wrap: wrap;
  margin: 0; padding: .5rem .7rem; border-radius: 8px;
  background: var(--accent-soft); border: 1px solid #c7ded6; font-size: .9rem;
}

.evidence {
  border: 1px solid #c7ded6; background: var(--accent-soft);
  border-radius: 8px; padding: .75rem .9rem; margin-bottom: 1.1rem;
  font-size: .88rem;
}
.evidence-head { display: flex; gap: .5rem; align-items: baseline; flex-wrap: wrap; }
/* The placeholder while a deferred lookup (the TPO register) loads: muted, no
   coloured fill, and its badge breathes so it reads as working, not settled. */
.evidence--loading { background: transparent; border-color: var(--line); }
.evidence--loading .evidence-badge {
  background: var(--ink-faint); animation: evidence-pulse 1s ease-in-out infinite;
}
@keyframes evidence-pulse { 50% { opacity: .45; } }
.evidence-badge {
  font-size: .66rem; text-transform: uppercase; letter-spacing: .06em;
  background: var(--accent); color: #fff; padding: .1rem .4rem; border-radius: 4px;
}
.evidence p { margin: .45rem 0 0; color: var(--ink-soft); }
.evidence-list { list-style: none; margin: .6rem 0 0; padding: 0; display: grid; gap: .3rem; }
.evidence-list li {
  display: flex; gap: .55rem; align-items: baseline; flex-wrap: wrap;
  background: var(--card); border-radius: 6px; padding: .35rem .55rem;
}
.evidence-grade {
  font-size: .68rem; text-transform: uppercase; letter-spacing: .05em;
  background: var(--warn-soft); color: var(--warn);
  padding: .08rem .4rem; border-radius: 4px; white-space: nowrap;
}
.evidence-name { flex: 1; min-width: 0; }
.evidence-source {
  margin-top: .5rem !important; font-size: .78rem !important;
  color: var(--ink-faint) !important; font-style: italic;
}
/* Nothing was settled, so the card must not look like an answer. */
.evidence--no_data { background: var(--unknown-soft); border-color: #ccd8ec; }
.evidence--no_data .evidence-badge { background: var(--unknown); }
/* An outline off the height model is indicative, not surveyed - tinted like
   the unknowns rail so it reads as awaiting confirmation, not settled. */
.evidence--site { background: var(--unknown-soft); border-color: #ccd8ec; }
.evidence--site .evidence-badge { background: var(--unknown); }
/* A protected tree is a refusal risk, so its evidence carries the warn tint;
   a clear result keeps the default settled green; no_data is handled above. */
.evidence--protected { background: var(--warn-soft); border-color: #ecdcae; }
.evidence--protected .evidence-badge { background: var(--warn); }

.how-to {
  margin-top: .75rem; border: 1px solid var(--line-strong); border-radius: 8px;
  background: var(--paper); padding: .55rem .75rem; font-size: .88rem;
}
.how-to summary {
  cursor: pointer; font-weight: 550; color: var(--accent);
  list-style: none; display: flex; align-items: center; gap: .4rem;
}
.how-to summary::-webkit-details-marker { display: none; }
.how-to summary::before {
  content: "→"; transition: transform .15s; display: inline-block;
}
.how-to[open] summary::before { transform: rotate(90deg); }
.how-to p { margin: .5rem 0 0; color: var(--ink-soft); }
.card-actions {
  margin-top: 1.25rem; display: flex; gap: .6rem; align-items: center; flex-wrap: wrap;
}
.card-actions .hint { flex-basis: 100%; margin: 0; }

.options { display: grid; gap: .5rem; }
.options--inline { grid-template-columns: repeat(auto-fit, minmax(190px, 1fr)); }
.option {
  display: flex; gap: .65rem; align-items: flex-start;
  border: 1px solid var(--line-strong); border-radius: 8px;
  padding: .65rem .8rem; cursor: pointer; font-weight: 400;
  background: var(--card); transition: border-color .12s, background .12s;
}
.option:hover { border-color: var(--ink-faint); }
.option:has(input:checked), .option--chosen {
  border-color: var(--accent); background: var(--accent-soft);
}
.option input { margin-top: .25rem; accent-color: var(--accent); }
.option-body { display: grid; gap: .15rem; }
.option-label { font-weight: 500; }
.option-help { font-size: .82rem; color: var(--ink-soft); }
.option--unknown { border-style: dashed; }
.option--muted { opacity: .45; cursor: default; }
/* An option a prior answer has ruled out - kept visible so the client sees it
   exists and why, but not selectable. */
.option--ruled-out {
  opacity: .5; cursor: not-allowed; background: var(--card);
  border-style: dashed;
}
.option--ruled-out:hover { border-color: var(--line-strong); }
.option--ruled-out input { cursor: not-allowed; }
.options-note {
  margin: 0 0 .7rem; padding: .55rem .7rem;
  border-left: 3px solid var(--accent);
  background: var(--accent-soft); border-radius: 4px;
  font-size: .88rem; color: var(--ink-soft);
}

.number-field { display: flex; align-items: center; gap: .6rem; max-width: 260px; }
.number-field input { margin-top: 0; }
.unit { color: var(--ink-faint); }

/* --- priority list ----------------------------------------------------- */

.priority-list { display: grid; gap: .1rem; }
.priority-head, .priority-row {
  display: grid; grid-template-columns: minmax(0, 1fr) 68px 68px 88px;
  align-items: center; gap: .5rem;
}
.priority-head span { font-size: .7rem; text-transform: uppercase; letter-spacing: .05em;
  color: var(--ink-faint); text-align: center; padding-bottom: .35rem; }
.priority-head span:first-child { text-align: left; }
.priority-row { padding: .5rem 0; border-top: 1px solid var(--line); }
.priority-row--suggested { background: linear-gradient(90deg, var(--warn-soft), transparent 60%); }
.priority-label { display: grid; gap: .15rem; font-weight: 450; }
.priority-name { display: block; }
.priority-help { font-size: .8rem; color: var(--ink-soft); }
.priority-cell { display: flex; justify-content: center; margin: 0; }
.priority-cell input { accent-color: var(--accent); width: 17px; height: 17px; }
.tag {
  display: inline-block; font-size: .66rem; padding: .05rem .35rem;
  border-radius: 4px; margin-left: .35rem; vertical-align: 1px;
}
.tag--ours { background: var(--warn-soft); color: var(--warn); }
.tag--dual { background: var(--unknown-soft); color: var(--unknown); }

/* --- preference / fallback --------------------------------------------- */

.pref { display: grid; gap: 1.1rem; }
.pref-block { border: 0; padding: 0; margin: 0; }
.pref-block legend {
  padding: 0; font-size: .78rem; text-transform: uppercase;
  letter-spacing: .06em; color: var(--ink-faint); margin-bottom: .45rem;
}
.pref-block--fallback { border-top: 1px dashed var(--line-strong); padding-top: 1rem; }
.pref-note { margin: -.25rem 0 .5rem; font-size: .84rem; color: var(--ink-soft); }

/* --- rank -------------------------------------------------------------- */

.rank { list-style: none; margin: 0; padding: 0; display: grid; gap: .45rem; counter-reset: rung; }
.rank-row {
  display: grid; grid-template-columns: 14px 28px minmax(0, 1fr) auto;
  gap: .7rem; align-items: center;
  border: 1px solid var(--line-strong); border-radius: 8px; padding: .6rem .75rem;
  background: var(--card); cursor: grab; user-select: none;
}
.rank-row:active { cursor: grabbing; }
/* The picked-up row is the placeholder the others glide around; leave the
   arrow controls interactive so a drag started by mistake is not a trap. */
.rank-row--dragging { opacity: .4; border-style: dashed; }
.rank-grip { color: var(--ink-faint); font-size: 1rem; line-height: 1; }
.rank-index {
  width: 24px; height: 24px; border-radius: 999px; background: var(--ink); color: #fff;
  display: grid; place-items: center; font-size: .78rem; font-weight: 600;
}
.rank-body { display: grid; gap: .1rem; }
.rank-label { font-weight: 500; }
.rank-reason { font-size: .8rem; color: var(--ink-soft); }
.rank-controls { display: flex; gap: .25rem; }
.rank-controls button {
  border: 1px solid var(--line-strong); background: var(--card);
  border-radius: 6px; width: 30px; height: 30px; line-height: 1;
}
.rank-controls button:disabled { opacity: .35; cursor: default; }
.rank-empty { color: var(--ink-soft); }

/* --- right rail -------------------------------------------------------- */

.column-rail {
  background: var(--card); border: 1px solid var(--line);
  border-radius: var(--radius); padding: 1.1rem; box-shadow: var(--shadow);
  max-height: calc(100vh - 2rem); overflow-y: auto;
  /* Native bar hidden - a custom rail-and-handle is drawn over it (JS pins the
     handle to scroll position). Falls back to no visible bar if the script does
     not run, which still scrolls by wheel and touch. */
  scrollbar-width: none;
}
.column-rail::-webkit-scrollbar { width: 0; height: 0; }

/* The custom scroll indicator: a thin rail with a short fixed capsule handle
   riding it, shown only when the panel overflows. The handle is draggable and
   tracks the wheel; JS sets its height and top. */
.rail-track, .rail-thumb {
  position: absolute; right: 6px; opacity: 0;
  transition: opacity .15s ease;
}
.rail-wrap.has-scroll .rail-track, .rail-wrap.has-scroll .rail-thumb { opacity: 1; }
.rail-track {
  top: 8px; bottom: 8px; width: 1px;
  background: var(--line-strong); border-radius: 999px; pointer-events: none;
}
.rail-thumb {
  width: 6px; right: 3.5px;   /* centred over the 1px rail */
  background: var(--ink-faint); border-radius: 999px;
  cursor: grab; touch-action: none;
}
.rail-thumb:hover, .rail-thumb.is-drag { background: var(--ink-soft); }
.rail-thumb.is-drag { cursor: grabbing; }
.rail-title { display: flex; align-items: center; gap: .5rem; font-size: .8rem;
  text-transform: uppercase; letter-spacing: .06em; color: var(--ink-faint); }
.rail-title .count {
  background: var(--ink); color: #fff; border-radius: 999px;
  padding: .05rem .45rem; font-size: .72rem; letter-spacing: 0;
}
.rail-empty, .rail-note { font-size: .85rem; color: var(--ink-soft); }

.flag-group { margin-top: 1rem; }
.flag-group h3 {
  display: flex; align-items: center; gap: .35rem;
  font-size: .74rem; text-transform: uppercase; letter-spacing: .06em;
  margin: 0 0 .45rem;
}
.flag-group--blocker h3 { color: var(--blocker); }
.flag-group--warn h3 { color: var(--warn); }
.flag-group--unknown h3, .flag-group--survey h3 { color: var(--unknown); }
.flag-group--info h3 { color: var(--ink-faint); }
/* The group icon carries severity by shape, inheriting the heading's colour. */
.grp-icon { width: 14px; height: 14px; flex: none; }

/* No coloured edge here: severity is the icon and the heading. The soft tint
   keeps a card scannable without a bar down its side. The title is always shown;
   the reasoning folds behind it, so the rail reads as a list of what fired. */
.flag {
  margin-bottom: .5rem; border-radius: 6px; background: var(--info-soft);
  overflow: hidden;   /* clip the folding body to the rounded corners */
}
.flag-group--blocker .flag { background: var(--blocker-soft); }
.flag-group--warn .flag { background: var(--warn-soft); }
.flag-group--unknown .flag { background: var(--unknown-soft); }
.flag-head {
  width: 100%; display: flex; gap: .4rem; align-items: center;
  font-size: .86rem; text-align: left; cursor: pointer;
  background: none; border: 0; color: inherit; padding: .5rem .7rem;
}
.flag-head strong { font-weight: 600; }
.flag-id {
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: .72rem; color: var(--ink-faint); white-space: nowrap;
}
/* A right-pointing caret that turns down when the flag is open. */
.flag-caret {
  margin-left: auto; flex: none; width: 0; height: 0;
  border-left: 4px solid var(--ink-faint);
  border-top: 3.5px solid transparent; border-bottom: 3.5px solid transparent;
  transition: transform .18s ease;
}
.flag-caret.is-open { transform: rotate(90deg); }
/* The fold: the same animatable 0fr -> 1fr grid row the log uses, hiding the
   detail from the tab order and the screen reader once it is closed. */
.flag-body {
  display: grid; grid-template-rows: 0fr; visibility: hidden;
  transition: grid-template-rows .2s ease, visibility 0s linear .2s;
}
.flag-body.is-open {
  grid-template-rows: 1fr; visibility: visible;
  transition: grid-template-rows .2s ease, visibility 0s;
}
.flag-body-clip { overflow: hidden; min-height: 0; }
.flag-body-inner { padding: 0 .7rem .55rem; }
.flag p { margin: .3rem 0 0; font-size: .84rem; color: var(--ink-soft); }
.flag-body-inner p:first-child { margin-top: 0; }
.flag-ref { font-size: .74rem !important; color: var(--ink-faint) !important; font-style: italic; }

/* The admitted-gap list, each item a way back to its question. */
.jump-list { list-style: none; margin: 0; padding: 0; display: grid; gap: .3rem; }
.jump {
  width: 100%; font: inherit; cursor: pointer; text-align: left;
  display: flex; justify-content: space-between; align-items: center; gap: .5rem;
  font-size: .86rem; padding: .35rem .55rem; border: 0; border-radius: 6px;
  background: var(--unknown-soft); color: var(--ink);
}
.jump:hover, .jump:focus-visible { background: var(--unknown); color: #fff; outline: none; }
.jump-cue { font-size: .72rem; color: var(--unknown); white-space: nowrap; }
.jump:hover .jump-cue, .jump:focus-visible .jump-cue { color: #fff; }

.survey-list { list-style: none; margin: 0; padding: 0; display: grid; gap: .3rem; }
.survey-list li {
  display: flex; justify-content: space-between; gap: .5rem;
  font-size: .86rem; padding: .3rem .5rem; background: var(--unknown-soft);
  border-radius: 6px;
}

/* --- brief ------------------------------------------------------------- */

.brief-hero h1 { margin-bottom: .35rem; }
.brief-hero .lede { margin-bottom: 0; }

/* Route verdict - the headline outcome, banded so it reads first. */
.verdict {
  margin-top: 1.25rem; padding: .9rem 1.1rem;
  background: var(--accent-soft); border-radius: 12px;
}
.verdict-label {
  font-size: .72rem; text-transform: uppercase; letter-spacing: .06em;
  font-weight: 600; color: var(--accent);
}
.verdict-body {
  display: flex; align-items: baseline; gap: .6rem; flex-wrap: wrap; margin-top: .3rem;
}
.verdict-route { font-size: 1.25rem; letter-spacing: -.01em; color: var(--ink); }
.verdict .hint { margin: .5rem 0 0; }

.brief-card h2 { font-size: 1.05rem; margin-bottom: .9rem; }

/* Rooms as rows: name (+ optional note) left, a priority pill right. */
.room-list { list-style: none; margin: 0; padding: 0; display: grid; gap: .5rem; }
.room-item {
  display: flex; align-items: center; justify-content: space-between; gap: .75rem;
  padding: .6rem .8rem; background: var(--paper);
  border: 1px solid var(--line); border-radius: 10px;
}
.room-main { display: flex; flex-direction: column; gap: .1rem; min-width: 0; }
.room-name { font-weight: 550; }
.room-note { font-size: .8rem; color: var(--ink-faint); }

/* Relaxation ladder as numbered steps. */
.step-list { list-style: none; margin: 0; padding: 0; display: grid; gap: .7rem; }
.step { display: flex; gap: .7rem; align-items: flex-start; }
.step-n {
  flex: none; width: 24px; height: 24px; border-radius: 50%;
  background: var(--accent-soft); color: var(--accent);
  font-size: .8rem; font-weight: 600;
  display: inline-flex; align-items: center; justify-content: center;
}
.step-body { display: flex; flex-direction: column; gap: .1rem; }
.step-reason { font-size: .82rem; color: var(--ink-faint); }

/* Survey items as chips; a clear positive line when there are none. */
.chip-row { display: flex; flex-wrap: wrap; gap: .4rem; }
.chip {
  font-size: .82rem; padding: .25rem .6rem; border-radius: 999px;
  background: var(--info-soft); color: var(--ink-soft);
}
.brief-clear { margin: 0; color: var(--accent); font-size: .9rem; }
.brief-clear::before { content: "\2713 "; font-weight: 700; }

.brief-next p { margin: 0 0 .5rem; }
.brief-next .hint { margin: 0; }
.brief-foot {
  display: flex; justify-content: space-between; align-items: baseline;
  gap: 1rem; margin: .25rem .25rem 0;
}
/* --- site plan --------------------------------------------------------- */

.siteplan { margin: .6rem 0 0; }
/* A fixed frame height with the default xMidYMid meet, so the drawing scales
   to fit and centres inside it. Sizing by width instead would give a terrace
   plot - twelve metres across and thirty-five deep - a frame three times the
   height of the page it sits on. */
.siteplan-svg {
  display: block; width: 100%; height: 380px; margin: 0 auto;
  background: var(--paper);
  border: 1px solid var(--line);
  border-radius: 6px;
  padding: .4rem;
  box-sizing: border-box;
}
/* An outline, not a filled shape: a hairline kept constant with
   non-scaling-stroke, so the boundary reads the same whether the plot renders
   at 150px or 760px, and the paper shows through inside it. */
.siteplan-plot {
  fill: none; stroke: var(--ink);
  stroke-width: 1px; vector-effect: non-scaling-stroke;
}
/* Shaded, not outlined-and-white: it must read as an approximate footprint,
   never as a surveyed line to match the crisp title boundary. */
.siteplan-building {
  fill: var(--ink); fill-opacity: .14;
  stroke: var(--ink); stroke-opacity: .55;
  stroke-width: 1px; vector-effect: non-scaling-stroke;
}
.siteplan-point { fill: var(--ink); }
.siteplan-number { fill: var(--ink); font-family: inherit; font-weight: 650; }
.siteplan-north path, .siteplan-bar path {
  stroke: var(--ink-soft); stroke-linecap: square;
}
.siteplan-bar text { fill: var(--ink-soft); font-family: inherit; }
.siteplan figcaption { margin-top: .55rem; display: grid; gap: .4rem; }
.siteplan figcaption p { margin: 0; font-size: .86rem; color: var(--ink-soft); }
.siteplan figcaption .siteplan-dims { font-weight: 550; color: var(--ink); }

/* Technical view: caption beside a full-height drawing, not stacked above it.
   Scoped with `--split` because the client copy's `.siteplan` also holds the
   orientation picker, which must not become a stray grid column. The SVG's
   inline max-width cap is lifted so it fills the column and runs full height. */
@media (min-width: 760px) {
  .siteplan--split {
    display: grid; grid-template-columns: minmax(0, 1fr);
    gap: 1.5rem; align-items: start; margin-top: .6rem;
  }
  .siteplan--split figcaption { order: -1; margin-top: 0; }  /* caption to the left */
  .siteplan--split .siteplan-frame { min-width: 0; }
  .siteplan--split .siteplan-svg {
    height: min(74vh, 700px); max-width: none !important;
  }
}

/* Click-to-enlarge. The inline plan is a button; tapping it reopens the same
   vector at full size, so a deep plot that renders as a sliver stays readable
   on demand. */
.siteplan-frame { position: relative; }
.siteplan-zoom { all: unset; display: block; width: 100%; cursor: zoom-in; }
.siteplan-zoom:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; }
.siteplan-zoom-cue {
  position: absolute; right: .55rem; bottom: .55rem;
  font-size: .72rem; color: var(--ink-soft);
  background: var(--paper); border: 1px solid var(--line);
  border-radius: 5px; padding: .1rem .45rem;
  opacity: 0; transition: opacity .15s ease; pointer-events: none;
}
.siteplan-zoom:hover .siteplan-zoom-cue,
.siteplan-zoom:focus-visible .siteplan-zoom-cue { opacity: 1; }

.siteplan-lightbox {
  position: fixed; inset: 0; z-index: 1000;
  display: grid; place-items: center; padding: 3vmin;
  background: rgba(15, 18, 22, .72); cursor: zoom-out;
}
/* The inner box carries the plot's own aspect ratio (--fw is the inline frame
   width against a 380 height), so the drawing fills it edge to edge and grows
   to whichever of the viewport's dimensions binds first. */
.siteplan-lightbox-inner {
  cursor: default;
  width: min(92vw, calc(92vh * var(--fw) / 380));
  height: min(92vh, calc(92vw * 380 / var(--fw)));
}
.siteplan-lightbox-inner svg.siteplan-svg {
  width: 100%; height: 100%; max-width: none;
  background: var(--paper); box-sizing: border-box;
  border: 1px solid var(--line); border-radius: 8px; padding: 1rem;
  box-shadow: 0 14px 50px rgba(0, 0, 0, .45);
}
.siteplan-lightbox-close {
  all: unset; cursor: pointer; position: absolute; top: 2.2vmin; right: 2.8vmin;
  width: 2.2rem; height: 2.2rem; border-radius: 50%;
  display: grid; place-items: center;
  font-size: 1.7rem; line-height: 1; color: #fff; background: rgba(0, 0, 0, .35);
}
.siteplan-lightbox-close:hover { background: rgba(0, 0, 0, .55); }
.siteplan-lightbox-close:focus-visible { outline: 2px solid #fff; outline-offset: 2px; }
.siteplan-withheld {
  border-left: 3px solid var(--line-strong); padding: .4rem .7rem;
  background: var(--paper); border-radius: 0 6px 6px 0;
}
.siteplan-orient {
  margin-top: .7rem; padding: .7rem .8rem;
  background: var(--accent-soft); border: 1px solid #c7ded6; border-radius: 8px;
}
.siteplan-orient p { margin: 0 0 .5rem; font-size: .86rem; color: var(--ink-soft); }
.siteplan-orient .compass {
  display: grid; grid-template-columns: repeat(4, 1fr); gap: .35rem;
}
.siteplan-orient .compass button {
  font: inherit; font-size: .82rem; cursor: pointer;
  padding: .4rem .2rem; border-radius: 6px;
  background: var(--card); border: 1px solid var(--line-strong); color: var(--ink);
}
.siteplan-orient .compass button:hover {
  border-color: var(--accent); color: var(--accent);
}
.siteplan-orient .compass button.chosen {
  background: var(--accent); border-color: var(--accent); color: #fff;
}
.orient-approve {
  font: inherit; font-weight: 600; cursor: pointer; margin-bottom: .6rem;
  background: var(--accent); color: #fff; border: 1px solid var(--accent);
  padding: .5rem 1rem; border-radius: 8px;
}
.orient-approve:hover { background: #19503f; }

.caveats { list-style: none; margin: .6rem 0 0; padding: 0; display: grid; gap: .7rem; }
.caveats li {
  border-left: 3px solid var(--line-strong); padding: .5rem .8rem;
  background: var(--paper); border-radius: 0 6px 6px 0;
}
.caveat-head { display: flex; gap: .45rem; align-items: baseline; flex-wrap: wrap; }
.caveat-id {
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: .72rem; color: var(--ink-faint); white-space: nowrap;
}
.caveat-owner {
  font-size: .68rem; text-transform: uppercase; letter-spacing: .05em;
  padding: .08rem .4rem; border-radius: 4px; white-space: nowrap;
}
.caveat-owner--designer { background: var(--unknown-soft); color: var(--unknown); }
.caveat-owner--client { background: var(--warn-soft); color: var(--warn); }
.caveats p { margin: .3rem 0 0; font-size: .86rem; color: var(--ink-soft); }

/* --- technical tables -------------------------------------------------- */

.table-scroll { overflow-x: auto; margin: 0 -.25rem; }
table.data { width: 100%; border-collapse: collapse; font-size: .88rem; }
table.data th, table.data td {
  text-align: left; padding: .5rem .6rem; vertical-align: top;
  border-bottom: 1px solid var(--line);
}
table.data thead th {
  font-size: .7rem; text-transform: uppercase; letter-spacing: .05em;
  color: var(--ink-faint); font-weight: 600; white-space: nowrap;
}
table.data tbody tr:last-child th, table.data tbody tr:last-child td { border-bottom: 0; }
table.data tbody th[scope="row"] { color: var(--ink-soft); font-weight: 500; width: 40%; }
table.data td.nowrap { white-space: nowrap; }
/* The two reasons a nearby application is relevant, each its own colour so they
   read apart at a glance: proximity (close by) vs the same kind of work. Carried
   by the pill alone - the row itself is not tinted. */
.pill--proximity, .pill--type {
  margin-left: .35rem; font-size: .62rem; text-transform: none; letter-spacing: 0;
}
.pill--proximity { background: var(--unknown-soft); color: var(--unknown); }
.pill--type { background: var(--warn-soft); color: var(--warn); }
.app-pager {
  display: flex; align-items: center; gap: 1rem; justify-content: flex-end;
  margin-top: .7rem; font-size: .84rem; color: var(--ink-soft);
}
.app-pager button {
  border: 1px solid var(--line-strong); background: var(--paper);
  border-radius: 6px; padding: .3rem .7rem; cursor: pointer; color: var(--ink);
}
.app-pager button:hover:not(:disabled) { border-color: var(--accent); color: var(--accent); }
.app-pager button:disabled { opacity: .4; cursor: default; }

/* A nearby application shown from the local mirror. */
.app-detail h1 { font-size: 1.35rem; margin: .5rem 0 .3rem; }
.app-decision {
  display: inline-block; margin: 0 0 1rem; padding: .3rem .8rem;
  border-radius: 999px; font-weight: 600; font-size: .9rem;
  background: var(--card); border: 1px solid var(--line-strong); color: var(--ink);
}
.app-decision--application-permitted, .app-decision--no-objection,
.app-decision--prior-approval-not-required {
  background: var(--accent-soft); border-color: var(--accent); color: var(--accent);
}
.app-decision--application-refused {
  background: #fdecec; border-color: #d9534f; color: #b02a26;
}
.app-fields { display: grid; grid-template-columns: 9rem 1fr; gap: .5rem 1rem; margin: 0 0 1.4rem; }
.app-fields dt { color: var(--ink-soft); font-size: .84rem; }
.app-fields dd { margin: 0; }
.app-portal { display: grid; gap: .3rem; }
.cell-id {
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: .7rem; color: var(--ink-faint);
}
.cell-note { color: var(--ink-soft); font-size: .84rem; }
.cell-unknown { color: var(--ink-faint); font-style: italic; }

.pill--must { background: var(--ink); color: #fff; }
.pill--nice { background: var(--info-soft); color: var(--ink-soft); }
.tag--solver { background: var(--accent-soft); color: var(--accent); }
.tag--rules { background: var(--unknown-soft); color: var(--unknown); }
.tag--human { background: var(--warn-soft); color: var(--warn); }

.ladder-list { margin: 0; padding-left: 1.2rem; display: grid; gap: .5rem; }
.plain-list { list-style: none; margin: 0; padding: 0; display: grid; gap: .3rem; font-size: .88rem; }
.plain-list li { display: flex; gap: .5rem; align-items: baseline; }

.brief-link { display: flex; gap: .6rem; align-items: baseline; margin: .3rem 0 0; }
