/* Dowser web (WO-002; palette WO-003). Every colour is a token from tokens.css — the Field
   palette: ink on paper, one signal colour for actions and current state, a distinct error
   colour for failures (L-RENDER-02's one-signal rule carried over). No colour value is
   written here (R-015); the roles are R-017 and R-018. */
@import url("tokens.css");
/* type (Tobias, Prompt 32, 2026-09-29): Freight from the Adobe Fonts kit base.html links, the
   stacks as tokens (R-031). Page and section headings (h1, h2) in Freight Display Pro at 600;
   everything else, the smaller headings included, in Freight Sans Pro: 400 and 400 italic for
   text, 500 for labels, 600 and 700 for emphasis. Those six styles are all a visitor downloads,
   so no other weight, and no other italic, is written here. */
* { box-sizing: border-box; }
body { margin: 0; background: var(--paper); color: var(--body);
       font: 400 16px/1.55 var(--font-sans); font-variant-numeric: lining-nums; }
/* a form control inherits no font setting from the body, and a `font:` shorthand resets the
   figures, so each sets lining itself: the Zips and Wards fields, the search box and the
   map's counts drew Freight's old-style figures until Prompt 34's screenshots (2026-09-29) */
input, select, textarea, button { font-variant-numeric: lining-nums; }
/* No browser-default blue (Tobias, Prompt 110 item 2, 2026-10-04). Every focusable thing takes
   the oxblood ring on keyboard focus (a text field on any focus, as browsers judge it), outside
   its edge, so the ring sits on the surface around the control and never on a filled button;
   each surface's contrast is in tokens.css. Checkboxes, radio buttons and the other native
   controls take the signal colour (accent-color), checked, hovered and pressed. A disabled
   control is a muted version of the site's own (opacity, never the browser's grey), with no
   hover of its own (the hover rules below say :not(:disabled)). Chrome's autofill wash and the
   text selection, both the browser's blue, take the site's surface and its signal wash. */
:root { accent-color: var(--signal); }
:focus-visible { outline: 2px solid var(--focus); outline-offset: 2px; }
button:disabled, input:disabled, select:disabled, textarea:disabled, fieldset:disabled { opacity: .45; cursor: default; }
fieldset:disabled :disabled { opacity: 1; }  /* the fieldset is muted once, not its controls again */
::selection { background: var(--signal-wash); color: var(--ink); }
input:-webkit-autofill, input:-webkit-autofill:hover, input:-webkit-autofill:focus,
textarea:-webkit-autofill, select:-webkit-autofill {
  -webkit-box-shadow: 0 0 0 1000px var(--surface) inset; box-shadow: 0 0 0 1000px var(--surface) inset;
  -webkit-text-fill-color: var(--ink); caret-color: var(--ink); }
strong, b { font-weight: 600; }
h1, h2, h3 { color: var(--ink); font-weight: 600; }
h1, h2 { font-family: var(--font-display); letter-spacing: 0; }
h1 { font-size: 1.75rem; line-height: 1.2; margin: 0 0 1rem; }
h2 { font-size: 1.375rem; line-height: 1.25; margin: 1.5rem 0 .5rem; }
h3 { font-size: 1.125rem; line-height: 1.3; }
em strong, strong em, em b, b em { font-style: normal; } /* no bold italic: not one of the six */
/* a heading's aside (its muted words, a count, a tag) is set in the sans, so Freight Display is
   only ever the 600 of the heading itself (seen 2026-09-29: "this morning's issue" in New's
   heading drew the display cut's 400 too) */
h1 .muted, h2 .muted, h1 .count, h2 .count, h1 .tag, h2 .tag { font-family: var(--font-sans); }
/* numerals (R-027; Prompt 32 item 3): no monospace for numbers, dates or ids; a column of numbers
   or dates, a date, an id sets the text font's lining, tabular figures, so they line up. Not on
   prose, where tabular figures space a code section like "4-60-040(e)" like a column (seen
   2026-09-14). A monospace is for code and raw rows only. */
/* figures (Tobias, Prompt 33 item 2, 2026-09-29): lining everywhere on a page, from the body;
   tabular only in a column of numbers or dates, so they line up down it: a table's number and
   date columns, and the position numbers down a list or a route. An id, a count, a date in a
   sentence read lining alone: tabular spacing widened an id's hyphen to "CHI - 22277". */
td.num, th.num, td.date, th.date, .card .pos, ol.stops .stop-pos { font-variant-numeric: lining-nums tabular-nums; }
code, kbd { font-family: var(--font-mono); }
.id { font-size: .8125rem; line-height: 1.4; color: var(--body); } /* the id row: body, never muted (R-011) */
.date, time { white-space: nowrap; } /* a date never breaks across lines (Prompt 32 item 7) */
label, .label { font-size: .8125rem; line-height: 1.4; font-weight: 500; }
/* links (R-017): signal marks actions and current state, ink marks things you read — prose
   links are signal; nav, card titles and table-row links are ink; footer links are muted */
a { color: var(--signal); }
a:hover { color: var(--signal-deep); }
main { max-width: var(--page); margin: 0 auto; padding: 2rem 1.5rem 4rem; }
.lede { font-size: 1.15rem; }
.hero, .coverage { padding: 1rem 0 2rem; }
/* WO-005 E1: the coverage rows — a term with its state badge, a line beside it */
.coverage-rows { margin: 1rem 0; }  /* ruled rows: the column's width, as the three columns under them (Prompt 110 item 1) */
.coverage-row { display: grid; grid-template-columns: 11rem 1fr; gap: 1rem; padding: .5rem 0; border-top: 1px solid var(--hairline); }
.coverage-row:last-child { border-bottom: 1px solid var(--hairline); }
.coverage-row dt { font-weight: 600; color: var(--ink); } .coverage-row dd { margin: 0; }
.actions { margin-top: 1.5rem; }
/* The button system (Tobias, Prompt 136 item 2, 2026-10-06; the tokens are tokens.css's --btn-*).
   Every button and every link that looks like one takes ONE rule: one height, one padding, one
   type size, one hover. What an action is picks its look, never the container it sits in:
   primary (no modifier) is filled oxblood, one in a section, its main action; `.secondary` is
   outlined in ink, every other action; `.destructive` is outlined with oxblood text, last in
   its row, always behind a confirm step. Disabled is the same look muted (opacity, no hover).
   The hover is a tint, --signal-wash, never --surface (white on the paper, the "flash"), or on
   the filled button the deeper oxblood. A button that is not an action of the page (the header's
   menu buttons, the stops' arrows, a link-styled button, the map's own controls, Share's small
   icon in a card's corner) is named in the list below and keeps its own look. */
button:not(:where(.link, .clear-field, .stop-btn, .stop-remove, .note-term, .org-button, .bar-button,
    .menu-close, .default-submit, .share:not(.button), .share-menu button, .signout button,
    .org-list button, .site-menu-rows button, .map button)),
a.button {
  --b-bg: var(--btn-primary-bg); --b-fg: var(--btn-primary-fg); --b-border: var(--btn-primary-border);
  --b-hover-bg: var(--btn-primary-hover-bg); --b-hover-fg: var(--btn-primary-hover-fg);
  display: inline-flex; align-items: center; justify-content: center; gap: .4rem;
  height: var(--btn-height); margin: 0; padding: 0 var(--btn-pad-x);
  font-family: var(--font-sans); font-size: var(--btn-size); font-weight: 400; line-height: 1;
  text-align: center; text-decoration: none; white-space: nowrap; cursor: pointer;
  color: var(--b-fg); background: var(--b-bg); border: 1px solid var(--b-border); border-radius: var(--btn-radius);
}
button.secondary:not(.link), a.button.secondary {
  --b-bg: var(--btn-secondary-bg); --b-fg: var(--btn-secondary-fg); --b-border: var(--btn-secondary-border);
  --b-hover-bg: var(--btn-secondary-hover-bg); --b-hover-fg: var(--btn-secondary-hover-fg);
}
button.destructive, a.button.destructive {
  --b-bg: var(--btn-destructive-bg); --b-fg: var(--btn-destructive-fg); --b-border: var(--btn-destructive-border);
  --b-hover-bg: var(--btn-destructive-hover-bg); --b-hover-fg: var(--btn-destructive-hover-fg);
}
/* the hover and the press are one rule for all (a touch screen has no hover to stick); a
   disabled button has neither, and a muted link says so by aria-disabled */
button:not(:where(.link, .clear-field, .stop-btn, .stop-remove, .note-term, .org-button, .bar-button,
    .menu-close, .default-submit, .share:not(.button), .share-menu button, .signout button,
    .org-list button, .site-menu-rows button, .map button)):not(:disabled):active, a.button:active { background: var(--b-hover-bg); color: var(--b-hover-fg); }
@media (hover: hover) {
  button:not(:where(.link, .clear-field, .stop-btn, .stop-remove, .note-term, .org-button, .bar-button,
    .menu-close, .default-submit, .share:not(.button), .share-menu button, .signout button,
    .org-list button, .site-menu-rows button, .map button)):not(:disabled):hover, a.button:hover { background: var(--b-hover-bg); color: var(--b-hover-fg); }
}
a.button[aria-disabled="true"] { opacity: var(--btn-disabled-opacity); pointer-events: none; }
button:disabled { opacity: var(--btn-disabled-opacity); }
/* a row of actions: one gap, wrapping; the destructive one last */
.actions, .route-actions, .maps-links { display: flex; flex-wrap: wrap; align-items: center; gap: .5rem var(--btn-gap); }
/* a row of fields and a button (Tobias, Prompt 136 item 3): the label above every field, the
   button on the fields' bottom edge, wrapping on a phone; a form of one field puts its button on
   the field's line, the field taking the room that is left */
.field-row { display: flex; flex-wrap: wrap; align-items: flex-end; gap: .5rem .75rem; }
.field-row > label.field, form.plain.field-row > label.field { display: grid; gap: .25rem; margin: 0; flex: 0 1 auto; min-width: 0; font-size: .8125rem; line-height: 1.3; font-weight: 500; color: var(--muted); }
.field-row > label.field .lbl { display: block; }
.field-row > label.field :is(input, select, textarea) { width: 100%; max-width: none; min-width: 0; }
.field-row > button, .field-row > a.button { flex: none; margin: 0; }
.field-row > a:not(.button) { line-height: var(--btn-height); }  /* a text link beside the button sits on its line */
.field-row[hidden], .route-name[hidden] { display: none; }
.route-title { margin: 0; }
.support-filter { margin: .5rem 0 1rem; }
.route-name { display: flex; flex-wrap: wrap; align-items: baseline; gap: .25rem .9rem; }
.route-name h2 { margin: 1.5rem 0 .5rem; }
.route-rename-link { font-size: .875rem; }
.route-rename { margin: 1.5rem 0 .5rem; max-width: 36rem; }
.field-row.one-field > label.field, .field-row.one-field > input { flex: 1 1 12rem; }
form.one-field :is(input[type="text"], input[type="email"], input[type="search"]) { flex: 1 1 12rem; min-width: 0; }
.three { display: grid; grid-template-columns: repeat(3, 1fr); gap: 2rem; }
.plans { display: grid; grid-template-columns: repeat(4, 1fr); gap: 1.5rem; margin: 1.5rem 0; }
.plan .seats, .plan .who { font-size: .9375rem; } .plan .who { color: var(--muted); } .plan ul.adds { padding-left: 1.1rem; margin: .5rem 0; font-size: .9375rem; }
p.interval a { display: inline-block; padding: .25rem .75rem; border: 1px solid var(--hairline); border-radius: 3px; color: var(--ink); text-decoration: none; margin-right: .5rem; } p.interval a[aria-current] { border-color: var(--signal); font-weight: 600; }
.plan { border: 1px solid var(--hairline); background: var(--surface); padding: 1rem 1.25rem; }
/* the four Choose buttons on one line (ruled 2026-09-23): the grid already makes the columns
   equal in height, so each column is a flex column and its button takes the space above it */
.plan { display: flex; flex-direction: column; }
.plan > p.choose { margin-top: auto; padding-top: .75rem; margin-bottom: 0; }
.price { font-size: 2rem; margin: .25rem 0; } .price span { font-size: 1rem; color: var(--muted); }
/* prose runs at most about 75 characters (2026-09-20); tables stay full width */
.plain, .lede, .fineprint, main > p, main > section > p, .plain p { max-width: var(--measure); }
.plain { max-width: var(--measure); }
/* a section carries prose and tables: the prose keeps the measure, a table takes the page's
   width (ruled 2026-09-20; the lead page's history table was clipped inside the measure).
   Any section, not only main's own: Details' tabs hold theirs one level down, and their
   tables stopped at the measure under the full-width tabs (Prompt 110 item 1, 2026-10-04) */
section.plain { max-width: none; }
section.plain > p, section.plain > dl, section.plain > ul, section.plain > ol { max-width: var(--measure); }
/* One content width per page (Tobias, Prompt 110 item 1, 2026-10-04): a box, a list, a grid, a
   table and a count line take the page's column (--page) and share its two edges; only running
   prose keeps the measure. A notice and an error block are boxes, so they take the column too:
   at the measure they stopped short of the filter box, the cards and the panels around them.
   A count line is the head of the list it counts, so it ends where the list does. */
main .notice, main p.notice, main .failure, main p.notice--error { max-width: none; }
#map-counts, #map-focus { max-width: none; }  /* the map's count lines, under the map's full width */
.fineprint { color: var(--muted); font-size: .9rem; }
/* errors (R-004, R-019): a filled block in the error colour, --on-signal text, an icon drawn
   in CSS beside a bold label; the signal colour never fills a block at this scale */
