/* Party First — the stylesheet.
 *
 * Hand-written, no framework. One design system, defined once as tokens and used everywhere:
 * a neutral ramp, one brand blue, and the four traffic-light hues. Nothing below hard-codes a
 * colour, a radius or a font size — if a value is worth using twice it is a token.
 *
 * The house rules this encodes:
 *   • Traffic lights are never the only signal — a dot always sits beside words, and the
 *     meaning is constant everywhere: green = with us / on track, amber = attention,
 *     red = against / action required, grey = not set. Positive is green, never blue.
 *   • Blue is the interface's accent (links, the active page, the primary button) and is not
 *     used to mean "good" — that would collide with the traffic lights.
 *   • Restraint: one accent, subtle depth, short transitions, generous whitespace. Colour
 *     carries meaning, so decorative colour is avoided.
 *
 * Layout order: tokens → reset → typography → shell → components → states → responsive.
 */

/* ============================================================ 1. tokens */

:root {
  /* ---- neutral ramp: every surface, border and shade of text ---- */
  --grey-25: #fbfcfd;
  --grey-50: #f6f8fa;
  --grey-100: #eef1f5;
  --grey-200: #e3e8ef;
  --grey-300: #cdd5e0;
  --grey-400: #98a2b3;
  /* --grey-500 is the lightest grey that still clears 4.5:1 on white (5.2:1); anything above
     --grey-400 reads as absent rather than as disabled. */
  --grey-500: #667085;
  --grey-600: #4b5565;
  --grey-700: #364152;
  --grey-800: #1f2a37;
  --grey-900: #121926;

  /* ---- brand: the one accent, anchored on the prototype's blue ---- */
  --brand-50: #eef3ff;
  --brand-100: #dde6fe;
  --brand-200: #c2d2fc;
  --brand-600: #1d4ed8;
  --brand-700: #1a43b4;
  --brand-800: #1e3a8a;

  /* ---- traffic lights: a vivid hue for the dot, a darker one for text on white ---- */
  --green: #0e9f6e;
  --green-ink: #05683f;
  --green-bg: #e3f5ec;
  /* Yellow, not orange: the swinger/attention colour ran orange (#f59e0b) and read too close
     to the red end of the scale. #eab308 keeps it unmistakably yellow while staying dark
     enough to hold up as a 10px dot on white. Requested 06/08/2026. */
  --amber: #eab308;
  --amber-ink: #92400e;
  --amber-bg: #fdf3e2;
  --red: #dc2626;
  --red-ink: #b42318;
  --red-bg: #fdeceb;
  --green-edge: #bfe6d4;
  --amber-edge: #f3ddb5;
  --red-edge: #f6cfcc;
  --grey-dot: #cbd5e0;
  --green-light: #86efac;
  --red-light: #fca5a5;

  /* ---- semantic surfaces and text ---- */
  /* These five are the prototype's palette, taken from its stylesheet rather than re-chosen.
     The rebuild is meant to look like the prototype, so the prototype owns these values. */
  --bg: #f4f6f9;
  --ink: #1c2733;
  --line: #e2e8f0;
  --muted: #5b6879;
  --row-hover: #eef2ff; /* the prototype's hover is a blue tint, not a grey one */

  --panel: #ffffff;
  --panel-sunken: var(--grey-50);
  /* A second, darker rule for the few places that must read as an edge rather than a hairline:
     the one line under a table header, a button's outline, a drop zone. It was aliased to
     --line, which left the header rule indistinguishable from the row rules it now replaces. */
  --line-strong: #cbd5e1;
  --ink-soft: var(--muted);
  --ink-muted: var(--muted);
  --accent: var(--brand-600);
  --accent-dark: var(--brand-800);
  --accent-wash: var(--brand-50);
  --brand: var(--brand-600); /* legacy alias */
  --grey: var(--grey-dot); /* legacy alias: the "not set" dot */
  --warn: var(--amber-ink);
  --warnbg: var(--amber-bg);

  /* ---- type scale ---- */
  --font: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;
  /* The scale is the prototype's, in its own rem values. This is a dense governance tool:
     the body text is 16px but the working UI — tables, meta, pills — sits well below it. */
  /* Uppercase micro-labels appeared in three different trackings, two of them at the same
     size and weight. Tracking should scale with size, so it is an em value and one token. */
  --track-caps: 0.05em;
  --text-2xs: 0.66rem; /* 10.6px — nav group labels */
  --text-xs: 0.75rem; /* 12px — table headings */
  --text-pill: 0.74rem; /* 11.8px — pills */
  --text-sm: 0.845rem; /* 13.5px — captions, meta */
  --text-md: 0.85rem; /* 13.6px — table body, dense UI */
  --text-nav: 0.87rem; /* 13.9px — sidebar items */
  --text-base: 1rem; /* 16px — body prose */
  --text-lg: clamp(1.0625rem, 1rem + 0.3125vw, 1.375rem); /* 17 → 20 @1280 → 22px */
  --text-xl: 1.15rem; /* 18.4px — the brand */
  /* The three display sizes breathe with the viewport; the working sizes do not. Each clamp
     is anchored so that at 1280px it resolves to exactly the value it had before — the
     prototype's proportions are preserved by construction, and only the room above 1280px is
     new. Table density stays fixed: --text-md and --text-xs are the prototype's and a
     governance table should read the same on every screen. */
  --text-2xl: clamp(1.375rem, 0.75rem + 0.9375vw, 1.875rem); /* 22 → 24 @1280 → 30px */
  --text-3xl: clamp(1.75rem, 0.95rem + 1.1875vw, 2.375rem); /* 28 → 30.4 @1280 → 38px */

  /* ---- spacing: a 4px base ---- */
  --space-1: 0.25rem;
  --space-2: 0.5rem;
  --space-3: 0.75rem;
  --space-4: 1rem;
  --space-5: 1.25rem;
  --space-6: 1.5rem;
  --space-8: 2rem;
  --space-10: 2.5rem;
  --gap: var(--space-4); /* legacy alias */

  /* ---- radii ---- */
  --radius-sm: 6px;
  --radius-md: 8px;
  --radius-lg: 12px;
  --radius-full: 999px;
  --radius: var(--radius-lg); /* legacy alias */

  /* ---- depth: subtle, never dramatic ---- */
  --shadow-xs: 0 1px 2px rgba(16, 24, 40, 0.04);
  --shadow-sm: 0 1px 3px rgba(16, 24, 40, 0.06), 0 1px 2px rgba(16, 24, 40, 0.04);
  --shadow-md: 0 4px 12px rgba(16, 24, 40, 0.07);
  --shadow-lg: 0 12px 32px rgba(16, 24, 40, 0.12);
  --ring: 0 0 0 3px rgba(29, 78, 216, 0.2);

  /* ---- motion: short, and switched off for those who ask ---- */
  --ease: cubic-bezier(0.4, 0, 0.2, 1);
  --fast: 120ms var(--ease);
  --slow: 200ms var(--ease);

  /* ---- structure ---- */
  --sidebar-w: 212px;
  --topbar-h: 60px;
  --content-max: 1180px;

  /* Layout rhythm. The prototype's values sat within 4px of each other — 18 inside a panel,
     20 between panels, 22 around the page — so nothing read as nested. These step decisively
     instead: what is inside a panel, what separates related panels, and what separates whole
     sections of a page are now three obviously different distances.

     Table rows are deliberately tighter than panels and prose: these lists are scanned, and
     the denser rhythm keeps more of a long worklist visible without shrinking its type. */
  /* Tells the browser to draw its own widgets — select popups, the date picker, scrollbars,
     autofill — for a light page. Without it they follow the OS, so a dark-mode machine got a
     dark calendar on a white form. One accent for every native control, in one place. */
  color-scheme: light;
  accent-color: var(--accent);

  --panel-pad: 24px;
  --panel-gap: 20px;
  --section-gap: 40px;
  --cell-pad-y: 7px;
  --cell-pad-x: 11px;
  --main-pad: 32px;
}

/* ============================================================ 2. reset */

*,
*::before,
*::after {
  box-sizing: border-box;
}

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

body {
  margin: 0;
  font-family: var(--font);
  font-size: var(--text-base);
  line-height: 1.55;
  color: var(--ink);
  background: var(--bg);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

h1,
h2,
h3,
p,
dl,
dd,
figure {
  margin: 0;
}

img,
svg {
  max-width: 100%;
}

/* The `hidden` attribute must win. Any author rule that sets `display` — `.form-error` sets
   flex — silently overrides the browser's own `[hidden] { display: none }`, which is how the
   upload page came to show "That is not an .xlsx file" before a file had been chosen. */
[hidden] {
  display: none !important;
}

/* The skip link's destination. `tabindex="-1"` in the layout makes <main> focusable so focus
   actually moves — without it the page scrolled but the next Tab went back to the topbar, and
   the link did nothing for the only person it exists for. scroll-margin keeps the heading out
   from under the sticky header; the ring is suppressed because the skip link itself already
   showed the user where they were going. */
.content:focus,
.app-main:focus {
  outline: none;
}
.content,
.app-main,
.card {
  scroll-margin-top: calc(var(--topbar-h) + var(--space-4));
}

/* One focus ring, everywhere, always visible. */
:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
  border-radius: var(--radius-sm);
}

/* ============================================================ 3. typography */

h1,
h2,
h3 {
  line-height: 1.3;
  letter-spacing: -0.011em;
  font-weight: 650;
  color: var(--ink);
  /* Even the lines of a heading rather than leaving one word stranded. */
  text-wrap: balance;
}

/* Prose gets the lighter treatment: no orphan on the last line, no rebalancing of long text. */
.cap,
.card p,
.empty-state,
.note-body {
  text-wrap: pretty;
}

a {
  color: var(--accent);
  text-decoration: none;
}
a:hover {
  color: var(--accent-dark);
  text-decoration: underline;
}

code {
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 0.9em;
  background: var(--grey-100);
  color: var(--ink-soft);
  padding: 0.1em 0.4em;
  border-radius: var(--radius-sm);
}

strong {
  font-weight: 650;
}

.muted {
  color: var(--ink-muted);
  font-size: var(--text-sm);
}

/* Visually hidden, still read aloud — lets a dot carry real words. */
.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
  border: 0;
}

.skip-link {
  position: absolute;
  left: -9999px;
  top: 0;
  z-index: 100;
  background: var(--accent);
  color: #fff;
  padding: var(--space-3) var(--space-4);
  border-radius: 0 0 var(--radius-md) 0;
  font-weight: 600;
}
.skip-link:focus {
  left: 0;
  text-decoration: none;
}

/* The page heading block: title, then one line saying what the page is for. */
.page-title {
  font-size: var(--text-2xl);
  font-weight: 700;
  letter-spacing: -0.015em;
  margin: 0 0 var(--space-1);
  display: flex;
  align-items: center;
  gap: var(--space-2);
  flex-wrap: wrap;
}
/* A page heading with something to say on the right of it — the date, the signed-in role. */
.page-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--space-4);
  flex-wrap: wrap;
}
.page-meta {
  color: var(--ink-muted);
  font-size: var(--text-sm);
}
.cap {
  color: var(--ink-soft);
  font-size: var(--text-sm);
  /* `ch` is the width of a zero, which is wider than the average character — 78ch was
     rendering about 96 characters a line, well past comfortable. */
  max-width: 62ch;
  margin: 0 0 var(--section-gap);
}
/* A page subline already has the main content column as its readable boundary. Applying the
   narrower prose measure here forced short introductions onto two lines while ample room sat
   beside them. Panel descriptions retain the measure; page introductions use the full row and
   still wrap naturally when the viewport itself becomes narrow. */
.content > .cap {
  max-width: none;
}
.card .cap {
  font-size: var(--text-sm);
  margin-bottom: 12px;
}
.proxy-found-intro {
  max-width: none;
}
.proxy-next-cell {
  min-width: min(20rem, 72vw);
}
.proxy-next-label {
  display: block;
  margin-bottom: var(--space-2);
  color: var(--ink-muted);
  font-size: var(--text-xs);
  font-weight: 600;
}
.proxy-row-actions {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: var(--space-2);
}
.proxy-row-actions .row-form {
  margin: 0;
}
.sec-head {
  font-size: 0.9rem;
  font-weight: 650;
  letter-spacing: normal;
  color: var(--ink);
  margin: 16px 0 8px;
}

/* ============================================================ 4. the shell */

.layout {
  display: grid;
  grid-template-columns: var(--sidebar-w) 1fr;
  grid-template-rows: auto 1fr;
  grid-template-areas:
    'top top'
    'side main';
  min-height: 100vh;
}

/* ---- topbar ---- */
.topbar {
  grid-area: top;
  display: flex;
  align-items: center;
  gap: var(--space-4);
  min-height: var(--topbar-h);
  padding: var(--space-3) var(--space-6);
  /* a grid item's default min-width:auto would let the header's contents push the whole
     layout wider than the viewport — let it shrink and truncate instead */
  min-width: 0;
  background: var(--panel);
  border-bottom: 1px solid var(--line);
  position: sticky;
  top: 0;
  z-index: 40;
}
.topbar .brand {
  /* A flex item by default shrinks below its content: the brand ellipsised to "Party Firs…"
     between 901 and 960px. There is room for it — it simply was not claiming it. */
  flex: none;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  color: var(--ink);
  font-weight: 700;
  font-size: var(--text-xl);
  letter-spacing: normal;
  white-space: nowrap;
}
.topbar .brand:hover {
  text-decoration: none;
}
.header-spacer {
  flex: 1;
}
.brand {
  font-weight: 680;
  letter-spacing: -0.02em;
}

.user-chip {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  font-size: var(--text-sm);
  color: var(--ink-soft);
  min-width: 0;
}
.role-badge {
  background: var(--accent-wash);
  color: var(--accent-dark);
  border-radius: var(--radius-full);
  padding: 0.15em 0.7em;
  font-size: var(--text-xs);
  font-weight: 600;
  white-space: nowrap;
}
.logout-form {
  display: inline;
}
.access-preview-chip {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  min-width: 0;
  padding: var(--space-2) var(--space-3);
  border-radius: var(--radius-full);
  background: var(--brand-800);
  color: #fff;
  font-size: var(--text-xs);
  white-space: nowrap;
}
.access-preview-chip strong {
  overflow: hidden;
  max-width: 14rem;
  text-overflow: ellipsis;
}
.access-preview-chip .role-badge {
  background: rgba(255, 255, 255, 0.16);
  color: #fff;
}
.preview-exit-form .linkbtn {
  border-color: var(--brand-800);
  color: var(--brand-800);
}

