/* COMPONENTS — BEM blocks. Each block's behaviour spec lives in
   guidelines/components.md; this file is the single source of visual truth. */

/* skip link — first element in <body>; visible on focus */
.skip-link {
  position: absolute;
  left: -9999px;
  top: 0;
  z-index: 100;
  padding: var(--space-2) var(--space-3);
  font-weight: var(--weight-semibold);
}
.skip-link:focus-visible { left: 0; position: fixed; }

/* back link */
.back-link {
  display: inline-block;
  margin-bottom: var(--space-4);
  color: var(--color-link);
  text-decoration: underline;
  text-underline-offset: 0.15em;
}
.back-link::before { content: "‹ "; text-decoration: none; }

/* navbar */
.navbar {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  padding: var(--space-2) var(--space-4);
  background: var(--color-surface);
  border-bottom: var(--border-width) solid var(--color-border);
  box-shadow: var(--shadow-sm);
  /* brand red lives here as a non-text identity rule — its only chrome use */
  border-top: var(--border-width-accent) solid var(--color-brand);
}
.navbar__start { display: flex; align-items: center; }
/* The mark is portrait (0.841 wide-to-tall), so the old 50% circle cropped its
   ears and feet. A percentage radius rather than a `--radius-*` token: icon
   corners are proportional — that is how Apple's icon grid is defined — so 22%
   gives the navbar mark, the hero mark and the app icon one shape at three
   sizes, where an absolute token would round the 4rem hero mark half as much as
   this 2rem one. The radius tokens stay for controls, which do round by an
   absolute amount. The plate is white on a #f6f7f8 navbar — only a hair lighter,
   but the rounded edge is what defines it, so it reads as a soft chip in the
   light scheme and a bright one in the dark, keeping the same tile shape in
   both. */
.navbar__logo { height: 2rem; width: 2rem; border-radius: 22%; }
.navbar__title { padding-inline: var(--space-2); font-weight: var(--weight-semibold); }
.navbar__nav { display: flex; align-items: center; gap: var(--space-1); margin-left: var(--space-4); }
.navbar__link {
  display: inline-flex;
  align-items: center;
  min-height: var(--target-min);
  padding: var(--space-1) var(--space-3);
  border-radius: var(--radius-sm) var(--radius-sm) 0 0;
  color: var(--color-text);
  text-decoration: none;
  font-weight: var(--weight-medium);
}
.navbar__link:visited { color: var(--color-text); }
.navbar__link:hover { background: var(--color-zebra); color: var(--color-text); }
.navbar__link[aria-current="page"] {
  font-weight: var(--weight-semibold);
  box-shadow: inset 0 calc(-1 * var(--border-width-accent)) 0 var(--color-brand);
}
.navbar__end { display: flex; align-items: center; gap: var(--space-2); margin-left: auto; }
.navbar__account { position: relative; }
.navbar__account > summary {
  display: flex;
  align-items: center;
  gap: var(--space-1);
  min-height: var(--target-min);
  padding: var(--space-2) var(--space-3);
  border-radius: var(--radius);
  cursor: pointer;
  list-style: none;
  user-select: none;
}
.navbar__account > summary::-webkit-details-marker { display: none; }
.navbar__account > summary:hover { background: var(--color-zebra); }
.navbar__user-name { display: flex; align-items: center; gap: var(--space-1); font-size: var(--text-sm); font-weight: var(--weight-medium); }
.navbar__user-email { font-size: var(--text-xs); color: var(--color-text-muted); }
/* ▾ is the small-triangle glyph — it fills a fraction of its em box, so it
   needs to run larger than the text to read at parity with it. It flips
   when the disclosure is open (state, not decoration); the global
   reduced-motion rule kills the transition. */
.navbar__caret {
  display: inline-block;
  font-size: 1.3em;
  line-height: 1;
  color: var(--color-text-muted);
  transition: transform var(--duration-fast) var(--ease);
}
.navbar__account[open] .navbar__caret { transform: scaleY(-1); }
.navbar__account[open] > summary { background: var(--color-zebra); }
.navbar__menu {
  position: absolute;
  right: 0;
  top: calc(100% + var(--space-1));
  z-index: 20;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--space-2);
  min-width: 12rem;
  padding: var(--space-3);
  background: var(--color-bg);
  border: var(--border-width) solid var(--color-border);
  border-radius: var(--radius);
  box-shadow: var(--shadow-lg);
}

/* page header — h1 + optional lead + optional primary action */
.page-header {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--space-4);
  margin-bottom: var(--space-6);
}
.page-header h1 { margin: 0; }
.page-header__lead { margin: var(--space-1) 0 0; color: var(--color-text-muted); }
/* avatar beside the h1 (the profile screen), wrapping to its own line on a
   narrow viewport rather than squeezing the heading */
.page-header__identity { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-4); }
.page-header__identity h1 { margin: 0; }

