/* CLA Workforce Planner brand stylesheet.
   Extracted from the mock-up at /wfp-tool/index.html.
   Hard brand rules apply: Midnight Blue nav, Convergence headings, Montserrat body,
   no em dashes, no emojis, no Google Fonts at runtime. */

@font-face {
  font-family: 'Convergence';
  src: url('fonts/Convergence-Regular.ttf') format('truetype');
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}

@font-face {
  font-family: 'Montserrat';
  src: url('fonts/Montserrat-VariableFont_wght.ttf') format('truetype-variations');
  font-weight: 100 900;
  font-style: normal;
  font-display: swap;
}

:root {
  /* Session 058 — aligned to the CLA Digital Design Standards v2 published
     by the Resources Hub (claresourceshub.pages.dev/assets/cla-brand.css).
     Core hexes are exact CLA brand codes; tints follow the hub's
     75/50/25/15 scale. Legacy token NAMES are kept and remapped so every
     component rule below picks up the new surfaces without a rewrite. */

  /* Core palette */
  --navy: #034554;
  --navy2: #045a6e;
  --teal: #5ec2a7;
  --teal-dk: #2e8a74;
  --amber: #febc11;
  --amber-dk: #c9960d;
  --lavender: #bbc0e2;
  --lav-dk: #5a5f91;

  /* Tints - 75 / 50 / 25 / 15 (hub scale) */
  --navy-75: #42737f;
  --navy-50: #81a2aa;
  --navy-25: #c0d1d4;
  --navy-15: #d9e4e6;
  --teal-75: #86d1bd;
  --teal-50: #afe0d3;
  --teal-25: #d7f0e9;
  --teal-15: #e7f6f2;
  --lav-75: #ccd0e9;
  --lav-50: #dde0f0;
  --lav-25: #ecedf7;
  --lav-15: #f4f5fa;
  --amber-75: #fecd4d;
  --amber-50: #ffde88;
  --amber-25: #ffefc4;
  --amber-15: #fff5dc;

  /* Surfaces (hub: neutral grey page, lavender-25 borders) */
  --page-bg: #f4f4f6;
  --line: #ecedf7;
  --paper: #ffffff;

  /* Legacy aliases - the names this stylesheet and the modules use */
  --teal-lt: var(--teal-15);
  --amber-lt: var(--amber-15);
  --lav-lt: var(--lav-15);
  --cream: var(--amber-15);
  --sand: var(--page-bg);
  --border: var(--line);

  /* Text (hub: primary text is midnight blue) */
  --text: #034554;
  --muted: #42737f;
  --hint: #81a2aa;
  --red: #b53535;
  --red-lt: #fbe9e9;

  --r-sm: 6px;
  --r-md: 8px;
  --r-lg: 14px;
  --sh-sm: 0 1px 2px rgba(3, 69, 84, 0.06);
  --sh-md: 0 4px 14px rgba(3, 69, 84, 0.06);
  --sh-lg: 0 10px 28px rgba(3, 69, 84, 0.10);
  --ff-head: 'Convergence', 'Avenir Next', Arial, system-ui, sans-serif;
  --ff-body: 'Montserrat', 'Avenir Next', Arial, system-ui, sans-serif;
}

* {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}

body {
  font-family: var(--ff-body);
  font-weight: 300;
  background: var(--sand);
  color: var(--text);
  line-height: 1.55;
  /* Sprint 33 readability: a touch of tracking opens up Montserrat at body
     weight. Elements that set their own letter-spacing (nav, badges, eyebrows)
     still override this base. */
  letter-spacing: 0.3px;
  -webkit-font-smoothing: antialiased;
}

h1, h2, h3, h4, h5 {
  font-family: var(--ff-head);
  font-weight: 400;
  color: var(--navy);
  line-height: 1.2;
  /* Sprint 33 readability: slightly more tracking on headings. */
  letter-spacing: 0.5px;
}

a {
  color: var(--teal-dk);
  text-decoration: none;
  border-bottom: 1px dotted var(--teal);
}

a:hover {
  color: var(--navy);
}

/* Top bar */
.topbar {
  background: var(--paper);
  border-bottom: 1px solid var(--border);
  height: 64px;
  display: flex;
  align-items: center;
  padding: 0 24px;
  gap: 16px;
  position: sticky;
  top: 0;
  z-index: 100;
}

.tb-logo {
  display: flex;
  align-items: center;
  gap: 12px;
}

/* Session 058 — the real CLA logo lockup (icon + Asdaen wordmark) replaces
   the placeholder CL circle, following the Resources Hub global header
   pattern: logo image, 1px divider, uppercase tool label. */
.tb-logo .tb-mark {
  height: 40px;
  width: auto;
  display: block;
  flex-shrink: 0;
}

.tb-divider {
  width: 1px;
  height: 28px;
  background: var(--border);
  flex-shrink: 0;
}

.tb-logo .name {
  font-family: var(--ff-body);
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--navy);
  white-space: nowrap;
}

@media (max-width: 720px) {
  .tb-logo .tb-mark { height: 30px; }
}

@media (max-width: 480px) {
  /* The wide lockup owns the brand moment on small screens; the divider
     and tool label step aside so the topbar never forces sideways scroll. */
  .tb-divider,
  .tb-logo .name { display: none; }
}

.tb-spacer {
  flex: 1;
}

.tb-badge {
  display: inline-flex;
  align-items: center;
  padding: 5px 12px;
  border-radius: 999px;
  background: var(--lav-lt);
  color: var(--lav-dk);
  font-size: 10.5px;
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
}

/* Session 23 — Unsaved changes pill.
   Sits in the topbar between the spacer and the service switcher. Hidden
   by default (the [hidden] attribute), shown when WFPState.isDirty()
   transitions to true. Amber/warning palette so it reads as a hint, not
   a hard error. */
.tb-unsaved {
  display: inline-flex;
  align-items: center;
  padding: 5px 12px;
  margin-right: 10px;
  border-radius: 999px;
  background: #fff4d6;
  color: #7a5400;
  border: 1px solid #f2c25a;
  font-size: 11.5px;
  font-weight: 600;
  letter-spacing: 0.02em;
}
.tb-unsaved[hidden] {
  display: none;
}

/* Hero block */
.hero {
  max-width: 960px;
  margin: 60px auto 36px;
  padding: 48px 36px;
  background: linear-gradient(180deg, var(--cream) 0%, var(--paper) 100%);
  border: 1px solid var(--border);
  border-radius: var(--r-lg);
}

.hero .eyebrow {
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--teal-dk);
  margin-bottom: 14px;
}

.hero h1 {
  font-size: 36px;
  margin-bottom: 14px;
}

.hero .lede {
  font-size: 16px;
  color: var(--text);
  max-width: 720px;
  line-height: 1.6;
}

.hero .actions {
  margin-top: 22px;
  display: flex;
  gap: 10px;
  flex-wrap: wrap;
}

.btn {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 10px 18px;
  border-radius: var(--r-md);
  border: 1px solid var(--border);
  background: var(--paper);
  font-family: var(--ff-body);
  font-size: 13.5px;
  font-weight: 500;
  color: var(--navy);
  cursor: pointer;
  transition: all .15s;
}

.btn[hidden] {
  display: none;
}

.btn:hover {
  background: var(--cream);
  border-color: var(--teal);
}

.btn.primary {
  background: var(--navy);
  color: var(--paper);
  border-color: var(--navy);
}

.btn.primary:hover {
  background: var(--navy2);
  color: var(--paper);
}

/* Status panel */
.status-wrap {
  max-width: 960px;
  margin: 0 auto 60px;
  padding: 0 24px;
}

.status-card {
  background: var(--paper);
  border: 1px solid var(--border);
  border-radius: var(--r-lg);
  padding: 28px 32px;
  margin-bottom: 18px;
}

.status-card h2 {
  font-size: 22px;
  margin-bottom: 8px;
  padding-bottom: 10px;
  border-bottom: 2px solid var(--teal);
}

.status-card p {
  font-size: 14px;
  line-height: 1.6;
  color: var(--text);
  margin-bottom: 8px;
}

.status-list {
  margin: 14px 0 4px 0;
  list-style: none;
}

.status-list li {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 10px 0;
  border-bottom: 1px solid var(--border);
  font-size: 13.5px;
}

.status-list li:last-child {
  border-bottom: none;
}

.status-list .item-label {
  flex: 1;
  color: var(--text);
}

.status-list .item-target {
  color: var(--muted);
  font-size: 12px;
  font-family: 'Consolas', 'Courier New', monospace;
}

.status-pill {
  display: inline-flex;
  align-items: center;
  padding: 3px 10px;
  border-radius: 999px;
  background: var(--teal-lt);
  color: var(--teal-dk);
  font-size: 10.5px;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
}

.status-pill.amber {
  background: var(--amber-lt);
  color: var(--amber-dk);
}

.frame {
  background: var(--paper);
  border: 1px solid var(--border);
  border-left: 3px solid var(--teal);
  padding: 14px 18px;
  border-radius: var(--r-md);
  margin: 18px 0;
  font-size: 13.5px;
  line-height: 1.6;
}

.frame.teal {
  border-left-color: var(--teal);
}

.frame strong {
  color: var(--navy);
  font-weight: 600;
}

/* Footer */
.foot {
  padding: 24px 24px;
  color: var(--muted);
  font-size: 11.5px;
  border-top: 1px solid var(--border);
  background: var(--paper);
  text-align: center;
}

.foot .foot-logo {
  font-family: var(--ff-head);
  color: var(--navy);
  font-size: 13px;
  margin-bottom: 4px;
}

.foot .foot-by {
  color: var(--muted);
}

/* ============================================================
   Session 5 — auth + app shell
   ============================================================ */

/* Auth screens (login.html, forgot.html) */
.auth-wrap {
  max-width: 440px;
  margin: 60px auto 36px;
  padding: 0 24px;
}

.auth-card {
  background: var(--paper);
  border: 1px solid var(--border);
  border-radius: var(--r-lg);
  padding: 32px 32px 28px;
}

.auth-card .auth-eyebrow {
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--teal-dk);
  margin-bottom: 12px;
}

.auth-card h1 {
  font-size: 26px;
  margin-bottom: 8px;
}

.auth-card .auth-sub {
  font-size: 13.5px;
  color: var(--muted);
  margin-bottom: 22px;
  line-height: 1.55;
}

.auth-form .field {
  margin-bottom: 14px;
}

.auth-form .field label {
  display: block;
  font-size: 10.5px;
  font-weight: 700;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--muted);
  margin-bottom: 5px;
}

.auth-form .field input {
  width: 100%;
  padding: 11px 13px;
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  font-family: var(--ff-body);
  font-size: 14px;
  color: var(--text);
  background: var(--paper);
  outline: none;
}

.auth-form .field input:focus {
  border-color: var(--teal);
}

.auth-form .submit-row {
  margin-top: 18px;
}

.auth-form button[type="submit"] {
  width: 100%;
  padding: 12px 18px;
  border-radius: var(--r-md);
  background: var(--navy);
  color: var(--paper);
  border: 1px solid var(--navy);
  font-family: var(--ff-body);
  font-size: 14px;
  font-weight: 600;
  cursor: pointer;
  transition: background .15s;
}

.auth-form button[type="submit"]:hover {
  background: var(--navy2);
}

.auth-form button[type="submit"]:disabled {
  background: var(--hint);
  border-color: var(--hint);
  cursor: not-allowed;
}

.auth-alt {
  margin-top: 18px;
  display: flex;
  flex-direction: column;
  gap: 6px;
  font-size: 12.5px;
  color: var(--muted);
}

.auth-alt a {
  color: var(--teal-dk);
  text-decoration: none;
  border-bottom: 1px dotted var(--teal);
}

.auth-alt a:hover {
  color: var(--navy);
}

.auth-msg {
  margin-top: 16px;
  padding: 12px 14px;
  border-radius: var(--r-sm);
  font-size: 13px;
  line-height: 1.5;
  display: none;
}