/* ---- sidebar ---- */
.sidebar {
  grid-area: side;
  /* The desktop navigation is pinned to the viewport. Sticky positioning can be rounded by
     a fraction of a pixel as the document crosses its sticking threshold, which makes this
     permanent left edge appear to twitch between otherwise identical pages. The grid still
     reserves this column for the main content. */
  position: fixed;
  top: var(--topbar-h);
  bottom: 0;
  left: 0;
  width: var(--sidebar-w);
  height: auto;
  background: var(--panel);
  border-right: 1px solid var(--line);
  padding: 10px 10px 24px;
  overflow-y: auto;
  overscroll-behavior: contain;
}
.nav-group + .nav-group {
  margin-top: 16px;
}
.nav-group-title {
  margin: 0 0 6px;
  padding: 0 10px;
  font-size: var(--text-2xs);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: var(--track-caps);
  color: var(--ink-muted);
}
.nav-disclosure > summary {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-2);
  cursor: pointer;
  list-style: none;
}
.nav-disclosure > summary::-webkit-details-marker {
  display: none;
}
.nav-disclosure > summary::after {
  content: '⌄';
  font-size: var(--text-sm);
  line-height: 1;
  transition: transform var(--fast);
}
.nav-disclosure:not([open]) > summary::after {
  transform: rotate(-90deg);
}
.nav-disclosure > summary:hover,
.nav-disclosure > summary:focus-visible {
  color: var(--ink);
}
.sidebar ul {
  list-style: none;
  margin: 0;
  padding: 0;
}
.sidebar a {
  display: block;
  padding: 8px 12px;
  margin-bottom: 1px;
  border-radius: var(--radius-md);
  color: var(--ink);
  font-size: var(--text-nav);
  font-weight: 400;
  transition:
    background var(--fast),
    color var(--fast);
}
.sidebar a:hover {
  background: var(--row-hover);
  color: var(--ink);
  text-decoration: none;
}
/* Solid, not a tint. Where you are should be unmistakable at a glance. */
.sidebar a.active {
  background: var(--accent);
  color: #fff;
  font-weight: 600;
}
/*
 * The click is answered before the page is. A server-rendered navigation spends a few hundred
 * milliseconds fetching and repainting, and until this the sidebar sat completely still through
 * all of it — so the first click read as a click that had missed, and people clicked again.
 * The destination takes the active style at once and runs a line along its base until the new
 * page arrives and replaces the whole sidebar anyway.
 */
.sidebar a.pending {
  background: var(--accent);
  color: #fff;
  font-weight: 600;
  position: relative;
  overflow: hidden;
}
.sidebar a.pending::after {
  content: '';
  position: absolute;
  left: 0;
  bottom: 0;
  height: 2px;
  width: 100%;
  background: rgba(255, 255, 255, 0.85);
  transform-origin: left;
  animation: nav-pending 1.1s ease-out infinite;
}
@keyframes nav-pending {
  0% {
    transform: scaleX(0);
    opacity: 1;
  }
  70% {
    transform: scaleX(1);
    opacity: 1;
  }
  100% {
    transform: scaleX(1);
    opacity: 0;
  }
}
/* Motion is decoration here — the colour change alone already answers the click. */
@media (prefers-reduced-motion: reduce) {
  .sidebar a.pending::after {
    animation: none;
  }
}

/* A contest's sub-pages sit under it, arrowed and slightly smaller. */
.sidebar a.subitem {
  font-size: var(--text-sm);
  padding: 6px 10px 6px 20px;
}
.sidebar a.subitem::before {
  content: '\2192';
  margin-right: 6px;
  opacity: 0.5;
}
.sidebar a.subitem.active::before {
  opacity: 0.85;
}

.nav-toggle {
  display: none;
  background: transparent;
  border: 1px solid var(--line);
  color: var(--ink-soft);
  border-radius: var(--radius-md);
  font-size: var(--text-lg);
  line-height: 1;
  cursor: pointer;
  padding: var(--space-2) var(--space-3);
}
.nav-toggle:hover {
  background: var(--grey-100);
}

/* ---- content column ---- */
.content {
  grid-area: main;
  /* A grid item defaults to min-width:auto, so a wide table would stretch the column past the
     viewport instead of scrolling inside its own wrapper. */
  min-width: 0;
  width: 100%;
  max-width: var(--content-max);
  margin: var(--main-pad) auto;
  padding: 0 var(--main-pad);
  /* The query container for everything on the page: panels ask how much room they have, not
     how wide the window is. */
  container: content / inline-size;
}

/* ---- signed-out shell (login) ---- */
.app-shell {
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  background: radial-gradient(120% 120% at 50% 0%, var(--brand-800) 0%, var(--brand-600) 100%);
}
.app-main {
  flex: 1;
  width: 100%;
  max-width: 960px;
  margin: 0 auto;
  padding: var(--space-6);
  display: flex;
  flex-direction: column;
  justify-content: center;
}
.app-footer {
  padding: var(--space-4) var(--space-6);
  color: var(--ink-muted);
  font-size: var(--text-sm);
  border-top: 1px solid var(--line);
}
.auth-card {
  max-width: 26rem;
  width: 100%;
  margin: var(--space-8) auto;
  padding: var(--space-8);
  border: 0;
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-lg);
}
.auth-card .page-title,
.auth-card h1 {
  font-size: var(--text-xl);
}
.auth-card .cap {
  margin-bottom: var(--space-5);
}
/* the note under the sign-in button needs air, not a hairline of it */
.auth-card form + .muted {
  display: block;
  margin-top: var(--space-5);
  padding-top: var(--space-4);
  border-top: 1px solid var(--line);
}

/* ============================================================ 5. components */

/* ---- card / panel ---- */
/* A panel is a hairline box on a grey field — no shadow. Stacking shadows down a long page
   was what made the rebuild read as a generic dashboard rather than this tool. */
.card {
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  padding: var(--panel-pad);
}
.card + .card {
  margin-top: var(--panel-gap);
}
.card h1 {
  font-size: var(--text-xl);
  margin-bottom: var(--space-2);
}
/* A panel title has to announce a panel. At 16px it was within half a pixel of body text and
   announced nothing; 20px puts a real step between the page title, the panel and the prose. */
.card h2 {
  font-size: var(--text-lg);
  font-weight: 650;
  letter-spacing: -0.01em;
  margin: 0 0 var(--space-1);
}

/* A panel was a heading and then nothing: white box, h2, prose, content, with no separation
   and no variation between a panel that summarises and one that lists. One hairline under the
   head gives every panel a structure; .card--summary lifts the one panel per page that is the
   answer rather than the detail. One differing is what makes the rest recede. */
.card > h2:first-of-type {
  padding-bottom: var(--space-3);
  border-bottom: 1px solid var(--line);
  margin-bottom: var(--space-4);
}
.card > h2:first-of-type + .cap {
  margin-top: calc(var(--space-3) * -1);
}
.card--summary > h2:first-of-type,
.card--summary > .panel-head {
  background: var(--panel-sunken);
  margin: calc(var(--panel-pad) * -1) calc(var(--panel-pad) * -1) var(--space-4);
  padding: var(--space-4) var(--panel-pad);
  border-bottom: 1px solid var(--line);
  border-radius: var(--radius-lg) var(--radius-lg) 0 0;
}

/* The prototype's needing-a-proxy panels: a red left edge marks a panel that is itself an
   action item. The edge is never the only signal — the panel opens with a red pill saying so. */
.card--alert {
  border-left: 3px solid var(--red);
}

/* Drag-to-rank. The grip is the visible promise that a row can be picked up; it only shows
   when the script is running (html.js), because without JavaScript the promise would be a
   lie — the ↑/↓ buttons carry ordering then. */
.drag-grip {
  display: none;
  color: var(--grey-400);
  cursor: grab;
  user-select: none;
}
html.js [data-reorder-url] .drag-grip {
  display: inline;
}
/* Once dragging is live the ↑/↓ forms are clutter — the same rows now move by hand. They
   come back whenever the script is off, where they are the only way to rank. */
html.js [data-reorder-url] form[action$='/move/up'],
html.js [data-reorder-url] form[action$='/move/down'] {
  display: none;
}
html.js [data-reorder-url] [data-drag-id] {
  cursor: grab;
}
[data-drag-id].dragging {
  opacity: 0.4;
}
[data-drag-id].drag-over {
  outline: 2px solid var(--accent);
  outline-offset: -2px;
}

.panel-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--space-4);
  flex-wrap: wrap;
  margin-bottom: var(--space-4);
}
.panel-head h2 {
  margin: 0;
}
.panel-head .ctx {
  color: var(--ink-muted);
  font-size: var(--text-sm);
}
.panel-head .ctx strong {
  color: var(--ink);
}

.crumb {
  font-size: var(--text-sm);
  margin-bottom: var(--space-3);
}
.crumb a {
  color: var(--ink-soft);
  font-weight: 500;
}
.crumb a:hover {
  color: var(--accent);
}

/* ---- stat tiles ---- */
/* Two surfaces, not one.
   Summary tiles are lifted a single step off the grey field — no border, a soft shadow — and
   content panels stay flat with a hairline. Before, every box on the page had identical weight
   and nothing led; giving exactly one thing elevation is what makes the rest recede. One step
   only: shadows on everything is how the earlier pass ended up reading as a generic dashboard. */
.tiles {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
  gap: var(--space-4);
  margin: 0 0 var(--section-gap);
}
/* A column, so the label can be ordered above the figure without touching every template
   that builds a tile. */
.tile {
  display: flex;
  flex-direction: column;
  background: var(--panel);
  border: 0;
  border-radius: var(--radius-lg);
  padding: var(--space-5) var(--space-5) var(--space-4);
  box-shadow: var(--shadow-sm);
}
/* The label leads and the figure answers it, so the eye lands on the number last and stays.
   The figure is the accent colour — in the prototype the numbers are what carry the page. */
/* Sentence case, as the prototype has it. Uppercase is the one place in this app where the
   treatment costs layout: at 375px "Delegates Entitled" and "Supportive Members" each wrapped
   to two lines and knocked the figures out of line across the row. */
.tile .lbl {
  display: flex;
  align-items: center;
  color: var(--ink-muted);
  font-size: var(--text-sm);
  font-weight: 500;
  margin: 0 0 var(--space-2);
  order: -1;
}
/* margin-top:auto pins the figure to the bottom of the tile, so a label that wraps to two
   lines does not push its number out of line with the others across the row. */
.tile .big {
  margin-top: auto;
  font-size: var(--text-3xl);
  font-weight: 700;
  line-height: 1.05;
  letter-spacing: -0.02em;
  color: var(--accent);
  font-variant-numeric: tabular-nums;
}
.tile .big .muted {
  font-size: var(--text-base);
  font-weight: 500;
  letter-spacing: normal;
}
/* A figure may carry a status hue; the words beside it still say what it means. */
.tile .big.num-red {
  color: var(--red-ink);
}
.tile .big.num-warn {
  color: var(--amber-ink);
}
.tile .big.num-green {
  color: var(--green-ink);
}
.tile .big.num-grey {
  color: var(--ink-muted);
}

/* A trailing block inside a card should not add space the card already provides. */
.card > *:last-child,
.card > .tiles:last-child,
.card > .table-scroll:last-child,
.card > .kv:last-child {
  margin-bottom: 0;
}

/* On the grey field a tile is lifted a step. Inside a white panel there is no field to lift
   off, and a 6%-alpha shadow on white-over-white gave no edge at all — so nested tiles take
   the prototype's hairline instead. One rule; no template has to know. */
.card .tile {
  box-shadow: none;
  border: 1px solid var(--line);
}

/* ---- Party Units directory ---- */
.unit-finder .toolbar {
  margin-bottom: var(--space-2);
}
.unit-finder .count-note {
  margin: 0;
}
.unit-directory {
  display: grid;
  gap: var(--section-gap);
  margin-top: var(--section-gap);
}
.unit-group-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--space-4);
  margin-bottom: var(--space-3);
}
.unit-group-head h2 {
  margin: 0;
  font-size: var(--text-lg);
}
.unit-group-head span {
  color: var(--ink-muted);
  font-size: var(--text-sm);
}
.unit-card-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 20rem), 1fr));
  gap: var(--panel-gap);
  align-items: stretch;
}
.unit-directory-card {
  display: flex;
  flex-direction: column;
  min-width: 0;
  padding: var(--space-5);
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
}
.unit-card-copy h3 {
  margin: 0 0 var(--space-1);
  font-size: var(--text-md);
}
.unit-card-copy p {
  margin: 0;
  color: var(--ink-soft);
  font-size: var(--text-sm);
}
.unit-card-metric {
  display: flex;
  align-items: baseline;
  gap: var(--space-2);
  margin-top: var(--space-5);
}
.unit-card-metric strong {
  color: var(--accent);
  font-size: var(--text-3xl);
  line-height: 1;
  letter-spacing: -0.02em;
  font-variant-numeric: tabular-nums;
}
.unit-card-metric span {
  color: var(--ink-muted);
  font-size: var(--text-sm);
  font-weight: 550;
}
.unit-card-detail {
  margin: var(--space-2) 0 var(--space-4);
  color: var(--ink-muted);
  font-size: var(--text-xs);
}
.unit-card-action {
  align-self: flex-start;
  margin-top: auto;
}
.unit-reference {
  margin-top: var(--section-gap);
}
.unit-reference-item {
  border-top: 1px solid var(--line);
}
.unit-reference-item:last-child {
  border-bottom: 1px solid var(--line);
}
.unit-reference-item > summary {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto 1rem;
  align-items: center;
  gap: var(--space-4);
  padding: var(--space-3) 0;
  color: var(--ink);
  font-size: var(--text-sm);
  font-weight: 650;
  cursor: pointer;
  list-style: none;
}
.unit-reference-item > summary::-webkit-details-marker {
  display: none;
}
.unit-reference-item > summary::after {
  content: '›';
  color: var(--ink-muted);
  font-size: var(--text-lg);
  line-height: 1;
  text-align: center;
  transform: rotate(90deg);
  transition: transform var(--fast);
}
.unit-reference-item:not([open]) > summary::after {
  transform: rotate(0);
}
.unit-reference-item > summary span:last-child {
  color: var(--ink-muted);
  font-weight: 500;
}
.unit-reference-item[open] > summary {
  color: var(--accent);
}
.unit-reference-item > .table-scroll {
  margin: 0 0 var(--space-4);
}

/* State Executive position groups are short, related tables. Pairing them on wide screens
   keeps the page compact while preserving one readable column on narrow screens. */
.executive-groups {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 25rem), 1fr));
  gap: var(--space-6);
  align-items: start;
}
.executive-group {
  min-width: 0;
}
.executive-group .sec-head {
  margin: 0 0 var(--space-2);
}
.executive-group .table-scroll,
.executive-support-table {
  margin-bottom: 0;
}
.executive-results-note {
  margin-top: var(--space-5);
  padding-top: var(--space-3);
  border-top: 1px solid var(--line);
}
.assembly-source-detail,
.assembly-manage-link {
  display: block;
  margin-top: 2px;
  font-size: var(--text-xs);
}
.assembly-party-room-status {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: var(--space-2) var(--space-5);
  margin-top: var(--space-4);
  padding: var(--space-3) var(--space-4);
  border: 1px solid var(--line);
  border-radius: var(--radius-md);
  background: var(--panel-sunken);
  font-size: var(--text-sm);
}