/* button — min 44px target, names the action, never "Submit"/"OK" */
.button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  min-height: var(--target-min);
  padding: var(--space-2) var(--space-4);
  border: var(--border-width-strong) solid transparent;
  border-radius: var(--radius);
  background: var(--color-surface);
  color: var(--color-text);
  font-weight: var(--weight-semibold);
  cursor: pointer;
  transition: background-color var(--duration-fast) var(--ease), border-color var(--duration-fast) var(--ease);
}
.button:hover { border-color: var(--color-border-strong); }
.button--primary { background: var(--color-primary); border-color: var(--color-primary); color: var(--color-primary-text); }
.button--primary:hover { background: var(--color-primary-hover); border-color: var(--color-primary-hover); }
.button--secondary { background: transparent; border-color: var(--color-border-strong); }
.button--secondary:hover { background: var(--color-zebra); }
.button--danger { background: var(--color-danger); border-color: var(--color-danger); color: var(--color-danger-text); }
.button--danger:hover { background: var(--color-danger-hover); border-color: var(--color-danger-hover); }
.button--ghost { background: transparent; }
.button--ghost:hover { background: var(--color-zebra); }
.button--sm { min-height: 2rem; padding: var(--space-1) var(--space-3); font-size: var(--text-sm); }
.button:disabled { opacity: 0.5; cursor: not-allowed; }
.button:disabled:hover { background: revert-layer; }

/* form group — label + hint + error + control; works schema-generated */
.form-group { margin-bottom: var(--space-6); max-width: 30rem; }
.form-group--error { border-left: var(--border-width-accent) solid var(--color-danger); padding-left: var(--space-4); }
.field-label { display: block; font-weight: var(--weight-semibold); margin-bottom: var(--space-1); }
.field-label__optional { font-weight: var(--weight-regular); color: var(--color-text-muted); }
.field-hint { display: block; margin-bottom: var(--space-2); color: var(--color-text-muted); font-size: var(--text-sm); }
.field-error {
  display: block;
  margin-bottom: var(--space-2);
  color: var(--color-danger);
  font-weight: var(--weight-semibold);
  font-size: var(--text-sm);
}
.field-error::before { content: "Error: "; position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); }
.field-control {
  width: 100%;
  min-height: var(--target-min);
  padding: var(--space-2) var(--space-3);
  border: var(--border-width-strong) solid var(--color-border-strong);
  border-radius: var(--radius-sm);
  background: var(--color-bg);
  color: var(--color-text);
}
.field-control--error { border-color: var(--color-danger); }
.field-control--width-10 { max-width: 11.5em; }
.field-control--width-5 { max-width: 6.5em; }
textarea.field-control { min-height: 6rem; resize: vertical; }

/* character count — <div class="char-count" data-max="1000"> wraps a textarea */
.char-count__status { display: block; margin-top: var(--space-1); font-size: var(--text-sm); color: var(--color-text-muted); font-variant-numeric: var(--numeric); }
.char-count__status--over { color: var(--color-danger); font-weight: var(--weight-semibold); }

/* radios & checkboxes — native inputs, enlarged, label is the target */
.choice { display: flex; align-items: flex-start; gap: var(--space-3); min-height: var(--target-min); padding-block: var(--space-1); }
.choice input[type="radio"], .choice input[type="checkbox"] {
  width: 1.5rem; height: 1.5rem; margin: 0.125rem 0 0;
  accent-color: var(--color-primary);
  flex: none;
}
.choice__label { cursor: pointer; }
.choice__hint { display: block; color: var(--color-text-muted); font-size: var(--text-sm); }
fieldset.choices { border: 0; padding: 0; margin: 0; }
fieldset.choices legend { font-weight: var(--weight-semibold); padding: 0; margin-bottom: var(--space-2); }

/* field markers — one deliberate pattern, not scattered emoji.
   Two of them, sharing a shape and meaning different things: `.encrypted` is
   about sensitivity (this value is PII), `.suggested` about provenance (this
   value was read off a receipt, not typed). Both sit beside a field's label, in
   the slot `components.md` gives the field anatomy. */
.encrypted, .suggested {
  display: inline-flex;
  align-items: center;
  gap: var(--space-1);
  font-size: var(--text-xs);
  font-weight: var(--weight-semibold);
  color: var(--color-text-muted);
  border: var(--border-width) solid var(--color-border);
  border-radius: var(--radius-pill);
  padding: 0 var(--space-2);
  line-height: 1.6;
}
/* `.suggested` deliberately draws no glyph: the lock says "encrypted" without
   words, and there is no comparable mark for "we read this" — so the label
   carries it alone, which the no-icon-set rule wants anyway. */
/* the group-level disclosure: one note for a section whose every field is
   encrypted, instead of a pill on every row. Mixed sections keep the pills. */
.encrypted-note {
  display: flex;
  align-items: center;
  gap: var(--space-1);
  margin: var(--space-3) 0 0;
  color: var(--color-text-muted);
  font-size: var(--text-sm);
}
.encrypted::before, .encrypted-note::before { content: ""; width: 0.6em; height: 0.75em; flex: none;
  border: 1.5px solid currentColor; border-radius: 2px 2px 1px 1px; margin-top: 0.1em;
  box-shadow: inset 0 -0.35em 0 currentColor; }

/* error summary — top of page, focused on render, links to fields */
.error-summary {
  border: var(--border-width-accent) solid var(--color-danger);
  border-radius: var(--radius);
  padding: var(--space-4);
  margin-bottom: var(--space-6);
}
.error-summary__title { margin: 0 0 var(--space-2); font-size: var(--text-lg); font-weight: var(--weight-bold); }
.error-summary ul { margin: 0; padding-left: var(--space-4); }
.error-summary a { color: var(--color-danger); font-weight: var(--weight-semibold); }