.auth-msg.show {
  display: block;
}

.auth-msg.error {
  background: var(--red-lt);
  color: var(--red);
  border-left: 4px solid var(--red);
}

.auth-msg.success {
  background: var(--teal-lt);
  color: var(--teal-dk);
  border-left: 4px solid var(--teal);
}

.auth-msg.info {
  background: var(--cream);
  color: var(--navy);
  border-left: 4px solid var(--amber);
}

/* ============================================================
   App shell (app.html)
   ============================================================ */

.tb-svc {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 8px 14px;
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  background: var(--cream);
  font-size: 12.5px;
  color: var(--navy);
}

.tb-svc strong {
  font-weight: 600;
}

.tb-svc .dot-svc {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--teal);
  display: inline-block;
  flex-shrink: 0;
}

.tb-svc-select {
  position: relative;
}

.tb-svc-select select {
  appearance: none;
  background: transparent;
  border: none;
  color: var(--navy);
  font-family: var(--ff-body);
  font-size: 12.5px;
  font-weight: 600;
  padding: 0 18px 0 0;
  outline: none;
  cursor: pointer;
}

.tb-svc-select::after {
  content: '';
  position: absolute;
  right: 0;
  top: 50%;
  width: 8px;
  height: 8px;
  border-right: 2px solid var(--navy);
  border-bottom: 2px solid var(--navy);
  transform: translateY(-70%) rotate(45deg);
  pointer-events: none;
}

.tb-btn {
  padding: 9px 16px;
  border-radius: var(--r-md);
  border: 1px solid var(--border);
  background: var(--paper);
  font-family: var(--ff-body);
  font-size: 13px;
  font-weight: 500;
  color: var(--navy);
  cursor: pointer;
  transition: all .15s;
}

.tb-btn:hover {
  background: var(--cream);
  border-color: var(--teal);
}

.tb-btn.ghost {
  border-color: transparent;
  background: transparent;
}

.tb-btn.ghost:hover {
  background: var(--cream);
}

/* Layout — sidebar + main.
   Sprint 9: the main track is minmax(0, 1fr), not bare 1fr. A bare 1fr
   track has an auto minimum, so any wide descendant (the 900px monthly
   counts matrix on the Children screen, say) propagated its min-content
   width up through the shell and forced the whole document to scroll
   horizontally on a phone, defeating the overflow-x scrollers
   (.matrix-wrap, .dt-scroll) that are meant to contain those tables.
   Flooring the track at 0 lets main shrink to the viewport so the inner
   scroll containers actually scroll. */
.app {
  display: grid;
  grid-template-columns: 240px minmax(0, 1fr);
  min-height: calc(100vh - 64px);
}

.side {
  background: var(--paper);
  border-right: 1px solid var(--border);
  padding: 22px 14px;
}

.side-section {
  margin-bottom: 22px;
}

.side-label {
  font-size: 10.5px;
  font-weight: 700;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--teal);
  padding: 0 10px 8px;
}

.side-link {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 9px 12px;
  border-radius: var(--r-md);
  font-size: 13.5px;
  color: var(--text);
  cursor: pointer;
  transition: all .15s;
  margin-bottom: 2px;
  background: transparent;
  border: none;
  width: 100%;
  text-align: left;
  font-family: var(--ff-body);
  text-decoration: none;
}

.side-link:hover {
  background: var(--lav-15);
  color: var(--navy);
}

.side-link.active {
  background: var(--navy);
  color: var(--paper);
}

.side-link.active .side-num {
  background: var(--teal);
  color: var(--paper);
}

.side-num {
  width: 22px;
  height: 22px;
  border-radius: 50%;
  background: var(--lav-15);
  color: var(--navy);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 11px;
  font-weight: 700;
  flex-shrink: 0;
}

.side-link .badge-mini {
  margin-left: auto;
  padding: 2px 7px;
  border-radius: 10px;
  background: var(--red-lt);
  color: var(--red);
  font-size: 10px;
  font-weight: 700;
}

.side-link.active .badge-mini {
  background: var(--paper);
  color: var(--navy);
}

.main {
  padding: 28px 36px 80px;
  max-width: 1280px;
}

.pg-title {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 24px;
  margin-bottom: 8px;
  flex-wrap: wrap;
}

.pg-title h1 {
  font-size: 28px;
}

.pg-heading-row {
  display: flex;
  align-items: center;
  gap: 12px;
}

.pg-icon {
  width: 28px;
  height: 28px;
  flex-shrink: 0;
  color: var(--navy);
  display: inline-block;
}

.pg-icon use {
  pointer-events: none;
}

.pg-title .sub {
  color: var(--muted);
  font-size: 14px;
  margin-top: 6px;
  max-width: 700px;
}

.pg-divider {
  height: 1px;
  background: var(--border);
  margin: 22px 0;
}

.module-stub {
  background: var(--paper);
  border: 1px dashed var(--border);
  border-radius: var(--r-lg);
  padding: 32px;
  margin-top: 18px;
  text-align: center;
  color: var(--muted);
  font-size: 13.5px;
  line-height: 1.6;
}

.module-stub strong {
  display: block;
  font-family: var(--ff-head);
  color: var(--navy);
  font-size: 16px;
  margin-bottom: 6px;
}

/* Sprint 10 — shared load-error panel (wfp-load-error.js). Inherits the
   .module-stub frame; these rules only space the body copy, the muted
   Detail line, and the Try again button that replaced the dead-end error
   stubs each module used to paint. */
.load-error-panel .load-error-body {
  margin: 0 auto;
  max-width: 520px;
}

.load-error-panel .load-error-detail {
  margin: 10px auto 0;
  font-size: 12px;
  color: var(--muted);
}

.load-error-panel .btn {
  margin-top: 16px;
}

.role-tag {
  display: inline-block;
  padding: 3px 10px;
  border-radius: 999px;
  background: var(--lav-lt);
  color: var(--lav-dk);
  font-size: 10.5px;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  margin-top: 10px;
}

.role-tag.owner {
  background: var(--teal-lt);
  color: var(--teal-dk);
}

.role-tag.admin {
  background: var(--amber-lt);
  color: var(--amber-dk);
}

/* Session 29 — role-tag now lives in the topbar so it persists across
   module mounts. Topbar context overrides the stub-context margin. */
.role-tag.tb-role {
  margin-top: 0;
  align-self: center;
}

/* Responsive shell: collapse sidebar to top on narrow screens.
   Sprint 9: minmax(0, 1fr) for the same reason as the desktop shell —
   wide tables must scroll inside their wrappers, not stretch the page. */
@media (max-width: 720px) {
  .app {
    grid-template-columns: minmax(0, 1fr);
  }
  .side {
    border-right: none;
    border-bottom: 1px solid var(--border);
    padding: 14px;
  }
  .side-section {
    margin-bottom: 14px;
  }
  /* Sprint 9: the topbar is a fixed-height no-wrap flex row, so on a phone
     the service tag, role tag, Sign out button and prototype badge ran
     past the right edge and scrolled the whole document sideways. Let it
     wrap onto extra lines instead. */
  .topbar {
    flex-wrap: wrap;
    height: auto;
    min-height: 64px;
    padding: 10px 14px;
    gap: 10px 12px;
  }
  /* The shell min-height assumes the 64px topbar; once the topbar can wrap
     taller, that calc overshoots and short pages grow a permanent vertical
     scrollbar. Let the content set its own height on phones. */
  .app {
    min-height: auto;
  }
}

/* ============================================================
   Session 7 — Service Setup module
   Matches the row-3 / row-4 grid pattern from the mock-up.
   ============================================================ */

.card {
  background: var(--paper);
  border: 1px solid var(--border);
  border-radius: var(--r-lg);
  padding: 22px;
  margin-bottom: 18px;
}

.card h3 {
  font-family: var(--ff-head);
  color: var(--navy);
  font-size: 18px;
  margin: 0 0 6px;
}

.card .card-sub {
  color: var(--muted);
  font-size: 13px;
  margin-bottom: 16px;
}

.row-2 {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 14px;
}

.row-3 {
  display: grid;
  grid-template-columns: 1fr 1fr 1fr;
  gap: 14px;
}

.row-4 {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 14px;
}

@media (max-width: 720px) {
  .row-2, .row-3, .row-4 {
    grid-template-columns: 1fr;
  }
}

.field {
  margin-bottom: 14px;
}

.field label {
  display: block;
  font-size: 10.5px;
  font-weight: 700;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--muted);
  margin-bottom: 5px;
}

.field input,
.field select,
.field textarea {
  width: 100%;
  padding: 10px 12px;
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  font-family: var(--ff-body);
  font-size: 13.5px;
  color: var(--text);
  background: var(--paper);
  outline: none;
  box-sizing: border-box;
}

.field input:focus,
.field select:focus,
.field textarea:focus {
  border-color: var(--teal);
  box-shadow: 0 0 0 3px var(--teal-lt);
}

.field .hint {
  font-size: 11.5px;
  color: var(--hint);
  margin-top: 4px;
}

.toggle-row {
  display: flex;
  gap: 8px;
  flex-wrap: wrap;
  margin-top: 6px;
}

.toggle {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 6px 12px;
  border-radius: 999px;
  background: var(--cream);
  color: var(--muted);
  border: 1px solid var(--border);
  font-family: var(--ff-body);
  font-size: 12px;
  font-weight: 500;
  cursor: pointer;
}

.toggle:hover {
  border-color: var(--teal);
}

.toggle.on {
  background: var(--teal-lt);
  color: var(--teal-dk);
  border-color: var(--teal);
  font-weight: 600;
}

table.dt {
  width: 100%;
  border-collapse: collapse;
  font-size: 13px;
}

table.dt thead th {
  text-align: left;
  padding: 10px 12px;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.07em;
  text-transform: uppercase;
  color: var(--muted);
  border-bottom: 1px solid var(--border);
  background: var(--sand);
}

table.dt tbody td {
  padding: 11px 12px;
  border-bottom: 1px solid var(--border);
  vertical-align: top;
}

table.dt tbody tr:hover td {
  background: var(--cream);
}

.setup-actions {
  display: flex;
  gap: 10px;
  align-items: center;
  margin-top: 18px;
}

.setup-status {
  font-size: 12.5px;
  color: var(--muted);
  margin-left: 8px;
}

.setup-status-ok {
  color: var(--teal-dk);
  font-weight: 600;
}

.setup-status-err {
  color: #a02a1a;
  font-weight: 600;
}

.btn[disabled] {
  opacity: 0.5;
  cursor: not-allowed;
}

/* ============================================================
   Session 9 — editable Rooms editor
   Inline-editable inputs sit inside the standard .dt table.
   ============================================================ */

table.dt.dt-editable thead th.rm-actions-col {
  width: 1%;
  white-space: nowrap;
}

table.dt.dt-editable tbody td {
  padding: 8px 10px;
  vertical-align: middle;
}

.rm-input {
  width: 100%;
  padding: 7px 9px;
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  font-family: var(--ff-body);
  font-size: 13px;
  color: var(--text);
  background: var(--paper);
  outline: none;
  box-sizing: border-box;
}

.rm-input:focus {
  border-color: var(--teal);
  box-shadow: 0 0 0 3px var(--teal-lt);
}

.rm-input[disabled],
.rm-input[data-readonly="1"] {
  background: var(--cream);
  color: var(--muted);
  cursor: not-allowed;
}

.rm-ratio {
  display: inline-block;
  font-weight: 600;
  color: var(--navy);
  font-variant-numeric: tabular-nums;
}

/* Sprint 11 — column-level note under the Rooms table explaining that the
   daily fee bills every child in the room. The .field .hint rule cannot
   reach it (no .field wrapper in a table footer), so it restates the same
   typography. */
.rm-fee-hint {
  font-size: 11.5px;
  color: var(--hint);
  margin-top: 6px;
}

.rm-actions {
  margin-top: 14px;
  display: flex;
  gap: 10px;
  align-items: center;
}

.rm-actions-cell {
  text-align: right;
  width: 1%;
  white-space: nowrap;
}

