/* The pages that stay server-rendered, on the console's own tokens and type (#333, phase 3).

   Sign-in, the sandbox invitation and its claim, the error pages, the classic approval page
   behind every notification, and the public showcase: everything else a person opens is the
   console, which has its own stylesheet inside its build. These pages are few and plain, so
   this file is a small one — the shell, a card, a table, a form, the decision badges and the
   live board — and it reads every colour from the tokens below.

   The token blocks are the console's, copied so a page renders with no build present;
   tests/test_page_tokens.py holds them equal to console/public/tokens.css value for value,
   the way the site's are held, so the three can never drift into three palettes. The fonts
   are the console build's own files under font-src 'self'; where no build is packaged a page
   falls back to the system stack and still reads.
*/

:root {
  color-scheme: light dark;
  --eb-bg: #F4F5F7;
  --eb-side: #FFFFFF;
  --eb-surface: #FFFFFF;
  --eb-surface2: #EEF0F3;
  --eb-line: #E1E4E9;
  --eb-line2: #CBD1D8;
  --eb-text: #0F1318;
  --eb-muted: #535D6A;
  --eb-faint: #646D79;
  --eb-accent: #0A7486;
  --eb-on-accent: #FFFFFF;
  --eb-accent-soft: #DCF2F5;
  --eb-accent-text: #0A6474;
  --eb-allow: #146B41;
  --eb-allow-bg: #DDF2E6;
  --eb-hold: #7A5200;
  --eb-hold-bg: #FCEFCB;
  --eb-deny: #A3242B;
  --eb-deny-bg: #FBE4E4;
  --eb-obs: #5A3EC2;
  --eb-obs-bg: #ECE6FD;
  --eb-stale: #535D6A;
  --eb-stale-bg: #EDEFF2;
  --eb-scrim: rgba(15, 19, 24, 0.38);
  --eb-shadow: 0 24px 64px rgba(16, 20, 26, 0.16);
  --eb-font-sans: "IBM Plex Sans", system-ui, "Segoe UI", sans-serif;
  --eb-font-mono: "IBM Plex Mono", ui-monospace, Consolas, Menlo, monospace;
}

@media (prefers-color-scheme: dark) {
  :root {
    --eb-bg: #0B0D11;
    --eb-side: #0F1217;
    --eb-surface: #141821;
    --eb-surface2: #1B202A;
    --eb-line: #232934;
    --eb-line2: #313947;
    --eb-text: #E8EBEF;
    --eb-muted: #A3ACB8;
    --eb-faint: #808996;
    --eb-accent: #35D3E6;
    --eb-on-accent: #032429;
    --eb-accent-soft: rgba(53, 211, 230, 0.13);
    --eb-accent-text: #74E3F1;
    --eb-allow: #5BD49A;
    --eb-allow-bg: rgba(91, 212, 154, 0.12);
    --eb-hold: #F4C152;
    --eb-hold-bg: rgba(244, 193, 82, 0.13);
    --eb-deny: #FF8A8A;
    --eb-deny-bg: rgba(255, 138, 138, 0.12);
    --eb-obs: #B8A2FF;
    --eb-obs-bg: rgba(184, 162, 255, 0.13);
    --eb-stale: #A3ACB8;
    --eb-stale-bg: rgba(163, 172, 184, 0.12);
    --eb-scrim: rgba(4, 6, 9, 0.62);
    --eb-shadow: 0 24px 64px rgba(0, 0, 0, 0.55);
  }
}

/* The live board is the console's one full-ink surface: a display for a wall or a screen
   share, dark in both schemes. #206 recorded that exception for the server-rendered board
   and #280 carries it into the rebuild. It is the dark block by another name, and
   tests/test_console_tokens.py holds the two equal, so this exception can never quietly
   become a second palette that drifts from the one everything else reads. */