/* notification banner — success / info / error; error is the live region */
.banner {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--space-3);
  border-left: var(--border-width-accent) solid;
  border-radius: var(--radius-sm);
  padding: var(--space-3) var(--space-4);
  margin-bottom: var(--space-4);
}
.banner--info { background: var(--banner-info-bg); border-color: var(--banner-info-border); }
.banner--success { background: var(--banner-success-bg); border-color: var(--banner-success-border); }
.banner--error { background: var(--banner-error-bg); border-color: var(--banner-error-border); }
.banner__title { display: block; font-weight: var(--weight-bold); margin-bottom: var(--space-1); }
.banner__close {
  flex: none;
  min-width: var(--target-min);
  min-height: var(--target-min);
  border: 0;
  background: transparent;
  color: inherit;
  font-size: var(--text-lg);
  line-height: 1;
  cursor: pointer;
  border-radius: var(--radius-sm);
}
.banner__close:hover { background: rgb(0 0 0 / 0.06); }

/* tag / status badge — tint + dark text + border; label carries the meaning */
.tag {
  display: inline-flex;
  align-items: center;
  padding: 0.125rem var(--space-2);
  border-radius: var(--radius-pill);
  font-size: var(--text-xs);
  font-weight: var(--weight-semibold);
  line-height: 1.5;
  border: var(--border-width) solid currentColor;
  background: var(--status-neutral-bg);
  color: var(--status-neutral-text);
}
.tag--positive { background: var(--status-positive-bg); color: var(--status-positive-text); }
.tag--attention { background: var(--status-attention-bg); color: var(--status-attention-text); }
.tag--danger { background: var(--status-danger-bg); color: var(--status-danger-text); }
.tag--info { background: var(--status-info-bg); color: var(--status-info-text); }

/* table — dense by default (expert tool); zebra + row affordance */
.table { font-size: var(--text-sm); }
.table tbody tr:nth-child(even) { background: var(--color-zebra); }
.table tbody tr.table__row--clickable { cursor: pointer; }
.table tbody tr.table__row--clickable:hover { background: var(--color-surface); }
.table__empty { padding-block: var(--space-6); text-align: center; color: var(--color-text-muted); }
.table caption { text-align: left; font-weight: var(--weight-semibold); margin-bottom: var(--space-2); }
.table__sort {
  display: inline-flex;
  align-items: center;
  gap: var(--space-1);
  padding: 0;
  border: none;
  background: none;
  font: inherit;
  font-weight: inherit;
  color: inherit;
  cursor: pointer;
}
.table__sort:hover { color: var(--color-link); }
.table__sort-arrow { color: var(--color-link); font-size: 0.75rem; min-width: 0.75rem; }
/* A cell that stacks several facts rather than holding one — the receipts inbox
   puts what a receipt is, what file it is, and when it was captured in a single
   column, so that the row reads the same here as it does on a phone. Each line
   is a `<p>`; the muted ones are supporting, and the first is the heading. */
.table__lines p { margin: 0; }
.table__lines p + p { margin-top: var(--space-1); }
.table__line--muted { color: var(--color-text-muted); }

/* summary list — key/value detail view */
.summary-list { margin: 0; }
.summary-list__row {
  display: grid;
  grid-template-columns: minmax(8rem, 14rem) 1fr auto;
  gap: var(--space-4);
  padding-block: var(--space-2);
  border-bottom: var(--border-width) solid var(--color-border);
}
.summary-list__key { color: var(--color-text-muted); }
/* an opaque value (a sign-in subject like auth0|8f2c1d) has no break
   opportunity, and its min-content width would push the row past its card */
.summary-list__value { margin: 0; overflow-wrap: break-word; }
.summary-list__value--numeric { font-variant-numeric: var(--numeric); }
/* the third column: per-row action(s), stacked so two of them don't widen the
   row, top-aligned so a wrapping value can't stretch a 44px control */
.summary-list__action { display: flex; flex-direction: column; gap: var(--space-1); align-self: start; }
@media (max-width: 32rem) {
  .summary-list__row { grid-template-columns: 1fr; gap: var(--space-1); }
  .summary-list__action { align-items: flex-start; }
}

/* card */
.card {
  background: var(--color-surface);
  border: var(--border-width) solid var(--color-border);
  border-radius: var(--radius);
  box-shadow: var(--shadow-sm);
  margin-bottom: var(--space-4);
}
.card__body { padding: var(--space-4); display: flex; flex-direction: column; gap: var(--space-2); }
.card__title { font-size: var(--text-lg); font-weight: var(--weight-semibold); margin: 0; }
.card__lead { margin: 0; color: var(--color-text-muted); }
/* user-authored free text (a bio, a skills narrative): keep the paragraph breaks
   the author typed — the value arrives as the raw string, not as markup */
.card__narrative { margin: 0; white-space: pre-line; }
.card__figure { font-size: var(--text-2xl); font-weight: var(--weight-bold); font-variant-numeric: var(--numeric); line-height: var(--leading-tight); }
.card__figure small { font-size: var(--text-md); font-weight: var(--weight-regular); color: var(--color-text-muted); }
.card--danger { border-color: var(--color-danger); border-width: var(--border-width-strong); }
.card--danger .card__title { color: var(--color-danger); }

