/* GENERATED from app.css for the sign-in page only (speed audit item 11). Do not edit by hand:
   regenerate with tools/build_login_css.mjs after changing login styles in app.css. */
:root {
  --brand-strip: #141c26; /* match --navy / .sidebar; Damien via Marketing 2026-09-10 */
  --navy: #141c26;
  --navy-2: #1b2430;
  --ink: #1a1f26;
  --muted: #5c6570;
  --faint: #8a929c;
  --canvas: #ffffff;
  --paper: #ffffff;
  --line: #d7dadd;
  --line-2: #c5c9ce;
  --blue: #0a8cf0;
  --blue-d: #0874c9;
  --blue-s: #e7f4fe;
  --grey: #acaeaf;
  --ok: #2f7d4a;
  --ok-s: #e8f5ec;
  --warn: #b45309;
  --warn-s: #fff6e8;
  --bad: #b42318;
  --bad-s: #fdecea;
  --sidebar-w: 212px;
  --shadow: 0 1px 2px rgba(20,28,38,.05);
  /* Type scale (Heartbeat font cleanup, Oct 2026). Source Sans 3 only, self-hosted, 400/600/700.
     Sizes 11/12/14/16/18/22 only. Roles: page title 22/700 · section header 18/700 · body 14 desk, 16 phone ·
     labels 12/600 · buttons 12/700 desk · captions 11/700 uppercase +0.04em (12px on the phone) ·
     every input, select and textarea 16px on the phone and at phone widths (stops iPhone zoom). */
  --font: "Source Sans 3", -apple-system, "Segoe UI", Roboto, sans-serif;
  --mono: var(--font); /* one family: codes and money use tabular figures, not a second typeface */
  --fs-11: 11px;
  --fs-12: 12px;
  --fs-14: 14px;
  --fs-16: 16px;
  --fs-18: 18px;
  --fs-22: 22px;
  --fs-caption: var(--fs-11);
  --fs-label: var(--fs-12);
  --fs-button: var(--fs-12);
  --fs-body: var(--fs-14);
  --fs-phone-body: var(--fs-16);
  --fs-control: var(--fs-16);
  --fs-section: var(--fs-18);
  --fs-title: var(--fs-22);
  --fw-regular: 400;
  --fw-semibold: 600;
  --fw-bold: 700;
  --ls-caption: .04em;
  --ls-title: -0.02em;
}
@font-face { font-family: "Source Sans 3"; font-style: normal; font-weight: 400; font-display: swap; src: url("fonts/source-sans-3-400.woff2?v=ss3-2026-1") format("woff2"); }
@font-face { font-family: "Source Sans 3"; font-style: normal; font-weight: 600; font-display: swap; src: url("fonts/source-sans-3-600.woff2?v=ss3-2026-1") format("woff2"); }
@font-face { font-family: "Source Sans 3"; font-style: normal; font-weight: 700; font-display: swap; src: url("fonts/source-sans-3-700.woff2?v=ss3-2026-1") format("woff2"); }
@font-face { font-family: "Source Sans 3"; font-style: italic; font-weight: 400; font-display: swap; src: url("fonts/source-sans-3-400-italic.woff2?v=ss3-2026-1") format("woff2"); }
* { box-sizing: border-box; }
html, body { margin: 0; min-height: 100%; }
body {
  font-family: var(--font);
  color: var(--ink);
  background: var(--canvas);
  font-size: var(--fs-14);
  line-height: 1.4;
}
a { color: var(--blue-d); }
button, input { font: inherit; }
img { max-width: 100%; border: 0; }
h1 { margin: 0; font-weight: 700; letter-spacing: -0.02em; }
p { margin: 0; }

/* —— Login (ops card, 360 brand) —— */
.login-page {
  min-height: 100vh;
  min-height: 100dvb;
  position: relative;
  display: grid;
  place-items: center;
  padding: 24px 16px 40px;
  overflow-y: auto;
  background: #0b1016 url("360-bg.webp?v=2026-1") center / cover no-repeat;
  color: var(--ink);
}
.login-page::before {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(155deg, rgba(20,28,38,.82) 0%, rgba(20,28,38,.62) 50%, rgba(20,28,38,.78) 100%);
}
.login-card {
  position: relative;
  width: min(420px, 100%);
  background: #fff;
  color: #111;
  color-scheme: light;
  border: 1px solid rgba(255,255,255,.12);
  box-shadow: 0 16px 40px rgba(0,0,0,.28);
  padding: 28px 24px 22px;
}
.login-card .brand-link { display: inline-block; margin-bottom: 14px; }
.login-card .brand-link img {
  display: block; height: 36px; width: auto;
  filter: none;
}
.login-kicker {
  font-size: var(--fs-12);
  letter-spacing: var(--ls-caption);
  text-transform: uppercase;
  color: var(--blue);
  font-weight: 700;
  margin-bottom: 6px;
}
.login-card h1 {
  font-size: var(--fs-22);
  letter-spacing: -0.02em;
  color: var(--navy);
  line-height: 1.1;
  margin-bottom: 6px;
}
.login-sub { color: var(--muted); font-size: var(--fs-14); margin-bottom: 20px; }
.login-card label {
  display: block; font-size: var(--fs-12); font-weight: 600;
  color: #111; margin: 0 0 6px;
}
.login-card .field { margin-bottom: 12px; }
.login-card input {
  width: 100%;
  background: #fff;
  border: 1px solid var(--grey);
  color: #111;
  -webkit-text-fill-color: #111;
  caret-color: #111;
  padding: 10px 12px;
  border-radius: 2px;
  font-size: var(--fs-16);
  color-scheme: light;
}
.login-card input::placeholder {
  color: #5c6570;
  -webkit-text-fill-color: #5c6570;
}
.login-card input:-webkit-autofill,
.login-card input:-webkit-autofill:hover,
.login-card input:-webkit-autofill:focus {
  -webkit-text-fill-color: #111;
  caret-color: #111;
  box-shadow: 0 0 0 1000px #fff inset;
  transition: background-color 9999s ease-out;
}
.login-card input:focus {
  outline: 2px solid var(--blue);
  outline-offset: 1px;
  border-color: transparent;
}
.login-hint {
  margin: 6px 0 0;
  font-size: var(--fs-12);
  line-height: 1.35;
  color: var(--muted);
  font-weight: 400;
}
.login-error {
  background: var(--bad-s);
  border: 1px solid #f5c2bd;
  color: var(--bad);
  padding: 10px 12px;
  margin-bottom: 12px;
  font-size: var(--fs-14);
}
.login-foot { margin-top: 16px; font-size: var(--fs-12); color: var(--faint); }
.login-card .btn-block { padding: 12px 18px; font-size: var(--fs-16); }
.login-card .login-remember, .login-remember {
  display: flex; align-items: center; gap: 8px;
  margin: 0 0 14px; font-size: var(--fs-14); font-weight: 400; color: #374151;
  cursor: pointer; user-select: none;
}
.login-remember input {
  width: 16px; height: 16px; margin: 0; accent-color: var(--blue);
}

.portal-homebar {
  position: absolute; top: 14px; left: 16px;
  display: flex; align-items: center; gap: 8px;
  z-index: 2;
  color: #fff; font-weight: 700; letter-spacing: .04em; font-size: var(--fs-12);
}
.portal-homebar-in { position: static; color: var(--navy); padding: 14px 20px 0; }
.portal-home-icon { width: 22px; height: 22px; border-radius: 4px; }