.failure, .notice--error { position: relative; background: var(--error); color: var(--on-signal);
  padding: .75rem 1rem .75rem 2.75rem; margin: 1rem 0; }
.failure::before, .notice--error::before { content: "!"; content: "!" / ""; position: absolute; left: .9rem; top: .9rem;
  width: 1.25rem; height: 1.25rem; border: 2px solid currentColor; border-radius: 50%;
  font-size: .85rem; font-weight: 600; line-height: 1.05rem; text-align: center; }
.failure p:first-child, .notice--error p:first-child { margin-top: 0; }
.failure p:last-child, .notice--error p:last-child { margin-bottom: 0; }
.failure a, .notice--error a { color: inherit; text-decoration: underline; }
.failure code, .notice--error code { color: inherit; }
table.plain { border-collapse: collapse; width: 100%; margin: 1rem 0; }
table.plain th, table.plain td { text-align: left; padding: .4rem .6rem; border-bottom: 1px solid var(--hairline); vertical-align: top; font-size: .875rem; line-height: 1.4; }
table.plain th { border-bottom: 2px solid var(--ink); }
table.plain a, table.results a { color: var(--ink); }
form.plain label { display: block; margin: .75rem 0; font-size: 1rem; font-weight: 400; }
form.plain input { display: block; width: 100%; max-width: 28rem; }
/* WO-007 D2: a control row inside a table cell — a select and a button on one line */
form.inline { display: inline-flex; gap: .4rem; align-items: center; margin: 0; }
section.plain form.plain + form.plain { margin-top: 1.25rem; }
section.plain h3 { font-size: 1.0625rem; font-weight: 600; margin: 1.75rem 0 .5rem; }
ul.connections { list-style: none; padding: 0; margin: 0; } ul.connections li { margin: .3rem 0; display: flex; gap: .6rem; align-items: center; flex-wrap: wrap; }
p.connect { display: flex; gap: .6rem; align-items: center; flex-wrap: wrap; }
/* the members table on a phone: each member a block, its controls stacked, no sideways scroll —
   below the same 40rem at which the container's grid becomes one column, so the two agree
   (they disagreed between 640px and 720px until 2026-09-23) */
@media (max-width: 39.99rem) {
  table.members thead { display: none; }
  table.members, table.members tbody, table.members tr, table.members td { display: block; width: 100%; }
  table.members tr { border-bottom: 1px solid var(--hairline); padding: .5rem 0; }
  table.members td { border: 0; padding: .2rem 0; }
}
dl.plain dt { font-weight: 600; margin-top: .75rem; } dl.plain dd { margin: 0; }
footer { display: flex; flex-wrap: wrap; gap: 1.5rem; justify-content: space-between; padding: 1rem 1.5rem;
         border-top: 1px solid var(--hairline); color: var(--muted); font-size: .85rem; }
