/**
 * Design tokens: Sistema Eleitoral CFO/CROs.
 *
 * Visual direction: institutional civic with editorial rigour. This is a public
 * election platform, so the surface has to read as trustworthy and legible
 * before it reads as modern. Deliberately light-first: an election is a daytime,
 * institutional act, and a dark interface would fight that.
 *
 * Scale contrast carries the hierarchy, not weight alone. Depth comes from
 * layered surfaces and hairlines rather than heavy shadows.
 */

:root {
  /* --- Neutrals: warm paper, not clinical grey --------------------------- */
  --color-paper: oklch(99% 0.004 95);
  --color-surface: oklch(100% 0 0);
  --color-surface-raised: oklch(97.5% 0.005 95);
  --color-surface-sunken: oklch(96% 0.006 95);

  --color-ink: oklch(21% 0.02 250);
  --color-ink-muted: oklch(46% 0.015 250);
  --color-ink-subtle: oklch(62% 0.012 250);

  --color-line: oklch(90% 0.008 250);
  --color-line-strong: oklch(82% 0.012 250);

  /* --- Institutional teal: the identity colour --------------------------- */
  --color-brand: oklch(48% 0.09 195);
  --color-brand-strong: oklch(38% 0.08 195);
  --color-brand-soft: oklch(95% 0.025 195);
  --color-brand-line: oklch(84% 0.05 195);
  --color-on-brand: oklch(99% 0.004 95);

  /* --- Semantic: colour carries meaning, never decoration ---------------- */
  --color-success: oklch(52% 0.13 155);
  --color-success-soft: oklch(95% 0.04 155);
  --color-warning: oklch(64% 0.14 75);
  --color-warning-soft: oklch(96% 0.05 85);
  --color-danger: oklch(53% 0.19 25);
  --color-danger-soft: oklch(96% 0.03 25);

  /* Reserved for live state: streaming, running tally, open assembly. */
  --color-live: oklch(62% 0.19 35);
  --color-live-soft: oklch(96% 0.04 35);

  /* --- Séries de gráfico --------------------------------------------------
   *
   * Uma escala categórica, e não um degradê da cor da marca. Painel eleitoral
   * compara conselhos e chapas, que são categorias sem ordem entre si, e um
   * degradê sugeriria uma progressão que os dados não têm.
   *
   * As matizes estão espaçadas de propósito, e a claridade varia junto com
   * elas: quem não distingue vermelho de verde continua distinguindo os traços
   * pelo tom, e a impressão em preto e branco também.
   */
  --chart-1: oklch(48% 0.09 195);
  --chart-2: oklch(58% 0.13 255);
  --chart-3: oklch(64% 0.14 75);
  --chart-4: oklch(52% 0.13 155);
  --chart-5: oklch(53% 0.16 25);
  --chart-6: oklch(45% 0.12 305);
  --chart-7: oklch(70% 0.10 140);
  --chart-8: oklch(38% 0.08 195);

  /* Fundo e malha do gráfico. Hairline, não caixa: a grade orienta a leitura
   * do valor e não deve competir com a série. */
  --chart-grid: oklch(92% 0.008 250);
  --chart-axis: oklch(70% 0.012 250);

  /* --- Typography -------------------------------------------------------- */
  --font-sans: ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto,
    "Helvetica Neue", Arial, sans-serif;
  --font-mono: ui-monospace, "SF Mono", "JetBrains Mono", "Fira Code",
    "Roboto Mono", monospace;

  --text-caption: clamp(0.72rem, 0.7rem + 0.1vw, 0.78rem);
  --text-small: clamp(0.82rem, 0.8rem + 0.1vw, 0.88rem);
  --text-body: clamp(0.94rem, 0.9rem + 0.18vw, 1rem);
  --text-lead: clamp(1.05rem, 1rem + 0.28vw, 1.2rem);
  --text-title: clamp(1.3rem, 1.15rem + 0.7vw, 1.75rem);
  --text-display: clamp(1.9rem, 1.4rem + 2.2vw, 3.1rem);
  /* Tally figures need to read across a room during the proclamation. */
  --text-figure: clamp(2.4rem, 1.6rem + 3.6vw, 4.5rem);

  --tracking-tight: -0.02em;
  --tracking-wide: 0.08em;
  --leading-tight: 1.15;
  --leading-body: 1.6;

  /* --- Spacing: a rhythm, not a uniform grid ----------------------------- */
  --space-2xs: 0.25rem;
  --space-xs: 0.5rem;
  --space-sm: 0.75rem;
  --space-md: 1rem;
  --space-lg: 1.5rem;
  --space-xl: 2.25rem;
  --space-2xl: 3.5rem;
  --space-section: clamp(2.5rem, 2rem + 3vw, 5rem);

  /* --- Radius: varied on purpose ---------------------------------------- */
  --radius-xs: 4px;
  --radius-sm: 6px;
  --radius-md: 10px;
  --radius-lg: 16px;
  --radius-pill: 999px;

  /* --- Depth: hairline first, shadow second ----------------------------- */
  --shadow-hairline: 0 0 0 1px oklch(21% 0.02 250 / 0.06);
  --shadow-raised: 0 1px 2px oklch(21% 0.02 250 / 0.05),
    0 4px 12px oklch(21% 0.02 250 / 0.05);
  --shadow-overlay: 0 8px 24px oklch(21% 0.02 250 / 0.1),
    0 2px 6px oklch(21% 0.02 250 / 0.06);

  /* --- Motion ------------------------------------------------------------ */
  --duration-fast: 140ms;
  --duration-normal: 240ms;
  --ease-out-expo: cubic-bezier(0.16, 1, 0.3, 1);

  --layout-max: 84rem;
  --layout-reading: 46rem;
}

/**
 * The platform commits to a single light identity, so no dark palette is
 * defined. Contrast, background and text are all painted explicitly, which
 * keeps the page from borrowing the host's theme.
 */

@media (prefers-reduced-motion: reduce) {
  :root {
    --duration-fast: 0ms;
    --duration-normal: 0ms;
  }
}
/* Reset and base typography. */

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

* {
  margin: 0;
}

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

@media (prefers-reduced-motion: reduce) {
  html {
    scroll-behavior: auto;
  }
}

body {
  min-height: 100dvh;
  font-family: var(--font-sans);
  font-size: var(--text-body);
  line-height: var(--leading-body);
  color: var(--color-ink);
  background: var(--color-paper);
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

img,
picture,
video,
canvas,
svg {
  display: block;
  max-width: 100%;
}

input,
button,
textarea,
select {
  font: inherit;
  color: inherit;
}

button {
  cursor: pointer;
  background: none;
  border: none;
}

h1,
h2,
h3,
h4 {
  line-height: var(--leading-tight);
  letter-spacing: var(--tracking-tight);
  text-wrap: balance;
  font-weight: 640;
}

p {
  text-wrap: pretty;
}

a {
  color: var(--color-brand-strong);
  text-underline-offset: 0.2em;
}

/* Focus is designed, not inherited. Keyboard voters must always see where
   they are: this is an accessibility requirement, not a nicety. */
:focus-visible {
  outline: 2px solid var(--color-brand);
  outline-offset: 2px;
  border-radius: var(--radius-xs);
}

:focus:not(:focus-visible) {
  outline: none;
}

::selection {
  background: var(--color-brand-soft);
  color: var(--color-brand-strong);
}

/* Visible only to screen readers. */
.vc-sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

/* Skip link: first stop for keyboard navigation. */
.vc-skip-link {
  position: absolute;
  top: var(--space-xs);
  left: var(--space-xs);
  z-index: 100;
  padding: var(--space-xs) var(--space-md);
  background: var(--color-brand);
  color: var(--color-on-brand);
  border-radius: var(--radius-sm);
  transform: translateY(-200%);
  transition: transform var(--duration-fast) var(--ease-out-expo);
}

.vc-skip-link:focus {
  transform: translateY(0);
}
/* Components of the shared design system. */

/* --- Layout -------------------------------------------------------------- */
.vc-shell {
  display: grid;
  grid-template-rows: auto 1fr auto;
  /* A grid item defaults to min-width: auto, which is its min-content width, so
     the single column here would refuse to be narrower than the widest row.
     The header's navigation held it at 945px and every screen scrolled
     sideways at 320px. minmax(0, 1fr) is what lets the column be as narrow as
     the viewport and hand the overflow to the element that can scroll. */
  grid-template-columns: minmax(0, 1fr);
  min-height: 100dvh;
}

.vc-container {
  width: 100%;
  max-width: var(--layout-max);
  margin-inline: auto;
  padding-inline: clamp(var(--space-md), 4vw, var(--space-xl));
}

/* --- Header -------------------------------------------------------------- */
.vc-header {
  position: sticky;
  top: 0;
  z-index: 20;
  background: color-mix(in oklch, var(--color-surface) 88%, transparent);
  backdrop-filter: blur(12px);
  border-bottom: 1px solid var(--color-line);
}

.vc-header__inner {
  display: flex;
  align-items: center;
  gap: var(--space-lg);
  min-height: 4rem;
}

.vc-header__brand {
  display: flex;
  align-items: center;
  gap: var(--space-sm);
  font-weight: 680;
  letter-spacing: var(--tracking-tight);
  color: var(--color-ink);
  text-decoration: none;
  white-space: nowrap;
  /* The brand keeps its size; the navigation is what gives way on narrow
     screens, because a truncated institution name reads as a broken page. */
  flex-shrink: 0;
}

.vc-header__mark {
  display: grid;
  place-items: center;
  width: 2rem;
  height: 2rem;
  border-radius: var(--radius-sm);
  background: var(--color-brand);
  color: var(--color-on-brand);
  font-size: var(--text-small);
  font-weight: 700;
  letter-spacing: 0;
}

.vc-header__nav {
  display: flex;
  align-items: center;
  gap: var(--space-2xs);
  margin-inline-start: auto;
  overflow-x: auto;
  scrollbar-width: none;
  /* Without this the scrolling never happens. A flex item will not shrink below
     the width of its content unless min-width is cleared, so the six links kept
     the header 945px wide and the whole page scrolled sideways at 320px, which
     is what item P33 forbids. The overflow-x above only takes effect once the
     item is allowed to be narrower than what it holds. */
  min-width: 0;
}

.vc-header__nav::-webkit-scrollbar {
  display: none;
}

/* On a narrow screen the brand, six modules and the session cannot share one
   line: the nav shrinks to a few pixels and the session is pushed past the
   viewport, which is the horizontal scrolling item P33 forbids. Two rows solve
   it without hiding anything. */
@media (max-width: 60rem) {
  .vc-header__inner {
    flex-wrap: wrap;
    gap: var(--space-sm);
    padding-block: var(--space-sm);
  }

  .vc-header__nav {
    order: 3;
    flex-basis: 100%;
    margin-inline-start: 0;
    /* Edge to edge, so the scrolled row does not look cut off mid-padding. */
    margin-inline: calc(-1 * var(--space-md));
    padding-inline: var(--space-md);
  }
}

.vc-navlink {
  padding: var(--space-2xs) var(--space-sm);
  border-radius: var(--radius-sm);
  color: var(--color-ink-muted);
  font-size: var(--text-small);
  font-weight: 520;
  text-decoration: none;
  white-space: nowrap;
  transition: color var(--duration-fast) var(--ease-out-expo),
    background-color var(--duration-fast) var(--ease-out-expo);
}

.vc-navlink:hover {
  color: var(--color-ink);
  background: var(--color-surface-sunken);
}

.vc-navlink[aria-current='page'] {
  color: var(--color-brand-strong);
  background: var(--color-brand-soft);
}

/* --- Surfaces ------------------------------------------------------------ */
.vc-card {
  background: var(--color-surface);
  border: 1px solid var(--color-line);
  border-radius: var(--radius-lg);
  padding: var(--space-lg);
}

.vc-card--raised {
  box-shadow: var(--shadow-raised);
  border-color: transparent;
}

.vc-card--sunken {
  background: var(--color-surface-sunken);
  border-style: dashed;
}

.vc-card__title {
  font-size: var(--text-lead);
  font-weight: 620;
  margin-bottom: var(--space-2xs);
}

.vc-card__hint {
  font-size: var(--text-small);
  color: var(--color-ink-muted);
}

/* --- Eyebrow: small caps label above a title ----------------------------- */
.vc-eyebrow {
  display: block;
  font-size: var(--text-caption);
  font-weight: 640;
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
  color: var(--color-ink-subtle);
  margin-bottom: var(--space-xs);
}

/* --- Badge --------------------------------------------------------------- */
.vc-badge {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2xs);
  padding: 0.15rem var(--space-xs);
  border-radius: var(--radius-pill);
  font-size: var(--text-caption);
  font-weight: 600;
  letter-spacing: 0.01em;
  white-space: nowrap;
}

