/* Dorset Rewires EICR capture app - phone first.
   Design tokens mirror public/assets/css/styles.css so the app feels like the business.
   Everything is sized for a thumb in a loft, not a mouse on a desk. */

:root {
  --colour-navy: #0F2540;
  --colour-navy-deep: #08182C;
  --colour-amber: #F4A300;
  --colour-amber-soft: #FFF8EC;
  --colour-green: #1FA45A;
  --colour-danger: #C0392B;
  --colour-text: #22293A;
  --colour-text-soft: #4A5468;
  --colour-text-faint: #7E8EA8;
  --colour-background: #FCFCFA;
  --colour-surface: #FFFFFF;
  --colour-border: #E3E7ED;

  --radius-small: 8px;
  --radius-medium: 12px;
  --radius-large: 16px;
  --radius-pill: 999px;

  /* One thumb target. Never make anything tappable smaller than this. */
  --tap-target-minimum: 56px;

  --font-stack: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
}

/* touch-action manipulation stops the double-tap-to-zoom gesture (annoying when
   tapping Back/Next fast) while keeping scroll and pinch-zoom. */
* { box-sizing: border-box; -webkit-tap-highlight-color: transparent; touch-action: manipulation; }

html, body {
  margin: 0;
  padding: 0;
  height: 100%;
  overscroll-behavior: none;
}

body {
  font-family: var(--font-stack);
  color: var(--colour-text);
  background: var(--colour-background);
  font-size: 17px;
  line-height: 1.45;
}

/* ---------- App frame: fixed header, scrolling slide, fixed footer ---------- */

.app-frame {
  display: flex;
  flex-direction: column;
  height: 100dvh;
}

/* Desktop: the app is phone-first, so on a wide screen cap it to a centred
   phone-ish column instead of stretching edge to edge (Pete, 2026-07-28). */
@media (min-width: 900px) {
  .app-frame {
    max-width: 560px;
    margin: 0 auto;
    border-left: 1px solid rgba(0, 0, 0, 0.12);
    border-right: 1px solid rgba(0, 0, 0, 0.12);
  }
}

.app-header {
  flex: 0 0 auto;
  background: var(--colour-navy);
  color: #fff;
  /* Installed on the home screen the app draws UNDER the iPhone status bar, so
     pad the top by the safe area to clear the clock, battery and signal icons.
     The navy fills behind them, which looks right. */
  padding: calc(10px + env(safe-area-inset-top)) 14px 0;
}

.app-header-row {
  display: flex;
  align-items: center;
  gap: 10px;
  min-height: 44px;
}

.app-header-title {
  flex: 1 1 auto;
  font-size: 15px;
  font-weight: 600;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.app-header-subtitle {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 10px;
  font-size: 12px;
  color: #A9BBD2;
  font-weight: 400;
}

#header-job-name {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* Amber page counter, always visible. Lets Pete say "page 34 needs a change"
   without scrolling to find where he is. Also shows how far through he is, and
   which certificate it is ("EIC 7/26") - the job name beside it is what gives
   way when the row runs out of room, never the counter. */
.header-page-number {
  flex: 0 0 auto;
  white-space: nowrap;
  font-variant-numeric: tabular-nums;
  font-weight: 700;
  color: var(--colour-amber);
}

.header-button {
  flex: 0 0 auto;
  min-width: 44px;
  min-height: 44px;
  border: 0;
  border-radius: var(--radius-small);
  background: rgba(255, 255, 255, 0.12);
  color: #fff;
  font-size: 15px;
  font-weight: 600;
  font-family: inherit;
  cursor: pointer;
}

.header-button:active { background: rgba(255, 255, 255, 0.25); }

.progress-track {
  height: 4px;
  background: rgba(255, 255, 255, 0.15);
  margin: 8px -14px 0;
}

.progress-fill {
  height: 100%;
  background: var(--colour-amber);
  width: 0;
  transition: width 0.18s ease-out;
}

/* ---------- The slide ---------- */

.slide-area {
  flex: 1 1 auto;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  padding: 22px 18px 28px;
}

.slide-step {
  font-size: 13px;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--colour-amber);
  margin-bottom: 6px;
}

.slide-question {
  font-size: 27px;
  line-height: 1.2;
  font-weight: 700;
  margin: 0 0 8px;
  color: var(--colour-navy);
}

.slide-note {
  font-size: 14px;
  color: var(--colour-text-soft);
  margin: 0 0 20px;
}

.slide-note.is-reg {
  font-size: 12px;
  color: var(--colour-text-faint);
}

/* ---------- Fields ---------- */

.field-block { margin-bottom: 22px; }

.field-label {
  display: block;
  font-size: 15px;
  font-weight: 600;
  margin-bottom: 8px;
  color: var(--colour-text);
}

.field-unit {
  font-weight: 400;
  color: var(--colour-text-faint);
}

.field-hint {
  font-size: 13px;
  color: var(--colour-text-faint);
  margin: 6px 0 0;
}

.field-input,
.field-textarea {
  width: 100%;
  min-height: var(--tap-target-minimum);
  padding: 14px 16px;
  font-size: 19px;
  font-family: inherit;
  color: var(--colour-text);
  background: var(--colour-surface);
  border: 2px solid var(--colour-border);
  border-radius: var(--radius-medium);
}

.field-textarea {
  min-height: 110px;
  resize: vertical;
  line-height: 1.4;
}

.field-input:focus,
.field-textarea:focus {
  outline: none;
  border-color: var(--colour-amber);
  box-shadow: 0 0 0 4px var(--colour-amber-soft);
}

/* Big tappable answers. These replace dropdowns everywhere - a native select
   on a phone is a fiddly wheel, and this is a gloved-hand job. */