a.tile-link {
  color: inherit;
  transition:
    box-shadow var(--fast),
    background var(--fast);
}
/* A tile that is also the filter currently applied. */
a.tile-link[aria-current='page'] {
  border-color: var(--accent);
  box-shadow: var(--ring);
}

a.tile-link:hover {
  box-shadow: var(--shadow-md);
  background: var(--panel);
  text-decoration: none;
}

/* ---- traffic-light dot ---- */
.tl-dot {
  display: inline-block;
  flex: none;
  width: 8px;
  height: 8px;
  border-radius: var(--radius-full);
  margin-right: var(--space-2);
  background: var(--grey-dot);
  box-shadow: 0 0 0 1px rgba(16, 24, 40, 0.08);
}
.tl-green {
  background: var(--green);
}
.tl-green-light {
  background: var(--green-light);
}
.tl-amber {
  background: var(--amber);
}
.tl-red {
  background: var(--red);
}
.tl-red-light {
  background: var(--red-light);
}
.tl-grey {
  background: var(--grey-dot);
}

/* ---- pills: a label whose words carry the meaning, colour only reinforces ---- */
/* The prototype's pill palette. Mine had flattened every hue to the same pale wash, which
   lost the five-point scale's light/solid distinction — a Strong and a Leaning read alike. */
.pill {
  display: inline-block;
  padding: 2px 8px;
  border-radius: var(--radius-full);
  font-size: var(--text-pill);
  font-weight: 500;
  line-height: 1.35;
  white-space: nowrap;
  background: #e0e7ff;
  color: #3730a3;
}
.pill.blue {
  background: var(--accent);
  color: #fff;
}
.pill.ltblue {
  background: #bfdbfe;
  color: #1e3a8a;
}
.pill.green {
  background: #bbf7d0;
  color: #166534;
}
.pill.solidgreen {
  background: #0a7f57;
  color: #fff;
}
.pill.yellow {
  background: #fde68a;
  color: #92400e;
}
.pill.ltred {
  background: #fecaca;
  color: #991b1b;
}
.pill.solidred {
  background: var(--red);
  color: #fff;
}
.pill.grey {
  background: var(--line);
  color: #475569;
}
.pill.metro {
  background: #dbeafe;
  color: #1e40af;
}
.pill.country {
  background: #dcfce7;
  color: #166534;
}
.pill.tba {
  background: var(--warnbg);
  color: var(--warn);
}
.pill.warn {
  background: #fee2e2;
  color: #991b1b;
}
.page-title .pill {
  font-size: var(--text-sm);
  font-weight: 500;
}

/* ---- tab strip: one of a small set of sibling views ---- */
/* The prototype's .rr-tab: a bordered pill, the current one filled with the accent. */
.tabset {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
  margin: 0 0 var(--space-4);
}
.tabset a {
  border: 1px solid var(--line);
  background: var(--panel);
  border-radius: var(--radius-md);
  padding: 9px 20px;
  font-size: var(--text-sm);
  font-weight: 600;
  color: var(--ink-muted);
}
.tabset a:hover {
  background: var(--grey-100);
  color: var(--ink);
  text-decoration: none;
}
.tabset a.active {
  background: var(--accent);
  border-color: var(--accent);
  color: #fff;
}

.organiser-worklist-tabs a {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
}
.worklist-tab-count {
  min-width: 1.6rem;
  padding: 1px 6px;
  border-radius: var(--radius-full);
  background: var(--grey-100);
  color: var(--ink-muted);
  font-size: var(--text-xs);
  text-align: center;
  font-variant-numeric: tabular-nums;
}
.organiser-worklist-tabs a.active .worklist-tab-count {
  background: rgba(255, 255, 255, 0.2);
  color: #fff;
}
.organiser-worklist-card .toolbar {
  margin-top: var(--space-4);
}
.organiser-worklist-table td {
  vertical-align: middle;
}
.organiser-worklist-table td:first-child .muted {
  display: block;
  margin-top: 2px;
  font-size: var(--text-xs);
}

/* ---- a few spacing utilities ----
   These exist because a strict `style-src 'self'` CSP silently discards every `style="…"`
   attribute: four of them were in the templates doing nothing at all, and one meant a vote
   field rendered full-width instead of 6rem. `npm run check` now fails on the attribute. */
.flush {
  margin: 0;
}
.spaced {
  margin-top: var(--space-3);
}
.vote-input {
  width: 6rem;
}

/* ---- filter chips ---- */
.chips {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
  margin: 0 0 var(--space-4);
}
.chip {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  background: var(--panel);
  border: 1px solid var(--line);
  color: var(--ink-soft);
  border-radius: var(--radius-full);
  padding: 0.2em 0.75em;
  font-size: var(--text-sm);
}
.chip a {
  color: var(--ink-muted);
  font-weight: 600;
  line-height: 1;
}
.chip a:hover {
  color: var(--red-ink);
  text-decoration: none;
}

/* ---- buttons ---- */
button,
.btn-ghost {
  font: inherit;
  font-size: var(--text-sm);
  font-weight: 600;
  line-height: 1.2;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  padding: 6px 13px;
  min-height: 30px;
  border-radius: 7px;
  border: 1px solid var(--accent);
  background: var(--accent);
  color: #fff;
  cursor: pointer;
  white-space: nowrap;
  transition:
    background var(--fast),
    border-color var(--fast),
    box-shadow var(--fast);
}
button:hover {
  background: var(--brand-700);
  border-color: var(--brand-700);
}
button:active {
  background: var(--brand-800);
  border-color: var(--brand-800);
}
button:disabled,
button[aria-disabled='true'] {
  background: var(--grey-200);
  border-color: var(--grey-200);
  color: var(--grey-500);
  cursor: not-allowed;
}

/* A link that is the page's primary action. The campaigner's Today has exactly one job and
   it was wearing the quietest control on the page. */
a.btn-link {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  font: inherit;
  font-size: var(--text-sm);
  font-weight: 600;
  padding: 6px 13px;
  min-height: 30px;
  border-radius: 7px;
  border: 1px solid var(--accent);
  background: var(--accent);
  color: #fff;
}
a.btn-link:hover {
  background: var(--brand-700);
  border-color: var(--brand-700);
  color: #fff;
  text-decoration: none;
}

/* secondary: the quieter action beside a primary one */
.btn-ghost {
  background: var(--panel);
  color: var(--accent);
  border-color: var(--line-strong);
  text-decoration: none;
}
.btn-ghost:hover {
  background: var(--accent-wash);
  border-color: var(--brand-200);
  color: var(--accent-dark);
  text-decoration: none;
}

.btn-block {
  width: 100%;
}

/* a bordered button that reads as chrome, not action (the header's Sign out) */
.linkbtn {
  background: var(--panel);
  color: var(--ink-soft);
  border: 1px solid var(--line-strong);
  font-size: var(--text-sm);
  font-weight: 550;
  padding: 0.4rem 0.8rem;
  min-height: 34px;
}
.linkbtn:hover {
  background: var(--grey-100);
  border-color: var(--line-strong);
  color: var(--ink);
}

/* An action that lives inside a sentence or a table cell.
   min-height is 24px, not 0: WCAG 2.2 asks for a 24px target and "retire" is destructive.
   Centring costs no layout — the line box was already taller than the text. */
.linktext {
  background: none;
  border: 0;
  color: var(--red-ink);
  padding: 0 var(--space-1);
  min-height: 24px;
  display: inline-flex;
  align-items: center;
  font: inherit;
  font-size: var(--text-sm);
  font-weight: 500;
  text-decoration: underline;
  text-underline-offset: 2px;
  cursor: pointer;
}
.linktext:hover,
.linktext:active {
  background: none;
  color: var(--red);
}
.linktext.move {
  color: var(--accent);
}
.linktext.move:hover {
  color: var(--accent-dark);
}
.inline-form {
  display: inline;
}

a.reclink {
  color: var(--accent);
  font-weight: 500;
}
a.reclink:hover {
  color: var(--accent-dark);
}
td .rowname,
.rowname {
  font-weight: 600;
}

/* ---- forms ---- */
.stack {
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
  max-width: 30rem;
}
.stack-full {
  max-width: none;
}

/* A form of many short fields reads better in columns than as one long ladder. Buttons and
   anything marked .full still span the width. */
.form-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 15rem), 1fr));
  gap: var(--space-4);
  max-width: none;
}
.form-grid > button,
.form-grid > .row-form,
.form-grid > .full,
.form-grid > fieldset,
.form-grid > .two-col,
.form-grid > h3,
.form-grid > p,
.form-grid > label.checkbox {
  grid-column: 1 / -1;
}
.form-grid > h3 {
  margin-top: var(--space-2);
}
.form-grid > button {
  justify-self: start;
}
.stack label,
.toolbar label,
.two-col label,
label.seat-row,
.linked-seat-row {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  font-size: var(--text-sm);
  font-weight: 600;
  color: var(--ink-soft);
}
.linked-seat-value {
  min-height: 34px;
  padding: 7px 10px;
  border: 1px solid var(--line);
  border-radius: var(--radius-md);
  background: var(--panel-sunken);
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: var(--space-2) var(--space-4);
  font-weight: 400;
  color: var(--ink);
}
input[type='text'],
input[type='search'],
input[type='email'],
input[type='password'],
input[type='date'],
input[type='number'],
input:not([type]),
select,
textarea {
  font: inherit;
  font-size: 0.88rem;
  font-weight: 400;
  color: var(--ink);
  background: var(--panel);
  padding: 7px 10px;
  border: 1px solid var(--line);
  border-radius: var(--radius-md);
  transition:
    border-color var(--fast),
    box-shadow var(--fast);
  min-height: 34px;
  width: 100%;
}
textarea {
  resize: vertical;
  line-height: 1.5;
}
input:hover,
select:hover,
textarea:hover {
  border-color: var(--grey-400);
}
input:focus,
select:focus,
textarea:focus {
  outline: none;
  border-color: var(--accent);
  box-shadow: var(--ring);
}
input::placeholder,
textarea::placeholder {
  color: var(--grey-400);
}
input:disabled,
select:disabled,
textarea:disabled {
  background: var(--grey-50);
  color: var(--ink-muted);
  cursor: not-allowed;
}

.stack label.checkbox,
fieldset.outcomes label.checkbox {
  flex-direction: row;
  align-items: center;
  gap: var(--space-2);
  font-size: var(--text-base);
  font-weight: 400;
  color: var(--ink);
  cursor: pointer;
}
label.checkbox input[type='checkbox'],
label.checkbox input[type='radio'] {
  width: auto;
  min-height: 0;
  margin: 0;
  accent-color: var(--accent);
  /* a comfortable target without knocking the row's rhythm out */
  width: 1rem;
  height: 1rem;
}

fieldset.outcomes {
  border: 1px solid var(--line);
  border-radius: var(--radius-md);
  padding: var(--space-3) var(--space-4) var(--space-4);
  margin: 0;
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2) var(--space-5);
}
.report-rec-fields {
  margin: 0;
  padding: var(--space-3) var(--space-4) var(--space-4);
  border: 1px solid var(--line);
  border-radius: var(--radius-md);
  background: var(--panel-sunken);
}
.report-rec-fields legend {
  padding: 0 var(--space-2);
  color: var(--ink);
  font-size: var(--text-sm);
  font-weight: 650;
}
.report-rec-fields .cap {
  margin-bottom: var(--space-3);
}

.report-delegate-groups {
  display: grid;
  gap: 0.65rem;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 20rem), 1fr));
}

.report-delegate-group {
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  background: var(--panel);
}

.report-delegate-group > summary {
  cursor: pointer;
  padding: 0.7rem 0.85rem;
  font-weight: 700;
}

.report-delegate-list {
  display: grid;
  gap: 0.4rem;
  padding: 0 0.65rem 0.65rem;
}

.report-delegate-row {
  display: grid;
  grid-template-columns: 1.5rem minmax(0, 1fr);
  align-items: center;
  gap: 0.45rem;
}

.report-delegate-row > span {
  color: var(--muted);
  font-variant-numeric: tabular-nums;
  text-align: right;
}

.report-delegate-row .gs-results {
  grid-column: 2;
}
.agm-meeting-form {
  margin-top: var(--space-5);
  padding-top: var(--space-4);
  border-top: 1px solid var(--line);
}
fieldset.outcomes legend {
  font-size: var(--text-sm);
  font-weight: 600;
  color: var(--ink-soft);
  padding: 0 var(--space-2);
}

/* a row of controls that reads as one line: search + filters + apply */
/* A toolbar is a row of controls, not a form section — no divider rule beneath it. */
.toolbar {
  display: flex;
  flex-wrap: wrap;
  gap: 9px;
  align-items: flex-end;
  margin-bottom: 12px;
}
.toolbar .grow {
  flex: 1;
  min-width: 14rem;
}
.toolbar input,
.toolbar select {
  font-size: var(--text-md);
}
.toolbar button {
  min-height: 38px;
}
.toolbar > .toolbar-action {
  min-height: 38px;
}
.member-search {
  position: relative;
}
.member-search .gs-results {
  min-width: min(24rem, 90vw);
  right: auto;
}

/* controls sitting inline in a table row or beneath a list */
.row-form {
  display: flex;
  gap: var(--space-2);
  flex-wrap: wrap;
  align-items: center;
}
.row-form input,
.row-form select {
  font-size: var(--text-md);
  min-height: 34px;
  padding: 0.35rem 0.6rem;
  width: auto;
}
.row-form button {
  min-height: 34px;
  padding: 0.4rem 0.85rem;
  font-size: var(--text-sm);
}
.row-form label {
  flex-direction: row;
  align-items: center;
  gap: var(--space-2);
}

/* ---- feedback ---- */
.form-error,
.form-warn,
.form-ok {
  display: flex;
  align-items: flex-start;
  gap: var(--space-2);
  padding: var(--space-3) var(--space-4);
  border-radius: var(--radius-md);
  font-size: var(--text-md);
  font-weight: 500;
  border: 1px solid transparent;
  margin-bottom: var(--space-4);
}
.form-error {
  background: var(--red-bg);
  border-color: var(--red-edge);
  color: var(--red-ink);
}
.form-ok {
  background: var(--green-bg);
  border-color: var(--green-edge);
  color: var(--green-ink);
}
/* Amber: worth knowing before you act, but nothing has gone wrong. */
.form-warn {
  background: var(--amber-bg);
  border-color: var(--amber-edge);
  color: var(--amber-ink);
}
.card > .form-error:last-child,
.card > .form-ok:last-child {
  margin-bottom: 0;
}

