:root {
  /* Carbon neutral scale */
  --cds-background: #ffffff;
  --cds-layer-01: #f4f4f4;
  --cds-layer-01-hover: #e8e8e8;
  --cds-layer-02: #e0e0e0;
  --cds-border-subtle: #c6c6c6;
  --cds-text-primary: #161616;
  --cds-text-secondary: #525252;
  --cds-text-placeholder: #6f6f6f;
  --cds-text-on-color: #ffffff;
  --cds-gray-90: #262626;
  --cds-gray-80: #393939;
  --cds-gray-30: #c6c6c6;

  /* Interactive */
  --cds-link-primary: #1b3a6b;
  --cds-link-primary-hover: #0043ce;
  --cds-button-primary-active: #002d9c;
  --cds-layer-selected: #edf5ff;
  --cds-focus: #1b3a6b;

  /* Support / status */
  --cds-support-error: #da1e28;
  --cds-support-success: #24a148;
  --cds-support-warning: #f1c21b;

  /* Notification grounds (Carbon v11, White theme). The pale tint behind an inline
     notification. Distinct from the tag palette below: tags sit on a page, notifications
     fill their own panel, so these are several steps lighter than the tag backgrounds. */
  --cds-notification-background-error: #fff1f1;
  --cds-notification-background-success: #defbe6;
  --cds-notification-background-warning: #fdf6dd;
  --cds-notification-background-info: #edf5ff;

  /* Warning's support colour is a mid yellow that disappears against its own pale ground,
     so the warning icon uses this darkened step instead. Left rules keep the yellow. */
  --cds-support-warning-icon: #b28600;

  /* The filled error glyph, as a background-image. Shared by the invalid input and the
     invalid select so a form never shows two different error icons. The colour is baked in
     because a background-image can't take currentColor; it is --cds-support-error. */
  --pcm-error-icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 32 32' fill='%23da1e28'%3E%3Cpath fill-rule='evenodd' d='M16 2C8.3 2 2 8.3 2 16s6.3 14 14 14 14-6.3 14-14S23.7 2 16 2zm-1.1 6h2.2v11h-2.2V8zM16 25c-.8 0-1.5-.7-1.5-1.5s.7-1.5 1.5-1.5 1.5.7 1.5 1.5-.7 1.5-1.5 1.5z'/%3E%3C/svg%3E");

  /* Tag palette (status pills). Carbon v11 tags: a light background from the
     hue's 10/20 step, text from its 70 step. Carbon ships no yellow or orange
     tag, so those two pair the hue's 10/20 step with a darkened text for
     contrast. Blue and cyan are kept apart because several status switches use
     Bootstrap's primary and info as distinct states. */
  --cds-tag-red-bg: #ffd7d9;
  --cds-tag-red-text: #a2191f;
  --cds-tag-green-bg: #a7f0ba;
  --cds-tag-green-text: #0e6027;
  --cds-tag-blue-bg: #d0e2ff;
  --cds-tag-blue-text: #0043ce;
  --cds-tag-cyan-bg: #bae6ff;
  --cds-tag-cyan-text: #00539a;
  --cds-tag-yellow-bg: #fcf4d6;
  --cds-tag-yellow-text: #4d3800;
  --cds-tag-orange-bg: #ffd9be;
  --cds-tag-orange-text: #8a3800;
  --cds-tag-gray-bg: #e0e0e0;
  --cds-tag-gray-text: #161616;

  /* Typography */
  --cds-font-sans:
    "IBM Plex Sans", "Helvetica Neue", Arial, sans-serif;

  /* Elevation (reserved for floating surfaces only) */
  --cds-shadow-raised: 0 2px 6px rgba(0, 0, 0, 0.3);
}

html,
body {
  font-family: var(--cds-font-sans);
  font-size: 16px;
  font-weight: 400;
  line-height: 1.5;
  color: var(--cds-text-primary);
  background: var(--cds-background);
  margin: 0;
}

#blazor-error-ui {
  position: fixed;
  bottom: 0;
  left: 0;
  right: 0;
  z-index: 1000;
}

.valid.modified:not([invalid]) {
  outline: 2px solid var(--cds-support-success);
}

.invalid {
  outline: 2px solid var(--cds-support-error);
}

/* === Sticky table header === */
/* Used by long admin/list pages so column headers stay visible when scrolling.
   Set `top` inline per call site: 52px below the page topbar, 0 in modal scroll containers. */
.sticky-thead {
  position: sticky;
  background: #fff;
  z-index: 1;
  box-shadow: inset 0 -1px 0 #dee2e6;
}

/* === Top bar layout === */
.top-bar {
  display: flex;
  align-items: center;
  background: var(--cds-text-primary);
  color: var(--cds-text-on-color);
  padding: 0 16px;
  height: 48px;
  position: sticky;
  top: 0;
  z-index: 100;
}

.top-bar-brand {
  font-family: var(--cds-font-sans);
  font-weight: 600;
  font-size: 0.875rem;
  letter-spacing: 0.16px;
  margin-right: 24px;
  white-space: nowrap;
}

.top-bar-right {
  margin-left: auto;
  white-space: nowrap;
}

/* === Horizontal nav === */
.top-nav {
  display: flex;
  align-items: center;
  gap: 0;
  flex-wrap: wrap;
  overflow: visible;
}

.top-nav > a,
.top-nav .nav-dropdown-toggle {
  display: inline-flex;
  align-items: center;
  padding: 0 16px;
  height: 48px;
  color: var(--cds-gray-30);
  text-decoration: none;
  font-family: inherit;
  font-size: 0.875rem;
  font-weight: 400;
  letter-spacing: 0.16px;
  white-space: nowrap;
  border: none;
  border-bottom: 2px solid transparent;
  background: none;
  cursor: pointer;
  transition:
    background 0.11s,
    color 0.11s,
    border-color 0.11s;
}

.top-nav > a:hover,
.top-nav .nav-dropdown-toggle:hover {
  background: var(--cds-gray-90);
  color: var(--cds-text-on-color);
}

.top-nav > a.active {
  color: var(--cds-text-on-color);
  background: var(--cds-gray-90);
  border-bottom-color: var(--cds-text-on-color);
}

/* === Dropdown menus === */
.nav-dropdown {
  position: relative;
}

.nav-dropdown-menu {
  position: absolute;
  top: 48px;
  left: 0;
  background: var(--cds-background);
  border: 1px solid var(--cds-layer-02);
  border-radius: 0;
  box-shadow: var(--cds-shadow-raised);
  min-width: 200px;
  z-index: 200;
  display: flex;
  flex-direction: column;
}

.nav-dropdown-menu a {
  display: block;
  padding: 8px 16px;
  color: var(--cds-text-primary);
  text-decoration: none;
  font-size: 0.875rem;
  letter-spacing: 0.16px;
  white-space: nowrap;
}

.nav-dropdown-menu a:hover,
.nav-dropdown-menu a.active {
  background: var(--cds-layer-01-hover);
  color: var(--cds-text-primary);
}

/* G96: the Flagged / Recent menus now render even when empty, so a new user can
   discover the features by exploration. This is the self-explaining empty row. */
.nav-dropdown-empty {
  display: block;
  padding: 8px 16px;
  color: var(--cds-text-secondary);
  font-size: 0.8125rem;
  letter-spacing: 0.16px;
  max-width: 260px;
  white-space: normal;
}

/* === Tooltips === */
/* Bootstrap centres tip text; ours reads as a sentence, so left-align it. One rule covers the
   whole app because every title goes through the single delegated tooltip in js/tooltips.js. */
.tooltip-inner {
  text-align: left;
}

/* === Main content === */
.content {
  padding-top: 24px;
}

/* === Notification bell === */
.notif-bell-wrapper {
  position: relative;
  display: inline-flex;
  align-items: center;
  margin-right: 8px;
}

.notif-bell-btn {
  position: relative;
  background: none;
  border: none;
  border-bottom: 2px solid transparent;
  cursor: pointer;
  color: var(--cds-gray-30);
  font-size: 1.125rem;
  padding: 0 8px;
  height: 48px;
  display: inline-flex;
  align-items: center;
  transition:
    color 0.11s,
    background 0.11s;
}

.notif-bell-btn:hover {
  color: var(--cds-text-on-color);
  background: var(--cds-gray-90);
}

.notif-badge {
  position: absolute;
  top: 8px;
  right: 2px;
  background: var(--cds-support-error);
  color: var(--cds-text-on-color);
  font-size: 0.75rem;
  font-weight: 600;
  letter-spacing: 0.32px;
  border-radius: 24px; /* pill — sole rounded exception */
  padding: 0 8px;
  min-width: 16px;
  text-align: center;
  line-height: 1.33;
  pointer-events: none;
}

.notif-dropdown {
  position: absolute;
  top: 48px;
  right: 0;
  width: 320px;
  background: var(--cds-background);
  border: 1px solid var(--cds-layer-02);
  border-radius: 0;
  box-shadow: var(--cds-shadow-raised);
  z-index: 300;
  display: flex;
  flex-direction: column;
  overflow: hidden;
}

.notif-dropdown-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 8px 16px;
  background: var(--cds-layer-01);
  border-bottom: 1px solid var(--cds-layer-02);
  font-size: 0.875rem;
  font-weight: 600;
  letter-spacing: 0.16px;
  color: var(--cds-text-primary);
}

.notif-mark-all-btn {
  background: none;
  border: none;
  cursor: pointer;
  font-family: inherit;
  font-size: 0.75rem;
  letter-spacing: 0.32px;
  color: var(--cds-link-primary);
  padding: 0;
  text-decoration: none;
}

.notif-mark-all-btn:hover {
  color: var(--cds-link-primary-hover);
  text-decoration: underline;
}

.notif-dropdown-list {
  max-height: 360px;
  overflow-y: auto;
}

.notif-empty {
  padding: 24px 16px;
  text-align: center;
  color: var(--cds-text-secondary);
  font-size: 0.875rem;
  letter-spacing: 0.16px;
}

.notif-item {
  padding: 8px 16px;
  border-bottom: 1px solid var(--cds-layer-01);
  cursor: pointer;
  transition: background 0.11s;
}

.notif-item:last-child {
  border-bottom: none;
}

.notif-item:hover {
  background: var(--cds-layer-01-hover);
}

.notif-unread {
  background: var(--cds-layer-selected);
}

.notif-read {
  background: var(--cds-background);
}

.notif-item-time {
  font-size: 0.75rem;
  letter-spacing: 0.32px;
  color: var(--cds-text-placeholder);
}

/* =====================================================================
   Carbon-style overrides for Bootstrap classes used across all pages.
   Loaded after bootstrap.min.css, before component-scoped CSS (which
   keeps page-specific styling working unchanged). Uses only --cds-*
   tokens declared above.
   ===================================================================== */

/* ─── Buttons ────────────────────────────────────────────── */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  height: 40px;
  padding: 0 16px;
  border: 1px solid transparent;
  border-radius: 0;
  font-family: var(--cds-font-sans);
  font-size: 0.875rem;
  font-weight: 400;
  letter-spacing: 0.16px;
  line-height: 1.29;
  cursor: pointer;
  white-space: nowrap;
  transition:
    background-color 0.07s,
    color 0.07s,
    border-color 0.07s;
}

/* .btn is a centered flex container, so Bootstrap's .text-start silently does nothing on one.
   Make the utility mean what it says wherever it is written on a button. */
.btn.text-start {
  justify-content: flex-start;
}

.btn:focus,
.btn:focus-visible {
  box-shadow: none;
  outline: 2px solid var(--cds-focus);
  outline-offset: -4px;
}

.btn:disabled,
.btn.disabled {
  opacity: 0.5;
  cursor: not-allowed;
  pointer-events: auto;
}

