/* Clearance review inbox — mobile-first, no build step.
   Tokens first: surfaces, text, semantics, depth, glass, spacing, radius.
   Rules below read from the tokens rather than hard-coding one-off values. */

/* --- type: vendored IBM Plex ----------------------------------------------
   Latin-1 subsets only, woff2 only. The version is in the path so a font URL
   never changes once shipped; the server marks /static/fonts/ immutable for a
   year on that basis (see the font handler in internal/web/web.go). Replace a
   font by adding a new plex-<version>/ directory, never by editing in place.
   The system stack stays the fallback in --sans/--mono. */
@font-face {
  font-family: "IBM Plex Sans";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("/static/fonts/plex-sans-1.1.0/Regular.woff2") format("woff2");
}
@font-face {
  font-family: "IBM Plex Sans";
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url("/static/fonts/plex-sans-1.1.0/Medium.woff2") format("woff2");
}
@font-face {
  font-family: "IBM Plex Sans";
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url("/static/fonts/plex-sans-1.1.0/SemiBold.woff2") format("woff2");
}
@font-face {
  font-family: "IBM Plex Sans";
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url("/static/fonts/plex-sans-1.1.0/Bold.woff2") format("woff2");
}
@font-face {
  font-family: "IBM Plex Mono";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("/static/fonts/plex-mono-2.5.0/Regular.woff2") format("woff2");
}
@font-face {
  font-family: "IBM Plex Mono";
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url("/static/fonts/plex-mono-2.5.0/Medium.woff2") format("woff2");
}
/* Mono italic ships because the app renders one italic mono value (the
   "absent" marker in the effects table); without it the browser would fake it. */
@font-face {
  font-family: "IBM Plex Mono";
  font-style: italic;
  font-weight: 400;
  font-display: swap;
  src: url("/static/fonts/plex-mono-2.5.0/Italic.woff2") format("woff2");
}

:root {
  color-scheme: light dark;

  /* Surfaces and text */
  --bg: #f4f5f7;
  --card: #ffffff;
  --sunken: #eef0f3;
  --fg: #14161a;
  --muted: #5b6472;
  --line: #dfe3e8;

  /* Interactive */
  --accent: #1a63d6;
  --hover: rgba(16, 24, 40, 0.06);
  --active: rgba(16, 24, 40, 0.10);

  /* Semantics */
  --ok: #0f6b3f;
  --ok-bg: #e8f6ee;
  --warn: #8a5300;
  --warn-bg: #fdf3e2;
  --bad: #b3261e;
  --bad-bg: #fdeceb;

  /* Depth: a small, ordered set of elevations. */
  --depth-1: 0 1px 2px rgba(16, 24, 40, 0.06), 0 1px 3px rgba(16, 24, 40, 0.04);
  --depth-2: 0 2px 4px rgba(16, 24, 40, 0.05), 0 4px 12px rgba(16, 24, 40, 0.07);
  --depth-3: 0 8px 24px rgba(16, 24, 40, 0.10), 0 2px 6px rgba(16, 24, 40, 0.06);

  /* Glass: used for the top-bar chrome only, never every surface. */
  --glass-bg: rgba(255, 255, 255, 0.74);
  --glass-border: rgba(16, 24, 40, 0.08);
  --glass-blur: 14px;
  /* A denser cut of the glass for the menu panel. It floats over arbitrary
     content rather than the page's own background, so it needs more fill than
     the bar to keep its labels legible; the blur and border stay the bar's. */
  --glass-panel-bg: rgba(255, 255, 255, 0.94);

  /* Spacing and shape */
  --space-1: 0.25rem;
  --space-2: 0.5rem;
  --space-3: 0.75rem;
  --space-4: 1rem;
  --space-5: 1.5rem;
  --space-6: 2rem;
  --space-7: 3rem;

  --radius-sm: 8px;
  --radius-md: 12px;
  --radius-lg: 16px;
  --radius-pill: 999px;

  --measure: 44rem;
  --gutter: 1rem;
  --sans: "IBM Plex Sans", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
  --mono: "IBM Plex Mono", ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace;

  /* Legacy alias kept so existing markup keeps working. */
  --radius: var(--radius-md);
}

@media (prefers-color-scheme: dark) {
  :root {
    --bg: #0d1014;
    --card: #161b22;
    --sunken: #0b0e12;
    --fg: #e8ebef;
    --muted: #a2abb8;
    --line: #262c36;

    --accent: #6aa8ff;
    --hover: rgba(255, 255, 255, 0.07);
    --active: rgba(255, 255, 255, 0.12);

    --ok: #5fd39a;
    --ok-bg: #10291d;
    --warn: #f0c274;
    --warn-bg: #2a2110;
    --bad: #ff9a93;
    --bad-bg: #2c1615;

    --depth-1: 0 1px 2px rgba(0, 0, 0, 0.45);
    --depth-2: 0 4px 14px rgba(0, 0, 0, 0.55);
    --depth-3: 0 10px 30px rgba(0, 0, 0, 0.65);

    --glass-bg: rgba(22, 27, 34, 0.68);
    --glass-border: rgba(255, 255, 255, 0.09);
    /* The panel needs more fill than the bar in the dark too. */
    --glass-panel-bg: rgba(22, 27, 34, 0.94);
  }
}