.btn.btn-row {
  padding: 6px 12px;
  font-size: 12px;
  border-radius: var(--r-md);
}

.btn.btn-ghost {
  background: var(--paper);
  color: var(--muted);
  border-color: var(--border);
}

.btn.btn-ghost:hover {
  background: var(--cream);
  color: var(--navy);
  border-color: var(--teal);
}

@media (max-width: 900px) {
  table.dt.dt-editable thead th,
  table.dt.dt-editable tbody td {
    padding: 6px 8px;
  }
  .rm-input {
    padding: 6px 7px;
    font-size: 12.5px;
  }
}

/* ============================================================
   Session 10 — Forward Occupancy: pills, matrix table, children
   editor styles. Inputs use the same .dt.dt-editable backbone
   as the Rooms editor so the two read as one design system.
   ============================================================ */

.pill {
  display: inline-block;
  padding: 2px 9px;
  border-radius: 10px;
  font-size: 10.5px;
  font-weight: 600;
  letter-spacing: 0.02em;
}
.pill-ect    { background: #ecedf7; color: var(--lav-dk); }
.pill-dip    { background: var(--teal-lt); color: var(--teal-dk); }
.pill-cert   { background: var(--amber-lt); color: var(--amber-dk); }
.pill-trainee{ background: var(--cream); color: var(--navy); }
.pill-support{ background: var(--sand); color: var(--muted); }
/* Session 077 — honest empty state for a qualification EH (or a person)
   never supplied. Deliberately the quietest pill in the palette: a hairline
   border on a plain background reads as "nothing recorded here yet" rather
   than competing with the real qualification colours. */
.pill-notset { background: transparent; color: var(--muted); border: 1px solid var(--sand); }

/* Session 39 — invitation status pills. Teal for accepted (positive,
   terminal state); cream for pending (neutral, waiting). Dedicated class
   names so the User Management table is not coupled to the qualification
   pill palette above. */
.pill-status-accepted { background: var(--teal-lt); color: var(--teal-dk); }
.pill-status-pending  { background: var(--cream); color: var(--navy); }

.ch-pill {
  display: inline-block;
  margin-left: 6px;
  vertical-align: middle;
}

.ch-input {
  width: 100%;
  padding: 7px 9px;
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  font-family: var(--ff-body);
  font-size: 13px;
  color: var(--text);
  background: var(--paper);
  outline: none;
  box-sizing: border-box;
}

.ch-input:focus {
  border-color: var(--teal);
  box-shadow: 0 0 0 3px var(--teal-lt);
}

.ch-input[disabled],
.ch-input[data-readonly="1"] {
  background: var(--cream);
  color: var(--muted);
  cursor: not-allowed;
}

.ch-room {
  display: inline-block;
  font-weight: 500;
  color: var(--navy);
  font-variant-numeric: tabular-nums;
}

.ch-actions {
  margin-top: 14px;
  display: flex;
  gap: 14px;
  align-items: center;
  flex-wrap: wrap;
}

/* Session 27 FE review — Staffing Register Save UX bug.
   The bottom-of-form Save button (#staffing-save) sits past the supply
   summary and wage cost cards, so a long staff list pushes it out of
   view. Duplicating the Save button into the table card's footer row
   keeps a save action reachable from where the user is editing. The
   primary button is right-aligned so it visually anchors the row and
   reads as the resolution of the table edit cluster. */
.staffing-table-save {
  margin-left: auto;
}

.ch-actions-cell {
  text-align: right;
  width: 1%;
  white-space: nowrap;
}

.ch-actions-col {
  width: 1%;
  white-space: nowrap;
}

.ch-count {
  color: var(--muted);
  font-size: 12.5px;
}

.children-actions {
  display: flex;
  gap: 10px;
  align-items: center;
  margin-top: 18px;
}

.children-status {
  font-size: 12.5px;
  color: var(--muted);
  margin-left: 8px;
}

.children-status-ok {
  color: var(--teal-dk);
  font-weight: 600;
}

.children-status-err {
  color: #a02a1a;
  font-weight: 600;
}

/* Sprint 2 — children register flags and manual overrides.
   ch-room-manual marks a projection cell driven by a manual band override
   (amber left border so auto vs manual reads at a glance). The pills reuse
   the .pill backbone: kindy eligibility is teal (informational), the manual
   marker is amber (matches the override border), the school start flag is
   cream on navy (neutral forward planning flag). */
.ch-room-manual {
  border-left: 3px solid var(--amber-dk);
  padding-left: 8px;
}

.pill.ch-pill-kindy {
  background: var(--teal-lt);
  color: var(--teal-dk);
  margin-left: 6px;
}

.pill.ch-pill-manual {
  background: var(--amber-lt);
  color: var(--amber-dk);
  margin-left: 6px;
}

.pill.ch-pill-school {
  background: var(--cream);
  color: var(--navy);
  margin-left: 6px;
}

/* The Override column stacks a compact band select over the repeating-kindy
   tick. min-width keeps the select labels ("36 to 47 months") on one line. */
.ch-override-cell {
  min-width: 160px;
}

.ch-override-cell .ch-repeat {
  display: flex;
  align-items: center;
  gap: 6px;
  margin-top: 6px;
  font-size: 12px;
  color: var(--muted);
  white-space: nowrap;
  cursor: pointer;
}

.matrix-wrap {
  overflow-x: auto;
  border: 1px solid var(--border);
  border-radius: var(--r-lg);
  background: var(--paper);
  margin-top: 6px;
}

table.mx {
  width: 100%;
  border-collapse: collapse;
  font-size: 12.5px;
  min-width: 900px;
}

table.mx thead th {
  background: var(--lav-15);
  padding: 10px 8px;
  text-align: center;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--navy);
  border-bottom: 1px solid var(--border);
}

table.mx thead th.metric-col {
  text-align: left;
  padding-left: 16px;
  min-width: 200px;
  background: var(--paper);
}

table.mx td {
  padding: 8px 6px;
  text-align: center;
  border-bottom: 1px solid var(--border);
}

table.mx td.metric {
  text-align: left;
  padding-left: 16px;
  font-weight: 500;
  color: var(--navy);
}

table.mx tbody tr:hover td {
  background: var(--sand);
}

.module-note {
  padding: 14px 16px;
  color: var(--muted);
  font-size: 13px;
  background: var(--sand);
  border: 1px solid var(--border);
  border-radius: var(--r-md);
}

/* Sprint 32 — Calculations explainer page. Each formula is a block: a
   plain-English lead, the formula in a monospace strip, a worked example,
   and a source reference. Reads top to bottom like a reference sheet. */