/* Selo que carrega frase, e nao rotulo.
 *
 * O nowrap acima esta certo para o uso comum, "Quorum atingido", "1 de 2
 * presentes": rotulo que quebra no meio fica ilegivel. Deixa de estar certo
 * quando o conteudo e uma frase inteira, porque ai o selo empurra a pagina e
 * cria rolagem horizontal.
 *
 * Aconteceu em /inteligencia a 320px, com "Nenhuma API de IA de terceiro
 * configurada". No macOS a fonte do sistema e mais estreita e cabia raspando;
 * no Linux nao cabia, e o teste P33 falhava so no runner. Nao era o teste: o
 * layout estava com margem zero. */
.vc-badge--wrap {
  white-space: normal;
  max-width: 100%;
}

.vc-badge--neutral {
  background: var(--color-surface-sunken);
  color: var(--color-ink-muted);
}
.vc-badge--brand {
  background: var(--color-brand-soft);
  color: var(--color-brand-strong);
}
.vc-badge--success {
  background: var(--color-success-soft);
  color: var(--color-success);
}
.vc-badge--warning {
  background: var(--color-warning-soft);
  color: oklch(42% 0.11 75);
}
.vc-badge--danger {
  background: var(--color-danger-soft);
  color: var(--color-danger);
}
.vc-badge--live {
  background: var(--color-live-soft);
  color: var(--color-live);
}

.vc-badge__dot {
  width: 0.45rem;
  height: 0.45rem;
  border-radius: var(--radius-pill);
  background: currentColor;
  flex-shrink: 0;
}

.vc-badge--live .vc-badge__dot {
  animation: vc-pulse 1.8s var(--ease-out-expo) infinite;
}

@keyframes vc-pulse {
  0%,
  100% {
    opacity: 1;
    transform: scale(1);
  }
  50% {
    opacity: 0.45;
    transform: scale(0.82);
  }
}

@media (prefers-reduced-motion: reduce) {
  .vc-badge--live .vc-badge__dot {
    animation: none;
  }
}

/* --- Button -------------------------------------------------------------- */
.vc-button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-xs);
  padding: 0.55rem var(--space-md);
  border-radius: var(--radius-sm);
  font-size: var(--text-small);
  font-weight: 580;
  border: 1px solid transparent;
  transition: background-color var(--duration-fast) var(--ease-out-expo),
    border-color var(--duration-fast) var(--ease-out-expo),
    transform var(--duration-fast) var(--ease-out-expo);
}

.vc-button:active:not(:disabled) {
  transform: translateY(1px);
}

.vc-button:disabled {
  opacity: 0.5;
  cursor: not-allowed;
}

.vc-button--primary {
  background: var(--color-brand);
  color: var(--color-on-brand);
}
.vc-button--primary:hover:not(:disabled) {
  background: var(--color-brand-strong);
}

.vc-button--secondary {
  background: var(--color-surface);
  color: var(--color-ink);
  border-color: var(--color-line-strong);
}
.vc-button--secondary:hover:not(:disabled) {
  background: var(--color-surface-sunken);
  border-color: var(--color-ink-subtle);
}

.vc-button--ghost {
  background: transparent;
  color: var(--color-ink-muted);
}
.vc-button--ghost:hover:not(:disabled) {
  background: var(--color-surface-sunken);
  color: var(--color-ink);
}

.vc-button--danger {
  background: var(--color-danger);
  color: var(--color-on-brand);
}

.vc-button--lg {
  padding: 0.8rem var(--space-lg);
  font-size: var(--text-body);
}

/* --- Module fallback: the graceful degradation card of item P28 ---------- */
.vc-fallback {
  display: grid;
  gap: var(--space-md);
  justify-items: start;
  padding: var(--space-xl);
  background: var(--color-surface);
  border: 1px dashed var(--color-line-strong);
  border-radius: var(--radius-lg);
  max-width: var(--layout-reading);
}

.vc-fallback__icon {
  display: grid;
  place-items: center;
  width: 2.75rem;
  height: 2.75rem;
  border-radius: var(--radius-md);
  background: var(--color-warning-soft);
  color: oklch(42% 0.11 75);
}

.vc-fallback__title {
  font-size: var(--text-title);
}

.vc-fallback__message {
  color: var(--color-ink-muted);
  max-width: 52ch;
}

.vc-fallback__meta {
  font-family: var(--font-mono);
  font-size: var(--text-caption);
  color: var(--color-ink-subtle);
}

.vc-fallback__actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-xs);
}

/* --- Spinner ------------------------------------------------------------- */
.vc-spinner {
  width: 1.15rem;
  height: 1.15rem;
  border: 2px solid var(--color-line-strong);
  border-top-color: var(--color-brand);
  border-radius: var(--radius-pill);
  animation: vc-spin 700ms linear infinite;
}

@keyframes vc-spin {
  to {
    transform: rotate(360deg);
  }
}

@media (prefers-reduced-motion: reduce) {
  .vc-spinner {
    animation-duration: 2s;
  }
}

.vc-loading {
  display: grid;
  gap: var(--space-sm);
  justify-items: center;
  padding: var(--space-2xl);
  color: var(--color-ink-muted);
  font-size: var(--text-small);
}

/* --- Table --------------------------------------------------------------- */
.vc-table-wrap {
  overflow-x: auto;
  border: 1px solid var(--color-line);
  border-radius: var(--radius-lg);
  background: var(--color-surface);
}

.vc-table {
  width: 100%;
  border-collapse: collapse;
  font-size: var(--text-small);
}

.vc-table th {
  position: sticky;
  top: 0;
  text-align: start;
  font-size: var(--text-caption);
  font-weight: 640;
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
  color: var(--color-ink-subtle);
  background: var(--color-surface-raised);
  padding: var(--space-sm) var(--space-md);
  border-bottom: 1px solid var(--color-line);
  white-space: nowrap;
}

.vc-table td {
  padding: var(--space-sm) var(--space-md);
  border-bottom: 1px solid var(--color-line);
  vertical-align: middle;
}

.vc-table tbody tr:last-child td {
  border-bottom: none;
}

.vc-table tbody tr:hover {
  background: var(--color-surface-sunken);
}

.vc-mono {
  font-family: var(--font-mono);
  font-size: 0.92em;
  color: var(--color-ink-muted);
}

/* --- Modal ----------------------------------------------------------------
   Rendered into document.body through a portal, so it escapes the overflow and
   the stacking context of whatever card invoked it. A camera preview mounted in
   the page flow gets clipped by its container or pushes the page down; here it
   floats above everything, at a size the dialog controls.
   -------------------------------------------------------------------------- */

.vc-modal {
  position: fixed;
  inset: 0;
  z-index: 100;
  display: grid;
  place-items: center;
  padding: var(--space-md);
  background: oklch(21% 0.02 250 / 0.45);
  backdrop-filter: blur(3px);
  animation: vc-modal-in var(--duration-normal) var(--ease-out-expo);
}

.vc-modal__panel {
  display: flex;
  flex-direction: column;
  width: 100%;
  /* Never taller than the viewport: the body scrolls, the dialog does not grow
     past the screen and strand its own close button off-screen. */
  max-height: min(92vh, 56rem);
  background: var(--color-surface);
  border: 1px solid var(--color-line);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-overlay);
  animation: vc-modal-rise var(--duration-normal) var(--ease-out-expo);
}

.vc-modal__panel--narrow {
  max-width: 32rem;
}

.vc-modal__panel--wide {
  max-width: 44rem;
}

/* Wide enough for two fields on a line and still narrow enough that the eye
   does not have to travel across a whole desktop to read one label. */
.vc-modal__panel--form {
  max-width: 56rem;
}

/* Para o que só se lê largo: um grafo de caminho com quatro participantes
   encolhido para caber vira quatro caixas indistintas. */
.vc-modal__panel--canvas {
  max-width: 76rem;
}

.vc-modal__header {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--space-md);
  padding: var(--space-lg) var(--space-lg) var(--space-md);
  border-bottom: 1px solid var(--color-line);
}

.vc-modal__title {
  margin: 0;
  font-size: var(--text-lead);
  font-weight: 600;
  letter-spacing: -0.01em;
  color: var(--color-ink);
}

.vc-modal__description {
  margin: var(--space-2xs) 0 0;
  font-size: var(--text-small);
  color: var(--color-ink-muted);
}

.vc-modal__close {
  flex-shrink: 0;
  display: grid;
  place-items: center;
  width: 2rem;
  height: 2rem;
  font-size: 1.35rem;
  line-height: 1;
  color: var(--color-ink-muted);
  background: transparent;
  border: 1px solid transparent;
  border-radius: var(--radius-sm);
  cursor: pointer;
  transition: background var(--duration-fast), color var(--duration-fast);
}

.vc-modal__close:hover {
  background: var(--color-surface-sunken);
  color: var(--color-ink);
}

.vc-modal__close:focus-visible {
  outline: 2px solid var(--color-brand);
  outline-offset: 2px;
}

.vc-modal__body {
  /* min-height keeps a grid child from refusing to shrink, which would make the
     scroll happen on the page instead of inside the dialog. */
  min-height: 0;
  overflow-y: auto;
  padding: var(--space-lg);
}

@keyframes vc-modal-in {
  from {
    opacity: 0;
  }
}

@keyframes vc-modal-rise {
  from {
    opacity: 0;
    transform: translateY(0.75rem) scale(0.985);
  }
}

@media (prefers-reduced-motion: reduce) {
  .vc-modal,
  .vc-modal__panel {
    animation: none;
  }
}

/* --- Face Liveness --------------------------------------------------------
   The AWS component ships its own stylesheet and its own theme variables. What
   is set here is only the frame it lives in: a fixed aspect box, so the camera
   cannot stretch the dialog, and the Amplify accent aligned with the platform
   brand instead of the default purple.
   -------------------------------------------------------------------------- */

.vc-liveness {
  width: 100%;
  /* Portrait, which is the orientation the oval expects. Without a bounded box
     the video element reports its intrinsic size and the widget grows past the
     dialog. */
  aspect-ratio: 3 / 4;
  max-height: 60vh;
  margin-inline: auto;
  overflow: hidden;
  border-radius: var(--radius-md);
  background: oklch(21% 0.02 250);
}

.vc-liveness [data-amplify-liveness-detector],
.vc-liveness .amplify-liveness-detector {
  width: 100%;
  height: 100%;
}

.vc-liveness {
  --amplify-colors-brand-primary-80: var(--color-brand);
  --amplify-colors-brand-primary-90: var(--color-brand-strong);
  --amplify-colors-brand-primary-100: var(--color-brand-strong);
  --amplify-components-button-primary-background-color: var(--color-brand);
  --amplify-components-button-primary-hover-background-color: var(--color-brand-strong);
  --amplify-fonts-default-variable: inherit;
  --amplify-fonts-default-static: inherit;
}

/* --- Session in the header ------------------------------------------------ */

.vc-header__session {
  display: flex;
  align-items: center;
  gap: var(--space-sm);
  margin-inline-start: auto;
  /* The session must not be the item that gives way: squeezed, it is the "Sair"
     button that disappears past the edge of the screen. */
  flex-shrink: 0;
  /* Without this the identity block refuses to shrink and reintroduces the
     horizontal overflow of item P33 on a narrow screen. */
  min-width: 0;
}

.vc-header__identity {
  display: none;
  min-width: 0;
  text-align: end;
  line-height: 1.25;
}