/* ---- tables ---- */
.table-scroll {
  overflow-x: auto;
  /* let a focus ring on a cell control breathe rather than clipping it */
  padding: 2px;
  margin: 0 -2px;
  /* A cut-off table looked identical to a complete one. These four layers fade the edge only
     while there is more to see: the two `local` gradients scroll away with the content, the
     two `scroll` shadows stay put, so the shadow appears exactly when the white does not
     reach the edge. Pure CSS, which the CSP requires. */
  background:
    linear-gradient(to right, var(--panel) 30%, rgba(255, 255, 255, 0)) left / 32px 100%
      no-repeat,
    linear-gradient(to left, var(--panel) 30%, rgba(255, 255, 255, 0)) right / 32px 100%
      no-repeat,
    radial-gradient(farthest-side at 0 50%, rgba(16, 24, 40, 0.14), transparent) left / 12px
      100% no-repeat,
    radial-gradient(farthest-side at 100% 50%, rgba(16, 24, 40, 0.14), transparent) right /
      12px 100% no-repeat;
  background-attachment: local, local, scroll, scroll;
}
/* Focusable, so the hidden columns can be reached without a mouse. */
.table-scroll:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}
table.grid {
  width: 100%;
  border-collapse: collapse;
  font-size: var(--text-md);
  /* Prose leading (1.55) inside a data row adds 6px of dead space to every line. A grid is
     scanned, not read, so it gets its own tighter leading. */
  line-height: 1.35;
}
table.grid th,
table.grid td {
  text-align: left;
  padding: var(--cell-pad-y) var(--cell-pad-x);
  /* No rule under every row. A hairline beneath 50 rows of a seven-column table is what made
     these read as busy; the space between rows separates them, and the hover wash is what
     tracks the eye across one. Only the header keeps a rule, and it is the stronger for being
     the only one. */
  border-bottom: 0;
  /* top, not middle: a wrapped cell should hang off the same baseline as its neighbours
     rather than float in the middle of a taller row */
  vertical-align: top;
  overflow-wrap: break-word;
}
table.grid thead th {
  color: var(--ink-muted);
  font-size: var(--text-xs);
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: var(--track-caps);
  white-space: nowrap;
  border-bottom: 1px solid var(--line-strong);
  padding-bottom: var(--space-2);
}
/* A key/value table has no header to anchor it, so its rows keep their rules. */
table.grid.keyed td {
  border-bottom: 1px solid var(--line);
}
table.grid th.wrap {
  white-space: normal;
}
table.grid td.nw,
table.grid .nw {
  white-space: nowrap;
}
table.grid tbody tr:last-child td {
  border-bottom: 0;
}
table.grid tbody tr {
  transition: background var(--fast);
}
table.grid tbody tr:hover {
  background: var(--row-hover);
}
/* Dropping the per-row hairline was right; replacing it with nothing was the overshoot. A row
   band mixed from the surface itself — about a 3% tint, far lighter than a rule — carries the
   eye across seven columns for readers, keyboard users and print, where :hover carries nobody.
   Applied only where a table is long enough to lose your place in. */
/* A zebra was the wrong instrument: at 97% the band is 1.06:1 on white and the hover wash is
   1.05:1 against the band, so hovering an even row would show almost nothing. A rule at 70% of
   the prototype's hairline reads at 1.15:1 — lighter than the prototype's, and it survives
   being hovered over. Only on tables wide and long enough to lose your place in. */
table.grid.tracked tbody td {
  border-bottom: 1px solid color-mix(in oklab, var(--line) 70%, var(--panel));
}
table.grid.tracked tbody tr:last-child td {
  border-bottom: 0;
}

table.grid td.empty {
  color: var(--ink-muted);
  font-style: italic;
}
/* figures line up when they are tabular */
table.grid td {
  font-variant-numeric: tabular-nums;
}

table.grid th a.sort {
  display: inline-flex;
  align-items: center;
  gap: var(--space-1);
  color: inherit;
  cursor: pointer;
}
table.grid th a.sort:hover {
  color: var(--ink);
  text-decoration: none;
}
table.grid th[aria-sort] a.sort {
  color: var(--accent);
}
.sort-arrow {
  font-size: 0.6rem;
}

.count-note {
  color: var(--ink-muted);
  font-size: var(--text-sm);
  margin: 0 0 var(--space-3);
}

/* ---- empty state ---- */
.empty-state {
  text-align: center;
  padding: var(--space-10) var(--space-4);
  color: var(--ink-muted);
  font-size: var(--text-md);
  background: var(--panel-sunken);
  border: 1px dashed var(--line-strong);
  border-radius: var(--radius-md);
}
.empty-state strong {
  display: block;
  color: var(--ink);
  font-size: var(--text-base);
  margin-bottom: var(--space-1);
}

/* ---- pager ---- */
.pager {
  display: flex;
  gap: var(--space-2);
  align-items: center;
  flex-wrap: wrap;
  margin-top: var(--space-5);
  font-size: var(--text-sm);
}
.pager a,
.pager span {
  padding: 0.4rem 0.8rem;
  border: 1px solid var(--line-strong);
  border-radius: var(--radius-md);
  background: var(--panel);
  color: var(--ink-soft);
  font-weight: 500;
}
.pager a:hover {
  background: var(--grey-100);
  color: var(--ink);
  text-decoration: none;
}
.pager .current {
  background: var(--grey-100);
  border-color: var(--line);
  color: var(--ink);
}
.pager .disabled {
  /* grey-400 measured 2.58:1 on white — "Page 1 of 22" was hard to read. grey-500 is 5.2:1
     and still plainly reads as unavailable. */
  color: var(--grey-500);
  border-color: var(--line);
}

/* ---- key/value lists ---- */
.kv,
.status-grid {
  display: grid;
  grid-template-columns: max-content 1fr;
  gap: var(--space-3) var(--space-6);
  margin: 0;
  font-size: var(--text-md);
}
.kv dt,
.status-grid dt {
  font-weight: 600;
  color: var(--ink-muted);
  font-size: var(--text-sm);
}
.kv dd,
.status-grid dd {
  margin: 0;
  color: var(--ink);
}

/* ---- two-column layouts and plain lists ---- */
/* A run of panels that belong together. --section-gap existed and was used twice in the whole
   stylesheet, so every page read as one undifferentiated stack: five unrelated panels at a flat
   20px each. Panels inside a section keep --panel-gap; between sections the page breathes. */
.page-section + .page-section,
.card + .page-section,
.page-section + .card,
.tiles + .page-section {
  margin-top: var(--section-gap);
}
.page-section > .card + .card,
.page-section > .panel-pair {
  margin-top: var(--panel-gap);
}

/* Two whole panels sharing a row, each keeping its own heading. Panels in the same grid row
   stretch to the tallest one so their lower edges line up; once they stack, each row resumes
   its natural content height. */
.panel-pair {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 26rem), 1fr));
  gap: var(--panel-gap);
  align-items: stretch;
}
.card + .panel-pair,
.panel-pair + .card,
.panel-pair + .panel-pair {
  margin-top: var(--panel-gap);
}
.panel-pair > .card + .card {
  margin-top: 0;
}

/* The men's and women's halves of the ticket, side by side. They are the same ballot asked
   twice, so they stay level with each other rather than stacking at the first excuse. */
.ticket-cols {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 17rem), 1fr));
  gap: var(--space-5);
  align-items: start;
}
.ticket-cols h3 {
  margin: 0 0 var(--space-2);
  font-size: 0.9rem;
}
.ticket-cols h3 .muted {
  font-weight: 400;
}
/* The rank column is as narrow as the number in it. */
table.ticket-table th.rank,
table.ticket-table td.rank {
  width: 1%;
  white-space: nowrap;
  text-align: right;
  padding-right: var(--space-2);
  color: var(--ink-muted);
  font-variant-numeric: tabular-nums;
}
/* The reorder and remove controls sit beside the name, compact but at full strength. Fading
   them until hover would have read better and been worse: they are the controls, and dimming
   a control drops its contrast and hides it from anyone scanning rather than pointing. */
.ticket-acts {
  white-space: nowrap;
  margin-left: var(--space-2);
}
.ticket-acts .linktext {
  padding: 0 var(--space-1);
}
/* A glyph-only button has no text to give it size: ✕ measured 18×18 and the reorder arrows
   19×18, under the 24×24 minimum. The text variants ("Retire", "make required") are already
   wide enough and keep sitting inline. */
.linktext.icon {
  min-width: 24px;
  min-height: 24px;
  padding: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
}
/* A delegate elected by both their conferences (cl 19.13B) — the cell itself says so. */
td.cell-clash {
  background: var(--red-bg);
  box-shadow: inset 3px 0 0 0 var(--red);
}

.two-col {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 20rem), 1fr));
  gap: var(--space-5);
}
.two-col h3 {
  margin: 0 0 var(--space-3);
  font-size: var(--text-md);
}
.plain-list {
  list-style: none;
  margin: 0;
  padding: 0;
}
.plain-list li {
  padding: var(--space-2) 0;
  border-bottom: 1px solid var(--line);
  font-size: var(--text-md);
}
.plain-list li:last-child {
  border-bottom: 0;
}
.ticket-list {
  counter-reset: none;
}

/* The AGM ticket is a workbench: totals stay visible at a glance, while separate male and
   female lists keep the two elected ballots explicit without making nomination rows bulky. */
.ticket-stage-strip {
  display: grid;
  grid-template-columns: repeat(6, minmax(0, 1fr));
  border: 1px solid var(--line);
  border-radius: var(--radius-md);
  background: var(--panel-sunken);
  margin-bottom: var(--space-4);
  overflow: hidden;
}
.ticket-stage-strip > span {
  padding: var(--space-3);
  text-align: center;
  border-right: 1px solid var(--line);
}
.ticket-stage-strip > span:last-child {
  border-right: 0;
}
.ticket-stage-strip strong,
.ticket-stage-strip small {
  display: block;
}
.ticket-stage-strip strong {
  color: var(--ink);
  font-size: var(--text-lg);
}
.ticket-stage-strip small {
  margin-top: 2px;
  color: var(--ink-muted);
  font-size: var(--text-xs);
}

/* Every AGM status is derived, so this is a compact worklist rather than four separate queues.
   Joined stages make the direction obvious without numbered steps or traffic-light dots. */
.agm-progress-tiles {
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: var(--space-3);
}
.agm-progress-tiles .tile {
  min-width: 0;
  padding: var(--space-4);
}
.agm-progress-tiles .lbl {
  margin-bottom: var(--space-1);
}
/* Filters offered from the column heading they act on. Small, quiet, and never the only way
   in — the same four choices sit in the toolbar's Progress dropdown and on the tiles. */
.th-filters {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-1);
  margin-top: var(--space-1);
  font-weight: 500;
  text-transform: none;
  letter-spacing: 0;
}
.th-filters a {
  padding: 1px 6px;
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  color: var(--ink-muted);
  font-size: var(--text-xs);
  white-space: nowrap;
}
.th-filters a:hover {
  background: var(--grey-100);
  color: var(--ink);
  text-decoration: none;
}
.th-filters a.active {
  background: var(--accent);
  border-color: var(--accent);
  color: #fff;
}
.agm-progress-count {
  margin: 0 0 0 auto;
  padding: 0 var(--space-1) 0 var(--space-3);
  white-space: nowrap;
}
.agm-progress-table {
  min-width: 54rem;
  table-layout: fixed;
}
.agm-progress-table td {
  vertical-align: middle;
  padding-block: 0.45rem;
}
.agm-progress-table th:nth-child(1),
.agm-progress-table td:nth-child(1) {
  width: 17%;
}
.agm-progress-table th:nth-child(2),
.agm-progress-table td:nth-child(2) {
  width: 8%;
}
.agm-progress-table th:nth-child(3),
.agm-progress-table td:nth-child(3) {
  width: 41%;
}
.agm-progress-table th:nth-child(4),
.agm-progress-table td:nth-child(4) {
  width: 12%;
  text-align: center;
}
.agm-progress-table th:nth-child(5),
.agm-progress-table td:nth-child(5) {
  width: 22%;
  text-align: right;
}
.agm-ec-name a {
  display: block;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.agm-progress-track {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  min-width: 0;
  overflow: hidden;
  border: 1px solid var(--line);
  border-radius: var(--radius-md);
  background: var(--panel-sunken);
}
.agm-progress-track > span {
  padding: 0.45rem 0.55rem;
  border-right: 1px solid var(--line);
  color: var(--ink-muted);
  font-size: var(--text-xs);
  font-weight: 600;
  line-height: 1.2;
  text-align: center;
  white-space: nowrap;
}
.agm-progress-track > span:last-child {
  border-right: 0;
}
.agm-progress-track > .is-complete {
  background: #dbeafe;
  color: #1e3a8a;
}
.agm-progress-track > .is-current {
  background: var(--accent);
  color: #fff;
}
.agm-progress-track > .is-current.is-final {
  background: var(--green);
}
.agm-next-action {
  min-height: 34px;
  padding: 0.4rem 0.7rem;
  white-space: nowrap;
}
.ticket-builder-tools {
  display: grid;
  grid-template-columns: minmax(15rem, 0.7fr) minmax(20rem, 1.3fr);
  gap: var(--space-4);
  align-items: end;
  margin-bottom: var(--space-4);
}
.ticket-builder-tools .row-form {
  flex-wrap: nowrap;
  margin: 0;
}
.ticket-builder-tools .ticket-member-form label {
  flex: 1;
}
.ticket-builder-tools .member-search input {
  width: 100%;
}
.ticket-strength {
  display: block;
  margin: 2px 0 0 1.15rem;
  color: var(--ink-muted);
  font-size: var(--text-xs);
}
.ticket-gender-lists {
  display: grid;
  gap: var(--space-4);
}
.ticket-gender-group {
  overflow: hidden;
  border: 1px solid var(--line);
  border-radius: var(--radius-md);
  background: var(--panel);
}
.ticket-gender-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-4);
  padding: var(--space-3) var(--space-4);
  border-bottom: 1px solid var(--line);
  background: var(--panel-sunken);
}
.ticket-gender-head h3,
.ticket-gender-head .cap {
  margin: 0;
}
.ticket-gender-head .cap {
  margin-top: 2px;
}
.ticket-gender-group .table-scroll {
  border: 0;
  border-radius: 0;
}
.agm-ticket-table .nomination-actions {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  margin-left: 0;
}
.agm-ticket-table button:not(.linktext) {
  min-height: 30px;
  padding: 0.3rem 0.65rem;
  font-size: var(--text-sm);
}
.ticket-suggestions {
  margin-top: var(--space-4);
  padding-top: var(--space-4);
  border-top: 1px solid var(--line);
}
.ticket-suggestions > summary {
  font-weight: 650;
  cursor: pointer;
}
.ticket-suggestions[open] > summary {
  margin-bottom: var(--space-3);
}

/* attention rows on Today: dot, count, what it is, and the way in */
.attn-row {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  padding: var(--cell-pad-y) 0;
  border-bottom: 1px solid var(--line);
  font-size: var(--text-md);
  line-height: 1.35;
}
.attn-row:last-child {
  border-bottom: 0;
}
.attn-row .n {
  font-weight: 680;
  min-width: 3.5ch;
  text-align: right;
  font-variant-numeric: tabular-nums;
}
.attn-row .spacer {
  flex: 1;
}
.needs-attention-card .panel-head {
  margin-bottom: 0;
}
.needs-attention-table th,
.needs-attention-table td,
.compact-governance-table th,
.compact-governance-table td {
  padding-top: var(--space-2);
  padding-bottom: var(--space-2);
}
.needs-attention-table td:first-child {
  min-width: 15rem;
}
.needs-attention-table .attention-count {
  width: 5rem;
  font-size: var(--text-base);
  font-weight: 700;
  font-variant-numeric: tabular-nums;
}