* { box-sizing: border-box; }

html {
  -webkit-text-size-adjust: 100%;
}

html, body {
  margin: 0;
  padding: 0;
  background: var(--bg);
  color: var(--fg);
  font: 16px/1.5 var(--sans);
  overflow-wrap: anywhere;
  accent-color: var(--accent);
}

a { color: var(--accent); }

h1 { font-size: 1.35rem; line-height: 1.25; }
h2 { font-size: 1rem; }
h3 { font-size: 0.95rem; }
h1, h2, h3 { margin: 0; }

.muted { color: var(--muted); }
.small { font-size: 0.82rem; }
.mono { font-family: var(--mono); font-size: 0.85rem; }

/* Focus is always visible, and never animated. */
:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

/* --- top bar: a nearly full-width frosted pill ---------------------------- */

.topbar {
  position: sticky;
  top: 0;
  z-index: 20;
  /* The transparent gutter around the pill must not swallow taps on the page
     content that scrolls beneath it. */
  pointer-events: none;
  padding: calc(0.6rem + env(safe-area-inset-top)) var(--gutter) 0.6rem;
}

.topbar-pill {
  pointer-events: auto;
  display: flex;
  align-items: center;
  flex-wrap: nowrap;
  gap: var(--space-2);
  max-width: var(--measure);
  margin: 0 auto;
  padding: 0.4rem 0.5rem 0.4rem 1rem;
  border: 1px solid var(--glass-border);
  border-radius: var(--radius-pill);
  background: var(--glass-bg);
  box-shadow: var(--depth-2);
  -webkit-backdrop-filter: blur(var(--glass-blur)) saturate(180%);
  backdrop-filter: blur(var(--glass-blur)) saturate(180%);
}

/* Where the browser cannot blur, fall back to an opaque surface so text over
   scrolled content stays legible. */
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .topbar-pill { background: var(--card); }
}

.brand {
  font-weight: 700;
  text-decoration: none;
  color: var(--fg);
  letter-spacing: -0.01em;
  margin-right: var(--space-2);
  white-space: nowrap;
}

.topnav {
  display: flex;
  align-items: center;
  gap: var(--space-1);
  flex-wrap: nowrap;
  min-width: 0;
}

.topnav a {
  color: var(--muted);
  text-decoration: none;
  padding: 0.35rem 0.75rem;
  border-radius: var(--radius-pill);
  font-size: 0.9rem;
  font-weight: 500;
  white-space: nowrap;
}

.topnav a:hover { color: var(--fg); background: var(--hover); }

.topnav a.is-active {
  color: var(--fg);
  background: var(--active);
  font-weight: 600;
}

.topbar-end {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  margin-left: auto;
  min-width: 0;
}

.logout { margin: 0; }

.linkish {
  background: none;
  border: 0;
  color: var(--muted);
  font: inherit;
  font-size: 0.9rem;
  padding: 0.35rem 0.5rem;
  border-radius: var(--radius-pill);
  cursor: pointer;
  white-space: nowrap;
}
.linkish:hover { color: var(--fg); background: var(--hover); }

.whoami {
  display: inline-block;
  max-width: 12rem;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  vertical-align: middle;
  color: var(--muted);
  font-size: 0.85rem;
}

/* --- the nav menu: the header pill's frosted glass, as a panel -----------
   Destinations also sit inline in the bar. The menu holds the same links plus
   sign-out, and is offered at every width: on a phone it is the only nav, and
   on the desktop it is the account menu that carries sign-out, which no longer
   has a place in the bar. The panel is the same glass material as the header
   pill — same border, background, blur, and shadow step — so it reads as a
   piece of the bar that dropped down rather than a different surface. Both
   presentations render the same template (the block is defined once). No JS:
   this is a <details>, so tapping the button opens it and tapping it again
   closes it. */

.navmenu {
  display: block;
  position: relative;
}

.navmenu-btn {
  list-style: none;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 2.25rem;
  height: 2.25rem;
  /* The button is the menu's only control, so give it the same generous hit
     area as every other touch target in the app. */
  min-height: 44px;
  border: 1px solid var(--glass-border);
  border-radius: var(--radius-pill);
  background: var(--glass-bg);
  box-shadow: var(--depth-1);
  -webkit-backdrop-filter: blur(var(--glass-blur)) saturate(180%);
  backdrop-filter: blur(var(--glass-blur)) saturate(180%);
}
.navmenu-btn::-webkit-details-marker { display: none; }
.navmenu-btn:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

