/* =========================================================
   Inter — self-hosted webfont (subset latin, woff2)
   ---------------------------------------------------------
   font-display: swap → text renders immediately with the
   system fallback and swaps in Inter without layout shift
   once it's available. No FOIT.
   =========================================================*/
@font-face {
  font-family: 'Inter';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('fonts/inter-400.woff2') format('woff2');
}
@font-face {
  font-family: 'Inter';
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url('fonts/inter-500.woff2') format('woff2');
}
@font-face {
  font-family: 'Inter';
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url('fonts/inter-600.woff2') format('woff2');
}
@font-face {
  font-family: 'Inter';
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url('fonts/inter-700.woff2') format('woff2');
}

:root{
  /* the company-ish tokens */
  --pad: 14px;
  --radius: 14px;
  --radius-sm: 8px;
  --radius-lg: 16px;

  --primary: #0075c9;          /* azul corporativo */
  --primary-hover: #0063aa;
  --primary-soft: #eaf4fd;
  --primary-soft-hover: #dbeafd;
  --primary-border: #cfe6f8;

  --bg: #f6f8fb;
  --surface: #ffffff;
  --surface-alt: #fafbfd;

  --text: #0b1220;
  --text-soft: #2a3340;
  --muted: #5f6670;
  --muted-soft: #8a9099;

  --border: #e6e9ef;
  --border-strong: #d7dde8;

  --shadow-soft: 0 1px 3px rgba(16, 24, 40, 0.04), 0 1px 2px rgba(16, 24, 40, 0.03);
  --shadow-md:   0 4px 12px rgba(16, 24, 40, 0.06);

  /* Semantic colors — used in badges, pills, alerts */
  --success:        #15803d;
  --success-soft:   #e6f9ec;
  --success-border: #a3dfb4;
  --warning:        #b45309;
  --warning-soft:   #fef3c7;
  --warning-border: #fcd34d;
  --danger:         #b91c1c;
  --danger-hover:   #991b1b;
  --danger-soft:    #fee2e2;
  --danger-border:  #fca5a5;
  --info:           #1e40af;
  --info-soft:      #dbeafe;
  --info-border:    #93c5fd;
  --purple:         #6b21a8;
  --purple-soft:    #f3e8ff;
  --purple-border:  #d8b4fe;

  /* Type system */
  --font-sans: 'Inter', system-ui, -apple-system, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
  --font-mono: ui-monospace, 'SF Mono', SFMono-Regular, 'JetBrains Mono', 'Cascadia Mono', Consolas, monospace;
}

*{ box-sizing:border-box; }
html,body{ height:100%; }

body{
  margin:0;
  font-family: var(--font-sans);
  background: var(--bg);
  color: var(--text);
  line-height: 1.5;
  font-size: 14px;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  font-feature-settings: 'cv11', 'ss01'; /* Inter: alternate single-storey 'a' & better number alignment */
  text-rendering: optimizeLegibility;
}

a{ color: var(--primary); text-decoration:none; }
a:hover{ color: var(--primary-hover); }

.container{
  /* Wider desktop layout (tables look cramped at 980px) */
  max-width: 1200px;
  margin: 0 auto;
  padding: 16px;
}

/* Topbar */
.topbar{
  position: sticky;
  top:0;
  z-index: 20;
  background: var(--surface);
  border-bottom: 1px solid var(--border);
  display:flex;
  gap:12px;
  align-items:center;
  justify-content:space-between;
  padding: 10px 16px;
}

.brand{
  font-weight: 800;
  letter-spacing: .2px;
  display:flex;
  align-items:center;
  gap:10px;
}
.brand img{ height: 26px; width: auto; display:block; }

/* Desktop nav */
.nav a{
  margin-left: 14px;
  color: var(--text);
  opacity: 0.9;
  font-weight: 600;
}
.nav a:hover{ color: var(--primary); opacity: 1; }

/* Cards */
.card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 18px 20px;
  box-shadow: var(--shadow-soft);
  margin-bottom: 14px;
}

@media (max-width: 640px) {
  .card { padding: 14px 16px; }
}

/* Layout grid */
.grid{ display:grid; grid-template-columns: 1fr; gap: 12px; }
@media (min-width: 860px){
  .grid.two{ grid-template-columns: 1fr 1fr; }
}

/* Typography — refined scale with Inter optimizations */
h1, h2, h3, h4 {
  margin: 0 0 10px 0;
  color: var(--text);
  font-feature-settings: 'cv11', 'ss01', 'ss03';
}
h1 {
  font-size: 28px;
  font-weight: 700;
  letter-spacing: -0.3px;
  line-height: 1.2;
  margin-bottom: 14px;
}
h2 {
  font-size: 19px;
  font-weight: 600;
  letter-spacing: -0.1px;
  line-height: 1.3;
  margin-bottom: 12px;
}
h3 {
  font-size: 13px;
  font-weight: 600;
  color: var(--muted);
  text-transform: uppercase;
  letter-spacing: 0.5px;
  line-height: 1.4;
  margin-bottom: 8px;
}
h4 { font-size: 14px; font-weight: 600; line-height: 1.4; }

/* Numbers feel tighter in Inter with these features */
.tabular-nums { font-variant-numeric: tabular-nums; }

/* Forms */
label {
  font-size: 12.5px;
  display: block;
  margin-bottom: 6px;
  color: var(--muted);
  font-weight: 600;
  letter-spacing: 0.1px;
}

input, select, textarea {
  width: 100%;
  padding: 10px 12px;
  border-radius: 10px;
  border: 1px solid var(--border-strong);
  background: var(--surface);
  color: var(--text);
  outline: none;
  font-family: var(--font-sans);
  font-size: 14px;
  line-height: 1.4;
  transition: border-color .15s ease, box-shadow .15s ease, background-color .15s ease;
}

input::placeholder, textarea::placeholder {
  color: var(--muted-soft);
  opacity: 1;
}

input:hover:not(:focus), select:hover:not(:focus), textarea:hover:not(:focus) {
  border-color: var(--muted-soft);
}

input:focus, select:focus, textarea:focus {
  border-color: rgba(0, 117, 201, 0.6);
  box-shadow: 0 0 0 4px rgba(0, 117, 201, 0.15);
}

textarea { min-height: 90px; resize: vertical; }

.row{ display:flex; gap:12px; }
.row > div{ flex:1; }

@media (max-width: 780px){
  .row{ flex-direction: column; }
  .row > div{ width: 100%; }
}

/* Select readability across OS native rendering */
select { color: var(--text); }
select option { color: var(--text); background: var(--surface); }

/* =========================================================
   Button system — 4 levels of hierarchy
   ---------------------------------------------------------
   Default (ghost):  neutral / cancel / back / view
   .primary:         the main action of a screen (one per context)
   .secondary:       affine action, supporting the primary
   .danger:          destructive action
   ---------------------------------------------------------
   All variants share the same shape, spacing and motion.
   Hover and focus states are subtle but unmistakable.
   =========================================================*/
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;

  padding: 9px 16px;
  border-radius: 10px;
  border: 1px solid var(--border-strong);
  /* v0.2.0-pre106 — Pin .btn (except .sm) to the same 34px effective height
     as .action-pill and .btn-icon, so legacy .btn / .btn.primary / .btn.danger
     buttons sit on the same baseline as the newer outlined pills in mixed
     action rows. .btn.sm overrides this below to keep small inline links
     compact. */
  box-sizing: border-box;
  min-height: 34px;

  /* Default = ghost */
  background: var(--surface);
  color: var(--text);
  text-decoration: none;
  cursor: pointer;

  font-family: var(--font-sans);
  font-weight: 600;
  font-size: 13.5px;
  letter-spacing: 0;
  line-height: 1;
  white-space: nowrap;

  transition: background-color .15s ease, border-color .15s ease,
              color .15s ease, transform .05s ease, box-shadow .15s ease;
}

.btn:hover {
  background: var(--bg);
  border-color: var(--muted-soft);
  color: var(--text);
}

.btn:visited { color: var(--text); }

.btn:active { transform: translateY(1px); }

.btn:focus,
.btn:focus-visible {
  outline: none;
  box-shadow: 0 0 0 4px rgba(0, 117, 201, 0.18);
}

.btn:disabled,
.btn.is-disabled {
  opacity: .5;
  cursor: not-allowed;
  pointer-events: none;
}

/* Primary — the main action of a screen.
   v0.2.0-pre104 — Switched from solid-blue fill to the same outlined-blue
   look as .action-pill. The few remaining .btn.primary call sites
   (/auth/login "Sign in", /reports/edit "Save changes", Reject form, etc.)
   now match the rest of the site's button language instead of standing
   out as the only filled-blue chips. Hover light-blue tint mirrors
   .action-pill:hover. */
.btn.primary {
  background: var(--surface);
  color: var(--primary);
  border-color: var(--primary-border);
}
.btn.primary:hover {
  background: var(--primary-soft);
  border-color: var(--primary-border);
  color: var(--primary-hover);
}
.btn.primary:visited { color: var(--primary); }

/* Secondary — affine support action (soft blue) */
.btn.secondary {
  background: var(--primary-soft);
  color: var(--primary);
  border-color: var(--primary-border);
}
.btn.secondary:hover {
  background: var(--primary-soft-hover);
  border-color: var(--primary);
  color: var(--primary-hover);
}
.btn.secondary:visited { color: var(--primary); }

/* Danger — destructive action.
   v0.2.0-pre106 — Switched from solid-red fill to outlined-red, matching
   the same treatment .btn.primary got in pre104. The destructive intent is
   still obvious (red border + red text), but the chip no longer screams
   "filled" while every other primary action in the row is outlined. Hover
   tints the background light-red for affordance. */
