/* AHRA Field — shared styles. The palette is the mockups' (apps/field/design/).
   System fonts on purpose: the mockups use Jost + Source Sans 3 from Google Fonts,
   and this site loads nothing from another origin (see vendor/README.md). Self-
   hosting those two (both OFL) is a later, separate download.
   The console is moving to the Dispatch board's look (3b): its tokens follow the first
   block below, and its classes are the last section, "The board's look". */

:root {
  --navy: #1b365d;
  --orange: #f05422;
  --ground: #faf8f5;
  --card: #ffffff;
  --alt: #f4f1ec;
  --rule: #e4dfd7;
  --muted: #5c7ba3;
  --dim: #93aac6;
  --ok: #2f6b4f;
  --warn: #b3340c;
  --bad: #a01b1b;
  --font: system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;

  /* The board's look: the Dispatch board mockup and Richard's daily screens drawn in it
     (the board's canvas, approved by Christian 2026-10-01). Added beside the names above,
     which the phone keeps unchanged. Contrast is on white unless it says otherwise; text
     needs 4.5:1. */
  --ink: var(--navy);      /* text, primary fills, a pressed control */
  --ink-deep: #0f2240;     /* a link's hover */
  --on-ink: #d6deea;       /* a second line on a navy fill: 9.0:1 */
  --text-2: #4f6d94;       /* secondary text: 5.3:1, 4.7:1 on --alt */
  --text-3: #5f7896;       /* tertiary (a drive time, a skipped stop): 4.6:1 on white ONLY */
  --text-off: #8a9bb5;     /* a disabled control's words, never words that must be read */
  --line: var(--rule);
  --line-soft: #efeae2;    /* a divider inside a card */
  --line-dash: #d9d2c6;    /* an empty day's dashed edge */
  --line-off: #c9c2b6;     /* a disabled control's dashed edge */
  --sunk: #f7f4ef;         /* an empty day, a stop not reached yet */
  --track: #ece7df;        /* a meter's track, a photo's placeholder */
  --hatch: #ebe5dc;        /* time off: stripes of this and --alt */
  --tint-ink: #eef2f8;     /* on site now; a neutral tag */
  --tint-bad: #fdf5f5;     /* an urgent item */
  --line-bad: #e8b4b4;
  --tint-warn: #fffaf6;    /* a row waiting on a draft */
  --moved: #9a3412;        /* moved in: 7.3:1 */
  --tint-moved: #fdeee6;
  --line-moved: #f3c9b4;
  --over: #c2410c;         /* a day longer than the cleaner's longest */

  --fs-xs: 11px;           /* a stop's code under its name */
  --fs-s: 12px;            /* tags, tallies, badges */
  --fs-sm: 13px;           /* secondary lines */
  --fs-control: 14px;      /* buttons, selects, fields */
  --fs-body: 15px;
  --fs-lead: 16px;         /* a page's subtitle, a quoted note */
  --fs-name: 17px;         /* a property's or cleaner's name on a row; the week on the board */
  --fs-h2: 19px;           /* a card's or a group's heading */
  --fs-title: 28px;        /* a page's title */
  --fs-stat: 32px;         /* the count on a tile */

  --r-tag: 4px;
  --r-control: 6px;
  --r-card: 8px;
  --r-pill: 999px;
  --control: 44px;         /* the smallest a control may be: a touch target */
  --page-max: 1376px;
}

/* The console's secondary words in the board's colors (the old --muted is 4.4:1 on white
   and 3.9:1 on --alt; the old --dim is 2.4:1). Console only: the phone is unchanged. */
body.console {
  --muted: var(--text-2);
  --dim: var(--text-3);
}

* { box-sizing: border-box; }

body {
  margin: 0;
  background: var(--ground);
  color: var(--navy);
  font: 15px/1.45 var(--font);
  -webkit-font-smoothing: antialiased;
}

.bar {
  display: flex;
  align-items: center;
  gap: 16px;
  padding: 12px 20px;
  background: var(--card);
  border-bottom: 1px solid var(--rule);
}