/* ---- legend under a chart or events table ---- */
.legend {
  display: flex;
  gap: var(--space-5);
  flex-wrap: wrap;
  font-size: var(--text-sm);
  color: var(--ink-muted);
  margin-top: var(--space-4);
  padding-top: var(--space-3);
  border-top: 1px solid var(--line);
}
.legend span {
  display: flex;
  align-items: center;
}

/* ---- chamber diagram ---- */
.chamber-svg {
  display: block;
  max-width: 430px;
  width: 100%;
  height: auto;
  margin: 0 auto;
}
.chamber-svg .seat-green {
  fill: var(--green);
}
.chamber-svg .seat-amber {
  fill: var(--amber);
}
.chamber-svg .seat-red {
  fill: var(--red);
}
.chamber-svg .seat-grey {
  fill: var(--grey-dot);
}
.chamber-svg .seat-green-light {
  fill: var(--green-light);
}
.chamber-svg .seat-red-light {
  fill: var(--red-light);
}

/* The support ring. Its segments are arcs, so they are stroked rather than filled. */
.donut-svg {
  display: block;
  max-width: 420px;
  width: 100%;
  height: auto;
  margin: 0 auto;
}
.donut-svg path {
  stroke-linecap: butt;
}
/* Hover and focus use a real SVG tooltip positioned by app.js. Fade the band under the pointer
   to say so — dimming, not resizing, because a thicker stroke would move the ring. The table
   beside it still holds every number: the tooltip is a convenience, never the only way to
   read the chart. */
.donut-svg path:not(.donut-track),
.split-bar rect {
  cursor: default;
  transition: opacity var(--fast);
}
.donut-pointer-tooltip {
  pointer-events: none;
}
.donut-pointer-tooltip rect {
  fill: var(--ink);
  stroke: rgba(255, 255, 255, 0.35);
  stroke-width: 1;
}
.donut-pointer-tooltip text {
  fill: #fff;
  font-family: var(--font);
  font-size: var(--text-sm);
  font-weight: 650;
}
.donut-svg path:not(.donut-track):focus-visible {
  outline: none;
  opacity: 0.78;
}
/* Dim the *siblings* of the band under the pointer, and only once a band is genuinely under
   it. Keying the dimming off the whole chart instead made everything fade whenever the pointer
   crossed the ring's hollow centre or the empty half below it, with nothing picked out — which
   reads as broken rather than as a highlight. Browsers without :has() simply get no effect;
   the tooltip and the table carry the information either way. */
.donut-svg:has(path:hover) path:not(.donut-track):not(:hover),
.donut-svg:has(path:focus-visible) path:not(.donut-track):not(:focus-visible),
.split-bar:has(rect:hover) rect:not(:hover) {
  opacity: 0.45;
}
.donut-svg .donut-track {
  stroke: var(--grey-100);
}
.donut-svg .seat-green {
  stroke: var(--green);
}
.donut-svg .seat-green-light {
  stroke: var(--green-light);
}
.donut-svg .seat-amber {
  stroke: var(--amber);
}
.donut-svg .seat-red-light {
  stroke: var(--red-light);
}
.donut-svg .seat-red {
  stroke: var(--red);
}
.donut-svg .seat-grey {
  stroke: var(--grey-dot);
}

/* The overlap bar: how one conference's members divide across the conferences that cross it.
   These segments are neighbours, not a scale — no segment is better than another — so the
   palette stays blue while taking larger steps in lightness and saturation. The swatch in the
   table beside it ties each band to its name; the bar alone never has to be decoded. */
.split-bar {
  display: block;
  width: 100%;
  height: 26px;
  border-radius: var(--radius-sm);
  overflow: hidden;
  margin-bottom: var(--space-3);
}
.split-bar rect {
  stroke: rgba(255, 255, 255, 0.82);
  stroke-width: 1px;
  vector-effect: non-scaling-stroke;
}
.split-1 {
  fill: #0b1f4d;
}
.split-2 {
  fill: #1d4ed8;
}
.split-3 {
  fill: #0284c7;
}
.split-4 {
  fill: #38bdf8;
}
.split-5 {
  fill: #bfdbfe;
}
.split-6 {
  fill: #eff6ff;
}
.split-swatch {
  display: inline-block;
  width: 10px;
  height: 10px;
  border-radius: 3px;
  margin-right: 7px;
  box-shadow: 0 0 0 1px rgba(15, 23, 42, 0.3);
  vertical-align: baseline;
  position: relative;
  top: -1px;
}
.sw-1 {
  background: #0b1f4d;
}
.sw-2 {
  background: #1d4ed8;
}
.sw-3 {
  background: #0284c7;
}
.sw-4 {
  background: #38bdf8;
}
.sw-5 {
  background: #bfdbfe;
}
.sw-6 {
  background: #eff6ff;
}
/* The chart takes only the width it needs; the table beside it — which carries every number —
   gets the rest.
   The decision is the *container's* to make, not the window's: the content column is the
   viewport less a 212px sidebar and 64px of padding, so a viewport rule stacked far too late
   and left the data table squeezed to 152px while the decorative half kept its full 384px. */
.chamber-wrap {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--space-6);
  align-items: center;
}
.support-presentation + .table-scroll,
.support-presentation + .muted {
  margin-top: var(--space-6);
}
.support-presentation-table th:first-child,
.support-presentation-table td:first-child {
  width: 52%;
}
@container content (min-width: 46rem) {
  .chamber-wrap {
    grid-template-columns: minmax(320px, 27rem) minmax(0, 1fr);
  }
}

/* ---- header live search ---- */
.global-search {
  position: relative;
  margin-left: auto;
  min-width: 0;
}
.global-search input {
  width: 20rem;
  max-width: 100%;
  background: var(--grey-50);
  border-color: transparent;
  font-size: var(--text-md);
  min-height: 36px;
}
.global-search input:hover {
  background: var(--grey-100);
  border-color: transparent;
}
.global-search input:focus {
  background: var(--panel);
  border-color: var(--accent);
}
.gs-results {
  position: absolute;
  top: calc(100% + var(--space-1));
  right: 0;
  left: 0;
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-lg);
  max-height: 22rem;
  overflow-y: auto;
  z-index: 200;
  padding: var(--space-1);
}
.gs-results:empty {
  display: none;
}
.gs-group {
  padding: var(--space-2) var(--space-3) var(--space-1);
  font-size: var(--text-2xs);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: var(--track-caps);
  color: var(--ink-muted);
}
.gs-row {
  display: flex;
  justify-content: space-between;
  gap: var(--space-3);
  align-items: center;
  padding: var(--space-2) var(--space-3);
  border-radius: var(--radius-sm);
  font-size: var(--text-md);
  color: var(--ink);
}
.gs-row:hover,
.gs-row:focus {
  background: var(--grey-100);
  text-decoration: none;
}

.mobile-search-menu {
  display: none;
  position: relative;
  flex: none;
}
.mobile-search-menu > summary {
  list-style: none;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 36px;
  min-height: 34px;
  border: 1px solid var(--line);
  border-radius: var(--radius-md);
  color: var(--ink-soft);
  font-size: var(--text-xl);
}
.mobile-search-menu > summary::-webkit-details-marker {
  display: none;
}
.search-glyph {
  position: relative;
  display: block;
  width: 14px;
  height: 14px;
  border: 2px solid currentcolor;
  border-radius: var(--radius-full);
}
.search-glyph::after {
  content: '';
  position: absolute;
  width: 6px;
  border-top: 2px solid currentcolor;
  right: -5px;
  bottom: -3px;
  transform: rotate(45deg);
  transform-origin: left center;
}
.mobile-search-menu[open] > summary {
  color: var(--accent-dark);
  background: var(--accent-wash);
  border-color: var(--brand-200);
}
.mobile-search-pop {
  position: fixed;
  top: calc(var(--topbar-h) + var(--space-2));
  right: var(--space-3);
  left: var(--space-3);
  z-index: 80;
  padding: var(--space-3);
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-lg);
}
.mobile-global-search {
  position: relative;
}
.mobile-global-search input {
  width: 100%;
}

/* ---- the idea logger, in the header ---- */
/* It was a full-width amber bar above the brand. Amber is this app's "needs attention", and a
   standing invitation to suggest something is not that — it was the loudest thing on every
   screen and the strongest signal that this was an unfinished internal tool. It is now a quiet
   header control whose panel opens beneath it. Still a <details>, so it needs no script. */
.idea-menu {
  position: relative;
  flex: none;
}
.idea-menu > summary {
  cursor: pointer;
  list-style: none;
  white-space: nowrap;
  font-size: var(--text-sm);
  color: var(--ink-soft);
  border: 1px solid var(--line);
  border-radius: var(--radius-md);
  padding: 5px 11px;
}
.idea-menu > summary::-webkit-details-marker {
  display: none;
}
.idea-menu > summary:hover {
  background: var(--grey-100);
  color: var(--ink);
}
.idea-menu[open] > summary {
  background: var(--accent-wash);
  border-color: var(--brand-200);
  color: var(--accent-dark);
}
.idea-pop {
  position: absolute;
  top: calc(100% + 8px);
  right: 0;
  z-index: 60;
  width: min(24rem, 80vw);
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-lg);
  padding: var(--space-4);
}
.idea-pop .cap {
  margin-bottom: var(--space-2);
}
.idea-form {
  margin: 0 0 var(--space-2);
}

/* The campaigner's Today leads with whoever is next. */
.next-call .next-name {
  font-size: var(--text-2xl);
  font-weight: 700;
  letter-spacing: -0.015em;
  line-height: 1.2;
}
.next-call .cap {
  margin-bottom: var(--space-3);
}

/* ---- the call card ---- */

/* The member record: one panel, read in columns — standing, contact, where they belong.
   The columns collapse to a single stack when the panel runs narrow. */
.profile-grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: var(--space-5);
}
@container content (max-width: 860px) {
  .profile-grid {
    grid-template-columns: 1fr;
  }
}
.col-head {
  font-size: var(--text-sm);
  font-weight: 650;
  letter-spacing: var(--track-caps);
  text-transform: uppercase;
  color: var(--ink-muted);
  margin: 0 0 var(--space-2);
}
.col-head.spaced {
  margin-top: var(--space-5);
  padding-top: var(--space-4);
  border-top: 1px solid var(--line);
}
.panel-head--ruled {
  align-items: center;
  padding-bottom: var(--space-3);
  margin-bottom: var(--space-4);
  border-bottom: 1px solid var(--line);
}
.profile-contact-actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
}

/* The per-package call-list picker on Campaigner Setup: a quiet disclosure in the cell. */
.list-picker {
  margin-top: var(--space-2);
}
.list-picker summary {
  cursor: pointer;
  color: var(--accent);
  font-size: var(--text-sm);
}
.list-picker form {
  margin-top: var(--space-2);
  padding: var(--space-3);
  border: 1px solid var(--line);
  border-radius: var(--radius-md);
  background: var(--panel-sunken);
}

/* Campaigner Setup separates the frequent jobs (assign and manage active work) from the
   historical and configuration controls that should not dominate every visit. */
.setup-assignment-form > button {
  align-self: flex-start;
}
.campaigner-member-search .gs-results {
  min-width: min(30rem, 90vw);
  right: auto;
}
.party-room-member-search .gs-results {
  min-width: min(30rem, 90vw);
  right: auto;
}
.party-room-member-actions {
  display: grid;
  gap: var(--space-3);
}
.party-room-member-action {
  border: 1px solid var(--line);
  border-radius: var(--radius-md);
  background: var(--panel);
  overflow: visible;
}
.party-room-member-action > summary {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: var(--space-3) var(--space-4);
  color: var(--ink);
  font-size: var(--text-md);
  font-weight: 650;
  cursor: pointer;
  list-style: none;
}
.party-room-member-action > summary::-webkit-details-marker {
  display: none;
}
.party-room-member-action > summary::after {
  content: '›';
  color: var(--ink-muted);
  transform: rotate(0);
  transition: transform var(--fast);
}
.party-room-member-action[open] > summary::after {
  transform: rotate(90deg);
}
.party-room-member-action[open] > summary {
  border-bottom: 1px solid var(--line);
  background: var(--panel-sunken);
}
.party-room-member-action-body {
  padding: var(--space-4);
}
.party-room-member-action-body > .cap {
  margin-bottom: var(--space-4);
}
.party-room-add-form {
  align-items: end;
  grid-template-columns: minmax(16rem, 1.5fr) repeat(3, minmax(10rem, 1fr));
}
.party-room-add-form > label.checkbox {
  align-self: center;
  grid-column: auto;
  white-space: nowrap;
}
.party-room-add-form > button {
  align-self: center;
  grid-column: auto;
}
.party-room-remove-form {
  display: grid;
  grid-template-columns: minmax(18rem, 1fr) auto;
  align-items: end;
  gap: var(--space-3);
}
.party-room-remove-form .member-search input {
  width: 100%;
}
.btn-danger,
.btn-danger:hover,
.btn-danger:active {
  background: var(--red);
  border-color: var(--red);
  color: #fff;
}
.party-room-position-house {
  display: block;
  margin-top: var(--space-1);
}
.party-room-position-edit {
  position: relative;
  min-width: 5rem;
}
.party-room-position-edit > summary {
  color: var(--accent);
  font-size: var(--text-sm);
  font-weight: 600;
  cursor: pointer;
}
.party-room-position-edit[open] {
  min-width: min(24rem, 72vw);
}
.party-room-position-form {
  gap: var(--space-3);
  margin-top: var(--space-2);
  padding: var(--space-3);
  border: 1px solid var(--line);
  border-radius: var(--radius-md);
  background: var(--panel-sunken);
}
.party-room-position-form button {
  align-self: flex-start;
}
.party-room-vacate-form {
  margin-top: var(--space-2);
}
@media (max-width: 1080px) {
  .party-room-add-form {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}
@media (max-width: 640px) {
  .party-room-add-form {
    grid-template-columns: 1fr;
  }
  .party-room-add-form > label.checkbox,
  .party-room-add-form > button {
    grid-column: 1;
  }
  .party-room-remove-form {
    grid-template-columns: 1fr;
  }
}
button.member-picker-option,
button.seat-picker-option {
  width: 100%;
  min-height: 42px;
  border: 0;
  background: transparent;
  color: var(--ink);
  font-weight: 500;
  text-align: left;
  white-space: normal;
}
button.member-picker-option:hover,
button.member-picker-option:focus,
button.seat-picker-option:hover,
button.seat-picker-option:focus {
  border: 0;
  background: var(--grey-100);
  color: var(--ink);
}
.member-picker-meta {
  display: flex;
  align-items: flex-end;
  flex-direction: column;
  gap: var(--space-1);
  text-align: right;
}
.setup-packages .panel-head .cap,
.setup-question-head .cap {
  margin: var(--space-1) 0 0;
}
.setup-question-head {
  align-items: flex-end;
}
.setup-question-head .tabset {
  margin: 0;
}
.setup-campaigner strong,
.setup-campaigner span,
.setup-by,
.setup-answer-options {
  display: block;
}
.setup-list-pills {
  margin-bottom: 0;
}
.setup-list-form {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
  min-width: min(20rem, 72vw);
}
.setup-list-options {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(9rem, 1fr));
  gap: var(--space-2) var(--space-4);
}
.setup-list-form button {
  align-self: flex-start;
}
.setup-retired {
  margin-top: var(--space-5);
  padding-top: var(--space-4);
  border-top: 1px solid var(--line);
}
.setup-retired > summary,
.setup-add-question > summary {
  cursor: pointer;
  color: var(--accent);
  font-size: var(--text-sm);
  font-weight: 650;
}
.setup-retired > .cap {
  margin-top: var(--space-3);
}
.setup-answer-options {
  margin-top: var(--space-1);
  max-width: 30rem;
  white-space: normal;
}
.setup-question-actions {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: var(--space-1) var(--space-2);
}
.setup-question-retired {
  background: var(--panel-sunken);
}
.setup-add-question {
  margin-top: var(--space-5);
  padding-top: var(--space-4);
  border-top: 1px solid var(--line);
}
.setup-add-question > summary {
  list-style: none;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
}
.setup-add-question > summary::-webkit-details-marker {
  display: none;
}
.setup-add-question > summary::after {
  content: '+';
  font-size: var(--text-lg);
  line-height: 1;
}
.setup-add-question[open] > summary::after {
  content: '−';
}
.setup-add-question form {
  margin-top: var(--space-4);
  padding: var(--space-4);
  border-radius: var(--radius-md);
  background: var(--panel-sunken);
}