.calc-docs .calc-block {
  padding: 16px 0;
  border-top: 1px solid var(--line);
}
.calc-docs .calc-block:first-of-type { border-top: none; }
.calc-docs .calc-block h3 {
  margin: 0 0 6px;
  color: var(--teal-dk);
  font-size: 16px;
}
.calc-docs .calc-plain {
  margin: 0 0 10px;
  color: var(--ink, #1d2433);
  font-size: 14px;
  line-height: 1.55;
}
.calc-docs .calc-formula {
  padding: 10px 12px;
  margin: 0 0 10px;
  background: var(--teal-15);
  border-left: 3px solid var(--teal);
  border-radius: var(--r-sm, 6px);
  font-family: 'Consolas', 'Courier New', monospace;
  font-size: 13px;
  color: var(--teal-dk);
}
.calc-docs .calc-example {
  margin: 0 0 8px;
  color: var(--muted);
  font-size: 13px;
  line-height: 1.5;
}
.calc-docs .calc-source {
  color: var(--muted);
  font-size: 12px;
  font-style: italic;
}

/* Sprint 31 — small info marker that surfaces an explanation on hover or
   focus via its title attribute. Keeps the column header compact while the
   detail stays one pointer away. */
.info-icon {
  display: inline-block;
  margin-left: 4px;
  width: 15px;
  height: 15px;
  line-height: 15px;
  text-align: center;
  font-size: 10px;
  font-style: normal;
  font-weight: 700;
  color: var(--teal, #0f766e);
  border: 1px solid currentColor;
  border-radius: 50%;
  cursor: help;
}
.info-icon:focus { outline: 2px solid var(--teal, #0f766e); outline-offset: 1px; }

/* Sprint 33 — collapsible registers. The Staffing and Children registers can
   collapse to an overview row so the Health Check tiles below sit above the
   fold on a long list. The toggle lives in the card head; the table, notes and
   bottom actions live in .register-body and hide when the card is collapsed.
   The .register-quickstats overview only shows in the collapsed state. */
.register-quickstats {
  display: none;
}
.register-collapsed .register-body {
  display: none;
}
.register-collapsed .register-quickstats {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 6px 18px;
  margin-top: 4px;
}
.register-quickstats .quickstats-count {
  font-weight: 700;
  color: var(--navy);
}
.register-quickstats .quickstats-break {
  color: var(--muted, #64748b);
}

/* Sprint 33 — qualitative gaps readability. The four Gap Plan reflection
   fields render at a larger size with comfortable line height so the AI draft
   is easy to read and edit. */
.qual-gap-field input {
  font-size: 16px;
  line-height: 1.5;
  color: var(--text);
}

.card-head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 16px;
  margin-bottom: 10px;
}

.card-actions {
  display: flex;
  gap: 8px;
  /* Session 24 FE review — the Staffing card now carries four buttons
     (Export, Edit all, Import, Add staff) in this row. Without wrap the
     fourth button overflows on tablet and below. Wrap onto a second line,
     keeping the buttons right-aligned to match the original head row. */
  flex-wrap: wrap;
  justify-content: flex-end;
}

@media (max-width: 900px) {
  /* Sprint 9: the dt-children padding squeeze that used to live here is
     superseded by the labelled grid layout further down, which zeroes td
     padding at every width. */
  .ch-input {
    padding: 6px 7px;
    font-size: 12.5px;
  }
  table.mx {
    font-size: 11.5px;
  }
}

/* ============================================================
   Session 13 - Staffing Register, reworked in Sprint 3,
   extended in Sprint 13 with Role, Award and Classification.
   The old 15-column table sat in a 1320px-wide horizontal
   scroller. It now lays each staff row out as a labelled CSS
   grid over four lines so the whole row is visible on a
   1280px laptop with no horizontal scrolling:
     line 1: Name, Role, Current qual, Working toward, Actions
     line 2: Award, Classification, Expected completion
     line 3: Hours/wk, Hourly rate, Type, Visa expiry, Support,
             AL days, Sick days, RDO days, Study days
     line 4: Notes (full width)
   Each td carries a data-label rendered via ::before in place
   of the column header. The thead stays in the DOM (specs and
   assistive tech) but is visually hidden. .dt-scroll itself is
   shared with the compliance and CLA tables and stays generic.
   ============================================================ */

.dt-scroll {
  overflow-x: auto;
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  background: var(--paper);
}

table.dt.dt-staffing {
  display: block;
  position: relative;
  width: 100%;
}

/* Visually hidden thead: clip pattern keeps it out of the layout while
   the markup (and the spec selectors that reference it) stay intact. */
table.dt.dt-staffing thead {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

table.dt.dt-staffing tbody {
  display: block;
  width: 100%;
}

/* Each staff row is a 12-track grid spanning four logical lines. Sprint 13
   added the role, award and classification cells; Sprint 31 adds the roster
   start and end date cells on the employment line. */
table.dt.dt-staffing tbody tr {
  display: grid;
  grid-template-columns: repeat(12, minmax(0, 1fr));
  grid-template-areas:
    "name name name qual qual upg upg comp comp role role actions"
    "type type hours hours hourly hourly start start end end visa visa"
    "award award award class class class support support al sick rdo study"
    "notes notes notes notes notes notes notes notes notes notes notes notes";
  gap: 10px 12px;
  padding: 12px 14px;
  border-bottom: 1px solid var(--border);
}

table.dt.dt-staffing tbody tr:last-child {
  border-bottom: 0;
}

/* Row hover: the generic table.dt rule paints td backgrounds, which would
   leave the grid gaps unpainted. Paint the whole row instead. */
table.dt.dt-staffing tbody tr:hover {
  background: var(--cream);
}

table.dt.dt-staffing tbody td {
  display: block;
  min-width: 0;
  padding: 0;
  border-bottom: 0;
  vertical-align: middle;
  /* An unbreakable string (a pasted URL in Notes, a long name) must wrap
     inside its cell rather than blowing the grid out into a horizontal
     scroller; minmax(0,1fr) caps the track but not visible overflow. */
  overflow-wrap: anywhere;
}

/* Grid area per cell. nth-child order is pinned by the Playwright specs.
   Sprint 31 inserts Start date and End date between Type and Visa expiry, so
   everything from Visa onward shifts by two:
   1 Name, 2 Current qual, 3 Working toward, 4 Expected completion, 5 Hours/wk,
   6 Hourly, 7 Type, 8 Start date, 9 End date, 10 Visa, 11 Support, 12 AL,
   13 Sick, 14 RDO, 15 Study, 16 Role, 17 Award, 18 Classification, 19 Notes,
   20 Actions. */
table.dt.dt-staffing tbody tr > td:nth-child(1)  { grid-area: name; }
table.dt.dt-staffing tbody tr > td:nth-child(2)  { grid-area: qual; }
table.dt.dt-staffing tbody tr > td:nth-child(3)  { grid-area: upg; }
table.dt.dt-staffing tbody tr > td:nth-child(4)  { grid-area: comp; }
table.dt.dt-staffing tbody tr > td:nth-child(5)  { grid-area: hours; }
table.dt.dt-staffing tbody tr > td:nth-child(6)  { grid-area: hourly; }
table.dt.dt-staffing tbody tr > td:nth-child(7)  { grid-area: type; }
table.dt.dt-staffing tbody tr > td:nth-child(8)  { grid-area: start; }
table.dt.dt-staffing tbody tr > td:nth-child(9)  { grid-area: end; }
table.dt.dt-staffing tbody tr > td:nth-child(10) { grid-area: visa; }
table.dt.dt-staffing tbody tr > td:nth-child(11) { grid-area: support; }
table.dt.dt-staffing tbody tr > td:nth-child(12) { grid-area: al; }
table.dt.dt-staffing tbody tr > td:nth-child(13) { grid-area: sick; }
table.dt.dt-staffing tbody tr > td:nth-child(14) { grid-area: rdo; }
table.dt.dt-staffing tbody tr > td:nth-child(15) { grid-area: study; }
table.dt.dt-staffing tbody tr > td:nth-child(16) { grid-area: role; }
table.dt.dt-staffing tbody tr > td:nth-child(17) { grid-area: award; }
table.dt.dt-staffing tbody tr > td:nth-child(18) { grid-area: class; }
table.dt.dt-staffing tbody tr > td:nth-child(19) { grid-area: notes; }
table.dt.dt-staffing tbody tr > td:nth-child(20) { grid-area: actions; }

/* Per-cell label, replacing the (hidden) column header. Typography matches
   table.dt thead th: small, uppercase, muted, Montserrat body family. */
table.dt.dt-staffing td[data-label]::before {
  content: attr(data-label);
  display: block;
  font-family: var(--ff-body);
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.07em;
  text-transform: uppercase;
  color: var(--muted);
  margin-bottom: 3px;
  white-space: nowrap;
}

table.dt.dt-staffing .ch-input {
  width: 100%;
  padding: 6px 7px;
  font-size: 12.5px;
}

/* Sprint 15 — Expected completion cell notes. The hint sits under the
   disabled date input until a Working toward value is chosen; the nudge
   borrows the warn palette (.flag.warn) when only one half of the upgrade
   pair is set. Both display block and wrap inside the grid track so a
   note can never push the row into a horizontal scroller. */
table.dt.dt-staffing .ch-hint {
  display: block;
  margin-top: 3px;
  font-size: 11px;
  color: var(--muted);
  white-space: normal;
}

table.dt.dt-staffing .st-nudge {
  display: block;
  margin-top: 3px;
  font-size: 11px;
  font-weight: 600;
  color: var(--amber-dk);
  white-space: normal;
}

/* Empty-register placeholder inside the .dt-scroll frame (the hidden thead
   leaves nothing else visible when the register has no rows). */
.st-empty {
  margin: 0;
  padding: 14px;
  border: 0;
}

.st-empty[hidden] {
  display: none;
}

/* Labels sit above values, so the checkbox no longer centres in a column. */
table.dt.dt-staffing .st-support {
  margin: 4px 0 0;
  display: block;
}

/* Qual pill sits under its label, flush left (the generic .ch-pill rule
   indents it to follow inline text). In edit mode it drops below the
   full-width select as a live preview. */
table.dt.dt-staffing .ch-pill {
  margin-left: 0;
  display: inline-block;
  margin-top: 2px;
}

/* Actions cell has no label; buttons keep to the right edge of line 1 and
   wrap rather than forcing the track wider. */
table.dt.dt-staffing .ch-actions-cell {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  align-content: center;
  justify-content: flex-end;
  gap: 6px;
  white-space: normal;
  width: auto;
}

/* Tablet and below: redistribute the areas over four tracks so the row
   stacks deeper instead of squeezing. */
@media (max-width: 900px) {
  table.dt.dt-staffing tbody tr {
    grid-template-columns: repeat(4, minmax(0, 1fr));
    grid-template-areas:
      "name name name actions"
      "role role role role"
      "qual qual upg upg"
      "comp comp type type"
      "award award class class"
      "hours hourly visa support"
      "al sick rdo study"
      "notes notes notes notes";
    gap: 8px 10px;
    padding: 10px 12px;
  }
}

/* Phone: two-column card per staff member. */
@media (max-width: 560px) {
  table.dt.dt-staffing tbody tr {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    grid-template-areas:
      "name name"
      "role role"
      "qual upg"
      "comp type"
      "award award"
      "class class"
      "hours hourly"
      "visa support"
      "al sick"
      "rdo study"
      "notes notes"
      "actions actions";
  }
  table.dt.dt-staffing .ch-actions-cell {
    justify-content: flex-start;
  }
}

/* ============================================================
   Sprint 9 - Children register, name clip fix.
   The children table squeezed 11 columns into the card width
   with no protected width on Name, so child names clipped to a
   few characters at laptop sizes. The table now lays each child
   out as a labelled CSS grid over three lines, the same pattern
   the Sprint 3 staffing register ships:
     line 1: Name, DOB, Status, Days/wk, Start, Actions
     line 2: Now, +6 mths, +12 mths, Override
             (OSHC swaps in Cohort and Sessions)
     line 3: Notes (full width)
   Each td carries a data-label rendered via ::before in place
   of the column header. The thead stays in the DOM (specs read
   its innerText, and assistive tech needs it) but is visually
   hidden via the clip pattern, never display:none.
   ============================================================ */

table.dt.dt-children {
  display: block;
  position: relative;
  width: 100%;
}

/* Visually hidden thead: clip pattern keeps it out of the layout while
   the markup (and the spec selectors that reference it) stay intact. */
table.dt.dt-children thead {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

table.dt.dt-children tbody {
  display: block;
  width: 100%;
}

/* Each child row is a 12-track grid spanning three logical lines. */
table.dt.dt-children tbody tr {
  display: grid;
  grid-template-columns: repeat(12, minmax(0, 1fr));
  gap: 10px 12px;
  padding: 12px 14px;
  border-bottom: 1px solid var(--border);
}

table.dt.dt-children tbody tr:last-child {
  border-bottom: 0;
}

/* Row hover: the generic table.dt rule paints td backgrounds, which would
   leave the grid gaps unpainted. Paint the whole row instead. */
table.dt.dt-children tbody tr:hover {
  background: var(--cream);
}

table.dt.dt-children tbody td {
  display: block;
  min-width: 0;
  padding: 0;
  border-bottom: 0;
  vertical-align: middle;
  /* An unbreakable string (a long name, a pasted URL in Notes) must wrap
     inside its cell rather than blowing the grid out into a horizontal
     scroller; minmax(0,1fr) caps the track but not visible overflow. */
  overflow-wrap: anywhere;
}

/* Standard (room-based) variant: 13 tds. Sprint 11 added the Room select
   after Override; Sprint 31 adds the Est. end date after Start. nth-child
   order is pinned by the Playwright specs:
   1 Name, 2 DOB, 3 Status, 4 Days/wk, 5 Start, 6 Est. end, 7 Now, 8 +6 mths,
   9 +12 mths, 10 Override, 11 Room, 12 Notes, 13 Actions. */
table.dt.dt-children:not(.dt-children-oshc) tbody tr {
  /* Name takes four tracks: three tracks left "Bartholomew
     Featherstonehaugh" clipping by 15px at 1280, the exact bug this
     sprint exists to fix.
     Status gives up the track; its select shrinks cleanly and the pill
     wraps below.
     Sprint 11: the middle line fits Room by trimming each projection cell
     to two tracks. Projection content is a short label plus pills, and
     pills already wrap below the label, so nothing clips at 1280; the
     Override and Room cells keep three tracks each for their selects. */
  /* Sprint 31: Name keeps its four protected tracks (the clip fix), so the
     new Est. end date pairs with Start on line 1 and the actions button
     moves to the end of the notes line to make room. */
  grid-template-areas:
    "name name name name dob dob status days start start estend estend"
    "now now plus6 plus6 plus12 plus12 override override override room room room"
    "notes notes notes notes notes notes notes notes notes notes actions actions";
}

table.dt.dt-children:not(.dt-children-oshc) tbody tr > td:nth-child(1)  { grid-area: name; }
table.dt.dt-children:not(.dt-children-oshc) tbody tr > td:nth-child(2)  { grid-area: dob; }
table.dt.dt-children:not(.dt-children-oshc) tbody tr > td:nth-child(3)  { grid-area: status; }
table.dt.dt-children:not(.dt-children-oshc) tbody tr > td:nth-child(4)  { grid-area: days; }
table.dt.dt-children:not(.dt-children-oshc) tbody tr > td:nth-child(5)  { grid-area: start; }
table.dt.dt-children:not(.dt-children-oshc) tbody tr > td:nth-child(6)  { grid-area: estend; }
table.dt.dt-children:not(.dt-children-oshc) tbody tr > td:nth-child(7)  { grid-area: now; }
table.dt.dt-children:not(.dt-children-oshc) tbody tr > td:nth-child(8)  { grid-area: plus6; }
table.dt.dt-children:not(.dt-children-oshc) tbody tr > td:nth-child(9)  { grid-area: plus12; }
table.dt.dt-children:not(.dt-children-oshc) tbody tr > td:nth-child(10) { grid-area: override; }
table.dt.dt-children:not(.dt-children-oshc) tbody tr > td:nth-child(11) { grid-area: room; }
table.dt.dt-children:not(.dt-children-oshc) tbody tr > td:nth-child(12) { grid-area: notes; }
table.dt.dt-children:not(.dt-children-oshc) tbody tr > td:nth-child(13) { grid-area: actions; }

/* OSHC variant: 10 tds (Cohort + Sessions replace the projection and
   Override cells). Sprint 31 adds Est. end after Start. 1 Name, 2 DOB,
   3 Status, 4 Days/wk, 5 Start, 6 Est. end, 7 Cohort, 8 Sessions, 9 Notes,
   10 Actions. */
table.dt.dt-children.dt-children-oshc tbody tr {
  /* Line 1 matches the standard variant: Name keeps its protected tracks
     here too. */
  grid-template-areas:
    "name name name name dob dob status days start start estend estend"
    "cohort cohort cohort sessions sessions sessions sessions sessions sessions sessions sessions sessions"
    "notes notes notes notes notes notes notes notes notes notes actions actions";
}

table.dt.dt-children.dt-children-oshc tbody tr > td:nth-child(1) { grid-area: name; }
table.dt.dt-children.dt-children-oshc tbody tr > td:nth-child(2) { grid-area: dob; }
table.dt.dt-children.dt-children-oshc tbody tr > td:nth-child(3) { grid-area: status; }
table.dt.dt-children.dt-children-oshc tbody tr > td:nth-child(4) { grid-area: days; }
table.dt.dt-children.dt-children-oshc tbody tr > td:nth-child(5) { grid-area: start; }
table.dt.dt-children.dt-children-oshc tbody tr > td:nth-child(6) { grid-area: estend; }
table.dt.dt-children.dt-children-oshc tbody tr > td:nth-child(7) { grid-area: cohort; }
table.dt.dt-children.dt-children-oshc tbody tr > td:nth-child(8) { grid-area: sessions; }
table.dt.dt-children.dt-children-oshc tbody tr > td:nth-child(9) { grid-area: notes; }
table.dt.dt-children.dt-children-oshc tbody tr > td:nth-child(10) { grid-area: actions; }

/* The td-level overflow-wrap: anywhere would break pill words mid-letter
   in the narrow Status track ("Curren / t"). Pills are short labels; keep
   each on one line and let the pill itself wrap below its input instead. */
table.dt.dt-children .pill {
  white-space: nowrap;
}

/* Per-cell label, replacing the (hidden) column header. Typography matches
   table.dt thead th: small, uppercase, muted, Montserrat body family. */
table.dt.dt-children td[data-label]::before {
  content: attr(data-label);
  display: block;
  font-family: var(--ff-body);
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.07em;
  text-transform: uppercase;
  color: var(--muted);
  margin-bottom: 3px;
  white-space: nowrap;
}

table.dt.dt-children .ch-input {
  width: 100%;
  padding: 6px 7px;
  font-size: 12.5px;
}

/* Empty-register placeholder under the table (the hidden thead leaves
   nothing visible at all when the register has no rows). */
.ch-empty[hidden] {
  display: none;
}

/* The global .ch-override-cell min-width (160px, keeps the band labels on
   one line in plain column tables) could force a 12-track row wider than
   the card on narrow screens. The grid hands the Override cell three
   tracks, which is plenty, so relax the floor inside the grid only; the
   global rule stays for any other context. */
table.dt.dt-children .ch-override-cell {
  min-width: 0;
}

/* The repeating-kindy label is nowrap globally; inside a grid track let
   it wrap rather than overflow when the track runs tight. */
table.dt.dt-children .ch-repeat {
  white-space: normal;
}

/* Sprint 11 — per-child Room select. An explicit assignment reuses the
   Sprint 2 manual-override language: the select carries ch-room-manual
   (amber left border, the rule above) and a small manual pill renders in
   the ch-room-flag span below the select. The pill span collapses when
   the assignment is Automatic so the cell stays compact. */
.ch-room-cell .ch-room-flag {
  display: inline-block;
}

.ch-room-cell .ch-room-flag:empty {
  display: none;
}

.ch-room-cell .ch-room-flag .pill {
  margin-top: 6px;
  margin-left: 0;
}

/* Sprint 11 — Monthly room counts: band sub-rows under a mixed room.
   Indented and muted so the room row stays the visual anchor; the
   sub-row cells carry "children · educators" pairs. */
table.mx tr.mx-band-subrow td {
  color: var(--muted);
  font-size: 12px;
}

table.mx tr.mx-band-subrow td.metric.mx-band-label {
  padding-left: 32px;
  font-weight: 500;
  color: var(--muted);
}

/* Explainer under the counts table, shown only when sub-rows exist. */
.mx-band-note {
  padding: 10px 16px;
  font-size: 12px;
  color: var(--muted);
  border-top: 1px solid var(--border);
}

/* Actions cell has no label; the Remove button keeps to the right edge of
   line 1 and wraps rather than forcing the track wider. */
table.dt.dt-children .ch-actions-cell {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  align-content: center;
  justify-content: flex-end;
  gap: 6px;
  white-space: normal;
  width: auto;
}

/* Tablet and below: redistribute the areas over four tracks so the row
   stacks deeper instead of squeezing. Name takes a full line of its own
   so it never clips on small screens. */
@media (max-width: 900px) {
  table.dt.dt-children tbody tr {
    grid-template-columns: repeat(4, minmax(0, 1fr));
    gap: 8px 10px;
    padding: 10px 12px;
  }
  table.dt.dt-children:not(.dt-children-oshc) tbody tr {
    /* Sprint 11: Room gets a full line of its own on small screens so the
       select never squeezes against the Override stack. */
    grid-template-areas:
      "name name name name"
      "dob dob status status"
      "days days start start"
      "now now plus6 plus6"
      "plus12 plus12 override override"
      "room room room room"
      "notes notes notes notes"
      "actions actions actions actions";
  }
  table.dt.dt-children.dt-children-oshc tbody tr {
    grid-template-areas:
      "name name name name"
      "dob dob status status"
      "days days start start"
      "cohort cohort cohort cohort"
      "sessions sessions sessions sessions"
      "notes notes notes notes"
      "actions actions actions actions";
  }
}

/* ============================================================
   Session 14 - CSV import wizard panel. Sits inside the
   staffing-table-card under the head row. Hidden until the
   Service Owner clicks Import from CSV.
   ============================================================ */

.csv-import {
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  background: var(--paper);
  padding: 14px 16px;
  margin: 8px 0 12px;
  display: grid;
  gap: 10px;
}

.csv-import[hidden] {
  display: none;
}

.csv-row {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
}

.csv-label {
  display: grid;
  gap: 4px;
  font-size: 12.5px;
  min-width: 200px;
}

.csv-label > span {
  color: var(--ink-2);
}

.csv-label select,
.csv-label input[type="file"] {
  padding: 6px 8px;
  border: 1px solid var(--border);
  border-radius: var(--r-sm);
  background: var(--paper);
  font: inherit;
}

.csv-paste {
  display: grid;
  gap: 4px;
  font-size: 12.5px;
}

.csv-paste > span {
  color: var(--ink-2);
}

.csv-paste textarea {
  width: 100%;
  border: 1px solid var(--border);
  border-radius: var(--r-sm);
  padding: 8px;
  font-family: ui-monospace, monospace;
  font-size: 12px;
  background: var(--paper);
  resize: vertical;
  box-sizing: border-box;
}

.csv-actions {
  display: flex;
  gap: 8px;
  align-items: center;
  flex-wrap: wrap;
}

.csv-status {
  font-size: 12.5px;
  color: var(--ink-2);
}

.csv-status-ok { color: #1f6b3a; }
.csv-status-err { color: #a33000; }

.csv-stage {
  border-top: 1px dashed var(--border);
  padding-top: 10px;
}

.csv-stage h4 {
  margin: 0 0 6px;
  font-size: 13px;
}

.csv-note {
  margin: 0 0 6px;
  font-size: 12.5px;
  color: var(--ink-2);
}

.csv-note-err {
  color: #a33000;
}

/* Sprint 29 — fuzzy header suggestion panel in the CSV mapping step. */
.csv-suggest {
  padding: 8px 10px;
  border: 1px solid var(--line, #d9dee5);
  border-radius: 6px;
  background: var(--surface-2, #f6f8fa);
}
.csv-suggest ul {
  margin: 6px 0 0;
  padding-left: 18px;
}
.csv-suggest li {
  margin: 2px 0;
}

.csv-summary {
  margin: 0 0 6px;
  font-size: 13px;
}

table.csv-map {
  width: 100%;
  border-collapse: collapse;
  font-size: 12.5px;
}

table.csv-map th,
table.csv-map td {
  border: 1px solid var(--border);
  padding: 6px 8px;
  text-align: left;
  vertical-align: middle;
}

table.csv-map code {
  background: var(--bg-2);
  padding: 1px 4px;
  border-radius: var(--r-sm);
}

table.csv-map select {
  padding: 4px 6px;
  border: 1px solid var(--border);
  border-radius: var(--r-sm);
  background: var(--paper);
  font: inherit;
  width: 100%;
}

.csv-detected {
  margin: 4px 0 4px;
  font-size: 12.5px;
}

.csv-detected ul {
  margin: 6px 0 0;
  padding-left: 18px;
}

.csv-detected code {
  background: var(--bg-2);
  padding: 1px 4px;
  border-radius: var(--r-sm);
}

/* ============================================================
   Session 15 - Three-mode staffing rows.
   Read mode renders display text per cell; edit mode keeps the
   Session 13 inline-input layout. The dt-staffing table shrinks
   in read mode because there is no input chrome to accommodate.
   ============================================================ */

table.dt.dt-staffing tbody tr[data-row-mode="read"] td {
  font-size: 12.5px;
  padding: 0;
}

/* Sprint 3 grid layout: labels sit above values, so the old right-aligned
   numeric and centred support alignments would orphan values away from
   their labels. Everything left-aligns; tabular figures are kept. The
   .st-num / .st-center classes stay in the markup for the specs. */
table.dt.dt-staffing tbody tr[data-row-mode="read"] td.st-num {
  text-align: left;
  font-variant-numeric: tabular-nums;
}

table.dt.dt-staffing tbody tr[data-row-mode="read"] td.st-center {
  text-align: left;
}

.st-dash {
  display: inline-block;
  color: var(--hint);
  font-weight: 400;
}

.st-display-name {
  font-weight: 600;
  color: var(--navy);
}

#staffing-edit-all[aria-pressed="true"] {
  background: var(--teal-lt);
  border-color: var(--teal-dk);
  color: var(--teal-dk);
}

/* ============================================================
   Session 15 - CSV wizard polish: step indicator + diff stats.
   ============================================================ */

.csv-steps {
  display: flex;
  gap: 6px;
  list-style: none;
  padding: 0;
  margin: 0 0 4px;
  font-size: 12.5px;
  flex-wrap: wrap;
}

.csv-steps li {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 6px 12px;
  border: 1px solid var(--border);
  border-radius: var(--r-sm);
  background: var(--paper);
  color: var(--muted);
}

.csv-steps li[data-step-state="active"] {
  background: var(--teal-lt);
  border-color: var(--teal-dk);
  color: var(--teal-dk);
  font-weight: 600;
}

.csv-steps li[data-step-state="done"] {
  background: var(--sand);
  border-color: var(--border);
  color: var(--navy);
}

.csv-steps .csv-step-num {
  display: inline-flex;
  width: 20px;
  height: 20px;
  border-radius: 50%;
  background: var(--paper);
  color: var(--muted);
  align-items: center;
  justify-content: center;
  font-weight: 600;
  border: 1px solid var(--border);
}

.csv-steps li[data-step-state="active"] .csv-step-num {
  background: var(--teal-dk);
  color: var(--paper);
  border-color: var(--teal-dk);
}

.csv-steps li[data-step-state="done"] .csv-step-num {
  background: var(--navy);
  color: var(--paper);
  border-color: var(--navy);
}

.csv-stats {
  display: flex;
  gap: 10px;
  margin: 6px 0 10px;
  flex-wrap: wrap;
}

.csv-stat {
  flex: 1 1 120px;
  min-width: 120px;
  padding: 10px 14px;
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  background: var(--paper);
}

.csv-stat-new {
  border-color: var(--teal-dk);
  background: var(--teal-lt);
}

.csv-stat-updated {
  border-color: var(--amber-dk);
  background: var(--amber-lt);
}

.csv-stat-unchanged {
  background: var(--sand);
}

.csv-stat-num {
  font-size: 22px;
  font-weight: 700;
  color: var(--navy);
  line-height: 1;
  font-variant-numeric: tabular-nums;
}

.csv-stat-new .csv-stat-num { color: var(--teal-dk); }
.csv-stat-updated .csv-stat-num { color: var(--amber-dk); }

.csv-stat-label {
  margin-top: 4px;
  font-size: 12px;
  color: var(--muted);
  text-transform: uppercase;
  letter-spacing: 0.04em;
}

/* ============================================================
   Session 18 FE Review - CSV wizard polish.
   Narrow viewport stacking, mapping persistence toggle, and
   children import preview line. The polish applies to both
   the staffing and the Forward Occupancy panels because they
   share the .csv-import / .csv-row / .csv-label classes.
   ============================================================ */

.csv-toggle {
  display: flex;
  align-items: center;
  gap: 8px;
  margin: 4px 0 2px;
  font-size: 12.5px;
  color: var(--ink-2);
  cursor: pointer;
  user-select: none;
}

.csv-toggle input[type="checkbox"] {
  width: 14px;
  height: 14px;
  margin: 0;
  accent-color: var(--teal-dk);
}

.csv-toggle-hint {
  display: block;
  margin-left: 22px;
  margin-top: 2px;
  font-size: 11.5px;
  color: var(--muted);
}

.csv-preview-line {
  display: block;
  margin: 6px 0 4px;
  padding: 8px 12px;
  border: 1px solid var(--border);
  border-radius: var(--r-sm);
  background: var(--sand);
  font-size: 12.5px;
  color: var(--navy);
}

.csv-preview-line[hidden] {
  display: none;
}

.csv-preview-line strong {
  font-variant-numeric: tabular-nums;
  color: var(--navy);
}

@media (max-width: 700px) {
  .csv-import {
    padding: 12px 12px;
    margin: 8px 0 10px;
    gap: 8px;
  }

  .csv-row {
    display: grid;
    grid-template-columns: 1fr;
    gap: 8px;
  }

  .csv-label {
    min-width: 0;
    width: 100%;
  }

  .csv-label select,
  .csv-label input[type="file"] {
    width: 100%;
    box-sizing: border-box;
  }

  .csv-actions {
    flex-direction: column;
    align-items: stretch;
    gap: 6px;
  }

  .csv-actions .btn {
    width: 100%;
  }

  .csv-actions .csv-status {
    text-align: left;
    padding: 4px 2px 0;
  }

  .csv-stats {
    flex-direction: column;
    gap: 8px;
  }

  .csv-stat {
    flex: 1 1 auto;
    padding: 10px 12px;
  }

  .csv-steps {
    flex-direction: column;
    gap: 4px;
  }

  .csv-steps li {
    width: 100%;
    box-sizing: border-box;
  }

  table.csv-map th,
  table.csv-map td {
    font-size: 12px;
    padding: 5px 6px;
  }
}

/* ============================================================
   Session 19 - Compliance Tracker
   ============================================================ */

/* Red urgent frame variant of the standard .frame band. Used by the
   Compliance Tracker to surface "N records need action" at the top of the
   screen. Matches the mock-up red-bordered cream band. */
.frame.red {
  border-left-color: var(--red);
  background: var(--red-lt);
}

.frame.red strong {
  color: var(--red);
}

/* Pill-style status flag. Three variants follow the calc engine status
   vocabulary (ok / warn / bad). Same shape as .pill but smaller and intent
   coloured so a glance at a row tells you what to do. */
.flag {
  display: inline-block;
  padding: 2px 9px;
  border-radius: 999px;
  font-size: 11px;
  font-weight: 600;
  line-height: 1.4;
  letter-spacing: 0.2px;
  vertical-align: middle;
  margin-left: 4px;
  white-space: nowrap;
}

.flag.ok {
  background: var(--teal-lt);
  color: var(--teal-dk);
}

.flag.warn {
  background: var(--amber-lt);
  color: var(--amber-dk);
}

.flag.bad {
  background: var(--red-lt);
  color: var(--red);
}

/* Compliance table polish. Same backbone as table.dt.dt-staffing but a
   touch denser since rows pack five status pills. */
table.dt.dt-compliance thead th {
  font-size: 12px;
  letter-spacing: 0.4px;
  text-transform: uppercase;
  color: var(--muted);
}

table.dt.dt-compliance tbody td {
  font-size: 13px;
  padding: 10px 12px;
  vertical-align: middle;
}

table.dt.dt-compliance .ch-input {
  font-size: 13px;
  padding: 5px 8px;
  width: 100%;
  box-sizing: border-box;
}

table.dt.dt-compliance .ch-actions-col,
table.dt.dt-compliance .ch-actions-cell {
  width: 1%;
  white-space: nowrap;
  text-align: right;
}

/* "Not recorded" placeholder in compliance cells. Subtle, since the brand
   audit bans em / en dashes and a blank cell would read as missing data. */
.comp-empty {
  color: var(--hint);
  font-style: italic;
  font-size: 12px;
}

.comp-visa-bulk {
  background: var(--cream);
  border-left: 4px solid var(--amber);
  padding: 10px 14px;
  border-radius: 0 var(--r-sm) var(--r-sm) 0;
  font-size: 13px;
  line-height: 1.6;
  margin: 6px 0 14px;
}

/* Sprint 28 — child protection two-track polish. */
/* Sub-label under a compliance column heading (refresh cadence). */
.comp-th-sub {
  display: block;
  font-size: 10px;
  font-weight: 500;
  letter-spacing: 0.2px;
  text-transform: none;
  color: var(--hint);
  margin-top: 2px;
}

/* Blue notification dot next to a name when a child protection refresher is
   due within 60 days. On-screen alert only. */
.comp-alert-dot {
  color: var(--teal);
  font-size: 16px;
  line-height: 1;
  vertical-align: middle;
}

/* Responsible Person checkbox label inside the compliance edit row. */
.comp-responsible-label {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: 12px;
  white-space: nowrap;
}

table.dt.dt-compliance .comp-responsible-check {
  width: auto;
}

/* As-at re-check reminder inside the child protection explainer note. */
.comp-cp-asat {
  display: block;
  margin-top: 6px;
  font-size: 12px;
  color: var(--muted);
}

.comp-visa-bulk strong {
  color: var(--navy);
}

/* Session 21 FE review additions. */

/* Calc-anchor hint on the Compliance Tracker card head — surfaces the
   asOfDate the engine used so users notice when the centre clock has
   drifted relative to the planning year. */
.comp-asof {
  display: inline;
  margin-left: 4px;
  color: var(--muted);
  font-style: italic;
  font-size: 12px;
}

/* Disambiguates "where do I edit a visa date" on the visa risk card —
   the answer is the Staffing Register, not the Compliance Tracker. */
.comp-visa-hint {
  margin-top: 12px;
  font-size: 12px;
  color: var(--muted);
  font-style: italic;
}

@media (max-width: 900px) {
  table.dt.dt-compliance thead th,
  table.dt.dt-compliance tbody td {
    padding: 8px 8px;
    font-size: 12px;
  }
  .flag {
    margin-left: 0;
    margin-top: 2px;
  }
}

/* Session 25 — Sustainable Roster Lens.
   Four per-room cards laid out in a two-column grid that collapses to a
   single column under 880px. Mirrors the mock-up at wfp-tool/index.html
   .lens-grid / .lens-card / .lens-line / .lens-total. */
.lens-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 16px;
}
@media (max-width: 880px) {
  .lens-grid { grid-template-columns: 1fr; }
}
.lens-card {
  background: var(--lav-15);
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  padding: 16px 18px;
}
.lens-card h4 {
  font-size: 14px;
  margin: 0 0 10px;
  padding-bottom: 8px;
  border-bottom: 1px solid var(--border);
  color: var(--navy);
}
.lens-line {
  display: flex;
  justify-content: space-between;
  padding: 5px 0;
  font-size: 12.5px;
}
.lens-line .lbl { color: var(--muted); }
.lens-line .val { color: var(--navy); font-weight: 600; }
.lens-total {
  display: flex;
  justify-content: space-between;
  margin-top: 10px;
  padding-top: 10px;
  border-top: 2px solid var(--teal);
  font-size: 13.5px;
}
.lens-total .val {
  font-family: var(--ff-head);
  font-size: 18px;
  color: var(--navy);
}
.sustain-summary {
  margin-top: 18px;
  padding-top: 14px;
  border-top: 1px solid var(--border);
}
.sustain-summary-line {
  display: flex;
  justify-content: space-between;
  padding: 5px 0;
  font-size: 13px;
}
.sustain-summary-line .lbl { color: var(--muted); }
.sustain-summary-line .val { color: var(--navy); font-weight: 600; }
.sustain-summary-note {
  margin-top: 8px;
  font-size: 12.5px;
  color: var(--muted);
}

/* Session 26 — Sustainable Roster Lens cost view + central staffing.
   Three-tile cost grid (legal / sustain / delta) that collapses to a single
   column under 720px. Relief-mode radio toggle on the right side of the
   cost-card header. Central staffing table reuses the .dt component. */
.cost-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 12px;
}
@media (max-width: 720px) {
  .cost-grid { grid-template-columns: 1fr; }
}
.cost-tile {
  padding: 14px 16px;
  border-radius: var(--r-md);
  border: 1px solid var(--border);
}
.cost-tile.legal {
  background: var(--teal-lt);
  border-color: var(--teal);
}
.cost-tile.sustain {
  background: var(--amber-lt);
  border-color: var(--amber);
}
.cost-tile.delta {
  background: var(--lav-lt);
  border-color: var(--lavender);
}
.cost-label {
  font-size: 10.5px;
  font-weight: 700;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--muted);
}
.cost-val {
  font-family: var(--ff-head);
  font-size: 22px;
  color: var(--navy);
  margin-top: 6px;
}
.cost-note {
  font-size: 11.5px;
  color: var(--muted);
  margin-top: 4px;
}
.cost-basis-note {
  font-size: 11.5px;
  color: var(--muted);
  margin-top: 8px;
}
.cost-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  flex-wrap: wrap;
  margin-bottom: 12px;
}
.cost-header h3 {
  margin: 0;
}
.relief-toggle {
  display: inline-flex;
  align-items: center;
  gap: 14px;
  font-size: 12.5px;
  color: var(--navy);
}
.relief-toggle-label {
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--muted);
}
.relief-toggle-option {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  cursor: pointer;
}
.relief-toggle-option input[type="radio"] {
  margin: 0;
}

/* ============================================================
   Session 30 - Workforce Health Check dashboard styles.

   Session 29 shipped app/js/modules/dashboard.js with classes
   (.kpis, .kpi, .kpi.amber/.lav/.red, .kpi-label, .kpi-val,
   .kpi-trend.warn/.bad, .ai-insight, .ai-eyebrow) that mapped to
   the mock-up at wfp-tool/index.html but were never copied into
   app/assets/wfp-styles.css. The dashboard rendered with the
   right markup but no visual treatment: tiles stacked vertically
   as plain divs, AI insight read as body text, matrix section
   headers rendered as default table rows.

   This block ports the mock-up rules across so the production
   dashboard reads cell-for-cell against the mock-up.
   ============================================================ */

/* KPI tile grid. Four tiles at desktop, two columns under 880px,
   single column on narrow phones. */
.kpis {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 14px;
  margin: 18px 0;
}
@media (max-width: 880px) {
  .kpis { grid-template-columns: repeat(2, 1fr); }
}
@media (max-width: 480px) {
  .kpis { grid-template-columns: 1fr; }
}

.kpi {
  background: var(--paper);
  border: 1px solid var(--border);
  border-radius: var(--r-lg);
  padding: 18px 20px;
  position: relative;
  overflow: hidden;
}
.kpi::before {
  content: '';
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  height: 4px;
  background: var(--teal);
}
.kpi.amber::before { background: var(--amber); }
.kpi.lav::before { background: var(--lavender); }
.kpi.red::before { background: var(--red); }

.kpi-label {
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--muted);
  margin-bottom: 8px;
}

.kpi-val {
  font-family: var(--ff-head);
  font-size: 32px;
  color: var(--navy);
  line-height: 1;
}
.kpi-val small {
  font-family: var(--ff-body);
  font-size: 14px;
  color: var(--muted);
  margin-left: 4px;
  font-weight: 400;
}

.kpi-trend {
  font-size: 11.5px;
  color: var(--teal-dk);
  margin-top: 6px;
}
.kpi-trend.warn { color: var(--amber-dk); }
.kpi-trend.bad { color: var(--red); }

/* AI workforce insight callout. Cream band with amber border-left
   matching the .frame.amber pattern, plus an uppercase eyebrow
   label and a slightly larger headline. */
.ai-insight {
  background: var(--paper);
  border: 1px solid var(--border);
  border-left: 3px solid var(--teal);
  border-radius: var(--r-md);
  padding: 18px 20px;
  margin: 18px 0;
}
.ai-eyebrow {
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--teal);
  margin-bottom: 6px;
}
.ai-insight h3 {
  font-family: var(--ff-head);
  color: var(--navy);
  font-size: 18px;
  line-height: 1.3;
  margin: 0 0 8px;
}
.ai-insight p {
  font-size: 13.5px;
  line-height: 1.55;
  color: var(--text);
  margin: 0 0 12px;
  max-width: 760px;
}

/* Matrix section header rows. Cream band, teal-dk small caps. The
   row is non-interactive so disable the row-hover treatment for
   section rows specifically. */
table.mx tr.section td {
  background: var(--lav-15);
  padding: 8px 16px;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--teal-dk);
  text-align: left;
}
table.mx tr.section:hover td {
  background: var(--lav-15);
}

/* Inline meta-text inside a metric cell (e.g. "(0 to 23m)" age
   band hint after a room name). Mock-up at wfp-tool/index.html
   table.mx td.metric .meta. */
table.mx td.metric .meta {
  font-size: 11px;
  color: var(--muted);
  font-weight: 400;
  margin-left: 4px;
}

/* Lavender variant of the .frame info band. Already shipped:
   .frame.teal (line ~331), .frame.red (line ~1763). Adding .lav
   for completeness so the dashboard or any later module can use
   the same vocabulary as the mock-up. */
.frame.lav {
  border-left-color: var(--lav-dk);
  background: var(--lav-lt);
}

/* Mock-up uses .btn.ghost for low-emphasis actions inside card-heads
   (e.g. Export to CSV, Print summary). The existing app CSS only ships
   .btn.btn-ghost; alias the unprefixed form so the mock-up class name
   round-trips into the production build. The Print summary button on
   the dashboard matrix card-head uses .btn.ghost directly. */
.btn.ghost {
  background: var(--paper);
  color: var(--muted);
  border-color: var(--border);
}
.btn.ghost:hover {
  background: var(--lav-15);
  color: var(--navy);
  border-color: var(--teal);
}

/* Pg-actions row inside a card-head. The mock-up at
   wfp-tool/index.html:316 stacks the title + sub on the left of a
   card-head and a .pg-actions row of buttons on the right. The
   shared .card-head selector already does flex space-between; the
   .pg-actions group needs gap + wrap so it lays out cleanly. */
.card-head .pg-actions {
  display: flex;
  gap: 8px;
  flex-wrap: wrap;
  align-items: center;
}

/* Session 31 — Hiring Radar.
   Three column grid: month label, ask copy, by-date hint.
   Mirrors wfp-tool/index.html:133-137 cell-for-cell so the dashboard
   reads identically to the mock-up. The Worker emits row-level
   inline background colours for severity (red-lt for overdue or
   high; amber-lt for medium); no severity → paper default. */
.radar-row {
  display: grid;
  grid-template-columns: 100px 1fr 130px;
  gap: 14px;
  padding: 12px 14px;
  border-bottom: 1px solid var(--border);
  align-items: center;
  font-size: 13px;
}
.radar-row:last-child {
  border-bottom: none;
}
.radar-month {
  font-weight: 700;
  color: var(--navy);
  font-size: 12px;
}
.radar-ask {
  color: var(--text);
}
.radar-by {
  font-size: 11.5px;
  color: var(--muted);
  text-align: right;
}

/* ============================================================
 * Session 34 — Gap Plan: strategies grid + diff modal + edits
 * ============================================================ */

/* Strategies grid (feasibility by impact) — mock-up at
 * wfp-tool/index.html:162-171. Three columns, three rows. */
.fi-grid {
  display: grid;
  grid-template-columns: 60px 1fr 1fr;
  grid-template-rows: 60px 1fr 1fr;
  gap: 6px;
  max-width: 720px;
}
.fi-cell {
  background: var(--paper);
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  padding: 10px;
  min-height: 130px;
  font-size: 12px;
}
.fi-cell.label {
  display: flex;
  align-items: center;
  justify-content: center;
  background: transparent;
  border: none;
  min-height: auto;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--muted);
}
.fi-cell.label.rotate {
  writing-mode: vertical-rl;
  transform: rotate(180deg);
}
.fi-now { background: var(--teal-lt); border-color: var(--teal); }
.fi-next { background: var(--amber-lt); border-color: var(--amber); }
.fi-last { background: var(--cream); }
.fi-never { background: var(--sand); color: var(--muted); }

