/* Eladora — bright lavender design system.
   Server-rendered, no build step. Component classes match the EJS views. */

:root {
  --bg: #F4EFFE;
  --surface: #FFFFFF;
  --surface-2: #EFE7FD;
  --ink: #2A2440;
  --muted: #6B6488;
  --faint: #A29AC0;
  --line: #E2D8F6;

  --accent: #7048E8;        /* full, rich lavender-violet */
  --accent-strong: #5127C9; /* deeper, for headings & brand */
  --accent-soft: #E9DEFD;
  --on-accent: #FFFFFF;

  --gold: #C69128;          /* warm secondary (the wings) */
  --gold-soft: #FAF0D8;

  --ok: #2E9E66;   --ok-soft: #E3F5EC;
  --warn: #B07A16; --warn-soft: #FAEFD6;   /* invited */
  --danger: #D4436B; --danger-soft: #FCE5EC; /* suspended / retired */
  --super: #7A3FD0; --super-soft: #EEE3FB;

  --sidebar: #ECE3FC;
  --sidebar-ink: #453A66;
  --sidebar-faint: #877CA8;
  --sidebar-hover: #E0D2FA;
  --sidebar-on: #FFFFFF;

  --shadow: 0 1px 2px rgba(50, 30, 90, .04), 0 8px 24px rgba(80, 50, 150, .06);
  --radius: 12px;

  --sans: system-ui, -apple-system, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
  --serif: Georgia, Cambria, "Times New Roman", serif;
  --mono: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
}

@media (prefers-color-scheme: dark) {
  :root {
    --bg: #16121F; --surface: #1E1930; --surface-2: #282136;
    --ink: #ECE7F6; --muted: #ABA2C0; --faint: #7C7292; --line: #322A44;
    --accent: #B49BFF; --accent-strong: #C9BAFF; --accent-soft: #251E38; --on-accent: #17121F;
    --gold: #DDBB63; --gold-soft: #2A2311;
    --ok: #67C79E; --ok-soft: #14271E; --warn: #DBAE5C; --warn-soft: #281F0F;
    --danger: #F08AA6; --danger-soft: #2E1620; --super: #C6A9F5; --super-soft: #251C38;
    --sidebar: #1B1528; --sidebar-ink: #C0B6D8; --sidebar-faint: #7C7192;
    --sidebar-hover: #262038; --sidebar-on: #FFFFFF;
    --shadow: 0 1px 2px rgba(0,0,0,.2), 0 8px 24px rgba(0,0,0,.28);
  }
}
:root[data-theme="light"] { color-scheme: light; }
:root[data-theme="dark"] {
  color-scheme: dark;
  --bg: #16121F; --surface: #1E1930; --surface-2: #282136;
  --ink: #ECE7F6; --muted: #ABA2C0; --faint: #7C7292; --line: #322A44;
  --accent: #B49BFF; --accent-strong: #C9BAFF; --accent-soft: #251E38; --on-accent: #17121F;
  --gold: #DDBB63; --gold-soft: #2A2311;
  --ok: #67C79E; --ok-soft: #14271E; --warn: #DBAE5C; --warn-soft: #281F0F;
  --danger: #F08AA6; --danger-soft: #2E1620; --super: #C6A9F5; --super-soft: #251C38;
  --sidebar: #1B1528; --sidebar-ink: #C0B6D8; --sidebar-faint: #7C7192;
  --sidebar-hover: #262038; --sidebar-on: #FFFFFF;
}

* { box-sizing: border-box; }

body {
  margin: 0;
  font: 15.5px/1.55 var(--sans);
  color: var(--ink);
  background: var(--bg);
  -webkit-font-smoothing: antialiased;
}

/* ---- app shell -------------------------------------------------------------- */
.app { display: grid; grid-template-columns: 232px 1fr; min-height: 100vh; }
.app--plain { grid-template-columns: 1fr; }
.app.nav-collapsed { grid-template-columns: 1fr; }
.app.nav-collapsed .sidebar { display: none; }
.nav-toggle { background: var(--surface-2); border: 1px solid var(--line); border-radius: 8px;
  color: var(--accent-strong); font-size: 15px; padding: .3rem .6rem; cursor: pointer; box-shadow: none; }
.nav-toggle:hover { border-color: var(--accent); filter: none; box-shadow: none; }

.sidebar {
  background: var(--sidebar);
  border-right: 1px solid var(--line);
  padding: 18px 14px;
  display: flex; flex-direction: column; gap: 4px;
  /* NOT overflow-y: auto, and not height: 100vh. A scrolling box clips its
     children, which sliced the mail panel in half at the sidebar's edge; taking
     the panel out with position: fixed then left it floating over the content.
     min-height lets a long nav make the PAGE taller instead of scrolling inside
     a box of its own — so nothing clips, and nothing can become unreachable at
     the bottom of a short window either. 2026-07-31. */
  position: sticky; top: 0; min-height: 100vh; overflow: visible;
}
.brand { display: flex; align-items: center; gap: 11px; text-decoration: none; padding: 4px 8px 16px; }
.mark {
  /* 44px, not 34. The mark stopped being decoration when it became the mailbox:
     it is now a button that carries an alert, and 34 is below the 44px touch
     minimum both iOS and Android use. It also gives the red count a corner to
     sit on instead of covering the artwork. Beyond about 54 it starts competing
     with the name and the brand block wants restacking, which is more change
     than the gain is worth. 2026-07-31. */
  width: 44px; height: 44px; border-radius: 10px; flex: none;
  background: linear-gradient(135deg, var(--accent), var(--super));
  color: #fff; display: grid; place-items: center; font-size: 17px;
  box-shadow: 0 3px 8px rgba(124, 92, 230, .35);
}
.brand-name { font-family: var(--serif); font-weight: 600; font-size: 16px; color: var(--accent-strong); line-height: 1.1; }
.brand-name small { display: block; font-family: var(--sans); font-size: 11px; font-weight: 500; color: var(--sidebar-faint); letter-spacing: .02em; }
.sidebar nav { display: flex; flex-direction: column; gap: 2px; }
.sidebar nav a {
  color: var(--sidebar-ink); text-decoration: none; font-size: 14px; font-weight: 500;
  padding: 9px 11px; border-radius: 9px; transition: background .12s, color .12s;
}
.sidebar nav a:hover { background: var(--sidebar-hover); }
.sidebar nav a.on { background: var(--accent); color: var(--sidebar-on); box-shadow: 0 2px 8px rgba(124,92,230,.3); }

.main { min-width: 0; display: flex; flex-direction: column; }
.topbar {
  display: flex; align-items: center; gap: 14px;
  padding: 12px 26px; background: var(--surface);
  border-bottom: 1px solid var(--line); position: sticky; top: 0; z-index: 5;
}
.topbar-title { font-family: var(--serif); font-weight: 600; font-size: 17px; color: var(--ink); }
.spacer { flex: 1; }
.who { color: var(--muted); font-size: 13px; margin-right: .4rem; }

/* ---- avatar menu (initials circle -> sign out) ------------------------------ */
.avatar-menu { position: relative; }
.avatar-menu summary { list-style: none; cursor: pointer; display: inline-flex; border-radius: 999px; }
.avatar-menu summary::-webkit-details-marker { display: none; }
.avatar-menu summary:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.avatar {
  width: 36px; height: 36px; border-radius: 999px; flex: none;
  background: linear-gradient(135deg, var(--accent), var(--super));
  color: #fff; display: grid; place-items: center;
  font-size: 13.5px; font-weight: 700; letter-spacing: .02em;
  box-shadow: 0 2px 8px rgba(124, 92, 230, .35);
}
.avatar-menu[open] .avatar { outline: 2px solid var(--accent-soft); }
.avatar-pop {
  position: absolute; right: 0; top: calc(100% + 8px); z-index: 20;
  background: var(--surface); border: 1px solid var(--line); border-radius: 12px;
  box-shadow: var(--shadow); padding: .8rem .95rem; min-width: 15rem;
  display: flex; flex-direction: column; gap: .6rem;
}
.avatar-pop .who { margin: 0; word-break: break-all; }
.avatar-pop form { margin: 0; }
.avatar-pop .signout { width: 100%; }

/* LEFT-ALIGNED, NOT CENTRED. The 68rem cap is a readability choice and it stays
   — a line of prose 2000px wide is unreadable. What changed on 2026-07-31 is
   where the leftover space goes.
   Centring a capped column inside the space left over by a 232px sidebar puts a
   large gap between the sidebar and the content on any wide monitor, and none on
   the right, so the page reads as having slid sideways. With a sidebar, content
   belongs beside it. Pages with no sidebar are centred by the rule below. */
