/* RFI Tracker WP33 — shared styles. Mobile-first, calm and legible. */
:root {
  --navy: #14213d;
  --navy-2: #1f2b4a;
  --amber: #fca311;
  --green: #15803d;
  --red: #b91c1c;
  --blue: #1d4ed8;
  --bg: #f4f5f7;
  --card: #ffffff;
  --line: #e5e7eb;
  --text: #111827;
  --muted: #6b7280;
}

* { box-sizing: border-box; }

body {
  margin: 0;
  background: var(--bg);
  color: var(--text);
  font-family: system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
  font-size: 16px;
  padding-bottom: calc(64px + env(safe-area-inset-bottom)); /* room for the bottom nav */
}

/* ===== Header ===== */
.app-header {
  background: var(--navy);
  color: #fff;
  padding: 12px 16px;
  position: sticky;
  top: 0;
  z-index: 30;
  display: flex;
  align-items: center;
  gap: 12px;
}
.app-header .back {
  color: #fff;
  text-decoration: none;
  font-size: 24px;
  line-height: 1;
  padding: 4px 8px 4px 0;
}

/* Offline sign-in about to lapse. Sits directly under the header and
   scrolls away with the page — it's a warning to act on soon, not an alert
   worth pinning over content on a phone-sized screen. Amber, not red: the
   app still works and nothing is lost yet. */
