/* ==========================================================================
   components.css — reusable pieces shared across every page and module.

   Ported from OHS-DB — if a component exists there, it looks identical here.
   Colors always come from tokens.css; never a literal hex.

   Built so far: buttons, cards, form fields, inline messages, theme swatches,
   badges, tables, filter bar, detail grid, cert rows, pager, banners, toasts,
   modal, and the officer verdict card.

   The officer shell's own frame (.phone, the navy header, the sync strip) is
   structure, so it lives in layout.css. What is here is what goes inside it.

   Still to come:
     - .kpi-*, .chart-* dashboard tiles (Stage 7)
   ========================================================================== */

/* ---------- Buttons ---------- */
.btn {
  border-radius: var(--radius-control);
  padding: 9px 15px;
  font-size: 13px;
  border: 1px solid transparent;
  font-weight: 600;
  display: inline-flex;
  align-items: center;
  gap: 7px;
}
.btn:disabled {
  opacity: .6;
  cursor: default;
}

.btn-primary { background: var(--primary); color: var(--navy-text-strong); }
.btn-primary:hover:not(:disabled) { background: var(--primary-dark); }

.btn-ghost { background: transparent; border-color: var(--border); color: var(--text2); }
.btn-ghost:hover:not(:disabled) { background: var(--bg); }
.btn-ghost.active { border-color: var(--primary); color: var(--primary); }

.btn-danger { background: var(--blocked-bg); color: var(--blocked-dark); }
.btn-danger:hover:not(:disabled) { background: var(--urgent-bg); }

.btn-sm { padding: 6px 10px; font-size: 12px; }

/* Touch-sized button for the officer mobile shell. */
.btn-lg {
  padding: 14px 18px;
  font-size: 15px;
  border-radius: var(--radius-mobile);
  justify-content: center;
}

.btn-block { width: 100%; justify-content: center; }

/* ---------- Cards ---------- */
.card {
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: var(--radius-card);
  box-shadow: var(--shadow-sm);
  padding: 18px;
}
.card h3 { margin: 0 0 10px; font-size: 15px; font-weight: 700; }

/* ---------- Form fields ---------- */
.field { display: flex; flex-direction: column; gap: 5px; margin-block-end: 12px; }
.field label { font-size: 12px; color: var(--text2); font-weight: 600; }
.field input,
.field select,
.field textarea {
  border: 1px solid var(--border);
  border-radius: var(--radius-control);
  padding: 9px 10px;
  background: var(--card);
}
.field input:focus,
.field select:focus,
.field textarea:focus {
  outline: none;
  border-color: var(--primary);
  box-shadow: 0 0 0 3px var(--primary-soft);
}
.field.inline { flex-direction: row; align-items: center; gap: 8px; }

/* ---------- Theme swatches (Section 8.3) ----------
   Four accent themes. The picker sits on the navy sidebar today and on the navy
   officer header in Stage 8, so the active ring is drawn against navy. */
.swatches {
  display: flex;
  gap: 8px;
  margin-block-end: 12px;
}
.swatch {
  width: 20px;
  height: 20px;
  padding: 0;
  border-radius: 50%;
  cursor: pointer;
  border: 2px solid transparent;
}
.swatch.blue    { background: var(--theme-color-blue); }
.swatch.teal    { background: var(--theme-color-teal); }
.swatch.purple  { background: var(--theme-color-purple); }
.swatch.crimson { background: var(--theme-color-crimson); }
.swatch.active {
  border-color: var(--navy-text-strong);
  box-shadow: 0 0 0 2px var(--navy);
}

/* ---------- Tabs ----------
   A strip of buttons above a panel, the active one underlined in the accent
   colour. Border-block-end rather than a physical side, so it holds in RTL. */
.tabs {
  display: flex;
  gap: 4px;
  flex-wrap: wrap;
  border-block-end: 1px solid var(--border);
  margin-block-end: 16px;
}
.tab {
  padding: 9px 14px;
  border: none;
  background: transparent;
  color: var(--text2);
  font-size: 13px;
  font-weight: 600;
  border-radius: var(--radius-control) var(--radius-control) 0 0;
  border-block-end: 2px solid transparent;
  margin-block-end: -1px;
  cursor: pointer;
}
.tab:hover { background: var(--surface-sunken); color: var(--text); }
.tab.active {
  color: var(--primary);
  border-block-end-color: var(--primary);
}