.vc-header__name {
  display: block;
  font-size: var(--text-small);
  font-weight: 600;
  color: var(--color-ink);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.vc-header__method {
  display: block;
  font-size: var(--text-caption);
  color: var(--color-ink-subtle);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.vc-header__signout {
  flex-shrink: 0;
  padding: var(--space-2xs) var(--space-sm);
  font: inherit;
  font-size: var(--text-small);
  font-weight: 500;
  color: var(--color-ink-muted);
  background: transparent;
  border: 1px solid var(--color-line-strong);
  border-radius: var(--radius-pill);
  cursor: pointer;
  transition:
    color var(--duration-fast),
    border-color var(--duration-fast),
    background var(--duration-fast);
}

.vc-header__signout:hover {
  color: var(--color-ink);
  background: var(--color-surface-sunken);
  border-color: var(--color-ink-subtle);
}

.vc-header__signout:focus-visible {
  outline: 2px solid var(--color-brand);
  outline-offset: 2px;
}

@media (min-width: 60rem) {
  .vc-header__identity {
    display: block;
    max-width: 14rem;
  }
}

/* --- Footer --------------------------------------------------------------- */

.vc-footer {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-xs);
  padding-block: var(--space-lg);
  border-top: 1px solid var(--color-line);
  font-size: var(--text-caption);
  color: var(--color-ink-subtle);
}

/* --- Access methods -------------------------------------------------------
   The login options, as one list of rows rather than a grid of cards. A card
   with a button inside gives the voter two targets for one decision, and on a
   screen whose only job is "choose how to identify yourself" that is one target
   too many.
   -------------------------------------------------------------------------- */

.vc-methods {
  display: grid;
  gap: var(--space-sm);
  margin: 0;
  padding: 0;
  list-style: none;
}

.vc-method {
  display: flex;
  align-items: center;
  gap: var(--space-md);
  width: 100%;
  padding: var(--space-md);
  font: inherit;
  text-align: start;
  color: var(--color-ink);
  background: var(--color-surface);
  border: 1px solid var(--color-line);
  border-radius: var(--radius-md);
  cursor: pointer;
  transition:
    border-color var(--duration-fast) var(--ease-out-expo),
    box-shadow var(--duration-fast) var(--ease-out-expo),
    transform var(--duration-fast) var(--ease-out-expo);
}

.vc-method:hover:not(:disabled) {
  border-color: var(--color-brand-line);
  box-shadow: var(--shadow-raised);
  transform: translateY(-1px);
}

.vc-method:focus-visible {
  outline: 2px solid var(--color-brand);
  outline-offset: 2px;
}

.vc-method:active:not(:disabled) {
  transform: translateY(0);
}

.vc-method:disabled {
  cursor: not-allowed;
  background: var(--color-surface-sunken);
  border-style: dashed;
}

.vc-method__icon {
  display: grid;
  place-items: center;
  flex-shrink: 0;
  width: 2.75rem;
  height: 2.75rem;
  color: var(--color-brand);
  background: var(--color-brand-soft);
  border-radius: var(--radius-md);
}

.vc-method:disabled .vc-method__icon {
  color: var(--color-ink-subtle);
  background: var(--color-surface-raised);
}

.vc-method__icon svg {
  width: 1.35rem;
  height: 1.35rem;
}

.vc-method__text {
  /* Lets the description wrap instead of forcing the row wide, which is what
     reintroduces horizontal scrolling at 320px. */
  min-width: 0;
  flex: 1;
}

.vc-method__label {
  display: block;
  font-size: var(--text-body);
  font-weight: 600;
  letter-spacing: -0.01em;
}

.vc-method__hint {
  display: block;
  margin-top: 0.1rem;
  font-size: var(--text-small);
  color: var(--color-ink-muted);
}

.vc-method__reason {
  display: block;
  margin-top: var(--space-2xs);
  font-size: var(--text-caption);
  color: var(--color-warning);
}

.vc-method__go {
  flex-shrink: 0;
  color: var(--color-ink-subtle);
  transition: transform var(--duration-fast) var(--ease-out-expo);
}

.vc-method:hover:not(:disabled) .vc-method__go {
  color: var(--color-brand);
  transform: translateX(2px);
}

.vc-method__go svg {
  width: 1.1rem;
  height: 1.1rem;
  display: block;
}

.vc-method__spinner {
  flex-shrink: 0;
  width: 1.1rem;
  height: 1.1rem;
  border: 2px solid var(--color-brand-line);
  border-top-color: var(--color-brand);
  border-radius: 50%;
  animation: vc-spin 700ms linear infinite;
}

@media (prefers-reduced-motion: reduce) {
  .vc-method,
  .vc-method__go {
    transition: none;
  }
  .vc-method__spinner {
    animation-duration: 2s;
  }
}

/* --- Corporate access layout ----------------------------------------------
   Two columns on a wide screen, one on a narrow one. The institutional column
   carries the council, the poll in progress and the notice that access is
   recorded; the access column carries the decision. A single centred column
   reads as a consumer product, and this screen is the front door of a federal
   council's election.
   -------------------------------------------------------------------------- */

.vc-auth {
  min-height: 100dvh;
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  background: var(--color-paper);
}

.vc-auth__aside {
  display: none;
  flex-direction: column;
  gap: var(--space-xl);
  padding: var(--space-2xl);
  color: var(--color-on-brand);
  background:
    /* A fine diagonal weave, barely visible. Flat colour at this size reads as
       an unfinished block; the texture is what makes it look like a surface. */
    repeating-linear-gradient(
      135deg,
      color-mix(in oklch, var(--color-on-brand) 3%, transparent) 0 1px,
      transparent 1px 7px
    ),
    radial-gradient(
      90% 60% at 15% 0%,
      color-mix(in oklch, var(--color-brand) 78%, white) 0%,
      transparent 55%
    ),
    var(--color-brand-strong);
}

/* Pushes everything after it down, so the column has one gap instead of two and
   the message sits with the poll rather than floating alone mid-height. */
.vc-auth__brand {
  margin-bottom: auto;
}

.vc-auth__brand {
  display: flex;
  align-items: center;
  gap: var(--space-md);
}

.vc-auth__mark {
  display: grid;
  place-items: center;
  flex-shrink: 0;
  width: 3rem;
  height: 3rem;
  font-size: var(--text-small);
  font-weight: 700;
  letter-spacing: 0.04em;
  color: var(--color-on-brand);
  background: var(--color-brand);
  border-radius: var(--radius-md);
}

.vc-auth__aside .vc-auth__mark {
  color: var(--color-brand-strong);
  background: var(--color-on-brand);
}

.vc-auth__org {
  margin: 0;
  font-size: var(--text-caption);
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--color-ink-subtle);
}

.vc-auth__aside .vc-auth__org {
  color: color-mix(in oklch, var(--color-on-brand) 70%, transparent);
}

.vc-auth__title {
  margin: 0;
  font-size: var(--text-lead);
  font-weight: 650;
  letter-spacing: -0.01em;
  color: var(--color-ink);
}

.vc-auth__aside .vc-auth__title {
  color: var(--color-on-brand);
}

.vc-auth__statement {
  max-width: 26rem;
  margin: 0;
  font-size: var(--text-title);
  font-weight: 600;
  line-height: 1.2;
  letter-spacing: -0.02em;
}

.vc-auth__poll {
  display: grid;
  gap: var(--space-2xs);
  padding: var(--space-md);
  border: 1px solid color-mix(in oklch, var(--color-on-brand) 22%, transparent);
  border-radius: var(--radius-md);
  background: color-mix(in oklch, var(--color-on-brand) 8%, transparent);
}

.vc-auth__poll dt {
  font-size: var(--text-caption);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: color-mix(in oklch, var(--color-on-brand) 68%, transparent);
}

.vc-auth__poll dd {
  margin: 0 0 var(--space-xs);
  font-size: var(--text-body);
  font-weight: 500;
}

.vc-auth__poll dd:last-child {
  margin-bottom: 0;
}

.vc-auth__notice {
  max-width: 28rem;
  margin: 0;
  padding-top: var(--space-lg);
  border-top: 1px solid color-mix(in oklch, var(--color-on-brand) 18%, transparent);
  font-size: var(--text-small);
  line-height: 1.5;
  color: color-mix(in oklch, var(--color-on-brand) 78%, transparent);
}

.vc-auth__main {
  display: grid;
  place-items: center;
  padding: var(--space-xl) var(--space-md);
}

.vc-auth__panel {
  width: 100%;
  max-width: 30rem;
  display: grid;
  gap: var(--space-lg);
}

/* Shown only on narrow screens, where the institutional column is gone and the
   voter would otherwise meet a login form with no indication of whose it is. */
.vc-auth__compact-brand {
  display: flex;
  align-items: center;
  gap: var(--space-md);
}

.vc-auth__footer {
  display: grid;
  gap: var(--space-2xs);
  padding-top: var(--space-md);
  border-top: 1px solid var(--color-line);
  font-size: var(--text-small);
  color: var(--color-ink-muted);
}

.vc-auth__footer p {
  margin: 0;
}

.vc-auth__legal {
  font-size: var(--text-caption);
  color: var(--color-ink-subtle);
}

@media (min-width: 64rem) {
  .vc-auth {
    grid-template-columns: minmax(0, 5fr) minmax(0, 7fr);
  }

  .vc-auth__aside {
    display: flex;
  }

  .vc-auth__compact-brand {
    display: none;
  }

  .vc-auth__main {
    padding: var(--space-2xl);
  }
}

/* --- Operational dashboard -------------------------------------------------
   What someone sees on entering. Not an index of modules: an index tells the
   person where things are, and what they arrive needing is the state of the
   poll they are part of.
   -------------------------------------------------------------------------- */

.vc-dash__header {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: var(--space-lg);
  flex-wrap: wrap;
  margin-bottom: var(--space-xl);
}

.vc-dash__grid {
  display: grid;
  gap: var(--space-md);
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 17rem), 1fr));
}

.vc-dash__section {
  margin-top: var(--space-xl);
}

.vc-dash__section-title {
  margin: 0 0 var(--space-md);
  font-size: var(--text-lead);
  font-weight: 600;
  letter-spacing: -0.01em;
}

/* A metric, not a card of text: the number carries the meaning and everything
   else exists to qualify it. */
.vc-metric {
  display: grid;
  gap: var(--space-2xs);
  align-content: start;
  padding: var(--space-lg);
  background: var(--color-surface);
  border: 1px solid var(--color-line);
  border-radius: var(--radius-md);
}

.vc-metric__label {
  font-size: var(--text-caption);
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--color-ink-subtle);
}

.vc-metric__value {
  font-size: var(--text-figure);
  font-weight: 600;
  line-height: 1;
  letter-spacing: -0.03em;
  color: var(--color-ink);
  font-variant-numeric: tabular-nums;
}

.vc-metric__unit {
  font-size: var(--text-lead);
  font-weight: 500;
  color: var(--color-ink-subtle);
}

.vc-metric__hint {
  font-size: var(--text-small);
  color: var(--color-ink-muted);
}

/* Progress as a bar rather than only a percentage: a number answers "how much",
   a bar answers "how far from the threshold", which is the question a turnout
   figure is actually asked. */
.vc-meter {
  height: 0.4rem;
  margin-top: var(--space-2xs);
  overflow: hidden;
  background: var(--color-surface-sunken);
  border-radius: var(--radius-pill);
}

.vc-meter__fill {
  height: 100%;
  background: var(--color-brand);
  border-radius: inherit;
  transition: width var(--duration-normal) var(--ease-out-expo);
}

.vc-meter__fill--warning {
  background: var(--color-warning);
}

.vc-action {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-md);
  padding: var(--space-md) var(--space-lg);
  color: inherit;
  text-decoration: none;
  background: var(--color-surface);
  border: 1px solid var(--color-line);
  border-radius: var(--radius-md);
  transition:
    border-color var(--duration-fast) var(--ease-out-expo),
    box-shadow var(--duration-fast) var(--ease-out-expo),
    transform var(--duration-fast) var(--ease-out-expo);
}

.vc-action:hover {
  border-color: var(--color-brand-line);
  box-shadow: var(--shadow-raised);
  transform: translateY(-1px);
}

.vc-action:focus-visible {
  outline: 2px solid var(--color-brand);
  outline-offset: 2px;
}

.vc-action__label {
  display: block;
  font-weight: 600;
}

.vc-action__hint {
  display: block;
  margin-top: 0.1rem;
  font-size: var(--text-small);
  color: var(--color-ink-muted);
}

.vc-table--compact td,
.vc-table--compact th {
  padding-block: var(--space-xs);
  font-size: var(--text-small);
}

@media (prefers-reduced-motion: reduce) {
  .vc-action,
  .vc-meter__fill {
    transition: none;
  }
}

/* --- Choosing a method, as a step -----------------------------------------
   Picking a method used to append a card below the whole list, so the panel
   appeared far from the row that was clicked and, on a phone, below the fold.
   The choice is a step now: the list gives way to the method, and a single
   control comes back.
   -------------------------------------------------------------------------- */

.vc-step {
  display: grid;
  gap: var(--space-md);
  animation: vc-step-in var(--duration-normal) var(--ease-out-expo);
}

.vc-step__back {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2xs);
  justify-self: start;
  padding: var(--space-2xs) var(--space-xs);
  margin-inline-start: calc(-1 * var(--space-xs));
  font: inherit;
  font-size: var(--text-small);
  font-weight: 500;
  color: var(--color-ink-muted);
  background: transparent;
  border: 1px solid transparent;
  border-radius: var(--radius-sm);
  cursor: pointer;
  transition: color var(--duration-fast), background var(--duration-fast);
}

.vc-step__back:hover {
  color: var(--color-ink);
  background: var(--color-surface-sunken);
}

.vc-step__back:focus-visible {
  outline: 2px solid var(--color-brand);
  outline-offset: 2px;
}

@keyframes vc-step-in {
  from {
    opacity: 0;
    transform: translateY(0.4rem);
  }
}

/* The certificate is the institutional method, and the only one that carries a
   legal identity end to end. A hairline of the brand colour marks it without
   turning the list into a ranking. */
.vc-method--featured {
  border-inline-start: 3px solid var(--color-brand);
}

/* Placeholders while the methods are fetched. An empty area reads as a broken
   screen; rows of the right shape read as a screen that is still arriving. */