.fi-tag {
  display: block;
  padding: 6px 8px;
  background: var(--paper);
  border-radius: var(--r-sm);
  margin-bottom: 5px;
  border: 1px solid var(--border);
  font-size: 11.5px;
}
.fi-tag .strat-meta {
  display: block;
  color: var(--muted);
  font-size: 10.5px;
  margin-top: 2px;
}

/* Cell-edited highlight — applied as `data-edited="true"` once the user
 * commits a change. Reads through into the diff modal so the user can
 * see at a glance what they edited. */
[data-edited="true"] {
  background: var(--amber-lt);
  border-color: var(--amber);
}

/* Diff modal — opens when Regenerate is pressed on a section with
 * manual edits. Two-column comparison per edited cell. */
.modal-backdrop {
  position: fixed;
  inset: 0;
  background: rgba(15, 23, 42, 0.55);
  display: flex;
  align-items: flex-start;
  justify-content: center;
  padding: 64px 20px;
  z-index: 1000;
  overflow-y: auto;
}
.modal-card {
  background: var(--paper);
  border-radius: var(--r-lg);
  padding: 24px 28px;
  width: 100%;
  max-width: 760px;
  box-shadow: 0 20px 50px rgba(15, 23, 42, 0.25);
}
.modal-card h3 {
  margin: 0 0 6px;
}
.modal-actions {
  display: flex;
  gap: 10px;
  justify-content: flex-end;
  margin-top: 18px;
}
.diff-list {
  display: flex;
  flex-direction: column;
  gap: 14px;
  margin-top: 14px;
}
.diff-row {
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  padding: 12px 14px;
  background: var(--cream);
}
.diff-row[data-choice="use_new"] .diff-proposed {
  border-color: var(--teal);
  background: var(--teal-lt);
}
.diff-row[data-choice="keep"] .diff-current {
  border-color: var(--amber);
  background: var(--amber-lt);
}
.diff-label {
  font-weight: 700;
  font-size: 12px;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--muted);
  margin-bottom: 8px;
}
.diff-cols {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 10px;
}
.diff-col {
  border: 1px solid var(--border);
  border-radius: var(--r-sm);
  padding: 10px;
  background: var(--paper);
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.diff-col-head {
  font-size: 11px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--muted);
}
.diff-col-body {
  font-size: 13px;
  line-height: 1.4;
  color: var(--text);
  flex: 1;
}
/* Session 36 FE pass — Session 34 P3 carry-over.
 * The two-column diff layout breaks awkwardly under the tablet
 * breakpoint. Stack to single-column so the user can still read each
 * side without horizontal scrolling. The Gap Plan workflow is desktop-
 * first; this rule is a graceful-degradation safety net. */