.btn-sm,
.btn-group-sm > .btn {
  height: 32px;
  padding: 0 12px;
  font-size: 0.875rem;
  line-height: 1.29;
}

.btn-lg,
.btn-group-lg > .btn {
  height: 48px;
  padding: 0 16px;
  font-size: 1rem;
}

/* Primary — IBM Blue 60 */
.btn-primary,
.btn-success {
  background-color: var(--cds-link-primary);
  color: var(--cds-text-on-color);
  border-color: var(--cds-link-primary);
}

.btn-primary:hover:not(:disabled):not(.disabled),
.btn-success:hover:not(:disabled):not(.disabled) {
  background-color: var(--cds-link-primary-hover);
  border-color: var(--cds-link-primary-hover);
  color: var(--cds-text-on-color);
}

.btn-primary:active,
.btn-success:active {
  background-color: var(--cds-button-primary-active);
  border-color: var(--cds-button-primary-active);
  color: var(--cds-text-on-color);
}

/* Secondary — Gray 80 solid */
.btn-secondary {
  background-color: var(--cds-gray-80);
  color: var(--cds-text-on-color);
  border-color: var(--cds-gray-80);
}

.btn-secondary:hover:not(:disabled):not(.disabled) {
  background-color: var(--cds-gray-90);
  border-color: var(--cds-gray-90);
  color: var(--cds-text-on-color);
}

/* Danger — Red 60 solid */
.btn-danger {
  background-color: var(--cds-support-error);
  color: var(--cds-text-on-color);
  border-color: var(--cds-support-error);
}

.btn-danger:hover:not(:disabled):not(.disabled) {
  background-color: var(--cds-support-error);
  filter: brightness(0.9);
  color: var(--cds-text-on-color);
}

/* Warning — keep yellow accent on text/border, neutral surface */
.btn-warning {
  background-color: var(--cds-support-warning);
  color: var(--cds-text-primary);
  border-color: var(--cds-support-warning);
}

/* Tertiary (outline-blue) — ghost with border */
.btn-outline-primary {
  background-color: transparent;
  color: var(--cds-link-primary);
  border-color: var(--cds-link-primary);
}

.btn-outline-primary:hover:not(:disabled):not(.disabled) {
  background-color: var(--cds-layer-selected);
  color: var(--cds-link-primary-hover);
  border-color: var(--cds-link-primary-hover);
}

/* Outline-secondary — neutral ghost */
.btn-outline-secondary {
  background-color: transparent;
  color: var(--cds-text-primary);
  border-color: var(--cds-border-subtle);
}

.btn-outline-secondary:hover:not(:disabled):not(.disabled) {
  background-color: var(--cds-layer-01);
  color: var(--cds-text-primary);
  border-color: var(--cds-text-primary);
}

/* Outline-warning */
.btn-outline-warning {
  background-color: transparent;
  color: var(--cds-text-primary);
  border-color: var(--cds-support-warning);
}

.btn-outline-warning:hover:not(:disabled):not(.disabled) {
  background-color: var(--cds-layer-01);
  color: var(--cds-text-primary);
  border-color: var(--cds-support-warning);
}

/* Outline-danger */
.btn-outline-danger {
  background-color: transparent;
  color: var(--cds-support-error);
  border-color: var(--cds-support-error);
}

.btn-outline-danger:hover:not(:disabled):not(.disabled) {
  background-color: var(--cds-layer-01);
  color: var(--cds-support-error);
  border-color: var(--cds-support-error);
}

/* Outline-success */
.btn-outline-success {
  background-color: transparent;
  color: var(--cds-support-success);
  border-color: var(--cds-support-success);
}

.btn-outline-success:hover:not(:disabled):not(.disabled) {
  background-color: var(--cds-layer-01);
  color: var(--cds-support-success);
  border-color: var(--cds-support-success);
}

/* Link button — ghost link, no chrome */
.btn-link {
  background: none;
  border: none;
  padding: 0;
  height: auto;
  color: var(--cds-link-primary);
  font-family: var(--cds-font-sans);
  font-size: 0.875rem;
  font-weight: 400;
  letter-spacing: 0.16px;
  text-decoration: none;
}

.btn-link:hover:not(:disabled):not(.disabled) {
  color: var(--cds-link-primary-hover);
  text-decoration: underline;
}

.btn-link.text-danger {
  color: var(--cds-support-error);
}

.btn-link.text-danger:hover:not(:disabled):not(.disabled) {
  color: var(--cds-support-error);
  text-decoration: underline;
}

/* Bootstrap utility shrinks like .py-0 .px-2 used on tiny icon-buttons */
.btn.py-0 {
  padding-top: 0;
  padding-bottom: 0;
}

/* ─── Badges → Carbon tags ───────────────────────────────── */
.badge {
  display: inline-flex;
  align-items: center;
  padding: 4px 12px;
  border-radius: 24px;
  font-family: var(--cds-font-sans);
  font-size: 0.75rem;
  font-weight: 400;
  letter-spacing: 0.32px;
  line-height: 1.33;
  background-color: var(--cds-layer-selected);
  color: var(--cds-link-primary);
}

.badge.bg-primary,
.badge.bg-info {
  background-color: var(--cds-layer-selected);
  color: var(--cds-link-primary);
}

.badge.bg-success {
  background-color: var(--cds-layer-selected);
  color: var(--cds-support-success);
}

.badge.bg-warning {
  background-color: var(--cds-layer-01);
  color: var(--cds-text-primary);
}

.badge.bg-danger {
  background-color: var(--cds-layer-01);
  color: var(--cds-support-error);
}

.badge.bg-secondary {
  background-color: var(--cds-layer-01);
  color: var(--cds-text-primary);
}

.badge.text-dark {
  color: var(--cds-text-primary);
}

/* Carbon tags — the status-pill family. Pair one of these with .badge and NO
   bg-* class. Bootstrap emits its bg-* utilities with !important, so a bg-*
   in the markup wins the background and leaves Carbon's text colour sitting on
   a Bootstrap fill — that is what made Rejected render red-on-red at 1.11:1.
   Nothing here competes with Bootstrap, so nothing here needs !important. */
.badge.tag-red    { background-color: var(--cds-tag-red-bg);    color: var(--cds-tag-red-text); }
.badge.tag-green  { background-color: var(--cds-tag-green-bg);  color: var(--cds-tag-green-text); }
.badge.tag-blue   { background-color: var(--cds-tag-blue-bg);   color: var(--cds-tag-blue-text); }
.badge.tag-cyan   { background-color: var(--cds-tag-cyan-bg);   color: var(--cds-tag-cyan-text); }
.badge.tag-yellow { background-color: var(--cds-tag-yellow-bg); color: var(--cds-tag-yellow-text); }
.badge.tag-orange { background-color: var(--cds-tag-orange-bg); color: var(--cds-tag-orange-text); }
.badge.tag-gray   { background-color: var(--cds-tag-gray-bg);   color: var(--cds-tag-gray-text); }

/* ─── Alerts → Carbon low-contrast inline notifications ─── */
/* Carbon's inline notification is four things: a 3px status rule down the left, a tinted
   ground, a filled status icon, and the message. We shipped the rule alone, which left an
   error sitting on the same Gray-10 panel as everything else — the stripe was the only red
   in it, and at a glance a failure read the same as an info box.
   Each variant now sets three custom properties and the shared rules below do the rest.
   The icon is a mask, not a coloured background-image, so its colour still comes from a
   --cds-* token rather than being baked into the data URI. */
.alert {
  position: relative;
  display: flex;
  align-items: flex-start;
  background-color: var(--cds-layer-01);
  border: none;
  border-left: 3px solid var(--cds-link-primary);
  border-radius: 0;
  padding: 12px 16px;
  margin-bottom: 16px;
  font-family: var(--cds-font-sans);
  font-size: 0.875rem;
  letter-spacing: 0.16px;
  line-height: 1.29;
  color: var(--cds-text-primary);
}

/* The tint-and-glyph treatment is scoped to the four STATUS variants. A bare .alert,
   .alert-secondary and .alert-light are muted panels rather than Carbon statuses — they keep
   the flat Gray-10 ground above and get no glyph. Applying this to the base class turned
   "View only — you are not the assigned examiner" into a blue info callout. */
.alert-primary,
.alert-info,
.alert-success,
.alert-warning,
.alert-danger {
  --alert-icon-color: var(--alert-accent);
  background-color: var(--alert-ground);
  border-left-color: var(--alert-accent);
  /* 16 inset + 16 glyph + 16 gutter, reserved because the glyph is positioned, not a flex item. */
  padding-left: 48px;
}

/* Filled status icon. Positioned rather than made a flex item, deliberately: seven alerts carry
   `justify-content-between` with exactly two children, and a third flex item would split the
   free space into two gaps so the message stopped hugging the left edge. It also keeps working
   on #blazor-error-ui, whose inline `display` overrides the flex above and would collapse an
   in-flow pseudo-element to zero size. `top` matches the base padding above. */
.alert-primary::before,
.alert-info::before,
.alert-success::before,
.alert-warning::before,
.alert-danger::before {
  content: "";
  position: absolute;
  left: 16px;
  top: 12px;
  width: 16px;
  height: 16px;
  background-color: var(--alert-icon-color);
  -webkit-mask: var(--alert-icon) no-repeat center / 16px 16px;
  mask: var(--alert-icon) no-repeat center / 16px 16px;
}

/* Hairline on the three sides the 3px rule doesn't cover, so the tint reads as a panel with
   an edge rather than a wash bleeding into the page. Held at 40% so it never competes with
   the status rule. Inset -3px on the left so it meets the rule instead of sitting inside it. */
.alert-primary::after,
.alert-info::after,
.alert-success::after,
.alert-warning::after,
.alert-danger::after {
  content: "";
  position: absolute;
  inset: 0 0 0 -3px;
  border: 1px solid var(--alert-accent);
  opacity: 0.4;
  pointer-events: none;
}

.alert-primary,
.alert-info {
  --alert-accent: var(--cds-link-primary);
  --alert-ground: var(--cds-notification-background-info);
  --alert-icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 32 32'%3E%3Cpath fill-rule='evenodd' d='M16 2C8.3 2 2 8.3 2 16s6.3 14 14 14 14-6.3 14-14S23.7 2 16 2zm1.1 22h-2.2V14h2.2v10zM16 11.5c-.8 0-1.5-.7-1.5-1.5s.7-1.5 1.5-1.5 1.5.7 1.5 1.5-.7 1.5-1.5 1.5z'/%3E%3C/svg%3E");
}

.alert-success {
  --alert-accent: var(--cds-support-success);
  --alert-ground: var(--cds-notification-background-success);
  --alert-icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 32 32'%3E%3Cpath fill-rule='evenodd' d='M16 2C8.3 2 2 8.3 2 16s6.3 14 14 14 14-6.3 14-14S23.7 2 16 2zm-2.3 19.7L8 16l1.6-1.6 4.1 4.1 8.7-8.7 1.6 1.6-10.3 10.3z'/%3E%3C/svg%3E");
}

.alert-warning {
  --alert-accent: var(--cds-support-warning);
  --alert-icon-color: var(--cds-support-warning-icon);
  --alert-ground: var(--cds-notification-background-warning);
  --alert-icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 32 32'%3E%3Cpath fill-rule='evenodd' d='M16 2L1 29h30L16 2zm-1.1 9h2.2v9h-2.2v-9zM16 26c-.8 0-1.5-.7-1.5-1.5s.7-1.5 1.5-1.5 1.5.7 1.5 1.5-.7 1.5-1.5 1.5z'/%3E%3C/svg%3E");
}