.ink {
  color-scheme: dark;
  --eb-bg: #0B0D11;
  --eb-side: #0F1217;
  --eb-surface: #141821;
  --eb-surface2: #1B202A;
  --eb-line: #232934;
  --eb-line2: #313947;
  --eb-text: #E8EBEF;
  --eb-muted: #A3ACB8;
  --eb-faint: #808996;
  --eb-accent: #35D3E6;
  --eb-on-accent: #032429;
  --eb-accent-soft: rgba(53, 211, 230, 0.13);
  --eb-accent-text: #74E3F1;
  --eb-allow: #5BD49A;
  --eb-allow-bg: rgba(91, 212, 154, 0.12);
  --eb-hold: #F4C152;
  --eb-hold-bg: rgba(244, 193, 82, 0.13);
  --eb-deny: #FF8A8A;
  --eb-deny-bg: rgba(255, 138, 138, 0.12);
  --eb-obs: #B8A2FF;
  --eb-obs-bg: rgba(184, 162, 255, 0.13);
  --eb-stale: #A3ACB8;
  --eb-stale-bg: rgba(163, 172, 184, 0.12);
  --eb-scrim: rgba(4, 6, 9, 0.62);
  --eb-shadow: 0 24px 64px rgba(0, 0, 0, 0.55);
}

/* The fonts: the console build's own files, under font-src 'self'. */
@font-face {
  font-family: "IBM Plex Sans";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("/console/fonts/IBMPlexSans-Regular-Latin1.woff2") format("woff2");
  unicode-range: U+0000, U+000D, U+0020-007E, U+00A0-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2013-2014, U+2018-201A, U+201C-201E, U+2020-2022, U+2026, U+2030, U+2039-203A, U+2044, U+2074, U+20AC, U+2122, U+2212, U+FB01-FB02;
}
@font-face {
  font-family: "IBM Plex Sans";
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url("/console/fonts/IBMPlexSans-Medium-Latin1.woff2") format("woff2");
  unicode-range: U+0000, U+000D, U+0020-007E, U+00A0-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2013-2014, U+2018-201A, U+201C-201E, U+2020-2022, U+2026, U+2030, U+2039-203A, U+2044, U+2074, U+20AC, U+2122, U+2212, U+FB01-FB02;
}
@font-face {
  font-family: "IBM Plex Sans";
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url("/console/fonts/IBMPlexSans-SemiBold-Latin1.woff2") format("woff2");
  unicode-range: U+0000, U+000D, U+0020-007E, U+00A0-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2013-2014, U+2018-201A, U+201C-201E, U+2020-2022, U+2026, U+2030, U+2039-203A, U+2044, U+2074, U+20AC, U+2122, U+2212, U+FB01-FB02;
}
@font-face {
  font-family: "IBM Plex Sans";
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url("/console/fonts/IBMPlexSans-Bold-Latin1.woff2") format("woff2");
  unicode-range: U+0000, U+000D, U+0020-007E, U+00A0-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2013-2014, U+2018-201A, U+201C-201E, U+2020-2022, U+2026, U+2030, U+2039-203A, U+2044, U+2074, U+20AC, U+2122, U+2212, U+FB01-FB02;
}
@font-face {
  font-family: "IBM Plex Mono";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("/console/fonts/IBMPlexMono-Regular-Latin1.woff2") format("woff2");
  unicode-range: U+0020-007E, U+00A0-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2013-2014, U+2018-201A, U+201C-201E, U+2020-2022, U+2026, U+2030, U+2039-203A, U+2044, U+20AC, U+2122, U+2212, U+FB01-FB02;
}
@font-face {
  font-family: "IBM Plex Mono";
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url("/console/fonts/IBMPlexMono-Medium-Latin1.woff2") format("woff2");
  unicode-range: U+0020-007E, U+00A0-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2013-2014, U+2018-201A, U+201C-201E, U+2020-2022, U+2026, U+2030, U+2039-203A, U+2044, U+20AC, U+2122, U+2212, U+FB01-FB02;
}
@font-face {
  font-family: "IBM Plex Mono";
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url("/console/fonts/IBMPlexMono-SemiBold-Latin1.woff2") format("woff2");
  unicode-range: U+0020-007E, U+00A0-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2013-2014, U+2018-201A, U+201C-201E, U+2020-2022, U+2026, U+2030, U+2039-203A, U+2044, U+20AC, U+2122, U+2212, U+FB01-FB02;
}