/* A three-line glyph, drawn in CSS so there is no icon asset to ship. */
.navmenu-glyph,
.navmenu-glyph::before,
.navmenu-glyph::after {
  display: block;
  width: 1rem;
  height: 2px;
  border-radius: 2px;
  background: var(--fg);
}
.navmenu-glyph { position: relative; }
.navmenu-glyph::before,
.navmenu-glyph::after { content: ""; position: absolute; left: 0; }
.navmenu-glyph::before { top: -5px; }
.navmenu-glyph::after { top: 5px; }

.navmenu-panel {
  position: absolute;
  top: calc(100% + 0.6rem);
  right: 0;
  min-width: 11rem;
  display: flex;
  flex-direction: column;
  gap: 0.15rem;
  padding: 0.35rem;
  /* The header pill's material, token for token: the glass border, the same
     blur and saturation, and the same shadow step. The fill is denser than the
     bar's, though: the panel floats over arbitrary content, so it needs more
     body to stay legible where the bar sits over the page background. */
  border: 1px solid var(--glass-border);
  border-radius: var(--radius-lg);
  background: var(--glass-panel-bg);
  box-shadow: var(--depth-2);
  -webkit-backdrop-filter: blur(var(--glass-blur)) saturate(180%);
  backdrop-filter: blur(var(--glass-blur)) saturate(180%);
}

.navmenu-panel a,
.navmenu-panel button {
  display: block;
  width: 100%;
  padding: 0.6rem 0.75rem;
  border: 0;
  border-radius: var(--radius-md);
  background: none;
  color: var(--fg);
  font: inherit;
  font-size: 0.95rem;
  font-weight: 500;
  text-align: left;
  text-decoration: none;
  cursor: pointer;
  white-space: nowrap;
}
.navmenu-panel a:hover,
.navmenu-panel button:hover { background: var(--hover); }
.navmenu-panel a.is-active { background: var(--active); font-weight: 600; }

/* Sign-out sits below a rule, set apart from the destinations above it. */
.navmenu-foot {
  margin-top: 0.15rem;
  padding-top: 0.35rem;
  border-top: 1px solid var(--glass-border);
}

/* Where the browser cannot blur the glass, fall back to the opaque card so the
   panel stays legible over the content it floats above. */
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .navmenu-btn,
  .navmenu-panel { background: var(--card); }
}

/* --- page frame ----------------------------------------------------------- */

.wrap {
  max-width: var(--measure);
  margin: 0 auto;
  padding: var(--space-5) var(--gutter) var(--space-7);
}

/* Vertical rhythm: top-level blocks are spaced by one step, so sections never
   rely on ad-hoc margins to line up. */
.wrap > * + *,
.card-detail > * + *,
.panel > * + *,
.decision > * + *,
.empty > * + * { margin-top: var(--space-4); }

/* A label hugs the control it names; the gap belongs above the label. */
.field-label + input,
.field-label + select,
.field-label + textarea { margin-top: 0; }

p { margin: 0; }

.foot {
  max-width: var(--measure);
  margin: 0 auto;
  padding: var(--space-4) var(--gutter) var(--space-6);
  color: var(--muted);
  font-size: 0.8rem;
  border-top: 1px solid var(--line);
}

/* --- banners -------------------------------------------------------------- */

.banner {
  padding: 0.6rem 0.85rem;
  border-radius: var(--radius-md);
  margin: var(--space-3) 0;
  border: 1px solid transparent;
}
.banner-error { background: var(--bad-bg); color: var(--bad); border-color: color-mix(in srgb, var(--bad) 22%, transparent); }
.banner-ok { background: var(--ok-bg); color: var(--ok); border-color: color-mix(in srgb, var(--ok) 22%, transparent); }
.banner-warn { background: var(--warn-bg); color: var(--warn); border-color: color-mix(in srgb, var(--warn) 22%, transparent); }
.banner ul { margin: var(--space-2) 0 0; padding-left: 1.1rem; }
.banner li + li { margin-top: var(--space-1); }

/* --- cards and inbox ------------------------------------------------------ */

.inbox-head { margin-bottom: var(--space-4); }
.cards { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--space-3); }

.card {
  background: var(--card);
  border: 1px solid var(--line);
  border-radius: var(--radius-md);
  box-shadow: var(--depth-1);
}
.card:hover { border-color: color-mix(in srgb, var(--line) 55%, var(--fg)); }
.card-pending { border-left: 4px solid var(--accent); }
.card-link { display: block; padding: var(--space-4); text-decoration: none; color: inherit; }