.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  border: 0; cursor: pointer; padding: 8px 14px; border-radius: 2px;
  font-weight: 700; text-decoration: none; color: inherit; background: transparent;
  font-size: var(--fs-12);
}
.btn[disabled] { opacity: .55; cursor: not-allowed; }
.btn-primary { background: var(--blue); color: #fff; }
.btn-primary:hover { background: var(--blue-d); }
.btn-ghost { border: 1px solid var(--line-2); background: #fff; color: var(--ink); }
.btn-ghost:hover { border-color: var(--blue); color: var(--blue-d); }
.btn-block { width: 100%; }
.btn-xl { padding: 14px 18px; font-size: var(--fs-16); min-height: 48px; }

/* —— Live-ish shell: dark side / light main —— */
.nav-item:hover { background: rgba(255,255,255,.06); color: #fff; }
.nav-group-sum:hover { background: rgba(255,255,255,.06); color: #fff; }
.signout:hover { border-color: var(--blue); color: var(--blue-d); }
.crumbs a:hover { text-decoration: underline; }
.site-card:hover { background: #f6f8fa; }
.field { margin-bottom: 10px; }
.field label { display: block; font-weight: 600; font-size: var(--fs-12); margin-bottom: 5px; }
.field input[type=text], .field input[type=password], .field input:not([type]) {
  width: 100%; padding: 8px 10px; border: 1px solid var(--line-2); background: #fff;
  color: #111; -webkit-text-fill-color: #111; caret-color: #111; color-scheme: light;
}
.banner.err + .banner.err { margin-top: -8px; }
.banner { padding: 10px 12px; margin-bottom: 12px; font-size: var(--fs-14); }
.banner.ok { background: var(--ok-s); color: var(--ok); }
.banner.warn { background: var(--warn-s); color: var(--warn); }
/* Error banners are amber for everyone (same as the manager banner). Red #BE1E2D stays for missed schedules and Issues only. */
.banner.err { background: #fff6e8; color: #b45309; border: 1px solid #f0d3a8; }
/* Thumbnail gap 20 px. Each × sits inside its own thumbnail (PR #186 F1), so the gap
   is the clearance between one × and the next thumbnail. */
/* Staged photo remove ×: a 44 × 44 px tap target (Apple HIG minimum) inside the
   thumbnail's own top-right corner (top: 0; right: 0). No part of it (no negative
   offset, no pseudo-element; its padding is inside the 44 px box) reaches past its
   own thumbnail, so a tap on
   the next photo, even a touchscreen tap that the browser nudges to the nearest
   control, can never land on this ×. The visible dark circle stays 22 px (24 px on
   the phone app), drawn by the background 4 px in from the corner; the × glyph is
   centred on it by the padding. */
.photo-preview .photo-thumb-x:active { --thumb-x-bg: #000; }
.photo-preview .photo-thumb-x:focus-visible { outline: 2px solid var(--blue, #1f6feb); outline-offset: -2px; }
table.data tbody tr:hover { background: #f7f9fb; }
.activity-close:hover { border-color: var(--blue); color: var(--blue-d); }
.btn-create-pdf {
  margin-left: auto;
  background: #b42318;
  border: 1px solid #b42318;
  color: #fff;
  font-weight: 700;
}
.btn-create-pdf:hover { background: #912018; border-color: #912018; color: #fff; }
.act-setup:hover { text-decoration: underline; }

/* —— chrome: no top bar, Live density, loop UI —— */
.signout-side:hover { color: #fff; border-color: #8ecfff; }
.side-settings:hover {
  color: #fff; border-color: #8ecfff; background: rgba(10,140,240,.18);
}
.lh-menu a:hover { background: #f4f5f7; }
/* Delete in desk ··· menus is attention amber #9a4600; red is kept for Issues and missed schedules. */
.lh-menu a.lh-menu-danger:hover { background: #fff4e5; }
/* Body-attached calendar must not be clipped by wizard/card overflow */
.lh-cal-grid button:hover { background: #e7f4fe; }
/* Client feedback CLOSED: slate/navy neutral — green is reserved for Issues. */
.signout-side:hover { color: #fff; }
.lh-drop-btn:hover, .lh-more-btn:hover { border-color: var(--blue); }
.lh-menu a:hover { background: var(--blue-s); }
.linkish:hover { text-decoration: underline; }

/* —— Settings (Users / Roles / Profile) Live-shaped, sidebar chrome only —— */
.settings-tabs a:hover { color: var(--ink); }
.btn-row { display: flex; gap: 8px; flex-wrap: wrap; }

/* —— Templates builder — one list, Task | Issues. No Audits. —— */
.tpl-pick-opt:hover { background: #f4f8fc; }


/* —— Consumables (mobile-first) —— */
.cons-order-card:hover, .cons-cat-card:hover { border-color: var(--blue); }

/* —— Maps: Live All Activity drawer (CONNECT Real-time feed) —— */
 .feed-clock:hover { border-color: var(--blue); color: var(--blue-d); }
.misses-toggle:focus-within { border-color: var(--blue); }
.feed-close:hover { color: #111; }
.feed-row:hover { background: #f6f8fa; }


/* Maps pin gestures — site activity list + form popup + pin drag */
.activity-row:hover { border-color: #0a8cf0; }

/* E3 short-needle asset pins (Maps hub / Real-time) — colour = Contract */
.map-near-me-apply:hover { background: #dbeafe; }

/* Contract face — map pin colour picker (Assets fold) */
.cf-map-swatch:focus-visible {
  outline: 2px solid #0a8cf0;
  outline-offset: 2px;
}
.fab-btn:hover { filter: brightness(1.05); }


/* Field Reports (Live drill-down) */
.report-card:hover { border-color: var(--blue); }
.tpl-asg-opt:hover { background: #f4f8fc; }
.tpl-asg-x:hover { color: #111; }
/* Assignments: CONNECT select-filter multi-pick chips */

/* —— Cleaner phone PWA (Live-like). Staff sidebar unchanged. —— */
/* Pull-to-refresh owns the overscroll at the top of the page (CoS CLEAR 25
   Sep 2026) — contain it so the browser's own native pull-to-refresh chrome
   (Android Chrome tab) and the iOS rubber-band bounce don't fight our
   affordance. Phone chrome only; desk keeps default overscroll. */
/* NAV-BOTTOM-1: clearance re-tuned for the 58px bar + 67px FAB (peaks ~71px
   above the safe area) — was 160px against the old 80px bar/112px FAB, which
   left page content floating far above the now much shorter bar. */
/* Pull-to-refresh banner (CoS CLEAR 25 Sep 2026) — sits between the sticky
   .m-top header and .m-main. Zero height/hidden text by default; assets/app.js
   grows it (inline height, no transition) 1:1 with the drag so it tracks the
   finger, then snaps to a fixed height while "Updating…" runs. Pushes
   .m-main down via normal flow — no transform/position tricks needed since
   .m-top is already sticky above it. */
@keyframes m-ptr-spin { to { transform: rotate(360deg); } }
.phone-app .m-drawer-nav a:hover { background: rgba(255,255,255,.06); }
/* NAV-BOTTOM-1 (Sep 2026, Damien hard Pass gate): mock aspect is compact and
   crisp — smaller AND sharper than the "live" bar, not just relabelled.
   72px (GTG Part 3 item 3's first pass) was still too tall/soft; cut again
   to 58px, and the 44px icons (oversized/soft against an 11px label) down
   to a proportionate 24px so icon+label fill the bar snugly with no dead
   space above/below. Centre grid column trimmed from the old 112px FAB's
   footprint to 68px to match the FAB-1 67px circle — tabs sit close to the
   FAB instead of spread wide either side of a gap sized for the old FAB.
   One shared rule/markup (field_mobile_layout_end() in lib/mobile.php), so
   every Field phone screen with the tabbar gets the exact same aspect —
   there is no per-screen override (including Site access, which now uses
   this bar instead of its own .keys-pwa-tabbar) to drift out of sync. */
/* Bug FAB-1 (Sep 2026): shrunk to ~60% (112px → 67px) so the circle's
   bottom edge lines up with the bottom of the Order/History/Feedback/Scan
   label text instead of covering it (and the page helper text above it).
   bottom re-tuned to 4px for the NAV-BOTTOM-1 58px bar cut above —
   re-measured with getBoundingClientRect() against the new label position
   each time this tabbar height changes. The FAB still peeks above the top
   edge of the (now shorter) bar, matching the mock's floating-FAB look,
   without ever reaching high enough to sit over the labels. Single shared
   .m-fab, so every Field phone screen with the tabbar picks this up. */
/* Task / Audit / Issue site picker: parent asset on top of its children, blue card. */
/* Bug H1 — Field History desk glyph parity (Sep 2026). Scoped to .m-fh-list
   (Field History only) — .m-card-kicker/.m-card h3/.m-card-meta above are
   shared with Consumables, Communication and Work Orders lists (out of
   scope for this bug). Icon + kicker colour keyed off .m-card--{kind},
   mirroring desk .feed-row.{closed|issue|missed} .feed-ico (assets/app.js
   svgIco / assets/app.css .feed-row rules).
   Bug H1b — Field History type scale +25% (Sep 2026), still .m-fh-list only.
   kicker 14→17.5px, title 16→20px, site+meta 13→16.25px; glyph column scaled
   the same +25% (feed-ico 22→27.5px, issue "!" triangle 28/22→35/27.5px) so
   icons stay balanced with the bigger text. Wrap, don't clip: none of these
   rules add white-space:nowrap/text-overflow, so long titles/meta wrap and
   rows grow. */
/* Activity type colours (LOCKED — Damien GTG Part 3, item 6, 25 Sep 2026).
   Shift started/finished now get distinct colours (previously both slate,
   provisional); Client feedback/Order share this same .m-card--{kind} map
   on the Heartbeat landing cards (lib/communication.php, .m-comm-landing
   rules below) — keep every surface reading this map in sync if it changes.
   Red #BE1E2D / green stay reserved for missed schedules + Issues (above) —
   never repurposed onto these four product types.
   Gold text rule (CoS 7 Oct 2026): gold TEXT at any size is #8A6500 (5.33:1 on white);
   the locked gold #C9920A (2.76:1) stays on non-text only: dots, rings, icons, borders,
   chip backgrounds. So Shift started keeps #C9920A on its play-triangle icon and the
   "Shift started" words use #8A6500. */
/* Consumables C3 — Field History order events use locked Field blue #4AA3FF. */
/* Item 5 (Sep 2026): NFC trigger is a small icon-only circle now — no
   "SCAN NFC" label, no full-width bar, no unavailable-browser explainer
   paragraph (that whole element is gone; app.js just hides this icon on a
   browser with no Web NFC — see showNfcUnavailable()). Now that the tabbar
   FAB (Bug FAB-1) sits inside the tabbar itself, this no longer needs the
   old FAB-clearance margin either. */

/* Direct-employee Start Shift landing + payroll */
.shift-go-btn:not(:disabled):active { transform: scale(.98); }

/* End Shift overtime step */

/* iPhone: never a persistent left rail. Hamburger only. [hidden] must beat display:flex. */

/* Phone Order tab: Consumables Order — hide office chrome, show product icons */

/* —— Public Communication /tell —— */
.tell-site:hover { border-color: var(--blue); background: var(--blue-s); }

.tell-star:hover span { background: var(--blue); color: #fff; border-color: var(--blue); }

/* Phone landing after Start Shift: raised Communication forms */
/* ORD-2 (Damien via Bug Bot, 25 Sep 2026): Order-tab / home open-order cards
   get a teal box glyph (same C3 consumables family, field_consumable_history_ico)
   and match the H1b History type scale exactly — kicker 17.5px, title 20px,
   site/meta 16.25px, icon 27.5px — so an open order "feels the same weight"
   as a History card, without touching the shift play/stop glyph or slate. */
/* Landing cards (Damien GTG Part 3, item 2, 25 Sep 2026): CLIENT FEEDBACK /
   ORDER cards get a type icon + the same .m-fh-list (Field History) type
   scale — kicker 17.5px, title 20px, site+meta 16.25px — scoped to
   .m-comm-landing only, not the shared .m-fh-list class (that stays History-
   only per Bug H1/H1b above) and not the general .m-card/.m-hist used by the
   Consumables catalogue or the desk Communication list. Icons reuse the
   existing bottom-nav glyphs (field_m_ico('messages'|'order'), 20 viewBox /
   1.7 stroke) for weight parity with the Order/Feedback tab icons — not the
   heavier 24-viewbox/2-stroke .feed-ico family. Colours are the locked
   activity-type map (see .m-fh-list rules above): feedback navy #141c26,
   order Field blue #4AA3FF. */

/* Communication media drop zone — camera roll, photos and/or video */
.media-drop-input:focus + .media-drop-zone { outline: 2px solid #0a8cf0; outline-offset: 2px; }
table.data tr.is-click:hover td, table.data tr[data-href]:hover td { background: #f4f7fb; }


/* Extra Works wizard chrome (CONNECT-style, Field brand) */

/* Extra Works desk */

/* Desk of record — Extra Works list */
.btn-new {
  display: inline-flex; align-items: center; gap: 4px;
  background: #1a9b4a; color: #fff; border: 1px solid #1a9b4a;
  padding: 8px 14px; font-weight: 700; font-size: var(--fs-12); text-decoration: none;
}
.btn-new:hover { background: #15853f; border-color: #15853f; color: #fff; }
.works-chip:hover { border-color: #0a8cf0; color: #0a8cf0; }
.works-ref:hover { text-decoration: underline; }
.works-open:hover { text-decoration: underline; }
.btn-files {
  display: inline-block; font-size: var(--fs-12); font-weight: 700;
  padding: 4px 8px; border: 1px solid var(--line-2); background: #f4f5f7; color: #334;
  text-decoration: none;
}
.btn-files:hover { border-color: #0a8cf0; color: #0a8cf0; }
.btn-closeout {
  display: inline-block; font-size: var(--fs-12); font-weight: 700;
  padding: 4px 10px; border: 1px solid #86efac; background: #dcfce7; color: #15803d;
  text-decoration: none; cursor: pointer; border-radius: 6px;
}
.btn-closeout:hover { background: #bbf7d0; border-color: #22c55e; }
/* Crew pin: last reading over 30 min old = faded; no good reading this shift = dashed outline. */
/* Desk Maps: long crew tips wrap and stay readable beside All Activity / legend. */
.lh-menu button:hover { background: #f4f5f7; }
.lh-menu button.lh-menu-danger:hover { background: #fff4e5; }
.gf-toggle-input:focus-visible + .gf-toggle-track { box-shadow: 0 0 0 3px rgba(10,140,240,.28); }

/* Ref 5 CLEAR fix — Signals desk manage on/off toggle (not opaque add/delete only) */
.sig-toggle-btn:focus-visible .sig-toggle-track { box-shadow: 0 0 0 3px rgba(21,128,61,.28); }

/* CONNECT-wide type-to-filter combobox (data-select-filter) */
/* Consumables forms: filter boxes same height as .cons-select (Damien 2026-09-11) */
.select-filter-option:hover {
  background: #eff6ff;
}

/* New Asset contract picker: solid list that never lets the fields below show through (5 Oct 2026) */
.select-filter-wrap:focus-within { z-index: 90; }
/* On New Asset the open list sits in the page flow and pushes the fields below it down,
   so nothing underneath can be covered or show through (works at desk, 390 px and 360 px). */


/* Extra Works cost box (CONNECT parity) */

/* WO booking acknowledge */


/* Contractor profile collapsible sections */
/* Nested sub-panels: 20px fold controls */

/* Recurring desk — fewer columns, no horizontal sprawl */

/* Work Orders desk — month / client / site filters */

/* Destructive action */
.btn-danger {
  background: #b42318;
  color: #fff;
  border: none;
}
.btn-danger:hover { background: #912018; color: #fff; }

/* WO POS / CRP gallery — display thumbs ~50% (Damien). Photo export standard is 830×641 — do not downscale uploads to thumb CSS. */

/* Contractor Compliance — licences stacked pairs */
.licence-file-del-btn:hover { color: #b91c1c; }
.licence-upload-icon:hover { filter: brightness(1.06); }

/* Site assignment — dates in one box */

/* Contractor profile — Identity / Commercial / Compliance / Notes in one card */

/* Contractor: Add assignment starts collapsed as + icon button */
.contractor-add-assignment > summary.contractor-add-assignment-btn:hover {
  background: var(--blue-d);
}

/* Contractor site assignments: one collapsed key-info row by default */

/* Contractors list: Allocate / Open as icons */
.contractor-icon-btn:hover {
  background: #0a8cf0;
  border-color: #0a8cf0;
  color: #fff;
}

/* Work Orders desk: Quote / POS / Open as icons */
.works-desk-ico:hover { color: #0369a1; }
.works-row-actions .works-desk-ico:hover {
  background: #0a8cf0;
  border-color: #0a8cf0;
  color: #fff;
}
.works-copy-pos-btn:hover { background: #0a8cf0; color: #fff; }

/* Desk of record — WO face title row: back-to-record icon, left of the PO title. */
.wo-back-link:hover, .wo-back-link:focus-visible {
  background: var(--navy); border-color: var(--navy); color: #fff;
}
.wo-back-link:focus-visible { outline: 2px solid var(--blue); outline-offset: 2px; }

/* Desk of record — Extra Works list: the row the wo-back-link icon deep-links to
   (`/works#wo-{id}`). .wo-row-highlight is added by app.js on arrival; :target is a
   CSS-only fallback (progressive enhancement — same row, no JS required) for anyone
   opening the #wo-{id} link with scripts off. Informational tint (var(--blue-s)/
   var(--blue), same tokens as .banner.info) — this is "here's the row", not an
   error/warning, so it does not reuse the red alert family. */
.works-file-del-btn:hover { background: #fef2f2; color: #b91c1c; }


/* WO POS video tiles */


/* Clients list expander — one blue chrome button; closed + / open − */

/* Location compliance X / + */

.btn-del-x {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 24px;
  height: 24px;
  border: 1px solid #fecaca;
  border-radius: 6px;
  background: #fef2f2;
  color: #dc2626;
  font-weight: 700;
  font-size: var(--fs-12);
  cursor: pointer;
  line-height: 1;
  padding: 0;
  flex-shrink: 0;
}
.compliance-x:hover,
.btn-del-x:hover { background: #fee2e2; }
.btn-remove-soft {
  border: 0; background: transparent; color: #b91c1c; cursor: pointer;
  font: inherit; font-size: var(--fs-12); font-weight: 700; padding: 0; text-decoration: underline;
}
.btn-remove-soft:hover { color: #991b1b; }


/* Consumables CONNECT desk (2026-09-11 brief) */
/* Catalogue actions: TD stays table-cell so vertical-align:middle works; keep row border under Edit/× */
.cons-act-edit:hover { border-color: var(--blue); color: var(--blue); }
.cons-act-del:hover { color: #fff; background: #b91c1c; border-color: #b91c1c; }

/* Consumables: contract pick is a filter select — never chip toggles */

/* Catalogue edit modal — CCS | ABCO | Other on one screen */

/* Schedule of rates picker (Create WO — near Client charge) */
.works-sor-link:hover { color: #066bb8; }
.works-sor-item:hover { background: #f0f7ff; }

/* In progress — orange (Issued → accept → In progress) */


/* —— Client block polish — match Works / CONNECT chrome (CoS CLEAR) —— */

/* Landing desk */
.client-name-link:hover { color: #0874c9; text-decoration: underline; }
.client-row:hover td { background: #f0f7ff; }
.client-contract-link:hover { color: #111; text-decoration: underline; }

/* Inside client */
.client-logo-box.empty:hover { border-color: #0a8cf0; background: #dbeafe; }
button.client-logo-box.has-logo:hover { border-color: #0a8cf0; background: #eff6ff; }
.client-id-row input:hover,
.client-id-row textarea:hover,
.client-id-row input:focus,
.client-id-row textarea:focus {
  border-color: #0a8cf0; outline: none; box-shadow: 0 0 0 3px rgba(10,140,240,.12);
}
.client-block-page .client-add-link:hover,
.client-inside .client-add-link:hover,
.client-add-link:hover { text-decoration: underline; color: #0874c9 !important; }
.client-section .data input:focus {
  border-color: #0a8cf0; outline: none; box-shadow: 0 0 0 3px rgba(10,140,240,.12);
}
.client-tick-toggle:hover { border-color: #0a8cf0; }
.client-insure-upload:hover { background: #eff6ff; border-color: #93c5fd; }
.client-insure-file-link:hover { background: #eff6ff; border-color: #93c5fd; }
a.client-contract-short-name:hover { color: #0a8cf0; text-decoration: underline; }
.client-contract-open:hover { text-decoration: underline; }

/* Compliance expanders — extra air, Works blue chevron already global */
.client-block-page .btn-ghost:hover,
.client-inside .btn-ghost:hover {
  border-color: #0a8cf0; color: #0a8cf0;
}
.client-block-page .btn-primary:hover,
.client-inside .btn-primary:hover { background: #0874c9; border-color: #0874c9; }

.btn-sm { padding: 4px 10px; font-size: var(--fs-12); }
.client-custom-req-row .client-custom-req-title:focus {
  border-color: #0a8cf0; outline: none; box-shadow: 0 0 0 3px rgba(10,140,240,.12);
}


/* Master Documents desk */
.md-linked a:hover { text-decoration:underline; }
.md-ico:hover { color:#066bb8; }

/* Service Delivery Staff desk */
/* Inductions OK tone = CONNECT blue (Clearances OK stays green) */
.btn-tiny {
  font-size: var(--fs-button); font-weight: 700; padding: 2px 8px; border: 1px solid #e5e9ef; background: #fff;
  border-radius: 6px; cursor: pointer; color: #64748b;
}
.btn-tiny:hover { color: #b91c1c; border-color: #fecaca; }

/* Portrait / ID / clearance cards */
/* F1 icon revert (CoS CLEAR 23 Sep 2026; Staff ID tile dropped 24 Sep 2026):
   icon row sits immediately beside the portrait, not beside the name text —
   see .sds-capture-grid-row further down, which lives inside this same
   wrapper. */
.sds-file-chip:hover { background: #dbeafe; }

/* Service Delivery Staff — Allocate access */
.sds-alloc-tab:not(.is-active):hover { color: #0f172a; background: #f8fafc; }
.sds-alloc-chip-x:hover { color: #b91c1c; background: #fee2e2; }

/* ── Service Delivery Staff — F2 3×2 grid (CoS CLEAR + Damien GTG,
   24 Sep 2026) ── Emergency · Banking · Medical / Employment contract ·
   File notes · blank, immediately beside the portrait. Supersedes the F1
   single-row lock of 23 Sep 2026 (Staff ID tile stays dropped, PR #80) and,
   before that, the Wave-2 eight-card "Onboarding captures" grid.
   Fixed 3-column grid, always 6 cells: a worker type that hides a tile
   (e.g. a contractor without Banking/Medical) leaves a blank cell in that
   locked slot — see field_sds_capture_catalog() / field_sds_render_capture_grid_cells()
   in lib/sds_capture_answers.php for the slot numbering this grid renders. */
.sds-xero-link:hover { background: #141c26; color: #fff; }
/* Compact grid of tiles beside the portrait — narrower + shorter cells than the self-profile grid. */
.sds-capture-icon:hover,
.sds-capture-icon:focus-visible { border-color: #BE1E2D; box-shadow: 0 4px 12px rgba(190,30,45,.12); }
/* Blank sixth-slot placeholder — never a button, never clickable. */
/* GPS tracking tile (F3, CoS CLEAR + Damien GTG, 24 Sep 2026) — slot 6,
   same size/shape as every other tile. A <form> wrapper (progressive
   enhancement round-trip) must never become its own grid cell, so it just
   passes layout through to the real <button>/<div> tile inside it. */
/* Small on/off switch badge overlaid on the glyph corner — colour alone
   is never the only signal (colourblind-safe: track position + colour). */
.sds-gps-tile.sds-gps-on:hover,
.sds-gps-tile.sds-gps-on:focus-visible { border-color: var(--ok); box-shadow: 0 4px 12px rgba(47,125,74,.15); }
/* Read-only (non-admin actor) — same slot/size, never a button. */
.sds-capture-icon.sds-gps-readonly:hover,
.sds-capture-icon.sds-gps-readonly:focus-visible { border-color: #e5e9ef; box-shadow: none; }
/* Employment contract slot + File notes drawer. */
/* Banking icon drawer: bank + super + tax/TFN as three labelled groups. */
.sds-capture-close:hover { color: #b91c1c; background: #fee2e2; }

/* ── Desk-only Xero setup pack (WAVE 2 §33) ── */

/* ── Periodicals master desk (light chrome) ── */
/* Halves/quarters removed — CoS CLEAR 2026-09-12 (solid L→R dots only). */
/* Adhoc WO markers are live Work Orders (24 Sep 2026) — clickable through to the WO detail
   screen, with a richer hover popover than the native title tooltip. */
.per-adhoc-link:hover,
.per-adhoc-link:focus-visible {
  outline: 2px solid #0a8cf0;
  outline-offset: 1px;
  border-radius: 2px;
}
/* Coloured periodical dots click through too (24 Sep 2026 widened scope) — to the issued WO
   when one is linked, else to the existing Issue-a-work-order destination. */
.per-dot-link:hover,
.per-dot-link:focus-visible {
  outline: 2px solid #0a8cf0;
  outline-offset: 1px;
  border-radius: 999px;
}
.per-day-marks [data-cal-tip]:hover::after,
.per-day-marks [data-cal-tip]:focus-visible::after {
  content: attr(data-cal-tip);
  position: absolute;
  bottom: 130%;
  left: 50%;
  transform: translateX(-50%);
  background: #0f172a;
  color: #fff;
  font-size: var(--fs-11);
  font-weight: 400;
  line-height: 1.35;
  padding: 6px 8px;
  border-radius: 6px;
  white-space: normal;
  width: max-content;
  max-width: 220px;
  z-index: 40;
  box-shadow: 0 6px 16px rgba(15, 23, 42, .28);
  pointer-events: none;
}


/* —— Contract face (CoS CLEAR 11 Sep 2026) —— */
.contract-face-page .cf-ref-view:hover { color: #0f172a; background: #f1f5f9; }
.contract-face-page .cf-ref-view:focus { outline: 2px solid #0a8cf0; outline-offset: 2px; }
.cf-nav li a:hover { background: #f8fafc; }

/* —— CONNECT Field Uniformity pass (11 Sep 2026) —— */ /* danger/expired pink-red */
.cf-file-actions a:hover { text-decoration: underline; }
.btn-attach-pdf {
  display: inline-flex; align-items: center; gap: 6px;
}


/* —— Contract face feedback batch #1–12 (11 Sep 2026) —— */
.cf-fold-minus:hover { background: #066bb8; }

/* Contract Representatives — copy from client (next to + Add) */
.cf-reps-copy-btn:hover {
  background: rgba(10, 140, 240, 0.10);
  color: #0874c9;
}
.cf-reps-copy-btn:focus-visible {
  outline: none;
  box-shadow: 0 0 0 3px rgba(10, 140, 240, 0.22);
}

/* —— Contract face ops full-width lock —— */

/* —— Contract face type theme match (12 Sep) —— */

/* —— Ops placement: full width under commercial (Damien markup) —— */

/* —— Value / Invoicing row align (Damien red lines) —— */

/* —— Ops mini under TERM (Marketing visual lock) —— */
/* Field grid: one label size, even gaps */

/* Contract Face reps: Email shorter so Notifications checkbox stays visible */

/* From/To/Apply live inside Combined totals grey strip */

/* Financial adjustments — list-first desk chrome */

/* Contract Face — CONNECT-consistent container density (match Client/Works cards) */

/* Fold headers carry section icons (nav list removed) */

/* WHS Safety multi-tick — full-width CONNECT list, not a shrunk grey box */
.contract-face-page .cf-comp-tick:hover,
.cf-comp-tick:hover { background: #eef6ff; }


/* WHS Safety — full width + quieter nests (Marketing P0) */

/* WHS width — ID selectors beat ancestor misses */

/* Contract Face vertical rhythm — same gap as Term → Representatives */

/* Sidebar edit mode (spanner) */
.side-settings:hover {
  color: #fff; border-color: #8ecfff; background: rgba(10,140,240,.18);
}
.nav-edit-tools button:hover { border-color: #8ecfff; }

/* Clients — Create client panel (CoS CLEAR 2026-09-12) */
.client-create-close:hover { color: #111; }


/* Contract Face — selectable status badge + delete (top-right) */


/* Inside Client — delete top-right */


/* Client name → client landing */
a.client-inside-title-link:hover {
  color: #0a8cf0 !important;
  text-decoration: none !important;
}
a.cf-head-logo-link:hover .cf-head-logo {
  border-color: #0a8cf0;
}
a.cf-client-name-link:hover { text-decoration: underline !important; }


/* Export overview — left of Delete */


/* Signed Contract icon on client contracts list */
a.client-signed-link:hover {
  background: #dbeafe;
  color: #0369a1 !important;
}


/* Fixed cost — true column grid (Periodicals align bar); view-only no X; Edit Remove X (13 Sep 2026) */
/* Edit mode: 6th col = red X Remove line (view stays 5-col, no X) */

/* Contract Face — editable contract name (same pattern as CT ref) */
.contract-face-page .cf-name-view:hover { background: #f1f5f9; }
.contract-face-page .cf-name-view:focus { outline: 2px solid #0a8cf0; outline-offset: 2px; }

/* Signed Contract drop zone */

/* Contract Documents tags — chip once selected; select on edit */
.cf-doc-tag-x:hover { background: #fee2e2; color: #b91c1c; }

/* Contract Documents — Tag header + tag manager popout */
button.cf-doc-tag-head-btn:hover { color: #1e3a8a; }
.cf-doc-tag-manager-close:hover { background: #e2e8f0; color: #0f172a; }
.btn.btn-sm { padding: 4px 10px; font-size: var(--fs-12); }


/* Contract Face Schedule of Rates editor */


/* Commercial collapsible on Contract Face */

/* —— Thin Asset create + face (2026-09-12) —— */
.places-suggest-item:hover { background: #f0fdfa; }
/* Compact note so pins + geofences stay visible while key deferred */


/* Geofence octagon radius slider (create + asset face) */

/* CONNECT-new Task Consumables block (allocation source) */

/*
 * Phone form fill — Lightform-open (Damien, Sep 2026):
 * Task / Audit (checkin-card) + Maintenance issue (issue-card).
 * white plane, soft section bars, no nested cards, more air between fields.
 */
.phone-app .checkin-card .cons-task-qty input:focus,
.phone-app .checkin-card .cons-task-qty select:focus {
  outline: none;
  border-bottom-color: #3b82f6;
}
.phone-app .checkin-card .field input:focus,
.phone-app .checkin-card .field select:focus,
.phone-app .checkin-card .field textarea:focus,
.phone-app .checkin-card textarea:focus,
.phone-app .issue-card .field input:focus,
.phone-app .issue-card .field select:focus,
.phone-app .issue-card .field textarea:focus,
.phone-app .issue-card textarea:focus {
  outline: none;
  border-bottom-color: #3b82f6;
}

/* Asset bulk upload — Mode A/B + loud confirm */
.asset-bulk-upload .bulk-mode-opt:hover {
  background: rgba(37, 99, 235, 0.06);
}

/* —— Heartbeat shell correction (Maps overlay · CONNECT) —— */

/* Chase overlays map below fixed map-overlay banner; Activity rail stays */

/* Heart ON snug — edge-to-edge chase; solid Field chrome banner; no map mat peek */

/* Three stage bands — collapsible; scroll inside open stage */
/* Stage band top accent — stage colours (13 Sep): Due now red · Follow-up orange · Closed today green */       /* Due now = red */   /* Follow-up = orange */    /* Closed today = green */
/* Expanded = blue − · collapsed = blue + (never twin +/+ while open — Damien 13 Sep) */
/* Add Heartbeat (Due now only) — green + left of blue collapse (Damien 13 Sep swap) */
.hb-band-add:hover { background: #15803d; }
/* Seen = button green only on open stages; Closed today rows keep green tint */
.hb-act.hb-act-seen:hover,
.hb-act.is-seen:hover {
  background: #15803d !important;
  border-color: #166534 !important;
  color: #fff !important;
}
/* Band column headers — top-aligned once per stage (Damien chase chrome 12 Sep) */ /* aligns under site column — headers sit over value grid only */ /* icon Seen+Convert+Park */
/* WHAT NEEDS + WHAT IS THE HOLD UP — expanding free text (no artificial caps) */ /* cascade: urgency/actions top when WHAT grows */ /* dropped RHS Due now pill — v2 amend */
.hb-act.hb-act-ico:hover { border-color: #0a8cf0; color: #0a8cf0; }
.hb-act:hover { border-color: #0a8cf0; color: #0a8cf0; }
.hb-act-closeout:hover { border-color: #15803d; color: #166534; background: #f0fdf4; }

/* Detail panel over chase (sibling of chase on map-stage) */


/* Maps people right-click (Admin/COG) */
.crew-ctx-item:hover { background: #f1f5f9; }
.crew-ctx-danger:hover { background: #fef2f2; }

/* Maps Legend — independent Markers + Contracts accordions (CONNECT +/−) */

/* Contract face — Periodicals fixed info table (13 Sep 2026) — true column grid; CTA drop + master Save; Edit Remove X */
/* Edit mode only: 8th col = red X Remove line (view stays 7-col, no X) */
/* Asset face view mode: same 7 data columns + an 8th "Issue a work order" action column. */
/* Contract face view mode: same 7 data columns + a narrow Raise a work order icon.
   Separate from .cf-per-grid-view-wo, which is sized for the asset-face text button. */
.cf-per-raise-wo:hover {
  background: #0a8cf0;
  border-color: #0a8cf0;
  color: #fff;
}
/* Service type dropdown + Other free text (24 Sep 2026) — the text input drops to its own
   line only while visible (Other selected); the select otherwise sits inline with the dot. */
/* Asset face cascade rows: Asset column is fixed to the current site, not a picker. */


/* Service category blocks inside Other services (13 Sep 2026) */
/* Other services Qty column (Damien send 13 Sep 2026) */


/* Contract Periodicals fold — inline calendar lens (CoS CLEAR 13 Sep 2026) */


/* Bin run — parent site / bin (never "sub-asset") */
/* Stand-in pin (Asset loaded without coordinates) — must never read as a real position.
   Amber, not red: red #BE1E2D is kept for Issues and missed schedules. The wording tells the two cases apart. */


/* —— Issues orange triangle ! — Heartbeat Due now attention family (Damien 13 Sep) —— */
/* Reuses .hb-urgency-attn .hb-tri; do not alter Heartbeat collapse − chrome. */

/* —— CONNECT Onboarding Package (M1) — signed Stage 0 mock 01 chrome —— */
.ob-back:hover { background: rgba(255,255,255,.08); }
@media (min-width: 800px) {
  /* Mock 01 desktop: grey track always visible under the status line, even at 0 of 6. */
}
.ob-row:hover { background: #fafbfc; }
.ob-cta:hover,
.ob-cta-btn:hover { background: #1b2430; }
.ob-btn-ghost:hover { border-color: #141c26; }

/* —— M2 Details & medical (signed mock 02 chrome; full 49Q) —— */
.ob-input:focus,
.ob-select:focus,
.ob-textarea:focus,
.ob-app .lh-date:focus {
  outline: 2px solid #141c26;
  outline-offset: 1px;
}
.ob-draft:hover { border-color: #141c26; }

/* —— K1 Keys desk of record (Contract face TOP) —— */
.keys-issue-btn:hover { background: #1b2430; color: #fff; }
.keys-pick-list a:hover { background: #eef6ff; }

/* —— K4 Receive-in / first custody (mock 01) —— */

/* —— K3 Site access pack (desk mock 01 + Field PWA mock 02) —— */
.keys-access-pill:hover { background: #e2e8f0; color: #141c26; }
/* NAV-BOTTOM-1 (Sep 2026): the private Home/Access/Jobs/More tabbar
   (.keys-pwa-tabbar / .keys-pwa-tab) is retired — Site access now renders
   the same shared .m-tabbar as every other Field phone screen (see
   field_view_site_access_index()/field_view_site_access() in
   lib/site_access.php, which no longer pass noTabbar). */

/* —— Field phone Site access & keys lock (Damien): return keys, view-only
   inductions/consumables, in-app Scope of works PDF — no QR, no video, no
   unrelated tiles on this screen. —— */

/* Return keys confirm dialog — Bug Bot HIGH fix. Cancel/Confirm sit side by
   side; Confirm is the destructive primary (matches .btn-danger red). */
.keys-return-dialog-confirm:hover { background: #912018; }

/* —— M3 Portrait photo (signed mock 03) —— */
/* Portrait guide as HTML (font audit F-3): captions are real 14px text, never scaled down with a picture. */
.ob-resource-link:hover { text-decoration: underline; }
.ob-file-btn:hover { border-color: #141c26; background: #fff; }

/* —— #9 White-bg portrait AI Prep (CoS CLEAR, Damien GTG 23 Sep 2026) —— */
/* Same [hidden] override bug as .ob-prep-compare below — the Prep button
   must actually disappear before a file is chosen (found in headless-Chrome
   render-check, 25 Sep 2026). */
/* Author `display:flex` above otherwise beats the browser's own [hidden]
   default (found in headless-Chrome render-check, 25 Sep 2026) — the
   Before/After compare boxes stayed visible, showing two broken-image
   placeholders, before a file was even chosen or Prep had run. */
/* Square (1/1) preview boxes, not a short landscape frame (PT4, Damien,
   25 Sep 2026 — the old fixed 140px-tall box cropped a portrait-oriented
   photo down to a sliver, showing only the top of the hair at 360/390px
   widths). BEFORE is the raw, not-guaranteed-square upload, so it uses
   object-fit:contain — the whole head, face and shoulders stays visible,
   letterboxed rather than cropped. AFTER is already Prep's own square
   cover-crop output (lib/portrait_prep.php), so object-fit:cover on an
   already-square image is a no-op crop — included explicitly so the rule
   still holds if Prep's output size assumptions ever change. */
/* AFTER · Prep ready sits on pure white (Portrait Prep rework, CoS CLEAR,
   24 Sep 2026) — the placeholder plate behind the thumbnail matches the
   Prep output itself while the image is loading. */

/* —— M4 ID & clearances (portrait chrome + Details draft/submit) —— */

/* —— M5 TFN & Super (same chrome as ID / Details / Portrait) —— */

/* Thin onboarding published-documents desk (Staff) */

/* Onboarding package desk — reuse Asset face /sites/{id} chrome family (CLEAR 17 Sep 2026).
   Navy #141c26 · accent #BE1E2D. Phone .ob-app shell unchanged. No flow redesign. */
.ob-desk .ob-cta:hover,
.ob-desk .ob-cta-btn:hover { background: #0d131a; }
.ob-desk .ob-draft:hover { background: #eef0f3; }
.ob-desk .ob-btn-ghost:hover { background: #eef0f3; }

/* CLEAR 20 Sep 2026 — Create new worker + Block Edit + ID expiry */
.ob-cta-accent:hover,
.ob-desk .ob-cta-accent:hover,
.ob-desk .ob-cta-btn.ob-cta-accent:hover { background: #0d131a !important; border-color: #0d131a; }
/* Resend link via SMS — "Last sent" label beside the ghost button. */
/* Ref 7 CLEAR fix — Delete sits apart from Cancel/Save (E1 mock: Delete left, Cancel/Save right).
   The desk slide-over is a fixed 380px drawer (narrower than the E1 desktop
   mock), so Delete stacks above a divider rather than crowding the Cancel/Save row. */
.ob-btn-danger-outline:hover { background: #fef2f2; }

/* Desk Onboarding face — admin package list + empty state (GTG mocks 01–02, 20 Sep 2026) */
.ob-face-table tbody tr[data-href]:hover td { background: #f0f7ff; }
.ob-face-name a:hover { text-decoration: underline; }

/* Edit worker — same slide-over chrome as Create new worker (Damien ask 20 Sep 2026) */

/* Asset face — site operating pack (CLEAR 15 Sep 2026). Navy #141c26. Long-scroll, no Sites tabs. */
/* ~3x the original 200px pane, per Damien's ask — "where it is now, just that again, and then that again". */
.af-btn-navy:hover { background: #0d131a; color: #fff; }
.af-btn-ghost:hover { background: #eef0f3; }
/* Compact calendar lens — same marker markup as desk/contract face, sized down to fit. */

/* —— Schedules desk — same table family as Templates / Audits / Issues —— */
.sched-work-table tbody tr:hover { background: #f7f9fb; }
.sched-dup-btn:hover { text-decoration: underline; }
.sched-asg-leaf:hover { background: #e7f4fe; }

/* ——— CoS CLEAR KEEP thin four (22 Sep 2026) ——— */

/* 1 · Heartbeat — verify documents (mock A7) */
/* Narrow screens: the Menu button becomes an in-flow sticky bar (body.has-menubar,
   set by the page via field_layout_start 'menu_bar'). It reserves its own row, so
   it never sits over the header or the cards while scrolling. */ /* gold text rule: #8A6500, not #C9920A */
/* Wider than a phone: contained horizontal scroll inside the table box, never the page. */ /* chip label text; chip background/border unchanged */
.hv-file-open:hover { text-decoration: underline; }
.hv-tick:hover { border-color: var(--blue); }
/* Phone: one card per document, every key column (File, Source, Status, Verified)
   reachable without sideways scrolling. */

/* 2 · WO cleaner assign after Issue */

/* 3 · Account manager (contract cascade + asset override) */

/* 4 · Crew FK on contractor desk (mock A9b) */
.crew-add-btn:hover { background: #0d131a; border-color: #0d131a; color: #fff; }

/* §28 service delivery staff multi-home affiliations (mocks B1 / B2) */
.aff-save:hover { background: #a31724; border-color: #a31724; }

/* WAVE 1 · account manager allowlist (mock C1) */

/* WAVE 1 · Service delivery staff list — sticky column headers (mock C2) */
/* An open staff detail panel is taller than the scroll box — hand scrolling back
   to the page so the whole panel is reachable. */

/* ── Mid-life bank · super · TFN (A2+B1, CoS CLEAR 23 Sep 2026) ──
   Field self-service profile (Banking icon edit) + desk Xero pack edit +
   Heartbeat "Pay details re-check" lane, separate from onboarding
   Verify->Active. Shared .pill / .pd-* / .hv-lane-* classes below. */
/* Field phone PROFILE — locked 3×1 tile row (Damien, 25 Sep 2026): exactly
   Emergency / Banking / Employment contract, no blanks, evenly filling the
   card width below the profile row. Desk keeps its own fixed 3×2 six-tile
   grid (.sds-capture-grid without this modifier) untouched. */
/* Home affiliation / contractor line on the Field phone profile. */
/* Staff ID button directly under the portrait block (24 Sep 2026, Damien —
   mirrors "Upload / Replace Portrait" on the desk profile) since the tile
   is gone from the icon row above. */

/* ── §22 Mapping dashboard — desk trail + scrubber (23 Sep 2026 CoS CLEAR) ──
   Uber Eats-style live marker + path trail for ONE Service delivery staff
   member, one shift/date-range at a time. Attended (red) vs Scheduled
   (slate, dashed) pins both stay on the map. No planned-route line — ever.
   Namespaced sds-trail-* throughout so it never leans on generic .stat /
   .legend / .scrubber names used elsewhere. */
:root {
  --sds-trail-red: #BE1E2D;
  --sds-trail-slate: #64748b;
}
@keyframes sdsTrailPulse {
  0% { box-shadow: 0 0 0 0 rgba(20,28,38,.35); }
  70% { box-shadow: 0 0 0 14px rgba(20,28,38,0); }
  100% { box-shadow: 0 0 0 0 rgba(20,28,38,0); }
}

/* ── Equipment Register — own top-level desk (J1 list / J2 add-edit, CoS
   CLEAR 23 Sep 2026). Navy #141c26 · accent #BE1E2D. Own sidebar — never
   nested under Assets; chrome stays Service delivery staff only. ── */
.eqr-table a:hover { text-decoration: underline; }

/* CLEAR 24 Sep 2026 · Tenant Admin desk (Comms + Organisation, against tenants / tenant_config) */

/* Payroll — fortnight grid, exceptions, manual attendance (§ Payroll rebuild) */
/* CLEARED — Week 1 / Week 2 render as two separate <table class="pay-day-grid">
   elements. Left at the default (auto) table layout, each table sized its own
   columns from its own content, so Rostered/On site/Lunch/Payable drifted out
   of alignment between weeks whenever the two weeks' text differed in length —
   most visibly when one week has no 'Open' link in any row at all and that
   whole column collapses, while the other week's column stays wide enough to
   fit the link text. table-layout: fixed forces every .pay-day-grid to read
   column widths from its (always-identical, 6-column) header row instead of
   its body content, so Week 1 and Week 2 line up pixel-for-pixel at desktop
   width regardless of what either week contains. */

/* Roster — default roster editor + profile summary card */
/* vertical-align: top (not middle) — the Site cell's chips can wrap onto a
   second line, and every cell in the row needs to line up at the same top
   edge regardless of which cell grew taller. */
/* Site cell — reuses the Schedules "Select Locations" picker
   (field_render_assign_dropdown(), .tpl-asg-*). Bounded + wrapping so a
   multi-chip selection never pushes the row's other cells out of column. */
/* Contract vs Location vs Asset badge — on the picked chip AND the add-select's dropdown row. */

/* Field Pause/Resume (lunch) */

/* CLEAR (Damien via CoS) 24 Sep 2026 · Field Web Push — Service delivery
   staff notifications permission screen + My roster fortnight view. Navy
   #141c26 · accent #BE1E2D. Phone .m-card shell — no new component system. */
.push-perm .btn-danger:hover { background: #971826; border-color: #971826; }

/* My roster — fortnight list, changed-shift highlight (accent border, from
   the roster-change push deep link). */
/* HOTFIX ROS-2 (25 Sep 2026) — the day/date kicker ("MON 28") is absolutely
   positioned over a left-hand gutter reserved by .roster-day's padding-left,
   so the time + site line (.roster-day-times) starts clear of it. But
   `.phone-app .m-card` (2 classes on the ancestor+card) sets the full
   `padding` shorthand, which beats a bare `.roster-day { padding-left }`
   (1 class) on specificity alone regardless of source order — collapsing
   the gutter back to 14px and printing the time/site text straight under
   the kicker, exactly like the field screenshot. Same fight, same fix,
   hits `.roster-day-changed`/`.roster-day-highlight`'s border-color against
   `.phone-app .m-card`'s `border` shorthand (the pink/red accent border
   silently never painted) and `.roster-day-times` against `.phone-app
   .m-card h3`'s font-size. Re-scoped every one of these to out-rank its
   `.phone-app .m-card` competitor instead of chasing specificity forever —
   no layout/markup change, phone-only (`.phone-app`), desk `.roster-day-cell`
   (different class, default roster editor) untouched. */

/* ===== Payroll P2-P4 — desk fortnight view for one Service delivery staff
   member (/payroll/person/{id}). P1's table-layout: fixed technique
   (aafae9d, PR #99, block above — untouched) is reused via the shared
   .pay-day-grid class; this modifier just supplies this page's own
   7-column widths so Week 1 and Week 2 line up pixel-for-pixel here too. */ /* Day */ /* Site */  /* Rostered */ /* On site */ /* Lunch */ /* Payable */ /* Status / Exceptions */
.pay2-page .breadcrumb a:hover { text-decoration: underline; }

/* Fortnight totals pinned at the top + Week 1 / Week 2 switch (locked decision a). */
.pay2-week-tab:focus-visible { outline: 2px solid var(--blue); outline-offset: 2px; }

/* Rows — click anywhere opens the drawer; hover/focus shows the pointer,
   highlight, left accent and "Edit shift" hint (brief interaction rule 1). */
tr.pay2-row:hover, tr.pay2-row:focus-within {
  background: var(--blue-s); border-left-color: var(--blue);
}
tr.pay2-row:focus { outline: none; }
tr.pay2-row:focus-visible { outline: 2px solid var(--blue); outline-offset: -2px; }
tr.pay2-row-future:hover, tr.pay2-row-future:focus-within { background: #f4f6f7; border-left-color: #c5c9ce; }
tr.pay2-row-pending:hover, tr.pay2-row-pending:focus-within { background: #fdecd2; border-left-color: var(--warn); }
tr.pay2-row:hover .pay2-edit-hint, tr.pay2-row:focus-within .pay2-edit-hint {
  opacity: 1;
}
.btn-sm { padding: 4px 10px; font-size: var(--fs-12); border-radius: 6px; }

/* Durable Undo fallback on an approved row (Bug Bot retest fix — Gate 3
   Undo must not depend on the toast still being on screen). */
.pay2-row-undo:hover { border-color: var(--warn); background: var(--warn-s); color: var(--warn); }

/* Toast (Undo after Approve — locked decision f). Sticky: stays on screen
   until Undo or Dismiss is clicked, no auto-hide timer to race during a
   screenshot walk. */
.pay2-toast button.pay2-toast-undo:hover { background: #e7f4fe; }
.pay2-toast button.pay2-toast-dismiss:hover { background: rgba(255,255,255,.24); }

/* Edit drawer (locked decision b — no approval; f — no "Add overtime request" tick). */

/* ————————————————————————————————————————————————————————————————————
   Consumables C3 — receive stock in (Damien via CoS, 25 Sep 2026, FULLY
   CLEARED). Field order detail (Draft·Placed·Ordered·Delivered·Received
   timeline, Mark delivered), Receive (per-line stepper + required photo),
   and the desk order record (pricing on received qty). Field primary
   action blue #1e88e5 (locked — matches live + FAB); brand strip #141c26,
   accent #BE1E2D untouched. Teal #0f766e stays Consumables-family only
   (glyphs above); chips here are neutral grey / navy per decision 6.
   ———————————————————————————————————————————————————————————————————— */

/* Timeline — Draft · Placed · Ordered · Delivered · Received */
.cons-c3-cta:hover { background: #1a72c2; }

/* Receive */
.cons-c3-submit:hover { background: #1a72c2; }

/* Desk order record */
.btn-navy { background: #141c26; color: #fff; border-color: #141c26; }
.btn-navy:hover { background: #0d131b; }

/* Contractor: assigned-to rows (Site / Location group / Contract / Asset) */

/* ——— Site assignments + Resend polish (Bug Bot walk of 8cb0a80) ——— */

/* Inline validation: amber, never red (red is reserved for Issues / missed schedules). */

/* Hours by day */

/* $ prefix on rate inputs */

/* Assignment summary: rates line */

/* Add assignment: proper modal, centred and scrollable */
.contractor-add-assignment > button.contractor-add-assignment-btn:hover { background: var(--blue-d); }

/* Keep anchored sections clear of the sticky menu bar */

/* Assets / groups pick chips never wider than their input */

/* Phones: stop date inputs clipping (no wheel change). The Menu button clearance comes from
   the 'menu_bar' layout option (body.has-menubar) on the contractor + onboarding pages. */

/* ——— Resend link via SMS polish ——— */
/* Topbar: buttons sit on one baseline, "+ Create new worker" never wraps its label. */
/* Modal buttons: label centred (no stray top margin from the desk button rule). */
/* The open panel dims and sits above the Menu button (float-menu is z-index 12). */

/* Desk Service delivery staff profile — inline Email error (amber, not red). */

/* ------------------------------------------------------------------
 * Scrolling-wheel date picker (assets/date-wheel.js, lib/date_wheel.php).
 * Day | Month | Year scroll-snap columns in a bottom sheet. Field navy
 * #141c26 + blue #4AA3FF.
 * ------------------------------------------------------------------ */
.dw-trigger:focus-visible { outline: 2px solid #141c26; outline-offset: 1px; }
/* No-JS fallback: the plain text input keeps the existing look. */
.dw-btn:focus-visible { outline: 2px solid #4AA3FF; outline-offset: 0; }
.dw-col:focus-visible { box-shadow: inset 0 0 0 2px #4AA3FF; border-radius: 10px; }
@keyframes dw-up { from { transform: translateY(100%); } to { transform: none; } }
@keyframes dw-fade { from { opacity: 0; } to { opacity: 1; } }

/* Wheel date picker in the remaining desk / Field screens (same .dw component as onboarding). */

/* —— Add an asset: floating Save pill in a sticky bar BELOW the header, under the Home icon (Damien, 5 Oct 2026: not inside the dark header). Blue and navy only: no green, no red; problems are amber. Kept above the 420px block so it holds at every width. —— */
.phone-app .aa-savefab:focus-visible { outline: 3px solid #141c26; outline-offset: 2px; }
@keyframes aa-spin { to { transform: rotate(360deg); } }
/* Why Save is grey */
/* A tap on grey outlines the first missing item in amber */
.phone-app .aa-field.is-bad select:focus, .phone-app .aa-field.is-bad input[type=text]:focus { outline: 2px solid #9a4600; outline-offset: 0; border-color: #9a4600; }
/* Saving: one tap only. The form dims and cannot be touched until the page moves on. */
/* Assets list (landing after a save) */
.phone-app .al-tap:focus-visible, .phone-app .al-view:focus-visible { outline: 3px solid #141c26; outline-offset: 2px; }
.phone-app .al-ptap:focus-visible { outline: 3px solid #141c26; outline-offset: 2px; }
.phone-app .au-nrow:focus-visible { outline: 3px solid #141c26; outline-offset: 2px; }
/* The amber "needs pin" marker: one style for Update position (Nearby rows) and the Assets list (child rows, Parent pin line). */


/* —— Desk Assets pages on narrow screens (Oct 2026) —— */
/* Signals: on a phone each row becomes a card, so the check-in link wraps instead of running off the page. */
/* New Asset: "Tap to pin" shows a clear on state with its label still readable. */

.draw-tools #btn-circle.is-on:hover,
.draw-tools #btn-circle.is-on:focus,
.draw-tools #btn-circle.is-on:active {
  background: #e7f3fd; border-color: var(--blue); color: #0a4f8a;
}
/* Signal choice uses the app blue. */

/* ——— Onboarding ID: mistake tolerance, Front/Back, top clearance (30 Sep 2026) ——— */
/* Inline errors on onboarding use the amber warning colour. */
/* Phone: the fixed Menu button sits at the top-left. Give the onboarding page its own
   row of clearance so it never covers the breadcrumb, the badge or the first letter of
   the heading (360 and 390 px). */

/* WWC Unique ID (SRN) — optional field, grey placeholder, amber inline message */

/* —— Add an asset (Field phone). Errors and flags are amber. —— */
.phone-app .aa-seg input:focus-visible + span { outline: 2px solid #0a8cf0; outline-offset: 2px; }

/* —— Add an asset > Update position (Damien, 5 Oct 2026). Assets only. Blue, navy and grey only; problems are amber #9a4600. Same pill, same cards as Add an asset. —— */
.phone-app .aa-mode2-seg a:focus-visible { outline: 2px solid #0a8cf0; outline-offset: 2px; }
.phone-app .au-link:focus-visible { outline: 3px solid #0a8cf0; outline-offset: 2px; border-radius: 4px; }
/* Child-asset hotfix (6 Oct 2026): the narrowed list says so, with a way out ("Showing children of <parent> · Show all"). Blue and navy only. */
/* Reads as one sentence; the padding gives Show all a 44 px tap height without making the line taller. */
/* Why Update position is grey, to the left of the pill in the pill bar (it never tells the person to get nearer: the limit is GPS accuracy, not distance). */
/* Update position: the tick only shows when the pill is ready (blue). Grey = no tick (polish on #177); the spinner and the Updated tick are unchanged. */ /* the reason beside it never squeezes the pill's own words */
/* Map key swatches: the marker as drawn on the map, on a small square map tile, so none of them reads as a radio button. */
/* The locate button sits under the zoom buttons. Blue = following the live dot; white = not following (tap to follow again). */
.phone-app .au-loc:focus-visible, .phone-app .au-expand:focus-visible { outline: 3px solid #141c26; outline-offset: 2px; }

/* —— Manager phone profile (Heartbeat) —— home tiles, Service delivery staff list and ID card, lists. Errors and warnings are amber. The Issues mark is the shared one. */
/* Who is on shift (manager home) and work order status chips. */
/* Manager phone profile: errors are amber. */

/* Filter dropdown on narrow screens: open it back towards the page edge so no filter is clipped (360 and 390 px). */

/* Filter dropdown (Filter button in the search bar): anchored to the button's right edge at every width, so the panel
   opens back into the page instead of running off the right edge (seen at 1280 px with the Pin filter added). */

/* Assets list on narrow screens: the table scrolls sideways inside its own box, never the whole page, so the search and
   Filter bar stay in view. The Menu button is the in-flow bar above the heading (menu_bar), not a button over it. */

/* PR E (#171 retest). Desk pages with the in-flow Menu bar (body.has-menubar): touch screens wider than 900 px (tablets,
   960 px in Bug Bot's check) also hide the sidebar (html.is-phone), so the bar must be in flow there too, not a
   button floating over the "Assets" heading or the Asset face breadcrumb. */

/* Desk Assets list on phone widths: one card per asset instead of a 980 px table, so nothing scrolls sideways and the
   ··· row actions stay in view. Each cell shows its column name (data-label) in front of its value. */

/* "No assets match this filter." under the desk Assets list, shown when the filters hide every row. */

/* Bulk create: the Mode A / Mode B help reads as one line of text with inline column chips (the generic
   ".bulk-mode-opt span" column layout was also stacking every chip on its own line), chips never split mid-name,
   and the Create Assets / Cancel buttons keep a gap at every width. */
/* Bulk create result: per-row warnings (for example an alias that was built automatically) in attention amber. */

/* Service details (sub_location) shown as small secondary text: desk Assets list, desk Asset face, phone asset page. */

/* —— Heartbeat type scale: shared roles (font cleanup, Oct 2026) ——
   Utility classes for markup that used inline font styles. Values come from the :root tokens only. */
/* Phone: secondary text never below 14px, buttons one step up from the desk (14), full-width buttons 16. */
/* iPhone zoom: Safari (and the iOS app's web view) zooms the page when a box under 16px gets focus.
   Every text box is 16px on the phone chrome, on onboarding, on sign-in, and on any page at phone width
   or on a touch-only device (an admin opening the desk on an iPhone). !important so no per-page rule can undercut it. */

.login-card input:not([type=checkbox]) { font-size: var(--fs-control) !important; }
@media (max-width: 600px), (hover: none) and (pointer: coarse) {
  input:not([type=checkbox], [type=radio], [type=file], [type=range], [type=color]) { font-size: var(--fs-control) !important; }
}

/* ---- Heartbeat tabular figures -------------------------------------------------------------
   Money, quantity and count columns line up digit for digit. Still Source Sans 3 (its default
   figures are already tabular; this locks that in for every desk list, for any proportional-figure
   override, and for the fallback fonts). `.num` is the shared class for new cells; the selector
   list below covers every desk list table (table.data) and the number cells built as grids. */

/* Heartbeat iOS app: location states (lib/heartbeat_location.php, assets/app.js) */
/* Desk map crew pin: Heartbeat app reported Precise Location off. Ring keeps the locked amber
   #C9920A; the small tooltip TEXT uses the darker text amber #8A6500 (5.33:1 on white). */
/* Warning buttons: at least 44 px tall (iOS tap target; outdoors, gloves), comfortable gap at 360 / 390 px. */
/* Neutral post-save note (field_flash flash_note), e.g. "Submitted · POS Task. Marked Location not checked." */
.banner.note { background: #f4f6f8; color: #141c26; border: 1px solid #e5e8eb; border-left: 3px solid #6b7480; }

/* ——— Move pin by hand (lib/asset_hand_pin.php + assets/hand-pin.js). Navy and amber only. ——— */
/* Desk: an asset whose pin was placed by hand. A long move is amber. */
/* No text selection or iOS callout on a long press of buttons and map controls (field phone). */
button, .btn {
  -webkit-user-select: none; user-select: none; -webkit-touch-callout: none;
}

/* Payroll-only lock: Banking / TFN step on someone else's pack, desk login without Payroll access. */
/* One style for every status value (On file / Not filled in yet / Uploaded <date> / Missing). */

/* Payroll-only lock: TFN & Super slot statuses on the onboarding checklist row
   sit on their own lines under the step title instead of running into it. */
/* 8px between the TFN declaration slot and the Super Choice slot; line spacing inside each slot unchanged. */
/* Same 14px dark style as the TFN / Banking step-card values (.ob-payroll-status-row .payroll-slot-status). */

/* Failed save (#204 follow-up, v2): the bad field gets a #c62828 outline with the error right by it. */
/* Phone History Issues card: issue type line; read-only completed issue form. */
/* #192: Needs pin chip in the Update position selected-asset panel. */
/* Photos held from a failed save (v2). */

/* 'Select all' row at the bottom of every multi-select asset picker (visible only).
   Heartbeat brand: navy; gold TEXT, if ever used here, must be #8A6500. */
.select-filter-all:hover { background: #eff6ff; }
/* Filtered-out picker rows: author display:flex on .check otherwise beats [hidden]. */
/* Schedules Assignments drawer: Select all pinned to the bottom of the scroll area while the tree is filtered/scrolled. */
/* Schedules day table scrolls inside its card on phones. Without this the table widened the
   page (569px at 360), so the fixed Assignments drawer sat half off-screen and could not be tapped. */
/* Same phone-width overflow on the pages whose pickers this rule covers: the hours tables on
   schedules/new and users/2|new, and the consumables assign sticky bar, widened the page past
   360/390 so the browser zoomed out and taps on the pickers missed. Scroll / clip locally instead. */
/* Drawer: room under the last picker so its open list (and Select all) scrolls fully clear of the Save bar. */
/* Select all counter: same row styling, number in tabular figures so the row does not jiggle while filtering. */
/* In the flex label the counter would sit a full gap away from "Select all"; pull it in to read as one label. */
/* Picker footer: two links side by side, "Select N …" left and "Remove N …" right. Lit = navy link,
   underlined; greyed + not tappable when its count is 0. Wraps to two lines on narrow phones. */
.select-filter-all.pick-foot:hover { background: #fff; }
.pick-foot-btn.is-on:hover, .pick-foot-btn.is-on:focus-visible { color: var(--blue-d, #0874c9); }

/* Service delivery staff — Xero employee ID (14 Oct 2026). Gold text rule: #8A6500. */
