/*
 * fm-design-system.css
 *
 * Finance Mentor design system, patch 20260515.25.
 *
 * Loaded AFTER every other stylesheet so cascade overrides legacy class
 * styling without view markup changes. New utility classes coexist with
 * legacy `.panel*` / `.gridview` etc; the override layer re-skins those
 * legacy selectors to match the new palette.
 *
 * See Claude work files/DESIGN_PROPOSAL.md for the rationale + audit.
 */

/* ============================================================ */
/* Design tokens                                                */
/* ============================================================ */

:root {
  /* Brand navy ramp */
  --fm-navy-900: #0B2447;
  --fm-navy-700: #19376D;
  --fm-navy-500: #2F5BB7;
  --fm-navy-100: #E6EDF7;

  /* Bronze accent (CTA, active markers, replaces #ca6702 family) */
  --fm-accent-700: #9C5A11;
  --fm-accent-500: #BE6F1A;
  --fm-accent-100: #FBEFDD;

  /* Semantic status colors */
  --fm-success:    #1E7A4D;   --fm-success-bg: #E6F4EC;
  --fm-warning:    #B7791F;   --fm-warning-bg: #FCF1DC;
  --fm-danger:     #B42318;   --fm-danger-bg:  #FBEAEA;
  --fm-info:       #155EEF;   --fm-info-bg:    #E7EFFE;

  /* Neutrals (replaces ~22 ad-hoc greys) */
  --fm-gray-50:  #F8F9FB;
  --fm-gray-100: #F1F3F6;
  --fm-gray-200: #E3E7EC;
  --fm-gray-300: #C8CFD7;
  --fm-gray-500: #8B95A1;
  --fm-gray-700: #4A5460;
  --fm-gray-900: #1B2230;
  --fm-white:    #FFFFFF;

  /* Typography */
  --fm-font: 'Inter', system-ui, -apple-system, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
  --fm-font-mono: ui-monospace, 'SF Mono', Consolas, 'Liberation Mono', monospace;

  --fm-text-xs:   12px;
  --fm-text-sm:   13px;
  --fm-text-base: 14px;
  --fm-text-md:   16px;
  --fm-text-lg:   18px;
  --fm-text-xl:   22px;
  --fm-text-2xl:  28px;
  --fm-text-3xl:  34px;

  --fm-weight-normal:   400;
  --fm-weight-medium:   500;
  --fm-weight-semibold: 600;
  --fm-weight-bold:     700;
  --fm-leading-tight: 1.25;
  --fm-leading-base:  1.5;

  /* Spacing scale (4px base) */
  --fm-space-1:  4px;
  --fm-space-2:  8px;
  --fm-space-3: 12px;
  --fm-space-4: 16px;
  --fm-space-5: 20px;
  --fm-space-6: 24px;
  --fm-space-8: 32px;
  --fm-space-10: 40px;
  --fm-space-12: 48px;

  /* Radii + shadows */
  --fm-radius-sm: 4px;
  --fm-radius-md: 6px;
  --fm-radius-lg: 10px;
  --fm-shadow-sm: 0 1px 2px rgba(11, 36, 71, 0.06);
  --fm-shadow-md: 0 4px 12px rgba(11, 36, 71, 0.10);
}

/* ============================================================ */
/* Element resets (re-skin legacy WebForms markup)              */
/* ============================================================ */

body {
  font-family: var(--fm-font);
  font-size: var(--fm-text-base);
  color: var(--fm-gray-900);
  background: var(--fm-gray-50);
  line-height: var(--fm-leading-base);
}

h1, h2, h3, h4, h5, h6 {
  font-family: var(--fm-font);
  color: var(--fm-navy-900);
  font-weight: var(--fm-weight-semibold);
  line-height: var(--fm-leading-tight);
}
h1 { font-size: var(--fm-text-3xl); }
h2 { font-size: var(--fm-text-2xl); }
h3 { font-size: var(--fm-text-xl); }
h4 { font-size: var(--fm-text-lg); }
h5 { font-size: var(--fm-text-md); }
h6 { font-size: var(--fm-text-base); }

a {
  color: var(--fm-navy-700);
  text-decoration: none;
}
a:hover { color: var(--fm-navy-900); text-decoration: underline; }
a:focus-visible {
  outline: 2px solid var(--fm-navy-500);
  outline-offset: 2px;
  border-radius: var(--fm-radius-sm);
}

/* Patch 20260706.93 — WCAG 2.4.1 Bypass Blocks / RFP 5.6 keyboard nav: skip-to-content
   link. Off-screen until it receives keyboard focus, then slides into the top-left.
   No visual change for mouse users. */
.fm-skip-link {
  position: absolute;
  left: 8px;
  top: -60px;
  z-index: 2000;
  background: var(--fm-navy-700);
  color: var(--fm-white);
  padding: 10px 16px;
  border-radius: var(--fm-radius-md);
  font-weight: var(--fm-weight-semibold);
  text-decoration: none;
  transition: top 120ms ease;
}
.fm-skip-link:focus {
  top: 8px;
  outline: 2px solid var(--fm-navy-500);
  outline-offset: 2px;
}

/* Patch 20260706.95 - Standardized keyboard focus indicator (Wayne 2026-07-10):
   ONE consistent 211-red outline on every :focus-visible element, replacing the
   prior mix (navy outlines, header background-swaps, field box-shadow, sortable
   accent). Keyboard-only (:focus-visible) - mouse users see no change. */
:focus-visible {
  outline: 2px solid #C8102E !important;
  outline-offset: 3px !important;
}
input:focus-visible,
select:focus-visible,
textarea:focus-visible {
  box-shadow: none !important;
}
#fm-main-content:focus-visible {
  outline: none !important;
}

/* Patch 20260706.102 - visually-hidden utility (screen-reader-only). Backs the
   per-page <h1> that gives a document outline (WCAG 1.3.1 / 2.4.6) without any
   visual change. */
.sr-only {
  position: absolute !important;
  width: 1px !important;
  height: 1px !important;
  padding: 0 !important;
  margin: -1px !important;
  overflow: hidden !important;
  clip: rect(0, 0, 0, 0) !important;
  white-space: nowrap !important;
  border: 0 !important;
}

/* Patch 20260706.96 - keep the focus ring INSET on table-header controls (sortable
   headers + the header export icon) so the red box is not clipped by the dark table
   header / rounded widget edge (Logged In Today, Recent Calls, etc.). */
.fm-th-sortable:focus-visible,
.fm-th-with-export .fm-table-export:focus-visible {
  outline-offset: -2px !important;
}

input[type="text"],
input[type="password"],
input[type="email"],
input[type="tel"],
input[type="number"],
input[type="date"],
input[type="search"],
input[type="url"],
select,
textarea {
  font-family: var(--fm-font);
  font-size: var(--fm-text-md);
  color: var(--fm-gray-900);
  background: var(--fm-white);
  border: 1px solid var(--fm-gray-300);
  border-radius: var(--fm-radius-md);
  padding: 10px 12px;
  box-sizing: border-box;
  transition: border-color 120ms ease, box-shadow 120ms ease;
}

/* Uniform field height across the whole app (Wayne 2026-07-02): every standard text field and
   single-select is 43px tall so field sizes don't drift page to page. Textareas (multi-line) and
   multi-select / Choices widgets are intentionally excluded. */
input[type="text"],
input[type="password"],
input[type="email"],
input[type="tel"],
input[type="number"],
input[type="date"],
input[type="search"],
input[type="url"],
select:not([multiple]) {
  height: 43px;
}
.choices__input { height: auto; }

input[type="text"]:focus,
input[type="password"]:focus,
input[type="email"]:focus,
input[type="tel"]:focus,
input[type="number"]:focus,
input[type="date"]:focus,
input[type="search"]:focus,
input[type="url"]:focus,
select:focus,
textarea:focus {
  outline: none;
  border-color: var(--fm-navy-500);
  box-shadow: 0 0 0 3px rgba(47, 91, 183, 0.18);
}

input[type="submit"],
input[type="button"],
button {
  font-family: var(--fm-font);
  font-size: var(--fm-text-sm);
  font-weight: var(--fm-weight-semibold);
  letter-spacing: 0.02em;
  background: var(--fm-navy-700);
  color: var(--fm-white);
  border: 1px solid var(--fm-navy-700);
  padding: 10px 18px;
  border-radius: var(--fm-radius-md);
  cursor: pointer;
  transition: background 120ms ease, border-color 120ms ease;
  text-transform: none;
}
input[type="submit"]:hover,
input[type="button"]:hover,
button:hover {
  background: var(--fm-navy-900);
  border-color: var(--fm-navy-900);
}
input[type="submit"]:focus-visible,
input[type="button"]:focus-visible,
button:focus-visible {
  outline: 2px solid var(--fm-navy-500);
  outline-offset: 2px;
}

table {
  border-collapse: collapse;
  width: 100%;
  font-size: var(--fm-text-base);
}

/* ============================================================ */
/* Legacy class overrides (cascade winners)                     */
/* ============================================================ */

/* Panel family — collapse all variants to one card style */
.panel1, .panel1b, .panel2, .panel3, .panel4, .panel_home, .cc_card, .griditem {
  background: var(--fm-white);
  border: 1px solid var(--fm-gray-200);
  border-radius: var(--fm-radius-lg);
  padding: var(--fm-space-5) var(--fm-space-6);
  box-shadow: var(--fm-shadow-sm);
  margin-bottom: var(--fm-space-4);
  box-sizing: border-box;
  max-width: none;
}