.card-top { display: flex; justify-content: space-between; align-items: center; gap: var(--space-2); }
.card-summary { margin: var(--space-2) 0; font-weight: 600; }
.card-meta { display: flex; flex-wrap: wrap; gap: var(--space-2); font-size: 0.8rem; color: var(--muted); }
.cap { font-family: var(--mono); }
.ver { color: var(--muted); }
.risk { color: var(--warn); }
.reason { margin: var(--space-2) 0 0; font-size: 0.82rem; color: var(--muted); }
.age { font-size: 0.8rem; color: var(--muted); white-space: nowrap; }

/* A chip sits at the card's bottom-right: a scannable flag, not an action. */
.card-foot { display: flex; justify-content: flex-end; margin-top: var(--space-3); }
.chip {
  display: inline-block;
  padding: 0.15rem 0.55rem;
  border-radius: var(--radius-pill);
  font-size: 0.75rem;
  font-weight: 600;
  border: 1px solid transparent;
}
.chip-eligible {
  background: var(--ok-bg);
  color: var(--ok);
  border-color: color-mix(in srgb, var(--ok) 22%, transparent);
}

/* --- grouped capability list ---------------------------------------------- */

/* Visually hidden but available to screen readers: keeps a filter control
   labelled without printing a label the design does not need. */
.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

/* The filter bar sits between the heading and the list. It is a plain GET form,
   so the filtered view is linkable and survives a reload without JavaScript.
   The global form rule sets width:100%, which would stack these controls; undo
   it here so the bar stays one row and wraps only when it must. */
.cap-filter {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-2);
  margin-bottom: var(--space-4);
}
.cap-filter input,
.cap-filter select { width: auto; }
.cap-search { flex: 1 1 14rem; min-width: 0; }
.cap-filter select { flex: 0 1 auto; }
.cap-filter .button { width: auto; flex: 0 0 auto; }
.cap-clear { font-size: 0.85rem; }

/* A group is the unit of meaning: each top-level namespace is a card, so the
   eye has a block to land on instead of an undifferentiated list. Rows inside
   stay dense — the comparison an operator makes is between clearances within a
   group, not across the whole page, so the card frames a group rather than a
   capability. */
.cap-groups { display: grid; gap: var(--space-4); }
.cap-groups > .cap-group {
  background: var(--card);
  border: 1px solid var(--line);
  border-radius: var(--radius-md);
  box-shadow: var(--depth-1);
  padding: var(--space-4);
}
.cap-groups > .cap-group > .group-toggle { margin: 0; }

/* The heading is the disclosure summary: the whole title row toggles the group,
   and the chevron from the shared disclosure pattern sits to its left. */
.group-toggle { cursor: pointer; }
.group-head {
  display: flex;
  align-items: baseline;
  gap: var(--space-2);
  margin: 0 0 var(--space-1);
  padding-bottom: var(--space-2);
  border-bottom: 1px solid var(--line);
  font-size: 0.95rem;
  flex: 1 1 auto;
}
.group-name { font-weight: 600; }
.group-count { color: var(--muted); font-size: 0.8rem; font-weight: 600; }

/* A collapsed group is just its heading: drop the rule that separated the
   heading from rows, so it does not read as an empty box. */
details.cap-group:not([open]) > .group-toggle { margin-bottom: 0; }
details.cap-group:not([open]) .group-head {
  margin-bottom: 0;
  padding-bottom: 0;
  border-bottom: 0;
}

/* A nested namespace is a subsection of its parent's card, not a second card:
   indentation and a quiet rule carry the depth without boxing a box. */
.cap-group .cap-group {
  margin-top: var(--space-3);
  padding-left: var(--space-4);
  border-left: 2px solid var(--line);
}
/* A nested heading has no rule of its own: the parent's card already separates
   the group, and a second line here reads as noise. */
.cap-group .cap-group .group-head {
  border-bottom: 0;
  padding-bottom: var(--space-1);
  font-size: 0.86rem;
}

.cap-rows { list-style: none; margin: 0; padding: 0; }
.cap-row {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: var(--space-2) var(--space-3);
  min-height: 44px;
  padding: var(--space-2) var(--space-1);
  color: inherit;
  text-decoration: none;
  border-radius: var(--radius-sm);
}
/* A rule between rows, but not above the first. Rows live inside <li>, so the
   adjacent sibling is the list item, not the row. */