/* avatar — a person's profile photo, or their initials when there is none.
   The photo fills the circle with `object-fit: cover` (centre-crop) rather than
   being squashed: there is no crop UI, so the shells crop and the server only
   downscales. Initials sit on --color-zebra with --color-text (14.9:1 light,
   13.3:1 dark) — never colour-coded, since the name beside it carries the
   meaning. Decorative: the image is alt="" and the initials aria-hidden. */
.avatar {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex: none;
  width: 6rem;
  height: 6rem;
  overflow: hidden;
  border-radius: var(--radius-pill);
  border: var(--border-width) solid var(--color-border);
  background: var(--color-zebra);
  color: var(--color-text);
  font-size: var(--text-2xl);
  font-weight: var(--weight-semibold);
  line-height: 1;
  user-select: none;
}
.avatar img { width: 100%; height: 100%; object-fit: cover; display: block; }
/* the row/card size: same crop, same initials fallback, half the diameter, so a
   row avatar is never a different *kind* of thing from a page one */
.avatar--sm { width: 3rem; height: 3rem; font-size: var(--text-md); }

/* media frame — a captured document shown at reading size (a receipt photo).
   `contain`, not the avatar's `cover`: a till receipt is much taller than it is
   wide, and cropping it would take off the total, which is what the person came
   to read. The height cap keeps a tall one from pushing its own actions off the
   screen. The border stays in both themes so a white receipt still has a visible
   edge against a light background. */
.media { margin: 0 0 var(--space-4); }
.media__image {
  display: block;
  width: auto;
  max-width: 100%;
  max-height: 60vh;
  margin-inline: auto;
  object-fit: contain;
  background: var(--color-zebra);
  border: var(--border-width) solid var(--color-border);
  border-radius: var(--radius);
}
.media__caption { margin-top: var(--space-2); color: var(--color-text-muted); text-align: center; }

/* person list — a short list of linked records inside a card (home's "Your team"
   and "Waiting for you"): one link per row plus its supporting figures. The
   moment a row needs a second comparable column or sorting, it is a table. */
.person-list { list-style: none; margin: 0; padding: 0; }
.person-list__item {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--space-1) var(--space-3);
  padding-block: var(--space-2);
  border-bottom: var(--border-width) solid var(--color-border);
}
.person-list__item:last-child { border-bottom: none; }
.person-list__meta {
  color: var(--color-text-muted);
  font-size: var(--text-sm);
  font-variant-numeric: var(--numeric);
}

/* badger card — a new joiner: avatar, name, and two muted lines. Sized so a row
   of them scrolls rather than squeezing; the card is the unit, not the grid cell,
   because how many fit is a function of the viewport and not of the content. */
.badger-card {
  flex: 0 0 14rem;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--space-2);
  padding: var(--space-4);
  background: var(--color-surface);
  border: var(--border-width) solid var(--color-border);
  border-radius: var(--radius);
}
.badger-card__meta { color: var(--color-text-muted); font-size: var(--text-sm); margin: 0; }

/* empty state — why it's empty + the next action */
.empty-state { text-align: center; padding-block: var(--space-8); max-width: 28rem; margin-inline: auto; }
.empty-state__title { font-weight: var(--weight-semibold); margin: 0 0 var(--space-2); }
.empty-state__text { color: var(--color-text-muted); margin: 0 0 var(--space-4); }

/* dialog — native <dialog>; destructive confirmations only */
.dialog {
  border: var(--border-width) solid var(--color-border);
  border-radius: var(--radius);
  box-shadow: var(--shadow-lg);
  padding: var(--space-6);
  max-width: 28rem;
  width: calc(100% - var(--space-8));
  background: var(--color-bg);
  color: var(--color-text);
  /* The UA stylesheet centres `dialog:modal` via `inset: 0` + `margin: auto`,
     but the site-wide `* { margin: 0 }` reset cancels the margin half of
     that, leaving it pinned to the top-left. Restore it explicitly. */
  margin: auto;
}
.dialog::backdrop { background: rgb(0 0 0 / 0.5); }
.dialog__title { margin: 0 0 var(--space-3); font-size: var(--text-xl); font-weight: var(--weight-bold); }
.dialog .o-actions { margin-bottom: 0; }

/* spinner + loading */
.spinner {
  display: inline-block;
  width: 1.5rem;
  height: 1.5rem;
  border: 2px solid var(--color-border);
  border-top-color: var(--color-primary);
  border-radius: var(--radius-pill);
  animation: sett-spin 0.6s linear infinite;
}
@keyframes sett-spin { to { transform: rotate(360deg); } }
.loading { display: flex; align-items: center; gap: var(--space-3); color: var(--color-text-muted); padding-block: var(--space-6); }
@media (prefers-reduced-motion: reduce) {
  .spinner { animation: none; border-top-color: var(--color-border); }
  .loading::after { content: "Loading…"; }
  .loading .loading__text { display: none; }
}

/* inline row-reference link-button (person names, ranges in tables) */
.tree__label {
  align-self: flex-start;
  padding: 0;
  border: none;
  background: none;
  font: inherit;
  color: var(--color-link);
  text-align: left;
  cursor: pointer;
  text-decoration: underline;
  text-underline-offset: 0.15em;
}
.tree__label:hover { color: var(--color-link-hover); text-decoration-thickness: 2px; }