/* ---- the page shell ----------------------------------------------------------------- */
*, *::before, *::after { box-sizing: border-box; }
/* `hidden` must win over every `display` below: an author rule such as `label { display:
   block }` otherwise overrides the attribute and a hidden element stays on screen. */
[hidden] { display: none !important; }
body {
  margin: 0;
  background: var(--eb-bg);
  color: var(--eb-text);
  font-family: var(--eb-font-sans);
  font-size: 13.5px;
  line-height: 1.55;
  font-variant-numeric: tabular-nums;
  -webkit-font-smoothing: antialiased;
}
a { color: var(--eb-accent-text); }
:focus-visible { outline: 2px solid var(--eb-accent); outline-offset: 2px; }
h1, h2, h3 { margin: 0; letter-spacing: -0.015em; }
h1 { font-size: 22px; font-weight: 600; }
h2 { font-size: 15px; font-weight: 600; }
h3 { font-size: 14.5px; font-weight: 600; margin: 18px 0 8px; }
p { margin: 0 0 10px; }
.skip {
  position: absolute; top: -48px; left: 12px; z-index: 10;
  padding: 8px 14px; border-radius: 7px;
  background: var(--eb-accent); color: var(--eb-on-accent); text-decoration: none;
}
.skip:focus { top: 12px; }
header {
  display: flex; align-items: center; gap: 16px;
  height: 56px; padding: 0 28px;
  background: var(--eb-side); border-bottom: 1px solid var(--eb-line);
}
.brand {
  display: inline-flex; align-items: center; gap: 9px;
  color: var(--eb-text); text-decoration: none; font-weight: 600; letter-spacing: -0.01em;
}
.mark { flex: none; }
.mark-bar { stroke: var(--eb-accent); }
header nav { margin-left: auto; display: flex; gap: 14px; }
header form { margin-left: auto; }
header nav + form { margin-left: 0; }
main { max-width: 1120px; margin: 0 auto; padding: 22px 28px 48px; }
footer {
  display: flex; align-items: center; justify-content: space-between; gap: 16px;
  max-width: 1120px; margin: 0 auto; padding: 18px 28px 28px;
  color: var(--eb-faint); font-size: 12px;
}
.footer-brand { display: inline-flex; align-items: center; gap: 7px; }

/* ---- page furniture ----------------------------------------------------------------- */
.page-heading { display: flex; gap: 24px; align-items: flex-start; justify-content: space-between; margin-bottom: 14px; }
.eyebrow { margin: 0 0 6px; font-size: 11px; font-weight: 600; letter-spacing: 0.07em; text-transform: uppercase; color: var(--eb-faint); }
.intro { margin: 6px 0 0; color: var(--eb-muted); max-width: 72ch; }
.muted { color: var(--eb-muted); }
.muted a, .bindings a { text-decoration: underline; text-underline-offset: 2px; }
.mono { font-family: var(--eb-font-mono); font-size: 12.5px; }
.count { flex: none; text-align: right; }
.count strong { display: block; font-size: 26px; font-weight: 600; line-height: 1.1; }
.count span { color: var(--eb-faint); font-size: 12px; }
.count-text strong { font-size: 18px; }
.scope-line {
  display: flex; flex-wrap: wrap; gap: 8px 18px; justify-content: space-between;
  padding: 0 0 12px; margin-bottom: 14px;
  border-bottom: 1px solid var(--eb-line); color: var(--eb-muted); font-size: 12.5px;
}
.notice { margin: 0 0 14px; padding: 12px 16px; border-radius: 10px; background: var(--eb-hold-bg); color: var(--eb-hold); }

/* Decision badges: word first, tint second. A modifier names a state, never a colour. */
.status {
  display: inline-flex; align-items: center; gap: 6px;
  height: 22px; padding: 0 9px; border-radius: 5px;
  background: var(--eb-stale-bg); color: var(--eb-stale);
  font-size: 11px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.05em;
  white-space: nowrap;
}
.status.allow { background: var(--eb-allow-bg); color: var(--eb-allow); }
.status.deny { background: var(--eb-deny-bg); color: var(--eb-deny); }
.status.pending { background: var(--eb-hold-bg); color: var(--eb-hold); }