/* ---------- Switch ----------
   A checkbox that looks like a toggle. The input stays in the DOM and keeps
   working with the keyboard — only its rendering is replaced. */
.switch {
  display: inline-flex;
  align-items: center;
  cursor: pointer;
}
.switch input {
  position: absolute;
  opacity: 0;
  inline-size: 1px;
  block-size: 1px;
}
.switch-track {
  position: relative;
  display: block;
  inline-size: 34px;
  block-size: 18px;
  border-radius: 999px;
  background: var(--missing-bg);
  border: 1px solid var(--border);
  transition: background .15s ease;
}
.switch-knob {
  position: absolute;
  inset-block-start: 2px;
  inset-inline-start: 2px;
  inline-size: 12px;
  block-size: 12px;
  border-radius: 50%;
  background: var(--card);
  box-shadow: var(--shadow-sm);
  transition: inset-inline-start .15s ease;
}
.switch input:checked + .switch-track { background: var(--primary); border-color: var(--primary); }
.switch input:checked + .switch-track .switch-knob { inset-inline-start: 18px; }
.switch input:focus-visible + .switch-track {
  outline: 2px solid var(--primary);
  outline-offset: 2px;
}
.switch input:disabled + .switch-track { opacity: .5; cursor: not-allowed; }

/* ---------- Form furniture ----------
   The explanatory line under a field, the label above a group of controls, and
   the button row that closes a form panel. */
.field-hint {
  font-size: 11.5px;
  color: var(--muted);
  line-height: 1.5;
}
.field-label {
  font-size: 12px;
  font-weight: 600;
  color: var(--text2);
  margin-block-end: 6px;
}
.form-actions {
  display: flex;
  justify-content: flex-end;
  gap: 8px;
  margin-block-start: 16px;
}

/* Actions cell in a table: keep the buttons on one line where there is room. */
.cell-actions { display: flex; gap: 6px; flex-wrap: wrap; }

/* A voided inspection wave. Struck through and dimmed rather than hidden: the
   row stays on the record (rule 6) and the point of showing it is that somebody
   can see it was cancelled, and read why. */
.row-voided td { color: var(--muted); text-decoration: line-through; }
.row-voided td .cell-sub { text-decoration: none; }

/* A row for a record that is switched off — deactivated user, retired option. */
.row-inactive td { opacity: .55; }

/* ---------- Inline messages ---------- */
.err { color: var(--danger); font-size: 12px; margin-block-start: 6px; min-height: 16px; }
.ok  { color: var(--success); font-size: 12px; margin-block-start: 6px; }

/* ---------- Page head ----------
   Subtitle and page actions, above the filter bar. The route's own name is the
   topbar's job and is never repeated here — a page head carries a title only
   when it says something the topbar cannot, like the name of the record on
   screen. Actions marked [data-topbar-actions] are hoisted into the topbar by
   render.js, so this block is empty of them by the time it is painted. */
.page-head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 12px;
  margin-block-end: 14px;
}
.page-head-title { font-size: 16px; font-weight: 700; color: var(--text); margin-block-end: 3px; }
.page-head-sub { font-size: 12.5px; color: var(--text2); }
.page-head-actions { display: flex; gap: 8px; flex-wrap: wrap; }

/* ---------- Section header ---------- */
.section-head {
  display: flex;
  align-items: center;
  gap: 8px;
  font-weight: 700;
  font-size: 14px;
  margin: 18px 0 10px;
  color: var(--text);
}
.section-head::before {
  content: "";
  width: 3px;
  height: 16px;
  background: var(--primary);
  border-radius: 2px;
}

/* ---------- Badges ---------- */
.badge {
  display: inline-block;
  padding: 3px 10px;
  border-radius: 12px;
  font-size: 11.5px;
  font-weight: 700;
}
.badge-cleared  { background: var(--cleared-bg);   color: var(--cleared-dark); }
.badge-warning  { background: var(--warn-bg);      color: var(--warn-dark); }
.badge-blocked  { background: var(--blocked-bg);   color: var(--blocked-dark); }
.badge-active   { background: var(--cleared-bg);   color: var(--cleared-dark); }
.badge-inactive { background: var(--missing-bg);   color: var(--missing-tx); }