/* hero — auth / splash screens */
.hero { min-height: 100vh; display: grid; place-items: center; padding: var(--space-4); background: var(--color-surface); }
.hero__content { max-width: 28rem; text-align: center; }
/* The mark above the hero title, on the splash and sign-in screens — the one
   place the brand appears before anyone is signed in. Same 22% icon radius as
   the navbar mark, so the two are one shape at two sizes. */
.hero__logo { display: block; margin: 0 auto var(--space-4); height: 4rem; width: 4rem; border-radius: 22%; }
.hero__title { font-size: var(--text-2xl); font-weight: var(--weight-bold); }
.hero__text { margin-block: var(--space-6); color: var(--color-text-muted); }

/* In an `.o-field` row (schema forms, working-pattern editor), stack the
   label text over its "encrypted" marker and nudge it down to sit level with
   the control's text. */
.o-field .field-label {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--space-1);
  padding-top: var(--space-2);
}
@media (max-width: 32rem) {
  .o-field .field-label { padding-top: 0; }
}

/* live booking cost line (new-leave-request) */
.form-cost { margin: var(--space-2) 0; font-weight: var(--weight-semibold); color: var(--color-text-muted); }

/* Working-pattern editor: a compact Mon–Fri × AM/PM checkbox grid. */
.pattern-grid { border-collapse: collapse; }
.pattern-grid th, .pattern-grid td {
  padding: var(--space-1) var(--space-3);
  text-align: center;
  font-weight: var(--weight-regular);
}
.pattern-grid thead th { font-size: var(--text-sm); color: var(--color-text-muted); }
.pattern-grid th[scope="row"] { text-align: left; font-weight: var(--weight-semibold); }
.pattern-grid input[type="checkbox"] { width: 1.1rem; height: 1.1rem; }
.pattern-grid__total {
  display: block;
  margin-top: var(--space-2);
  color: var(--color-text-muted);
}

/* shell adaptation (not in handoff) — the Leptos shell renders primary-nav
   items as <button>s dispatching navigation events; neutralise UA button
   chrome so .navbar__link applies as designed. `font: inherit` is already
   set for all buttons in 04-elements.css; text-align and margin were
   verified (via computed-style diff against a reference <a class="navbar__link">)
   to need no override — the flex layout ignores text-align on a single text
   child, and margin is already 0 on both elements. */
button.navbar__link { appearance: none; background: none; border: 0; cursor: pointer; }

/* shell adaptation (not in handoff) — the handoff navbar defines no
   narrow-viewport strategy (its own reference overflows at 320px), and this
   shell's bar carries more items (five sections, an action, the account
   menu). Let the bar, its end cluster and the primary nav wrap so every
   screen reflows at 320px width / 200% zoom without horizontal scrolling
   (WCAG 1.4.10). Reported upstream against the design-system source. */
.navbar, .navbar__end, .navbar__nav { flex-wrap: wrap; }

/* shell adaptation (not in handoff) — same narrow-viewport gap for the page
   header: h1 + action sit in an unwrappable flex row, squeezing long titles
   beside the button. Wrap so the action drops below the title on narrow
   screens (GOV.UK behaviour). Reported upstream. */
.page-header { flex-wrap: wrap; }

/* shell adaptation (not in handoff) — below 64rem (mobile and tablet
   portrait) the primary nav, action and account collapse behind a native
   "Menu" disclosure button (GOV.UK header pattern), wired to aria-expanded
   by the shell; at 64rem and up the navbar is the designed single row. */
.navbar__menu-toggle { display: none; }
@media (width < 64rem) {
  .navbar__menu-toggle {
    display: inline-flex;
    align-items: center;
    gap: var(--space-1);
    margin-left: auto;
    min-height: var(--target-min);
    padding: var(--space-1) var(--space-2);
    appearance: none;
    background: none;
    border: 0;
    cursor: pointer;
    font: inherit;
    font-weight: var(--weight-semibold);
    color: var(--color-text);
  }
  .navbar__menu-toggle:hover { background: var(--color-zebra); }
  .navbar__end { display: none; }
  .navbar__end.navbar__end--open {
    display: flex;
    flex-basis: 100%;
    min-width: 0;
    flex-direction: column;
    align-items: stretch;
    margin-left: 0;
    padding-block: var(--space-2);
    border-top: var(--border-width) solid var(--color-border);
  }
  .navbar__end--open .navbar__nav {
    flex-direction: column;
    align-items: stretch;
    flex-wrap: nowrap;
    margin-left: 0;
    gap: 0;
  }
  .navbar__end--open .navbar__link {
    justify-content: flex-start;
    /* square corners: the current-page bar is an inset shadow, and any
       border-radius clips its ends into a taper */
    border-radius: 0;
  }
  .navbar__end--open .navbar__link[aria-current="page"] {
    box-shadow: inset var(--border-width-accent) 0 0 var(--color-brand);
  }
  .navbar__end--open > .button {
    align-self: flex-start;
    margin-block: var(--space-2);
  }
  .navbar__end--open .navbar__account { align-self: stretch; }
  .navbar__end--open .navbar__account > summary { min-height: var(--target-min); }
  /* inside the panel the account menu flows as a nested disclosure — the
     desktop rule floats it right-aligned to its (narrow) anchor, which on
     mobile lands off the left edge of the viewport */
  .navbar__end--open .navbar__menu {
    position: static;
    min-width: 0;
    background: none;
    border: 0;
    box-shadow: none;
    padding: var(--space-2) var(--space-3) var(--space-2) var(--space-6);
  }
}