/* ---- annual renewal worklists ---- */
.renewal-summary .panel-head .cap,
.renewal-list-head .cap {
  max-width: 70ch;
  margin-bottom: 0;
}
.renewal-tiles {
  margin-bottom: 0;
}
.renewal-list-head {
  align-items: flex-start;
}
.renewal-list-actions {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  flex-wrap: wrap;
  gap: var(--space-2);
}
.renewal-email-help {
  flex-basis: 100%;
  color: var(--ink-muted);
  font-size: var(--text-xs);
  text-align: right;
  overflow-wrap: anywhere;
}
.renewal-email-help strong {
  color: var(--ink-soft);
  font-weight: 550;
}
.renewal-worklists td:last-child {
  white-space: nowrap;
}
.renewal-contact {
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-width: 11rem;
  max-width: 18rem;
  overflow-wrap: anywhere;
}
.renewal-record-form {
  flex-wrap: nowrap;
}

.call-head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--space-5);
  flex-wrap: wrap;
  border-left: 3px solid var(--accent);
}
.call-who {
  min-width: 0;
}
.pill-row {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
  margin-bottom: var(--space-2);
}
.call-target-mobile-line {
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: var(--space-2);
  margin-bottom: var(--space-4);
  font-variant-numeric: tabular-nums;
}
.call-target-mobile-line a {
  font-weight: 600;
}
.call-target-tags {
  margin-bottom: 0;
}
.call-list-buttons {
  display: flex;
  flex-wrap: nowrap;
  gap: var(--space-2);
  margin: 0;
  overflow-x: auto;
  padding-bottom: var(--space-1);
}
.call-list-buttons a {
  display: flex;
  flex: 1 0 auto;
  align-items: center;
  justify-content: center;
  min-height: 38px;
  padding: var(--space-2) var(--space-3);
  text-align: center;
  line-height: 1.25;
  white-space: nowrap;
}
.call-dial {
  text-align: right;
}
.call-dial .cap {
  margin: 0;
}
a.dial {
  font-size: 1.6rem;
  font-weight: 700;
  letter-spacing: -0.01em;
  white-space: nowrap;
  font-variant-numeric: tabular-nums;
}
a.dial:hover {
  text-decoration: none;
  color: var(--accent-dark);
}

/* Outcome and attendance as toggle buttons. The input stays a real checkbox or radio — it is
   only visually replaced — so this needs no script, keeps the browser's keyboard behaviour,
   and still submits without JavaScript. */
.toggles {
  border: 0;
  padding: 0;
  margin: 0 0 var(--space-4);
}
.toggles legend {
  padding: 0;
  font-size: var(--text-sm);
  font-weight: 600;
  color: var(--ink-soft);
  margin-bottom: var(--space-2);
}
.toggles legend .muted {
  font-weight: 400;
}
.toggle-row {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
}
.toggle input {
  position: absolute;
  width: 1px;
  height: 1px;
  opacity: 0;
  margin: 0;
}
.toggle span {
  display: inline-block;
  border: 1px solid var(--line-strong);
  background: var(--panel);
  border-radius: var(--radius-md);
  padding: 9px 15px;
  font-size: var(--text-sm);
  cursor: pointer;
  transition:
    background var(--fast),
    border-color var(--fast),
    color var(--fast);
}
.toggle span:hover {
  background: var(--grey-100);
}
.toggle input:checked + span {
  background: var(--accent);
  border-color: var(--accent);
  color: #fff;
  font-weight: 600;
}
/* The ring has to come from the input's focus, since the input itself is not visible. */
.toggle input:focus-visible + span {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

/* The log owns the wider column while both panels retain the product's standard card skin. */
.call-grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--panel-gap);
  align-items: stretch;
  margin-top: var(--panel-gap);
}
.call-grid > .card + .card {
  margin-top: 0;
}
.call-grid + .call-list-card {
  margin-top: var(--panel-gap);
}
@container content (min-width: 52rem) {
  .call-grid {
    grid-template-columns: minmax(0, 1.25fr) minmax(18rem, 0.75fr);
  }
}
.call-history-panel {
  display: flex;
  flex-direction: column;
}
.call-history-empty {
  display: flex;
  flex: 1;
  flex-direction: column;
  justify-content: center;
}
/* Every saved call gets a compact audit row. Notes remain optional content beneath the facts,
   rather than deciding whether a call is visible at all. */
.call-notes li + li {
  margin-top: var(--space-3);
  padding-top: var(--space-3);
  border-top: 1px solid var(--line);
}
.call-log-outcomes {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-1);
  margin-bottom: var(--space-2);
}
.call-log-facts {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(5rem, 1fr));
  gap: var(--space-2);
  margin: 0;
  padding: var(--space-2) var(--space-3);
  border-radius: var(--radius-md);
  background: var(--panel-sunken);
}
.call-log-facts dt {
  color: var(--ink-muted);
  font-size: var(--text-xs);
  font-weight: 650;
  letter-spacing: var(--track-caps);
  text-transform: uppercase;
}
.call-log-facts dd {
  margin: 2px 0 0;
  color: var(--ink);
  font-size: var(--text-sm);
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  overflow-wrap: anywhere;
}
.call-log-note {
  margin-top: var(--space-2);
}
.call-log-note > span {
  color: var(--ink-muted);
  font-size: var(--text-xs);
  font-weight: 650;
  letter-spacing: var(--track-caps);
  text-transform: uppercase;
}
.call-log-note p {
  margin: 2px 0 0;
  font-size: var(--text-sm);
  color: var(--ink);
  white-space: pre-wrap;
}

/* Call notes run from a phrase to a paragraph; the box grows with what is in it. */
.stack textarea[name='notes'] {
  field-sizing: content;
  min-height: 4lh;
  max-height: 18lh;
}

.call-actions {
  align-items: center;
}
.call-actions .spacer {
  flex: 1;
}
.toggle-secondary span {
  background: var(--panel-sunken);
  border-style: dashed;
}
[data-answer-fields] {
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
}

.card-actions {
  display: flex;
  justify-content: flex-end;
  margin-top: var(--space-4);
  padding-top: var(--space-4);
  border-top: 1px solid var(--line);
}

.admin-settings {
  margin-top: var(--panel-gap);
}
.admin-settings > summary {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-4);
  list-style: none;
  cursor: pointer;
  font-weight: 650;
}
.admin-settings > summary::-webkit-details-marker {
  display: none;
}
.admin-settings > summary::after {
  content: 'Show';
  color: var(--accent);
  font-size: var(--text-sm);
  font-weight: 600;
}
.admin-settings[open] > summary::after {
  content: 'Hide';
}
.admin-settings-body {
  margin-top: var(--space-4);
  padding-top: var(--space-4);
  border-top: 1px solid var(--line);
}
.admin-status {
  margin-top: var(--space-5);
  padding-top: var(--space-4);
  border-top: 1px solid var(--line);
}

/* ---- users and effective access ---- */
.access-add-account {
  margin-left: auto;
}
.access-add-account > summary {
  display: inline-flex;
  align-items: center;
  min-height: 30px;
  padding: 6px 13px;
  list-style: none;
  border: 1px solid var(--accent);
  border-radius: 7px;
  background: var(--accent);
  color: #fff;
  cursor: pointer;
  font-size: var(--text-sm);
  font-weight: 600;
}
.access-add-account > summary::-webkit-details-marker {
  display: none;
}
.access-add-account[open] {
  width: 100%;
  margin-left: 0;
}
.access-add-account[open] > summary {
  background: var(--brand-700);
  border-color: var(--brand-700);
}
.access-add-account form {
  margin-top: var(--space-4);
  padding: var(--space-4);
  border: 1px solid var(--line);
  border-radius: var(--radius-md);
  background: var(--panel-sunken);
}
.access-user-fields {
  margin: 0;
  padding: var(--space-3) var(--space-4) var(--space-4);
  border: 1px solid var(--line-strong);
  border-radius: var(--radius-md);
}
.access-user-fields legend {
  padding: 0 var(--space-2);
  color: var(--ink);
  font-size: var(--text-sm);
  font-weight: 650;
}
.user-access-totals {
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: var(--space-3);
  margin-bottom: var(--space-5);
}
.user-access-totals .tile {
  padding: var(--space-4);
}
.user-access-identity,
.user-access-identity > span,
.user-access-grid section > p > span {
  display: block;
}
.access-warnings {
  margin-bottom: var(--space-5);
  padding: var(--space-3) var(--space-4);
  border: 1px solid var(--amber-edge);
  border-radius: var(--radius-md);
  background: var(--amber-bg);
  color: var(--amber-ink);
  font-size: var(--text-sm);
}
.access-warnings ul {
  margin: var(--space-1) 0 0;
  padding-left: var(--space-5);
}
.user-access-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--space-5);
}
.user-access-grid section + section {
  padding-left: var(--space-5);
  border-left: 1px solid var(--line);
}
.user-access-grid h3,
.user-access-visibility h3,
.user-package-access h3,
.user-access-change h3 {
  margin: 0 0 var(--space-3);
  font-size: var(--text-base);
}
.access-facts {
  margin: 0;
}
.access-facts > div {
  display: grid;
  grid-template-columns: minmax(7rem, auto) 1fr;
  gap: var(--space-3);
  padding: var(--space-2) 0;
  border-bottom: 1px solid var(--line);
}
.access-facts dt {
  color: var(--ink-muted);
  font-size: var(--text-sm);
}
.access-facts dd {
  margin: 0;
  overflow-wrap: anywhere;
}
.package-access-list {
  display: grid;
  gap: var(--space-2);
  margin: var(--space-3) 0 0;
  padding: 0;
  list-style: none;
}
.package-access-list li {
  padding: var(--space-2) var(--space-3);
  border-radius: var(--radius-sm);
  background: var(--panel-sunken);
}
.package-access-list span {
  display: block;
  color: var(--ink-muted);
  font-size: var(--text-sm);
}
.user-package-access,
.user-access-visibility,
.user-access-change {
  margin-top: var(--space-5);
  padding-top: var(--space-5);
  border-top: 1px solid var(--line);
}
.user-access-visibility-head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--space-5);
  margin-bottom: var(--space-3);
}
.user-access-visibility-head .cap {
  margin: 0;
}
.user-access-scope {
  max-width: 34rem;
  margin: 0;
  text-align: right;
}
.user-access-scope strong,
.user-access-scope span {
  display: block;
}
.user-access-scope span {
  margin-top: 2px;
  color: var(--ink-muted);
  font-size: var(--text-sm);
}
.access-checklist {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--space-2);
}
.access-check-item {
  display: grid;
  grid-template-columns: 1rem minmax(0, 1fr);
  align-items: start;
  gap: var(--space-3);
  padding: var(--space-3);
  border: 1px solid var(--line);
  border-radius: var(--radius-md);
  background: var(--panel-sunken);
}
.access-check-item input {
  width: 1rem;
  height: 1rem;
  min-height: 0;
  margin: 2px 0 0;
  accent-color: var(--accent);
  opacity: 1;
}
.access-check-copy,
.access-check-copy > span {
  display: block;
}
.access-check-copy > span {
  margin-top: 2px;
  color: var(--ink-muted);
  font-size: var(--text-sm);
  line-height: 1.4;
}
.access-check-item[data-access-granted='false'] .access-check-copy strong {
  color: var(--ink-soft);
}
.user-package-access {
  display: grid;
  grid-template-columns: minmax(12rem, 0.65fr) 1.35fr;
  gap: var(--space-5);
  align-items: start;
}
.user-package-access .cap {
  margin-bottom: 0;
}

@container content (max-width: 860px) {
  .user-access-grid,
  .user-package-access,
  .access-checklist {
    grid-template-columns: 1fr;
  }
  .user-access-visibility-head {
    display: block;
  }
  .user-access-scope {
    margin-top: var(--space-3);
    text-align: left;
  }
  .user-access-grid section + section {
    padding-left: 0;
    padding-top: var(--space-4);
    border-left: 0;
    border-top: 1px solid var(--line);
  }
}

/* ---- upload drop zone ---- */
.drop-zone {
  display: block;
  padding: var(--space-8);
  border: 1.5px dashed var(--line-strong);
  border-radius: var(--radius-lg);
  text-align: center;
  cursor: pointer;
  background: var(--panel-sunken);
  transition:
    border-color var(--fast),
    background var(--fast),
    box-shadow var(--fast);
  max-width: none;
}
.drop-zone:hover,
.drop-zone:focus-within {
  border-color: var(--accent);
  background: var(--accent-wash);
}
.drop-zone.dragover {
  border-color: var(--accent);
  border-style: solid;
  background: var(--accent-wash);
  box-shadow: var(--ring);
}
.drop-zone input[type='file'] {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
}
.drop-zone .drop-idle,
.drop-zone .drop-chosen {
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
  align-items: center;
  font-size: var(--text-base);
  color: var(--ink);
  font-weight: 400;
}
.drop-zone .drop-idle[hidden],
.drop-zone .drop-chosen[hidden] {
  display: none;
}
.drop-zone .cap {
  margin: 0;
  max-width: 46ch;
}
.drop-zone .drop-chosen strong {
  font-size: var(--text-lg);
}