.lockup { font-weight: 600; font-size: 21px; letter-spacing: -0.03em; }
.lockup i { font-style: normal; color: var(--orange); }
.where { color: var(--muted); font-size: 13px; letter-spacing: .12em; text-transform: uppercase; }
.who { margin-left: auto; display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.who .name { font-weight: 600; }

.badge {
  font-size: 12px;
  padding: 2px 8px;
  border: 1px solid var(--rule);
  border-radius: 999px;
  color: var(--muted);
  background: var(--alt);
}

.banner {
  padding: 10px 20px;
  background: var(--bad);
  color: #fff;
  font-weight: 600;
}
/* A newer console build is deployed (console/update.js): news, not a fault. */
.banner.update { background: var(--navy); font-weight: 400; }
.banner.update button { border-color: #fff; color: #fff; padding: 2px 12px; margin-left: 6px; }
.banner.update .why { display: block; margin-top: 4px; font-weight: 600; }
.banner.update .why:empty { display: none; }

main { padding: 20px 16px; margin: 0 auto; }
main.narrow { max-width: 480px; }
main.wide { max-width: 1100px; }

.panel {
  background: var(--card);
  border: 1px solid var(--rule);
  border-radius: 6px;
  padding: 18px 20px;
}

h1 { font-size: 20px; margin: 0 0 12px; }
h2 {
  font-size: 11px;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--muted);
  margin: 22px 0 8px;
}

.sections { display: flex; gap: 8px; flex-wrap: wrap; margin-bottom: 14px; }
.section {
  padding: 6px 12px;
  border: 1px solid var(--rule);
  border-radius: 4px;
  background: var(--card);
}
.section.pending { color: var(--dim); border-style: dashed; }

.facts { display: grid; grid-template-columns: max-content 1fr; gap: 6px 18px; margin: 0; }
.facts dt { color: var(--muted); }
.facts dd { margin: 0; font-weight: 600; word-break: break-word; }

ul.plain { padding-left: 18px; margin: 0; }
ul.plain li { margin: 4px 0; }

button {
  font: inherit;
  cursor: pointer;
  border: 1px solid var(--navy);
  background: transparent;
  color: var(--navy);
  border-radius: 4px;
  padding: 8px 14px;
}
button.primary { width: 100%; min-height: 48px; background: var(--navy); color: #fff; }
button.quiet { border-color: var(--rule); color: var(--muted); padding: 4px 10px; }
button:focus-visible { outline: 3px solid var(--orange); outline-offset: 2px; }

.ok { color: var(--ok); }
.warn { color: var(--warn); }
.bad { color: var(--bad); }
.dim { color: var(--dim); }

@media (max-width: 600px) {
  .bar { flex-wrap: wrap; }
  .facts { grid-template-columns: 1fr; }
  .facts dd { margin-bottom: 8px; }
}

/* ---- console sections ---------------------------------------------------- */

button.section { padding: 6px 12px; }
.section.on { background: var(--navy); color: #fff; border-color: var(--navy); }

input[type="text"], input[type="search"], select {
  font: inherit;
  color: var(--navy);
  background: var(--card);
  border: 1px solid var(--rule);
  border-radius: 4px;
  padding: 7px 10px;
  min-width: 0;
}
input:focus-visible, select:focus-visible { outline: 3px solid var(--orange); outline-offset: 1px; }

.small { font-size: 13px; }
.badge.warn { color: var(--warn); border-color: #f1c9b8; background: #fdf1eb; }
button.primary-inline { background: var(--navy); color: #fff; }
/* Schedule (S5 step 4): Publish while visits are undecided is disabled, and must look it. */
button.publish:disabled { opacity: 0.45; cursor: not-allowed; }

.flash { padding: 8px 12px; border-radius: 4px; background: var(--alt); margin: 0 0 12px; }

/* ---- codes ---------------------------------------------------------------- */

.split { display: grid; grid-template-columns: minmax(220px, 300px) 1fr; gap: 18px; align-items: start; }
.split input[type="search"] { width: 100%; margin-bottom: 8px; }
.picker { display: flex; flex-direction: column; gap: 4px; max-height: 70vh; overflow-y: auto; }
.pick {
  display: grid; gap: 2px; text-align: left; border: 1px solid var(--rule);
  border-radius: 4px; padding: 8px 10px; background: var(--card);
}
.pick.on { border-color: var(--navy); box-shadow: inset 3px 0 0 var(--orange); }
.pick .name { font-weight: 600; }
.pick .counts { display: flex; gap: 6px; align-items: center; font-size: 13px; color: var(--muted); }

.codes { display: flex; flex-direction: column; gap: 10px; margin: 10px 0; }
.code { border: 1px solid var(--rule); border-radius: 6px; padding: 10px 12px; background: var(--card); }
.code.retired { background: var(--alt); color: var(--muted); }
.code .head { display: flex; flex-wrap: wrap; gap: 8px; align-items: baseline; }
.code .kind {
  font-size: 11px; letter-spacing: .1em; text-transform: uppercase; color: var(--muted);
  border: 1px solid var(--rule); border-radius: 3px; padding: 1px 6px;
}
.code .actions { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 8px; }
.code .actions button { padding: 5px 10px; }
.inline { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; margin-top: 8px; }
.add { border-top: 1px solid var(--rule); margin-top: 18px; padding-top: 6px; }
.toggle { font-size: 13px; color: var(--muted); }

.reveal {
  border: 2px solid var(--orange); border-radius: 6px; padding: 12px 16px;
  margin: 0 0 14px; background: #fff7f3;
}
.reveal .value {
  font: 600 32px/1.2 ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  letter-spacing: .08em; margin: 6px 0; user-select: all;
}

.notices { margin: 0 0 14px; }
.notices h3 { font-size: 15px; margin: 12px 0 4px; }
.pre { white-space: pre-wrap; }

table.log { border-collapse: collapse; width: 100%; font-size: 13px; margin-top: 8px; }
table.log th, table.log td { text-align: left; padding: 4px 8px; border-bottom: 1px solid var(--rule); }
table.log th { color: var(--muted); font-weight: 600; }

@media (max-width: 800px) {
  .split { grid-template-columns: 1fr; }
  .picker { max-height: 40vh; }
}

/* ---- queue and people (S5 step 3; the Attention mockup's groups) ----------------- */

.grp { background: var(--card); border: 1px solid var(--rule); border-radius: 6px; margin: 14px 0; }
.ghead {
  display: flex; align-items: baseline; gap: 10px; padding: 10px 16px;
  border-bottom: 1px solid var(--rule); background: var(--alt); border-radius: 6px 6px 0 0;
}
.ghead h2 { margin: 0; }
.ghead .count { font-weight: 600; font-variant-numeric: tabular-nums; }
.rows { display: flex; flex-direction: column; }
.row {
  display: flex; gap: 12px; align-items: flex-start; justify-content: space-between;
  padding: 12px 16px; border-bottom: 1px solid var(--rule);
}
.row:last-child { border-bottom: 0; }
.row .what { flex: 1 1 auto; min-width: 0; }
.row .what p { margin: 4px 0; }
.row .acts { display: flex; flex-wrap: wrap; gap: 6px; justify-content: flex-end; flex: 0 0 auto; }
.row .acts button { padding: 6px 12px; white-space: nowrap; }
.pad { padding: 0 16px; margin: 8px 0; }
.kind {
  font-size: 11px; letter-spacing: .12em; text-transform: uppercase; font-weight: 600;
  color: var(--muted);
}
.kind.bad { color: var(--bad); }
.kind.warn { color: var(--warn); }
.badge.bad { color: #fff; background: var(--bad); border-color: var(--bad); }
/* 6c.1: a tech's note on a queue row stands out from the row's other lines: its own tinted block, a bar on the left, its
   number, who and when, the words at body size, and its photos inside it (Christian, 2026-09-30). */
.tech-note { margin: 8px 0; padding: 8px 12px; background: #fdf6e3; border-left: 3px solid #d9a441; border-radius: 0; }
.row .what .tech-note p { margin: 2px 0; }
.tech-note .note-head { font-size: 12px; color: #7a4f00; }
.tech-note .note-body { font-size: 15px; font-weight: 600; color: var(--navy); overflow-wrap: anywhere; white-space: pre-wrap; }
.tech-note .strip { margin-top: 6px; }
.badge.note { color: #7a4f00; border-color: #ecd49a; background: #fdf6e3; }
/* 6c.2: a flag's photos on a queue row, headed with which flag ("On a flag: Safety"), a flag's red beside a note's amber. */
/* D-6 (2026-10-15): a Queue row's required photos, when one needs a look, are a callout in the flag photos' colors; the
   photo's line is body size wherever it is drawn (the Queue, the job page, a property's visit). */
.flag-photos, .shots-look { margin: 8px 0; padding: 8px 12px; background: #fdf1eb; border-left: 3px solid var(--warn); border-radius: 0; }
.row .what .flag-photos p, .row .what .shots-look p { margin: 2px 0; }
.shot-look { font-size: 15px; font-weight: 600; overflow-wrap: anywhere; }
.row .what p.badges { display: flex; flex-wrap: wrap; gap: 6px; }
.flag-photos .flag-head { font-size: 12px; color: var(--warn); }
.flag-photos .strip { margin-top: 6px; }
.form { display: flex; flex-direction: column; gap: 8px; margin-top: 10px; padding: 10px 12px;
        border: 1px solid var(--rule); border-radius: 6px; background: var(--alt); }
.form input[type="text"], .form input[type="date"], .form select { width: 100%; }
.form.grid label { display: flex; flex-direction: column; gap: 4px; font-size: 13px; color: var(--muted); }
.panel.inset { margin: 10px 0 18px; background: var(--alt); }
.panel.inset .form { border: 0; padding: 0; background: none; }
.banner b { margin-right: 4px; }
.banner [data-line] + [data-line] { margin-top: 4px; }
/* On dev data only (S6 step 3, screen 45): news, not a fault, so not red. */
.devline { padding: 10px 20px; background: #fffaf6; color: #9a3412; border-bottom: 1px solid #f3c9b4; }
.devline b { margin-right: 4px; }
/* The escalation job on a flag's row (S6 step 3 part B, screens 39-41). #9a3412 on #fdf3ec: 6.6:1. */
.badge.ui-esc-badge { color: #9a3412; border-color: #f1c7aa; background: #fdf3ec; font-weight: 700; }
.badge.ui-esc-badge.ui-esc-was { background: #fff; font-weight: 600; }
.ui-esc { margin: 2px 0; }
.ui-esc-alert { color: #9a3412; font-weight: 600; }
.ui-esc-clock { color: var(--ink); }
.ui-esc-dim { color: var(--text-2); }
/* People › Who gets flags (S6 step 3, screen 42): the board's 44 px targets; the three numbers are short fields. */
[data-panel="routing"] select, [data-panel="routing"] input, [data-panel="routing"] button { min-height: 44px; }
[data-panel="routing"] .form.grid input.ui-number { width: 6em; }
.ui-routing-rules { margin-top: 14px; display: flex; flex-direction: column; gap: 6px; }
.ui-routing-rules .ui-rule p { margin: 2px 0 0; }
.banner button { color: #fff; border-color: #fff; margin-left: 8px; }

@media (max-width: 700px) {
  .row { flex-direction: column; }
  .row .acts { justify-content: flex-start; }
}

/* Photos in the console (S4 step 6, 6b): the strips, the Photos screen and the viewer. */
input[type="date"] { font: inherit; padding: 6px 8px; border: 1px solid var(--rule); border-radius: 4px; background: var(--card); color: var(--navy); }
.strip { display: flex; flex-wrap: wrap; gap: 6px; margin: 8px 0; }
.thumb {
  width: 96px; height: 96px; padding: 0; overflow: hidden;
  display: flex; align-items: center; justify-content: center;
  background: var(--alt); border: 1px solid var(--rule); border-radius: 4px;
}
.thumb img { width: 100%; height: 100%; object-fit: cover; display: block; }
.thumb-words { font-size: 11px; color: var(--muted); padding: 4px; text-align: center; line-height: 1.2; }
.photo-day h2 { margin-top: 18px; }
.photo-visit { margin: 6px 0 12px; }
.viewer {
  position: fixed; inset: 0; z-index: 50;
  background: rgba(15, 26, 43, 0.92);
  display: flex; align-items: center; justify-content: center;
}
.viewer[hidden] { display: none; }
.viewer-box { width: 100%; height: 100%; display: flex; flex-direction: column; padding: 12px 16px; color: #fff; }
.viewer-box:focus { outline: none; }
.viewer-top { display: flex; align-items: center; justify-content: space-between; gap: 12px; }
.viewer-top .count { font-weight: 600; }
.viewer-top button { color: #fff; border-color: rgba(255, 255, 255, 0.5); font-size: 20px; line-height: 1; padding: 4px 12px; }
.viewer-stage { flex: 1; min-height: 0; display: flex; align-items: center; gap: 12px; }
.viewer-stage .stage { flex: 1; min-width: 0; height: 100%; display: flex; align-items: center; justify-content: center; }
.viewer-stage .stage img { max-width: 100%; max-height: 100%; object-fit: contain; display: block; }
.viewer-stage .arrow {
  flex: none; width: 56px; height: 96px; font-size: 40px; line-height: 1;
  color: #fff; border-color: rgba(255, 255, 255, 0.5); background: transparent;
}
.viewer-stage .arrow:disabled { opacity: 0.25; cursor: default; }
.viewer-stage .placeholder { color: #fff; font-size: 18px; text-align: center; }
.viewer-stage .placeholder button { color: #fff; border-color: rgba(255, 255, 255, 0.5); margin-top: 8px; }
.viewer-box .line { margin: 8px 0 0; text-align: center; }
.viewer-box .line.warn { color: #ffb899; }

/* ---- the Queue in the board's look (S5 step 4b part C, screen 6), console only ---------- */
body.console .ui-queue-filters { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; margin: 12px 0 4px; }
body.console .ui-queue-chips { display: flex; gap: 8px; flex-wrap: wrap; margin-right: auto; }
body.console .ui-queue-group { margin-top: 18px; }
body.console .ui-queue-group .count, body.console .ui-queue-more .count {
  font-size: var(--fs-sm); font-weight: 700; padding: 1px 8px; border-radius: var(--r-pill); background: var(--line); }
body.console .ui-queue-rows { display: flex; flex-direction: column; gap: 10px; margin-top: 10px; }
body.console .ui-qrow { display: flex; flex-direction: column; gap: 6px; padding: 12px;
  border: 1px solid var(--line); border-radius: var(--r-card); background: var(--card); }
body.console .ui-qrow-urgent { border-color: var(--line-bad); background: var(--tint-bad); }
body.console .ui-qrow .row { border: 0; padding: 0; margin: 0; background: transparent; }
body.console .ui-qrow-tag { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
body.console .ui-qrow-alarm { font-size: var(--fs-sm); font-weight: 600; color: var(--bad); }
body.console .ui-queue-more { margin-top: 14px; border: 1px solid var(--line); border-radius: var(--r-card);
  background: var(--card); padding: 0 16px; }
body.console .ui-queue-more > summary { min-height: var(--control); display: flex; align-items: center; gap: 10px;
  cursor: pointer; flex-wrap: wrap; }
body.console .ui-queue-more[open] { padding-bottom: 12px; }

/* ---- Today (S5 step 4b part C, screen 5), console only; the one console screen with a phone layout (decision C) - */
body.console .ui-nav-count { display: inline-block; min-width: 22px; margin-left: 8px; padding: 1px 6px;
  border-radius: var(--r-pill); background: var(--bad); color: #fff; font-size: var(--fs-sm); font-weight: 700;
  text-align: center; }
body.console .ui-nav-count[hidden] { display: none; }
body.console .ui-today-tiles { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)) minmax(0, 1.3fr);
  gap: 12px; margin-top: 12px; }
body.console .ui-today-queue { display: flex; align-items: center; gap: 14px; padding: 14px 16px; text-align: left;
  min-height: var(--control); background: var(--ink); color: #fff; border: 0; border-radius: var(--r-card);
  font: inherit; cursor: pointer; }
body.console .ui-today-queue .small { color: #d6deea; }
body.console .ui-today-columns { display: grid; grid-template-columns: minmax(0, 1fr) 420px; gap: 16px;
  align-items: start; margin-top: 16px; }
body.console .ui-today-side { display: flex; flex-direction: column; gap: 16px; }
body.console .ui-today-cleaner { display: flex; flex-direction: column; gap: 8px; padding: 14px; margin-top: 12px;
  border: 1px solid var(--line); border-radius: var(--r-card); }
body.console .ui-today-where { font-weight: 600; }
body.console .ui-today-stops { list-style: none; margin: 0; padding: 0; display: grid;
  grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap: 8px; }
body.console .ui-today-stop { display: flex; flex-direction: column; gap: 2px; padding: 8px 10px; min-width: 0;
  border: 1px solid var(--line); border-radius: var(--r-card); overflow-wrap: break-word; }
body.console .ui-today-next { border-style: dashed; border-color: var(--ink); }
body.console .ui-today-stop-top { font-size: var(--fs-sm); line-height: 1.3; }
body.console .ui-today-stop-state { margin-top: 4px; font-size: var(--fs-sm); font-weight: 600; }
body.console .ui-state-done .ui-today-stop-state { color: var(--ok); }
body.console .ui-state-later .ui-today-stop-state { color: var(--text-2); font-weight: 400; }
body.console .ui-state-missed .ui-today-stop-state { color: var(--bad); }
body.console .ui-today-stop-tag { font-size: var(--fs-s, 12px); font-weight: 700; color: var(--warn); }
body.console .ui-today-columns p, body.console .ui-today-tiles + p { margin: 4px 0; }
body.console .ui-today-entry { display: flex; flex-direction: column; gap: 4px; padding: 8px 0;
  border-bottom: 1px solid var(--line); }
body.console .ui-today-foot { display: flex; gap: 20px; flex-wrap: wrap; align-items: center; margin-top: 16px;
  padding-top: 12px; border-top: 1px solid var(--line); }
body.console .ui-today-foot .ui-link:last-child { margin-left: auto; }
body.console button.ui-link { background: none; border: 0; padding: 0; min-height: var(--control); font: inherit;
  font-weight: 600; color: var(--ink); cursor: pointer; text-align: left; }
@media (max-width: 767px) {
  body.console .ui-today-tiles { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  body.console .ui-today-queue { grid-column: 1 / -1; }
  /* Needs you first, then where everyone is, this week, tomorrow (part C, T7). */
  body.console .ui-today-columns { display: flex; flex-direction: column; align-items: stretch; }
  body.console .ui-today-side { display: contents; }
  body.console .ui-today-columns [data-panel="queue"] { order: 0; }
  body.console .ui-today-main { order: 1; }
  body.console .ui-today-columns [data-panel="week"] { order: 2; }
  body.console .ui-today-columns [data-panel="tomorrow"] { order: 3; }
  body.console .ui-today-stops { grid-template-columns: minmax(0, 1fr); }
}

/* ---- Schedule in the board's look (S5 step 4b part C, screens 7 and 8), console only ---------------------------- */
body.console .ui-sched-inforce, body.console .ui-sched-off, body.console .ui-sched-draft { margin-top: 16px; }
body.console .ui-sched-label { font-size: var(--fs-sm); font-weight: 700; letter-spacing: 0.08em;
  text-transform: uppercase; color: var(--ok); }
body.console .ui-sched-label.warn { color: var(--warn); }
body.console .ui-sched-label.quiet { color: var(--muted); }
body.console .ui-sched-inforce .ui-card-top .ui-btn, body.console .ui-sched-off .ui-card-top .ui-btn,
body.console .ui-sched-draft .ui-card-top .ui-btn { margin-left: auto; }
body.console .ui-card[data-panel="today"] > .ui-card-top .ui-btn { margin-left: auto; }
body.console .ui-sched-table { display: flex; flex-direction: column; margin-top: 12px;
  border: 1px solid var(--line); border-radius: var(--r-card); overflow: hidden; }
body.console .ui-sched-tr { display: grid; grid-template-columns: 130px 120px 220px minmax(0, 1fr) 200px 96px;
  gap: 12px; padding: 12px 14px; align-items: center; }
body.console .ui-sched-th { background: var(--alt); font-size: var(--fs-sm); font-weight: 700; }
body.console .ui-sched-note { display: block; overflow-wrap: anywhere; }
body.console .row.ui-sched-entry { display: block; padding: 0; border-top: 1px solid var(--line); border-bottom: 0; }
body.console .ui-sched-late { background: var(--tint-warn, #fffaf6); }
body.console .ui-sched-outcome { display: flex; flex-direction: column; gap: 2px; }
body.console .ui-sched-extra:empty { display: none; }
body.console .ui-sched-extra { padding: 0 14px 12px; }
body.console .ui-sched-columns { display: grid; grid-template-columns: minmax(0, 1fr) 420px; gap: 16px;
  align-items: start; margin-top: 12px; }
/* Narrower than 1100 px (where the job and Properties pages stack too) the fixed 420 px side squeezed a draft's
   decisions to a sliver, the Move form to nothing at 768 px, and scrolled a phone sideways by 104 px (found in S6 step
   4 part B, 2026-10-09): one column, in the page's own order, what to decide first, then What publishing changes and
   Publish. */
@media (max-width: 1100px) { body.console .ui-sched-columns { grid-template-columns: minmax(0, 1fr); } }
/* A typed word longer than the column (a closure's note in its group's title, a decision's reason in its row) breaks
   rather than scrolling a phone sideways (review, 2026-10-10). Only those lines: the rows are flex rows, where
   `break-word` keeps the longest word's width, and `anywhere` on the whole draft split ordinary words in the Move
   form's side panel at 320 px. */
body.console .ui-sched-columns .what > p, body.console .ui-sched-columns .what > b { overflow-wrap: anywhere; }
body.console .ui-sched-earlier { margin-top: 16px; }
/* A group to decide: its forms on a line of their own under the title and the buttons (S5 step 4c part B). */
body.console .row.ui-sched-group { flex-wrap: wrap; row-gap: 6px; }
body.console .row.ui-sched-group > .what { flex: 1 1 0; min-width: 12em; }
body.console .ui-sched-forms { flex: 1 0 100%; min-width: 0; }
body.console .ui-sched-forms:not(:has(> p, .form)) { display: none; }
body.console .ui-sched-forms > p { margin: 0; }
body.console .ui-sched-forms .form { margin-top: 8px; }
/* Suggestions (S5 step 4c part B, screen 9b): one list per group under its header, each landing day once below it. */
body.console .ui-sug-list { display: flex; flex-direction: column; margin: 0 16px 12px; border: 1px solid var(--line);
  border-radius: var(--r-card); overflow: hidden; background: var(--card); }
body.console .ui-sug-tr { display: grid; grid-template-columns: minmax(140px, 200px) minmax(0, 1fr) auto; gap: 12px;
  padding: 10px 14px; align-items: center; }
body.console .ui-sug-th { background: var(--alt); font-size: var(--fs-sm); font-weight: 700; }
body.console .ui-sug-item { border-top: 1px solid var(--line); }
body.console .ui-sug-none { background: var(--alt); }
body.console .ui-sug-visit { display: flex; flex-direction: column; gap: 1px; min-width: 0; overflow-wrap: anywhere; }
body.console .ui-sug-extra:empty { display: none; }
body.console .ui-sug-extra { padding: 0 14px 12px; }
body.console .ui-sug-days { display: flex; flex-direction: column; gap: 4px; padding: 12px 14px;
  border-top: 1px solid var(--line); background: var(--alt); }
body.console .ui-sug-days p { margin: 0; }
body.console .ui-sug-more { margin: 0 16px 12px; }
@media (max-width: 700px) {
  body.console .ui-sug-tr { grid-template-columns: minmax(0, 1fr); gap: 6px; }
  body.console .ui-sug-th { display: none; }
}
body.console .ui-move-grid { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 16px;
  align-items: start; }
body.console .ui-move-aside { display: flex; flex-direction: column; gap: 12px; }
body.console .ui-move-aside:empty { display: none; }
body.console .ui-move-day, body.console .ui-move-else { padding: 10px 12px; border: 1px solid var(--line);
  border-radius: var(--r-card); background: var(--alt); }
body.console .ui-move-day h4, body.console .ui-move-else h4 { margin: 0 0 4px; }
body.console .ui-move-track { position: relative; height: 8px; background: var(--track); border-radius: 4px; margin: 6px 0 2px; }
body.console .ui-move-before, body.console .ui-move-after { position: absolute; top: 0; bottom: 0; left: 0; width: 0; }
body.console .ui-move-before { background: var(--ink); border-radius: 4px 0 0 4px; }
body.console .ui-move-after { background: #8fa6c4; }
body.console .ui-move-longest { position: absolute; top: -4px; bottom: -4px; width: 2px; background: var(--over); }
body.console .ui-move-scale { display: flex; justify-content: space-between; }
body.console .ui-move-route { margin: 6px 0 0; padding-left: 0; list-style: none; display: flex; flex-direction: column; gap: 4px; }
body.console .ui-move-this { padding: 4px 6px; border: 1px dashed var(--ink); border-radius: var(--r-card); }
/* A stop's drive, the stop and "This move…" each on a line of their own: as one line they ran together ("18 min drive2
   Place 2 · 60 minThis move…"), spans with nothing between them (seen 2026-10-03, fixed on Christian's word). */
body.console .ui-move-route li { display: flex; flex-direction: column; gap: 2px; }
body.console .ui-move-route .ui-stop-drive { padding-left: 14px; }

/* ---- part C's screens: every control at least 44 px (the plan's rule; the older rows' buttons were 32-40 px) ----- */
body.console .ui-queue-filters select,
body.console .ui-qrow button, body.console .ui-qrow select, body.console .ui-qrow input:not([type=checkbox]),
body.console .ui-queue-more button, body.console .ui-queue-more input:not([type=checkbox]),
body.console .ui-today-columns button, body.console .ui-today-foot button,
body.console .ui-sched-inforce button, body.console .ui-sched-off button, body.console .ui-sched-off select,
body.console .ui-sched-off input:not([type=checkbox]), body.console .ui-sched-draft button,
body.console .ui-sched-draft select, body.console .ui-sched-draft input:not([type=checkbox]) { min-height: var(--control); }

/* ---- the board's look (3b) ------------------------------------------------------------ */
/* What board part B and each screen restyled in 3b are built from; a screen's old rules
   above go when it moves over. `ui-` because the short names are taken (.tag, .tile, .count,
   .card-head, .line by the phone or the console), and `button.primary` above would make any
   button full width. Modifiers are classes of their own (ui-btn ui-btn-primary) for the same
   reason; the color words (.ok .warn .bad) still combine. Pressed is aria-pressed, not a
   class, so what reads as pressed is what a screen reader hears.
   No style="" anywhere: the policy is style-src 'self', which refuses style attributes. */

/* The sections bar, on every console screen. */
body.console .sections { gap: 8px; margin-bottom: 16px; }
body.console .section {
  display: inline-flex; align-items: center; gap: 8px;
  min-height: var(--control); padding: 0 14px; font-size: var(--fs-body);
  background: var(--card); color: var(--ink);
  border: 1px solid var(--line); border-radius: var(--r-control);
}
body.console .section.on { background: var(--ink); border-color: var(--ink); color: #fff; }
body.console .section.pending { background: transparent; border: 1px dashed var(--line-off); color: var(--text-off); }

/* The console's header and page (board part B): the mockups' 32 px gutter and 1376 px page. */
body.console .bar { gap: 14px; padding: 12px 32px; }
body.console .who button { min-height: var(--control); padding: 0 12px; font-size: var(--fs-control); }
body.console .banner, body.console .devline { padding: 10px 32px; }
body.console main.wide { max-width: var(--page-max); padding: 20px 32px 48px; }
@media (max-width: 600px) {
  body.console .bar, body.console .banner, body.console .devline { padding-left: 16px; padding-right: 16px; }
  body.console main.wide { padding: 16px 16px 32px; }
}

/* A page's head: title and subtitle, then "As of" and its buttons at the right. */
.ui-head { display: flex; align-items: flex-end; gap: 16px; flex-wrap: wrap; padding-top: 4px; }
.ui-head-words { display: flex; flex-direction: column; gap: 2px; }
.ui-title { margin: 0; font-size: var(--fs-title); font-weight: 700; letter-spacing: -0.01em; }
.ui-sub { margin: 0; font-size: var(--fs-lead); color: var(--text-2); }
.ui-asof { margin-left: auto; font-size: var(--fs-sm); color: var(--text-2); }

/* Cards, and the items inside them. */
.ui-card {
  display: flex; flex-direction: column; gap: 12px; padding: 20px;
  background: var(--card); border: 1px solid var(--line); border-radius: var(--r-card);
}
.ui-card-urgent { border-color: var(--line-bad); }
.ui-card-top { display: flex; align-items: baseline; gap: 12px; flex-wrap: wrap; }
.ui-h2 { margin: 0; font-size: var(--fs-h2); font-weight: 700; letter-spacing: normal; text-transform: none; color: inherit; }
.ui-h2.bad { color: var(--bad); }
.ui-note { font-size: var(--fs-sm); color: var(--text-2); }
.ui-item { display: flex; flex-direction: column; gap: 4px; padding: 12px; border: 1px solid var(--line); border-radius: var(--r-card); }
.ui-item-urgent { gap: 6px; border-color: var(--line-bad); background: var(--tint-bad); }
.ui-quote { margin: 0; padding: 10px 12px; background: var(--alt); border-radius: var(--r-control); font-size: var(--fs-lead);
            overflow-wrap: anywhere; }   /* a flag's or note's email address or URL wraps, never scrolls a phone sideways */
.ui-divider { height: 0; margin: 0; border: 0; border-top: 1px solid var(--line-soft); }
.ui-link { color: var(--ink); font-weight: 600; }
.ui-link:hover { color: var(--ink-deep); }

/* A Queue group's head: heading, its tally, what belongs in it. */
.ui-group { display: flex; align-items: baseline; gap: 10px; margin-top: 10px; }

/* Counts in a pill: in a group's head, or on a section's button. */
.ui-tally {
  display: inline-block; min-width: 22px; padding: 1px 8px; text-align: center;
  font-size: var(--fs-s); font-weight: 700; border-radius: var(--r-pill);
  background: var(--line); color: var(--ink);
}
.ui-tally-ink { background: var(--ink); color: #fff; }
.ui-tally-bad { background: var(--bad); color: #fff; }
.ui-tally-on-ink { background: #fff; color: var(--bad); }   /* on a pressed (navy) button */

/* What kind of thing a row is: Safety, Photo skipped, Check-in, a note's number. */
.ui-tag {
  display: inline-block; padding: 2px 8px; font-size: var(--fs-s); font-weight: 700;
  border-radius: var(--r-tag); background: var(--tint-ink); color: var(--ink);
}
.ui-tag-big { padding: 3px 10px; font-size: var(--fs-sm); }
.ui-tag-bad { background: var(--bad); color: #fff; }
.ui-tag-plain { background: var(--alt); border: 1px solid var(--line); }

/* Buttons, and links drawn as buttons. Every one at least 44 px tall. */
.ui-btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 6px;
  min-height: var(--control); padding: 0 14px;
  font: inherit; font-size: var(--fs-control); text-decoration: none;
  background: var(--card); color: var(--ink);
  border: 1px solid var(--ink); border-radius: var(--r-control);
}
.ui-btn-primary { background: var(--ink); color: #fff; font-weight: 600; }
.ui-btn-quiet { border-color: var(--line); }
.ui-btn-pill { border-color: var(--line); border-radius: var(--r-pill); }
.ui-btn-pill[aria-pressed="true"] { background: var(--ink); border-color: var(--ink); color: #fff; font-weight: 600; }
.ui-btn-icon { width: var(--control); min-width: var(--control); padding: 0; }   /* a crowded row shrank it to 8 px */
.ui-btn:disabled { background: transparent; color: var(--text-off); border: 1px dashed var(--line-off); cursor: not-allowed; }

/* Choose one of two or three (In force / With the draft). */
.ui-seg { display: inline-flex; border: 1px solid var(--ink); border-radius: var(--r-control); overflow: hidden; }
.ui-seg > button {
  min-height: calc(var(--control) - 2px); padding: 0 14px; font-size: var(--fs-control);
  border: 0; border-radius: 0; background: var(--card); color: var(--ink);
}
.ui-seg > button[aria-pressed="true"] { background: var(--ink); color: #fff; }
.ui-seg > button:disabled { color: var(--text-off); cursor: not-allowed; }
.ui-seg > button:focus-visible { outline-offset: -3px; }   /* the group's overflow would clip it */

/* A label with its select or input beside it (Cleaner, Property). */
.ui-field { display: inline-flex; align-items: center; gap: 8px; font-size: var(--fs-control); color: var(--text-2); }
.ui-field select, .ui-field input {
  min-height: var(--control); padding: 0 10px; font: inherit; font-size: var(--fs-control);
  color: var(--ink); background: var(--card); border: 1px solid var(--line); border-radius: var(--r-control);
}

/* A count on a tile (Done 6 of 17). */
.ui-stat {
  display: flex; flex-direction: column; gap: 2px; padding: 14px 16px;
  background: var(--card); border: 1px solid var(--line); border-radius: var(--r-card);
}
.ui-stat-label { font-size: var(--fs-sm); color: var(--text-2); }
.ui-stat-num { font-size: var(--fs-stat); font-weight: 700; line-height: 1.1; }

/* A bar against a whole (a day against the shift, stops done). Decoration only: the words
   beside it say the same thing, so mark it aria-hidden. Script sets the fill's width with
   el.style.width, which the policy allows (it refuses style attributes, not the CSSOM). */
.ui-meter { height: 6px; overflow: hidden; background: var(--track); border-radius: 3px; }
.ui-meter > span { display: block; width: 0; height: 100%; background: var(--ink); border-radius: 3px; }
.ui-meter-ok > span { background: var(--ok); }
.ui-meter-over > span { background: var(--over); }

/* ---- the Dispatch board (S5 step 4b part B) --------------------------------------------- */
/* Screens 1-3 of the board's canvas. A CSS grid read as a table (role=table/row/cell), five to seven day
   columns after the 172 px cleaner column; held from 1100 px of board (a 1280 px window), narrower scrolls
   sideways inside .ui-board-scroll, never the page (B10). */
.ui-board-page { display: flex; flex-direction: column; gap: 16px; }
.ui-board-tools { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; }
.ui-board-week { display: inline-flex; align-items: center; gap: 4px; }
.ui-board-weeklabel { padding: 0 10px; font-size: var(--fs-name); font-weight: 700; }
.ui-board-grow { flex-grow: 1; }
.ui-board-print { display: inline-flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.ui-board-printnote { max-width: 360px; }
.ui-board-stale { margin: 0; }
.ui-board-draft {
  display: flex; align-items: center; gap: 16px; flex-wrap: wrap;
  padding: 12px 14px; background: var(--alt); border-radius: var(--r-card);
}
.ui-board-draftwords { margin: 0; flex-grow: 1; min-width: 320px; font-size: var(--fs-control); font-weight: 600; }
.ui-board-legend { display: flex; align-items: center; gap: 20px; flex-wrap: wrap; font-size: var(--fs-sm); }
.ui-board-totals { font-weight: 600; }
.ui-legend-item { display: inline-flex; align-items: center; gap: 6px; }
.ui-swatch { display: inline-block; width: 14px; height: 14px; border-radius: 3px; }
.ui-swatch-moved { background: var(--tint-moved); border: 1px solid var(--line-moved); }
.ui-swatch-off { background: repeating-linear-gradient(135deg, var(--alt) 0 4px, var(--line) 4px 8px); }
.ui-swatch-shift { width: 22px; height: 6px; background: var(--ink); }
.ui-swatch-over { width: 22px; height: 6px; background: var(--over); }
.ui-swatch-moving { background: var(--tint-warn); border: 1px dashed var(--over); }
.ui-swatch-needs { background: #fbeaea; border: 1px solid var(--line-bad); }
.ui-swatch-skipped { height: 2px; background: var(--text-3); }
.ui-swatch-done { background: var(--card); border: 1px solid var(--ok); }
.ui-swatch-onsite { background: var(--tint-ink); border: 1px solid var(--ink); }
.ui-swatch-missed { background: #fbeaea; border: 1px solid var(--line-bad); }

.ui-board-scroll { overflow-x: auto; }
.ui-board { display: flex; flex-direction: column; gap: 10px; min-width: 1100px; }
.ui-board[aria-busy="true"] { opacity: 0.55; }
.ui-board-row { display: grid; gap: 10px; align-items: stretch; }
.ui-board-days-5 .ui-board-row { grid-template-columns: 172px repeat(5, minmax(0, 1fr)); }
.ui-board-days-6 .ui-board-row { grid-template-columns: 172px repeat(6, minmax(0, 1fr)); }
.ui-board-days-7 .ui-board-row { grid-template-columns: 172px repeat(7, minmax(0, 1fr)); }
.ui-board-dayhead {
  display: flex; flex-direction: column; gap: 6px; padding: 8px 10px;
  font-size: var(--fs-sm); font-weight: 700; background: var(--alt); border-radius: var(--r-control);
}
.ui-board-dayhead-today { background: var(--ink); color: #fff; }
.ui-board-who { display: flex; flex-direction: column; gap: 4px; padding: 10px 4px 10px 0; min-width: 0; }
.ui-board-name { font-size: var(--fs-name); font-weight: 700; }
.ui-board-who .ui-note { font-size: var(--fs-s); }
.ui-board-weekline { font-size: var(--fs-s); font-weight: 600; }
.ui-board-who .ui-board-weekline { margin-top: 2px; }
.ui-sr { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }

.ui-day {
  display: flex; flex-direction: column; gap: 6px; min-width: 0; padding: 10px;
  background: var(--card); border: 1px solid var(--line); border-radius: var(--r-card);
}
.ui-day-today { border: 2px solid var(--ink); padding: 9px; }
.ui-day-empty { background: var(--sunk); border: 1px dashed var(--line-dash); }
.ui-day-empty.ui-day-today { border: 2px solid var(--ink); }
.ui-day-closed { background: repeating-linear-gradient(135deg, var(--card) 0 10px, var(--sunk) 10px 20px); }
.ui-day-top { display: flex; flex-direction: column; gap: 1px; font-size: var(--fs-sm); }
.ui-day-status, .ui-day-summary { font-weight: 700; }
.ui-day-status + .ui-day-summary { font-weight: 400; color: var(--text-2); font-size: var(--fs-s); }
.ui-day-change { font-size: var(--fs-s); color: var(--moved); font-weight: 600; }
.ui-day-over { margin: 0; font-size: var(--fs-s); line-height: 1.35; color: var(--warn); }
.ui-day-takenoff, .ui-day-emptywords { margin: 0; }
.ui-bar { display: block; height: 6px; background: var(--track); border-radius: 3px; overflow: hidden; }
.ui-bar-fill { display: block; height: 100%; width: 0; background: var(--ink); border-radius: 3px; }
.ui-bar-over { background: var(--over); }

.ui-off, .ui-closure {
  display: flex; flex-direction: column; gap: 2px; padding: 8px 10px; border-radius: var(--r-control);
  background: repeating-linear-gradient(135deg, var(--alt) 0 8px, var(--hatch) 8px 16px); color: var(--ink);
}
.ui-closure { font-weight: 400; }
.ui-off-label { font-size: var(--fs-sm); font-weight: 700; }
.ui-off-detail { font-size: var(--fs-s); }
.ui-off-late { font-size: var(--fs-s); font-weight: 600; color: var(--warn); }
.ui-off-voided .ui-off-label { text-decoration: line-through; }

.ui-day-marks, .ui-day-stops { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 3px; }
.ui-mark-row { display: flex; flex-wrap: wrap; align-items: baseline; gap: 2px 6px; padding: 2px 6px; min-width: 0; }
.ui-mark-name { flex-basis: 100%; min-width: 0; font-size: var(--fs-sm); font-weight: 600; line-height: 1.3;
                overflow-wrap: break-word; }
.ui-mark-code { font-size: var(--fs-xs); color: var(--text-2); }
.ui-mark-words { font-size: var(--fs-s); font-weight: 600; color: var(--moved); }
.ui-mark-skipped .ui-mark-name, .ui-mark-skipping .ui-mark-name { text-decoration: line-through; color: var(--text-2); }
.ui-mark-skipped .ui-mark-words, .ui-mark-skipping .ui-mark-words { font-weight: 400; color: var(--text-2); }
.ui-mark-needs_decision .ui-mark-words {
  padding: 1px 6px; border-radius: var(--r-tag); background: #fbeaea; color: var(--bad);
}

.ui-stop-item { display: flex; flex-direction: column; gap: 1px; }
.ui-stop-drive { padding-left: 28px; font-size: var(--fs-xs); line-height: 14px; color: var(--text-3); }
.ui-stop-drive-history { font-style: italic; }
.ui-stop { display: flex; flex-direction: column; gap: 1px; padding: 3px 6px; border: 1px solid transparent; border-radius: 5px; }
.ui-stop-line { display: flex; align-items: baseline; gap: 8px; }
.ui-stop-n { width: 14px; flex-shrink: 0; text-align: right; font-size: var(--fs-s); color: var(--text-2); }
/* A property's name wraps rather than being cut: staff know the buildings by their names (4b decision). */
.ui-stop-name { flex-grow: 1; min-width: 0; font-size: var(--fs-sm); font-weight: 600; line-height: 1.3;
                overflow-wrap: break-word; }
.ui-stop-sub, .ui-stop-mark, .ui-stop-state, .ui-stop-flags { padding-left: 22px; font-size: var(--fs-xs); }
.ui-stop-sub { color: var(--text-2); }
.ui-stop-mins { color: var(--ink); }
.ui-stop-mark { color: var(--moved); font-weight: 600; }
.ui-stop-state { font-size: var(--fs-s); }
.ui-stop-flags { font-size: var(--fs-s); font-weight: 700; color: var(--bad); }
.ui-stop-moved_in { background: var(--tint-moved); }
.ui-stop-moving_in { background: var(--tint-warn); border: 1px dashed var(--over); }
.ui-stop-new { border: 1px dashed var(--ink); }
.ui-state-done .ui-stop-state { color: var(--ok); font-weight: 600; }
.ui-state-onsite { background: var(--tint-ink); }
.ui-state-onsite .ui-stop-state { font-weight: 700; }
.ui-state-missed { background: #fbeaea; }
.ui-state-missed .ui-stop-state { color: var(--bad); font-weight: 600; }
.ui-state-odd .ui-stop-state { color: var(--warn); font-weight: 600; }
.ui-state-later .ui-stop-state { color: var(--text-2); }

/* ---- moving a visit on the board (S5 step 4d, screens 11-14 of the board's canvas) ---------------------------- */
/* The Move form in a 400 px panel beside the board, which narrows and scrolls sideways inside its own panel (B10).
   A movable card or mark is a real button at least 44 px tall (rule 12); dragging it lifts it, a copy follows the
   pointer (placed through the CSSOM), and the day under the pointer is outlined and named when it takes a drop. */
.ui-board-split { display: flex; align-items: flex-start; gap: 16px; }
.ui-board-split > .ui-board-scroll { flex: 1 1 auto; min-width: 0; }
.ui-board-panel {
  flex: 0 0 400px; box-sizing: border-box; position: sticky; top: 16px; max-height: calc(100vh - 32px); overflow-y: auto;
  padding: 18px; background: var(--card); border: 1px solid var(--ink); border-radius: var(--r-card);
  box-shadow: 0 6px 18px rgba(27, 54, 93, 0.12);
}
body.console .ui-board-panel .ui-move-grid { grid-template-columns: minmax(0, 1fr); }
.ui-board-panel .form { margin: 0; padding: 0; border: 0; background: none; }
/* Every control in the panel at least 44 px (rule 12): the shared form's fields and buttons. */
.ui-board-panel button, .ui-board-panel select, .ui-board-panel input:not([type="checkbox"]) {
  min-height: 44px; box-sizing: border-box;
}
.ui-board-panel label:has(> input[type="checkbox"]) { display: inline-flex; align-items: center; min-height: 44px; }
.ui-board-panel-title { margin: 0 0 4px; font-size: var(--fs-name); }
.ui-board-status { display: flex; flex-direction: column; gap: 4px; }
.ui-board-status:empty { display: none; }
.ui-board-status p { margin: 0; }
.ui-move-item {
  appearance: none; box-sizing: border-box; width: 100%; min-height: 44px; margin: 0; font: inherit; color: inherit;
  text-align: left; background-color: transparent; cursor: grab;
  user-select: none; -webkit-user-select: none; -webkit-touch-callout: none;
}
.ui-move-item:focus-visible { outline: 3px solid var(--ink); outline-offset: 2px; }
.ui-move-item:disabled { cursor: default; }
.ui-mark-move {
  display: flex; flex-wrap: wrap; align-items: baseline; gap: 2px 6px; padding: 2px 6px;
  border: 1px solid transparent; border-radius: 5px;
}
.ui-mark-row > .ui-mark-move { flex-basis: 100%; }
.ui-move-lifted { opacity: 0.55; border: 1px dashed var(--ink); }
.ui-drag-ghost {
  position: fixed; left: 0; top: 0; z-index: 50; pointer-events: none; padding: 6px 10px; font-size: var(--fs-sm);
  background: var(--card); border: 1px solid var(--ink); border-radius: 6px; box-shadow: 0 6px 18px rgba(27, 54, 93, 0.18);
}
.ui-day-drop, .ui-day-target { outline: 3px solid var(--ink); outline-offset: -3px; }
.ui-drop-words { font-size: var(--fs-s); font-weight: 700; color: var(--ink); }
.ui-movednow { padding-left: 22px; font-size: var(--fs-s); font-weight: 700; color: var(--ok); }
.ui-mark-row .ui-movednow { padding-left: 0; }
/* Nothing of moving a visit prints (rule 12): no panel, no drag cue, no outline. */
@media print {
  .ui-board-panel, .ui-drag-ghost, .ui-drop-words { display: none !important; }
  .ui-day-drop, .ui-day-target { outline: none !important; }
}

/* The route sheets (rule 12): only while one of the board's prints is out (body.ui-printing), and only on
   paper. One page per cleaner per day, in tools/route_sheets.py's layout. */
.ui-print-root { display: none; }
@media print {
  body.ui-printing > :not(.ui-print-root) { display: none !important; }
  body.ui-printing { background: #fff; }
  body.ui-printing .ui-print-root { display: block; }
  .ui-sheet { break-after: page; color: #000; font-size: 12pt; }
  .ui-sheet:last-child { break-after: auto; }
  .ui-sheet-line { margin: 0 0 8pt; font-size: 9pt; }
  .ui-sheet-day { margin: 0; font-size: 16pt; }
  .ui-sheet-who { margin: 2pt 0; font-size: 12pt; font-weight: 700; }
  .ui-sheet-note { margin: 0 0 8pt; font-size: 9.5pt; }
  .ui-sheet-stops { list-style: none; margin: 0; padding: 0; }
  .ui-sheet-stop { break-inside: avoid; margin-bottom: 8pt; }
  .ui-sheet-stop p { margin: 0; }
  .ui-sheet-drive, .ui-sheet-lunch { padding-left: 22pt; font-size: 9pt; font-style: italic; }
  .ui-sheet-place { font-size: 12.5pt; }
  .ui-sheet-box { display: inline-block; width: 11pt; height: 11pt; margin-right: 8pt; border: 1pt solid #000;
                  vertical-align: -1pt; }
  .ui-sheet-address, .ui-sheet-scope, .ui-sheet-small { padding-left: 19pt; font-size: 10pt; }
  .ui-sheet-small { font-size: 9pt; }
  .ui-sheet-foot { margin-top: 12pt; font-size: 8.5pt; font-style: italic; text-align: center; }
}

/* ---- the Work list, the job page and the links to them (S5 step 5, screens 15-18 of the board's canvas) ------- */
/* Rule 18: the board's look, 44 px controls, no style attributes; the list is a real table that scrolls sideways in
   its own box if it must, never the page. A state is words in its color, never a row's background. */
.ui-wstate-done .ui-work-state, .ui-job-state.ui-wstate-done, .ui-job-partstate.ui-wstate-done { color: var(--ok); font-weight: 600; }
.ui-wstate-onsite .ui-work-state, .ui-job-state.ui-wstate-onsite, .ui-job-partstate.ui-wstate-onsite { color: var(--ink); font-weight: 700; }
.ui-wstate-missed .ui-work-state, .ui-job-state.ui-wstate-missed, .ui-job-partstate.ui-wstate-missed { color: var(--bad); font-weight: 600; }
.ui-wstate-odd .ui-work-state, .ui-job-state.ui-wstate-odd, .ui-job-partstate.ui-wstate-odd { color: var(--warn); font-weight: 600; }
.ui-wstate-later .ui-work-state, .ui-job-state.ui-wstate-later, .ui-job-partstate.ui-wstate-later { color: var(--text-2); }

.ui-work-filters {
  display: flex; align-items: center; gap: 12px; flex-wrap: wrap; margin: 16px 0;
  padding: 12px 16px; background: var(--card); border: 1px solid var(--line); border-radius: var(--r-card);
}
.ui-work-filters .ui-btn, .ui-work-flagged { min-height: var(--control); }
.ui-work-filters [hidden] { display: none; }   /* a field's own display would show From and To under a named range */
.ui-work-flagged { display: inline-flex; align-items: center; gap: 8px; }
.ui-work-flagged input, .ui-work-statusopt input { width: 18px; height: 18px; margin: 0; }
.ui-work-status { position: relative; }
.ui-work-statusbtn {
  display: inline-flex; align-items: center; justify-content: space-between; gap: 10px; min-width: 150px;
  min-height: var(--control); padding: 0 10px; font: inherit; font-size: var(--fs-control); text-align: left;
  color: var(--ink); background: var(--card); border: 1px solid var(--line); border-radius: var(--r-control);
}
.ui-work-statusbtn[aria-expanded="true"] { border-color: var(--ink); }
.ui-work-statuslist {
  position: absolute; top: calc(100% + 6px); left: 0; z-index: 5; width: 220px; padding: 8px 14px;
  display: flex; flex-direction: column; background: var(--card); border: 1px solid var(--ink);
  border-radius: var(--r-card); box-shadow: 0 8px 24px rgba(27, 54, 93, 0.14);
}
.ui-work-statuslist[hidden] { display: none; }
.ui-work-statusopt { display: flex; align-items: center; gap: 10px; min-height: var(--control); font-size: var(--fs-body); color: var(--ink); }
.ui-work-notes p { margin: 8px 0; }
.ui-work-scroll { overflow-x: auto; background: var(--card); border: 1px solid var(--line); border-radius: var(--r-card); }
.ui-work-table { width: 100%; min-width: 900px; border-collapse: collapse; }
.ui-work-table th, .ui-work-table td { padding: 10px 16px; text-align: left; vertical-align: middle; }
.ui-work-table thead th { font-size: var(--fs-sm); font-weight: 600; color: var(--text-2); border-bottom: 1px solid var(--line); }
.ui-work-day th { padding: 12px 16px 6px; background: var(--sunk); border-bottom: 1px solid var(--line); font-weight: 400; }
.ui-work-dayname { font-size: var(--fs-body); font-weight: 700; }
.ui-work-row td { border-bottom: 1px solid var(--line-soft); }
.ui-work-row td:nth-child(2), .ui-work-row td:nth-child(5) { min-width: 0; }
.ui-work-row td > span { display: block; }
.ui-work-visit a {
  display: inline-flex; align-items: center; min-height: var(--control); font-weight: 600;
  font-variant-numeric: tabular-nums; color: var(--ink);
  white-space: nowrap;   /* beside long names "V-105975" broke after its "V-" (the step 5 e2e, 1280 and 1440 px) */
}
.ui-work-place { font-weight: 700; }
.ui-work-moved { font-size: var(--fs-s); font-weight: 600; color: var(--moved); }
.ui-work-row .ui-work-on { font-size: var(--fs-sm); }
.ui-work-row .ui-work-on > span { display: inline-block; margin: 2px 6px 2px 0; }
.ui-work-flag { background: var(--tint-bad); color: var(--bad); border: 1px solid var(--line-bad); }
.ui-work-queue { background: var(--tint-ink); color: var(--ink); }
.ui-work-more { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; margin-top: 12px; }
.ui-work-more p { margin: 0; }

.ui-job-back, .ui-job-actrow a, .ui-job-flag > a {
  display: inline-flex; align-items: center; min-height: var(--control); font-weight: 600; color: var(--ink);
}
.ui-job-number { margin: 0; font-variant-numeric: tabular-nums; }
/* Typed words (a reason, a note, an address) wrap rather than scroll a phone sideways (review, 2026-10-07): every line in
   the columns breaks a word too long for it; the head's two lines of typed reasons sit in its flex row, where
   `break-word` keeps the longest word's width, so they take `anywhere`. */
.ui-job-moved { margin: 0; font-size: var(--fs-sm); font-weight: 600; color: var(--moved); overflow-wrap: anywhere; }
.ui-job-state {
  padding: 6px 12px; font-size: var(--fs-body); border-radius: var(--r-pill); background: var(--alt);
  border: 1px solid var(--line);
}
.ui-job-outcome { margin: 12px 0 0; font-size: var(--fs-lead); font-weight: 600; overflow-wrap: anywhere; }
.ui-job-columns { display: grid; grid-template-columns: minmax(0, 1fr) 460px; gap: 16px; align-items: start; margin-top: 16px;
                  overflow-wrap: break-word; }
.ui-job-main, .ui-job-side { display: flex; flex-direction: column; gap: 16px; min-width: 0; }
/* Narrower than 1100 px (where the Properties page stacks too) the fixed 460 px side squeezed the visit to a sliver,
   30 px at 580 px, and scrolled a phone sideways (seen 2026-10-07): one column, in the page's own order, the visit
   first, then Review, What happened and Code reveals (Christian, 2026-10-07). An empty page's blank first column goes. */
@media (max-width: 1100px) {
  .ui-job-columns { grid-template-columns: minmax(0, 1fr); }
  .ui-job-columns > :empty { display: none; }
}
/* A case page's Review card holds its "Open in the Queue" on its own, outside the Accept and Ask row: 44 px too
   (it was 22 px; found in review, 2026-10-07). */
.ui-job-review > .ui-link { display: inline-flex; align-items: center; align-self: flex-start; min-height: var(--control); }
.ui-job-section, .ui-job-review, .ui-job-timeline, .ui-job-reveals { display: flex; flex-direction: column; gap: 10px; }
.ui-job-section > .ui-h2 { font-size: var(--fs-name); }
.ui-job-part { display: flex; flex-direction: column; gap: 12px; padding: 14px; border: 1px solid var(--line);
               border-radius: var(--r-card); background: var(--sunk); }
.ui-job-part-replaced { border-style: dashed; }
.ui-job-parthead { margin: 0; font-size: var(--fs-h2); font-weight: 700; letter-spacing: normal; text-transform: none;
                   color: var(--ink); }
.ui-job-partstate { margin: 0; }
.ui-job-issues { margin: 0; padding: 0; list-style: none; }
.ui-job-partreview { display: flex; flex-direction: column; gap: 8px; }
.ui-job-event { display: flex; flex-wrap: wrap; gap: 4px 16px; align-items: baseline; }
.ui-job-band { color: var(--text-2); }
.ui-job-band-onsite { color: var(--ok); }
.ui-job-flag { display: flex; flex-direction: column; gap: 6px; padding: 10px 12px; border: 1px solid var(--line);
               border-radius: var(--r-card); }
.ui-job-flaghead { margin: 0; }
.ui-job-review { border-color: #c6d2e3; }
.ui-job-review p { margin: 0; }
.ui-job-inqueue { font-weight: 700; }
.ui-job-actrow { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.ui-job-acts { display: flex; gap: 8px; flex-wrap: wrap; }
.ui-job-acts .ui-btn, .ui-job-review .form button, .ui-job-review .form input,
.ui-job-partreview .ui-btn, .ui-job-partreview .form button, .ui-job-partreview .form input { min-height: var(--control); }
.ui-job-lines { list-style: none; margin: 0; padding: 0; }
.ui-job-lines li { display: grid; grid-template-columns: 112px minmax(0, 1fr); gap: 12px; padding: 6px 0;
                   border-bottom: 1px solid var(--line-soft); font-size: var(--fs-control); }
.ui-job-when { color: var(--text-2); font-variant-numeric: tabular-nums; }
.ui-job-reveal p { margin: 0; }
.ui-job-section .thumb, .ui-job-flag .thumb { width: 112px; height: 84px; }

/* Messaging M1 part C (mockup 65): the job's messages, one timeline for every thread of the job, first in the main
   column. Each line names its person in a column of its own; an office message is tinted, an office note says so and is
   tinted differently, unread lines are tinted with "· new" (never color alone). */
.ui-job-messages { display: flex; flex-direction: column; gap: 12px; border-color: #c6d2e3; }
.ui-job-messages[hidden], .ui-msg-composer[hidden], .ui-msg-code[hidden], .ui-msg-closed[hidden], .ui-msg-ack[hidden] {
  display: none; }
.ui-msg-head { display: flex; align-items: center; gap: 10px; }
.ui-msg-head .ui-h2 { font-size: var(--fs-name); }
.badge.new { color: #fff; background: var(--ink); border-color: var(--ink); font-weight: 700; }
.ui-msg-lines { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; }
.ui-msg-line { display: grid; grid-template-columns: 150px minmax(0, 1fr); gap: 14px; padding: 10px 0;
               border-bottom: 1px solid var(--line-soft); }
.ui-msg-line:last-child { border-bottom: 0; }
.ui-msg-unread { background: #f7f9fc; }
.ui-msg-who { display: flex; flex-direction: column; overflow-wrap: anywhere; }
.ui-msg-body { display: flex; flex-direction: column; gap: 6px; min-width: 0; }
.ui-msg-words { margin: 0; font-size: var(--fs-body); overflow-wrap: anywhere; white-space: pre-wrap; }
.ui-msg-bubble { padding: 8px 12px; border-radius: var(--r-control); background: var(--tint-ink); }
.ui-msg-memo { padding: 8px 12px; border-radius: var(--r-control); background: var(--alt); }
.ui-msg-tag { margin: 0; font-size: var(--fs-s); font-weight: 700; letter-spacing: 0.06em; text-transform: uppercase;
              color: var(--text-2); }
.ui-msg-flagline { margin: 0; }
.ui-msg-safety .ui-tag { color: #9a3412; border-color: #f3c9b4; background: #fdeee6; }
.ui-msg-body .thumb { width: 112px; height: 84px; }
.ui-msg-composer { display: flex; flex-direction: column; gap: 10px; padding-top: 14px; border-top: 1px solid var(--line); }
.ui-msg-torow { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; }
.ui-msg-tolabel { display: flex; align-items: center; gap: 8px; font-weight: 600; }
.ui-msg-pick { min-height: var(--control); }
.ui-msg-text { font: inherit; font-size: var(--fs-body); padding: 8px 10px; border: 1px solid var(--line);
               border-radius: var(--r-control); resize: vertical; min-height: 84px; }
.ui-msg-ack p { margin: 0; padding: 8px 12px; border-radius: var(--r-control); background: var(--tint-ink); }
.ui-msg-code { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; padding: 12px 14px; border: 1px solid #e8d9bf;
               border-radius: var(--r-card); background: #fbf6ee; }
.ui-msg-code b { flex-grow: 1; }
.ui-msg-composer button, .ui-msg-code button { min-height: var(--control); }
.ui-msg-said { margin: 0; }
.ui-msg-said:empty { display: none; }
.ui-ask-dest { margin: 0; font-weight: 600; }
@media (max-width: 700px) {
  .ui-msg-line { grid-template-columns: minmax(0, 1fr); gap: 4px; }
}

/* "Open in the Queue" lands here: the row it named, outlined (rule 12). */
.ui-qrow-focus { outline: 3px solid var(--ink); outline-offset: 2px; }

/* A visit's name on the board and on Today opens its page (rule 15): a link in the card's own words. */
.ui-stop-line a, .ui-today-stop-top a { color: var(--ink); text-decoration: underline; text-decoration-thickness: 1px;
                                        text-underline-offset: 2px; }
.ui-stop-line a:hover, .ui-today-stop-top a:hover { color: var(--ink-deep); }


/* The search box (S5 step 5 rule 14, screen 19): in the header bar, its results dropped down under it, grouped by
   kind. The marked result is outlined, never only colored. Laid out for a desktop, as the console is. */
.ui-search { position: relative; flex: 0 1 420px; min-width: 220px; margin-left: 8px; }
.ui-search[hidden] { display: none; }
.ui-search-field { display: flex; align-items: center; gap: 8px; min-height: var(--control); padding: 0 12px;
                   background: var(--card); border: 1px solid var(--ink); border-radius: var(--r-control);
                   color: var(--text-2); cursor: text; }
.ui-search-field:focus-within { outline: 3px solid var(--orange); outline-offset: 1px; }   /* the site's focus ring, on the field */
.ui-search .ui-search-input:focus-visible { outline: none; }
/* `.ui-search` too: the site's input[type="search"] rule would otherwise draw a border and padding inside the field. */
.ui-search .ui-search-input { font: inherit; font-size: var(--fs-body); flex: 1 1 auto; min-width: 0; min-height: 42px; padding: 0;
                   border: 0; outline: none; background: transparent; color: var(--ink); }
.ui-search-input::placeholder { color: var(--text-2); opacity: 1; }
.ui-search-input::-webkit-search-cancel-button { display: none; }
/* A magnifier drawn in CSS (the policy loads no image for it): a ring and its handle. */
.ui-search-icon { position: relative; flex: none; width: 12px; height: 12px; margin-right: 2px;
                  border: 2px solid currentColor; border-radius: 50%; }
.ui-search-icon::after { content: ""; position: absolute; right: -5px; bottom: -4px; width: 2px; height: 6px;
                         background: currentColor; transform: rotate(-45deg); }
.ui-search-hint { flex: none; font: inherit; font-size: var(--fs-s); line-height: 1.4; padding: 0 6px;
                  border: 1px solid var(--line); border-radius: var(--r-tag); background: var(--alt); color: var(--text-2); }
.ui-search-pop { position: absolute; top: calc(100% + 8px); left: 0; right: 0; z-index: 20; display: flex;
                 flex-direction: column; max-height: calc(100vh - 96px); overflow-y: auto; padding: 6px;
                 background: var(--card); border: 1px solid var(--ink); border-radius: var(--r-card);
                 box-shadow: 0 12px 32px rgba(27, 54, 93, 0.18); }
.ui-search-pop[hidden], .ui-search-list[hidden], .ui-search-line[hidden] { display: none; }
.ui-search-line { margin: 0; padding: 10px 12px; font-size: var(--fs-control); color: var(--text-2); }
.ui-search-line.bad { color: var(--bad); }
.ui-search-head { padding: 8px 12px 2px; font-size: var(--fs-s); font-weight: 700; letter-spacing: 0.06em;
                  text-transform: uppercase; color: var(--text-2); }
.ui-search-group { list-style: none; margin: 0; padding: 0; }
.ui-search-opt { display: flex; flex-direction: column; justify-content: center; gap: 1px; min-height: var(--control);
                 padding: 8px 12px; border-radius: var(--r-control); cursor: pointer; }
.ui-search-opt:hover { background: var(--alt); }
.ui-search-opt[aria-selected="true"] { background: var(--tint-ink); outline: 2px solid var(--ink); outline-offset: -2px; }
.ui-search-title { font-size: var(--fs-body); font-weight: 600; overflow-wrap: anywhere; }
.ui-search-sub { font-size: var(--fs-s); color: var(--text-2); overflow-wrap: anywhere; }
.ui-search-tag { font-weight: 700; color: var(--moved); }

/* ---- The Properties list and a property's page (S5 step 6, screens 20-25; rules 3, 4 and 16) ---------------------- */
/* The list: Work's table, one row a property. */
.ui-props-table { min-width: 980px; }
.ui-props-table td > a.ui-work-place { display: inline-flex; align-items: center; min-height: var(--control); color: var(--ink); }
.ui-props-inactive td { color: var(--text-2); }
.ui-props-checked { color: var(--ok); font-weight: 600; }
.ui-props-cardnote { font-size: var(--fs-s); font-weight: 700; color: var(--moved); }
.ui-props-foot { display: flex; flex-direction: column; gap: 4px; margin-top: 12px; }
.ui-props-foot p { margin: 0; }

/* The Settings menu at the end of the bar: a disclosure, its entries 44 px tall. */
.ui-menu-box { position: relative; }
.ui-menu {
  position: absolute; right: 0; top: calc(100% + 8px); z-index: 30; width: 340px; max-width: calc(100vw - 32px);
  display: flex; flex-direction: column; padding: 6px; background: var(--card); border: 1px solid var(--ink);
  border-radius: var(--r-card); box-shadow: 0 12px 32px rgba(27, 54, 93, 0.18);
}
.ui-menu[hidden] { display: none; }
.ui-menu-item {
  display: flex; flex-direction: column; gap: 1px; min-height: var(--control); padding: 10px 12px; box-sizing: border-box;
  border-radius: var(--r-control); color: var(--ink); text-decoration: none;
}
.ui-menu-item:hover, .ui-menu-item.on { background: var(--tint-ink); }
.ui-menu-off { color: var(--text-off); }
.ui-menu-name { font-size: var(--fs-body); font-weight: 600; }
.ui-menu-line { font-size: var(--fs-s); color: var(--text-2); }

/* The page: its head, the jumps, two columns (what Richard needs when a cleaner calls first), then Work here. */
.ui-prop-back { display: inline-flex; align-items: center; min-height: var(--control); font-weight: 600; color: var(--ink); }
.ui-prop-head .ui-prop-cycle { margin: 0; }
.ui-prop-count { font-weight: 600; }
.ui-prop-inactive { margin: 12px 0 0; font-weight: 600; }
.ui-prop-jumps { display: flex; flex-wrap: wrap; gap: 4px 16px; margin: 12px 0; }
.ui-prop-jumps .ui-link { background: none; border: 0; padding: 0; min-height: var(--control); font: inherit; font-weight: 600;
                          color: var(--ink); text-decoration: underline; text-underline-offset: 3px; cursor: pointer; }
.ui-prop-columns { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 16px; align-items: start; }
.ui-prop-main, .ui-prop-side { display: flex; flex-direction: column; gap: 16px; min-width: 0; }
.ui-prop-work { margin-top: 16px; }
@media (max-width: 1100px) { .ui-prop-columns { grid-template-columns: minmax(0, 1fr); } }
.ui-prop-section { gap: 14px; }
.ui-prop-top { align-items: flex-start; }
.ui-prop-top .ui-head-words { gap: 2px; }
.ui-prop-section .extra:empty, .ui-prop-addslot:empty { display: none; }

/* Building info, read and edited. */
.ui-prop-group { display: flex; flex-direction: column; gap: 6px; }
.ui-prop-grouphead { margin: 0; font-size: var(--fs-s); font-weight: 700; letter-spacing: 0.06em; text-transform: uppercase;
                     color: var(--text-2); }
.ui-prop-fields { display: grid; grid-template-columns: minmax(120px, 180px) minmax(0, 1fr); gap: 6px 16px; margin: 0; }
.ui-prop-fields dt { font-size: var(--fs-sm); font-weight: 600; color: var(--text-2); }
.ui-prop-fields dd { margin: 0; overflow-wrap: anywhere; }
.ui-prop-fields dd:first-child, .ui-prop-fields dt + dd:only-child { grid-column: 1 / -1; }
.ui-prop-cardnote, .ui-prop-typed, .ui-prop-waitnote {
  display: flex; flex-direction: column; gap: 6px; padding: 12px 14px; border-radius: var(--r-card);
  background: var(--tint-moved); border: 1px solid var(--line-moved);
}
.ui-prop-cardnote p, .ui-prop-typed p, .ui-prop-waitnote p { margin: 0; }
.ui-prop-notehead { margin: 0; font-size: var(--fs-sm); font-weight: 700; color: var(--moved); }
.ui-prop-differs { margin-left: 6px; }
.ui-prop-differ { font-weight: 700; }
.ui-prop-form {
  display: flex; flex-direction: column; gap: 12px; padding: 16px; border-radius: var(--r-card); background: var(--alt);
}
.ui-prop-form p { margin: 0; }
.ui-prop-formhead { margin: 0; font-size: var(--fs-lead); font-weight: 700; }
.ui-prop-fieldset { display: flex; flex-direction: column; gap: 8px; margin: 0; padding: 0; border: 0; }
.ui-prop-fieldset > legend { padding: 0; margin-bottom: 8px; font-size: var(--fs-sm); font-weight: 700; letter-spacing: 0.06em;
                             text-transform: uppercase; color: var(--text-2); }
.ui-prop-field { display: flex; flex-direction: column; gap: 6px; }
.ui-prop-label { font-size: var(--fs-control); font-weight: 600; color: var(--ink); }
.ui-prop-field input, .ui-prop-field textarea, .ui-prop-field select {
  box-sizing: border-box; width: 100%; min-height: var(--control); padding: 0 10px; font: inherit; font-size: var(--fs-body);
  color: var(--ink); background: var(--card); border: 1px solid var(--line); border-radius: var(--r-control);
}
.ui-prop-field textarea { padding: 10px; resize: vertical; }
.ui-prop-field input[type="date"] { width: 240px; max-width: 100%; }
.ui-prop-field [aria-invalid="true"] { border: 2px solid var(--bad); }
.ui-prop-why { margin: 0; font-weight: 600; }
.ui-prop-check { display: flex; align-items: center; gap: 8px; min-height: var(--control); font-size: var(--fs-body); }
.ui-prop-check input { width: 18px; height: 18px; }
.ui-prop-checked { display: flex; flex-direction: column; gap: 2px; border-top: 1px solid var(--line); padding-top: 12px; }
.ui-prop-acts { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; }
.ui-prop-acts button, .ui-prop-section .code .actions button, .ui-code-more button { min-height: var(--control); }
.ui-prop-pair { display: flex; flex-wrap: wrap; gap: 12px; }
.ui-prop-picks, .ui-prop-days { display: flex; flex-wrap: wrap; gap: 6px; align-items: center; }
.ui-prop-preview { padding: 10px 12px; background: var(--card); border: 1px solid var(--line); border-radius: var(--r-control); }
.ui-prop-preview:empty { display: none; }

/* Required photos, contacts and the codes' More. */
.ui-prop-shot, .ui-prop-contact { display: flex; flex-direction: column; gap: 6px; padding: 12px 14px;
                                  border: 1px solid var(--line); border-radius: var(--r-card); }
.ui-prop-shot p, .ui-prop-contact p { margin: 0; }
.ui-prop-shot-past { background: var(--sunk); }
.ui-prop-shothead, .ui-prop-contacthead { display: flex; flex-wrap: wrap; gap: 4px 10px; align-items: baseline; }
.ui-prop-shothead b, .ui-prop-contacthead b { font-size: var(--fs-lead); }
.ui-prop-contacthead a { display: inline-flex; align-items: center; min-height: var(--control); color: var(--ink); font-weight: 600; }
.ui-prop-onphones { color: var(--ok); font-weight: 600; }
.ui-prop-waiver { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; padding: 8px 10px;
                  background: var(--alt); border-radius: var(--r-control); }
.ui-prop-waiver p { margin: 0; flex: 1 1 260px; }
.ui-prop-contacts { display: flex; flex-direction: column; gap: 10px; }
.ui-code-more { display: flex; flex-wrap: wrap; gap: 6px; width: 100%; }
.ui-code-more[hidden] { display: none; }
.ui-prop-queue { display: flex; flex-direction: column; gap: 10px; }
.ui-prop-queue .ui-item b { overflow-wrap: anywhere; }
.ui-prop-queue .ui-link { display: inline-flex; align-items: center; min-height: var(--control); }

/* Work here: the opened visit under its row, the photos across visits. */
.ui-work-details { width: 1%; white-space: nowrap; }
.ui-prop-openrow > td { padding: 0 16px 16px; background: var(--sunk); border-bottom: 1px solid var(--line); }
.ui-prop-visit { display: flex; flex-direction: column; gap: 12px; padding-top: 12px; }
.ui-prop-visitpart { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 16px; }
.ui-prop-visitsection { display: flex; flex-direction: column; gap: 8px; min-width: 0; }
.ui-prop-visitfoot { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; }
.ui-prop-visitfoot a { display: inline-flex; align-items: center; min-height: var(--control); font-weight: 600; color: var(--ink); }
.ui-prop-photos { display: flex; flex-wrap: wrap; gap: 8px 12px; align-items: center; }
.ui-prop-photos p { margin: 0; flex-basis: 100%; }
.ui-prop-photos p:empty { display: none; }
@media (max-width: 1100px) { .ui-prop-visitpart { grid-template-columns: minmax(0, 1fr); } }
.ui-prop-wide { grid-column: 1 / -1; }
.ui-prop-field textarea { min-height: 72px; }
.ui-prop-field textarea.ui-prop-tall { min-height: 120px; }
.ui-props-table td > span.ui-tag { display: inline-block; width: auto; }
.ui-prop-top .ui-link { display: inline-flex; align-items: center; min-height: var(--control); }

/* S6 step 1: the pilot's figures at the bottom of Today (screen 26). */
body.console .ui-pilot { margin-top: 16px; display: flex; flex-direction: column; gap: 12px; }
body.console .ui-pilot p { margin: 0; }
.ui-pilot-top { display: grid; grid-template-columns: minmax(200px, 280px) minmax(0, 1fr); gap: 24px; align-items: start; }
.ui-pilot-total { display: flex; flex-direction: column; gap: 4px; }
.ui-pilot-verdict { font-weight: 700; }
.ui-pilot-cleaners { display: flex; flex-direction: column; gap: 10px; min-width: 0; }
.ui-pilot-cleaner { display: grid; grid-template-columns: 96px minmax(120px, 1fr) minmax(0, 1.4fr); gap: 12px;
                    align-items: center; }
.ui-pilot-name { font-weight: 600; overflow-wrap: anywhere; }
.ui-pilot-bar { position: relative; height: 14px; border-radius: 7px; background: var(--track); }
.ui-pilot-fill { position: absolute; left: 0; top: 0; height: 100%; border-radius: 7px; background: var(--ok); }
.ui-pilot-fill.ui-pilot-low { background: var(--over); }
.ui-pilot-goal { position: absolute; left: 90%; top: -3px; bottom: -3px; width: 2px; background: var(--ink); }
.ui-pilot-figure { font-size: var(--fs-body); font-weight: 600; font-variant-numeric: tabular-nums; }
.ui-pilot-figure.warn { font-weight: 700; }
.ui-pilot-stats { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 16px; }
.ui-pilot-stat { display: flex; flex-direction: column; gap: 4px; padding: 12px 14px; border: 1px solid var(--line);
                 border-radius: var(--r-card); min-width: 0; }
.ui-pilot-num { font-size: var(--fs-h2); font-weight: 700; font-variant-numeric: tabular-nums; }
.ui-pilot-how > summary { min-height: var(--control); display: flex; align-items: center; font-weight: 600;
                          color: var(--ink); cursor: pointer; }
.ui-pilot-how p { margin: 4px 0; }
@media (max-width: 767px) {
  .ui-pilot-top, .ui-pilot-stats { grid-template-columns: minmax(0, 1fr); }
  .ui-pilot-cleaner { grid-template-columns: 80px minmax(0, 1fr); }
  .ui-pilot-figure { grid-column: 1 / -1; }
}

/* S6 step 1: "Was the cleaning done?" in every form that asks it (screens 27 and 30), the answer on the job page's
   Review card (28 and 31), and a check-in that came after the answer (27). */
.ui-answer { margin: 0; padding: 8px 12px; border: 1px solid var(--line); border-radius: var(--r-control);
             display: flex; flex-direction: column; gap: 2px; }
.ui-answer legend { padding: 0 4px; font-weight: 700; }
.ui-answer-choice { display: flex; align-items: center; gap: 8px; min-height: var(--control); cursor: pointer; }
.ui-answer-choice input { width: 20px; height: 20px; margin: 0; }
.ui-answer-grid { display: grid; grid-template-columns: max-content minmax(0, 1fr); gap: 6px 14px; margin: 0; }
.ui-answer-grid dt { color: var(--text-2); }
.ui-answer-grid dd { margin: 0; font-weight: 600; overflow-wrap: anywhere; }
.ui-after-answer { margin: 6px 0; padding: 8px 10px; background: var(--tint-warn); border: 1px solid var(--line-moved);
                   border-radius: var(--r-control); }
.ui-after-answer p { margin: 0; }
@media (max-width: 600px) { .ui-answer-grid { grid-template-columns: minmax(0, 1fr); } }

/* S6 step 2 (screens 32-38): Offboard on People, held work in the Queue and on the job page, an offboarded person's
   visits on the board and in Work, and Codes across properties. */
button.danger { background: var(--bad); border-color: var(--bad); color: #fff; font-weight: 600; }
.ui-offboard { max-width: 900px; background: var(--tint-warn); border: 1px solid var(--line-moved);
               border-radius: var(--r-card); padding: 14px 16px; }
.ui-offboard h3 { margin: 0 0 8px; }
.ui-offboard .facts dd, .ui-offboard-lines dd { font-weight: 400; }
.ui-offboard-lines { margin-top: 6px; }
.ui-people-left { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; margin-top: 16px; }
.ui-people-left h2 { margin: 0; }
.ui-held-visit { margin: 10px 0 0; padding: 8px 0 0; border-top: 1px solid var(--line-soft); }
.ui-held-item { display: flex; gap: 12px; align-items: flex-start; flex-wrap: wrap; margin: 8px 0 0 12px;
                padding-left: 10px; border-left: 3px solid var(--line); }
.ui-held-item > .what { flex: 1 1 320px; min-width: 0; }
/* An item's buttons wrap under its words on a narrow screen rather than push the page sideways. */
.ui-held-item > .acts { flex: 0 1 auto; min-width: 0; max-width: 100%; }
.ui-held-item p { margin: 2px 0; }
.ui-checks { list-style: none; margin: 4px 0; padding: 0; display: flex; flex-wrap: wrap; gap: 6px; }
.ui-checks li { font-size: var(--fs-sm); padding: 2px 8px; border-radius: var(--r-tag, 4px); overflow-wrap: anywhere; }
.ui-check-ok { background: #edf5f0; color: var(--ok); }
.ui-check-bad { background: #fbeaea; color: var(--bad); font-weight: 600; }
.ui-job-held { margin: 6px 0 0; }
.ui-job-helditem { margin: 6px 0; padding: 6px 10px; border-left: 3px solid var(--line-moved); background: var(--tint-warn); }
.ui-job-helditem p { margin: 2px 0; }
.ui-board-offboarded { font-size: var(--fs-sm); font-weight: 700; color: var(--warn); }
.ui-board-needscleaner { font-size: var(--fs-sm); color: var(--warn); }
.ui-day-needscleaner { display: flex; flex-direction: column; gap: 2px; margin-bottom: 6px; padding: 6px 8px;
                       background: var(--tint-warn); border: 1px solid var(--line-moved); border-radius: var(--r-control); }
.ui-day-needswords { font-size: var(--fs-sm); font-weight: 700; color: var(--warn); }
.ui-stop-needscleaner { box-shadow: inset 3px 0 0 var(--warn); }
.ui-swatch-needscleaner { background: var(--tint-warn); border: 1px solid var(--warn); }
.ui-work-needscleaner { background: var(--tint-warn); color: var(--warn); }
.ui-across-group { margin: 12px 0; }
.ui-across-group h3 { margin: 0 0 6px; }
.ui-across-filters { display: flex; flex-wrap: wrap; gap: 12px; margin: 8px 0 12px; }
.ui-across-scroll { overflow-x: auto; }
/* On a narrow screen the table scrolls inside its card, never the page, and never breaks a word letter by letter. */
.ui-across-table { width: 100%; min-width: 680px; border-collapse: collapse; font-size: var(--fs-sm); }
.ui-across-table th, .ui-across-table td { text-align: left; padding: 6px 8px; border-bottom: 1px solid var(--line-soft);
                                           vertical-align: top; }
.ui-across .acts a.ui-btn { display: inline-flex; align-items: center; min-height: var(--control); }
/* The step 2 controls are touch targets (44 px): People's row actions and forms, Who has left, the codes screen. */
body.console [data-person] .acts button, body.console [data-person] .form button, body.console .ui-people-left button,
body.console .ui-across button, body.console .ui-across select, body.console .ui-across input { min-height: var(--control); }
/* ---- S6 step 4 part B: the schedule kept 4 weeks ahead (screens 47-52), console only ---------------------------- */
body.console .ui-sched-inforce.ui-sched-stopped { border: 2px solid var(--over); }
body.console .ui-sched-kept { display: flex; flex-direction: column; gap: 2px; padding-top: 12px;
  border-top: 1px solid var(--line-soft); }
body.console .ui-sched-kept p, body.console .ui-sched-stop-words p, body.console .ui-sched-hlate { margin: 0; }
body.console .ui-sched-stop { display: flex; align-items: center; gap: 16px; flex-wrap: wrap; padding: 14px 16px;
  background: var(--tint-warn); border: 1px solid var(--line-moved); border-radius: var(--r-card); }
body.console .ui-sched-stop-words { display: flex; flex-direction: column; gap: 4px; flex: 1 1 420px; min-width: 0; }
body.console .ui-sched-stop-title { font-size: var(--fs-lead); color: var(--moved); }
body.console .ui-sched-hlate { color: var(--bad); }
body.console .ui-sched-carry { margin: 0 0 8px; padding: 10px 12px; font-size: var(--fs-control); color: #24563f;
  background: #f1f7f3; border: 1px solid #bcd9c7; border-radius: var(--r-control); }
.ui-tag-stop { background: #fdf3ec; color: var(--moved); border: 1px solid #f1c7aa; }
body.console .ui-qrow.ui-qrow-stop { border-color: #f1c7aa; }
body.console .ui-stop-when { font-weight: 600; color: var(--moved); }
body.console .ui-stop-title { font-size: var(--fs-name); }
body.console .ui-stopbox { margin-top: 6px; padding: 8px 12px; background: var(--tint-warn);
  border-left: 3px solid var(--over); }
body.console .ui-stopbox p { margin: 2px 0 0; }
.ui-day-stopday { background: var(--tint-warn); border: 1px dashed var(--over); }
.ui-day-stopday .ui-day-emptywords { color: var(--moved); }
/* ---- S6 step 5 part C: the nightly jobs (screens 59 and 60), console only -------------------------------------- */
/* Today's green lines, after the photo library's: the server's words in ink, each after a check drawn with borders
   (decoration, not a glyph a screen reader would read). "open it" is a 44 px target, as the foot's other controls. */
/* The green lines' own node (round 3): its children lay out in the foot as if it were not there. */
body.console .ui-today-nightly { display: contents; }
body.console .ui-nightly-ok { position: relative; display: inline-block; max-width: 100%; box-sizing: border-box;
  padding-left: 18px; color: var(--ink); }
/* The check stays beside the words when they wrap on a phone (a flex row put it on a line of its own). */
body.console .ui-nightly-ok::before { content: ""; position: absolute; left: 4px; top: calc(50% - 7px); width: 4px;
  height: 9px; border: solid var(--ok); border-width: 0 2px 2px 0; transform: rotate(45deg); }
body.console .ui-nightly-ok a { display: inline-flex; align-items: center; min-height: var(--control); font-weight: 600;
  color: var(--ink); }
body.console .ui-nightly-ok a:hover { color: var(--ink-deep); }
/* Work's link to the spreadsheet, beside the title and before As of (screen 60); hidden while there is none. */
.ui-work-sheet { margin-left: auto; max-width: 100%; }
.ui-work-sheet:not([hidden]) + .ui-asof { margin-left: 0; }
.ui-sheet-link { display: inline-flex; align-items: center; flex-wrap: wrap; gap: 0 8px; min-height: var(--control);
  max-width: 100%; box-sizing: border-box; padding: 4px 14px; font-size: var(--fs-control); font-weight: 600;
  color: var(--ink); text-decoration: none; background: var(--card); border: 1px solid var(--line);
  border-radius: var(--r-control); }
.ui-sheet-link:hover { color: var(--ink-deep); border-color: var(--ink); }
/* A sheet's outline, a header row and a column, in the ok green (decoration). */
.ui-sheet-link::before { content: ""; flex: none; width: 12px; height: 14px; border: 2px solid var(--ok);
  border-radius: 2px; background: linear-gradient(var(--ok), var(--ok)) 0 4px / 100% 2px no-repeat,
  linear-gradient(var(--ok), var(--ok)) 4px 0 / 2px 100% no-repeat; }
.ui-sheet-when { font-weight: 400; color: var(--text-2); }
/* Messaging M2 part C (mockups 67-70): the console's Notifications item in the header, the panel under it (the Turn on
   step, a refusal, "Sent. Did it show up?", Sign out's question) and the coming-forward bar on an installed console on a
   phone (navy: Richard asked for it to stand out). */
body.console .ui-push-slot { display: inline-flex; align-items: center; }
body.console .ui-push-item { display: inline-flex; align-items: center; gap: 6px; flex-wrap: wrap; font-size: var(--fs-control); }
body.console .ui-push-on { color: var(--ok); font-weight: 600; }
body.console .ui-push-link { min-height: var(--control); padding: 0 6px; border: none; background: transparent; color: var(--ink);
  font: inherit; text-decoration: underline; cursor: pointer; }
body.console .ui-push-link:hover { color: var(--ink-deep); }
body.console .ui-push-link:disabled { color: var(--dim); cursor: default; }
body.console .ui-push-turn-on { min-height: var(--control); font-weight: 600; color: var(--ink); border-color: var(--ink); }
body.console #pushpanel:empty { display: none; }
body.console #pushpanel { display: flex; justify-content: flex-end; padding: 8px 20px 0; }
body.console .ui-push-panel { width: min(460px, 100%); box-sizing: border-box; padding: 16px 18px; background: var(--card);
  border: 1px solid var(--ink); border-radius: var(--r-card, 8px); box-shadow: 0 6px 20px rgba(27, 54, 93, 0.12); }
body.console .ui-push-panel h2 { margin: 0 0 8px; font-size: 18px; }
body.console .ui-push-panel p { margin: 0 0 8px; }
body.console .ui-push-note { width: min(760px, 100%); box-sizing: border-box; padding: 10px 16px; background: #eef2f8;
  border: 1px solid #c6d2e3; border-radius: var(--r-card, 8px); }
body.console .ui-push-note p { margin: 0; }
body.console .ui-push-bar { display: flex; align-items: center; gap: 12px; padding: 12px 20px; background: var(--navy); color: #fff;
  font-size: 17px; font-weight: 600; }
body.console .ui-push-bar span { flex-grow: 1; }
body.console .ui-push-bar button { min-height: var(--control); padding: 0 18px; background: #fff; color: var(--navy);
  border: 1px solid #fff; border-radius: var(--r-control, 6px); font: inherit; font-size: 16px; font-weight: 700; }