/* shell adaptation (not in handoff) — a tag inside a card body sits in a
   stretch flex column and would pill across the full card width; keep it
   hugging its label. */
.card__body > .tag { align-self: flex-start; }

/* shell adaptation (not in handoff) — the native select arrow hugs the
   control's border. Draw the caret in CSS instead (like the encrypted
   lock: no icon assets) with proper breathing room; currentColor keeps it
   correct in both schemes. */
select.field-control {
  appearance: none;
  padding-right: var(--space-8);
  /* matches .navbar__caret: same muted tone, same optical weight */
  background-image:
    linear-gradient(45deg, transparent 50%, var(--color-text-muted) 50%),
    linear-gradient(135deg, var(--color-text-muted) 50%, transparent 50%);
  background-position:
    calc(100% - var(--space-4) - 5px) calc(50% - 1px),
    calc(100% - var(--space-4)) calc(50% - 1px);
  background-size: 5px 5px;
  background-repeat: no-repeat;
}

/* org tree (list view) — designed in-shell: the handoff ships no org-tree
   spec (the reference screens don't cover this surface). Quiet expert-tool
   rows in system tokens: name-first typography, a fixed caret gutter so
   names align across depths, 44px rhythm, hairline dividers. */
.view-toggle {
  display: inline-flex;
  margin-bottom: var(--space-4);
  border: var(--border-width) solid var(--color-border-strong);
  border-radius: var(--radius);
  overflow: hidden;
}
.view-toggle__option {
  appearance: none;
  background: none;
  border: 0;
  cursor: pointer;
  font: inherit;
  /* the system's --sm scale (sanctioned for dense surfaces) — full-size
     buttons overpower the 14px tree this control sits above */
  min-height: 2rem;
  padding: var(--space-1) var(--space-3);
  font-size: var(--text-sm);
  color: var(--color-text);
}
.view-toggle__option + .view-toggle__option {
  border-left: var(--border-width) solid var(--color-border-strong);
}
.view-toggle__option:hover { background: var(--color-zebra); }
.view-toggle__option[aria-pressed="true"] {
  background: var(--color-text);
  color: var(--color-bg);
  font-weight: var(--weight-semibold);
}
.view-toggle__option:disabled { opacity: 0.5; cursor: not-allowed; }

.org-tree {
  list-style: none;
  margin: 0;
  padding: 0;
  max-width: 44rem;
}
.org-tree__row {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  min-height: var(--target-min);
  border-bottom: var(--border-width) solid var(--color-border);
}
.org-tree__row:hover { background: var(--color-zebra); }
.org-tree__toggle {
  flex: none;
  width: var(--target-min);
  min-height: var(--target-min);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  appearance: none;
  background: none;
  border: 0;
  cursor: pointer;
  font: inherit;
  color: var(--color-text-muted);
}
span.org-tree__toggle { cursor: default; }
.org-tree__label {
  appearance: none;
  background: none;
  border: 0;
  cursor: pointer;
  font: inherit;
  text-align: left;
  padding-block: var(--space-2);
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  column-gap: var(--space-2);
  color: var(--color-text);
}
.org-tree__name {
  font-weight: var(--weight-semibold);
  color: var(--color-link);
  text-decoration: underline;
  text-underline-offset: 0.15em;
}
.org-tree__label:hover .org-tree__name {
  color: var(--color-link-hover);
  text-decoration-thickness: 2px;
}
.org-tree__meta {
  color: var(--color-text-muted);
  font-size: var(--text-sm);
}

/* org chart canvas (shell adaptation, not in handoff) — the classic top-down
   chart: cards on a pannable, zoomable surface joined by elbow connectors.

   Every coordinate comes from the core (`org_chart::layout`), so this file
   owns appearance only — no geometry, no magic offsets that could drift from
   what the core computed. Cards are real <button>s in the DOM positioned over
   an SVG connector layer, rather than SVG shapes, so they keep focus rings,
   tokens and dark mode for free. Wide all-leaf groups are stacked into an
   indented column by the core, which is what keeps this canvas roughly 2,500px
   wide instead of 15,000. */
.org-canvas {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
  margin-top: var(--space-4);
}
.org-canvas__controls {
  display: flex;
  align-items: center;
  gap: var(--space-2);
}
.org-canvas__zoom {
  font-size: var(--text-sm);
  font-variant-numeric: var(--numeric);
  color: var(--color-text-muted);
  /* Fixed width so stepping the zoom doesn't shuffle the buttons beside it. */
  min-width: 3.5rem;
  text-align: center;
}
.org-canvas__viewport {
  overflow: auto;
  max-height: 75vh;
  background: var(--color-surface);
  border: var(--border-width) solid var(--color-border);
  border-radius: var(--radius);
  cursor: grab;
  /* The chart is a diagram, not prose: a drag should pan it, not select it. */
  user-select: none;
}
.org-canvas__viewport.is-panning { cursor: grabbing; }
.org-canvas__surface {
  position: relative;
  transform-origin: 0 0;
}
.org-canvas__wires {
  position: absolute;
  inset: 0;
  overflow: visible;
}
.org-canvas__wire {
  fill: none;
  stroke: var(--color-border-strong);
  stroke-width: 1.5;
}