footer a { color: var(--muted); }
footer a:hover { color: var(--ink); }
@media (max-width: 1000px) { .plans { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 720px) { .three, .plans { grid-template-columns: 1fr; } }

fieldset.focus { border: 1px solid var(--hairline); background: var(--surface); padding: .75rem 1rem; margin: 1rem 0; max-width: 28rem; }
fieldset.focus legend { font-weight: 600; padding: 0 .3rem; }
/* a radio or a checkbox beside its caption, centred on it (2026-09-21: form.plain's
   block-level inputs had put the control above the caption) */
fieldset.focus label.check { display: flex; align-items: center; gap: .5rem; margin: .35rem 0; font-size: 1rem; font-weight: 400; }
fieldset.focus label.check input { display: inline-block; width: auto; max-width: none; margin: 0; flex: none; }
/* /licenses */
.muted { color: var(--muted); font-weight: 400; }
/* informational, never coloured: a hairline box in ink (R-018) */
.notice { border: 1px solid var(--hairline); color: var(--ink); padding: .75rem 1rem; margin: 1rem 0; background: var(--surface); }
.notice.stale { border-color: var(--signal); } .notice.stale a { color: var(--ink); font-weight: 600; text-decoration: underline; }
/* forms (2026-09-20): one height and one padding for text inputs, selects and buttons */
.filters input, .filters select, form.plain input, form.plain select, form.inline select, form.role select {
  height: var(--control); padding: 0 .6rem; font-family: var(--font-sans); font-size: .9375rem; line-height: calc(var(--control) - 2px); font-weight: 400; border-radius: 3px; }
.filters input, .filters select, form.plain input, form.plain select, form.inline select, form.role select { color: var(--ink); border: 1px solid var(--hairline); background: var(--surface); }
/* the filter rows: a fixed grid, four columns wide, two on a phone; every field is a label
   above a control, the label given two lines of room, so the controls in a row share a baseline */
/* the filter form (2026-09-20): one component for filings, changes and licences. An outlined
   box (hairline 1px, the one rule for a box; the spacing scale: 4px label to control, 16px
   between rows, fields and lines, 16px inside the box). The fields on four equal fixed
   columns, two on a phone; a label above each control with room for two lines; every control
   fills its column — a select sizes to the column, never to its options. The checkboxes on
   their own line below the fields, aligned with column one, each with its caption; the
   button last, the same height as an input. */
.filters { border: 1px solid var(--hairline); border-radius: 3px; padding: 1rem; margin: 1rem 0; }
.filters .fields { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 1rem; align-items: end; }
.filters .field { display: grid; grid-template-rows: auto var(--control); gap: .25rem; align-items: end; align-content: end; min-width: 0; font-size: .8125rem; line-height: 1.3; font-weight: 500; color: var(--muted); }
/* the label row is as tall as its label, 4px above the control; a row's controls line up at
   their foot (.fields aligns to the end), so a label that wraps adds its line above its own
   field only, and the box's space above the fields matches the space below (Prompt 89 part 3A) */
.filters .lbl { display: block; }
.filters .lbl .muted { font-weight: 400; }
.filters .grow { grid-column: span 2; }
/* a member with no territory assigned (Prompt 36 item 2): the line in the list's place, the
   reader's own words at the field's height or taller, never cut to it */
.filters .territory-none { grid-template-rows: auto minmax(var(--control), auto); }
.filters .territory-none p { margin: 0; align-self: center; font-weight: 400; color: var(--body); font-size: .875rem; line-height: 1.35; }
.filters input:not([type=checkbox]), .filters select { width: 100%; max-width: 100%; min-width: 0; }
/* a typed filter's circled x (Prompt 35 item 5): at the field's right end while it holds text,
   the browser's own clear control on a search field hidden so there is one; a touch screen
   gets a 44px target over the field's end */
.filters .clearable { position: relative; display: block; min-width: 0; }
.filters .clearable input { padding-right: 2.1rem; }
.filters .clearable input::-webkit-search-cancel-button { -webkit-appearance: none; appearance: none; display: none; }
/* above `.filters button`, whose signal fill and control height every filter button takes */
.filters .clear-field { position: absolute; right: .3rem; top: 50%; transform: translateY(-50%); display: inline-flex; align-items: center; justify-content: center;
  width: 1.75rem; height: 1.75rem; min-height: 0; padding: 0; margin: 0; border: 0; border-radius: 50%; background: transparent; color: var(--muted);
  line-height: 1; cursor: pointer; }
.clear-field[hidden] { display: none; }
.clear-field .clear-disc { fill: currentColor; }
.clear-field .clear-cross { stroke: var(--surface); stroke-width: 1.6; stroke-linecap: round; fill: none; }
.filters .clear-field:hover, .filters .clear-field:active, .filters .clear-field:focus-visible { background: transparent; color: var(--ink); }
.filters .clear-field:focus-visible { outline: 2px solid var(--focus); outline-offset: 1px; }
@media (pointer: coarse) { .filters .clear-field { width: 44px; height: 44px; right: -.2rem; } }
.filters .checks { display: flex; flex-wrap: wrap; align-items: center; gap: .5rem 1.5rem; margin-top: 1rem; }
/* a checkbox's own text is its label — no caption beside it; its definition is the "?" after
   the text, a control of its own (2026-09-20) */
.filters .checks .check { display: inline-flex; align-items: center; gap: .4rem; min-height: var(--control); }
.filters .checks label { display: inline-flex; align-items: center; gap: .4rem; white-space: nowrap; color: var(--ink); font-weight: 400; font-size: .9375rem; }
.filters .checks input { width: auto; height: auto; margin: 0; }
/* a form's default submit button, placed first and kept out of sight (2026-09-21) */
form.plain .default-submit { position: absolute; left: -9999px; width: 1px; height: 1px; overflow: hidden; }
/* the digest's presets (2026-09-20): outlined, one height, before the days */
form.plain .presets { margin: .75rem 0; } form.plain .presets button { margin-right: .25rem; }
form.plain .check { display: flex; align-items: center; gap: .4rem; margin: .75rem 0; }
form.plain .check label { display: inline-flex; align-items: center; gap: .4rem; margin: 0; }
form.plain .check input { display: inline; width: auto; }
.filters .actions { margin-top: 1rem; }
/* the Status filter (2026-09-23): the organisation's marks, a row of boxes with their counts */
.filters .status-filter .lbl { margin-right: .25rem; }
.filters .status-filter .count-inline { font-size: .875rem; }
.status-form .status-filter { margin-top: 0; }
.summary { display: flex; flex-direction: column; gap: .25rem; margin: .75rem 0 1rem; font-size: .95rem; }
/* words inside a tabular line keep prose figures (R-027): "pours on-premise" in the licence
   card's status line came out "on - premise" under tnum (seen 2026-09-26) */
/* a count is a record (2026-09-20): the figure in a box with the signal outline, ink, tabular */
.count { display: inline-block; min-width: 1.7em; padding: 0 .4em; border: 1px solid var(--signal); border-radius: 2px; color: var(--ink); background: var(--surface); font-weight: 500; font-size: .875em; line-height: 1.55; text-align: center; vertical-align: .08em; }
h1 .count, h2 .count, h3 .count { font-size: .7em; vertical-align: .18em; margin-left: .2em; }
.table-wrap { overflow-x: auto; }  /* a table keeps its columns and scrolls sideways where the screen is narrower */
table.results { border-collapse: collapse; width: 100%; font-size: .875rem; line-height: 1.4; }
table.results th, table.results td { text-align: left; vertical-align: top; padding: .45rem .5rem; border-bottom: 1px solid var(--hairline); }
table.results th { font-weight: 600; border-bottom: 2px solid var(--ink); }
/* dates, licence numbers and wards never wrap; their columns are sized to hold them */
table.results .date, table.results .id, .ward, .nowrap { white-space: nowrap; }
table.results th.date, table.results td.date { min-width: 7.25rem; }
table.results th.id, table.results td.id { min-width: 6.5rem; }
/* the Dowser column's markers: a word, not a sentence; the sentence is the marker's definition */
/* the Dowser column stays in view while a narrow screen scrolls the table sideways
   (2026-09-21: the "Another business here" marker sat past the visible edge at tablet
   width until the reader scrolled, and read as cut off); the paper behind it hides the
   columns passing underneath, the shadow says there are some */
.marker { display: inline-block; font-size: .8125rem; line-height: 1.4; font-weight: 500; letter-spacing: .02em; padding: 0 .35rem; border: 1px solid var(--ink); color: var(--ink); text-decoration: none; white-space: nowrap; }
a.marker:hover { background: var(--signal-wash); }
.marker.muted { border-color: var(--hairline); color: var(--muted); }
.tag { display: inline-block; font-size: .8125rem; line-height: 1.4; font-weight: 500; letter-spacing: .04em; text-transform: uppercase; border: 1px solid var(--ink); color: var(--ink); padding: 0 .3rem; margin-left: .3rem; }
.pager { display: flex; flex-wrap: wrap; gap: .5rem 1.5rem; align-items: center; margin: 1rem 0; }
.pager a { white-space: nowrap; }  /* on a phone, "← Previous" never breaks at its arrow (2026-09-26) */
/* a tag's or a label's definition (2026-09-20): the text comes from data-tip, so one definition
   serves the note and what a screen reader reads. Positioned under the tag, never wider than
   the screen. A note (operating rule 16, ruled 2026-10-01, Prompt 80 item 3; it replaces Prompt
   31 item 6's hover only): it opens on hover, on keyboard focus and on a tap (app.js, .open),
   never on hover alone; a tap elsewhere or Escape closes it. A click with a mouse hushes the
   one under the pointer until the pointer leaves it (.tip-off). On a phone the open note sits
   across the foot of the screen, as a term's note does. */
.has-tip { position: relative; }
.has-tip::after { content: attr(data-tip); display: none; position: absolute; left: 0; top: calc(100% + .35rem); z-index: 20; width: max-content; max-width: min(22rem, 80vw); padding: .5rem .65rem; background: var(--ink); color: var(--paper); font-family: var(--font-sans); font-size: .8125rem; font-weight: 400; line-height: 1.4; letter-spacing: 0; text-transform: none; white-space: normal; border-radius: .2rem; border: 1px solid var(--hairline); transform: translateX(var(--tip-shift, 0px)); pointer-events: none; }
@media (hover: hover) and (pointer: fine) {
  .has-tip { cursor: help; }
  .has-tip:hover::after { display: block; }
  .has-tip.tip-off:hover::after { display: none; }
}
.has-tip:focus-visible::after, .has-tip.open::after { display: block; }
.has-tip:focus-visible { outline: 2px solid var(--focus); outline-offset: 2px; }
@media (max-width: 640px) { .has-tip:focus-visible::after, .has-tip.open::after { position: fixed; left: 16px; right: 16px; top: auto; bottom: 16px; width: auto; max-width: none; transform: none; z-index: 70; } }
td .has-tip::after { left: auto; right: 0; }  /* a table's tags sit to the right; the tip opens leftward */
.src.has-tip, .basis.has-tip { border-bottom: 1px dotted currentColor; }
/* a label with a definition (2026-09-20): the same dotted mark, on a control's label and, since
   2026-09-29, on a checkbox's own text, where the "?" beside it used to be */
.lbl.has-tip { text-decoration: underline dotted; text-decoration-color: var(--muted); text-underline-offset: .2em; }
label .lbl.has-tip { cursor: pointer; }
@media (hover: hover) and (pointer: fine) { label .lbl.has-tip { cursor: help; } }

/* lead cards (the report's card, in HTML) */
.cards { display: grid; gap: .75rem; }
.card { border: 1px solid var(--hairline); background: var(--surface); padding: .75rem 1rem .75rem calc(1.6rem + var(--pos-digits, 2) * .5rem); position: relative; }
/* The left gutter fits the widest position number on the page (2026-09-23). It was a fixed
   1.6rem, which holds two digits: from 1,000 on, /licenses' numbers overflowed their box to
   the right and ran into the business name — 11,763 covered 9px of it — while a check of the
   box's own rectangle still read clean, because a fixed-width box reports the same rectangle
   whatever overflows it. The list says how many digits its last position has; the gutter and
   the number's box grow together, keeping the same 0.45rem between the number and the name.
   A data attribute rather than an inline style, so the layout does not lean on the
   'unsafe-inline' the policy carries only for Clerk. One and two digits keep the old gutter. */
.cards[data-digits="3"] { --pos-digits: 3; }
.cards[data-digits="4"] { --pos-digits: 4; }
.cards[data-digits="5"] { --pos-digits: 5; }
.cards[data-digits="6"] { --pos-digits: 6; }
/* Alternating tone (ruled 2026-09-22). The parity comes from the card's own position number,
   written by the template as data-tone — never :nth-child, which restarts at every group
   heading and at every page, so the same card would change tone when the list was re-sorted
   or paged. The difference is 1.035: texture, not two kinds of card. The card on /leads/<id>
   stands alone, carries no position and no tone, and stays --surface. */
.card[data-tone="alt"] { background: var(--surface-alt); }
/* Hover and keyboard focus carry the same cue: one step darker than whichever tone the card
   carries, and the hairline to oxblood. Hover only where a pointer can hover — on a phone a
   :hover state sticks after the tap that opened the page. Focus is the card's own link having
   focus, not :focus-within: tabbing to the status select should not light the whole card. */
@media (hover: hover) {
  /* only a card that opens something (2026-09-23: a licence card with no lead of its own lit
     up like a link and opened nothing — "clicking one does nothing") */
  .card:has(> h3 > .card-link):hover { background: var(--surface-hover); border-color: var(--signal); }
  .card[data-tone="alt"]:has(> h3 > .card-link):hover { background: var(--surface-alt-hover); }
}
.card:has(> h3 > .card-link:focus-visible) { background: var(--surface-hover); border-color: var(--signal); }
.card[data-tone="alt"]:has(> h3 > .card-link:focus-visible) { background: var(--surface-alt-hover); }
@media (prefers-reduced-motion: no-preference) {
  .card { transition: background-color .12s ease-out, border-color .12s ease-out; }
}
/* The whole card is the link the business name already is (ruled 2026-09-22): the name's own
   anchor grows an overlay over the card, so cmd-click and middle-click open a tab, right-click
   offers the menu, and no JS click handler is involved. The controls that own their clicks are
   raised above it — the status form, the record id's click-to-copy, the source link, the
   licence number, and any tag or label whose definition opens on tap.
   Every card whose name is a link carries it, positioned in a list or not (Tobias, Prompt 23
   item 7, 2026-09-28): the dashboard's newest cards have no position, lit up on hover like a
   link, and opened nothing but from their name. And nothing else rises above it: the address
   was raised so it could be selected (2026-09-22), and its whole line was then a strip across
   the card with no hand that opened nothing, as were the position number and the licence
   number. One link over the whole card, the hand throughout; the address and the number still
   select with Option (Alt) held. Ruled by Tobias 2026-09-29 (Prompt 26 item 1), superseding
   the ruling of 2026-09-22; on Details the card has no link of its own, so its address stays
   plain, selectable text. */
.card .card-link::after { content: ""; position: absolute; inset: 0; z-index: 0; }
/* Raising these above the overlay must not move them: `.card .rid` is already absolutely
   positioned in the card's corner, and a blanket `position: relative` here outranks that rule
   and drops it into the text flow — which is what it did between 2026-09-22 and 2026-09-23,
   putting the record id on top of the business name on every card on /filings. A positioned
   element takes z-index on its own, so it is given z-index alone; everything else, which is
   static, takes both. */
.card .rid, .card .share, .card .corner { z-index: 1; }
/* a note on a card's address (Prompt 137 item 6: a licence whose address is an office's) rises
   above the overlay so a tap reaches its term, at the address line's own size */
.card .addr span.note { z-index: 1; margin: 0; font-size: inherit; }
.card .source a, .card form.status, .card .status-block, .card .notes-line a, .card .kind a.elsewhere, .card .kind a.operator-count, .card .more-toggle { position: relative; z-index: 1; }
/* A tag rises above the overlay, so a pointer can hover it and a tap reaches it, for its note
   (operating rule 16, 2026-10-01): a tap opens the note; a click with a mouse still opens the
   card (app.js), with the hand, as anywhere on the card. */
.card .has-tip { z-index: 1; }
.card .has-tip.open, .card .has-tip:focus-visible { z-index: 30; }
.card:has(.has-tip.open), .card:has(.has-tip:focus-visible) { z-index: 5; }
@media (hover: hover) and (pointer: fine) {
  .card:has(> h3 > .card-link) .has-tip:not(.lbl) { cursor: pointer; }
  /* a definition shown rises above its card's other controls, and its card above the cards
     after it (Tobias's review, 2026-09-25: "Another business here" drew its tip under the
     status select, which covered the text): each of those controls is its own stacking layer
     at z-index 1, so the tip's own z-index counted only inside its layer */
  .card .has-tip:hover { z-index: 30; }
  .card:has(.has-tip:hover) { z-index: 5; }
}
/* the card's corners (ruled 2026-09-21): top-left the position in the current list; top-right,
   inside the corner, the record's dowser_id (deploy 4) */
.card .pos { position: absolute; left: .55rem; top: .7rem; width: calc(var(--pos-digits, 2) * .5rem + .6rem); text-align: right; font-size: .8125rem; color: var(--muted); }
.card .rid { position: absolute; right: .75rem; top: .7rem; font-size: .8125rem; color: var(--muted); cursor: copy; letter-spacing: .01em; }
.card .rid:hover, .card .rid:focus-visible { color: var(--ink); text-decoration: underline dotted; text-underline-offset: .2em; }
.card .rid.copied::after { content: " copied"; font-family: var(--font-sans); font-size: .75rem; color: var(--muted); }
.card h3 { padding-right: 6.5rem; }  /* room for Share (the id, on the sample) in the corner */
/* Share (Tobias, Prompt 31 item 5, 2026-09-29): where the record's id copied itself, top-right on
   a card, above the Watching rows' Stop watching; its menu is app.js's, one at a time */
button.share:not(.button) { display: inline-flex; align-items: center; gap: .3rem; padding: .2rem .5rem; font: inherit; font-size: .8125rem; font-weight: 500; line-height: 1.2; color: var(--muted); background: transparent; border: 1px solid transparent; border-radius: .2rem; cursor: pointer; }
button.share .icon { width: 16px; height: 16px; }
button.share:not(.button):focus-visible { outline: 2px solid var(--focus); outline-offset: 1px; }
button.share:not(.button)[aria-expanded="true"] { color: var(--ink); border-color: var(--hairline); background: var(--surface); }
@media (hover: hover) { button.share:not(.button):hover { color: var(--ink); border-color: var(--hairline); background: var(--surface); } }
/* Share keeps its small icon style only in a card's bottom-right corner (Tobias, Prompt 136 item
   2); among other actions (a route's page, the Watching rows) it is the outlined button, the
   same `.share` for the script that opens its menu */
button.share.button[aria-expanded="true"] { background: var(--btn-secondary-hover-bg); }
/* the card's top-right corner (Tobias, Prompt 71 item 4c, 2026-10-01): the record's ID as plain
   text, then Share under it; the ID was the copy control until 1c37e76 (2026-09-29) gave copying
   to Share's Copy ID, and it comes back to be read, not pressed */
.card .corner { position: absolute; right: .45rem; top: .45rem; display: flex; flex-direction: column; align-items: flex-end; gap: .05rem; }
.card .corner .rid { position: static; padding: .1rem .5rem 0; cursor: auto; }
.card .corner .rid:hover { color: var(--muted); text-decoration: none; }
/* the corner holds the ID alone since Prompt 102 item 3; Share sits at the card's bottom right,
   and at the bottom right of every record box, everywhere: the card's foot, one class (a route's
   stop, a pin's record on the map; Tobias, Prompt 106 item 1, 2026-10-04) */
.card-foot { display: flex; justify-content: flex-end; align-items: center; gap: .75rem; margin-top: .3rem; }
.card .card-foot { position: relative; z-index: 1; pointer-events: none; }  /* the strip still opens the card */
.card .card-foot .share { pointer-events: auto; }
.card .card-foot .share { position: static; }
.card .share { position: absolute; right: .45rem; top: .45rem; }
.card .corner .share { position: static; }
.share-menu { position: absolute; z-index: 60; min-width: 14rem; max-width: calc(100vw - 16px); padding: .35rem 0; background: var(--surface); border: 1px solid var(--hairline); border-radius: 4px; box-shadow: 0 10px 28px var(--shadow); }
.share-menu button { display: flex; align-items: baseline; justify-content: space-between; gap: 1rem; width: 100%; min-height: 40px; padding: .5rem 1rem; font: inherit; font-weight: 500; color: var(--ink); background: none; border: 0; text-align: left; cursor: pointer; }
.share-menu button .muted { font-weight: 400; font-size: .8125rem; }
@media (hover: hover) { .share-menu button:hover { background: var(--paper); } }
@media (pointer: coarse) { .share-menu button { min-height: 44px; } }
.share-menu button:focus-visible { outline: 2px solid var(--focus); outline-offset: -2px; }
.share-said { margin: .25rem 1rem .35rem; font-size: .8125rem; color: var(--muted); }
.share-said:empty { display: none; }
.share-menu textarea { display: block; width: calc(100% - 2rem); margin: .25rem 1rem .5rem; min-height: 8rem; font: inherit; font-size: .8125rem; }
.share-scratch { position: fixed; top: -1000px; left: 0; opacity: 0; }
table.results .rid { font-size: .8125rem; color: var(--muted); cursor: copy; }
table.results .rid.copied::after { content: " copied"; font-family: var(--font-sans); font-size: .75rem; }
/* the record status control (WO-008 §B): a small select at the card's foot and in the table's
   last column; a set status carries the signal colour on its border; "saved" for a moment */
form.status { display: inline-flex; align-items: center; gap: .4rem; margin: .35rem 0 0; font-size: .8125rem; }
form.status label { display: inline-flex; align-items: center; gap: .4rem; }
form.status select { font-size: .8125rem; padding: .15rem .3rem; border: 1px solid var(--hairline); background: var(--surface); color: var(--ink); border-radius: .2rem; }
form.status--set select { border-color: var(--signal); font-weight: 600; }
form.status .saved { color: var(--muted); font-size: .75rem; }
table.results form.status { margin: 0; }
/* the staff page (WO-008 §J.2): a candidate card with its two ids, a reason and two buttons,
   sized for a thumb */
.card.staff .rid { position: static; font-size: .8125rem; color: var(--ink); }
/* The decision's row (Tobias, 2026-09-25): the Reason field and its two buttons one control
   high, their bottoms on one line, the buttons right beside the field. The buttons' padding
   was inside the control's fixed height, so their labels sat at the bottom; the label's own
   block margin dropped the field below them; and a 1fr column put them at the card's far edge. */
.card.staff form { display: grid; gap: .5rem; margin-top: .5rem; }
.card.staff form label { margin: 0; }
.card.staff input[type="text"] { width: 100%; max-width: none; height: var(--control); padding: 0 .5rem; font-size: 1rem; border: 1px solid var(--hairline); background: var(--paper); }
@media (min-width: 40rem) { .card.staff form { grid-template-columns: minmax(0, 28rem) auto auto; justify-content: start; align-items: end; } }
/* the map and Route Builder (WO-008 §J.1, §C) */
.map { width: 100%; height: 60vh; min-height: 18rem; border: 1px solid var(--hairline); margin: .5rem 0; background: var(--paper); }
.maplibregl-popup-content { font-family: var(--font-sans); font-size: .875rem; background: var(--surface); color: var(--ink); border: 1px solid var(--hairline); }
/* Route Builder, re-laid 2026-09-23 (Tobias's list). The origin said first; the settings in
   one row of compact number fields with their units — never full width — and the filter box
   without its label band above the first row. */
/* Start from at the top of the box (Tobias, Prompt 110 item 3, 2026-10-04): the list as wide as
   an address needs and never wider than the box, Change home base beside it on its baseline;
   Another address…'s field and its button under it, shown by the stylesheet while that choice
   is made, so it opens without script too */
.route-start { display: flex; flex-wrap: wrap; align-items: flex-end; gap: .5rem 1rem; margin: 0 0 1rem; }
.route-start .start-from { flex: 0 1 30rem; min-width: 0; margin: 0; }
.route-start .start-home { font-size: .875rem; line-height: var(--control); white-space: nowrap; }
.start-address { display: none; grid-template-columns: minmax(0, 30rem) auto; justify-content: start; gap: .25rem .5rem; align-items: end; margin: 0 0 1rem; }
.route-settings:has(select[name="start"] option[value="address"]:checked) .start-address { display: grid; }
.start-address label.field { margin: 0; }
.start-address button.secondary { margin: 0; }
.start-address .start-placed { grid-column: 1 / -1; margin: 0; font-size: .875rem; font-weight: 400; }
/* a saved route's page keeps the start said in a line, with the opener's choice of start beside
   it (WO-012 §L.2); Build's line became Start from above */
.route-origin { display: flex; flex-wrap: wrap; align-items: center; gap: .4rem .75rem; margin: 0 0 .75rem; }
.route-origin .button.secondary { margin: 0; }
.route-origin .origin-text { flex: 1 1 16rem; }
.route-settings .start-notice { margin: 0 0 1rem; }
@media (max-width: 39.99rem) { .start-address { grid-template-columns: minmax(0, 1fr); } .start-address button.secondary { justify-self: start; } }
.route-settings.filters { padding-top: .85rem; }
.route-row { display: flex; flex-wrap: wrap; gap: .75rem 1.5rem; align-items: flex-end; }
.route-row label.compact { display: inline-flex; align-items: center; gap: .45rem; margin: 0; font-size: .9375rem; font-weight: 400; color: var(--ink); }
.route-row label.compact .lbl { font-size: .8125rem; font-weight: 500; color: var(--muted); }
.route-row input[type=number] { width: 4.5rem; height: var(--control); padding: 0 .5rem; font: inherit; color: var(--ink); border: 1px solid var(--hairline); border-radius: 3px; background: var(--surface); }
.route-row select { height: var(--control); padding: 0 .5rem; font: inherit; color: var(--ink); border: 1px solid var(--hairline); border-radius: 3px; background: var(--surface); }
.route-row .unit { color: var(--muted); font-size: .9375rem; }
/* each stop a row of one grid (ruled 2026-09-23): the position and its handle; the name and
   the address; one controls column — up, down, Remove — aligned down the list, with an empty
   slot where the first and the last rows have no arrow */
ol.stops { list-style: none; padding: 0; margin: .75rem 0; display: grid; gap: 0; border-top: 1px solid var(--hairline); }
ol.stops li.stop { display: grid; grid-template-columns: 3.25rem minmax(0, 1fr) auto; gap: .35rem .75rem; align-items: center; padding: .6rem 0; border-bottom: 1px solid var(--hairline); position: relative; background: var(--paper); }
ol.stops li.dragging { opacity: .6; background: var(--surface); }
ol.stops .stop-pos { display: inline-flex; align-items: center; gap: .35rem; color: var(--muted); }
ol.stops .stop-pos .n { min-width: 1.4rem; text-align: right; color: var(--ink); font-weight: 600; }
ol.stops .grip { cursor: grab; color: var(--muted); }
ol.stops .stop-main { min-width: 0; }
ol.stops .rid { position: static; font-size: .8125rem; color: var(--muted); cursor: copy; white-space: nowrap; }
ol.stops .stop-controls { display: grid; grid-template-columns: 2.25rem 2.25rem auto; justify-content: end; gap: .4rem; align-items: center; justify-items: start; }  /* packed to the right, no empty track after Remove, so Remove's right edge is the stop's (Prompt 108 part 1) */
ol.stops .stop-btn, ol.stops .stop-remove { height: 2rem; margin: 0; padding: 0 .55rem; font: inherit; font-size: .875rem; line-height: 1.9rem; color: var(--ink); background: transparent; border: 1px solid var(--hairline); border-radius: 3px; cursor: pointer; }
ol.stops .stop-btn { width: 2.25rem; padding: 0; text-align: center; }
ol.stops .stop-btn--empty { visibility: hidden; border-color: transparent; cursor: default; }
/* the stop's status (WO-016) in a row of its own, under the name and the buttons, at every
   width: as a column beside the buttons it took the row and squeezed the name and address to
   a word a line (Tobias's screenshot, 2026-10-02 evening) */
/* Share in the stop's bottom-right corner (Tobias, Prompt 106 item 1, 2026-10-04): on a wide
   screen the status takes the name's column, its full width, and Share the controls' column
   beside it, at the bottom, so the right-hand column reads ↑ ↓ Remove at the top and Share at
   the foot; on a phone, one column, Share on the last line at its right. In the status, the
   list and Save share a line and the note runs the whole width under them (their order in the
   page stays list, note, Save, the order they are used in) */
ol.stops .stop-status { grid-column: 2; grid-row: 2; min-width: 0; }
ol.stops .stop-status .status-block { margin: 0; }
ol.stops .stop-status .status-update .status-note { order: 1; flex: 1 1 100%; }
ol.stops .stop-status .status-update .status-reasons { order: 2; }
ol.stops li.stop > .card-foot { grid-column: 3; grid-row: 2; align-self: end; margin: 0; }  /* Share's right edge on Remove's, inside the stop (Tobias, Prompt 108 part 1, 2026-10-04: its padding hung past the stop's edge) */
@media (hover: hover) { ol.stops .stop-btn:hover, ol.stops .stop-remove:hover { border-color: var(--ink); } }
@media (max-width: 39.99rem) {
  ol.stops li.stop { grid-template-columns: 2.75rem minmax(0, 1fr); }
  ol.stops .stop-controls { grid-column: 2; }  /* still packed to the right: Remove's right edge over Share's */
  /* a phone: the status at the column's width, Share under it at the right */
  ol.stops .stop-status { grid-row: auto; }
  ol.stops li.stop > .card-foot { grid-column: 2; grid-row: auto; margin: 0; }  /* no negative margin on a phone: it could scroll the page sideways */
}
/* a saved route's page (WO-012 §K.3, 2026-10-06): its actions in one row, Edit the one filled
   button; the stops without Build's arrows, so the status takes the name's width and Share the
   right-hand column at the foot, as on Build; a change since the save in the signal's colour */
.route-actions { display: flex; flex-wrap: wrap; align-items: center; gap: .5rem .75rem; margin: .5rem 0 .75rem; }
.route-actions form.inline { display: inline; margin: 0; }
.route-actions .button, .route-actions button { margin: 0; }
.route-confirm { display: flex; flex-wrap: wrap; align-items: center; gap: .5rem .9rem; }
.route-confirm p { flex: 1 1 100%; max-width: none; margin: 0; }  /* over `.plain p`'s measure, which let Keep sit beside it */
.route-assign { display: flex; flex-wrap: wrap; align-items: end; gap: .5rem .75rem; margin: .5rem 0; }
.route-editing { margin: 0 0 .75rem; }
.route-note-block { margin-top: .9rem; }
ol.route-stops li.stop { grid-template-columns: 3.25rem minmax(0, 1fr) auto; }
ol.stops .stop-mark { color: var(--signal); font-size: .875rem; }
nav.route-filters { display: flex; flex-wrap: wrap; gap: .25rem .9rem; margin: 0 0 .75rem; }
nav.route-filters a[aria-current="page"] { color: var(--ink); font-weight: 600; text-decoration: none; }
ul.saved-routes { list-style: none; padding: 0; margin: 0 0 1rem; border-top: 1px solid var(--hairline); }
ul.saved-routes li { padding: .5rem 0; border-bottom: 1px solid var(--hairline); }
.route-save > a { margin-right: .75rem; }
/* adding a stop: the label, the list and the button on one line, the count beneath */
.add-stop { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: .25rem .5rem; align-items: end; margin: 1rem 0; max-width: none; }  /* the list's width, so Add ends where the stops' controls do */
/* Route Builder on one width (Tobias, Prompt 110 item 1, 2026-10-04): the settings box, the
   count line, the stops and Add a stop share the page's column and its two edges, as the map
   under them does. The count line and the stops stopped at the prose measure (694 of 976 px at
   1,280 wide) under a box that spanned the column. */
.route > p.route-counts, .route > ol.stops { max-width: none; }
.add-stop label.field { display: grid; gap: .25rem; margin: 0; font-size: .8125rem; font-weight: 500; color: var(--muted); }
.add-stop select { width: 100%; min-width: 0; height: var(--control); padding: 0 .5rem; font: inherit; color: var(--ink); border: 1px solid var(--hairline); border-radius: 3px; background: var(--surface); }
.add-stop button.secondary { height: var(--control); margin: 0; }
.add-stop .add-count { grid-column: 1 / -1; font-size: .875rem; }
/* the handoff (ruled 2026-09-23): a computer one link, a phone its legs of four */
.maps-links { display: flex; flex-wrap: wrap; gap: .5rem; }
.maps-links .button.secondary { margin-left: 0; }
.maps-phone { display: none; }
@media (hover: none) and (pointer: coarse) { .maps-computer { display: none; } .maps-phone { display: flex; } }
/* a numbered stop on the map: an HTML marker, which needs no glyphs */
/* the map's cluster counts: HTML over the circle, which takes the tap (ruled 2026-09-23) */
.cluster-count { pointer-events: none; color: var(--paper); font: 600 .75rem/1 var(--font-sans); font-variant-numeric: lining-nums; text-align: center; white-space: nowrap; }
.map-popup { max-height: 16rem; overflow-y: auto; }
.map-popup p { margin: 0 0 .5rem; font-size: .875rem; }
.map-popup p:last-child { margin-bottom: 0; }
/* a popup's record (Prompt 106 item 1, 2026-10-04): its name and place, then its foot, Open at
   the left and Share at the bottom right, as on a card; one record under another is ruled off */
.map-record { font-size: .875rem; }
.map-popup .map-record p { margin: 0; }
.map-record .card-foot { margin: .2rem 0 0; }  /* inside the popup's edge: a negative margin scrolled it sideways on a phone */
.map-record .card-foot > a { margin-right: auto; }
.map-popup .map-record + .map-record { margin-top: .5rem; padding-top: .5rem; border-top: 1px solid var(--hairline); }
.map-popup .map-record + p { margin-top: .5rem; }
.stop-marker { width: 1.6rem; height: 1.6rem; border-radius: 50%; background: var(--ink); color: var(--paper); border: 2px solid var(--paper); font: 600 .8125rem/1.35rem var(--font-sans); font-variant-numeric: lining-nums; text-align: center; cursor: pointer; box-shadow: 0 0 0 1px var(--ink); }
.route-save { margin-top: 1rem; }
.route { margin-top: 1.5rem; }
table.results th.pos, table.results td.pos { text-align: right; color: var(--muted); width: 2.5rem; padding-right: .4rem; }
.card h3 { margin: 0 0 .2rem; font-size: 1.05rem; } .card h3 a { color: var(--ink); text-decoration: none; }
.card .addr { color: var(--muted); } .card .status { font-weight: 600; color: var(--ink); margin: .25rem 0; }
.card .flags { margin: .2rem 0; } .card .kind, .card .owners, .card .note, .card .permit, .card .dates { margin: .2rem 0; font-size: .95rem; }
/* the sample (WO-005 D2): a locked element reads as a link that leads to pricing; the withheld
   owners line is italic; the week's dates row is body colour with tabular figures */
.locked { color: var(--body); text-decoration: underline dotted; }
.locked::after { content: " \2192 pricing"; font-size: .8em; color: var(--muted); }
.card .owners.withheld { font-style: italic; }
.sample-banner span { display: block; margin-top: .3rem; }
h3.group { font-size: 1rem; margin: .8rem 0 .2rem; }
.card .source { font-size: .8rem; margin-top: .3rem; color: var(--body); } /* 12.8px: below the 13px floor for muted (R-018) */
form.inline { display: inline; } button.link { background: none; border: 0; padding: 0; color: var(--signal); text-decoration: underline; cursor: pointer; font: inherit; }
button.link:hover { color: var(--signal-deep); }
details.raw { display: inline; margin-left: .4rem; } details.raw summary { display: inline; cursor: pointer; font-size: .8rem; } details.raw code { display: block; font-size: .75rem; white-space: pre-wrap; color: var(--body); } /* 12px monospace: body, not muted (R-011) */
/* the phone (after the grid rules above, so it wins): two columns, the wide fields still two */
@media (max-width: 720px) { .filters .fields { grid-template-columns: repeat(2, minmax(0, 1fr)); } .filters .grow { grid-column: span 2; } .filters .checks label { white-space: normal; } }


/* A subsection is its own container, built like a card: the same hairline, the same white,
   the same square corners — nothing on this page has a radius, so neither does this. */
.panel { border: 1px solid var(--hairline); background: var(--surface); padding: .85rem 1rem 1rem; margin: 0 0 .9rem; }
.panel > h2 { margin: 0 0 .35rem; font-size: 1.05rem; }
.panel > .lede { color: var(--body); margin: 0 0 .7rem; font-size: .95rem; }
.panel > .notice, .panel > form > .notice { margin: .3rem 0 .7rem; }
.panel > p.muted:last-child { margin-bottom: 0; }

/* Label and value: stacked below the breakpoint, two columns above it, and the control that
   changes a value sits beside that value rather than on a line of its own. */
.panel .grid { display: grid; }
.panel .grid > .row { display: grid; gap: .3rem; padding: .6rem 0; border-top: 1px solid var(--hairline); }
.panel .grid > .row:first-child { border-top: 0; padding-top: .1rem; }
.panel .grid > .row:last-child { padding-bottom: .1rem; }
.panel .grid .k { color: var(--muted); font-size: .875rem; line-height: 1.5; }
.panel .grid .v { display: flex; flex-wrap: wrap; align-items: center; gap: .4rem .6rem; min-width: 0; }
.panel .grid .v > .muted { flex-basis: 100%; font-size: .875rem; }
.panel .grid .v form.inline { display: flex; flex-wrap: wrap; align-items: center; gap: .4rem; margin: 0; }
.panel .grid .v form.fields input[type="text"], .panel .grid .v form.fields input[type="email"] {
  height: var(--control); padding: 0 .5rem; border: 1px solid var(--hairline); background: var(--surface);
  font: inherit; font-size: .9375rem; min-width: 0; flex: 1 1 9rem; max-width: 18rem; }
/* a name is two short fields and a button on one line, not a field per line */
.panel .grid .v form.fields.narrow input { flex: 0 1 8.5rem; }
/* the home base, set here alone since Prompt 110 item 3: a whole street address in view */
#home-base .grid .v form.fields { flex: 1 1 22rem; min-width: 0; }
#home-base .grid .v form.fields input[type="text"] { max-width: 26rem; }
.panel .grid .v fieldset.focus { margin: 0; }
.panel .grid .v .presets { display: flex; gap: .4rem; flex-wrap: wrap; }
.panel .grid .v ul.connections { margin: 0; }
.panel .grid .v form.plain { margin: 0; width: 100%; }
@media (min-width: 40rem) {
  .panel .grid > .row { grid-template-columns: 12.5rem minmax(0, 1fr); gap: .25rem 1.25rem; align-items: baseline; }
  .panel .grid > .row.row--wide { grid-template-columns: 1fr; }
  .panel .grid > .row.row--wide .k { margin-bottom: .2rem; }
}


/* One filled button per container, for its main action (ruled 2026-09-23), now the button
   system's (above): the outlined `.secondary` look is one rule for every container. */
/* Territories' one-click regions (Prompt 133 item 2): the sentence, then a button a region */
.region-territories { margin: 1rem 0 0; }
.region-territories p { margin: 0 0 .5rem; }
.region-territories form.inline { display: flex; flex-wrap: wrap; align-items: center; gap: .5rem; }
/* A member's role: saved on change, "saved" beside it, a refusal in words (2026-09-23) */
form.role { display: inline-flex; align-items: center; gap: .5rem; margin: 0; }
form.role .saved { color: var(--muted); font-size: .75rem; }
form.role .refused { color: var(--ink); font-weight: 600; font-size: .8125rem; }  /* not --error: that is for system and billing failures only (R-004); the words carry it */
/* Remove, quiet, with a confirm step: a disclosure that needs no script. The summary reads as a
   plain control in the body colour; opening it asks the question and offers the one button. */
details.confirm > summary { cursor: pointer; color: var(--body); text-decoration: underline;
  text-underline-offset: .2em; list-style: none; display: inline; font-size: .875rem; }
details.confirm > summary::-webkit-details-marker { display: none; }
details.confirm[open] > summary { color: var(--muted); }
details.confirm > form { display: flex; flex-wrap: wrap; align-items: center; gap: .5rem;
  margin-top: .4rem; font-size: .875rem; }


/* Visually hidden, still read aloud. Referenced by the account page's two legends since
   2026-09-22 and defined nowhere until 2026-09-23 — so both legends printed, the Days one
   repeating its row's label. A class used and never defined renders as nothing at all, and
   no check reported it. */
.sr-only { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden;
  clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap; border: 0; }

/* The digest's Days (2026-09-23): the presets on one line, the seven days beneath in one row
   of compact boxes — seven columns of 2.2rem, which is 285px and fits the 298px value column
   at 375px — each box over its three-letter name. */
.panel .grid .v .days { display: grid; gap: .6rem; flex-basis: 100%; }
.panel .grid .v .days .presets { display: flex; flex-wrap: wrap; gap: .4rem; }
fieldset.days { border: 0; margin: 0; padding: 0; min-width: 0;
  display: grid; grid-template-columns: repeat(7, 2.2rem); gap: .2rem .4rem; }
fieldset.days label { display: flex; flex-direction: column; align-items: center; gap: .15rem;
  font-size: .8125rem; color: var(--body); cursor: pointer; }
/* `form.plain input` gives every input the control height (36px), checkboxes included; the
   `.check` ones are reset, and these must be too, or the boxes render at the height of a text
   field (seen in the review, 2026-09-23) */
form.plain fieldset.days input { height: auto; width: auto; padding: 0; margin: 0; border: 0; }
/* a fieldset inside a container is a group, not a second box: the container is the box */
.panel fieldset.focus { border: 0; padding: 0; margin: 0; max-width: none; }
.panel fieldset.focus label.check { margin: .2rem 0; }
/* a form's Save as the grid's last row, standing in the value column */
.panel .grid > .row.row--actions { border-top: 0; padding-top: .2rem; }

/* inside a container's value column a checkbox sits on its label's line, and a sentence after
   a form's button starts on a line of its own — at 375 it began beside the button and wrapped
   around it (both seen in the review, 2026-09-23) */
.panel .grid .v .check { margin: 0; }
.panel form.plain button + .muted { display: block; margin-top: .35rem; }

/* a field whose placeholder is a sentence gets the room to show it: the territory request's
   "A town, a county, a metro — the suburbs you sell in" was cut off at 18rem (seen in the
   review, 2026-09-23) */
.panel .grid .v form.fields.wide { flex: 1 1 100%; }  /* the column's width, or the field cannot grow into it */
.panel .grid .v form.fields.wide input[type="text"] { flex: 1 1 18rem; max-width: 30rem; }

/* The grid aligns a row's label to its value's baseline, which is right for text and fields
   and wrong when the value starts with a checkbox or a list of radios: the label landed beside
   the second line ("Send the digest" between "On" and the sentence under it; "Show me" beside
   the second radio — seen in the review, 2026-09-23). Those rows align to their first line. */
@media (min-width: 40rem) {
  .panel .grid > .row:has(> .v > .check:first-child),
  .panel .grid > .row:has(> .v > fieldset.focus:first-child) { align-items: start; }
  /* measured, not guessed: these put the label's centre on its first line's centre */
  .panel .grid > .row:has(> .v > .check:first-child) > .k { padding-top: .64rem; }
  .panel .grid > .row:has(> .v > fieldset.focus:first-child) > .k { padding-top: .45rem; }
}

/* A label in the grid's label column is the grid's label, not a form's stacked one:
   `form.plain label` makes labels blocks with a margin, which the password form's labels, now in
   the label column, must not carry (2026-09-23) */
.panel .grid label.k { display: block; margin: 0; font-weight: 400; }
/* a container split into two grids (the password form's, then the rest) keeps the hairline
   between them that one grid would have drawn */
.panel .grid.grid--cont > .row:first-child { border-top: 1px solid var(--hairline); padding-top: .6rem; }

/* The members table's columns on the container's grid (ruled 2026-09-23): the Member column is
   the label column and its gap (12.5rem + 1.25rem), with no padding at its left, so the role
   select starts exactly where the Invite row's field does; the table spans the container
   rather than stopping at the prose measure `.plain` gives it. */
@media (min-width: 40rem) {
  .panel table.members { max-width: none; width: 100%; table-layout: fixed; margin: .2rem 0 .6rem; }
  .panel table.members th, .panel table.members td { box-sizing: border-box; vertical-align: middle; }
  .panel table.members th:first-child, .panel table.members td:first-child { width: 13.75rem; padding-left: 0; }
  .panel table.members th:nth-child(2), .panel table.members td:nth-child(2) { padding-left: 0; }
  .panel table.members th:nth-child(3), .panel table.members td:nth-child(3) { width: 7rem; text-align: right; padding-right: 0; }
}

/* `.plain` caps prose at the reading measure (75ch); a form inside a container is not prose,
   and the cap drew its rows' hairlines short of the container's edge — the password form's and
   the digest's (seen in the review, 2026-09-23), as it had capped the members table */
.panel form.plain { max-width: none; }

/* the line on a card that matched a search off its name */
.card .matched { margin: .2rem 0; font-size: .95rem; color: var(--muted); }
.see-all { margin: .5rem 0 1.25rem; }
/* a record id inline in prose, as the cards' corner prints it */
.rid-inline { font-size: .85em; color: var(--muted); white-space: nowrap; }
kbd { font-family: var(--font-mono, ui-monospace, monospace); font-size: .9em; border: 1px solid var(--hairline); border-radius: 3px; padding: 0 .3em; }

/* The feed's URL, shown once (WO-008 §D, 2026-09-25): the whole secret on one wrapping line,
   selectable, beside its Copy button; "copied" said as the ids say it. */
.feed-url { display: block; font-family: var(--font-mono, ui-monospace, monospace); font-size: .8125rem; overflow-wrap: anywhere; background: var(--surface-alt); padding: .5rem .6rem; border: 1px solid var(--hairline); border-radius: 4px; user-select: all; }
.feed-url.copied::after { content: " copied"; font-family: var(--font-sans); font-size: .75rem; color: var(--muted); }

/* The territory being edited (Prompt 2, 2026-09-25): its row marked in the grid, as the form
   below says "Editing …". */
table.results tr.editing td { background: var(--signal-wash); }
/* Operations: what a step did inside itself, on a line of its own under the step's row (the
   towns' agendas under ingest, Prompt 23 item 2) */
table.results tr.has-sub td { border-bottom: 0; padding-bottom: .1rem; }
table.results tr.sub td { padding-top: 0; font-size: .875rem; }
/* Operations (Prompt 40): a failed step's exception and message beside its status (the error colour
   is for an icon and a label, R-004), the whole traceback folded under it, a warning in the body's ink; each
   sub-row of a step without a rule between them */
table.results tr.sub:has(+ tr.sub) td { border-bottom: 0; padding-bottom: .1rem; }
.error-line { color: var(--body); font-weight: 500; overflow-wrap: anywhere; }
table.results td.warning { color: var(--body); overflow-wrap: anywhere; }
details.traceback summary { cursor: pointer; color: var(--muted); }
details.traceback pre { margin: .4rem 0 0; max-height: 18rem; overflow: auto; font-size: .75rem; line-height: 1.35; white-space: pre; background: var(--surface); border: 1px solid var(--hairline); padding: .5rem; }
/* A cell that is its link (Prompt 6, 2026-09-25): the territory's name. A wrapped name left
   gaps between its lines that opened nothing on a tap (the preview at 375, 078925d); the
   link's box now covers the whole cell, whatever else the row wraps to, and the cell is never
   shorter than a 44px tap. */
table.results td.cell-link { position: relative; height: 44px; }
table.results td.cell-link > a::after { content: ""; position: absolute; inset: 0; }
/* Delete below the edit's Save changes and Cancel (Prompt 9 fix 6, 2026-09-26) */
/* the destructive button of the button system (outlined, oxblood text), never filled like Save
   changes: the destructive action reads as the other one */
form.territory-delete { margin-top: 1.25rem; }
/* assigning territories (Prompt 34 item 2, 2026-09-29): the two lists and Assign on one line,
   as a Route Builder stop is added; a phone stacks them. The assigned, one per line */
form.assign { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr) auto; gap: .25rem .75rem; align-items: end; margin: 1rem 0 1.25rem; max-width: none; }  /* Assign ends at the table's right edge (Prompt 110 item 1) */
form.assign label.field { display: grid; gap: .25rem; margin: 0; font-size: .8125rem; font-weight: 500; color: var(--muted); }
form.assign select { width: 100%; min-width: 0; height: var(--control); padding: 0 .5rem; font: inherit; color: var(--ink); border: 1px solid var(--hairline); border-radius: 3px; background: var(--surface); }
/* Assign is the tab's one filled button (ruled 2026-09-23): the button system's primary */
@media (max-width: 560px) { form.assign { grid-template-columns: minmax(0, 1fr); } }
/* each name's Remove is quiet text beside it, never form.inline's signal fill. On a touch
   screen it takes a line of its own under its name, and its 44px target is padding inside
   that line's own height, so the lines keep their rhythm and no two targets meet */