.vc-method--skeleton {
  display: flex;
  align-items: center;
  gap: var(--space-md);
  padding: var(--space-md);
  border: 1px solid var(--color-line);
  border-radius: var(--radius-md);
  background: var(--color-surface);
}

.vc-skeleton {
  background: linear-gradient(
    90deg,
    var(--color-surface-sunken) 0%,
    var(--color-surface-raised) 50%,
    var(--color-surface-sunken) 100%
  );
  background-size: 200% 100%;
  border-radius: var(--radius-sm);
  animation: vc-skeleton 1.4s ease-in-out infinite;
}

@keyframes vc-skeleton {
  to {
    background-position: -200% 0;
  }
}

@media (prefers-reduced-motion: reduce) {
  .vc-step,
  .vc-skeleton {
    animation: none;
  }
}

/* --- Form fields ----------------------------------------------------------
   `.vc-input` was used across every module and never defined, so every text
   box in the platform rendered with the browser's default chrome: a hairline
   border, no radius, no padding, and a width that ignored its container. Inputs
   are where most of the interaction happens, so that one gap made the whole
   system look unfinished.
   -------------------------------------------------------------------------- */

.vc-field {
  display: grid;
  gap: var(--space-2xs);
}

.vc-label {
  font-size: var(--text-small);
  font-weight: 600;
  color: var(--color-ink);
}

.vc-label__optional {
  margin-inline-start: var(--space-2xs);
  font-weight: 400;
  color: var(--color-ink-subtle);
}

.vc-input,
.vc-select,
.vc-textarea {
  /* Block-level and full width by default. Inline-level inputs are what made
     labels, fields and buttons share a line and collide. */
  display: block;
  width: 100%;
  padding: 0.6rem 0.75rem;
  font: inherit;
  font-size: var(--text-body);
  color: var(--color-ink);
  background: var(--color-surface);
  border: 1px solid var(--color-line-strong);
  border-radius: var(--radius-sm);
  transition:
    border-color var(--duration-fast) var(--ease-out-expo),
    box-shadow var(--duration-fast) var(--ease-out-expo);
  /* Safari rounds and shades form controls on its own. */
  appearance: none;
}

.vc-textarea {
  min-height: 6rem;
  line-height: 1.5;
  resize: vertical;
}

.vc-input::placeholder,
.vc-textarea::placeholder {
  color: var(--color-ink-subtle);
}

.vc-input:hover:not(:disabled),
.vc-select:hover:not(:disabled),
.vc-textarea:hover:not(:disabled) {
  border-color: var(--color-ink-subtle);
}

.vc-input:focus-visible,
.vc-select:focus-visible,
.vc-textarea:focus-visible {
  outline: none;
  border-color: var(--color-brand);
  /* A ring rather than an outline, so the field does not shift by a pixel when
     it takes focus. */
  box-shadow: 0 0 0 3px color-mix(in oklch, var(--color-brand) 18%, transparent);
}

.vc-input:disabled,
.vc-select:disabled,
.vc-textarea:disabled {
  color: var(--color-ink-subtle);
  background: var(--color-surface-sunken);
  cursor: not-allowed;
}

.vc-input[aria-invalid='true'],
.vc-textarea[aria-invalid='true'] {
  border-color: var(--color-danger);
}

.vc-input[aria-invalid='true']:focus-visible,
.vc-textarea[aria-invalid='true']:focus-visible {
  box-shadow: 0 0 0 3px color-mix(in oklch, var(--color-danger) 18%, transparent);
}

.vc-select {
  padding-inline-end: 2.25rem;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20' fill='none' stroke='%236b7280' stroke-width='1.75'%3E%3Cpath d='m5 7.5 5 5 5-5' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 0.6rem center;
  background-size: 1.1rem;
  cursor: pointer;
}

.vc-field__hint {
  font-size: var(--text-small);
  color: var(--color-ink-muted);
}

/* Numbers in a fixed pitch, so a column of CPFs lines up digit under digit. */
.vc-input--mono {
  font-variant-numeric: tabular-nums;
  letter-spacing: 0.01em;
}

/* A field and its action on one line, collapsing to two on a narrow screen.
   The pairing used to be built ad hoc in each module, which is why the search
   box and its button touched. */
.vc-input-group {
  display: flex;
  gap: var(--space-sm);
  align-items: flex-start;
  flex-wrap: wrap;
}

.vc-input-group > .vc-input,
.vc-input-group > .vc-field {
  flex: 1 1 14rem;
  min-width: 0;
}

/* --- Application shell with a side rail -----------------------------------
   The modules used to sit in a top bar. Six of them plus the session pushed
   that row past the width of a phone, and a horizontal list gives no room for
   the section a module belongs to. A rail holds them vertically, with space
   for grouping, and leaves the top bar to say where you are and who you are.
   -------------------------------------------------------------------------- */

.vc-app {
  min-height: 100dvh;
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  background: var(--color-paper);
}

.vc-rail {
  display: none;
  flex-direction: column;
  gap: var(--space-lg);
  padding: var(--space-lg) var(--space-md);
  background: var(--color-surface);
  border-inline-end: 1px solid var(--color-line);
}

.vc-rail__brand {
  display: flex;
  align-items: center;
  gap: var(--space-sm);
  padding-inline: var(--space-2xs);
  color: inherit;
  text-decoration: none;
}

.vc-rail__mark {
  display: grid;
  place-items: center;
  flex-shrink: 0;
  width: 2.25rem;
  height: 2.25rem;
  font-size: 0.7rem;
  font-weight: 700;
  letter-spacing: 0.04em;
  color: var(--color-on-brand);
  background: var(--color-brand);
  border-radius: var(--radius-sm);
}

.vc-rail__product {
  display: block;
  font-size: var(--text-small);
  font-weight: 650;
  letter-spacing: -0.01em;
  color: var(--color-ink);
}

.vc-rail__org {
  display: block;
  font-size: var(--text-caption);
  color: var(--color-ink-subtle);
}

.vc-rail__group {
  display: grid;
  gap: 0.15rem;
}

.vc-rail__group-title {
  padding: 0 var(--space-sm) var(--space-2xs);
  font-size: var(--text-caption);
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--color-ink-subtle);
}

.vc-rail__link {
  display: flex;
  align-items: center;
  gap: var(--space-sm);
  padding: var(--space-xs) var(--space-sm);
  font-size: var(--text-small);
  font-weight: 500;
  color: var(--color-ink-muted);
  text-decoration: none;
  border-radius: var(--radius-sm);
  transition:
    color var(--duration-fast),
    background var(--duration-fast);
}

.vc-rail__link:hover {
  color: var(--color-ink);
  background: var(--color-surface-sunken);
}

.vc-rail__link:focus-visible {
  outline: 2px solid var(--color-brand);
  outline-offset: -2px;
}

.vc-rail__link.active {
  color: var(--color-brand-strong);
  background: var(--color-brand-soft);
  font-weight: 600;
}

.vc-rail__icon {
  flex-shrink: 0;
  width: 1.15rem;
  height: 1.15rem;
}

.vc-rail__icon svg {
  width: 100%;
  height: 100%;
  display: block;
}

.vc-rail__foot {
  margin-top: auto;
  padding-top: var(--space-md);
  border-top: 1px solid var(--color-line);
  font-size: var(--text-caption);
  color: var(--color-ink-subtle);
}

/* --- Top bar: where you are, and who you are ------------------------------ */

.vc-topbar {
  position: sticky;
  top: 0;
  z-index: 20;
  display: flex;
  align-items: center;
  gap: var(--space-md);
  min-height: 3.5rem;
  padding-inline: var(--space-lg);
  background: color-mix(in oklch, var(--color-paper) 88%, transparent);
  backdrop-filter: blur(12px);
  border-bottom: 1px solid var(--color-line);
}

.vc-topbar__title {
  min-width: 0;
  font-size: var(--text-small);
  font-weight: 600;
  color: var(--color-ink);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.vc-topbar__spacer {
  flex: 1;
}

/* Opens the rail as a drawer on a narrow screen. Hidden once the rail is
   permanently on screen, so there is never a control for something already
   visible. */
.vc-topbar__menu {
  display: grid;
  place-items: center;
  width: 2.25rem;
  height: 2.25rem;
  color: var(--color-ink-muted);
  background: transparent;
  border: 1px solid var(--color-line);
  border-radius: var(--radius-sm);
  cursor: pointer;
}

.vc-topbar__menu:hover {
  color: var(--color-ink);
  background: var(--color-surface-sunken);
}

.vc-topbar__menu:focus-visible {
  outline: 2px solid var(--color-brand);
  outline-offset: 2px;
}

.vc-main {
  min-width: 0;
  padding: var(--space-xl) var(--space-lg) var(--space-2xl);
}

/* The rail as a drawer, below the breakpoint. */
.vc-rail--open {
  display: flex;
  position: fixed;
  inset: 0 auto 0 0;
  z-index: 60;
  width: min(17rem, 84vw);
  box-shadow: var(--shadow-overlay);
  overflow-y: auto;
}

.vc-rail__scrim {
  position: fixed;
  inset: 0;
  z-index: 55;
  background: oklch(21% 0.02 250 / 0.4);
}

@media (min-width: 64rem) {
  .vc-app {
    grid-template-columns: 16rem minmax(0, 1fr);
  }

  .vc-rail {
    display: flex;
    position: sticky;
    top: 0;
    height: 100dvh;
    overflow-y: auto;
  }

  .vc-topbar__menu,
  .vc-rail__scrim {
    display: none;
  }

  .vc-main {
    padding-inline: var(--space-xl);
  }
}

/* --- Page header inside the application ----------------------------------- */

.vc-page-head {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: var(--space-lg);
  flex-wrap: wrap;
  margin-bottom: var(--space-lg);
}

.vc-page-head h1 {
  margin: 0;
  /* Title, not display. A module screen is a working surface, and a heading
     sized for a landing page pushes the actual work below the fold. */
  font-size: var(--text-title);
  font-weight: 650;
  letter-spacing: -0.02em;
}

.vc-page-head p {
  margin: var(--space-2xs) 0 0;
  max-width: 60ch;
  font-size: var(--text-small);
  color: var(--color-ink-muted);
}

/* --- Tabs ------------------------------------------------------------------
   The modules drew these as rows of buttons, which reads as four actions
   rather than one choice among four. */

.vc-tabs {
  display: flex;
  gap: var(--space-2xs);
  margin-bottom: var(--space-lg);
  padding-bottom: 1px;
  overflow-x: auto;
  scrollbar-width: none;
  border-bottom: 1px solid var(--color-line);
}

.vc-tabs::-webkit-scrollbar {
  display: none;
}

.vc-tab {
  flex-shrink: 0;
  padding: var(--space-xs) var(--space-sm);
  margin-bottom: -1px;
  font: inherit;
  font-size: var(--text-small);
  font-weight: 500;
  color: var(--color-ink-muted);
  background: transparent;
  border: none;
  border-bottom: 2px solid transparent;
  cursor: pointer;
  transition: color var(--duration-fast), border-color var(--duration-fast);
}

.vc-tab:hover {
  color: var(--color-ink);
}

.vc-tab:focus-visible {
  outline: 2px solid var(--color-brand);
  outline-offset: -2px;
}

.vc-tab[aria-selected='true'] {
  color: var(--color-brand-strong);
  font-weight: 600;
  border-bottom-color: var(--color-brand);
}

/* --- Profile ---------------------------------------------------------------- */

.vc-profile {
  display: grid;
  gap: var(--space-md);
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 22rem), 1fr));
  align-items: start;
}

.vc-datalist {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: var(--space-xs) var(--space-md);
  margin: var(--space-md) 0 0;
  font-size: var(--text-small);
}

.vc-datalist dt {
  color: var(--color-ink-subtle);
}

.vc-datalist dd {
  margin: 0;
  color: var(--color-ink);
}

.vc-photo {
  display: flex;
  align-items: center;
  gap: var(--space-lg);
  flex-wrap: wrap;
}

.vc-photo__frame {
  display: grid;
  place-items: center;
  flex-shrink: 0;
  width: 7rem;
  height: 7rem;
  overflow: hidden;
  background: var(--color-surface-sunken);
  border: 1px solid var(--color-line);
  border-radius: var(--radius-lg);
}

.vc-photo__frame img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.vc-photo__empty {
  width: 2.75rem;
  height: 2.75rem;
  color: var(--color-ink-subtle);
}

.vc-photo__empty svg {
  width: 100%;
  height: 100%;
}

.vc-photo__actions {
  display: flex;
  gap: var(--space-sm);
  flex-wrap: wrap;
}

/* --- Conversation ----------------------------------------------------------
   The chat used to be one field and one answer card, replaced on every
   question. An operator comparing two answers had to remember the first, and
   the trail is the whole point of this module.
   -------------------------------------------------------------------------- */