/* node — avatar column beside a tinted department bar over the name, which is
   the anatomy of a paper org-chart box */
.org-node { position: absolute; }
.org-node__card {
  appearance: none;
  border: var(--border-width) solid var(--color-border-strong);
  border-radius: var(--radius-sm);
  padding: 0;
  cursor: pointer;
  font: inherit;
  width: 100%;
  overflow: hidden;
  display: grid;
  grid-template-columns: 2.75rem 1fr;
  grid-template-rows: 1.5rem 1fr;
  background: var(--color-bg);
  box-shadow: var(--shadow-sm);
  transition: box-shadow var(--duration-fast) var(--ease);
}
.org-node__card:hover { box-shadow: var(--shadow-lg); }
.org-node__avatar {
  grid-row: 1 / 3;
  /* Square, not the pill the standalone avatar uses: it fills the box's left
     column edge to edge, exactly as the photo does on a paper chart. */
  width: 100%;
  height: 100%;
  border-radius: 0;
  border: 0;
  border-right: var(--border-width) solid var(--color-border);
  font-size: var(--text-sm);
}
/* Both rows are `display: block` with a line-height that fills their grid
   track, NOT flex: `text-overflow: ellipsis` has no effect on a flex
   container, so a long job title would hard-cut mid-word instead of eliding. */
.org-node__title {
  display: block;
  line-height: 1.5rem;
  padding-inline: var(--space-2);
  font-size: var(--text-xs);
  font-weight: var(--weight-semibold);
  text-transform: uppercase;
  letter-spacing: 0.02em;
  /* One line: a wrapped title would push the name out of a fixed-height box. */
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.org-node__name {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  height: 2.75rem;
  padding-inline: var(--space-2);
  font-size: var(--text-sm);
  font-weight: var(--weight-medium);
  color: var(--color-text);
  overflow: hidden;
}
/* The name elides; the "You" marker beside it never does. */
.org-node__name-text {
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* "you are here" — the first thing anyone looks for in an org chart.
   An outline rather than a fill, so it reads on top of any of the six
   department tints without fighting them, and it is drawn *outside* the card
   so it doesn't shift the layout the core computed. Never colour alone: the
   card also carries a "You" marker, and says so in its accessible name. */
.org-node__card.is-self {
  outline: var(--border-width-strong) solid var(--color-primary);
  outline-offset: 2px;
}
.org-node__you {
  flex: none;
  padding-inline: var(--space-1);
  border-radius: var(--radius-sm);
  background: var(--color-primary);
  color: var(--color-primary-text);
  font-size: var(--text-xs);
  font-weight: var(--weight-semibold);
  line-height: 1.25rem;
}
/* the six categorical department bands (tokens in 01-settings.css) */
.org-node__card--tint-1 .org-node__title { background: var(--tint-1-bg); color: var(--tint-1-text); }
.org-node__card--tint-2 .org-node__title { background: var(--tint-2-bg); color: var(--tint-2-text); }
.org-node__card--tint-3 .org-node__title { background: var(--tint-3-bg); color: var(--tint-3-text); }
.org-node__card--tint-4 .org-node__title { background: var(--tint-4-bg); color: var(--tint-4-text); }
.org-node__card--tint-5 .org-node__title { background: var(--tint-5-bg); color: var(--tint-5-text); }
.org-node__card--tint-6 .org-node__title { background: var(--tint-6-bg); color: var(--tint-6-text); }

/* toggle — the ⊕/⊖ node on the outgoing connector. Deliberately smaller than
   --target-min: it sits in the gap between two rows of cards, and a 44px
   target there would overlap the cards it sits between. The same action is
   always available at full size in the List view, which is the sanctioned
   escape hatch for a dense expert surface. */
.org-node__toggle {
  position: absolute;
  /* Cards are absolutely positioned siblings painted in DOM order, so a later
     card would cover a control that reaches into its space. The core reserves
     room so that should never happen; this is the belt to that pair of braces,
     and it costs nothing. */
  z-index: 1;
  appearance: none;
  width: 1.25rem;
  height: 1.25rem;
  margin: -0.625rem 0 0 -0.625rem;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 0;
  cursor: pointer;
  font: inherit;
  font-size: var(--text-sm);
  line-height: 1;
  border: var(--border-width) solid var(--color-border-strong);
  border-radius: var(--radius-pill);
  background: var(--color-bg);
  color: var(--color-text);
}
.org-node__toggle:hover {
  background: var(--color-text);
  color: var(--color-bg);
}

/* org explorer (shell adaptation, not in handoff) — the same reason as the
   org-tree list above: the reference screens don't cover this surface.

   Replaces the old D3 canvas. The organisation is shallow and very wide (depth
   2, fan-out up to 19), so a tidy-tree canvas of the whole thing is thousands
   of pixels across and two rows tall. Instead one person is centred and only
   their neighbourhood is drawn: chain above, peers beside, reports below. That
   reads at any fan-out and at any RBAC scope — a member who can see only their
   own line gets a complete-looking page, not a two-node stump.

   The connectors between tiers are borders on the tier itself, not SVG: there
   is no arbitrary geometry to draw once the layout is a stack of rows. Every
   value below is a token, which is precisely what the deleted `.orgchart`
   block got wrong — it named custom properties that never existed and so
   always rendered its light-mode fallbacks. */
.org-explorer {
  display: flex;
  flex-direction: column;
  gap: var(--space-6);
  margin-top: var(--space-4);
}

/* chain — the management line above the focus, root first */
.org-explorer__chain {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}
.org-explorer__chain ol {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-1);
}
/* The separator is decorative, so it is generated rather than marked up — the
   list semantics already carry the sequence for assistive tech. */
.org-explorer__chain li + li::before {
  content: "›";
  margin-right: var(--space-1);
  color: var(--color-text-muted);
}
.org-explorer__crumb {
  appearance: none;
  background: none;
  border: 0;
  cursor: pointer;
  font: inherit;
  font-size: var(--text-sm);
  padding: var(--space-1) var(--space-2);
  border-radius: var(--radius-sm);
  color: var(--color-link);
  text-decoration: underline;
  text-underline-offset: 0.15em;
}
.org-explorer__crumb:hover {
  color: var(--color-link-hover);
  background: var(--color-zebra);
}

/* tiers — peers and reports, each headed by a counted label */
.org-explorer__tier {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
}
.org-explorer__tier-head {
  margin: 0;
  font-size: var(--text-sm);
  font-weight: var(--weight-semibold);
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--color-text-muted);
}
/* A hairline above each tier separates the three bands (focus / peers /
   reports) without drawing connector geometry — the vertical stack already
   carries the hierarchy, so lines between individual cards would add ink
   without adding meaning. */