.cap-rows li + li .cap-row { border-top: 1px solid var(--line); }
.cap-row:hover { background: var(--hover); }
.cap-leaf { font-family: var(--mono); font-size: 0.85rem; flex: 1 1 auto; min-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
/* A default tag hugs the leaf: it qualifies the action, it is not a second
   clearance. It is quiet, because most unconfigured capabilities are noise. */
.cap-default {
  flex: 0 0 auto;
  padding: 0 var(--space-2);
  border: 1px solid var(--line);
  border-radius: 999px;
  color: var(--muted);
  font-size: 0.7rem;
  text-transform: uppercase;
  letter-spacing: 0.04em;
}
/* Clearance is neutral text of equal weight to its neighbours: the list exists
   to compare levels, not to rate them, so it carries no good/bad colour. */
.clearance { margin-left: auto; flex: 0 0 auto; color: var(--muted); font-size: 0.82rem; white-space: nowrap; }
.cap-row .chip { flex: 0 0 auto; }

/* --- state pills ---------------------------------------------------------- */

.state {
  display: inline-block;
  padding: 0.15rem 0.55rem;
  border-radius: var(--radius-pill);
  font-size: 0.75rem;
  font-weight: 600;
  background: var(--sunken);
  color: var(--fg);
}
.state-awaiting_review { background: var(--warn-bg); color: var(--warn); }
.state-approved, .state-modified, .state-completed { background: var(--ok-bg); color: var(--ok); }
.state-rejected, .state-failed, .state-indeterminate, .state-expired, .state-cancelled { background: var(--bad-bg); color: var(--bad); }

/* --- detail and panels ---------------------------------------------------- */

.crumb { margin: var(--space-1) 0; font-size: 0.85rem; }
.detail-head { margin-bottom: var(--space-4); }
.cap-title { font-size: 1.3rem; }

.panel {
  background: var(--card);
  border: 1px solid var(--line);
  border-radius: var(--radius-md);
  box-shadow: var(--depth-1);
  padding: var(--space-4);
  margin: 0;
}

.panel + .panel { margin-top: var(--space-4); }

.panel-head { margin-bottom: var(--space-3); }
.panel-head .small { margin: var(--space-1) 0 0; }

/* Setting rows: one overridable setting each, separated by a rule. */
.setting-row + .setting-row {
  margin-top: var(--space-4);
  padding-top: var(--space-4);
  border-top: 1px solid var(--line);
}
.setting-head h3 { margin: 0; font-size: 1rem; }
.setting-row .decision { margin-top: var(--space-3); }

.kv { display: grid; grid-template-columns: minmax(5rem, auto) 1fr; gap: var(--space-1) var(--space-3); margin: 0; }
.kv dt { color: var(--muted); }
.kv dd { margin: 0; }
.kv dt, .kv dd { padding: 0.15rem 0; }

/* Effects table: collapses cleanly on a phone. */
.effects { width: 100%; border-collapse: collapse; font-size: 0.9rem; }
.effects th { text-align: left; color: var(--muted); font-weight: 600; font-size: 0.78rem; }
.effects th, .effects td { padding: 0.45rem 0.4rem; border-bottom: 1px solid var(--line); vertical-align: top; }
.effects tr:last-child td { border-bottom: 0; }
.effects .field { font-weight: 600; }
.absent { color: var(--muted); font-style: italic; }

.risk-badge {
  display: inline-block;
  padding: 0.2rem 0.6rem;
  border-radius: var(--radius-pill);
  background: var(--warn-bg);
  color: var(--warn);
  font-weight: 600;
}

/* --- cohort evidence ------------------------------------------------------ */

.cohort + .cohort { margin-top: var(--space-5); padding-top: var(--space-4); border-top: 1px solid var(--line); }
.cohort-head { display: flex; flex-wrap: wrap; align-items: baseline; gap: var(--space-2); margin-bottom: var(--space-2); }

/* --- timeline ------------------------------------------------------------- */

.timeline { list-style: none; margin: 0; padding: 0; }
.timeline li { position: relative; padding: 0 0 var(--space-3) var(--space-4); border-left: 2px solid var(--line); }
.timeline li:last-child { padding-bottom: 0; }
.timeline li::before {
  content: "";
  position: absolute;
  left: -0.4rem; top: 0.35rem;
  width: 0.55rem; height: 0.55rem;
  border-radius: 50%;
  background: var(--muted);
}
.tl-created::before { background: var(--accent); }
.tl-approved::before { background: var(--ok); }
.tl-rejected::before { background: var(--bad); }
.tl-label { display: block; font-weight: 600; }
.tl-meta { display: block; font-size: 0.78rem; color: var(--muted); }
.tl-detail { display: block; font-size: 0.85rem; }

/* --- forms ---------------------------------------------------------------- */

.decision { margin-top: var(--space-4); }
.field + .field { margin-top: var(--space-4); }
.field-label { display: block; margin: 0 0 var(--space-1); font-size: 0.85rem; font-weight: 600; color: var(--fg); }
.field-hint { margin: var(--space-1) 0 0; font-size: 0.82rem; color: var(--muted); }

input, select, textarea {
  width: 100%;
  padding: 0.6rem 0.7rem;
  font: inherit;
  color: var(--fg);
  background: var(--card);
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  box-shadow: inset 0 1px 2px rgba(16, 24, 40, 0.05);
}
@media (prefers-color-scheme: dark) {
  input, select, textarea { box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.35); }
}