.vc-chat {
  display: grid;
  gap: var(--space-md);
}

.vc-chat__thread {
  display: grid;
  gap: var(--space-md);
  max-height: 32rem;
  overflow-y: auto;
  padding-inline-end: var(--space-2xs);
}

.vc-chat__turn {
  display: grid;
  gap: var(--space-2xs);
  max-width: min(46rem, 100%);
}

.vc-chat__turn--asked {
  justify-self: end;
  text-align: end;
}

.vc-chat__who {
  font-size: var(--text-caption);
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--color-ink-subtle);
}

.vc-chat__bubble {
  padding: var(--space-sm) var(--space-md);
  font-size: var(--text-body);
  line-height: 1.55;
  border-radius: var(--radius-md);
  white-space: pre-wrap;
}

.vc-chat__turn--asked .vc-chat__bubble {
  color: var(--color-on-brand);
  background: var(--color-brand);
  border-end-end-radius: var(--radius-xs);
}

.vc-chat__turn--answered .vc-chat__bubble {
  color: var(--color-ink);
  background: var(--color-surface);
  border: 1px solid var(--color-line);
  border-end-start-radius: var(--radius-xs);
}

.vc-chat__meta {
  font-size: var(--text-caption);
  color: var(--color-ink-subtle);
}

.vc-chat__meta summary {
  cursor: pointer;
}

.vc-chat__composer {
  display: grid;
  gap: var(--space-sm);
  padding: var(--space-md);
  background: var(--color-surface);
  border: 1px solid var(--color-line);
  border-radius: var(--radius-md);
}

.vc-chat__composer-row {
  display: flex;
  gap: var(--space-sm);
  align-items: flex-end;
  flex-wrap: wrap;
}

.vc-chat__composer-row .vc-textarea {
  flex: 1 1 18rem;
  min-height: 3.25rem;
}

/* Suggestions, so an empty conversation is not an empty box with a cursor in
   it. The wording matches what the tools actually answer. */
.vc-chat__suggestions {
  display: flex;
  gap: var(--space-2xs);
  flex-wrap: wrap;
}

.vc-chip {
  padding: var(--space-2xs) var(--space-sm);
  font: inherit;
  font-size: var(--text-small);
  color: var(--color-ink-muted);
  background: var(--color-surface);
  border: 1px solid var(--color-line);
  border-radius: var(--radius-pill);
  cursor: pointer;
  transition: color var(--duration-fast), border-color var(--duration-fast);
}

.vc-chip:hover {
  color: var(--color-brand-strong);
  border-color: var(--color-brand-line);
}

.vc-chip:focus-visible {
  outline: 2px solid var(--color-brand);
  outline-offset: 2px;
}

.vc-empty {
  display: grid;
  gap: var(--space-xs);
  justify-items: center;
  padding: var(--space-2xl) var(--space-lg);
  text-align: center;
  color: var(--color-ink-muted);
  background: var(--color-surface-sunken);
  border: 1px dashed var(--color-line-strong);
  border-radius: var(--radius-md);
}

.vc-empty__title {
  font-size: var(--text-body);
  font-weight: 600;
  color: var(--color-ink);
}

.vc-empty p {
  margin: 0;
  max-width: 46ch;
  font-size: var(--text-small);
}

/* --- Avatar and the user menu ---------------------------------------------
   Initials until a picture exists, which is the state of everyone on the first
   day. A grey circle with nothing in it reads as a photograph that failed to
   load; two letters read as a person.
   -------------------------------------------------------------------------- */

.vc-avatar {
  display: grid;
  place-items: center;
  flex-shrink: 0;
  width: 2rem;
  height: 2rem;
  overflow: hidden;
  font-size: 0.72rem;
  font-weight: 650;
  letter-spacing: 0.02em;
  color: var(--color-brand-strong);
  background: var(--color-brand-soft);
  border: 1px solid var(--color-brand-line);
  border-radius: 50%;
}

.vc-avatar--lg {
  width: 4.5rem;
  height: 4.5rem;
  font-size: 1.35rem;
}

.vc-avatar img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.vc-usermenu {
  position: relative;
}

.vc-usermenu__trigger {
  display: flex;
  align-items: center;
  gap: var(--space-xs);
  padding: var(--space-2xs) var(--space-2xs) var(--space-2xs) var(--space-2xs);
  font: inherit;
  color: var(--color-ink);
  background: transparent;
  border: 1px solid transparent;
  border-radius: var(--radius-pill);
  cursor: pointer;
  transition: background var(--duration-fast), border-color var(--duration-fast);
}

.vc-usermenu__trigger:hover,
.vc-usermenu__trigger[aria-expanded='true'] {
  background: var(--color-surface);
  border-color: var(--color-line);
}

.vc-usermenu__trigger:focus-visible {
  outline: 2px solid var(--color-brand);
  outline-offset: 2px;
}

.vc-usermenu__name {
  display: none;
  max-width: 12rem;
  font-size: var(--text-small);
  font-weight: 550;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.vc-usermenu__caret {
  display: none;
  flex-shrink: 0;
  color: var(--color-ink-subtle);
}

.vc-usermenu__panel {
  position: absolute;
  inset-block-start: calc(100% + var(--space-2xs));
  inset-inline-end: 0;
  z-index: 40;
  min-width: 15rem;
  padding: var(--space-2xs);
  background: var(--color-surface);
  border: 1px solid var(--color-line);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-overlay);
  animation: vc-menu-in var(--duration-fast) var(--ease-out-expo);
}

.vc-usermenu__head {
  display: grid;
  gap: 0.1rem;
  padding: var(--space-sm) var(--space-sm) var(--space-xs);
  border-bottom: 1px solid var(--color-line);
  margin-bottom: var(--space-2xs);
}

.vc-usermenu__head strong {
  font-size: var(--text-small);
  font-weight: 600;
}

.vc-usermenu__head span {
  font-size: var(--text-caption);
  color: var(--color-ink-subtle);
}

.vc-usermenu__item {
  display: flex;
  align-items: center;
  gap: var(--space-sm);
  width: 100%;
  padding: var(--space-xs) var(--space-sm);
  font: inherit;
  font-size: var(--text-small);
  text-align: start;
  text-decoration: none;
  color: var(--color-ink);
  background: transparent;
  border: none;
  border-radius: var(--radius-sm);
  cursor: pointer;
}

.vc-usermenu__item:hover,
.vc-usermenu__item:focus-visible {
  background: var(--color-surface-sunken);
  outline: none;
}

.vc-usermenu__item svg {
  flex-shrink: 0;
  width: 1.05rem;
  height: 1.05rem;
  color: var(--color-ink-subtle);
}

.vc-usermenu__item--danger {
  color: var(--color-danger);
}

.vc-usermenu__item--danger svg {
  color: currentColor;
}

@keyframes vc-menu-in {
  from {
    opacity: 0;
    transform: translateY(-0.25rem);
  }
}

@media (min-width: 48rem) {
  .vc-usermenu__name,
  .vc-usermenu__caret {
    display: block;
  }
}

@media (prefers-reduced-motion: reduce) {
  .vc-usermenu__panel {
    animation: none;
  }
}

/* --- Rail, second level ------------------------------------------------------
   The sections of the module you are in. Indented under their module and set in
   a lighter weight, so the eye reads the module first and the sections as its
   contents rather than as five more modules.

   Same tokens as the first level, deliberately. Written once against a dark
   palette, these came out white on a white rail, which is invisible rather than
   subtle.
   -------------------------------------------------------------------------- */

.vc-rail__sections {
  display: grid;
  gap: 0.1rem;
  margin: 0.15rem 0 var(--space-xs);
  /* The hairline ties the group to the module above it, which the indent alone
     stops doing once the list is longer than the eye takes in at once. */
  margin-left: calc(var(--space-sm) + 0.575rem);
  padding-left: var(--space-sm);
  border-left: 1px solid var(--color-line-strong);
}

.vc-rail__sublink {
  padding: var(--space-2xs) var(--space-sm);
  font-size: var(--text-small);
  font-weight: 450;
  color: var(--color-ink-subtle);
  text-decoration: none;
  border-radius: var(--radius-sm);
  transition:
    color var(--duration-fast),
    background var(--duration-fast);
}

.vc-rail__sublink:hover {
  color: var(--color-ink);
  background: var(--color-surface-sunken);
}

.vc-rail__sublink:focus-visible {
  outline: 2px solid var(--color-brand);
  outline-offset: -2px;
}

.vc-rail__sublink.active {
  color: var(--color-brand-strong);
  font-weight: 600;
}

/* --- Card grid ---------------------------------------------------------------
   The one shape repeated across the modules: cards that keep a readable width
   and wrap instead of shrinking. Declared once here because it was being
   written inline in four screens, each with its own idea of the minimum.
   -------------------------------------------------------------------------- */

.vc-grid-cards {
  display: grid;
  gap: var(--space-md);
  grid-template-columns: repeat(auto-fill, minmax(min(100%, 22rem), 1fr));
  margin-top: var(--space-lg);
}

/* Hashes and receipt codes have no spaces, so without this they push the page
   sideways on a phone. */
.vc-break {
  overflow-wrap: anywhere;
}

/* --- Split screen: a list beside its detail ----------------------------------
   The shape every registration screen in the administration module wants: what
   exists on the left, what the selected one contains on the right. Below the
   breakpoint the list goes above the detail rather than beside it, because two
   narrow columns are two columns nobody can read.
   -------------------------------------------------------------------------- */

.vc-split {
  display: grid;
  gap: var(--space-lg);
  grid-template-columns: minmax(0, 18rem) minmax(0, 1fr);
  align-items: start;
}

@media (max-width: 64rem) {
  .vc-split {
    grid-template-columns: minmax(0, 1fr);
  }
}

.vc-list-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-sm);
  margin-bottom: var(--space-sm);
  font-size: var(--text-caption);
  color: var(--color-ink-subtle);
}

.vc-list {
  display: grid;
  gap: 0.25rem;
  margin: 0;
  padding: 0;
  list-style: none;
}

.vc-list__item {
  display: grid;
  gap: 0.15rem;
  width: 100%;
  padding: var(--space-sm);
  text-align: left;
  background: transparent;
  border: 1px solid transparent;
  border-radius: var(--radius-md);
  cursor: pointer;
  transition:
    background var(--duration-fast),
    border-color var(--duration-fast);
}

.vc-list__item:hover {
  background: var(--color-surface-sunken);
}

.vc-list__item:focus-visible {
  outline: 2px solid var(--color-brand);
  outline-offset: -2px;
}

.vc-list__item--active {
  background: var(--color-surface);
  border-color: var(--color-line-strong);
  box-shadow: var(--shadow-sm);
}

.vc-list__title {
  display: flex;
  align-items: center;
  gap: var(--space-2xs);
  font-size: var(--text-small);
  font-weight: 600;
  color: var(--color-ink);
}

.vc-list__meta {
  font-size: var(--text-caption);
  color: var(--color-ink-subtle);
}

/* --- The permission matrix --------------------------------------------------
   Grouped by area on purpose. Forty checkboxes in one column is a column nobody
   reads before ticking, and what gets ticked here decides what somebody can do
   on election day.
   -------------------------------------------------------------------------- */

.vc-permissions {
  display: grid;
  gap: var(--space-lg);
  grid-template-columns: repeat(auto-fill, minmax(min(100%, 17rem), 1fr));
  margin-top: var(--space-lg);
}

.vc-permission-group {
  margin: 0;
  padding: 0;
  border: 0;
}

.vc-permission-group legend {
  padding: 0 0 var(--space-2xs);
  font-size: var(--text-caption);
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--color-ink-subtle);
}

.vc-check {
  display: flex;
  gap: var(--space-xs);
  align-items: flex-start;
  padding: var(--space-2xs) 0;
  font-size: var(--text-small);
  color: var(--color-ink);
  cursor: pointer;
}

.vc-check input {
  margin-top: 0.15rem;
  accent-color: var(--color-brand);
  width: 1rem;
  height: 1rem;
  flex-shrink: 0;
}

/* The code beside the label, quietly. It is what the routes cite, so somebody
   reading a refusal message can find the box that grants it. */
.vc-check__code {
  display: block;
  font-size: var(--text-caption);
  color: var(--color-ink-subtle);
}

.vc-card-head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--space-md);
  flex-wrap: wrap;
}

.vc-card-foot {
  display: flex;
  gap: var(--space-sm);
  flex-wrap: wrap;
  margin-top: var(--space-lg);
  padding-top: var(--space-md);
  border-top: 1px solid var(--color-line-strong);
}

.vc-inline-form {
  margin-top: var(--space-lg);
  grid-column: 1 / -1;
}

/* --- Timeline ----------------------------------------------------------------
   A process, in the order it happened. The rule down the left is what makes it
   read as one sequence rather than as a stack of unrelated rows, which matters
   because the commission reads this to reconstruct a registration.
   -------------------------------------------------------------------------- */