/* the table below the tab's form, with the room a new part of the page takes */
.table-wrap.territory-table { margin-top: 1.5rem; }
table.results td.assigned .assignee { display: block; }
/* a territory's units, one kind a line (Prompt 113) */
table.results td.area .unit { display: block; }
table.results td.area .unit + .unit { margin-top: .375rem; }
table.results td.assigned form.inline button.link { height: auto; margin: 0 0 0 .5rem; padding: 0; background: none; border: 0; color: var(--signal);
  font: inherit; line-height: inherit; text-decoration: underline; cursor: pointer; }
table.results td.assigned form.inline button.link:hover { color: var(--signal-deep); }
@media (pointer: coarse) {
  table.results td.assigned .assignee + .assignee { margin-top: .375rem; }
  table.results td.assigned form.inline { display: block; }
  table.results td.assigned form.inline button.link { display: inline-block; margin: calc((1lh - 44px) / 2) 0; padding: calc((44px - 1lh) / 2) 0; }
}

/* --- the header (Prompt 9 item 8, 2026-09-26) ---------------------------------------------
   A band a shade darker than the page above the red rule, so the header reads as the frame
   and the pages stay quiet. The bar's height derives from the lockup (R-042): 160px wide at
   its 3.1283:1 is 51.15px tall, plus 8px above and below and the 3px rule. Every colour a
   token (tokens.css), so the queued dark theme redefines the tokens and nothing here. */