.badge-team-field  { background: var(--team-field-bg);  color: var(--team-field-tx); }
.badge-team-safety { background: var(--team-safety-bg); color: var(--team-safety-tx); }

/* An outstanding RDT pick, and the phase label above it. This is the
   non-compliance use the --plan tokens were kept for (Section 8.3): work not
   done yet is neither a problem nor a success. */
.badge-rdt-selected { background: var(--plan-bg); color: var(--plan-tx); }

.badge-row { display: flex; gap: 10px; align-items: center; flex-wrap: wrap; margin-block-end: 16px; }

/* ---------- Certificate state pills (Section 6.1) ----------
   Seven states, worst to best, with `na` outside the ladder entirely. No `plan`
   tier — anything past soon_days is `valid`, so --plan-bg deliberately goes
   unused here. */
.cert-state {
  display: inline-block;
  padding: 3px 9px;
  border-radius: 10px;
  font-size: 11px;
  font-weight: 700;
  white-space: nowrap;
}
.cs-suspended { background: var(--suspended-bg); color: var(--suspended-tx); }
.cs-expired   { background: var(--blocked-bg);   color: var(--blocked-dark); }
.cs-urgent    { background: var(--urgent-bg);    color: var(--urgent-tx); }
.cs-soon      { background: var(--warn-bg);      color: var(--warn-dark); }
.cs-missing   { background: var(--missing-bg);   color: var(--missing-tx); }
.cs-valid     { background: var(--cleared-bg);   color: var(--cleared-dark); }
.cs-na        { background: var(--na-bg);        color: var(--na-tx); }

/* ---------- Tables ---------- */
.tbl {
  width: 100%;
  border-collapse: collapse;
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: var(--radius-card);
  overflow: hidden;
}
.tbl th,
.tbl td {
  padding: 11px 14px;
  text-align: start;
  border-block-end: 1px solid var(--border);
  font-size: 13px;
  vertical-align: middle;
}
.tbl th {
  background: var(--surface-sunken);
  color: var(--text2);
  font-weight: 600;
  font-size: 12px;
  text-transform: uppercase;
  letter-spacing: .3px;
}
.tbl tr:last-child td { border-block-end: none; }
.tbl tbody tr:hover td { background: var(--surface-sunken); }

/* Dropped inside a .card, which already draws the frame. */
.tbl-flush { border: none; border-radius: 0; }

.row-clickable { cursor: pointer; }
.row-selected td { background: var(--primary-soft); }

/* Cell variants used across every list. */
.cell-sub   { color: var(--muted); font-size: 11.5px; margin-block-start: 2px; }
.cell-mono  { font-family: ui-monospace, 'Cascadia Mono', Consolas, monospace; font-size: 12px; }
.cell-danger { color: var(--danger); font-size: 11px; margin-inline-start: 6px; }
.cell-check { width: 40px; }
.cell-empty {
  text-align: center;
  padding: 40px 14px;
  color: var(--muted);
  font-size: 13px;
}

/* A leading edge stripe keyed to the row's compliance state, for lists sorted
   by urgency. Subtler than tinting the whole row, and it survives the hover
   background. */
.row-suspended td:first-child { box-shadow: inset 3px 0 0 var(--suspended-tx); }
.row-expired   td:first-child { box-shadow: inset 3px 0 0 var(--blocked); }
.row-urgent    td:first-child { box-shadow: inset 3px 0 0 var(--urgent-tx); }
.row-soon      td:first-child { box-shadow: inset 3px 0 0 var(--warn); }

/* ---------- Filter bar ---------- */
.filter-bar {
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: var(--radius-card);
  padding: 14px;
  margin-block-end: 14px;
  display: flex;
  gap: 12px;
  align-items: flex-end;
  flex-wrap: wrap;
}
.filter-bar .field { margin-block-end: 0; min-width: 180px; }
.filter-bar .filter-search { flex: 1; max-width: 340px; }
.filter-bar .count {
  margin-inline-start: auto;
  color: var(--text2);
  font-size: 12.5px;
  padding-block-end: 9px;
}