.vc-timeline {
  display: grid;
  gap: var(--space-md);
  margin: var(--space-lg) 0 0;
  padding: 0 0 0 var(--space-md);
  list-style: none;
  border-left: 2px solid var(--color-line-strong);
}

.vc-timeline__item {
  display: grid;
  gap: 0.1rem;
  position: relative;
}

.vc-timeline__item::before {
  content: '';
  position: absolute;
  left: calc(var(--space-md) * -1 - 5px);
  top: 0.45rem;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--color-brand);
}

.vc-timeline__when {
  font-size: var(--text-caption);
  color: var(--color-ink-subtle);
}

.vc-timeline__title {
  font-size: var(--text-small);
  font-weight: 600;
  color: var(--color-ink);
}

.vc-timeline__detail {
  font-size: var(--text-small);
  color: var(--color-ink-muted);
}

/* --- Metric grid -------------------------------------------------------------
   Narrower than the card grid, because a metric is a short label and a figure.
   At the card width four of them wrap after the third, and a summary of four
   numbers that reads as three plus one is a summary somebody misreads.
   -------------------------------------------------------------------------- */

.vc-grid-metrics {
  display: grid;
  gap: var(--space-md);
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 11rem), 1fr));
  margin-top: var(--space-lg);
}

/* --- Fields stacked in a dialog ----------------------------------------------
   A form is a sequence of fields, and `.vc-field` only spaces the label from
   its own control. Without this the hint of one field sits against the label of
   the next, and the eye stops being able to tell which hint belongs to which
   control, which on a registration form is where mistakes come from.
   -------------------------------------------------------------------------- */

.vc-modal__body .vc-field + .vc-field,
.vc-modal__body .vc-field + .vc-card-foot,
.vc-modal__body .vc-field + .vc-field-error {
  margin-top: var(--space-md);
}


/* --- Two fields to a line ----------------------------------------------------
   A registration form reads as pairs: code and state, city and postal code,
   start and end of a term. One field per line turns eight fields into a
   dialog that scrolls, and a form that scrolls is a form where the button is
   never on screen at the same time as the field somebody just filled in.

   A field marked `--full` keeps the whole line, for the ones where the value
   is long: a name, an address, a reason.
   -------------------------------------------------------------------------- */

.vc-form-grid {
  display: grid;
  gap: var(--space-md);
  grid-template-columns: repeat(2, minmax(0, 1fr));
  align-items: start;
}

.vc-form-grid > .vc-field--full,
.vc-form-grid > .vc-field-error,
.vc-form-grid > .vc-card-foot {
  grid-column: 1 / -1;
}

/* Below the breakpoint the pairs stack. Two columns on a phone give two fields
   nobody can read rather than one anybody can. */
@media (max-width: 40rem) {
  .vc-form-grid {
    grid-template-columns: minmax(0, 1fr);
  }
}

/* The stacking rule for fields in a dialog does not apply inside the grid: the
   grid already spaces them, and both together double the gap. */
.vc-modal__body .vc-form-grid .vc-field + .vc-field {
  margin-top: 0;
}

/* --- Autocomplete ------------------------------------------------------------
   A select you can type into. The list floats over the form rather than pushing
   it down: a list that reflows the dialog moves the field the person is reading
   while they read it.
   -------------------------------------------------------------------------- */

.vc-autocomplete {
  position: relative;
}

.vc-autocomplete .vc-input {
  /* Room for the caret, so a long value never runs under it. */
  padding-right: 2.25rem;
}

.vc-autocomplete__caret {
  position: absolute;
  right: 0.75rem;
  top: 50%;
  transform: translateY(-50%);
  display: flex;
  color: var(--color-ink-subtle);
  pointer-events: none;
}

.vc-autocomplete__list {
  position: absolute;
  z-index: 30;
  top: calc(100% + 0.25rem);
  left: 0;
  right: 0;
  max-height: 16rem;
  overflow-y: auto;
  margin: 0;
  padding: 0.25rem;
  list-style: none;
  background: var(--color-surface);
  border: 1px solid var(--color-line-strong);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-md, 0 12px 32px rgba(15, 23, 42, 0.12));
}

.vc-autocomplete__option {
  display: grid;
  gap: 0.05rem;
  padding: var(--space-2xs) var(--space-xs);
  border-radius: var(--radius-sm);
  font-size: var(--text-small);
  color: var(--color-ink);
  cursor: pointer;
}

/* One highlight, driven by the keyboard and followed by the mouse. Two
   different highlights, one for hover and one for the arrows, is how somebody
   presses Enter and gets the row they were not looking at. */
.vc-autocomplete__option--active {
  background: var(--color-brand-soft);
  color: var(--color-brand-strong);
}

.vc-autocomplete__option[aria-selected='true'] {
  font-weight: 600;
}

.vc-autocomplete__hint {
  font-size: var(--text-caption);
  color: var(--color-ink-subtle);
}

.vc-autocomplete__empty,
.vc-autocomplete__more {
  padding: var(--space-xs);
  font-size: var(--text-caption);
  color: var(--color-ink-subtle);
}

/* --- Filter bar --------------------------------------------------------------
   The shape every listing screen opens with: a few fields that narrow the grid
   below, and the actions that do not belong to any row. Fields wrap rather than
   shrink, because a filter squeezed to four characters is a filter nobody uses.
   -------------------------------------------------------------------------- */

.vc-filters {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  gap: var(--space-md);
  padding: var(--space-md);
  margin-bottom: var(--space-lg);
  background: var(--color-surface-sunken);
  border: 1px solid var(--color-line-strong);
  border-radius: var(--radius-md);
}

.vc-filters .vc-field {
  flex: 1 1 12rem;
  min-width: 0;
  margin-bottom: 0;
}

/* Pushed to the end of the row: the actions are not one more filter, and lined
   up with them they read as one. */
.vc-filters__actions {
  display: flex;
  gap: var(--space-sm);
  margin-left: auto;
}

/* --- Row actions -------------------------------------------------------------
   Kept on one line and never wrapped into a second: a row whose actions wrap is
   a row twice as tall as the ones around it, and the eye reads the difference as
   meaning something.
   -------------------------------------------------------------------------- */

.vc-row-actions {
  display: flex;
  gap: var(--space-2xs);
  white-space: nowrap;
}

/* --- Pending list ------------------------------------------------------------
   What is still missing before something can be submitted. Beside the disabled
   button rather than behind it: hidden, somebody hunts for the button; listed,
   they read the reasons.
   -------------------------------------------------------------------------- */

.vc-pending {
  display: grid;
  gap: var(--space-2xs);
  margin: var(--space-sm) 0 0;
  padding-left: var(--space-md);
  font-size: var(--text-small);
  color: var(--color-ink-muted);
}

/* --- Accordion ---------------------------------------------------------------
   A group that opens, built on <details>. The count lives in the summary so a
   closed group still says whether it is worth opening: a queue where every
   group has to be opened to find out it is empty is a queue nobody reads twice.
   -------------------------------------------------------------------------- */

.vc-accordion {
  margin-bottom: var(--space-md);
  background: var(--color-surface);
  border: 1px solid var(--color-line-strong);
  border-radius: var(--radius-md);
  overflow: hidden;
}

.vc-accordion__summary {
  display: flex;
  align-items: center;
  gap: var(--space-sm);
  padding: var(--space-md);
  cursor: pointer;
  list-style: none;
  font-weight: 600;
  color: var(--color-ink);
}

/* The default triangle is replaced by one that turns, and the marker has to be
   removed in both spellings for Safari and the rest to agree. */
.vc-accordion__summary::-webkit-details-marker {
  display: none;
}

.vc-accordion__summary::before {
  content: '';
  width: 0.5rem;
  height: 0.5rem;
  border-right: 2px solid var(--color-ink-subtle);
  border-bottom: 2px solid var(--color-ink-subtle);
  transform: rotate(-45deg);
  transition: transform var(--duration-fast);
}

.vc-accordion[open] > .vc-accordion__summary::before {
  transform: rotate(45deg);
}

.vc-accordion__summary:focus-visible {
  outline: 2px solid var(--color-brand);
  outline-offset: -2px;
}

.vc-accordion__count {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 1.75rem;
  height: 1.5rem;
  padding: 0 0.4rem;
  border-radius: 999px;
  background: var(--color-surface-sunken);
  font-size: var(--text-caption);
  font-variant-numeric: tabular-nums;
}