/* ---- cards, records and tables ------------------------------------------------------ */
.card, .record {
  border: 1px solid var(--eb-line); border-radius: 10px;
  background: var(--eb-surface); margin: 0 0 14px;
}
.card { padding: 16px 18px; }
.card h2 { margin-bottom: 8px; }
.card-wide { margin: 14px 0; }
.record-heading {
  display: flex; gap: 18px; align-items: flex-start; justify-content: space-between;
  padding: 16px 18px; border-bottom: 1px solid var(--eb-line);
}
.detail-body { padding: 16px 18px; }
.bindings {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
  gap: 10px 22px; margin: 0; padding: 14px 18px;
}
.bindings > div { min-width: 0; }
.bindings dt { font-size: 11px; font-weight: 600; letter-spacing: 0.07em; text-transform: uppercase; color: var(--eb-faint); }
.bindings dd { margin: 0; overflow-wrap: anywhere; }
.evidence { border-top: 1px solid var(--eb-line); }
.external-effect { margin: 0; padding: 12px 18px; color: var(--eb-muted); border-top: 1px solid var(--eb-line); }
.review-columns { display: grid; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); gap: 0 28px; }
.review-columns ul { margin: 0 0 10px; padding-left: 20px; }
.table-scroll { overflow-x: auto; }
table { width: 100%; border-collapse: collapse; font-size: 13px; }
caption { text-align: left; padding: 0 0 10px; color: var(--eb-muted); font-size: 12.5px; }
th, td { text-align: left; padding: 9px 12px 9px 0; border-bottom: 1px solid var(--eb-line); vertical-align: top; }
thead th { font-size: 11px; font-weight: 600; letter-spacing: 0.07em; text-transform: uppercase; color: var(--eb-faint); }
tbody th[scope="row"] { font-weight: 500; }
td small { color: var(--eb-faint); }

/* ---- forms and controls -------------------------------------------------------------- */
button, .btn {
  height: 34px; padding: 0 14px; border-radius: 7px;
  border: 1px solid transparent; background: var(--eb-accent); color: var(--eb-on-accent);
  font: inherit; font-weight: 600; cursor: pointer;
}
button.secondary, button.quiet {
  background: transparent; color: var(--eb-text); border-color: var(--eb-line2); font-weight: 500;
}
button.quiet { border-color: transparent; color: var(--eb-muted); padding: 0 8px; }
button.secondary:hover, button.quiet:hover { background: var(--eb-surface2); }
label { display: block; font-size: 12.5px; font-weight: 500; color: var(--eb-muted); }
input, textarea {
  display: block; width: 100%; margin-top: 6px; padding: 8px 10px;
  border: 1px solid var(--eb-line2); border-radius: 7px;
  background: var(--eb-bg); color: var(--eb-text); font: inherit;
}
textarea { min-height: 68px; resize: vertical; }
.decision-detail { margin-top: 14px; }
.decision-buttons { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 12px; }
.decision-buttons button { height: 44px; }
.decision button[value="DENY"] {
  background: var(--eb-deny-bg); color: var(--eb-deny); border-color: transparent;
}

/* ---- sign-in, the invitation and the error pages ------------------------------------- */
.login { max-width: 460px; margin: 48px auto 0; }
.login h1 { font-size: 32px; }
.login form { margin-top: 22px; }
.login label + label, .login button { margin-top: 14px; }
.login button { width: 100%; height: 40px; }
.login .muted { margin-top: 16px; font-size: 12.5px; }
/* A second way out beneath the page's button: a link, but still a target of its own, clear
   of the button above it and at least 24 px tall (WCAG 2.2, 2.5.8). */
.login .alternative { margin-top: 16px; }
/* Account security: each section starts clear of the button above it, a choice is a full
   control like the fields beside it, and the way back to the console is at the top. */