/* ---------- Pager ---------- */
.pager {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 12px;
  margin-block-start: 14px;
}
.pager-label { font-size: 12.5px; color: var(--text2); }

/* ---------- Detail grid ---------- */
.detail-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 16px; }
.field-disp { display: flex; flex-direction: column; gap: 3px; }
.field-disp .lab {
  font-size: 11px;
  color: var(--muted);
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: .3px;
}
.field-disp .val { font-size: 13.5px; font-weight: 500; }
.field-disp .val.muted { color: var(--muted); font-style: italic; }

/* ---------- Certificate rows ---------- */
.cert-list { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; }
.cert-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  padding: 10px 12px;
  border: 1px solid var(--border);
  border-radius: var(--radius-control);
  background: var(--surface-sunken);
}
.cert-info .name { font-weight: 600; font-size: 13px; }
.cert-info .date { font-size: 12px; color: var(--text2); margin-block-start: 2px; }
.cert-days { color: var(--muted); }
.cert-actions { display: flex; gap: 8px; align-items: center; flex-shrink: 0; }

/* The two flagged states tint the whole row, not just the badge — in a list of
   ten certificates the badge alone is too small to find. Same colours the form
   panel uses, so a certificate looks the same wherever it is shown. */
.cert-row-na        { background: var(--na-bg);        border-color: var(--na-bg); }
.cert-row-na .name  { color: var(--na-tx); }
.cert-row-suspended { background: var(--suspended-bg); border-color: var(--suspended-bg); }
.cert-row-suspended .name { color: var(--suspended-tx); }

/* ---------- Checkbox rows ---------- */
.check-row { display: flex; gap: 20px; flex-wrap: wrap; }
.check { display: flex; align-items: center; gap: 6px; font-size: 13px; cursor: pointer; }

/* ---------- Banners ----------
   A page-level message that stays put, unlike a toast. */
.banner {
  border-radius: var(--radius-control);
  padding: 10px 14px;
  font-size: 12.5px;
  margin-block-end: 14px;
}
.banner-warn   { background: var(--warn-bg);    color: var(--warn-dark); }
.banner-danger { background: var(--blocked-bg); color: var(--blocked-dark); }

/* ---------- Toasts ----------
   Mounted on body, outside #app, so a redraw cannot remove a message the user
   has not read yet. */
.toast-stack {
  position: fixed;
  inset-block-end: 20px;
  inset-inline-end: 20px;
  display: flex;
  flex-direction: column;
  gap: 8px;
  z-index: 99;
  pointer-events: none;
}
.toast {
  background: var(--text);
  color: var(--navy-text-strong);
  padding: 12px 18px;
  border-radius: 9px;
  font-size: 13px;
  box-shadow: var(--shadow-md);
  max-width: 380px;
  transition: opacity .2s ease;
}
.toast-success { background: var(--cleared-dark); }
.toast-error   { background: var(--blocked-dark); }
.toast-out     { opacity: 0; }

/* ---------- Modal ---------- */
.overlay {
  position: fixed;
  inset: 0;
  background: var(--overlay);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 100;
  padding: 20px;
}
.modal {
  background: var(--card);
  border-radius: 12px;
  padding: 22px;
  max-width: 460px;
  width: 100%;
  max-height: 88vh;
  overflow: auto;
  box-shadow: var(--shadow-md);
}
/* Wide enough for the import review table, but never wider than the viewport. */
.modal-wide { max-width: min(980px, 96vw); }
.modal h3 { margin: 0 0 8px; font-size: 15px; font-weight: 700; }
.modal-body { margin: 0 0 14px; font-size: 13px; line-height: 1.6; color: var(--text2); }
.modal-actions { display: flex; justify-content: flex-end; gap: 8px; margin-block-start: 16px; }

/* The caller's form inside a formDialog. */
.modal-form { margin-block-start: 14px; }
.modal-form .field:last-of-type { margin-block-end: 0; }