.choice-list {
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.choice-button {
  min-height: var(--tap-target-minimum);
  padding: 15px 18px;
  text-align: left;
  font-size: 18px;
  font-family: inherit;
  font-weight: 500;
  color: var(--colour-text);
  background: var(--colour-surface);
  border: 2px solid var(--colour-border);
  border-radius: var(--radius-medium);
  cursor: pointer;
}

.choice-button:active { background: var(--colour-amber-soft); }

.choice-button.is-selected {
  border-color: var(--colour-navy);
  background: var(--colour-navy);
  color: #fff;
}

.choice-code {
  display: inline-block;
  min-width: 30px;
  font-weight: 700;
  color: var(--colour-amber);
}

.choice-button.is-selected .choice-code { color: var(--colour-amber); }

/* ---------- Footer navigation ---------- */

.app-footer {
  flex: 0 0 auto;
  display: flex;
  flex-direction: column;
  gap: 10px;
  padding: 12px 14px;
  padding-bottom: max(12px, env(safe-area-inset-bottom));
  background: var(--colour-surface);
  border-top: 1px solid var(--colour-border);
}

.footer-nav {
  display: flex;
  gap: 10px;
}

/* The add-observation button now lives in the footer, below Back/Next, so it
   never floats over the answer buttons on a short slide. */
.observation-bar {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  min-height: 46px;
  font-size: 16px;
  font-weight: 700;
  font-family: inherit;
  color: #fff;
  background: var(--colour-danger);
  border: 0;
  border-radius: var(--radius-medium);
  cursor: pointer;
}

.observation-bar:active { background: #a5301f; }

.navigation-button {
  min-height: var(--tap-target-minimum);
  border: 0;
  border-radius: var(--radius-medium);
  font-size: 18px;
  font-weight: 700;
  font-family: inherit;
  cursor: pointer;
}

.navigation-button.is-back {
  flex: 0 0 34%;
  background: #EDF0F5;
  color: var(--colour-text-soft);
}

.navigation-button.is-next {
  flex: 1 1 auto;
  background: var(--colour-navy);
  color: #fff;
}

.navigation-button:disabled { opacity: 0.4; }

/* ---------- Overview sheet ---------- */

.overview-sheet {
  position: fixed;
  inset: 0;
  background: var(--colour-background);
  z-index: 20;
  display: flex;
  flex-direction: column;
}

.overview-sheet[hidden] { display: none; }

.overview-body { flex: 1 1 auto; overflow-y: auto; padding: 18px; }

.overview-deck-title {
  font-size: 13px;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--colour-text-faint);
  margin: 22px 0 10px;
}

.overview-deck-title:first-child { margin-top: 0; }

.overview-item {
  display: flex;
  align-items: center;
  gap: 12px;
  width: 100%;
  min-height: var(--tap-target-minimum);
  padding: 12px 14px;
  margin-bottom: 8px;
  text-align: left;
  font-size: 16px;
  font-family: inherit;
  color: var(--colour-text);
  background: var(--colour-surface);
  border: 2px solid var(--colour-border);
  border-radius: var(--radius-medium);
  cursor: pointer;
}

.overview-item.is-current { border-color: var(--colour-amber); }

.overview-status {
  flex: 0 0 auto;
  width: 24px;
  font-weight: 700;
  color: var(--colour-green);
}

.overview-status.is-empty { color: var(--colour-border); }

.deck-locked {
  font-size: 13px;
  color: var(--colour-text-faint);
  padding: 10px 14px;
  background: #F4F6FA;
  border-radius: var(--radius-medium);
  margin-bottom: 8px;
}

/* ---------- Client picker ---------- */

.client-search {
  width: 100%;
  min-height: var(--tap-target-minimum);
  padding: 14px 16px;
  font-size: 18px;
  font-family: inherit;
  border: 2px solid var(--colour-border);
  border-radius: var(--radius-medium);
  margin-bottom: 12px;
}

.client-result {
  display: block;
  width: 100%;
  min-height: var(--tap-target-minimum);
  padding: 12px 14px;
  margin-bottom: 8px;
  text-align: left;
  font-family: inherit;
  background: var(--colour-surface);
  border: 2px solid var(--colour-border);
  border-radius: var(--radius-medium);
  cursor: pointer;
}

.client-result-name { font-size: 17px; font-weight: 600; }
.client-result-detail { font-size: 14px; color: var(--colour-text-faint); }

.picker-message {
  font-size: 14px;
  color: var(--colour-text-soft);
  padding: 14px;
  background: var(--colour-amber-soft);
  border-radius: var(--radius-medium);
}

/* ---------- Circuits ---------- */

/* Wraps instead of side-scrolling - on a phone, off-screen chips are invisible
   chips. A 21-circuit board just gets a taller block. */
.board-strip,
.circuit-strip {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  padding-bottom: 10px;
  margin-bottom: 16px;
}

.board-chip,
.circuit-chip {
  flex: 0 0 auto;
  min-height: 44px;
  padding: 10px 16px;
  font-size: 16px;
  font-weight: 600;
  font-family: inherit;
  background: var(--colour-surface);
  border: 2px solid var(--colour-border);
  border-radius: var(--radius-pill, 999px);
  cursor: pointer;
}

.board-chip.is-current,
.circuit-chip.is-current {
  background: var(--colour-navy);
  border-color: var(--colour-navy);
  color: #fff;
}

/* Test-by-meter tab bar. One tab per test type; scrolls sideways on a narrow
   phone. Tap a tab and the whole board screen switches to that test. */
/* Wraps instead of side-scrolling, so no test tab ever hides off-screen. */
.mode-tabs {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  padding-bottom: 10px;
  margin-bottom: 8px;
}

.mode-tab {
  flex: 0 0 auto;
  min-height: 44px;
  padding: 10px 16px;
  font-size: 15px;
  font-weight: 600;
  font-family: inherit;
  color: var(--colour-text-soft);
  background: var(--colour-surface);
  border: 2px solid var(--colour-border);
  border-radius: var(--radius-pill, 999px);
  cursor: pointer;
}

.mode-tab.is-current {
  background: var(--colour-amber-soft);
  border-color: var(--colour-amber);
  color: var(--colour-navy);
}

/* Board setup wizard: Back and Next sit side by side, not full width each. */
.wizard-nav { display: flex; gap: 10px; }
.wizard-nav .action-button { flex: 1; margin-top: 12px; }
.wizard-nav .action-button:disabled { opacity: 0.45; cursor: default; }

/* One circuit's row on a batch test screen: its label, then the reading box. */
.batch-row {
  padding: 12px 0;
  border-bottom: 1px solid var(--colour-border);
}

.batch-row-label {
  font-size: 15px;
  font-weight: 700;
  color: var(--colour-navy);
  margin-bottom: 8px;
}

.batch-row .field-block {
  margin-bottom: 8px;
}

/* THE FOUR CONTINUITY BOXES (2026-09-17): r1, rn, r2 and R1+R2 on every
   circuit, two by two, so a row still fits a phone without a scroll per
   circuit. */
.batch-row.is-four-boxes {
  display: grid;
  grid-template-columns: 1fr 1fr;
  column-gap: 10px;
}

.batch-row.is-four-boxes .batch-row-label {
  grid-column: 1 / -1;
}

/* THE "RING FINAL?" GATE (2026-09-17 evening): the question spans the row
   above the four boxes, so the grid below it still pairs r1 with rn and r2
   with R1+R2. */
.batch-row.is-four-boxes .ring-final-gate {
  grid-column: 1 / -1;
}

.ring-final-gate .quick-pick-row { margin-bottom: 4px; }

/* NOTHING TO TEST, SAID IN ITS PLACE (Pete 2026-09-17 17:47: a circuit that
   vanished from a test page "would be deceiving"). One plain line where the
   boxes would be - not a button, not a box, not a warning. */
.nothing-to-test-line {
  margin: 0;
  font-size: 15px;
  color: var(--colour-text-soft);
}

.batch-row.is-nothing-to-test { padding: 12px 0; }

/* The not-a-ring line sits above the R1+R2 box, so it keeps a little air. */
.batch-row.is-continuity .nothing-to-test-line { margin-bottom: 10px; }

/* THE EXPECTED R1+R2 (Pete 17:45): the derived figure sits in the box in a
   lighter style until a measured reading is typed over it, with the line
   under it saying so. A glance tells calculated from measured. */
.field-input.is-expected {
  color: var(--colour-text-faint);
  font-style: italic;
  border-style: dashed;
}

.reading-marker.expected-reading-line {
  color: var(--colour-text-soft);
  font-weight: 600;
}

/* THE ONE-TAP YES at the top of a yes-or-no test page. */
.bulk-yes-control { margin-bottom: 8px; }
.bulk-yes-control .field-hint { margin-top: 4px; }

/* THE BONDING RESISTANCE BOX sits above the one-tap status choice on a
   single-tap page, so it keeps a tighter margin than a field of its own
   (the page must still fit 609 px on the flow-shape gate). */
.bonding-resistance-box { margin-bottom: 10px; }

/* THE BONDING RESISTANCE LINE: plain words under the box, never a block. */
.bonding-guide-line {
  color: var(--colour-danger);
  font-weight: 600;
}

.bonding-recap-line { margin: -4px 0 12px; }

/* A PROPOSED observation looks like an observation card but says what it
   is: a suggestion waiting for the inspector's tap. Its one code pill is a
   label, not a choice, so it keeps its own width. */
.observation-card.observation-proposal { border-style: dashed; }
.observation-proposal .code-pill {
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  padding: 0 18px;
}

/* THE CIRCUIT COUNT LINE (2026-09-17, "Go count"): plain words and two quiet
   buttons, at least 24 px clear of the circuit tabs below it and visibly not
   a tab - no pill, no border, a soft strip. */
.circuit-count-line {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 8px;
  padding: 10px 12px;
  margin-bottom: 28px;
  background: #EDF0F5;
  border-radius: var(--radius-medium);
  font-size: 15px;
  color: var(--colour-text-soft);
}

.circuit-count-words {
  flex: 1 1 auto;
  font-weight: 600;
  color: var(--colour-text);
}

.circuit-count-button {
  min-height: 44px;
  padding: 8px 14px;
  font-size: 14px;
  font-weight: 600;
  font-family: inherit;
  color: var(--colour-text-soft);
  background: var(--colour-surface);
  border: 1px solid var(--colour-border);
  border-radius: var(--radius-medium);
  cursor: pointer;
}

/* The Change sheet sits ABOVE the line, never beside the tabs. */
.circuit-count-sheet {
  padding: 4px 12px 12px;
  margin-bottom: 12px;
  border: 2px solid var(--colour-amber-line, #FCE6B6);
  border-radius: var(--radius-medium);
  background: var(--colour-amber-soft);
}

.circuit-count-sheet .field-group-heading {
  margin-top: 10px;
  padding-top: 0;
  border-top: 0;
}

.circuit-count-sheet .action-button { margin-top: 10px; }

/* The inline shrink question. Never a native popup. */
.circuit-count-question {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 10px;
  padding: 12px;
  margin-bottom: 12px;
  border: 2px solid var(--colour-amber);
  border-radius: var(--radius-medium);
  background: #fff;
}

.circuit-count-question p {
  flex: 1 1 100%;
  margin: 0;
  font-size: 15px;
  font-weight: 600;
  color: var(--colour-navy);
}

.circuit-count-question .action-button {
  flex: 1 1 40%;
  margin-top: 0;
}

/* THE PICKER'S SECOND ROW (2026-09-17): "Which property?" / "Which job?"
   under the customer's own button, one tap each. */
.client-choice-row:empty { display: none; }

.client-choice-row {
  padding: 4px 0 12px 14px;
  border-left: 3px solid var(--colour-amber);
  margin: 0 0 8px 6px;
}

.client-choice-question {
  font-size: 14px;
  font-weight: 700;
  color: var(--colour-navy);
  margin: 6px 0 8px;
}

.client-choice {
  display: block;
  width: 100%;
  min-height: 44px;
  margin-bottom: 8px;
  padding: 10px 14px;
  text-align: left;
  font-size: 15px;
  font-family: inherit;
  color: var(--colour-text);
  background: var(--colour-amber-soft);
  border: 2px solid var(--colour-amber-line, #FCE6B6);
  border-radius: var(--radius-medium);
  cursor: pointer;
}

.field-group-heading {
  font-size: 13px;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--colour-text-faint);
  margin: 26px 0 12px;
  padding-top: 14px;
  border-top: 1px solid var(--colour-border);
}

.action-button {
  width: 100%;
  min-height: var(--tap-target-minimum);
  margin-top: 12px;
  font-size: 17px;
  font-weight: 600;
  font-family: inherit;
  color: var(--colour-navy);
  background: var(--colour-amber-soft);
  border: 2px solid var(--colour-amber);
  border-radius: var(--radius-medium);
  cursor: pointer;
}

/* An ANCHOR wearing the action-button look (the Receipts entry in the Jobs
   sheet, 2026-09-09). A link is inline by default, so without this it would
   ignore the full width and sit its text against the left edge - the same
   control has to look the same however it is marked up. */
a.action-button {
  display: flex;
  align-items: center;
  justify-content: center;
  text-decoration: none;
  box-sizing: border-box;
  padding: 12px 16px;
}

.action-button.is-quiet {
  color: var(--colour-text-soft);
  background: #EDF0F5;
  border-color: var(--colour-border);
}

/* A measured Zs above the maximum permitted is a FAIL. The app knows the OCPD,
   so it can say so on site - no tester does this for you. */
.zs-verdict {
  margin-top: 10px;
  padding: 12px 14px;
  border-radius: var(--radius-medium);
  font-size: 15px;
  font-weight: 600;
}

.zs-verdict.is-pass { background: #E8F6EE; color: #14733D; }
.zs-verdict.is-fail { background: #FBEAE7; color: var(--colour-danger); }

.save-flash {
  position: fixed;
  left: 50%;
  bottom: 88px;
  transform: translateX(-50%);
  padding: 8px 16px;
  font-size: 13px;
  color: #fff;
  background: rgba(15, 37, 64, 0.9);
  border-radius: 999px;
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.2s;
}

.save-flash.is-visible { opacity: 1; }

/* ---------- Inspection outcomes ----------
   Eight possible answers per item, 66 items. A list of eight full-width
   buttons would mean scrolling on every single one, so they go in a grid
   that fits one screen. Colour carries the meaning at a glance: red is
   dangerous, amber is advisory, grey is "did not apply". */

.outcome-grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 10px;
  margin-top: 4px;
}

.outcome-button {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  justify-content: center;
  gap: 2px;
  min-height: 72px;
  padding: 10px 14px;
  text-align: left;
  font-family: inherit;
  background: var(--colour-surface);
  border: 2px solid var(--colour-border);
  border-radius: var(--radius-medium);
  cursor: pointer;
}

.outcome-symbol { font-size: 20px; font-weight: 700; color: var(--colour-navy); }
.outcome-caption { font-size: 12px; color: var(--colour-text-faint); line-height: 1.2; }

.outcome-button.is-c1 .outcome-symbol,
.outcome-button.is-c2 .outcome-symbol { color: var(--colour-danger); }
.outcome-button.is-c3 .outcome-symbol,
.outcome-button.is-fi .outcome-symbol { color: #B57200; }
.outcome-button.is-acceptable .outcome-symbol { color: var(--colour-green); }

.outcome-button.is-selected {
  border-color: var(--colour-navy);
  background: var(--colour-navy);
}
.outcome-button.is-selected .outcome-symbol,
.outcome-button.is-selected .outcome-caption { color: #fff; }

.outcome-button.is-c1.is-selected,
.outcome-button.is-c2.is-selected {
  background: var(--colour-danger);
  border-color: var(--colour-danger);
}
.outcome-button.is-acceptable.is-selected {
  background: var(--colour-green);
  border-color: var(--colour-green);
}

/* ---------- Inspection checklist ---------- */

/* One tappable line per item. The whole row opens its outcome buttons. */
.checklist-item { margin-bottom: 8px; }

.checklist-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  width: 100%;
  min-height: var(--tap-target-minimum);
  padding: 12px 14px;
  text-align: left;
  font-family: inherit;
  background: var(--colour-surface);
  border: 2px solid var(--colour-border);
  border-radius: var(--radius-medium);
  cursor: pointer;
}

.checklist-row.is-open {
  border-color: var(--colour-navy);
  border-bottom-left-radius: 0;
  border-bottom-right-radius: 0;
}

.checklist-row-text {
  font-size: 15px;
  font-weight: 600;
  color: var(--colour-navy);
  line-height: 1.3;
}

/* The status badge on the right: green tick when acceptable, red for C1/C2,
   amber for C3/FI, a faint prompt when nothing is set yet. */
.checklist-status {
  flex: 0 0 auto;
  min-width: 40px;
  padding: 4px 10px;
  font-size: 14px;
  font-weight: 700;
  text-align: center;
  border-radius: var(--radius-pill, 999px);
  background: #EDF0F5;
  color: var(--colour-text-soft);
}

.checklist-status.is-unset { background: var(--colour-amber-soft); color: var(--colour-amber); }
.checklist-status.is-acceptable { background: #E8F6EE; color: var(--colour-green); }
.checklist-status.is-c1,
.checklist-status.is-c2 { background: #FBEAE7; color: var(--colour-danger); }
.checklist-status.is-c3,
.checklist-status.is-fi { background: #FBF1DC; color: #B57200; }

.checklist-item .outcome-grid,
.checklist-item .sub-item-list { margin-top: 10px; }

.sub-item-list {
  margin: 0 0 18px;
  padding-left: 20px;
  font-size: 15px;
  color: var(--colour-text-soft);
}

.sub-item-list li { margin-bottom: 6px; }

/* ---------- Observations ---------- */

.observation-editor { margin-top: 8px; }

.observation-card {
  padding: 14px;
  margin-bottom: 14px;
  background: var(--colour-surface);
  border: 2px solid var(--colour-border);
  border-left-width: 6px;
  border-radius: var(--radius-medium);
}

.observation-card.is-c1,
.observation-card.is-c2 { border-left-color: var(--colour-danger); }
.observation-card.is-c3,
.observation-card.is-fi { border-left-color: var(--colour-amber); }

.observation-code-row { display: flex; gap: 8px; margin-bottom: 12px; }

.code-pill {
  flex: 1 1 auto;
  min-height: 44px;
  font-size: 15px;
  font-weight: 700;
  font-family: inherit;
  color: var(--colour-text-soft);
  background: #EDF0F5;
  border: 2px solid transparent;
  border-radius: var(--radius-small);
  cursor: pointer;
}

.code-pill.is-selected { color: #fff; background: var(--colour-navy); }
.code-pill.is-c1.is-selected,
.code-pill.is-c2.is-selected { background: var(--colour-danger); }
.code-pill.is-c3.is-selected,
.code-pill.is-fi.is-selected { background: #B57200; }

/* ---------- Photos ---------- */

.photo-strip { display: flex; flex-wrap: wrap; gap: 10px; margin: 12px 0 0; }

.photo-thumbnail {
  position: relative;
  width: 88px;
  height: 88px;
  border-radius: var(--radius-small);
  overflow: hidden;
  border: 2px solid var(--colour-border);
}

.photo-thumbnail img { width: 100%; height: 100%; object-fit: cover; display: block; }

.photo-remove {
  position: absolute;
  top: 2px;
  right: 2px;
  width: 26px;
  height: 26px;
  font-size: 15px;
  font-weight: 700;
  font-family: inherit;
  color: #fff;
  background: rgba(15, 37, 64, 0.85);
  border: 0;
  border-radius: 50%;
  cursor: pointer;
}

/* ---------- Signature ---------- */

.signature-pad {
  width: 100%;
  height: 180px;
  background: var(--colour-surface);
  border: 2px dashed var(--colour-border);
  border-radius: var(--radius-medium);
  touch-action: none;
}

/* ---------- Finish ---------- */

.assessment-banner {
  padding: 20px;
  margin-bottom: 14px;
  text-align: center;
  font-size: 24px;
  font-weight: 700;
  letter-spacing: 0.02em;
  color: #fff;
  border-radius: var(--radius-medium);
}

.assessment-banner.is-satisfactory { background: var(--colour-green); }
.assessment-banner.is-unsatisfactory { background: var(--colour-danger); }

.client-result.is-current { border-color: var(--colour-amber); }

/* ---------- Quick-pick chips ----------
   Tap the most likely answer instead of typing. The text box stays below for
   anything the chips do not cover. This is the thumbs-first ADHD win. */
.quick-pick-row {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin-bottom: 10px;
}

.quick-pick {
  min-height: 44px;
  padding: 10px 16px;
  /* Buttons centre text by default - a long two-line chip then sits centred
     next to left-aligned labels. Left keeps every slide reading one way. */
  text-align: left;
  font-size: 16px;
  font-weight: 600;
  font-family: inherit;
  color: var(--colour-navy);
  background: var(--colour-amber-soft);
  border: 2px solid var(--colour-amber-line, #FCE6B6);
  border-radius: var(--radius-pill);
  cursor: pointer;
}

.quick-pick:active { background: #FDEFCF; }

.quick-pick.is-selected {
  color: #fff;
  background: var(--colour-navy);
  border-color: var(--colour-navy);
}

/* A SUGGESTED chip is outlined, never filled. Filled means chosen, and the
   next-inspection tier is only ever a suggestion until a thumb lands on it
   (Pete 2026-09-06). The dotted edge and the marker say "we think this one"
   without pretending the answer has been given. */
.quick-pick.is-suggested {
  border-style: dashed;
  border-color: var(--colour-green);
}

.quick-pick.is-suggested::after {
  content: " \00B7 suggested";
  color: var(--colour-green);
  font-weight: 700;
}

.quick-pick.is-suggested.is-selected::after { color: #BFEBD2; }

.slide-note.is-suggestion {
  color: var(--colour-green);
  font-weight: 600;
  margin-top: -12px;
}

/* ---------- New build: the one prominent tap ----------
   The initial verification schedule is the electrician's judgement, so it is
   confirmed by a deliberate tap rather than filled in silently like the
   descriptive answers around it. */
.new-build-confirm {
  margin: -8px 0 22px;
  padding: 14px;
  background: var(--colour-amber-soft);
  border: 2px solid var(--colour-amber);
  border-radius: var(--radius-medium);
}

.new-build-confirm-line {
  margin: 0;
  font-size: 15px;
  font-weight: 600;
  color: var(--colour-navy);
}

.new-build-confirm .action-button {
  background: var(--colour-surface);
}

/* ---------- Floating "+ Note" button ----------
   Spot a fault anywhere in the flow, capture it there and then without losing
   your place. Sits above the footer, clear of the thumb's Next/Back reach. */
.floating-observation {
  position: fixed;
  right: 16px;
  bottom: calc(72px + env(safe-area-inset-bottom));
  display: inline-flex;
  align-items: center;
  gap: 8px;
  min-height: 48px;
  padding: 0 18px;
  font-size: 16px;
  font-weight: 700;
  font-family: inherit;
  color: #fff;
  background: var(--colour-danger);
  border: 0;
  border-radius: var(--radius-pill);
  box-shadow: 0 4px 14px rgba(192, 57, 43, 0.4);
  cursor: pointer;
  z-index: 15;
}

.floating-observation svg { flex: 0 0 auto; }

.floating-observation:active { background: #a5301f; }

/* ---------- Home-screen install tip (page 1, hidden once installed) ---------- */
.install-tip {
  padding: 14px 16px;
  margin-bottom: 16px;
  font-size: 14px;
  line-height: 1.5;
  color: var(--colour-navy);
  background: var(--colour-amber-soft);
  border: 2px solid var(--colour-amber);
  border-radius: var(--radius-medium);
}

/* ---------- Field help accordion ("How do I work this out?") ---------- */
.field-help { margin-top: 10px; }

/* THE QUESTION AND ITS "?" SHARE ONE LINE (2026-09-06, with the EIC helper
   sweep). Every field now has a note, and a note on its own row cost 50px on
   every field - enough to push single-tap pages into scrolling. Beside the
   label it costs nothing. The negative margin keeps the tap area a full 44px
   tall without the row growing. */
.field-label-row {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px;
  margin-bottom: 8px;
}

.field-label-row .field-label { margin-bottom: 0; }

.field-label-row .field-help-toggle {
  flex: 0 0 auto;
  min-height: 0;
  padding: 10px 0;
  margin: -10px 0;
}

.field-help-toggle {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  min-height: 40px;
  padding: 6px 0;
  font-size: 14px;
  font-weight: 600;
  font-family: inherit;
  color: var(--colour-navy);
  background: none;
  border: 0;
  cursor: pointer;
}

.field-help-toggle::before {
  content: "?";
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 20px;
  height: 20px;
  font-size: 13px;
  font-weight: 700;
  color: #fff;
  background: var(--colour-amber);
  border-radius: 50%;
}

.field-help-toggle.is-open { color: var(--colour-amber); }

/* Opened from the label row, the explanation sits between the question and the
   answer - where the eye already is - and pushes the answer down only while it
   is open. */
.field-label-row + .field-help-body { margin: 0 0 12px; }

.field-help-body {
  margin-top: 6px;
  padding: 12px 14px;
  font-size: 14px;
  line-height: 1.5;
  color: var(--colour-text-soft);
  background: var(--colour-amber-soft);
  border-radius: var(--radius-medium);
}

.field-help-body p { margin: 0 0 8px; }
.field-help-body p:last-child { margin-bottom: 0; }
.field-help-body strong { color: var(--colour-navy); }

/* ---------- Update banner (appears after a new version deploys) ---------- */
.update-banner {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  z-index: 30;
  min-height: 44px;
  padding: calc(8px + env(safe-area-inset-top)) 14px 8px;
  font-size: 15px;
  font-weight: 700;
  font-family: inherit;
  color: var(--colour-navy);
  background: var(--colour-amber);
  border: 0;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.2);
  cursor: pointer;
}

.update-banner[hidden] { display: none; }

/* ---------- Photo lightbox (tap a thumbnail to see it big, pinch to zoom) ---------- */
.photo-lightbox {
  position: fixed;
  inset: 0;
  z-index: 40;
  background: rgba(0, 0, 0, 0.92);
  display: flex;
  align-items: center;
  justify-content: center;
  touch-action: none;
  overflow: hidden;
}

.photo-lightbox img {
  max-width: 100%;
  max-height: 100%;
  transform-origin: center center;
  user-select: none;
  -webkit-user-drag: none;
}

.photo-lightbox-close {
  position: absolute;
  top: calc(10px + env(safe-area-inset-top));
  right: 14px;
  width: 44px;
  height: 44px;
  border-radius: 50%;
  border: 0;
  font-size: 22px;
  font-weight: 700;
  font-family: inherit;
  color: var(--colour-navy);
  background: var(--colour-amber);
  cursor: pointer;
}

/* ---------- Board photo reader (proposal review panel on the Boards page) ---------- */
.board-ocr-panel {
  border: 1px solid var(--colour-amber);
  border-radius: 10px;
  padding: 14px;
  margin: 0 0 18px;
  background: rgba(244, 163, 0, 0.06);
}

.board-ocr-row { margin-bottom: 12px; }

.ocr-confidence {
  display: inline-block;
  margin-left: 8px;
  padding: 1px 8px;
  border-radius: 999px;
  font-size: 11px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.04em;
}

.ocr-confidence.is-high { background: rgba(31, 164, 90, 0.18); color: #1FA45A; }
.ocr-confidence.is-medium { background: rgba(244, 163, 0, 0.2); color: #B47500; }
.ocr-confidence.is-low { background: rgba(226, 85, 85, 0.16); color: #E25555; }
.ocr-confidence.is-unknown { background: rgba(226, 85, 85, 0.16); color: #E25555; }

/* ---------- PDF field copy (print-styled report view; Save as PDF in the print dialog) ---------- */
.print-report { display: none; }

@media print {
  body > *:not(.print-report) { display: none !important; }
  body { background: #ffffff; }
  .print-report {
    display: block;
    color: #111111;
    background: #ffffff;
    font-family: Georgia, 'Times New Roman', serif;
    font-size: 11pt;
    line-height: 1.4;
    padding: 0;
  }
  .print-report h1 { font-size: 17pt; margin: 0 0 6pt; }
  .print-report h2 {
    font-size: 12pt; margin: 14pt 0 4pt;
    border-bottom: 1.5pt solid #111111; padding-bottom: 2pt;
  }
  .print-report .print-field-copy-note {
    border: 1pt solid #111111; padding: 6pt 8pt; font-size: 9pt; margin: 0 0 8pt;
  }
  .print-report .print-assessment { font-size: 13pt; margin: 0 0 6pt; }
  .print-report table { width: 100%; border-collapse: collapse; page-break-inside: auto; }
  .print-report tr { page-break-inside: avoid; }
  .print-report td, .print-report th {
    border: 0.5pt solid #555555; padding: 2pt 5pt; text-align: left;
    font-size: 9pt; vertical-align: top;
  }
  .print-report .print-pairs td:first-child { width: 45%; color: #333333; }
  .print-report th { background: #eeeeee; font-weight: 700; }
  .print-report .print-code { font-weight: 700; white-space: nowrap; }
}

/* ---------- The in-app AI assistant chat ---------- */

.assistant-chat-overlay {
  position: fixed;
  inset: 0;
  z-index: 50;
  display: flex;
  flex-direction: column;
  background: var(--colour-background);
  padding-top: env(safe-area-inset-top);
  padding-bottom: env(safe-area-inset-bottom);
}

.assistant-chat-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 14px 16px;
  background: var(--colour-navy);
  color: #FFFFFF;
  font-weight: 700;
}

.assistant-chat-close {
  width: 44px;
  height: 44px;
  border: 0;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.15);
  color: #FFFFFF;
  font-size: 20px;
  font-weight: 700;
  font-family: inherit;
}

.assistant-chat-messages {
  flex: 1;
  overflow-y: auto;
  padding: 14px;
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.assistant-chat-bubble {
  max-width: 88%;
  padding: 10px 14px;
  border-radius: var(--radius-medium);
  font-size: 16px;
  line-height: 1.45;
  white-space: pre-wrap;
  word-break: break-word;
}

.assistant-chat-bubble.is-user {
  align-self: flex-end;
  background: var(--colour-navy);
  color: #FFFFFF;
}

.assistant-chat-bubble.is-assistant {
  align-self: flex-start;
  background: var(--colour-surface);
  border: 1px solid var(--colour-border);
}

.assistant-chat-bubble.is-app {
  align-self: center;
  background: var(--colour-amber-soft);
  border: 1px solid var(--colour-amber);
  color: var(--colour-text-soft);
  font-size: 14px;
}

.assistant-chat-bubble.is-thinking { color: var(--colour-text-faint); font-style: italic; }

.assistant-chat-photo-note { color: var(--colour-text-faint); font-size: 13px; }

.assistant-chat-input-row {
  display: flex;
  gap: 8px;
  align-items: flex-end;
  padding: 10px 12px;
  border-top: 1px solid var(--colour-border);
  background: var(--colour-surface);
}

.assistant-chat-photo-button {
  min-height: var(--tap-target-minimum);
  padding: 0 14px;
  border: 1px solid var(--colour-border);
  border-radius: var(--radius-medium);
  background: var(--colour-surface);
  font-family: inherit;
  font-size: 15px;
}

.assistant-chat-input {
  flex: 1;
  min-height: var(--tap-target-minimum);
  max-height: 120px;
  padding: 14px;
  border: 1px solid var(--colour-border);
  border-radius: var(--radius-medium);
  font-family: inherit;
  font-size: 16px;
  resize: none;
}

.assistant-chat-send {
  min-height: var(--tap-target-minimum);
  padding: 0 20px;
  border: 0;
  border-radius: var(--radius-medium);
  background: var(--colour-amber);
  color: var(--colour-navy-deep);
  font-family: inherit;
  font-size: 16px;
  font-weight: 700;
}

.assistant-chat-telegram-fallback {
  border: 0;
  background: none;
  color: var(--colour-text-faint);
  font-family: inherit;
  font-size: 13px;
  text-decoration: underline;
  padding: 8px 0 12px;
}

/* Rewire survey capture (2026-08-16) */
.counter-row { display: flex; align-items: center; gap: 10px; margin: 6px 0; }
.counter-row span:first-child { flex: 1; }
.counter-button { width: 44px; height: 40px; font-size: 20px; border-radius: 10px;
  border: 1px solid var(--line, #ccc); background: var(--card, #fff); }
.counter-value { min-width: 28px; text-align: center; font-weight: 700; }
.field-row { display: flex; gap: 8px; }
.field-row input { flex: 1; }

/* ---------- The locked saved-clients option (free tenants, 2026-09-05) ----------
   A quiet advert, never a toll gate. It sits UNDER the address road, it is
   dimmer than a real choice, and tapping it only opens one calm sentence. */
.locked-option {
  display: flex;
  align-items: center;
  gap: 10px;
  width: 100%;
  min-height: var(--tap-target-minimum);
  margin-top: 22px;
  padding: 12px 14px;
  text-align: left;
  font-family: inherit;
  background: var(--colour-surface);
  border: 2px dashed var(--colour-border);
  border-radius: var(--radius-medium);
  cursor: pointer;
}

.locked-option-name {
  flex: 1;
  font-size: 16px;
  font-weight: 600;
  color: var(--colour-text-faint);
}

.locked-option-chip {
  flex: 0 0 auto;
  padding: 4px 10px;
  font-size: 12px;
  font-weight: 700;
  color: var(--colour-navy);
  background: var(--colour-amber-soft);
  border: 1px solid var(--colour-amber);
  border-radius: var(--radius-pill);
}

/* ---------- Signatory invites (2026-09-05) ---------- */
.invite-card {
  padding: 12px 14px;
  margin-bottom: 10px;
  background: var(--colour-surface);
  border: 2px solid var(--colour-border);
  border-radius: var(--radius-medium);
}

.invite-card.is-signed { border-color: var(--colour-green); }
.invite-card.is-revoked { opacity: 0.6; }

.invite-card-name { font-size: 16px; font-weight: 600; }
.invite-card-status { font-size: 14px; color: var(--colour-text-soft); margin-top: 2px; }

.invite-form {
  padding: 14px;
  margin-top: 12px;
  background: var(--colour-surface);
  border: 2px solid var(--colour-border);
  border-radius: var(--radius-medium);
}

.awaiting-signature-banner {
  padding: 14px 16px;
  margin-bottom: 10px;
  font-size: 17px;
  font-weight: 700;
  color: var(--colour-navy);
  background: var(--colour-amber-soft);
  border: 2px solid var(--colour-amber);
  border-radius: var(--radius-medium);
}

/* Test Vision: the camera on a test-reading box (2026-09-05). Small and
   quiet, sitting under the box it fills, so it never competes with the
   keyboard - typing the reading in is still the main way. */
.test-vision {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px;
  margin-top: 6px;
}

.test-vision-button {
  flex: 0 0 auto;
  padding: 7px 14px;
  font-size: 14px;
  font-weight: 700;
  color: var(--colour-text-soft);
  background: var(--colour-surface);
  border: 1px solid var(--colour-border);
  border-radius: var(--radius-medium);
  cursor: pointer;
}

.test-vision-button:disabled {
  color: var(--colour-text-faint);
  cursor: progress;
}

.test-vision-status {
  flex: 1 1 100%;
  font-size: 14px;
  color: var(--colour-text-soft);
}

/* A query is the reader refusing to fill the box - it has to be readable at
   arm's length at a board, so it gets the amber treatment. */
.test-vision-status.is-query {
  padding: 8px 10px;
  font-weight: 700;
  color: var(--colour-navy);
  background: var(--colour-amber-soft);
  border: 1px solid var(--colour-amber);
  border-radius: var(--radius-medium);
}

.test-vision-marker {
  flex: 1 1 100%;
  font-size: 13px;
  font-weight: 700;
  color: var(--colour-green);
}

/* Photo Answer: the camera on one of the board reader's questions
   (2026-09-05). Same quiet shape as Test Vision - typing the answer in is
   still the main way - but the answer arrives as a suggestion panel, because
   an answer in words is not a number that can just drop into a box. */
/* THE GROUP CAMERA, above the reader's question list. It is the primary
   action there, so it reads as one - the per-question Photo buttons stay
   quiet underneath. */
.multi-question-photo {
  margin-bottom: 12px;
  padding: 12px;
  background: var(--colour-surface);
  border: 2px solid var(--colour-amber);
  border-radius: var(--radius-medium);
}

.multi-question-photo-button {
  padding: 10px 16px;
  font-size: 16px;
  font-weight: 700;
  color: var(--colour-navy);
  background: var(--colour-amber-soft);
  border: 1px solid var(--colour-amber);
  border-radius: var(--radius-medium);
  cursor: pointer;
}

.multi-question-photo-button:disabled {
  color: var(--colour-text-faint);
  cursor: progress;
}

.multi-question-photo-hint {
  margin-top: 6px;
  font-size: 13px;
  color: var(--colour-text-soft);
}

.multi-question-photo-status {
  margin-top: 8px;
  font-size: 14px;
  color: var(--colour-text-soft);
}

.multi-question-photo-status.is-done {
  font-weight: 700;
  color: var(--colour-green);
}

/* The reader coming back empty-handed has to be readable at arm's length at a
   board, so it gets the amber treatment the single camera's query line gets. */
.multi-question-photo-status.is-query {
  padding: 8px 10px;
  font-weight: 700;
  color: var(--colour-navy);
  background: var(--colour-amber-soft);
  border: 1px solid var(--colour-amber);
  border-radius: var(--radius-medium);
}

.question-photo {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px;
  margin-top: 6px;
}

.question-photo-button {
  flex: 0 0 auto;
  padding: 7px 14px;
  font-size: 14px;
  font-weight: 700;
  color: var(--colour-text-soft);
  background: var(--colour-surface);
  border: 1px solid var(--colour-border);
  border-radius: var(--radius-medium);
  cursor: pointer;
}

.question-photo-button:disabled {
  color: var(--colour-text-faint);
  cursor: progress;
}

.question-photo-hint {
  font-size: 13px;
  color: var(--colour-text-faint);
}

.question-photo-status {
  flex: 1 1 100%;
  font-size: 14px;
  color: var(--colour-text-soft);
}

/* The reader refusing to answer has to be readable at arm's length at a
   board, so it gets the amber treatment. */
.question-photo-status.is-query {
  padding: 8px 10px;
  font-weight: 700;
  color: var(--colour-navy);
  background: var(--colour-amber-soft);
  border: 1px solid var(--colour-amber);
  border-radius: var(--radius-medium);
}

.question-photo-suggestion-holder { flex: 1 1 100%; }

.question-photo-suggestion {
  padding: 12px;
  background: var(--colour-surface);
  border: 2px solid var(--colour-amber);
  border-radius: var(--radius-medium);
}

.question-photo-suggestion-heading {
  margin-bottom: 6px;
  font-size: 14px;
  font-weight: 700;
  color: var(--colour-navy);
}

.question-photo-suggestion-text {
  width: 100%;
  margin-bottom: 8px;
}

.question-photo-evidence {
  margin-bottom: 6px;
  font-size: 13px;
  color: var(--colour-text-soft);
}

.question-photo-evidence.is-low-confidence {
  font-weight: 700;
  color: var(--colour-navy);
}

.question-photo-marker {
  flex: 1 1 100%;
  font-size: 13px;
  font-weight: 700;
  color: var(--colour-green);
}

/* The board reader's tap-to-confirm rows (board type, enclosure). Same buttons
   as a normal choice list - the read comes back pre-selected and one tap
   changes it. Added 2026-09-06 after a high-confidence wrong board type put
   BS EN 60898 on every circuit of an all-RCBO board. */
.choice-row {
  display: flex;
  flex-direction: column;
  gap: 10px;
  margin-bottom: 4px;
}

/* Confirm-or-edit summary: the pages that re-ask for a client already captured
   on page 2 show what is stored instead of drawing empty boxes again. */
.confirm-summary {
  margin: 0 0 14px;
  padding: 14px 16px;
  border: 1px solid var(--colour-border);
  border-radius: var(--radius-medium);
  background: var(--colour-surface);
}

.confirm-summary dt {
  font-size: 14px;
  color: var(--colour-text-soft);
  margin-top: 10px;
}

.confirm-summary dt:first-child { margin-top: 0; }

/* The one line that answers "is this right?" before the rows are read at all
   (Pete 2026-09-06: three screens of confirming right answers is slower than
   one). It sits above the summary, big enough to be the thing the eye lands on. */
.confirm-summary-headline {
  margin: 0 0 12px;
  font-size: 18px;
  font-weight: 700;
  line-height: 1.35;
  color: var(--colour-navy);
}

.confirm-summary dd {
  margin: 2px 0 0;
  font-size: 17px;
  white-space: pre-wrap;
}

/* The new-build "mark all" button after it has been tapped: green, disabled,
   reading as done (Pete 2026-09-06 - the tap must answer back). */
.action-button.new-build-confirm-done {
  background: var(--colour-green);
  border-color: var(--colour-green);
  color: #ffffff;
  opacity: 1;
}

/* SUPPLY VISION (2026-09-06). Two things arrive as offers rather than answers:
   the second reading on a tester screen, and every fact read off a meter
   cupboard photo. Both use the amber "this is a suggestion" treatment the
   photo answer panel already established, so nothing on a page ever looks
   like a typed answer until it has been tapped. */

.test-vision-partner-offer {
  flex: 1 1 100%;
  margin-top: 8px;
  padding: 12px;
  background: var(--colour-amber-soft);
  border: 2px solid var(--colour-amber);
  border-radius: var(--radius-medium);
}

.test-vision-partner-offer-heading {
  margin-bottom: 4px;
  font-size: 16px;
  font-weight: 700;
  color: var(--colour-navy);
}

.test-vision-partner-offer-detail {
  margin-bottom: 10px;
  font-size: 13px;
  color: var(--colour-text-soft);
}

.test-vision-partner-offer-decline,
.reading-suggestion-decline {
  display: block;
  margin-top: 8px;
  padding: 8px 14px;
  font-size: 14px;
  color: var(--colour-text-soft);
  background: none;
  border: 1px solid var(--colour-border);
  border-radius: var(--radius-medium);
  cursor: pointer;
}

/* The second photo, under the board photo on the same page. Ruled off so it
   reads as a separate ask, not as more of the board instructions. */
.meter-cupboard-capture {
  margin-top: 20px;
  padding-top: 16px;
  border-top: 1px solid var(--colour-border);
}

.meter-cupboard-capture-heading {
  margin: 0 0 6px;
  font-size: 19px;
  color: var(--colour-navy);
}

.picker-message.meter-cupboard-read {
  background: #e8f6ee;
  border: 1px solid #2e9e5b;
  color: #17603a;
}

.meter-cupboard-read-line {
  margin-top: 4px;
  font-size: 14px;
}

.meter-cupboard-read-line.is-question {
  margin-top: 10px;
  font-weight: 700;
}

/* ONE PANEL FOR EVERY PHOTO READER (2026-09-06). The meter cupboard fills the
   supply pages and the fuseboard photo fills the main switch page. Both are
   suggestions, both take the same two taps, so both wear the same amber panel -
   a third reader is a class name, not another block of styles. */
.reading-suggestion {
  margin-top: 8px;
  padding: 12px;
  background: var(--colour-amber-soft);
  border: 2px solid var(--colour-amber);
  border-radius: var(--radius-medium);
}

.reading-suggestion-heading {
  margin-bottom: 4px;
  font-size: 16px;
  font-weight: 700;
  color: var(--colour-navy);
}

.reading-suggestion-detail {
  margin-bottom: 10px;
  font-size: 13px;
  color: var(--colour-text-soft);
}

/* Side by side, because stacked they cost a whole thumb target of height and
   pushed two pages past the screen the moment a photo offered an answer
   (flow-wide canary walk, 2026-09-06). Each one is still 165px wide at 375px. */
.reading-suggestion-actions {
  display: flex;
  gap: 8px;
}

.reading-suggestion-actions .action-button,
.reading-suggestion-actions .reading-suggestion-decline {
  flex: 1 1 0;
  margin-top: 0;
}

/* An accepted photo value never looks like a typed one. */
.reading-marker {
  margin-top: 6px;
  font-size: 13px;
  font-weight: 700;
  color: var(--colour-green);
}

/* ---------------------------------------------------------- the photo set */

/* Four photographs, asked one at a time. The strip is the whole answer to
   "how far through this am I" without a word of reading. */
.photo-set-strip {
  display: flex;
  gap: 8px;
  margin: 4px 0 16px;
}

/* EVERY CHIP IS A BUTTON (Pete 2026-09-09) - tap one and that ask comes back
   on screen to be taken or retaken. 54px of picture plus its label clears the
   44px target on its own; min-height states it so a shorter label can never
   shrink it below a thumb. */
.photo-set-chip {
  flex: 1 1 0;
  min-width: 0;
  min-height: 44px;
  text-align: center;
  padding: 0;
  border: 0;
  background: none;
  font: inherit;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}

.photo-set-chip:focus-visible .photo-set-chip-frame {
  outline: 3px solid var(--colour-amber);
  outline-offset: 2px;
}

.photo-set-chip-frame {
  position: relative;
  width: 100%;
  height: 54px;
  display: flex;
  align-items: center;
  justify-content: center;
  border: 2px solid var(--colour-border);
  border-radius: var(--radius-small);
  background: #F4F6F9;
  overflow: hidden;
}

.photo-set-chip-frame img { width: 100%; height: 100%; object-fit: cover; display: block; }

.photo-set-chip-number { font-size: 18px; font-weight: 700; color: #A9B3C1; }

/* The amber ring says "this is the one on screen". */
.photo-set-chip.is-current .photo-set-chip-frame {
  border-color: var(--colour-amber);
  box-shadow: 0 0 0 2px rgba(244, 163, 0, 0.35);
}

.photo-set-chip.is-done .photo-set-chip-frame { border-color: var(--colour-green); }

.photo-set-chip.is-skipped .photo-set-chip-frame,
.photo-set-chip.is-not-applicable .photo-set-chip-frame { opacity: 0.45; }

/* The green tick that says this one has been READ, not merely photographed. */
.photo-set-chip-tick {
  position: absolute;
  right: 2px;
  bottom: 2px;
  width: 20px;
  height: 20px;
  line-height: 20px;
  border-radius: 50%;
  background: var(--colour-green);
  color: #fff;
  font-size: 13px;
  font-weight: 700;
}

.photo-set-chip-label {
  margin-top: 4px;
  font-size: 12px;
  font-weight: 700;
  color: var(--colour-navy);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.photo-set-chip-status { font-size: 11px; color: var(--colour-text-soft); }

/* All four settled. Said directly under the strip, because the strip is what
   he taps next. */
.photo-set-all-done {
  margin: 0 0 8px;
  font-weight: 700;
  color: var(--colour-navy);
}

.photo-set-ask-counter {
  font-size: 13px;
  font-weight: 700;
  color: var(--colour-text-soft);
}

.photo-set-ask-heading {
  margin: 2px 0 6px;
  font-size: 19px;
  color: var(--colour-navy);
}

/* AN ASK WITH A PHOTO ON IT IS A DIFFERENT SCREEN. It carries a picture, a
   status and a retake button that an untaken one does not, and page 3's rule
   is that an ask fits a phone without scrolling. So the preview shrinks to a
   thumbnail and the two buttons sit BESIDE it - the picture and "retake it"
   read as one thing, and 740px of 609px becomes 563px. */
.photo-set-ask.has-a-photo .photo-set-preview {
  float: left;
  max-height: 96px;
  margin: 8px 12px 8px 0;
}

.photo-set-ask.has-a-photo::after {
  content: '';
  display: block;
  clear: both;
}

.photo-set-preview {
  display: block;
  max-width: 100%;
  max-height: 150px;
  border-radius: 10px;
  margin: 8px 0;
  object-fit: contain;
}

/* Retaking is the quiet option under a loud success banner. */
.photo-set-retake {
  display: block;
  margin-top: 6px;
  padding: 8px 14px;
  font-size: 14px;
  font-family: inherit;
  color: var(--colour-text-soft);
  background: none;
  border: 1px solid var(--colour-border);
  border-radius: 9px;
  cursor: pointer;
}

.photo-set-skip {
  display: block;
  margin-top: 14px;
  padding: 8px 14px;
  font-size: 14px;
  font-family: inherit;
  color: var(--colour-text-soft);
  background: none;
  border: 1px solid var(--colour-border);
  border-radius: 9px;
  cursor: pointer;
}

/* "Not applicable - nothing to bond here". It is a real answer, not a skip, so
   it is a real button - just never louder than taking the photograph. */
.photo-set-not-applicable {
  display: block;
  width: 100%;
  margin-top: 10px;
  padding: 12px 14px;
  font-size: 15px;
  font-weight: 700;
  font-family: inherit;
  color: var(--colour-navy);
  background: #fff;
  border: 2px solid var(--colour-navy);
  border-radius: var(--radius-medium);
  cursor: pointer;
}

.photo-set-finished {
  padding: 12px;
  background: #e8f6ee;
  border: 1px solid #2e9e5b;
  border-radius: var(--radius-medium);
  color: #17603a;
}

.photo-set-finished-heading { font-weight: 700; margin-bottom: 8px; }

.photo-set-finished-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  padding: 4px 0;
}

.photo-set-finished-line { font-size: 14px; }

.photo-set-finished-again {
  flex: 0 0 auto;
  padding: 6px 10px;
  font-size: 13px;
  font-family: inherit;
  color: #17603a;
  background: #fff;
  border: 1px solid #2e9e5b;
  border-radius: 9px;
  cursor: pointer;
}

/* The bonding tap is the electrician's own answer, so its line is navy - the
   green markers mean "a photo read this". */
.reading-marker.photo-set-not-applicable-marker { color: var(--colour-navy); }

/* ------------------------------------------------------- the board walk
   (Pete on site at BWJ Homes, 2026-09-11): one device per screen, a small
   strip of the devices so far, and the confirm screen's boxes. */
.board-walk-counter {
  font-size: 13px;
  font-weight: 700;
  color: var(--colour-amber);
  margin-top: 2px;
}

.board-walk-heading {
  margin: 0 0 4px;
  font-size: 18px;
  color: var(--colour-navy);
}

.board-walk-order {
  margin: 0 0 8px;
}

.board-walk-choices {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin-top: 8px;
}

.board-walk-choices .action-button {
  width: auto;
  flex: 1 1 45%;
}

.board-walk-strip {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin-top: 10px;
}

.board-walk-chip {
  width: 52px;
  text-align: center;
}

.board-walk-chip .photo-set-chip-frame {
  width: 52px;
  height: 52px;
}

.board-walk-chip.is-blank .photo-set-chip-frame { opacity: 0.45; }

.board-walk-chip .photo-set-chip-label {
  font-size: 10px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.board-walk-field .field-label .ocr-confidence { margin-left: 6px; }

.board-walk-evidence { margin-bottom: 8px; }

.board-walk-conflict-note {
  margin: 4px 0;
  color: var(--colour-amber);
}

/* ROUND TWO (2026-09-11 evening) gave the walk the app's own live camera
   with the white guide box; THE FULL-SCREEN CAMERA (2026-09-12, Pete on
   site: the 180px strip was "oddly placed within the certificate page" and
   its landscape box the wrong shape for a breaker) moves it into an overlay
   that fills the viewport. The page under it is untouched and comes back
   as it was when the overlay closes. */
.has-board-walk-camera { overflow: hidden; }

.board-walk-overlay {
  position: fixed;
  inset: 0;
  height: 100vh;
  height: 100dvh;
  z-index: 100;
  display: flex;
  flex-direction: column;
  background: #000;
  color: #fff;
}

/* The viewfinder takes every pixel the panel does not need. */
.board-walk-overlay-viewfinder {
  position: relative;
  flex: 1 1 auto;
  min-height: 0;
  overflow: hidden;
  background: #111;
}

.board-walk-camera-video {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

/* THE PORTRAIT GUIDE BOX: WALK_GUIDE_BOX_WIDTH_FRACTION by
   WALK_GUIDE_BOX_HEIGHT_FRACTION of the viewfinder, set inline by the app.
   A guide, not a crop. */
.board-walk-camera-guide {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  border: 3px solid #fff;
  border-radius: 12px;
  box-shadow: 0 0 0 9999px rgba(0, 0, 0, 0.28);
  pointer-events: none;
}

.board-walk-camera-copy {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  margin: 0;
  padding: 6px 10px;
  font-size: 12px;
  line-height: 1.3;
  color: #fff;
  background: rgba(0, 0, 0, 0.55);
}

.board-walk-camera-fallback {
  position: absolute;
  left: 12px;
  right: 12px;
  top: 50%;
  transform: translateY(-50%);
  margin: 0;
  text-align: center;
  font-size: 15px;
  color: var(--colour-amber);
}

/* The X, top-left, over the viewfinder. Leaves the camera, keeps the walk. */
.board-walk-overlay-close {
  position: absolute;
  top: calc(10px + env(safe-area-inset-top));
  left: 10px;
  width: 44px;
  height: 44px;
  border-radius: 50%;
  border: 0;
  font-size: 20px;
  font-family: inherit;
  color: #fff;
  background: rgba(0, 0, 0, 0.55);
  cursor: pointer;
}

/* The frozen frame with the tick, WALK_SHUTTER_FREEZE_MILLISECONDS long. */
.board-walk-overlay-freeze {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  background: #000;
}

/* display: flex above would beat the hidden attribute; this keeps it hidden. */
.board-walk-overlay-freeze[hidden] { display: none; }

.board-walk-overlay-frozen-frame {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.board-walk-overlay-tick {
  position: relative;
  width: 72px;
  height: 72px;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 40px;
  font-weight: 700;
  color: #fff;
  background: var(--colour-green);
  box-shadow: 0 0 0 6px rgba(255, 255, 255, 0.35);
}

/* THE PANEL under the viewfinder: strip, prompt, That's it, shutter, the
   two small buttons. */
.board-walk-overlay-panel {
  flex: 0 0 auto;
  padding: 6px 12px calc(10px + env(safe-area-inset-bottom));
  background: #111;
}

/* The strip in ONE row, scrollable, newest at the right. */
.board-walk-overlay-strip .board-walk-strip {
  flex-wrap: nowrap;
  overflow-x: auto;
  margin-top: 0;
  padding-bottom: 4px;
  -webkit-overflow-scrolling: touch;
}

.board-walk-overlay-strip .board-walk-chip { flex: 0 0 44px; width: 44px; }
.board-walk-overlay-strip .board-walk-chip .photo-set-chip-frame { width: 44px; height: 44px; }
.board-walk-overlay-strip .board-walk-chip .photo-set-chip-label { color: #fff; }

/* THE ROLLING PROMPT: one line, the counter beside it. */
.board-walk-overlay-prompt-row {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 10px;
  margin: 6px 0 8px;
  font-size: 17px;
  font-weight: 600;
  line-height: 1.3;
}

.board-walk-overlay-counter {
  flex: 0 0 auto;
  font-size: 13px;
  font-weight: 700;
  color: var(--colour-amber);
}

/* "THAT'S IT - EVERY DEVICE PHOTOGRAPHED": full width, above the shutter,
   never behind a scroll. Greyed only until the first device exists. */
.board-walk-overlay-last-one {
  width: 100%;
  min-height: 48px;
  margin: 0 0 8px;
  font-size: 16px;
  font-weight: 700;
  font-family: inherit;
  color: var(--colour-navy);
  background: var(--colour-amber);
  border: 0;
  border-radius: var(--radius-medium);
  cursor: pointer;
}

.board-walk-overlay-last-one:disabled { opacity: 0.45; cursor: default; }

.board-walk-overlay-shutter-row {
  display: flex;
  justify-content: center;
  margin: 0 0 8px;
}

/* THE SHUTTER: one big round button, centred, thumb reach. */
.board-walk-shutter {
  width: 72px;
  height: 72px;
  border-radius: 50%;
  border: 4px solid rgba(255, 255, 255, 0.55);
  background: #fff;
  box-shadow: inset 0 0 0 3px #111;
  font-family: inherit;
  font-size: 0;
  cursor: pointer;
  padding: 0;
}

.board-walk-shutter:disabled { opacity: 0.6; }

/* With no camera the same button is the file picker, with words on it. */
.board-walk-shutter.is-file-picker {
  width: auto;
  min-width: 180px;
  height: 56px;
  padding: 0 20px;
  border-radius: 28px;
  box-shadow: none;
  font-size: 16px;
  font-weight: 700;
  color: var(--colour-navy);
}

.board-walk-overlay-secondary {
  display: flex;
  gap: 8px;
}

.board-walk-overlay-small-button {
  flex: 1 1 50%;
  min-height: 40px;
  padding: 6px 8px;
  font-size: 13px;
  font-family: inherit;
  color: #fff;
  background: transparent;
  border: 1px solid rgba(255, 255, 255, 0.45);
  border-radius: 9px;
  cursor: pointer;
}

.board-walk-overlay-small-button:disabled { opacity: 0.35; cursor: default; }

.board-walk-progress {
  margin: 8px 0 0;
  font-weight: 700;
}

.board-walk-chip.is-failed .photo-set-chip-frame { border-color: var(--colour-amber); }

.board-walk-still-reading { display: flex; align-items: center; gap: 8px; }

.board-walk-spinner {
  width: 16px;
  height: 16px;
  flex: 0 0 16px;
  border: 2px solid rgba(0, 0, 0, 0.15);
  border-top-color: var(--colour-navy);
  border-radius: 50%;
  animation: board-walk-spin 0.9s linear infinite;
}

@keyframes board-walk-spin { to { transform: rotate(360deg); } }

.board-walk-duplicate { margin-bottom: 8px; }

/* ------------------------------------- one question per screen (page 3)
   The question, the photo it came from (tap to enlarge), the evidence, one
   box, three buttons. */
.one-question-screen { margin-top: 8px; }

/* The thumbnail sits BESIDE the question so the screen fits a phone without
   scrolling (measured 741px of 609px with it above); tapping it opens it out
   full width. */
.one-question-photo {
  float: left;
  width: 72px;
  height: 72px;
  border-radius: 10px;
  margin: 2px 10px 4px 0;
  object-fit: cover;
  cursor: pointer;
  border: 1px solid var(--colour-border);
}

.one-question-photo.is-enlarged {
  float: none;
  display: block;
  width: 100%;
  height: auto;
  max-height: 60vh;
  object-fit: contain;
}

.one-question-screen .board-ocr-row::after {
  content: '';
  display: block;
  clear: both;
}

.one-question-screen .field-input { clear: both; }

/* With questions still to answer, the green box makes itself small: the
   questions are what the electrician is here for. */
.photo-set-finished.has-questions .photo-set-all-done {
  font-size: 14px;
  margin: 0;
}

.one-question-evidence { margin: 0 0 6px; }

.one-question-buttons {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin-top: 8px;
}

.one-question-buttons .action-button {
  width: auto;
  flex: 1 1 30%;
}

/* A question off a walk close-up already has its photo; the camera stays
   out of the way entirely. */
.question-photo.has-close-up { min-height: 0; }

/* The device kind on the confirm screen is eight short words, not eight
   full-width rows: a wrapped row of pills keeps the screen to the boxes. */
.board-walk-field .choice-row {
  flex-direction: row;
  flex-wrap: wrap;
  gap: 6px;
}

.board-walk-field .choice-button {
  flex: 0 1 auto;
  padding: 9px 12px;
  font-size: 15px;
  min-height: 40px;
}

/* TWO BOARDS ON ONE CERTIFICATE (2026-09-12): the board tree on the Boards
   page, the "way 3 feeds another board" card, and the sub boards section on
   page 3 with one photo row per sub board. */
.board-tree {
  margin: -6px 0 14px;
  font-size: 15px;
  line-height: 1.5;
}

.board-tree-line.is-fed {
  color: var(--colour-muted, #5b6472);
}

.board-tree-line.is-fed::before {
  content: '\2514 ';
}

.feeds-board-card {
  margin-bottom: 14px;
}

.feeds-board-toggle {
  margin-top: -4px;
}

.sub-boards-section {
  margin-top: 18px;
  padding-top: 12px;
  border-top: 1px solid var(--colour-border);
}

.sub-board-row {
  padding: 10px 0;
  border-bottom: 1px solid var(--colour-border);
}

.sub-board-row.is-open {
  background: var(--colour-surface);
  border-radius: 12px;
  padding: 12px;
  border: 2px solid var(--colour-navy);
}