main { padding: 26px; max-width: 68rem; width: 100%; margin: 0; flex: 1; }
.app--plain main { margin: 0 auto; }
/* A page whose point is a wide grid uses the whole window. The 68rem column is
   a readability choice for prose; applied to a payroll sheet it leaves the
   table squeezed into two thirds of the screen with nothing beside it. */
main.wide { max-width: none; }
/* The same argument for the matrix grids — permission grid, document grid, the
   per-person grid. A grid is read ACROSS: every extra column of window is one
   more level you can compare without scrolling sideways, and comparing levels
   against each other is the entire point of the page. At 68rem the eight levels
   sat squeezed into two thirds of a wide monitor with the right third empty.
   `main.wide` already exists for this, but it has to be set per route and the
   grids are reached from several — matching on the wrapper means the page is
   wide because of what is ON it, which cannot be forgotten. */
main:has(.pg-wrap) { max-width: none; }
.app--plain main { display: flex; align-items: flex-start; justify-content: center; padding-top: 8vh; }

/* ---- typography ------------------------------------------------------------- */
h1 { font-family: var(--serif); font-weight: 600; font-size: 1.7rem; margin: 0 0 .5rem; color: var(--ink); letter-spacing: -.01em; }
h2 { font-family: var(--serif); font-weight: 600; font-size: 1.2rem; margin: 2rem 0 .6rem; color: var(--ink); }
h3 { font-size: 1rem; margin: 1.4rem 0 .5rem; }
p { margin: .5rem 0; }
a { color: var(--accent); }
code {
  font-family: var(--mono); font-size: .85em; background: var(--surface-2);
  color: var(--accent-strong); padding: .12em .4em; border-radius: 5px;
}

/* ---- tables ----------------------------------------------------------------- */
table {
  width: 100%; border-collapse: collapse; background: var(--surface);
  border: 1px solid var(--line); border-radius: var(--radius); overflow: hidden; box-shadow: var(--shadow);
}
th, td { text-align: left; padding: .62rem .85rem; border-bottom: 1px solid var(--line); vertical-align: top; }
th {
  background: var(--surface-2); font-size: .74rem; text-transform: uppercase;
  letter-spacing: .05em; color: var(--muted); font-weight: 700;
}
tbody tr:last-child td { border-bottom: none; }
tbody tr:hover { background: var(--surface-2); }
table.small { font-size: .875rem; }
table.small th { font-size: .68rem; }