/* GridView tables — match new fm-table treatment */
.gridview, table.gridview {
  background: var(--fm-white);
  border: 1px solid var(--fm-gray-200);
  border-radius: var(--fm-radius-md);
  overflow: hidden;
}
.gridview > thead th,
.gridview > tbody > tr:first-child > td[style*="background-color:#0B2447"],
.gridview > tbody > tr:first-child > th {
  background: var(--fm-navy-900) !important;
  color: var(--fm-white) !important;
  font-size: var(--fm-text-xs);
  font-weight: var(--fm-weight-semibold);
  letter-spacing: 0.05em;
  text-transform: uppercase;
  padding: 10px 12px;
  text-align: left;
}
.gridview td {
  padding: 10px 12px;
  font-size: var(--fm-text-base);
  color: var(--fm-gray-900);
  border-top: 1px solid var(--fm-gray-200);
}
.gridview tbody tr:nth-child(even) td { background: var(--fm-gray-50); }
.gridview tbody tr:hover td { background: var(--fm-navy-100); }

/* Catch-all for inline navy-row headers used in 20+ files */
tr[style*="background-color:#0B2447"] > td,
tr[style*="background-color:#0B2447"] > th {
  background: var(--fm-navy-900) !important;
  color: var(--fm-white) !important;
  font-size: var(--fm-text-xs);
  font-weight: var(--fm-weight-semibold);
  letter-spacing: 0.05em;
  text-transform: uppercase;
}

/* Legacy button classes — re-skin to match new variants */
.cc_button, .cc_button2 {
  background: var(--fm-navy-700);
  color: var(--fm-white);
  border: 1px solid var(--fm-navy-700);
  padding: 10px 18px;
  border-radius: var(--fm-radius-md);
  font-weight: var(--fm-weight-semibold);
  text-transform: none;
}
.cc_button:hover, .cc_button2:hover {
  background: var(--fm-navy-900);
  border-color: var(--fm-navy-900);
}

.outlinebutton, .outlinebutton2, .outlinebutton3 {
  background: var(--fm-white);
  color: var(--fm-navy-700);
  border: 1px solid var(--fm-gray-300);
  padding: 10px 18px;
  border-radius: var(--fm-radius-md);
  font-weight: var(--fm-weight-semibold);
}
.outlinebutton:hover, .outlinebutton2:hover, .outlinebutton3:hover {
  background: var(--fm-gray-100);
  border-color: var(--fm-navy-500);
  color: var(--fm-navy-900);
}

.call2action {
  background: var(--fm-accent-500);
  color: var(--fm-white);
  border: 1px solid var(--fm-accent-500);
  text-transform: uppercase;
  letter-spacing: 0.05em;
  font-weight: var(--fm-weight-semibold);
  padding: 12px 24px;
  border-radius: var(--fm-radius-md);
}
.call2action:hover {
  background: var(--fm-accent-700);
  border-color: var(--fm-accent-700);
  text-decoration: none;
  color: var(--fm-white);
}

.signin-button, .btn, .sso-btn {
  background: var(--fm-navy-700);
  color: var(--fm-white);
  border: 1px solid var(--fm-navy-700);
  padding: 10px 18px;
  border-radius: var(--fm-radius-md);
  font-weight: var(--fm-weight-semibold);
}
.signin-button:hover, .btn:hover, .sso-btn:hover {
  background: var(--fm-navy-900);
  border-color: var(--fm-navy-900);
  color: var(--fm-white);
}

/* Tab-button used on Client/ClientEdit */
.tab-button {
  background: transparent !important;
  color: var(--fm-gray-700) !important;
  border: 0 !important;
  border-bottom: 3px solid transparent !important;
  padding: 10px 16px !important;
  border-radius: 0 !important;
  font-weight: var(--fm-weight-medium) !important;
  font-size: var(--fm-text-base) !important;
}
.tab-button:hover { color: var(--fm-navy-900) !important; }
.tab-button.selectedButton {
  color: var(--fm-navy-900) !important;
  font-weight: var(--fm-weight-semibold) !important;
  border-bottom-color: var(--fm-accent-500) !important;
}

/* User box dropdown in the header */
.user_box.dropdown { color: var(--fm-white); }
.monogram {
  background: var(--fm-navy-500);
  color: var(--fm-white);
  border: 2px solid rgba(255, 255, 255, 0.3);
  border-radius: 50%;
  width: 36px;
  height: 36px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-weight: var(--fm-weight-semibold);
  font-size: var(--fm-text-sm);
}
.dropdown-content {
  background: var(--fm-white);
  border: 1px solid var(--fm-gray-200);
  border-radius: var(--fm-radius-md);
  box-shadow: var(--fm-shadow-md);
}
.dropdown-content a {
  color: var(--fm-gray-900);
  padding: 10px 14px;
  display: block;
  font-size: var(--fm-text-base);
}
.dropdown-content a:hover {
  background: var(--fm-gray-50);
  color: var(--fm-navy-900);
  text-decoration: none;
}

/* Title helpers used across legacy pages */
.title, .title2, .title3, .title4, .title5, .title6, .title7 {
  color: var(--fm-navy-900);
  font-family: var(--fm-font);
}
.title3 { font-weight: var(--fm-weight-semibold); font-size: var(--fm-text-lg); }

/* Validation messages */
.validation-summary-errors,
.field-validation-error {
  color: var(--fm-danger);
  background: var(--fm-danger-bg);
  border: 1px solid var(--fm-danger);
  border-radius: var(--fm-radius-md);
  padding: var(--fm-space-2) var(--fm-space-3);
  font-size: var(--fm-text-sm);
}

/* "Back to Home Page" / similar back-links (legacy pattern) */
a[style*="font-weight:bold"][style*="#0B2447"] {
  color: var(--fm-navy-700) !important;
  text-decoration: none !important;
  font-weight: var(--fm-weight-medium) !important;
}
a[style*="font-weight:bold"][style*="#0B2447"]:hover {
  color: var(--fm-navy-900) !important;
  text-decoration: underline !important;
}

/* ============================================================ */
/* New utility classes (use on new views; opt-in)              */
/* ============================================================ */

.fm-card {
  background: var(--fm-white);
  border: 1px solid var(--fm-gray-200);
  border-radius: var(--fm-radius-lg);
  padding: var(--fm-space-5) var(--fm-space-6);
  box-shadow: var(--fm-shadow-sm);
}

/* 20260808.298 - STAT TILES. Added to the design system rather than to
   the page that needed them (PTI-RULE-15), and built only from tokens
   that already existed: --fm-text-2xl was already the eighth step of the
   ladder, and the warning and danger colours were already defined. No
   new hex, no new size, no new weight enters the system here.

   Named fm-stat- rather than dash- because .dash-card belongs to the
   staff home dashboard's fixed-height grid, which carries the
   FM-DIFF-45 box-sizing hazard. These tiles size to their content and
   have no fixed height, so they cannot reproduce it. */
.fm-stat-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  gap: var(--fm-space-3);
  margin: var(--fm-space-4) 0 var(--fm-space-6);
}

.fm-stat {
  background: var(--fm-white);
  border: 1px solid var(--fm-gray-200);
  border-radius: var(--fm-radius-lg);
  padding: var(--fm-space-4) var(--fm-space-5);
  box-shadow: var(--fm-shadow-sm);
  box-sizing: border-box;
}

.fm-stat-label {
  font-size: var(--fm-text-sm);
  color: var(--fm-gray-700);
  margin-bottom: var(--fm-space-2);
}

.fm-stat-value {
  font-size: var(--fm-text-2xl);
  font-weight: var(--fm-weight-semibold);
  color: var(--fm-gray-900);
  line-height: var(--fm-leading-tight);
}

.fm-stat-sub {
  font-size: var(--fm-text-sm);
  color: var(--fm-gray-700);
  margin-top: var(--fm-space-2);
}

.fm-stat-links { list-style: none; margin: 0; padding: 0; }
.fm-stat-links li { margin-top: var(--fm-space-2); }

/* Tone is a border and the number, never a filled tile: a wash of colour
   behind a dashboard reads as an alarm even when the number is fine. */
.fm-stat-warning { border-color: var(--fm-warning); }
.fm-stat-warning .fm-stat-value { color: var(--fm-warning); }
.fm-stat-danger { border-color: var(--fm-danger); }
.fm-stat-danger .fm-stat-value { color: var(--fm-danger); }
/* 20260808.338 - a stat tile that navigates. Rendered as <a class="fm-stat">
   so the whole tile is the click target; inherits the tile chrome and
   keeps text colors, with a hover cue built from existing tokens only. */
a.fm-stat { display: block; text-decoration: none; color: inherit; cursor: pointer; }
a.fm-stat:hover, a.fm-stat:focus-visible { border-color: var(--fm-navy-900); }
a.fm-stat:hover .fm-stat-sub, a.fm-stat:focus-visible .fm-stat-sub { text-decoration: underline; }

.fm-table {
  width: 100%;
  border-collapse: separate;
  border-spacing: 0;
  background: var(--fm-white);
  border: 1px solid var(--fm-gray-200);
  border-radius: var(--fm-radius-md);
  overflow: hidden;
}
.fm-table thead th {
  background: var(--fm-navy-900);
  color: var(--fm-white);
  font-size: var(--fm-text-xs);
  font-weight: var(--fm-weight-semibold);
  letter-spacing: 0.05em;
  text-transform: uppercase;
  padding: 12px 14px;
  text-align: left;
}
.fm-table tbody td {
  padding: 12px 14px;
  font-size: var(--fm-text-base);
  color: var(--fm-gray-900);
  border-top: 1px solid var(--fm-gray-200);
}
.fm-table tbody tr:nth-child(even) td { background: var(--fm-gray-50); }
.fm-table tbody tr:hover td { background: var(--fm-navy-100); }