.vc-accordion--warning .vc-accordion__count {
  background: var(--color-warning-soft, #fef3c7);
  color: var(--color-warning-strong, #92400e);
}

.vc-accordion--danger .vc-accordion__count {
  background: var(--color-danger-soft, #fee2e2);
  color: var(--color-danger-strong, #991b1b);
}

.vc-accordion--success .vc-accordion__count {
  background: var(--color-success-soft, #dcfce7);
  color: var(--color-success-strong, #166534);
}

.vc-accordion__hint {
  font-size: var(--text-caption);
  font-weight: 400;
  color: var(--color-ink-subtle);
}

.vc-accordion__body {
  padding: 0 var(--space-md) var(--space-md);
}

/* --- Dossiê de análise -------------------------------------------------------
   O caso inteiro dentro de uma modal: resumo, conferência, composição,
   documentos, diligências, impugnações e linha do tempo, com a decisão fixada
   no rodapé. A decisão fica presa embaixo porque quem rola o dossiê até o fim
   para conferir um documento não deveria ter de rolar de volta para decidir, e
   porque o painel visível o tempo todo lembra que a leitura termina num ato.
   -------------------------------------------------------------------------- */

.vc-case {
  display: grid;
  gap: var(--space-lg);
}

.vc-case__section {
  display: grid;
  gap: var(--space-sm);
  padding-bottom: var(--space-lg);
  border-bottom: 1px solid var(--color-line);
}

.vc-case__section:last-of-type {
  border-bottom: 0;
  padding-bottom: 0;
}

/* Amarelo em vez de vermelho: pendência de conferência não impede a comissão de
   decidir, ela informa o que pesar. Vermelho aqui leria como impedimento. */
.vc-case__section--warning {
  padding: var(--space-md);
  background: var(--color-warning-soft);
  border: 1px solid var(--color-warning);
  border-radius: var(--radius-md);
}

.vc-case__title {
  margin: 0;
  font-size: var(--text-small);
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--color-ink-subtle);
}

.vc-case__facts {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(9rem, 1fr));
  gap: var(--space-md);
  margin: 0;
}

.vc-case__facts dt {
  font-size: var(--text-caption);
  color: var(--color-ink-subtle);
}

.vc-case__facts dd {
  margin: 0.15rem 0 0;
  font-size: var(--text-small);
  color: var(--color-ink);
}

.vc-case__item {
  display: grid;
  gap: 0.2rem;
  padding: var(--space-sm) 0;
  border-bottom: 1px solid var(--color-line);
}

.vc-case__item:last-child {
  border-bottom: 0;
}

/* O que a chapa escreveu, marcado como fala dela e não como texto da tela. */
.vc-case__quote {
  margin: 0.25rem 0 0;
  padding-left: var(--space-sm);
  border-left: 2px solid var(--color-line-strong);
  font-size: var(--text-small);
  color: var(--color-ink-muted);
}

.vc-case__problems {
  margin: 0;
  padding-left: var(--space-md);
  display: grid;
  gap: 0.2rem;
  font-size: var(--text-small);
  color: var(--color-ink);
}

.vc-case__decision {
  position: sticky;
  bottom: calc(var(--space-lg) * -1);
  display: grid;
  gap: var(--space-sm);
  margin: 0 calc(var(--space-lg) * -1) calc(var(--space-lg) * -1);
  padding: var(--space-md) var(--space-lg);
  background: var(--color-surface);
  border-top: 1px solid var(--color-line-strong);
  box-shadow: 0 -8px 20px -18px rgb(0 0 0 / 40%);
}

/* --- Escolha de ato ----------------------------------------------------------
   Radios de verdade, e não botões que fingem ser escolha: um grupo de rádio já
   chega navegável pelas setas, é anunciado como grupo e diz qual item está
   marcado. Reconstruir isso com botões custa o mesmo e perde tudo.
   -------------------------------------------------------------------------- */

.vc-choices {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(13rem, 1fr));
  gap: var(--space-xs);
  margin: 0;
  padding: 0;
  border: 0;
}

.vc-choices legend {
  padding: 0;
  margin-bottom: var(--space-2xs);
}

.vc-choice {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: 0 var(--space-xs);
  align-items: start;
  padding: var(--space-xs) var(--space-sm);
  border: 1px solid var(--color-line-strong);
  border-radius: var(--radius-md);
  cursor: pointer;
  transition:
    border-color var(--duration-fast),
    background var(--duration-fast);
}

.vc-choice:hover {
  background: var(--color-surface-sunken);
}

.vc-choice:has(input:checked) {
  border-color: var(--color-brand);
  background: var(--color-surface-sunken);
}

.vc-choice:has(input:focus-visible) {
  outline: 2px solid var(--color-brand);
  outline-offset: 2px;
}

.vc-choice input {
  margin-top: 0.2rem;
}

.vc-choice__label {
  font-size: var(--text-small);
  font-weight: 600;
  color: var(--color-ink);
}

.vc-choice__hint {
  grid-column: 2;
  font-size: var(--text-caption);
  color: var(--color-ink-subtle);
}

/* --- Pareamento com o celular ------------------------------------------------
   O código de um lado, o estado da espera do outro. Em tela estreita vira uma
   coluna só, com o código em cima: o celular que abre esta mesma tela por
   engano precisa ler o código antes de qualquer outra coisa.
   -------------------------------------------------------------------------- */

.vc-handoff {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  gap: var(--space-lg);
  align-items: center;
  margin-top: var(--space-lg);
}

@media (max-width: 40rem) {
  .vc-handoff {
    grid-template-columns: minmax(0, 1fr);
  }
}

.vc-handoff__code {
  display: grid;
  place-items: center;
  width: 15rem;
  height: 15rem;
  padding: var(--space-sm);
  /* Fundo claro fixo, e não a superfície do tema: um código desenhado em
     escuro sobre escuro é um código que a câmera não lê. */
  background: #fff;
  border: 1px solid var(--color-line);
  border-radius: var(--radius-lg);
}

.vc-handoff__placeholder {
  font-size: var(--text-caption);
  color: var(--color-ink-subtle);
}

.vc-handoff__side {
  display: grid;
  gap: var(--space-md);
  align-content: start;
}

/* Grande porque existe para ser comparado de longe, entre duas telas, e
   espaçado porque comparar caractere a caractere é o que a pessoa vai fazer. */
.vc-handoff__pairing {
  margin: var(--space-2xs) 0 var(--space-xs);
  font-size: var(--text-lead);
  font-weight: 700;
  letter-spacing: 0.35em;
  color: var(--color-ink);
}

.vc-link {
  justify-self: start;
  padding: 0;
  font-size: var(--text-small);
  color: var(--color-brand);
  text-decoration: underline;
  background: none;
  border: 0;
  cursor: pointer;
}

.vc-link:hover {
  color: var(--color-brand-strong);
}

/* --- Impressão ------------------------------------------------------------
   A folha existe só no papel: fora da impressão ela não ocupa espaço, e na
   impressão é a única coisa que sobra. Esconder os irmãos é o que impede a
   barra lateral, o cabeçalho e o diálogo aberto de saírem junto do
   comprovante.

   As cores vêm cravadas em vez de virem dos tokens porque a impressora não
   pinta fundo por padrão, e um texto definido por contraste com um fundo que
   não sai imprime cinza-claro sobre branco. */

.vc-print-sheet {
  display: none;
}

@media print {
  @page {
    size: A4 portrait;
    margin: 18mm 16mm;
  }

  body > *:not(.vc-print-sheet) {
    display: none !important;
  }

  .vc-print-sheet {
    display: block;
    max-width: none;
    margin: 0;
    font-family: var(--font-sans);
    font-size: 10.5pt;
    line-height: 1.45;
    color: #000;
    background: #fff;
  }

  .vc-print-sheet__head {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 1rem;
    padding-bottom: 6pt;
    border-bottom: 1.5pt solid #000;
  }

  .vc-print-sheet__org {
    font-size: 11pt;
    font-weight: 700;
    letter-spacing: 0.04em;
    text-transform: uppercase;
  }

  .vc-print-sheet__stamp {
    font-family: var(--font-mono);
    font-size: 9pt;
  }

  .vc-print-sheet__title {
    margin: 14pt 0 2pt;
    font-size: 16pt;
    font-weight: 700;
    letter-spacing: -0.01em;
  }

  .vc-print-sheet__subtitle {
    margin: 0 0 14pt;
    font-size: 10.5pt;
    color: #333;
  }

  .vc-print-sheet dl {
    display: grid;
    grid-template-columns: 42mm 1fr;
    gap: 4pt 8pt;
    margin: 0 0 14pt;
  }

  .vc-print-sheet dt {
    font-size: 9pt;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: #444;
  }

  .vc-print-sheet dd {
    margin: 0;
    font-weight: 600;
  }

  .vc-print-sheet__mono {
    font-family: var(--font-mono);
    font-weight: 400;
    word-break: break-all;
  }

  .vc-print-sheet h2 {
    margin: 0 0 6pt;
    font-size: 11pt;
    text-transform: uppercase;
    letter-spacing: 0.06em;
  }

  .vc-print-sheet table {
    width: 100%;
    border-collapse: collapse;
    margin-bottom: 14pt;
  }

  .vc-print-sheet th,
  .vc-print-sheet td {
    padding: 4pt 6pt 4pt 0;
    text-align: left;
    vertical-align: top;
    border-bottom: 0.5pt solid #999;
  }

  .vc-print-sheet th {
    font-size: 9pt;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    border-bottom-width: 1pt;
    border-bottom-color: #000;
  }

  /* Uma linha de candidato não se parte entre duas páginas: nome numa folha e
     cargo na outra é o que faz alguém conferir a composição errada. */
  .vc-print-sheet tr {
    break-inside: avoid;
  }

  .vc-print-sheet__note {
    padding-top: 8pt;
    font-size: 9pt;
    line-height: 1.4;
    color: #333;
    border-top: 0.5pt solid #999;
  }
}

/* Um rótulo que age como botão.

   O campo de arquivo nativo não se deixa estilizar, e disparar o clique dele
   por código é o caminho que o teclado e o leitor de tela não seguem. O rótulo
   resolve os dois: o clique chega ao campo, e o campo continua sendo o que
   recebe foco. */
label.vc-button {
  display: inline-flex;
  cursor: pointer;
}

label.vc-button[aria-busy='true'] {
  pointer-events: none;
  opacity: 0.6;
}

/* O campo escondido continua focalizável, e o foco nele precisa aparecer em
   algum lugar: sem isto, quem navega por teclado chega no anexo e não vê onde
   está. */
input[type='file'].vc-sr-only:focus-visible + * ,
input[type='file'].vc-sr-only:focus-visible ~ label.vc-button,
label.vc-button:has(+ input[type='file']:focus-visible) {
  outline: 2px solid var(--color-brand);
  outline-offset: 2px;
}

/* --- Atendimento e comunicação (itens P49 a P52) ---------------------------- */

/*
 * Utilitários de arranjo que faltavam. Declarados aqui, e não repetidos em
 * `style` inline em cada tela, porque três seções novas os usam e a terceira
 * cópia é onde o espaçamento começa a divergir das outras duas.
 */
.vc-stack {
  display: grid;
  gap: var(--space-md);
}

.vc-row {
  display: flex;
  align-items: center;
  gap: var(--space-xs);
  flex-wrap: wrap;
}

.vc-row--between {
  justify-content: space-between;
}

.vc-row--end {
  justify-content: flex-end;
}

/*
 * A tabela rola dentro do próprio contêiner, e nunca a página.
 *
 * Oito colunas de atendimento não cabem em 320px, e sem isto a página inteira
 * ganha rolagem lateral, que é o que o item P33 proíbe. O `min-width: 0` é o
 * que faz a regra valer dentro de um item de flex ou de grade: sem ele o
 * contêiner se recusa a ficar menor que o conteúdo e o overflow nunca ocorre.
 */
.vc-table-scroll {
  overflow-x: auto;
  min-width: 0;
  border: 1px solid var(--color-line);
  border-radius: var(--radius-md);
}

.vc-table-scroll .vc-table {
  margin: 0;
}

.vc-definition {
  display: grid;
  grid-template-columns: minmax(6rem, max-content) 1fr;
  gap: var(--space-2xs) var(--space-sm);
  margin: 0 0 var(--space-md);
}

.vc-definition dt {
  font-size: var(--text-small);
  font-weight: 600;
  color: var(--color-ink-muted);
}

.vc-definition dd {
  margin: 0;
}

/*
 * A conversa do atendimento.
 *
 * Bloco próprio, e não os filhos de `.vc-chat`: aquele é a conversa com o
 * agente de inteligência, que tem pergunta, resposta e a explicação de como a
 * resposta foi produzida. Aqui são duas pessoas trocando mensagens, e forçar
 * uma na estrutura da outra faria as duas mudarem juntas sem motivo.
 */
.vc-conversa {
  display: grid;
  gap: var(--space-2xs);
  max-height: 22rem;
  overflow-y: auto;
  padding: var(--space-xs);
  margin-bottom: var(--space-sm);
  background: var(--color-surface-sunken);
  border-radius: var(--radius-md);
}

.vc-conversa__msg {
  justify-self: start;
  max-width: min(100%, 32rem);
  padding: var(--space-2xs) var(--space-xs);
  background: var(--color-surface);
  border: 1px solid var(--color-line);
  border-radius: var(--radius-md);
}

.vc-conversa__msg--mine {
  justify-self: end;
  background: var(--color-brand-soft, var(--color-surface));
}

.vc-conversa__msg p {
  margin: 0;
}

.vc-conversa__author {
  display: block;
  font-size: var(--text-caption);
  font-weight: 600;
  color: var(--color-ink-subtle);
}

/*
 * A página pública de ajuda.
 *
 * Ela vive fora do shell autenticado, então não herda a largura nem o respiro
 * do `.vc-main`. Sem isto o FAQ encosta nas bordas da janela.
 */
.vc-public {
  max-width: 60rem;
  margin: 0 auto;
  padding: var(--space-lg) var(--space-md) var(--space-2xl);
  display: grid;
  gap: var(--space-md);
}

/* O caminho para a ajuda, na coluna institucional da entrada. */
.vc-auth__help {
  justify-self: start;
  font-size: var(--text-small);
  font-weight: 600;
  color: var(--color-on-brand, #fff);
  text-decoration: underline;
  text-underline-offset: 3px;
}

.vc-auth__help:focus-visible {
  outline: 2px solid currentColor;
  outline-offset: 3px;
}

/*
 * Grupo dentro da trilha do módulo.
 *
 * O título aparece uma vez, quando o grupo começa, e as seções seguem com o
 * mesmo recuo das demais: o grupo separa assuntos, e não cria um segundo nível
 * de navegação para percorrer.
 */
.vc-rail__group {
  display: contents;
}

.vc-rail__group-title {
  display: block;
  margin: var(--space-xs) 0 var(--space-3xs);
  padding-inline-start: var(--space-sm);
  font-size: var(--text-caption);
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--color-ink-subtle);
}

/* Os caminhos públicos na coluna institucional da entrada. */
.vc-auth__links {
  display: grid;
  gap: var(--space-2xs);
  justify-items: start;
}
/**
 * Gráficos do painel por prompt.
 *
 * O traçado é SVG próprio, sem biblioteca. A decisão não foi de tamanho de
 * pacote: em Module Federation uma biblioteca de gráfico vira dependência
 * compartilhada entre remotos, e duas versões carregadas ao mesmo tempo quebram
 * de um jeito que só aparece em produção.
 */

.vc-grafico {
  margin: 0;
}

.vc-grafico__tela {
  width: 100%;
}

.vc-grafico__svg {
  display: block;
  width: 100%;
  height: auto;
  /* Sem isto, um gráfico dentro de grade estreita força a página a rolar na
     horizontal, que a regra de responsividade do projeto proíbe. */
  max-width: 100%;
  overflow: visible;
}

.vc-grafico__malha {
  stroke: var(--chart-grid);
  stroke-width: 1;
}

.vc-grafico__eixo,
.vc-grafico__rotulo,
.vc-grafico__legenda,
.vc-grafico__legenda-valor {
  font-family: var(--font-sans);
  fill: var(--color-ink-muted);
  font-size: 12px;
}

.vc-grafico__eixo,
.vc-grafico__legenda-valor {
  /* Número em coluna precisa alinhar dígito com dígito. */
  font-variant-numeric: tabular-nums;
}

.vc-grafico__legenda {
  fill: var(--color-ink);
}

.vc-grafico__centro {
  font-family: var(--font-sans);
  font-size: 24px;
  font-weight: 600;
  fill: var(--color-ink);
  font-variant-numeric: tabular-nums;
}

.vc-grafico__vazio {
  margin: 0;
  padding: var(--space-lg, 1.5rem);
  text-align: center;
  color: var(--color-ink-subtle);
  background: var(--color-surface-sunken);
  border-radius: var(--radius-md, 0.5rem);
  font-size: 0.875rem;
}

@media print {
  /* Um gráfico cortado na dobra da página é pior do que um gráfico na página
     seguinte. */
  .vc-grafico {
    break-inside: avoid;
  }
}
/**
 * A urna, como objeto físico.
 *
 * O resto da plataforma é papel institucional: fundo claro, tinta escura,
 * hierarquia por escala. A urna não é papel, é um aparelho, e por isso tem
 * paleta própria em vez de herdar a do sistema. Um eleitor brasileiro reconhece
 * essa caixa antes de ler uma palavra dela, e esse reconhecimento é a própria
 * instrução de uso.
 *
 * As cores das teclas de ação não são decoração: branco, laranja e verde são as
 * mesmas do aparelho que a pessoa já usou, e trocá-las por tons da marca
 * custaria justamente o que esta tela quer comprar.
 */

.vc-urna {
  /* Paleta local. O aparelho tem uma cor só, como todo aparelho. */
  --urna-casca: #dedede;
  --urna-casca-alta: #ececec;
  --urna-casca-borda: #b4b4b0;
  --urna-visor: #e7edf3;
  --urna-visor-borda: #94a3b2;
  --urna-tinta: #131922;
  --urna-tinta-fraca: #5b6774;
  --urna-teclado: #202327;
  --urna-tecla: #3a3f45;
  --urna-tecla-alta: #4b5158;
  --urna-tecla-tinta: #f4f6f8;
  --urna-branco: #f2f2ee;
  --urna-corrige: #db5f11;
  --urna-confirma: #16913a;
  --urna-nulo: #64707d;

  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  gap: var(--space-lg);
  align-items: stretch;

  /* Um aparelho tem tamanho. Sem teto, a urna se estica pela largura toda da
     página e o visor vira um campo vazio de um metro. */
  max-width: 58rem;
  padding: var(--space-lg);
  border: 1px solid var(--urna-casca-borda);
  border-radius: var(--radius-lg);
  background: linear-gradient(160deg, var(--urna-casca-alta), var(--urna-casca));
  box-shadow:
    inset 0 1px 0 rgb(255 255 255 / 0.7),
    var(--shadow-md);
}

@media (max-width: 60rem) {
  .vc-urna {
    grid-template-columns: minmax(0, 1fr);
  }
}

/* --- O visor -------------------------------------------------------------- */

.vc-urna__visor {
  display: flex;
  flex-direction: column;
  min-height: 19rem;
  padding: var(--space-md) var(--space-lg);
  border: 1px solid var(--urna-visor-borda);
  border-radius: var(--radius-sm);
  background: var(--urna-visor);
  box-shadow: inset 0 2px 8px rgb(19 25 34 / 0.16);
  color: var(--urna-tinta);
}

.vc-urna__cargo {
  padding-bottom: var(--space-2xs);
  border-bottom: 2px solid var(--urna-tinta);
  font-size: var(--text-caption);
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
}

.vc-urna__corpo {
  display: flex;
  flex: 1;
  flex-direction: column;
  gap: var(--space-sm);
  padding-top: var(--space-md);
}

/* A linha do número digitado: é o que o eleitor confere antes de confirmar. */
.vc-urna__numero {
  display: flex;
  align-items: baseline;
  gap: var(--space-sm);
}

.vc-urna__rotulo {
  font-size: var(--text-small);
  font-weight: 600;
}

.vc-urna__digitos {
  display: flex;
  gap: 0.35rem;
}

.vc-urna__digito {
  display: grid;
  place-items: center;
  min-width: 2.1rem;
  padding: 0.15rem 0.35rem;
  border: 1px solid var(--urna-visor-borda);
  border-radius: 2px;
  background: #fff;
  font-family: var(--font-mono);
  font-size: 1.65rem;
  font-variant-numeric: tabular-nums;
  font-weight: 700;
  line-height: 1.1;
}

.vc-urna__digito--vazio {
  color: transparent;
}

/* O cursor pisca só onde o próximo dígito entra. Parado, ele viraria ruído. */
.vc-urna__digito--cursor {
  border-color: var(--urna-tinta);
  box-shadow: inset 0 -3px 0 var(--urna-tinta);
}

@media (prefers-reduced-motion: no-preference) {
  .vc-urna__digito--cursor {
    animation: vc-urna-cursor 1.1s steps(1, end) infinite;
  }

  @keyframes vc-urna-cursor {
    50% {
      box-shadow: inset 0 -3px 0 transparent;
    }
  }
}

.vc-urna__chamada {
  display: grid;
  gap: var(--space-2xs);
  place-content: center;
  flex: 1;
  margin: 0;
  color: var(--urna-tinta-fraca);
  font-size: var(--text-lead);
  text-align: center;
}

.vc-urna__chamada small {
  font-size: var(--text-caption);
  letter-spacing: 0.12em;
  text-transform: uppercase;
}

.vc-urna__ficha {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  gap: var(--space-md);
  align-items: start;
}

.vc-urna__retrato {
  display: grid;
  place-items: center;
  width: 5.5rem;
  height: 7rem;
  border: 1px solid var(--urna-visor-borda);
  background: #fff;
  color: var(--urna-tinta-fraca);
  font-size: 1.6rem;
  font-weight: 700;
  letter-spacing: 0.04em;
}

.vc-urna__linha {
  display: block;
  font-size: var(--text-small);
  line-height: 1.5;
}

.vc-urna__linha strong {
  font-weight: 700;
}

.vc-urna__nomes {
  margin: var(--space-2xs) 0 0;
  padding-left: 1.05rem;
  font-size: var(--text-caption);
  line-height: 1.6;
}

/* --- Os avisos do visor --------------------------------------------------- */

.vc-urna__aviso {
  padding: var(--space-sm) var(--space-md);
  border-left: 4px solid currentColor;
  background: rgb(255 255 255 / 0.75);
  font-size: var(--text-small);
  line-height: 1.5;
}

.vc-urna__aviso--atencao {
  color: #9a4b06;
}

.vc-urna__aviso--neutro {
  color: var(--urna-tinta-fraca);
}

.vc-urna__veredito {
  font-size: var(--text-title);
  font-weight: 800;
  letter-spacing: 0.02em;
  line-height: 1.15;
}

/* O rodapé do visor repete a instrução das teclas, como no aparelho real: é
   onde o olho já está quando a dúvida aparece. */
.vc-urna__rodape {
  margin-top: auto;
  padding-top: var(--space-sm);
  border-top: 1px solid var(--urna-visor-borda);
  color: var(--urna-tinta-fraca);
  font-size: var(--text-caption);
  line-height: 1.6;
}

/* --- O teclado ------------------------------------------------------------ */

.vc-urna__teclado {
  /* A largura da placa é a das teclas, e as duas grades usam a mesma medida.
     Era isto que faltava: com as ações em 1fr, a placa ficava mais larga que a
     grade de números e os dígitos encostavam na borda esquerda. */
  --tecla: 3.4rem;
  --vao: 0.55rem;
  --grade: calc(var(--tecla) * 3 + var(--vao) * 2);

  display: flex;
  flex-direction: column;
  gap: var(--vao);
  align-items: center;
  justify-content: center;
  padding: var(--space-md);
  border-radius: var(--radius-sm);
  background: var(--urna-teclado);
  box-shadow: inset 0 1px 0 rgb(255 255 255 / 0.08);
}

.vc-urna__digitos-grade,
.vc-urna__acoes {
  display: grid;
  grid-template-columns: repeat(3, var(--tecla));
  gap: var(--vao);
  width: var(--grade);
}

.vc-urna__acoes {
  margin-top: var(--space-xs);
}

/* O nulo ocupa a fila inteira, abaixo do trio conhecido. O aparelho de verdade
   não tem essa tecla: anular é digitar um número que não existe. Ela está aqui
   porque foi pedida, e fica fora da fila que a memória do eleitor reconhece. */
.vc-urna__tecla--largo {
  grid-column: 1 / -1;
}

.vc-urna__tecla {
  display: grid;
  place-items: center;
  min-height: 3rem;
  padding: 0.2rem;
  border: 0;
  border-radius: 5px;
  background: linear-gradient(180deg, var(--urna-tecla-alta), var(--urna-tecla));
  box-shadow:
    0 2px 0 rgb(0 0 0 / 0.45),
    inset 0 1px 0 rgb(255 255 255 / 0.16);
  color: var(--urna-tecla-tinta);
  font-family: inherit;
  font-size: 1.25rem;
  font-variant-numeric: tabular-nums;
  font-weight: 700;
  cursor: pointer;
  transition:
    transform var(--duration-fast) var(--ease-out-expo),
    box-shadow var(--duration-fast) var(--ease-out-expo);
}

/* A tecla afunda ao ser apertada. É a confirmação tátil que o aparelho dá e a
   única resposta imediata que uma tela consegue devolver no lugar dela. */
.vc-urna__tecla:active:not(:disabled) {
  transform: translateY(2px);
  box-shadow: inset 0 1px 3px rgb(0 0 0 / 0.5);
}

.vc-urna__tecla:focus-visible {
  outline: 3px solid #7dd3fc;
  outline-offset: 2px;
}

.vc-urna__tecla:disabled {
  cursor: not-allowed;
  opacity: 0.4;
}

.vc-urna__tecla--acao {
  min-height: 3.2rem;
  padding-inline: 0.15rem;
  font-size: 0.58rem;
  letter-spacing: 0.03em;
  line-height: 1.15;
  text-transform: uppercase;
}

.vc-urna__tecla--largo {
  min-height: 2.5rem;
}

.vc-urna__tecla--branco {
  background: linear-gradient(180deg, #fff, var(--urna-branco));
  color: #1b1b1b;
}

.vc-urna__tecla--nulo {
  background: linear-gradient(180deg, #7b8794, var(--urna-nulo));
}

.vc-urna__tecla--corrige {
  background: linear-gradient(180deg, #ef7420, var(--urna-corrige));
}

.vc-urna__tecla--confirma {
  background: linear-gradient(180deg, #1cae47, var(--urna-confirma));
}

/* O rodapé do aparelho, fora da placa: dentro dela a frase quebrava em quatro
   linhas e empurrava as teclas para fora do lugar. */
.vc-urna-rodape {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-md);
  align-items: center;
  justify-content: space-between;
  max-width: 58rem;
  margin-top: var(--space-md);
  padding-top: var(--space-md);
  border-top: 1px solid var(--color-line);
}

.vc-urna-rodape p {
  margin: 0;
  color: var(--color-ink-subtle);
  font-size: var(--text-small);
}

/* --- A tela de instruções, antes da cabine -------------------------------- */

.vc-urna-aviso {
  display: grid;
  grid-template-columns: minmax(0, 22rem) minmax(0, 1fr);
  gap: var(--space-xl);
  align-items: center;
}

@media (max-width: 55rem) {
  .vc-urna-aviso {
    grid-template-columns: minmax(0, 1fr);
  }
}

/* O desenho ganha um painel próprio. Solto no branco do cartão ele flutua;
   sobre uma superfície rebaixada ele se lê como o retrato de um objeto. */
.vc-urna-aviso__moldura {
  display: grid;
  place-items: center;
  padding: var(--space-lg) var(--space-md);
  border: 1px solid var(--color-line);
  border-radius: var(--radius-md);
  background: linear-gradient(165deg, var(--color-surface-raised), var(--color-surface-sunken));
}

.vc-urna-aviso__desenho {
  width: 100%;
  height: auto;
}

/* Texto corrido não passa da medida em que o olho ainda encontra a linha
   seguinte sem se perder. */
.vc-urna-aviso__texto {
  max-width: 62ch;
}

.vc-urna-aviso__passos {
  display: grid;
  gap: var(--space-md);
  margin: var(--space-lg) 0 0;
  padding: 0;
  list-style: none;
}

.vc-urna-aviso__passo {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  gap: var(--space-md);
  align-items: start;
}

/* A marca do passo é a própria tecla que ele descreve, no mesmo tamanho e na
   mesma cor. Ler a instrução já é reconhecer o botão. */
.vc-urna-aviso__marca {
  display: grid;
  place-items: center;
  /* Largura suficiente para "CONFIRMA" caber inteiro: uma marca cortada deixa
     de ser a tecla que ela existe para apresentar. */
  width: 3.6rem;
  height: 2.1rem;
  border-radius: 4px;
  box-shadow: 0 2px 0 rgb(0 0 0 / 0.3);
  color: #fff;
  font-size: 0.55rem;
  font-weight: 800;
  letter-spacing: 0.02em;
}

.vc-urna-aviso__marca--numero {
  background: linear-gradient(180deg, #4b5158, #3a3f45);
  font-size: 0.95rem;
}

.vc-urna-aviso__marca--branco {
  background: linear-gradient(180deg, #fff, #f2f2ee);
  color: #1b1b1b;
}

.vc-urna-aviso__marca--nulo {
  background: linear-gradient(180deg, #7b8794, #64707d);
}

.vc-urna-aviso__marca--corrige {
  background: linear-gradient(180deg, #ef7420, #db5f11);
}

.vc-urna-aviso__marca--confirma {
  background: linear-gradient(180deg, #1cae47, #16913a);
}