input::placeholder, textarea::placeholder { color: var(--muted); opacity: 1; }

select {
  appearance: none;
  -webkit-appearance: none;
  padding-right: 2rem;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8'%3E%3Cpath d='M1 1.5 6 6.5l5-5' fill='none' stroke='%235b6472' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 0.7rem center;
  background-size: 0.75rem;
}
@media (prefers-color-scheme: dark) {
  select {
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8'%3E%3Cpath d='M1 1.5 6 6.5l5-5' fill='none' stroke='%23a2abb8' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  }
}

input:focus-visible, select:focus-visible, textarea:focus-visible {
  border-color: var(--accent);
}

textarea { resize: vertical; min-height: 3rem; }

/* Conditions are a JSON editor, so treat them as a code field: monospace,
   preserved whitespace, a sunken surface that reads differently from prose
   inputs, and a comfortable line box for scanning predicates. */
.code {
  font-family: var(--mono);
  font-size: 0.85rem;
  line-height: 1.6;
  tab-size: 2;
  white-space: pre;
  overflow: auto;
  resize: vertical;
  min-height: 9rem;
  background: var(--sunken);
}

.examples {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-1) var(--space-2);
  margin-top: var(--space-2);
}
.examples-label { font-size: 0.78rem; color: var(--muted); }
.code-chip {
  display: inline-block;
  padding: 0.12rem 0.45rem;
  border-radius: var(--radius-sm);
  border: 1px solid var(--line);
  background: var(--sunken);
  font-family: var(--mono);
  font-size: 0.78rem;
  color: var(--fg);
}

.form-actions { display: flex; gap: var(--space-2); margin-top: var(--space-5); }

.actions { display: grid; grid-template-columns: 1fr 1fr; gap: var(--space-2); margin-top: var(--space-3); }

.button {
  display: inline-block;
  padding: 0.75rem 1rem;
  min-height: 44px;
  text-align: center;
  text-decoration: none;
  font: inherit;
  font-weight: 600;
  color: #fff;
  background: var(--accent);
  border: 1px solid transparent;
  border-radius: var(--radius-sm);
  box-shadow: var(--depth-1);
  cursor: pointer;
}
.button:hover { filter: brightness(0.95); }
.button-approve { background: var(--ok); }
.button-reject { background: var(--bad); }
.button-modify { background: var(--accent); width: 100%; }

@media (prefers-color-scheme: dark) {
  /* On the dark palette the semantic colours are light, so the button text
     must be dark to keep contrast. */
  .button, .button-approve, .button-reject, .button-modify { color: #0d1014; }
}

/* --- disclosure ------------------------------------------------------------
   One chevron implementation for every <details> in the app. The semantic
   classes (modify / post-review / abandon) and group cards add layout only, so
   there is a single place that draws the marker and it cannot drift.
   A flex summary loses the native triangle, so draw our own and flip it on
   open. Without it the summary reads as inert text. */
details.disclosure > summary {
  cursor: pointer;
  font-weight: 600;
  min-height: 44px;
  display: flex;
  align-items: center;
  gap: var(--space-2);
  list-style: none;
}
details.disclosure > summary::-webkit-details-marker { display: none; }
details.disclosure > summary::before {
  content: "";
  flex: 0 0 auto;
  width: 0;
  height: 0;
  border-left: 5px solid var(--muted);
  border-top: 4px solid transparent;
  border-bottom: 4px solid transparent;
}
details.disclosure[open] > summary::before {
  border-left: 4px solid transparent;
  border-right: 4px solid transparent;
  border-top: 5px solid var(--muted);
  border-bottom: 0;
}
details.disclosure > summary:hover { color: var(--accent); }
details.disclosure > summary:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; border-radius: var(--radius-sm); }

/* The form disclosures sit below a rule that separates them from the form. */
details.modify, details.post-review, details.abandon {
  margin-top: var(--space-4);
  border-top: 1px solid var(--line);
  padding-top: var(--space-3);
}
/* A group heading is a disclosure too, but it is the group card's title rather
   than a sub-form, so it wants no top rule of its own. */
details.cap-group > summary { border-top: 0; margin-top: 0; }

/* The card header marker echoes the inbox chip so an owed post-review is
   visible without scrolling to the form. */
.head-marker { margin: var(--space-2) 0 0; }

/* The inbox uses this as a plain marker, not a disclosure. */
span.post-review {
  display: inline-block;
  padding: 0.05rem 0.45rem;
  border-radius: var(--radius-pill);
  background: var(--warn-bg);
  color: var(--warn);
  font-size: 0.75rem;
  font-weight: 600;
}