@media (max-width: 640px) {
  .diff-cols { grid-template-columns: 1fr; }
  .modal-card { padding: 18px 16px; }
  .modal-backdrop { padding: 24px 12px; }
}

/* ============================================================
 * AI Insights Report — Session 35
 * ============================================================
 * Ported from the mock-up at wfp-tool/index.html:182. The report
 * sits on the AI Insights Report screen alongside a per-page action
 * toolbar (Regenerate + Export PDF) above the card.
 */
.ai-report-toolbar {
  display: flex;
  gap: 10px;
  justify-content: flex-end;
  margin-bottom: 18px;
}
.ai-report {
  background: var(--paper);
  border: 2px solid var(--navy);
  border-radius: var(--r-lg);
  padding: 32px 36px;
  margin-bottom: 22px;
}
.ai-report-head {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  gap: 24px;
  padding-bottom: 16px;
  border-bottom: 2px solid var(--teal);
  margin-bottom: 22px;
}
.ai-report-head .arh-eye {
  font-size: 10.5px;
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--teal-dk);
  margin-bottom: 4px;
}
.ai-report-head h2 {
  font-size: 22px;
  margin: 0;
}
.ai-report-head .arh-meta {
  font-size: 11.5px;
  color: var(--muted);
  margin-top: 4px;
}
.ai-section {
  margin-bottom: 22px;
}
.ai-section h4 {
  font-size: 14px;
  color: var(--navy);
  margin-bottom: 8px;
  padding-bottom: 4px;
  border-bottom: 1px solid var(--amber);
  display: inline-block;
}
.ai-section p {
  font-size: 13.5px;
  line-height: 1.65;
  color: var(--text);
  margin-bottom: 8px;
}
.ai-section ul {
  margin: 8px 0 8px 20px;
  padding: 0;
}
.ai-section li {
  font-size: 13.5px;
  line-height: 1.6;
  color: var(--text);
  margin-bottom: 4px;
}
.ai-section strong {
  color: var(--navy);
}