/* ---- undo bar ---- */
.undo-bar {
  position: fixed;
  left: 50%;
  bottom: var(--space-6);
  z-index: 400;
  transform: translateX(-50%) translateY(160%);
  transition: transform var(--slow);
  display: flex;
  align-items: center;
  gap: var(--space-4);
  max-width: min(38rem, calc(100vw - var(--space-8)));
  padding: var(--space-3) var(--space-3) var(--space-3) var(--space-5);
  background: var(--grey-900);
  color: #fff;
  border-radius: var(--radius-lg);
  font-size: var(--text-md);
  box-shadow: var(--shadow-lg);
}
.undo-bar.on {
  transform: translateX(-50%) translateY(0);
}
.undo-text {
  font-size: var(--text-md);
}
.undo-form {
  margin: 0;
}
.undo-do {
  background: transparent;
  border: 1px solid rgba(255, 255, 255, 0.35);
  color: #fff;
  font-weight: 600;
  min-height: 34px;
  padding: 0.35rem 0.85rem;
}
.undo-do:hover {
  background: rgba(255, 255, 255, 0.14);
  border-color: rgba(255, 255, 255, 0.5);
}
.undo-x {
  background: transparent;
  border: 0;
  color: #fff;
  opacity: 0.7;
  min-height: 34px;
  padding: 0.35rem 0.5rem;
  font-weight: 400;
}
.undo-x:hover {
  background: rgba(255, 255, 255, 0.14);
  opacity: 1;
}

/* ============================================================ 6. responsive */

/* Tablet: the sidebar folds away behind the menu button. */
@media (max-width: 900px) {
  .layout {
    grid-template-columns: 1fr;
    grid-template-areas:
      'top'
      'main';
  }
  .sidebar {
    position: fixed;
    top: var(--topbar-h);
    bottom: 0;
    left: 0;
    height: auto;
    width: var(--sidebar-w);
    transform: translateX(-100%);
    transition: transform var(--slow);
    z-index: 45;
    box-shadow: var(--shadow-lg);
  }
  body.nav-open .sidebar {
    transform: none;
  }
  body.nav-open::after {
    content: '';
    position: fixed;
    inset: var(--topbar-h) 0 0 0;
    background: rgba(18, 25, 38, 0.35);
    z-index: 44;
  }
  .nav-toggle {
    display: inline-flex;
  }
  .topbar {
    padding: var(--space-3) var(--space-4);
    gap: var(--space-3);
  }
  /* The header held eight things and the role badge overlapped Sign Out by 19px here, with
     the brand crushed to "Party …". Anything available elsewhere goes at the same width the
     sidebar collapses — the name and role are both on My Account. This used to happen 128px
     later, at 640px. */
  .user-chip {
    display: none;
  }
  .access-preview-chip > span:first-child,
  .access-preview-chip .role-badge {
    display: none;
  }
  .global-search input {
    width: 100%;
    max-width: 12rem;
  }
  .content {
    padding: var(--space-6) var(--space-4) var(--space-8);
  }
  /* a diagram beside a table is two cramped columns at this width — stack them */
  .chamber-wrap {
    grid-template-columns: 1fr;
  }
  .chamber-svg {
    max-width: 360px;
  }
}

/* Phone: one column, comfortable targets, and the widest tables become cards. */
@media (max-width: 640px) {
  .topbar {
    flex-wrap: nowrap;
    gap: var(--space-2);
    padding: var(--space-2) var(--space-3);
  }
  .mobile-search-menu {
    display: block;
    margin-left: auto;
  }
  .idea-menu {
    margin-left: 0;
  }
  .topbar .brand {
    font-size: var(--text-base);
  }
  .global-search {
    display: none;
  }
  .idea-menu .idea-word {
    display: none;
  }
  .role-badge {
    font-size: var(--text-2xs);
  }
  .linkbtn {
    padding: 0.35rem 0.6rem;
  }
  .nav-toggle {
    padding: var(--space-1) var(--space-2);
  }
  /* The page title used to shrink to 18.4px here while .card h2 stayed at 20px, so the one
     element saying what page you are on was outranked by the first panel on it. Shrink the
     panel heading instead; the title rides its own clamp down to a 22px floor. */
  .card h2 {
    font-size: 1.05rem;
  }
  .card {
    padding: var(--space-4);
    border-radius: var(--radius-md);
  }
  .content {
    padding: var(--space-5) var(--space-3) var(--space-8);
  }
  .tiles {
    grid-template-columns: repeat(auto-fit, minmax(min(100%, 140px), 1fr));
  }
  .profile-contact-actions {
    width: 100%;
  }
  .profile-contact-actions .btn-ghost {
    flex: 1;
  }
  .renewal-contact {
    min-width: 0;
    align-items: flex-end;
  }
  .renewal-record-form {
    justify-content: flex-end;
  }
  .call-dial {
    width: 100%;
    text-align: left;
  }
  a.dial {
    display: inline-flex;
    min-height: 44px;
    align-items: center;
  }
  .call-actions .spacer {
    display: none;
  }
  .user-access-totals {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
  .admin-settings > summary {
    align-items: flex-start;
  }
  .admin-settings > summary .muted {
    display: none;
  }
  .two-col {
    grid-template-columns: 1fr;
  }
  .ticket-stage-strip {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
  .ticket-stage-strip > span {
    border-bottom: 1px solid var(--line);
  }
  .ticket-stage-strip > span:nth-child(2n) {
    border-right: 0;
  }
  .ticket-stage-strip > span:last-child {
    grid-column: auto;
    border-bottom: 0;
    border-right: 0;
  }
  .ticket-stage-strip > span:nth-last-child(2) {
    border-bottom: 0;
  }
  .agm-progress-cell {
    display: block !important;
    text-align: left !important;
  }
  .agm-progress-cell::before {
    display: block;
    margin-bottom: var(--space-2);
  }
  .agm-progress-track {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    min-width: 0;
  }
  .agm-progress-track > span {
    white-space: normal;
    border-bottom: 1px solid var(--line);
  }
  .agm-progress-track > span:nth-child(2n) {
    border-right: 0;
  }
  .agm-progress-track > span:nth-child(n + 3) {
    border-bottom: 0;
  }
  .agm-progress-tiles {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
  .agm-progress-count {
    width: 100%;
    margin-left: 0;
    padding: var(--space-1) 0 0;
  }
  .agm-progress-table {
    min-width: 0;
    table-layout: auto;
  }
  .agm-progress-table th,
  .agm-progress-table td {
    width: auto !important;
    text-align: right;
  }
  .agm-progress-table td.stack-lead {
    text-align: left;
  }
  .agm-ec-name a {
    white-space: normal;
  }
  .ticket-builder-tools {
    grid-template-columns: 1fr;
  }
  .ticket-builder-tools .row-form {
    flex-wrap: wrap;
  }
  .toolbar .grow {
    min-width: 100%;
  }
  /* a comfortable touch target for the things a thumb must hit */
  .sidebar a {
    padding: var(--space-3);
    min-height: 44px;
    display: flex;
    align-items: center;
  }
  .pager a,
  .pager span {
    min-height: 40px;
    display: inline-flex;
    align-items: center;
  }
  /* The dense desktop control sizes are for a mouse. On a touch screen a button needs a
     thumb-sized target, and an input below 16px makes iOS Safari zoom the page on focus. */
  button,
  .btn-ghost {
    min-height: 44px;
    padding: 10px 16px;
  }
  .agm-ticket-table button:not(.linktext) {
    min-height: 44px;
    padding: 10px 16px;
  }
  input[type='text'],
  input[type='search'],
  input[type='email'],
  input[type='password'],
  input[type='date'],
  input[type='number'],
  input:not([type]),
  select,
  textarea {
    font-size: 1rem;
    min-height: 44px;
  }

  /* A table of seven columns cannot be read at 375px, so the widest ones become one card per
     row: a lead line, then every other column as a label and its value. The labels come from
     the column headings, copied onto the cells by app.js — without JS the table just scrolls. */
  table.stackable thead {
    position: absolute;
    width: 1px;
    height: 1px;
    overflow: hidden;
    clip: rect(0 0 0 0);
    white-space: nowrap;
  }
  table.stackable,
  table.stackable tbody,
  table.stackable tr,
  table.stackable td {
    display: block;
    width: auto;
  }
  table.stackable tr {
    border: 1px solid var(--line);
    border-radius: var(--radius-md);
    padding: var(--space-3) var(--space-4);
    margin-bottom: var(--space-3);
    background: var(--panel);
    display: flex;
    flex-direction: column;
    gap: var(--space-1);
  }
  table.stackable tr:hover {
    background: var(--panel);
  }
  table.stackable td {
    border: none;
    padding: var(--space-1) 0;
    display: flex;
    justify-content: space-between;
    gap: var(--space-4);
    align-items: baseline;
    text-align: right;
  }
  table.stackable td.stack-lead {
    display: block;
    text-align: left;
    font-size: var(--text-base);
    font-weight: 650;
    margin-bottom: var(--space-1);
    padding-bottom: var(--space-2);
    border-bottom: 1px solid var(--line);
    order: -1;
  }
  table.stackable td.stack-lead::before {
    content: none;
  }
  table.stackable td::before {
    content: attr(data-label);
    flex: 0 0 auto;
    text-align: left;
    color: var(--ink-muted);
    font-size: var(--text-2xs);
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.05em;
  }
  table.stackable td:empty {
    display: none;
  }
}

@media (max-width: 420px) {
  .role-badge {
    display: none;
  }
}

/* ---- Senate preselection workbench ----
   This is one long constitutional workflow, so joined stages and dense drill-down tables carry
   the hierarchy. The page reuses the product's ordinary cards, controls and blue accent. */
.preselection-create-grid {
  margin-bottom: var(--panel-gap);
}
.preselection-create-grid > .card {
  height: 100%;
}
.preselection-create-grid .stack {
  max-width: none;
}
.senate-page-head {
  align-items: flex-start;
  margin-bottom: var(--space-4);
}
.senate-page-head .cap {
  margin-bottom: 0;
}
.senate-stage-strip {
  display: grid;
  grid-template-columns: repeat(6, minmax(0, 1fr));
  overflow: hidden;
  margin-bottom: var(--section-gap);
  border: 1px solid var(--line-strong);
  border-radius: var(--radius-lg);
  background: var(--panel);
}
.senate-stage-strip a {
  min-width: 0;
  padding: var(--space-3);
  border-right: 1px solid var(--line);
  color: var(--ink-muted);
  text-align: center;
}
.senate-stage-strip a:last-child {
  border-right: 0;
}
.senate-stage-strip a:hover {
  background: var(--accent-wash);
  color: var(--accent-dark);
  text-decoration: none;
}
.senate-stage-strip span,
.senate-stage-strip strong {
  display: block;
  overflow: hidden;
  text-overflow: ellipsis;
}
.senate-stage-strip span {
  margin-bottom: 2px;
  font-size: var(--text-2xs);
  font-weight: 700;
  letter-spacing: var(--track-caps);
  text-transform: uppercase;
}
.senate-stage-strip strong {
  color: inherit;
  font-size: var(--text-xs);
  white-space: nowrap;
}
.senate-stage-strip .is-complete {
  background: #dbeafe;
  color: #1e3a8a;
}
.senate-stage-strip .is-current {
  background: var(--accent);
  color: #fff;
}
.senate-summary-tiles {
  grid-template-columns: repeat(4, minmax(0, 1fr));
}
.senate-attention .panel-head {
  margin-bottom: var(--space-2);
}
.senate-compact-table th,
.senate-compact-table td {
  padding-block: 0.45rem;
  vertical-align: middle;
}
.senate-fec-table,
.senate-room-table {
  min-width: 62rem;
}
.senate-overview-form > label,
.senate-form-grid > label {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  color: var(--ink-soft);
  font-size: var(--text-sm);
  font-weight: 600;
}
.senate-deadlines {
  margin: 0;
}
.senate-deadlines > div {
  display: flex;
  justify-content: space-between;
  gap: var(--space-4);
  padding: var(--space-3) 0;
  border-bottom: 1px solid var(--line);
}
.senate-deadlines > div:last-child {
  border-bottom: 0;
}
.senate-deadlines dt {
  color: var(--ink-muted);
  font-size: var(--text-sm);
}
.senate-deadlines dd {
  margin: 0;
  color: var(--ink);
  font-size: var(--text-sm);
  font-weight: 650;
  text-align: right;
}
.senate-picker-form {
  align-items: flex-end;
  margin-bottom: var(--space-4);
}
.senate-picker-form > label {
  display: flex;
  flex-direction: column;
  align-items: stretch;
  gap: var(--space-2);
  color: var(--ink-soft);
  font-size: var(--text-sm);
  font-weight: 600;
}
.senate-picker-form .grow {
  flex: 1 1 20rem;
}
.senate-picker-form input {
  width: 100%;
}
.senate-pool-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--space-4);
}
.senate-pool {
  min-width: 0;
  border: 1px solid var(--line);
  border-radius: var(--radius-md);
  background: var(--panel);
  overflow: hidden;
}
.senate-pool > summary,
.senate-ballot-history summary {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
  padding: var(--space-3) var(--space-4);
  background: var(--panel-sunken);
  cursor: pointer;
}
.senate-pool > summary strong,
.senate-pool > summary small,
.senate-ballot-history summary strong,
.senate-ballot-history summary small {
  display: block;
}
.senate-pool > summary small,
.senate-ballot-history summary small {
  margin-top: 2px;
  color: var(--ink-muted);
  font-size: var(--text-xs);
}
.senate-pool .table-scroll,
.senate-ballot-history .table-scroll {
  border-top: 1px solid var(--line);
}
.senate-pool table {
  min-width: 38rem;
}
.senate-pool .is-reserve {
  color: var(--ink-muted);
  background: var(--grey-25);
}
.senate-row-control {
  flex-wrap: nowrap;
}
.senate-row-control select {
  min-width: 7rem;
}
.senate-source-pair {
  align-items: stretch;
}
.senate-source-pair > .card {
  height: 100%;
}
.senate-person-list li {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
}
.senate-source-strip {
  display: grid;
  grid-template-columns: repeat(6, minmax(0, 1fr));
  margin-bottom: var(--space-4);
  border: 1px solid var(--line);
  border-radius: var(--radius-md);
  background: var(--panel-sunken);
  overflow: hidden;
}
.senate-source-strip > span {
  min-width: 0;
  padding: var(--space-3);
  border-right: 1px solid var(--line);
  text-align: center;
}
.senate-source-strip > span:last-child {
  border-right: 0;
}
.senate-source-strip strong,
.senate-source-strip small {
  display: block;
}
.senate-source-strip strong {
  font-size: var(--text-lg);
}
.senate-source-strip small {
  margin-top: 2px;
  color: var(--ink-muted);
  font-size: var(--text-2xs);
  line-height: 1.25;
}
.senate-duplicate-warning,
.senate-casting-vote {
  margin-bottom: var(--space-4);
  padding: var(--space-3) var(--space-4);
  border: 1px solid var(--amber-edge);
  border-radius: var(--radius-md);
  background: var(--amber-bg);
  color: var(--amber-ink);
  font-size: var(--text-sm);
}
.senate-duplicate-warning ul {
  margin: var(--space-2) 0 0;
  padding-left: var(--space-5);
}
.table-note {
  display: block;
  margin-top: 2px;
  color: var(--ink-muted);
  font-size: var(--text-xs);
}
.senate-ballot-history {
  display: grid;
  gap: var(--space-2);
  margin-bottom: var(--space-4);
}
.senate-ballot-history details {
  border: 1px solid var(--line);
  border-radius: var(--radius-md);
  overflow: hidden;
}
.senate-current-ballot {
  padding: var(--space-4);
  border: 1px solid var(--brand-200);
  border-radius: var(--radius-md);
  background: var(--brand-50);
}
.senate-current-ballot h3 {
  margin: 0 0 var(--space-1);
}
.senate-vote-form > div {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(12rem, 1fr));
  gap: var(--space-3);
  margin-bottom: var(--space-3);
}
.senate-vote-form label {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
  padding: var(--space-2) var(--space-3);
  border: 1px solid var(--line);
  border-radius: var(--radius-md);
  background: var(--panel);
  font-size: var(--text-sm);
  font-weight: 600;
}
.senate-vote-form input {
  width: 5rem;
}
.senate-ballot-actions {
  margin: var(--space-4) 0 0;
}
.senate-order-table {
  max-width: 48rem;
}
.senate-order-table th:last-child,
.senate-order-table td:last-child {
  text-align: right;
}
.senate-finalise-form {
  margin-top: var(--space-4);
}
.senate-audit > summary {
  cursor: pointer;
  font-weight: 650;
}
.senate-audit > .table-scroll {
  margin-top: var(--space-4);
}