.effects-edit { display: grid; gap: var(--space-3); margin-top: var(--space-3); }
.effect-edit {
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  padding: var(--space-3);
  margin: 0;
  background: var(--sunken);
}
.effect-edit legend { color: var(--muted); font-size: 0.78rem; padding: 0 0.3rem; }
.two { display: grid; grid-template-columns: 1fr 1fr; gap: var(--space-2); }

/* --- auth ---------------------------------------------------------------- */

.panel-auth { max-width: 28rem; margin: var(--space-6) auto; }
.panel-auth .decision button { width: 100%; margin-top: var(--space-4); }

.decided { border-left: 4px solid var(--line); }

/* --- admin: user accounts ------------------------------------------------- */

/* A user row is a self-contained record with its own actions, so it reads as a
   small card rather than a table: on a phone the actions would not fit a grid,
   and every field belongs to the one account above it. */
.user-rows { list-style: none; margin: 0 0 var(--space-4); padding: 0; display: grid; gap: var(--space-3); }
.user-row {
  background: var(--card);
  border: 1px solid var(--line);
  border-radius: var(--radius-md);
  box-shadow: var(--depth-1);
  padding: var(--space-4);
}
.user-head { display: flex; flex-wrap: wrap; align-items: baseline; gap: var(--space-2); }
.user-email { font-size: 0.95rem; overflow-wrap: anywhere; }
.user-meta { margin: var(--space-1) 0 0; }
.user-actions { display: flex; flex-wrap: wrap; gap: var(--space-2); margin-top: var(--space-3); }
/* The row's controls are secondary to the record, so they do not stretch to the
   full field width the global form rule sets. */
.inline-form { display: flex; flex-wrap: wrap; gap: var(--space-2); align-items: center; }
.inline-form select { width: auto; }
.inline-form .button { width: auto; min-height: 40px; padding: 0.5rem 0.9rem; }
.restore-form { margin-top: var(--space-3); }
.restore-form .field + .field { margin-top: var(--space-3); }
.restore-form .form-actions { margin-top: var(--space-4); }
.state-active { background: var(--ok-bg); color: var(--ok); }
.state-revoked { background: var(--bad-bg); color: var(--bad); }

/* The minted key is shown exactly once, so it is the loudest thing on the page
   at that moment: a distinct panel with the material selectable in one gesture.
   It is not a "success" colour — the key existing is the fact, not an approval. */
.key-reveal {
  border: 1px solid var(--line);
  border-left: 3px solid var(--accent);
  border-radius: var(--radius-md);
  background: var(--card);
  padding: var(--space-4);
  margin-bottom: var(--space-4);
}
.key-reveal p { margin: 0 0 var(--space-2); }
.key-material {
  display: block;
  padding: var(--space-3);
  background: var(--bg);
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  overflow-wrap: anywhere;
  user-select: all;
}

.empty { text-align: center; padding: var(--space-6) var(--space-4); }
.toggle { margin-top: var(--space-4); font-size: 0.9rem; display: flex; flex-wrap: wrap; gap: var(--space-3); }

/* --- signed-out home ------------------------------------------------------ */

.home-hero {
  text-align: center;
  max-width: 46rem;
  margin: 0 auto;
  padding-top: var(--space-4);
}
.home-pill {
  display: inline-block;
  padding: 0.25rem 0.7rem;
  border: 1px solid var(--line);
  border-radius: var(--radius-pill);
  background: var(--card);
  color: var(--muted);
  font-size: 0.78rem;
  font-weight: 600;
  letter-spacing: 0.01em;
}
/* A display size for this page only; the global h1 stays the inbox's size. */
.home-h1 {
  margin: var(--space-4) 0 0;
  font-size: clamp(2.75rem, 7vw, 4rem);
  line-height: 1.05;
  letter-spacing: -0.035em;
  font-weight: 700;
}
.home-sub {
  margin: var(--space-4) auto 0;
  max-width: 34rem;
  font-size: 1.1rem;
}
/* The top-bar button is enough on desktop; the hero button repeats on phones. */
.home-hero-cta { display: none; margin: var(--space-5) 0 0; }

.home-shot {
  max-width: 58rem;
  margin: var(--space-6) auto 0;
  background: var(--card);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg) var(--radius-lg) 0 0;
  box-shadow: var(--depth-3);
  overflow: hidden;
}
.home-shot-inner {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1.35fr);
}
/* On a laptop the picture is meant to run off the bottom edge of the first
   screen, as in the mockup, so it reads as "there is more of this" rather than
   a finished card. A min-height taller than the space under the hero does that
   on a typical laptop; on a very tall display it simply centres. */