/* ---- soft group tints (stable per group) ------------------------------------ */
.tint-0 { --t: #B45AC8; --t-soft: #F6E7FA; }  /* orchid — Human Resources */
.tint-1 { --t: #5B6CE0; --t-soft: #E9EDFC; }  /* periwinkle — DrChrono */
.tint-2 { --t: #7A3FA8; --t-soft: #F0E7F8; }  /* plum — Compliance */
.tint-3 { --t: #D2679A; --t-soft: #FBE9F1; }  /* rose — QAPI */
.tint-4 { --t: #4F9E96; --t-soft: #E4F3F1; }  /* soft teal */
.tint-5 { --t: #C69128; --t-soft: #FAF0D8; }  /* soft gold */
@media (prefers-color-scheme: dark) {
  .tint-0 { --t-soft: #2E2136; } .tint-1 { --t-soft: #1F2338; } .tint-2 { --t-soft: #291F33; }
  .tint-3 { --t-soft: #301F28; } .tint-4 { --t-soft: #172A28; } .tint-5 { --t-soft: #2A2311; }
}
:root[data-theme="dark"] .tint-0 { --t-soft: #2E2136; }
:root[data-theme="dark"] .tint-1 { --t-soft: #1F2338; }
:root[data-theme="dark"] .tint-2 { --t-soft: #291F33; }
:root[data-theme="dark"] .tint-3 { --t-soft: #301F28; }
:root[data-theme="dark"] .tint-4 { --t-soft: #172A28; }
:root[data-theme="dark"] .tint-5 { --t-soft: #2A2311; }

.medallion {
  width: 40px; height: 40px; border-radius: 11px; flex: none;
  background: var(--t-soft); color: var(--t);
  display: grid; place-items: center; font-weight: 800; font-size: 13.5px; letter-spacing: .02em;
}
.group-band {
  background: var(--t-soft); border: 1px solid color-mix(in srgb, var(--t) 25%, var(--line));
  border-left: 5px solid var(--t);
  border-radius: var(--radius); padding: 1rem 1.25rem; margin: .8rem 0 1.2rem;
  display: flex; align-items: center; gap: .9rem;
}
.group-band h1 { margin: 0; }
.group-band .muted { margin: 0; }

/* ---- landing-page group tiles (click to open the group's page) -------------- */
.group-tiles { display: grid; gap: 1rem; grid-template-columns: repeat(auto-fill, minmax(14rem, 1fr)); margin: 1.1rem 0 1.6rem; }
.group-tile {
  display: flex; align-items: center; gap: .9rem; text-decoration: none;
  background: var(--t-soft, var(--surface));
  border: 1px solid color-mix(in srgb, var(--t, var(--accent)) 22%, var(--line));
  border-radius: var(--radius);
  padding: .9rem 1.1rem; box-shadow: var(--shadow);
  transition: transform .12s, box-shadow .12s, border-color .12s;
}
.group-tile:hover { transform: translateY(-2px); box-shadow: 0 6px 20px rgba(112, 72, 232, .18); border-color: var(--t, var(--accent)); }
.group-tile .medallion { background: var(--t, var(--accent)); color: #fff; width: 38px; height: 38px; }
.group-tile-text { display: flex; flex-direction: column; gap: .05rem; min-width: 0; }
.group-tile-name { font-family: var(--serif); font-weight: 600; font-size: 1.1rem; color: var(--ink); }
.group-tile-count { color: var(--muted); font-size: .8rem; }
.group-tile-go { margin-left: auto; color: var(--t, var(--accent)); font-weight: 700; font-size: 1.1rem; }
.back { color: var(--accent); text-decoration: none; font-size: .9rem; font-weight: 600; }
.back:hover { text-decoration: underline; }

/* ---- agent boxes (Agents page) ----------------------------------------------- */
.agent-tiles { display: grid; gap: .9rem; grid-template-columns: repeat(auto-fill, minmax(19rem, 1fr)); margin: 1rem 0; }
.agent-tile {
  display: flex; align-items: center; gap: .9rem; text-decoration: none;
  background: var(--t-soft, var(--surface));
  border: 1px solid color-mix(in srgb, var(--t, var(--accent)) 22%, var(--line));
  border-radius: var(--radius); padding: .9rem 1.05rem; box-shadow: var(--shadow);
  transition: transform .12s, box-shadow .12s, border-color .12s; color: var(--ink);
}
.agent-tile:hover { transform: translateY(-2px); border-color: var(--t, var(--accent)); box-shadow: 0 6px 20px rgba(112, 72, 232, .18); }
.agent-tile .medallion { background: var(--t, var(--accent)); color: #fff; width: 38px; height: 38px; }
.agent-tile-text { display: flex; flex-direction: column; gap: .1rem; min-width: 0; }
.agent-tile-name { font-family: var(--serif); font-weight: 600; font-size: 1.05rem; }
.agent-tile-sub { color: var(--muted); font-size: .78rem; }
.agent-tile-sub code { background: transparent; padding: 0; color: var(--muted); }
.agent-tile-meta { color: var(--muted); font-size: .78rem; display: flex; align-items: center; gap: .35rem; flex-wrap: wrap; }

/* ---- landing-page group boxes ----------------------------------------------- */
.group-box {
  background: var(--surface-2);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 1.1rem 1.25rem 1.25rem;
  margin: 1.1rem 0;
}
.group-box .grid { margin-top: .35rem; }
.group-title {
  margin: 0 0 .7rem;
  font-family: var(--serif); font-weight: 600; font-size: 1.15rem;
  color: var(--accent-strong);
  display: flex; align-items: center; gap: .55rem;
}
.group-title::before {
  content: ""; width: 9px; height: 9px; border-radius: 99px; flex: none;
  background: linear-gradient(135deg, var(--accent), var(--super));
}

/* ---- cards & layout --------------------------------------------------------- */
.card { background: var(--surface); border: 1px solid var(--line); border-radius: var(--radius); padding: 1.35rem 1.5rem; box-shadow: var(--shadow); }
.card.centered { max-width: 26rem; width: 100%; margin: 0 auto; padding: 2rem; }

/* THE LOGIN LOGO HAD NO SIZE RULE ANYWHERE. It rendered at its natural
   378x520, and 520px of logo made the sign-in card 942px tall on a 844px
   phone — so the card did not fit the screen and the buttons were pushed
   below the fold. Capped by width; the height follows the aspect ratio. */
.signin-logo { display: block; width: 55%; max-width: 150px; height: auto; margin: 0 auto .75rem; }
/* NOT :is(table) — a CSS grid container and a table are different things wearing
   one class name, and the table loses.
   The scheduling sheets are <table class="grid">, and this rule turned them into
   CSS grids: thead and tbody became independent blocks with their own widths, so
   the headings stopped lining up with the columns underneath and drifted further
   apart the wider the sheet got. It looked like a scrolling bug and was not.
   Found 2026-07-31 by measuring where a heading sat against its own column —
   they were over a thousand pixels apart. The messaging repo's CLAUDE.md warns
   about this exact collision; the portal had it on its own page. */
.grid:not(table) { display: grid; gap: 1rem; grid-template-columns: repeat(auto-fill, minmax(15rem, 1fr)); }
.row { display: flex; gap: .75rem; align-items: flex-end; flex-wrap: wrap; margin: 1rem 0; }
.stack { display: flex; flex-direction: column; gap: 1rem; }
.inline { display: inline-flex; gap: .5rem; align-items: center; margin: 0; }

/* ---- forms ------------------------------------------------------------------ */
label { display: block; font-size: .8rem; color: var(--muted); font-weight: 600; margin-bottom: .25rem; }
input, select {
  font: inherit; padding: .5rem .65rem; border: 1px solid var(--line);
  border-radius: 9px; background: var(--surface); color: var(--ink);
}
input:focus, select:focus { outline: 2px solid var(--accent); outline-offset: 1px; border-color: var(--accent); }
input[type="search"], input[type="text"], input[type="email"] { min-width: 15rem; }

button, .button {
  font: inherit; font-weight: 600; padding: .5rem 1.05rem; border: 1px solid var(--accent);
  border-radius: 9px; background: var(--accent); color: var(--on-accent);
  cursor: pointer; text-decoration: none; display: inline-block; transition: filter .12s, box-shadow .12s;
  box-shadow: 0 2px 8px rgba(124, 92, 230, .28);
}
button:hover, .button:hover { filter: brightness(1.06); box-shadow: 0 4px 14px rgba(124, 92, 230, .34); }
button:focus-visible, .button:focus-visible { outline: 2px solid var(--accent-strong); outline-offset: 2px; }
button.danger { background: var(--danger); border-color: var(--danger); box-shadow: none; color: #fff; }
button.link { background: none; border: none; color: var(--accent); padding: 0; text-decoration: underline; box-shadow: none; font-weight: 500; }

/* ---- pills & status --------------------------------------------------------- */
.pill { display: inline-flex; align-items: center; gap: 5px; font-size: .72rem; font-weight: 700; padding: .15rem .55rem; border-radius: 999px; background: var(--surface-2); color: var(--muted); }
.pill.active { background: var(--ok-soft); color: var(--ok); }
.pill.invited { background: var(--warn-soft); color: var(--warn); }
.pill.suspended, .pill.retired { background: var(--danger-soft); color: var(--danger); }
.pill.super { background: var(--super-soft); color: var(--super); }
.pill.scope-self { background: var(--ok-soft); color: var(--ok); }
.pill.scope-team { background: var(--warn-soft); color: var(--warn); }
.pill.scope-all { background: var(--accent-soft); color: var(--accent-strong); }

/* The × that removes a title from a person, inside its own tiny form so the
   removal is a POST like every other change. Looks like part of the pill. */
.linkish { background: none; border: 0; padding: 0 0 0 2px; margin: 0; cursor: pointer; color: inherit; font: inherit; line-height: 1; opacity: .65; }
.linkish:hover { opacity: 1; color: var(--danger); }

.banner { background: var(--gold-soft); border: 1px solid color-mix(in srgb, var(--gold) 35%, var(--line)); border-radius: 10px; padding: .8rem 1.05rem; color: var(--ink); }
.banner strong { color: var(--gold); }
.flash { padding: .8rem 1.05rem; border-radius: 10px; }
.flash.error { background: var(--danger-soft); border: 1px solid color-mix(in srgb, var(--danger) 40%, var(--line)); color: var(--danger); }

/* ---- utilities -------------------------------------------------------------- */
.muted { color: var(--muted); }
.small { font-size: .875rem; }
.dim { opacity: .55; }
ul.tight { margin: .5rem 0; padding-left: 1.1rem; }
ul.tight li { margin: .15rem 0; }

/* ---- HR Files drill-down (big tiles, person list, doc rows) ------------------- */
.bigtiles { display: grid; gap: 14px; grid-template-columns: repeat(auto-fill, minmax(240px, 1fr)); margin: 14px 0; }
.bigtiles.two-up { grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); }
.bigtile {
  display: flex; align-items: center; gap: 1rem; flex-wrap: wrap; text-decoration: none; color: var(--ink);
  background: var(--t-soft, var(--surface-2));
  border: 1px solid color-mix(in srgb, var(--t, var(--accent)) 22%, var(--line));
  border-radius: var(--radius); padding: 1.1rem 1.2rem; box-shadow: var(--shadow);
}
a.bigtile { transition: transform .12s, border-color .12s; }
a.bigtile:hover { transform: translateY(-2px); border-color: var(--t, var(--accent)); }
.bigtile .medallion { background: var(--t, var(--accent)); color: #fff; }
/* The status pill sits AFTER the text, never across it — at narrow widths it
   drops to its own line instead of overlapping the name. */
.bigtile .tx { display: flex; flex-direction: column; gap: .05rem; min-width: 0; flex: 1 1 8rem; }
.bigtile .att { margin-left: auto; }
.bigtile .nm { font-family: var(--serif); font-weight: 600; font-size: 1.15rem; }
.bigtile .ct { color: var(--muted); font-size: .8rem; }
.bigtile .go { margin-left: auto; color: var(--t, var(--accent)); font-weight: 700; font-size: 1.1rem; }
.att { display: inline-flex; align-items: center; gap: 4px; font-size: .7rem; font-weight: 800; color: var(--danger); background: var(--danger-soft); border-radius: 999px; padding: 1px 8px; white-space: nowrap; }
.att.warn { color: var(--warn); background: var(--warn-soft); }
.att.ok { color: var(--ok); background: var(--ok-soft); }
.crumb { color: var(--muted); font-size: .82rem; margin-bottom: 4px; }
.plist { display: flex; flex-direction: column; gap: .55rem; max-width: 40rem; margin-top: 12px; }
.prow {
  display: flex; align-items: center; gap: .85rem; text-decoration: none; color: var(--ink);
  background: var(--t-soft, var(--surface-2));
  border: 1px solid color-mix(in srgb, var(--t, var(--accent)) 20%, var(--line));
  border-radius: 11px; padding: .65rem .95rem; box-shadow: var(--shadow);
  transition: transform .12s, border-color .12s;
}
.prow:hover { transform: translateY(-1px); border-color: var(--t, var(--accent)); }
.prow .medallion { width: 32px; height: 32px; font-size: 12px; background: var(--t, var(--accent)); color: #fff; }
.prow .grow { flex: 1; display: flex; flex-direction: column; gap: .02rem; min-width: 0; }
.prow .nm { font-weight: 600; font-size: .95rem; }
.prow .sub { color: var(--muted); font-size: .75rem; }
.prow .go { color: var(--t, var(--accent)); font-weight: 700; }
.doclist { background: var(--surface); border: 1px solid var(--line); border-radius: 12px; box-shadow: var(--shadow); overflow: hidden; margin-top: 10px; }
.docrow { display: flex; align-items: center; gap: 10px; padding: .65rem .9rem; border-bottom: 1px solid var(--line); font-size: .86rem; flex-wrap: wrap; }
.docrow:last-child { border-bottom: none; }
.docrow b { flex: 1; min-width: 10rem; }
.docrow .dt { color: var(--muted); font-size: .76rem; }
.viewlink { font-size: .74rem; font-weight: 700; color: var(--accent-strong); border: 1px solid var(--line); background: var(--surface-2); border-radius: 7px; padding: .22rem .6rem; text-decoration: none; }
.auto { font-size: .72rem; font-weight: 700; color: var(--muted); background: var(--surface-2); border: 1px dashed var(--line); border-radius: 7px; padding: .22rem .6rem; }

/* ---- HR dashboard -------------------------------------------------------------- */
.tiles5 { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 12px; margin: 0 0 18px; }
.tile { background: var(--surface); border: 1px solid var(--line); border-radius: 12px; padding: 14px 16px; box-shadow: var(--shadow); }
.tile .k { font-size: .72rem; color: var(--muted); font-weight: 800; letter-spacing: .04em; }
.tile .v { font-size: 1.7rem; font-weight: 700; margin-top: 2px; font-variant-numeric: tabular-nums; }
.tile .d { font-size: .72rem; color: var(--faint); }
.tile.ok .v { color: var(--ok); } .tile.warn .v { color: var(--warn); } .tile.bad .v { color: var(--danger); }
.panel { background: var(--surface); border: 1px solid var(--line); border-radius: 14px; box-shadow: var(--shadow); padding: 18px 20px; margin-bottom: 16px; }
.panel h2 { margin: 0 0 4px; font-size: 1.05rem; }
.panel .sub { color: var(--muted); font-size: .8rem; margin: 0 0 12px; }
.legend { display: flex; gap: 14px; flex-wrap: wrap; font-size: .74rem; color: var(--muted); margin-top: 10px; }
.legend span { display: inline-flex; align-items: center; gap: 5px; font-weight: 600; }
.sw { width: 11px; height: 11px; border-radius: 3px; display: inline-block; }
.crow { display: flex; align-items: center; gap: 12px; margin: 7px 0; }
.cl { width: 110px; font-size: .82rem; font-weight: 600; text-align: right; }
.cbar { flex: 1; display: flex; gap: 2px; height: 16px; border-radius: 5px; overflow: hidden; background: var(--surface-2); }
.cbar span { display: block; height: 100%; }
.cv { width: 130px; font-size: .75rem; color: var(--muted); font-variant-numeric: tabular-nums; }
.brow { display: flex; align-items: center; gap: 10px; margin: 8px 0; }
.bl { width: 210px; font-size: .8rem; text-align: right; }
.btrack { flex: 1; height: 14px; background: var(--surface-2); border-radius: 5px; overflow: hidden; }
.bfill { display: block; height: 100%; background: var(--accent); border-radius: 0 4px 4px 0; }
.bv { width: 34px; font-size: .8rem; font-weight: 700; font-variant-numeric: tabular-nums; }
.drow { display: flex; align-items: center; gap: 10px; padding: .5rem .2rem; border-bottom: 1px solid var(--line); font-size: .84rem; }
.drow:last-child { border-bottom: none; }
.two { display: grid; grid-template-columns: 1.2fr .8fr; gap: 16px; }
@media (max-width: 800px) { .two { grid-template-columns: 1fr; } .cl { width: 80px; } .bl { width: 140px; } }

/* ---- HR side-by-side review ----------------------------------------------------- */
.review { display: grid; grid-template-columns: 270px 1fr; gap: 14px; margin-top: 10px; }

.review-list { display: flex; flex-direction: column; gap: 7px; max-height: 80vh; overflow-y: auto; padding-right: 2px; }
.docbox { display: flex; flex-direction: column; gap: 1px; text-decoration: none; border-radius: 10px;
  padding: .55rem .8rem; border: 1.5px solid transparent; }
.docbox .nm { font-weight: 600; font-size: .84rem; color: var(--ink); }
.docbox .dt { font-size: .72rem; color: var(--muted); }
.docbox.ok { background: var(--ok-soft); }
.docbox.warn { background: var(--warn-soft); }
.docbox.bad { background: var(--danger-soft); }
.docbox.na { background: var(--surface-2); }
.docbox:hover { border-color: var(--accent); }
.docbox.sel { border-color: var(--accent); box-shadow: 0 2px 10px rgba(112,72,232,.18); }
.review-pane { background: var(--surface); border: 1px solid var(--line); border-radius: var(--radius);
  box-shadow: var(--shadow); padding: 14px 16px; min-height: 60vh; }
.review-head { display: flex; align-items: center; gap: 10px; margin-bottom: 10px; flex-wrap: wrap; }
.review-frame { width: 100%; height: 72vh; border: 1px solid var(--line); border-radius: 10px; background: #fff; }
@media (max-width: 820px) { .review { grid-template-columns: 1fr; } .review-list { max-height: 34vh; } }

/* ---- document processing drop zone --------------------------------------------- */
.dropzone { background: var(--surface-2); border: 2.5px dashed var(--faint); border-radius: 16px;
  padding: 2.2rem 1rem; text-align: center; margin: 6px 0 22px; transition: border-color .15s, background .15s; }
.dropzone.over { border-color: var(--accent); background: var(--accent-soft); }
.dz-inner { display: flex; flex-direction: column; align-items: center; gap: .45rem; }
.dz-icon { font-size: 26px; color: var(--faint); }

/* ---- permission grid ---------------------------------------------------------- */
.pg-wrap { overflow-x: auto; border: 1px solid var(--line); border-radius: var(--radius); box-shadow: var(--shadow); background: var(--surface); }
table.pg { border: none; box-shadow: none; border-radius: 0; min-width: 720px; }
table.pg th.permit-col { min-width: 230px; }
table.pg th.lvl { text-align: center; font-size: .78rem; text-transform: none; letter-spacing: 0; color: var(--ink); padding: .7rem .5rem; }
table.pg th.lvl a { color: var(--ink); text-decoration: none; }
table.pg th.lvl a:hover { color: var(--accent); }
table.pg th.lvl small { display: block; font-size: .62rem; color: var(--faint); font-weight: 600; }
table.pg td.cell { text-align: center; vertical-align: middle; }
table.pg td.permit { font-weight: 600; font-size: .88rem; }
table.pg td.permit small { display: block; font-weight: 400; color: var(--faint); font-size: .72rem; }
table.pg td.permit small code { background: transparent; padding: 0; color: var(--faint); }
.cb {
  width: 22px; height: 22px; border-radius: 6px; border: 1.8px solid var(--line);
  background: var(--surface); display: inline-grid; place-items: center;
  color: transparent; font-size: 13px; font-weight: 800; vertical-align: middle;
  padding: 0; cursor: pointer; box-shadow: none; transition: border-color .12s, background .12s;
}
.cb:hover { border-color: var(--accent); filter: none; box-shadow: none; }
.cb.on { background: var(--accent); border-color: var(--accent); color: #fff; }
.cb.lock { background: var(--super-soft); border-color: transparent; color: var(--super); cursor: default; }
span.cb { cursor: default; }

footer { padding: 1.5rem 26px 2.5rem; color: var(--faint); font-size: .8rem; }

/* ---- responsive ------------------------------------------------------------- */
/* PHONE AND IPAD the menu is a DRAWER, not a strip.

   The breakpoint is 900px, and it is 900 rather than 820 because an iPad in
   PORTRAIT is 834pt wide: at 820 it fell on the desktop side and got a 232px
   sidebar eating a quarter of the screen. Landscape iPads are 1024pt and up, so
   they still get the full sidebar, which is right — there is room for it.

   **nav.js matches on the same 900px.** If these two ever disagree, the range
   between them shows the drawer in CSS while the script believes it is on a
   desktop, so it never collapses and sits open across the page.
   It used to lie across the top and scroll sideways, which put most of the menu
   past the edge of the screen — "Messages" showed as "Mess…" and Teams, Audit
   and the rest were simply not findable. A drawer shows the whole menu at once
   and gives the page back its full width. `nav.js` opens and shuts it with the
   ☰ button that was already there, and shuts it on a tap outside or on a link. */
@media (max-width: 900px) {
  .app { grid-template-columns: 1fr; }

  .sidebar {
    position: fixed; inset: 0 auto 0 0; z-index: 40;
    width: min(78vw, 300px); height: 100dvh; overflow-y: auto;
    flex-direction: column; align-items: stretch; gap: 2px;
    padding: 14px 12px; border-right: 1px solid var(--line); border-bottom: none;
    box-shadow: 0 0 40px rgba(40, 20, 80, .28);
    transform: translateX(0); transition: transform .18s ease;
  }
  /* Shut: slid off to the left rather than display:none, so it can animate and
     so its links stay reachable to a screen reader's own navigation. */
  .app.nav-collapsed .sidebar { display: flex; transform: translateX(-102%); }

  .sidebar nav { flex-direction: column; gap: 2px; }
  .sidebar nav a { white-space: nowrap; padding: 12px 12px; }   /* 44px tap target */

  .env-band { position: relative; z-index: 41; }
  main { padding: 16px; }

  /* A table is the one thing that will not fit. Let it scroll inside its own
     box; the page itself must never move sideways, or every heading and button
     drifts off-screen with it. */
  main table { display: block; overflow-x: auto; max-width: 100%; }
  body { overflow-x: hidden; }

  /* Anything tappable gets a finger-sized target. */
  .topbar button, .topbar .nav-toggle, .avatar-menu summary { min-height: 44px; min-width: 44px; }
}

/* The page behind the open drawer, dimmed — so it reads as "the menu is over
   the page" rather than "the page has gone wrong". */
@media (max-width: 900px) {
  /* NOT on app--plain. That is the signed-out layout: no sidebar, no drawer,
     so nav.js never sets nav-collapsed and this dimmer sat over the login page
     permanently — 38% opaque, which reads as a grey tint, and above everything,
     which meant no tap ever reached the Google button. Reported 2026-07-29 as
     "Google nothing happen"; a real browser named it in one line:
     "<div class=\"main\"> intercepts pointer events". curl could never have
     seen it, because the HTML was correct the whole time. */
  .app:not(.nav-collapsed):not(.app--plain) .main::before {
    content: ""; position: fixed; inset: 0; z-index: 39;
    background: rgba(30, 16, 60, .38);
  }
}
@media (prefers-reduced-motion: reduce) { * { transition: none !important; } }


/* ---- people: profile form, per-person grid, employee page ---------------------- */
.person-form h3 { margin: 4px 0 0; font-size: .82rem; text-transform: uppercase;
  letter-spacing: .06em; color: var(--muted); }
.field-row { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; }
@media (max-width: 640px) { .field-row { grid-template-columns: 1fr; } }
label .hint { font-weight: 400; color: var(--faint); text-transform: none;
  letter-spacing: 0; font-size: .72rem; }
label.check { display: flex; align-items: flex-start; gap: 10px; background: var(--surface-2);
  border: 1px solid var(--line); border-radius: 10px; padding: .7rem .85rem; }
label.check input { width: 18px; height: 18px; margin-top: 1px; accent-color: var(--accent); }
label.check span { display: block; font-weight: 400; }
label.check small { display: block; color: var(--muted); font-size: .76rem; margin-top: 2px; }

.pill.emp { background: var(--gold-soft); color: var(--gold); }
.pill.direct { background: var(--accent-soft); color: var(--accent-strong); }

table.pg.person-grid { min-width: 860px; }
/* the levels this person actually holds, so their role reads at a glance */
table.pg.person-grid th.lvl.theirs, table.pg.person-grid td.cell.theirs { background: var(--accent-soft); }
table.pg.person-grid th.lvl.theirs small { color: var(--accent-strong); font-weight: 800; }
/* the person's own column — the only one that changes here */
table.pg.person-grid th.lvl.person, table.pg.person-grid td.cell.person {
  background: var(--surface-2); border-left: 2px solid var(--accent); }
table.pg.person-grid th.lvl.person { color: var(--accent-strong); }
table.pg.person-grid td.cell.person .cb.exc { border-color: var(--gold); border-width: 2.5px; }
table.pg.person-grid td.cell.person .cb.on.exc { background: var(--accent); border-color: var(--gold); }
table.pg.person-grid tr.grp td { background: var(--surface-2); font-weight: 800;
  font-size: .74rem; text-transform: uppercase; letter-spacing: .05em; color: var(--muted); }
table.pg td.cell small.src { display: block; font-size: .66rem; color: var(--faint);
  margin-top: 3px; font-weight: 600; }
table.pg td.cell.ticks { white-space: nowrap; }


.me-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; align-items: start; }
@media (max-width: 860px) { .me-grid { grid-template-columns: 1fr; } }
.me-grid .card h2 { margin-top: 0; font-size: 1rem; }
.me-grid .dropzone { padding: 1.1rem; }

.me-docs { display: grid; grid-template-columns: repeat(auto-fill, minmax(230px, 1fr));
  gap: 10px; margin-top: 10px; }
.me-docs .docbox { border: 1.5px solid var(--line); gap: 3px; padding: .7rem .9rem; }
.me-docs .docbox strong { font-size: .88rem; }
.me-docs .docbox span { font-size: .76rem; color: var(--muted); }

.key { display: flex; gap: 14px; flex-wrap: wrap; color: var(--muted); margin-top: 10px;
  align-items: center; }
.key .dot { width: 11px; height: 11px; border-radius: 3px; display: inline-block; margin-right: 2px; }
.key .dot.ok { background: var(--ok); } .key .dot.warn { background: var(--warn); }
.key .dot.bad { background: var(--danger); } .key .dot.na { background: var(--faint); }
.key .dot.lv { background: var(--accent-soft); border: 1px solid var(--accent); }
.key .dot.exc { background: var(--surface); border: 2px solid var(--gold); }

ul.plain { list-style: none; padding: 0; margin: 8px 0 0; }
ul.plain li { display: flex; align-items: center; gap: 8px; padding: .4rem 0;
  border-bottom: 1px solid var(--line); flex-wrap: wrap; }
ul.plain li:last-child { border-bottom: none; }

/* landing-page groups that hold no agents yet (administrators only) */
.group-tile.coming { opacity: .62; border-style: dashed; }
.group-tile.coming .group-tile-count { font-style: italic; }

/* ---- HR settings + chart drawers ------------------------------------------------ */
.setlist { display: flex; flex-direction: column; gap: 7px; margin: 10px 0 6px; }
.setrow { display: flex; align-items: center; gap: 9px; flex-wrap: wrap;
  background: var(--surface); border: 1px solid var(--line); border-radius: 10px;
  padding: .5rem .7rem; box-shadow: var(--shadow); }
.setrow.off { opacity: .55; border-style: dashed; }
.setrow input[type=text] { min-width: 12rem; flex: 1; }
.setrow.wide { gap: 7px; }
.setrow.wide input[type=text] { min-width: 10rem; }
.setrow.wide select { max-width: 11rem; }
.setrow label.small { display: flex; align-items: center; gap: 5px; margin: 0; white-space: nowrap; }
.setrow button { flex: 0 0 auto; }
/* Keep the row on one line where there is space; wrap gracefully where there is not. */
@media (min-width: 1100px) { .setrow.wide { flex-wrap: nowrap; } }

.drawer { background: var(--surface); border: 1px solid var(--line); border-radius: 12px;
  box-shadow: var(--shadow); margin: 8px 0; overflow: hidden; }
.drawer > summary { cursor: pointer; list-style: none; display: flex; align-items: center;
  gap: 10px; padding: .7rem .9rem; font-weight: 600; }
.drawer > summary::-webkit-details-marker { display: none; }
.drawer > summary::before { content: '▸'; color: var(--faint); font-size: .8rem; }
.drawer[open] > summary::before { content: '▾'; }
.drawer[open] > summary { border-bottom: 1px solid var(--line); }
.drawer > summary:hover { background: var(--surface-2); }
.drawer .dw-name { flex: 1; }
.drawer .dw-ct { color: var(--muted); font-size: .78rem; font-weight: 500; }
.drawer .doclist { border: none; box-shadow: none; border-radius: 0; margin: 0; }

/* ---- messaging ------------------------------------------------------------------ */
.sidebar nav .badge { display: inline-grid; place-items: center; min-width: 18px; height: 18px;
  padding: 0 5px; margin-left: 7px; border-radius: 999px; background: var(--accent);
  color: #fff; font-size: .68rem; font-weight: 800; }
.msg-layout { grid-template-columns: 1.4fr .6fr; align-items: start; }
@media (max-width: 900px) { .msg-layout { grid-template-columns: 1fr; } }

.convlist { display: flex; flex-direction: column; gap: 8px; }
.convrow { display: flex; flex-direction: column; gap: 3px; text-decoration: none; color: var(--ink);
  background: var(--surface); border: 1px solid var(--line); border-radius: 12px;
  padding: .75rem .9rem; box-shadow: var(--shadow); }
.convrow:hover { border-color: var(--accent); }
.convrow.new { border-left: 3px solid var(--accent); }
.cv-top { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.cv-subject { font-weight: 700; }
.cv-meta { color: var(--muted); font-size: .74rem; }
.cv-last { color: var(--faint); font-size: .8rem; }

.thread { display: flex; flex-direction: column; gap: 9px; max-height: 62vh; overflow-y: auto;
  padding: 4px 2px 8px; }
.bubble { background: var(--surface); border: 1px solid var(--line); border-radius: 12px;
  padding: .6rem .85rem; box-shadow: var(--shadow); max-width: 85%; }
.bubble.mine { background: var(--accent-soft); border-color: transparent; align-self: flex-end; }
.bub-head { display: flex; align-items: baseline; gap: 8px; margin-bottom: 2px; }
.bub-head strong { font-size: .82rem; }
.bub-body { white-space: pre-wrap; font-size: .9rem; line-height: 1.45; }
.sendbox textarea { width: 100%; font: inherit; padding: .6rem .7rem; border-radius: 10px;
  border: 1px solid var(--line); background: var(--surface); color: var(--ink); resize: vertical; }
.sendbox { margin-top: 10px; }
/* visually hidden, still read aloud */
.vh { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }

/* ---- take a photo --------------------------------------------------------------- */
.shot { display: block; cursor: pointer; }
.shot input[type=file] { position: absolute; width: 1px; height: 1px; opacity: 0; }
.shot-face { display: flex; flex-direction: column; align-items: center; gap: 3px;
  background: var(--accent-soft); border: 2.5px dashed var(--accent); border-radius: 16px;
  padding: 1.4rem 1rem; text-align: center; }
.shot-face strong { color: var(--accent-strong); }
.shot-face small { color: var(--muted); font-size: .78rem; }
.shot input:focus-visible + .shot-face { outline: 3px solid var(--accent); outline-offset: 2px; }
.shot:hover .shot-face { background: var(--surface-2); }

/* Messages: its own box on the landing page, not inside a group. */
.group-tile.msg-tile { background: var(--gold-soft); border-color: color-mix(in srgb, var(--gold) 35%, var(--line)); }
.group-tile.msg-tile .medallion { background: var(--gold); }
.group-tile.msg-tile .group-tile-go { color: var(--gold); }

/* ---- agent launcher ------------------------------------------------------------ */
/* An agent's box on a group page. The Open button is the point of the page, so it
   gets the weight; the function keys fold away behind a summary. */
.card.launch h3 { margin: 0 0 .2rem; font-family: var(--serif); font-weight: 600; }
.card.launch .button { margin-top: .2rem; }
.card.launch details { margin-top: .7rem; }
.card.launch details summary { cursor: pointer; }
.card.launch details ul { margin-top: .4rem; }

/* ---- frozen panes ------------------------------------------------------------
   Dr. Katz, 2026-07-27: "freeze the panel with roles, so when I scroll down I
   know which function belongs to which role."

   A permission grid is unreadable the moment the column headings scroll away:
   six near-identical columns of ticks, and no way to tell Supervisor from Field
   user without scrolling back up. The same is true sideways — the function name
   is the only thing that says WHAT a tick means.

   So both are pinned: the heading row while scrolling down, the function column
   while scrolling across. Which needs the grid to do its own scrolling rather
   than the page, because `sticky` pins to the nearest scrolling ancestor and the
   wrapper already scrolls horizontally — the height cap is what makes the
   vertical pin engage at all, not a cosmetic choice.

   Sticky cells must be opaque. A transparent one lets the rows underneath show
   through as they pass, which reads as a rendering fault. */
.pg-wrap, .grid-wrap { max-height: calc(100vh - 13rem); overflow: auto; }

/* THE ONE THAT MATTERS. The base `table` rule sets `overflow: hidden` to clip its
   own rounded corners — and that quietly makes every table its own scroll
   container. `sticky` pins to the nearest scrolling ancestor, so the heading was
   pinning to a table that never scrolls: the CSS was correct and did nothing.
   These tables live in a wrapper that draws the border and corners, so they have
   no corners of their own to clip and can give the overflow back. */
table.pg, table.grid { overflow: visible; }

table.pg thead th, table.grid thead th { position: sticky; top: 0; z-index: 3; }

/* `border-collapse: collapse` hands ownership of a border to the table, not the
   cell, so the heading's bottom border stays behind when the heading moves. A
   shadow belongs to the cell and travels with it. */
table.pg thead th, table.grid thead th { box-shadow: 0 1px 0 var(--line); }

table.pg th.permit-col, table.pg td.permit,
table.grid thead th:first-child, table.grid tbody td:first-child {
  position: sticky; left: 0; z-index: 2; background: var(--surface);
}
/* The corner belongs to both frozen edges, so it outranks each of them. */
table.pg th.permit-col, table.grid thead th:first-child { z-index: 4; background: var(--surface-2); }

/* Keep the pinned cells in step with the row they belong to. */
table.pg tbody tr:hover td.permit { background: var(--accent-soft); }
table.pg tr.grp td.permit { background: var(--surface-2); }
table.grid tbody tr:hover td:first-child { background: var(--accent-soft); }
table.grid tr.grid-new td:first-child { background: var(--surface-2); }

/* A shadow on the inside edge, so a frozen column reads as pinned rather than as
   a column that happens to be there while everything else slides under it. The
   corner cell is on both frozen edges and needs both shadows, or the heading's
   underline stops short exactly where the eye follows it. */
table.pg td.permit, table.grid tbody td:first-child { box-shadow: 1px 0 0 var(--line); }
table.pg th.permit-col, table.grid thead th:first-child {
  box-shadow: 1px 0 0 var(--line), 0 1px 0 var(--line);
}

/* Role detail scrolls with the page — no wrapper — so its heading pins to the
   viewport instead. The top bar is sticky at 0 and 56px tall, so the heading has
   to sit below it or it slides underneath and disappears. */
/* 36px avatar + 12px padding top and bottom + a 1px border. Named rather than
   typed as a number in two places, so moving the bar cannot leave a heading
   floating in the wrong spot on one page only. */
:root { --topbar-h: 61px; }

table.role-perms { overflow: visible; }
.role-perms thead th {
  position: sticky; top: var(--topbar-h); z-index: 2;
  background: var(--surface-2); box-shadow: 0 1px 0 var(--line);
}

/* The drop box, while a file is over it. Without this the zone gives no sign it
   will accept anything, so people aim at it and hope. */
/* "Take a photo" — a real button, sized for a thumb. Kept small on a computer,
   where it is the less useful of the two controls, and full width on a phone,
   where it is the more useful one. */
.camera-form { margin: -4px 0 14px; }
.camera-btn { display: inline-block; cursor: pointer; }
.camera-btn input[type=file] { position: absolute; width: 1px; height: 1px; opacity: 0; }
.camera-btn span {
  display: inline-flex; align-items: center; justify-content: center; gap: .4rem;
  min-height: 44px; padding: .6rem 1rem; border-radius: 10px;
  background: var(--surface); border: 1px solid var(--line); color: var(--accent-strong);
  font-weight: 600; font-size: .9rem; box-shadow: var(--shadow);
}
.camera-btn:hover span { border-color: var(--accent); background: var(--accent-soft); }
.camera-btn input:focus-visible + span { outline: 3px solid var(--accent); outline-offset: 2px; }
@media (max-width: 900px) {
  .camera-btn, .camera-btn span { display: flex; width: 100%; }
}

.shot.is-over .shot-face { background: var(--accent); border-style: solid; border-color: var(--accent-strong); }
.shot.is-over .shot-face strong, .shot.is-over .shot-face small { color: #fff; }

/* The payroll build, while it is happening. A striped bar that also MOVES, so a
   stage that sits at 42% for four minutes still shows something alive — the
   percentage is honest about position, the motion is honest about "not dead". */
.build { border: 1px solid var(--line); border-radius: var(--radius); background: var(--surface);
  box-shadow: var(--shadow); padding: 1rem 1.1rem; margin: 0 0 1.2rem; }
.build-top { display: flex; align-items: baseline; justify-content: space-between; margin-bottom: .5rem; }
.build .bar { height: 12px; border-radius: 999px; background: var(--surface-2); overflow: hidden; }
.build .bar span {
  display: block; height: 100%; border-radius: 999px;
  background-color: var(--accent);
  background-image: linear-gradient(115deg, rgba(255,255,255,.35) 25%, transparent 25%,
    transparent 50%, rgba(255,255,255,.35) 50%, rgba(255,255,255,.35) 75%, transparent 75%);
  background-size: 28px 28px;
  animation: build-move 1s linear infinite;
  transition: width .4s ease;
}
@keyframes build-move { to { background-position: 28px 0; } }
@media (prefers-reduced-motion: reduce) { .build .bar span { animation: none; } }
.build-step { margin: .55rem 0 .2rem; }

/* The Payroll tab, rebuilt as the portal's own table.
   Standalone on purpose — it does NOT use the `grid` class. The scheduling
   grids pin their first column (`position: sticky; left: 0`) and make each
   `th` sticky in its own right; inside this table's frozen `thead` that
   stacked sticky within sticky and slid the body columns out of line with the
   headings above them. Everything this table needs is therefore declared here.

   Widths, twice learned. Measured across the 103 rows, the MEDIAN cell is 2-8
   characters while a few header and note cells run 30, 41, even 153. Left on
   `nowrap` (as the other grids are), each of those single cells set the width
   of its whole column — the 153-character note alone made the employee column
   wide enough to scroll past, for names averaging 23 characters. Capping the
   columns fixed that and caused a worse one: with `overflow-wrap: anywhere` a
   long heading broke ONE LETTER PER LINE. So wrapping is left at the browser
   default, which breaks at spaces like prose, and the cap sits above the
   longest single word rather than the longest cell. */
table.pay-table {
  width: auto; min-width: 0; table-layout: auto;
  border-collapse: collapse; border: none; border-radius: 0;
  box-shadow: none; background: var(--surface);
  /* The base `table` rule sets `overflow: hidden` to clip its corners, which
     makes a table its own scroll container and silently kills every sticky
     heading inside it. This table has a wrapper for its corners. */
  overflow: visible;
}
table.pay-table td, table.pay-table th {
  padding: .3rem .55rem; font-size: .875rem; text-align: left;
  white-space: normal; max-width: 10rem; vertical-align: middle;
  border-right: 1px solid var(--line); border-bottom: 1px solid var(--line);
  text-transform: none; letter-spacing: 0; font-weight: 400; color: inherit;
}
table.pay-table td.pay-num, table.pay-table th.pay-num {
  text-align: right; font-variant-numeric: tabular-nums; white-space: nowrap; max-width: none;
}
table.pay-table td.pay-bold, table.pay-table th.pay-bold { font-weight: 700; }
/* The name column: room for the longest name, and no more. */
table.pay-table td:first-child, table.pay-table th:first-child { max-width: 14rem; min-width: 8rem; }
table.pay-table tbody tr:hover { background: var(--accent-soft); }

/* The header block stays put — pinned as one piece rather than row by row,
   because the rows' heights change as their text wraps and stacked offsets
   computed against a guessed height drift the moment they do. */
table.pay-table thead { position: sticky; top: 0; z-index: 3; }
table.pay-table thead th { background: var(--surface-2); }
/* A group label belongs over its columns, not against the first of them. */
table.pay-table th.pay-group { text-align: center; font-weight: 700; }
table.pay-table tr.pay-section td, table.pay-table tr.pay-section th {
  background: var(--surface-2); font-weight: 800; font-size: .8rem;
  letter-spacing: .03em; max-width: none; white-space: nowrap;
}

/* The one column somebody types into. Marked plainly so it is obvious which
   figures the pipeline produced and which a person entered — on a payroll that
   distinction matters more than it looks. */
table.pay-table td.pay-entry { padding: .15rem .25rem; background: var(--gold-soft); }
table.pay-table td.pay-entry input {
  /* `min-width: 0` matters as much as `width`: without it the input keeps the
     intrinsic width its `size` attribute implies, and an auto-layout table
     sizes the column from THAT rather than from the CSS. The `size` attribute
     on the element is what actually lets this column be narrow. */
  width: auto; min-width: 0; border: 1px solid var(--line); border-radius: 6px;
  background: var(--surface); padding: .2rem .35rem;
  font: inherit; font-variant-numeric: tabular-nums; text-align: right; color: inherit;
}
table.pay-table td.pay-entry input.entry-narrow { width: 3.6rem; }
table.pay-table td.pay-entry input.entry-wide { width: 8rem; text-align: left; }
table.pay-table td.pay-entry input:focus { outline: 2px solid var(--accent); outline-offset: -1px; }
table.pay-table td.pay-typed input { border-color: var(--gold); font-weight: 700; }
/* Settings-page inputs only. Scoped, because an unscoped rule here reached the
   run page and widened the ADP column straight back out. */
table.settings-table input[type="text"] {
  width: 7rem; border: 1px solid var(--line); border-radius: 6px;
  background: var(--surface); padding: .2rem .4rem; font: inherit; color: inherit;
}
table.settings-table input[type="text"].wide { width: 16rem; }
table.settings-table input[type="text"]:focus { outline: 2px solid var(--accent); outline-offset: -1px; }
table.settings-table td, table.settings-table th { max-width: none; }

/* A figure the page worked out rather than the workbook — typed Book mileage
   folded into the total. Marked because a pay figure that no longer matches the
   downloaded file must not look identical to one that does. */
table.pay-table td.pay-recomputed { background: var(--accent-soft); font-weight: 700; }
table.pay-table td.pay-recomputed::after { content: " *"; color: var(--accent); }

/* Roster rows that are not counted this period. */
table.settings-table tr.row-leave td { background: var(--warn-soft); }
table.settings-table tr.row-terminated td { background: var(--surface-2); color: var(--muted); }
table.settings-table select { border: 1px solid var(--line); border-radius: 6px;
  background: var(--surface); padding: .18rem .3rem; font: inherit; color: inherit; }

/* What the agent did with a dropped document, and how it decided. Stacked
   rather than one line: "identified from the file name" is the sentence that
   tells you whether to double-check it, and it must not be truncated away. */
.filed-row { border: 1px solid var(--line); border-radius: 10px; background: var(--surface);
  padding: .55rem .75rem; margin-bottom: .4rem; }
.filed-top { display: flex; align-items: center; gap: .5rem; }
.filed-row .muted { margin-top: .15rem; }

/* Why the agent stopped. Sits between the document's name and the form that
   settles it, because it is the reason the reader is being asked at all. */
.agent-said { background: var(--warn-soft); border-left: 3px solid var(--warn);
  border-radius: 8px; padding: .5rem .7rem; margin: .4rem 0 .7rem; font-size: .86rem; }
.agent-said strong { color: var(--warn); }
.agent-said a { margin-left: .5rem; white-space: nowrap; }
.remove-row { margin: -.6rem 0 1rem; }
.link.danger { color: var(--danger); }
.link.danger:hover { text-decoration: underline; }
.employment-row { align-items: center; gap: .8rem; flex-wrap: wrap; }
.employment-row form { align-items: center; gap: .4rem; }

/* Policies: two manuals on one page, kept visibly apart. */
h2.policy-section { border-bottom: 2px solid var(--accent); padding-bottom: .3rem;
  margin: 1.8rem 0 .6rem; color: var(--accent-strong); }
h2.policy-section .muted { font-weight: 400; margin-left: .5rem; }
.policy-chapter { margin: 0 0 1rem .4rem; }
.policy-chapter h3 { margin: .6rem 0 .3rem; font-size: 1rem; }

/* A policy as a box you can hit, not a line of underlined text among forty. */
.policy-boxes { display: grid; gap: .5rem; grid-template-columns: repeat(auto-fill, minmax(17rem, 1fr)); }
.policy-box { display: flex; align-items: center; gap: .6rem; text-decoration: none;
  background: var(--surface); border: 1px solid var(--line); border-radius: 10px;
  padding: .6rem .8rem; color: var(--ink); box-shadow: var(--shadow);
  transition: border-color .12s, background .12s; }
.policy-box:hover { border-color: var(--accent); background: var(--accent-soft); }
.policy-box .nm { flex: 1; font-weight: 600; font-size: .88rem; line-height: 1.3; }
.policy-box .go { color: var(--accent); font-weight: 700; }

/* Policies: the shelf, then the folders, then the documents. */
.manual-boxes { display: grid; gap: .8rem; grid-template-columns: repeat(auto-fit, minmax(20rem, 1fr)); margin: 1rem 0; }
.manual-box { display: flex; align-items: center; gap: .9rem; text-decoration: none;
  background: var(--surface); border: 1px solid var(--line); border-radius: var(--radius);
  padding: 1rem 1.1rem; color: var(--ink); box-shadow: var(--shadow);
  transition: border-color .12s, background .12s; }
.manual-box:hover { border-color: var(--accent); background: var(--accent-soft); }
.manual-box .tx { display: flex; flex-direction: column; gap: .1rem; flex: 1; min-width: 0; }
.manual-box .nm { font-family: var(--serif); font-size: 1.15rem; color: var(--accent-strong); }
.manual-box .ct { color: var(--muted); font-size: .82rem; }
.manual-box .go { color: var(--accent); font-weight: 700; font-size: 1.2rem; }

.policy-box.folder .fold { font-size: 1.1rem; }
.policy-box.folder .nm { display: flex; flex-direction: column; gap: .1rem; }

/* The pending-approval folder sits among the chapters and must not be mistaken
   for one: what is inside it is not policy yet. Dashed rather than solid, and
   using the warning colour the rest of the app uses for "needs attention". */
.policy-box.pending { border-style: dashed; border-color: var(--warn); background: var(--warn-soft); }
.policy-box.pending:hover { border-color: var(--warn); background: var(--warn-soft); }
.policy-box.pending .nm, .policy-box.pending .go { color: var(--warn); }

/* A draft awaiting approval — deliberately unlike a published policy. */
.draft-row { display: flex; align-items: center; gap: .8rem; flex-wrap: wrap;
  background: var(--warn-soft); border: 1px solid var(--warn); border-radius: 10px;
  padding: .6rem .85rem; margin-bottom: .5rem; }
.draft-row form { margin: 0; }

/* --- Messaging Center, and the mark that makes somebody look ----------------
   Dr. Katz, 2026-07-29: people have to be told something arrived, where they
   already are. The count comes from a fetch after load — see messaging.js —
   and is a NUMBER only: no sender, no subject, no patient ever reaches this
   page, because a portal screen is often on a desk somebody walks past.

   RED, AND PULSING ONLY WHEN URGENT. If everything blinks, nothing does; the
   rare thing has to look different from the ordinary one or the mark stops
   meaning anything within a week. Ordinary unread is a steady red count.       */
.group-tile .alert-dot, .sidebar nav .alert-dot {
  display: inline-grid; place-items: center; min-width: 18px; height: 18px;
  margin-left: .4rem; padding: 0 5px; border-radius: 9px;
  background: var(--danger, #D4436B); color: #fff;
  font-size: .68rem; font-weight: 700; line-height: 1; }
.group-tile.has-unread .group-tile-name { font-weight: 700; }

/* Urgency, which the owner chose to make loud. Opacity rather than colour, so
   it still reads on a screen that renders colour badly, and it stops on hover
   so somebody reading the number is not fighting it. */
@keyframes eladora-urgent-pulse {
  0%, 100% { opacity: 1; transform: scale(1); }
  50%      { opacity: .45; transform: scale(1.12); }
}
.group-tile.is-urgent .alert-dot, .sidebar nav .messaging-center.is-urgent .alert-dot {
  animation: eladora-urgent-pulse 1.1s ease-in-out infinite;
  box-shadow: 0 0 0 3px rgba(212, 67, 107, .22); }
.group-tile.is-urgent:hover .alert-dot { animation: none; }

/* A blinking red mark is exactly what some people cannot look at — migraine,
   vestibular conditions, and photosensitive epilepsy are all real in a
   workforce this size. They still get the red count; they do not get the
   motion. The information is in the number, never in the movement. */
@media (prefers-reduced-motion: reduce) {
  .group-tile.is-urgent .alert-dot, .sidebar nav .messaging-center.is-urgent .alert-dot { animation: none; }
}

/* The message mark in the topbar — on every page, because a message waiting is
   not something you should only learn by going back to the landing page. */
.msg-mark { position: relative; display: inline-grid; place-items: center;
  width: 34px; height: 34px; border-radius: 50%; text-decoration: none;
  background: var(--surface-2); border: 1px solid var(--line);
  color: var(--accent-strong); margin-right: .4rem; }
.msg-mark:hover { border-color: var(--accent); }
.msg-mark-icon { font-size: 15px; line-height: 1; }
.msg-mark .alert-dot { position: absolute; top: -3px; right: -3px;
  min-width: 16px; height: 16px; padding: 0 4px; border-radius: 8px;
  background: var(--danger, #D4436B); color: #fff; font-size: 10px;
  font-weight: 700; display: grid; place-items: center;
  border: 2px solid var(--surface-2); }

/* The envelope menu — on every page, in the topbar. Opens with <details>, so it
   works with no JavaScript and keyboards get it free. */
.msg-menu { position: relative; margin-right: .4rem; }
.msg-menu > summary { list-style: none; cursor: pointer; position: relative;
  display: inline-grid; place-items: center; width: 34px; height: 34px;
  border-radius: 50%; background: var(--surface-2); border: 1px solid var(--line);
  color: var(--accent-strong); }
.msg-menu > summary::-webkit-details-marker { display: none; }
.msg-menu > summary:hover { border-color: var(--accent); }
.msg-pop { position: absolute; right: 0; top: calc(100% + .4rem); width: 320px;
  background: var(--surface-2); border: 1px solid var(--line);
  border-radius: 12px; box-shadow: var(--shadow); z-index: 60; overflow: hidden; }
.msg-pop-head { padding: .5rem .8rem; background: var(--accent-soft);
  border-bottom: 1px solid var(--line); font-size: .78rem; font-weight: 600; }
.msg-pop-empty { padding: .9rem .8rem; margin: 0; color: var(--muted); font-size: .82rem; }
.msg-row { display: flex; gap: .55rem; align-items: flex-start; padding: .55rem .8rem;
  border-bottom: 1px solid var(--line); text-decoration: none; color: inherit; }
.msg-row:hover { background: var(--accent-soft); }
.msg-row-what { font-size: .84rem; display: block; }
.msg-row-detail { font-size: .74rem; color: var(--muted); display: block; }
.msg-row-go { margin-left: auto; color: var(--muted); }
.msg-pop-foot { display: block; padding: .5rem .8rem; text-align: center;
  font-size: .78rem; background: var(--surface-1); text-decoration: none; }
@media (max-width: 900px) { .msg-pop { width: min(84vw, 320px); } }

/* DrChrono rows on the Permission Grid.
 *
 * Two companies, two sets of obligations. A function governing the EHR should
 * not look identical to one governing hospice work — 2026-07-30.
 *
 * A tinted band and a coloured edge, NOT coloured text: the key and the
 * function name have to stay as readable as every other row, and colour alone
 * is never the only signal — the category is written in the row already, for
 * anybody who does not see the difference. */
tr.is-drchrono td.permit {
  border-left: 4px solid var(--drchrono-edge);
  background: var(--drchrono-tint);
}
tr.is-drchrono td { background: var(--drchrono-tint); }
:root {
  --drchrono-tint: #eef6fb;
  --drchrono-edge: #2b7fb8;
}
@media (prefers-color-scheme: dark) {
  :root { --drchrono-tint: #12222c; --drchrono-edge: #4aa3d6; }
}
:root[data-theme="dark"] { --drchrono-tint: #12222c; --drchrono-edge: #4aa3d6; }
:root[data-theme="light"] { --drchrono-tint: #eef6fb; --drchrono-edge: #2b7fb8; }

/* THE LOGO IS THE MAILBOX — Dr. Katz, 2026-07-31.
 *
 * The mark keeps its own look; what changes is that it opens the list of what is
 * waiting, and carries the red count. The brand NAME beside it still goes home,
 * because a logo that does not take you home is a small betrayal of every other
 * site somebody uses.
 *
 * ONE INDICATOR, NEVER TWO. He removed a duplicate dot on 2026-07-30 for exactly
 * the right reason — two marks for one fact have to agree, and the day they
 * disagree neither is believed. So the topbar envelope is hidden while the
 * sidebar is on screen, and appears only below 900px where the sidebar is behind
 * the drawer and the logo with it. That is where field staff are, and losing the
 * mark there would be losing it where it matters most. */
.brand { position: relative; }
.brand-name { text-decoration: none; }
.brand-mail { margin-right: 0; }
.brand-mail > summary { width: auto; height: auto; background: none; border: 0;
  border-radius: 10px; padding: 0; }
.brand-mail > summary:hover { border: 0; }
.brand-mail > summary .mark { display: block; }
.brand-mail .alert-dot { position: absolute; top: -4px; right: -4px; }

/* Anchored to the BRAND, not to the mark. Positioned against the mark it started
   155px in and overhung the 232px sidebar by 243px, which is why it read as
   floating over the page rather than belonging to anything. From the brand's
   left edge it lines up with the sidebar and overhangs by the little it must.
   `position: static` here hands the anchoring to .brand; the red dot keeps its
   own anchor on the summary, which is already positioned. */
.brand-mail { position: static; }
.brand-mail .msg-pop { position: absolute; left: 0; right: auto; top: calc(100% - .2rem); z-index: 70; }

.topbar-mail { display: none; }
@media (max-width: 900px) {
  .topbar-mail { display: inline-block; }
}

/* A label and its box on one line, vertically centred. A plain block label puts
   its text on the row above and the input hangs below it, which reads as the box
   having slipped down — 2026-07-31. */
label.field-row { display: flex; align-items: center; gap: .6rem; flex-wrap: wrap; margin: 1rem 0 0; }
label.field-row .field-label { display: inline-flex; align-items: baseline; gap: .4rem; }
label.field-row input { margin: 0; }

/* An evaluation box that opens its PDF. It has to look pressable — a box that
   navigates and looks identical to one that does not is a box nobody presses. */
.docbox.openable { text-decoration: none; color: inherit; cursor: pointer; }
.docbox.openable:hover { border-color: var(--accent); box-shadow: 0 2px 8px rgba(124,92,230,.18); }

/* The sentence that says what a function lets somebody do. Darker and roomier
   than the key beneath it: this is the line somebody reads before ticking a box,
   and the key is only there for whoever has to match it to code. */
.permit .fn-what { display: block; color: var(--ink); font-size: .82rem;
  line-height: 1.35; margin: .2rem 0 .3rem; max-width: 46rem; font-weight: 400; }

/* The company a block of functions belongs to. Two separate legal entities, so
   the grid says which one you are reading rather than leaving it to be inferred
   from a category name. Sticky under the heading row so it stays true while you
   scroll down a long block. */
table.pg tr.company-row td.company-name {
  font-family: var(--serif); font-size: 1rem; font-weight: 600;
  color: var(--accent-strong); background: var(--surface-2);
  padding: .85rem .8rem .5rem; border-top: 2px solid var(--accent);
}