/* A line of explanation above a form, where the title alone is not enough. */
.modal-intro {
  font-size: 12.5px;
  color: var(--text2);
  line-height: 1.6;
  margin-block-end: 14px;
}

/* A field whose value is fixed and shown rather than edited — the employee on a
   dialog opened from that employee's own page. Padded to match the inputs
   beside it so the column of labels stays on one rhythm. */
.field-static {
  display: flex;
  align-items: baseline;
  gap: 8px;
  padding: 9px 10px;
  border: 1px solid var(--border);
  border-radius: var(--radius-control);
  background: var(--bg);
}

/* The permission checkbox grid in the user editor. */
.perm-section {
  margin-block-start: 16px;
  padding-block-start: 14px;
  border-block-start: 1px solid var(--border);
}
.perm-grid {
  border: 1px solid var(--border);
  border-radius: var(--radius-control);
  overflow: hidden;
}
.perm-row {
  display: grid;
  grid-template-columns: 1fr 60px 60px;
  align-items: center;
  gap: 8px;
  padding: 8px 12px;
  font-size: 13px;
  border-block-end: 1px solid var(--border);
}
.perm-row:last-child { border-block-end: none; }
.perm-row > input { justify-self: center; }
.perm-head {
  background: var(--surface-sunken);
  font-size: 11px;
  font-weight: 700;
  color: var(--text2);
  text-transform: uppercase;
  letter-spacing: .3px;
}
.perm-head > span:not(:first-child) { text-align: center; }

/* ==========================================================================
   Officer app components (Sections 7.5, 8.6)

   Ported from design/officer_prototype.html, with every literal hex replaced by
   its token. Touch targets are sized for a gloved hand at a tower, not a mouse.
   ========================================================================== */

/* ---------- Search box ---------- */
.search-box {
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: 12px;
  padding: 12px 14px;
  display: flex;
  align-items: center;
  gap: 10px;
  margin-block-end: 14px;
}
.search-box input {
  flex: 1;
  min-width: 0;
  border: none;
  background: none;
  font-size: 15px;
  outline: none;
  color: var(--text);
}
.search-box .ic { color: var(--muted); font-size: 17px; flex-shrink: 0; }
.search-box .search-clear {
  color: var(--muted);
  font-size: 20px;
  line-height: 1;
  background: none;
  border: none;
  padding: 4px 6px;
  flex-shrink: 0;
}
.search-box .search-clear.is-hidden { visibility: hidden; }

/* ---------- Result list ---------- */
.section-h {
  font-size: 11.5px;
  font-weight: 700;
  color: var(--muted);
  text-transform: uppercase;
  letter-spacing: .5px;
  margin: 6px 4px 8px;
}

.result-list { display: flex; flex-direction: column; gap: 8px; }

.result-item {
  width: 100%;
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: 12px;
  padding: 12px 14px;
  display: flex;
  align-items: center;
  gap: 12px;
  text-align: start;
  cursor: pointer;
}
.result-item:active { background: var(--surface-sunken); }