.masthead { background: var(--band); border-bottom: 3px solid var(--signal); }
.masthead .bar { display: flex; align-items: center; gap: 1.25rem; max-width: 94rem; margin: 0 auto;
  padding: 8px max(1.5rem, env(safe-area-inset-right)) 8px max(1.5rem, env(safe-area-inset-left)); }
/* the brand: DowserLogo.svg whole — icon and wordmark — never the icon beside set type */
/* its link is the band's full height, as the tabs are (Prompt 23 item 7, 2026-09-28): the image
   alone was 51 of the band's 67 px, and a pointer just above or below the mark showed no hand */
.wordmark { display: inline-flex; align-items: center; flex: none; align-self: stretch; margin: -8px 0; padding: 8px 0; }
.wordmark img { display: block; width: 160px; height: auto; }
/* the pages as tabs, the bar's full height, each with its line icon (approved by Tobias,
   2026-09-26, over text alone): the current one in the ink over a bar of the signal colour,
   which stands on the rule below as one thicker stroke; a tint behind a hovered one. */
.site-tabs { display: flex; align-self: stretch; margin: -8px 0; }
.site-tab { display: inline-flex; align-items: center; gap: .45rem; padding: 0 .85rem; color: var(--body);
  text-decoration: none; font-weight: 500; border-bottom: 3px solid transparent; }