/* ============================================================
   Session 37 — Educator Pathways + Succession Map.
   Two read-only cards. Tables reuse the .dt backbone so spacing,
   header weight, and hover state match the rest of the product.
   ============================================================ */
.pathways-shell .card + .card {
  margin-top: 20px;
}

.dt-pathways tbody td,
.dt-succession tbody td {
  vertical-align: top;
  line-height: 1.5;
}

.dt-pathways .pill,
.dt-succession .pill {
  margin: 0;
}

/* Successor list cell can stack multiple successors on top of each other
   for roles with more than one named candidate. Each name is bold to match
   the incumbent column. */
.pathway-successor {
  display: block;
  font-size: 13px;
  color: var(--text);
}
.pathway-successor + .pathway-successor {
  margin-top: 4px;
}

/* No-successor placeholder. Muted so it reads as a gap, not a value. */
.pathway-none {
  color: var(--muted);
  font-style: italic;
  font-size: 13px;
}

@media (max-width: 720px) {
  .dt-pathways thead,
  .dt-succession thead {
    font-size: 11px;
  }
  .dt-pathways tbody td,
  .dt-succession tbody td {
    font-size: 12.5px;
  }
}

/* ============================================================
   User Management module (Session 38)
   Invite card + members table + pending invites table.
   Reuses .auth-form for the invite card so the field styling
   matches the login + invite-accept pages.
   ============================================================ */
.um-shell .card + .card {
  margin-top: 20px;
}

.um-form {
  max-width: 480px;
}

/* Session 39 — promoted .field-hint from `.um-form .field-hint` to a global
   rule so the invite-accept page's password helper text picks up the muted
   styling. Previously the hint on /auth/invite/accept rendered in default
   body type because the only selector that styled it was scoped to .um-form.
   The form on the invite-accept page is .auth-form, not .um-form. */
.field-hint {
  margin-top: 6px;
  font-size: 12px;
  color: var(--muted);
}

.dt-users td,
.dt-users-pending td {
  vertical-align: middle;
}

.dt-users .um-role-select {
  padding: 6px 8px;
  border: 1px solid var(--border);
  border-radius: var(--r-sm);
  background: var(--paper);
  font-family: var(--ff-body);
  font-size: 13px;
  color: var(--text);
}

.dt-users .um-role-select:disabled {
  background: var(--cream);
  color: var(--muted);
  cursor: not-allowed;
}

.dt-users .um-remove {
  padding: 6px 12px;
  font-size: 12.5px;
}

.dt-users .um-remove:disabled {
  opacity: 0.5;
  cursor: not-allowed;
}

/* Sprint 7 — per-member module access row. Sits directly under the member
   row, full width, with a wrap-friendly tick grid that stays tidy at
   1280px (two lines of ticks at most). */
.dt-users tr.um-access-row td {
  background: var(--sand);
  padding: 8px 12px 10px;
  border-bottom: 1px solid var(--border);
}