.btn-primary {
  background: var(--fm-navy-700);
  color: var(--fm-white);
  border: 1px solid var(--fm-navy-700);
  padding: 10px 18px;
  border-radius: var(--fm-radius-md);
  font-size: var(--fm-text-sm);
  font-weight: var(--fm-weight-semibold);
  letter-spacing: 0.02em;
  cursor: pointer;
  text-decoration: none;
  display: inline-flex;
  align-items: center;
  gap: 6px;
}
.btn-primary:hover {
  background: var(--fm-navy-900);
  border-color: var(--fm-navy-900);
  color: var(--fm-white);
  text-decoration: none;
}

.btn-secondary {
  background: var(--fm-white);
  color: var(--fm-navy-700);
  border: 1px solid var(--fm-gray-300);
  padding: 10px 18px;
  border-radius: var(--fm-radius-md);
  font-size: var(--fm-text-sm);
  font-weight: var(--fm-weight-semibold);
  cursor: pointer;
  text-decoration: none;
  display: inline-flex;
  align-items: center;
  gap: 6px;
}
.btn-secondary:hover {
  background: var(--fm-gray-100);
  border-color: var(--fm-navy-500);
  color: var(--fm-navy-900);
  text-decoration: none;
}

.btn-cta {
  background: var(--fm-navy-700);
  color: var(--fm-white);
  border: 1px solid var(--fm-navy-700);
  padding: 12px 24px;
  border-radius: var(--fm-radius-md);
  font-size: var(--fm-text-sm);
  font-weight: var(--fm-weight-semibold);
  letter-spacing: 0.05em;
  text-transform: uppercase;
  cursor: pointer;
  text-decoration: none;
  display: inline-flex;
  align-items: center;
  gap: 6px;
}
.btn-cta:hover {
  background: var(--fm-navy-900);
  border-color: var(--fm-navy-900);
  color: var(--fm-white);
  text-decoration: none;
}

.btn-danger {
  background: var(--fm-danger);
  color: var(--fm-white);
  border: 1px solid var(--fm-danger);
  padding: 10px 18px;
  border-radius: var(--fm-radius-md);
  font-size: var(--fm-text-sm);
  font-weight: var(--fm-weight-semibold);
  cursor: pointer;
  text-decoration: none;
}
.btn-danger:hover { background: #8B1A12; border-color: #8B1A12; color: var(--fm-white); }

.btn-icon {
  width: 32px;
  height: 32px;
  padding: 0;
  background: transparent;
  border: 1px solid var(--fm-gray-300);
  border-radius: var(--fm-radius-sm);
  color: var(--fm-gray-700);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
}
.btn-icon:hover {
  background: var(--fm-gray-100);
  color: var(--fm-navy-900);
  border-color: var(--fm-navy-500);
}

/* Status pills */
.fm-badge,
.fm-badge--success,
.fm-badge--warning,
.fm-badge--danger,
.fm-badge--info {
  display: inline-block;
  padding: 3px 10px;
  border-radius: 999px;
  font-size: var(--fm-text-xs);
  font-weight: var(--fm-weight-semibold);
  letter-spacing: 0.02em;
  line-height: 1.4;
}
.fm-badge--success { background: var(--fm-success-bg); color: var(--fm-success); }
.fm-badge--warning { background: var(--fm-warning-bg); color: var(--fm-warning); }
.fm-badge--danger  { background: var(--fm-danger-bg);  color: var(--fm-danger);  }
.fm-badge--info    { background: var(--fm-info-bg);    color: var(--fm-info);    }

/* Spacing utilities */
.fm-stack-1 > * + * { margin-top: var(--fm-space-1); }
.fm-stack-2 > * + * { margin-top: var(--fm-space-2); }
.fm-stack-3 > * + * { margin-top: var(--fm-space-3); }
.fm-stack-4 > * + * { margin-top: var(--fm-space-4); }
.fm-stack-5 > * + * { margin-top: var(--fm-space-5); }
.fm-stack-6 > * + * { margin-top: var(--fm-space-6); }
.fm-stack-8 > * + * { margin-top: var(--fm-space-8); }

/* Helpers */
.fm-muted { color: var(--fm-gray-700); }
.fm-eyebrow {
  font-size: var(--fm-text-xs);
  font-weight: var(--fm-weight-semibold);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--fm-gray-500);
}

/* ============================================================ */
/* Header + top-nav overrides (patch 20260515.26)               */
/*                                                              */
/* `.25`'s cascade overrides missed two things:                 */
/*   1. `.header` in CoachConnectMain.css:214 has a teal        */
/*      gradient (`linear-gradient(180deg, #0B2447, #09779A)`)  */
/*      that needs to become solid navy-900.                    */
/*   2. `.top-nav` styles live in an inline `<style>` block     */
/*      inside src/views/partials/_top-nav.ejs:181-196 — that   */
/*      inline `<style>` tag is later in the document than our  */
/*      external stylesheet, so same-specificity rules in it    */
/*      win. `!important` is required here because we can't     */
/*      change the load order without editing the partial.      */
/* ============================================================ */

.header {
  background: var(--fm-navy-900) !important;
  background-image: none !important;
  border-bottom: 1px solid rgba(255, 255, 255, 0.08);
}

.header_inner {
  /* Keep layout, just inherit the new background color above. */
  color: var(--fm-white);
}

.header_inner h1,
.header_inner h2,
.header_inner a,
.header_inner #BrandLogo + * {
  color: var(--fm-white) !important;
}

.top-nav {
  background: var(--fm-navy-700) !important;
  color: var(--fm-white) !important;
  border-top: 1px solid rgba(255, 255, 255, 0.10);
}

.top-nav-menu > li > a,
.top-nav-dropdown-toggle {
  color: var(--fm-white) !important;
  background: transparent !important;
  font-weight: var(--fm-weight-medium) !important;
  letter-spacing: 0.02em;
}

.top-nav-menu > li > a:hover,
.top-nav-dropdown-toggle:hover,
.top-nav-dropdown-toggle[aria-expanded="true"] {
  background: var(--fm-navy-500) !important;
  color: var(--fm-white) !important;
}

.top-nav-dropdown-menu {
  background: var(--fm-white) !important;
  border: 1px solid var(--fm-gray-200) !important;
  border-radius: var(--fm-radius-md) !important;
  box-shadow: var(--fm-shadow-md) !important;
  color: var(--fm-gray-900) !important;
}

.top-nav-dropdown-menu a {
  color: var(--fm-gray-900) !important;
  font-size: var(--fm-text-base) !important;
}

.top-nav-dropdown-menu a:hover {
  background: var(--fm-gray-50) !important;
  color: var(--fm-navy-900) !important;
}

/* 20260809.47 (owner request, hotfix of .46): legacy-app menu items
   render RED. The .46 rules lived only in the _top-nav partial's
   inline <style> and lost to the !important colors above — these
   equally-!important, more-specific rules (declared later) win.
   Hover keeps the red so the state stays visible. */
.top-nav-menu > li > a.top-nav-classic,
.top-nav-menu > li > a.top-nav-classic:hover {
  color: #FF8787 !important;
}
.top-nav-dropdown-menu a.top-nav-classic,
.top-nav-dropdown-menu a.top-nav-classic:hover {
  color: #C92A2A !important;
}

/* ============================================================ */
/* User box — full name + email + click-to-toggle dropdown      */
/* (patch 20260515.34 — replaces legacy hover-only positioning  */
/* that anchored to viewport because no ancestor was relative)  */
/* ============================================================ */

.user_box.dropdown {
  position: relative !important;       /* anchor for dropdown-content */
  display: inline-flex !important;
  align-items: center;
  gap: 10px;
  cursor: pointer;
  padding: 6px 12px 6px 8px;
  border-radius: var(--fm-radius-md);
  user-select: none;
  transition: background 120ms ease;
  border: 0 !important;                /* legacy border off */
}
.user_box.dropdown:hover,
.user_box.dropdown.is-open {
  background: rgba(255, 255, 255, 0.10);
}

.user_box .monogram {
  width: 36px;
  height: 36px;
  background: var(--fm-navy-500);
  color: var(--fm-white);
  border: 2px solid rgba(255, 255, 255, 0.3);
  border-radius: 50%;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-weight: var(--fm-weight-semibold);
  font-size: var(--fm-text-sm);
  flex: 0 0 auto;
}

.user_box__name {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  line-height: 1.15;
  min-width: 0;
}
.user_box__display-name {
  font-size: var(--fm-text-base);
  font-weight: var(--fm-weight-semibold);
  color: var(--fm-white);
  white-space: nowrap;
}
.user_box__email {
  font-size: 11px;
  font-weight: var(--fm-weight-normal);
  color: rgba(255, 255, 255, 0.70);
  margin-top: 2px;
  white-space: nowrap;
  letter-spacing: 0.01em;
}

.user_box__caret {
  display: inline-block;
  font-size: 10px;
  line-height: 1;
  color: rgba(255, 255, 255, 0.70);
  margin-left: 4px;
  transition: transform 120ms ease, color 120ms ease;
}
.user_box.dropdown.is-open .user_box__caret {
  transform: rotate(180deg);
  color: var(--fm-white);
}

.user_box .dropdown-content {
  display: none !important;            /* override legacy + show only when is-open */
  position: absolute !important;
  top: calc(100% + 6px) !important;
  right: 0 !important;
  left: auto !important;
  transform: none !important;
  min-width: 240px !important;
  width: auto !important;
  height: auto !important;
  background: var(--fm-white) !important;
  color: var(--fm-gray-900) !important;
  border: 1px solid var(--fm-gray-200) !important;
  border-radius: var(--fm-radius-md) !important;
  box-shadow: var(--fm-shadow-md) !important;
  padding: 6px 0 !important;
  z-index: 1500 !important;
  overflow: hidden;
}
.user_box.dropdown.is-open .dropdown-content {
  display: block !important;
}