.site-tab[aria-current="page"] { color: var(--ink); font-weight: 600; border-bottom-color: var(--signal); }
@media (hover: hover) { .site-tab:hover { background: var(--band-hover); color: var(--ink); } }
.site-tab .icon { flex: none; }
/* the search at the right: a magnifier in the field, the outlined button */
/* the field never narrower than its placeholder reads (Prompt 12 item 2, 2026-09-26): below
   the width where it would be, the search button stands in for it (the 1303px query below) */
.masthead form.search { display: flex; gap: .4rem; align-items: center; flex: 1 1 22rem; max-width: 26rem; min-width: var(--search-min); margin: 0 0 0 auto; }
.search-field { position: relative; flex: 1 1 auto; min-width: 0; display: flex; }
.search-field .search-icon { position: absolute; left: .55rem; top: 50%; transform: translateY(-50%); color: var(--muted); pointer-events: none; }
.masthead form.search input { flex: 1 1 auto; width: 100%; min-width: 0; height: var(--control); padding: 0 .6rem 0 2.1rem; font-family: var(--font-sans); font-size: .9375rem; line-height: calc(var(--control) - 2px); color: var(--ink); border: 1px solid var(--hairline); border-radius: 3px; background: var(--surface); }
.masthead form.search input:focus { outline: 2px solid var(--focus); outline-offset: 1px; }
/* the header's Search is the one button whose side padding is narrower than the system's, by
   the token alone (Prompt 136): the field beside it was measured to show its placeholder whole
   at --search-min, and a button 6px wider would clip it. Height, type and hover are the system's. */
.masthead form.search button { --btn-pad-x: .8rem; }
/* the organization at the far right: its mark, its name, a chevron; a menu below it */
/* the name gives way before the search field does (Prompt 12 item 2): it shortens with an
   ellipsis to 5rem, its whole name in the button's title and in the phone's menu */
.org-menu { position: relative; flex: 0 1 auto; min-width: 0; }
.org-button { display: inline-flex; align-items: center; gap: .5rem; height: 2.5rem; max-width: 100%; padding: 0 .5rem 0 .35rem;
  background: transparent; border: 1px solid transparent; border-radius: 4px; color: var(--ink); font: inherit;
  font-weight: 500; cursor: pointer; }