@media (min-width: 601px) and (min-height: 700px) {
  .home-shot-inner { min-height: 34rem; }
}
.home-pane-list {
  border-right: 1px solid var(--line);
  padding: var(--space-3);
  background: color-mix(in srgb, var(--sunken) 40%, var(--card));
}
.home-pane-title {
  margin: 0 0 var(--space-2);
  padding: 0 var(--space-2);
  color: var(--muted);
  font-size: 0.78rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.04em;
}
.home-items { list-style: none; margin: 0; padding: 0; display: grid; gap: 2px; }
.home-item {
  display: flex;
  gap: var(--space-2);
  align-items: flex-start;
  padding: var(--space-2) var(--space-2);
  border-radius: var(--radius-sm);
}
.home-item.is-selected { background: var(--hover); }
.home-item.is-faded { opacity: 0.6; }
.home-item-body { display: grid; min-width: 0; }
.home-item-name { font-weight: 600; font-size: 0.9rem; }
.home-item-meta { color: var(--muted); font-size: 0.78rem; }
.home-dot {
  flex: 0 0 auto;
  width: 8px;
  height: 8px;
  margin-top: 0.4rem;
  border-radius: 50%;
  background: var(--muted);
}
.home-dot-warn { background: var(--warn); }
.home-dot-ok { background: var(--ok); }

.home-pane-detail { padding: var(--space-5); display: grid; gap: var(--space-3); align-content: start; }
/* The state pill hugs its text rather than stretching to the grid track. */
.home-pane-detail .state { justify-self: start; }
.home-detail-title { font-size: 1.25rem; font-weight: 700; }
.home-detail-reason { margin: 0; }
.home-mono {
  margin: 0;
  padding: var(--space-3);
  background: var(--sunken);
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  font-family: var(--mono);
  font-size: 0.85rem;
  line-height: 1.7;
  color: var(--fg);
}
.home-shot-actions { display: flex; flex-wrap: wrap; gap: var(--space-2); margin-top: var(--space-2); }
/* Illustration only: styled spans, never a focusable control. */
.home-btn {
  padding: 0.55rem 0.9rem;
  border-radius: var(--radius-sm);
  font-size: 0.9rem;
  font-weight: 600;
  box-shadow: var(--depth-1);
}
.home-btn-approve { background: var(--ok); color: #fff; }
.home-btn-modify { background: var(--accent); color: #fff; }
.home-btn-reject { background: var(--sunken); color: var(--fg); border: 1px solid var(--line); }
@media (prefers-color-scheme: dark) {
  .home-btn-approve, .home-btn-modify { color: #0d1014; }
}

.home-foot-hint { margin-top: var(--space-2); }

/* The top-bar pilot button is smaller than a page-level primary action. */
.topbar .button-pilot {
  min-height: 36px;
  padding: 0.4rem 0.85rem;
  font-size: 0.85rem;
  box-shadow: none;
}

/* --- narrow phones -------------------------------------------------------- */

/* A pill with brand + nav + identity + sign-out does not fit a phone, so the
   inline links collapse into the glass menu and the identity yields. */
@media (max-width: 600px) {
  .topbar-pill { padding-left: 0.85rem; gap: var(--space-1); }
  .brand { font-size: 0.95rem; margin-right: 0; }
  .topnav { display: none; }
  .linkish { padding: 0.3rem 0.4rem; font-size: 0.85rem; }
  .whoami { display: none; }
  /* A long action name and its clearance cannot share one line on a phone.
     Let the row wrap so the name stays whole and the clearance drops below it,
     rather than truncating the name an operator needs to read. */
  .cap-row { flex-wrap: wrap; row-gap: var(--space-1); }
  .cap-leaf { white-space: normal; overflow: visible; overflow-wrap: anywhere; }
  .clearance { margin-left: 0; flex-basis: 100%; }

  /* On a phone the top-bar pilot button yields to the hero, which shows the
     primary action under the supporting line at full width. */
  .topbar .button-pilot { display: none; }
  .home-hero-cta { display: block; }
  .home-hero-cta .button { display: block; width: 100%; }
  .home-h1 { margin-top: var(--space-3); }
  /* The phone picture is the detail pane alone, as in the mockup. */
  .home-shot-inner { grid-template-columns: 1fr; }
  .home-pane-list { display: none; }
  .home-pane-detail { padding: var(--space-4); }
}

@media (max-width: 360px) {
  .topbar-pill { padding-left: 0.6rem; }
  .brand { font-size: 0.85rem; }
  .topnav a { padding: 0.3rem 0.4rem; font-size: 0.8rem; }
  .linkish { padding: 0.3rem 0.35rem; font-size: 0.8rem; }
  .actions { grid-template-columns: 1fr; }
  .two { grid-template-columns: 1fr; }
  .kv { grid-template-columns: 1fr; }
  .kv dt { margin-top: var(--space-1); }
}