.user_box .dropdown-content a {
  display: block !important;
  width: auto !important;
  padding: 10px 16px !important;
  font-size: var(--fm-text-base) !important;
  color: var(--fm-gray-900) !important;
  text-decoration: none !important;
  white-space: nowrap;
}
.user_box .dropdown-content a:hover {
  background: var(--fm-gray-50) !important;
  color: var(--fm-navy-900) !important;
}

/* Suppress the legacy hover-only show rule on the user_box.
   Otherwise hovering would show the dropdown briefly even when
   is-open is false, which conflicts with the click model. */
.user_box.dropdown:hover .dropdown-content {
  display: none !important;
}
.user_box.dropdown.is-open .dropdown-content {
  display: block !important;
}

/* Hide the legacy .navigation-full span if it shows up — the
   new markup uses .user_box__name instead. */
.user_box .navigation-full { display: none !important; }

/* Mobile: collapse email + display-name into single line */
@media (max-width: 600px) {
  .user_box__email { display: none; }
  .user_box__name { line-height: 1.4; }
}

/* ============================================================ */
/* Envelope icon in the user_box (patch 20260515.29)            */
/* ============================================================ */

.fm-message-bell {
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 36px;
  height: 36px;
  /* Patch 20260515.37 — spacing now comes from the .header-right
     flex group's `gap`. Reset margin so the icon hugs that gap. */
  margin: 0;
  color: var(--fm-white);
  text-decoration: none;
  border-radius: 50%;
  transition: background 120ms ease, color 120ms ease;
}

/* Patch 20260515.37 — right-aligned group for envelope + user_box.
   .header_inner is `display: flex; justify-content: space-between`,
   so wrapping these two in one child means the group as a whole
   gets pushed all the way right and `gap` controls the in-between
   spacing. */
.header-right {
  display: flex;
  align-items: center;
  gap: var(--fm-space-2);
}

/* Patch 20260515.39 — header icon-button (gear) + variant of
   .fm-message-bell for the Virtual Coach speech-bubbles icon. */
.fm-icon-button {
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 36px;
  height: 36px;
  margin: 0;
  padding: 0;
  color: var(--fm-white);
  background: transparent;
  border: 0;
  border-radius: 50%;
  cursor: pointer;
  transition: background 120ms ease, color 120ms ease;
}
.fm-icon-button:hover,
.fm-icon-button:focus-visible {
  background: rgba(255, 255, 255, 0.12);
  outline: none;
}

/* 20260808.341 - the blinking header-icon alert (Wayne: the SMS icon
   "should blink RED when there is a new message - just like the 211
   system"; animation ported from 211's _chat-queue-bell-poll.ejs).
   Defined HERE, not inline in the layouts (PTI-RULE-15), so the next
   icon that needs to demand attention reuses the class pair instead of
   growing a second animation. --fm-danger is too dark to glow on the
   navy header, so the alert red is its own token. */