.alert-danger {
  --alert-accent: var(--cds-support-error);
  --alert-ground: var(--cds-notification-background-error);
  /* Reuses the form field's glyph rather than carrying a second copy of the same path: a mask
     keys on the source's alpha channel, so the #da1e28 baked into that token is ignored here
     and the colour still comes from --alert-icon-color. One glyph, so the two can't diverge. */
  --alert-icon: var(--pcm-error-icon);
}

.alert code {
  background: var(--cds-background);
  padding: 0 4px;
  font-family: "IBM Plex Mono", Menlo, Courier, monospace;
  font-size: 0.8125rem;
  color: var(--cds-text-primary);
}

/* ─── Cards ──────────────────────────────────────────────── */
.card {
  background-color: var(--cds-layer-01);
  border: none;
  border-radius: 0;
  box-shadow: none;
}

.card-header {
  background-color: transparent;
  border-bottom: 1px solid var(--cds-layer-02);
  padding: 12px 16px;
  font-family: var(--cds-font-sans);
  font-size: 0.875rem;
  font-weight: 600;
  letter-spacing: 0.16px;
  color: var(--cds-text-primary);
}

.card-body {
  padding: 16px;
}

.card-footer {
  background-color: transparent;
  border-top: 1px solid var(--cds-layer-02);
  padding: 12px 16px;
}

/* Required-field marker — red asterisk next to required input labels. Decorative;
   pair with aria-hidden="true" so the asterisk isn't read aloud as "Star". */
.required-marker {
  color: var(--cds-support-error);
  margin-left: 2px;
}

/* ─── Form controls — Carbon bottom-border inputs ─────────
   .form-control / .form-select / textarea share the look:
   Gray-10 surface, no top/side border, hairline bottom border that
   thickens to 2px Blue-60 on focus. */
.form-control,
.form-select {
  background-color: var(--cds-layer-01);
  border: none;
  border-bottom: 1px solid var(--cds-border-subtle);
  border-radius: 0;
  height: 40px;
  padding: 0 16px;
  font-family: var(--cds-font-sans);
  font-size: 0.875rem;
  letter-spacing: 0.16px;
  line-height: 1.29;
  color: var(--cds-text-primary);
  box-shadow: none;
  transition: border-color 0.07s;
}

textarea.form-control {
  height: auto;
  min-height: 64px;
  padding: 8px 16px;
  resize: vertical;
}

.form-control:hover,
.form-select:hover {
  border-bottom-color: var(--cds-text-primary);
}

.form-control:focus,
.form-select:focus {
  outline: none;
  border-color: transparent transparent var(--cds-focus) transparent;
  border-bottom-width: 2px;
  box-shadow: none;
  background-color: var(--cds-layer-01);
  color: var(--cds-text-primary);
}

.form-control:disabled,
.form-select:disabled {
  color: var(--cds-text-placeholder);
  cursor: not-allowed;
  border-bottom-color: transparent;
}

.form-control::placeholder {
  color: var(--cds-text-placeholder);
}

/* Invalid / missing required field. Carbon marks the whole control, not just its bottom
   edge — a 2px support-error outline drawn inside the box, so a missing field is findable
   by scanning rather than by reading. This is the same mechanism .prefilled uses just
   below, red for "fix this" against its green for "check this"; a Carbon input has no side
   or top borders, so an outline is what draws a box round one.
   The previous rule moved only the 1px bottom hairline from grey to red, which was all but
   invisible against the Gray-10 fill — and nothing in the app set the class anyway.
   :focus is included so the outline survives the examiner clicking into the field to fix
   it; it clears when the value changes, not when the caret lands. */
.form-control.is-invalid,
.form-select.is-invalid,
.form-control.is-invalid:focus,
.form-select.is-invalid:focus {
  outline: 2px solid var(--cds-support-error);
  outline-offset: -2px;
  border-bottom-color: var(--cds-support-error);
  box-shadow: none;
}

/* Filled error icon inside the right edge, matching the notification icon. */
.form-control.is-invalid {
  background-image: var(--pcm-error-icon);
  background-repeat: no-repeat;
  background-position: right 12px center;
  background-size: 16px 16px;
  padding-right: 36px;
}

/* A select already carries a background-image — its dropdown caret — and Bootstrap's own
   .form-select.is-invalid appends an icon of its own beside it, in Bootstrap's red and its
   outline style. Left alone that puts two different error glyphs in one form, so both layers
   are restated here with the filled icon the inputs use.
   The :not() guards are not decorative: Bootstrap positions and sizes these layers from
   `.form-select.is-invalid:not([multiple]):not([size])`, which outranks a plain
   `.form-select.is-invalid`. Overriding the image alone leaves Bootstrap's geometry applied to
   our layer order — the icon silently takes the caret's 16x12 box and renders as an ellipse.
   Matching the selector keeps image, position and size described in one place. */
.form-select.is-invalid:not([multiple]):not([size]) {
  /* The `none` fallback matters: --bs-form-select-bg-img is Bootstrap's, not ours, so a version
     bump or a failed CDN load would otherwise leave the whole shorthand invalid at computed-value
     time and strip BOTH layers — losing the error icon, which is the half that must survive. */
  background-image: var(--pcm-error-icon), var(--bs-form-select-bg-img, none);
  background-repeat: no-repeat, no-repeat;
  background-position: right 36px center, right 12px center;
  background-size: 16px 16px, 16px 12px;
  padding-right: 60px;
}

/* Bootstrap ships .invalid-feedback hidden until a sibling carries .is-invalid, which is
   the behaviour we want; this only restyles it to Carbon's 12px error text. */
.invalid-feedback {
  font-family: var(--cds-font-sans);
  font-size: 0.75rem;
  letter-spacing: 0.32px;
  line-height: 1.33;
  color: var(--cds-support-error);
  margin-top: 4px;
}

/* Carbon inputs only have a bottom border, so a four-sided outline visually circles the field
   to mark it as a roster-suggested value distinct from original data. Overrides :focus too so
   the marker doesn't disappear the moment the examiner clicks into the field. The class is
   removed by ClaimFormFields once the user edits the field. */
.form-control.prefilled,
.form-select.prefilled,
.form-control.prefilled:focus,
.form-select.prefilled:focus {
  outline: 2px solid var(--cds-support-success);
  outline-offset: -2px;
}

/* A roster value can be both prefilled and invalid — the roster carried an SSN and the SSN is
   malformed. Both draw the same outline, so without this the later .prefilled rule would win
   and a bad value would sit behind a green "looks good" border. Invalid outranks suggested:
   "fix this" is the more urgent of the two, and the "from roster" badge still says where the
   value came from. */
.form-control.prefilled.is-invalid,
.form-select.prefilled.is-invalid,
.form-control.prefilled.is-invalid:focus,
.form-select.prefilled.is-invalid:focus {
  outline-color: var(--cds-support-error);
}

.form-control-sm,
.form-select-sm {
  height: 32px;
  padding: 0 12px;
  font-size: 0.875rem;
}

.form-control-lg,
.form-select-lg {
  height: 48px;
}

.form-label {
  display: block;
  font-family: var(--cds-font-sans);
  font-size: 0.75rem;
  font-weight: 400;
  letter-spacing: 0.32px;
  line-height: 1.33;
  color: var(--cds-text-secondary);
  margin-bottom: 8px;
}

.form-text {
  font-family: var(--cds-font-sans);
  font-size: 0.75rem;
  letter-spacing: 0.32px;
  line-height: 1.33;
  color: var(--cds-text-secondary);
}

.form-check {
  padding-left: 0;
  margin-bottom: 8px;
}

.form-check .form-check-input {
  float: none;
  margin-left: 0;
}

.form-check-input {
  width: 16px;
  height: 16px;
  margin-right: 8px;
  border: 1px solid var(--cds-text-primary);
  border-radius: 0;
  accent-color: var(--cds-link-primary);
  background-color: var(--cds-background);
}

.form-check-input:checked {
  background-color: var(--cds-link-primary);
  border-color: var(--cds-link-primary);
}

.form-check-input:focus {
  box-shadow: none;
  outline: 2px solid var(--cds-focus);
  outline-offset: 2px;
}

.form-check-label {
  font-family: var(--cds-font-sans);
  font-size: 0.875rem;
  letter-spacing: 0.16px;
  color: var(--cds-text-primary);
}

.input-group-text {
  background-color: var(--cds-layer-02);
  border: none;
  border-radius: 0;
  font-family: var(--cds-font-sans);
  font-size: 0.875rem;
  letter-spacing: 0.16px;
  color: var(--cds-text-primary);
}

/* ─── List groups ────────────────────────────────────────── */
.list-group {
  border-radius: 0;
}

.list-group-item {
  background-color: var(--cds-background);
  border: none;
  border-bottom: 1px solid var(--cds-layer-02);
  border-radius: 0;
  padding: 12px 16px;
  font-family: var(--cds-font-sans);
  font-size: 0.875rem;
  letter-spacing: 0.16px;
  color: var(--cds-text-primary);
}

.list-group-item:last-child {
  border-bottom: none;
}

.list-group-flush .list-group-item {
  background-color: transparent;
}

/* ─── Tables — light Carbon treatment for .table users ──── */
.table {
  font-family: var(--cds-font-sans);
  font-size: 0.875rem;
  letter-spacing: 0.16px;
  color: var(--cds-text-primary);
  border-color: var(--cds-layer-02);
}

.table > :not(caption) > * > * {
  background-color: transparent;
  border-bottom-color: var(--cds-layer-02);
}

.table > thead > tr > th {
  font-weight: 600;
  font-size: 0.75rem;
  letter-spacing: 0.32px;
  text-transform: uppercase;
  color: var(--cds-text-secondary);
  border-bottom: 1px solid var(--cds-text-primary);
  background-color: var(--cds-layer-01);
  padding: 12px 16px;
}

.table > tbody > tr > td {
  padding: 12px 16px;
  vertical-align: middle;
}

.table-hover > tbody > tr:hover > * {
  background-color: var(--cds-layer-01);
}

/* Clickable sort headers used by list pages with server-side sort. */
.table > thead > tr > th.sortable {
  cursor: pointer;
  user-select: none;
  white-space: nowrap;
}

.table > thead > tr > th.sortable:hover {
  background-color: var(--cds-layer-01-hover);
}

/* ─── Headings ───────────────────────────────────────────── */
h1, .h1 {
  font-family: var(--cds-font-sans);
  font-weight: 400;
  letter-spacing: 0;
  color: var(--cds-text-primary);
}

h2, .h2 {
  font-family: var(--cds-font-sans);
  font-weight: 400;
  letter-spacing: 0;
  color: var(--cds-text-primary);
}

h3, .h3 {
  font-family: var(--cds-font-sans);
  font-weight: 400;
  letter-spacing: 0;
  color: var(--cds-text-primary);
}

h4, .h4 {
  font-family: var(--cds-font-sans);
  font-size: 1.25rem;
  font-weight: 600;
  line-height: 1.4;
  letter-spacing: 0;
  color: var(--cds-text-primary);
}

h5, .h5 {
  font-family: var(--cds-font-sans);
  font-weight: 600;
  color: var(--cds-text-primary);
}

/* ─── Text utilities (color only — keep Bootstrap spacing intact) ── */
.text-muted {
  color: var(--cds-text-secondary) !important;
}

.text-danger {
  color: var(--cds-support-error) !important;
}

.text-success {
  color: var(--cds-support-success) !important;
}

.text-warning {
  color: var(--cds-support-warning) !important;
}

.text-primary,
.text-info {
  color: var(--cds-link-primary) !important;
}

/* ─── Inline anchor links (outside .btn-link) ────────────── */
a:not(.btn):not(.nav-link):not(.dropdown-item) {
  color: var(--cds-link-primary);
  text-decoration: none;
}