@media (max-width: 1000px) {
  .senate-stage-strip,
  .senate-source-strip {
    grid-template-columns: repeat(3, minmax(0, 1fr));
  }
  .senate-stage-strip a:nth-child(3),
  .senate-source-strip > span:nth-child(3) {
    border-right: 0;
  }
  .senate-stage-strip a:nth-child(-n + 3),
  .senate-source-strip > span:nth-child(-n + 3) {
    border-bottom: 1px solid var(--line);
  }
}
@media (max-width: 760px) {
  .senate-summary-tiles,
  .senate-pool-grid {
    grid-template-columns: 1fr 1fr;
  }
  .senate-stage-strip {
    grid-template-columns: 1fr 1fr;
  }
  .senate-stage-strip a:nth-child(3) {
    border-right: 1px solid var(--line);
  }
  .senate-stage-strip a:nth-child(2n) {
    border-right: 0;
  }
  .senate-stage-strip a:nth-child(-n + 4) {
    border-bottom: 1px solid var(--line);
  }
  .senate-row-control {
    flex-wrap: wrap;
    justify-content: flex-end;
  }
}
@media (max-width: 480px) {
  .senate-summary-tiles,
  .senate-pool-grid {
    grid-template-columns: 1fr;
  }
  .senate-source-strip {
    grid-template-columns: 1fr 1fr;
  }
  .senate-source-strip > span:nth-child(3) {
    border-right: 1px solid var(--line);
  }
  .senate-source-strip > span:nth-child(2n) {
    border-right: 0;
  }
  .senate-source-strip > span:nth-child(-n + 4) {
    border-bottom: 1px solid var(--line);
  }
}

/* ---- Party First organisation chart ----
   The central Core owns the composition, while nested organiser cards stay compact enough for
   large teams. Direct member names remain collapsed until requested. */
.organisation-chart-tiles {
  grid-template-columns: repeat(4, minmax(0, 1fr));
}
.organisation-chart-card {
  overflow: hidden;
}
.organisation-chart {
  min-width: 0;
  padding: var(--space-2) 0 var(--space-3);
}
.organisation-core-root {
  width: min(22rem, 100%);
  margin: 0 auto;
  padding: var(--space-4) var(--space-5);
  border-radius: var(--radius-lg);
  background: var(--accent);
  color: #fff;
  text-align: center;
}
.organisation-core-root h2,
.organisation-core-root p {
  color: inherit;
}
.organisation-core-root h2 {
  margin: 0;
  font-size: var(--text-xl);
}
.organisation-core-root p {
  margin: var(--space-1) 0 0;
  font-size: var(--text-sm);
}
.organisation-node-kicker {
  display: block;
  margin-bottom: 2px;
  font-size: var(--text-2xs);
  font-weight: 750;
  letter-spacing: var(--track-caps);
  text-transform: uppercase;
  opacity: 0.82;
}
.organisation-core-line {
  width: 2px;
  height: var(--space-6);
  margin: 0 auto;
  background: var(--brand-200);
}
.organisation-core-grid {
  position: relative;
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: var(--space-5);
  align-items: start;
  padding-top: var(--space-6);
}
.organisation-core-grid::before {
  content: '';
  position: absolute;
  top: 0;
  left: calc(16.666% - 1px);
  right: calc(16.666% - 1px);
  height: 2px;
  background: var(--brand-200);
}
.organisation-core-grid > .organisation-branch::before {
  content: '';
  position: absolute;
  top: calc(var(--space-6) * -1);
  left: 50%;
  width: 2px;
  height: var(--space-6);
  background: var(--brand-200);
}
.organisation-branch {
  position: relative;
  min-width: 0;
}
.organisation-node {
  position: relative;
  z-index: 1;
  padding: var(--space-4);
  border: 1px solid var(--line-strong);
  border-radius: var(--radius-lg);
  background: var(--panel);
}
.organisation-branch.is-core-person > .organisation-node {
  border-color: var(--brand-200);
  box-shadow: inset 0 3px 0 var(--accent);
}
.organisation-node.needs-assignment {
  border-color: var(--amber-edge);
  box-shadow: inset 3px 0 0 var(--amber);
}
.organisation-node-head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--space-3);
}
.organisation-node h3 {
  margin: 0;
  font-size: var(--text-base);
}
.organisation-node h3 a {
  color: var(--ink);
}
.organisation-node h3 a:hover {
  color: var(--accent);
}
.organisation-node .organisation-node-kicker {
  color: var(--accent);
}
.organisation-node-place,
.organisation-node-attention {
  margin: var(--space-1) 0 0;
  color: var(--ink-muted);
  font-size: var(--text-xs);
}
.organisation-node-attention {
  color: var(--amber-ink);
}
.organisation-node-counts {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2) var(--space-4);
  margin-top: var(--space-3);
  padding-top: var(--space-3);
  border-top: 1px solid var(--line);
  color: var(--ink-muted);
  font-size: var(--text-xs);
}
.organisation-node-counts strong {
  color: var(--ink);
}
.organisation-assignment {
  margin-top: var(--space-3);
  padding-top: var(--space-3);
  border-top: 1px solid var(--line);
}
.organisation-assignment > summary {
  width: fit-content;
  color: var(--accent);
  font-size: var(--text-xs);
  font-weight: 700;
  cursor: pointer;
}
.organisation-assignment > summary:hover {
  color: var(--accent-dark);
}
.organisation-assignment-panel {
  margin-top: var(--space-3);
  padding: var(--space-3);
  border: 1px solid var(--brand-100);
  border-radius: var(--radius-md);
  background: var(--accent-wash);
}
.organisation-assignment-panel > .muted {
  margin: 0 0 var(--space-2);
  font-size: var(--text-xs);
}
.organisation-assignment-panel .stack {
  max-width: none;
}
.organisation-assignment-panel label {
  font-size: var(--text-xs);
}
.organisation-assignment-panel input {
  font-size: var(--text-sm);
}
.organisation-assignment-panel button[type='submit'] {
  width: 100%;
}
.organisation-assignment .gs-results {
  position: static;
  min-width: 0;
  max-height: 14rem;
  margin-top: var(--space-1);
}
.organisation-repair-list > li {
  padding: var(--space-3);
  border: 1px solid var(--line);
  border-radius: var(--radius-md);
}
.organisation-descendants {
  position: relative;
  margin-left: var(--space-4);
  padding: var(--space-5) 0 0 var(--space-5);
  border-left: 2px solid var(--brand-100);
}
.organisation-child-grid {
  display: grid;
  gap: var(--space-4);
}
.organisation-child-grid > .organisation-branch::before,
.organisation-people::before {
  content: '';
  position: absolute;
  top: var(--space-5);
  left: calc((var(--space-5) + 2px) * -1);
  width: var(--space-5);
  height: 2px;
  background: var(--brand-100);
}
.organisation-people {
  position: relative;
  margin-top: var(--space-4);
  border: 1px solid var(--line);
  border-radius: var(--radius-md);
  background: var(--panel-sunken);
}
.organisation-people > summary {
  padding: var(--space-3);
  color: var(--accent);
  font-size: var(--text-sm);
  cursor: pointer;
}
.organisation-people-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(11rem, 1fr));
  gap: 1px;
  padding: 1px;
  border-top: 1px solid var(--line);
  background: var(--line);
}
.organisation-people-grid a {
  display: block;
  min-width: 0;
  padding: var(--space-2) var(--space-3);
  background: var(--panel);
  color: var(--ink);
}
.organisation-people-grid a:hover {
  background: var(--accent-wash);
  color: var(--accent-dark);
  text-decoration: none;
}
.organisation-people-grid strong,
.organisation-people-grid small {
  display: block;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.organisation-people-grid strong {
  font-size: var(--text-sm);
}
.organisation-people-grid small {
  margin-top: 1px;
  color: var(--ink-muted);
  font-size: var(--text-2xs);
}
.organisation-unassigned-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 18rem), 1fr));
  gap: var(--space-5);
  align-items: start;
}
.organisation-attention > summary {
  cursor: pointer;
  font-weight: 650;
}
.organisation-gap-grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: var(--space-3);
  margin: var(--space-4) 0;
}
.organisation-gap-grid > div {
  padding: var(--space-3);
  border: 1px solid var(--line);
  border-radius: var(--radius-md);
  background: var(--panel-sunken);
}
.organisation-gap-grid strong,
.organisation-gap-grid span {
  display: block;
}
.organisation-gap-grid strong {
  font-size: var(--text-lg);
}
.organisation-gap-grid span {
  margin-top: 2px;
  color: var(--ink-muted);
  font-size: var(--text-xs);
}
.organisation-attention h3 {
  margin: var(--space-5) 0 var(--space-2);
  font-size: var(--text-base);
}

@media (max-width: 900px) {
  .organisation-core-grid {
    grid-template-columns: 1fr;
    padding-top: 0;
  }
  .organisation-core-grid::before,
  .organisation-core-grid > .organisation-branch::before {
    display: none;
  }
  .organisation-core-grid > .organisation-branch + .organisation-branch {
    margin-top: var(--space-4);
  }
}
@media (max-width: 680px) {
  .organisation-chart-tiles,
  .organisation-gap-grid {
    grid-template-columns: 1fr 1fr;
  }
  .organisation-descendants {
    margin-left: var(--space-2);
    padding-left: var(--space-4);
  }
}
@media (max-width: 430px) {
  .organisation-chart-tiles,
  .organisation-gap-grid {
    grid-template-columns: 1fr;
  }
  .organisation-node-counts {
    gap: var(--space-2);
  }
}

/* ============================================================ 7. preferences */

/* Windows High Contrast substitutes the system colours for every background, which would
   erase a .tl-dot entirely — it is an empty span whose only rendering IS its background. The
   same goes for the chart fills and the split bar. Keeping our own colours here is the one
   case where overriding the user's palette is the accessible choice, because the alternative
   is no signal at all; the words beside each dot remain the primary carrier either way. */
@media (forced-colors: active) {
  .tl-dot,
  .split-swatch {
    forced-color-adjust: none;
    border: 1px solid CanvasText;
  }
  .donut-svg path,
  .chamber-svg circle,
  .split-bar rect {
    forced-color-adjust: none;
  }
  .sidebar a.active {
    forced-color-adjust: none;
    outline: 2px solid CanvasText;
  }
}

@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
}

@media print {
  .sidebar,
  .topbar,
  .idea-menu,
  .undo-bar,
  .toolbar,
  .pager {
    display: none !important;
  }
  .layout {
    display: block;
  }
  .card {
    border-color: var(--grey-300);
    box-shadow: none;
    break-inside: avoid;
  }
}

/* ---- Users & Access: the account table and its open row ----
   A table, because the question this page answers first is "who has access to what", and that
   is a comparison across people. Detail opens as a row beneath the one you clicked, so the
   account you are changing stays in its place in the list. */
.filter-bar {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  gap: var(--space-3);
  padding: var(--space-4) 0;
  border-bottom: 1px solid var(--line);
}
.filter-bar label {
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
  font-size: var(--text-sm);
  font-weight: 600;
}
.filter-search {
  flex: 1 1 18rem;
}
.account-table td {
  vertical-align: top;
}
.account-row > td {
  border-bottom: none;
}
.account-open-cell {
  text-align: right;
  white-space: nowrap;
}
/* The open row is the same panel colour as the page beneath the list, so it reads as a drawer
   pulled out of the table rather than as another row of data. */
.account-detail-row > td {
  padding: 0;
  background: var(--panel-sunken);
  border-bottom: 2px solid var(--line);
}
.account-detail {
  padding: var(--space-5);
}
.account-detail > .cap {
  margin-top: 0;
}
.account-detail h3 {
  margin: var(--space-5) 0 var(--space-2);
  font-size: var(--text-base);
}
.account-detail section:first-of-type h3 {
  margin-top: 0;
}
.account-edit {
  margin-top: var(--space-5);
  padding-top: var(--space-5);
  border-top: 1px solid var(--line);
}
.account-actions {
  margin-top: var(--space-5);
  gap: var(--space-3);
}
/* Permissions read as a list of things this person can do, ticked or not — the exceptions are
   flagged rather than colour-coded, so the difference from the role survives a greyscale print. */
.permission-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(15rem, 1fr));
  gap: var(--space-2) var(--space-4);
}
.permission-item {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  padding: var(--space-2);
  border: 1px solid transparent;
  border-radius: var(--radius-md);
  font-size: var(--text-sm);
  font-weight: 400;
}
.permission-item--exception {
  border-color: var(--line);
  background: var(--panel);
}
.permission-item .pill {
  margin-left: var(--space-1);
}
.inline-check {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  font-weight: 400;
}
.empty-note {
  padding: var(--space-6) 0;
  text-align: center;
}
/* Narrow screens drop the two columns the open drawer repeats anyway, rather than putting the
   table in a horizontal scroller — which would clip the drawer's height as well as its width. */
@media (max-width: 720px) {
  .account-table th:nth-child(3),
  .account-table td:nth-child(3),
  .account-table th:nth-child(5),
  .account-table td:nth-child(5) {
    display: none;
  }
  .account-detail {
    padding: var(--space-4);
  }
  .permission-grid {
    grid-template-columns: 1fr;
  }
}
/* Present for a screen reader, absent on screen — a table header that would only repeat what
   the button beside it already says. */
.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}