.result-item .avatar {
  width: 42px;
  height: 42px;
  flex-shrink: 0;
  border-radius: 50%;
  background: var(--primary-soft);
  color: var(--primary);
  display: flex;
  align-items: center;
  justify-content: center;
  font-weight: 800;
  font-size: 14px;
}
.result-info { flex: 1; min-width: 0; }
.result-name {
  display: block;
  font-weight: 700;
  font-size: 15px;
  color: var(--text);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.result-meta {
  display: block;
  font-size: 12px;
  color: var(--text2);
  margin-block-start: 2px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* The verdict at a glance. A dot rather than a word, because the officer is
   scanning a list, and the card they tap into spells it out. */
.v-dot { width: 14px; height: 14px; border-radius: 50%; flex-shrink: 0; }
.v-cleared { background: var(--cleared); }
.v-warning { background: var(--warn); }
.v-blocked { background: var(--blocked); }

/* ---------- Empty states ---------- */
.officer-empty {
  text-align: center;
  padding: 56px 20px;
  color: var(--muted);
  font-size: 14px;
}
.officer-empty .big { font-size: 44px; margin-block-end: 12px; opacity: .3; }

/* ---------- Verdict hero (Section 7.5) ----------
   The one screen in the platform that is read from three metres away. Colour is
   the message; the icon and the label repeat it, so it does not depend on
   colour vision or on direct sunlight. */
.verdict-hero {
  padding: 26px 22px 24px;
  color: var(--navy-text-strong);
  position: relative;
}
.verdict-hero.cleared { background: linear-gradient(135deg, var(--cleared) 0%, var(--cleared-dark) 100%); }
.verdict-hero.warning { background: linear-gradient(135deg, var(--warn) 0%, var(--warn-dark) 100%); }
.verdict-hero.blocked { background: linear-gradient(135deg, var(--blocked) 0%, var(--blocked-dark) 100%); }

/* Placed by logical properties, so Back leads and Refresh trails in both
   directions without an RTL override (Section 8.2). */
.verdict-nav {
  position: absolute;
  inset-block-start: 14px;
  color: var(--navy-text-strong);
  font-size: 18px;
  line-height: 1;
  min-width: 40px;
  min-height: 40px;
  padding: 8px 10px;
  border: none;
  border-radius: var(--radius-control);
  background: rgba(255, 255, 255, .18);
}
.verdict-nav:disabled { opacity: .5; }
.verdict-nav.back    { inset-inline-start: 14px; }
.verdict-nav.refresh { inset-inline-end: 14px; }

.verdict-icon { font-size: 62px; text-align: center; margin: 10px 0 4px; line-height: 1; }
.verdict-label { font-size: 25px; font-weight: 800; text-align: center; letter-spacing: .5px; }
.verdict-sub { font-size: 14px; text-align: center; opacity: .92; margin-block-start: 4px; }

/* ---------- Identity card ----------
   Pulled up over the hero so the two read as one unit. */
.officer-id-card {
  background: var(--card);
  margin: -14px 14px 14px;
  border-radius: var(--radius-card);
  padding: 16px;
  box-shadow: var(--shadow-md);
  position: relative;
  z-index: 1;
}
.officer-id-card .id-name { font-weight: 800; font-size: 19px; }
.officer-id-card .id-sub {
  font-family: ui-monospace, Consolas, monospace;
  font-size: 13px;
  color: var(--text2);
  margin-block-start: 4px;
}
.officer-id-card .id-tags {
  display: flex;
  gap: 6px;
  flex-wrap: wrap;
  margin-block-start: 12px;
}

.id-tag {
  padding: 3px 10px;
  border-radius: 12px;
  font-size: 11.5px;
  font-weight: 700;
  background: var(--missing-bg);
  color: var(--missing-tx);
}
.id-tag.ok  { background: var(--cleared-bg); color: var(--cleared-dark); }
.id-tag.bad { background: var(--blocked-bg); color: var(--blocked-dark); }
.id-tag.team-field  { background: var(--team-field-bg);  color: var(--team-field-tx); }
.id-tag.team-safety { background: var(--team-safety-bg); color: var(--team-safety-tx); }

/* ---------- Issues found ---------- */
.officer-section { padding: 0 14px 4px; }
.officer-section h3 { margin: 6px 0 10px; font-size: 14px; font-weight: 700; }
.officer-section h3.is-blocked { color: var(--blocked-dark); }
.officer-section h3.is-warning { color: var(--warn-dark); }

.reason-item {
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: var(--radius-mobile);
  padding: 12px 14px;
  margin-block-end: 8px;
  display: flex;
  align-items: center;
  gap: 10px;
  font-size: 13.5px;
  line-height: 1.45;
}
/* The severity stripe sits on the leading edge, so it flips with the text. */
.reason-item.blocker { border-inline-start: 4px solid var(--blocked); }
.reason-item.warning { border-inline-start: 4px solid var(--warn); }
.reason-ic { font-size: 17px; flex-shrink: 0; }
.reason-item.blocker .reason-ic { color: var(--blocked); }
.reason-item.warning .reason-ic { color: var(--warn); }
.reason-txt { flex: 1; }

/* ---------- Panels (certificates, inspection, waves) ---------- */
.officer-panel {
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: 12px;
  padding: 14px;
  margin: 14px;
}
.officer-panel h3 { margin: 0 0 10px; font-size: 14px; font-weight: 700; }

.cert-line {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 10px;
  padding: 9px 0;
  border-block-end: 1px solid var(--border);
  font-size: 13.5px;
}
.cert-line:last-child { border-block-end: none; }
.cert-line-main { min-width: 0; }
.cert-line-name { color: var(--text); }
.cert-line-date { color: var(--text2); font-size: 12.5px; margin-block-start: 2px; }
.cert-line-value { color: var(--text2); font-size: 12.5px; text-align: end; }
.cert-line .cert-days { color: var(--muted); margin-inline-start: 4px; }

/* ---------- Inspection waves on the officer card ----------
   The comment an officer left for the next one. Wrapped rather than truncated:
   "webbing frayed near the D-ring" is the whole value of the line, and an
   ellipsis in the middle of it would be worse than a taller row. */
.cert-line-note {
  color: var(--text2);
  font-size: 12.5px;
  line-height: 1.5;
  margin-block-start: 4px;
  white-space: pre-wrap;
  overflow-wrap: anywhere;
}

/* A wave recorded on this phone and not yet on the record. Marked, never
   coloured like a verdict — rule 13 keeps derivation on the server, and the
   hero above this row still reflects the last thing the server said. */
.cert-line-pending {
  background: var(--plan-bg);
  border-inline-start: 3px solid var(--warn);
  padding-inline-start: 8px;
  margin-inline: -8px;
  padding-inline-end: 8px;
}
.cert-line-pending .cert-line-name { color: var(--plan-tx); font-weight: 600; }

/* The record button under an equipment card. Full width — it is a thumb target
   at the bottom of a scrolled page, not a toolbar action. */
.officer-card-actions {
  padding: 14px 16px 4px;
}
.officer-card-actions .btn { width: 100%; }

/* Pass / Fail as two large targets rather than a select. An officer is wearing
   gloves and holding the item in the other hand. */
.officer-choice-row { display: flex; gap: 10px; }
.officer-choice {
  flex: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  padding: 14px 10px;
  border: 2px solid var(--border);
  border-radius: var(--radius-control);
  font-weight: 600;
  cursor: pointer;
  background: var(--card);
}
.officer-choice input { accent-color: currentColor; }
.officer-choice-pass:has(input:checked) {
  border-color: var(--cleared);
  background: var(--cleared-bg);
  color: var(--cleared-dark);
}
.officer-choice-fail:has(input:checked) {
  border-color: var(--blocked);
  background: var(--blocked-bg);
  color: var(--blocked-dark);
}

/* The unsent-waves banner on the officer home screen. */
.officer-pending {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  margin: 0 16px 12px;
}

/* ---------- Lockout screen (Section 7.4) ----------
   Deliberately the whole viewport with one button on it. There is nothing else
   to do from here, and the screen must not suggest otherwise. */
.officer-lock {
  padding: 56px 24px;
  text-align: center;
  background: var(--card);
  min-height: 70vh;
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
}
.officer-lock .lock-icon { font-size: 58px; margin-block-end: 14px; }
.officer-lock h2 { font-size: 20px; margin: 0 0 8px; }
.officer-lock p {
  color: var(--text2);
  font-size: 13.5px;
  line-height: 1.6;
  max-width: 300px;
  margin-block-end: 24px;
}
.officer-lock .btn { max-width: 300px; }

/* ---------- Entity not in the snapshot ---------- */
.officer-missing {
  padding: 40px 24px;
  text-align: center;
  color: var(--text2);
}
.officer-missing .officer-missing-icon {
  font-size: 46px;
  color: var(--muted);
  opacity: .4;
  margin: 20px 0 10px;
}
.officer-missing h2 { font-size: 17px; margin: 0 0 8px; color: var(--text); }
.officer-missing p { font-size: 13.5px; line-height: 1.6; max-width: 300px; margin-inline: auto; }

/* ---------- Sync page ---------- */
.sync-fact { display: flex; justify-content: space-between; gap: 12px; font-size: 13.5px; }
.sync-fact .lab { color: var(--text2); }
.sync-fact .val { font-weight: 600; text-align: end; }