.login h2 { margin-top: 32px; }
.login .back { margin-top: 8px; }
.login .back a { display: inline-flex; align-items: center; min-height: 24px; }
.login select {
  display: block; width: 100%; height: 38px; margin-top: 6px; padding: 0 10px;
  border: 1px solid var(--eb-line2); border-radius: 7px;
  background: var(--eb-bg); color: var(--eb-text); font: inherit;
}
/* The second step of signing in: one code, large and centred, as every sign-in asks for it. */
.login .code-input {
  height: 48px; font-size: 22px; letter-spacing: 0.3em; text-align: center;
  font-variant-numeric: tabular-nums;
}
.challenge form + form { margin-top: 10px; }
.challenge .recovery { margin-top: 20px; }
.challenge .recovery summary { cursor: pointer; min-height: 24px; color: var(--eb-muted); }
.challenge .muted { margin-top: 28px; }
.login .alternative a { display: inline-flex; align-items: center; min-height: 24px; }
/* A provider is a way in, not a footnote: the same width and weight as the password button,
   its own border, and the provider's mark before its name. `quiet` made these read as text
   somebody scrolls past, which is what they did. */
.login .rule {
  display: flex; align-items: center; gap: 12px;
  margin-top: 24px; font-size: 12px; letter-spacing: .06em;
  text-transform: uppercase; color: var(--eb-muted);
}
.login .rule::before, .login .rule::after {
  content: ""; flex: 1; height: 1px; background: var(--eb-line2);
}
.login .providers form { margin-top: 12px; }
.login button.provider {
  display: flex; align-items: center; justify-content: center; gap: 10px;
  height: 44px; background: var(--eb-surface); color: var(--eb-text);
  border: 1px solid var(--eb-line2); font-weight: 500;
}
.login button.provider:hover { background: var(--eb-surface2); border-color: var(--eb-line); }
.provider-mark { flex: none; }
/* The one control on the invitation page that is a link rather than a button: the page could
   not have named the customer's directory in its own `form-action`, and a link is not governed
   by it. It is sized like the buttons beside it so it reads as the same kind of thing. */
.login a.btn {
  display: flex; align-items: center; justify-content: center;
  width: 100%; height: 44px; margin-top: 22px; text-decoration: none;
}
/* The signup form's consent line, and the field no person is shown. The honeypot is clipped
   rather than moved off the page, so it adds no scrollable width at any viewport, and it is
   still a labelled control because every control on these pages has to be one. */
.login .consent { display: flex; gap: 9px; align-items: flex-start; margin-top: 16px; }
.login .consent input { width: auto; margin: 2px 0 0; flex: none; }
.login .consent span { font-size: 12.5px; line-height: 1.45; }
.honeypot {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip-path: inset(50%); white-space: nowrap; border: 0;
}
.empty { max-width: 560px; margin: 64px auto 0; text-align: center; }
.empty h1 { margin-bottom: 8px; }

/* ---- the banners the classic approval page carries ----------------------------------- */
.stop-banner, .mode-banner {
  margin: 0; padding: 12px 28px; font-size: 12.5px;
  background: var(--eb-deny-bg); color: var(--eb-deny);
}
.mode-banner { background: var(--eb-obs-bg); color: var(--eb-obs); }

/* ---- the classic approval page: content beside the decision panel --------------------- */
.approval { display: grid; grid-template-columns: minmax(0, 1fr) 330px; align-items: start; }
.approval-content { min-width: 0; }
.approval-panel {
  padding: 18px; border-left: 1px solid var(--eb-line); background: var(--eb-surface2);
  border-radius: 0 10px 10px 0; align-self: stretch;
}
.panel-clock { margin: 0; font-size: 26px; font-weight: 600; line-height: 1.1; }
.panel-reason { margin: 12px 0 0; font-weight: 500; }
.panel-recheck { margin: 10px 0 0; color: var(--eb-muted); font-size: 12.5px; }
.approval-panel .decision-buttons button { width: 100%; }

/* ---- the live board (#280), which /showcase renders publicly -------------------------- */
/* The one full-ink surface, recorded as #206's exception and carried into the rebuild by
   #333: a display for a wall or a screen share, dark in both schemes. `.ink` is the dark
   token block by another name and the token test holds the two equal, so the exception can
   never quietly become a second palette. */