.session-warn {
  background: #fef3c7;
  border-bottom: 1px solid #fcd34d;
  color: #78350f;
  padding: 10px 16px;
  font-size: 12.5px;
  line-height: 1.5;
  display: flex;
  align-items: center;
  gap: 12px;
}
.session-warn button {
  flex-shrink: 0;
  background: #b45309;
  color: #fff;
  border: none;
  border-radius: 8px;
  padding: 7px 12px;
  font: inherit;
  font-weight: 650;
  cursor: pointer;
}
.session-warn button:active { background: #92400e; }
.app-header .hdr-avatar {
  width: 32px; height: 32px;
  border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  font-size: 10.5px;
  font-weight: 800;
  color: #14213d;
  flex-shrink: 0;
}
.app-header .titles { flex: 1; min-width: 0; }
.app-header .app-title {
  font-size: 16px;
  font-weight: 700;
  margin: 0;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.app-header .app-sub {
  font-size: 12px;
  color: #9ca3af;
  margin: 2px 0 0;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.app-header .role-line { color: #d1d5db; }
.app-header .role-line a { color: #fca311; text-decoration: none; font-weight: 600; }

/* Sync pill in header */
.sync-pill {
  border: none;
  border-radius: 999px;
  padding: 8px 14px;
  font-size: 12px;
  font-weight: 600;
  cursor: pointer;
  display: flex;
  align-items: center;
  gap: 7px;
  white-space: nowrap;
}
.sync-pill .dot { width: 8px; height: 8px; border-radius: 50%; background: currentColor; }
.sync-pill.online { background: #dcfce7; color: #166534; }
.sync-pill.pending { background: #fef3c7; color: #92400e; }
.sync-pill.offline { background: #fee2e2; color: #991b1b; }
.sync-pill.offline .dot { animation: blink 1.2s infinite; }
@keyframes blink { 50% { opacity: 0.25; } }

main { padding: 16px; max-width: 720px; margin: 0 auto; }

/* ===== Cards ===== */
.card {
  background: var(--card);
  border: 1px solid var(--line);
  border-radius: 12px;
  padding: 16px;
  margin-bottom: 12px;
}
a.card { display: block; text-decoration: none; color: inherit; }
a.card:active { background: #fafafa; }

.card .row { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.ref { font-size: 12px; font-weight: 600; color: var(--muted); letter-spacing: 0.02em; }
.card h3 { margin: 8px 0 2px; font-size: 16px; font-weight: 650; }
.card .loc { font-size: 13px; color: var(--muted); margin: 0; }

/* One calm meta line replaces the old badge boxes */
.meta {
  font-size: 13px;
  color: var(--muted);
  margin: 10px 0 0;
  line-height: 1.5;
}
.meta .ok { color: var(--green); }
.meta .warn { color: #b45309; font-weight: 600; }
.meta .danger { color: var(--red); font-weight: 600; }

.note {
  font-size: 13px;
  color: #92400e;
  background: #fffbeb;
  border: 1px solid #fde68a;
  border-radius: 8px;
  padding: 8px 12px;
  margin: 10px 0 0;
}

/* Status chips — grouped into calm tones by phase (16-status flow) */
.chip {
  font-size: 11px;
  font-weight: 600;
  border-radius: 999px;
  padding: 4px 11px;
  white-space: nowrap;
}
/* QAQC/SE raising + numbering / site confirming */
.chip.rfi_created, .chip.rfi_drafted, .chip.numbered, .chip.site_ready, .chip.site_signed { background: #f3f4f6; color: #374151; }
/* awaiting Consultant DC / site-side action */
.chip.sent_to_consultant, .chip.registered, .chip.awaiting_iow, .chip.iow_assigned { background: #fef3c7; color: #92400e; }
/* joint inspection + DC review phase */
.chip.joint_inspection_done, .chip.inspection_signed, .chip.evidence_verified, .chip.acknowledged { background: #dbeafe; color: #1e40af; }
/* ARE / SOR sign-off chain + return */
.chip.with_consultant_dc, .chip.with_are, .chip.are_signed, .chip.sor_signed, .chip.returned { background: #ede9fe; color: #5b21b6; }
/* done */
.chip.closed { background: #dcfce7; color: #166534; }
.chip.expired { background: #fee2e2; color: #991b1b; }

/* ===== List search (rfis.html) =====
   Sits above the tabs: the query scopes everything, the tabs then slice it.
   type="search" for the mobile keyboard's Search key, with the native
   WebKit clear button suppressed so there aren't two X's side by side. */
.list-search { position: relative; margin: 0 0 10px; }
.list-search input {
  width: 100%;
  border: 1px solid var(--line);
  border-radius: 10px;
  padding: 11px 40px 11px 12px;
  font: inherit;
  font-size: 15px;
  background: #fff;
  color: var(--text);
  outline: none;
  -webkit-appearance: none;
}
.list-search input::-webkit-search-cancel-button { -webkit-appearance: none; display: none; }
.list-search input::placeholder { color: #9ca3af; }
.list-search input:focus { border-color: #94a3b8; }
.list-search .q-clear {
  position: absolute;
  right: 4px;
  top: 50%;
  transform: translateY(-50%);
  display: none;
  border: none;
  background: none;
  color: var(--muted);
  font-size: 21px;
  line-height: 1;
  padding: 7px 11px;
  cursor: pointer;
}
.list-search.has-q .q-clear { display: block; }

/* ===== Scope tabs + filter dropdowns (rfis.html) =====
   Replaced the horizontal tab strip 2026-08-18: two scope tabs, then two
   multi-select dropdowns for RFI type and status. Nothing is selected by
   default, so the page opens on the full list. */

/* Two-way segmented control — only ever two scopes, so a segmented pair
   reads better than a scrolling row of pills. */
.seg {
  display: flex;
  background: #e8eaee;
  border-radius: 10px;
  padding: 3px;
  margin-bottom: 10px;
}
.seg-btn {
  flex: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  border: none;
  background: none;
  border-radius: 8px;
  padding: 9px 10px;
  font: inherit;
  font-size: 13px;
  font-weight: 600;
  color: var(--muted);
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}
.seg-btn.active { background: #fff; color: var(--navy); box-shadow: 0 1px 2px rgba(17, 24, 39, 0.12); }
.seg-n {
  font-size: 11px;
  font-weight: 700;
  color: #9ca3af;
  font-variant-numeric: tabular-nums;
}
.seg-btn.active .seg-n { color: var(--navy); }

.filter-row { display: flex; gap: 8px; margin-bottom: 10px; }

/* Multi-select dropdown. Native <select multiple> is unusable on a phone,
   so this is a button plus an absolutely-positioned tick list that stays
   open while options are toggled. */
.msel { position: relative; flex: 1 1 0; min-width: 0; }
.msel-btn {
  display: flex;
  align-items: center;
  gap: 8px;
  width: 100%;
  border: 1px solid var(--line);
  background: #fff;
  border-radius: 10px;
  padding: 10px 12px;
  font: inherit;
  font-size: 13.5px;
  font-weight: 550;
  color: var(--text);
  text-align: left;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}
.msel-btn .msel-text { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.msel-btn .msel-chev { font-size: 10px; color: #94a3b8; flex-shrink: 0; }
.msel-btn.has-sel { border-color: var(--navy); color: var(--navy); font-weight: 650; }
.msel-btn.open { border-color: #94a3b8; }

.msel-menu {
  position: absolute;
  top: calc(100% + 4px);
  left: 0;
  right: 0;
  z-index: 25;
  background: #fff;
  border: 1px solid var(--line);
  border-radius: 10px;
  box-shadow: 0 8px 24px rgba(17, 24, 39, 0.16);
  max-height: 320px;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  padding: 4px;
}
.msel-menu[hidden] { display: none; }

.msel-all {
  display: block;
  width: 100%;
  border: none;
  background: none;
  border-bottom: 1px solid var(--line);
  padding: 9px 10px;
  font: inherit;
  font-size: 13px;
  font-weight: 600;
  color: var(--blue);
  text-align: left;
  cursor: pointer;
}
.msel-group {
  font-size: 10px;
  text-transform: uppercase;
  letter-spacing: 0.07em;
  color: var(--muted);
  font-weight: 700;
  margin: 10px 0 4px;
  padding: 0 10px;
}
.msel-row {
  display: flex;
  align-items: center;
  gap: 9px;
  width: 100%;
  border: none;
  background: none;
  border-radius: 7px;
  padding: 9px 10px;
  font: inherit;
  font-size: 13.5px;
  color: var(--text);
  text-align: left;
  cursor: pointer;
}
.msel-row:active { background: #f1f5f9; }
.msel-row .msel-row-label { flex: 1; min-width: 0; }
.msel-row .msel-n {
  font-size: 11px;
  font-weight: 700;
  color: #9ca3af;
  font-variant-numeric: tabular-nums;
  flex-shrink: 0;
}
.msel-box {
  width: 17px;
  height: 17px;
  border: 1.5px solid #cbd5e1;
  border-radius: 5px;
  flex-shrink: 0;
  position: relative;
}
.msel-row.on .msel-box { background: var(--navy); border-color: var(--navy); }
.msel-row.on .msel-box::after {
  content: "";
  position: absolute;
  left: 5px;
  top: 1px;
  width: 4px;
  height: 9px;
  border: solid #fff;
  border-width: 0 2px 2px 0;
  transform: rotate(45deg);
}
.msel-row.on .msel-row-label { font-weight: 650; }

.result-bar {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-bottom: 10px;
}
.result-count {
  font-size: 12.5px;
  color: var(--muted);
  font-variant-numeric: tabular-nums;
}
.filter-reset {
  margin-left: auto;
  border: none;
  background: none;
  font: inherit;
  font-size: 12.5px;
  font-weight: 600;
  color: var(--blue);
  padding: 4px;
  cursor: pointer;
}
.filter-reset[hidden] { display: none; }

/* Focus for these is handled by the consolidated block at the end of this
   file, which uses navy for contrast on light surfaces. */

/* Task cards (dashboard "Your tasks") */
.task-card { border-left: 3px solid var(--amber); }
.task-card .next {
  font-size: 13px;
  color: var(--text);
  margin: 8px 0 0;
}
.task-card .next b { font-weight: 650; }

/* ===== Timeline ===== */
.timeline { list-style: none; margin: 0; padding: 0; }
.timeline li { position: relative; padding: 0 0 22px 34px; }
.timeline li::before {
  content: "";
  position: absolute;
  left: 10px; top: 22px; bottom: -2px;
  width: 2px;
  background: var(--line);
}
.timeline li:last-child::before { display: none; }
.timeline .marker {
  position: absolute;
  left: 0; top: 2px;
  width: 22px; height: 22px;
  border-radius: 50%;
  background: #fff;
  border: 2px solid var(--line);
  display: flex; align-items: center; justify-content: center;
  font-size: 12px;
  color: #fff;
}
.timeline li.done .marker { background: var(--green); border-color: var(--green); }
.timeline li.current .marker {
  background: var(--amber); border-color: var(--amber);
  animation: pulse 1.6s infinite;
}
.timeline li.expired-step .marker { background: var(--red); border-color: var(--red); }
@keyframes pulse {
  0% { box-shadow: 0 0 0 0 rgba(252, 163, 17, 0.45); }
  70% { box-shadow: 0 0 0 9px rgba(252, 163, 17, 0); }
  100% { box-shadow: 0 0 0 0 rgba(252, 163, 17, 0); }
}
.timeline .t-label { font-weight: 650; font-size: 14px; }
.timeline li.pending-step .t-label { color: var(--muted); font-weight: 500; }
.timeline .t-by { font-size: 12px; color: var(--muted); }
.timeline .t-when { font-size: 12px; color: var(--green); font-weight: 550; }

/* ===== Buttons ===== */
.btn {
  display: block;
  width: 100%;
  border: none;
  border-radius: 10px;
  padding: 15px;
  font-size: 15px;
  font-weight: 650;
  cursor: pointer;
  text-align: center;
  text-decoration: none;
}
.btn.primary { background: var(--navy); color: #fff; }
.btn.primary:active { background: var(--navy-2); }
.btn.ghost { background: #fff; border: 1px solid var(--line); color: var(--text); }
.btn[disabled] { opacity: 0.45; cursor: not-allowed; }

.action-hint { font-size: 12px; color: var(--muted); text-align: center; margin: 8px 0 0; }
.outcome-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; margin-top: 10px; }
.outcome-grid .btn { padding: 12px 8px; font-size: 13px; }
.outcome-grid .btn.selected { background: var(--navy); color: #fff; box-shadow: inset 0 0 0 2px var(--amber); }

/* (The floating "+ New RFI" button was retired 2026-08-06 — creating an RFI
   is the DC's "New" tab in the bottom nav now.) */

/* ===== Photos ===== */
.photo-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 8px; }
.photo-grid .ph {
  position: relative;
  aspect-ratio: 1;
  border-radius: 10px;
  overflow: hidden;
  background: #e5e7eb;
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--muted);
  font-size: 12px;
  font-weight: 550;
}
.photo-grid .ph img { width: 100%; height: 100%; object-fit: cover; }
.photo-grid .ph .tag {
  position: absolute;
  bottom: 4px; left: 4px; right: 4px;
  font-size: 10px;
  font-weight: 700;
  text-align: center;
  border-radius: 6px;
  padding: 3px 4px;
}
.ph .tag.pending { background: rgba(252, 163, 17, 0.95); color: #14213d; }
.ph .tag.synced { background: rgba(21, 128, 61, 0.92); color: #fff; }
.photo-grid .add {
  border: 2px dashed #c4c9d0;
  background: #fafafa;
  color: var(--muted);
  cursor: pointer;
  font-size: 13px;
  font-weight: 600;
  text-align: center;
  line-height: 1.4;
}

/* ===== Checklist ===== */
.cl-group h4 {
  margin: 18px 0 8px;
  font-size: 12px;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--muted);
}
.cl-item {
  background: #fff;
  border: 1px solid var(--line);
  border-radius: 10px;
  padding: 10px 12px;
  margin-bottom: 8px;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 10px;
}
.cl-item .q { flex: 1; font-size: 14px; }
/* Numbered rows vs their indented variants, mirroring the paper FCL form */
.cl-item.cl-numbered { background: #f8fafc; border-color: #cbd5e1; }
.cl-item.cl-sub { margin-left: 16px; }
.cl-item .opts { display: flex; gap: 4px; }
.cl-item .opts button {
  border: 1px solid var(--line);
  background: #fafafa;
  border-radius: 8px;
  min-width: 44px;
  padding: 9px 6px;
  font-size: 12px;
  font-weight: 600;
  color: var(--muted);
  cursor: pointer;
}
.cl-item .opts button.sel-yes { background: var(--green); border-color: var(--green); color: #fff; }
.cl-item .opts button.sel-no { background: var(--red); border-color: var(--red); color: #fff; }
.cl-item .opts button.sel-na { background: #6b7280; border-color: #6b7280; color: #fff; }
/* Per-item remarks — its own full-width line below q + opts, not squeezed
   into the same row (2026-08-13). */
.cl-item .cl-remark { flex-basis: 100%; margin: 0; padding: 7px 10px; font-size: 12.5px; }

textarea, select, input[type="text"] {
  width: 100%;
  border: 1px solid var(--line);
  border-radius: 10px;
  padding: 12px;
  font-size: 15px;
  font-family: inherit;
  background: #fff;
}

/* ===== Signature pad (shared: sign-rfi + capture consultant sign-off) ===== */
.sig-wrap {
  background: #fff;
  border: 1px solid var(--line);
  border-radius: 10px;
  overflow: hidden;
}
.sig-wrap canvas {
  width: 100%;
  height: 180px;
  display: block;
  touch-action: none;
  cursor: crosshair;
}
.sig-hint {
  font-size: 12px;
  color: var(--muted);
  text-align: center;
  padding: 6px 0;
  border-top: 1px dashed var(--line);
}

/* ===== Minimal WYSIWYG editor (Information Required) ===== */
.wysiwyg-bar {
  display: flex;
  gap: 4px;
  border: 1px solid var(--line);
  border-bottom: none;
  border-radius: 10px 10px 0 0;
  background: #fafafa;
  padding: 6px;
}
.wysiwyg-bar button {
  border: 1px solid var(--line);
  background: #fff;
  border-radius: 6px;
  min-width: 34px;
  padding: 6px 8px;
  font-size: 13px;
  color: var(--text);
  cursor: pointer;
}
.wysiwyg-bar button:active { background: #eef2f7; }
.wysiwyg {
  min-height: 130px;
  background: #fff;
  border: 1px solid var(--line);
  border-radius: 0 0 10px 10px;
  padding: 12px;
  font-size: 15px;
  outline: none;
}
.wysiwyg:focus { border-color: #94a3b8; }
.wysiwyg:empty::before {
  content: attr(data-placeholder);
  color: #9ca3af;
}
.wysiwyg ul, .wysiwyg ol { margin: 6px 0; padding-left: 22px; }

/* ===== Bottom navigation ===== */
.bottom-nav {
  position: fixed;
  bottom: 0; left: 0; right: 0;
  background: rgba(255, 255, 255, 0.96);
  backdrop-filter: saturate(180%) blur(12px);
  -webkit-backdrop-filter: saturate(180%) blur(12px);
  border-top: 1px solid var(--line);
  display: flex;
  z-index: 40;
  padding-bottom: env(safe-area-inset-bottom);
}
.bottom-nav a {
  position: relative;
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 3px;
  padding: 8px 4px 7px;
  text-decoration: none;
  color: #94a3b8;
  font-size: 10.5px;
  font-weight: 600;
  letter-spacing: 0.01em;
  -webkit-tap-highlight-color: transparent;
  transition: color 0.15s;
}
.bottom-nav a svg {
  width: 22px; height: 22px;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.7;
  stroke-linecap: round;
  stroke-linejoin: round;
}
.bottom-nav a.active { color: var(--navy); }
.bottom-nav a.active svg { stroke-width: 2.1; }
.bottom-nav a:active { background: #f1f5f9; }
/* Pending-action count on the Home tab */
.bottom-nav .nav-badge {
  position: absolute;
  top: 4px;
  left: 50%;
  margin-left: 4px;
  min-width: 16px;
  height: 16px;
  border-radius: 999px;
  background: var(--red);
  color: #fff;
  font-size: 10px;
  font-weight: 700;
  line-height: 16px;
  text-align: center;
  padding: 0 4px;
}

/* ===== Dashboard ===== */
.dash-greet {
  padding: 4px 0 14px;
}
.dash-greet h2 {
  margin: 0;
  font-size: 22px;
  font-weight: 700;
  letter-spacing: -0.015em;
}
.dash-greet p {
  margin: 3px 0 0;
  font-size: 13px;
  color: var(--muted);
}

.stat-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 10px;
  margin-bottom: 4px;
}
.stat {
  background: var(--card);
  border: 1px solid var(--line);
  border-radius: 14px;
  padding: 14px;
}
.stat .val {
  font-size: 28px;
  font-weight: 700;
  line-height: 1.05;
  letter-spacing: -0.02em;
}
.stat .lbl {
  margin-top: 4px;
  font-size: 12px;
  color: var(--muted);
  line-height: 1.35;
}
/* Tiles that link into rfis.html (2026-08-18). Rendered as <a>, so they
   need the tap + keyboard affordances a bare <div> never did. The .action
   rule has to come after the plain one and carry an extra class, or the
   navy tile would flash near-white on press. */
a.stat { display: block; text-decoration: none; color: inherit; -webkit-tap-highlight-color: transparent; }
a.stat:active { background: #f1f5f9; }

.stat.action { background: #14213d; border-color: #14213d; }
.stat.action .val { color: #fff; }
.stat.action .lbl { color: #b6c0d4; }
a.stat.action:active { background: var(--navy-2); }
.stat.warn .val { color: #b45309; }
.stat.danger .val { color: var(--red); }
.stat.ok .val { color: var(--green); }

/* Stalled-item widget (SOR oversight) */
.stall-row {
  display: flex;
  align-items: baseline;
  gap: 10px;
  padding: 9px 0;
  border-bottom: 1px solid var(--line);
  font-size: 13px;
}
.stall-row:last-child { border-bottom: none; }
.stall-row .ref { flex: 1; }
.stall-row .age { font-size: 12px; font-weight: 650; color: #b45309; white-space: nowrap; }
.stall-row .age.fresh { color: var(--muted); font-weight: 550; }

/* Pipeline breakdown (Consultant DC oversight) */
.pipe-row {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 7px 0;
  font-size: 13px;
}
.pipe-row .pipe-lbl { flex: 1; color: var(--muted); }
.pipe-row .pipe-bar {
  height: 6px;
  border-radius: 999px;
  background: var(--navy);
  min-width: 6px;
}
.pipe-row .pipe-n { width: 22px; text-align: right; font-weight: 650; }
/* Only the clickable variant (wTypeChart's rows) gets hover feedback —
   CDC's plain pipeline rows aren't links, so leaving them unstyled avoids
   implying they're clickable when they're not. */
a.pipe-row:hover { background: #f8fafc; border-radius: 8px; }

/* Simple column charts (SOR oversight) — shared by the 2-column Open/Closed
   chart and the 4-column aging chart, so gap/width work for both without a
   modifier class. */
.col-chart {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  justify-content: center;
  gap: 22px;
  padding: 8px 0 2px;
}
.col-chart-item { display: flex; flex-direction: column; align-items: center; gap: 6px; }
.col-chart-n { font-size: 13px; font-weight: 700; }
.col-chart-bar { width: 40px; border-radius: 8px 8px 3px 3px; transition: height 0.2s ease; }
.col-chart-bar.open { background: var(--blue); }
.col-chart-bar.closed { background: var(--green); }
/* Aging chart bars — calm (fresh) to urgent (stale), reusing the same
   tones already used elsewhere for warn/danger rather than inventing new
   colours. */
.col-chart-bar.age0, .legend-dot.age0 { background: var(--green); }
.col-chart-bar.age1, .legend-dot.age1 { background: var(--blue); }
.col-chart-bar.age2, .legend-dot.age2 { background: #b45309; }
.col-chart-bar.age3, .legend-dot.age3 { background: var(--red); }
a.col-chart-item:hover .col-chart-bar { opacity: 0.85; }
.col-chart-lbl { font-size: 12px; color: var(--muted); }

/* Chart legend — colour swatch + label, explains what a chart's colours
   mean (the aging chart's ramp is urgency, not just category, so the
   per-bar day-range labels alone don't say that). */
.chart-legend {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 4px 14px;
  margin-top: 10px;
  font-size: 11.5px;
  color: var(--muted);
}
.chart-legend .legend-item { display: flex; align-items: center; gap: 5px; }
.legend-dot { width: 9px; height: 9px; border-radius: 50%; flex-shrink: 0; }

/* Side-by-side widget pairs (e.g. SOR's status + type charts) — wraps to
   stacked automatically once a column would drop below ~260px, so it
   degrades gracefully on narrow phones instead of squeezing. `align-items:
   stretch` (the flex default) only makes .widget-col itself match the
   row's height — its .card child is a normal block box and won't grow to
   fill that on its own, which is what left a gap under the shorter chart.
   Making .widget-col a flex column and growing its .card closes it.
   Growing the card only moves the gap inside it, though: the shorter
   chart then sits against the card's top edge with all the slack pooled
   underneath. Centring the grown card's own content puts the chart in the
   middle of the space it was given. The taller card in the pair defines
   the row height, so its content exactly fills and centring is a no-op
   there. */
.widget-row { display: flex; flex-wrap: wrap; gap: 12px; align-items: stretch; }
.widget-row .widget-col { flex: 1 1 260px; min-width: 0; display: flex; flex-direction: column; }
.widget-row .widget-col .card {
  flex: 1;
  display: flex;
  flex-direction: column;
  justify-content: center;
}

.dash-empty {
  text-align: center;
  color: var(--muted);
  font-size: 13.5px;
  padding: 22px 12px;
  line-height: 1.5;
}

/* ===== Account page ===== */
.acct-head {
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 6px 0 18px;
}
.acct-head .avatar {
  width: 52px; height: 52px;
  border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  font-size: 15px; font-weight: 800;
  color: #14213d;
  flex-shrink: 0;
}
.acct-head b { display: block; font-size: 17px; }
.acct-head span { font-size: 13px; color: var(--muted); }

.acct-list {
  background: var(--card);
  border: 1px solid var(--line);
  border-radius: 14px;
  overflow: hidden;
}
.acct-list a, .acct-list button {
  display: flex;
  align-items: center;
  gap: 10px;
  width: 100%;
  background: none;
  border: none;
  border-bottom: 1px solid var(--line);
  padding: 14px 16px;
  font: inherit;
  font-size: 14.5px;
  color: var(--text);
  text-align: left;
  text-decoration: none;
  cursor: pointer;
}
.acct-list > *:last-child { border-bottom: none; }
.acct-list a:active, .acct-list button:active { background: #f8fafc; }
.acct-list .chev { margin-left: auto; color: #cbd5e1; font-size: 17px; }
.acct-list .state { margin-left: auto; font-size: 12.5px; color: var(--muted); }
.acct-list .danger { color: var(--red); }

/* ===== Searchable picker =====
   A plain <select> is unusable for 148 checklist templates on a phone, so the
   field opens a slide-up sheet with a search box and a filtered list. */
.combo-field {
  display: flex;
  align-items: center;
  gap: 10px;
  width: 100%;
  background: #fff;
  border: 1px solid var(--line);
  border-radius: 10px;
  padding: 12px;
  font: inherit;
  font-size: 15px;
  color: var(--text);
  text-align: left;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}
.combo-field:active { background: #f8fafc; }
.combo-field .combo-val { flex: 1; min-width: 0; }
.combo-field .combo-ref { font-weight: 650; }
.combo-field .combo-hint {
  display: block;
  font-size: 12px;
  color: var(--muted);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  margin-top: 2px;
}
.combo-field .combo-caret { color: #94a3b8; font-size: 12px; flex-shrink: 0; }
.combo-field.placeholder .combo-ref { color: #9ca3af; font-weight: 500; }

.picker-overlay {
  position: fixed;
  inset: 0;
  background: rgba(17, 24, 39, 0.45);
  z-index: 56;
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.2s;
}
.picker-overlay.show { opacity: 1; pointer-events: auto; }

.picker-sheet {
  position: fixed;
  bottom: 0; left: 0; right: 0;
  background: #fff;
  border-radius: 16px 16px 0 0;
  box-shadow: 0 -8px 30px rgba(17, 24, 39, 0.28);
  z-index: 58;
  display: flex;
  flex-direction: column;
  max-height: 82vh;
  transform: translateY(100%);
  transition: transform 0.24s ease;
  padding-bottom: env(safe-area-inset-bottom);
}
.picker-sheet.open { transform: translateY(0); }

.picker-head {
  padding: 12px 14px 10px;
  border-bottom: 1px solid var(--line);
  flex-shrink: 0;
}
.picker-head .picker-title {
  display: flex;
  align-items: center;
  gap: 10px;
  margin: 0 0 10px;
}
.picker-head .picker-title b { flex: 1; font-size: 15px; }
.picker-head .picker-title button {
  border: none;
  background: none;
  color: var(--blue);
  font: inherit;
  font-size: 14px;
  font-weight: 600;
  cursor: pointer;
  padding: 2px 4px;
}
.picker-search {
  width: 100%;
  border: 1px solid var(--line);
  border-radius: 10px;
  padding: 11px 12px;
  font: inherit;
  font-size: 15px;
  background: #f8fafc;
  outline: none;
  -webkit-appearance: none;
}
.picker-search:focus { border-color: #94a3b8; background: #fff; }
.picker-count { font-size: 11.5px; color: var(--muted); margin: 8px 2px 0; }

.picker-list {
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  padding: 6px 0 10px;
}
.picker-row {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  width: 100%;
  background: none;
  border: none;
  border-bottom: 1px solid #f1f5f9;
  padding: 11px 14px;
  font: inherit;
  text-align: left;
  cursor: pointer;
}
.picker-row:active { background: #f1f5f9; }
.picker-row .p-ref {
  flex-shrink: 0;
  min-width: 62px;
  font-size: 12px;
  font-weight: 700;
  color: var(--navy);
  padding-top: 1px;
}
.picker-row .p-hint { flex: 1; font-size: 13.5px; line-height: 1.35; }
.picker-row .p-tick { color: var(--green); font-weight: 700; flex-shrink: 0; }
.picker-row.sel { background: #f0f9ff; }
.picker-row mark { background: #fef08a; color: inherit; border-radius: 2px; padding: 0 1px; }
.picker-empty { text-align: center; color: var(--muted); font-size: 13.5px; padding: 26px 14px; }

/* ===== Queue panel (slide-up, opened from the header sync pill) =====
   .q-item and friends are also reused by attachment lists (new-rfi.html,
   verify-evidence.html), not just the sync queue. */

.queue-panel {
  position: fixed;
  bottom: 0; left: 0; right: 0;
  background: #fff;
  border-radius: 16px 16px 0 0;
  box-shadow: 0 -8px 30px rgba(17, 24, 39, 0.25);
  z-index: 50;
  max-height: 70vh;
  overflow-y: auto;
  padding: 18px 16px;
  transform: translateY(100%);
  transition: transform 0.25s ease;
}
.queue-panel.open { transform: translateY(0); }
.queue-panel h3 { margin: 0 0 4px; font-size: 16px; }
.queue-panel .hint { font-size: 12px; color: var(--muted); margin: 0 0 14px; }
.q-item {
  display: flex;
  align-items: center;
  gap: 10px;
  border: 1px solid var(--line);
  border-radius: 10px;
  padding: 10px 12px;
  margin-bottom: 8px;
  font-size: 13px;
}
.q-item .q-type {
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.04em;
  color: var(--muted);
  background: #f3f4f6;
  border-radius: 6px;
  padding: 4px 7px;
  flex-shrink: 0;
}
.q-item .q-main { flex: 1; min-width: 0; }
.q-item .q-title { font-weight: 600; }
.q-item .q-sub { color: var(--muted); font-size: 11px; }
.q-item .q-state { font-size: 11px; font-weight: 700; }
.q-item.pending .q-state { color: #b45309; }
.q-item.syncing .q-state { color: var(--blue); }
.q-item.synced { opacity: 0.55; }
.q-item.synced .q-state { color: var(--green); }

.overlay {
  position: fixed;
  inset: 0;
  background: rgba(17, 24, 39, 0.4);
  z-index: 45;
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.25s;
}
.overlay.show { opacity: 1; pointer-events: auto; }

/* Toast */
.toast {
  position: fixed;
  left: 50%;
  bottom: calc(78px + env(safe-area-inset-bottom));
  transform: translateX(-50%) translateY(20px);
  background: var(--navy);
  color: #fff;
  padding: 12px 18px;
  border-radius: 10px;
  font-size: 14px;
  font-weight: 550;
  z-index: 60;
  opacity: 0;
  transition: all 0.3s;
  max-width: 90vw;
}
.toast.show { opacity: 1; transform: translateX(-50%) translateY(0); }

.section-title {
  font-size: 12px;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--muted);
  margin: 22px 0 10px;
  font-weight: 700;
}
.empty {
  text-align: center;
  color: var(--muted);
  padding: 30px 10px;
  font-size: 14px;
}

/* ==========================================================================
   Quality floor + responsive layout (2026-08-19)
   ========================================================================== */

:root {
  /* Focus ring colours. Amber is the palette accent and was the obvious
     pick, but #fca311 on white measures roughly 2:1 — under the 3:1 a focus
     indicator needs to be seen. Navy on light surfaces, amber reserved for
     the navy ones (primary button, action tile, active nav). */
  --focus: #14213d;
  --focus-on-navy: #fca311;
}

/* ---- Keyboard focus -----------------------------------------------------
   Every interactive element, in one place. Before this only the filter
   controls added in the same week had a visible focus state; buttons, RFI
   cards, the bottom nav and the checklist Yes/No/NA rows had none at all,
   so a keyboard user could not tell where they were. */
.btn:focus-visible,
a.card:focus-visible,
a.stat:focus-visible,
.bottom-nav a:focus-visible,
.app-header .back:focus-visible,
.sync-pill:focus-visible,
.cl-item .opts button:focus-visible,
.combo-field:focus-visible,
.picker-row:focus-visible,
.picker-head .picker-title button:focus-visible,
.acct-list a:focus-visible,
.acct-list button:focus-visible,
.wysiwyg-bar button:focus-visible,
.photo-grid .add:focus-visible,
a.pipe-row:focus-visible,
a.col-chart-item:focus-visible,
.seg-btn:focus-visible,
.msel-btn:focus-visible,
.msel-row:focus-visible,
.msel-all:focus-visible,
.filter-reset:focus-visible,
.list-search .q-clear:focus-visible {
  outline: 2px solid var(--focus);
  outline-offset: 2px;
}

/* On navy grounds the navy ring is invisible — switch to amber there. */
.btn.primary:focus-visible,
a.stat.action:focus-visible,
.bottom-nav a.active:focus-visible,
.msel-row.on:focus-visible,
.cl-item .opts button.sel-yes:focus-visible,
.cl-item .opts button.sel-no:focus-visible,
.cl-item .opts button.sel-na:focus-visible {
  outline-color: var(--focus-on-navy);
}

/* Text inputs. .picker-search and .wysiwyg actively set outline:none, so
   the ring has to be put back rather than merely added. */
textarea:focus-visible,
select:focus-visible,
input[type="text"]:focus-visible,
input[type="date"]:focus-visible,
input[type="time"]:focus-visible,
input[type="number"]:focus-visible,
.picker-search:focus-visible,
.list-search input:focus-visible,
.wysiwyg:focus-visible {
  outline: 2px solid var(--focus);
  outline-offset: 1px;
}

/* ---- Touch targets ------------------------------------------------------
   Anything tapped on site, often in gloves, needs ~44px. These were the
   ones measuring under. */
.app-header .back { min-width: 44px; min-height: 44px; display: flex; align-items: center; }
.bottom-nav a { min-height: 52px; }
.cl-item .opts button { min-height: 44px; }
.picker-row { min-height: 48px; }
.picker-head .picker-title button { min-height: 44px; padding: 10px 8px; }
.list-search .q-clear { min-width: 44px; min-height: 44px; display: none; align-items: center; justify-content: center; }
.list-search.has-q .q-clear { display: flex; }
.filter-reset { min-height: 44px; padding: 4px 8px; }
.msel-row { min-height: 44px; }
.seg-btn { min-height: 44px; }
.sync-pill { min-height: 40px; }

/* ---- Reduced motion -----------------------------------------------------
   The timeline's current-step marker pulses and the offline pill blinks.
   Both also carry their meaning in colour alone, so stopping the animation
   loses nothing. */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
}

/* ---- Tablet -------------------------------------------------------------
   Until now the only layout rule in the stylesheet was max-width: 720px, so
   a tablet rendered the phone layout stranded in dead space. From 768px up
   there is room to stop stacking everything. */
@media (min-width: 768px) {
  main { max-width: 960px; padding: 22px 24px; }

  /* Four tiles across instead of 2x2 — the whole readout in one glance. */
  .stat-grid { grid-template-columns: repeat(4, 1fr); gap: 12px; }

  /* The RFI list is the page people scan longest; two columns roughly
     halves the scrolling. align-items:start stops a tall card stretching
     its neighbour. */
  #list {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 12px;
    align-items: start;
  }
  #list .card { margin-bottom: 0; }
  /* "No RFIs match these filters" is one message, not a column of one. */
  #list .empty { grid-column: 1 / -1; }

  /* Filter controls shouldn't stretch the full 960px — they look adrift. */
  .list-search, .seg, .filter-row { max-width: 560px; }

  .photo-grid { grid-template-columns: repeat(5, 1fr); }
}

/* ---- Wide tablet / desktop --------------------------------------------- */
@media (min-width: 1100px) {
  main { max-width: 1080px; }
  #list { grid-template-columns: repeat(3, 1fr); }
  .photo-grid { grid-template-columns: repeat(6, 1fr); }
}

/* ===== Superadmin — permissions grid (admin-permissions.html) =====
   A desk action, not a site one (see rfi-api.js's grantPermission comment)
   — the one screen in this app that assumes a wider view and doesn't try
   to be thumb-friendly first. Wrapped in .perm-scroll so a narrow phone
   still works via horizontal scroll rather than an unreadable squeeze. */
.perm-scroll { overflow-x: auto; border: 1px solid var(--line); border-radius: 12px; background: var(--card); }
.perm-grid { border-collapse: collapse; width: 100%; min-width: 720px; font-size: 13px; }
.perm-grid th, .perm-grid td { padding: 10px 12px; border-bottom: 1px solid var(--line); text-align: center; }
.perm-grid td:first-child, .perm-grid th:first-child {
  text-align: left; position: sticky; left: 0; background: var(--card);
  font-weight: 600; white-space: nowrap;
}
.perm-grid thead th {
  font-size: 11px; text-transform: uppercase; letter-spacing: 0.03em; color: var(--muted);
  font-weight: 700; vertical-align: bottom; white-space: normal; max-width: 110px;
}
.perm-grid tbody tr:last-child td { border-bottom: none; }
.perm-grid input[type="checkbox"] { width: 20px; height: 20px; accent-color: var(--navy); cursor: pointer; }
.perm-grid input[type="checkbox"]:disabled { opacity: 0.4; cursor: default; }
.perm-cell.busy { opacity: 0.5; }
.perm-role-org { display: block; font-weight: 400; font-size: 11px; color: var(--muted); }

/* Editable-field variant of the same admin grid (admin-categories.html) —
   each cell holds a real input rather than a checkbox, still auto-saving
   on change, same as the permissions grid. */
.perm-grid input[type="text"], .perm-grid input[type="number"] {
  width: 100%; min-width: 70px; border: 1px solid var(--line); border-radius: 6px;
  padding: 6px 8px; font-size: 13px; font-family: inherit; background: #fff;
}
.perm-grid input[type="number"] { text-align: right; }
.perm-grid td.perm-cell.field { text-align: left; }
.perm-grid input:disabled { opacity: 0.5; background: #f3f4f6; }
