/* HR Strategix — shared design tokens + component styles for authenticated pages. */

:root {
  --bg: #ffffff;
  --bg-soft: #fafafa;
  --bg-elev: #ffffff;
  --ink: #0a0a0a;
  --ink-2: #404040;
  --muted: #737373;
  --border: #e7e7e9;
  --border-strong: #d4d4d8;
  --accent: #4f46e5;
  --accent-ink: #ffffff;
  --accent-soft: color-mix(in oklab, var(--accent) 12%, var(--bg));
  --success: #10b981;
  --danger: #ef4444;
  --radius: 12px;
  --radius-sm: 8px;
  --radius-lg: 16px;
  --shadow-sm: 0 1px 2px rgba(10,10,10,.04), 0 1px 3px rgba(10,10,10,.05);
  --shadow: 0 4px 12px -2px rgba(0,0,0,.06), 0 2px 4px rgba(0,0,0,.04);
  --shadow-lg: 0 24px 48px -12px rgba(0,0,0,.14), 0 8px 16px -4px rgba(0,0,0,.05);
  --font-sans: -apple-system, BlinkMacSystemFont, "Segoe UI", ui-sans-serif, system-ui, "Helvetica Neue", Arial, sans-serif;
  --font-mono: ui-monospace, "SF Mono", Menlo, Consolas, monospace;
}
@media (prefers-color-scheme: dark) {
  :root:not([data-theme]) {
    --bg: #0a0a0a; --bg-soft: #111113; --bg-elev: #16161a;
    --ink: #fafafa; --ink-2: #d4d4d8; --muted: #a1a1aa;
    --border: #26262b; --border-strong: #3f3f46; --accent-ink: #0a0a0a;
    --shadow-sm: 0 1px 2px rgba(0,0,0,.4), 0 1px 3px rgba(0,0,0,.35);
    --shadow: 0 4px 12px -2px rgba(0,0,0,.4), 0 2px 4px rgba(0,0,0,.3);
    --shadow-lg: 0 24px 48px -12px rgba(0,0,0,.6), 0 8px 16px -4px rgba(0,0,0,.4);
  }
}
:root[data-theme="light"] { --bg:#ffffff; --bg-soft:#fafafa; --bg-elev:#ffffff; --ink:#0a0a0a; --ink-2:#404040; --muted:#737373; --border:#e7e7e9; --border-strong:#d4d4d8; --accent-ink:#ffffff; }
:root[data-theme="warm"]  { --bg:#faf7f2; --bg-soft:#f4ede0; --bg-elev:#fdfaf5; --ink:#1b1a17; --ink-2:#4a4740; --muted:#7d786d; --border:#ece3d1; --border-strong:#d7c9a9; --accent-ink:#ffffff; }
:root[data-theme="cool"]  { --bg:#f5f7fb; --bg-soft:#eef2f8; --bg-elev:#ffffff; --ink:#0f172a; --ink-2:#334155; --muted:#64748b; --border:#dfe5ee; --border-strong:#c9d1de; --accent-ink:#ffffff; }
:root[data-theme="dark"]  { --bg:#0a0a0a; --bg-soft:#111113; --bg-elev:#16161a; --ink:#fafafa; --ink-2:#d4d4d8; --muted:#a1a1aa; --border:#26262b; --border-strong:#3f3f46; --accent-ink:#0a0a0a;
  --shadow-sm: 0 1px 2px rgba(0,0,0,.4), 0 1px 3px rgba(0,0,0,.35);
  --shadow: 0 4px 12px -2px rgba(0,0,0,.4), 0 2px 4px rgba(0,0,0,.3);
  --shadow-lg: 0 24px 48px -12px rgba(0,0,0,.6), 0 8px 16px -4px rgba(0,0,0,.4);
}

*,*::before,*::after { box-sizing: border-box; }
html { -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; }
body {
  margin: 0;
  background: var(--bg);
  color: var(--ink);
  font-family: var(--font-sans);
  font-size: 15.5px;
  line-height: 1.55;
  font-feature-settings: "ss01","cv11","tnum";
}
a { color: inherit; text-decoration: none; }
button, input, select, textarea { font: inherit; font-family: var(--font-sans); }

.container { max-width: 1200px; margin: 0 auto; padding: 0 24px; }

/* ---------- top nav ---------- */
.topnav {
  position: sticky; top: 0; z-index: 30;
  background: color-mix(in oklab, var(--bg) 85%, transparent);
  backdrop-filter: saturate(150%) blur(12px);
  -webkit-backdrop-filter: saturate(150%) blur(12px);
  border-bottom: 1px solid var(--border);
}
/* position:relative so the updates panel can anchor to the *container's* right
   edge rather than to the bell's. Measured at 375px: anchored to the bell, the
   panel ran from -132px to 213px, because the bell is not the rightmost thing in
   the nav — the avatar and Sign out sit to its right. Aligning it to the
   container is also simply where a nav dropdown belongs at any width. */
/* min-height, not height (2026-08-31). A fixed height is a promise the content
   cannot keep: assets/mobile.css's tablet block sets `flex-wrap: wrap` on the
   links between 768 and 1024, and a wrapped second row inside a 60px box does
   not make the box taller — it lands on the page underneath it. On an iPad in
   portrait that put "Admin  Inbox" over the top of the workspace heading, with
   the brand and the user's name each broken across two lines beside it.

   The wrap itself is gone now (see the 721–1024 block below); this is the belt
   to that pair of braces. Anything that ever does need a second line gets one
   instead of escaping the bar. On a desktop the content is 60px tall anyway,
   so nothing moves. */
.topnav__inner { display: flex; align-items: center; gap: 24px; min-height: 60px; position: relative; }
.brand { display: inline-flex; align-items: center; gap: 10px; font-weight: 650; letter-spacing: -0.01em; color: var(--ink); font-size: 15px; }
.brand__mark {
  width: 28px; height: 28px; border-radius: 7px;
  background: linear-gradient(135deg, var(--accent), #7c3aed);
  color: #fff; font-weight: 700; font-size: 12.5px;
  display: grid; place-items: center;
}
.topnav__links { display: flex; gap: 20px; margin-left: 12px; font-size: 14px; color: var(--ink-2); }
.topnav__links a { padding: 6px 10px; border-radius: 6px; transition: background .15s, color .15s; }
.topnav__links a:hover, .topnav__links a.is-active { color: var(--ink); background: var(--bg-soft); }
.topnav__spacer { flex: 1; }
.topnav__user { display: flex; align-items: center; gap: 10px; }
.avatar {
  width: 30px; height: 30px; border-radius: 50%;
  background: var(--accent); color: var(--accent-ink);
  display: grid; place-items: center; font-weight: 600; font-size: 12.5px;
}
/* ---------- top nav: Inbox link ---------- */
.topnav__inbox { display: inline-flex; align-items: center; gap: 7px; }
.topnav__count {
  min-width: 18px; height: 18px; padding: 0 5px;
  background: var(--accent); color: var(--accent-ink);
  border-radius: 999px; font-size: 10.5px; font-weight: 700;
  display: inline-flex; align-items: center; justify-content: center;
  line-height: 1; font-variant-numeric: tabular-nums;
}

/* ---------- top nav: updates panel ---------- */
/* Deliberately NOT position:relative — the panel anchors to .topnav__inner, and
   a containing block here is what put it off-screen on a phone. The dot is
   positioned against .notif__btn, which has its own relative, so nothing here
   needs one. */
.notif { flex: 0 0 auto; }
.notif__btn {
  position: relative;
  display: inline-grid; place-items: center;
  width: 34px; height: 34px; padding: 0;
  border: 1px solid transparent; border-radius: 8px;
  background: transparent; color: var(--ink-2); cursor: pointer;
  transition: background .15s, color .15s;
}
.notif__btn:hover { background: var(--bg-soft); color: var(--ink); }
.notif__btn:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
.notif.is-open .notif__btn { background: var(--bg-soft); color: var(--ink); }
.notif__dot {
  position: absolute; top: -2px; right: -2px;
  min-width: 16px; height: 16px; padding: 0 4px;
  background: var(--danger); color: #fff;
  border: 2px solid var(--bg);
  border-radius: 999px;
  font-size: 9.5px; font-weight: 700; line-height: 1;
  display: inline-flex; align-items: center; justify-content: center;
}
/* absolute, not fixed — .topnav's backdrop-filter would capture a fixed panel
   and anchor it to the nav bar (§9 trap 3). Right-aligned and width-clamped so
   it cannot push a narrow viewport sideways. */
.notif__menu {
  position: absolute; top: calc(100% + 8px); right: 0;
  width: clamp(260px, 92vw, 360px);
  max-height: min(70vh, 520px); overflow-y: auto;
  background: var(--bg-elev);
  border: 1px solid var(--border); border-radius: var(--radius);
  box-shadow: var(--shadow-lg);
  z-index: 5;                 /* inside .topnav's own stacking context (§9 trap 4) */
  padding: 6px;
  overscroll-behavior: contain;
}
.notif__head {
  display: flex; align-items: center; gap: 8px;
  padding: 8px 10px 10px; font-size: 12px; font-weight: 650;
  color: var(--muted); text-transform: uppercase; letter-spacing: .04em;
}
.notif__empty { margin: 0; padding: 4px 10px 12px; font-size: 13px; color: var(--muted); }
.notif__item {
  display: block; padding: 9px 10px; border-radius: var(--radius-sm);
  transition: background .12s;
}
.notif__item:hover { background: var(--bg-soft); }
.notif__item + .notif__item { border-top: 1px solid var(--border); border-radius: 0; }
.notif__item-top { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.notif__what { font-size: 11.5px; font-weight: 650; color: var(--accent); }
.notif__status { font-size: 11.5px; color: var(--muted); }
.notif__status::before { content: '· '; }
/* Two lines, then ellipsis. A long title must not push the panel taller than
   the list it belongs to. */
.notif__title {
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
  overflow: hidden;
  margin-top: 4px; font-size: 13.5px; font-weight: 550; color: var(--ink);
  overflow-wrap: anywhere;
}
.notif__who { display: block; margin-top: 2px; font-size: 12px; color: var(--muted); }
.notif__foot {
  display: block; margin-top: 4px; padding: 9px 10px;
  border-top: 1px solid var(--border);
  font-size: 12.5px; font-weight: 600; color: var(--accent);
}
.notif__foot:hover { background: var(--bg-soft); }

@media (max-width: 720px) {
  /* The links used to be display:none here, which left Workspace, Documents,
     Admin and Inbox unreachable on a phone — the nav simply was not there. One
     swipeable row instead, the same treatment the Org Chart toolbars got.
     `overflow-x` makes this a clipping context (§9 trap 2), which is exactly why
     the updates panel is a sibling of this row and not inside it. */
  .topnav__links {
    display: flex; margin-left: 0; gap: 6px;
    overflow-x: auto; overscroll-behavior-x: contain;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
    min-width: 0;                 /* or the row refuses to shrink (§9 trap 7) */
  }
  .topnav__links::-webkit-scrollbar { display: none; }
  /* 44px, the same floor mobile.css holds every button to. These are anchors,
     so that rule never reached them, and they measured 34px. */
  .topnav__links a { flex: 0 0 auto; white-space: nowrap; min-height: 44px; display: inline-flex; align-items: center; }
  .topnav__inner { gap: 12px; }

  /* "HR Strategix" was wrapping onto two lines and pushing the nav taller,
     because the brand had nothing stopping it. */
  .brand { flex-shrink: 0; }
  .brand span:not(.brand__mark) { white-space: nowrap; }

  /* Ask becomes its mark alone. The word cost about 44px of a row that also has
     to hold the brand, the links, the bell and the avatar — and the panel it
     opens says what it is the moment it is open. */
  .ask__btn { padding-left: 10px; padding-right: 10px; }
  .ask__btn-label { display: none; }
  /* Only the name goes, by class. The rule used to be `.topnav__user span`,
     which at (0,1,1) also beat `.avatar { display:grid }` and blanked the
     profile link — and would now hide every span inside the updates panel,
     since that panel is a child of .topnav__user too. */
  .topnav__name { display: none; }
  /* An even gutter each side instead of sitting flush against the screen edge —
     `right: 0` resolves to the container's padding-box edge, which at this width
     is the viewport edge itself. */
  .notif__menu { right: 8px; width: clamp(260px, calc(100vw - 16px), 360px); }
  /* Anchors again, so mobile.css's 44px floor never applied. */
  .notif__foot, .topnav__user > a { min-height: 44px; display: flex; align-items: center; }
}

/* ---------- top nav on a tablet (2026-08-31) ----------
   Reported from an iPad in portrait: the header was a wreck. "HR Strategix" on
   two lines, "Workspace  Documents" on one row with "Admin  Inbox" spilling out
   of the bar and over the page heading, "Timothy Johnson" broken in half.

   Every piece of it was already solved 48 pixels lower down. The block above
   makes the links ONE horizontally-scrollable row, pins the brand to a single
   line and stops it shrinking — and it ends at 720. Between 721 and 1024 none
   of that applied, and assets/mobile.css's tablet block instead reached for
   `flex-wrap: wrap`, which is the one thing a fixed-height bar cannot absorb.
   (That wrap has been removed there; see the note in mobile.css.)

   ── Why a second row and not the ≤720 scrolling row ──
   The scrolling row was tried here first and measured: at 820pt the four links
   want 378px and 286 are free, so Workspace and Documents showed and Admin and
   Inbox sat off the end behind a swipe. Dropping the "Ask" label recovers 31px
   of that, which is not enough; hiding the user's name as well would be, at
   the price of two things an iPad has the room for. A row of links you have to
   discover a gesture to reach is barely better than the row that was clipped.

   So the original instinct in mobile.css — wrap it — was right, and the only
   thing wrong with it was that nothing had made room for the result. This is
   the shape the Project Manager's own top bar already uses at the same widths,
   for the same reason, down to the tinted band: two lines that read as a
   header and a nav rather than as one tall bar with a hole in it.

   721, not 768: a 744pt iPad mini in portrait falls in the gap between the two
   old breakpoints and was getting neither. 1024 is where the links stop
   crowding — every landscape iPad is 1180 or wider and has room to spare. */
@media (min-width: 721px) and (max-width: 1024px) {
  /* align-content: flex-start, or a wrapping flex container shares the spare
     cross-space between its LINES and both rows float in the middle of a
     too-tall bar. (The same trap the Project Manager hit at 1023.) */
  .topnav__inner {
    flex-wrap: wrap;
    align-content: flex-start;
    gap: 0 12px;
    padding-top: 6px; padding-bottom: 0;
  }

  /* 100% basis forces its own line; `order` puts that line last rather than
     first. It must look like a second row and not like a gap, so it carries a
     hairline and a tint and bleeds to the container's edges — without the
     negative margins the band stops short on both sides and reads as a
     misaligned panel. -24px is .container's own padding. */
  .topnav__links {
    order: 10;
    flex: 1 0 100%;
    margin: 6px -24px 0;
    padding: 0 24px;
    gap: 4px;
    border-top: 1px solid var(--border);
    /* --bg, not --bg-soft. The hairline is what separates the two rows; the
       band's own fill only has to differ from the ACTIVE LINK's, and
       `.topnav__links a.is-active` is --bg-soft. Painting the band that colour
       made the current page's pill vanish into it — the band read fine and you
       could no longer tell where you were. */
    background: var(--bg);
    overflow: visible;      /* an overflow here would clip any nav dropdown */
  }
  /* 44px: these are anchors, so mobile.css's button floor never reached them.
     They measured 34. */
  .topnav__links a {
    flex: 0 0 auto; white-space: nowrap;
    min-height: 44px; display: inline-flex; align-items: center;
  }

  /* The brand and the name each wrapped because nothing said they may not.
     Both are on the first row now and there is room, but the row only has room
     because they are each one line — so these are what keep it that way. */
  .brand { flex-shrink: 0; }
  .brand span:not(.brand__mark) { white-space: nowrap; }
  .topnav__user { flex-shrink: 0; }
  .topnav__name { white-space: nowrap; }

  /* The spacer has to keep asking for nothing, or it takes a line of its own
     between the two rows and pushes the user chip off the bar. */
  .topnav__spacer { flex: 1 1 0; min-width: 0; }
}

/* Touch targets in the header on a landscape iPad (1180 / 1194 / 1366).
   mobile.css's tablet block stops at 1024, so up here the nav links sit at
   34px on a device with no pointer. Asked by pointer rather than by width
   because 1180 and 1194 are also ordinary laptop window widths, and a laptop
   does not want its header links grown. */
@media (min-width: 1025px) and (pointer: coarse) {
  .topnav__links a,
  .topnav__user > a,
  .notif__btn,
  .ask__btn { min-height: 44px; display: inline-flex; align-items: center; }
}

/* ---------- buttons ---------- */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  padding: 9px 14px;
  border-radius: var(--radius-sm);
  border: 1px solid transparent;
  font-size: 14px; font-weight: 550; cursor: pointer;
  transition: transform .06s, background .15s, border-color .15s, filter .15s;
  white-space: nowrap;
}
.btn:active { transform: translateY(1px); }
.btn--primary { background: var(--ink); color: var(--bg); border-color: var(--ink); }
.btn--primary:hover { background: color-mix(in oklab, var(--ink) 88%, var(--accent)); }
.btn--accent  { background: var(--accent); color: var(--accent-ink); border-color: var(--accent); }
.btn--accent:hover { filter: brightness(1.06); }
.btn--outline { background: transparent; color: var(--ink); border-color: var(--border-strong); }
.btn--outline:hover { background: var(--bg-soft); }
.btn--ghost { background: transparent; color: var(--ink-2); border-color: transparent; }
.btn--ghost:hover { color: var(--ink); background: var(--bg-soft); }
.btn--danger { background: transparent; color: var(--danger); border-color: color-mix(in oklab, var(--danger) 40%, var(--border-strong)); }
.btn--danger:hover { background: color-mix(in oklab, var(--danger) 8%, transparent); }
.btn--sm { padding: 6px 10px; font-size: 12.5px; }
.btn--lg { padding: 12px 18px; font-size: 15px; }
.btn--block { width: 100%; }

/* ---------- form controls ---------- */
.field { margin-bottom: 14px; }
.field label { display: block; margin-bottom: 6px; font-size: 13px; color: var(--ink-2); font-weight: 550; }
.field input, .field select, .field textarea {
  width: 100%; padding: 10px 12px;
  background: var(--bg-elev);
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-sm);
  color: var(--ink); font-size: 14.5px;
  transition: border-color .15s, box-shadow .15s;
}
.field input:focus-visible, .field select:focus-visible, .field textarea:focus-visible {
  outline: 3px solid color-mix(in oklab, var(--accent) 25%, transparent);
  outline-offset: 1px;
  border-color: var(--accent);
}
.field input[aria-invalid="true"] { border-color: var(--danger); }
/* A hint belongs to the field above it, so it sits inside .field and carries no
   margin of its own beyond the gap — pages were reaching for inline styles for
   this and getting a different size each time. */
.field__hint { margin: 6px 0 0; font-size: 12.5px; color: var(--muted); }
.checkbox { display: inline-flex; align-items: center; gap: 8px; color: var(--ink-2); font-size: 13.5px; }
.checkbox input { accent-color: var(--accent); }

/* ---------- alerts / flash ---------- */
.alert {
  padding: 10px 14px;
  border-radius: var(--radius-sm);
  font-size: 14px;
  margin-bottom: 18px;
  border: 1px solid transparent;
}
.alert--info    { background: var(--accent-soft); color: var(--accent); border-color: color-mix(in oklab, var(--accent) 25%, transparent); }
.alert--success { background: color-mix(in oklab, var(--success) 10%, var(--bg)); color: var(--success); border-color: color-mix(in oklab, var(--success) 30%, transparent); }
.alert--error   { background: color-mix(in oklab, var(--danger) 8%, var(--bg)); color: var(--danger); border-color: color-mix(in oklab, var(--danger) 30%, transparent); }
/* Warn sits between info and error: something is being asked of you, but
   nothing has gone wrong. Uses the same --warning fallback pair as the
   banner rules further down, so light and dark both land. */
.alert--warn    { background: color-mix(in oklab, var(--warning, #E8A33D) 12%, var(--bg)); color: var(--warning, #8a5a00); border-color: color-mix(in oklab, var(--warning, #E8A33D) 34%, transparent); }
.alert--warn strong { display: block; margin-bottom: 3px; }
.alert--warn div    { color: var(--text); }

/* ---------- page ---------- */
/* Vertical only. Every shell page is <main class="container page">, and
   `.container` sets `padding: 0 24px` — but the shorthand here has the same
   specificity, comes later in the file, and so was resetting left and right to
   zero on every page. Invisible on a desktop, where the 1200px max-width leaves
   margins anyway; on a phone the content ran edge to edge. Reported by Tim from
   a real handset, 2026-08-18. */
.page { padding-top: 40px; padding-bottom: 80px; }
.page__head { margin-bottom: 32px; }
.page__head h1 { margin: 0 0 6px; font-size: 28px; letter-spacing: -0.02em; }
.page__head p  { margin: 0; color: var(--muted); font-size: 15px; }
.section       { margin-top: 40px; }
.section h2    { font-size: 18px; letter-spacing: -0.01em; margin: 0 0 14px; }

/* ---------- cards ---------- */
.card {
  background: var(--bg-elev);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 20px;
}
.card + .card { margin-top: 12px; }

/* ---------- table ---------- */
.table {
  width: 100%;
  border-collapse: separate;
  border-spacing: 0;
  font-size: 14px;
  background: var(--bg-elev);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  overflow: hidden;
}
.table th, .table td {
  padding: 10px 14px;
  text-align: left;
  border-bottom: 1px solid var(--border);
}
.table th {
  font-size: 12px; letter-spacing: .04em; text-transform: uppercase;
  color: var(--muted); font-weight: 600;
  background: var(--bg-soft);
}
.table tr:last-child td { border-bottom: 0; }

/* ---------- app tile grid (workspace hub) ---------- */
.apps {
  display: grid; grid-template-columns: repeat(3, 1fr); gap: 16px;
}
@media (max-width: 900px) { .apps { grid-template-columns: 1fr 1fr; } }
@media (max-width: 620px) { .apps { grid-template-columns: 1fr; } }

.app-tile {
  display: block;
  padding: 22px;
  background: var(--bg-elev);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  color: inherit;
  transition: border-color .15s, transform .15s, box-shadow .15s;
}
.app-tile:hover { border-color: var(--border-strong); transform: translateY(-2px); box-shadow: var(--shadow); }
.app-tile__icon {
  width: 40px; height: 40px; border-radius: 10px;
  background: var(--accent-soft); color: var(--accent);
  display: grid; place-items: center;
  margin-bottom: 16px;
}
.app-tile__icon svg { width: 22px; height: 22px; }
.app-tile h3 { margin: 0 0 6px; font-size: 16px; letter-spacing: -0.005em; }
.app-tile p { margin: 0; color: var(--muted); font-size: 13.5px; line-height: 1.5; }
.app-tile--empty {
  padding: 22px;
  border: 1px dashed var(--border-strong);
  border-radius: var(--radius);
  background: transparent;
  color: var(--muted);
  text-align: center;
  font-size: 13.5px;
}

/* ---------- icons ---------- */
.i { width: 18px; height: 18px; }
.i--sm { width: 14px; height: 14px; }
.i--lg { width: 22px; height: 22px; }

/* ---------- tag ---------- */
.tag {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 2px 8px;
  background: var(--accent-soft);
  color: var(--accent);
  border-radius: 999px;
  font-size: 11.5px; font-weight: 550; letter-spacing: .02em;
}
.tag--muted { background: var(--bg-soft); color: var(--muted); }
/* Solid rather than soft: "this changed" has to win against the two or three
   other pills already on the row, and every value is a token so it survives all
   four themes and the personal accent colour. */
.tag--new { background: var(--accent); color: var(--accent-ink); font-weight: 650; }

/* ---------- accessible-only text ---------- */
/* For a label a screen reader needs and the layout does not. Not `display:none`
   and not `visibility:hidden` — both take it out of the accessibility tree too,
   which defeats the point. */
.sr-only {
  position: absolute; width: 1px; height: 1px;
  padding: 0; margin: -1px; overflow: hidden;
  clip-path: inset(50%); white-space: nowrap; border: 0;
}

/* ---------- Help & Suggestions: cases ---------- */
/* Monospace and tabular so two case numbers line up digit under digit when they
   are stacked — that is the whole reason a reference is not set in prose. */
.case-no {
  font-family: var(--font-mono); font-size: 12px; font-weight: 600;
  letter-spacing: .02em; color: var(--ink-2);
  background: var(--bg-soft); border: 1px solid var(--border);
  border-radius: var(--radius-sm); padding: 1px 7px;
  font-variant-numeric: tabular-nums;
}
.case-find {
  display: flex; gap: 8px; align-items: center; flex-wrap: wrap;
  margin: 0 0 14px;
}
/* min-width:0 with the grow, or the input refuses to shrink and pushes the
   buttons off a narrow screen (§9 trap 7 in the other direction). */
.case-find input {
  flex: 1 1 260px; min-width: 0;
  padding: 8px 11px; font-size: 14px;
  border: 1px solid var(--border-strong); border-radius: var(--radius-sm);
  background: var(--bg); color: var(--ink);
}
.case-find input:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
/* A changed case is marked on its edge rather than by tinting the whole card:
   the body text stays on the same ground it always had, so nothing has to be
   restated for the dark themes (§9 trap 9). */
.card--flagged { border-left: 3px solid var(--accent); }
/* "Dana is reading this". Green and quiet: it is a courtesy, not a status, and
   it must never compete with the case's real state. */
.presence {
  display: inline-flex; align-items: center; gap: 6px;
  font-size: 12px; color: var(--muted);
}
.presence::before {
  content: ''; width: 7px; height: 7px; border-radius: 50%;
  background: var(--success); flex: 0 0 auto;
  box-shadow: 0 0 0 3px color-mix(in oklab, var(--success) 22%, transparent);
}
/* The dot pulses so it reads as live rather than as another static pill —
   and stops entirely for anyone who has asked for less motion. */
@media (prefers-reduced-motion: no-preference) {
  .presence::before { animation: hrx-pulse 2s ease-in-out infinite; }
}
@keyframes hrx-pulse {
  0%, 100% { box-shadow: 0 0 0 3px color-mix(in oklab, var(--success) 22%, transparent); }
  50%      { box-shadow: 0 0 0 5px color-mix(in oklab, var(--success) 8%, transparent); }
}
/* The one case you were sent to, as opposed to the several that merely changed.
   A ring rather than a fill, so the card's own contents are untouched. */
.card--target {
  border-left: 3px solid var(--accent);
  box-shadow: 0 0 0 3px var(--accent-soft), var(--shadow);
  scroll-margin-top: 84px;      /* clear the sticky topnav when scrolled to */
}
@media (max-width: 760px) {
  .case-find input { font-size: 16px; }   /* under 16px iOS zooms the page on focus */
}


/* ============================================================
   Impersonation banner
   Amber, not red: this is a deliberate admin action, not an error.
   Sticky and non-dismissible — forgetting you are impersonating is
   the failure mode it exists to prevent.
   ============================================================ */
.impersonation-bar {
  position: sticky; top: 0; z-index: 900;
  display: flex; align-items: center; gap: 12px; flex-wrap: wrap;
  padding: 10px 18px;
  background: #fffaeb; color: #7c2d12;
  border-bottom: 1px solid #fedf89;
  font-size: 13.5px; line-height: 1.45;
}
.impersonation-bar strong { font-weight: 650; color: #7c2d12; }
.impersonation-bar__dot {
  width: 9px; height: 9px; border-radius: 50%; background: #d97706; flex: 0 0 auto;
}
.impersonation-bar__back {
  padding: 7px 13px; border-radius: var(--radius-sm);
  border: 1px solid #d97706; background: #d97706; color: #fff;
  font-size: 13px; font-weight: 600; cursor: pointer; white-space: nowrap;
}
.impersonation-bar__back:hover { filter: brightness(1.06); }
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .impersonation-bar {
    background: rgba(217,119,6,.16); color: #fed7aa; border-bottom-color: rgba(254,223,137,.3);
  }
  :root:not([data-theme="light"]) .impersonation-bar strong { color: #fed7aa; }
}
:root[data-theme="dark"] .impersonation-bar {
  background: rgba(217,119,6,.16); color: #fed7aa; border-bottom-color: rgba(254,223,137,.3);
}
:root[data-theme="dark"] .impersonation-bar strong { color: #fed7aa; }
@media print { .impersonation-bar { display: none; } }

/* ============================================================
   INBOX — list on top, the open case below it
   ============================================================
   Cases used to render fully expanded and stacked. The list is
   scannable; the case you pick opens underneath it.

   The detail pane is the same server-rendered cards as before —
   only their visibility is switched — so every form, CSRF token
   and presence marker in them is untouched.
   ============================================================ */

.case-list {
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  overflow: hidden;
  margin-bottom: 16px;
  /* Tall queues scroll inside the list instead of pushing the open
     case off the bottom of the screen, which would defeat the point
     of having the two together. */
  max-height: 46vh;
  overflow-y: auto;
}

.case-row {
  display: grid;
  grid-template-columns: 5.5rem minmax(0, 1fr) 9rem 8rem 5.5rem auto;
  gap: 10px;
  align-items: center;
  width: 100%;
  padding: 9px 12px;
  border: 0;
  border-bottom: 1px solid var(--border);
  background: var(--bg);
  color: var(--ink);
  font: inherit;
  font-size: 13px;
  text-align: left;
  cursor: pointer;
}
.case-row:last-child { border-bottom: 0; }
.case-row:hover { background: color-mix(in oklab, var(--accent) 7%, var(--bg)); }
.case-row:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }

.case-row.is-selected {
  background: color-mix(in oklab, var(--accent) 13%, var(--bg));
  box-shadow: inset 3px 0 0 var(--accent);
}

.case-row__no      { font-variant-numeric: tabular-nums; color: var(--muted); font-size: 12px; }
.case-row__subject { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-weight: 550; }
.case-row__who,
.case-row__status,
.case-row__when    { color: var(--muted); font-size: 12px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.case-row__when    { font-variant-numeric: tabular-nums; }

.case-row.is-new .case-row__subject { font-weight: 700; }
.case-row__new {
  font-size: 10.5px; font-weight: 700; text-transform: uppercase; letter-spacing: .04em;
  padding: 1px 6px; border-radius: 999px;
  background: color-mix(in oklab, var(--accent) 20%, var(--bg)); color: var(--accent);
}
.case-row__flag {
  display: inline-flex; align-items: center; justify-content: center;
  width: 16px; height: 16px; margin-left: 4px; border-radius: 50%;
  font-size: 11px; font-weight: 700;
  background: color-mix(in oklab, var(--danger) 16%, var(--bg)); color: var(--danger);
}

.case-detail__hint {
  color: var(--muted);
  font-size: 13.5px;
  padding: 18px 2px;
}

/* Narrow screens: the middle columns are the first to go. The case
   number, subject and unread marker are what make a row findable. */
@media (max-width: 900px) {
  .case-row { grid-template-columns: 5rem minmax(0, 1fr) auto; }
  .case-row__who,
  .case-row__status { display: none; }
}
@media (max-width: 620px) {
  .case-row { grid-template-columns: minmax(0, 1fr) auto; }
  .case-row__no, .case-row__when { display: none; }
}

/* ---------- case replies, and the notes that are not replies ---------- */
.reply {
  border-left: 2px solid var(--border);
  padding: 6px 0 6px 12px;
  margin-bottom: 8px;
}

/* An internal note must be impossible to mistake for something the requester
   has seen. Amber rather than the accent: the accent already means "new" on
   these cards, and a second meaning for one colour is how a glance goes wrong.
   The flag says who cannot see it by name — "not visible to Dana Reed" is a
   sentence you check yourself against, in a way that "internal" is not. */
.reply--note {
  border-left: 3px solid #d97706;
  background: color-mix(in oklab, #d97706 7%, var(--bg));
  border-radius: 0 var(--radius-sm) var(--radius-sm) 0;
  padding: 8px 12px 8px 12px;
}
.reply__flag {
  display: block;
  font-family: var(--font-mono);
  font-size: 10px;
  font-weight: 650;
  letter-spacing: .07em;
  text-transform: uppercase;
  color: #b45309;
  margin-bottom: 3px;
}
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .reply__flag { color: #fbbf24; }
}
:root[data-theme="dark"] .reply__flag { color: #fbbf24; }

/* ============================================================
   CASE VIEWS — one render, three arrangements
   ============================================================
   Workbench, Ledger and Triage are the same server-rendered case
   with different things shown. Switching is pure CSS on
   [data-case-view], so changing view never re-fetches and never
   loses what you had typed in the reply box.
   ============================================================ */

.case-views { display: flex; align-items: center; gap: 4px; margin: 0 0 12px; flex-wrap: wrap; }
.case-view-btn {
  font: inherit; font-size: 12.5px; font-weight: 550;
  padding: 6px 13px; min-height: 34px;
  border: 1px solid var(--border); border-radius: 999px;
  background: var(--bg); color: var(--muted); cursor: pointer;
}
.case-view-btn:hover { color: var(--ink); border-color: var(--border-strong); }
.case-view-btn.is-on { background: var(--accent-soft); border-color: color-mix(in oklab, var(--accent) 34%, transparent); color: var(--accent); }
.case-view-btn:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.case-views__note { font-size: 12px; color: var(--muted); margin-left: 8px; }

/* ---------- the panes ---------- */
.case__panes { display: block; }
.case__ledger, .case__rail { display: none; }   /* Workbench is the default */

.case__rail-title {
  font-family: var(--font-mono); font-size: 10px; letter-spacing: .09em;
  text-transform: uppercase; color: var(--muted);
  margin: 0 0 12px; padding-bottom: 8px; border-bottom: 1px solid var(--border);
}
.case__field { display: block; margin-bottom: 11px; }
.case__k {
  display: block; font-family: var(--font-mono); font-size: 10px;
  letter-spacing: .08em; text-transform: uppercase; color: var(--muted); margin-bottom: 2px;
}
.case__v { font-size: 12.5px; color: var(--ink); }
.case__link {
  display: block; width: 100%; text-align: left;
  font: inherit; font-size: 12px; color: var(--accent);
  background: none; border: 0; padding: 2px 0; cursor: pointer;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.case__link:hover { text-decoration: underline; }

/* ---------- A · Workbench: conversation left, facts right ---------- */
[data-case-view="workbench"] .case__panes {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 210px;
  gap: 18px;
  align-items: start;
}
[data-case-view="workbench"] .case__rail {
  display: block;
  background: var(--bg-soft);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  padding: 12px 14px;
}

/* ---------- B · Ledger: one column, history instead of thread ---------- */
[data-case-view="ledger"] .case__conversation { display: none; }
[data-case-view="ledger"] .case__ledger { display: block; }

.case__ledger { list-style: none; margin: 0 0 10px; padding: 0; }
.ev { display: grid; grid-template-columns: 18px minmax(0, 1fr); gap: 10px; position: relative; padding: 5px 0; }
.ev::before {
  content: ""; position: absolute; left: 8px; top: 0; bottom: 0;
  width: 1px; background: var(--border);
}
.ev:first-child::before { top: 14px; }
.ev:last-child::before  { bottom: calc(100% - 14px); }
.ev__dot {
  width: 9px; height: 9px; margin: 9px 0 0 4px; border-radius: 50%;
  background: var(--border-strong); z-index: 1;
}
.ev--reply  .ev__dot,
.ev--raised .ev__dot { background: var(--accent); }
.ev--note   .ev__dot { background: #d97706; }
.ev--read   .ev__dot { background: var(--success); }
.ev__body { min-width: 0; }
.ev__sys { margin: 4px 0; font-size: 12.5px; color: var(--ink-2); }
.ev__by { color: var(--muted); font-size: 11.5px; margin-left: 6px; }
/* Impersonation. Not decoration — it is the answer to "who really did this". */
.ev__real { color: var(--danger); font-weight: 600; }

/* ---------- C · Triage: dense, conversation only ---------- */
[data-case-view="triage"] .case__panes { display: block; }
[data-case-view="triage"] .reply { padding-top: 3px; padding-bottom: 3px; }
[data-case-view="triage"] .card { padding: 12px 14px; }

@media (max-width: 900px) {
  /* The rail drops under the conversation rather than squeezing it. */
  [data-case-view="workbench"] .case__panes { grid-template-columns: 1fr; }
}

/* ---------- the Ask box, following the shell's theme ----------
   assets/assistant.css sets its own colours so it survives being injected into
   five tools that share no design system. Inside the shell we do have tokens —
   and four themes plus a per-person accent — so they are handed back to it
   here. This is the only place the two stylesheets meet. */
.ask {
  --ask-bg: var(--bg-elev);
  --ask-soft: var(--bg-soft);
  --ask-ink: var(--ink);
  --ask-ink-2: var(--ink-2);
  --ask-muted: var(--muted);
  --ask-line: var(--border);
  --ask-line-strong: var(--border-strong);
  --ask-accent: var(--accent);
  --ask-accent-soft: var(--accent-soft);
  --ask-shadow: var(--shadow-lg);
  --ask-radius: var(--radius);
  --ask-radius-sm: var(--radius-sm);
  --ask-font: var(--font-sans);
  --ask-mono: var(--font-mono);
  margin-right: 8px;
}
/* In the shell the box lives in the nav, so it is never the floating variant. */
.topnav .ask__input { font-size: 14px; }

/* ---------- the user menu ----------
   The name in the corner is a menu: Profile, Help & Suggestions, Sign out.
   Help used to be a footer link inside the notifications panel, which meant
   opening a bell about updates to find the page for raising a case. */

.usermenu { position: relative; display: inline-flex; }

.usermenu__btn {
  display: inline-flex; align-items: center; gap: 10px;
  padding: 4px 8px; border: 0; border-radius: 8px;
  background: none; color: inherit; font: inherit; cursor: pointer;
  transition: background .15s;
}
.usermenu__btn:hover { background: var(--bg-soft); }
.usermenu__btn:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.usermenu.is-open .usermenu__btn { background: var(--bg-soft); }

.usermenu__caret { color: var(--muted); flex-shrink: 0; transition: transform .15s; }
.usermenu.is-open .usermenu__caret { transform: rotate(180deg); }

.usermenu__menu {
  position: absolute; top: calc(100% + 8px); right: 0; z-index: 80;
  width: 264px; padding: 6px;
  background: var(--bg-elev); border: 1px solid var(--border);
  border-radius: var(--radius); box-shadow: var(--shadow-lg);
}
.usermenu__menu[hidden] { display: none; }

.usermenu__head {
  padding: 8px 10px 10px; margin-bottom: 4px;
  border-bottom: 1px solid var(--border);
  display: flex; flex-direction: column; gap: 1px; min-width: 0;
}
.usermenu__head-name { font-size: 13.5px; font-weight: 600; color: var(--ink); }
.usermenu__head-mail {
  font-size: 12px; color: var(--muted);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

.usermenu__item {
  display: flex; align-items: flex-start; gap: 10px;
  padding: 9px 10px; border-radius: var(--radius-sm);
  color: var(--ink); text-decoration: none; font-size: 13.5px;
  min-height: 44px;             /* the same touch floor the rest of the app uses */
}
.usermenu__item:hover { background: var(--bg-soft); }
.usermenu__item:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }
.usermenu__item.is-on { background: var(--accent-soft); color: var(--accent); font-weight: 600; }

.usermenu__ico { width: 18px; text-align: center; font-size: 13px; opacity: .75; flex-shrink: 0; line-height: 1.5; }
.usermenu__sub { display: block; font-size: 11.5px; color: var(--muted); font-weight: 400; margin-top: 1px; }
.usermenu__item.is-on .usermenu__sub { color: color-mix(in oklab, var(--accent) 70%, var(--muted)); }

.usermenu__n {
  margin-left: auto; align-self: center;
  font-family: var(--font-mono); font-size: 10px; font-weight: 650;
  padding: 1px 6px; border-radius: 999px;
  background: var(--accent); color: var(--accent-ink);
}

.usermenu__divider { height: 1px; background: var(--border); margin: 5px 4px; }
.usermenu__item--quiet { color: var(--ink-2); }

@media (max-width: 620px) {
  /* The name is hidden on a phone (topnav__name already does that), so the
     avatar alone opens it — and the panel takes the width it needs rather than
     hanging off the edge. */
  .usermenu__menu { position: fixed; left: 12px; right: 12px; width: auto; top: 58px; }
}

/* ============================================================
   WORKSPACE ON A PHONE
   ============================================================
   Six tiles at ~160px each is ~960px of cards against ~700px of
   screen: you see four and scroll for the rest, and the
   descriptions — the part you need least once you know the
   apps — are most of that height.

   Under 620px the tiles become rows and a "Waiting on you" card
   goes above them. Desktop is untouched: the tiles work there,
   and this is not a desktop problem.
   ============================================================ */

/* Hidden by default, shown only on phones. Rendered into the markup
   regardless because $badges is already computed for the tiles — there is no
   query to save by leaving it out, and this way turning it on for desktop is
   deleting one line rather than writing any. */
.needs { display: none; }

@media (max-width: 620px) {

  /* The heading and greeting took about a fifth of the screen before anything
     you can act on. Smaller, and the greeting goes — "Welcome back, Tim" is
     pleasant on a desktop and is a line of scrolling on a phone. */
  /* 40px above the heading is a desktop measure. */
  .page { padding-top: 18px; padding-bottom: 40px; }
  .container { padding-left: 16px; padding-right: 16px; }

  .page__head h1 { font-size: 22px; margin-bottom: 2px; }
  .page__head p  { display: none; }
  .page__head    { margin-bottom: 14px; }

  .needs {
    display: block;
    background: color-mix(in oklab, #d97706 8%, var(--bg-elev));
    border: 1px solid color-mix(in oklab, #d97706 26%, transparent);
    border-radius: var(--radius);
    padding: 12px 14px;
    margin-bottom: 18px;
  }
  .needs__h {
    display: flex; align-items: center; gap: 8px;
    margin: 0 0 4px; font-size: 14px; font-weight: 650; color: var(--ink);
  }
  .needs__total {
    min-width: 20px; height: 20px; padding: 0 6px;
    background: #d97706; color: #fff; border-radius: 999px;
    font-size: 11px; font-weight: 700;
    display: inline-flex; align-items: center; justify-content: center;
  }
  .needs__row {
    display: flex; align-items: center; gap: 11px;
    padding: 10px 0; min-height: 48px;
    color: inherit; text-decoration: none;
    border-top: 1px solid color-mix(in oklab, #d97706 16%, transparent);
  }
  .needs__row:first-of-type { border-top: 0; }
  .needs__ico { width: 26px; flex-shrink: 0; color: #b45309; display: grid; place-items: center; }
  .needs__ico svg { width: 19px; height: 19px; }
  .needs__text { min-width: 0; flex: 1; }
  .needs__name { display: block; font-size: 13.5px; font-weight: 600; color: var(--ink); }
  .needs__why  { display: block; font-size: 11.5px; color: var(--muted); line-height: 1.4; margin-top: 1px; }
  /* An age is a fact until it is a problem; then it is the loudest thing in the
     row. Amber matches the card it sits in rather than introducing a colour. */
  .needs__age { color: var(--muted); }
  .needs__age.is-stale { color: #b45309; font-weight: 600; }
  .needs__n {
    min-width: 22px; height: 22px; padding: 0 7px; flex-shrink: 0;
    background: #d97706; color: #fff; border-radius: 999px;
    font-size: 11.5px; font-weight: 700;
    display: inline-flex; align-items: center; justify-content: center;
  }

  /* ── tiles become rows ──
     Same markup: the description is hidden and the card lays out sideways.
     Nothing in app.php changes, so a tile added later gets this for free. */
  .apps { gap: 8px; }

  .app-tile {
    display: flex; align-items: center; gap: 12px;
    padding: 11px 13px; min-height: 56px;
    position: relative;
  }
  .app-tile:hover { transform: none; }        /* no lift on a touch screen */
  .app-tile__icon { width: 32px; height: 32px; margin-bottom: 0; flex-shrink: 0; border-radius: 9px; }
  .app-tile__icon svg { width: 18px; height: 18px; }
  .app-tile h3 { margin: 0; font-size: 14px; flex: 1; min-width: 0; }
  .app-tile p  { display: none; }

  /* The badge was absolutely positioned for a tall card. In a row it belongs
     in the flow, at the end, where the eye already finishes. Overridden with
     !important only because the original is an inline style in app.php and
     nothing else can beat it. */
  /* Already named in the card above — see app.php. */
  .app-tile--listed > span[title] { display: none !important; }

  .app-tile > span[title] {
    position: static !important;
    top: auto !important; right: auto !important;
    /* The badge is FIRST in the markup — it was absolutely positioned, so its
       order never mattered. As a flex item it does: `margin-left: auto` on the
       first child pushes everything after it rightwards instead of moving the
       badge, which put the count on the left of the row. `order` sends it to
       the end, where the eye finishes. */
    order: 9;
    margin-left: auto; flex-shrink: 0;
  }
}

/* ---------- one department, everything about it ---------- */

.dept-stats { display: flex; gap: 10px; flex-wrap: wrap; margin-bottom: 8px; }
.dept-stat {
  flex: 1 1 auto; min-width: 108px;
  border: 1px solid var(--border); border-radius: var(--radius);
  background: var(--bg-elev); padding: 12px 14px;
}
.dept-stat b { display: block; font-size: 22px; line-height: 1.1; letter-spacing: -.02em; }
.dept-stat span { font-size: 12px; color: var(--muted); }
/* An open position is a fact, not a fault — amber rather than red, and only
   when there is one. */
.dept-stat--warn { border-color: color-mix(in oklab, #d97706 34%, transparent); }
.dept-stat--warn b { color: #b45309; }

.dept-row {
  display: flex; align-items: center; gap: 10px;
  padding: 11px 14px; border-bottom: 1px solid var(--border);
  color: inherit; text-decoration: none; font-size: 13.5px; min-height: 48px;
}
.dept-row:last-child { border-bottom: 0; }
a.dept-row:hover { background: var(--bg-soft); }
.dept-row__name { font-weight: 550; color: var(--ink); }
.dept-row__sub  { color: var(--muted); font-size: 12.5px; }
.dept-row__sp   { flex: 1; }
/* A vacancy reads differently from a person without shouting. */
.dept-row--vacant .dept-row__name { color: var(--ink-2); font-style: italic; }

@media (max-width: 620px) {
  /* Name over detail, and the tags drop under both rather than squeezing the
     name into two words. */
  .dept-row { flex-wrap: wrap; row-gap: 2px; padding: 10px 12px; }
  .dept-row__name { width: 100%; }
  .dept-row__sp { display: none; }
  .dept-stat { min-width: calc(50% - 5px); }
  .dept-stat b { font-size: 19px; }
}

/* ── The bell carries more than support cases now (2026-08-19) ────────────
   Assignments from Strategic Alignment share the item markup, but their tag is
   a word — "Overdue", "Due", "Assigned" — not a case number, and .case-no is a
   monospace chip built for SUP-00042. Restyled per kind so the two read as the
   different things they are, and so the one you are already late for is the one
   that catches the eye. Semantic colour, not the accent: this is state, not
   emphasis. */
.notif__item--overdue .case-no,
.notif__item--due .case-no,
.notif__item--assigned .case-no {
  font-family: inherit;
  letter-spacing: .01em;
  text-transform: uppercase;
  font-size: 10.5px;
}
.notif__item--overdue .case-no {
  color: var(--danger);
  background: color-mix(in oklab, var(--danger) 12%, var(--bg));
  border-color: color-mix(in oklab, var(--danger) 35%, var(--border));
}
.notif__item--due .case-no {
  color: var(--warning, #8a5a00);
  background: color-mix(in oklab, var(--warning, #E8A33D) 14%, var(--bg));
  border-color: color-mix(in oklab, var(--warning, #E8A33D) 35%, var(--border));
}
.notif__item--assigned .case-no {
  color: var(--accent);
  background: color-mix(in oklab, var(--accent) 10%, var(--bg));
  border-color: color-mix(in oklab, var(--accent) 30%, var(--border));
}
/* A hairline down the left of anything already late, so the panel can be read
   at a glance rather than word by word. */
.notif__item--overdue { border-left: 3px solid var(--danger); }

/* ── Announcement banners (2026-08-19) ────────────────────────────────────
   An admin can put one of these in front of everybody — a maintenance window,
   a deadline, an outage. There was no way to do that before: GoDaddy's mail()
   lands in spam, which is the same constraint that keeps approvals in-app.

   Tone is semantic colour, separate from the site accent, so "critical" still
   reads as critical whatever colour somebody has chosen for themselves. */
.hrx-banners { display: flex; flex-direction: column; gap: 8px; margin: 14px auto 0; max-width: var(--page-max, 1180px); padding: 0 var(--page-pad, 20px); }
.hrx-banner {
  display: flex; align-items: flex-start; gap: 10px;
  padding: 11px 14px; border-radius: var(--radius-sm);
  border: 1px solid var(--border); border-left-width: 4px;
  background: var(--bg-soft); color: var(--ink);
  font-size: 13.5px; line-height: 1.5;
}
.hrx-banner__icon { font-size: 16px; line-height: 1.35; flex: 0 0 auto; }
.hrx-banner__text { flex: 1 1 auto; min-width: 0; }
.hrx-banner__actions { display: flex; align-items: center; gap: 6px; flex: 0 0 auto; flex-wrap: wrap; }
.hrx-banner__btn {
  font: inherit; font-size: 12.5px; font-weight: 600;
  padding: 4px 10px; border-radius: var(--radius-sm);
  border: 1px solid currentColor; background: transparent; color: inherit;
  cursor: pointer; opacity: .8;
}
.hrx-banner__btn:hover { opacity: 1; background: color-mix(in oklab, currentColor 10%, transparent); }
/* Why there is no Dismiss, said rather than left to be noticed. */
.hrx-banner__note { font-size: 11.5px; opacity: .7; font-style: italic; }

.hrx-banner--info     { border-left-color: var(--accent); }
.hrx-banner--success  { border-left-color: var(--success); color: var(--success); }
.hrx-banner--warning  { border-left-color: #E8A33D; background: color-mix(in oklab, #E8A33D 10%, var(--bg)); color: #7A4B00; }
.hrx-banner--critical { border-left-color: var(--danger); background: color-mix(in oklab, var(--danger) 10%, var(--bg)); color: var(--danger); font-weight: 500; }

@media (max-width: 620px) {
  /* The actions drop under the message rather than squeezing it to nothing —
     a notice you cannot read is not a notice. */
  .hrx-banner { flex-wrap: wrap; }
  .hrx-banner__actions { width: 100%; justify-content: flex-end; }
}

/* ── Site footer (2026-08-19) ─────────────────────────────────────────────
   Terms, privacy, cookies and accessibility, at the bottom of every page.
   Quiet by design: these are links people look for deliberately, not ones that
   should compete with the work. */
.sitefoot { margin-top: 48px; border-top: 1px solid var(--border); background: var(--bg-soft); }
.sitefoot__inner {
  max-width: var(--page-max, 1180px); margin: 0 auto; padding: 18px var(--page-pad, 20px);
  display: flex; flex-wrap: wrap; gap: 10px 20px; align-items: center; justify-content: space-between;
  font-size: 12.5px; color: var(--muted);
}
.sitefoot__links { display: flex; flex-wrap: wrap; gap: 4px 16px; }
.sitefoot__links a { color: var(--muted); text-decoration: none; }
.sitefoot__links a:hover { color: var(--ink); text-decoration: underline; }
@media (max-width: 620px) {
  /* Stacked rather than squeezed — five link targets on one line at 375px are
     five things nobody can hit. The rows are given the site's 44px touch
     target as well: these are small, quiet links, but "quiet" is about how
     they look, not about how hard they are to press. */
  .sitefoot__inner { flex-direction: column; align-items: flex-start; gap: 4px; }
  .sitefoot__links { flex-direction: column; gap: 0; width: 100%; }
  .sitefoot__links a { display: flex; align-items: center; min-height: 44px; width: 100%; }
}