:root { --fm-alert: #FF5252; }
@keyframes fmIconPulse {
  0%   { transform: scale(1);    filter: none; }
  50%  { transform: scale(1.22); filter: drop-shadow(0 0 6px var(--fm-alert)); }
  100% { transform: scale(1);    filter: none; }
}
.fm-icon-button.fm-icon-alert {
  animation: fmIconPulse 1s ease-in-out infinite;
  color: var(--fm-alert);
}
/* 20260808.343 - the footer copyright line (Wayne). Sits beside the
   version link in both staff layouts' .footer. */
.footer-copyright {
  margin-left: var(--fm-space-4);
  color: var(--fm-gray-700);
  font-size: var(--fm-text-xs);
}

/* The count pill. Hidden until a poller fills it and removes [hidden]. */
.fm-icon-badge {
  position: absolute;
  top: -2px;
  right: -4px;
  min-width: 16px;
  padding: 2px 4px;
  border-radius: 9px;
  background: var(--fm-alert);
  color: var(--fm-white);
  font-size: 11px;
  font-weight: var(--fm-weight-semibold);
  line-height: 1.1;
  text-align: center;
}

/* Header dropdown wrapper (gear) — relative-positioned so the
   absolutely-positioned content panel anchors to it. */
.fm-header-menu {
  position: relative;
  display: inline-flex;
  align-items: center;
}
.fm-header-menu__content {
  display: none;
  position: absolute;
  top: calc(100% + 6px);
  right: 0;
  min-width: 180px;
  background: var(--fm-white);
  /* Patch 20260515.42 — --fm-text is undefined in this
     stylesheet; was rendering invalid. Use the real dark
     text variable with a hex fallback. */
  color: var(--fm-gray-900, #1B2230);
  border: 1px solid var(--fm-gray-200, #e5e7eb);
  border-radius: 6px;
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.15);
  padding: 6px 0;
  z-index: 1000;
}
.fm-header-menu.is-open .fm-header-menu__content {
  display: block;
}
.fm-header-menu__content a {
  display: block;
  padding: 8px 14px;
  /* Patch 20260515.40 + .42 — !important to beat the legacy
     .header_inner a { color: white !important } rule from
     .26. .40 used var(--fm-text) which is UNDEFINED in this
     stylesheet; an invalid value is discarded BEFORE
     specificity/!important is evaluated, so the cascade
     fell through to white. Use the defined dark text
     variable with a hex fallback. */
  color: var(--fm-gray-900, #1B2230) !important;
  text-decoration: none;
  font-size: 14px;
}
.fm-header-menu__content a:hover,
.fm-header-menu__content a:focus-visible {
  background: var(--fm-gray-100, #f3f4f6);
  /* Keep the darker text color on hover too (same reason). */
  color: var(--fm-navy-900, #0b1d4f) !important;
  outline: none;
}

/* ============================================================ */
/* 20260808.58 — menu restructure (owner). Cog menu additions.  */
/* The former System top-nav group now renders inside the cog   */
/* (nav.cogMenuItems). These rules live HERE (not the layouts)  */
/* because the .fm-header-menu__content a color rules above use */
/* !important — a later, more-specific, equally-!important rule */
/* is the only clean way to win (same lesson as .46/.47 red).   */
/* ============================================================ */

/* Classic (.NET-served) targets keep the red marker in the cog,
   matching .top-nav-dropdown-menu a.top-nav-classic. */
.fm-header-menu__content a.fm-classic,
.fm-header-menu__content a.fm-classic:hover,
.fm-header-menu__content a.fm-classic:focus-visible {
  color: #C92A2A !important;
}

/* Labeled section heading inside a header dropdown (the
   'Platform' divider between the role-gated System items and the
   allowlist-only platform panels). */
.fm-header-menu__content .fm-header-menu__section {
  display: block;
  padding: 8px 14px 4px;
  margin-top: 4px;
  border-top: 1px solid var(--fm-gray-200, #e5e7eb);
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--fm-gray-500, #667085);
}

/* The merged cog list is long (up to 21 System items + platform
   links) — cap it to the viewport and scroll inside, like the
   long top-nav dropdowns. */
#systemMenu .fm-header-menu__content {
  min-width: 240px;
  max-height: min(70vh, 560px);
  overflow-y: auto;
}

/* ============================================================ */
/* 20260808.229 - MANAGE flyout inside the cog (Wayne).         */
/* 20260808.232 - the panel is now a TRUE BODY PORTAL: script   */
/* appends it to document.body and positions it from the        */
/* anchor's rect at show time (PTI-RULE-3's own pattern - the   */
/* .229 fixed-in-place shape never became visible on dev).      */
/* Because the panel no longer lives inside the cog content,    */
/* its links get their OWN copies of the menu link rules below  */
/* - descendant inheritance from .fm-header-menu__content is    */
/* gone by construction.                                        */
/* ============================================================ */
.fm-header-submenu__parent {
  display: block;
  padding: 8px 14px;
  color: var(--fm-gray-900, #1B2230) !important;
  text-decoration: none;
  font-size: 14px;
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: uppercase;
}
.fm-header-submenu__parent:hover,
.fm-header-submenu__parent:focus-visible {
  background: var(--fm-gray-100, #f3f4f6);
  color: var(--fm-navy-900, #0b1d4f) !important;
  outline: none;
}
.fm-header-submenu__arrow {
  float: right;
  margin-left: 10px;
  color: var(--fm-gray-500, #667085);
}
.fm-header-submenu__content {
  display: none;
  position: fixed; /* left/top set by script at open time */
  min-width: 200px;
  background: var(--fm-white);
  color: var(--fm-gray-900, #1B2230);
  border: 1px solid var(--fm-gray-200, #e5e7eb);
  border-radius: 6px;
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.15);
  padding: 6px 0;
  /* 20260808.420 - the panel outgrew its stacking (Wayne: "the submenu
     is below the menu bar so the top item is hidden"). At 14 items the
     placement script clamps the panel's top toward the viewport top,
     which slides the FIRST rows (Diagnosis Codes is first) underneath
     the header bar, and 1001 lost to the header's paint order. Same
     answer as every floating list here (PTI-RULE-3 / pti-dropdown):
     paint at 10000, above all page chrome, and let the panel SCROLL
     inside the viewport instead of ever being taller than it - the
     same max-height the cog panel itself already uses. */
  z-index: 10000;
  max-height: min(70vh, 560px);
  overflow-y: auto;
}
.fm-header-submenu__content.is-open {
  display: block;
}
/* 20260808.232 - own link rules (the panel is body-portaled, so the
   .fm-header-menu__content a rules no longer reach it). Same values,
   same !important rationale (the legacy .header_inner white) - and the
   body portal ALSO escapes .header_inner, but the rules stay explicit
   so a future re-parent cannot silently unstyle the panel. */
.fm-header-submenu__content a {
  display: block;
  padding: 8px 14px;
  color: var(--fm-gray-900, #1B2230) !important;
  text-decoration: none;
  font-size: 14px;
}
.fm-header-submenu__content a:hover,
.fm-header-submenu__content a:focus-visible {
  background: var(--fm-gray-100, #f3f4f6);
  color: var(--fm-navy-900, #0b1d4f) !important;
  outline: none;
}
.fm-header-submenu__content a.fm-classic,
.fm-header-submenu__content a.fm-classic:hover,
.fm-header-submenu__content a.fm-classic:focus-visible {
  color: #C92A2A !important;
}

/* 20260808.82 (timeout spec item 7): the Virtual Coach Messages hover
   rule was removed with the bell itself. The .fm-message-bell--virtual
   class no longer appears in any view. */

/* =====================================================================
   20260808.288 - THE PATIENT SEARCH LOOK, SHARED.

   Wayne, 2026-08-15, looking at the doctor portal search after .286 gave
   it the staff page's FIELDS: "this page does not look like the staff
   page. I am confused when I say I want it to look like the staff page,
   why would you give me something that doesn't look like the staff
   search page".

   Fair. .286 moved the portal onto the staff QUERY and the staff FIELDS
   and left it wearing its own markup: a .gridview table, its own Arial
   13px block, its own label/input table. Same data, same behaviour,
   visibly a different page. Matching function is not matching form, and
   the request was about form.

   These rules were the private <style> block of views/patients/search.ejs
   and are moved here UNCHANGED so both views can use them. Moved rather
   than copied: two copies of a look is exactly the drift PTI-RULE-15
   exists to stop, and the staff page is the one that defines it, so it
   must read from the same source rather than keep a twin.

   The values are deliberately NOT retokenised in this patch. They are the
   legacy grid look (#000084 headers, #EEEEEE/#DCDCDC banding, 13px Arial)
   that 222 staff routes and the whole reporting estate already show, and
   changing them here would restyle the staff page while claiming to
   restyle the portal. A token pass over .ps-* is worth doing on its own,
   against a screenshot, not smuggled into a patch about the portal.
   ===================================================================== */

.ps-wrap { font-family: Arial, Helvetica, sans-serif; }
.ps-msg-error { font-weight: bold; font-size: 16px; color: red; }
.ps-topbar { width: 100%; display: flex; justify-content: space-between; align-items: flex-start; gap: 12px; }
.ps-recent { width: 30%; min-width: 240px; position: relative; }
.ps-recent summary { cursor: pointer; font-weight: bold; padding: 6px 10px; background: #000084; color: #fff; list-style: none; }
.ps-recent summary::-webkit-details-marker { display: none; }
.ps-recent ul { position: absolute; z-index: 60; left: 0; right: 0; top: 100%; max-height: 320px; overflow-y: auto; box-shadow: 0 4px 10px rgba(0,0,0,0.3); list-style: disc; margin: 0; padding: 8px 8px 8px 26px; border: 1px solid #999; border-top: 0; background: #fff; }
.ps-recent li { padding: 2px 0; font-size: 13px; }
.ps-recent a { color: #000084; }
/* 20260808.288 - section heading above a group of search fields. The staff
   page has one undivided form and does not use this; the doctor portal
   splits its fields into "who you are looking for" and "confirm who they
   are", because on that page the second group is REQUIRED and a bare
   asterisk would not say why. It lives here rather than in the portal view
   so the staff page can adopt the same grouping without a second rule. */
.ps-section { font-size: 13px; font-weight: bold; color: #555; border-bottom: 1px solid #999999;
              padding-bottom: 4px; margin: 14px 0 6px; }
.ps-search-table.ps-actions { margin-top: 10px; border-top: 1px solid #999999; padding-top: 4px; }
.ps-search-table { width: 100%; font-size: 16px; border-collapse: collapse; }
.ps-search-table td { padding: 3px; vertical-align: middle; }
.ps-search-table td.ps-label { width: 30%; }
.ps-search-table input[type=text] { width: 200px; }
.ps-field-error { color: red; font-weight: bold; font-size: 13px; margin-left: 6px; }
.ps-hint { font-weight: normal; font-size: 10px; color: #555; }
.ps-btn { width: 100px; font-size: 13px; }
.ps-btn-link { display: inline-block; width: 100px; font-size: 13px; text-align: center;
               padding: 2px 0; margin-left: 8px; border: 1px solid #767676; border-radius: 2px;
               background: #efefef; color: #000; text-decoration: none; line-height: normal; }
.ps-btn-link:hover { background: #e0e0e0; }
/* Legacy .gridview look */
.ps-grid { width: 100%; border: 1px solid #999999; border-collapse: collapse; font-size: 13px; }
.ps-grid th, .ps-grid td { border: 1px solid #999999; padding: 3px; font-family: Arial, Helvetica, sans-serif; font-size: 13px; vertical-align: top; }
.ps-grid th { background: #000084; color: #fff; font-weight: bold; text-align: center; }
.ps-grid tr.r0 td { background: #EEEEEE; color: #000; }
.ps-grid tr.r1 td { background: #DCDCDC; color: #000; }
.ps-grid tr.ps-footer td { background: #CCCCCC; }
.ps-grid a { color: #000084; }
.ps-pager { background: #999999; text-align: center; padding: 4px; font-size: 13px; }
.ps-pager a, .ps-pager span { margin: 0 4px; color: #000084; }
.ps-pager span.cur { font-weight: bold; color: #000; text-decoration: none; }
.ps-empty { padding: 6px; font-size: 13px; }
.ps-home { width: 100%; text-align: center; margin-top: 14px; }
.ps-home a { font-weight: bold; text-decoration: underline; font-size: 16px; color: #000084; }
/* Doctor autocomplete. LOOK ONLY. Placement belongs to
   /Scripts/pti-dropdown.js (PTI-RULE-3): the list is portalled to
   document.body at position:fixed with z-index 10000, because anything
   positioned inside a page container gets clipped or painted over.
   DO NOT add position, z-index, left, right or top to .ps-doc-list.
   ⚠ The doctor portal does not render an autocomplete (a doctor there IS
   the scope), so these four rules serve the staff page only. They move
   with the block rather than being split off, because splitting a look
   across two files is how the halves drift. */
.ps-doc-wrap { width: 95%; }
.ps-doc-wrap input[type=text] { width: 100%; box-sizing: border-box; }
.ps-doc-list { max-height: 300px; overflow-y: auto; background: #fff; border: 1px solid #999; }
.ps-doc-list [role="option"] { padding: 4px 6px; cursor: pointer; border-bottom: 1px solid #eee; }
.ps-doc-list [role="option"]:hover, .ps-doc-list [role="option"].active { background: #f89013; }
.ps-doc-name { font-weight: bold; padding: 1px 0; }
.ps-doc-sub { font-weight: normal; font-size: 13px; padding: 1px 0; }

/* ============================================================ */
/* 20260808.285 - THE .fm-action-icon RULES ARE GONE.

   Patch 20260515.40 added them to style the pencil and trash icons
   that fm-table-tools.js swapped in for every Edit and Delete button
   on the page. Wayne, 2026-08-15: "let's get rid of that totally. I
   don't want that anywhere in the app." The sweep is retired, so
   nothing carries these classes any more and the rules are removed
   rather than left orphaned.

   Those buttons now fall through to the base button rule near the top
   of this file, which is the point: an Edit button looks like every
   other button in the system and says Edit.

   The Excel export icon in the table header is a SEPARATE feature from
   the same patch and is untouched; its rules follow below. */
/* ============================================================ */

/* Header-mounted export icon. The <th> that holds it gets
   .fm-th-with-export so we know to make space on the right. */
.fm-th-with-export {
  position: relative;
  padding-right: 36px !important;
}
.fm-th-with-export .fm-table-export {
  position: absolute;
  top: 50%;
  right: 6px;
  transform: translateY(-50%);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 26px;
  height: 26px;
  padding: 0;
  background: transparent;
  border: 1px solid transparent;
  border-radius: 4px;
  color: var(--fm-white);
  cursor: pointer;
  line-height: 1;
  transition: background 100ms ease, border-color 100ms ease;
}
.fm-th-with-export .fm-table-export:hover,
.fm-th-with-export .fm-table-export:focus-visible {
  background: rgba(255, 255, 255, 0.16);
  border-color: rgba(255, 255, 255, 0.28);
  outline: none;
}

/* ============================================================ */
/* Patch 20260515.43 — impersonation banner. */
/* ============================================================ */

.fm-impersonation-banner {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 8px 16px;
  background: #FCF1DC;
  color: #6B4400;
  border-top: 1px solid #E0B65A;
  border-bottom: 1px solid #E0B65A;
  font-size: 14px;
  font-weight: 500;
  z-index: 100;
}
.fm-impersonation-banner__icon {
  display: inline-flex;
  color: #B7791F;
}
.fm-impersonation-banner__text {
  flex: 1 1 auto;
}
.fm-impersonation-banner__text strong {
  color: #4A3000;
  font-weight: 700;
}
.fm-impersonation-banner__form {
  margin: 0;
}
.fm-impersonation-banner__btn {
  background: #B7791F;
  color: #fff;
  border: 0;
  border-radius: 4px;
  padding: 6px 12px;
  font-size: 13px;
  font-weight: 600;
  cursor: pointer;
  font-family: inherit;
}
.fm-impersonation-banner__btn:hover,
.fm-impersonation-banner__btn:focus-visible {
  background: #8A5A11;
  outline: none;
}

/* ============================================================ */
/* Patch 20260515.45 — Impersonate modal. */
/* ============================================================ */

.fm-modal {
  position: fixed;
  inset: 0;
  display: none;
  align-items: flex-start;
  justify-content: center;
  z-index: 9999;
}
.fm-modal.is-open { display: flex; }
.fm-modal__backdrop {
  position: absolute;
  inset: 0;
  background: rgba(11, 36, 71, 0.45);
}
.fm-modal__dialog {
  position: relative;
  margin-top: 8vh;
  width: min(640px, calc(100vw - 32px));
  max-height: 80vh;
  display: flex;
  flex-direction: column;
  background: var(--fm-white);
  border-radius: 10px;
  box-shadow: 0 20px 60px rgba(0, 0, 0, 0.30);
  overflow: hidden;
}
.fm-modal__header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 14px 18px;
  border-bottom: 1px solid var(--fm-gray-200, #E3E7EC);
}
.fm-modal__title {
  margin: 0;
  font-size: 18px;
  font-weight: 600;
  color: var(--fm-navy-900, #0B2447);
}
.fm-modal__close {
  background: transparent;
  border: 0;
  font-size: 24px;
  line-height: 1;
  color: var(--fm-gray-700, #4A5460);
  cursor: pointer;
  padding: 4px 8px;
}
.fm-modal__close:hover { color: var(--fm-navy-900, #0B2447); }
.fm-modal__body {
  display: flex;
  flex-direction: column;
  padding: 14px 18px 18px;
  overflow: hidden;
}
.fm-modal__search {
  width: 100%;
  padding: 10px 12px;
  font-size: 14px;
  border: 1px solid var(--fm-gray-200, #E3E7EC);
  border-radius: 6px;
  margin-bottom: 12px;
  box-sizing: border-box;
  font-family: inherit;
}
.fm-modal__list {
  flex: 1 1 auto;
  overflow-y: auto;
  border: 1px solid var(--fm-gray-200, #E3E7EC);
  border-radius: 6px;
  max-height: 56vh;
}
.fm-modal__row {
  display: grid;
  grid-template-columns: 1fr auto;
  align-items: center;
  gap: 12px;
  padding: 10px 14px;
  border-bottom: 1px solid #F1F3F6;
  margin: 0;
}
.fm-modal__row:last-child { border-bottom: 0; }
.fm-modal__row:hover { background: #F1F3F6; }
.fm-modal__row-name {
  font-size: 14px;
  font-weight: 500;
  color: var(--fm-gray-900, #1B2230);
}
.fm-modal__row-meta {
  font-size: 12px;
  color: var(--fm-gray-700, #4A5460);
  margin-top: 2px;
}
.fm-modal__row-btn {
  background: var(--fm-navy-700, #19376D);
  color: #fff;
  border: 0;
  border-radius: 4px;
  padding: 6px 12px;
  font-size: 13px;
  font-weight: 500;
  cursor: pointer;
  font-family: inherit;
}
.fm-modal__row-btn:hover { background: var(--fm-navy-900, #0B2447); }
.fm-modal__loading,
.fm-modal__empty {
  padding: 14px;
  text-align: center;
  color: var(--fm-gray-700, #4A5460);
  font-size: 13px;
}

/* ============================================================ */
/* Patch 20260515.55 — Vendor-standard SSO sign-in buttons.    */
/* Google uses its own SDK-rendered g_id_signin element so      */
/* only Facebook + Microsoft need styling here. Both are sized */
/* to 320x41 to align with the Google button (data-width=320). */
/* ============================================================ */

.fm-sso-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 12px;
  width: 320px;
  height: 41px;
  padding: 0 16px;
  margin: 6px 0;
  font-size: 15px;
  font-weight: 500;
  line-height: 1;
  text-decoration: none;
  border-radius: 4px;
  cursor: pointer;
  box-sizing: border-box;
  transition: background 100ms ease, border-color 100ms ease;
}
.fm-sso-btn svg { flex: 0 0 auto; }

/* Facebook — Meta brand: #1877F2 background, white text + logo. */
.fm-sso-btn--facebook {
  background: #1877F2;
  color: #ffffff !important;
  border: 0;
  font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;
}
.fm-sso-btn--facebook:hover,
.fm-sso-btn--facebook:focus-visible {
  background: #166FE5;
  outline: none;
}

/* Microsoft — Microsoft Identity Platform: white bg, 1px gray  */
/* border, Segoe UI text, the iconic 4-square color logo.       */
.fm-sso-btn--microsoft {
  background: #FFFFFF;
  color: #1F1F1F !important;
  border: 1px solid #8C8C8C;
  font-family: 'Segoe UI', system-ui, -apple-system, sans-serif;
}
.fm-sso-btn--microsoft:hover,
.fm-sso-btn--microsoft:focus-visible {
  background: #F5F5F5;
  border-color: #6B6B6B;
  outline: none;
}

/* The old toolbar div is no longer emitted by fm-table-tools.js,
   but if any page still has a stale one (cached HTML, manual
   markup), hide it so we don't show two export buttons. */
.fm-table-toolbar {
  display: none !important;
}

.fm-message-bell:hover,
.fm-message-bell:focus-visible {
  background: rgba(255, 255, 255, 0.12);
  color: var(--fm-white);
  text-decoration: none;
  outline: none;
}

.fm-message-bell__badge {
  position: absolute;
  top: 1px;
  right: 0;
  min-width: 18px;
  height: 18px;
  padding: 0 4px;
  background: var(--fm-danger);
  color: var(--fm-white);
  border: 2px solid var(--fm-navy-900);
  border-radius: 9px;
  font-size: 11px;
  font-weight: var(--fm-weight-bold);
  line-height: 14px;
  text-align: center;
  box-sizing: border-box;
  pointer-events: none;
}

/* ============================================================ */
/* Table sort + XLS export (patch 20260515.30)                  */
/* ============================================================ */

.fm-table-toolbar {
  display: flex;
  justify-content: flex-end;
  align-items: center;
  gap: var(--fm-space-2);
  margin-bottom: var(--fm-space-2);
}

.fm-table-export {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 6px 12px;
  font-size: var(--fm-text-xs);
  font-weight: var(--fm-weight-semibold);
  letter-spacing: 0.02em;
  background: var(--fm-white);
  color: var(--fm-navy-700);
  border: 1px solid var(--fm-gray-300);
  border-radius: var(--fm-radius-md);
  cursor: pointer;
  transition: background 120ms ease, border-color 120ms ease;
}
.fm-table-export:hover {
  background: var(--fm-gray-100);
  border-color: var(--fm-navy-500);
  color: var(--fm-navy-900);
}
.fm-table-export svg {
  flex: 0 0 14px;
}

.fm-th-sortable {
  cursor: pointer;
  user-select: none;
  position: relative;
}
.fm-th-sortable:hover { background: var(--fm-navy-700) !important; }
.fm-th-sortable:focus-visible {
  outline: 2px solid var(--fm-accent-500);
  outline-offset: -2px;
}

.fm-sort-indicator {
  font-size: 0.85em;
  margin-left: 4px;
  opacity: 0.85;
  display: inline-block;
  min-width: 0.8em;
  text-align: right;
}
.fm-th-sortable[data-fm-sort-dir="asc"] .fm-sort-indicator,
.fm-th-sortable[data-fm-sort-dir="desc"] .fm-sort-indicator {
  opacity: 1;
  color: var(--fm-accent-500);
  font-weight: var(--fm-weight-bold);
}

/* ============================================================ */
/* Dashboard widget skeleton (patch 20260515.31)                */
/* ============================================================ */

@keyframes fm-skeleton-pulse {
  0%, 100% { opacity: 0.55; }
  50%      { opacity: 0.85; }
}

.dashboard-widget__skeleton {
  min-height: 120px;
  background: linear-gradient(110deg, var(--fm-gray-100) 25%, var(--fm-gray-200) 50%, var(--fm-gray-100) 75%);
  background-size: 200% 100%;
  border: 1px solid var(--fm-gray-200);
  border-radius: var(--fm-radius-lg);
  animation: fm-skeleton-shimmer 1.6s ease-in-out infinite, fm-skeleton-pulse 1.6s ease-in-out infinite;
  grid-column-end: span max(1, min(12, var(--dw-w, 12)));
}

@keyframes fm-skeleton-shimmer {
  0% { background-position: 200% 0; }
  100% { background-position: -200% 0; }
}

/* =====================================================================
   20260808.276: ONE TYPE SIZE.

   Wayne, 2026-08-15: "I want all pages to have a consistent look with the
   fonts. That means I want one main size of type. If there are section
   headers etc, it is ok if they have different sizes but mostly i want
   things to be the same font and the same size and the same color and the
   same level of bold."

   WHY THIS IS !important, WHICH IS OTHERWISE A SMELL. The app carries 808
   inline `style="font-size:..."` declarations across 183 views, inherited
   from the WebForms port. An inline style beats any selector, so a normal
   rule here would lose on 183 pages and the result would be exactly the
   inconsistency this is meant to end. The alternative, editing all 808
   sites, is a far larger and much less reversible change.

   SO THIS IS DELIBERATELY THE BLUNT VERSION FIRST: one file, one number,
   and reverting this patch restores the old behaviour exactly. If the size
   is right but a specific element genuinely needs its own, give it
   `fm-size-exempt` rather than reaching for another inline style, and if
   the whole approach proves right, the proper follow-up is to delete the
   808 inline declarations and drop the !important.

   TUNING: change --fm-text-base below. Everything follows it.
   ===================================================================== */

body,
p, div, span, td, th, li, dt, dd,
label, a, button, small, strong, b, em, i,
legend, caption {
  font-size: var(--fm-text-base) !important;   /* 14px */
}

/* 20260808.280: input, select and textarea are DELIBERATELY NOT in the rule
   above, and this is a technical exception rather than style drift.

   iOS Safari AUTOMATICALLY ZOOMS THE PAGE when a field is focused whose
   font-size is under 16px. There is no way to opt out short of disabling
   pinch zoom, which is an accessibility regression. So form fields stay at
   16px, which is what the design system already set them to at line 194
   with var(--fm-text-md), long before the one-size rule existed.

   .276 swept them into the 14px force and would have made every field tap
   jump the page. That lands hardest on the technician mobile views, which
   carry 102 inputs and are used on phones all day.

   If a desktop-only field genuinely needs to match body text, give it a
   class rather than reaching for an inline style (PTI-RULE-15). */
input, select, textarea {
  font-size: var(--fm-text-md) !important;     /* 16px, iOS zoom floor */
}

/* Headings keep a deliberate, shallow ladder. The old 34/28/22 was sized
   for a different app and read as a different product next to 14px body. */
h1 { font-size: var(--fm-text-xl)   !important; }  /* 22px */
h2 { font-size: var(--fm-text-lg)   !important; }  /* 18px */
h3 { font-size: var(--fm-text-md)   !important; }  /* 16px */
h4, h5, h6 { font-size: var(--fm-text-base) !important; }  /* 14px */

/* One weight for bold. The tree mixes 600, 700 and the `bold` keyword. */
strong, b, th, h1, h2, h3, h4, h5, h6 {
  font-weight: var(--fm-weight-semibold) !important;
}

/* The single documented escape hatch. Nothing uses it yet; it exists so a
   genuine exception is declared rather than smuggled in as another inline
   style, which is how the 808 accumulated in the first place. */
.fm-size-exempt, .fm-size-exempt * { font-size: revert !important; }

/* Icons must not be dragged to 14px: they size from their own box. */
svg, .fa, .fas, .far, .fab, [class^="icon-"], [class*=" icon-"] {
  font-size: revert !important;
}

/* =====================================================================
   20260808.277: EVERY TABLE CELL LEFT ALIGNED, HEADERS INCLUDED.

   Wayne, 2026-08-15: "for all tables lets make sure everything is
   justified left. There are a lot of tables where things aren't and it is
   distracting", and on being asked, "that includes header rows".

   TWO CAUSES, and the second is the one nothing in the tree ever set:

   1. 503 inline `text-align: center|right` on cells across 84 views
      (404 center, 99 right), inherited from the WebForms port. Inline
      styles beat any selector, hence !important, same reasoning as .276.

   2. NOTHING set `th` alignment anywhere, so the browser default applied
      and EVERY table header rendered centred over left-aligned data. That
      is almost certainly the bulk of what reads as distracting, and it
      needed no bad markup to happen: it was the default all along.

   ⚠ THIS DELIBERATELY FLATTENS THE 99 RIGHT-ALIGNED CELLS TOO. Those are
   mostly numeric and currency columns, where right alignment is a genuine
   typographic convention because it lines up the decimal point. Wayne
   asked for everything left knowing that. If a money column later looks
   wrong, `fm-align-keep` is the way to excuse it rather than a new inline
   style.

   SCOPED TO THE CELL ITSELF, not its descendants, on purpose: the sort
   indicator inside a th carries its own `text-align: right` and must keep
   it, otherwise the arrow jumps to the wrong side of the header.
   ===================================================================== */

table th,
table td {
  text-align: left !important;
}

/* The documented exception, for a column where alignment carries meaning
   (decimal alignment in a money column, for instance). Nothing uses it
   yet; it exists so the next exception is declared rather than smuggled
   back in as an inline style. */
.fm-align-keep,
.fm-align-keep th,
.fm-align-keep td,
th.fm-align-keep,
td.fm-align-keep {
  text-align: revert !important;
}

/* =====================================================================
   20260808.278: EVERY BUTTON CENTRES ITS OWN LABEL.

   Wayne, 2026-08-15, on the Expected Revenue report: "the words view are
   not center of the button. in this case the words are the bottom right of
   the button. We need to audit all buttons and make sure they are correct."

   THE AUDIT: 892 buttons in the tree (774 <button>, 118 submit/button
   inputs). The design system already had .btn-primary, .btn-secondary,
   .btn-cta, .btn-danger and .btn-icon, and every one of them already
   centres correctly with inline-flex. Only 29 views use any of them. The
   other 863 buttons were running on browser defaults, and 133 carry an
   inline style instead.

   ⚠ AND 20260808.276 MADE ONE CASE WORSE, which is on me. Nine report
   views share a copy-pasted line:

       .xxx-actions button { height: 26px; width: 55px; font-size: 13px; }

   (daily-draw-summary, tests-by-lab, year-over-year, orders-by-created-date,
   expected-revenue, missed-reason, third-party-lab-billing, top-doctors,
   company-metrics)

   .276 forces 14px over that 13px, so a slightly taller label went into a
   fixed 26px box that was already tight. Rather than carve those nine out
   of the type rule, which would reintroduce the inconsistency .276 exists
   to remove, the button is made able to hold the label: flex centring plus
   line-height 1 plus border-box, so a 14px label sits centred in a 26px
   box instead of drifting.

   This is the SAME treatment .btn-primary already gets, applied to the 863
   buttons that never opted in.
   ===================================================================== */

button,
input[type="submit"],
input[type="button"],
input[type="reset"] {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  line-height: 1;
  box-sizing: border-box;
  text-align: center;
}

/* An <input> is a replaced element: flex does not lay out its internals, so
   it needs the classic centring too. Harmless on the others. */
input[type="submit"],
input[type="button"],
input[type="reset"] {
  display: inline-block;
}

/* Buttons that wrap an icon and a label keep a consistent gap rather than
   relying on whitespace in the markup. */
button > svg + *,
button > * + svg { margin-left: 6px; }

/* =====================================================================
   20260808.281: REMOVES THE .279 BUTTON OVERRIDE. IT WAS A REGRESSION.

   Wayne, on the patches page: "I prefer the size / styling of the restart
   and download buttons over the validate and apply buttons."

   He was pointing straight at a bug I introduced. .279 claimed 530 buttons
   were "rendering as raw browser chrome" and gave them the .btn-secondary
   look. THAT PREMISE WAS WRONG. This file has carried a base button rule
   since the design system was written, at line 235: navy fill, white text,
   10px 18px padding, semibold, radius, transition, with its own :hover and
   :focus-visible below it. Bare buttons were already styled, and correctly.

   .279 appended a competing rule at the END of the file, so it won on
   source order and repainted every bare button white and outlined. Restart
   and Download kept their look only because they carry INLINE styles, which
   beat both rules. That is the entire difference Wayne spotted.

   The audit missed it because it grepped for `.btn-*` CLASSES and never for
   a bare `button {` ELEMENT rule. Worth remembering: before adding a base
   rule for an element, grep for that element AS A SELECTOR, not just for
   the classes you expect people to be using.

   The override is gone and the original rule governs again. Only the two
   genuinely new pieces are kept, as additive rules that do not fight it.
   The nine report views that pinned `height: 26px` are freed in the same
   patch: a 14px label (.276) in a 26px box with the design system's 10px
   vertical padding is the squeeze that started all of this.
   ===================================================================== */

/* Not in the original: a disabled button should look disabled. */
button:disabled,
input[type="submit"]:disabled,
input[type="button"]:disabled,
input[type="reset"]:disabled {
  opacity: 0.55;
  cursor: not-allowed;
}

/* Not in the original: never let a fixed width clip a label. Load bearing
   for any view that pins a button width. */
button,
input[type="submit"],
input[type="button"],
input[type="reset"] {
  min-width: fit-content;
  white-space: nowrap;
}

/* =====================================================================
   20260808.282: THE TWO EXTERNAL PORTALS JOIN THE PLATFORM SHELL.

   WHAT WAS ACTUALLY WRONG. Wayne, 2026-08-15: "it looks like the old
   system is coming up with the new system header". That was literal,
   not impressionistic. The three portal layouts loaded Styles/screen.css
   IN ADDITION to the four sheets every staff page loads, and screen.css
   is the legacy page shell:

       body             { font-size:62.5%; background:#081154 url(bg.jpg) }
       .globalContainer { width:1060px; font:1.2em/1.25 "Trebuchet MS" }
       .header          { height:103px }

   CoachConnectMain.css then loads AFTER it and redefines .header as the
   navy gradient. So the pages really were the old 1060px Trebuchet shell
   wearing the new header: two stylesheets fighting over one class.

   THE FIX IS TO DELETE A DEPENDENCY, NOT TO ADD STYLING. The layouts now
   use the same shell as layouts/site.ejs (content > header + main >
   inset), screen.css is gone, and body falls through to
   CoachConnectMain's flex column on #f3f3f3 in the platform font. 222
   staff routes have run on exactly that shell for weeks.

   WHY .220 KEPT screen.css AND WHY THAT NO LONGER HOLDS. The .220 note
   said the page bodies were transcribed against the legacy classes, so
   the sheet had to stay. Measured before removing it: of the 61 classes
   screen.css defines, the portal VIEWS use six. `footer` is also defined
   in CoachConnectMain.css:66, so it keeps its styling for free. The
   other five (webpart, mainNavigation, group, groupName, children) are
   the doctor sidebar in doctor-portal/_nav.ejs and are replaced by the
   .fm-portal-nav block below. Nothing else referenced it.

   THE TWO RULES BELOW ARE COMPONENTS, NOT PAGE STYLES. PTI-RULE-15
   forbids a new per-page font, colour, size or button style; it does not
   forbid adding a reusable component to the design system, which is the
   sanctioned place for one. Every value here is a token.
   ===================================================================== */

/* 20260808.284 - THE DOCTOR PORTAL HAS NO PORTAL-SPECIFIC NAV CSS, AND
   THAT IS THE POINT.

   This is the third shape in three patches, so the reasoning is worth
   leaving behind rather than just the result:

     .282  rebuilt the legacy sidebar as .fm-portal-nav, a card in a
           right-hand column, because that is what the legacy master had.
           Only one route rendered that master, so four of the five
           doctor pages had no navigation at all.
     .283  moved the links into the header as .fm-portal-topnav. Present
           on every page, but a bespoke component that would have had to
           re-implement sticky positioning and a responsive drawer to
           match the staff bar.
     .284  feeds the same five links through partials/_top-nav.ejs, the
           bar the staff site already uses. Wayne, 2026-08-15: "look how
           the staff menu works. it should also stay at the top of the
           page like the staff one."

   So both .fm-portal-columns/.fm-portal-nav (.282) and
   .fm-portal-topnav (.283) are gone from this file, and nothing
   replaced them. The doctor bar is styled by the .top-nav rules above
   and by the partial's own inline block. Sticky top:0 and the sub-768px
   hamburger come free, and the next fix to the staff bar lands on the
   doctor bar in the same commit.

   The lesson worth keeping: the first instinct was to build a portal
   component, twice. The correct move was to find the platform one and
   feed it. PTI-RULE-15 is easy to satisfy in the letter by using tokens
   while still adding a component nobody needed. */

/* ============================================================ */
/* Patch 20260808.305 - generic admin-page furniture.           */
/*                                                              */
/* Added HERE rather than on /admin/data-cleanup, per           */
/* PTI-RULE-15. Every one of these was about to be written as a */
/* per-page <style> block, and every one of them is the kind of */
/* thing the next admin page will want too: a message banner, a */
/* tab strip, a labelled field row, a compact table and a pager.*/
/* Built ONLY from tokens that already existed above; no new    */
/* colour, size or weight is introduced.                        */
/* ============================================================ */

/* Message banners. The app had badges (inline pills) but no block-level
   success/error banner, so pages kept inventing bold red spans. */
.fm-alert {
  padding: var(--fm-space-3) var(--fm-space-4);
  border-radius: var(--fm-radius-md);
  border: 1px solid var(--fm-gray-200);
  background: var(--fm-gray-50);
  color: var(--fm-gray-900);
  font-size: var(--fm-text-base);
}
.fm-alert--success { background: var(--fm-success-bg); border-color: var(--fm-success); color: var(--fm-success); }
.fm-alert--error   { background: var(--fm-danger-bg);  border-color: var(--fm-danger);  color: var(--fm-danger);  }
.fm-alert--warning { background: var(--fm-warning-bg); border-color: var(--fm-warning); color: var(--fm-warning); }
.fm-alert--info    { background: var(--fm-info-bg);    border-color: var(--fm-info);    color: var(--fm-info);    }

/* Tab strip. Anchors, so each tab is a real, linkable URL. */
.fm-tabs {
  display: flex;
  flex-wrap: wrap;
  gap: var(--fm-space-1);
  border-bottom: 1px solid var(--fm-gray-200);
}
.fm-tab {
  display: inline-block;
  padding: var(--fm-space-2) var(--fm-space-4);
  font-size: var(--fm-text-base);
  font-weight: var(--fm-weight-medium);
  color: var(--fm-gray-700);
  text-decoration: none;
  border: 1px solid transparent;
  border-bottom: 0;
  border-radius: var(--fm-radius-md) var(--fm-radius-md) 0 0;
}
.fm-tab:hover { background: var(--fm-gray-50); color: var(--fm-gray-900); }
.fm-tab.is-active {
  background: var(--fm-white);
  border-color: var(--fm-gray-200);
  color: var(--fm-navy-900);
  font-weight: var(--fm-weight-semibold);
  margin-bottom: -1px;
}

/* Labelled controls laid out in a row. */
.fm-field-row {
  display: flex;
  flex-wrap: wrap;
  gap: var(--fm-space-4);
  align-items: flex-end;
}
.fm-field { display: flex; flex-direction: column; gap: var(--fm-space-1); }
.fm-field--grow { flex: 1 1 240px; }
.fm-field > label {
  font-size: var(--fm-text-sm);
  font-weight: var(--fm-weight-medium);
  color: var(--fm-gray-700);
}
.fm-check {
  display: inline-flex;
  align-items: center;
  gap: var(--fm-space-2);
  font-size: var(--fm-text-base);
  color: var(--fm-gray-900);
}

/* A denser fm-table, for detail grids sitting inside another surface. */
.fm-table--compact thead th { padding: var(--fm-space-2) var(--fm-space-3); }
.fm-table--compact tbody td {
  padding: var(--fm-space-2) var(--fm-space-3);
  font-size: var(--fm-text-sm);
}

/* Pager. */
.fm-pager {
  display: flex;
  flex-wrap: wrap;
  gap: var(--fm-space-2);
  align-items: center;
  font-size: var(--fm-text-base);
  color: var(--fm-gray-700);
}
.fm-pager a { color: var(--fm-navy-700); }
.fm-pager strong { color: var(--fm-navy-900); }

/* ============================================================ */
/* Patch 20260808.312 - the rest of the generic admin furniture, */
/* plus the hover card.                                          */
/*                                                               */
/* Added HERE and not on /admin/tests, per PTI-RULE-15. The page  */
/* that needed them is rebuilt in the same patch and carries no   */
/* <style> block at all. Built only from tokens defined above.    */
/* ============================================================ */

.fm-admin-page { padding: var(--fm-space-4); }

/* A bordered grouping for a form that is not the page's main content,
   e.g. an Add panel above a list. */
.fm-panel {
  background: var(--fm-gray-50);
  border: 1px solid var(--fm-gray-200);
  border-radius: var(--fm-radius-md);
  padding: var(--fm-space-4);
}
.fm-panel__title {
  margin: 0 0 var(--fm-space-3);
  font-size: var(--fm-text-md);
  font-weight: var(--fm-weight-semibold);
  color: var(--fm-gray-900);
}
.fm-find { margin: var(--fm-space-3) 0; }
.fm-hint { font-size: var(--fm-text-sm); color: var(--fm-gray-700); }

/* ---- Hover card -------------------------------------------------- */
/* POSITIONING IS NOT SET HERE, DELIBERATELY. The card is portalled to
   document.body and placed from the anchor's getBoundingClientRect at
   show time, exactly as PTI-RULE-3 requires of floating UI, because
   platform ancestors carry overflow:hidden and WILL clip anything
   positioned inside a page container. This rule owns the LOOK only.
   It is not routed through PtiDropdown because that helper is
   input-anchored and owns listbox a11y; a hover card is neither. */
.fm-hovercard {
  background: var(--fm-white);
  border: 1px solid var(--fm-gray-300);
  border-radius: var(--fm-radius-md);
  box-shadow: var(--fm-shadow-md);
  padding: var(--fm-space-3);
  max-width: min(1100px, calc(100vw - 32px));
  max-height: 70vh;
  overflow: auto;
  font-size: var(--fm-text-sm);
  color: var(--fm-gray-900);
}
.fm-hovercard__title {
  margin: 0 0 var(--fm-space-2);
  font-weight: var(--fm-weight-semibold);
  color: var(--fm-navy-900);
}
/* The server renders these inline and the script copies their innerHTML
   into the portalled card, so they must never be visible themselves. */
.fm-hovercard__source { display: none; }

/* ---- Modal extras ------------------------------------------------ */
.fm-modal__dialog--wide { width: min(1000px, calc(100vw - 32px)); }
.fm-modal__body--scroll { overflow-y: auto; }
.fm-modal__section {
  margin: var(--fm-space-5) 0 var(--fm-space-2);
  font-size: var(--fm-text-md);
  font-weight: var(--fm-weight-semibold);
  color: var(--fm-gray-900);
}
.fm-modal__actions {
  display: flex;
  gap: var(--fm-space-2);
  margin-top: var(--fm-space-4);
}

/* The legacy FromLabcorp highlight, moved off the page (PTI-RULE-15).
   The colour is unchanged from the 20260808.191 port. */
.fm-table tr.labcorpRow td { background-color: #FBF3C4; }

/* ============================================================ */
/* Patch 20260808.313 - the clock-in reminder banner.            */
/* Staff layouts; the technician layout styles its own copy in   */
/* pti-tech-mobile.css because that surface has its own palette. */
/* ============================================================ */
.fm-clockin-banner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: var(--fm-space-3);
  padding: var(--fm-space-3) var(--fm-space-4);
  background: var(--fm-warning-bg);
  border-bottom: 2px solid var(--fm-warning);
  color: var(--fm-gray-900);
  font-size: var(--fm-text-base);
}
.fm-clockin-banner__actions { display: inline-flex; gap: var(--fm-space-2); align-items: center; }

/* 20260808.314 - a wider dialog and a textarea with room for prose.
   Wayne: "Make the EDIT box much larger. it has to be able to accommodate
   more prose in the requirements box." TestLabs.TestRequirements is
   varchar(1000) and a single-line input showed roughly 30 characters of
   it. The dialog also grows, because a wider textarea in a 640px box just
   moves the problem. */
.fm-modal__dialog--xwide {
  width: min(1400px, calc(100vw - 32px));
  max-height: 90vh;
}
.fm-textarea-wide {
  width: 100%;
  min-width: 320px;
  resize: vertical;
  font-family: inherit;
  font-size: var(--fm-text-sm);
  line-height: var(--fm-leading-base);
}