.btn.danger {
  background: var(--surface);
  color: #dc2626;
  border-color: var(--danger-border);
}
.btn.danger:hover {
  background: var(--danger-soft);
  border-color: var(--danger-border);
  color: #dc2626;
}
.btn.danger:visited { color: #dc2626; }

/* Modifiers */
.btn.full { width: 100%; }

.btn.sm {
  padding: 6px 12px;
  font-size: 12.5px;
  /* v0.2.0-pre106 — Opt out of the 34px standard: .sm is the explicit
     "small inline action" variant (Clear filter, View, Remove contact,
     Clear signature pad). Keep them compact. */
  min-height: 0;
}

.btn.lg { padding: 11px 20px; font-size: 14.5px; }

/* Action blocks (stacked buttons with spacing) */
.actions {
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.btn.center {
  width: min(520px, 90%);
  margin: 0 auto;
}

/* Custom file picker to avoid browser-localized labels */
.file-picker {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-top: 8px;
  flex-wrap: wrap;
}

.file-label {
  color: var(--muted);
  font-size: 0.875rem;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  max-width: min(260px, 100%);
  flex: 1;
  min-width: 0;
}

/* When a file is selected, highlight the label */
.file-label.has-file {
  color: var(--text);
  font-weight: 600;
}

/* Fix <summary> buttons (same font + remove marker) */
summary.btn{
  list-style:none;
  -webkit-appearance:none;
  appearance:none;
  font: inherit;
}
summary.btn::-webkit-details-marker{ display:none; }

/* Badges */
.badge{
  display:inline-flex;
  align-items:center;
  gap:6px;
  padding: 4px 10px;
  border-radius: 999px;
  border:1px solid #cfe6f8;
  background: var(--primary-soft);
  color: #0a4f86;
  font-size: 12px;
  font-weight: 700;
}

/* Tables */
.table{ width:100%; border-collapse: collapse; }
table{ max-width: 100%; }

/*
  Global responsive tables (mobile)
  -------------------------------
  By default, any table can overflow on mobile. Instead of having to wrap
  every table in a .table-responsive div, we make tables horizontally
  scrollable on small screens.

  - Key/Value tables (.kv) usually fit, so we don't force a large min-width.
  - Wide tables (workflow log, software versions, etc.) keep a min-width.
*/
@media (max-width: 900px){
  table, .table{
    display:block;
    overflow-x:auto;
    -webkit-overflow-scrolling: touch;
    max-width: 100%;
  }
  .table:not(.kv){
    min-width: 720px;
  }
  .table.kv{
    min-width: 0;
  }
}

/*
  Responsive tables
  -----------------
  Workflow log (and any other wide table) should not break the mobile layout.
  We keep the table layout but allow horizontal scroll on small screens.
*/
.table-responsive{
  width:100%;
  overflow-x:auto;
  -webkit-overflow-scrolling: touch;
}
.table-responsive .table{
  min-width: 720px; /* enough to keep columns readable */
}
.table th, .table td{
  padding: 10px 8px;
  border-bottom: 1px solid var(--border);
  vertical-align: middle;
  text-align:left;
}
.table th{
  font-size: 12px;
  color: var(--muted);
  text-transform: uppercase;
  letter-spacing: .6px;
}

/*
  Key/Value tables (used in Reports → Contacts / General information)
  - No ALL CAPS
  - Labels in bold / darker gray
  - Values normal
*/
.table.kv th{
  text-transform: none;
  letter-spacing: 0;
  font-weight: 700;
  color: #3b3b3b;
  width: 160px;
}

.table.kv td{
  color: #111;
}

/* Center TYPE + VERSION columns (Protocols tables) — not for key/value tables */
.table:not(.kv) th:nth-child(2), .table:not(.kv) td:nth-child(2),
.table:not(.kv) th:nth-child(3), .table:not(.kv) td:nth-child(3){
  text-align: center;
  white-space: nowrap;
}
.table:not(.kv) th:last-child, .table:not(.kv) td:last-child{
  text-align: right;
  white-space: nowrap;
}

/* Button stacks in table actions */
.table .btn-stack{
  display:flex;
  flex-direction: column;
  gap: 10px;
  align-items: flex-end;
}
.table .btn{ min-width: 96px; text-align:center; }
.table .badge{ justify-content:center; white-space: nowrap; }

/* KPI row */
.kpi{ display:flex; gap:10px; flex-wrap: wrap; }

/* Alerts */
.error{
  padding: 10px 12px;
  border-radius: 12px;
  background:#ffe8ea;
  border:1px solid #ffb3bb;
  margin-bottom: 12px;
}

/* Photos — shared grid (saved + new-selection preview) */
.photos {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 8px;
  margin-top: 8px;
}
@media (min-width: 560px) {
  .photos { grid-template-columns: repeat(4, 1fr); }
}

/* Clickable photo thumbnail link wrapper */
.photo-thumb-link {
  display: block;
  border-radius: 12px;
  overflow: hidden;
  border: 1px solid var(--border);
  transition: transform .15s ease, box-shadow .15s ease;
  flex-shrink: 0;
}
.photo-thumb-link:hover {
  transform: translateY(-2px);
  box-shadow: 0 4px 14px rgba(16,24,40,.14);
}

/* Photo thumbnails — both saved and preview */
.photos img {
  width: 100%;
  height: 100px;
  object-fit: cover;
  display: block;
}

/* Fallback for <a> wrapping the image in the old saved photos block */
.photos a {
  display: block;
  border-radius: 12px;
  overflow: hidden;
  border: 1px solid var(--border);
  transition: transform .15s ease, box-shadow .15s ease;
}
.photos a:hover {
  transform: translateY(-2px);
  box-shadow: 0 4px 14px rgba(16,24,40,.14);
}

/* Saved-photos section container */
.saved-photos-section {
  margin-top: 14px;
  padding: 12px 14px;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: #fafbfd;
}

/* Footer */
.footer{
  padding: 18px;
  text-align:center;
  color: var(--muted);
}

/* --- Technicians responsive: cards on mobile, table on desktop --- */
.tech-cards{ display:grid; gap:16px; }
.tech-card{
  border: 1px solid #e9e9ef;
  border-radius: var(--radius);
  padding: 14px;
  background:#fff;
}

.tech-top{
  display:flex;
  align-items:flex-start;
  justify-content:space-between;
  gap:12px;
}

.tech-name{ font-weight:800; font-size:1.05rem; }
.tech-email{ opacity:.75; font-size:.92rem; margin-top:4px; word-break: break-word; }
.tech-badge{ margin-top:2px; }

.tech-details{ margin-top:12px; }
.tech-details > summary{ list-style:none; }
.tech-details > summary::-webkit-details-marker{ display:none; }

.tech-view{ width:100%; text-align:center; margin-top:6px; }

.tech-meta{
  margin-top:14px;
  display:grid;
  gap:8px;
  padding-top:12px;
  border-top:1px solid #eee;
}

.tech-actions{
  margin-top:18px;
  display:grid;
  gap:12px;
}
.tech-disable{ margin-top:6px; }

.tech-table{ display:none; }

@media (min-width: 860px){
  .container{ max-width: 1280px; }
  .tech-cards{ display:none; }
  .tech-table{ display:block; }
}

/* Buttons inline on desktop, stacked on mobile (used in Plants/View etc.) */
.btn-row{
  display:flex;
  gap:10px;
  justify-content:flex-end;
  align-items:center;
  flex-wrap: wrap;
}
@media (max-width: 640px){
  .btn-row{ flex-direction: column; align-items: stretch; }
  .btn-row .btn{ width:100%; }
}

/* --- Topbar mobile dropdown --- */
.logo{ height:28px; width:auto; display:block; }

/* Brand block: logo + "SERVICE / PORTAL" sit on ONE row on every viewport.
   Mobile keeps the same row layout; only the font-size shrinks via the
   desktop @media block below. */
.brand-stack{
  display:flex;
  flex-direction:row;
  align-items:center;
  gap:10px;
  text-align:left;
}
.brand-text{
  display:flex;
  flex-direction:column;
  align-items:flex-start;
  gap:1px;
  border-left: 1px solid var(--border-strong);
  padding-left: 10px;
  margin-left: 2px;
}
.brand-subtitle{
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 1.2px;
  text-transform: uppercase;
  color: var(--muted);
  line-height: 1.05;
  margin: 0;
  white-space: nowrap;
}

.nav-desktop{ display:none; }

.nav-mobile{ position: relative; }
.hamburger{
  list-style:none;
  cursor:pointer;
  font-size:20px;
  padding: 8px 10px;
  border-radius: 12px;
  border: 1px solid var(--border-strong);
  background:#fff;
  color: var(--text);
}
.nav-mobile summary::-webkit-details-marker{ display:none; }

.nav-mobile-panel{
  position:absolute;
  right:0;
  top:46px;
  min-width:200px;
  background:#fff;
  border:1px solid var(--border);
  border-radius: 14px;
  box-shadow: 0 10px 30px rgba(0,0,0,0.08);
  padding:8px;
  display:grid;
  gap:6px;
  z-index:50;
}
.nav-mobile-panel a{
  padding:10px 10px;
  border-radius:12px;
  color: var(--text);
  font-weight: 700;
}
.nav-mobile-panel a:hover{ background:#f1f2f7; }

/* v0.2.0-pre100 — Topbar nav cutover raised from 860px to 1080px. At 860px
   the inline nav (DASHBOARD / REPORTS / INVENTORY / CUSTOMERS / PLANTS /
   TECHNICIANS / MANAGERS / DOCS) plus the user pill + Logout was being
   cropped at half-screen on a 1920px desktop (~960px viewport). Anything
   narrower than 1080px now falls back to the hamburger so the Logout
   stays reachable. */
@media (min-width: 1080px){
  .nav-desktop{
    display: flex;
    align-items: center;
    gap: 2px;
  }
  .nav-mobile{ display:none; }
  .brand-subtitle{ font-size:13px; }
}

/* Wider dashboard on very large screens */
@media (min-width: 1100px){
  .container{ max-width: 1400px; }
}


/* --- Responsive helpers --- */
.desktop-only{ display:block; }
.mobile-only{ display:none; }

/* Force visibility rules in both directions to avoid any cascade surprises */
@media (min-width: 769px){
  .desktop-only{ display:block !important; }
  .mobile-only{ display:none !important; }
}
@media (max-width: 768px){
  .desktop-only{ display:none !important; }
  .mobile-only{ display:block !important; }
}

.plant-card{
  position: relative;
  background:#fff;
  border:1px solid var(--border);
  border-radius:14px;
  padding:12px 14px;
  margin:10px 0;
  box-shadow: var(--shadow-soft);
  overflow: hidden;
}
/* v0.2.0-pre5: universal status accent strip on the left edge of any listing
   card. Tone names match the .section-card.is-* and .kpi-card.is-* tokens
   that dashboards and reports already use — so a customer card flagged with
   is-warning reads the same yellow as a "Pending validation" KPI on the
   dashboard. The strip is 3px wide and aligns flush with the card border.   */
.plant-card.is-danger::before,
.plant-card.is-warning::before,
.plant-card.is-info::before,
.plant-card.is-success::before,
.plant-card.is-purple::before,
.plant-card.is-primary::before,
.plant-card.is-neutral::before {
  content: '';
  position: absolute;
  left: 0; top: 0; bottom: 0;
  width: 3px;
}
.plant-card.is-danger::before  { background: var(--danger); }
.plant-card.is-warning::before { background: var(--warning); }
.plant-card.is-info::before    { background: var(--info); }
.plant-card.is-success::before { background: var(--success); }
.plant-card.is-purple::before  { background: var(--purple); }
.plant-card.is-primary::before { background: var(--primary); }
.plant-card.is-neutral::before { background: var(--muted-soft); }

/* v0.2.0-pre18: when a .plant-card is nested inside a .section-card that
   ALREADY carries a status accent, drop the inner card's accent strip.
   The outer bucket strip is the canonical signal — doubling it just
   stacks two parallel colored lines, which on mobile reads as visual
   noise. Desktop tables don't have this issue because they have no
   inner accent at all. */
.section-card.is-urgent  .plant-card::before,
.section-card.is-danger  .plant-card::before,
.section-card.is-warning .plant-card::before,
.section-card.is-info    .plant-card::before,
.section-card.is-success .plant-card::before,
.section-card.is-purple  .plant-card::before,
.section-card.is-primary .plant-card::before,
.section-card.is-neutral .plant-card::before,
.section-card.tint-blue   .plant-card::before,
.section-card.tint-indigo .plant-card::before,
.section-card.tint-purple .plant-card::before,
.section-card.tint-teal   .plant-card::before,
.section-card.tint-slate  .plant-card::before { content: none; }

/* v0.2.0-pre23: same suppression for legacy bespoke accent classes
   (.card-overdue, .card-pending-works) that draw their colored strip
   via border-left instead of the ::before pattern. The dashboard's
   REJECTED and PENDING WORKS mobile cards used these — they survived
   the pre18 fix and showed a doubled red/purple strip inside an
   already-toned section. Now suppressed too. */
.section-card.is-urgent  .plant-card.card-overdue,
.section-card.is-danger  .plant-card.card-overdue,
.section-card.is-warning .plant-card.card-overdue,
.section-card.is-info    .plant-card.card-overdue,
.section-card.is-purple  .plant-card.card-pending-works,
.section-card.is-purple  .plant-card.card-overdue,
.section-card.is-success .plant-card.card-overdue { border-left: 1px solid var(--border); }
.plant-title{ font-weight:800; font-size:15px; line-height:1.25; }
.plant-sub{ margin-top:3px; color: var(--muted); font-size:13px; line-height:1.35; }
/* v0.2.0-pre4: header row inside a card — title on the left, primary status
   on the right. Used by every listing's mobile card for consistency. */
.card-head-row{
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  margin-bottom: 2px;
}
.card-head-row .plant-title{ margin: 0; flex: 1; min-width: 0; word-break: break-word; }
.card-head-row .plant-status{ flex-shrink: 0; }
/* v0.2.0-pre4: actions footer — compact, right-aligned, no more 50/50 grid.
   Icon buttons sit flush; text buttons size to their content. */
.plant-actions{
  margin-top: 10px;
  display: flex;
  flex-wrap: wrap;
  justify-content: flex-end;
  align-items: center;
  gap: 6px;
}
.plant-actions .btn{ width: auto; }
.plant-actions .btn-icon{ margin: 0; }
.plant-actions .inline-action-form{ margin: 0; }
/* Inline info row inside the card (assignment, last activity, etc). */
.card-info-row{
  margin-top: 6px;
  font-size: 12.5px;
  color: var(--text-soft);
  line-height: 1.35;
}
.card-info-row .card-info-label{ color: var(--muted); margin-right: 4px; }

.step-card{ background:#fff; border:1px solid var(--border); border-radius:16px; padding:14px; margin:10px 0; box-shadow: var(--shadow-soft); }
.steps-cards{ max-width: 980px; margin: 0 auto; }
.step-top{ display:flex; gap:10px; align-items:flex-start; justify-content:space-between; }
.step-title{ font-weight:800; font-size:14px; line-height:1.25; }
.step-ref{ margin-top:8px; font-size:12px; color: var(--muted); }
.step-ins{ margin-top:8px; font-size:13px; color: var(--text); }

.photo-preview-wrap{ margin-top:10px; border-radius:14px; overflow:hidden; border:1px solid var(--border); display:none; }
.photo-preview-img{ width:100%; display:block; max-height:260px; object-fit:cover; }
.hint{ margin-top:8px; color: var(--muted); font-size: 0.9rem; }
.apu-line{ margin-top:8px; font-weight:800; }

/* Inline validation (server-side + client-side) */
.field-error{ color:#b00020; font-size:13px; margin-top:6px; }
.input-error{ border-color:#b00020 !important; box-shadow: 0 0 0 3px rgba(176,0,32,.12); }
/* Green confirmation — used by client-side validators (inventory serial, etc.) */
.input-ok{ border-color: var(--success) !important; box-shadow: 0 0 0 3px rgba(21,128,61,.12); }

/* =========================================================
   PHOTO REQUIRED / OPTIONAL - TOGGLE PILL (Protocols > Steps)
   - Used on protocols/view for managers (button submit)
   - For other roles it's shown as <span> (read-only)
   - Responsive friendly (mobile)
   ========================================================= */

/* The <form> wrapper stays inline so it doesn't break the step header layout. */
.photo-toggle-form {
  display: inline;
  margin: 0;
}

/* Base pill style (works for both <button> and <span>). */
.photo-pill {
  display: inline-flex;          /* centers text */
  align-items: center;
  justify-content: center;

  padding: 8px 14px;             /* pill size */
  border-radius: 999px;          /* capsule */
  font-weight: 700;
  font-size: 13px;

  border: 1px solid #cfe3f7;
  cursor: pointer;
  user-select: none;
  white-space: nowrap;

  transition: transform 0.05s ease, background 0.2s ease, border-color 0.2s ease;
}

/* Small feedback on click. */
.photo-pill:active {
  transform: scale(0.98);
}

/* OPTIONAL state (light grey). */
.photo-pill.is-optional {
  background: #f2f4f7;
  color: #333;
  border-color: #d8dde6;
}

/* REQUIRED state (the company-ish blue). */
.photo-pill.is-required {
  background: #e7f2ff;
  color: #0b5aa6;
  border-color: #9ec8f3;
}

/* Hover states. */
.photo-pill.is-optional:hover { background: #e9edf3; }
.photo-pill.is-required:hover { background: #d9ecff; }

/* Mobile sizing. */
@media (max-width: 600px) {
  .photo-pill {
    font-size: 12px;
    padding: 7px 12px;
  }
}

/* =========================================================
   v25 - Step Help accordion (wizard)
   ---------------------------------------------------------
   - Uses <details>/<summary> for a dependency-free dropdown
   - Mobile friendly + manual thumbnails + lightbox
   ========================================================= */

.help-accordion {
  margin-top: 12px;
  border: 1px solid #d7e7f7;
  border-radius: 10px;
  background: #ffffff;
  overflow: hidden;
}

.help-accordion summary {
  list-style: none;
  cursor: pointer;
  padding: 10px 12px;
  display: flex;
  align-items: center;
  gap: 10px;
  user-select: none;
}

.help-accordion summary::-webkit-details-marker { display: none; }

.help-accordion[open] summary {
  border-bottom: 1px solid #e6eef7;
  background: #f7fbff;
}

.help-pill {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 2px 8px;
  border-radius: 999px;
  font-size: 12px;
  font-weight: 800;
  background: #e7f2ff;
  color: #0b5aa6;
  border: 1px solid #9ec8f3;
}

.help-summary-text {
  font-weight: 800;
  color: #0b5aa6; /* corporate-ish blue */
}

.help-body {
  padding: 12px;
}

.help-sections {
  display: grid;
  grid-template-columns: 1fr;
  gap: 12px;
}

.help-section h4 {
  margin: 0 0 6px 0;
  font-size: 14px;
  font-weight: 800;
  color: #0b5aa6;
}

.help-section ul {
  margin: 0;
  padding-left: 18px;
  color: #333;
}

.help-section li {
  margin: 4px 0;
  line-height: 1.4;
}

.help-thumbs {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 10px;
}

@media (max-width: 700px) {
  .help-thumbs {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

.help-thumb {
  display: block;
  border: 1px solid #e0e7ef;
  border-radius: 10px;
  overflow: hidden;
  text-decoration: none;
  background: #fff;
}

.help-thumb img {
  width: 100%;
  height: 130px;
  object-fit: cover;
  display: block;
}

.help-thumb-label {
  padding: 6px 8px;
  font-size: 12px;
  color: #555;
}

.help-note {
  margin-top: 6px;
  font-size: 12px;
  color: #777;
}

/* =========================================================
   v25 - Lightbox (manual thumbnails)
   ========================================================= */

.lightbox {
  position: fixed;
  inset: 0;
  display: none;
  z-index: 9999;
}

.lightbox.open { display: block; }

.lightbox-backdrop {
  position: absolute;
  inset: 0;
  background: rgba(0,0,0,0.7);
}

.lightbox-content {
  position: absolute;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
  background: #fff;
  border-radius: 12px;
  padding: 12px;
  width: min(960px, 92vw);
  height: min(720px, 88vh);
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.lightbox-close {
  align-self: flex-end;
  border: none;
  background: transparent;
  font-size: 26px;
  cursor: pointer;
  line-height: 1;
}

.lightbox-img {
  width: 100%;
  height: 100%;
  object-fit: contain;
}

/* =========================================================
   v25 - Signatures (report view)
   ========================================================= */

.sig-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 14px;
}

@media (max-width: 900px) {
  .sig-grid { grid-template-columns: 1fr; }
}

.sig-card {
  border: 1px solid #e6eef7;
  border-radius: 12px;
  padding: 12px;
  background: #fff;
}

.sig-card h3 {
  margin: 0 0 10px 0;
}

.sig-preview {
  width: 100%;
  max-height: 200px;
  object-fit: contain;
  border: 1px solid #e0e7ef;
  border-radius: 10px;
  background: #fafafa;
}

.sig-canvas {
  width: 100%;
  height: 160px;
  border: 1px dashed #b9c7d6;
  border-radius: 10px;
  background: #fff;
  touch-action: none; /* allow drawing on mobile */
}

.sig-actions {
  margin-top: 10px;
  display: flex;
  gap: 10px;
  flex-wrap: wrap;
}

/* =========================================================
   v27 - Checklist responsive (report view)
   - Mobile: show cards (no horizontal scroll)
   - Desktop: show table
   ========================================================= */

.checklist-cards {
  display: grid;
  gap: 12px;
}

.check-card {
  border: 1px solid #e6eef7;
  border-radius: 12px;
  padding: 12px;
  background: #fff;
}

.check-top {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  gap: 12px;
}

.check-title {
  font-weight: 700;
}

.check-line {
  margin-top: 6px;
  font-size: 14px;
}

/* Hide the wide checklist table on phones */
.checklist-table {
  display: none;
}

/* Desktop breakpoint: table is nicer, cards are redundant */
@media (min-width: 900px) {
  .checklist-cards { display: none; }
  .checklist-table { display: table; }
}

/* =========================================================
   v30 — Software Versions: smart-field cards + responsive
   ---------------------------------------------------------
   Design rationale:
   - Field technician on-site, possibly with gloves / sunlight
   - Only render fields that apply to each component (data-driven)
   - Stack vertically on mobile + tablet (≤ 820px) for comfortable
     thumb-driven entry on any phone or tablet held in portrait
   - Large tap targets (≥ 46px), clear labels in sentence case
   - Filled-state indicator: subtle border tint + check icon at right
   - Desktop (> 820px): table with "—" cells for non-applicable fields
   - One single breakpoint (820px) covers start.php, edit.php and view.php
   ========================================================= */

/* ── Mobile + tablet: card grid (default — overridden at 820px) ── */
.swv-cards {
  display: grid;
  gap: 14px;
  margin-top: 14px;
}

/* Card shell */
.swv-card {
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--surface);
  overflow: hidden;
  box-shadow: var(--shadow-soft);
}

/* Coloured header strip — makes each component instantly identifiable */
.swv-comp-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 12px 14px;
  background: var(--primary-soft);
  border-bottom: 1px solid #cfe6f8;
}

.swv-comp-meta { min-width: 0; }

/* Component name */
.swv-comp-name {
  font-weight: 700;
  font-size: 15px;
  color: #0a3d6b;
  line-height: 1.2;
  letter-spacing: .1px;
}

/* Subtitle */
.swv-comp-subtitle {
  font-size: 12px;
  color: #3b6a94;
  margin-top: 2px;
  line-height: 1.3;
}

/* SW badge pill */
.swv-comp-badge {
  flex-shrink: 0;
  font-size: 11px;
  font-weight: 700;
  padding: 3px 10px;
  border-radius: 999px;
  background: #fff;
  color: #0a4f86;
  border: 1px solid #9ec8f3;
  letter-spacing: .3px;
}

/* Fields area — always stacked vertically */
.swv-fields {
  display: flex;
  flex-direction: column;
  gap: 12px;
  padding: 14px;
}

/* Individual field row */
.swv-field { min-width: 0; }

.swv-field label {
  display: block;
  font-size: 11px;
  font-weight: 700;
  color: var(--muted);
  letter-spacing: .4px;
  margin-bottom: 6px;
  text-transform: uppercase;
}

/* Input wrapper: holds input + filled-state checkmark */
.swv-input-wrap {
  position: relative;
}

/* Input inside card: comfortable size for field use (≥ 46px tap target).
   font-size: 16px prevents iOS Safari auto-zoom on focus. */
.swv-field .swn-ui-input {
  font-size: 16px;
  padding: 12px 38px 12px 14px; /* extra right padding for the checkmark */
  border-radius: 10px;
  width: 100%;
  min-height: 46px;
  transition: border-color .15s ease, box-shadow .15s ease, background-color .15s ease;
}

/* Filled-state: subtle tint on border + background, no layout shift */
.swv-field .swn-ui-input:not(:placeholder-shown) {
  border-color: rgba(0, 117, 201, 0.55);
  background: #f5fbff;
}

/* Filled-state checkmark — pure CSS, no extra assets */
.swv-check {
  position: absolute;
  top: 50%;
  right: 14px;
  transform: translateY(-50%) scale(.85);
  width: 18px;
  height: 18px;
  border-radius: 50%;
  background: var(--success, #1a6e31);
  opacity: 0;
  transition: opacity .15s ease, transform .15s ease;
  pointer-events: none;
}
.swv-check::after {
  content: "";
  position: absolute;
  left: 5px;
  top: 3px;
  width: 5px;
  height: 9px;
  border: solid #fff;
  border-width: 0 2px 2px 0;
  transform: rotate(45deg);
}
.swv-input-wrap:has(.swn-ui-input:not(:placeholder-shown)) .swv-check {
  opacity: 1;
  transform: translateY(-50%) scale(1);
}

/* Focus ring — accessible + premium */
.swv-field .swn-ui-input:focus,
.swv-field .swn-ui-input:focus-visible {
  outline: none;
  border-color: rgba(0, 117, 201, 0.85);
  box-shadow: 0 0 0 3px rgba(0, 117, 201, 0.18);
}

/* Read-only value display (view.php) — same card chrome, no inputs */
.swv-value {
  font-size: 16px;
  font-weight: 600;
  color: var(--text);
  padding: 10px 12px;
  min-height: 44px;
  display: flex;
  align-items: center;
  background: #f8fafc;
  border: 1px solid var(--border);
  border-radius: 10px;
}

/* ── Desktop (> 820px): hide cards, show table ───────────────── */
.swv-table-wrap { display: none; }

@media (min-width: 820px) {
  .swv-cards { display: none; }

  .swv-table-wrap {
    display: block;
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
    border-radius: var(--radius);
    border: 1px solid var(--border);
    margin-top: 14px;
    background: var(--surface);
  }

  .swv-table {
    min-width: 640px;
    margin: 0;
  }

  .swv-table thead th {
    background: var(--primary-soft);
    color: #0a4f86;
    padding: 11px 14px;
    font-weight: 700;
    letter-spacing: .2px;
  }

  .swv-table .swv-th-comp { width: 32%; }

  .swv-table td { padding: 10px 14px; vertical-align: middle; }

  .swv-tcell-name {
    font-weight: 700;
    color: var(--text);
    line-height: 1.2;
  }

  .swv-tcell-sub {
    font-size: 11px;
    color: var(--muted);
    margin-top: 2px;
  }

  .swv-table td input {
    width: 100%;
    min-width: 110px;
    padding: 9px 11px;
    transition: border-color .15s ease, background-color .15s ease;
  }

  .swv-table td input:not(:placeholder-shown) {
    border-color: rgba(0, 117, 201, 0.5);
    background: #fafdff;
  }

  .swv-table td input:focus,
  .swv-table td input:focus-visible {
    outline: none;
    border-color: rgba(0, 117, 201, 0.85);
    box-shadow: 0 0 0 3px rgba(0, 117, 201, 0.18);
  }

  /* Not-applicable cell marker */
  .swv-na {
    display: inline-block;
    color: var(--muted);
    opacity: .55;
    font-size: 14px;
    user-select: none;
  }

  /* Zebra rows for readability */
  .swv-table tbody tr:nth-child(even) td { background: #fafbfd; }
}

/* =========================================================
   v28 — Visual polish improvements
   =========================================================*/

/* Semantic badge states for report status */
.badge.is-completed    { background: #e6f9ec; color: #1a6e31; border-color: #a3dfb4; }
.badge.is-in_progress  { background: #fff8e1; color: #7a4f00; border-color: #ffe08a; }
.badge.is-validated    { background: #e7f2ff; color: #0b5aa6; border-color: #9ec8f3; }
.badge.is-rejected     { background: #ffe8ea; color: #8f001a; border-color: #ffb3bb; }
.badge.is-pending_validation { background: #f3eeff; color: #5b21b6; border-color: #c4b5fd; }
.badge.is-purple       { background: #f3eeff; color: #5b21b6; border-color: #c4b5fd; }
.badge.is-neutral      { background: #f1f3f6; color: #475569; border-color: #d8dde4; }

/* v0.2.0-pre26 — additional badge tones so the inventory status pills
   can match their section colour 1:1 (Registered blue, Assigned indigo,
   Scheduled purple, In commissioning warning-orange). */
.badge.is-indigo       { background: #ecedfb; color: #4338ca; border-color: #cccff0; }
.badge.is-warning      { background: #fff3e0; color: #b45309; border-color: #fcd9a4; }

/* v0.2.0-pre31 — Page-header CTA pill. Used by /inventory, /customers,
   and /plants for their "+ New X" action. Sits in the H1 row at the
   top-right of the page. Outlined primary at rest (visible but not
   shouting), fills on hover (clear it's an action). Replaces the old
   solid `btn primary` block which was too pushy at the page top. */
.action-pill {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 7px 14px;
  font-size: 13.5px;
  font-weight: 600;
  color: var(--primary);
  background: var(--surface);
  /* v0.2.0-pre35 — 1px border to visually match the .btn-icon next to it.
     The 1.5px was reading as a heavier "stronger" pill compared to the
     back-arrow chip beside it. */
  border: 1px solid var(--primary-border);
  border-radius: 10px;
  text-decoration: none;
  transition: background .15s ease, border-color .15s ease, color .15s ease, box-shadow .15s ease;
  white-space: nowrap;
  letter-spacing: 0.2px;
  line-height: 1;
  /* v0.2.0-pre105 — Anchor to the same effective height as .btn-icon (34px)
     so every outlined chip + icon-only button + form submit forms a single
     baseline across action-rows. Content stays centred via inline-flex
     align-items:center; padding is kept so the focus ring still breathes
     outside the text. */
  box-sizing: border-box;
  min-height: 34px;
}
/* v0.2.0-pre36 — Hover now matches .btn-icon.is-primary:hover (light blue
   tint, primary text), not the strong primary fill. Action chip + back
   arrow now read as siblings — one outlined-blue family that lights
   up softly on interaction. */
.action-pill:hover {
  background: var(--primary-soft);
  border-color: var(--primary-border);
  color: var(--primary-hover);
}
.action-pill svg { flex-shrink: 0; }
.action-pill:active { transform: translateY(1px); }

/* v0.2.0-pre90 — Disabled state for non-actionable pills (e.g. wizard
   step-1 "← Previous" with nowhere to go back to). Keeps the layout
   slot but visually mutes it and blocks interaction. */
.action-pill.is-disabled,
.action-pill[aria-disabled="true"] {
  opacity: .45;
  pointer-events: none;
  cursor: default;
}

/* v0.2.0-pre47 — Destructive variant. Same outlined-then-soft-fill
   choreography as the primary chip, but in danger red. Used for
   Retire / Delete actions where the user opted in to a section
   dedicated to that consequence. */
.action-pill-danger {
  color: #dc2626;
  border-color: var(--danger-border);
}
.action-pill-danger:hover {
  background: var(--danger-soft);
  border-color: var(--danger-border);
  color: #dc2626;
}

/* Make .action-pill work as a <button> too (form submits). Override the
   browser's default button styling (font, cursor). */
button.action-pill {
  font-family: inherit;
  cursor: pointer;
}

/* v0.2.0-pre34 — .action-pill-submit is the form-submit variant. Unlike
   the header CTA chip, the label here MUST stay readable on every
   width (a "+" alone isn't enough verb for a database-creating submit),
   so it's exempted from the mobile icon-only collapse. */
.action-pill-submit .action-pill-label { display: inline !important; }

/* v0.2.0-pre104 — Reverted the filled-primary look from pre65. The user
   preferred the outlined .action-pill style ("+ New plant" type chips)
   over the solid-blue submit. Now .action-pill-submit inherits the same
   outlined appearance as .action-pill — only the label-always-visible
   behaviour above survives. Geometry (padding, border width, font size)
   matches .action-pill exactly so submit buttons line up pixel-perfect
   with their neighbouring outlined pills (Cancel / Back / View summary).
   The focus ring is kept softer-than-default since this is still a form
   submit and benefits from a clear keyboard-focus indicator. */
.action-pill-submit:focus {
  outline: none;
  box-shadow: 0 0 0 4px rgba(0, 117, 201, 0.18);
}

@media (max-width: 540px) {
  /* v0.2.0-pre67 — Labels stay visible on mobile too. The previous rule
     collapsed every .action-pill on narrow widths to icon-only ("+", "✓")
     which made action rows (Send back, Cancel, Edit …) unreadable. The
     header CTA "+ New X" reads fine with a 5-char label even on 360px;
     not worth blowing up everything else to save those few pixels. */
  .action-pill { padding: 7px 12px; }
}
/* Opt-in: chips inside an .action-row right-rail (the H1's sibling) can
   still drop to icon-only on narrow viewports if a future page needs it.
   Add .action-pill-compact on the chip itself.
   v0.2.0-pre67 — explicit-opt-in beats global hide. */
@media (max-width: 540px) {
  .action-pill-compact .action-pill-label { display: none; }
}

/* v0.2.0-pre28 — Locked-record padlock in inventory rows. Inherits the
   bucket colour so a Commissioned row's lock reads green and a Retired
   row's lock reads red, matching the rest of that bucket's visuals. */
.inv-lock {
  display: inline-flex;
  align-items: center;
  color: var(--muted);
  font-size: 12px;
  vertical-align: middle;
}
.section-card.is-success .inv-lock { color: var(--success); }
.section-card.is-urgent  .inv-lock,
.section-card.is-danger  .inv-lock { color: #dc2626; }
.section-card.is-warning .inv-lock { color: var(--warning); }
.section-card.is-info    .inv-lock { color: var(--info); }
.section-card.is-purple  .inv-lock { color: var(--purple); }
.section-card.tint-blue   .inv-lock { color: #1d4e89; }
.section-card.tint-indigo .inv-lock { color: #4338ca; }
.section-card.tint-purple .inv-lock { color: var(--purple); }
.section-card.tint-teal   .inv-lock { color: #0f6e56; }
.section-card.tint-slate  .inv-lock { color: #475569; }

/* Improve h1 on desktop for more presence */
@media (min-width: 700px) {
  h1 { font-size: 26px; }
  h2 { font-size: 20px; }
}

/* Desktop brand block — same row layout as mobile, just bigger. */
@media (min-width: 860px) {
  .brand-stack { gap: 12px; }
  .brand-text  { padding-left: 12px; }
  .brand-subtitle { font-size: 13px; letter-spacing: 1.6px; }
  .brand img,
  .logo { height: 36px; }
}

/* Accordion spacing fix on mobile */
details.card + details.card,
details.card + details.card[open] {
  margin-top: 10px;
}

/* Slightly larger form inputs on mobile for field use */
@media (max-width: 700px) {
  input, select, textarea {
    font-size: 16px; /* prevents iOS auto-zoom on focus */
    padding: 12px 13px;
  }
}

/* =========================================================
   v29 — Utility classes (replaces inline styles)
   Reduces inline style duplication across views
   =========================================================*/

/* Alert / notification banners */
.alert {
  margin-top: 12px;
  padding: 10px 14px;
  border-radius: 10px;
  border: 1px solid;
  font-size: 14px;
  line-height: 1.5;
}
.alert-warning {
  background: #fffbeb;
  border-color: #f5d87a;
  color: #7a4f00;
}
.alert-info {
  background: #eef6ff;
  border-color: #93c5fd;
  color: #1e40af;
}
.alert-danger {
  background: #fff1f2;
  border-color: #fca5a5;
  color: #7f1d1d;
}
.alert-success {
  background: #f0fdf4;
  border-color: #86efac;
  color: #14532d;
}

/* v71 — audit alerts (manager_resubmitted, manager_edited_pending).
   Same base as .alert but with icon + text aligned in a flex row, and a
   slightly smaller type so they don't compete with the report header. */
.audit-alert {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  font-size: 13px;
  padding: 9px 13px;
}
.audit-alert .app-icon {
  flex-shrink: 0;
  margin-top: 2px;
}

/* Report meta line (site / serial / dates) */
.report-meta {
  margin-top: 10px;
  font-size: 14px;
  opacity: .75;
  line-height: 1.7;
}

/* Action row (flex row of buttons) */
.action-row {
  display: flex;
  gap: 10px;
  flex-wrap: wrap;
  margin-top: 12px;
  align-items: center;
}

/* v0.2.0-pre33 — When an .action-row wraps the page H1 (the "page header"
   pattern from /customers, /inventory, /plants, /docs detail, etc.) it
   sits at the very top of the content with no margin-top, and gets a
   real margin-bottom so the next block (KPI bar / intro paragraph)
   doesn't crowd the title.

   Button-rows used inside cards (Save / Cancel groups) don't have an
   H1 child, so they keep the default spacing. */
.action-row:has(> h1) {
  margin-top: 0;
  margin-bottom: 16px;
}

/* v0.2.0-pre103 — Back-arrow drift fix. Pages that pair an H1 with just an
   icon-only back arrow (e.g. /inverters/create, /inventory/create, edit
   forms…) used to inline `justify-content: space-between` so the arrow
   would float to the right edge. On wide viewports that meant a huge gap
   between the title and the lone arrow, which read as a layout bug.
   When the row contains an H1 and a .btn-icon but NO right-rail chip
   (.action-pill), pin them next to each other on the left. Listings that
   render H1 + chip ("+ New X") still get the spread — the chip belongs on
   the right rail because it's the primary CTA of the page. */
.action-row:has(> h1):has(> .btn-icon):not(:has(> .action-pill)) {
  justify-content: flex-start !important;
  gap: 12px !important;
}

/* v0.2.0-pre107 — Reject form block on reports/view.
   Vertical stack: dashed separator | label | textarea | right-aligned
   action-pill-danger. Replaces the legacy .reject-row flex layout
   where the button floated at the textarea's flex-end and read as a
   stranded corner element. Mobile: textarea expands, button falls
   below it (still right-aligned), tap-friendly. */
.reject-block {
  margin-top: 16px;
  padding-top: 14px;
  border-top: 1px dashed var(--border);
}
.reject-form { display: block; }
.reject-label {
  display: block;
  font-size: 13px;
  font-weight: 600;
  color: var(--text);
  margin-bottom: 6px;
}
.reject-label .text-muted-sm {
  display: inline-block;
  margin-left: 4px;
}
.reject-form textarea {
  width: 100%;
  resize: vertical;
}
.reject-actions {
  display: flex;
  justify-content: flex-end;
  margin-top: 12px;
}
@media (max-width: 540px) {
  .reject-actions { justify-content: stretch; }
  .reject-actions .action-pill {
    flex: 1;
    justify-content: center;
  }
  .reject-label .text-muted-sm {
    display: block;
    margin: 4px 0 0;
  }
}

/* Section intro paragraph */
.section-intro {
  opacity: .75;
  margin-top: 8px;
  font-size: 14px;
}

/* Signature signer name */
.sig-name {
  margin-top: 6px;
  font-size: 13px;
  opacity: .8;
}
.sig-empty {
  opacity: .7;
  font-size: 14px;
  margin-top: 4px;
}
.sig-grid {
  margin-top: 12px;
}

/* Signature sub-accordions */
.sig-accordion {
  margin-top: 10px;
}

/* Dashboard card header rows */
.card-header-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  flex-wrap: wrap;
}
.card-header-row h2 {
  margin: 0;
}

/* Dashboard hero text block */
.dash-hero {
  padding: 14px;
}
.dash-hero h2 {
  margin: 0 0 4px 0;
}
.dash-hero p {
  margin: 0;
  opacity: .75;
  font-size: 14px;
}

/* Table action cell */
.td-actions {
  white-space: nowrap;
}
.td-actions-inner {
  display: flex;
  gap: 10px;
  justify-content: flex-end;
  flex-wrap: wrap;
}

/* Muted small labels (e.g. protocol code under title) */
.text-muted-sm {
  opacity: .7;
  font-size: 13px;
}

/* Wizard: step header meta */
.step-meta {
  opacity: .75;
  margin-top: 10px;
  font-size: 14px;
}
.step-ref {
  font-size: 12px;
  opacity: .7;
}

/* Wizard: photo section */
.saved-photos-header {
  display: flex;
  align-items: center;
  gap: 6px;
  font-weight: 800;
  font-size: 14px;
  color: var(--text);
}
.wizard-nav {
  margin-top: 12px;
  display: flex;
  gap: 10px;
  flex-wrap: wrap;
}

/* =========================================================
   v0.3.0-pre4 — Workflow log: stacked entries (Option C)
   =========================================================
   Previous design used a 6-column desktop table that broke when the
   browser was at ~half-width: the Note column lost its space and the
   text pushed outside the card. This stacked layout works at every
   width with no breakpoints needed — each entry has a header row
   (time + actor + event badge), an optional state-transition row, and
   an optional note row that spans the full card width.
*/

.wf-log {
  display: grid;
  gap: 0;
}

.wf-entry {
  padding: 12px 0;
  border-bottom: 1px solid var(--border);
}
.wf-entry:first-child { padding-top: 4px; }
.wf-entry:last-child  { padding-bottom: 4px; border-bottom: 0; }

/* Top row: timestamp + actor + event badge on the right */
.wf-entry-head {
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: 6px 14px;
}

.wf-entry-time {
  font-size: 12px;
  color: var(--muted);
  white-space: nowrap;
  flex: 0 0 auto;
}

.wf-entry-actor {
  font-weight: 600;
  font-size: 13px;
  color: var(--text);
  flex: 1 1 auto;
  min-width: 0;
  word-break: break-word;
}

.wf-entry-event {
  flex: 0 0 auto;
  margin-left: auto;
  text-transform: capitalize;
}

/* Middle row: from → to state transition */
.wf-entry-meta {
  margin-top: 4px;
  font-size: 12px;
  color: var(--muted);
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
}

.wf-entry-status {
  /* v0.3.0-pre7 — Dropped the monospace family; it clashed with the
     rest of the project's typography (sans-serif everywhere else).
     The pill background alone is enough to signal "this is a state
     value". */
  font-size: 12px;
  background: var(--bg-soft, #f4f6f8);
  padding: 1px 8px;
  border-radius: 4px;
  color: var(--text);
}

.wf-entry-arrow {
  opacity: .5;
}

/* Bottom row: the free-form note. Always full-width inside the card,
   never overflows — long sentences wrap, long unbroken strings break. */
.wf-entry-note {
  margin-top: 8px;
  padding: 8px 12px;
  font-size: 13px;
  line-height: 1.5;
  color: var(--text);
  background: var(--bg-soft, #f4f6f8);
  border-left: 3px solid var(--border);
  border-radius: 0 4px 4px 0;
  word-break: break-word;
  overflow-wrap: anywhere;
  white-space: pre-wrap;
}

/* Mobile compactness — tighten gaps below 600px so each entry still
   reads cleanly on a phone-sized viewport. */
@media (max-width: 600px) {
  .wf-entry-head {
    gap: 4px 10px;
  }
  .wf-entry-event {
    margin-left: 0;          /* let it wrap to its own line if needed */
  }
}

/* =========================================================
   v31 — Wizard step header (no title repetition)
   =========================================================*/

.step-header-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  flex-wrap: wrap;
  margin-bottom: 10px;
}

.step-counter-pill {
  display: inline-flex;
  align-items: baseline;
  gap: 3px;
  background: var(--primary-soft);
  border: 1px solid #cfe6f8;
  border-radius: 999px;
  padding: 4px 12px;
}
.step-counter-num {
  font-size: 16px;
  font-weight: 800;
  color: #0a4f86;
}
.step-counter-of {
  font-size: 12px;
  color: #0a4f86;
  opacity: .7;
}

.step-header-meta {
  display: flex;
  gap: 8px;
  align-items: center;
  flex-wrap: wrap;
}

.step-main-title {
  font-size: 18px;
  font-weight: 800;
  margin: 0 0 8px 0;
  line-height: 1.3;
}

@media (min-width: 700px) {
  .step-main-title { font-size: 22px; }
}

/* v0.2.0-pre119 — Measurements table inside a wizard step.
   A step can declare a measurements config in fields_json that the
   wizard renders as one or more sectioned grids of compact numeric
   inputs. Mobile-first: single column under 540px, 2 cols on tablets,
   3 cols on desktop. Used by step 11 (AC + auxiliary voltage check)
   and reusable by any future step that needs structured numeric
   readings. */
.measure-section-wrap {
  display: grid;
  gap: 16px;
}
.measure-block {
  border: 1px solid var(--border, #d8e0ea);
  border-radius: 10px;
  padding: 12px 14px;
  background: var(--surface, #fff);
}
.measure-block-title {
  font-size: 12px;
  font-weight: 800;
  text-transform: uppercase;
  letter-spacing: .4px;
  color: var(--primary, #0075c9);
  margin-bottom: 10px;
}
.measure-grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: 10px 14px;
}
@media (min-width: 540px) { .measure-grid { grid-template-columns: 1fr 1fr; } }
@media (min-width: 860px) { .measure-grid { grid-template-columns: 1fr 1fr 1fr; } }
.measure-field {
  display: flex;
  flex-direction: column;
  gap: 4px;
  min-width: 0;
  margin: 0;
}
.measure-label {
  font-size: 12px;
  font-weight: 600;
  color: var(--muted, #5f6670);
  font-family: var(--font-mono, ui-monospace, monospace);
  letter-spacing: .3px;
}
.measure-input-wrap {
  display: flex;
  align-items: stretch;
  border: 1px solid var(--border-strong, #c8d0db);
  border-radius: 8px;
  background: var(--surface, #fff);
  transition: border-color .15s ease, box-shadow .15s ease;
}
.measure-input-wrap:focus-within {
  border-color: var(--primary, #0075c9);
  box-shadow: 0 0 0 3px rgba(0, 117, 201, 0.12);
}
.measure-input-wrap input {
  flex: 1 1 auto;
  min-width: 0;
  border: none;
  background: transparent;
  padding: 8px 10px;
  font-size: 14px;
  font-family: var(--font-mono, ui-monospace, monospace);
  font-weight: 600;
  color: var(--text, #1a1a2e);
  text-align: right;
  width: 100%;
}
.measure-input-wrap input:focus {
  outline: none;
  box-shadow: none;
  border: none;
}
.measure-unit {
  flex: 0 0 auto;
  padding: 8px 10px 8px 0;
  font-size: 13px;
  color: var(--muted, #5f6670);
  font-weight: 600;
  display: flex;
  align-items: center;
}

/* v0.2.0-pre119 — Saved measurements rendered inside the report view's
   checklist card. Read-only, compact, mobile-first grid that mirrors the
   editable grid above. */
.check-measurements {
  margin-top: 8px;
  display: grid;
  gap: 8px;
}
.check-meas-section {
  border: 1px solid var(--border, #d8e0ea);
  border-radius: 8px;
  padding: 8px 10px;
  background: var(--surface-alt, #f7f9fc);
}
.check-meas-title {
  font-size: 11px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .4px;
  color: var(--primary, #0075c9);
  margin-bottom: 6px;
}
.check-meas-grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: 4px 14px;
}
@media (min-width: 540px) { .check-meas-grid { grid-template-columns: 1fr 1fr; } }
@media (min-width: 860px) { .check-meas-grid { grid-template-columns: 1fr 1fr 1fr; } }
.check-meas-row {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 8px;
  font-size: 13px;
  border-bottom: 1px dashed var(--border, #d8e0ea);
  padding: 2px 0;
}
.check-meas-row:last-child { border-bottom: none; }
.check-meas-label {
  color: var(--muted, #5f6670);
  font-family: var(--font-mono, ui-monospace, monospace);
  letter-spacing: .3px;
}
.check-meas-value {
  font-weight: 700;
  color: var(--text, #1a1a2e);
  font-family: var(--font-mono, ui-monospace, monospace);
}
.check-meas-unit {
  font-size: 11px;
  font-weight: 600;
  color: var(--muted, #5f6670);
  margin-left: 2px;
}

.step-instruction {
  margin: 0 0 8px 0;
  opacity: .85;
  font-size: 14px;
  line-height: 1.55;
  /* v0.2.0-pre109 — Honour newlines and paragraph breaks coming from the
     protocol seed so multi-section procedures (e.g. "1. MV OFF, 2. DC OFF,
     3. Aux OFF, 4. Verify zero V") read as a numbered list rather than a
     wall of text. Existing single-paragraph instructions are unaffected. */
  white-space: pre-wrap;
}

.step-ref-line {
  display: flex;
  gap: 6px;
  align-items: baseline;
  font-size: 12px;
  color: var(--muted);
  margin-top: 4px;
}
.step-ref-label { font-weight: 700; }
.step-ref-value  { opacity: .85; }

/* =========================================================
   v31 — Datalogger file upload (Step 05)
   =========================================================*/

.datalogger-upload-section {
  margin-top: 18px;
  padding: 14px;
  border: 1px solid #cfe6f8;
  border-radius: var(--radius);
  background: var(--primary-soft);
}

.datalogger-upload-header {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  margin-bottom: 12px;
}

.datalogger-upload-icon {
  font-size: 20px;
  line-height: 1.2;
  flex-shrink: 0;
}

.datalogger-upload-title {
  font-weight: 800;
  font-size: 14px;
  color: #0a4f86;
}

.datalogger-upload-subtitle {
  font-size: 12px;
  color: #3b6a94;
  margin-top: 2px;
}

.datalogger-saved {
  margin-top: 10px;
  font-size: 13px;
  color: #1a6e31;
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: nowrap;
  background: #e6f9ec;
  border: 1px solid #a3dfb4;
  border-radius: 8px;
  padding: 9px 12px;
}

.datalogger-saved-info {
  flex: 1;
  min-width: 0;
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
}

.datalogger-saved-name {
  font-weight: 700;
  color: #1a6e31;
  word-break: break-all;
}

.datalogger-saved-size {
  font-size: 11px;
  color: #3a8a55;
  white-space: nowrap;
  background: #c5f0d3;
  padding: 1px 7px;
  border-radius: 999px;
}

.datalogger-saved-icon {
  font-size: 15px;
  color: #1a6e31;
  flex-shrink: 0;
}

/* v0.2.0-pre143 — Saved-attachment rows render the ✕ remove button inline
   inside the flex row (not absolute-positioned as on photo thumbnails).
   Override .photo-del-btn here so the same control works in both contexts. */
.datalogger-saved .photo-del-btn {
  position: static;
  flex-shrink: 0;
  margin-left: 8px;
}

/* v0.2.0-pre148 — Per-field validation marks. Server validates on submit;
   when something is missing the controller passes the input's name in
   missingFields[] and the view stamps these classes. Visual: red border on
   the input, red tint on the wrapping measurement/attachment block, and a
   red label for textareas / photo+attachment section headings. */
.is-invalid {
  border-color: #e53e3e !important;
  background: #fff5f5 !important;
  box-shadow: 0 0 0 2px rgba(229, 62, 62, .12);
}
.is-invalid:focus {
  border-color: #e53e3e !important;
  box-shadow: 0 0 0 3px rgba(229, 62, 62, .22);
}
.is-invalid-label {
  color: #c53030 !important;
  font-weight: 700;
}
.is-invalid-wrap .measure-label,
.is-invalid-wrap .measure-block-title,
.is-invalid-wrap .datalogger-upload-title {
  color: #c53030 !important;
}
.is-invalid-wrap.datalogger-upload-section {
  border-color: #f5a3a3 !important;
  background: #fff5f5 !important;
}

/* =========================================================
   v32 — Phone field with country prefix dropdown
   =========================================================*/

.phone-field { margin: 0; }

.phone-inner {
  display: flex;
  gap: 0;
  border: 1px solid var(--border-strong);
  border-radius: 12px;
  overflow: hidden;
  background: #fff;
  transition: box-shadow .15s ease, border-color .15s ease;
}

.phone-inner:focus-within {
  border-color: rgba(0,117,201,0.6);
  box-shadow: 0 0 0 4px rgba(0,117,201,0.15);
}

.phone-prefix-sel {
  /* Override global input styles */
  width: auto;
  min-width: 90px;
  max-width: 110px;
  flex-shrink: 0;
  border: none;
  border-right: 1px solid var(--border-strong);
  border-radius: 0;
  background: #f6f8fb;
  color: var(--text);
  font-size: 14px;
  padding: 10px 8px 10px 10px;
  cursor: pointer;
  outline: none;
  box-shadow: none;
  -webkit-appearance: none;
  appearance: none;
  /* Arrow */
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6'%3E%3Cpath d='M0 0l5 6 5-6z' fill='%235f6670'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 8px center;
  padding-right: 22px;
}

.phone-prefix-sel:focus {
  outline: none;
  box-shadow: none;
  border-color: var(--border-strong);
}

.phone-number-inp {
  flex: 1;
  min-width: 0;
  border: none;
  border-radius: 0;
  outline: none;
  box-shadow: none;
  padding: 10px 12px;
  font-size: 15px;
  background: #fff;
  color: var(--text);
}

.phone-number-inp:focus {
  outline: none;
  box-shadow: none;
}

/* Mobile: slightly larger touch targets */
@media (max-width: 700px) {
  .phone-prefix-sel { min-width: 86px; font-size: 15px; padding: 12px 22px 12px 10px; }
  .phone-number-inp { font-size: 16px; padding: 12px 12px; }
}

/* =========================================================
   v33 — Dashboard priority sections + Technician tracking
   =========================================================*/

/* ── KPI bar ─────────────────────────────────────────────*/
.dash-kpi-bar {
  display: flex;
  gap: 1px;
  background: var(--border);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  overflow: hidden;
  margin-bottom: 14px;
}
.dash-kpi-item {
  flex: 1;
  background: var(--bg);
  padding: 14px 10px;
  text-align: center;
  min-width: 0;
  transition: background .15s;
}
.dash-kpi-item.kpi-urgent  { background: #fff6f6; }
.dash-kpi-item.kpi-active  { background: #f0f7ff; }
.dash-kpi-item.kpi-rejected{ background: #fff8f0; }

.kpi-num {
  font-size: 26px;
  font-weight: 800;
  line-height: 1;
  color: var(--text);
}
.kpi-label {
  font-size: 11px;
  font-weight: 500;
  color: var(--muted);
  margin-top: 4px;
  text-transform: uppercase;
  letter-spacing: .4px;
}
.kpi-urgent  .kpi-num { color: #c0392b; }
.kpi-active  .kpi-num { color: var(--primary); }
.kpi-rejected .kpi-num { color: #e67e22; }

@media (max-width: 500px) {
  .kpi-num { font-size: 20px; }
  .kpi-label { font-size: 10px; }
  .dash-kpi-item { padding: 10px 6px; }
}

/* ── Priority section header ─────────────────────────────*/
.dash-section-title {
  display: flex;
  align-items: center;
  gap: 10px;
}
.dash-section-title h2 { margin: 0; }

.dash-priority-dot {
  width: 10px; height: 10px;
  border-radius: 50%;
  flex-shrink: 0;
}
.dot-urgent { background: #e74c3c; box-shadow: 0 0 0 3px rgba(231,76,60,.2); }
.dot-active { background: var(--primary); box-shadow: 0 0 0 3px rgba(0,117,201,.15); }

.dash-count-badge {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 22px;
  height: 22px;
  border-radius: 999px;
  font-size: 12px;
  font-weight: 700;
  padding: 0 6px;
  background: #fde8e8;
  color: #c0392b;
  margin-left: 6px;
  vertical-align: middle;
}
.dash-count-blue { background: #dbeafe; color: #1e40af; }

/* ── Priority card accent ────────────────────────────────*/
.dash-priority-card {
  border-top: 3px solid #e74c3c !important;
}

/* =========================================================
   v40 — Dashboard refresh: semantic KPIs + icon-led sections
   ---------------------------------------------------------
   New classes live alongside legacy (.dash-kpi-bar, etc.)
   while the migration is in progress. Once all views adopt
   the v2 markup we'll delete the legacy block.
   =========================================================*/

/* ── KPI bar v2: independent semantic cards ──────────────── */
.kpi-grid {
  display: grid;
  /* v0.4.0 — minmax(0,1fr) so tracks can shrink below content min-width and
     never force horizontal overflow on narrow screens (mobile KPI cards). */
  grid-template-columns: repeat(6, minmax(0, 1fr));
  gap: 10px;
  margin-bottom: 20px;
}

@media (max-width: 1100px) {
  .kpi-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}
@media (max-width: 560px) {
  .kpi-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 8px; }
}

/* Opt-in: pages with exactly 4 KPI cards (e.g. inventory/view) want a
   4-col layout on desktop instead of the default 6-col. Mobile still
   collapses to 2-col via the base rule above. */
.kpi-grid.kpi-grid-cols-4 { grid-template-columns: repeat(4, minmax(0, 1fr)); }
@media (max-width: 720px) {
  .kpi-grid.kpi-grid-cols-4 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

.kpi-card {
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding: 14px 14px 13px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 12px;
  text-decoration: none;
  transition: border-color .15s ease, transform .05s ease, box-shadow .15s ease;
  min-width: 0;
}

.kpi-card:hover {
  border-color: var(--muted-soft);
  box-shadow: var(--shadow-soft);
}

.kpi-card:active { transform: translateY(1px); }

.kpi-card-head {
  display: flex;
  align-items: center;
  gap: 8px;
  min-width: 0;
}

.kpi-card-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 24px;
  height: 24px;
  border-radius: 6px;
  flex-shrink: 0;
  background: var(--bg);
  color: var(--muted);
}

.kpi-card-label {
  font-size: 10.5px;
  font-weight: 600;
  color: var(--muted);
  letter-spacing: .5px;
  text-transform: uppercase;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  /* v0.4.0 — flex item must allow shrink below its (nowrap) content so the
     ellipsis kicks in and 2-col KPI cards never overflow narrow phones. */
  min-width: 0;
}

.kpi-card-num {
  font-size: 28px;
  font-weight: 700;
  line-height: 1;
  color: var(--text);
  font-variant-numeric: tabular-nums;
  letter-spacing: -0.5px;
}

/* Semantic variants — active when the count is > 0.
   v0.2.0-pre28 — KPI danger tone bumped from `--danger` (#b91c1c, quite
   dark) to red-600 #dc2626 so the X icon stroke and big number actually
   read as red on the soft pink card background. */
.kpi-card.is-danger { background: #fff8f7; border-color: var(--danger-border); }
.kpi-card.is-danger .kpi-card-icon  { background: var(--danger-soft);  color: #dc2626; }
.kpi-card.is-danger .kpi-card-label { color: #dc2626; }
.kpi-card.is-danger .kpi-card-num   { color: #dc2626; }

.kpi-card.is-warning { background: #fffbf3; border-color: var(--warning-border); }
.kpi-card.is-warning .kpi-card-icon  { background: var(--warning-soft); color: var(--warning); }
.kpi-card.is-warning .kpi-card-label { color: var(--warning); }
.kpi-card.is-warning .kpi-card-num   { color: var(--warning); }

.kpi-card.is-info { background: #f5f9ff; border-color: var(--info-border); }
.kpi-card.is-info .kpi-card-icon  { background: var(--info-soft);    color: var(--info); }
.kpi-card.is-info .kpi-card-label { color: var(--info); }
.kpi-card.is-info .kpi-card-num   { color: var(--info); }

.kpi-card.is-success { background: #f4faf6; border-color: var(--success-border); }
.kpi-card.is-success .kpi-card-icon  { background: var(--success-soft); color: var(--success); }
.kpi-card.is-success .kpi-card-label { color: var(--success); }
.kpi-card.is-success .kpi-card-num   { color: var(--success); }

.kpi-card.is-purple { background: #faf7fd; border-color: var(--purple-border); }
.kpi-card.is-purple .kpi-card-icon  { background: var(--purple-soft); color: var(--purple); }
.kpi-card.is-purple .kpi-card-label { color: var(--purple); }
.kpi-card.is-purple .kpi-card-num   { color: var(--purple); }

/* Total — summary KPI. Neutral fill but stronger border + brand-blue
   accents so it reads as "this is the roll-up of the row above" instead
   of looking like an unstyled card next to all the tinted ones. */
.kpi-card.is-total {
  background: var(--surface);
  border-color: #9ec8f3;
}
.kpi-card.is-total .kpi-card-icon  { background: #e6f1fb; color: #0a4f86; }
.kpi-card.is-total .kpi-card-label { color: #0a4f86; }
.kpi-card.is-total .kpi-card-num   { color: #0a4f86; }

/* Descriptive tinted variants — used for stat KPIs (not status).
   Distinct from semantic .is-* which signal urgency/state.
   Tints are subtle: light tinted background + icon chip in the
   matching tone. Labels and numbers stay in neutral text color
   so they don't compete with semantic states elsewhere. */
.kpi-card.tint-blue   { background: #f3f7fc; border-color: #d0dded; }
.kpi-card.tint-blue   .kpi-card-icon { background: #dbe9f7; color: #1d4e89; }

.kpi-card.tint-teal   { background: #f1faf7; border-color: #c8e6db; }
.kpi-card.tint-teal   .kpi-card-icon { background: #d4ede4; color: #0f6e56; }

.kpi-card.tint-indigo { background: #f5f5fc; border-color: #d8d8ed; }
.kpi-card.tint-indigo .kpi-card-icon { background: #e3e3f6; color: #4338ca; }

.kpi-card.tint-purple { background: #f9f5fc; border-color: #e4d4ee; }
.kpi-card.tint-purple .kpi-card-icon { background: #efe1f6; color: #6b21a8; }

.kpi-card.tint-slate  { background: #f5f6f8; border-color: #d8dde4; }
.kpi-card.tint-slate  .kpi-card-icon { background: #e2e6ed; color: #475569; }

/* v0.2.0-pre6 fix — Section-card tints mirror the KPI palette so the
   bucket headers on /inventory and /reports use the SAME colour as the
   KPI cards at the top of the page. */
.section-card.tint-blue::before,
.section-card.tint-indigo::before,
.section-card.tint-purple::before,
.section-card.tint-teal::before,
.section-card.tint-slate::before {
  content: ''; position: absolute; left: 0; top: 0; bottom: 0; width: 3px;
}
.section-card.tint-blue::before    { background: #1d4e89; }
.section-card.tint-indigo::before  { background: #4338ca; }
.section-card.tint-purple::before  { background: #6b21a8; }
.section-card.tint-teal::before    { background: #0f6e56; }
.section-card.tint-slate::before   { background: #475569; }

.section-head-icon.tint-blue   { background: #dbe9f7; color: #1d4e89; }
.section-head-icon.tint-indigo { background: #e3e3f6; color: #4338ca; }
.section-head-icon.tint-purple { background: #efe1f6; color: #6b21a8; }
.section-head-icon.tint-teal   { background: #d4ede4; color: #0f6e56; }
.section-head-icon.tint-slate  { background: #e2e6ed; color: #475569; }

.count-badge.tint-blue    { background: #dbe9f7; color: #1d4e89; }
.count-badge.tint-indigo  { background: #e3e3f6; color: #4338ca; }
.count-badge.tint-purple  { background: #efe1f6; color: #6b21a8; }
.count-badge.tint-teal    { background: #d4ede4; color: #0f6e56; }
.count-badge.tint-slate   { background: #e2e6ed; color: #475569; }

/* Active filter state (for reports/index.php KPI bar) */
.kpi-card.is-current {
  border-color: var(--primary);
  box-shadow: 0 0 0 3px var(--primary-soft);
}

@media (max-width: 560px) {
  .kpi-card { padding: 11px 12px; gap: 6px; }
  .kpi-card-num { font-size: 22px; }
  .kpi-card-label { font-size: 9.5px; }
  .kpi-card-icon { width: 22px; height: 22px; }
  .kpi-card-icon svg { width: 12px; height: 12px; }
}

/* ── Priority section card — left accent variant ─────────── */
.section-card {
  position: relative;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 18px 20px;
  box-shadow: var(--shadow-soft);
  margin-bottom: 14px;
  overflow: hidden;
}

.section-card.is-urgent::before,
.section-card.is-warning::before,
.section-card.is-info::before,
.section-card.is-success::before,
.section-card.is-purple::before,
.section-card.is-neutral::before {
  content: '';
  position: absolute;
  left: 0;
  top: 0;
  bottom: 0;
  width: 3px;
}

.section-card.is-urgent::before  { background: var(--danger); }
.section-card.is-warning::before { background: var(--warning); }
.section-card.is-info::before    { background: var(--info); }
.section-card.is-success::before { background: var(--success); }
.section-card.is-purple::before  { background: var(--purple); }
.section-card.is-neutral::before { background: var(--muted); }

/* v0.2.0-pre19 — H2 inside a toned section-card takes the bucket colour
   (PENDING WORKS purple, REJECTED red, AWAITING yellow, etc). Wins over
   the global `h2 → primary` rule via increased specificity (.section-card
   prefix). The count-badge already carries the same tone, so the section
   title now reads as a coherent coloured unit. */
.section-card.is-urgent  .section-head h2 { color: #dc2626; }
.section-card.is-danger  .section-head h2 { color: #dc2626; }
.section-card.is-warning .section-head h2 { color: var(--warning); }
.section-card.is-info    .section-head h2 { color: var(--info); }
.section-card.is-success .section-head h2 { color: var(--success); }
.section-card.is-purple  .section-head h2 { color: var(--purple); }
.section-card.is-neutral .section-head h2 { color: var(--muted); }

/* v0.2.0-pre19 — "View all" / "All protocols" / "View on Reports" header
   actions previously rendered as a plain `.btn sm` chip, which fights with
   the section card's quieter aesthetic. .section-link is a ghost pill:
   transparent at rest, primary-tint on hover, with a chevron that nudges
   right. Reads as a link, not a CTA. */
.section-link {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding: 5px 11px;
  font-size: 12.5px;
  font-weight: 600;
  color: var(--primary);
  text-decoration: none;
  letter-spacing: 0.2px;
  border-radius: 999px;
  border: 1px solid transparent;
  background: transparent;
  transition: background 0.15s, border-color 0.15s, color 0.15s;
  white-space: nowrap;
  flex-shrink: 0;
}
.section-link::after {
  content: '→';
  font-weight: 500;
  transition: transform 0.15s;
}
.section-link:hover {
  background: var(--primary-soft);
  border-color: var(--primary-border);
}
.section-link:hover::after {
  transform: translateX(2px);
}
/* When inside a toned section-card, the chevron link picks up the bucket
   colour so it reads as part of that section's visual unit. */
.section-card.is-urgent  .section-link,
.section-card.is-danger  .section-link { color: var(--danger); }
.section-card.is-warning .section-link { color: var(--warning); }
.section-card.is-info    .section-link { color: var(--info); }
.section-card.is-success .section-link { color: var(--success); }
.section-card.is-purple  .section-link { color: var(--purple); }
.section-card.is-urgent  .section-link:hover,
.section-card.is-danger  .section-link:hover { background: var(--danger-soft);  border-color: var(--danger-border); }
.section-card.is-warning .section-link:hover { background: var(--warning-soft); border-color: var(--warning-border); }
.section-card.is-info    .section-link:hover { background: var(--info-soft);    border-color: var(--info-border); }
.section-card.is-success .section-link:hover { background: var(--success-soft); border-color: var(--success-border); }
.section-card.is-purple  .section-link:hover { background: var(--purple-soft);  border-color: var(--purple-border); }

@media (max-width: 640px) {
  .section-card { padding: 14px 16px; }
}

/* ── Section header (icon + title + count badge + action) ── */
.section-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  margin-bottom: 4px;
}

.section-head-left {
  display: flex;
  align-items: center;
  gap: 10px;
  min-width: 0;
  flex: 1;
}

.section-head-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 28px;
  height: 28px;
  border-radius: 8px;
  flex-shrink: 0;
  background: var(--bg);
  color: var(--muted);
}

.section-head-icon.is-danger  { background: var(--danger-soft);  color: #dc2626; }
.section-head-icon.is-urgent  { background: var(--danger-soft);  color: #dc2626; }
.section-head-icon.is-warning { background: var(--warning-soft); color: var(--warning); }
.section-head-icon.is-info    { background: var(--info-soft);    color: var(--info); }
.section-head-icon.is-success { background: var(--success-soft); color: var(--success); }
.section-head-icon.is-purple  { background: var(--purple-soft);  color: var(--purple); }
.section-head-icon.is-neutral { background: var(--bg);  color: var(--muted); border: 1px solid var(--border); }

.section-head h2 {
  margin: 0;
  font-size: 17px;
  font-weight: 600;
  color: var(--text);
  letter-spacing: -0.1px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.section-intro {
  font-size: 13px;
  color: var(--muted);
  margin: 6px 0 14px;
  line-height: 1.5;
}

/* Semantic count badge (replaces dash-count-badge inline-styled hardcoding) */
.count-badge {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 22px;
  height: 22px;
  border-radius: 999px;
  font-size: 12px;
  font-weight: 700;
  padding: 0 8px;
  font-variant-numeric: tabular-nums;
  flex-shrink: 0;
  background: var(--bg);
  color: var(--muted);
}

.count-badge.is-danger  { background: var(--danger-soft);  color: #dc2626; }
.count-badge.is-urgent  { background: var(--danger-soft);  color: #dc2626; }
.count-badge.is-warning { background: var(--warning-soft); color: var(--warning); }
.count-badge.is-info    { background: var(--info-soft);    color: var(--info); }
.count-badge.is-success { background: var(--success-soft); color: var(--success); }
.count-badge.is-purple  { background: var(--purple-soft);  color: var(--purple); }
.count-badge.is-neutral { background: var(--bg);  color: var(--muted); border: 1px solid var(--border-strong); }

/* On mobile, hide the "View all" button text and just show an arrow icon */
@media (max-width: 480px) {
  .section-head { gap: 10px; }
  .section-head h2 { font-size: 15px; }
}

/* ── Auxiliary utilities used by dashboard tables/cards ──── */
.th-actions { width: 1%; white-space: nowrap; }

.td-truncate {
  max-width: 280px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.text-warning-soft {
  color: var(--warning);
  font-weight: 500;
}

.text-purple-soft {
  color: var(--purple);
  font-weight: 500;
}

.plant-sub-quote {
  margin-top: 4px;
  font-style: italic;
  color: var(--muted);
}

.card-pending-works {
  border-left: 3px solid var(--purple);
}

/* Commissioning certifications — small inline badges shown on the tech
   list and on tech avatars in plant views. Internal vs external uses
   different tones so it's obvious at a glance whether a tech got their
   cert from the company or from a partner course. */
.cert-badges {
  display: inline-flex;
  flex-wrap: wrap;
  gap: 4px;
}
.cert-badge {
  display: inline-flex;
  align-items: center;
  padding: 2px 8px;
  font-size: 11px;
  font-weight: 700;
  border-radius: 999px;
  border: 1px solid transparent;
  white-space: nowrap;
  font-family: var(--font-mono, monospace);
  letter-spacing: 0.02em;
}
.cert-badge.cert-internal {
  background: var(--primary-soft);
  color: var(--primary);
  border-color: var(--primary-border);
}
.cert-badge.cert-external {
  background: #e6fffa;        /* soft teal */
  color: #0f766e;             /* teal-700 */
  border-color: #99f6e4;
}

/* =========================================================
   Contact row (Site contacts editor) — formerly inline styles
   so the same layout can also be applied via the standalone
   "Manage contacts" page without duplicating CSS.
   ========================================================= */
.contact-row {
  border: 1px solid var(--border);
  border-radius: 10px;
  padding: 12px;
  margin-bottom: 10px;
  background: #fafbfd;
}

/* =========================================================
   Read-only company name display in customer edit. Mirrors the
   serial-readonly chip pattern used in inventory/edit so the
   visual language is consistent.
   ========================================================= */
.company-readonly {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 10px 14px;
  background: #f6f8fb;
  border: 1px dashed var(--border-strong);
  border-radius: 10px;
  margin-bottom: 4px;
  flex-wrap: wrap;
}
.company-readonly-name {
  font-weight: 700;
  color: var(--text);
  font-size: 15px;
}
.company-readonly-note {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  color: var(--muted);
  font-size: 13px;
}
.company-readonly-note svg { flex: 0 0 auto; }

/* Per-workflow accent stripe on report cards. Matches the parent
   section-card's left accent so the visual semantic ladder
   (red = problem · amber = waiting · blue = active · purple = needs
   works · green = done) is consistent down to the card level. */
.card-accent-rejected   { border-left: 3px solid var(--danger); }
.card-accent-pending    { border-left: 3px solid var(--warning); }
.card-accent-in-process { border-left: 3px solid var(--info); }
.card-accent-validated  { border-left: 3px solid var(--success); }

/* When a report is actually overdue (open > 72h and still actionable),
   the time counter turns red — a less aggressive signal than painting
   the whole card border. The accent stripe stays in its semantic
   color so users still see at a glance which bucket the card belongs
   to. */
.plant-card.is-overdue .time-overdue {
  color: var(--danger);
  font-weight: 700;
}

/* Apply Inter consistently to inline SVG icons sized by the helper */
.app-icon { display: inline-block; vertical-align: -2px; flex-shrink: 0; }

/* Improvement flag: refresh to use the semantic token + icon-friendly inline layout */
.improvement-flag {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  margin-top: 6px;
  padding: 3px 9px;
  background: var(--warning-soft);
  color: var(--warning);
  border: 1px solid var(--warning-border);
  border-radius: 999px;
  font-size: 11px;
  font-weight: 600;
  white-space: nowrap;
  cursor: help;
}
.improvement-flag .app-icon { vertical-align: 0; }

/* ── Page title meta — small muted suffix next to <h1> ──── */
.page-title-meta {
  font-size: 16px;
  font-weight: 400;
  color: var(--muted);
  margin-left: 6px;
}

/* ── Alert with right-aligned action button ──────────────── */
.alert-with-action {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 10px;
  margin-bottom: 14px;
}
.alert-with-action > span {
  display: inline-flex;
  align-items: center;
  gap: 6px;
}

/* ── Filters card / form ─────────────────────────────────── */
.filters-card {
  padding: 14px 16px;
  margin-bottom: 14px;
}

.filters-row {
  display: flex;
  gap: 10px;
  flex-wrap: wrap;
  align-items: flex-end;
}

.filters-field { display: flex; flex-direction: column; }
.filters-field--grow { flex: 1; min-width: 200px; }

.filters-field label {
  font-size: 12px;
  font-weight: 600;
  color: var(--muted);
  margin-bottom: 4px;
  letter-spacing: 0.1px;
}

.filters-field input,
.filters-field select {
  margin: 0;
}

.filters-actions {
  display: flex;
  gap: 8px;
  align-items: flex-end;
  /* v0.2.0-pre74 — Dropped the legacy `padding-bottom: 1px` that shifted
     children up by a pixel relative to a flex-end input row. */
}

/* v0.2.0-pre74 — Make the lupa share the input's box exactly. The input
   geometry is: padding 10px×2 + line-height ~19.6px (14px × 1.4) +
   border 1px×2 ≈ 41.6px. So we set the btn-icon to the same effective
   height by using padding 12px×2 + 16px icon + border 1px×2 = 42px and
   override width to keep the chip square. This avoids the previous
   off-by-a-pixel that made the magnifier sit visibly above the input. */
.filters-actions .btn-icon {
  width: 42px;
  height: 42px;
  padding: 0;
}

/* v0.2.0-pre101 — Clear sat at ~32px tall (default .btn padding/line-height)
   next to the 42px lupa, breaking the baseline. Stretch the text button to
   the same effective height as the input + lupa so the row reads as one
   strip. */
.filters-actions .btn {
  height: 42px;
  padding: 0 16px;
  line-height: 42px;
}

@media (max-width: 640px) {
  .filters-row { flex-direction: column; align-items: stretch; }
  .filters-field--grow { width: 100%; }
  .filters-actions { width: 100%; }
  .filters-actions .btn { flex: 1; }
}

/* ── Advanced filters disclosure ─────────────────────────── */
.adv-filters {
  margin-top: 12px;
}

.adv-filters-toggle {
  background: none;
  border: none;
  cursor: pointer;
  font-family: var(--font-sans);
  font-size: 13px;
  color: var(--primary);
  font-weight: 600;
  padding: 0;
  display: inline-flex;
  align-items: center;
  gap: 6px;
}
.adv-filters-toggle:hover { color: var(--primary-hover); }

.adv-filters-chevron {
  display: inline-flex;
  transition: transform .2s ease;
  color: currentColor;
}
.adv-filters-chevron.is-open { transform: rotate(90deg); }

.adv-filters-panel {
  margin-top: 12px;
  padding-top: 12px;
  border-top: 1px solid var(--border);
}

.adv-filters-count {
  font-size: 10px;
  padding: 2px 7px;
  margin-left: 4px;
}

/* ── Empty state ──────────────────────────────────────────── */
.empty-state {
  text-align: center;
  padding: 40px 24px;
  color: var(--muted);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 12px;
}
.empty-state-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 56px;
  height: 56px;
  border-radius: 14px;
  background: var(--bg);
  color: var(--muted-soft);
}
.empty-state p { margin: 0; font-size: 14px; }

/* =========================================================
   v43 — Users views (Technicians, Managers)
   =========================================================*/

.user-name-link {
  font-weight: 600;
  color: var(--primary);
  text-decoration: none;
}
.user-name-link:hover { text-decoration: underline; }

.user-name-bold { font-weight: 600; color: var(--text); }

.user-card-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 8px;
  margin-bottom: 10px;
}

.user-metrics-grid {
  display: grid;
  gap: 8px;
  grid-template-columns: repeat(4, 1fr);
  margin-top: 6px;
}

.user-metric {
  text-align: center;
  padding: 8px 4px;
  background: var(--bg);
  border-radius: 8px;
}
.user-metric-num {
  font-size: 18px;
  font-weight: 700;
  color: var(--text);
  letter-spacing: -0.3px;
  line-height: 1;
}
.user-metric-num.num-active   { color: var(--warning); }
.user-metric-num.num-overdue  { color: var(--danger); }
.user-metric-label {
  font-size: 10.5px;
  font-weight: 600;
  color: var(--muted);
  text-transform: uppercase;
  letter-spacing: 0.4px;
  margin-top: 4px;
}

/* Disabled state for user rows and cards */
.row-disabled {
  opacity: 0.55;
}
.is-disabled-card {
  opacity: 0.6;
}

/* Profile page */
.profile-shell {
  max-width: 560px;
  margin: 0 auto;
}

.profile-meta {
  margin-top: 18px;
  border-top: 1px solid var(--border);
  padding-top: 14px;
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.profile-meta-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  font-size: 13.5px;
  gap: 12px;
}

.profile-meta-label {
  color: var(--muted);
  font-weight: 500;
}

.profile-meta-value {
  color: var(--text);
  font-weight: 500;
  text-align: right;
}

/* Two-column form grid for fields that pair naturally (name+email, etc.).
   Falls back to single column on narrow viewports. */
.form-grid-2 {
  display: grid;
  gap: 14px 16px;
  grid-template-columns: 1fr 1fr;
  margin-bottom: 14px;
}
@media (max-width: 560px) {
  .form-grid-2 { grid-template-columns: 1fr; }
}

/* Inline helper text below a disabled/locked field */
.form-helper {
  font-size: 12px;
  color: var(--muted);
  margin-top: 6px;
  margin-bottom: 14px;
  line-height: 1.4;
}

/* =========================================================
   v44 — Protocols views (steps list)
   =========================================================*/

.proto-admin-note {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  margin-top: 14px;
  padding: 12px 14px;
  background: var(--info-soft);
  border: 1px solid var(--info-border);
  border-radius: 10px;
  font-size: 12.5px;
  line-height: 1.55;
  color: #0a4f86;
}
.proto-admin-note-icon {
  flex-shrink: 0;
  color: var(--info);
  margin-top: 2px;
}
.proto-admin-note code {
  font-family: var(--font-mono);
  font-size: 11.5px;
  background: rgba(0,0,0,0.06);
  padding: 1px 5px;
  border-radius: 4px;
}

.steps-list {
  display: flex;
  flex-direction: column;
  gap: 10px;
  margin-top: 6px;
}

.step-card {
  border: 1px solid var(--border);
  border-radius: 10px;
  padding: 14px 16px;
  background: var(--surface);
  transition: border-color .15s, background .15s;
}
.step-card:hover { border-color: var(--border-strong); }

.step-top {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 12px;
  flex-wrap: wrap;
}

.step-title {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 8px;
  min-width: 0;
  flex: 1;
}

.step-no {
  display: inline-block;
  background: var(--bg);
  color: var(--text);
  padding: 3px 9px;
  border-radius: 6px;
  font-size: 11.5px;
  font-weight: 700;
  letter-spacing: 0.5px;
  text-transform: uppercase;
  flex-shrink: 0;
}

.step-section-badge {
  display: inline-block;
  background: var(--info-soft);
  color: var(--info);
  border: 1px solid var(--info-border);
  padding: 2px 8px;
  border-radius: 999px;
  font-size: 10.5px;
  font-weight: 700;
  letter-spacing: 0.3px;
  text-transform: uppercase;
}

.step-title-text {
  font-weight: 600;
  font-size: 14px;
  color: var(--text);
  line-height: 1.4;
}

.step-pills {
  display: flex;
  align-items: center;
  gap: 6px;
  flex-wrap: wrap;
  flex-shrink: 0;
}

.step-pill {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding: 4px 10px;
  border-radius: 999px;
  font-size: 11.5px;
  font-weight: 600;
  border: 1px solid transparent;
  background: var(--bg);
  color: var(--muted);
  cursor: default;
}
.step-pill.is-required {
  background: var(--info-soft);
  color: var(--info);
  border-color: var(--info-border);
}
.step-pill.is-optional {
  background: var(--bg);
  color: var(--muted);
  border-color: var(--border);
}
button.step-pill { cursor: pointer; font-family: inherit; }
button.step-pill:hover { filter: brightness(0.96); }

.photo-toggle-form { margin: 0; display: inline-block; }

.step-ins {
  margin-top: 10px;
  font-size: 13.5px;
  color: var(--text);
  line-height: 1.55;
}

.step-ref {
  margin-top: 6px;
  display: inline-flex;
  align-items: center;
  gap: 5px;
  font-size: 12px;
  color: var(--muted);
}

.step-attach-hint {
  margin-top: 8px;
  display: inline-flex;
  align-items: center;
  gap: 5px;
  font-size: 12px;
  color: var(--muted);
  background: var(--bg);
  padding: 4px 10px;
  border-radius: 6px;
}

/* ── Progress column inside report tables ────────────────── */
.td-progress { min-width: 110px; }
.prog-steps-lbl { font-size: 11px; }

/* ── Pending Works hint inside a normal table row ───────── */
.row-pending-works-hint {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  margin-top: 4px;
  max-width: 320px;
  font-size: 11.5px;
  color: var(--warning);
  font-weight: 600;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  cursor: help;
}
.row-pending-works-hint span {
  overflow: hidden;
  text-overflow: ellipsis;
}

/* ── Meta badges row inside mobile plant-card ────────────── */
.plant-meta-badges {
  display: flex;
  gap: 6px;
  flex-wrap: wrap;
  align-items: center;
  margin-top: 2px;
}

/* =========================================================
   Pending Works section (view.php)
   ---------------------------------------------------------
   Two visual states:
     - .is-warning  → unresolved (amber tones)
     - .is-success  → resolved   (green tones, history block)
   =========================================================*/

.pw-header {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 12px;
  margin-bottom: 12px;
}

.pw-header-left {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  min-width: 0;
  flex: 1;
}

.pw-header-meta { min-width: 0; }

.pw-title {
  /* v0.2.0-pre67 — Match the default h2 weight (600) so it sits at the
     same visual level as the other section titles ("4 CHECKLIST FOR ...",
     "6 COMMISSIONING FINISHED ..."). pre64 used 700 which made this one
     read slightly heavier than its neighbours. */
  margin: 0;
  font-size: 19px;
  font-weight: 600;
  color: var(--primary);
  text-transform: uppercase;
  letter-spacing: 0.4px;
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 8px;
  line-height: 1.3;
}

.pw-subtitle {
  font-size: 12.5px;
  color: var(--muted);
  margin-top: 4px;
}

.pw-header-actions {
  display: flex;
  gap: 6px;
  align-items: center;
  flex-shrink: 0;
}

/* ── Read view: list of pending items ────────────────────── */
.pw-list {
  margin: 0;
  padding-left: 20px;
  display: flex;
  flex-direction: column;
  gap: 6px;
}

.pw-list li {
  font-size: 14px;
  color: var(--text);
  line-height: 1.5;
}

.pw-list.is-resolved li {
  color: var(--muted);
  text-decoration: line-through;
}

.pw-empty {
  font-size: 13px;
  color: var(--muted);
  font-style: italic;
  margin: 0;
}

/* ── Resolution history block (shown when resolved) ──────── */
.pw-resolution {
  margin-top: 14px;
  padding: 14px 16px;
  background: var(--success-soft);
  border: 1px solid var(--success-border);
  border-radius: 10px;
}

.pw-resolution-head {
  display: flex;
  align-items: center;
  gap: 7px;
  font-size: 13px;
  font-weight: 600;
  color: var(--success);
}

.pw-resolution-head strong {
  font-weight: 700;
  color: var(--success);
}

.pw-resolution-label {
  margin-top: 10px;
  font-size: 11px;
  font-weight: 700;
  color: var(--success);
  text-transform: uppercase;
  letter-spacing: 0.5px;
}

.pw-resolution-body {
  margin-top: 4px;
  font-size: 13.5px;
  color: var(--text);
  line-height: 1.55;
}

/* ── Edit view ───────────────────────────────────────────── */
.pw-edit-view { margin-top: 14px; }

.pw-edit-block { margin-bottom: 16px; }

.pw-label {
  font-size: 12px;
  font-weight: 600;
  color: var(--muted);
  display: block;
  margin-bottom: 6px;
  letter-spacing: 0.1px;
}

.pw-label-optional {
  font-weight: 400;
  color: var(--muted-soft);
}

.pw-required { color: var(--danger); margin-left: 2px; }

.pw-help-text {
  font-size: 11px;
  color: var(--muted);
  margin-top: 6px;
  margin-bottom: 10px;
  line-height: 1.4;
  font-style: italic;
}

.pw-textarea,
.pw-input {
  width: 100%;
  margin-bottom: 0;
  font-family: var(--font-sans);
}

.pw-textarea {
  resize: vertical;
  min-height: 90px;
}

.pw-edit-actions {
  display: flex;
  gap: 8px;
  align-items: center;
  margin-top: 10px;
}

/* Mark-as-resolved sub-block (inside edit view) */
.pw-resolve-block {
  background: var(--success-soft);
  border: 1px solid var(--success-border);
  border-radius: 10px;
  padding: 16px;
}

.pw-resolve-head {
  display: flex;
  align-items: center;
  gap: 7px;
  font-size: 13.5px;
  font-weight: 700;
  color: var(--success);
  margin-bottom: 14px;
}

.pw-resolve-block .pw-input,
.pw-resolve-block .pw-textarea {
  margin-bottom: 12px;
  background: var(--surface);
  border-color: var(--success-border);
}

.pw-resolve-block .pw-input:focus,
.pw-resolve-block .pw-textarea:focus {
  border-color: var(--success);
  box-shadow: 0 0 0 4px rgba(21, 128, 61, 0.12);
}

.pw-resolve-btn {
  background: var(--success);
  border-color: var(--success);
  color: #fff;
}
.pw-resolve-btn:hover {
  background: #126932;
  border-color: #126932;
  color: #fff;
}

/* Loading / busy state for any button awaiting AJAX */
.btn.is-busy {
  opacity: 0.65;
  pointer-events: none;
  position: relative;
}

/* Inline input error state (used in pwResolvedBy validation) */
.input-error {
  border-color: var(--danger) !important;
  box-shadow: 0 0 0 3px rgba(185, 28, 28, 0.12) !important;
}

/* ── Report UID small ────────────────────────────────────*/
.report-uid-sm {
  font-size: 12px;
  font-weight: 600;
  font-family: var(--font-mono, monospace);
  color: var(--text);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  max-width: 200px;
}

/* ── Time labels ─────────────────────────────────────────*/
.time-overdue { color: #c0392b; font-weight: 700; }
.time-normal  { color: var(--muted); }

/* ── Stalled / overdue rows ──────────────────────────────*/
.row-overdue { background: #fff9f9; }
.card-overdue { border-left: 3px solid #e74c3c; }

/* ── Progress bar ────────────────────────────────────────*/
.prog-bar-wrap {
  background: var(--border);
  border-radius: 999px;
  height: 6px;
  overflow: hidden;
  margin-bottom: 3px;
}
.prog-bar {
  background: var(--primary);
  height: 100%;
  border-radius: 999px;
  transition: width .3s ease;
  min-width: 2px;
}
.prog-bar--done {
  background: #1a7f37;
}

/* ── Insight bar ─────────────────────────────────────────*/
.insight-bar {
  display: flex;
  gap: 10px;
  flex-wrap: wrap;
  margin-bottom: 14px;
}
.insight-chip {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 8px 14px;
  border-radius: 999px;
  font-size: 13px;
  border: 1px solid;
}
.insight-speed {
  background: #f0fdf4; border-color: #86efac; color: #14532d;
}
.insight-load {
  background: #eff6ff; border-color: #93c5fd; color: #1e40af;
}
.insight-icon { font-size: 16px; }

/* ── Tracking table ──────────────────────────────────────*/
.tracking-table th, .tracking-table td {
  vertical-align: middle;
}
.th-center { text-align: center !important; }
.th-right  { text-align: right !important; }
.badge-col { min-width: 52px; }
.time-cell { font-variant-numeric: tabular-nums; font-size: 13px; }

.tech-name-cell {
  font-weight: 600;
  font-size: 14px;
  color: var(--text);
}

/* ── Load badge ──────────────────────────────────────────*/
.load-badge {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 28px;
  height: 28px;
  border-radius: 999px;
  font-size: 13px;
  font-weight: 800;
  padding: 0 6px;
}
.load-high { background: #fde8e8; color: #c0392b; }
.load-med  { background: #fef9c3; color: #78350f; }
.load-low  { background: #f0fdf4; color: #14532d; }

/* ── Technician metrics grid (mobile) ────────────────────*/
.tech-metrics-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 8px;
  margin: 12px 0 0;
  text-align: center;
}
.tech-metric-num {
  font-size: 20px;
  font-weight: 800;
  line-height: 1;
}
.tech-metric-label {
  font-size: 11px;
  color: var(--muted);
  margin-top: 3px;
}
.num-active  { color: var(--primary); }
.num-overdue { color: #c0392b; }

/* =========================================================
   v41 — Auth screens: login, register, password fields
   ---------------------------------------------------------
   Password classes (.password-*) replace the old (.pw-*)
   namespace, which now belongs exclusively to Pending Works
   in reports/view.php. This avoids selector collisions.
   =========================================================*/

/* ── Standalone auth layout (login / register) ───────────── */
.auth-page {
  min-height: 100vh;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 32px 16px;
  max-width: none;        /* override .container max-width if inherited */
}

body.is-auth {
  background: var(--bg);
}

.auth-shell { width: 100%; max-width: 420px; }

/* Brand block above the auth card */
.auth-brand {
  display: flex;
  flex-direction: column;
  align-items: center;
  margin-bottom: 24px;
}

.auth-brand-mark {
  width: 56px;
  height: 56px;
  background: var(--primary);
  border-radius: 14px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  margin-bottom: 14px;
  color: #fff;
  box-shadow: 0 4px 12px rgba(0, 117, 201, 0.18);
}

/* v0.2.0-pre15 — login no longer shows the the company wordmark; the product
   name is the big title. .auth-brand-name / .auth-brand-tag are kept
   defined for backward-compat (other views may still use them) but the
   login template uses .auth-brand-title below. */
.auth-brand-name {
  font-size: 11px;
  font-weight: 700;
  color: var(--muted);
  letter-spacing: 1.4px;
  text-transform: uppercase;
  margin-bottom: 3px;
}

.auth-brand-tag {
  font-size: 13px;
  color: var(--muted);
}

.auth-brand-title {
  margin: 4px 0 0;
  font-size: 26px;
  font-weight: 700;
  color: var(--primary);
  letter-spacing: -0.4px;
  line-height: 1.2;
  text-align: center;
}
@media (min-width: 700px) {
  .auth-brand-title { font-size: 30px; }
}

.auth-card-title {
  font-size: 20px;
  font-weight: 700;
  letter-spacing: 1.4px;
  text-transform: uppercase;
  color: var(--primary);
  margin: 0 0 6px;
}

/* Main auth card */
.auth-card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 16px;
  padding: 28px 28px 24px;
  box-shadow: 0 1px 3px rgba(16, 24, 40, 0.04);
}

.auth-card h1 {
  font-size: 22px;
  font-weight: 700;
  margin: 0 0 6px;
  letter-spacing: -0.3px;
}

.auth-card-intro {
  font-size: 13.5px;
  color: var(--muted);
  line-height: 1.55;
  margin: 0 0 22px;
}

.auth-card label { margin-top: 0; }
.auth-card .auth-field { margin-bottom: 14px; }
.auth-card .auth-field:last-of-type { margin-bottom: 18px; }

/* Inline error message above form */
.auth-error {
  display: flex;
  align-items: flex-start;
  gap: 8px;
  padding: 10px 12px;
  background: var(--danger-soft);
  border: 1px solid var(--danger-border);
  border-radius: 10px;
  color: var(--danger);
  font-size: 13px;
  font-weight: 500;
  line-height: 1.4;
  margin-bottom: 18px;
}

.auth-error .app-icon { flex-shrink: 0; margin-top: 1px; }

/* Submit button uses .btn.primary.full — no extra styling here */

/* Demo credentials hint card */
.auth-demo-hint {
  margin-top: 14px;
  padding: 12px 14px;
  background: var(--primary-soft);
  border: 1px solid var(--primary-border);
  border-radius: 10px;
  font-size: 11.5px;
  color: #0a4f86;
  line-height: 1.55;
}

.auth-demo-hint-title {
  font-weight: 700;
  letter-spacing: 0.2px;
  margin-bottom: 6px;
}

.auth-demo-hint-row {
  font-family: var(--font-mono);
  font-size: 11px;
  display: flex;
  align-items: baseline;
  gap: 8px;
}

.auth-demo-hint-role {
  display: inline-block;
  min-width: 64px;
  font-weight: 600;
  letter-spacing: 0.2px;
}

.auth-footer {
  margin-top: 18px;
  text-align: center;
  font-size: 11.5px;
  color: var(--muted-soft);
}

/* ── Password input + visibility toggle ──────────────────── */
.password-field {
  position: relative;
  display: flex;
  align-items: center;
}

.password-field input {
  flex: 1;
  padding-right: 44px; /* room for the toggle button */
}

.password-toggle {
  position: absolute;
  right: 0;
  top: 0;
  height: 100%;
  width: 42px;
  display: flex;
  align-items: center;
  justify-content: center;
  background: transparent;
  border: none;
  cursor: pointer;
  color: var(--muted);
  border-radius: 0 10px 10px 0;
  transition: color .15s, background-color .15s;
  padding: 0;
}

.password-toggle:hover {
  color: var(--text);
  background: rgba(0, 0, 0, 0.04);
}

.password-toggle:focus-visible {
  outline: none;
  box-shadow: 0 0 0 3px rgba(0, 117, 201, 0.25);
}

/* ── Legacy aliases (kept for create_user.php compatibility)
   Will be removed once that view is migrated to .password-*  */
.pw-field-wrap { position: relative; display: flex; align-items: center; }
.pw-field-wrap .pw-input { flex: 1; padding-right: 44px; }
.pw-field-wrap .pw-toggle {
  position: absolute; right: 0; top: 0; height: 100%; width: 42px;
  display: flex; align-items: center; justify-content: center;
  background: transparent; border: none; cursor: pointer;
  color: var(--muted); border-radius: 0 10px 10px 0; padding: 0;
}
.pw-field-wrap .pw-toggle:hover { color: var(--text); background: rgba(0,0,0,.04); }

/* Legacy login classes — kept until view migrated, but auth-* is the new way */
.login-card { max-width: 480px; margin: 0 auto; }

/* Responsive: smaller padding on tiny phones */
@media (max-width: 420px) {
  .auth-page { padding: 20px 12px; }
  .auth-card { padding: 22px 20px 20px; }
  .auth-brand-mark { width: 48px; height: 48px; }
}

/* =========================================================
   v42 — Plants index & view: aligned with v40 visual system
   =========================================================*/

/* KPI numbers that are strings (e.g. "5.8 MW") are typeset
   slightly smaller so they fit in the same card width */
.kpi-card-num-string {
  font-size: 22px;
  letter-spacing: -0.3px;
  line-height: 1.2;
  word-break: break-word;
}
/* Long status labels like "In commissioning" need more breathing room
   on narrow phones — shrink the type so they wrap to two lines instead
   of clipping. */
@media (max-width: 720px) {
  .kpi-card-num-string { font-size: 15px; }
}

/* Insight bar (largest plant hint) */
.insight-bar {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-bottom: 14px;
  padding: 10px 14px;
  background: var(--primary-soft);
  border: 1px solid var(--primary-border);
  border-radius: 10px;
  font-size: 13px;
  color: #0a4f86;
}
.insight-bar .insight-icon {
  display: inline-flex;
  align-items: center;
  color: var(--primary);
}

/* Plant header card */
.plant-header-card {
  position: relative;
}

.plant-header-row {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  gap: 14px;
  flex-wrap: wrap;
  margin-bottom: 14px;
}

.plant-header-meta { min-width: 0; flex: 1; }
.plant-header-meta h1 { margin: 0 0 4px; }

.plant-header-sub {
  font-size: 13.5px;
  color: var(--muted);
  line-height: 1.4;
  /* v0.3.0-pre16 — let the subtitle breathe under the H1 (the inline
     style="margin:0" on the H1 in plants/view.php was crushing the gap).
     v0.3.0-pre19 — also push down from the next block (KPI section card),
     which sat flush against the address line and felt cramped. */
  margin-top: 6px;
  margin-bottom: 14px;
}

.plant-header-actions {
  display: flex;
  gap: 8px;
  flex-wrap: wrap;
  align-items: flex-start;
}
.plant-header-actions-secondary {
  display: flex;
  gap: 8px;
  flex-wrap: wrap;
}

/* Mobile: stack the whole header so action buttons never overlap the title.
   Title takes the full width on its own row; secondary actions (Back / Edit)
   sit below at their natural size; the primary "Start report here" — the main
   reason the user is on this screen during report creation — spans full width
   and is easy to tap. */
@media (max-width: 640px) {
  .plant-header-row {
    flex-direction: column;
    align-items: stretch;
    gap: 12px;
  }
  .plant-header-meta { flex: none; width: 100%; }
  .plant-header-actions {
    width: 100%;
    flex-direction: column;
    gap: 10px;
  }
  .plant-header-actions-secondary {
    width: 100%;
  }
  .plant-header-actions-secondary .btn {
    flex: 1;
    justify-content: center;
  }
  .plant-header-start {
    width: 100%;
    justify-content: center;
    padding-top: 11px;
    padding-bottom: 11px;
    font-weight: 600;
  }
}

/* KPI grid inside plant header is more compact.
   v0.3.0-pre21 — give it the standard kpi-grid bottom margin again. The
   previous "margin-bottom: 0" only made sense when this grid lived inside
   a section-card wrap (dropped in pre20); without that wrap the grid was
   sitting flush against the next section. */
.plant-kpi-grid {
  margin-bottom: 18px;
  grid-template-columns: repeat(5, 1fr);
}
@media (max-width: 1000px) {
  .plant-kpi-grid { grid-template-columns: repeat(3, 1fr); }
}
@media (max-width: 560px) {
  .plant-kpi-grid { grid-template-columns: repeat(2, 1fr); }
}

/* Plant name link inside list — v0.2.0-pre38: primary-blue at rest (was
   inherit/black). Matches .user-name-link on /customers so plant names
   read as the actionable identity of the row everywhere.
   v0.2.0-pre43: weight aligned to 600 (was 700) so the plant column and
   the customer column on their respective listings render with identical
   visual weight. */
.plant-name-link {
  display: block;
  color: var(--primary);
  text-decoration: none;
  font-weight: 600;
}
.plant-name-link:hover { text-decoration: underline; }

.plant-name-bold { font-weight: 600; color: var(--primary); }

/* Commissioning status pills (refined from comm-badge) */
.comm-pill {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 3px 10px;
  border-radius: 999px;
  font-size: 11.5px;
  font-weight: 600;
  white-space: nowrap;
  border: 1px solid transparent;
}

/* Pills group wrapper: flex with gap so cold/hot pills never touch,
   and wrap cleanly to the next line when the column is narrow */
.comm-pill-group {
  display: flex;
  flex-wrap: wrap;
  gap: 5px 6px;
  align-items: center;
}

.comm-pill .app-icon { vertical-align: 0; }

.comm-cold-done    { background: var(--success-soft); color: var(--success); border-color: var(--success-border); }
.comm-cold-partial { background: var(--info-soft);    color: var(--info);    border-color: var(--info-border); }
.comm-cold-missing { background: var(--bg);           color: var(--muted);   border-color: var(--border); }
.comm-hot-done     { background: var(--info-soft);    color: var(--info);    border-color: var(--info-border); }
.comm-hot-partial  { background: var(--warning-soft); color: var(--warning); border-color: var(--warning-border); }
.comm-hot-missing  { background: var(--bg);           color: var(--muted);   border-color: var(--border); }

/* Legacy comm-badge classes — keep as alias during migration */
.comm-badge { display: inline-flex; align-items: center; gap: 4px;
  padding: 3px 10px; border-radius: 999px; font-size: 11.5px; font-weight: 600; border: 1px solid transparent; }
.comm-cold-done.comm-badge    { background: var(--success-soft); color: var(--success); border-color: var(--success-border); }
.comm-cold-partial.comm-badge { background: var(--info-soft); color: var(--info); border-color: var(--info-border); }
.comm-cold-missing.comm-badge { background: var(--bg); color: var(--muted); border-color: var(--border); }
.comm-hot-done.comm-badge     { background: var(--info-soft); color: var(--info); border-color: var(--info-border); }
.comm-hot-partial.comm-badge  { background: var(--warning-soft); color: var(--warning); border-color: var(--warning-border); }
.comm-hot-missing.comm-badge  { background: var(--bg); color: var(--muted); border-color: var(--border); }

/* Comm row inside a mobile plant-card */
.plant-comm-row {
  margin-top: 8px;
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
}

/* Details card with summary used by plant info disclosure */
/* v0.2.0-pre77 — Use the same .card chrome (padding, border, shadow) so
   "Plant & contact details" reads as a regular site card, not a stripped
   collapsible. The chevron stays on the right; the h2 inside picks up
   the standard uppercase blue section heading style. */
.plant-details-card { padding: 18px 20px; }
.plant-details-card[open] { padding: 18px 20px; }

.plant-details-summary {
  cursor: pointer;
  padding: 0;
  display: flex;
  align-items: center;
  gap: 8px;
  list-style: none;
  user-select: none;
}
/* The h2 inside the summary inherits the uppercase blue site h2 style. */
.plant-details-summary h2 {
  color: var(--primary);
  text-transform: uppercase;
  letter-spacing: 0.4px;
  font-size: 19px;
  font-weight: 600;
}
.plant-details-summary h2 svg { color: var(--primary); }
.plant-details-summary::-webkit-details-marker { display: none; }
.plant-details-summary::after {
  content: '';
  margin-left: auto;
  width: 8px;
  height: 8px;
  border-right: 2px solid var(--muted);
  border-bottom: 2px solid var(--muted);
  transform: rotate(-45deg);
  transition: transform .15s ease;
}
.plant-details-card[open] .plant-details-summary { padding: 0; margin-bottom: 14px; }
.plant-details-card[open] .plant-details-summary::after { transform: rotate(45deg); }

.plant-details-grid {
  display: grid;
  gap: 24px;
  grid-template-columns: 1fr 1fr;
}
.plant-details-grid h3 {
  margin: 0 0 8px;
  font-size: 12px;
  font-weight: 700;
  color: var(--muted);
  text-transform: uppercase;
  letter-spacing: .5px;
}
@media (max-width: 720px) {
  .plant-details-grid { grid-template-columns: 1fr; }
}

/* =========================================================
   v35 — Hot commissioning prerequisite UI
   =========================================================*/

.cold-report-list {
  display: grid;
  gap: 8px;
  margin-top: 10px;
}

.cold-report-option {
  display: flex;
  align-items: flex-start;
  gap: 12px;
  padding: 12px 14px;
  border: 1px solid var(--border-strong);
  border-radius: var(--radius);
  background: #fff;
  cursor: pointer;
  transition: border-color .15s, background .15s;
}

.cold-report-option:hover { border-color: var(--primary); }

.cold-report-option input[type="radio"] {
  margin-top: 3px;
  flex-shrink: 0;
  width: auto;
  accent-color: var(--primary);
}

.cold-selected {
  border-color: var(--primary);
  background: var(--primary-soft);
}

.cold-option-uid {
  font-weight: 700;
  font-size: 13px;
  font-family: var(--font-mono, monospace);
  color: var(--text);
}

.cold-option-meta {
  font-size: 12px;
  color: var(--muted);
  margin-top: 2px;
}

/* =========================================================
   v36 — Hot commissioning: cold prefill card
   =========================================================*/

.cold-prefill-card {
  border-left: 4px solid var(--primary) !important;
  background: #f6faff !important;
}

.cold-prefill-header {
  display: flex;
  flex-direction: column;
  gap: 4px;
  margin-bottom: 14px;
  padding-bottom: 10px;
  border-bottom: 1px solid var(--border);
}

.cold-prefill-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
  gap: 10px;
}

.cold-prefill-label {
  display: block;
  font-size: 11px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .4px;
  color: var(--muted);
  margin-bottom: 2px;
}

.cold-prefill-value {
  display: block;
  font-size: 14px;
  font-weight: 500;
  color: var(--text);
}

@media (max-width: 600px) {
  .cold-prefill-grid { grid-template-columns: 1fr 1fr; }
}

/* =========================================================
   v37 — Plants view, avatars, user pill in topbar
   =========================================================*/

/* ── Serial number badge ─────────────────────────────────*/
/* v0.2.0-pre95 — Serial badge slimmed down to plain corporate-blue
   bold mono text. The pill chrome (soft-blue bg + border) read fine on
   wide screens but on tablet/phone the rounded chip pushed neighboring
   text to wrap awkwardly and competed with real action chips. Anyone
   who needs the chip styling back can opt-in with .serial-badge-chip. */
.serial-badge {
  font-family: var(--font-mono, monospace);
  font-size: 13px;
  font-weight: 700;
  color: var(--primary);
  white-space: nowrap;
}
.serial-badge-chip {
  background: var(--primary-soft);
  padding: 2px 8px;
  border-radius: 6px;
  border: 1px solid #cfe6f8;
}
.serial-badge-sm {
  font-family: var(--font-mono, monospace);
  font-size: 11px;
  color: var(--primary);
  white-space: nowrap;
}

/* v0.2.0-pre20 — Body-sized monospace serial for the reports table.
   Same blue as serial-badge but no pill background, so it sits at the
   same visual weight as the cell text instead of looking like a
   secondary tag. */
.serial-cell {
  font-family: var(--font-mono, monospace);
  font-size: 14px;
  font-weight: 700;
  color: var(--primary);
  white-space: nowrap;
  letter-spacing: 0.2px;
  /* v0.2.0-pre60 — also used as an <a> (link to the report view). Remove
     the default underline and let the row-level hover provide the cue. */
  text-decoration: none;
}
a.serial-cell:hover {
  color: var(--primary-hover);
  text-decoration: underline;
  text-underline-offset: 3px;
}
/* Same treatment for the chunkier .report-card-serial used by the
   mobile / dashboard cards via report_card_title(). */
a.report-card-serial {
  text-decoration: none;
}
a.report-card-serial:hover {
  color: var(--primary-hover);
  text-decoration: underline;
  text-underline-offset: 3px;
}

/* v0.2.0-pre23 — Version chip mimics the .badge silhouette exactly so a
   row like  [COLD] [v020]  reads as a single sentence of equal-weight
   pills. Only the colour story differs (neutral grey vs semantic tone). */
.version-tag {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-family: var(--font-mono, monospace);
  font-size: 12px;
  font-weight: 700;
  color: #475569;
  background: #f1f3f6;
  border: 1px solid #d8dde4;
  padding: 4px 10px;
  border-radius: 999px;
  white-space: nowrap;
  letter-spacing: 0.3px;
}

/* ── Tech avatar grid (plant view) ──────────────────────*/
.tech-avatar-grid {
  display: flex;
  flex-wrap: wrap;
  gap: 16px;
  margin-top: 12px;
}

.tech-avatar-card {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  gap: 6px;
  width: 100px;
}

.tech-avatar-img {
  width: 64px;
  height: 64px;
  border-radius: 50%;
  object-fit: cover;
  border: 2px solid var(--border-strong);
}

.tech-avatar-initials {
  width: 64px;
  height: 64px;
  border-radius: 50%;
  background: var(--primary-soft);
  border: 2px solid #cfe6f8;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 20px;
  font-weight: 800;
  color: #0a4f86;
  flex-shrink: 0;
}

.tech-avatar-name {
  font-size: 12px;
  font-weight: 600;
  color: var(--text);
  line-height: 1.3;
  word-break: break-word;
}

.tech-avatar-company, .tech-avatar-reports {
  font-size: 11px;
  color: var(--muted);
}

/* ── Nav user pill (topbar) ──────────────────────────────*/
.nav-user-pill {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  padding: 4px 10px 4px 4px;
  border-radius: 999px;
  background: var(--primary-soft);
  border: 1px solid #cfe6f8;
  text-decoration: none;
  transition: background .15s, border-color .15s;
}
.nav-user-pill:hover {
  background: #dbeafe;
  border-color: #93c5fd;
  color: var(--text);
  text-decoration: none;
}

.nav-avatar-img {
  width: 26px;
  height: 26px;
  border-radius: 50%;
  object-fit: cover;
  flex-shrink: 0;
}

.nav-avatar-initials {
  width: 26px;
  height: 26px;
  border-radius: 50%;
  background: var(--primary);
  color: #fff;
  font-size: 11px;
  font-weight: 800;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
}

.nav-user-name {
  font-size: 13px;
  font-weight: 600;
  color: #0a4f86;
  max-width: 120px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* ── Profile page ────────────────────────────────────────*/
.profile-avatar-wrap {
  display: flex;
  align-items: center;
  gap: 20px;
  margin-top: 16px;
  padding: 16px;
  background: var(--primary-soft);
  border: 1px solid #cfe6f8;
  border-radius: var(--radius);
}

.profile-avatar-img {
  width: 80px;
  height: 80px;
  border-radius: 50%;
  object-fit: cover;
  border: 3px solid #cfe6f8;
  flex-shrink: 0;
}

.profile-avatar-initials {
  width: 80px;
  height: 80px;
  border-radius: 50%;
  background: var(--primary);
  color: #fff;
  font-size: 28px;
  font-weight: 800;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
}

.profile-avatar-actions {
  flex: 1;
}

.profile-meta {
  margin-top: 16px;
  padding: 12px 14px;
  background: var(--bg-secondary, #f6f8fb);
  border-radius: var(--radius);
  display: grid;
  gap: 6px;
  font-size: 14px;
}

@media (max-width: 700px) {
  .profile-avatar-wrap { flex-direction: column; text-align: center; }
  .tech-avatar-card { width: 80px; }
  .tech-avatar-img, .tech-avatar-initials { width: 52px; height: 52px; }
  .tech-avatar-initials { font-size: 16px; }
}

/* =========================================================
   v38 — Hot commissioning serial search
   =========================================================*/

.serial-search-wrap {
  display: flex;
  align-items: center;
  border: 1px solid var(--border-strong);
  border-radius: 12px;
  overflow: hidden;
  margin-top: 6px;
  transition: box-shadow .15s, border-color .15s;
}

.serial-search-wrap:focus-within {
  border-color: rgba(0,117,201,.6);
  box-shadow: 0 0 0 4px rgba(0,117,201,.15);
}

.serial-prefix {
  padding: 12px 10px 12px 14px;
  background: #f0f4fa;
  font-family: var(--font-mono, monospace);
  font-size: 16px;
  font-weight: 700;
  color: var(--muted);
  border-right: 1px solid var(--border-strong);
  flex-shrink: 0;
  white-space: nowrap;
}

.serial-search-input {
  flex: 1;
  min-width: 0;
  border: none;
  border-radius: 0;
  outline: none;
  box-shadow: none;
  padding: 12px 12px;
  font-size: 20px;
  font-family: var(--font-mono, monospace);
  font-weight: 700;
  letter-spacing: 2px;
  color: var(--text);
  background: #fff;
}

.serial-search-input:focus {
  outline: none;
  box-shadow: none;
}

.serial-search-wrap .btn {
  border-radius: 0 10px 10px 0;
  flex-shrink: 0;
}

@media (max-width: 480px) {
  .serial-search-input { font-size: 16px; letter-spacing: 1px; }
  .serial-prefix { font-size: 14px; }
}

/* =========================================================
   v39 — Checklist attachments + cold serial search
   =========================================================*/

.check-attachment {
  margin-top: 6px;
  padding-top: 6px;
  border-top: 1px solid var(--border);
  display: flex;
  align-items: center;
  gap: 6px;
  flex-wrap: wrap;
}

.attach-icon { font-size: 14px; flex-shrink: 0; }

.attach-link {
  font-size: 13px;
  color: var(--primary);
  text-decoration: none;
  font-weight: 500;
  word-break: break-all;
}

.attach-link:hover { text-decoration: underline; }

/* =========================================================
   v40 — Cold resolved confirmation bar + serial validation
   =========================================================*/

/* Compact confirmed-cold bar shown when cold already linked */
.cold-resolved-bar {
  display: flex;
  flex-direction: column;
  gap: 4px;
  padding: 12px 16px;
  margin-top: 12px;
  background: #f0fdf4;
  border: 1px solid #86efac;
  border-radius: var(--radius);
  border-left: 4px solid #1a6e31;
}

.cold-resolved-icon {
  font-size: 18px;
  color: #1a6e31;
  font-weight: 800;
  margin-right: 6px;
}

/* Serial input valid/invalid visual states */
.serial-search-wrap {
  transition: border-color .2s ease, box-shadow .2s ease;
}

/* =========================================================
   v41 — Reports index: active KPI filter state
   =========================================================*/

.dash-kpi-item.kpi-active-filter {
  outline: 2px solid var(--primary);
  outline-offset: -2px;
  position: relative;
}

.dash-kpi-item.kpi-active-filter .kpi-label {
  font-weight: 700;
  color: var(--primary);
}

/* KPI items as links — hover feedback */
a.dash-kpi-item:hover {
  opacity: .85;
  cursor: pointer;
}

/* Rejected KPI accent color */
.kpi-rejected .kpi-num { color: #e67e22; }

/* =========================================================
   v42 — Per-step edit button in checklist
   =========================================================*/

.check-edit-btn {
  padding: 4px 10px !important;
  font-size: 12px !important;
  line-height: 1.4 !important;
  min-width: 0 !important;
  background: #0075c9 !important;
  border-color: #0075c9 !important;
  color: #fff !important;
  border-radius: 6px !important;
  font-weight: 600 !important;
}

.check-edit-btn:hover {
  background: #005fa3 !important;
  border-color: #005fa3 !important;
  color: #fff !important;
}

/* =========================================================
   v43 — Protocol view admin note + step section badge
   =========================================================*/

.step-section-badge {
  display: inline-block;
  font-size: 11px;
  font-weight: 600;
  color: var(--muted);
  background: var(--bg-secondary, #f6f8fb);
  border: 1px solid var(--border);
  border-radius: 4px;
  padding: 1px 6px;
  margin-left: 6px;
  vertical-align: middle;
}

.proto-admin-note {
  margin-top: 14px;
  padding: 10px 14px;
  background: #fefce8;
  border: 1px solid #fde68a;
  border-radius: var(--radius);
  font-size: 13px;
  color: #78350f;
  line-height: 1.55;
}

.proto-admin-note code {
  font-family: var(--font-mono, monospace);
  background: rgba(0,0,0,.07);
  padding: 1px 5px;
  border-radius: 3px;
}

/* Field error inline */
.field-error {
  color: #c0392b;
  font-size: 12px;
  font-weight: 600;
  margin-left: 6px;
}

/* v0.2.0-pre76 — Per-field error markers used by /users/create_user.
   .has-error on the input draws the danger border + tinted background;
   the .field-error helper above renders the message under the input. */
input.has-error,
select.has-error,
textarea.has-error {
  border-color: var(--danger);
  background: var(--danger-soft, #fdecea);
}
input.has-error:focus,
select.has-error:focus,
textarea.has-error:focus {
  box-shadow: 0 0 0 4px rgba(192, 57, 43, 0.18);
}

/* =========================================================
   v44 — Attachment toggle pill (mirrors photo-pill)
   =========================================================*/

.attach-pill {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 8px 14px;
  border-radius: 999px;
  font-size: 13px;
  font-weight: 700;
  cursor: pointer;
  border: 1px solid transparent;
  white-space: nowrap;
  transition: opacity .15s;
  user-select: none;
}

.attach-pill.is-required {
  background: #fff7ed;
  border-color: #fdba74;
  color: #7c2d12;
}

.attach-pill.is-optional {
  background: #f6f8fb;
  border-color: var(--border-strong);
  color: var(--muted);
}

.attach-pill:hover { opacity: .8; }

/* =========================================================
   v45 — Nav user pill dropdown (profile + logout)
   =========================================================*/

.nav-user-dropdown {
  position: relative;
  display: inline-flex;
}

/* Override pill: now a button, not a link */
.nav-user-pill {
  background: none;
  cursor: pointer;
  gap: 6px;
}

.nav-dropdown-caret {
  font-size: 10px;
  opacity: .7;
  margin-left: 2px;
  color: #0a4f86;
}

.nav-dropdown-menu {
  display: none;
  position: absolute;
  top: calc(100% + 8px);
  right: 0;
  min-width: 180px;
  background: #fff;
  border: 1px solid var(--border-strong);
  border-radius: 12px;
  box-shadow: 0 8px 24px rgba(0,0,0,.12);
  overflow: hidden;
  z-index: 1000;
  animation: dropIn .12s ease;
}

.nav-dropdown-menu.is-open { display: block; }

@keyframes dropIn {
  from { opacity:0; transform:translateY(-6px); }
  to   { opacity:1; transform:translateY(0); }
}

.nav-dropdown-menu a {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 10px 16px;
  font-size: 14px;
  color: var(--text) !important;
  text-decoration: none;
  transition: background .1s;
  white-space: nowrap;
}

.nav-dropdown-menu a:hover { background: var(--primary-soft); }

.nav-dropdown-divider {
  height: 1px;
  background: var(--border);
  margin: 4px 0;
}

.nav-dropdown-logout {
  color: #c0392b !important;
}
.nav-dropdown-logout:hover { background: #fde8e8 !important; }

/* Mobile nav user header */
.nav-mobile-user {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 12px 16px;
  background: var(--primary-soft);
}

.nav-mobile-divider {
  height: 1px;
  background: var(--border);
  margin: 4px 0;
}

/* =========================================================
   v46 — Nav pending badge + user management
   =========================================================*/

.nav-pending-badge {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 18px;
  height: 18px;
  padding: 0 5px;
  background: #e74c3c;
  color: #fff !important;
  border-radius: 999px;
  font-size: 11px;
  font-weight: 700;
  margin-left: auto;
}

/* =========================================================
   v47 — Logout button in nav + nav cleanup
   =========================================================*/

.nav-logout-btn {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding: 6px 12px;
  border-radius: 999px;
  border: 1px solid var(--border-strong);
  color: #c0392b !important;
  text-decoration: none;
  font-size: 13px;
  font-weight: 600;
  background: #fef2f2;
  transition: background .15s, border-color .15s;
  white-space: nowrap;
}

.nav-logout-btn:hover {
  background: #fde8e8;
  border-color: #f87171;
  color: #b91c1c !important;
}

.nav-logout-label {
  display: inline;
}

@media (max-width: 900px) {
  .nav-logout-label { display: none; }
  .nav-logout-btn   { padding: 6px 8px; }
}

/* Remove old dropdown CSS that's no longer used */
.nav-user-dropdown  { display: none; }
.nav-dropdown-menu  { display: none !important; }

/* =========================================================
   v48 — Help section: mandatory photo evidence
   =========================================================*/

.help-photo-count {
  display: inline-flex;
  align-items: center;
  margin-left: 8px;
  padding: 2px 10px;
  border-radius: 999px;
  background: #fde8e8;
  color: #c0392b;
  font-size: 12px;
  font-weight: 700;
  font-family: var(--font-sans, sans-serif);
  vertical-align: middle;
}

/* Wider thumbnail grid for real field photos */
.help-thumbs {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
  gap: 12px;
  margin-top: 10px;
}

.help-thumb {
  display: flex;
  flex-direction: column;
  border: 1px solid var(--border-strong);
  border-radius: 10px;
  overflow: hidden;
  text-decoration: none;
  transition: box-shadow .15s, transform .15s;
}

.help-thumb:hover {
  box-shadow: 0 4px 16px rgba(0,0,0,.15);
  transform: translateY(-2px);
}

.help-thumb img {
  width: 100%;
  aspect-ratio: 4/3;
  object-fit: cover;
  display: block;
}

.help-thumb-label {
  padding: 6px 8px;
  font-size: 11px;
  font-weight: 600;
  color: var(--text);
  background: #f6f8fb;
  line-height: 1.35;
}

@media (max-width: 600px) {
  .help-thumbs { grid-template-columns: repeat(2, 1fr); }
}

/* =========================================================
   v49 — PDF archive bar in report view
   =========================================================*/

.pdf-archive-bar {
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 12px 16px;
  background: #f0fdf4;
  border: 1px solid #86efac;
  border-left: 4px solid #16a34a;
  border-radius: var(--radius);
  margin-top: 18px;
  margin-bottom: 14px;
  flex-wrap: wrap;
}

.pdf-archive-icon {
  font-size: 24px;
  flex-shrink: 0;
}

.pdf-archive-body {
  flex: 1;
  min-width: 0;
}

.pdf-archive-title {
  font-size: 12px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .5px;
  color: #15803d;
  margin-bottom: 3px;
}

.pdf-archive-row {
  display: flex;
  align-items: baseline;
  gap: 10px;
  flex-wrap: wrap;
}

.pdf-archive-link {
  font-family: var(--font-mono, monospace);
  font-size: 13px;
  font-weight: 600;
  color: #15803d;
  word-break: break-all;
  text-decoration: none;
}

.pdf-archive-link:hover { text-decoration: underline; }

.pdf-archive-meta {
  font-size: 11px;
  color: var(--muted);
  white-space: nowrap;
}

/* Small PDF icon button in reports list */
.pdf-attach-btn {
  padding: 5px 8px !important;
  font-size: 14px !important;
  line-height: 1 !important;
  min-width: 0 !important;
  border-radius: 6px !important;
}

/* =========================================================
   v50 — Validated report: frozen badge + PDF inline btn
   =========================================================*/

.report-frozen-badge {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding: 5px 12px;
  border-radius: 999px;
  background: #f0fdf4;
  border: 1px solid #86efac;
  color: #15803d;
  font-size: 12px;
  font-weight: 700;
}

/* PDF inline button — matches View button height */
.pdf-attach-btn {
  background: #f0fdf4 !important;
  border-color: #86efac !important;
  color: #15803d !important;
  font-size: 13px !important;
  font-weight: 600 !important;
  padding: 6px 10px !important;
  border-radius: 999px !important;
  white-space: nowrap !important;
}
.pdf-attach-btn:hover {
  background: #dcfce7 !important;
  border-color: #4ade80 !important;
  color: #166534 !important;
}

/* =========================================================
   v51 — Reopen flow: superseded PDFs + reopen button
   =========================================================*/

.pdf-superseded {
  opacity: .65;
  padding-top: 6px;
  border-top: 1px dashed var(--border-strong);
  margin-top: 6px;
}

.pdf-superseded-badge {
  display: inline-flex;
  align-items: center;
  padding: 1px 7px;
  border-radius: 999px;
  background: #fef3cd;
  border: 1px solid #fbbf24;
  color: #92400e;
  font-size: 10px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .4px;
  margin-right: 6px;
  flex-shrink: 0;
}

.pdf-link-superseded {
  text-decoration: line-through !important;
  color: var(--muted) !important;
}

/* =========================================================
   v52 — PDF archive bar: simplified, filename as text
   =========================================================*/

/* Rename filename from link to plain text */
.pdf-archive-name {
  font-family: var(--font-mono, monospace);
  font-size: 13px;
  font-weight: 600;
  color: #15803d;
  word-break: break-all;
}

.pdf-archive-name.pdf-link-superseded {
  text-decoration: line-through;
  color: var(--muted);
}

/* Download button — pill style matching other primary btns */
.pdf-download-btn {
  flex-shrink: 0;
  white-space: nowrap;
}

/* Reopen button — more visible orange */
.btn-reopen {
  border-color: #d97706 !important;
  color: #fff !important;
  background: #d97706 !important;
  font-weight: 700 !important;
}
.btn-reopen:hover {
  background: #b45309 !important;
  border-color: #b45309 !important;
}

/* =========================================================
   Safety Notices — Protocol start page (Section 1)
   ---------------------------------------------------------
   4 severity levels matching the official the company manual:
   DANGER (red) · WARNING (orange) · CAUTION (amber) · NOTICE (blue)
   =========================================================*/

/* Mandatory read notice — always shown, always prominent */
.safety-notice-mandatory {
  display: flex;
  gap: 12px;
  align-items: flex-start;
  margin-top: 10px;
  padding: 12px 14px;
  border-radius: 10px;
  background: #fff8e1;
  border: 1.5px solid #f5d87a;
  color: #7a4f00;
}
.safety-notice-mandatory .safety-notice-icon {
  font-size: 20px;
  flex-shrink: 0;
  line-height: 1.2;
}
.safety-notice-mandatory .safety-notice-label {
  font-weight: 800;
  font-size: 13px;
  text-transform: uppercase;
  letter-spacing: .4px;
  margin-bottom: 3px;
}
.safety-notice-mandatory .safety-notice-text {
  font-size: 14px;
  line-height: 1.55;
}

/* Collapsible wrapper */
.safety-details {
  border: 1px solid var(--border);
  border-radius: 10px;
  overflow: hidden;
}
.safety-details-summary {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 10px 14px;
  cursor: pointer;
  font-weight: 700;
  font-size: 14px;
  background: #fafbfd;
  list-style: none;
  user-select: none;
}
.safety-details-summary::-webkit-details-marker { display: none; }
.safety-details[open] .safety-details-summary {
  background: var(--primary-soft);
  border-bottom: 1px solid #cfe6f8;
  color: #0a4f86;
}
.safety-details-hint {
  font-size: 11px;
  opacity: .6;
  font-weight: 400;
  margin-left: auto;
}
.safety-details[open] .safety-details-hint { display: none; }

.safety-notices-list {
  display: grid;
  gap: 8px;
  padding: 12px;
  background: #fff;
}

/* Base notice card */
.safety-notice {
  display: flex;
  gap: 12px;
  align-items: flex-start;
  padding: 11px 13px;
  border-radius: 8px;
  border-left: 4px solid;
}
.safety-notice-body { flex: 1; min-width: 0; }
.safety-notice-icon {
  font-size: 18px;
  flex-shrink: 0;
  line-height: 1.3;
  min-width: 22px;
  text-align: center;
}
.safety-notice-label {
  font-weight: 800;
  font-size: 12px;
  text-transform: uppercase;
  letter-spacing: .5px;
  margin-bottom: 4px;
}
.safety-notice-text {
  font-size: 13px;
  line-height: 1.5;
  opacity: .9;
}
.safety-notice-list {
  margin: 6px 0 0 0;
  padding-left: 18px;
  font-size: 13px;
  line-height: 1.6;
  opacity: .9;
}
.safety-notice-list li { margin-bottom: 2px; }

/* DANGER — red */
.safety-notice-danger {
  background: #fff5f5;
  border-color: #e53e3e;
  color: #7b1d1d;
}
.safety-notice-danger .safety-notice-label { color: #c53030; }

/* WARNING — orange */
.safety-notice-warning {
  background: #fff7ed;
  border-color: #dd6b20;
  color: #7a3d00;
}
.safety-notice-warning .safety-notice-label { color: #c05621; }

/* CAUTION — amber */
.safety-notice-caution {
  background: #fffbeb;
  border-color: #d69e2e;
  color: #744210;
}
.safety-notice-caution .safety-notice-label { color: #b7791f; }

/* NOTICE — blue-grey */
.safety-notice-notice {
  background: #f0f4f8;
  border-color: #4a90c4;
  color: #2d3748;
}
.safety-notice-notice .safety-notice-label { color: #2b6cb0; }

/* Mobile: tighter spacing */
@media (max-width: 640px) {
  .safety-notice { padding: 10px 12px; gap: 10px; }
  .safety-notice-icon { font-size: 16px; min-width: 18px; }
  .safety-notice-text, .safety-notice-list { font-size: 12px; }
  .safety-notices-list { padding: 10px; gap: 6px; }
}

/* =========================================================
   PDF archive bar — mobile simplification
   - On mobile: no filename (too long), just size + date + Download btn
   - Bar is more compact, no icon gap
   =========================================================*/
@media (max-width: 640px) {
  .pdf-archive-bar {
    gap: 10px;
    padding: 10px 12px;
  }
  .pdf-archive-icon { display: none; }
  .pdf-archive-title { font-size: 11px; }
  .pdf-archive-meta { font-size: 11px; white-space: normal; }
  .pdf-download-btn { font-size: 13px !important; padding: 8px 14px !important; }
}

/* =========================================================
   Photo delete button — wizard step photo grid
   =========================================================*/
.photo-saved-wrap,
#photoPreviewGrid > div {
  position: relative;
  border-radius: 12px;
  overflow: hidden;
}

.photo-del-btn {
  position: absolute;
  top: 5px;
  right: 5px;
  width: 26px;
  height: 26px;
  border-radius: 50%;
  border: none;
  background: rgba(0,0,0,.62);
  color: #fff;
  font-size: 13px;
  font-weight: 700;
  line-height: 1;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 2;
  transition: background .15s;
  padding: 0;
}
.photo-del-btn:hover {
  background: #e53e3e;
}

/* =========================================================
   Software Versions — read-only display (view.php)
   Now uses the unified .swv-cards / .swv-table-wrap breakpoint
   defined above (820px). The standalone .swv-value rule lives
   alongside the rest of the swv- styles for cohesion.
   ========================================================= */

/* Tighten the h3 subsection spacing inside General Information card */
.card h3 {
  margin-top: 24px;
  margin-bottom: 8px;
}
.card h3:first-of-type {
  margin-top: 0;
}

/* =========================================================
   Technical Documentation Library — Docs page
   =========================================================*/

/* Grid: 2 columns on tablet+, 1 on narrow mobile */
.docs-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
  gap: 12px;
}

/* Individual document card */
.doc-card {
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding: 14px 16px;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--color-background-primary, #fff);
  transition: box-shadow .15s ease, transform .15s ease;
}
.doc-card:hover {
  box-shadow: 0 3px 12px rgba(16,24,40,.08);
  transform: translateY(-1px);
}
.doc-card-pending {
  background: #fafbfd;
  opacity: .75;
}

/* Category row: icon + label + version */
.doc-cat-row {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
}
.doc-cat-icon {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 30px;
  height: 30px;
  border-radius: 8px;
  font-size: 15px;
  flex-shrink: 0;
}
.doc-cat-label {
  font-size: 11px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .5px;
  flex: 1;
  min-width: 0;
}
.doc-version-badge {
  font-size: 10px;
  font-weight: 600;
  padding: 2px 7px;
  border-radius: 999px;
  background: var(--primary-soft, #e6f1fb);
  color: var(--primary, #0075c9);
  white-space: nowrap;
  flex-shrink: 0;
}

/* Document title */
.doc-title {
  font-size: 14px;
  font-weight: 700;
  color: var(--text);
  line-height: 1.35;
}

/* Description */
.doc-description {
  font-size: 12px;
  color: var(--muted);
  line-height: 1.5;
  flex: 1;
}

/* Actions row */
.doc-actions {
  display: flex;
  gap: 8px;
  flex-wrap: wrap;
  margin-top: 4px;
}

/* Pending badge */
.doc-pending-badge {
  font-size: 11px;
  font-weight: 600;
  color: #9ca3af;
  padding: 4px 10px;
  border: 1px dashed #d1d5db;
  border-radius: 999px;
}

@media (max-width: 480px) {
  .docs-grid {
    grid-template-columns: 1fr;
  }
}

/* =========================================================
   Docs v2 — Equipment Selector + Document Library
   =========================================================*/

/* ── Landing page ──────────────────────────────────────── */
.docs-landing {
  max-width: 860px;
  margin: 0 auto;
}

.docs-landing-header {
  margin-bottom: 28px;
}

.docs-landing-title {
  /* v0.2.0-pre17 — let the global h1 rule (blue + uppercase) win so the
     docs page header matches /customers, /plants, /reports… The size /
     weight / spacing here is what differs from the global default. */
  font-size: 28px;
  font-weight: 700;
  margin: 0 0 6px;
}

.docs-landing-subtitle {
  color: var(--muted);
  font-size: 14px;
  margin: 0;
}

/* ── Equipment card grid ───────────────────────────────── */
.docs-eq-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
  gap: 18px;
}

.docs-eq-card {
  display: flex;
  flex-direction: column;
  border: 1px solid var(--border);
  border-radius: 12px;
  background: #fff;
  text-decoration: none;
  color: inherit;
  overflow: hidden;
  transition: box-shadow .18s ease, transform .18s ease;
}

.docs-eq-card:hover:not(.docs-eq-card--soon) {
  box-shadow: 0 6px 24px rgba(16, 24, 40, .10);
  transform: translateY(-2px);
}

.docs-eq-card--soon {
  cursor: default;
  opacity: .72;
}

/* Coloured top bar */
.docs-eq-bar {
  height: 5px;
  background: var(--eq-color, #0075c9);
}

.docs-eq-body {
  padding: 20px 22px 22px;
  display: flex;
  flex-direction: column;
  gap: 10px;
  flex: 1;
}

/* Head row: badge + pill */
.docs-eq-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
}

.docs-eq-badge {
  font-size: 18px;
  font-weight: 900;
  color: var(--eq-color, #0075c9);
  letter-spacing: -.3px;
}

.docs-eq-count-pill {
  font-size: 11px;
  font-weight: 700;
  padding: 3px 10px;
  border-radius: 999px;
  background: var(--eq-bg, #e6f1fb);
  color: var(--eq-color, #0075c9);
  white-space: nowrap;
}

.docs-eq-soon-pill {
  font-size: 11px;
  font-weight: 600;
  padding: 3px 10px;
  border-radius: 999px;
  background: #f3f4f6;
  color: #9ca3af;
  white-space: nowrap;
}

.docs-eq-tagline {
  font-size: 15px;
  font-weight: 700;
  color: var(--text);
  margin-top: 2px;
}

.docs-eq-description {
  font-size: 12px;
  color: var(--muted);
  margin-top: -4px;
}

/* Feature checklist */
.docs-eq-features {
  list-style: none;
  margin: 4px 0 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 5px;
}

.docs-eq-features li {
  font-size: 12px;
  color: var(--text);
  display: flex;
  align-items: center;
  gap: 7px;
}

.docs-eq-feature--muted {
  color: var(--muted) !important;
}

.docs-eq-check {
  font-size: 11px;
  font-weight: 800;
  color: #1a6e31;
  flex-shrink: 0;
}

.docs-eq-check--muted {
  color: #d1d5db !important;
}

/* CTA line */
.docs-eq-cta {
  margin-top: auto;
  padding-top: 14px;
  border-top: 1px solid var(--border);
}

.docs-eq-cta-text {
  font-size: 13px;
  font-weight: 700;
  color: var(--eq-color, #0075c9);
}

.docs-eq-cta-text--muted {
  color: #9ca3af;
  font-weight: 600;
}

/* ── Breadcrumb ────────────────────────────────────────── */
.docs-breadcrumb {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 13px;
  color: var(--muted);
  margin-bottom: 16px;
}

.docs-breadcrumb a {
  color: var(--primary);
  text-decoration: none;
}

.docs-breadcrumb a:hover {
  text-decoration: underline;
}

.docs-breadcrumb-sep {
  opacity: .5;
}

/* ── Equipment page header ─────────────────────────────── */
.docs-eq-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  padding: 14px 18px;
  background: #fff;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  margin-bottom: 20px;
  flex-wrap: wrap;
}

.docs-eq-header-title {
  /* v0.2.0-pre17 — inherit global h1 blue+uppercase styling. Custom font
     size only. */
  font-size: 22px;
  font-weight: 700;
  margin: 0 0 4px;
}

.docs-eq-header-sub {
  font-size: 12px;
  color: var(--muted);
}

.docs-eq-header-stats {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-shrink: 0;
}

.docs-stat-pill--available {
  font-size: 11px;
  font-weight: 700;
  padding: 4px 12px;
  border-radius: 999px;
  background: #e6f9ec;
  color: #1a6e31;
}

.docs-stat-pill--soon {
  font-size: 11px;
  font-weight: 600;
  padding: 4px 12px;
  border-radius: 999px;
  background: #f3f4f6;
  color: #9ca3af;
}

/* ── Document list (category sections + rows) ──────────── */
.docs-doc-list {
  display: flex;
  flex-direction: column;
  gap: 0;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  overflow: hidden;
  background: #fff;
}

/* Category section
   ───────────────────────────────────────────────────────────────
   Visual goal: replace the previous full-bleed coloured stripe with
   a subtle left-accent + a small icon chip that carries the category
   colour. This brings Docs in line with the rest of the app (section
   cards, alerts, KPI tints) where colour is used as an accent — not
   as a full background fill that competes for attention. */
.docs-cat-section {
  border-bottom: 1px solid var(--border);
  border-left: 3px solid var(--cat-color, var(--border));
}

.docs-cat-section:last-child {
  border-bottom: none;
}

/* Category header row */
.docs-cat-header {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 12px 18px;
  background: #fff;
  border-bottom: 1px solid var(--border);
}

/* Category icon — small coloured chip on white surface. Replaces the
   previous full-width tinted background. */
.docs-cat-icon-wrap {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 26px;
  height: 26px;
  border-radius: 6px;
  background: var(--cat-bg, #f3f4f6);
  color: var(--cat-color, #555);
  flex-shrink: 0;
  line-height: 1;
}

.docs-cat-icon-wrap svg {
  width: 14px;
  height: 14px;
}

.docs-cat-label {
  font-size: 11px;
  font-weight: 800;
  text-transform: uppercase;
  letter-spacing: .6px;
  color: var(--text);
}

/* Individual document row.
   v0.2.0-pre25 — tightened padding so the list reads as a compact
   catalogue, not a card-per-doc. Each row is body-height tall. */
.docs-doc-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 14px;
  padding: 10px 16px;
  border-bottom: 1px solid var(--border);
  transition: background .12s ease;
}

.docs-cat-section:last-child .docs-doc-row:last-child {
  border-bottom: none;
}

.docs-doc-row:hover:not(.docs-doc-row--pending) {
  background: #fafbfd;
}

.docs-doc-row--pending {
  opacity: .7;
}

.docs-doc-info {
  flex: 1;
  min-width: 0;
}

.docs-doc-title {
  font-size: 14px;
  font-weight: 700;
  color: var(--text);
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
}

.docs-doc-version {
  font-size: 10px;
  font-weight: 600;
  padding: 2px 8px;
  border-radius: 999px;
  background: var(--primary-soft, #e6f1fb);
  color: var(--primary, #0075c9);
  white-space: nowrap;
}

.docs-doc-desc {
  font-size: 12px;
  color: var(--muted);
  margin-top: 3px;
  line-height: 1.5;
}

.docs-doc-actions {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-shrink: 0;
}

/* v0.2.0-pre27 — Tint the View / Download icon buttons with the doc
   category colour. Each .docs-cat-section sets --cat-color and --cat-bg
   inline (see docs/index.php), so the icons read green inside
   Commissioning Protocol, purple inside Function & Interface, etc. */
.docs-cat-section .btn-icon {
  border-color: var(--cat-color);
  color: var(--cat-color);
}
.docs-cat-section .btn-icon:hover {
  background: var(--cat-bg);
  color: var(--cat-color);
}

.docs-pending-label {
  font-size: 11px;
  font-weight: 600;
  color: #9ca3af;
  padding: 5px 12px;
  border: 1px dashed #d1d5db;
  border-radius: 999px;
  white-space: nowrap;
}

/* ── Responsive ────────────────────────────────────────── */
@media (max-width: 540px) {
  .docs-eq-grid {
    grid-template-columns: 1fr;
  }

  /* v0.2.0-pre25 — keep the icon actions on the right on mobile too;
     they're already compact (two icon buttons), no need to drop to a
     full-width row underneath the title. */
  .docs-doc-row {
    flex-direction: row;
    align-items: center;
    gap: 10px;
  }

  .docs-eq-header {
    flex-direction: column;
    align-items: flex-start;
  }
}

/* =========================================================
   Help accordion v2 — documentation reference buttons
   =========================================================*/

/* Docs count pill in summary */
.help-doc-count {
  margin-left: auto;
  font-size: 11px;
  font-weight: 700;
  padding: 2px 8px;
  border-radius: 999px;
  background: #fff3e0;
  color: #b45309;
  border: 1px solid #fcd34d;
  white-space: nowrap;
  flex-shrink: 0;
}

/* Section title variants */
.help-section {
  margin-bottom: 14px;
}

.help-section:last-child {
  margin-bottom: 0;
}

.help-section-title {
  font-size: 12px;
  font-weight: 800;
  text-transform: uppercase;
  letter-spacing: .5px;
  margin: 0 0 8px;
  padding: 4px 10px;
  border-radius: 6px;
  display: inline-block;
}

.help-title-do       { background: #e6f1fb; color: #0b5aa6; }
.help-title-check    { background: #e6f9ec; color: #1a6e31; }
.help-title-evidence { background: #fef3e2; color: #b45309; }
.help-title-photos   { background: #f0ebfc; color: #6c3eb8; }
.help-title-docs     { background: #fef3e2; color: #b45309; }

.help-photo-count {
  font-size: 10px;
  font-weight: 600;
  margin-left: 8px;
  padding: 2px 7px;
  border-radius: 999px;
  background: #f0ebfc;
  color: #6c3eb8;
  vertical-align: middle;
}

/* Documentation section */
.help-docs-section {
  border-top: 1px solid var(--border);
  padding-top: 14px;
  margin-top: 14px;
}

.help-doc-links {
  display: flex;
  flex-direction: column;
  gap: 8px;
}

/* Document link button */
.help-doc-btn {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px 13px;
  border: 1px solid #e0c97a;
  border-radius: 8px;
  background: #fffdf0;
  text-decoration: none;
  color: inherit;
  transition: background .12s ease, border-color .12s ease;
}

a.help-doc-btn:hover {
  background: #fff8d6;
  border-color: #c9a227;
}

.help-doc-btn--unavailable {
  opacity: .6;
  cursor: default;
  border-style: dashed;
  border-color: #e0d8c0;
  background: #fafaf5;
}

.help-doc-btn-icon {
  font-size: 18px;
  flex-shrink: 0;
  line-height: 1;
}

.help-doc-btn-body {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.help-doc-btn-label {
  font-size: 13px;
  font-weight: 700;
  color: #7a4f00;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.help-doc-btn-section {
  font-size: 11px;
  color: #a07830;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.help-doc-btn-version {
  font-size: 10px;
  font-weight: 700;
  padding: 2px 7px;
  border-radius: 999px;
  background: #f5e7b0;
  color: #7a4f00;
  white-space: nowrap;
  flex-shrink: 0;
}

.help-doc-btn-soon {
  background: #f0f0ec;
  color: #888;
}

.help-doc-btn-arrow {
  font-size: 14px;
  color: #b47c1c;
  flex-shrink: 0;
  opacity: .7;
}

/* Mobile: ensure doc buttons are fully readable */
@media (max-width: 540px) {
  .help-doc-btn {
    padding: 12px 12px;
  }
  .help-doc-btn-label {
    font-size: 13px;
    white-space: normal;
  }
  .help-doc-btn-section {
    white-space: normal;
  }
}

/* =========================================================
   v49 — Plant commissioning status badges
   =========================================================*/

.plant-name-link {
  text-decoration: none;
  color: inherit;
}
.plant-name-link:hover div {
  color: var(--primary);
  text-decoration: underline;
  text-underline-offset: 2px;
}

.comm-badge {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 3px 9px;
  border-radius: 999px;
  font-size: 11.5px;
  font-weight: 700;
  white-space: nowrap;
  line-height: 1.4;
  border: 1px solid transparent;
}

/* Cold — all done (green) */
.comm-cold-done {
  background: #dcfce7;
  color: #166534;
  border-color: #86efac;
}

/* Cold — partial / in progress (blue) */
.comm-cold-partial {
  background: #e0f2fe;
  color: #0c4a6e;
  border-color: #7dd3fc;
}

/* Cold — missing entirely (light red) */
.comm-cold-missing {
  background: #fee2e2;
  color: #991b1b;
  border-color: #fca5a5;
}

/* Hot — all done (amber/orange) */
.comm-hot-done {
  background: #fef3c7;
  color: #92400e;
  border-color: #fcd34d;
}

/* Hot — partial / in progress (amber lighter) */
.comm-hot-partial {
  background: #fff7ed;
  color: #9a3412;
  border-color: #fdba74;
}

/* Hot — missing (grey dashed) */
.comm-hot-missing {
  background: #f4f6f8;
  color: #6b7280;
  border-color: #d1d5db;
  border-style: dashed;
}

/* =========================================================
   v57 — Pending Works status styles (legacy KPI variant)
   =========================================================*/
.kpi-pending-works .kpi-num {
  color: #b45309;
}
.kpi-pending-works.kpi-active-filter {
  border-top: 3px solid #d97706;
  background: #fffbeb;
}
.badge.is-validated_pending_works,
.badge.is-pending-works {
  background: #fef3e2;
  color: #b45309;
  border: 1px solid #fcd34d;
  font-weight: 700;
}
.dash-count-validated_pending_works {
  background: #fef3e2;
  color: #b45309;
}

/* =========================================================
   v70 — Finish report screen: pending works + signature
   ---------------------------------------------------------
   Replaces the previous inline-style block. Coherent with the
   rest of the system: card chrome, semantic accents, focus rings.
   ========================================================= */
.finish-section {
  margin-bottom: 20px;
  border-top: 3px solid var(--border-strong);
}
.finish-section-pw {
  border-top-color: var(--warning, #d97706);
}
.finish-section-sig {
  border-top-color: var(--primary, #0075c9);
}
.finish-section-head {
  display: flex;
  align-items: flex-start;
  gap: 12px;
  margin-bottom: 14px;
}
.finish-section-icon {
  flex-shrink: 0;
  width: 28px;
  height: 28px;
  border-radius: 8px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background: var(--warning-soft, #fef3e2);
  color: var(--warning, #b45309);
}
.finish-section-sig .finish-section-icon {
  background: var(--primary-soft, #e6f1fb);
  color: var(--primary, #0075c9);
}
.finish-section-title {
  font-weight: 700;
  font-size: 15px;
  color: #7a4500;
  line-height: 1.2;
}
.finish-section-sig .finish-section-title {
  color: var(--primary, #0075c9);
}
.finish-section-sub {
  font-size: 12px;
  color: var(--muted);
  margin-top: 4px;
  line-height: 1.5;
}
.finish-pw-preexisting-flag {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: 11px;
  font-weight: 700;
  color: #b45309;
  margin-bottom: 6px;
  text-transform: uppercase;
  letter-spacing: .4px;
}
.finish-pw-textarea {
  width: 100%;
  box-sizing: border-box;
  font-size: 14px;
  line-height: 1.55;
  border: 1px solid var(--border-strong);
  border-radius: 10px;
  padding: 11px 13px;
  resize: vertical;
  transition: border-color .15s ease, box-shadow .15s ease;
}
.finish-pw-textarea.has-prefill {
  border-color: #d97706;
  background: #fffbeb;
}
.finish-pw-textarea:focus,
.finish-pw-textarea:focus-visible {
  outline: none;
  border-color: rgba(0, 117, 201, 0.85);
  box-shadow: 0 0 0 3px rgba(0, 117, 201, 0.18);
}
.finish-pw-textarea.has-prefill:focus,
.finish-pw-textarea.has-prefill:focus-visible {
  border-color: #d97706;
  box-shadow: 0 0 0 3px rgba(217, 119, 6, 0.22);
}

/* =========================================================
   Approve report — manager signature + email recipients
   ========================================================= */
.approve-card {
  max-width: 640px;
  margin: 0 auto;
}
.approve-head {
  display: flex;
  align-items: center;
  gap: 14px;
  margin-bottom: 18px;
}
.approve-head-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  border-radius: 10px;
  background: var(--success-soft);
  color: var(--success);
  flex-shrink: 0;
}
.approve-title {
  margin: 0;
  font-size: 22px;
  line-height: 1.2;
}
.approve-subtitle {
  font-size: 13px;
  color: var(--muted);
  margin-top: 4px;
}
.approve-preview-row {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 6px;
  padding: 10px 12px;
  background: var(--surface-alt, #f8fafc);
  border: 1px solid var(--border);
  border-radius: 8px;
}
.approve-section {
  margin-top: 18px;
  padding-top: 14px;
  border-top: 1px solid var(--border);
}
.approve-section-title {
  font-size: 13px;
  font-weight: 700;
  color: var(--muted);
  text-transform: uppercase;
  letter-spacing: .4px;
  margin: 0 0 10px 0;
}
.approve-section-sig .approve-section-title {
  color: var(--success);
}
.approve-required {
  color: #c0392b;
  font-weight: 700;
}
.approve-help {
  font-size: 12px;
  color: var(--muted);
  margin-top: 6px;
  line-height: 1.5;
}
.approve-signer-fixed {
  margin-top: 4px;
  padding: 9px 12px;
  background: var(--surface-alt, #f8fafc);
  border: 1px solid var(--border);
  border-radius: 8px;
  font-size: 14px;
  font-weight: 600;
  color: var(--text);
  display: flex;
  align-items: baseline;
  gap: 8px;
}
.approve-signer-fixed .text-muted-sm {
  font-weight: 400;
}
.approve-sig-canvas {
  width: 100%;
  max-height: 180px;
  border: 1px solid var(--border-strong);
  border-radius: 8px;
  background: #fff;
  touch-action: none;
  cursor: crosshair;
  transition: border-color .15s ease;
}
.approve-sig-or {
  display: flex;
  align-items: center;
  text-align: center;
  gap: 10px;
  margin: 14px 0 10px;
  font-size: 12px;
  text-transform: uppercase;
  letter-spacing: .5px;
  color: var(--muted);
}
.approve-sig-or::before,
.approve-sig-or::after {
  content: '';
  flex: 1;
  height: 1px;
  background: var(--border);
}

/* =========================================================
   v71.3 — Mandatory documentation acknowledgment (start.php)
   ========================================================= */
.ack-box {
  margin-top: 16px;
  padding: 14px 16px;
  border: 1.5px solid var(--border-strong, #cbd5e1);
  border-radius: 10px;
  background: var(--surface-alt, #f8fafc);
  transition: border-color .15s ease, background .15s ease;
}
.ack-box-error {
  border-color: var(--danger, #dc2626);
  background: #fef2f2;
}
.ack-label {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  cursor: pointer;
  font-size: 13.5px;
  line-height: 1.5;
  margin: 0;
}
.ack-label input[type="checkbox"] {
  width: 20px;
  height: 20px;
  margin: 1px 0 0 0;
  flex-shrink: 0;
  cursor: pointer;
  accent-color: var(--primary, #0a4f86);
}
.ack-error-msg {
  display: flex;
  align-items: center;
  gap: 6px;
  margin-top: 10px;
  font-size: 12.5px;
  color: var(--danger, #dc2626);
  font-weight: 600;
}

/* =========================================================
   v71.4 — Finish report (two-phase): unified styling
   Matches the rest of the report (.section-card, h2, etc.)
   No hardcoded orange/blue accents.
   ========================================================= */
.finish-wrap { margin: 0 auto; }

.finish-header { margin-bottom: 20px; }
.finish-header h1 { margin: 0 0 4px; }
.finish-header-sub { font-size: 13px; color: var(--muted); }

.finish-steps-indicator {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-top: 14px;
  flex-wrap: wrap;
}
.finish-step-dot {
  font-size: 12.5px;
  font-weight: 600;
  padding: 5px 12px;
  border-radius: 999px;
  background: var(--surface-alt, #f1f5f9);
  color: var(--muted);
  border: 1px solid var(--border);
}
.finish-step-dot.is-active {
  background: var(--info-soft, #e6f1fb);
  color: var(--info, #185fa5);
  border-color: var(--info, #185fa5);
}
.finish-step-dot.is-done {
  background: var(--success-soft, #e1f5ee);
  color: var(--success, #0f6e56);
  border-color: var(--success, #0f6e56);
}
.finish-step-arrow { color: var(--muted); display: inline-flex; }

.finish-section-sub {
  font-size: 13px;
  color: var(--muted);
  margin: 0 0 14px;
  line-height: 1.5;
}

.finish-note {
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: 12.5px;
  color: var(--muted);
  margin-bottom: 10px;
}

.finish-pw-textarea {
  width: 100%;
  max-width: 760px;
  resize: vertical;
  min-height: 110px;
  font-family: inherit;
  font-size: 14px;
}

.finish-alert { margin-bottom: 14px; }

/* Signature blocks */
.finish-sig-block {
  padding: 16px 0;
  border-top: 1px solid var(--border);
}
.finish-sig-block:first-of-type { border-top: none; padding-top: 4px; }
.finish-sig-label {
  font-size: 14px;
  font-weight: 600;
  margin-bottom: 12px;
}
.finish-req { color: var(--danger, #dc2626); }
.finish-optional { color: var(--muted); font-weight: 400; font-size: 12.5px; }

.finish-sig-fields label {
  display: block;
  font-size: 12px;
  font-weight: 600;
  color: var(--muted);
  margin: 10px 0 4px;
}
.finish-sig-fields label:first-child { margin-top: 0; }
.finish-sig-fixedname {
  font-size: 14px;
  font-weight: 600;
  padding: 9px 12px;
  background: var(--surface-alt, #f8fafc);
  border: 1px solid var(--border);
  border-radius: 8px;
  margin-bottom: 4px;
}
.finish-sig-fields input[type="text"],
.finish-sig-fields input:not([type]) {
  width: 100%;
  max-width: 560px;
  margin-bottom: 4px;
}
.finish-sig-fixedname { max-width: 560px; }
.finish-sig-or { max-width: 560px; }
.finish-sig-fields input[type="file"] { max-width: 560px; }
.finish-sig-canvas {
  width: 100%;
  max-width: 560px;
  max-height: 170px;
  border: 1px solid var(--border-strong);
  border-radius: 8px;
  background: #fff;
  touch-action: none;
  cursor: crosshair;
  transition: border-color .15s ease;
  display: block;
}
.finish-sig-or {
  display: flex;
  align-items: center;
  text-align: center;
  gap: 10px;
  margin: 12px 0 8px;
  font-size: 12px;
  text-transform: uppercase;
  letter-spacing: .5px;
  color: var(--muted);
}
.finish-sig-or::before,
.finish-sig-or::after {
  content: '';
  flex: 1;
  height: 1px;
  background: var(--border);
}
.finish-sig-tools { display: flex; gap: 8px; margin-top: 8px; }

.finish-sig-saved img {
  max-height: 72px;
  border: 1px solid var(--border);
  border-radius: 6px;
  padding: 6px;
  background: #fff;
}
.finish-sig-saved-name { font-size: 12px; color: var(--muted); margin-top: 4px; }
.finish-sig-replace { margin-top: 10px; }
.finish-sig-replace summary {
  cursor: pointer;
  font-size: 13px;
  color: var(--info, #185fa5);
  font-weight: 600;
}

.finish-sig-required-msg {
  display: flex;
  align-items: center;
  gap: 6px;
  margin-top: 12px;
  font-size: 12.5px;
  font-weight: 600;
  color: var(--danger, #dc2626);
}

/* Action bars */
.finish-actions {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 12px;
  margin-top: 16px;
}
.finish-actions-right { display: flex; gap: 10px; flex-wrap: wrap; }

@media (max-width: 560px) {
  .finish-actions { flex-direction: column-reverse; align-items: stretch; }
  /* v0.2.0-pre91 — Buttons migrated from .btn to .action-pill, both stay
     full-width on narrow screens so the finish flow stays single-column. */
  .finish-actions .btn,
  .finish-actions .action-pill { width: 100%; justify-content: center; }
  .finish-actions-right { flex-direction: column; }
}

/* =========================================================
   v71.4.3 — Section 1: Documentation & Safety acknowledgment
   ========================================================= */
.doc-ack-row {
  display: flex;
  align-items: flex-start;
  gap: 12px;
}
.doc-ack-check {
  flex-shrink: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 36px;
  height: 36px;
  border-radius: 50%;
  background: var(--success-soft, #e1f5ee);
  color: var(--success, #0f6e56);
}
.doc-ack-body { min-width: 0; }
.doc-ack-title {
  font-size: 14px;
  font-weight: 600;
  color: var(--text);
  margin-bottom: 4px;
}
.doc-ack-text {
  font-size: 13px;
  color: var(--muted);
  line-height: 1.55;
}
.doc-ack-meta {
  font-size: 12px;
  color: var(--muted);
  margin-top: 8px;
  font-style: italic;
}

/* v0.2.0-pre92 — Pending state for Section 1 (technician hasn't acked yet).
   Same row layout, amber/warning palette to make it obvious this is not
   yet confirmed and stands as a soft TODO until the tech opens the
   wizard or accepts the schedule. */
.doc-ack-row.is-pending .doc-ack-check {
  background: #fff4e6;
  color: #b45309;
}
.doc-ack-row.is-pending .doc-ack-title {
  color: #b45309;
}

/* =========================================================
   v71.4.4 — In-line section editing (report view)
   ========================================================= */
.section-edit-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  margin-bottom: 12px;
}
.section-edit-head h2 { margin: 0; }
.section-edit-btn {
  flex-shrink: 0;
  display: inline-flex;
  align-items: center;
  gap: 5px;
}
.section-edit-pencil { font-size: 14px; line-height: 1; }
.section-edit-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 12px 16px;
  margin-bottom: 8px;
}
.section-edit-grid label {
  display: flex;
  flex-direction: column;
  gap: 4px;
  font-size: 12.5px;
  font-weight: 600;
  color: var(--muted);
}
.section-edit-grid input {
  width: 100%;
  font-weight: 400;
  font-size: 14px;
  color: var(--text);
}
.section-edit-actions {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-top: 16px;
}
.section-edit-msg { font-size: 12.5px; }
.section-edit-msg.is-error { color: var(--danger, #dc2626); font-weight: 600; }
.section-edit-note {
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: 12px;
  color: var(--muted);
  margin: 14px 0 0;
}

@media (max-width: 560px) {
  .section-edit-grid { grid-template-columns: 1fr; }
}

/* In-line edit: software versions (3.3) rows */
.sw-edit-list {
  display: flex;
  flex-direction: column;
  gap: 10px;
  margin-bottom: 4px;
}
.sw-edit-row {
  display: grid;
  grid-template-columns: 180px 1fr;
  gap: 12px 16px;
  align-items: start;
  padding: 12px;
  border: 1px solid var(--border);
  border-radius: 8px;
  background: var(--surface-alt, #fafbfd);
}
.sw-edit-comp { display: flex; flex-direction: column; gap: 2px; }
.sw-edit-name { font-size: 14px; font-weight: 700; color: var(--text); }
.sw-edit-sub  { font-size: 12px; color: var(--muted); }
.sw-edit-fields {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
  gap: 10px 14px;
}
.sw-edit-fields label {
  display: flex;
  flex-direction: column;
  gap: 4px;
  font-size: 12px;
  font-weight: 600;
  color: var(--muted);
}
.sw-edit-fields input { width: 100%; font-weight: 400; font-size: 14px; color: var(--text); }

@media (max-width: 640px) {
  .sw-edit-row { grid-template-columns: 1fr; gap: 10px; }
}

/* =========================================================
   v71.4.6 — Master (read-only) fields inside in-line editor
   ========================================================= */
.section-edit-master {
  background: var(--surface-alt, #fafbfd);
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 12px 14px;
  margin-bottom: 16px;
}
.section-edit-master-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  margin-bottom: 10px;
}
.master-lock {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  font-size: 11px;
  font-weight: 600;
  color: var(--muted);
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 999px;
  padding: 2px 9px;
}
.master-lock-inline { color: var(--muted-soft, #8a9099); }
.section-edit-grid-readonly {
  grid-template-columns: repeat(2, minmax(0, 1fr));
}
.ro-field {
  display: flex;
  flex-direction: column;
  gap: 2px;
}
.ro-label {
  font-size: 12px;
  font-weight: 600;
  color: var(--muted);
  display: inline-flex;
  align-items: center;
  gap: 4px;
}
.ro-value {
  font-size: 14px;
  color: var(--muted);
}
.master-note {
  font-size: 11.5px;
  color: var(--muted-soft, #8a9099);
  font-style: italic;
  margin: 10px 0 0;
  display: flex;
  align-items: center;
  gap: 5px;
}
/* Mixed grid (3.2): read-only fields + editable inputs side by side */
.section-edit-grid-mixed .ro-value {
  padding: 9px 0;
}
@media (max-width: 560px) {
  .section-edit-grid-readonly { grid-template-columns: 1fr; }
}

/* v71.5.2 — Edit signatures button (replaces inline accordions in report view) */
.sig-edit-btn {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  margin-top: 12px;
}
.sig-edit-hint {
  font-size: 12px;
  color: var(--muted);
  font-style: italic;
  margin: 12px 0 0;
}

/* =========================================================
   v71.6 — Start-report visual refinement (Camino A)
   Presentation-only. No logic touched. Self-contained block,
   appended last so it overrides earlier rules predictably and
   can be removed in one piece if ever needed.
   Goals: kill nested-card "boxes-in-boxes", unify subsection
   typography, add breathing room. Uses existing :root tokens.
   ========================================================= */

/* 1) De-nest cards: a .card inside another .card becomes a flat
   section (no own border/shadow/bg), separated by a hairline.
   This removes the "boxes inside boxes" effect on start.php
   without changing any markup. */
.card .card {
  border: 0;
  box-shadow: none;
  background: transparent;
  border-radius: 0;
  padding: 18px 0 4px;
  margin-bottom: 0;
  border-top: 1px solid var(--border);
}
/* First nested card needs no top divider — it sits right under
   the page title, a line there would look like a stray rule. */
.card > .card:first-of-type {
  border-top: 0;
  padding-top: 6px;
}
@media (max-width: 640px) {
  .card .card { padding: 16px 0 4px; }
}

/* 2) Section summaries (the numbered "1 / 2 / 3.1" headers).
   Replace the inline font-weight:800 look with a calmer, more
   "engineered" hierarchy: medium weight, the number badge in
   brand blue. Targets the <summary> used across start.php. */
.card > .card > summary,
.card details.card > summary {
  font-weight: 600 !important;
  font-size: 16px;
  letter-spacing: -0.1px;
  color: var(--text);
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 4px 0;
  margin-bottom: 2px;
}
/* The number/marker pill in section headers → soft blue chip */
.card > .card > summary .badge,
.card details.card > summary .badge {
  background: var(--primary-soft);
  color: var(--primary);
  border: 1px solid var(--primary-border);
  font-weight: 700;
  min-width: 26px;
  justify-content: center;
}

/* 3) Subsection titles (2.1, 2.2, 2.3 …). These are inline
   <div style="font-weight:800"> today. We can't restyle inline
   styles via CSS, so start.php switches them to .subsection-title.
   Calmer weight, brand blue accent, consistent rhythm. */
.subsection-title {
  font-weight: 600;
  font-size: 13.5px;
  color: var(--text-soft);
  margin: 18px 0 10px;
  padding-left: 10px;
  border-left: 3px solid var(--primary);
  line-height: 1.3;
}
.subsection-title:first-child { margin-top: 8px; }

/* 4) Breathing room: rows inside sections get a touch more air
   so ~15 inputs don't feel like a wall. */
.card .card .row { margin-top: 12px; }
.card .card .row:first-of-type { margin-top: 10px; }

/* 5) The intro <p> under each summary — make it read as a quiet
   helper line, not body copy competing with the fields. */
.card .card > p:first-of-type {
  color: var(--muted);
  font-size: 13px;
  line-height: 1.5;
  margin: 8px 0 14px;
}

/* =========================================================
   Inline action form
   ---------------------------------------------------------
   Wrapper for action_button() — POST mini-form used in place
   of GET <a> links for destructive actions (approve, disable,
   delete). display:contents removes the form from the layout
   so the inner button participates directly in the parent
   flex/grid/nowrap container exactly like an <a> did.
   ========================================================= */
.inline-action-form { display: contents; }

/* =========================================================
   Toggle switch (option on/off pill) + toggle card
   ---------------------------------------------------------
   Modern replacement for raw <input type="checkbox"> when the
   field represents an on/off feature flag. The native checkbox
   stays in the DOM (hidden visually) so form submission and
   keyboard/a11y behavior are preserved; the visible track +
   knob is a sibling styled via :checked.
   ========================================================= */
.toggle-row {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 10px;
}
@media (max-width: 720px) {
  .toggle-row { grid-template-columns: 1fr; }
}

.toggle-card {
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 12px 14px;
  border: 1px solid var(--border);
  border-radius: 12px;
  background: #fff;
  cursor: pointer;
  transition: background-color .15s ease, border-color .15s ease,
              box-shadow .15s ease;
  user-select: none;
}
.toggle-card:hover { background: #f6f8fb; }
.toggle-card:has(input:checked) {
  background: var(--success-soft);
  border-color: var(--success-border);
}
.toggle-card:has(input:focus-visible) {
  box-shadow: 0 0 0 3px rgba(0, 117, 201, 0.22);
}

.toggle-switch {
  position: relative;
  display: inline-block;
  width: 42px;
  height: 24px;
  flex: 0 0 auto;
}
.toggle-switch input[type="checkbox"] {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  margin: 0;
  opacity: 0;
  cursor: pointer;
  z-index: 1;
}
.toggle-track {
  position: absolute;
  inset: 0;
  background: #cfd5de;
  border-radius: 999px;
  transition: background-color .18s ease;
}
.toggle-knob {
  position: absolute;
  top: 2px;
  left: 2px;
  width: 20px;
  height: 20px;
  background: #fff;
  border-radius: 50%;
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.18);
  transition: transform .2s cubic-bezier(.4, .0, .2, 1);
}
.toggle-switch input:checked ~ .toggle-track  { background: #22c55e; }
.toggle-switch input:checked ~ .toggle-knob   { transform: translateX(18px); }
.toggle-switch input:disabled ~ .toggle-track { background: #e6e9ef; }
.toggle-switch input:disabled ~ .toggle-knob  { box-shadow: none; }

.toggle-label {
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-width: 0;
}
.toggle-label-main {
  font-weight: 600;
  color: var(--text);
  font-size: 14px;
}
.toggle-label-desc {
  color: var(--muted);
  font-size: 12px;
  line-height: 1.4;
}

/* =========================================================
   Callout
   ---------------------------------------------------------
   Soft notice block used inline inside cards (e.g. "no
   customers yet"). Neutral by default; accepts .is-info /
   .is-warning modifiers later if needed.
   ========================================================= */
.callout {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 12px 14px;
  background: #f6f8fb;
  border: 1px dashed var(--border-strong);
  border-radius: 12px;
  color: var(--text-soft);
  font-size: 14px;
  flex-wrap: wrap;
}
.callout a { font-weight: 600; }

/* =========================================================
   Inverter picker (plant create / edit "Assign from inventory")
   ---------------------------------------------------------
   Grid of selectable inverter cards with a live summary bar
   on top. Each card is a <label> wrapping a hidden checkbox
   plus presentational chrome — toggled state styled via the
   .is-on class (toggled in JS for full browser support, with
   :has() as the progressive enhancement fallback).
   ========================================================= */
.inv-pick-summary {
  display: flex;
  align-items: center;
  flex-wrap: wrap;          /* let pieces drop to next line on narrow */
  row-gap: 4px;
  column-gap: 8px;
  padding: 10px 14px;
  background: var(--primary-soft);
  border: 1px solid var(--primary-border);
  border-radius: 10px;
  font-size: 14px;
  color: var(--text);
  margin: 6px 0 10px;
}
.inv-pick-summary strong { color: var(--primary); font-size: 15px; }
.inv-pick-summary-sep { color: var(--muted-soft); }
.inv-pick-summary-hint {
  color: var(--muted);
  font-size: 13px;
  font-style: italic;
}
/* Narrow viewports: hide the dot separators and let each chunk be its own
   line. The hint becomes a soft footnote under the numbers. */
@media (max-width: 560px) {
  .inv-pick-summary { flex-direction: column; align-items: flex-start; }
  .inv-pick-summary-sep { display: none; }
}

.inv-pick-list {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));
  gap: 10px;
}

.inv-pick-card {
  position: relative;
  display: flex;
  align-items: flex-start;
  gap: 12px;
  padding: 12px 14px;
  border: 1px solid var(--border);
  border-radius: 12px;
  background: #fff;
  cursor: pointer;
  transition: background-color .15s ease, border-color .15s ease,
              box-shadow .15s ease;
  user-select: none;
}
.inv-pick-card:hover { background: #f6f8fb; }
.inv-pick-card.is-on,
.inv-pick-card:has(input:checked) {
  background: var(--success-soft);
  border-color: var(--success-border);
  box-shadow: inset 0 0 0 1px var(--success-border);
}
.inv-pick-card input[type="checkbox"] {
  width: 18px;
  height: 18px;
  margin: 2px 0 0;
  accent-color: var(--success);
  flex: 0 0 auto;
  cursor: pointer;
}
.inv-pick-card.is-locked {
  cursor: not-allowed;
  background: #fff7ed;
  border-color: #fcd9a8;
}
.inv-pick-card.is-locked.is-on,
.inv-pick-card.is-locked:has(input:checked) {
  background: #fff7ed;
  border-color: #fcd9a8;
  box-shadow: inset 0 0 0 1px #fcd9a8;
}
.inv-pick-card .inv-pick-lock {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 18px;
  height: 18px;
  margin: 2px 0 0;
  color: #b45309;
  flex: 0 0 auto;
}
.inv-pick-card-body {
  display: flex;
  flex-direction: column;
  gap: 4px;
  min-width: 0;
  flex: 1;
}
.inv-pick-card-line1 {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
}
.inv-pick-card-line2 {
  font-family: var(--font-mono, monospace);
  font-size: 12px;
  color: var(--text-soft);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.inv-pick-card-line3 {
  font-size: 13px;
  color: var(--muted);
  font-weight: 600;
}

/* =========================================================
   Read-only serial display (edit-inverter form)
   ---------------------------------------------------------
   In edit mode the serial number is immutable (factory-set).
   Render as a styled chip with a lock affordance, while the
   actual value is still submitted via hidden inputs so the
   controller's readForm() stays unchanged.
   ========================================================= */
.serial-readonly {
  display: inline-flex;
  align-items: center;
  gap: 12px;
  padding: 8px 12px;
  background: #f6f8fb;
  border: 1px dashed var(--border-strong);
  border-radius: 10px;
  max-width: 480px;
}
.serial-readonly-badge {
  font-size: 15px;
  padding: 4px 12px;
}
.serial-readonly-note {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  color: var(--muted);
  font-size: 13px;
}
.serial-readonly-note svg { flex: 0 0 auto; }

/* =========================================================
   Type-code help diagram (collapsible <details>)
   ---------------------------------------------------------
   Mirrors Figure 3 of the APS Operating Instructions:
   visualises the 6 segments of the type designation and what
   each one means. Pure HTML/CSS — no images, no JS, scales
   with the theme.
   ========================================================= */
.type-code-help {
  margin-top: 8px;
  padding: 10px 12px;
  background: var(--primary-soft);
  border: 1px solid var(--primary-border);
  border-radius: 10px;
}
.type-code-help > summary {
  cursor: pointer;
  font-weight: 600;
  color: var(--primary);
  font-size: 13px;
  list-style: none;
  padding: 2px 0;
}
.type-code-help > summary::-webkit-details-marker { display: none; }
.type-code-help > summary::before {
  content: '▸';
  display: inline-block;
  margin-right: 6px;
  transition: transform .15s ease;
  color: var(--primary);
}
.type-code-help[open] > summary::before { transform: rotate(90deg); }
.tc-help-hint {
  font-weight: 400;
  color: var(--muted);
  font-size: 12px;
}

.tc-diagram {
  display: grid;
  grid-template-columns: repeat(6, 1fr);
  gap: 0;
  margin-top: 10px;
}
.tc-segment {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  gap: 4px;
  padding: 6px 4px;
  position: relative;
}
/* Dash separator between segments — drawn via ::before so the markup
   stays clean (one segment = one logical block). */
.tc-segment + .tc-segment::before {
  content: '−';
  position: absolute;
  left: -7px;
  top: 14px;             /* aligned to chip vertical center */
  color: var(--muted);
  font-weight: 700;
  font-size: 16px;
  line-height: 1;
}
.tc-chip {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 100%;
  padding: 8px 6px;
  background: #fff;
  border: 1px solid var(--primary-border);
  border-radius: 8px;
  font-family: var(--font-mono, monospace);
  font-weight: 700;
  font-size: 14px;
  color: var(--primary);
}
.tc-chip-brand {
  background: var(--primary);
  color: #fff;
  border-color: var(--primary);
}
.tc-cell-title {
  font-size: 12px;
  font-weight: 700;
  color: var(--text);
  line-height: 1.2;
  margin-top: 4px;
}
.tc-cell-eg {
  font-size: 11px;
  color: var(--muted);
  line-height: 1.3;
}

.tc-legend {
  margin: 10px 0 0;
  padding-top: 8px;
  border-top: 1px solid var(--primary-border);
  font-size: 12px;
  color: var(--text-soft);
  line-height: 1.5;
}
.tc-legend strong { color: var(--text); }

@media (max-width: 720px) {
  .tc-diagram { grid-template-columns: repeat(3, 1fr); }
  .tc-segment + .tc-segment::before { display: none; }
}

/* =========================================================
   Responsive cards-on-mobile table
   ---------------------------------------------------------
   Opt-in pattern: a <table class="table table-mobile-cards">
   keeps its normal table layout on desktop / tablet, but on
   narrow viewports each <tr> collapses into a stacked card.
   Each <td> must carry a data-label="..." attribute — the
   label is rendered inline before the value.

   Layout uses plain block flow (not flex / not grid) so that:
     - Long text values wrap inside the card instead of being
       pushed off-screen by space-between justification.
     - Anonymous text nodes (e.g. <td>foo</td>) render the same
       as elements (e.g. <td><span>foo</span></td>).
     - Empty values still show their label, which makes the
       data shape visible even when fields are blank.

   Use `.td-hide-on-mobile` on any cell that shouldn't appear
   in the card view (the equivalent <th> needs the same class
   if you want the header gone too).
   ========================================================= */
@media (max-width: 720px) {
  .table-mobile-cards thead { display: none; }
  .table-mobile-cards,
  .table-mobile-cards tbody,
  .table-mobile-cards tr {
    display: block;
    width: 100%;
    max-width: 100%;       /* clamp: never exceed parent on real mobile */
    min-width: 0;          /* allow flex/grid children to shrink */
    box-sizing: border-box;
  }
  .table-mobile-cards tr {
    border: 1px solid var(--border);
    border-radius: 12px;
    padding: 14px 16px;
    margin-bottom: 12px;
    background: #fff;
    box-shadow: 0 1px 2px rgba(0, 0, 0, 0.03);
    overflow: hidden;       /* clip any anti-social content (long UIDs etc.) */
  }

  .table-mobile-cards td {
    display: block;
    padding: 6px 0;
    border: none;
    text-align: left !important;  /* override .th-center on cells */
    width: 100%;
    max-width: 100%;
    min-width: 0;
    box-sizing: border-box;
    word-break: break-word;
    overflow-wrap: anywhere;      /* break long UIDs at any char if needed */
  }
  .table-mobile-cards td[data-label]::before {
    content: attr(data-label) ': ';
    display: inline-block;
    margin-right: 8px;
    min-width: 96px;
    font-size: 11px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--muted);
    vertical-align: top;
  }

  /* First cell = card header: bigger, no inline label, divider below. */
  .table-mobile-cards td:first-child {
    padding: 0 0 10px;
    margin-bottom: 8px;
    border-bottom: 1px solid var(--border);
    font-size: 16px;
  }
  .table-mobile-cards td:first-child::before { display: none; }

  /* Action cell sits at the bottom; buttons stretch to fill the card
     width so they are tappable without precision. Use grid (auto-fit)
     instead of flex with basis 0 — that combo could collapse a button
     to zero width on some mobile WebKits (the text disappeared and the
     button rendered as an empty outline). */
  .table-mobile-cards td.td-actions {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(120px, 1fr));
    gap: 8px;
    padding-top: 12px;
    margin-top: 8px;
    border-top: 1px solid var(--border);
  }
  .table-mobile-cards td.td-actions::before { display: none; }
  .table-mobile-cards td.td-actions .btn {
    text-align: center;
    min-width: 0;  /* let grid handle widths */
  }

  /* Nested wrapper treatment: when .table-mobile-cards lives inside a
     .card or .section-card, the inner row-cards switch to an off-white
     background so they read as "items contained inside the wrapper"
     instead of "white blocks stacked on a white panel". Original
     chrome (border + radius + padding) is preserved so the View/Edit
     buttons stay neatly inside their row card.  */
  .card .table-mobile-cards tr,
  .section-card .table-mobile-cards tr {
    background: #f6f8fb;
    border-color: #e3e7ee;
    box-shadow: none;
  }

  /* Opt-out: drop low-priority cells from the mobile card. */
  .table-mobile-cards td.td-hide-on-mobile,
  .table-mobile-cards th.td-hide-on-mobile { display: none; }
}

/* =========================================================
   v0.1.0-pre34 — Branding pass (the company corporate look)
   ---------------------------------------------------------
   - Body background flips to pure white (was --bg #f6f8fb).
     The --bg token is preserved for chip/icon backgrounds
     (section-head-icon, count-badge neutral, etc.) so we
     don't lose those visual cues.
   - h1 and section h2 → brand blue + UPPERCASE + tracking.
   - Top nav → UPPERCASE blue links, white-on-blue active pill.
   - Logo header subtitle handled in the .brand-* rules above.
   Appended at the file's end so it wins by source order
   without rewriting the rules upstream.
   ========================================================= */

body { background: var(--surface); }

/* brand blue UPPERCASE headings — global */
h1 {
  color: var(--primary);
  text-transform: uppercase;
  letter-spacing: 0.6px;
}
/* All section-level h2 (direct child of card/section-card, inside
   section-head, or wrapped in section-edit-head — the "2 Contacts" / "3
   General Information" pattern on the report view). */
.section-head h2,
.section-card > h2,
.card > h2,
.section-edit-head h2,
.card .section-edit-head h2,
.card-header-row h2,
.card .card-header-row h2 {
  color: var(--primary);
  text-transform: uppercase;
  letter-spacing: 0.4px;
}

/* "Reports — TechName" style trailing meta inside an h1: stay readable */
.page-title-meta {
  text-transform: none !important;
  letter-spacing: 0;
  color: var(--muted);
  font-weight: 400;
}

/* ── Top navigation ── UPPERCASE blue links + active pill */
.nav .nav-link {
  margin-left: 4px;
  padding: 6px 10px;
  border-radius: 8px;
  color: var(--primary);
  font-weight: 700;
  font-size: 12.5px;
  text-transform: uppercase;
  letter-spacing: 0.6px;
  opacity: 1;
  transition: background-color .15s ease, color .15s ease;
}
.nav .nav-link:hover {
  background: var(--primary-soft);
  color: var(--primary-hover);
}
.nav .nav-link.is-active,
.nav .nav-link.is-active:visited {
  background: var(--primary);
  color: #fff;
}
.nav .nav-link.is-active:hover {
  background: var(--primary-hover);
  color: #fff;
}

/* Mobile nav panel links share the same uppercase treatment for consistency */
.nav-mobile-panel a {
  text-transform: uppercase;
  letter-spacing: 0.5px;
  color: var(--primary);
}
.nav-mobile-panel a:hover { background: var(--primary-soft); }

/* =========================================================
   v0.2.0-pre3 — Icon-only action buttons
   ---------------------------------------------------------
   Square ~34px button with a single 16px icon and a native
   tooltip via title=. Used in every listing's action cell
   (technicians, managers, customers, plants, inventory,
   reports). Five tones map to the semantic colour tokens:
     default → neutral grey
     .is-primary → brand blue
     .is-success → green   (Activate, Confirm)
     .is-warning → amber   (Disable, Pending)
     .is-danger  → red     (Delete)
   The wrapping <form> for POST actions keeps zero margin so
   icon buttons sit flush in a row.
   ========================================================= */
.btn-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 34px;
  height: 34px;
  padding: 0;
  border-radius: 10px;
  border: 1px solid var(--border-strong);
  background: var(--surface);
  color: var(--muted);
  cursor: pointer;
  text-decoration: none;
  flex-shrink: 0;
  transition: background-color .15s ease, border-color .15s ease,
              color .15s ease, transform .05s ease, box-shadow .15s ease;
}
.btn-icon:hover {
  background: var(--bg);
  border-color: var(--muted-soft);
  color: var(--text);
}
.btn-icon:active { transform: translateY(1px); }
.btn-icon:focus  { outline: none; box-shadow: 0 0 0 4px rgba(0, 117, 201, 0.15); }

.btn-icon.is-primary  { border-color: var(--primary-border); color: var(--primary); }
.btn-icon.is-primary:hover  { background: var(--primary-soft); color: var(--primary-hover); }
.btn-icon.is-success  { border-color: var(--success-border); color: var(--success); }
.btn-icon.is-success:hover  { background: var(--success-soft); }
.btn-icon.is-warning  { border-color: var(--warning-border); color: var(--warning); }
.btn-icon.is-warning:hover  { background: var(--warning-soft); }
.btn-icon.is-danger   { border-color: var(--danger-border);  color: var(--danger); }
.btn-icon.is-danger:hover   { background: var(--danger-soft); }

/* Filled variant — useful when an icon button is THE primary action of a row
   (e.g. "Continue" on an in_process report). */
.btn-icon.is-primary-solid {
  background: var(--primary);
  border-color: var(--primary);
  color: #fff;
}
.btn-icon.is-primary-solid:hover {
  background: var(--primary-hover);
  border-color: var(--primary-hover);
  color: #fff;
}

/* v0.2.0-pre21 — Icon buttons inside a toned section-card inherit the
   bucket colour. The default outlined variant picks up the tone on
   border + icon; .is-primary-solid (the row's primary CTA) gets the
   tone as its fill. Keeps every row visually consistent with the
   section's identity (orange in AWAITING, purple in PENDING WORKS,
   etc.) without having to thread tone classes through every template. */
.section-card.is-urgent  .btn-icon:not(.is-primary-solid),
.section-card.is-danger  .btn-icon:not(.is-primary-solid) {
  border-color: var(--danger-border); color: var(--danger);
}
.section-card.is-urgent  .btn-icon:not(.is-primary-solid):hover,
.section-card.is-danger  .btn-icon:not(.is-primary-solid):hover {
  background: var(--danger-soft); color: var(--danger);
}
.section-card.is-warning .btn-icon:not(.is-primary-solid) {
  border-color: var(--warning-border); color: var(--warning);
}
.section-card.is-warning .btn-icon:not(.is-primary-solid):hover {
  background: var(--warning-soft); color: var(--warning);
}
.section-card.is-info    .btn-icon:not(.is-primary-solid) {
  border-color: var(--info-border); color: var(--info);
}
.section-card.is-info    .btn-icon:not(.is-primary-solid):hover {
  background: var(--info-soft); color: var(--info);
}
.section-card.is-success .btn-icon:not(.is-primary-solid) {
  border-color: var(--success-border); color: var(--success);
}
.section-card.is-success .btn-icon:not(.is-primary-solid):hover {
  background: var(--success-soft); color: var(--success);
}
.section-card.is-purple  .btn-icon:not(.is-primary-solid) {
  border-color: var(--purple-border); color: var(--purple);
}
.section-card.is-purple  .btn-icon:not(.is-primary-solid):hover {
  background: var(--purple-soft); color: var(--purple);
}

/* v0.2.0-pre25 — Inventory uses tint-* neutral-leaning section colours
   (tint-blue Registered, tint-indigo Assigned, tint-purple Scheduled,
   etc). Mirror the bucket-tint rule for btn-icon + section-link so the
   action icons stop reading as "generic grey" inside those sections. */
.section-card.tint-blue   .btn-icon:not(.is-primary-solid)         { border-color: #c5dbef; color: #1d4e89; }
.section-card.tint-blue   .btn-icon:not(.is-primary-solid):hover   { background: #dbe9f7;  color: #1d4e89; }
.section-card.tint-indigo .btn-icon:not(.is-primary-solid)         { border-color: #cccff0; color: #4338ca; }
.section-card.tint-indigo .btn-icon:not(.is-primary-solid):hover   { background: #e3e3f6;  color: #4338ca; }
.section-card.tint-purple .btn-icon:not(.is-primary-solid)         { border-color: var(--purple-border); color: var(--purple); }
.section-card.tint-purple .btn-icon:not(.is-primary-solid):hover   { background: var(--purple-soft);     color: var(--purple); }
.section-card.tint-teal   .btn-icon:not(.is-primary-solid)         { border-color: #b9dcce; color: #0f6e56; }
.section-card.tint-teal   .btn-icon:not(.is-primary-solid):hover   { background: #d4ede4;  color: #0f6e56; }
.section-card.tint-slate  .btn-icon:not(.is-primary-solid)         { border-color: #cfd5de; color: #475569; }
.section-card.tint-slate  .btn-icon:not(.is-primary-solid):hover   { background: #e2e6ed;  color: #475569; }

.section-card.tint-blue   .section-link { color: #1d4e89; }
.section-card.tint-blue   .section-link:hover { background: #dbe9f7; border-color: #c5dbef; }
.section-card.tint-indigo .section-link { color: #4338ca; }
.section-card.tint-indigo .section-link:hover { background: #e3e3f6; border-color: #cccff0; }
.section-card.tint-purple .section-link { color: var(--purple); }
.section-card.tint-purple .section-link:hover { background: var(--purple-soft); border-color: var(--purple-border); }
.section-card.tint-teal   .section-link { color: #0f6e56; }
.section-card.tint-teal   .section-link:hover { background: #d4ede4; border-color: #b9dcce; }
.section-card.tint-slate  .section-link { color: #475569; }
.section-card.tint-slate  .section-link:hover { background: #e2e6ed; border-color: #cfd5de; }

/* H2 in tint-* sections matches the tone too, same pattern as is-*. */
.section-card.tint-blue   .section-head h2 { color: #1d4e89; }
.section-card.tint-indigo .section-head h2 { color: #4338ca; }
.section-card.tint-purple .section-head h2 { color: var(--purple); }
.section-card.tint-teal   .section-head h2 { color: #0f6e56; }
.section-card.tint-slate  .section-head h2 { color: #475569; }

/* Solid CTA variant takes the bucket colour as its fill. */
.section-card.is-urgent  .btn-icon.is-primary-solid,
.section-card.is-danger  .btn-icon.is-primary-solid {
  background: var(--danger); border-color: var(--danger);
}
.section-card.is-warning .btn-icon.is-primary-solid {
  background: var(--warning); border-color: var(--warning);
}
.section-card.is-info    .btn-icon.is-primary-solid {
  background: var(--info); border-color: var(--info);
}
.section-card.is-success .btn-icon.is-primary-solid {
  background: var(--success); border-color: var(--success);
}
.section-card.is-purple  .btn-icon.is-primary-solid {
  background: var(--purple); border-color: var(--purple);
}

/* The inline-action-form wrapper that csrf-form helpers produce —
   keep it inline so consecutive icon buttons sit on one row. */
.inline-action-form { display: inline-flex; margin: 0; }

/* td.td-actions: tight gap between row actions.
   v0.2.0-pre51 — keep the <td> as a real table-cell (display: table-cell,
   inherited from `.table td`) so the row's border-bottom stays flush
   across all columns. The pre45 switch to display:inline-flex broke that
   geometry: the action cell stopped participating in the cell-grid and the
   horizontal divider drew a tiny step where the button sat.
   Center alignment of mixed-height chips + icon buttons is now achieved
   via vertical-align:middle on the children (the cell itself already has
   vertical-align:middle via `.table td`), and inline gaps are restored
   via margin-left on adjacent items so chips and buttons sit on a single
   visual centerline without leaving the table-cell box model. */
.td-actions {
  white-space: nowrap;
  text-align: right;
}
.td-actions .btn-icon,
.td-actions .inline-action-form,
.td-actions .sched-chip {
  vertical-align: middle;
  margin-left: 6px;
}
.td-actions > :first-child,
.td-actions .inline-action-form:first-child .btn-icon {
  margin-left: 0;
}

/* (Legacy left-aligned icon spacing replaced by the compact flex-end
   pattern defined under .plant-actions above.) */

/* ── Certifications grid on users/edit (v0.2.0-pre2) ─────────────────────── */
.cert-grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: 10px;
  margin-top: 6px;
}
@media (min-width: 720px) {
  .cert-grid { grid-template-columns: 1fr 1fr; }
}
.cert-row {
  border: 1px solid var(--border);
  border-radius: 12px;
  padding: 12px 14px;
  background: var(--surface);
  transition: border-color .15s ease, background-color .15s ease;
}
.cert-row.is-held {
  border-color: var(--primary-border);
  background: var(--primary-soft);
}
.cert-row-toggle {
  display: flex;
  align-items: center;
  gap: 8px;
  cursor: pointer;
  font-weight: 600;
  color: var(--text);
}
.cert-row-toggle input[type="checkbox"] {
  width: 16px; height: 16px;
  accent-color: var(--primary);
  margin: 0;
  cursor: pointer;
}
.cert-row-name { font-size: 13.5px; }
.cert-row-date {
  margin-top: 10px;
  display: none;
  flex-direction: column;
}
.cert-row.is-held .cert-row-date { display: flex; }
.cert-row-date input[type="date"] {
  max-width: 220px;
}
.cert-row-expiry {
  display: inline-block;
  margin-top: 6px;
  font-size: 12.5px;
  font-weight: 600;
}

/* ── v0.2.0-pre14: Locked form field (e.g. customer pinned on plant
   creation when the manager came from /customers/view → +Add plant) ── */
.locked-field {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
  padding: 10px 14px;
  background: var(--primary-soft);
  border: 1px solid var(--primary-border);
  border-radius: 10px;
  max-width: 560px;
}
.locked-field-value {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  font-weight: 600;
  color: var(--primary);
  flex: 1;
  min-width: 0;
  overflow-wrap: anywhere;
}
.locked-field-value svg { flex-shrink: 0; }

/* v0.2.0-pre43 — Inline "Schedule cold/hot" chips on the plant view's
   inverter rows. Labeled (not icon-only) because scheduling is a
   high-stakes action — the manager needs to read "Cold" / "Hot"
   unambiguously before clicking. Color-coded for the temperature
   metaphor: cold = blue, hot = warning-orange. */
.sched-chip {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  /* v0.2.0-pre45 — bumped padding so the chip height (~30px) sits closer
     to the .btn-icon (34px) it shares a row with on /plants/view. */
  padding: 7px 11px;
  font-size: 12.5px;
  font-weight: 700;
  text-decoration: none;
  border-radius: 999px;
  border: 1px solid transparent;
  white-space: nowrap;
  transition: background .15s ease, color .15s ease, border-color .15s ease;
  letter-spacing: 0.3px;
  line-height: 1;
}
.sched-chip-cold {
  background: #e7f2ff;
  color: #0b5aa6;
  border-color: #9ec8f3;
}
.sched-chip-cold:hover {
  background: #0b5aa6;
  color: #fff;
  border-color: #0b5aa6;
}
.sched-chip-hot {
  background: #fff3e0;
  color: #b45309;
  border-color: #fcd9a4;
}
.sched-chip-hot:hover {
  background: #b45309;
  color: #fff;
  border-color: #b45309;
}
.sched-chip svg { flex-shrink: 0; }

/* ── v0.2.0-pre23: Mobile report-card head.
   One row: SERIAL + [COLD] + [v020]. Plant drops to a second line.
   Compact: no orphan badge stack, no extra vertical air. */
.report-card-head { margin-bottom: 2px; min-width: 0; }
.report-card-serial-row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 6px 8px;
}
.report-card-serial {
  font-family: var(--font-mono, monospace);
  font-size: 15px;
  font-weight: 800;
  color: var(--primary);
  letter-spacing: 0.3px;
  line-height: 1.15;
  overflow-wrap: anywhere;
}
.report-card-serial-row .badge {
  font-weight: 700;
  letter-spacing: 0.4px;
}
.report-card-plant {
  margin-top: 4px;
  font-weight: 600;
  color: var(--text);
  font-size: 14px;
  overflow-wrap: anywhere;
  line-height: 1.3;
}
.report-card-meta {
  margin-top: 4px;
  font-size: 12px;
  color: var(--muted);
  letter-spacing: 0.1px;
  overflow-wrap: anywhere;
}

/* =========================================================
   v0.2.0-pre53 — Docs-ack manuals panel
   ---------------------------------------------------------
   Rendered in /reports/confirm right above the "I have read
   the manuals" toggle. Lists the equipment's available
   manuals so the tech can actually open / download them in
   place instead of being told they should have read them
   somewhere else.
   ========================================================= */
.doc-ack-manuals {
  margin: 0 0 14px 0;
  padding: 12px 14px;
  border: 1px solid var(--border);
  border-radius: 12px;
  background: var(--bg);
}
.doc-ack-manuals-head {
  display: flex;
  align-items: center;
  gap: 8px;
  font-weight: 600;
  font-size: 13px;
  color: var(--text);
  margin-bottom: 10px;
  text-transform: uppercase;
  letter-spacing: 0.4px;
}
.doc-ack-manuals-head > svg { flex: 0 0 auto; color: var(--primary); }
.doc-ack-manuals-all {
  margin-left: auto;
  display: inline-flex;
  align-items: center;
  gap: 4px;
  font-size: 12px;
  font-weight: 500;
  color: var(--primary);
  text-decoration: none;
  letter-spacing: 0.2px;
  text-transform: none;
}
.doc-ack-manuals-all:hover { color: var(--primary-hover); text-decoration: underline; }

.doc-ack-manuals-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: 6px;
}
.doc-ack-manuals-list li {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 8px 10px;
  border: 1px solid var(--border);
  border-radius: 8px;
  background: var(--surface);
  transition: border-color .15s ease, background-color .15s ease;
}
.doc-ack-manuals-list li:hover {
  border-color: var(--primary-border);
  background: var(--primary-soft);
}
.doc-ack-manuals-list li > a:first-child {
  flex: 1 1 auto;
  display: flex;
  align-items: center;
  gap: 10px;
  color: var(--text);
  text-decoration: none;
  font-size: 14px;
  min-width: 0;
}
.doc-ack-manuals-list li > a:first-child svg { flex: 0 0 auto; color: var(--muted); }
.doc-ack-manuals-list li:hover > a:first-child svg { color: var(--primary); }

.doc-ack-manuals-title {
  font-weight: 500;
  color: var(--text);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.doc-ack-manuals-cat {
  margin-left: auto;
  flex: 0 0 auto;
  font-size: 12px;
  color: var(--muted);
  padding: 2px 8px;
  border-radius: 999px;
  background: var(--bg);
  border: 1px solid var(--border);
}
.doc-ack-manuals-dl {
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 30px;
  height: 30px;
  border-radius: 8px;
  border: 1px solid var(--border);
  background: var(--surface);
  color: var(--muted);
  text-decoration: none;
  transition: background-color .15s ease, color .15s ease, border-color .15s ease;
}
.doc-ack-manuals-dl:hover {
  background: var(--primary-soft);
  border-color: var(--primary-border);
  color: var(--primary);
}

/* v0.2.0-pre95 — Manuals list mobile layout.
   Old rule wrapped the category as a full-width chip BELOW the title and
   pushed the download icon to a third line, with the chip rendering as
   a fake "search input" pill. New layout: title + dl icon on a single
   row, full title visible (allowed to wrap to 2 lines via word-break),
   category collapsed to a small muted caption below — no pill chrome.
   Breakpoint bumped to 760px so tablets (which were the worst case)
   pick up the same fix. */
@media (max-width: 760px) {
  .doc-ack-manuals-list li > a:first-child {
    flex-wrap: wrap;
    align-items: flex-start;
    row-gap: 2px;
  }
  .doc-ack-manuals-title {
    flex: 1 1 auto;
    white-space: normal;
    overflow: visible;
    text-overflow: clip;
    word-break: break-word;
    min-width: 0;
  }
  .doc-ack-manuals-cat {
    margin-left: 24px;
    margin-top: 0;
    flex-basis: 100%;
    padding: 0;
    background: none;
    border: none;
    border-radius: 0;
    color: var(--muted);
    font-size: 11.5px;
    letter-spacing: 0.2px;
  }
  .doc-ack-manuals-head {
    flex-wrap: wrap;
    row-gap: 4px;
  }
  .doc-ack-manuals-all { margin-left: 0; }
}

/* =========================================================
   v0.2.0-pre56 — Report view header
   ---------------------------------------------------------
   Header chip row + subhead used by /reports/view. Pulls
   the report identity apart (serial in blue, COLD/HOT type,
   version, wizard + workflow status) so the tech can scan
   the row at a glance instead of reading a long underscore-
   joined report_uid.
   ========================================================= */
.report-head-chips {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 8px;
  margin: 4px 0 0 0;
}
/* pre56 legacy chip (kept for back-compat with older builds). pre58
   promotes the serial into the H1 instead — see .report-head-title /
   .report-head-serial-inline below. */
.report-head-serial {
  display: inline-flex;
  align-items: center;
  padding: 4px 10px;
  font-family: 'JetBrains Mono', 'Courier New', monospace;
  font-weight: 600;
  font-size: 14px;
  color: var(--primary);
  background: var(--primary-soft);
  border: 1px solid var(--primary-border);
  border-radius: 999px;
  letter-spacing: 0.4px;
}

/* v0.2.0-pre58 — Serial baked into the H1.
   Reads "Report · APS-000605 HOT" as a single confident headline:
   the word "Report" in the dark site title style, then a thin separator,
   then the serial in primary blue (monospaced so digits stay aligned),
   then the type pill. Wraps cleanly on narrow viewports. */
.report-head-title {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 10px;
  margin: 0 0 8px 0;
  line-height: 1.2;
}
.report-head-title-sep {
  color: var(--muted);
  font-weight: 400;
}
.report-head-serial-inline {
  /* v0.2.0-pre61 — Switched OFF monospace so the serial reads as part of
     the H1 ("REPORT · APS-000405"), same font / size as the word REPORT,
     just in primary blue. Monospace made it stand apart and felt out of
     place inside the title row. */
  font-weight: 700;
  color: var(--primary);
}
.report-head-type {
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.6px;
  align-self: center;
}

/* v0.2.0-pre61 — Drop the COLD/HOT pill out of the H1 onto the chip row
   below, so the title stays clean ("REPORT · APS-000405") and the rest of
   the badges line up under it. The pill is still added in the markup;
   this rule moves it into a separate flex grid via order if a layout
   ever needs it. Currently we just keep it inside the H1 — but we also
   render it on the chip row below for the new layout. */
.report-head-plant {
  margin-top: 8px;
  font-size: 16px;
  color: var(--text);
}
.report-head-plant strong { font-weight: 600; }
.report-head-meta {
  margin-top: 4px;
  font-size: 13px;
  color: var(--muted);
}
.report-head-meta strong { color: var(--text); font-weight: 500; }

/* =========================================================
   v0.2.0-pre69 — Shared column grid for /reports bucket tables
   ---------------------------------------------------------
   Every bucket section (Awaiting, Scheduled, Rejected, Pending
   validation, In process, Pending works, Validated) renders its
   own <table> with the SAME 8 columns. Default table-layout:auto
   sized each one independently from its contents — so the
   Plant column in "REJECTED" (1 row, short text) was narrower
   than the Plant column in "AWAITING" (3 rows, longer text)
   and the columns drifted between sections. Lock all bucket
   tables to a fixed grid so they line up vertically when
   stacked on the page.
   ========================================================= */
.report-bucket-table {
  table-layout: fixed;
  width: 100%;
}
.report-bucket-table th,
.report-bucket-table td {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
/* Column widths in percent so the grid scales with the viewport.
   Sum = 100%. Tuned so Serial / Type / Version don't squash and
   the Plant column still has room for the longest demo names. */
.report-bucket-table th:nth-child(1),
.report-bucket-table td:nth-child(1) { width: 12%; } /* Serial */
.report-bucket-table th:nth-child(2),
.report-bucket-table td:nth-child(2) { width: 15%; overflow: visible; text-overflow: clip; } /* Work (Comm. / Maint. / Repair) */
.report-bucket-table th:nth-child(3),
.report-bucket-table td:nth-child(3) { width: 14%; white-space: normal; } /* Plant (allow wrap) */
.report-bucket-table th:nth-child(4),
.report-bucket-table td:nth-child(4) { width: 13%; } /* Day */
.report-bucket-table th:nth-child(5),
.report-bucket-table td:nth-child(5) { width: 12%; } /* Technician */
.report-bucket-table th:nth-child(6),
.report-bucket-table td:nth-child(6) { width: 13%; white-space: normal; } /* Stage (bar + label) */
.report-bucket-table th:nth-child(7),
.report-bucket-table td:nth-child(7) { width:  7%; } /* Open */
.report-bucket-table th:nth-child(8),
.report-bucket-table td:nth-child(8) { width: 14%; text-align: right; white-space: nowrap; } /* Actions: eye + PDF icons */

/* v0.3.0-pre8 — The bucket-table generic rule above applies
   `overflow: hidden + text-overflow: ellipsis` to every cell, which
   is what we want for long Plant / Customer / Tech names. But for
   action cells it was clipping the second icon (e.g. the Download
   PDF button next to the eye on validated reports) and showing "…"
   instead. The actions cell is always the LAST column and aligns
   right, so allowing the content to be visible doesn't overlap
   anything — it just stops the unwanted ellipsis. */
.report-bucket-table td.td-actions,
.inventory-bucket-table td.td-actions,
.plants-bucket-table td.td-actions,
.customers-bucket-table td.td-actions,
.users-bucket-table td.td-actions {
  overflow: visible;
  text-overflow: clip;
}

/* v0.2.0-pre71 — Same shared-column-grid trick for /inventory bucket
   tables (Registered, Assigned, Scheduled, In commissioning,
   Commissioned, Retired). Default table-layout: auto sized each
   bucket independently, so columns drifted vertically between
   sections. Lock all to a fixed grid summing 100%. */
.inventory-bucket-table {
  table-layout: fixed;
  width: 100%;
}
.inventory-bucket-table th,
.inventory-bucket-table td {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.inventory-bucket-table th:nth-child(1),
.inventory-bucket-table td:nth-child(1) { width: 13%; } /* Serial */
.inventory-bucket-table th:nth-child(2),
.inventory-bucket-table td:nth-child(2) { width: 17%; } /* Type   */
.inventory-bucket-table th:nth-child(3),
.inventory-bucket-table td:nth-child(3) { width:  8%; text-align: center; } /* Year */
.inventory-bucket-table th:nth-child(4),
.inventory-bucket-table td:nth-child(4) { width: 18%; white-space: normal; } /* Options chips */
.inventory-bucket-table th:nth-child(5),
.inventory-bucket-table td:nth-child(5) { width: 22%; white-space: normal; } /* Assigned to (plant + customer) */
.inventory-bucket-table th:nth-child(6),
.inventory-bucket-table td:nth-child(6) { width: 13%; } /* Status pill */
.inventory-bucket-table th:nth-child(7),
.inventory-bucket-table td:nth-child(7) { width:  9%; text-align: right; } /* Actions */

/* v0.2.0-pre72 — Shared grid for /customers bucket tables.
   Columns: Name | Country | Plants | Commissioning chips | Actions. */
.customers-bucket-table {
  table-layout: fixed;
  width: 100%;
}
.customers-bucket-table th,
.customers-bucket-table td {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.customers-bucket-table th:nth-child(1),
.customers-bucket-table td:nth-child(1) { width: 30%; white-space: normal; } /* Name */
.customers-bucket-table th:nth-child(2),
.customers-bucket-table td:nth-child(2) { width: 10%; } /* Country */
.customers-bucket-table th:nth-child(3),
.customers-bucket-table td:nth-child(3) { width:  8%; text-align: center; } /* Plants count */
.customers-bucket-table th:nth-child(4),
.customers-bucket-table td:nth-child(4) { width: 40%; white-space: normal; } /* Commissioning chips */
.customers-bucket-table th:nth-child(5),
.customers-bucket-table td:nth-child(5) { width: 12%; text-align: right; } /* Actions */

/* v0.2.0-pre72 — Shared grid for /plants bucket tables.
   Columns: Plant | Customer | Inverters | Commissioning status | Capacity | Actions. */
.plants-bucket-table {
  table-layout: fixed;
  width: 100%;
}
.plants-bucket-table th,
.plants-bucket-table td {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.plants-bucket-table th:nth-child(1),
.plants-bucket-table td:nth-child(1) { width: 22%; white-space: normal; } /* Plant name + country */
.plants-bucket-table th:nth-child(2),
.plants-bucket-table td:nth-child(2) { width: 22%; white-space: normal; } /* Customer */
.plants-bucket-table th:nth-child(3),
.plants-bucket-table td:nth-child(3) { width:  9%; text-align: center; } /* Inverters count */
.plants-bucket-table th:nth-child(4),
.plants-bucket-table td:nth-child(4) { width: 28%; white-space: normal; } /* Commissioning status chips */
.plants-bucket-table th:nth-child(5),
.plants-bucket-table td:nth-child(5) { width: 10%; text-align: center; } /* Capacity */
.plants-bucket-table th:nth-child(6),
.plants-bucket-table td:nth-child(6) { width:  9%; text-align: right; } /* Actions */

/* =========================================================
   v0.2.0-pre62 — "Respond to counter-proposal" card layout
   ---------------------------------------------------------
   Two cells side-by-side on desktop, stacked on mobile.
   Send-back form keeps the date input and the submit chip
   on a single flex row that snaps the chip to the input's
   baseline (so they look vertically centered together
   instead of the chip floating below the field).
   ========================================================= */
/* v0.2.0-pre64 — Single-column stack. Accept on top, Send another date
   below. The two-column layout felt cramped even on desktop and was
   confusing on mobile. */
/* v0.2.0-pre97 — Reassign-technician card on /reports/view and the matching
   decline-assignment card on /reports/confirm. Both use <details>/<summary>
   so they're collapsed by default and only expand when the action is needed
   (or when the controller sent an error back via the query string). */
.reassign-card,
.decline-card {
  padding: 0 !important;
}
.reassign-card > summary,
.decline-card > summary {
  list-style: none;
  cursor: pointer;
  padding: 14px 18px;
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 8px 14px;
  border-radius: 12px;
}
.reassign-card > summary::-webkit-details-marker,
.decline-card > summary::-webkit-details-marker { display: none; }
.reassign-card[open] > summary,
.decline-card[open] > summary {
  border-bottom: 1px solid var(--border, #d8e0ea);
}
.reassign-card-title,
.decline-card-title {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  font-size: 16px;
  font-weight: 700;
  color: var(--primary, #0075c9);
}
.decline-card-title { color: #b91c1c; }
.reassign-card-hint,
.decline-card-hint {
  color: var(--muted);
  font-size: 13px;
  flex: 1 1 100%;
}
.reassign-form,
.decline-card form {
  padding: 14px 18px 18px;
}
.reassign-row {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 2fr);
  gap: 14px;
}
.reassign-field { display: flex; flex-direction: column; gap: 4px; min-width: 0; }
.reassign-field label,
.decline-card label {
  font-size: 12px;
  font-weight: 600;
  color: var(--muted);
}
.reassign-field select,
.reassign-field textarea,
.decline-card textarea,
.decline-card input[type="text"] {
  width: 100%;
  padding: 10px 12px;
  border: 1px solid var(--border, #d8e0ea);
  border-radius: 10px;
  font: inherit;
  font-size: 14px;
  background: var(--surface, #fff);
  color: var(--text, #1a1a2e);
  box-sizing: border-box;
}
.reassign-field textarea,
.decline-card textarea { resize: vertical; }
.reassign-field select:focus,
.reassign-field textarea:focus,
.decline-card textarea:focus,
.decline-card input[type="text"]:focus {
  outline: none;
  border-color: var(--primary, #0075c9);
  box-shadow: 0 0 0 4px rgba(0, 117, 201, 0.12);
}
.reassign-actions {
  display: flex;
  justify-content: flex-end;
  margin-top: 14px;
}
@media (max-width: 720px) {
  .reassign-row { grid-template-columns: 1fr; }
}

/* v0.2.0-pre96 — Tech's counter-proposal note inside the manager response
   card. Pulled from report_workflow_log so the manager sees the rationale
   without scrolling to the audit log at the bottom of the page. */
.mgr-response-note {
  margin: 0 0 16px;
  padding: 10px 12px;
  background: var(--primary-soft, #eaf4fb);
  border: 1px solid var(--primary-border, #bcd9ee);
  border-radius: 10px;
}
.mgr-response-note-head {
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: 12px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.3px;
  color: var(--primary, #0075c9);
  margin-bottom: 6px;
}
.mgr-response-note-body {
  font-size: 14px;
  line-height: 1.5;
  color: var(--text, #1a1a2e);
  word-wrap: break-word;
  white-space: pre-wrap;
}

.mgr-response-grid {
  display: flex;
  flex-direction: column;
  gap: 22px;
}
.mgr-response-cell { min-width: 0; }
.mgr-response-counter-form {
  margin: 0;
  display: flex;
  align-items: flex-end;     /* date input + chip share the bottom edge */
  gap: 10px;
  flex-wrap: wrap;
}
.mgr-response-date-field {
  display: flex;
  flex-direction: column;
  flex: 1 1 auto;
  min-width: 0;
  max-width: 320px;
}
.mgr-response-date-field label {
  margin: 0 0 4px 0;
  font-size: 12px;
  font-weight: 600;
  color: var(--muted);
  text-transform: uppercase;
  letter-spacing: 0.4px;
}
.mgr-response-date-field input[type="date"] {
  width: 100%;
}
.mgr-response-counter-form > .action-pill {
  flex-shrink: 0;
}
@media (max-width: 540px) {
  /* Mobile: date input takes its own row, button below full-width. */
  .mgr-response-counter-form {
    flex-direction: column;
    align-items: stretch;
  }
  .mgr-response-date-field { max-width: none; }
  .mgr-response-counter-form > .action-pill {
    align-self: flex-start;
  }
}

/* =========================================================
   v0.2.0-pre89 — Internal comments card on /reports/view
   ---------------------------------------------------------
   Unnumbered card living between Signatures and Workflow log.
   It's an append-only message thread between the technician
   and the manager(s) of a report. Not part of the audited
   workflow log (which is system-generated state transitions)
   and never included in the PDF.
   ========================================================= */
.report-comments-card { }
.report-comments-sub {
  margin: -4px 0 14px;
  color: var(--muted);
  font-size: 13px;
}
.report-comments-list {
  display: flex;
  flex-direction: column;
  gap: 10px;
  margin-bottom: 16px;
}
.report-comments-empty {
  margin: 0;
  padding: 14px 16px;
  background: var(--surface-alt, #f7f9fc);
  border: 1px dashed var(--border, #d8e0ea);
  border-radius: 10px;
  color: var(--muted);
  font-size: 13.5px;
  text-align: center;
}
.report-comment {
  border: 1px solid var(--border, #d8e0ea);
  border-radius: 10px;
  padding: 12px 14px;
  background: var(--surface, #fff);
}
.report-comment.is-mine {
  background: var(--primary-soft, #eaf4fb);
  border-color: var(--primary-border, #bcd9ee);
}
.report-comment-head {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px;
  margin-bottom: 6px;
  font-size: 12.5px;
  color: var(--muted);
}
.report-comment-author {
  font-weight: 700;
  color: var(--text, #1a1a2e);
  font-size: 13px;
}
.report-comment-role-badge {
  display: inline-block;
  padding: 2px 8px;
  border-radius: 999px;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.3px;
  text-transform: uppercase;
  background: var(--primary-soft, #eaf4fb);
  color: var(--primary, #0075c9);
  border: 1px solid var(--primary-border, #bcd9ee);
}
.report-comment-role-badge.role-admin {
  background: #fff4e6;
  color: #b45309;
  border-color: #f3d6a8;
}
.report-comment-role-badge.role-manager {
  background: #eaf4fb;
  color: #0075c9;
  border-color: #bcd9ee;
}
.report-comment-role-badge.role-technician {
  background: #e8f5ec;
  color: #15803d;
  border-color: #c4e1cc;
}
.report-comment-time { margin-left: auto; font-variant-numeric: tabular-nums; }
.report-comment-mine-tag {
  font-size: 10.5px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.4px;
  color: var(--primary, #0075c9);
  background: var(--surface, #fff);
  border: 1px solid var(--primary-border, #bcd9ee);
  border-radius: 999px;
  padding: 1px 6px;
}
.report-comment-body {
  font-size: 14px;
  line-height: 1.5;
  color: var(--text, #1a1a2e);
  white-space: pre-wrap;
  word-wrap: break-word;
}
.report-comments-alert {
  margin-bottom: 10px;
  padding: 8px 12px;
  background: #fdecea;
  border: 1px solid #f3b3ad;
  border-radius: 8px;
  color: #c0392b;
  font-size: 13px;
}
.report-comments-form { }
.report-comments-label {
  display: block;
  font-size: 12px;
  font-weight: 600;
  color: var(--muted);
  margin-bottom: 6px;
}
.report-comments-textarea {
  width: 100%;
  padding: 10px 12px;
  border: 1px solid var(--border, #d8e0ea);
  border-radius: 10px;
  font: inherit;
  font-size: 14px;
  resize: vertical;
  background: var(--surface, #fff);
  color: var(--text, #1a1a2e);
  box-sizing: border-box;
}
.report-comments-textarea:focus {
  outline: none;
  border-color: var(--primary, #0075c9);
  box-shadow: 0 0 0 4px rgba(0, 117, 201, 0.12);
}
.report-comments-actions {
  display: flex;
  justify-content: flex-end;
  margin-top: 10px;
}
@media (max-width: 540px) {
  .report-comment-time { margin-left: 0; width: 100%; }
}

/* =========================================================
   v0.2.0-pre85 — Friendly error pages (403 / 404 / 5xx)
   ---------------------------------------------------------
   Replaces the legacy `echo 'Forbidden'` plain-text response.
   Renders inside the standard layout so the user keeps the
   topbar / nav and gets a "Back to dashboard" CTA.
   ========================================================= */
.error-page-wrap {
  display: flex;
  justify-content: center;
  padding: 40px 20px;
}
.error-page-card {
  max-width: 540px;
  width: 100%;
  text-align: center;
  padding: 36px 28px;
}
.error-page-icon {
  display: inline-flex;
  width: 72px;
  height: 72px;
  align-items: center;
  justify-content: center;
  border-radius: 50%;
  margin: 0 auto 12px;
  background: var(--primary-soft);
  color: var(--primary);
}
.error-page-card.is-warning .error-page-icon {
  background: var(--warning-soft); color: var(--warning);
}
.error-page-card.is-danger .error-page-icon {
  background: var(--danger-soft);  color: var(--danger);
}
.error-page-card.is-info .error-page-icon {
  background: var(--info-soft);    color: var(--info);
}
.error-page-code {
  font-family: 'JetBrains Mono', 'Courier New', monospace;
  font-size: 13px;
  font-weight: 700;
  letter-spacing: 1px;
  color: var(--muted);
  margin-bottom: 8px;
}
.error-page-title {
  margin: 0 0 10px 0;
  color: var(--primary);
  text-transform: uppercase;
  letter-spacing: 0.4px;
}
.error-page-message {
  margin: 0 0 22px 0;
  color: var(--muted);
  line-height: 1.5;
  font-size: 15px;
}
.error-page-actions {
  display: flex;
  justify-content: center;
  gap: 10px;
}

/* =========================================================
   v0.2.0-pre56 — toggle-card error / shake states
   ---------------------------------------------------------
   Used by /reports/confirm to highlight the "I have read
   the manuals" toggle when the tech tried to submit without
   ticking it. The shake animation fires once on click (the
   class is added, reflow forced, animation plays then is
   removed by future toggling).
   ========================================================= */
.toggle-card-error {
  border: 1.5px solid var(--danger);
  background: var(--danger-soft, #fdecea);
  border-radius: 12px;
  padding: 12px;
}
.toggle-card-error .toggle-label-desc {
  color: var(--danger);
  font-weight: 500;
}
@keyframes toggle-card-shake {
  0%, 100% { transform: translateX(0); }
  20%      { transform: translateX(-6px); }
  40%      { transform: translateX(6px); }
  60%      { transform: translateX(-4px); }
  80%      { transform: translateX(4px); }
}
.toggle-card-shake { animation: toggle-card-shake .35s ease-out; }

/* =========================================================
   v0.3.0-pre6 — Table scroll wrapper + secondary col hide
   =========================================================
   Listings (Inventory, Reports, Plants, Customers, Users) wrap
   their <table> in a `.desktop-only.table-scroll` container.
   At intermediate widths the layout stays usable in three ways:

   1. Columns flagged `.col-secondary` collapse out first
      (least critical info, e.g. Options badges, Year, Version,
      Capacity, Plant count).

   2. If remaining columns still overflow, the wrapper scrolls
      horizontally — the table never gets crushed into pegado
      cells where action icons disappear.

   3. The first column (Serial / Name / Plant) is pinned to the
      left so the row anchor stays visible while you scroll right
      to see other data.

   Mobile (<769px) keeps swapping to the card layout below the
   wrapper, so this CSS only ever applies in the tablet / half-
   screen range (769px - 1100px) and beyond.
*/

.table-scroll {
  position: relative;
  overflow-x: auto;
  /* Smooth scroll on touch devices and trackpads. */
  -webkit-overflow-scrolling: touch;
}

/* v0.3.0-pre7 — Removed the right-edge gradient hint. It conflicted
   with the rounded card corners (rectangle inside a curved card) and
   produced inconsistency between pages that had / didn't have the
   wrapper. The sticky-column shadow + the browser's native horizontal
   scrollbar are enough to signal "there's more to the right". */

/* Tables inside the scroll wrapper need a sane minimum width so they
   don't compress past readability — the wrapper takes over scroll.
   The per-listing tables already set table-layout: fixed; width: 100%;
   we just enforce a floor. */
.table-scroll > .table {
  min-width: 720px;
}

/* Sticky first column — anchored to the left edge of the viewport.
   Background is required so content scrolling beneath stays hidden. */
.table-scroll > .table > thead > tr > th:first-child,
.table-scroll > .table > tbody > tr > td:first-child {
  position: sticky;
  left: 0;
  background: #fff;
  z-index: 1;
  /* Soft shadow on the right edge so the sticky column reads as a
     separate plane from the scrolling content. */
  box-shadow: 8px 0 10px -8px rgba(15, 23, 42, 0.10);
}
/* Header sticky cell must sit above body sticky cells AND above
   non-sticky body cells, so we bump its z-index. */
.table-scroll > .table > thead > tr > th:first-child {
  z-index: 2;
  /* Header background — slightly different so the header row reads
     as a distinct band even when scrolled. */
  background: #fff;
}

/* Hide low-priority columns at intermediate viewports. Only fires
   in the band 769px - 1100px: below 769px the table is hidden
   anyway (mobile-only cards take over), above 1100px there's enough
   width for the full table. */
@media (max-width: 1100px) and (min-width: 769px) {
  .col-secondary { display: none !important; }

  /* When a fixed-layout table loses a column, the remaining widths
     (which were percentages summing to 100%) can leave gaps. Flip
     to auto layout in this band so the visible columns redistribute
     naturally. */
  .table-scroll > .table {
    table-layout: auto;
  }
  .table-scroll > .table th,
  .table-scroll > .table td {
    width: auto;
  }
}



/* =========================================================
   Commissioning plans — technician availability calendar and plan form
   =========================================================*/
.avail-wrap { overflow-x: auto; }
.avail-grid { border-collapse: separate; border-spacing: 2px; width: 100%; font-size: 13px; }
.avail-grid th, .avail-grid td { text-align: center; }
.avail-grid .avail-tech { text-align: left; padding: 6px 10px 6px 0; white-space: nowrap; font-weight: 600; position: sticky; left: 0; background: var(--bg, #fff); }
.avail-grid .avail-day { font-weight: 500; color: var(--muted); line-height: 1.15; padding: 2px 0; min-width: 40px; }
.avail-grid .avail-day span { display: block; font-size: 10.5px; text-transform: uppercase; letter-spacing: .3px; }
.avail-grid .avail-day strong { display: block; font-size: 14px; color: var(--text); }
.avail-grid .avail-day.is-today strong { color: var(--primary); }
.avail-grid .avail-day.is-weekend { opacity: .55; }
.avail-cell { height: 34px; border-radius: 6px; border: 1px solid var(--success-border); background: var(--success-soft); font-weight: 700; cursor: default; }
.avail-cell.is-some { background: var(--warning-soft); border-color: var(--warning-border); color: #7a4f00; }
.avail-cell.is-busy { background: var(--danger-soft);  border-color: var(--danger-border);  color: #b91c1c; }
.avail-cell.is-weekend.is-free { background: #f3f4f6; border-color: #e5e7eb; }
.avail-certs { display: block; font-size: 10.5px; font-weight: 500; color: var(--muted); }
.avail-legend { margin: 8px 0 0; }
.avail-key { display: inline-block; width: 12px; height: 12px; border-radius: 3px; vertical-align: -1px; margin: 0 4px 0 12px; border: 1px solid var(--success-border); background: var(--success-soft); }
.avail-key:first-child { margin-left: 0; }
.avail-key.is-some { background: var(--warning-soft); border-color: var(--warning-border); }
.avail-key.is-busy { background: var(--danger-soft);  border-color: var(--danger-border); }
.plan-check { display: inline-flex; align-items: center; gap: 8px; margin: 0; font-size: 13.5px; font-weight: 600; color: var(--text); cursor: pointer; }
.plan-check input, .plan-tech input { width: 18px; height: 18px; margin: 0; padding: 0; flex: none; cursor: pointer; accent-color: var(--primary, #0a4f86); }
.plan-techs { display: grid; grid-template-columns: repeat(auto-fill, minmax(240px, 1fr)); gap: 8px; margin-top: 6px; }
.plan-tech { display: flex; align-items: center; gap: 10px; padding: 8px 12px; border: 1px solid var(--border); border-radius: 8px; cursor: pointer; font-weight: 600; font-size: 13.5px; color: var(--text); margin: 0; }
.plan-tech .avail-certs { margin-left: auto; white-space: nowrap; }

/* =========================================================
   Vertical sidebar layout (default; 'layout' => 'topbar' in config.local.php
   brings back the horizontal menu). Structure borrowed from the owner's
   management app; colours stay the company: navy derived from --primary.
   Markup: layouts/main.php (.sidebar, .app-main, .app-topbar).
   =========================================================*/
:root {
  --side-w: 248px;
  --side-bg: #0b2239;
  --side-text: #b9cbdd;
  --side-muted: #6f8aa5;
  --side-hover: rgba(255, 255, 255, 0.07);
}
.nav-toggle { position: absolute; opacity: 0; pointer-events: none; width: 0; height: 0; }
.sidebar {
  position: fixed; top: 0; bottom: 0; left: 0; z-index: 40;
  width: var(--side-w); background: var(--side-bg); color: var(--side-text);
  display: flex; flex-direction: column; overflow-y: auto;
  transform: translateX(-100%); transition: transform .25s ease;
  scrollbar-width: thin; scrollbar-color: #1d3b57 transparent;
}
.sidebar::-webkit-scrollbar { width: 6px; }
.sidebar::-webkit-scrollbar-thumb { background: #1d3b57; border-radius: 9999px; }
.nav-toggle:checked ~ .sidebar { transform: none; }
.sidebar-backdrop {
  position: fixed; inset: 0; z-index: 30; background: rgba(8, 20, 34, .5);
  opacity: 0; pointer-events: none; transition: opacity .2s ease;
}
.nav-toggle:checked ~ .sidebar-backdrop { opacity: 1; pointer-events: auto; }

.side-brand { display: flex; flex-direction: column; gap: 6px; padding: 22px 22px 16px; text-decoration: none; }
.side-logo { height: 22px; width: auto; align-self: flex-start; filter: brightness(0) invert(1); }
.side-wordmark { font-weight: 800; font-size: 20px; color: #fff; letter-spacing: .3px; }
.side-sub { font-size: 10.5px; font-weight: 700; letter-spacing: .18em; text-transform: uppercase; color: var(--side-muted); }

.side-nav { flex: 1; padding: 4px 12px 12px; }
.side-group {
  margin: 20px 10px 6px; font-size: 10.5px; font-weight: 700;
  letter-spacing: .14em; text-transform: uppercase; color: var(--side-muted);
}
.side-link {
  display: flex; align-items: center; gap: 12px; padding: 9px 12px; margin-bottom: 2px;
  border-radius: 12px; color: var(--side-text); font-size: 14px; font-weight: 600;
  text-decoration: none; transition: background .15s ease, color .15s ease;
}
.side-link svg { flex: none; opacity: .9; }
.side-link:hover { background: var(--side-hover); color: #fff; }
.side-link.is-active { background: var(--primary); color: #fff; box-shadow: 0 1px 2px rgba(0, 0, 0, .25); }
.side-link.is-active svg { opacity: 1; }

.side-foot { padding: 12px; border-top: 1px solid rgba(255, 255, 255, .08); }
.side-user {
  display: flex; align-items: center; gap: 10px; padding: 8px; margin-bottom: 4px;
  border-radius: 12px; color: #fff; text-decoration: none;
}
.side-user:hover { background: var(--side-hover); color: #fff; }
.side-user-text { min-width: 0; line-height: 1.25; }
.side-user-text strong { display: block; font-size: 13.5px; color: #fff; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.side-user-text small { font-size: 11.5px; color: #8ea6bd; }
.side-logout:hover { background: #b91c1c; color: #fff; }

.app-main { min-height: 100vh; display: flex; flex-direction: column; }
.app-main > .container { flex: 1; width: 100%; }
.app-topbar {
  position: sticky; top: 0; z-index: 20; display: flex; align-items: center; gap: 12px;
  padding: 8px 14px; background: var(--surface); border-bottom: 1px solid var(--border);
}
.app-burger {
  display: inline-grid; place-items: center; width: 40px; height: 40px; margin: 0; cursor: pointer;
  border: 1px solid var(--border-strong); border-radius: 12px; background: #fff; color: var(--text);
}

@media (min-width: 1080px) {
  .sidebar { transform: none; }
  .sidebar-backdrop { display: none; }
  .app-main { margin-left: var(--side-w); }
  .app-topbar { display: none; }
  .has-sidebar .container { max-width: 1360px; padding: 26px 32px; }
}
@media print {
  .sidebar, .sidebar-backdrop, .app-topbar { display: none !important; }
  .app-main { margin-left: 0; }
}

/* ==========================================================================
   Map, profile cards and plan picker (2026-10)
   ========================================================================== */
.seg { display: inline-flex; border: 1px solid var(--border-strong); border-radius: 10px; overflow: hidden; background: var(--surface); }
.seg-item { display: inline-flex; align-items: center; gap: 6px; padding: 7px 14px; font-size: 13px; font-weight: 600; color: var(--muted); text-decoration: none; }
.seg-item + .seg-item { border-left: 1px solid var(--border-strong); }
a.seg-item:hover { background: var(--primary-soft); color: var(--primary); }
.seg-item.is-active { background: var(--primary); color: #fff; }

.map-filters { margin-top: 14px; }
.map-chips { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 12px; }
.map-chip { display: inline-flex; align-items: center; gap: 7px; padding: 6px 12px; border-radius: 999px; border: 1px solid var(--border-strong);
  background: var(--surface); color: var(--muted); font: inherit; font-size: 13px; font-weight: 600; cursor: pointer; opacity: .55; }
.map-chip.is-on { opacity: 1; color: var(--text); border-color: var(--primary-border); background: var(--primary-soft); }
.map-chip-n { color: var(--muted); font-weight: 500; }
.map-dot { display: inline-block; width: 11px; height: 11px; border-radius: 50%; margin-right: 6px; border: 2px solid #fff; box-shadow: 0 0 0 1px var(--border-strong); vertical-align: -1px; }
.map-chip .map-dot { margin-right: 0; }
.map-wrap { display: grid; grid-template-columns: minmax(0, 1fr) 300px; gap: 14px; margin-top: 14px; align-items: start; }
.plants-map { height: 580px; border-radius: var(--radius); border: 1px solid var(--border); background: #e8edf3; z-index: 0; }
.map-side { padding: 0; max-height: 580px; display: flex; flex-direction: column; overflow: hidden; }
.map-side-head { padding: 12px 14px; border-bottom: 1px solid var(--border); font-size: 13px; color: var(--muted); }
.map-list { list-style: none; margin: 0; padding: 4px 0; overflow-y: auto; }
.map-list li { display: flex; align-items: center; gap: 8px; padding: 9px 14px; cursor: pointer; border-bottom: 1px solid var(--border); }
.map-list li:hover { background: var(--primary-soft); }
.map-li-main { display: flex; flex-direction: column; min-width: 0; }
.map-li-main strong { font-size: 13px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.map-li-main small { color: var(--muted); font-size: 12px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.map-pop { font: 13px/1.45 var(--font-sans); min-width: 190px; }
.map-pop-title { font-size: 14px; font-weight: 700; color: var(--primary); text-decoration: none; }
.map-pop-muted { color: var(--muted); font-size: 12px; }
@media (max-width: 1080px) {
  .map-wrap { grid-template-columns: 1fr; }
  .map-side { max-height: 320px; }
  .plants-map { height: 440px; }
}

/* Location card on a plant */
.loc-card { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1.4fr); gap: 16px; align-items: start; }
.loc-map { height: 240px; border-radius: var(--radius-sm); border: 1px solid var(--border); background: #e8edf3; z-index: 0; }
.loc-links { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 12px; }
@media (max-width: 760px) { .loc-card { grid-template-columns: 1fr; } }

/* Profile card (technician / manager / user / customer) */
.pcard-head { display: flex; align-items: center; gap: 16px; flex-wrap: wrap; }
.pcard-avatar { width: 64px; height: 64px; border-radius: 50%; background: var(--primary-soft); color: var(--primary); display: flex; align-items: center; justify-content: center;
  font-size: 22px; font-weight: 700; flex: none; overflow: hidden; }
.pcard-avatar img { width: 100%; height: 100%; object-fit: cover; }
.pcard-head h1 { margin: 0; }
.pcard-meta { color: var(--muted); font-size: 14px; display: flex; flex-wrap: wrap; gap: 6px 16px; margin-top: 4px; }
.pcard-meta span { display: inline-flex; align-items: center; gap: 6px; }
.pcard-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); gap: 14px; margin-top: 14px; }
.cert-row { display: flex; flex-wrap: wrap; gap: 8px; }
.cert-pill { display: inline-flex; align-items: center; gap: 6px; padding: 5px 11px; border-radius: 999px; font-size: 12px; font-weight: 700; border: 1px solid var(--border-strong); color: var(--muted-soft); background: var(--surface-alt); }
.cert-pill.is-internal { color: var(--success); background: var(--success-soft); border-color: var(--success-border); }
.cert-pill.is-external { color: var(--info); background: var(--info-soft); border-color: var(--info-border); }
.pcard-num { font-size: 26px; font-weight: 700; line-height: 1.1; }
.pcard-num small { display: block; font-size: 12px; font-weight: 500; color: var(--muted); margin-top: 3px; }

/* Plan: inverter picker */
.inv-pick { width: 100%; border-collapse: collapse; }
.inv-pick th, .inv-pick td { padding: 8px 10px; border-bottom: 1px solid var(--border); text-align: left; font-size: 13px; vertical-align: middle; }
.inv-pick th { color: var(--muted); font-weight: 600; font-size: 12px; background: var(--surface-alt); position: sticky; top: 0; }
.inv-pick tr.is-done td { color: var(--muted-soft); }
.inv-pick-scroll { max-height: 360px; overflow: auto; border: 1px solid var(--border); border-radius: var(--radius-sm); }
.inv-tools { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; margin: 8px 0; }
.tech-opt { display: flex; align-items: center; gap: 8px; }
.tech-warn { color: var(--warning); font-size: 12px; font-weight: 600; }

/* Plan: technician picker with up to four certification badges */
.plan-techs { grid-template-columns: repeat(auto-fill, minmax(330px, 1fr)); }
.plan-tech > span:first-of-type { flex: 1; min-width: 0; }
.plan-tech .avail-certs { white-space: normal; text-align: right; max-width: 45%; }

/* Dashboard: commissioning outlook */
.outlook-card { margin: 14px 0; }
.outlook-grid { display: grid; grid-template-columns: minmax(230px, 1fr) 2fr; gap: 22px; align-items: end; margin-top: 12px; }
.outlook-nums { display: grid; grid-template-columns: 1fr 1fr; gap: 14px; }
.outlook-chart { display: flex; align-items: flex-end; gap: 10px; min-height: 120px; }
.outlook-col { flex: 1; display: flex; flex-direction: column; align-items: center; justify-content: flex-end; min-width: 0; }
.outlook-bars { display: flex; flex-direction: column; justify-content: flex-end; width: 70%; max-width: 38px; min-height: 2px; }
.outlook-bar { width: 100%; }
.outlook-bar.is-done { background: var(--success); border-radius: 0 0 4px 4px; }
.outlook-bar.is-planned { background: var(--primary); border-radius: 4px 4px 0 0; opacity: .85; }
.outlook-bar.is-planned:last-child { border-radius: 4px; }
.outlook-n { font-size: 11px; font-weight: 700; color: var(--muted); height: 14px; }
.outlook-m { font-size: 11px; color: var(--muted); margin-top: 4px; }
.outlook-col.is-now .outlook-m { color: var(--primary); font-weight: 700; }
.outlook-key { display: inline-block; width: 10px; height: 10px; border-radius: 3px; margin: 0 4px 0 12px; vertical-align: -1px; }
.outlook-key.is-done { background: var(--success); }
.outlook-key.is-planned { background: var(--primary); opacity: .85; }
@media (max-width: 760px) { .outlook-grid { grid-template-columns: 1fr; } }
@media (max-width: 640px) {
  .inv-pick th:nth-child(4), .inv-pick td:nth-child(4) { display: none; }
}

/* Global search */
.side-search { position: relative; display: flex; align-items: center; gap: 8px; margin: 0 12px 8px; padding: 0 10px; height: 36px; border-radius: 10px;
  background: rgba(255, 255, 255, 0.07); color: var(--side-muted); border: 1px solid transparent; }
.side-search:focus-within { background: rgba(255, 255, 255, 0.12); border-color: rgba(255, 255, 255, 0.25); color: #fff; }
.side-search input[type="search"] { flex: 1; min-width: 0; width: auto; height: 100%; padding: 0; border: 0; background: transparent; color: #fff; font: inherit; font-size: 13.5px; box-shadow: none; outline: none; }
.side-search input::placeholder { color: var(--side-muted); }
.side-search kbd { font: 600 11px var(--font-sans); color: var(--side-muted); border: 1px solid rgba(255, 255, 255, 0.18); border-radius: 5px; padding: 1px 6px; }
.search-page-form { display: flex; gap: 10px; align-items: center; margin-top: 10px; max-width: 640px; }
.search-page-form input[type="search"] { flex: 1; }
.search-list { list-style: none; margin: 0; padding: 0; }
.search-list li { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 10px; padding: 9px 0; border-bottom: 1px solid var(--border); }
.search-list li:last-child { border-bottom: 0; }
kbd { font: 600 11px var(--font-sans); background: var(--surface-alt); border: 1px solid var(--border-strong); border-radius: 5px; padding: 1px 6px; }

/* Technician absences in the availability grid */
.avail-cell.is-away { background: repeating-linear-gradient(135deg, #eef0f6, #eef0f6 6px, #e2e6f0 6px, #e2e6f0 12px); border-color: #cbd2e4; color: #55607a; font-size: 10.5px; font-weight: 700; letter-spacing: .02em; }
.avail-key.is-away { background: repeating-linear-gradient(135deg, #eef0f6, #eef0f6 3px, #e2e6f0 3px, #e2e6f0 6px); border-color: #cbd2e4; }

.absence-form { display: flex; flex-wrap: wrap; gap: 10px; align-items: flex-end; margin-top: 12px; }
.absence-form > div { min-width: 140px; }

/* Two-factor authentication */
.recovery-codes { display: grid; grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap: 8px; }
.recovery-codes code { background: var(--surface-alt); border: 1px solid var(--border-strong); border-radius: 8px; padding: 8px 10px; text-align: center; font-size: 14px; letter-spacing: .05em; }
.twofa-setup { display: flex; flex-wrap: wrap; gap: 20px; align-items: center; }
.twofa-qr { padding: 10px; background: #fff; border: 1px solid var(--border-strong); border-radius: 10px; width: 210px; height: 210px; display: flex; align-items: center; justify-content: center; }

/* Security posture */
.posture-list { list-style: none; margin: 12px 0 0; padding: 0; display: grid; grid-template-columns: repeat(auto-fill, minmax(340px, 1fr)); gap: 4px 28px; }
.posture-list li { display: flex; gap: 10px; align-items: flex-start; padding: 8px 0; border-bottom: 1px solid var(--border); }
.posture-ico { flex: none; margin-top: 1px; }
.posture-list li.is-ok .posture-ico { color: var(--success); }
.posture-list li.is-warn .posture-ico { color: var(--warning); }
.posture-list em { color: var(--warning); font-style: normal; font-weight: 600; }

/* Team schedule: toolbar, KPIs, load bars, technician cards, clickable free cells */
.team-bar-row { display: flex; gap: 14px; align-items: center; justify-content: space-between; flex-wrap: wrap; }
.team-nav { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; }
.team-filters { display: flex; gap: 12px; align-items: flex-end; flex-wrap: wrap; margin-top: 12px; }
.team-check { display: inline-flex; gap: 6px; align-items: center; font-size: 13px; padding-bottom: 8px; cursor: pointer; }
.team-kpis { display: grid; grid-template-columns: repeat(auto-fit, minmax(170px, 1fr)); gap: 12px; margin-top: 14px; }
.team-kpi { background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius); padding: 12px 14px; }
.team-kpi span { display: block; font-size: 12px; color: var(--muted); font-weight: 600; }
.team-kpi strong { display: block; font-size: 26px; line-height: 1.2; color: var(--text); }
.team-kpi small { color: var(--muted); font-size: 12px; }
.team-bars { display: flex; gap: 8px; align-items: flex-end; overflow-x: auto; padding-bottom: 2px; }
.team-bar-col { flex: 1 0 44px; max-width: 80px; display: flex; flex-direction: column; align-items: center; gap: 3px; }
.team-bar-track { width: 100%; height: 90px; background: var(--surface-2, #f3f4f6); border-radius: 6px; display: flex; align-items: flex-end; overflow: hidden; }
.team-bar-fill { width: 100%; background: var(--success); min-height: 0; }
.team-bar-fill.is-some, .team-meter-fill.is-some { background: var(--warning); }
.team-bar-fill.is-busy, .team-meter-fill.is-busy { background: var(--danger, #dc2626); }
.team-bar-pct { font-size: 12px; font-weight: 700; }
.team-bar-lbl { font-size: 11px; color: var(--muted); }
.team-cards { display: grid; grid-template-columns: repeat(auto-fill, minmax(230px, 1fr)); gap: 12px; }
.team-card { display: flex; flex-direction: column; gap: 6px; align-items: flex-start; }
.team-card-head { display: flex; flex-direction: column; font-weight: 700; }
.team-card-certs { display: flex; gap: 5px; flex-wrap: wrap; min-height: 22px; }
.team-cert { font-size: 11px; font-weight: 700; padding: 2px 7px; border-radius: 999px; background: var(--primary-soft); color: var(--primary); border: 1px solid var(--primary-border); }
.team-cert.is-mcs { background: #f1ecfb; color: #5b3aa6; border-color: #d9cdf2; }
.team-meter { width: 100%; height: 8px; border-radius: 999px; background: var(--surface-2, #e5e7eb); overflow: hidden; }
.team-meter-fill { height: 100%; background: var(--success); }
.team-card-line { font-size: 13px; }
.avail-cell.is-none { background: #f6f7f9; border-color: #e5e7eb; color: #9aa3b2; }
.avail-weeks .avail-day { min-width: 54px; }
.avail-weeks .avail-cell { height: 38px; font-size: 12.5px; }
.avail-go { display: block; height: 100%; min-height: 32px; line-height: 32px; color: inherit; text-decoration: none; border-radius: 5px; }
.avail-go:hover { background: var(--primary); color: #fff; }
.avail-cell.is-free .avail-go { color: transparent; }
.avail-cell.is-free .avail-go:hover { color: #fff; }
.avail-weeks .avail-cell.is-free .avail-go { color: inherit; }
.avail-weeks .avail-cell.is-free .avail-go:hover { color: #fff; }

/* Map: all/none and reset buttons next to the status chips */
.map-chips-tools { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; margin-top: 12px; }
.map-chips-tools .map-chips { margin-top: 0; flex: 1 1 auto; }
.map-chip.is-empty { opacity: .35; }
.map-chip.is-on.is-empty { opacity: .5; }

/* Plan form: free days per technician; change panel in the plan view */
.tech-free { display: block; font-size: 12px; font-weight: 600; color: var(--success); }
.tech-free.is-none { color: var(--danger, #dc2626); }
.pc-ops { display: flex; gap: 18px; }
.pc-panel { border-left: 3px solid var(--primary); }

/* Week numbers (WK48) in the calendars */
.avail-grid .avail-wk { font-size: 11px; font-weight: 700; letter-spacing: .03em; color: var(--primary); background: var(--primary-soft); border-radius: 5px; padding: 2px 0; text-align: center; }
.avail-grid .is-wk-start { border-left: 2px solid var(--primary-border, #bcd6ee); }
.team-bar-lbl strong { color: var(--primary); }
.avail-weeks .avail-day strong { font-size: 13px; color: var(--primary); }

.team-go { font-size: 13px; color: var(--muted); margin: 0 0 0 6px; }
.team-nav input[type=date] { width: auto; }
.avail-grid .avail-month { background: var(--surface-2, #f3f4f6); color: var(--text); }

/* Import data */
.import-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: 14px; margin-top: 14px; }
.import-card input[type=file] { width: 100%; }
.import-table td { vertical-align: top; }
.imp-chg { display: inline-block; margin: 0 8px 4px 0; padding: 1px 8px; border-radius: 6px; background: var(--primary-soft); font-size: 12.5px; }
.imp-chg b { color: var(--primary); margin-right: 4px; }
.imp-chg s { color: var(--muted); }
.imp-err { color: var(--danger, #dc2626); font-size: 13px; }
.imp-warn { color: var(--warning); font-size: 13px; }

/* Team schedule: header, filters and KPI cards */
.team-hero { margin-top: 14px; background: linear-gradient(135deg, var(--primary-soft, #eaf3fb) 0%, var(--surface, #fff) 70%); border: 1px solid var(--primary-border, #bcd6ee); border-radius: var(--radius); padding: 16px 18px 14px; }
.team-hero-main { display: flex; flex-wrap: wrap; gap: 14px 22px; align-items: center; justify-content: space-between; }
.team-period { display: flex; align-items: center; gap: 12px; }
.team-period-text strong { display: block; font-size: 22px; line-height: 1.1; letter-spacing: .01em; color: var(--text); }
.team-period-text strong span { color: var(--primary); font-weight: 400; margin: 0 2px; }
.team-period-text small { color: var(--muted); font-size: 13px; }
.team-hero-tools { display: flex; gap: 8px; align-items: center; }
.team-pill { display: inline-flex; align-items: center; gap: 6px; height: 34px; padding: 0 14px; border-radius: 999px; border: 1px solid var(--border-strong); background: var(--surface, #fff); color: var(--text); font-size: 13.5px; font-weight: 600; text-decoration: none; cursor: pointer; }
.team-pill:hover { border-color: var(--primary); color: var(--primary); }
.team-pill--field { padding: 0 10px 0 12px; color: var(--muted); }
.team-pill--field input { border: 0; background: transparent; padding: 0; height: 30px; width: 132px; font: inherit; color: var(--text); outline: none; }
.team-views { display: inline-flex; background: var(--surface, #fff); border: 1px solid var(--border-strong); border-radius: 999px; padding: 3px; gap: 2px; margin-left: auto; }
.team-view { padding: 7px 16px; border-radius: 999px; font-size: 13.5px; font-weight: 600; color: var(--muted); text-decoration: none; white-space: nowrap; }
.team-view:hover { color: var(--primary); }
.team-view.is-active { background: var(--primary); color: #fff; box-shadow: 0 1px 4px rgba(0, 117, 201, .35); }
.team-filters { display: flex; flex-wrap: wrap; gap: 10px; align-items: center; margin-top: 14px; padding-top: 12px; border-top: 1px dashed var(--primary-border, #bcd6ee); }
.team-filters-label { display: inline-flex; gap: 6px; align-items: center; font-size: 12px; font-weight: 700; letter-spacing: .06em; text-transform: uppercase; color: var(--muted); margin-right: 4px; }
.team-sel { display: inline-flex; align-items: center; gap: 8px; height: 34px; padding: 0 6px 0 12px; margin: 0; border: 1px solid var(--border-strong); border-radius: 999px; background: var(--surface, #fff); }
.team-sel span { font-size: 12.5px; color: var(--muted); font-weight: 600; white-space: nowrap; }
.team-sel select { border: 0; background: transparent; height: 30px; padding: 0 4px; font-weight: 600; color: var(--text); width: auto; outline: none; cursor: pointer; }
.team-switch { display: inline-flex; align-items: center; gap: 8px; margin: 0; font-size: 13.5px; font-weight: 600; cursor: pointer; }
.team-switch input { position: absolute; opacity: 0; width: 0; height: 0; }
.team-switch i { width: 38px; height: 22px; border-radius: 999px; background: var(--border-strong, #cbd2dc); position: relative; transition: background .15s; flex: none; }
.team-switch i::after { content: ''; position: absolute; top: 3px; left: 3px; width: 16px; height: 16px; border-radius: 50%; background: #fff; transition: transform .15s; box-shadow: 0 1px 2px rgba(0,0,0,.25); }
.team-switch input:checked + i { background: var(--primary); }
.team-switch input:checked + i::after { transform: translateX(16px); }
.team-switch input:focus-visible + i { box-shadow: 0 0 0 3px rgba(0, 117, 201, .25); }
.team-clear { font-size: 13px; font-weight: 600; color: var(--primary); text-decoration: none; margin-left: 4px; }
.team-clear:hover { text-decoration: underline; }
.team-kpi { border-left: 4px solid var(--border-strong); }
.team-kpi.is-blue   { border-left-color: var(--primary); }
.team-kpi.is-amber  { border-left-color: var(--warning); }
.team-kpi.is-green  { border-left-color: var(--success); }
.team-kpi.is-purple { border-left-color: #7c5cc4; }
.team-kpi.is-grey   { border-left-color: #94a3b8; }
@media (max-width: 760px) { .team-views { margin-left: 0; } .team-period-text strong { font-size: 19px; } }

.team-sel select { width: auto !important; min-width: 0; flex: none; }
.avail-cell.is-low { background: var(--primary-soft, #eaf3fb); border-color: var(--primary-border, #bcd6ee); color: var(--primary); }
.avail-key.is-low { background: var(--primary-soft, #eaf3fb); border-color: var(--primary-border, #bcd6ee); }
.team-bar-fill.is-low, .team-meter-fill.is-low { background: var(--primary); }

/* Stopped commissioning */
.stop-reasons { display: grid; gap: 8px; }
.stop-reason { display: flex; gap: 12px; align-items: flex-start; padding: 12px 14px; border: 1px solid var(--border); border-radius: 10px; cursor: pointer; margin: 0; }
.stop-reason:hover { border-color: var(--danger-border, #f5b5b5); background: var(--danger-soft, #fdf0f0); }
.stop-reason input { width: 18px; height: 18px; margin: 3px 0 0; flex: none; accent-color: #b91c1c; }
.stop-reason small { display: block; color: var(--muted); font-weight: 400; margin-top: 2px; }
.stop-reason:has(input:checked) { border-color: #b91c1c; background: var(--danger-soft, #fdf0f0); }
.stop-banner { display: flex; gap: 12px; align-items: flex-start; }
.stop-why { margin: 8px 0 4px; display: flex; gap: 10px; align-items: center; flex-wrap: wrap; }
.stop-comment { background: rgba(255,255,255,.6); border-radius: 8px; padding: 8px 10px; margin-top: 6px; color: var(--text); }
.stop-photos { display: flex; gap: 8px; flex-wrap: wrap; margin-top: 8px; }
.stop-photos img { height: 84px; width: auto; border-radius: 8px; border: 1px solid var(--border); display: block; }
.stop-actions { display: flex; gap: 10px; flex-wrap: wrap; margin-top: 12px; align-items: center; }
.stop-actions form { margin: 0; display: flex; gap: 8px; align-items: center; }
.stop-cancel input { width: 220px; }
.stop-link { margin: 0 0 6px; text-align: right; font-size: 13px; }
.stop-link a { color: #b91c1c; text-decoration: none; font-weight: 600; }
.stop-link a:hover { text-decoration: underline; }
.live-toast { position: fixed; right: 18px; bottom: 18px; z-index: 60; background: var(--primary); color: #fff; padding: 10px 16px; border-radius: 999px; box-shadow: 0 6px 20px rgba(0,0,0,.25); font-size: 13.5px; font-weight: 600; display: none; }
.live-toast.is-on { display: block; }
.live-dot { position: fixed; right: 18px; top: 14px; z-index: 60; font-size: 12px; color: var(--muted); display: none; align-items: center; gap: 6px; }
.live-dot i { width: 8px; height: 8px; border-radius: 50%; background: var(--success); display: inline-block; animation: livepulse 2s infinite; }
@keyframes livepulse { 0% { box-shadow: 0 0 0 0 rgba(22,163,74,.5); } 70% { box-shadow: 0 0 0 7px rgba(22,163,74,0); } 100% { box-shadow: 0 0 0 0 rgba(22,163,74,0); } }

/* Planning hub and the "When can we?" assistant */
.plan-hub { display: grid; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); gap: 14px; margin-top: 14px; }
.plan-svc { border-top: 4px solid var(--primary); }
.plan-svc.is-maintenance { border-top-color: #7c5cc4; }
.plan-svc.is-repair { border-top-color: #dc2626; }
.plan-svc-head { display: flex; align-items: center; gap: 10px; }
.plan-svc-head h3 { margin: 0; font-size: 18px; }
.plan-svc-ico { width: 38px; height: 38px; border-radius: 10px; background: var(--primary-soft); color: var(--primary); display: inline-flex; align-items: center; justify-content: center; }
.is-maintenance .plan-svc-ico { background: #f1ecfb; color: #5b3aa6; }
.is-repair .plan-svc-ico { background: var(--danger-soft, #fdecec); color: #b91c1c; }
.plan-svc-stats { display: flex; gap: 14px; flex-wrap: wrap; font-size: 12.5px; color: var(--muted); margin-bottom: 14px; }
.plan-svc-stats b { display: block; font-size: 20px; color: var(--text); line-height: 1.1; }
.plan-svc-stats .is-red b { color: #b91c1c; }
.plan-svc-actions { display: flex; gap: 8px; flex-wrap: wrap; }
.asst-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(170px, 1fr)); gap: 12px; }
.asst-options { display: grid; grid-template-columns: repeat(auto-fit, minmax(290px, 1fr)); gap: 14px; margin-top: 10px; }
.asst-opt { border-top: 4px solid var(--border-strong); }
.asst-opt.is-best { border-top-color: var(--success); }
.asst-opt.is-selected { box-shadow: 0 0 0 2px var(--primary); }
.asst-opt-head { display: flex; gap: 8px; align-items: center; font-size: 16px; }
.chip-ok, .chip-sel { font-size: 11px; font-weight: 700; padding: 2px 9px; border-radius: 999px; }
.chip-ok { background: var(--success-soft); color: var(--success); border: 1px solid var(--success-border); }
.chip-sel { background: var(--primary-soft); color: var(--primary); border: 1px solid var(--primary-border); }
.asst-dates { display: flex; gap: 12px; align-items: center; margin: 14px 0 10px; }
.asst-dates small { display: block; font-size: 10.5px; letter-spacing: .06em; color: var(--muted); }
.asst-dates b { display: block; font-size: 22px; line-height: 1.1; }
.asst-dates span { font-size: 12.5px; color: var(--muted); }
.asst-arrow { color: var(--primary); font-size: 20px; }
.asst-days { margin-left: auto; text-align: right; }
.asst-team { list-style: none; margin: 0; padding: 0; }
.asst-team li { display: flex; gap: 8px; align-items: baseline; padding: 5px 0; border-top: 1px solid var(--border); }
.asst-team li em { margin-left: auto; font-style: normal; font-weight: 700; color: var(--primary); font-size: 12.5px; }
.asst-note { margin: 8px 0 0; font-size: 12.5px; color: var(--muted); }
.asst-note.is-ok { color: var(--success); }
.asst-note.is-warn { color: #b45309; }

/* ════════════════════════════════════════════════════════════════════════════
   Unified filters (v2): one look for every list, planner and calendar.
   Controls share a height and radius; labels are small caps; chips and switches
   replace loose checkboxes. Applies to .filters-card / .filters-row everywhere.
   ════════════════════════════════════════════════════════════════════════════ */
:root { --ctl-h: 40px; --ctl-r: 10px; }
.filters-card, .map-filters, .fbar {
  background: linear-gradient(135deg, var(--primary-soft, #eaf3fb) 0%, var(--surface, #fff) 72%);
  border: 1px solid var(--primary-border, #bcd6ee); border-radius: 14px; padding: 14px 18px;
}
.filters-row, .fbar-row { display: flex; flex-wrap: wrap; gap: 12px 14px; align-items: flex-end; }
.filters-field, .fbar-field { display: flex; flex-direction: column; min-width: 0; }
.filters-field > label, .fbar-field > label, .fbar-label {
  font-size: 10.5px; font-weight: 700; letter-spacing: .07em; text-transform: uppercase; color: var(--muted); margin: 0 0 5px 2px; line-height: 1.1;
}
.filters-row .filters-field input:not([type=checkbox]):not([type=radio]),
.filters-row .filters-field select,
.fbar .fbar-field input:not([type=checkbox]):not([type=radio]),
.fbar .fbar-field select {
  height: var(--ctl-h); box-sizing: border-box; padding: 0 12px; margin: 0; border-radius: var(--ctl-r);
  border: 1px solid var(--border-strong); background-color: var(--surface, #fff); color: var(--text); font-size: 14px; line-height: normal; width: 100%;
}
.filters-row .filters-field select, .fbar .fbar-field select {
  appearance: none; -webkit-appearance: none; padding-right: 32px; cursor: pointer;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8'%3E%3Cpath d='M1 1.5l5 5 5-5' fill='none' stroke='%235b6b7d' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  background-repeat: no-repeat; background-position: right 12px center;
}
.filters-row .filters-field input:focus, .filters-row .filters-field select:focus,
.fbar .fbar-field input:focus, .fbar .fbar-field select:focus { outline: none; border-color: var(--primary); box-shadow: 0 0 0 3px rgba(0, 117, 201, .16); }
.filters-actions { display: flex; gap: 8px; align-items: flex-end; }
.filters-actions .btn-icon { width: var(--ctl-h); height: var(--ctl-h); border-radius: var(--ctl-r); }
.filters-actions .btn { height: var(--ctl-h); line-height: var(--ctl-h); padding: 0 16px; border-radius: var(--ctl-r); }
.fbar-field--grow { flex: 1 1 220px; }
.fbar-hint { font-size: 12px; color: var(--muted); margin: 6px 0 0 2px; }

/* chips: toggle filters (company, status...) */
.fchips { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; }
.fchip {
  display: inline-flex; align-items: center; gap: 7px; height: 34px; padding: 0 14px; border-radius: 999px; border: 1px solid var(--border-strong);
  background: var(--surface, #fff); color: var(--text); font: inherit; font-size: 13px; font-weight: 600; cursor: pointer; text-decoration: none; white-space: nowrap;
}
.fchip:hover { border-color: var(--primary); color: var(--primary); }
.fchip.is-on, .fchip[aria-pressed="true"] { background: var(--primary); border-color: var(--primary); color: #fff; box-shadow: 0 1px 4px rgba(0, 117, 201, .3); }
.fchip small { font-weight: 600; opacity: .75; }
.fchip-tool { background: transparent; border-style: dashed; color: var(--muted); font-weight: 600; }
.fbar-sep { width: 1px; height: 24px; background: var(--primary-border, #bcd6ee); margin: 0 4px; }

/* switch (any page): <label class="fswitch"><input type=checkbox><i></i> text</label> */
.fswitch { display: inline-flex; align-items: center; gap: 8px; margin: 0; height: var(--ctl-h); font-size: 13.5px; font-weight: 600; cursor: pointer; }
.fswitch input { position: absolute; opacity: 0; width: 0; height: 0; }
.fswitch i { width: 38px; height: 22px; border-radius: 999px; background: var(--border-strong, #cbd2dc); position: relative; transition: background .15s; flex: none; }
.fswitch i::after { content: ''; position: absolute; top: 3px; left: 3px; width: 16px; height: 16px; border-radius: 50%; background: #fff; transition: transform .15s; box-shadow: 0 1px 2px rgba(0,0,0,.25); }
.fswitch input:checked + i { background: var(--primary); }
.fswitch input:checked + i::after { transform: translateX(16px); }
.fswitch input:focus-visible + i { box-shadow: 0 0 0 3px rgba(0, 117, 201, .25); }

/* Team schedule filters follow the same height and radius */
.team-sel { height: var(--ctl-h); }
.team-pill { height: var(--ctl-h); }
@media (max-width: 640px) { .filters-row, .fbar-row { flex-direction: column; align-items: stretch; } .fbar-field--grow { flex-basis: auto; } }

.asst-why { margin: 0 0 6px; font-size: 12.5px; color: var(--primary); font-weight: 600; display: flex; gap: 6px; align-items: center; }
.tech-picker .plan-techs { grid-template-columns: repeat(auto-fill, minmax(260px, 1fr)); }
.tech-picker .plan-tech { border-radius: 12px; transition: border-color .12s, box-shadow .12s; }
.tech-picker .plan-tech:has(input:checked) { border-color: var(--primary); box-shadow: 0 0 0 2px var(--primary-soft, #eaf3fb); background: var(--primary-soft, #eaf3fb); }

/* Team schedule: company chips, order-by and multi-select */
.team-who-head { display: flex; flex-wrap: wrap; gap: 10px 20px; align-items: center; justify-content: space-between; margin: 22px 0 0; }
.team-sortline { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.team-card { position: relative; }
.team-pick { position: absolute; top: 12px; right: 12px; margin: 0; cursor: pointer; }
.team-pick input { position: absolute; opacity: 0; width: 0; height: 0; }
.team-pick i { display: block; width: 22px; height: 22px; border-radius: 7px; border: 2px solid var(--border-strong, #cbd2dc); background: #fff; position: relative; transition: all .12s; }
.team-pick input:checked + i { background: var(--primary); border-color: var(--primary); }
.team-pick input:checked + i::after { content: ''; position: absolute; left: 6px; top: 2px; width: 6px; height: 11px; border: solid #fff; border-width: 0 2.5px 2.5px 0; transform: rotate(45deg); }
.team-pick input:focus-visible + i { box-shadow: 0 0 0 3px rgba(0, 117, 201, .25); }
.team-card:has(.tc-pick:checked) { border-color: var(--primary); box-shadow: 0 0 0 2px var(--primary-soft, #eaf3fb); }
.team-selbar { position: sticky; bottom: 14px; z-index: 30; display: flex; gap: 14px; align-items: center; justify-content: center; margin: 14px auto 0; width: fit-content; max-width: 100%;
  background: #0b2540; color: #fff; padding: 10px 18px; border-radius: 999px; box-shadow: 0 10px 30px rgba(0,0,0,.3); }
.team-selbar[hidden] { display: none; }
.team-selbar .btn { background: transparent; color: #fff; border-color: rgba(255,255,255,.4); }
.filters-field .fchips .fchip { height: var(--ctl-h); }

/* Travel days in the availability grid */
.avail-cell.is-travel { background: repeating-linear-gradient(135deg, #fff7e6, #fff7e6 6px, #ffecc2 6px, #ffecc2 12px); border-color: #f1d28a; color: #8a5a00; font-size: 14px; font-weight: 700; }
.avail-key.is-travel { background: repeating-linear-gradient(135deg, #fff7e6, #fff7e6 3px, #ffecc2 3px, #ffecc2 6px); border-color: #f1d28a; }
.asst-trip { margin: 0 0 6px; font-size: 12.5px; color: #8a5a00; display: flex; gap: 6px; align-items: baseline; flex-wrap: wrap; }

/* Kind of work in the calendar: commissioning · maintenance · repair · stopped (one click to filter) */
.kd { display: inline-block; width: 8px; height: 8px; border-radius: 50%; flex: none; background: var(--primary); }
.kd.is-maintenance { background: var(--purple); }
.kd.is-repair { background: #ea8a1a; }
.kd.is-stopped { background: var(--danger); box-shadow: 0 0 0 2px var(--danger-soft); }
.kd.is-trip { background: repeating-linear-gradient(135deg, #f1d28a, #f1d28a 2px, #fff7e6 2px, #fff7e6 4px); border: 1px solid #e0b95a; }
.kd-row { display: flex; gap: 3px; justify-content: center; margin-top: 2px; }
.kd-legend { display: inline-flex; gap: 6px; align-items: center; flex-wrap: wrap; margin-right: 12px; }
.kd-legend .kd { margin-left: 8px; }
.avail-kindbar { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; margin: 0 0 10px; }
.avail-kindbar .fchip { cursor: pointer; display: inline-flex; align-items: center; gap: 6px; font-family: inherit; }
.avail-kindbar .fchip.is-on { background: var(--primary); border-color: var(--primary); color: #fff; }
.avail-kindbar .kd-chip.is-on .kd { box-shadow: 0 0 0 2px rgba(255,255,255,.7); }
.avail-cell { line-height: 1.1; }
[data-kindgrid].is-filtering .avail-cell { opacity: .28; transition: opacity .15s; }
[data-kindgrid].is-filtering .avail-cell.is-match { opacity: 1; box-shadow: 0 0 0 2px var(--primary); position: relative; }

/* Work outlook: one click on a kind of work isolates it; months link to their reports */
a.outlook-col { color: inherit; text-decoration: none; border-radius: 8px; padding: 2px 0; transition: background .12s; }
a.outlook-col:hover { background: var(--primary-soft); }
button.outlook-type { font: inherit; text-align: left; background: transparent; border: 1px solid transparent; border-radius: 999px; padding: 4px 12px 4px 4px; cursor: pointer; color: inherit; }
button.outlook-type:hover { background: var(--primary-soft); }
button.outlook-type.is-on { background: var(--primary-soft); border-color: var(--primary-border); }
.outlook-card.is-filtering .outlook-bar { opacity: .12; transition: opacity .15s; }
.outlook-card.is-filtering .outlook-bar.is-match { opacity: 1; }

/* Stop button: clearly a button, red but calm until hovered */
.stop-link { display: flex; justify-content: flex-end; align-items: center; gap: 10px; margin: 0 0 10px; }
.stop-hint { font-size: 12.5px; color: var(--muted); }
.stop-link a.stop-btn { display: inline-flex; align-items: center; gap: 7px; min-height: 34px; box-sizing: border-box; padding: 7px 14px; border-radius: 10px;
  background: var(--danger-soft); border: 1px solid var(--danger-border); color: var(--danger); font-size: 13.5px; font-weight: 700; letter-spacing: .2px; text-decoration: none;
  transition: background .15s, color .15s, box-shadow .15s, transform .05s; }
.stop-link a.stop-btn:hover { background: var(--danger); border-color: var(--danger); color: #fff; text-decoration: none; box-shadow: 0 4px 12px rgba(185,28,28,.28); }
.stop-link a.stop-btn:active { transform: translateY(1px); }
.stop-link a.stop-btn:focus-visible { outline: 3px solid var(--danger-border); outline-offset: 2px; }

/* Today: ordered priorities, each with its reason and its button */
.dash-today { margin: 14px 0; }
.today-line { margin: 6px 0 12px; color: var(--muted); font-size: 14px; }
.today-line b { color: var(--text); }
.today-list { list-style: none; margin: 0; padding: 0; display: grid; gap: 8px; }
.today-item { display: grid; grid-template-columns: 26px 46px 1fr auto; gap: 12px; align-items: center; padding: 10px 14px; border: 1px solid var(--border); border-left-width: 4px; border-radius: 12px; background: var(--surface); }
.today-item.is-danger { border-left-color: var(--danger); background: linear-gradient(90deg, var(--danger-soft), var(--surface) 40%); }
.today-item.is-warning { border-left-color: #e0a800; background: linear-gradient(90deg, var(--warning-soft), var(--surface) 40%); }
.today-item.is-info { border-left-color: var(--primary); }
.today-item.is-purple { border-left-color: var(--purple); }
.today-rank { width: 22px; height: 22px; border-radius: 50%; background: var(--primary-soft); color: var(--primary); font-size: 12px; font-weight: 700; display: grid; place-items: center; }
.today-n { font-size: 24px; font-weight: 700; line-height: 1; text-align: center; }
.today-text { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.today-text strong { display: flex; align-items: center; gap: 6px; }
.today-text small { color: var(--muted); font-size: 12.5px; }
.today-empty { margin: 0; display: flex; align-items: center; gap: 8px; color: var(--success); }
@media (max-width: 640px) { .today-item { grid-template-columns: 22px 38px 1fr; } .today-item .action-pill { grid-column: 3; justify-self: start; } }

/* My week: the technician's calendar */
.myweek { margin: 14px 0; }
.myweek-grid { display: grid; grid-template-columns: repeat(7, minmax(0, 1fr)); gap: 6px; }
.myweek-dn { font-size: 11px; font-weight: 700; color: var(--muted); text-transform: uppercase; letter-spacing: .04em; padding: 0 4px; }
.myweek-day { display: flex; flex-direction: column; gap: 4px; min-height: 76px; padding: 6px; border: 1px solid var(--border); border-radius: 10px; background: var(--surface); color: inherit; text-decoration: none; transition: border-color .12s, box-shadow .12s; }
.myweek-day:hover { border-color: var(--primary); box-shadow: 0 2px 8px rgba(0,117,201,.15); }
.myweek-day.is-weekend { background: #f5f6f8; }
.myweek-day.is-past { opacity: .55; }
.myweek-day.is-today { border-color: var(--primary); box-shadow: 0 0 0 2px var(--primary-soft); }
.myweek-day.has-work { background: #fff; }
.myweek-day.is-travel { background: repeating-linear-gradient(135deg, #fff7e6, #fff7e6 6px, #ffecc2 6px, #ffecc2 12px); border-color: #f1d28a; }
.myweek-day.is-away { background: repeating-linear-gradient(135deg, #eef0f6, #eef0f6 6px, #e2e6f0 6px, #e2e6f0 12px); border-color: #cbd2e4; }
.myweek-date { font-size: 11.5px; color: var(--muted); display: flex; gap: 4px; align-items: baseline; }
.myweek-date b { font-size: 14px; color: var(--text); }
.myweek-date em { font-style: normal; font-size: 10px; font-weight: 700; color: #fff; background: var(--primary); border-radius: 999px; padding: 1px 6px; margin-left: auto; }
.myweek-job { display: flex; align-items: center; gap: 5px; font-size: 11.5px; line-height: 1.2; padding: 3px 6px; border-radius: 6px; background: var(--primary-soft); min-width: 0; }
.myweek-job span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; flex: 1; min-width: 0; }
.myweek-job small { font-weight: 700; }
.myweek-job.is-maintenance { background: var(--purple-soft); }
.myweek-job.is-repair { background: #fdebd3; }
.myweek-job.is-stopped { background: var(--danger-soft); }
.myweek-note { font-size: 11px; font-weight: 600; color: #8a5a00; }
.myweek-note.is-away { color: #55607a; }
.myweek-grid.is-3m .myweek-job span, .myweek-grid.is-1m .myweek-job span { display: none; }
.myweek-grid.is-3m .myweek-day { min-height: 54px; }
@media (max-width: 760px) { .myweek-job span { display: none; } .myweek-day { min-height: 56px; padding: 4px; } }

/* Steps of a flow */
.stepper { list-style: none; display: flex; gap: 6px; margin: 14px 0 4px; padding: 0; flex-wrap: wrap; }
.stepper-step { display: flex; align-items: center; gap: 8px; padding: 6px 14px 6px 6px; border-radius: 999px; border: 1px solid var(--border); background: var(--surface); color: var(--muted); font-size: 13px; font-weight: 600; }
.stepper-dot { width: 22px; height: 22px; border-radius: 50%; display: grid; place-items: center; font-size: 12px; background: #eef1f5; color: var(--muted); }
.stepper-step.is-done { color: var(--success); border-color: var(--success-border); }
.stepper-step.is-done .stepper-dot { background: var(--success); color: #fff; }
.stepper-step.is-current { color: var(--primary); border-color: var(--primary); background: var(--primary-soft); }
.stepper-step.is-current .stepper-dot { background: var(--primary); color: #fff; }

/* Help strip */
.help-strip { display: flex; gap: 10px; align-items: flex-start; margin: 10px 0 14px; padding: 10px 12px; border-radius: 12px; background: var(--primary-soft); border: 1px solid var(--primary-border); font-size: 13.5px; line-height: 1.45; }
.help-strip[hidden] { display: none; }
.help-ico { color: var(--primary); flex: none; margin-top: 1px; }
.help-body { flex: 1; min-width: 0; }
.help-close { flex: none; border: 0; background: transparent; font-size: 20px; line-height: 1; color: var(--muted); cursor: pointer; padding: 0 4px; border-radius: 6px; }
.help-close:hover { background: rgba(0,0,0,.06); color: var(--text); }

/* Timeline of a job: trip out, working days, trip back */
.tl { display: flex; gap: 3px; flex-wrap: wrap; margin: 8px 0; }
.tl-day { position: relative; width: 26px; height: 30px; border-radius: 6px; display: grid; place-items: center; font-size: 13px; font-weight: 700; border: 1px solid transparent; }
.tl-day small { position: absolute; top: 1px; left: 0; right: 0; text-align: center; font-size: 8.5px; font-weight: 600; opacity: .65; line-height: 1; }
.tl-day.is-work { background: var(--primary); color: #fff; }
.tl-day.is-out, .tl-day.is-back { background: repeating-linear-gradient(135deg, #fff7e6, #fff7e6 4px, #ffecc2 4px, #ffecc2 8px); border-color: #f1d28a; color: #8a5a00; }
.tl-day.is-rest { background: #f3f4f6; color: #9aa3b2; border-color: #e5e7eb; }

/* A readable day: "Mon 26 Oct · WK44 · in 3 days" */
.day-chip { display: inline-flex; flex-direction: column; gap: 1px; line-height: 1.2; white-space: nowrap; }
.day-chip b { font-size: 13.5px; font-weight: 700; color: var(--text); }
.day-chip small { font-size: 11px; color: var(--muted); }
.day-chip.is-today b { color: var(--primary); }
.day-chip.is-past b { color: var(--muted); font-weight: 600; }
.myweek-day.is-mark { border-color: var(--primary); box-shadow: 0 0 0 3px var(--primary-soft); background: #fff; }

/* One look for icons: a small tinted rounded tile, as in the KPI cards */
.today-ico { display: inline-flex; align-items: center; justify-content: center; width: 24px; height: 24px; border-radius: 6px; flex: none; background: var(--primary-soft); color: var(--primary); }
.today-item.is-danger .today-ico { background: var(--danger-soft); color: var(--danger); }
.today-item.is-warning .today-ico { background: var(--warning-soft); color: var(--warning); }
.today-item.is-info .today-ico { background: var(--info-soft); color: var(--info); }
.today-item.is-purple .today-ico { background: var(--purple-soft); color: var(--purple); }
.today-item { border-left-width: 1px; border-color: var(--border); background: var(--surface) !important; }
.today-item.is-danger { border-color: var(--danger-border); background: var(--danger-soft) !important; }
.today-item.is-warning { border-color: var(--warning-border); background: #fffaf0 !important; }
.today-item.is-info { border-color: var(--info-border); background: #f5f9ff !important; }
.today-item.is-purple { border-color: #e1cdf8; background: #fbf7ff !important; }
.today-rank { background: #fff; border: 1px solid var(--border); }

/* Donut charts ("quesitos") */
.donut-row-wrap { margin: 14px 0; }
.donut-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: 14px; }
.donut-card { border: 1px solid var(--border); border-radius: 14px; padding: 12px 14px; background: var(--surface); }
.donut-title { margin: 0 0 10px; font-size: 14px; display: flex; align-items: baseline; gap: 8px; }
.donut-title small { color: var(--muted); font-weight: 500; }
.donut-body { display: flex; gap: 16px; align-items: center; flex-wrap: wrap; }
.donut { width: 128px; height: 128px; border-radius: 50%; position: relative; flex: none; }
.donut-hole { position: absolute; inset: 22px; border-radius: 50%; background: var(--surface); display: flex; flex-direction: column; align-items: center; justify-content: center; text-align: center; line-height: 1.1; }
.donut-hole b { font-size: 22px; }
.donut-hole small { font-size: 10.5px; color: var(--muted); max-width: 70px; }
.donut-legend { list-style: none; margin: 0; padding: 0; flex: 1; min-width: 150px; display: grid; gap: 2px; }
.donut-row { display: flex; align-items: center; gap: 8px; padding: 4px 8px; border-radius: 8px; color: inherit; text-decoration: none; font-size: 13px; border: 1px solid transparent; }
.donut-row:hover { background: var(--primary-soft); }
.donut-row.is-on { background: var(--primary-soft); border-color: var(--primary-border); font-weight: 600; }
.donut-name { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.donut-row em { font-style: normal; color: var(--muted); font-size: 12px; min-width: 34px; text-align: right; }

/* My week: week numbers, pending absences and the "I am away" form */
.myweek-grid { grid-template-columns: 58px repeat(7, minmax(0, 1fr)); }
.myweek-wk { display: flex; flex-direction: column; justify-content: center; align-items: flex-start; padding: 0 4px; line-height: 1.2; }
.myweek-wk b { font-size: 12.5px; color: var(--primary); }
.myweek-wk small { font-size: 10.5px; color: var(--muted); }
.myweek-day.is-pending { background: repeating-linear-gradient(135deg, #fff, #fff 6px, #f1f3f8 6px, #f1f3f8 12px); border: 1px dashed #aab4cc; }
.myweek-note.is-pend { color: #55607a; font-style: italic; }
.myweek-away { margin-top: 12px; border: 1px solid var(--border); border-radius: 12px; padding: 8px 12px; background: var(--surface); }
.myweek-away summary { cursor: pointer; font-weight: 600; color: var(--primary); display: flex; align-items: center; gap: 6px; }
.myweek-away .absence-form { margin-top: 10px; }
.myweek-abs { list-style: none; margin: 10px 0 0; padding: 0; display: grid; gap: 4px; font-size: 13px; }
.myweek-abs li { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; }
@media (max-width: 760px) { .myweek-grid { grid-template-columns: 40px repeat(7, minmax(0, 1fr)); } .myweek-wk small { display: none; } }

/* Reports table: kind of work and a three-step stage bar */
.type-pill { display: inline-flex; align-items: center; gap: 6px; padding: 3px 10px 3px 8px; border-radius: 999px; font-size: 12.5px; font-weight: 600; background: var(--primary-soft); color: var(--primary); white-space: nowrap; }
.type-pill small { font-size: 10.5px; font-weight: 600; opacity: .75; padding-left: 6px; border-left: 1px solid currentColor; line-height: 1.1; }
.type-pill.is-maintenance { background: var(--purple-soft); color: var(--purple); }
.type-pill.is-repair { background: #fdebd3; color: #b45309; }
.stage { min-width: 120px; }
.stage-bar { display: grid; grid-template-columns: repeat(3, 1fr); gap: 3px; }
.stage-bar i { display: block; height: 7px; border-radius: 99px; background: #e5e9f0; }
.stage-bar i.on { background: #93b4d6; }
.stage-bar i.wait { background: #fff; border: 1px dashed #93b4d6; box-sizing: border-box; }
.stage-bar i.bad { background: var(--danger); }
.stage-bar i.is-open { background: #f59e0b; }
.stage-bar i.is-stop { background: var(--danger); }
.stage-bar i.is-done { background: var(--success); }
.stage-bar i.is-works { background: var(--purple); }
.stage-lbl { display: block; margin-top: 4px; font-size: 11.5px; color: var(--muted); }
.stage-lbl.is-open { color: #b45309; font-weight: 600; }
.stage-lbl.is-bad { color: var(--danger); font-weight: 600; }
.stage-lbl.is-done { color: var(--success); font-weight: 600; }
.stage-lbl.is-works { color: var(--purple); font-weight: 600; }
.stage-lbl.is-wait { color: #4a5b6d; }

/* My hours */
.hours-todo { color: #b45309; font-weight: 700; }
.hours-table .hrs-in { width: 100%; min-width: 74px; padding: 5px 7px; border: 1px solid var(--border); border-radius: 8px; background: #fff; font: inherit; }
.hours-table .hrs-n { min-width: 58px; max-width: 86px; }
.hours-table .hrs-in.is-suggested { color: #8a94a6; background: #f6f8fb; }
.hours-table tr.is-todo td:first-child { box-shadow: inset 3px 0 0 #f59e0b; }
.hours-table tr.is-logged td:first-child { box-shadow: inset 3px 0 0 var(--success); }

/* Google Maps pin next to a plant name */
.maps-pin { display: inline-flex; vertical-align: -2px; margin-left: 6px; color: var(--primary); opacity: .75; }
.maps-pin:hover { opacity: 1; }
.maps-links { display: inline-flex; gap: 6px; margin-left: 10px; vertical-align: middle; flex-wrap: wrap; }

/* Team report */
.tr-bar { display: flex; gap: 14px; align-items: center; flex-wrap: wrap; justify-content: space-between; }
.tr-nav { display: flex; align-items: center; gap: 8px; }
.tr-label { min-width: 190px; text-align: center; }
.tr-table th, .tr-table td { text-align: center; white-space: nowrap; }
.tr-table th:first-child, .tr-table td:first-child { text-align: left; }
.tr-table .tr-grp { border-bottom: 1px solid var(--border); font-size: 11px; letter-spacing: .04em; text-transform: uppercase; color: var(--muted); }
.tr-table tr.tr-idle td { color: var(--muted); }
.tr-table td.tr-bad { color: var(--danger); font-weight: 700; }
.tr-table tfoot tr.tr-total td { font-weight: 700; border-top: 2px solid var(--border); background: #f6f8fb; }
.tr-hist { display: flex; gap: 10px; align-items: flex-end; min-height: 130px; }
.tr-hist-col { flex: 1; display: flex; flex-direction: column; align-items: center; justify-content: flex-end; gap: 4px; text-decoration: none; color: inherit; border-radius: 10px; padding: 4px 0; }
.tr-hist-col:hover { background: var(--primary-soft); }
.tr-hist-col.is-now .tr-hist-m { color: var(--primary); font-weight: 700; }
.tr-hist-bars { display: flex; flex-direction: column-reverse; width: 46%; max-width: 44px; min-height: 2px; border-radius: 6px 6px 3px 3px; overflow: hidden; }
.tr-hist-bars i { display: block; min-height: 0; }
.tr-hist-bars .b-comm { background: var(--primary); }
.tr-hist-bars .b-maint { background: var(--purple); }
.tr-hist-bars .b-rep { background: #ea8a1a; }
.tr-hist-n { font-size: 12px; font-weight: 700; color: var(--muted); height: 16px; }
.tr-hist-m { font-size: 12px; color: var(--muted); }

/* Technician picker: two weeks at a glance */
.tp-strip { display: flex; gap: 2px; margin-top: 6px; }
.tp-d { display: block; width: 11px; height: 14px; border-radius: 3px; background: #e5e9f0; }
.tp-d.is-mon { margin-left: 5px; }
.tp-d.is-mon:first-child { margin-left: 0; }
.tp-d.is-free { background: #86d19c; }
.tp-d.is-some { background: #f6c75a; }
.tp-d.is-full { background: #ef7b7b; }
.tp-d.is-trip { background: repeating-linear-gradient(135deg, #fff7e6, #fff7e6 2px, #f1d28a 2px, #f1d28a 4px); outline: 1px solid #f1d28a; outline-offset: -1px; }
.tp-d.is-away { background: repeating-linear-gradient(135deg, #eef0f6, #eef0f6 2px, #c9d0e2 2px, #c9d0e2 4px); }
.tp-d.is-we { background: #f1f3f6; }
.tp-sum { display: block; margin-top: 4px; font-size: 11.5px; color: var(--muted); }
.tp-sum b { color: var(--text); }
.tp-best { font-style: normal; font-weight: 700; font-size: 10.5px; color: var(--success); background: var(--success-soft); border-radius: 999px; padding: 1px 7px; margin-left: 4px; }

/* Report summary: where it is, what it found, what happens now */
.rsum { margin-top: 14px; }
.rsum-top { display: grid; grid-template-columns: minmax(260px, 1fr) minmax(300px, 1.2fr); gap: 16px; align-items: stretch; }
.rsum-next { display: flex; flex-direction: column; gap: 4px; align-items: flex-start; padding: 14px 16px; border-radius: 14px; border: 1px solid var(--border); background: var(--primary-soft); }
.rsum-next.is-done { background: var(--success-soft); border-color: var(--success-border); }
.rsum-next.is-bad { background: var(--danger-soft); border-color: var(--danger-border); }
.rsum-next.is-open { background: var(--warning-soft); border-color: var(--warning-border); }
.rsum-next-k { font-size: 11px; letter-spacing: .06em; text-transform: uppercase; color: var(--muted); font-weight: 700; }
.rsum-next strong { font-size: 17px; }
.rsum-next > span:not(.rsum-next-k) { font-size: 13.5px; color: #3b4756; line-height: 1.4; }
.rsum-next .action-pill { margin-top: 8px; }
.rsum-steps { list-style: none; margin: 0; padding: 0; display: grid; grid-template-columns: repeat(3, 1fr); gap: 8px; align-content: center; }
.rsum-steps li { position: relative; display: flex; flex-direction: column; gap: 2px; padding-top: 22px; font-size: 12.5px; color: var(--muted); }
.rsum-steps li i { position: absolute; top: 4px; left: 0; right: 0; height: 8px; border-radius: 99px; background: #e5e9f0; }
.rsum-steps li.is-done i { background: var(--success); }
.rsum-steps li.is-now i { background: #f59e0b; }
.rsum-steps.is-bad li.is-now i { background: var(--danger); }
.rsum-steps li:first-child i { background: #93b4d6; }
.rsum-steps li.is-done:first-child i { background: var(--success); }
.rsum-steps li b { color: var(--text); font-size: 13.5px; }
.rsum-facts { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 10px; margin-top: 14px; }
.rsum-facts > div { display: flex; flex-direction: column; gap: 2px; padding: 10px 12px; border: 1px solid var(--border); border-radius: 12px; background: var(--surface); min-width: 0; }
.rsum-facts small { font-size: 11px; letter-spacing: .05em; text-transform: uppercase; color: var(--muted); font-weight: 700; }
.rsum-facts b { font-size: 14px; overflow-wrap: anywhere; }
.rsum-facts span { font-size: 12px; color: var(--muted); }
.rsum-found { margin-top: 14px; }
.rsum-bar { display: flex; gap: 2px; height: 10px; border-radius: 99px; overflow: hidden; background: #e5e9f0; }
.rsum-bar i { display: block; }
.rsum-bar .is-ok { background: var(--success); } .rsum-bar .is-bad { background: var(--danger); } .rsum-bar .is-na { background: #cbd5e1; }
.rsum-nums { display: flex; gap: 6px 18px; flex-wrap: wrap; margin-top: 8px; font-size: 13px; color: var(--muted); }
.rsum-nums b { color: var(--text); font-size: 15px; }
.rsum-nums .is-bad b { color: var(--danger); } .rsum-nums .is-warn b { color: #b45309; }
.rsum-bad { list-style: none; margin: 8px 0 0; padding: 0; display: grid; gap: 3px; font-size: 13px; }
.rsum-bad li { display: flex; align-items: center; gap: 8px; }
.rsum-jump { display: flex; gap: 8px; flex-wrap: wrap; margin-top: 14px; padding-top: 12px; border-top: 1px solid var(--border); }
.rsum-jump a { padding: 4px 12px; border-radius: 999px; border: 1px solid var(--border); font-size: 12.5px; color: var(--primary); text-decoration: none; background: var(--surface); }
.rsum-jump a:hover { background: var(--primary-soft); border-color: var(--primary-border); }
@media (max-width: 860px) { .rsum-top { grid-template-columns: 1fr; } }

/* Inventory charts: three side by side, each donut above its own legend */
@media (min-width: 1100px) { .donut-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
.donut-grid .donut-body { flex-direction: column; align-items: stretch; gap: 10px; }
.donut-grid .donut { margin: 0 auto; }
.donut-grid .donut-legend { min-width: 0; }

.myweek-note.is-missed { color: var(--danger); font-weight: 700; }
.myweek-day.has-work:has(.is-missed) { border-color: var(--danger-border); background: var(--danger-soft); }

/* Reports grouped by job */
.rep-view { display: flex; gap: 8px; align-items: center; margin: 4px 0 12px; }
.job-row td { background: #f8fafc; border-top: 1px solid var(--border); }
.job-row:hover td { background: var(--primary-soft); }
.job-toggle { display: inline-flex; align-items: center; gap: 6px; border: 0; background: transparent; padding: 3px 6px; border-radius: 8px; cursor: pointer; font: inherit; color: var(--primary); }
.job-toggle:hover { background: #fff; }
.job-chev { display: inline-block; transition: transform .15s; font-size: 12px; }
.job-toggle[aria-expanded="true"] .job-chev { transform: rotate(90deg); }
tr.job-child td:first-child { padding-left: 28px; }
tr.job-child td { background: #fff; border-top-style: dashed; }
tr.job-child td { border-top: 1px solid #eef1f5; }
tr.job-child td:first-child { padding-left: 24px; }
.job-row td { border-top: 1px solid var(--border); }
.report-bucket-table th:nth-child(1), .report-bucket-table td:nth-child(1) { width: 15%; }
.report-bucket-table th:nth-child(2), .report-bucket-table td:nth-child(2) { width: 14%; }
.report-bucket-table th:nth-child(3), .report-bucket-table td:nth-child(3) { width: 15%; }
.job-toggle { white-space: nowrap; }

/* Confirm a whole job in one click */
.plans-confirm { margin-top: 14px; padding-top: 12px; border-top: 1px solid var(--border); }
.plans-confirm h3 { margin: 0 0 6px; display: flex; align-items: center; gap: 8px; font-size: 15px; }
.plan-card { display: flex; justify-content: space-between; align-items: center; gap: 12px; padding: 10px 14px; margin-top: 8px; border: 1px solid var(--warning-border); border-radius: 12px; background: #fffaf0; color: inherit; text-decoration: none; }
.plan-card:hover { border-color: var(--primary); background: var(--primary-soft); }
.plan-card-main { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.plan-card-main small { color: var(--muted); font-size: 12.5px; }

/* Days proposed by the technicians: seen and accepted in the plan */
.prop-banner { border-color: var(--warning-border); background: #fffaf0; }
.prop-head { display: flex; gap: 12px; align-items: center; }
.prop-head > div { flex: 1; }
.prop-ico { display: grid; place-items: center; width: 34px; height: 34px; border-radius: 10px; background: var(--warning-soft); color: var(--warning); flex: none; }
.prop-list { list-style: none; margin: 10px 0 0; padding: 0; display: grid; gap: 3px; font-size: 13px; }
.prop-new { color: var(--primary); }
.prop-accept { margin-left: 8px; padding: 2px 10px; border-radius: 999px; border: 1px solid var(--primary); background: #fff; color: var(--primary); font-size: 12px; font-weight: 600; cursor: pointer; }
.prop-accept:hover { background: var(--primary); color: #fff; }

.prop-inline { display: inline; margin: 0; }
td .prop-inline { margin-left: 6px; }

.report-bucket-table th:nth-child(1), .report-bucket-table td:nth-child(1) { width: 14%; }
.report-bucket-table th:nth-child(2), .report-bucket-table td:nth-child(2) { width: 13%; }
.report-bucket-table th:nth-child(3), .report-bucket-table td:nth-child(3) { width: 14%; }
.report-bucket-table th:nth-child(4), .report-bucket-table td:nth-child(4) { width: 15%; white-space: normal; }
.report-bucket-table th:nth-child(5), .report-bucket-table td:nth-child(5) { width: 11%; }
.report-bucket-table th:nth-child(6), .report-bucket-table td:nth-child(6) { width: 14%; }
.report-bucket-table th:nth-child(7), .report-bucket-table td:nth-child(7) { width: 5%; }
.report-bucket-table th:nth-child(8), .report-bucket-table td:nth-child(8) { width: 14%; text-align: right; white-space: nowrap; overflow: visible; }

.dl-chip.is-danger { background:#fde8e8; color:#b42318; }
.dl-chip.is-warning { background:#fff4d6; color:#8a5a00; }
.dl-chip.is-success { background:#e3f6ea; color:#17653a; }

/* the sticky header of the inverter picker hides the rows that scroll under it */
.inv-pick th { background: #f1f5f9; z-index: 2; box-shadow: 0 1px 0 var(--border); }

/* My hours: the table fits its card (the "where" column wraps instead of stretching it) */
.hours-table td:nth-child(2) { white-space: normal; min-width: 130px; max-width: 220px; }
.hours-table .hrs-in { min-width: 66px; }
.hours-table td, .hours-table th { padding-left: 6px; padding-right: 6px; }