a:not(.btn):not(.nav-link):not(.dropdown-item):hover {
  color: var(--cds-link-primary-hover);
  text-decoration: underline;
}

/* ─── Border-accent panel — used for override notes etc. ──
   Carbon flat panel with a coloured left bar; we override the
   thick Bootstrap border with a 3px coloured rail. */
.border-start.border-warning {
  border-left: 3px solid var(--cds-support-warning) !important;
  border-top: none !important;
  border-right: none !important;
  border-bottom: none !important;
}

.border-start.border-secondary {
  border-left: 3px solid var(--cds-border-subtle) !important;
  border-top: none !important;
  border-right: none !important;
  border-bottom: none !important;
}

.border-start.border-danger {
  border-left: 3px solid var(--cds-support-error) !important;
  border-top: none !important;
  border-right: none !important;
  border-bottom: none !important;
}

.border-start.border-primary,
.border-start.border-info {
  border-left: 3px solid var(--cds-link-primary) !important;
  border-top: none !important;
  border-right: none !important;
  border-bottom: none !important;
}

/* =====================================================================
   Carbon record-detail primitives.

   Shared by state-record pages (BC3E, BC28, BC2 once converted) for both
   read and edit views. Each page groups its ~12–29 fields into "sections"
   that render as flat Gray-10 panels with a 12px uppercase caption title.

   Two field-layout flavors:
     - .record-fields: read-only, inline [label value] pairs that wrap.
     - .record-grid:   editable, auto-fit columns of stacked label/input.

   Page-specific structures (e.g., BC3E's quarterly mini-table) live in
   that page's own scoped CSS.
   ===================================================================== */

.record-form {
  display: flex;
  flex-direction: column;
  gap: 16px;
  font-family: var(--cds-font-sans);
  color: var(--cds-text-primary);
  margin-top: 8px;
}

.record-section {
  background: var(--cds-layer-01);
  padding: 16px;
}

.record-section-title {
  margin: 0 0 12px 0;
  padding: 0;
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.32px;
  line-height: 16px;
  text-transform: uppercase;
  color: var(--cds-text-secondary);
}

/* Edit forms increase section-title margin to breathe under their grid. */
.record-form .record-section .record-grid + * {
  margin-top: 12px;
}

/* ─── Read view: inline label-value pairs ────────────────── */
.record-fields {
  display: flex;
  flex-wrap: wrap;
  gap: 8px 32px;
  margin: 0;
}

.record-field {
  display: flex;
  align-items: baseline;
  gap: 8px;
  min-width: 0;
}

.record-field dt {
  font-size: 12px;
  font-weight: 400;
  letter-spacing: 0.32px;
  line-height: 16px;
  color: var(--cds-text-secondary);
  margin: 0;
  white-space: nowrap;
}

.record-field dd {
  font-size: 14px;
  font-weight: 400;
  letter-spacing: 0.16px;
  line-height: 20px;
  color: var(--cds-text-primary);
  margin: 0;
}

/* ─── Edit form: stacked label + input in an auto-fit grid ── */
.record-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
  gap: 12px 16px;
}

.record-grid__field {
  display: flex;
  flex-direction: column;
  min-width: 0;
}

/* Single-character / 2-digit fields shouldn't claim a full grid column. */
.record-grid__field--narrow {
  flex: 0 0 96px;
  max-width: 96px;
}

/* Long string fields (Intake key, Employer name, Full address) span two
   columns when there's room. */
.record-grid__field--wide {
  grid-column: span 2;
}

@media (max-width: 480px) {
  .record-grid__field--narrow {
    flex: initial;
    max-width: none;
  }
  .record-grid__field--wide {
    grid-column: span 1;
  }
}

/* ─── Action bar (right-aligned Save/Cancel) ─────────────── */
.record-actions {
  display: flex;
  justify-content: flex-end;
  align-items: stretch;
  gap: 1px;
  margin-top: 16px;
  padding-top: 16px;
  border-top: 1px solid var(--cds-layer-02);
}

.record-actions .btn {
  min-width: 144px;
}