.board-page main { max-width: none; padding: 16px; }
.board-caption { color: var(--eb-muted); font-size: 13px; }
.board-caption a { color: var(--eb-accent-text); }
.board svg { display: block; width: 100%; height: auto; }
.lane-label { fill: var(--eb-muted); font-size: 11px; font-family: var(--eb-font-sans); }
.lane-group { fill: var(--eb-faint); font-size: 10px; font-family: var(--eb-font-sans); }
.lane-rule { stroke: var(--eb-line2); stroke-width: 1; }
.checkpoint-rule { stroke: var(--eb-accent); stroke-width: 3; stroke-linecap: round; }
.checkpoint-word { fill: var(--eb-accent-text); font-size: 11px; font-family: var(--eb-font-sans); text-anchor: middle; }
.shot { fill: var(--eb-accent); }
.shot.deny, .shot.short { fill: var(--eb-deny); }
.shot.hold { fill: var(--eb-hold); }
.shot.land { fill: var(--eb-allow); }
.shot.unsettled { fill: var(--eb-hold); }
.shot.hollow { fill: none; stroke: var(--eb-accent); stroke-width: 1.5; }
.shot.observe { fill: none; stroke: var(--eb-obs); stroke-width: 1.5; }

/* Six phases, each a fixed keyframe run; the age class supplies the negative delay that
   anchors a shot on its own event time, so a reload lands it where it was. */
@keyframes shot-in { from { transform: translateX(0); } to { transform: translateX(340px); } }
@keyframes shot-out { from { transform: translateX(0); } to { transform: translateX(120px); } }
@keyframes land { from { transform: translateX(0); } to { transform: translateX(120px); } }
@keyframes hold { 0%, 100% { opacity: 0.35; } 50% { opacity: 1; } }
@keyframes deny { from { opacity: 1; } to { opacity: 0.25; } }
@keyframes fade { from { opacity: 1; } to { opacity: 0; } }
@keyframes seen { from { transform: translateX(0); } to { transform: translateX(760px); } }
.shot.shot-in { animation: shot-in 2s linear forwards; }
.shot.observe { animation: shot-in 2s linear forwards; }
.shot.short { animation: shot-in 1s linear forwards, fade 60s linear forwards; }
.shot.hold { animation: hold 1.6s ease-in-out infinite; }
.shot.deny { animation: deny 60s linear forwards; }
.shot.shot-out, .shot.unsettled { animation: shot-out 2s linear forwards; }
.shot.land, .shot.hollow { animation: land 2s ease-out forwards; }
.shot.unsettled { animation: shot-out 2s linear forwards, hold 1.6s ease-in-out infinite; }

/* Paused, and reduced motion: every shot is drawn at the final position of its phase with
   no motion at all, so the picture is the same picture, still. */
.board-still .shot,
.board-still .shot.hold,
.board-still .shot.unsettled { animation: none; }
.board-still .shot.shot-in, .board-still .shot.observe { transform: translateX(340px); }
.board-still .shot.shot-out,
.board-still .shot.unsettled,
.board-still .shot.land,
.board-still .shot.hollow { transform: translateX(120px); }

.band-rule { stroke: var(--eb-line2); stroke-width: 1; }
.band-label { fill: var(--eb-muted); font-size: 11px; font-family: var(--eb-font-sans); }
/* Grey, and never one of the decision colours: nothing here was decided. */
.seen { fill: var(--eb-stale); animation: seen 3s linear forwards; }
.seen.flagged { fill: var(--eb-obs); }
.board-still .seen { animation: none; transform: translateX(760px); }

@media (prefers-reduced-motion: reduce) {
  .shot, .seen { animation: none !important; }
  .shot.shot-in, .shot.observe { transform: translateX(340px); }
  .shot.shot-out, .shot.unsettled, .shot.land, .shot.hollow { transform: translateX(120px); }
  .seen { transform: translateX(760px); }
}