.org-explorer__tier--peers,
.org-explorer__tier--reports {
  border-top: var(--border-width) solid var(--color-border);
  padding-top: var(--space-4);
}

/* reports and search hits: a grid that reflows instead of scrolling sideways,
   so 19 reports wrap rather than running off the canvas */
.org-explorer__grid {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(14rem, 1fr));
  gap: var(--space-3);
}
/* peers: a horizontal strip, because they are context rather than the subject */
.org-explorer__strip {
  list-style: none;
  margin: 0;
  padding: 0 0 var(--space-2);
  display: flex;
  gap: var(--space-3);
  overflow-x: auto;
  scroll-snap-type: x proximity;
}
.org-explorer__strip > li {
  flex: 0 0 14rem;
  scroll-snap-align: start;
}

/* card — one person. The whole body is the re-centre control; the focused card
   additionally offers "View full record" for the other intent. */
.org-card {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  align-items: flex-start;
  height: 100%;
  padding: var(--space-3);
  background: var(--color-bg);
  border: var(--border-width) solid var(--color-border);
  border-radius: var(--radius);
  box-shadow: var(--shadow-sm);
}
.org-card__body {
  appearance: none;
  background: none;
  border: 0;
  cursor: pointer;
  font: inherit;
  text-align: left;
  width: 100%;
  min-height: var(--target-min);
  padding: 0;
  display: flex;
  align-items: center;
  gap: var(--space-3);
  color: var(--color-text);
  border-radius: var(--radius-sm);
  transition: background var(--duration-fast) var(--ease);
}
.org-card__body:hover { background: var(--color-zebra); }
.org-card__avatar { align-self: flex-start; }
.org-card__text {
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
  min-width: 0;
}
.org-card__name {
  font-weight: var(--weight-semibold);
  color: var(--color-link);
  text-decoration: underline;
  text-underline-offset: 0.15em;
  /* Long names truncate rather than widening the grid track and breaking the
     column rhythm; the full name stays in the button's aria-label. */
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.org-card__body:hover .org-card__name {
  color: var(--color-link-hover);
  text-decoration-thickness: 2px;
}
.org-card__role {
  font-size: var(--text-sm);
  color: var(--color-text);
}
.org-card__place,
.org-card__tenure {
  font-size: var(--text-sm);
  color: var(--color-text-muted);
}
/* The reports line is the one number on the card, so it gets the tabular
   figures every data figure in this system uses. */
.org-card__reports {
  font-size: var(--text-sm);
  font-variant-numeric: var(--numeric);
  color: var(--color-text-muted);
}
.org-card__tags {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-1);
}
.org-card__tags:empty { display: none; }

/* the focused card: the subject of the page, so it is bigger, sits on the
   raised surface, and carries a brand-red accent edge — a non-text accent,
   which is the only role brand red may play */
.org-card--focus {
  background: var(--color-surface);
  border-left: var(--border-width-accent) solid var(--color-brand);
  padding: var(--space-4);
}
.org-card--focus .org-card__avatar {
  width: 6rem;
  height: 6rem;
  font-size: var(--text-2xl);
}
.org-card--focus .org-card__name {
  font-size: var(--text-xl);
  font-weight: var(--weight-bold);
}
.org-card--focus .org-card__role { font-size: var(--text-lg); }

/* peers are context: quieter, and never taller than the card beside them */
.org-card--peer {
  background: var(--color-surface);
  box-shadow: none;
}

@media (width < 40rem) {
  /* The focus card's avatar dominates a narrow column, so it drops to the row
     size and the card reads as a single stack. */
  .org-card--focus { padding: var(--space-3); }
  .org-card--focus .org-card__avatar {
    width: 3rem;
    height: 3rem;
    font-size: var(--text-md);
  }
  .org-card--focus .org-card__name { font-size: var(--text-lg); }
  .org-card--focus .org-card__role { font-size: var(--text-md); }
}