.um-access {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 6px 16px;
}

.um-access-label {
  font-size: 11px;
  font-weight: 500;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--muted);
  margin-right: 2px;
}

.um-access-item {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  font-size: 12.5px;
  color: var(--text);
  cursor: pointer;
  white-space: nowrap;
}

.um-access-item input[type="checkbox"] {
  accent-color: var(--teal-dk);
  width: 14px;
  height: 14px;
}

.um-access-item input[type="checkbox"]:disabled {
  cursor: wait;
}

/* Sprint 19 — static (Service Owner / CLA Admin) module access rows render
   the same tick grid as members but permanently disabled. Dim the ticks and
   drop the pointer cursor so the row reads as a statement, not a control.
   Placed after the in-flight :disabled rule above so the default cursor wins
   for static rows at equal specificity. */
.um-access-item-static {
  cursor: default;
  color: var(--muted);
}

.um-access-item-static input[type="checkbox"]:disabled {
  cursor: default;
  opacity: 0.55;
}

.um-access-static {
  font-size: 12.5px;
  color: var(--muted);
}

.um-access-static strong {
  color: var(--navy);
  font-weight: 500;
}

.um-access-saved {
  font-size: 12px;
  color: var(--teal-dk);
  font-weight: 500;
}

.um-access-error {
  font-size: 12px;
  color: var(--red);
}

@media (max-width: 720px) {
  .dt-users thead,
  .dt-users-pending thead {
    font-size: 11px;
  }
  .dt-users tbody td,
  .dt-users-pending tbody td {
    font-size: 12.5px;
  }
}

/* ============================================================
   Session 42 FE Review - CLA Aggregate Dashboard polish.

   Session 41 shipped the network dashboard with class names that
   did not exist in this stylesheet (.kpi-row, .kpi-tile, .kpi-value,
   .rollup-chip, .dt-cla-services, .cla-aggregate-shell). The tiles
   rendered as plain stacked divs and the rollup pills as bare
   spans. Session 42 ports the markup onto the canonical KPI grid
   used by the Workforce Health Check (.kpis / .kpi / .kpi-label /
   .kpi-val) and adds the missing rules below.
   ============================================================ */

/* Six-tile variant of the KPI grid. The Health Check uses .kpis with
   the default four-column layout; the Aggregate Dashboard needs six
   tiles on a wide screen, three on tablet, two on phone. */
.kpis.kpis-six {
  grid-template-columns: repeat(6, 1fr);
}
@media (max-width: 1180px) {
  .kpis.kpis-six { grid-template-columns: repeat(3, 1fr); }
}
@media (max-width: 720px) {
  .kpis.kpis-six { grid-template-columns: repeat(2, 1fr); }
}
@media (max-width: 480px) {
  .kpis.kpis-six { grid-template-columns: 1fr; }
}

/* Aggregate Dashboard shell - vertical spacing between the KPI row,
   the per-organisation cards, and the empty-state stub. */
.cla-aggregate-shell {
  display: block;
}
.cla-aggregate-shell .card.cla-org-card {
  margin-top: 18px;
}

/* Session 43 — AI Network Briefing card. Sits between the KPI row and
   the per-org cards. Mirrors the per-service .ai-report visual language
   but uses the lavender accent (the CLA Network surface accent) instead
   of teal so the network briefing reads visually distinct from the
   per-service Insights Report. */
.cla-aggregate-shell .card.net-brief {
  margin: 18px 0;
  padding: 24px 28px;
  border: 2px solid var(--navy);
}
.net-brief-head {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  gap: 24px;
  padding-bottom: 14px;
  border-bottom: 2px solid var(--lavender);
  margin-bottom: 18px;
}
.net-brief-head .arh-eye {
  font-size: 10.5px;
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--navy);
  margin-bottom: 4px;
}
.net-brief-head h3 {
  font-size: 18px;
  margin: 0;
}
.net-brief-section {
  margin-bottom: 16px;
}
.net-brief-section h4 {
  font-size: 13px;
  color: var(--navy);
  margin-bottom: 6px;
  padding-bottom: 3px;
  border-bottom: 1px solid var(--amber);
  display: inline-block;
}
.net-brief-section p {
  font-size: 13.5px;
  line-height: 1.6;
  color: var(--text);
  margin-bottom: 6px;
}
.net-brief-section ul {
  margin: 6px 0 6px 20px;
  padding: 0;
}
.net-brief-section li {
  font-size: 13.5px;
  line-height: 1.55;
  color: var(--text);
  margin-bottom: 4px;
}

/* Rollup chips inside each service row. Compact pill style that pairs
   with the .pill family but stays neutral on its own row so it does
   not visually compete with the Plan status pill in the next column. */
.rollup-chip {
  display: inline-block;
  padding: 2px 10px;
  margin: 2px 4px 2px 0;
  border-radius: 999px;
  background: var(--cream);
  color: var(--text);
  font-size: 12px;
  line-height: 1.4;
  white-space: nowrap;
}
.rollup-chip strong {
  color: var(--navy);
  font-weight: 700;
  margin-left: 4px;
}

/* Services table inside an org card. Inherits .dt backbone but pins
   the Members column to a numeric width and lets the Rollup column
   absorb the slack on wide screens. On narrow viewports the Rollup
   column is hidden because the chips would otherwise wrap the row to
   four lines and break the visual rhythm of stacked org cards. */
table.dt.dt-cla-services {
  width: 100%;
}
table.dt.dt-cla-services thead th.num-h {
  text-align: right;
  width: 90px;
}
table.dt.dt-cla-services tbody td.td-rollup {
  min-width: 220px;
}
table.dt.dt-cla-services thead th:last-child,
table.dt.dt-cla-services tbody td:last-child {
  text-align: right;
  width: 90px;
}
@media (max-width: 880px) {
  table.dt.dt-cla-services thead th.rollup-h,
  table.dt.dt-cla-services tbody td.td-rollup {
    display: none;
  }
}

/* Return-to-network banner. Cream band with a lavender 4px left
   border, mirroring the .ai-insight pattern but tuned to read as a
   nav affordance rather than a tip. Stays single-line on wide
   viewports and wraps cleanly on phones. The "Return to network"
   anchor reads as a quiet ghost link (not a button) because it is a
   nav action, not a destructive one. */
.cla-banner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  background: var(--cream);
  border: 1px solid var(--border);
  border-left: 4px solid var(--lavender);
  border-radius: 0 var(--r-md) var(--r-md) 0;
  padding: 12px 16px;
  margin: 0 0 14px;
}
.cla-banner .cla-banner-label {
  font-size: 13px;
  color: var(--text);
  line-height: 1.5;
}
.cla-banner .cla-banner-label strong {
  font-family: var(--ff-head);
  color: var(--navy);
  font-weight: 700;
}
.cla-banner .cla-banner-link {
  color: var(--lav-dk);
  font-size: 12.5px;
  font-weight: 700;
  text-decoration: none;
  letter-spacing: 0.02em;
  white-space: nowrap;
}
.cla-banner .cla-banner-link:hover {
  text-decoration: underline;
}
@media (max-width: 560px) {
  .cla-banner {
    flex-direction: column;
    align-items: flex-start;
  }
}

/* ============================================================
   Sprint 5 — Gap Plan user-added rows, quiet save status, and
   editable Pathways cells.
   ============================================================ */

/* Quiet-save status line at the top of the Gap Plan and Pathways shells.
   Reuses the children-status colour states; the base class carries a
   margin-left that only makes sense beside a button row, so reset it. */
.module-save-status {
  margin: 0 0 10px;
  text-align: right;
}

/* Rows the user added by hand. Cream wash + tag so they read as distinct
   from the AI-drafted rows. */
tr[data-user-row="true"] > td {
  background: var(--cream);
}
.fi-tag[data-user-row="true"] {
  background: var(--cream);
}

.user-row-tag {
  display: inline-block;
  font-size: 10px;
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--teal-dk);
  background: var(--teal-lt);
  border-radius: var(--r-sm);
  padding: 1px 6px;
  margin-top: 4px;
}

/* The editable surface of a user row is an inner span, so the tag and the
   remove control are never part of the editable text. Block display gives
   an empty cell a clickable line; the placeholder renders until the user
   types. */
.user-cell {
  display: block;
  min-height: 18px;
  outline: none;
}
.user-cell:empty::before {
  content: attr(data-placeholder);
  color: var(--muted);
  font-style: italic;
}
.user-cell:focus {
  background: var(--paper);
  box-shadow: 0 0 0 2px var(--teal-lt);
  border-radius: var(--r-sm);
}

.user-row-remove {
  margin-top: 6px;
}

/* Sprint 16 — the status select in the action plan tables. Sized to its
   options rather than the cell; on user rows the Remove control stacks
   under it, matching every other user-row cell. */
.gap-status-select {
  width: auto;
  min-width: 118px;
  display: block;
}

/* Per-quadrant "Add strategy" control inside the feasibility grid. */
.fi-add {
  margin-top: 2px;
  font-size: 11px;
}

/* Pathways inline editing. Editable cells get the same placeholder
   treatment; the likely-by date input reuses the register input look. */
.dt-pathways td[contenteditable="true"]:empty::before {
  content: attr(data-placeholder);
  color: var(--muted);
  font-style: italic;
}
.dt-pathways td[contenteditable="true"]:focus {
  outline: none;
  background: var(--paper);
  box-shadow: inset 0 0 0 2px var(--teal-lt);
}
.pathway-by-input {
  max-width: 150px;
}

/* Sprint 17 — successor staff select. A select's minimum size is its
   widest option label, which would force the Successor column wide on
   long staff names; min-width 0 lets it compress to the cell instead. */
.dt-pathways .pathway-successor-select {
  width: 100%;
  min-width: 0;
}

/* Sprint 22 — CLA Admin Console. Reuses .card, .dt, .btn, .ch-input and the
   children-status line. Only the form and inline-row layouts are new. */
.cla-admin-shell .admin-create-form {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  gap: 10px 14px;
  margin-top: 14px;
}

.cla-admin-shell .admin-field {
  display: flex;
  flex-direction: column;
  gap: 4px;
  min-width: 180px;
}

.cla-admin-shell .admin-field label {
  font-size: 11px;
  font-weight: 500;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--muted);
}

.cla-admin-shell .admin-submit-row {
  display: flex;
  align-items: center;
  gap: 10px;
}

.cla-admin-shell .admin-org {
  margin-top: 18px;
}

.cla-admin-shell .admin-org h4 {
  margin: 0 0 8px;
}

.cla-admin-shell .admin-invite-inline,
.cla-admin-shell .admin-pending-inline {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px 12px;
  padding: 4px 0;
}

.cla-admin-shell .admin-invite-email {
  min-width: 220px;
}

.cla-admin-shell .admin-pending-label {
  font-size: 11px;
  font-weight: 500;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--muted);
}

/* ============================================================
   Sprint 25b — Employment Hero connect and sync UI.
   eh- scoped additions; everything else reuses .card, .btn,
   .module-note, .cla-banner and the --red error token.
   ============================================================ */
.eh-line {
  font-size: 13px;
  line-height: 1.55;
  color: var(--text);
  margin: 10px 0 0;
}

.eh-error {
  color: var(--red);
  font-weight: 600;
}

.eh-consent {
  background: var(--cream);
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  padding: 12px 14px;
  margin: 12px 0 0;
  font-size: 13px;
  line-height: 1.55;
  max-width: 560px;
}

.eh-consent p {
  margin: 0;
}

.eh-actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px;
  margin-top: 12px;
}

.eh-admin-line {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px 12px;
  font-size: 13px;
  margin: 0 0 10px;
}

.eh-admin-line .eh-consent {
  flex-basis: 100%;
  margin-top: 4px;
}

.eh-sync-note {
  margin: 12px 0 0;
}

.eh-banner-dismiss {
  background: none;
  border: 0;
  padding: 0;
  cursor: pointer;
  font-family: inherit;
}