/* ─── Carbon-style page breadcrumb (used on detail pages) ── */
.page-breadcrumb { font-size: 0.85rem; margin-bottom: 0.5rem; color: #6c7a8a; }

/* ─── Wage-audit prefill badge / read-only answer (public form + round-builder modal) ── */
.wa-prefill-badge { display: inline-block; margin-left: .5rem; padding: .05rem .4rem; font-size: .7rem; font-weight: 500; background: #fff3cd; color: #664d03; border-radius: 999px; }
.wa-readonly-answer { padding: .3rem 0; font-weight: 600; }
.page-breadcrumb a { color: #0d6efd; text-decoration: none; }
.page-breadcrumb a:hover { text-decoration: underline; }
.page-breadcrumb .separator { margin: 0 0.4rem; color: #adb5bd; }
.page-breadcrumb .current { color: #495057; }

/* ─── Wage audit submit modal — fax preflight estimate row ── */
.fax-preflight { font-size: 13px; color: #555; padding: 6px 0; }
.fax-preflight-warn { color: #b35900; font-weight: 600; }
.fax-preflight .warn-suffix { margin-left: 4px; }

/* ─── Click-to-place modals (FormFill + WA BPC98) ─────────────
   Shared two-pane layout: left rail = field/question list,
   right pane = PdfViewer with overlay markers. */
.click-to-place-modal { display: flex; flex-direction: column; min-height: 75vh; }

.click-to-place-body {
    display: grid;
    grid-template-columns: 280px 1fr;
    gap: 0;
    min-height: 65vh;
    position: relative;
}

.field-list-pane {
    display: flex;
    flex-direction: column;
    border-right: 1px solid #e5e7eb;
    background: #f9fafb;
    min-height: 0;
}

.field-list-active {
    padding: 8px 12px;
    border-bottom: 1px solid #e5e7eb;
    background: #fff;
}
.field-list-active-label {
    font-size: 0.7rem;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    color: #6b7280;
}
.field-list-active-key { font-size: 0.95rem; font-weight: 600; color: #111827; margin-top: 2px; }

.field-list-scroll {
    flex: 1;
    overflow-y: auto;
    padding: 4px;
    min-height: 0;
}

.field-row {
    display: flex;
    align-items: center;
    gap: 6px;
    width: 100%;
    text-align: left;
    background: transparent;
    border: 1px solid transparent;
    padding: 4px 6px;
    border-radius: 4px;
    font-size: 0.82rem;
    color: #374151;
    cursor: pointer;
}
.field-row:hover { background: #eef2ff; }
.field-row.active { background: #2563eb; color: #fff; border-color: #2563eb; }
.field-row.active code { color: #fff; }

.field-row-dot {
    display: inline-block;
    width: 8px;
    height: 8px;
    border-radius: 50%;
    background: #d1d5db;
    flex: 0 0 auto;
}
.field-row.has-placement .field-row-dot { background: #10b981; }
.field-row.active.has-placement .field-row-dot { background: #fde68a; }

.field-row-key { flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.field-row-page { font-size: 0.7rem; color: #6b7280; }
.field-row.active .field-row-page { color: #dbeafe; }

.field-list-controls {
    border-top: 1px solid #e5e7eb;
    padding: 8px 12px;
    background: #fff;
}

.ctp-canvas-pane {
    display: flex;
    flex-direction: column;
    min-width: 0;
    min-height: 0;
    position: relative;
}

.placement-marker {
    position: absolute;
    /* Top-left anchored: matches the server's TextPlacement convention
       (top-left origin per CONTEXT.md / WageAuditFieldPlacement) so the
       preview lands where the fill actually renders. */
    background: rgba(96, 165, 250, 0.85);
    color: #fff;
    border: 1px solid #1d4ed8;
    padding: 1px 4px;
    border-radius: 3px;
    pointer-events: none;
    white-space: nowrap;
    font-weight: 500;
    line-height: 1.1;
    max-width: 240px;
    overflow: hidden;
    text-overflow: ellipsis;
}
.placement-marker.active {
    background: rgba(250, 204, 21, 0.95);
    color: #111827;
    border-color: #b45309;
}

.click-to-place-modal .overlay-click-catch {
    position: absolute;
    top: 0; left: 0; right: 0; bottom: 0;
    cursor: crosshair;
    background: transparent;
    /* PdfViewer's .pdf-viewer-overlay sets pointer-events:none; its scoped
       ".pdf-viewer-overlay > *" re-enable can't reach this element because it's
       rendered from a consumer RenderFragment and carries no PdfViewer scope
       attribute. Re-enable explicitly so clicks reach OnCanvasClick. */
    pointer-events: auto;
}

/* DocumentReviseModal's redaction overlay (EmployerDocumentRedaction SPEC §7.2). Global for TWO
   reasons that stack, either of which alone would void a scoped rule:

   1. Like .overlay-click-catch above, these sit inside PdfViewer's .pdf-viewer-overlay, whose scoped
      ".pdf-viewer-overlay > *" pointer-events re-enable only matches children carrying PdfViewer's
      OWN scope attribute. A consumer's children never do.
   2. These three elements are emitted from a RenderTreeBuilder in the modal's @code block, not from
      markup, so the Razor compiler stamps no scope attribute on them at all — a rule in
      DocumentReviseModal.razor.css would compile to ".revise-overlay[b-xxxx]" and match nothing.

   Shipped scoped, which left the overlay at pointer-events:none, position:static and height 0 — the
   examiner could open a document and had no way to drag a redaction box at all. No test caught it:
   bUnit does not evaluate CSS. Keep these here. */
.revise-overlay {
    position: absolute;
    inset: 0;
    cursor: crosshair;
    pointer-events: auto;
}

/* Literal #000 on purpose, not a token: this previews a bar that will be burned into the PDF as actual
   black pixels, so it must not shift with any future theme work. */
.revise-box {
    position: absolute;
    background: #000;
    opacity: .85;
    pointer-events: none;
}

/* The in-progress rectangle reads as a selection, not as an applied redaction — an examiner must not
   mistake a half-finished drag for something that will be burned in. */
.revise-box.drafting {
    background: transparent;
    border: 2px dashed #d00;
    opacity: 1;
}

/* SIDES due-date / resubmit-window badge — used by SidesRequestCard
   and all SidesAdminView list rows + detail modals. */
.sides-due-badge {
    display: inline-block;
    padding: 0.15rem 0.6rem;
    border-radius: 999px;
    font-size: 0.85rem;
    font-weight: 600;
    line-height: 1.3;
    white-space: nowrap;
}
.sides-due-badge--green   { background:#d4edda; color:#155724; }
.sides-due-badge--yellow  { background:#fff3cd; color:#856404; }
.sides-due-badge--red     { background:#f8d7da; color:#721c24; }
.sides-due-badge--orange  { background:#ffe5b4; color:#7a3b00; }
.sides-due-badge--darkred { background:#6c1115; color:#fff; text-decoration:line-through; }

/* Payment weekly-cap breach badge (PaymentsDetailPage row + PaymentsCard count). Its title/text
   always speaks of the WEEK's net and overage, never the row's own amount — see the tokens'
   consumers for why. --cds-support-error/--cds-text-on-color are both defined in :root above. */
.pay-over-cap {
    display: inline-block;
    margin-left: .5rem;
    padding: .0625rem .375rem;
    border-radius: .125rem;
    font-size: .75rem;
    font-weight: 600;
    white-space: nowrap;
    color: var(--cds-text-on-color);
    background-color: var(--cds-support-error);
}

.round-channel-block { margin: 8px 12px 12px; }

/* Communication Activity Log card (CommunicationToken Phase 4) */
.comm-log-card .comm-row { display: flex; align-items: flex-start; gap: .5rem; padding: .35rem 0; border-bottom: 1px solid #f0f3f8; }
.comm-log-card .comm-row:last-child { border-bottom: 0; }
.comm-log-card .comm-row .icon { width: 18px; text-align: center; }
.comm-log-card .comm-row .icon.in { color: #198754; }
.comm-log-card .comm-row .icon.out { color: #0d6efd; }
.comm-log-card .comm-row .body { flex: 1; min-width: 0; }
.comm-log-card .comm-row .title-row { display: flex; align-items: center; gap: .4rem; flex-wrap: wrap; }
.comm-log-card .comm-row .subject { font-size: .9rem; }
.comm-log-card .comm-row .chan { font-size: .7rem; background: #f1f5f9; color: #475569; border-radius: 999px; padding: .05rem .45rem; }
.comm-log-card .comm-row .parse-warn { font-size: .7rem; color: #92400e; }
.comm-log-card .comm-row .meta { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.comm-log-card .comm-row .when { flex-shrink: 0; }

/* ClaimCommunications — shared badge + row styles (CommunicationCard + CommunicationsDetailPage) */
.comm-sum-row { display:flex; align-items:center; gap:.5rem; padding:.35rem 0; border-bottom:1px solid #f0f3f8; }
.comm-sum-row .cat { width:7rem; font-size:.9rem; }
.comm-sum-row .count { margin-left:auto; }
.comm-needs { display:flex; align-items:center; gap:.5rem; padding:.5rem 0; margin-top:.25rem; }
.comm-needs .na-text { font-size:.85rem; }
.badge-pill { padding:.05rem .45rem; border-radius:999px; font-size:.7rem; font-weight:600; white-space:nowrap; border:1px solid transparent; }
.badge-pill.b-overdue   { background:#fecaca; color:#7f1d1d; border-color:#f87171; }
.badge-pill.b-awaiting  { background:#fee2e2; color:#991b1b; border-color:#fca5a5; }
.badge-pill.b-replied   { background:#eef2ff; color:#3730a3; border-color:#c7d2fe; }
.badge-pill.b-sent      { background:#e0f2fe; color:#075985; border-color:#7dd3fc; }
.badge-pill.b-responded { background:#dcfce7; color:#166534; border-color:#4ade80; }
.badge-pill.b-closed    { background:#e5e7eb; color:#374151; border-color:#9ca3af; }
.badge-pill.b-draft     { background:#fef3c7; color:#92400e; border-color:#fcd34d; }
.badge-pill.b-initial   { background:#f3e8ff; color:#6b21a8; border-color:#d8b4fe; }

/* ClaimCommunications — dedicated page + reading pane */
.comm-page { display:flex; gap:0; border:1px solid #e5e7eb; border-radius:8px; overflow:hidden; min-height:60vh; }
.comm-list { width:46%; border-right:1px solid #e5e7eb; overflow-y:auto; }
.comm-pane { width:54%; background:#fafbfc; display:flex; flex-direction:column; }
.comm-group-h { display:flex; align-items:center; gap:.5rem; font-weight:600; font-size:.75rem; text-transform:uppercase; padding:.4rem .6rem; background:#f1f5f9; }
.comm-row { display:flex; align-items:center; gap:.5rem; padding:.4rem .6rem; border-bottom:1px solid #f0f3f8; cursor:pointer; font-size:.85rem; }
.comm-row:hover { background:#f5f7ff; }
.comm-row.sel { background:rgba(59,130,246,.15); }
.comm-row .seq { flex-shrink:0; color:#94a3b8; font-size:.75rem; font-variant-numeric:tabular-nums; }
.comm-row .title { flex:1; min-width:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.comm-row .msg-count { flex-shrink:0; font-size:.7rem; color:#94a3b8; white-space:nowrap; }
.comm-row .row-date { flex-shrink:0; font-size:.7rem; color:#94a3b8; white-space:nowrap; }
.comm-row .row-closed { flex-shrink:0; font-size:.7rem; color:#16a34a; white-space:nowrap; }
.comm-row .followup { color:#3730a3; font-size:.75rem; }
.comm-pane-h { display:flex; align-items:center; padding:.5rem .7rem; border-bottom:1px solid #e5e7eb; font-weight:600; font-size:.85rem; }
.comm-pane-h .btn-close-pane { margin-left:auto; border:none; background:none; cursor:pointer; color:#888; }
.comm-pane-body { padding:.7rem; overflow-y:auto; }
@media (max-width: 768px) { .comm-page { flex-direction:column; } .comm-list, .comm-pane { width:100%; } }

/* Work-item status badge — color + icon + label together (never color alone, Carbon a11y) */
.wi-status { display:inline-flex; align-items:center; gap:.25rem; font-size:.75rem; font-weight:600; white-space:nowrap; }
.wi-status .bi { font-size:.85rem; }
.wi-status--overdue   { color: var(--cds-support-error); }
.wi-status--due-today { color:#8a3800; }  /* AA-contrast amber for text; --cds-support-warning #f1c21b is too light on white */
.wi-status--open      { color: var(--cds-link-primary); }

/* Overdue / due-today banner in the claim summary header (own row beneath the stats) */
.wi-banner { flex-basis:100%; display:flex; gap:1rem; margin-top:.35rem; font-size:.8rem; font-weight:600; }
.wi-banner .wi-seg { display:inline-flex; align-items:center; gap:.3rem; }
.wi-banner .wi-seg--overdue   { color: var(--cds-support-error); }
.wi-banner .wi-seg--due-today { color:#8a3800; }

/* ── Lifecycle panel (claim detail) ──────────────────────────────────────────────────
   Carbon layer-01 surface that visually separates the lifecycle from the white summary
   header above it. A header row carries the "Lifecycle" label; the pipeline renders
   full-width below (ticket 17: the old row's action bar retired to the header/axis rows). */
.lifecycle-panel {
  background: var(--cds-layer-01);
  border: 1px solid var(--cds-border-subtle);
  border-radius: 10px;
  padding: 0.85rem 1.25rem 1rem;
  margin-bottom: 1rem;
}
.lifecycle-panel__head { display: flex; align-items: center; gap: 1rem; flex-wrap: wrap; margin-bottom: 0.85rem; }
.lifecycle-panel__label { font-size: 0.75rem; font-weight: 600; letter-spacing: 0.16px; text-transform: uppercase; color: var(--cds-text-secondary); }
/* G2's legend pointer. Global, not scoped to LifecyclePipeline, because it now renders in TWO
   components: the claim page's panel head (beside the LIFECYCLE label) and — for the appeal queue's
   inline row, which has no head — inside the pipeline itself. One definition, two hosts.

   Colour is deliberately NOT set here. The generic `a:not(.btn):not(.nav-link):not(.dropdown-item)`
   rule above (specificity 0,3,1) outranks any single class, so it owns link colour and hover. The
   scoped copy this replaced carried `color:#64748b` plus a hover colour that never applied for the
   same reason — the link has always rendered as an ordinary link. Only the declarations that
   actually take effect are kept, so this block cannot mislead the next reader. */
.lcp-legend-link {
    font-size: .72rem;
    display: inline-flex;
    gap: .25rem;
    align-items: baseline;
}

/* ── Claim Action Bar styling (SPEC: src/features/ClaimActionBar/SPEC.md, ADR-0040; component
   retired ticket 17 — the .cab-* classes below are reused by ClaimSummaryHeader's button column and
   LifecyclePipeline's per-axis rows, survey-before-add). Carbon-inspired: square corners, 32px compact
   field height, the app's --cds-* interactive palette (IBM Blue = --cds-link-primary). Scoped under
   .claim-action-bar so global .btn / .dropdown are untouched. */
.claim-action-bar { display: flex; align-items: center; gap: 0.375rem; flex-wrap: wrap; }
.claim-action-bar .cab-primary-group { display: inline-flex; align-items: stretch; }

.claim-action-bar .cab-btn {
  font-family: inherit;
  font-size: 0.8125rem;
  font-weight: 500;
  height: 32px;
  padding: 0 0.625rem;
  border: 1px solid transparent;
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  cursor: pointer;
  border-radius: 0;
  white-space: nowrap;
  line-height: 1;
  transition: background-color 0.11s, color 0.11s, border-color 0.11s;
}
.claim-action-bar .cab-btn .bi { font-size: 1rem; }
/* Keyboard focus ring — matches the app's .btn (Carbon inset focus) */
.claim-action-bar .cab-btn:focus-visible,
.claim-action-bar .cab-icon-btn:focus-visible {
  outline: 2px solid var(--cds-focus);
  outline-offset: -4px;
}
.claim-action-bar .cab-btn:disabled,
.claim-action-bar .cab-icon-btn:disabled {
  opacity: 0.5;
  cursor: not-allowed;
}

/* Filled primary — matches the app's .btn-primary (IBM Blue) */
.claim-action-bar .cab-btn--primary { background: var(--cds-link-primary); color: var(--cds-text-on-color); }
.claim-action-bar .cab-btn--primary:hover { background: var(--cds-link-primary-hover); }
.claim-action-bar .cab-btn--primary:active { background: var(--cds-button-primary-active); }

/* Tertiary — blue outline that fills on hover (informational / waiting primaries, menubuttons) */
.claim-action-bar .cab-btn--tertiary {
  background: transparent;
  color: var(--cds-link-primary);
  border-color: var(--cds-link-primary);
}
.claim-action-bar .cab-btn--tertiary:hover { background: var(--cds-link-primary); color: var(--cds-text-on-color); }
.claim-action-bar .cab-btn--tertiary:active { background: var(--cds-button-primary-active); border-color: var(--cds-button-primary-active); color: var(--cds-text-on-color); }

/* ComboButton caret — attached to the primary, narrow; the Bootstrap ::after triangle is the affordance */
.claim-action-bar .cab-caret > .dropdown-toggle { width: 32px; padding: 0; justify-content: center; }
.claim-action-bar .cab-caret > .cab-btn--primary { border-left: 1px solid rgba(255, 255, 255, 0.4); }

/* Ghost icon buttons + overflow trigger */
.claim-action-bar .cab-icon-btn {
  height: 32px;
  width: 32px;
  padding: 0;
  border: 1px solid transparent;
  background: transparent;
  color: var(--cds-text-primary);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  border-radius: 0;
  transition: background-color 0.11s;
}
.claim-action-bar .cab-icon-btn:hover { background: var(--cds-layer-01-hover); }
.claim-action-bar .cab-icon-btn .bi { font-size: 1rem; }
.claim-action-bar .cab-icon-btn.is-flagged { color: var(--cds-support-warning); }
.claim-action-bar .cab-icon-btn.is-questionable { color: var(--cds-support-warning); }

/* Resolved commit (ClaimStatusRedesign SPEC §5.2, ticket 10) — greyed-but-clickable convention: styled
   disabled, but no [disabled] attribute, so a click still reveals the blocking reason(s). */
.claim-action-bar .cab-btn--blocked {
  background: var(--cds-layer-02);
  color: var(--cds-text-secondary);
  border-color: var(--cds-border-subtle);
}
.claim-action-bar .cab-btn--blocked:hover { background: var(--cds-layer-01-hover); }
.claim-action-bar .cab-mark-status { display: inline-flex; align-items: center; gap: 0.375rem; font-size: 0.8125rem; }
.claim-action-bar .cab-mark-blocked-wrap { position: relative; }
.claim-action-bar .cab-mark-blocked-reasons {
  position: absolute;
  right: 0;
  top: 100%;
  z-index: 20;
  margin-top: 0.25rem;
  padding: 0.5rem 0.75rem;
  background: var(--cds-layer-01);
  border: 1px solid var(--cds-layer-02);
  box-shadow: var(--cds-shadow-raised);
  font-size: 0.8125rem;
  max-width: 320px;
}
.claim-action-bar .cab-mark-blocked-reasons ul { margin: 0; padding-left: 1.1rem; }

/* Dropdown surfaces — square Carbon panels (scoped; global dropdowns unaffected) */
.claim-action-bar .dropdown-menu {
  border-radius: 0;
  border: 1px solid var(--cds-layer-02);
  box-shadow: var(--cds-shadow-raised);
  font-size: 0.8125rem;
}
.claim-action-bar .dropdown-header {
  font-size: 0.6875rem;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--cds-text-placeholder);
}

/* ===== Communications timeline (CommunicationsTimeline SPEC §2) ===== */
.comm-tl { position: relative; padding-left: 26px; }
.comm-tl::before { content: ""; position: absolute; left: 9px; top: 6px; bottom: 6px; width: 2px; background: #d1d5db; }
.comm-tl .tl-item { position: relative; margin-bottom: 16px; }
.comm-tl .tl-dot { position: absolute; left: -23px; top: 4px; width: 12px; height: 12px; border-radius: 50%; border: 2px solid #fff; }
.comm-tl .dot-out { background: #1d4ed8; }
.comm-tl .dot-in { background: #15803d; }
.comm-tl .tl-head { display: flex; gap: 10px; align-items: baseline; margin-bottom: 4px; flex-wrap: wrap; }
.comm-tl .tl-when { font-weight: 700; font-size: .8rem; }
.comm-tl .tl-dir { font-size: .7rem; font-weight: 700; text-transform: uppercase; letter-spacing: .04em; }
.comm-tl .dir-in { color: #15803d; }
.comm-tl .dir-out { color: #1d4ed8; }
.comm-tl .parse-warn { font-size: .72rem; color: #b45309; }
.comm-tl .corrected-mark { font-size: .8rem; color: #6b7280; cursor: help; }
.comm-tl .tl-card { background: #f9fafb; border: 1px solid #e5e7eb; border-radius: 6px; padding: 10px 12px; font-size: .85rem; }
.comm-tl .who { font-weight: 700; }
.comm-tl .who .addr { color: #6b7280; font-size: .78rem; font-weight: 400; margin-left: .4rem; }
.comm-tl .who .failed { color: #b91c1c; font-weight: 400; font-size: .78rem; }
.comm-tl .subject { font-size: .78rem; color: #6b7280; margin: 2px 0 6px; }
/* ADR-0077: outbound bodies are now stored in full, so a long email must scroll inside its own
   panel rather than growing the timeline. */
.comm-tl .body { line-height: 1.5; overflow-wrap: anywhere; max-height: 24rem; overflow-y: auto; }
.comm-tl .body img { max-width: 100%; height: auto; }
.comm-tl .body :first-child { margin-top: 0; }
.comm-tl .body :last-child { margin-bottom: 0; }
.comm-tl .fwd-note { font-size: .72rem; color: #9ca3af; font-style: italic; margin-top: 6px; }
.comm-tl .tl-actions { display: flex; gap: 12px; margin-top: 8px; flex-wrap: wrap; }
.comm-tl .tl-act { background: none; border: none; padding: 0; font: inherit; font-size: .78rem; color: #2563eb; cursor: pointer; text-decoration: underline; }
.comm-tl .tl-act.has-comments { color: #b45309; font-weight: 600; }
.modal-backdrop-pcm { position: fixed; inset: 0; background: rgba(15,23,42,.45); display: flex; align-items: center; justify-content: center; z-index: 1050; }
.modal-card-pcm { background: #fff; border-radius: 8px; width: min(480px, 92vw); max-height: 80vh; overflow-y: auto; padding: 16px; box-shadow: 0 10px 30px rgba(0,0,0,.25); }
.modal-head-pcm { display: flex; justify-content: space-between; align-items: center; }
.modal-head-pcm h5 { margin: 0; }
.modal-ctx-pcm { font-size: .72rem; color: #6b7280; margin: 2px 0 10px; }
/* DocumentModal: the iframe fills the modal body so the browser's own PDF/image viewer is usable. */
.document-modal-frame { width: 100%; height: 75vh; border: 0; display: block; }
.cmt-row { border-top: 1px solid #f3f4f6; padding: 8px 0; font-size: .85rem; }
.cmt-meta { font-size: .72rem; color: #6b7280; }
.cmt-save { margin-top: 8px; }
.cmt-edit-actions { display: flex; gap: 8px; margin-top: 8px; }
.fix-label { font-size: .72rem; color: #6b7280; margin-top: 8px; display: block; }
.fix-actions { display: flex; gap: 8px; margin-top: 12px; }

/* Lifecycle determination/appeals decision-phase surfaces (ADR-0046).
   Global (not scoped) so the PhaseWorkItemCard / OutcomesStrip subcomponents pick them up. */
.lpp-posture { font-size: .68rem; font-weight: 600; padding: 2px 8px; border-radius: 999px; margin-left: 8px; }
.lpp-posture-active { background: #fef3c7; color: #92400e; }
.lpp-posture-passivemonitoring { background: #fef9c3; color: #854d0e; }
.lpp-posture-history { background: #ccfbf1; color: #115e59; }
.lpp-workitem { margin: 12px 0; padding: 12px; border: 1px solid #fde68a; background: #fffbeb; border-radius: 8px; }
.lpp-workitem-title { font-size: .72rem; font-weight: 600; color: #92400e; text-transform: uppercase; letter-spacing: .04em; margin-bottom: 8px; }
/* One flex row of .lpp-action-btns — the boxed panels' action row, and the condensed phase bar and
   its groups, are the same thing and share the rule. */
.lpp-workitem-actions, .lpp-action-bar, .lpp-action-group { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; }
/* One condensed action bar for the phase panel: the "Actions" group, then "Information Gathering",
   then the closure commit pushed to the far right — all on one line, no card chrome, no headings (the
   groups keep their names on aria-label). The hairline only draws when the bar holds something, so a
   phase with nothing to offer leaves no stray rule behind. Layout is shared with
   .lpp-workitem-actions above. */
.lpp-action-bar:has(> *) { margin-top: 10px; padding-top: 10px; border-top: 1px solid #e5e9f0; }
/* Neutral outline in the bar (the amber .lpp-action-btn reads as a warning without its amber card
   around it); scoped to the bar so the boxed panels that share the class keep their look. The two
   :not()s keep this rule off the buttons that carry their own colour — an already-recorded action
   (muted "handled") and the headline (filled blue) — so the three are mutually exclusive rather than
   fighting on specificity. */
.lpp-action-bar .lpp-action-btn:not(.lpp-action-btn-done):not(.lpp-action-btn-lead),
.lpp-hearing-group-actions .lpp-action-btn:not(.lpp-action-btn-done):not(.lpp-action-btn-lead) { border-color: #d1d5db; color: #1f2937; }
.lpp-action-bar .lpp-action-btn:not(.lpp-action-btn-done):not(.lpp-action-btn-lead):hover:not([disabled]),
.lpp-hearing-group-actions .lpp-action-btn:not(.lpp-action-btn-done):not(.lpp-action-btn-lead):hover:not([disabled]) { background: #f3f4f6; }
/* The bar's headline action (PhaseWorkItemCard.Headline — the phase's own first undone action, never
   a supporting one). Same filled IBM Blue as .btn-primary and .claim-action-bar .cab-btn--primary, so
   an action shown as the header bar's primary and as the panel's headline is one colour, not two. When the
   headline targets a hearing it renders inside that hearing's group (LifecyclePhasePanel.HeadlineIn), and
   keeps the look there. */
.lpp-action-bar .lpp-action-btn-lead,
.lpp-hearing-group-actions .lpp-action-btn-lead {
    background: var(--cds-link-primary); border-color: var(--cds-link-primary);
    color: var(--cds-text-on-color); font-weight: 600;
}
.lpp-action-bar .lpp-action-btn-lead:hover:not([disabled]),
.lpp-hearing-group-actions .lpp-action-btn-lead:hover:not([disabled]) {
    background: var(--cds-link-primary-hover); border-color: var(--cds-link-primary-hover);
}
/* Group hint (was the "Information Gathering" card's title icon) — trails its buttons. */
.lpp-action-group-hint { color: #6b7280; cursor: help; font-size: .85rem; }
/* Closure commit (AppealClosureCommitControl): ends the appeal rather than advancing it, so it sits at
   the far right of the bar — separated by space, not a divider — and reads as a quiet muted link rather
   than a button competing with the headline. Both DOM shapes the control can render (the commit button,
   the committed-by note) get pushed; the confirm modal it may also render is fixed-position, so the
   auto margin never lands on that. */
.lpp-action-bar > [data-action='commit-closure'],
.lpp-action-bar > [data-testid='closure-committed'] { margin-left: auto; }
.lpp-closure-commit {
    border: none; background: none; padding: 0; font: inherit; font-size: .78rem;
    color: #6b7280; cursor: pointer; text-decoration: none;
}
.lpp-closure-commit:hover:not([disabled]) { color: #374151; text-decoration: underline; }
.lpp-closure-commit[disabled] { opacity: .5; cursor: not-allowed; }
.lpp-action { display: inline-flex; flex-direction: column; gap: 2px; }
.lpp-action-btn { font-size: .8rem; padding: 6px 12px; border-radius: 6px; border: 1px solid #d97706; background: #fff; color: #92400e; cursor: pointer; }
.lpp-action-btn:hover:not([disabled]) { background: #fef3c7; }
.lpp-action-btn[disabled] { opacity: .5; cursor: not-allowed; border-color: #d1d5db; color: #6b7280; }
/* De-emphasised but still clickable: disabled look, live hover. Two DIFFERENT action states share it —
   Done (already handled: recommendation recorded, extension decided) and Advisory (allowed but off the
   expected path, e.g. scheduling prep for a hearing the employer declined). They are told apart by their
   icon and tooltip in PhaseWorkItemCard, not by colour, so don't rename this to either one's meaning. */
.lpp-action-btn-done { border-color: #d1d5db; color: #6b7280; background: #f9fafb; }
.lpp-action-btn-done:hover:not([disabled]) { background: #f3f4f6; }
/* Icon-only bar action — today only "Delete appeal" (PhaseWorkItemCard). Destructive and off-path, so
   it reads as a quiet red trash glyph instead of claiming a labelled slot beside the real next steps.
   Only the horizontal padding is squeezed: font-size and vertical padding stay inherited from
   .lpp-action-btn so the glyph button matches its labelled siblings' height exactly.
   The colour rule has to out-specify the bar's neutral-outline rule above, which lands on this button
   too (an icon action is neither done nor lead) — hence the trailing :not()s bringing it level and
   later in source order. :not([disabled]) then leaves the shared disabled grey in charge when the
   delete is refused, so a locked delete still looks locked rather than live-and-red.
   align-self keeps the glyph button at its natural width: .lpp-action is a stretch-aligned column, so
   anything wider than the glyph in that column would otherwise stretch the button into a wide empty box
   around a tiny icon. A labelled action fills that width; an icon one does not. */
.lpp-action-btn-icon { padding: 6px 9px; align-self: start; }
.lpp-action-bar .lpp-action-btn-icon:not(.lpp-action-btn-done):not(.lpp-action-btn-lead):not([disabled]) { border-color: #fca5a5; color: #b91c1c; }
.lpp-action-bar .lpp-action-btn-icon:not(.lpp-action-btn-done):not(.lpp-action-btn-lead):hover:not([disabled]) { background: #fef2f2; }
.lpp-action-lock { font-size: .68rem; color: #6b7280; }
/* Locked icon action (today only a refused "Delete appeal"). The refusal is a full sentence, which
   under a 33px glyph button stretched the action bar and dwarfed the button it explains — so it moves to the
   hover tip and a lock badge takes the glyph's top-right corner in its place. Labelled actions keep the
   visible .lpp-action-lock sentence.

   Three things this rule has to get right:
   - The badge anchors to the WRAPPER, not the button, and PhaseWorkItemCard renders it as the button's
     sibling for the same reason: a disabled button paints at 50% opacity, which applies to its whole
     subtree, and inside it the badge came out washed to near-invisible. The wrapper is shrink-to-fit
     around the button, so its corner is the button's corner.
   - Negative offsets park it ON the corner rather than inside it, and the white ring keeps the small
     glyph legible where it crosses the button's border.
   - pointer-events keeps the badge from eating the hover: it sits over the button, and the tip belongs
     to the wrapper underneath. */
.lpp-action-locked-icon { position: relative; cursor: not-allowed; }
.lpp-action-lock-badge {
    position: absolute; top: -5px; right: -5px; padding: 2px;
    font-size: .58rem; line-height: 1; color: #4b5563;
    background: #fff; border-radius: 999px; box-shadow: 0 0 0 1px #fff;
    pointer-events: none;
}
/* The tip has to hang off the wrapper: a disabled button dispatches no hover events, so a title on one
   never opens (src/Client/PCMSystem.Blazor/CLAUDE.md § Tooltips). pointer-events lets the pointer fall
   through to the wrapper, which then also carries the not-allowed cursor the button can no longer show
   for itself. */
.lpp-action-locked-icon > .lpp-action-btn { pointer-events: none; }
.lpp-fact-info-btn { border: none; background: none; padding: 0 0 0 6px; color: #0284c7; cursor: pointer; font-size: .85rem; vertical-align: baseline; }
.lpp-fact-info { font-size: .72rem; color: #475569; background: #f0f9ff; border: 1px solid #bae6fd; border-radius: 6px; padding: 4px 8px; margin-top: 3px; }
/* Source-document affordance: a button (the authenticated download can't be a plain anchor) that reads
   as a link. Used by fact rows and the prep-session document list. */
.lpp-doc-link { border: none; background: none; padding: 0; color: #0284c7; cursor: pointer; font: inherit; text-align: left; display: inline-flex; gap: 5px; align-items: baseline; }
.lpp-doc-link:hover { color: #0369a1; text-decoration: underline; }

/* "Where this can go" — a hover hint, not a card: the reachable outcomes are speculative, so they sit
   in the title tooltip and only this one muted line takes space in the panel. */
.lpp-outcomes-hint { display: inline-flex; align-items: center; gap: 5px; margin: 0 0 0 auto; font-size: .72rem; color: #0f766e; cursor: help; }
/* One row: the appeal-level pills lead, the outcomes hint is pushed hard right (margin-left:auto
   above) so it reads as an aside rather than a section of its own. Stages with no levels show the
   hint alone — this row replaced the "Commit closure" row it used to share. */
.lpp-levels-row { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; margin-bottom: 10px; }
/* AppealsLifecycleHearingGrouping (SPEC §1): forum bands over the level pills, and one collapsible group per hearing
   under the selected docket. Chrome matches the fact cards (hairline #e5e9f0, 8px radius); the live hearing takes the
   amber the current pill already wears, and an unmatched notice the same amber dashed — a hearing not yet placed.
   The stepper and .lpp-badge rules these sit beside are scoped (LifecyclePhasePanel.razor.css) and load after this
   file, so every override below out-specifies its scoped rule rather than relying on source order. */
.lpp-forum-band { display: inline-flex; align-items: center; gap: .5rem; flex-wrap: wrap; padding-left: 10px; border-left: 1px solid #e5e9f0; }
.lpp-forum-band:first-child { padding-left: 0; border-left: none; }
.lpp-forum-band-label { font-size: .68rem; font-weight: 600; color: #6c7a8a; text-transform: uppercase; letter-spacing: .04em; }
.lpp-hearing-groups { display: flex; flex-direction: column; gap: 8px; margin: 0 0 10px; }
.lpp-hearing-groups-title { font-size: .72rem; font-weight: 600; color: #6c7a8a; text-transform: uppercase; letter-spacing: .04em; }
.lpp-hearing-group { border: 1px solid #e5e9f0; border-radius: 8px; background: #fff; padding: 6px 10px; }
.lpp-hearing-group-active { border-color: #d97706; }
.lpp-hearing-group-unmatched { border-color: #d97706; border-style: dashed; }
.lpp-hearing-group-head { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.lpp-hearing-group-toggle { border: none; background: none; padding: 0; font: inherit; font-size: .85rem; font-weight: 600; color: #1f2937; cursor: pointer; display: inline-flex; gap: 6px; align-items: center; }
.lpp-hearing-group-toggle:hover { color: #0f62fe; }
.lpp-hearing-group-meta { font-size: .78rem; color: #6c7a8a; }
/* The scoped .lpp-badge pushes itself right with margin-left:auto; a second badge must follow the first, not split the row. */
.lpp-hearing-group-head .lpp-badge + .lpp-badge { margin-left: 0; }
/* The docket's Email/+Add menu is last in the header row, after the badges. margin-left:auto of its own so
   it still sits hard right on a group that shows no badge at all; once a badge precedes it the badge has
   already claimed the gap, so the menu just follows. flex-shrink:0 keeps the menu from being what a long
   header squeezes. */
.lpp-hearing-group-head > .lpp-hearing-group-menu { margin-left: auto; flex-shrink: 0; }
.lpp-hearing-group-head > .lpp-badge ~ .lpp-hearing-group-menu { margin-left: 0; }
.lpp-hearing-group-body { margin-top: 8px; }
/* Collapsed: the body stays in the DOM for aria-controls but takes no space. */
.lpp-hearing-group-body[hidden] { display: none; }
.lpp-hearing-group-body .lpp-facts { margin: 8px 0 0; }
.lpp-hearing-group-actions { margin-top: 6px; }
/* SPEC §5.1 terminal marks: a step the hearing never reached because it was replaced (⊘ superseded) or decided
   (⊘ decided). Muted like a skipped step, but a dashed ring and no strike-through: it was not leapfrogged. */
.lpp-step.lpp-step-superseded .lpp-step-dot,
.lpp-step.lpp-step-decided .lpp-step-dot { background: #eef1f5; border-style: dashed; color: #9aa7b8; }
.lpp-step.lpp-step-superseded .lpp-step-label,
.lpp-step.lpp-step-decided .lpp-step-label { color: #9aa7b8; font-weight: 500; }
.lpp-step-terminal { font-style: italic; color: #6c7a8a; }
.lpp-outcomes-hint:hover { color: #115e59; }
.lpp-banner { display: flex; gap: 10px; align-items: flex-start; margin: 10px 0; padding: 10px 12px; background: #eff6ff; border: 1px solid #bfdbfe; border-radius: 8px; color: #1e40af; }
.lpp-banner-body { display: flex; flex-direction: column; gap: 2px; }
.lpp-banner-body span { font-size: .78rem; color: #1e3a8a; }
.lpp-toolkit { margin: 12px 0; padding: 12px; border: 1px dashed #93c5fd; background: #f8fafc; border-radius: 8px; }
.lpp-toolkit-title { font-size: .72rem; font-weight: 600; color: #1e40af; text-transform: uppercase; letter-spacing: .04em; margin-bottom: 8px; }
.lpp-toolkit-actions { display: flex; flex-wrap: wrap; gap: 8px; }
.lpp-packet-list { list-style: none; margin: 0 0 10px; padding: 0; display: flex; flex-direction: column; gap: 6px; font-size: .82rem; }
.lpp-suggestion { display: flex; align-items: center; justify-content: space-between; gap: 10px; margin: 10px 0; padding: 10px 12px; background: #f5f3ff; border: 1px solid #ddd6fe; border-radius: 8px; }
.lpp-suggestion-body { display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap; }
.lpp-suggestion-tag { font-size: .62rem; font-weight: 700; text-transform: uppercase; letter-spacing: .05em; color: #6d28d9; background: #ede9fe; padding: 2px 6px; border-radius: 4px; }
.lpp-suggestion-label { font-weight: 600; font-size: .85rem; color: #5b21b6; }
.lpp-suggestion-hint { font-size: .72rem; color: #6b7280; }
/* Badges for lifecycle child components — the scoped copies in LifecyclePhasePanel.razor.css don't reach
   children. Same palette; no margin-left:auto (that's the parent's fact-head flex concern). */
.lpp-badge { display: inline-block; border-radius: 999px; font-size: .7rem; font-weight: 600; padding: .1rem .55rem; }
.lpp-badge-neutral { background: #e9ecef; color: #495057; }
.lpp-badge-good    { background: #d6efe7; color: #0c6e54; }
.lpp-badge-warn    { background: #fdf3e3; color: #92510a; }
.lpp-badge-bad     { background: #fde5e8; color: #b02a37; }
/* Per-mailing-date determination card (AppealFilingPanel) — same chrome as .lpp-fact-card. */
.lpp-appeal-filing { margin: 12px 0; padding: .75rem .9rem; background: #f7f8fa; border: 1px solid #e5e9f0; border-radius: 8px; }
.lpp-appeal-filing .lpp-workitem:last-child { margin-bottom: 0; }
.lpp-det-entry { padding: 6px 0; }
.lpp-det-entry + .lpp-det-entry { border-top: 1px solid #e5e9f0; }
/* The entry's identifying line and its own Email/+Add menus on one row, menus hard right.
   align-items: flex-start keeps the menus level with the first line when the title wraps;
   the .small block takes the slack so the menus stay pinned to the right edge. */
.lpp-det-entry-head { display: flex; align-items: flex-start; justify-content: space-between; gap: .75rem; flex-wrap: wrap; }
.lpp-det-entry-head > .small { flex: 1 1 auto; min-width: 0; }
.lpp-det-entry-head > .claim-action-bar { flex: 0 0 auto; margin-left: auto; }
/* Stage actions and the exclusion toggle read as one set of per-determination actions. */
.lpp-det-actions-row { display: flex; align-items: center; gap: .375rem; flex-wrap: wrap; margin-top: .25rem; }
.lpp-det-actions-row > .lpp-det-own-actions { display: flex; align-items: center; gap: .375rem; flex-wrap: wrap; }
.lpp-appeal-explanation { font-size: .78rem; color: #475569; background: #fff; border: 1px solid #e5e9f0; border-radius: 6px; padding: 6px 10px; white-space: pre-wrap; }

/* ─── Appeal Queue urgency chips (AppealQueue.razor) ────────
   One chip per row; class switches on UrgencyStatus.
   Behind → red  /  Soon → light-red  /  Ready → green
   OnTrack → blue  /  Awaiting (and fallback) → muted gray. */
.urgency-chip {
  display: inline-flex;
  align-items: center;
  padding: 2px 8px;
  border-radius: 24px;
  font-size: 0.75rem;
  font-weight: 500;
  letter-spacing: 0.32px;
  line-height: 1.33;
  white-space: nowrap;
  /* The pill has to hold its shape on any ground, not just white: the open appeal
     row is filled with --cds-layer-selected (#edf5ff), which .chip-ontrack's
     #e0f2fe would otherwise dissolve into. Translucent so one rule darkens every
     tone by the same amount instead of needing a matching border per chip. */
  border: 1px solid rgba(15, 23, 42, 0.12);
}
.chip-behind  { background: #fecaca; color: #7f1d1d; }
.chip-soon    { background: #fee2e2; color: #991b1b; }
.chip-ready   { background: #dcfce7; color: #166534; }
.chip-ontrack { background: #e0f2fe; color: #075985; }
.chip-muted   { background: var(--cds-layer-01); color: var(--cds-text-secondary); }

/* =====================================================================
   Dashboard shell — stat cards, phase tiles, activity tables.
   Global (not scoped to Index.razor) because /dashboard and /myday share
   this markup and must look identical.
   ===================================================================== */
.dashboard {
  padding: 1.5rem 0;
}

/* ─── Header ──────────────────────────────────────────────── */
.dashboard-header {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  margin-bottom: 1.75rem;
  gap: 1rem;
  flex-wrap: wrap;
}

.dashboard-header h1 {
  font-size: 1.75rem;
  font-weight: 700;
  margin: 0;
  color: #111827;
  letter-spacing: -0.01em;
}

/* ─── Stat Cards ──────────────────────────────────────────── */
.stat-card {
  background: #ffffff;
  border-radius: 12px;
  padding: 1.25rem 1.5rem;
  box-shadow:
    0 1px 3px rgba(0, 0, 0, 0.07),
    0 1px 2px rgba(0, 0, 0, 0.04);
  border: 1px solid #f0f0f0;
  display: flex;
  align-items: center;
  gap: 1rem;
  transition:
    box-shadow 0.15s ease,
    transform 0.15s ease;
  height: 100%;
}

.stat-card:hover {
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.09);
  transform: translateY(-1px);
}

.stat-icon {
  width: 48px;
  height: 48px;
  border-radius: 10px;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
}

.stat-icon.blue {
  background: #eff6ff;
}
.stat-icon.amber {
  background: #fffbeb;
}
.stat-icon.red {
  background: #fef2f2;
}
.stat-icon.indigo {
  background: #eef2ff;
}

/* Skeleton placeholder sizing */
.stat-card .stat-icon.placeholder {
  width: 48px;
  height: 48px;
}

.stat-value {
  font-size: 2rem;
  font-weight: 700;
  line-height: 1;
  color: #111827;
  margin-top: 0.2rem;
}

.stat-label {
  font-size: 0.75rem;
  font-weight: 500;
  color: #6b7280;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  margin-bottom: 0.1rem;
}

/* Phase breakdown cards: compact variant of the stat card (no icon, colored accent). */
.phase-card {
  padding: 1rem 1.1rem;
}

.phase-card .stat-value {
  font-size: 1.6rem;
}

/* ─── Activity Card ───────────────────────────────────────── */
.dashboard-card {
  border-radius: 12px;
  border: 1px solid #f0f0f0;
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.07);
  overflow: hidden;
}

.dashboard-card .card-header {
  background: #ffffff;
  font-weight: 600;
  font-size: 0.9rem;
  border-bottom: 1px solid #f0f0f0;
  padding: 0.875rem 1.25rem;
  color: #111827;
}

/* ─── Activity Table ──────────────────────────────────────── */
.activity-table th {
  font-size: 0.72rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: #9ca3af;
  border-top: none;
  padding: 0.65rem 1.25rem;
  white-space: nowrap;
}

.activity-table td {
  padding: 0.7rem 1.25rem;
  vertical-align: middle;
  border-color: #f9fafb;
}

.activity-table tbody tr:hover {
  background: #fafafa;
}

.activity-badge {
  display: inline-block;
  font-size: 0.72rem;
  font-weight: 600;
  padding: 0.2em 0.55em;
  border-radius: 4px;
  background: #f3f4f6;
  color: #374151;
  white-space: nowrap;
}

/* Hearing-package modal fact table — narrow muted label column so the values line up and read as
   the record rather than as form labels. */
.hp-facts .hp-fact-label {
  width: 11rem;
  font-weight: 500;
  color: #6b7280;
  white-space: nowrap;
}

/* === Appeal queue: the open row and its panel read as one card ============
   AppealQueue.razor wraps each row and its inline lifecycle panel in one
   .appeal-row-group. Boxing that wrapper ties the panel to the row it came
   from, and pinning the row keeps the claim's identity on screen while the
   panel — which runs several screens tall — is scrolled.

   Every rule below targets the wrapper or the row. Nothing touches
   .appeal-row-panel's background or anything inside it, because the phase
   panel draws its own chrome on white: .lpp-fact-card is #f7f8fa and
   .lpp-banner is #eff6ff (LifecyclePhasePanel.razor.css). A fill on the panel
   would invert that card-to-ground relationship and swallow the banner. */
.appeal-row-group.is-open {
  border: 2px solid var(--cds-link-primary);
  margin: 14px 0;
  background: var(--cds-background);
}

.appeal-row-group.is-open > .appeal-row {
  /* The app's selected fill — the same token .notif-unread uses (line ~312) — so the
     row being worked reads as active rather than merely grey.

     This reverses an earlier decision to keep the fill neutral because #edf5ff is two
     hex points from .lpp-banner's #eff6ff (defined in THIS file, line ~1585, despite
     what the header above says). Two things now separate them: only this row wears the
     2px primary border and stays pinned under the topbar, and .urgency-chip carries its
     own border so the pale-blue chips keep their edge against this fill. If a third
     pale blue ever lands in the panel, revisit here rather than adding a fourth. */
  background: var(--cds-layer-selected);
  /* Only the inline padding — Bootstrap's py-2 on this element is !important,
     so a shorthand `padding` would silently lose its vertical half. */
  padding-inline: 14px;
  /* Rides at the top of the viewport while the panel scrolls beneath it.
     52px is the fixed .app-topbar's height (MainLayout.razor.css); z-index
     stays below the topbar's 90 so the row slides under it, and far below
     Bootstrap's 1050 modal layer so panel modals still cover it. */
  position: sticky;
  top: 52px;
  z-index: 1;
}

.appeal-row-group.is-open > .appeal-row-panel {
  padding-inline: 14px;
}

/* Claim number + employer, shown on the open (pinned) row only. */
.appeal-row-ident {
  font-size: 0.8125rem;
  color: var(--cds-text-secondary);
}

/* Fact-finding round attachments: one file per row, its redacted versions nested beneath it.
   Global rather than scoped because this page has no .razor.css and the project keeps shared
   Blazor CSS here. Deliberately NOT a flex row — the badges and icon buttons sit in normal
   inline flow with Bootstrap margins, which avoids the trap where Razor's source indentation
   becomes a whitespace text node and turns into an extra flex item. */
.ff-attach-list {
  list-style: none;
  margin: 0.25rem 0 0;
  padding-left: 0;
}

.ff-attach-list li {
  padding: 0.1rem 0;
}

/* The nesting cue. The left border reads as "belongs to the row above" at a glance, which the
   indent alone does not once a filename wraps. */
.ff-attach-revisions {
  margin-top: 0.1rem;
  padding-left: 0.75rem;
  border-left: 2px solid var(--cds-border-subtle);
  margin-left: 0.35rem;
}

/* G12: the claims-grid sort and filter triggers were unfocusable <span>s. They are real
   <button>s now; strip the UA chrome so the header looks unchanged. */
/* G98: a column the server cannot sort renders its label as plain text — same weight and
   spacing as the sortable headers, minus the affordance. */
.claims-th-static { font: inherit; color: inherit; }

.claims-th-sort,
.claims-th-filter {
  border: none;
  background: none;
  padding: 0;
  font: inherit;
  color: inherit;
  cursor: pointer;
  text-align: left;
}

.claims-th-filter {
  margin-left: 4px;
  font-size: 12px;
  line-height: 1;
}

.claims-th-sort:focus-visible,
.claims-th-filter:focus-visible,
.alpha-letter:focus-visible {
  outline: 2px solid var(--cds-focus, #0f62fe);
  outline-offset: 1px;
}

/* G12: SortableHeader's trigger is a <button> now (was the <th>'s own onclick). Strip the UA
   chrome so every grid that uses it looks unchanged, and keep a visible focus ring. */
.sortable-trigger {
  border: none;
  background: none;
  padding: 0;
  font: inherit;
  color: inherit;
  cursor: pointer;
  text-align: inherit;
  white-space: inherit;
}

.sortable-trigger:focus-visible {
  outline: 2px solid var(--cds-focus);
  outline-offset: 1px;
}

/* ClaimPicker result rows. Without a reset these are bare <button>s wearing UA chrome — grey
   buttonface, content-width, centre-aligned — wrapping a name over a d-block sub-line, in the one
   control whose whole job is telling similar claims apart. Token is --cds-layer-01-hover, NOT
   --cds-layer-hover-01: an undefined custom property voids the entire declaration silently. */
.claim-picker-result {
  display: block;
  width: 100%;
  text-align: left;
  border: none;
  background: none;
  padding: .35rem .6rem;
  font: inherit;
  color: inherit;
  cursor: pointer;
}
.claim-picker-result:hover:not(:disabled) {
  background: var(--cds-layer-01-hover);
}
.claim-picker-result:disabled {
  cursor: default;
  opacity: .6;
}
.claim-picker-result:focus-visible {
  outline: 2px solid var(--cds-focus);
  outline-offset: -2px;
}

/* === Help & glossary (G1) === */
.help-page { max-width: 62rem; }
.help-page h1 { font-size: 1.5rem; font-weight: 600; margin-bottom: .5rem; }
.help-search { max-width: 26rem; margin: 1rem 0 .5rem; }

.help-toc {
  display: flex;
  flex-wrap: wrap;
  gap: .25rem .75rem;
  padding: .6rem .8rem;
  margin-bottom: 1rem;
  background: var(--cds-layer-01);
  border-left: 3px solid var(--cds-focus);
}
.help-toc a { font-size: .8125rem; color: var(--cds-text-primary); }

.help-section { margin-bottom: 2rem; }
.help-section h2 {
  font-size: 1.05rem;
  font-weight: 600;
  padding-bottom: .3rem;
  border-bottom: 1px solid var(--cds-layer-02);
}
.help-terms { display: grid; grid-template-columns: minmax(11rem, 18rem) 1fr; gap: .35rem 1.25rem; margin: 0; }
.help-terms dt { font-weight: 600; font-size: .875rem; }
.help-terms dd { margin: 0; font-size: .875rem; color: var(--cds-text-secondary); }
@media (max-width: 640px) {
  .help-terms { grid-template-columns: 1fr; }
  .help-terms dd { margin-bottom: .5rem; }
}

/* The inline ⓘ marker. Focusable on purpose: Bootstrap's trigger is "hover focus", so without
   tabindex the definition would be mouse-only (see HelpTip.razor). */
.help-tip {
  display: inline-flex;
  margin-left: .25rem;
  color: var(--cds-text-secondary);
  cursor: help;
  font-size: .8em;
  vertical-align: baseline;
}
.help-tip:hover, .help-tip:focus-visible { color: var(--cds-focus); }
.help-tip:focus-visible { outline: 2px solid var(--cds-focus); outline-offset: 2px; }

/* G103: the unbound-mail preview panel. Bind/dismiss used to be decided from a subject line. */
.mailbox-preview {
  margin-top: 1rem;
  padding: .85rem 1rem;
  background: var(--cds-layer-01);
  border-left: 3px solid var(--cds-focus);
}
.mailbox-preview-body {
  max-height: 22rem;
  overflow: auto;
  white-space: pre-wrap;
  word-break: break-word;
  font-size: .8125rem;
  background: var(--cds-background);
  border: 1px solid var(--cds-layer-02);
  padding: .6rem .75rem;
  margin: 0;
}

/* G7 unsaved-work guard. The wrapper exists only to catch input/change events bubbling out of the
   form fields inside it (see Shared/UnsavedWorkGuard.razor); display:contents keeps it from adding
   a box, so wrapping a form region cannot disturb the surrounding layout. */
.unsaved-work-guard {
  display: contents;
}