/* ---- one column on a phone ------------------------------------------------------------ */
@media (max-width: 767px) {
  header { padding: 0 16px; gap: 10px; }
  main { padding: 16px 16px 32px; }
  footer { padding: 16px; }
  .page-heading { flex-direction: column; gap: 10px; }
  .count { text-align: left; }
  .approval { grid-template-columns: minmax(0, 1fr); }
  .approval-panel { border-left: 0; border-top: 1px solid var(--eb-line); border-radius: 0 0 10px 10px; }
  .decision-buttons { display: grid; grid-template-columns: 2fr 1fr; }
  .decision-buttons button { height: 50px; }
  .stop-banner, .mode-banner { padding: 12px 16px; }
}

/* BEGIN generated age classes - scripts/render_age_classes.py */
.age-0 { animation-delay: -0.0s; }
.age-1 { animation-delay: -0.1s; }
.age-2 { animation-delay: -0.2s; }
.age-3 { animation-delay: -0.3s; }
.age-4 { animation-delay: -0.4s; }
.age-5 { animation-delay: -0.5s; }
.age-6 { animation-delay: -0.6s; }
.age-7 { animation-delay: -0.7s; }
.age-8 { animation-delay: -0.8s; }
.age-9 { animation-delay: -0.9s; }
.age-10 { animation-delay: -1.0s; }
.age-11 { animation-delay: -1.1s; }
.age-12 { animation-delay: -1.2s; }
.age-13 { animation-delay: -1.3s; }
.age-14 { animation-delay: -1.4s; }
.age-15 { animation-delay: -1.5s; }
.age-16 { animation-delay: -1.6s; }
.age-17 { animation-delay: -1.7s; }
.age-18 { animation-delay: -1.8s; }
.age-19 { animation-delay: -1.9s; }
.age-20 { animation-delay: -2.0s; }
.age-21 { animation-delay: -2.1s; }
.age-22 { animation-delay: -2.2s; }
.age-23 { animation-delay: -2.3s; }
.age-24 { animation-delay: -2.4s; }
.age-25 { animation-delay: -2.5s; }
.age-26 { animation-delay: -2.6s; }
.age-27 { animation-delay: -2.7s; }
.age-28 { animation-delay: -2.8s; }
.age-29 { animation-delay: -2.9s; }
.age-30 { animation-delay: -3.0s; }
.age-31 { animation-delay: -3.1s; }
.age-32 { animation-delay: -3.2s; }
.age-33 { animation-delay: -3.3s; }
.age-34 { animation-delay: -3.4s; }
.age-35 { animation-delay: -3.5s; }
.age-36 { animation-delay: -3.6s; }
.age-37 { animation-delay: -3.7s; }
.age-38 { animation-delay: -3.8s; }
.age-39 { animation-delay: -3.9s; }
.age-40 { animation-delay: -4.0s; }
.age-41 { animation-delay: -4.1s; }
.age-42 { animation-delay: -4.2s; }
.age-43 { animation-delay: -4.3s; }
.age-44 { animation-delay: -4.4s; }
.age-45 { animation-delay: -4.5s; }
.age-46 { animation-delay: -4.6s; }
.age-47 { animation-delay: -4.7s; }
.age-48 { animation-delay: -4.8s; }
.age-49 { animation-delay: -4.9s; }
.age-50 { animation-delay: -5.0s; }
.age-51 { animation-delay: -5.1s; }
.age-52 { animation-delay: -5.2s; }
.age-53 { animation-delay: -5.3s; }
.age-54 { animation-delay: -5.4s; }
.age-55 { animation-delay: -5.5s; }
.age-56 { animation-delay: -5.6s; }
.age-57 { animation-delay: -5.7s; }
.age-58 { animation-delay: -5.8s; }
.age-59 { animation-delay: -5.9s; }
.age-60 { animation-delay: -6.0s; }
.age-61 { animation-delay: -6.1s; }
.age-62 { animation-delay: -6.2s; }
.age-63 { animation-delay: -6.3s; }
.age-64 { animation-delay: -6.4s; }
.age-65 { animation-delay: -6.5s; }
.age-66 { animation-delay: -6.6s; }
.age-67 { animation-delay: -6.7s; }
.age-68 { animation-delay: -6.8s; }
.age-69 { animation-delay: -6.9s; }
.age-70 { animation-delay: -7.0s; }
.age-71 { animation-delay: -7.1s; }
.age-72 { animation-delay: -7.2s; }
.age-73 { animation-delay: -7.3s; }
.age-74 { animation-delay: -7.4s; }
.age-75 { animation-delay: -7.5s; }
.age-76 { animation-delay: -7.6s; }
.age-77 { animation-delay: -7.7s; }
.age-78 { animation-delay: -7.8s; }
.age-79 { animation-delay: -7.9s; }
.age-80 { animation-delay: -8.0s; }
.age-81 { animation-delay: -8.1s; }
.age-82 { animation-delay: -8.2s; }
.age-83 { animation-delay: -8.3s; }
.age-84 { animation-delay: -8.4s; }
.age-85 { animation-delay: -8.5s; }
.age-86 { animation-delay: -8.6s; }
.age-87 { animation-delay: -8.7s; }
.age-88 { animation-delay: -8.8s; }
.age-89 { animation-delay: -8.9s; }
.age-90 { animation-delay: -9.0s; }
.age-91 { animation-delay: -9.1s; }
.age-92 { animation-delay: -9.2s; }
.age-93 { animation-delay: -9.3s; }
.age-94 { animation-delay: -9.4s; }
.age-95 { animation-delay: -9.5s; }
.age-96 { animation-delay: -9.6s; }
.age-97 { animation-delay: -9.7s; }
.age-98 { animation-delay: -9.8s; }
.age-99 { animation-delay: -9.9s; }
.age-100 { animation-delay: -10.0s; }
.age-101 { animation-delay: -10.1s; }
.age-102 { animation-delay: -10.2s; }
.age-103 { animation-delay: -10.3s; }
.age-104 { animation-delay: -10.4s; }
.age-105 { animation-delay: -10.5s; }
.age-106 { animation-delay: -10.6s; }
.age-107 { animation-delay: -10.7s; }
.age-108 { animation-delay: -10.8s; }
.age-109 { animation-delay: -10.9s; }
.age-110 { animation-delay: -11.0s; }
.age-111 { animation-delay: -11.1s; }
.age-112 { animation-delay: -11.2s; }
.age-113 { animation-delay: -11.3s; }
.age-114 { animation-delay: -11.4s; }
.age-115 { animation-delay: -11.5s; }
.age-116 { animation-delay: -11.6s; }
.age-117 { animation-delay: -11.7s; }
.age-118 { animation-delay: -11.8s; }
.age-119 { animation-delay: -11.9s; }
.age-120 { animation-delay: -12.0s; }
.age-121 { animation-delay: -12.1s; }
.age-122 { animation-delay: -12.2s; }
.age-123 { animation-delay: -12.3s; }
.age-124 { animation-delay: -12.4s; }
.age-125 { animation-delay: -12.5s; }
.age-126 { animation-delay: -12.6s; }
.age-127 { animation-delay: -12.7s; }
.age-128 { animation-delay: -12.8s; }
.age-129 { animation-delay: -12.9s; }
.age-130 { animation-delay: -13.0s; }
.age-131 { animation-delay: -13.1s; }
.age-132 { animation-delay: -13.2s; }
.age-133 { animation-delay: -13.3s; }
.age-134 { animation-delay: -13.4s; }
.age-135 { animation-delay: -13.5s; }
.age-136 { animation-delay: -13.6s; }
.age-137 { animation-delay: -13.7s; }
.age-138 { animation-delay: -13.8s; }
.age-139 { animation-delay: -13.9s; }
.age-140 { animation-delay: -14.0s; }
.age-141 { animation-delay: -14.1s; }
.age-142 { animation-delay: -14.2s; }
.age-143 { animation-delay: -14.3s; }
.age-144 { animation-delay: -14.4s; }
.age-145 { animation-delay: -14.5s; }
.age-146 { animation-delay: -14.6s; }
.age-147 { animation-delay: -14.7s; }
.age-148 { animation-delay: -14.8s; }
.age-149 { animation-delay: -14.9s; }
.age-150 { animation-delay: -15.0s; }
/* END generated age classes */

.mfa-qr { background: white; padding: 1rem; width: fit-content; max-width: 100%; }
.mfa-qr svg { display: block; max-width: 100%; height: auto; }