@media (hover: hover) { .org-button:hover { background: var(--band-hover); } }
.org-button[aria-expanded="true"] { background: var(--band-hover); border-color: var(--hairline); }
.org-button .org-name { flex: 0 1 auto; min-width: 5rem; max-width: 14rem; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.org-button .chevron { width: 16px; height: 16px; color: var(--muted); transition: transform .15s; }
.org-button[aria-expanded="true"] .chevron { transform: rotate(180deg); }
.org-mark { flex: none; border-radius: 50%; display: block; }
img.org-mark { object-fit: cover; background: var(--surface); border: 1px solid var(--hairline); }
.org-mark-bg { fill: var(--signal); }
.org-mark-fg { fill: var(--on-signal); opacity: .8; }
.org-mark-front { fill: var(--on-signal); stroke: var(--signal); stroke-width: 1.2; }
.org-list { position: absolute; right: 0; top: calc(100% + 6px); min-width: 14rem; padding: .35rem 0; z-index: 50;
  background: var(--surface); border: 1px solid var(--hairline); border-radius: 4px; box-shadow: 0 10px 28px var(--shadow); }
.org-list[hidden] { display: none; }
.org-list a, .org-list form.signout button { display: flex; align-items: center; gap: .65rem; width: 100%;
  padding: .6rem 1rem; color: var(--ink); text-decoration: none; font: inherit; font-weight: 500;
  background: none; border: 0; text-align: left; cursor: pointer; }
.org-list a .icon, .org-list form.signout .icon { color: var(--muted); }
.org-list a[aria-current="page"] { box-shadow: inset 3px 0 0 var(--signal); font-weight: 600; }
@media (hover: hover) { .org-list a:hover, .org-list form.signout button:hover { background: var(--paper); } }
.org-list form.signout { margin: .35rem 0 0; padding-top: .35rem; border-top: 1px solid var(--hairline); }
/* the pages below the account's rows (Prompt 31 item 8, 2026-09-29), after a divider */
.org-list hr { border: 0; border-top: 1px solid var(--hairline); margin: .35rem 0; }
/* signed out: the few links, as words */
.site-links { display: flex; align-items: center; gap: 1.25rem; margin-left: auto; }
.site-links a { color: var(--ink); text-decoration: none; border-bottom: 1px solid transparent; }
.site-links a:hover { border-bottom-color: var(--ink); }
.site-links a[aria-current="page"] { border-bottom-color: var(--signal); }
.site-links form.signout { display: inline; margin: 0; }
.site-links form.signout button { background: none; border: 0; padding: 0; font: inherit; color: var(--ink); cursor: pointer; }
.site-links .account { padding-left: 1.25rem; border-left: 1px solid var(--hairline); white-space: nowrap; }
/* the header's buttons: the search's, where the field would be too narrow, and on a phone
   Menu. Each a full tap high. */
.bar-button { display: none; align-items: center; justify-content: center; gap: .35rem; min-width: 44px; min-height: 44px;
  padding: 0 .55rem; background: transparent; border: 1px solid transparent; border-radius: 4px; color: var(--ink);
  font: inherit; font-weight: 500; cursor: pointer; }
.bar-button[aria-expanded="true"] { background: var(--band-hover); }
@media (hover: hover) { .bar-button:hover { background: var(--band-hover); } }
/* narrower than 1,304 px the field folds behind the search button and opens as a second row
   (Prompt 12 item 2, 2026-09-26). Measured in the preview with the icon tabs: the full header
   fits from 1,285 px, the field showing its placeholder whole and an organization's name at its
   5rem; the rest is room for a scrollbar that takes width (Windows). A grid, not a wrapping
   row: a row that may wrap gives way by wrapping, which dropped the organization's menu to a
   second line at 960–1,040 px before its name could shorten. */
@media (max-width: 1303px) {
  .masthead.app .bar { display: grid; grid-template-columns: auto auto minmax(0, 1fr) auto minmax(0, max-content) auto;
    column-gap: 0; }
  .masthead.app .wordmark { grid-column: 1; grid-row: 1; }
  .masthead.app .site-tabs { grid-column: 2; grid-row: 1; margin-left: 1.25rem; }
  .masthead.app .search-toggle { display: inline-flex; grid-column: 4; grid-row: 1; margin-left: .75rem; }
  .masthead.app .org-menu { grid-column: 5; grid-row: 1; margin-left: .5rem; }
  .masthead.app .menu-toggle { grid-column: 6; grid-row: 1; margin-left: .25rem; }
  .masthead.app form.search { display: none; grid-column: 1 / -1; grid-row: 2; min-width: 0; max-width: none; margin: 6px 0 4px; }
  .masthead.app.search-open form.search { display: flex; }
}
/* the search button's two faces: the magnifier, and while its field is open between 1,024
   and 1,303 px, Close */
.search-toggle .when-open { display: none; }
/* 1,024 to 1,303 px (Prompt 13 item 1, 2026-09-26): the opened field takes the tabs' place in
   the row, so the header stays one row, the page below does not move, and no tab's signal bar
   is left standing above the rule. Escape, Close or a search gives the tabs back (app.js). */
@media (min-width: 1024px) and (max-width: 1303px) {
  .masthead.app.search-open .site-tabs { display: none; }
  .masthead.app.search-open form.search { grid-column: 2 / 4; grid-row: 1; margin: 0 0 0 1.25rem; }
  .masthead.app.search-open .search-toggle { background: transparent; border-color: var(--hairline); }
  .masthead.app.search-open .search-toggle .when-closed { display: none; }
  .masthead.app.search-open .search-toggle .when-open { display: inline-flex; align-items: center; gap: .35rem; }
}
/* a phone and a narrow window: a compact bar that stays at the top — the lockup, the search
   button and Menu. Below 1,024 px: the icon tabs and the organization's menu need about
   1,011 px on one line (measured 2026-09-26). */
@media (max-width: 1023px) {
  html { scroll-padding-top: 5.5rem; }  /* a jumped-to heading clears the bar */
  .masthead.app { position: sticky; top: 0; z-index: 40; }
  .masthead.app .bar { padding-top: max(6px, env(safe-area-inset-top)); padding-bottom: 6px;
    padding-left: max(1rem, env(safe-area-inset-left)); padding-right: max(.5rem, env(safe-area-inset-right)); }
  .masthead.app .wordmark { margin: -6px 0; padding: 6px 0; }  /* the compact bar's 6 px */
  .masthead.app .site-tabs, .masthead.app .org-menu { display: none; }
  .masthead.app .menu-toggle { display: inline-flex; }
  .masthead:not(.app) .bar { flex-wrap: wrap; gap: .5rem 1.25rem; }
  .site-links { margin-left: 0; }
}
/* a phone's search has no button beside it (Prompt 13 item 2, 2026-09-26): the field is a
   search field, so the keyboard carries its own Search key, and the placeholder reads whole */
@media (max-width: 719px) {
  .masthead.app form.search button[type="submit"] { display: none; }
}
/* the phone's menu: a panel from the right over the dimmed page, clear of the notch and the
   home indicator; under reduced motion it appears without sliding */
.menu-scrim { position: fixed; inset: 0; z-index: 60; background: var(--scrim); opacity: 0; transition: opacity .2s ease; }
.menu-scrim.open { opacity: 1; }
.site-menu { position: fixed; top: 0; right: 0; bottom: 0; z-index: 61; width: min(22rem, 88vw); display: flex; flex-direction: column;
  overflow-y: auto; overscroll-behavior: contain; background: var(--surface); box-shadow: -10px 0 28px var(--shadow);
  padding: max(10px, env(safe-area-inset-top)) env(safe-area-inset-right) max(16px, env(safe-area-inset-bottom)) 0;
  transform: translateX(100%); transition: transform .25s ease; }
.site-menu.open { transform: none; }
.menu-scrim[hidden], .site-menu[hidden] { display: none; }
@media (prefers-reduced-motion: reduce) { .site-menu, .menu-scrim { transition: none; } }
.site-menu-head { display: flex; align-items: center; gap: .75rem; padding: .35rem .75rem .9rem 1.25rem; border-bottom: 1px solid var(--hairline); }
.site-menu-head .org-name { flex: 1 1 auto; color: var(--ink); font-weight: 600; font-size: 1.0625rem; overflow-wrap: anywhere; }
.menu-close { display: inline-flex; align-items: center; gap: .35rem; min-height: 44px; padding: 0 .7rem; background: none;
  border: 1px solid var(--hairline); border-radius: 4px; color: var(--ink); font: inherit; font-weight: 500; cursor: pointer; }
.site-menu-rows { display: flex; flex-direction: column; padding: .4rem 0; }
.site-menu-rows a, .site-menu-rows form.signout button { display: flex; align-items: center; gap: .9rem; width: 100%; min-height: 56px;
  padding: 0 1.25rem; color: var(--ink); text-decoration: none; font: inherit; font-size: 1.125rem; font-weight: 500;
  background: none; border: 0; border-left: 4px solid transparent; text-align: left; cursor: pointer; }
.site-menu-rows .icon { color: var(--muted); flex: none; }
.site-menu-rows a[aria-current="page"] { border-left-color: var(--signal); background: var(--signal-wash); font-weight: 600; }
.site-menu-rows a[aria-current="page"] .icon { color: var(--signal); }
.site-menu-rows.account-rows a, .site-menu-rows.account-rows form.signout button { min-height: 52px; font-size: 1rem; }
.site-menu-rows form.signout { margin: 0; }
.site-menu hr { border: 0; border-top: 1px solid var(--hairline); margin: .25rem 1.25rem; }
@media (min-width: 1024px) { .menu-scrim, .site-menu { display: none !important; } }
body.menu-locked { overflow: hidden; }

/* --- in-page tabs (Prompt 9 items 7 and 8): /filings's sections and the account's two tabs,
   the header's tab a size smaller, each with its count where it has one. Server-rendered
   links with their own URLs, so the back button, a reload and a bookmark keep the tab. On a
   phone the row scrolls sideways rather than wrapping. */
nav.tabs, nav.page-tabs { display: flex; gap: .15rem; border-bottom: 1px solid var(--hairline); margin: .25rem 0 1.1rem;
  overflow-x: auto; scrollbar-width: none; }
nav.tabs::-webkit-scrollbar, nav.page-tabs::-webkit-scrollbar { display: none; }
nav.tabs a, nav.page-tabs a { display: inline-flex; align-items: center; gap: .4rem; flex: none; padding: .45rem .7rem .5rem;
  color: var(--body); font-size: .9375rem; font-weight: 500; text-decoration: none; white-space: nowrap;
  border-bottom: 3px solid transparent; margin-bottom: -1px; }
nav.tabs a[aria-current="page"], nav.page-tabs a[aria-current="page"] { color: var(--ink); font-weight: 600; border-bottom-color: var(--signal); }
@media (hover: hover) { nav.tabs a:hover, nav.page-tabs a:hover { background: var(--band); color: var(--ink); } }
nav.page-tabs .count { font-weight: 500; }
nav.page-tabs a.empty { color: var(--muted); }
/* the Organization tab's logo row */
.logo-now { display: inline-flex; align-items: center; gap: .6rem; }
/* the file, and beside it Replace with Remove under it, one width (Prompt 34 item 3): a line
   of its own under the logo, the file level with Replace. Outside form.inline, the buttons
   take the control's size here, as Route Builder's Add does */
.panel .grid .v form.logo-form { flex-basis: 100%; display: grid; grid-template-columns: auto auto; justify-content: start; align-items: center;
  gap: .4rem .75rem; margin: 0; }
.logo-form input[type="file"] { grid-column: 1; grid-row: 1; min-width: 0; font-family: var(--font-sans); font-size: .875rem; }
.logo-form .logo-buttons { display: contents; }
.logo-form .logo-buttons button { grid-column: 2; }
.logo-form .logo-buttons button + button { grid-row: 2; }
/* the page's kind above its heading (Details, 2026-09-26): on Details the heading is the business,
   across the page, its label above it (Prompt 16 item 1); the card below starts at the address,
   which keeps clear of the record id in the card's corner as the name did */
.page-head { margin: .25rem 0 1rem; }
.page-head h1 { margin: 0; overflow-wrap: anywhere; }
.page-head h1 .muted { font-weight: 400; }
.card.untitled > .addr { padding-right: 6.5rem; }
/* Watch on Details (Prompt 17 part 3): an outlined button under the heading, or the word
   Watching with the way to stop; one line on a wide screen, wrapping on a phone */
form.watch { display: flex; flex-wrap: wrap; align-items: center; gap: .35rem .75rem; margin: .6rem 0 0; }
form.watch .watch-button .icon { width: 16px; height: 16px; flex: none; }  /* its look is the button system's secondary */
form.watch .watching { display: inline-flex; align-items: center; gap: .4rem; font-weight: 600; color: var(--ink); }
form.watch .watch-note { flex: 1 1 18rem; font-size: .875rem; }
/* the Alerts tab's Stop watching: a quiet link-button in its row (never form.inline's fill) */
form.unwatch { display: inline; margin: 0; }
form.unwatch button.link { white-space: nowrap; min-height: 44px; }
/* its row's last cell: Stop watching, then Share at the cell's bottom right (Prompt 23 item 5,
   2026-09-28; Share under Stop watching since Prompt 106 item 1, 2026-10-04) */
table.results.watching td.watch-actions { white-space: nowrap; text-align: right; }
/* Details' timeline and licence history (Tobias, Prompt 32 items 7 to 9, 2026-09-29): a date whole
   on its line, "seen" small under it; a term may wrap between its two dates, never inside one;
   the city's record small at the row's end; how Dowser found the rows behind a line */
table.results td.date { white-space: nowrap; }
table.results td.date.term { white-space: normal; }
.timeline .seen { display: block; font-size: .75rem; line-height: 1.3; color: var(--muted); }
/* A list of names opened in place (ruled 2026-10-01; Prompts 80 item 7 and 81 item 2c): the
   rest continue on the same line, one flowing list, and the control sits after the last name
   showing, More… while closed, Less… while open. Its checkbox holds the state (_owners.html). */
.more-flow > .more-rest, .more-flow > .more-gap { display: none; }
.more-flow:has(> .more-toggle > input:checked) > .more-rest, .more-flow:has(> .more-toggle > input:checked) > .more-gap { display: inline; }
.more-flow:has(> .more-toggle > input:checked) > .more-sep { display: none; }
.more-toggle { font: inherit; cursor: pointer; color: var(--signal); text-decoration: underline; white-space: nowrap; }  /* a label: the form labels' size and weight are not its */
.more-toggle:has(> input:checked) { color: var(--muted); }
.more-toggle:has(> input:focus-visible) { outline: 2px solid var(--focus); outline-offset: 2px; }
.more-toggle > input:checked ~ .when-closed, .more-toggle > input:not(:checked) ~ .when-open { display: none; }
/* the same in rows (the Dashboard's New panel): the rest above, the control under the last row */
.more-block > .more-rest { display: none; }
.more-block:has(> .more-toggle > input:checked) > .more-rest { display: block; }
.more-block > .more-toggle { display: inline-block; margin: .25rem 0; }
details.how { margin: .25rem 0 .75rem; }
details.how > summary { cursor: pointer; color: var(--muted); font-size: .875rem; }
details.how > p { margin: .35rem 0 0; }
/* a dashboard list's "Show more", at its bottom right (Prompt 31 item 2, 2026-09-29) */
.show-more { margin: .5rem 0 0; text-align: right; }
main > section.plain > p.show-more, .plain p.show-more { max-width: none; } /* at the table's right edge, not the prose's */
.show-more a { display: inline-block; min-height: 44px; line-height: 44px; font-weight: 500; }
.dash-newest [data-more-item] { display: contents; }
.more-past { margin: .25rem 0 0; text-align: right; }
.dash-newest [data-more-item][hidden] { display: none; }
/* the news mark on a watched record (Tobias, Prompt 31 item 3, 2026-09-29): New, in the signal
   colour, beside the name; its definition on a desktop's hover says what changed, and a phone,
   which shows no tooltip, reads it as a line under the name instead */
.news { display: inline-block; margin-left: .4rem; padding: 0 .45rem; font-size: .75rem; font-weight: 600; line-height: 1.5; color: var(--on-signal); background: var(--signal); border-radius: 999px; vertical-align: .08em; }
.news-line { display: none; font-size: .875rem; color: var(--signal); }
@media (hover: none), (pointer: coarse) { .news-line { display: block; } .news-line + br { display: none; } }
/* Stop watching, then Share under it at the cell's bottom right, as on a card (Prompt 106 item 1,
   2026-10-04: every record box; Share sat above Stop watching from Prompt 31 item 5 until then) */
table.results.watching td.watch-actions form.unwatch { display: block; }
table.results.watching td.watch-actions .share { display: inline-flex; margin: .15rem -.5rem 0 0; }
/* on a phone each watched record is a block, as a member is (no sideways scroll, so Share and
   Stop watching stay in view): the name and address, the latest, since when, then Stop watching
   with Share at the line's right end */
@media (max-width: 39.99rem) {
  table.results.watching thead { display: none; }
  table.results.watching, table.results.watching tbody, table.results.watching tr,
  table.results.watching td { display: block; width: 100%; }
  table.results.watching tr { border-bottom: 1px solid var(--hairline); padding: .5rem 0; }
  table.results.watching td { border: 0; padding: .15rem 0; }
  table.results.watching td.date::before { content: "Watching since "; color: var(--muted); }
  /* Stop watching on the block's last line, Share at that line's right end: the block's
     bottom-right corner, as on a card (Prompt 106 item 1, 2026-10-04; Share came first on
     the line until then) */
  table.results.watching td.watch-actions { display: flex; align-items: center; justify-content: space-between; gap: 1.25rem; text-align: left; }
  table.results.watching td.watch-actions .share, table.results.watching td.watch-actions form.unwatch { display: inline-flex; vertical-align: middle; }
  table.results.watching td.watch-actions .share { margin: 0; }  /* inside the cell: a negative margin scrolled the table sideways; it follows Stop watching in the page's order, so focus and the eye agree */
}
.eyebrow { margin: .25rem 0 .35rem; font-size: .8125rem; font-weight: 600; letter-spacing: .06em; text-transform: uppercase; color: var(--muted); }
/* The filter panel on a phone (Prompt 12 item 3, 2026-09-26): folded behind Filters, which
   shows how many filters are set, so the results come first; on a wider screen the panel is
   open and the button not shown. */
details.filters-fold > summary.filters-toggle { display: none; }
details.filters-fold > summary::-webkit-details-marker { display: none; }
@media (max-width: 719px) {
  details.filters-fold > summary.filters-toggle { display: inline-flex; align-items: center; gap: .5rem; min-height: 44px;
    padding: 0 1rem; margin: 0 0 .75rem; list-style: none; cursor: pointer; font-weight: 500; color: var(--ink);
    background: transparent; border: 1px solid var(--ink); border-radius: 3px; }
  details.filters-fold[open] > summary.filters-toggle { background: var(--band); }
  details.filters-fold .filters-set[hidden] { display: none; }
}

/* Every text field and select at 16 px or more on a phone (Prompt 16 item 3, 2026-09-26):
   iPhone Safari zooms the page into a field whose text is smaller the moment it is tapped: the
   header's search and the filters' fields were 15 px, a card's Status 13 px. The fix is the
   text's size, never turning zoom off: the viewport meta leaves zooming on, and a test holds it
   there. Below 1,024 px, which is every phone in either orientation. A floor over every
   component's own size, so it is marked important. */
@media (max-width: 1023px) {
  input:not([type="checkbox"]):not([type="radio"]):not([type="range"]):not([type="file"]):not([type="color"]):not([type="button"]):not([type="submit"]):not([type="reset"]):not([type="image"]):not([type="hidden"]),
  select, textarea { font-size: max(1rem, 16px) !important; }
}

/* The dashboard (Prompt 17 part 2, 2026-09-26): quiet like the rest. Counts first, each a link to
   the list it counts; two columns on a wide screen, the parts in their order on a phone. */
.dash-fresh { margin: -.25rem 0 1rem; }
.dash { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 1rem 1.25rem; align-items: start; }
.dash-part { margin: 0; }
.dash-part#new, .dash-part#operations { grid-column: 1 / -1; }
.dash-part h2 { margin-top: 0; }
.dash-part h2 .muted { font-weight: 400; font-size: .9375rem; }
.dash-counts { list-style: none; margin: 0 0 .75rem; padding: 0; display: flex; flex-wrap: wrap; gap: .5rem 1.25rem; }
.dash-counts a { display: inline-flex; align-items: center; gap: .45rem; min-height: 44px; color: var(--ink); text-decoration: none; }
.dash-counts a span:not(.count) { text-decoration: underline; text-decoration-color: var(--hairline); text-underline-offset: 3px; }
@media (hover: hover) { .dash-counts a:hover span:not(.count) { text-decoration-color: var(--ink); } }
.dash-list { list-style: none; margin: 0; padding: 0; }
/* New's items (Prompt 75): a category's count heads its rows; the rest open under More… */
.new-group { margin: 0 0 .5rem; }
.new-group .dash-counts { margin: .25rem 0 0; }
.new-rows li { padding: .4rem 0; }
.new-continued { margin: .5rem 0 0; font-size: .875rem; }
.dash-list li { padding: .55rem 0; border-top: 1px solid var(--hairline); }
.dash-list li:first-child { border-top: 0; }
/* New's rows, richer and tighter (Prompt 102 item 4): the name and its tag, then one muted line */
.dash-list.new-rows li { padding: .3rem 0; line-height: 1.35; }
.new-rows .new-name { font-weight: 500; }
.new-rows .new-line { display: block; font-size: .875rem; color: var(--muted); }  /* 14px: above the 13px floor (R-018) */
.new-rows .new-line .rid-inline { font-size: inherit; }  /* the ID at 14px, never under the floor */
.new-also { margin: .1rem 0 .2rem; font-size: .875rem; }
/* Share on a dashboard row, at its right (Prompt 33 item 4, 2026-09-29), at the row's bottom
   right, beside its last line, as on a card (Prompt 106 item 1, 2026-10-04; at its top right
   until then). A route's stop carries Share in its own foot since then (.card-foot). */
.dash-list li:has(> button.share) { position: relative; padding-right: 5.75rem; }
.dash-list li > button.share { position: absolute; right: -.5rem; bottom: .5rem; }
.dash-facts { margin: .75rem 0; padding-left: 1.1rem; }
.dash-facts li { margin: .2rem 0; }
.dash-newest { margin-top: .5rem; }
/* one column on a phone, never wider than the screen (2026-10-02, Prompt 83): a bare `1fr`
   track is at least as wide as its widest content, so one long unbroken word in a table, an
   Operations call's escaped command, widened the column and every panel with it past the
   screen, and the page scrolled sideways under the menu. minmax(0, 1fr) keeps the column to
   the screen, and a wide table scrolls inside its own .table-wrap, as on a desktop. */
@media (max-width: 719px) {
  .dash { grid-template-columns: minmax(0, 1fr); }
}
/* a call's command, as the gate keeps it, breaks anywhere rather than stretching its table,
   at a readable width; past the screen, the table scrolls inside its .table-wrap */
td.asked { overflow-wrap: anywhere; min-width: 12rem; }


/* A note on a term (ruled by Tobias 2026-10-01, operating rule 16): the explanation hidden but
   reachable. The term is a button with a dotted underline; its note opens on hover, on keyboard
   focus and on a tap (app.js toggles .open), never on hover alone. */
span.note { position: relative; display: inline; }  /* span: a card's own note line is a div.note, and stays a block */
.note-term { font: inherit; color: inherit; background: none; border: 0; padding: 0; margin: 0; cursor: help; text-decoration: underline dotted; text-decoration-color: var(--muted); text-underline-offset: .2em; }
.note-term:focus-visible { outline: 2px solid var(--focus); outline-offset: 2px; }
.note-body { display: none; position: absolute; left: 0; top: calc(100% + .35rem); z-index: 40; width: max-content; max-width: min(22rem, 80vw); padding: .5rem .65rem; background: var(--ink); color: var(--paper); font-family: var(--font-sans); font-size: .8125rem; font-weight: 400; line-height: 1.4; letter-spacing: 0; text-transform: none; white-space: normal; border-radius: .2rem; border: 1px solid var(--hairline); }
@media (hover: hover) { .note:hover > .note-body { display: block; } }
.note-term:focus-visible + .note-body, .note.open > .note-body { display: block; }
/* on a phone the note sits across the screen near its foot, inside the 16px gutters, so it is never
   cut off at the right edge, however far right its term is (seen 2026-10-01 at 375px) */
@media (max-width: 640px) { .note-body { position: fixed; left: 16px; right: 16px; top: auto; bottom: 16px; width: auto; max-width: none; z-index: 70; } }
.owners-label { color: var(--muted); }  /* the owners' names' label on a card (Prompt 76) */
/* every label on a card in the owners' label colour, its value in the body's (Prompt 102 item 2) */
.card-label { color: var(--muted); }  /* 15.2px on .kind and .note: above the 13px floor (R-018) */
.card .kind, .card .note { color: var(--body); }

/* the map's key (Prompt 87, request 283): each symbol as map.js draws it, beside its meaning */
.map-legend { list-style: none; display: flex; flex-wrap: wrap; gap: .5rem 1.5rem; margin: .75rem 0; padding: 0; font-size: .9375rem; color: var(--body); }
.map-legend li { display: inline-flex; align-items: center; gap: .5rem; }
.map-legend .sym { display: inline-flex; align-items: center; justify-content: center; flex: none; border-radius: 50%; box-shadow: 0 0 0 1.5px var(--map-ring); }
.map-legend .dot { width: 10px; height: 10px; }
.map-legend .hint { color: var(--muted); }
.map-legend .filing { background: var(--map-filing); }
.map-legend .active { background: var(--map-license); }
.map-legend .cluster { width: 26px; height: 26px; background: var(--map-license); background: color-mix(in srgb, var(--map-license) 88%, transparent); color: var(--paper); font-size: .75rem; font-weight: 600; box-shadow: 0 0 0 2px var(--map-ring); }

/* statuses (WO-016): the pill between the ID and Share, wrapping below the ID on a narrow card
   rather than compressing Share; the block's control, its note beside it, Save, its reasons, and
   Status history */
.card .corner { flex-wrap: wrap; justify-content: flex-end; max-width: 9.5rem; }
/* (the corner was three rows, ID, pill and Share, until Prompt 102 item 3: one row now) */
.status-history form.undo button.link, .status-history form.undo button.link:hover { background: none; border: 0; padding: 0; color: var(--signal); text-decoration: underline; line-height: inherit; font-size: inherit; }
.status-pill { display: inline-block; margin: .1rem .5rem 0; padding: .05rem .45rem; border: 1px solid var(--hairline); border-radius: 999px; font-size: .75rem; line-height: 1.5; color: var(--body); background: var(--surface); white-space: nowrap; }
.status-pill[data-status="new"] { color: var(--muted); }
.status-pill[data-status="won"], .status-pill[data-status="meeting_set"] { border-color: var(--signal); color: var(--signal); }
.status-pill[data-status="not_applicable"], .status-pill[data-status="lost"], .status-pill[data-status="not_a_fit"] { text-decoration: none; color: var(--muted); background: var(--paper); }
.status-block { margin: .5rem 0 0; font-size: .8125rem; }
.status-update { display: flex; flex-wrap: wrap; align-items: center; gap: .4rem .6rem; }
.status-update .status-pick { display: inline-flex; align-items: center; gap: .4rem; }
.status-update select, .status-update textarea { font: inherit; font-size: .8125rem; padding: .2rem .35rem; border: 1px solid var(--hairline); background: var(--surface); color: var(--ink); border-radius: .2rem; }
.status-update .status-note { flex: 1 1 12rem; min-width: 0; display: flex; }
.status-update textarea { width: 100%; min-height: 1.9rem; resize: vertical; }
/* a status's Save and a business's Add note (WO-016) are the button system's secondary, at the
   one height like every other button (Prompt 136 item 2; they were a compact .8125rem button
   until then, and their hover a white flash); the status control's select takes that height so
   the row's two controls match */
.status-update select { height: var(--control); }
.status-update .saved { color: var(--muted); }
.status-update .refused { color: var(--signal); }
.status-reasons { flex-basis: 100%; display: flex; flex-wrap: wrap; gap: .35rem; border: 0; margin: 0; padding: 0; }
.status-reasons[hidden] { display: none; }
.status-reasons legend { float: left; margin-right: .4rem; color: var(--muted); }
.status-reasons .chip { display: inline-flex; align-items: center; gap: .25rem; padding: .1rem .5rem; border: 1px solid var(--hairline); border-radius: 999px; }
.status-history { margin-top: .35rem; }
.status-history summary { cursor: pointer; color: var(--muted); }
.status-history ol.history { margin: .35rem 0 0; padding-left: 1.1rem; }
.status-history .history-rows { margin: 0; }
.status-history .change { color: var(--ink); }
.status-history li { margin: .2rem 0; }
.status-history .history-note { color: var(--body); white-space: normal; overflow-wrap: anywhere; }
.status-history form.undo { display: inline; margin-left: .4rem; }
@media (max-width: 719px) { .card .corner { max-width: 7rem; } }

/* notes on a business (WO-016's second phase): the card's line, the record page's thread */
.notes-line { margin: .35rem 0 0; font-size: .8125rem; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.notes-thread .note-add { display: flex; flex-wrap: wrap; align-items: flex-end; gap: .4rem .75rem; font-size: .8125rem; }
.notes-thread .note-field { flex: 1 1 100%; display: flex; flex-direction: column; gap: .2rem; }
.notes-thread textarea { font: inherit; font-size: .875rem; padding: .3rem .4rem; border: 1px solid var(--hairline); background: var(--surface); color: var(--ink); border-radius: .2rem; width: 100%; min-height: 3.2rem; resize: vertical; }
.notes-thread .note-add .refused { color: var(--signal); }
.notes-thread label.check { display: inline-flex; align-items: center; gap: .35rem; }
.notes-thread label.check input { width: auto; margin: 0; }
.notes-thread ol.notes { margin: .75rem 0 0; padding: 0; list-style: none; max-width: none; }
.notes-thread ol.notes > li { padding: .5rem 0; border-top: 1px solid var(--hairline); font-size: .875rem; }
.notes-thread .note-text { margin: .2rem 0; color: var(--ink); white-space: pre-line; overflow-wrap: anywhere; }
.notes-thread form.inline { display: inline; margin-right: .6rem; }
.team-note > summary { cursor: pointer; list-style-position: inside; }
.team-note > summary h2 { display: inline; margin: 0; }
.team-note-text { margin: .5rem 0 .25rem; color: var(--ink); white-space: pre-line; overflow-wrap: anywhere; }
.team-note-by { margin: 0 0 .5rem; font-size: .8125rem; }
.team-note-change > summary, .route-note > summary { cursor: pointer; font-size: .8125rem; }
.team-note-edit textarea, .route-note textarea { display: block; width: 100%; font: inherit; font-size: .875rem; padding: .3rem .4rem; border: 1px solid var(--hairline); background: var(--surface); color: var(--ink); border-radius: .2rem; margin: .2rem 0 .4rem; resize: vertical; }
.territory-note { font-size: .8125rem; color: var(--body); white-space: pre-line; overflow-wrap: break-word; }
.territory-table tr:has(+ tr.territory-note-row) td { border-bottom: 0; }
.territory-table tr.territory-note-row td { padding-top: 0; }
form.plain textarea { display: block; width: 100%; max-width: 28rem; font-family: var(--font-sans); font-size: .9375rem; padding: .4rem .6rem; color: var(--ink); border: 1px solid var(--hairline); background: var(--surface); border-radius: 3px; margin-top: .25rem; }
.route-note-text { white-space: pre-line; overflow-wrap: anywhere; color: var(--body); font-size: .875rem; }
.notes-thread button.link, .notes-thread button.link:hover { background: none; border: 0; padding: 0; color: var(--signal); text-decoration: underline; font-size: .8125rem; line-height: inherit; cursor: pointer; }

/* Chicago's rules over Applied, as a note (Prompt 89 part 3A) */
.tab-note { margin: .25rem 0 .75rem; }

/* WO-015's 15b: "Report a problem" (record_report.html) */
.report-form .report-fields { border: 0; margin: .5rem 0 1rem; padding: 0; }
.report-form .report-fields legend { font-weight: 600; margin-bottom: .35rem; }
.report-form label.report-choice { display: flex; flex-wrap: wrap; align-items: baseline; gap: .2rem .6rem; margin: .35rem 0; }
.report-form label.report-choice input { display: inline-block; width: auto; max-width: none; height: auto; margin: 0; flex: none; }
.report-form label.report-choice .muted { flex-basis: 100%; margin-left: 1.6rem; font-size: .875rem; overflow-wrap: anywhere; }
.report-link { margin-top: .75rem; font-size: .875rem; }

/* WO-015's 15a: Ask us on /help, a request's messages, Tobias's queue's filter */
.ask-form .ask-kinds { border: 0; margin: .25rem 0 .75rem; padding: 0; }
.ask-form .ask-kinds legend { font-weight: 600; margin-bottom: .35rem; }
.ask-form .ask-kinds label.check { display: flex; align-items: center; gap: .5rem; margin: .3rem 0; }
.ask-form .ask-kinds label.check input { display: inline-block; width: auto; height: auto; margin: 0; }
/* a request's messages are a ruled list, so they take the column under its notice, and each
   message's words keep the measure (Prompt 110 item 1: at the measure the rules stopped 219 px
   short of the "sent" notice above them, at 1,280 wide) */
.support-messages { list-style: none; padding: 0; max-width: none; }
.support-messages > li { padding: .6rem 0; border-top: 1px solid var(--hairline); }
.support-body { margin-top: .25rem; color: var(--ink); white-space: pre-line; overflow-wrap: anywhere; max-width: var(--measure); }
/* a screenshot as a thumbnail that opens full size (the ruled screens, 15a) */
.support-shot { display: inline-block; max-width: 100%; margin-top: .4rem; border: 1px solid var(--hairline); line-height: 0; }
/* a fixed bound, never a percentage of the frame the image itself sizes (it left the frame wider) */
.support-shot img { display: block; max-width: 16rem; max-height: 12rem; width: auto; height: auto; }

/* "Your organization", every member's card (Prompt 102 item 7): the logo, then the name, centred */
.org-card-head { display: flex; flex-direction: column; align-items: center; gap: .35rem; margin: .25rem 0 .75rem; }
.org-card-head .org-mark { width: 56px; height: 56px; border-radius: 50%; object-fit: cover; }
.org-card-name { margin: 0; font-weight: 600; text-align: center; }
.org-people { margin-bottom: .5rem; }
/* a card outside the member's prospecting focus, shown all the same (Prompt 121 ruling 7): the
   tag's shape in the muted token, a neutral mark, never a signal colour */
.tag--focus { border-color: var(--muted); color: var(--muted); }
/* the focus's Makers and Resellers sit under its three choices */
fieldset.focus-boxes { flex-basis: 100%; margin-top: .35rem; }  /* a line of its own in the value column, which is a wrapping row */

/* a file field's button (the logo on Organization, a screenshot on Ask us) is the site's outlined
   button, never the browser's grey one (Prompt 110 item 2, finished by Prompt 125) */
form.plain input[type="file"] { height: auto; padding: 0; border: 0; background: transparent; }  /* a file field is its button and the file's name, never a text box around them */
input[type="file"]::file-selector-button { margin-right: .6rem; padding: .3rem .8rem; font: inherit; color: var(--ink); background: transparent; border: 1px solid var(--ink); border-radius: 3px; cursor: pointer; }
@media (hover: hover) { input[type="file"]:not(:disabled)::file-selector-button:hover { background: var(--btn-secondary-hover-bg); } }
/* the ring inside the filled error block, where oxblood is 1.69:1: paper, 5.47:1 (Prompt 110
   item 2). Last in the file, and as specific as any focus rule above, so it holds for a note's
   term or a tag inside the block too */
.failure :focus-visible, .notice--error :focus-visible,
.failure .note-term:focus-visible, .notice--error .note-term:focus-visible,
.failure .has-tip:focus-visible, .notice--error .has-tip:focus-visible { outline-color: var(--focus-on-fill); }
/* MapLibre's own controls drew a blue glow on focus (maplibre-gl.css, which loads
   after this file): the ring instead, and no glow */
.map .maplibregl-ctrl-group button:focus, .map .maplibregl-ctrl-attrib-button:focus,
.map .maplibregl-ctrl-group button:focus:focus-visible { box-shadow: none; }
.map .maplibregl-ctrl-group button:focus-visible, .map .maplibregl-ctrl-attrib-button:focus-visible { outline: 2px solid var(--focus); outline-offset: 2px; }
/* a disabled control never shows the hand: the components that give their buttons a pointer
   (Add, Connect) come earlier at the same weight, so this last rule is the one that holds */
:root button:disabled, :root input:disabled, :root select:disabled, :root textarea:disabled { cursor: default; }
