*,
:after,
:before {
  border: 0 solid var(--hairline);
  box-sizing: border-box;
}
:host,
html {
  -webkit-text-size-adjust: 100%;
  font-feature-settings: normal;
  -webkit-tap-highlight-color: transparent;
  font-family:
    ui-sans-serif,
    system-ui,
    sans-serif,
    Apple Color Emoji,
    Segoe UI Emoji,
    Segoe UI Symbol,
    Noto Color Emoji;
  font-variation-settings: normal;
  line-height: 1.5;
  -moz-tab-size: 4;
  -o-tab-size: 4;
  tab-size: 4;
}
body {
  line-height: inherit;
  margin: 0;
}
hr {
  border-top-width: 1px;
  color: inherit;
  height: 0;
}
abbr:where([title]) {
  -webkit-text-decoration: underline dotted;
  text-decoration: underline dotted;
}
h1,
h2,
h3,
h4,
h5,
h6 {
  font-size: inherit;
  font-weight: inherit;
}
a {
  color: inherit;
  text-decoration: inherit;
}
b,
strong {
  font-weight: bolder;
}
code,
kbd,
pre,
samp {
  font-feature-settings: normal;
  font-family:
    JetBrains Mono,
    Courier New,
    monospace;
  font-size: 1em;
  font-variation-settings: normal;
}
small {
  font-size: 80%;
}
sub,
sup {
  font-size: 75%;
  line-height: 0;
  position: relative;
  vertical-align: baseline;
}
sub {
  bottom: -0.25em;
}
sup {
  top: -0.5em;
}
table {
  border-collapse: collapse;
  border-color: inherit;
  text-indent: 0;
}
button,
input,
optgroup,
select,
textarea {
  font-feature-settings: inherit;
  color: inherit;
  font-family: inherit;
  font-size: 100%;
  font-variation-settings: inherit;
  font-weight: inherit;
  letter-spacing: inherit;
  line-height: inherit;
  margin: 0;
  padding: 0;
}
button,
select {
  text-transform: none;
}
button,
input:where([type="button"]),
input:where([type="reset"]),
input:where([type="submit"]) {
  -webkit-appearance: button;
  background-color: transparent;
  background-image: none;
}
:-moz-focusring {
  outline: auto;
}
:-moz-ui-invalid {
  box-shadow: none;
}
progress {
  vertical-align: baseline;
}
::-webkit-inner-spin-button,
::-webkit-outer-spin-button {
  height: auto;
}
[type="search"] {
  -webkit-appearance: textfield;
  outline-offset: -2px;
}
::-webkit-search-decoration {
  -webkit-appearance: none;
}
::-webkit-file-upload-button {
  -webkit-appearance: button;
  font: inherit;
}
summary {
  display: list-item;
}
blockquote,
dd,
dl,
figure,
h1,
h2,
h3,
h4,
h5,
h6,
hr,
p,
pre {
  margin: 0;
}
fieldset {
  margin: 0;
}
fieldset,
legend {
  padding: 0;
}
menu,
ol,
ul {
  list-style: none;
  margin: 0;
  padding: 0;
}
dialog {
  padding: 0;
}
textarea {
  resize: vertical;
}
input::-moz-placeholder,
textarea::-moz-placeholder {
  color: var(--muted);
  opacity: 1;
}
input::placeholder,
textarea::placeholder {
  color: var(--muted);
  opacity: 1;
}
[role="button"],
button {
  cursor: pointer;
}
:disabled {
  cursor: default;
}
audio,
canvas,
embed,
iframe,
img,
object,
svg,
video {
  display: block;
  vertical-align: middle;
}
img,
video {
  height: auto;
  max-width: 100%;
}
[hidden]:where(:not([hidden="until-found"])) {
  display: none;
}
:root,
[data-theme="light"] {
  --brand-primary: #0c7253;
  --canvas: #fff;
  --surface-card: #f6f6f5;
  --surface-dark: #0a0a0b;
  --ink: #0a0a0b;
  --body-text: #3d3d40;
  --muted: #6a6a6e;
  --accent: var(--brand-accent, var(--brand-primary));
  --accent-subtle: var(--brand-accent-weak,color-mix(in srgb,var(--brand-primary) 12%,#fff));
  --cta-bg: var(--accent);
  --cta-bg-hover: var(--brand-accent-strong,color-mix(in srgb,var(--accent) 85%,#000));
  --cta-text: var(--brand-on, #fff);
  --hairline: #e6e6e4;
  --border-strong: #d8d8d6;
  --danger: #bf3529;
  --danger-subtle: #f8e7e4;
  --danger-hover: #a82e23;
  --warning: #8a5a12;
  --warning-subtle: #f6ecd9;
  --success: #0c7253;
  --success-subtle: #e5f3ee;
  --info: #2f57e6;
  --info-subtle: #eaeefc;
  --bg-code: #f6f6f5;
  --on-dark: #fafafa;
  --muted-on-dark: #a1a1aa;
  --font-display: "Sora",system-ui,sans-serif;
  --font-body: "Sora",system-ui,sans-serif;
  --font-mono: "JetBrains Mono","Courier New",monospace;
  --radius-btn: 8px;
  --radius-card: 8px;
  --radius-hero: 12px;
  --radius-pill: 9999px;
  --radius-input: 6px;
  --radius-sm: 6px;
  --space-1: 4px;
  --space-2: 8px;
  --space-3: 12px;
  --space-4: 16px;
  --space-5: 20px;
  --space-6: 24px;
  --space-8: 32px;
  --space-10: 40px;
  --space-12: 48px;
  --space-16: 64px;
  --space-20: 80px;
  --space-24: 96px;
  --text-badge: 0.6875rem;
  --text-hint: 0.75rem;
  --text-label: 0.8125rem;
  --text-body-sm: 0.875rem;
  --text-body: 1rem;
  /* The website's frame (openwhistle/website tokens.css --max-width) and its gutter. */
  --frame: 1200px;
  --gutter: 2rem;
  --duration-fast: 140ms;
  --duration-mid: 280ms;
}
/* The admin pages hold eight-column tables: their frame is wider, and the nav and
   footer follow it, so the edges still line up. */
:root:has(.admin-shell) { --frame: 1440px; }
/* A short admin page without a scroll bar no longer shifts the menu sideways. Admin pages
   only: on a phone the reserved gutter narrowed the reporter's case number into two lines. */
@media (min-width: 901px) {
  html:has(.admin-shell) { scrollbar-gutter: stable; }
}
@media (max-width: 540px) {
  :root { --gutter: 1rem; }
}
[data-theme="light"] { color-scheme: only light; }
[data-theme="dark"] { color-scheme: dark; }
[data-theme="dark"] {
  --canvas: #08080a;
  --surface-card: #131315;
  --surface-dark: #050506;
  --ink: #fafafa;
  --body-text: #bcbcc0;
  --muted: #8e8e93;
  --accent: var(--brand-accent-dark,color-mix(in srgb,var(--brand-primary) 72%,#fff));
  --accent-subtle: var(--brand-accent-weak-dark,color-mix(in srgb,var(--brand-primary) 24%,#08080a));
  --cta-bg: var(--accent);
  --cta-bg-hover: var(--brand-accent-strong-dark,color-mix(in srgb,var(--accent) 88%,#fff));
  --cta-text: var(--brand-on-dark, #06120d);
  --hairline: #262629;
  --border-strong: #34343a;
  --danger: #f0776b;
  --danger-subtle: #2a1512;
  --danger-hover: #e0604f;
  --warning: #d6a13c;
  --warning-subtle: #241c0d;
  --success: #23c088;
  --success-subtle: #0d211a;
  --info: #6d8dff;
  --info-subtle: #171b2e;
  --bg-code: #131315;
  --on-dark: #fafafa;
  --muted-on-dark: #a1a1aa;
}
*,
:after,
:before {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}
html {
  font-size: 16px;
  scroll-behavior: smooth;
}
body {
  background-color: var(--canvas);
  color: var(--body-text);
  display: flex;
  flex-direction: column;
  font-family: var(--font-body);
  line-height: 1.6;
  min-height: 100vh;
  transition-duration: 0.25s;
  transition-property: color, background-color, border-color, box-shadow, text-decoration-color, fill, stroke;
  transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
}
[data-theme="dark"] body {
  background-image: none;
}
main {
  flex: 1 1 0%;
}
h1,
h2,
h3 {
  text-wrap: balance;
}
code,
table,
.mono,
.token,
.credential-display,
.stat-card__number,
.stat-card__value,
.guarantee-num,
.session-expiry-countdown {
  font-variant-numeric: tabular-nums;
}
h1 {
  color: var(--ink);
  font-family: var(--font-display);
  font-size: clamp(1.75rem, 4vw, 2.25rem);
  font-weight: 600;
  letter-spacing: -0.04em;
  line-height: 1.25;
}
h2 {
  font-size: 1.375rem;
  letter-spacing: -0.015em;
  line-height: 1.375;
}
h2,
h3 {
  color: var(--ink);
  font-family: var(--font-display);
  font-weight: 600;
}
h3 {
  font-size: 1.125rem;
  letter-spacing: -0.01em;
  line-height: 1.75rem;
  line-height: 1.375;
}
h4 {
  color: var(--ink);
  font-family: var(--font-display);
  font-size: 0.875rem;
  font-weight: 600;
  line-height: 1.25rem;
}
h1 em,
h2 em,
h3 em {
  font-style: italic;
}
p {
  color: var(--body-text);
  line-height: 1.625;
  margin-bottom: 1rem;
}
p:last-child {
  margin-bottom: 0;
}
a {
  color: var(--accent);
  text-decoration-line: none;
}
a:hover {
  text-decoration-line: underline;
}
/* A link inside running text must not rely on colour alone (WCAG 1.4.1). */
p a:not(.btn) {
  text-decoration-line: underline;
  text-underline-offset: 0.15em;
}
a:focus-visible {
  border-radius: 0.125rem;
  outline: 2px solid transparent;
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}
.mono,
code {
  background: var(--surface-card);
  border-radius: var(--radius-sm);
  color: var(--ink);
  font-family: var(--font-mono);
  font-size: 0.875em;
  padding: 0.125rem 0.375rem;
}
strong {
  font-weight: 600;
}
@keyframes fadeSlideIn {
  0% {
    opacity: 0;
    transform: translateY(10px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}
@keyframes shake {
  0%,
  to {
    transform: translateX(0);
  }
  15% {
    transform: translateX(-6px);
  }
  30% {
    transform: translateX(6px);
  }
  45% {
    transform: translateX(-5px);
  }
  60% {
    transform: translateX(5px);
  }
  75% {
    transform: translateX(-3px);
  }
  90% {
    transform: translateX(3px);
  }
}
@keyframes slideInBanner {
  0% {
    opacity: 0;
    transform: translateX(120%);
  }
  to {
    opacity: 1;
    transform: translateX(0);
  }
}
.shake {
  animation: shake 0.45s ease both;
}
.card:nth-child(2),
.panel:nth-child(2) {
  animation-delay: 0.05s;
}
.card:nth-child(3),
.panel:nth-child(3) {
  animation-delay: 0.1s;
}
.card:nth-child(4),
.panel:nth-child(4) {
  animation-delay: 0.15s;
}
.container {
  width: 100%;
}
/* ── Navigation: the website's (openwhistle/website base.css) ─────────────
   The nav, the page and the footer share one frame: content at most
   --frame wide, a --gutter inside it, so their edges line up. */
.nav {
  align-items: center;
  background: var(--canvas);
  box-shadow: 0 1px 3px color-mix(in srgb, var(--surface-dark) 8%, transparent);
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2) var(--space-6);
  justify-content: space-between;
  min-height: 60px;
  padding: 0 max(var(--gutter), calc((100% - var(--frame)) / 2 + var(--gutter)));
  position: sticky;
  top: 0;
  z-index: 100;
}
.nav-brand {
  align-items: center;
  color: var(--ink);
  display: flex;
  font-family: var(--font-display);
  font-size: 0.9rem;
  font-weight: 600;
  gap: var(--space-3);
  letter-spacing: 0.04em;
}
.nav-brand:hover {
  text-decoration-line: none;
}
/* K3 takes the wordmark's colour. */
.mark {
  fill: currentColor;
  flex: none;
}
/* An operator logo of any shape stays inside the nav: 4000 × 50 px must not
   widen a 390 px page. The dark variant replaces the light one in the dark theme. */
.nav-logo-img {
  height: 2rem;
  max-width: min(12rem, 40vw);
  object-fit: contain;
  width: auto;
}
/* Two rules, no :has(): a browser without it drops a rule naming it, and both
   logos showed in the light theme. */
.nav-logo-dark {
  display: none;
}
[data-theme="dark"] .nav-logo-light.has-dark {
  display: none;
}
[data-theme="dark"] .nav-logo-dark {
  display: inline-block;
}
.nav-links {
  align-items: center;
  display: flex;
  gap: var(--space-6);
}
.nav-links a {
  color: var(--muted);
  font-size: 0.8rem;
  letter-spacing: 0.02em;
  transition: color var(--duration-fast) ease;
  white-space: nowrap;
}
.nav-links a:hover {
  color: var(--ink);
  text-decoration-line: none;
}
.nav-links a.active {
  color: var(--accent);
}
.nav-tools {
  align-items: center;
  display: flex;
  gap: var(--space-3);
}
/* Theme and language: equal-height controls with a hairline-strong ring (DESIGN.md "Navigation"). */
.theme-toggle,
.lang-picker-btn {
  align-items: center;
  border-radius: var(--radius-btn);
  box-shadow: 0 0 0 1px var(--border-strong);
  color: var(--muted);
  display: flex;
  min-height: 44px;
  justify-content: center;
  transition: color var(--duration-fast) ease, box-shadow var(--duration-fast) ease;
}
.theme-toggle {
  min-width: 44px;
}
.theme-toggle:hover,
.lang-picker-btn:hover {
  box-shadow: 0 0 0 1px var(--muted);
  color: var(--ink);
}
.theme-toggle svg {
  height: 16px;
  width: 16px;
}
[data-theme="dark"] .theme-icon-moon,
:root:not([data-theme="dark"]) .theme-icon-sun {
  display: none;
}
.lang-picker {
  display: inline-block;
  position: relative;
}
.lang-picker-btn {
  cursor: pointer;
  font-size: 0.75rem;
  font-weight: 600;
  gap: var(--space-1);
  letter-spacing: 0.04em;
  list-style: none;
  padding: 0 var(--space-3);
}
.lang-picker-btn::-webkit-details-marker {
  display: none;
}
.lang-picker-btn:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}
.lang-picker-menu {
  background: var(--canvas);
  border-radius: 0.5rem;
  box-shadow: 0 0 0 1px var(--hairline), 0 8px 24px rgba(0, 0, 0, 0.12);
  margin: 0;
  min-width: 8rem;
  padding-bottom: 0.25rem;
  padding-top: 0.25rem;
  position: absolute;
  right: 0;
  top: calc(100% + 0.25rem);
  width: max-content;
  z-index: 200;
}
[data-theme="dark"] .lang-picker-menu {
  background: var(--surface-card);
  box-shadow: 0 0 0 1px var(--hairline), 0 8px 24px rgba(0, 0, 0, 0.55);
}
.lang-picker-option {
  border-radius: 0.25rem;
  color: var(--body-text);
  display: block;
  font-size: 0.875rem;
  line-height: 1.25rem;
  padding: 0.45rem 1rem;
  text-align: left;
  transition: color var(--duration-fast) ease, background-color var(--duration-fast) ease;
  white-space: nowrap;
  width: 100%;
}
.lang-picker-option:focus-visible,
.lang-picker-option:hover {
  background: var(--surface-card);
  color: var(--ink);
  outline: 2px solid transparent;
  outline-offset: 2px;
}
.lang-picker-option.active {
  color: var(--accent);
  font-weight: 600;
}
.container {
  max-width: var(--frame);
}
.container,
.container-sm {
  margin-left: auto;
  margin-right: auto;
  padding-left: var(--gutter);
  padding-right: var(--gutter);
}
.container-sm {
  max-width: 540px;
}
.page-header {
  padding-bottom: 2rem;
  padding-top: 3rem;
}
.page-header h1 {
  margin-bottom: 0.5rem;
}
.card,
.panel {
  background: var(--surface-card);
  border: none;
  border-radius: var(--radius-card);
  padding: 1.75rem;
  transition: box-shadow 0.15s;
}
[data-theme="dark"] .card,
[data-theme="dark"] .panel {
  box-shadow: 0 0 0 1px var(--hairline);
}
.card + .card,
.panel + .panel,
.panel + .demo-credentials {
  margin-top: 1.25rem;
}
.panel-outline {
  background: var(--canvas);
  border-radius: var(--radius-card);
  padding: 1.5rem;
  box-shadow: 0 0 0 1px var(--hairline);
}
.card-title,
.panel-header {
  align-items: center;
  border-bottom-width: 1px;
  border-color: var(--hairline);
  display: flex;
  gap: 0.75rem;
  margin-bottom: 1.25rem;
  padding-bottom: 0.75rem;
}
.card-title,
.detail-label {
  color: var(--muted);
  font-family: var(--font-body);
  font-size: 0.75rem;
  font-weight: 600;
  line-height: 1rem;
}
.detail-row {
  align-items: baseline;
  display: flex;
  gap: 0.5rem;
  margin-bottom: 0.75rem;
}
/* Beside its value, not above it: the label's own bottom margin lifted it
   off the value's baseline. */
.detail-row .detail-label {
  margin-bottom: 0;
}
.panel-header,
.panel-header-title {
  color: var(--ink);
  font-family: var(--font-body);
  font-size: var(--text-body);
  font-weight: 600;
  letter-spacing: normal;
  line-height: 1rem;
}
.panel-header-title {
  margin: 0;
}
/* The main content of a page: an ink stripe, not the accent — the accent
   budget belongs to the view's one primary action. */
.panel-primary {
  box-shadow: inset 0 3px 0 var(--ink);
}
/* Dark panels draw a hairline ring (specificity 0,2,0), so the stripe is composed with it. */
[data-theme="dark"] .panel-primary {
  box-shadow: inset 0 3px 0 var(--ink), 0 0 0 1px var(--hairline);
}
/* Case page: facts without panel chrome, actions as sections of one panel. */
.report-facts {
  display: grid;
  gap: var(--space-3);
  margin: 0 0 var(--space-6);
  padding: 0;
}
.report-facts > div {
  border-bottom: 1px solid var(--hairline);
  padding-bottom: var(--space-3);
}
.action-section + .action-section {
  border-top: 1px solid var(--hairline);
  margin-top: var(--space-5);
  padding-top: var(--space-5);
}
.action-title {
  font-size: var(--text-body-sm);
  font-weight: 600;
  margin: 0 0 var(--space-3);
}
.danger-zone {
  border-top: 1px solid var(--hairline);
  margin-top: var(--space-5);
  padding-top: var(--space-4);
}
.danger-zone > summary {
  color: var(--danger);
  cursor: pointer;
  font-weight: 600;
  min-height: 44px;
}
.detail-label {
  font-size: var(--text-hint);
  font-weight: 600;
  margin-bottom: 0.375rem;
}
.stat-card {
  background: var(--surface-card);
  border-radius: var(--radius-card);
  min-width: 0;
  padding: 1.5rem;
  text-align: center;
  transition-duration: 0.15s;
  transition-property: box-shadow;
  transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
}
/* A status badge is the sole label of a KPI card here, unlike a badge next
   to table text: let it wrap instead of forcing the card, and the page,
   wider than its grid track. German status labels are the long ones. */
.stat-card .badge {
  white-space: normal;
}
.stat-card:hover {
  box-shadow: 0 4px 14px rgba(0, 0, 0, 0.08);
}
.stat-card__number {
  color: var(--ink);
  font-family: var(--font-display);
  font-size: 2.25rem;
  font-weight: 700;
  letter-spacing: -0.04em;
  line-height: 1;
  margin-bottom: 0.5rem;
}
.\!btn,
.btn {
  align-items: center;
  border-radius: 8px;
  cursor: pointer;
  display: inline-flex;
  font-size: 0.875rem;
  font-weight: 600;
  gap: 0.375rem;
  height: 2.5rem;
  justify-content: center;
  line-height: 1.25rem;
  line-height: 1;
  padding-left: 1.25rem;
  padding-right: 1.25rem;
  text-decoration-line: none;
  transition-duration: 0.15s;
  transition-property: color, background-color, box-shadow, text-decoration-color, fill, stroke;
  transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
  white-space: nowrap;
}
.\!btn {
  font-family: var(--font-body) !important;
}
.btn {
  font-family: var(--font-body);
}
.btn-primary:active {
  opacity: 0.9;
}
.btn-primary {
  background: var(--cta-bg);
  color: var(--cta-text);
}
.btn-primary:hover {
  background: var(--cta-bg-hover);
  color: var(--cta-text);
  text-decoration-line: none;
}
.btn-secondary {
  background: var(--canvas);
  color: var(--body-text);
  box-shadow: 0 0 0 1px var(--hairline);
}
.btn-secondary:hover {
  background: var(--surface-card);
  color: var(--ink);
  text-decoration-line: none;
  box-shadow: 0 0 0 1px var(--border-strong);
}
.btn-ghost {
  background: transparent;
  color: var(--muted);
}
.btn-ghost:hover {
  background: var(--surface-card);
  color: var(--body-text);
  text-decoration-line: none;
}
.btn-danger {
  background: var(--danger);
}
.btn-danger,
.btn-danger:hover {
  color: var(--canvas);
}
.btn-danger:hover {
  background: var(--danger-hover);
  text-decoration-line: none;
}
.btn-block {
  width: 100%;
}
.btn-sm {
  border-radius: 0.375rem;
  font-size: 0.8125rem;
  height: 2rem;
  padding-left: 0.75rem;
  padding-right: 0.75rem;
}
.\!btn:disabled,
.btn:disabled {
  cursor: not-allowed;
  opacity: 0.4;
}
.form-group {
  margin-bottom: 1.25rem;
}
.form-label {
  color: var(--ink);
  display: block;
  font-size: 0.875rem;
  font-weight: 600;
  line-height: 1.25rem;
  margin-bottom: 0.375rem;
}
.form-hint,
.form-label {
  font-family: var(--font-body);
}
.form-hint {
  color: var(--muted);
  font-size: 0.8125rem;
  margin-top: 0.375rem;
}
.form-control {
  -webkit-appearance: none;
  -moz-appearance: none;
  appearance: none;
  background: var(--canvas);
  border-color: var(--hairline);
  border-radius: var(--radius-input);
  border-width: 1px;
  color: var(--ink);
  font-family: var(--font-body);
  font-size: 0.875rem;
  height: 2.5rem;
  line-height: 1.25rem;
  outline: 2px solid transparent;
  outline-offset: 2px;
  padding-left: 0.875rem;
  padding-right: 0.875rem;
  transition-duration: 0.15s;
  transition-property: color, background-color, border-color, box-shadow, text-decoration-color, fill, stroke;
  transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
  width: 100%;
}
.form-control:hover {
  border-color: var(--border-strong);
}
.form-control:focus {
  border-color: var(--ink);
  box-shadow: 0 0 0 3px var(--accent-subtle);
}
textarea.form-control {
  height: auto;
  line-height: 1.625;
  min-height: 160px;
  padding-bottom: 0.625rem;
  padding-top: 0.625rem;
  resize: vertical;
}
select.form-control {
  background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6'%3E%3Cpath d='m1 1 4 4 4-4' stroke='%236b7280' stroke-width='1.5' fill='none' stroke-linecap='round'/%3E%3C/svg%3E");
  background-position: right 0.875rem center;
  background-repeat: no-repeat;
  cursor: pointer;
  padding-right: 2.25rem;
}
[data-theme="dark"] select.form-control {
  background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6'%3E%3Cpath d='m1 1 4 4 4-4' stroke='%238e8e93' stroke-width='1.5' fill='none' stroke-linecap='round'/%3E%3C/svg%3E");
}
.form-control.mono {
  font-family: var(--font-mono);
  font-size: 0.875rem;
  letter-spacing: 0.03em;
  line-height: 1.25rem;
}
input[type="file"].form-control {
  cursor: pointer;
  height: auto;
  min-height: 40px;
  padding: 0.5rem 0.75rem;
}
input[type="file"].form-control::file-selector-button {
  background: var(--cta-bg);
  border-radius: 0.375rem;
  border-style: none;
  color: var(--cta-text);
  cursor: pointer;
  font-family: var(--font-body);
  font-size: 0.8125rem;
  font-weight: 600;
  margin-right: 0.75rem;
  padding: 0.375rem 0.75rem;
}
[data-theme="dark"] .form-control {
  background-color: var(--surface-card);
  border-color: var(--hairline);
  color: var(--ink);
}
[data-theme="dark"] .form-control:focus {
  border-color: var(--accent);
}
.badge {
  align-items: center;
  border-radius: var(--radius-sm);
  display: inline-flex;
  font-family: var(--font-body);
  font-size: 0.8125rem;
  font-weight: 600;
  line-height: 1;
  padding: 0.25rem 0.625rem;
  white-space: nowrap;
}
/* One neutral pill for every status; only the dot carries a colour. Four tinted
   pills put blue, amber and green next to each other on one screen. */
.badge-received,
.badge-in_review,
.badge-pending_feedback,
.badge-closed {
  background: var(--surface-card);
  box-shadow: 0 0 0 1px var(--hairline);
  color: var(--body-text);
}
/* A status pill leads with a dot in its own colour (DESIGN.md "Status pills"). */
.badge-received::before,
.badge-in_review::before,
.badge-pending_feedback::before,
.badge-closed::before {
  background: var(--muted);
  border-radius: 50%;
  content: "";
  flex: none;
  height: 6px;
  margin-right: 6px;
  width: 6px;
}
.badge-in_review::before { background: var(--ink); }
.badge-pending_feedback::before { background: var(--warning); }
.badge-closed::before { background: var(--success); }
/* A role or a category is not a state: one neutral pill without the dot, the label says
   which (DESIGN.md "Status pills" reserves the dot and its colour for the report status). */
.badge-admin,
.badge-case_manager,
.badge-superadmin,
.badge-neutral {
  background: var(--surface-card);
  box-shadow: 0 0 0 1px var(--hairline);
  color: var(--body-text);
}
.badge-action {
  background: var(--accent-subtle);
  border-radius: var(--radius-sm);
  color: var(--accent);
  display: inline-block;
  font-family: var(--font-mono);
  font-size: 0.75rem;
  letter-spacing: 0.01em;
  line-height: 1rem;
  padding: 0.125rem 0.5rem;
}
/* One banner system (DESIGN.md "Alerts / banners"), drawn as the website's callout
   (openwhistle/website base.css): a 3 px bar in the semantic colour on its -weak tint,
   rounded only away from the bar, the title in sentence case. */
.alert {
  animation: fadeSlideIn 0.3s ease both;
  border-left: 3px solid;
  border-radius: 0 var(--radius-card) var(--radius-card) 0;
  color: var(--body-text);
  font-size: 0.875rem;
  line-height: 1.625;
  margin-bottom: 1rem;
  padding: var(--space-4) var(--space-6);
}
.alert-title {
  font-size: 0.9375rem;
  font-weight: 600;
  line-height: 1.4;
  margin-bottom: var(--space-1);
}
.alert-error {
  background: var(--danger-subtle);
  border-color: var(--danger);
}
.alert-success {
  background: var(--success-subtle);
  border-color: var(--success);
}
.alert-warning {
  background: var(--warning-subtle);
  border-color: var(--warning);
}
/* Information is neutral; amber and red stay for what needs the reader to act. */
.alert-info {
  background: var(--surface-card);
  border-color: var(--border-strong);
}
.alert-error .alert-title { color: var(--danger); }
.alert-success .alert-title { color: var(--success); }
.alert-warning .alert-title { color: var(--warning); }
.alert-info .alert-title { color: var(--ink); }
.telemetry-ask-actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
  margin-top: var(--space-3);
}
.dashboard-panel-header {
  justify-content: space-between;
}
.dashboard-panel-header,
.dashboard-toolbar {
  gap: 0.75rem;
}
.dashboard-panel-header,
.dashboard-toolbar,
.filter-pills {
  align-items: center;
  display: flex;
  flex-wrap: wrap;
}
/* A chip track: chips nest concentric inside it (8 px - 2 px = 6 px). */
.filter-pills {
  background: var(--canvas);
  border-radius: var(--radius-btn);
  box-shadow: 0 0 0 1px var(--hairline);
  gap: 0.25rem;
  padding: 2px;
}
.filter-pill {
  border-radius: var(--radius-sm);
  border-style: none;
  color: var(--muted);
  display: inline-block;
  font-family: var(--font-body);
  font-size: 0.8125rem;
  font-weight: 500;
  padding: 0.25rem 0.75rem;
  transition: color var(--duration-fast) ease, background-color var(--duration-fast) ease;
  white-space: nowrap;
}
.filter-pill,
.filter-pill:hover {
  text-decoration-line: none;
}
.filter-pill:hover {
  color: var(--ink);
}
/* The selected chip (DESIGN.md "Choice chips"). */
.filter-pill-active,
.filter-pill-active:hover {
  background: var(--accent-subtle);
  color: var(--accent);
  font-weight: 600;
}
.filter-pill-count {
  color: var(--muted);
  font-family: var(--font-mono);
  margin-left: var(--space-1);
}
.filter-pill-active .filter-pill-count {
  color: inherit;
}
.per-page-wrap {
  align-items: center;
  display: flex;
  gap: 0.375rem;
}
.per-page-label {
  color: var(--muted);
  font-size: 0.75rem;
  line-height: 1rem;
  white-space: nowrap;
}
.per-page-select {
  background: var(--canvas);
  border-color: var(--hairline);
  border-radius: 0.375rem;
  border-width: 1px;
  color: var(--ink);
  cursor: pointer;
  font-family: var(--font-body);
  font-size: 0.8rem;
  padding: 0.25rem 0.5rem;
}
.per-page-select:focus {
  outline: 2px solid var(--accent);
  outline-offset: 1px;
}
.table-meta {
  border-bottom-width: 1px;
  border-color: var(--hairline);
  color: var(--muted);
  font-size: 0.78rem;
  padding: 0.5rem 1rem;
}
.sort-link {
  align-items: center;
  color: inherit;
  display: inline-flex;
  gap: 0.25rem;
  white-space: nowrap;
}
.sort-link,
.sort-link:hover {
  text-decoration-line: none;
}
.sort-link:hover {
  color: var(--accent);
}
.sort-indicator {
  font-size: 0.65rem;
  opacity: 0.35;
  transition-duration: 0.12s;
  transition-property: opacity;
  transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
}
.sort-link:hover .sort-indicator {
  opacity: 0.75;
}
.sort-active {
  color: var(--accent);
  opacity: 1;
}
.table-wrapper {
  overflow-x: auto;
}
/* A URL in a table cell may break anywhere: unbroken, the organisations list's
   reporting links pushed the row's actions out of view at 1920 px. */
.link-wrap {
  overflow-wrap: anywhere;
}
/* The telemetry request line is one unbroken URL; at phone width it would
   widen the whole page. Wrap it instead, anywhere. */
pre {
  white-space: pre-wrap;
  overflow-wrap: anywhere;
  /* DESIGN.md: a code block is an inverse fill in both themes. */
  background: var(--surface-dark);
  border-radius: var(--radius-sm);
  color: var(--on-dark);
  padding: 0.75rem 1rem;
}
/* An inline code chip inside a block: its background matched the card and its
   padding indented only the first line. */
pre code {
  background: none;
  color: inherit;
  padding: 0;
}
/* The long-form admin pages (system, retention, telephone channel) write plain
   headings, paragraphs and lists inside a .card, and the reset strips their
   spacing and the numbers of an ordered list. */
.card > * + * {
  margin-top: 0.75rem;
}
.card ol {
  list-style: decimal;
  padding-left: 1.25rem;
}
.card li + li {
  margin-top: 0.375rem;
}
/* A long unbreakable value (a German status badge — "Rückmeldung ausstehend" —
   is wider than its English equivalent and forces a nowrap badge) can widen
   the table past .table-wrapper's scrollable viewport. The wrapper already
   handles that overflow, but its default scroll position hides whatever sits
   in the last column — the row's own "view" action — behind the fold with no
   visual hint to scroll. Pin that column so the action stays reachable
   regardless of how wide any other column's content gets.
   Scoped by an explicit class on both the header and the data cell, not
   `th:last-child` — not every .table-stack table's last column is an action
   column (admin/audit_log.html's is "Detail", real content), and a positional
   selector would pin that header while its own data cells scroll normally
   underneath it, desyncing the two. */
.table-stack td.stack-action,
.table-stack th.stack-action-header {
  position: sticky;
  right: 0;
  background: var(--surface-card);
}
.table-stack td.stack-action {
  border-left: 1px solid var(--hairline);
}
/* Let a status badge wrap onto two lines instead of forcing the table wider
   still — the badge shape survives wrapping fine, unlike breaking mid-word. */
.table-stack .stack-status .badge {
  white-space: normal;
}
table {
  border-collapse: collapse;
  font-size: 0.875rem;
  line-height: 1.25rem;
  width: 100%;
}
th {
  border-bottom-width: 2px;
  border-color: var(--hairline);
  color: var(--muted);
  font-size: 0.78rem;
  font-weight: 600;
  line-height: 1rem;
  /* 0.75rem a side, not 1rem: eight dashboard columns in German need 1,093 px
     at 1rem and the admin content is 1,064 px wide. */
  padding: 0.625rem 0.75rem;
  text-align: left;
}
td {
  border-bottom-width: 1px;
  border-color: var(--hairline);
  color: var(--body-text);
  padding: 0.75rem;
  vertical-align: middle;
}
tr:last-child td {
  border-bottom-width: 0;
}
tr:hover td {
  background: var(--surface-card);
}
.pagination-bar {
  align-items: center;
  border-color: var(--hairline);
  border-top-width: 1px;
  display: flex;
  flex-wrap: wrap;
  gap: 0.75rem;
  justify-content: space-between;
  padding: 0.875rem 1rem;
}
.pagination-info {
  color: var(--muted);
  font-size: 0.78rem;
}
.pagination-controls {
  align-items: center;
  display: flex;
  flex-wrap: wrap;
  gap: 0.25rem;
}
.pagination-btn {
  font-size: 0.78rem;
  height: 2rem;
  min-width: unset;
  padding-left: 0.75rem;
  padding-right: 0.75rem;
}
.pagination-disabled {
  /* Muted colour, not opacity: 38 % opacity fell below the 4.5:1 contrast
     axe asks of text, which showed once the dashboard had a second page. */
  background: transparent;
  box-shadow: none;
  color: var(--muted);
  cursor: default;
  outline: 1px dashed var(--hairline);
  outline-offset: -1px;
  pointer-events: none;
}
.pagination-page {
  align-items: center;
  border-radius: 0.375rem;
  box-shadow: 0 0 0 1px var(--hairline);
  color: var(--body-text);
  display: inline-flex;
  font-family: var(--font-body);
  font-size: 0.8rem;
  font-weight: 600;
  height: 2rem;
  justify-content: center;
  min-width: 2rem;
  padding-left: 0.375rem;
  padding-right: 0.375rem;
  transition-duration: 0.12s;
  transition-property: color, background-color, box-shadow, text-decoration-color, fill, stroke;
  transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
}
.pagination-page,
.pagination-page:hover {
  text-decoration-line: none;
}
.pagination-page:hover {
  background: var(--surface-card);
  box-shadow: 0 0 0 1px var(--border-strong);
  color: var(--ink);
}
.pagination-page-current {
  background: var(--cta-bg);
  box-shadow: 0 0 0 1px var(--cta-bg);
  color: var(--cta-text);
  cursor: default;
  pointer-events: none;
}
.pagination-ellipsis {
  color: var(--muted);
  font-size: 0.8rem;
  padding-left: 0.125rem;
  padding-right: 0.125rem;
  -webkit-user-select: none;
  -moz-user-select: none;
  user-select: none;
}
/* A page that fills the space between the nav and the footer (the wizard,
   the login and MFA screens) is marked .page-fill. Each used to take
   a min-height of the viewport minus a guess at nav plus footer: 144 px for the
   wizard, 112 px for the login screens, against a real 151 px, plus the
   36 px demo banner. Every one of those pages scrolled, with the footer
   below the fold. main already flexes to the leftover height; a .page-fill
   child follows it, whatever the chrome above and below measures. */
main:has(> .page-fill) {
  display: flex;
  flex-direction: column;
}
.page-fill {
  flex: 1 1 auto;
}
/* The promises block and the form share the header's frame. The block used to
   be a full-height dark column pinned to the window's left edge, which left
   two thirds of an ultra-wide screen empty beside the form. */
.split-layout {
  align-items: start;
  display: grid;
  gap: var(--space-10);
  grid-template-columns: 22rem minmax(0, 1fr);
  margin: 0 auto;
  max-width: var(--frame);
  padding: var(--space-6) var(--gutter);
  width: 100%;
}
/* DESIGN.md's signature: the one place the accent is used generously. */
.split-sidebar {
  background: var(--surface-card);
  border-radius: var(--radius-card);
  box-shadow: 0 0 0 1px var(--hairline);
  color: var(--body-text);
  grid-column: 1;
  /* The markup puts the form first (phones read it first); pin both to row 1 or
     auto-placement drops the sidebar into a second row under the form. */
  grid-row: 1;
  padding: var(--space-6) var(--space-8);
  position: sticky;
  top: var(--space-6);
}
.split-main {
  grid-column: 2;
  grid-row: 1;
  max-width: 760px;
}
.sidebar-title {
  color: var(--ink);
  font-family: var(--font-display);
  font-size: 1.375rem;
  font-weight: 600;
  letter-spacing: -0.02em;
  line-height: 1.3;
  margin-bottom: var(--space-4);
  text-wrap: balance;
}
.guarantee-list {
  margin-top: 0.5rem;
  position: relative;
}
.guarantee-item {
  border-bottom-width: 1px;
  border-color: var(--hairline);
  display: flex;
  gap: 0.75rem;
  padding-bottom: 0.75rem;
  padding-top: 0.75rem;
}
.guarantee-item:last-child {
  border-bottom-width: 0;
}
.guarantee-num {
  color: var(--muted-on-dark);
  flex-shrink: 0;
  font-family: var(--font-mono);
  font-size: 0.625rem;
  letter-spacing: 0.06em;
  min-width: 2.5rem;
  padding-top: 0.125rem;
}
.guarantee-check {
  color: var(--accent);
  flex: none;
  padding-top: 0.0625rem;
}
.guarantee-check svg {
  height: 1.125rem;
  width: 1.125rem;
}
.guarantee-title {
  color: var(--ink);
  font-size: 0.875rem;
  font-weight: 600;
  line-height: 1.25rem;
  margin-bottom: 0.375rem;
}
.guarantee-desc,
.guarantee-title {
  font-family: var(--font-body);
}
.guarantee-desc {
  color: var(--body-text);
  font-size: 0.8125rem;
  line-height: 1.55;
}
.sidebar-note {
  border-top: 1px solid var(--hairline);
  color: var(--body-text);
  font-family: var(--font-body);
  font-size: 0.8125rem;
  line-height: 1.55;
  padding-top: var(--space-4);
}
.sidebar-note + .sidebar-note {
  border-top: 0;
  padding-top: var(--space-2);
}
.sidebar-note a {
  color: var(--accent);
  text-decoration: underline;
}
/* Labels wrap and steps shrink: German's long labels used to run into one
   another and the last was cut, since nowrap labels squeezed the lines to
   nothing and overflow: hidden clipped the rest. Lines align on the dots'
   centre, so a two-line label does not move them. */
.stepper {
  align-items: flex-start;
  display: flex;
  gap: 0.25rem;
  margin-bottom: 1.5rem;
  margin-top: 1rem;
  overflow: hidden;
}
.stepper-step {
  flex: 0 1 auto;
  flex-direction: column;
  gap: 0.375rem;
  min-width: 0;
}
.stepper-dot,
.stepper-step {
  align-items: center;
  display: flex;
}
.stepper-dot {
  background: var(--surface-card);
  border-color: var(--hairline);
  border-radius: 9999px;
  border-width: 2px;
  color: var(--muted);
  font-family: var(--font-mono);
  font-size: 0.75rem;
  font-weight: 600;
  height: 2rem;
  justify-content: center;
  line-height: 1rem;
  transition-duration: 0.2s;
  transition-property: background-color, border-color, color;
  transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
  width: 2rem;
}
.stepper-step.active .stepper-dot {
  background: var(--accent);
  border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-subtle);
  color: var(--cta-text);
}
.stepper-step.done .stepper-dot {
  background: var(--accent);
  border-color: var(--accent);
  color: var(--cta-text);
  opacity: 0.65;
}
.stepper-label {
  color: var(--muted);
  font-family: var(--font-body);
  font-size: 0.75rem;
  font-weight: 600;
  hyphens: auto;
  line-height: 1.3;
  max-width: 6.5rem;
  overflow-wrap: anywhere;
  text-align: center;
}
@media (max-width: 480px) {
  .stepper-label {
    font-size: 0.6875rem;
    max-width: 4.75rem;
  }
  .split-main .stepper-label {
    display: none;
  }
}
/* The step labels say it on wider screens; "Step n of 6" stays for screen readers. */
@media (min-width: 481px) {
  .split-main .stepper-text {
    clip: rect(0, 0, 0, 0);
    height: 1px;
    margin: -1px;
    overflow: hidden;
    position: absolute;
    white-space: nowrap;
    width: 1px;
  }
}
.stepper-step.active .stepper-label {
  color: var(--accent);
}
.stepper-line {
  background: var(--hairline);
  flex: 1 1 0%;
  height: 0.125rem;
  margin-top: 0.9375rem;
  min-width: 0.5rem;
  transition-duration: 0.2s;
  transition-property: color, background-color, border-color, box-shadow, text-decoration-color, fill, stroke;
  transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
}
.stepper-line.done {
  background: var(--accent);
  opacity: 0.5;
}
.stepper-text {
  color: var(--muted);
  font-family: var(--font-mono);
  font-size: 0.78rem;
  margin-bottom: 1.25rem;
}
.mode-cards {
  display: grid;
  gap: 1rem;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  margin-bottom: 0.75rem;
  margin-top: 0.75rem;
}
.mode-card {
  background: var(--canvas);
  border-radius: var(--radius-card);
  cursor: pointer;
  display: block;
  padding: 0;
  transition-duration: 0.15s;
  transition-property: color, background-color, border-color, box-shadow, text-decoration-color, fill, stroke;
  transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
  box-shadow: 0 0 0 1px var(--hairline);
}
.mode-card input[type="radio"] {
  height: 0;
  opacity: 0;
  position: absolute;
  width: 0;
}
.mode-card:has(input:checked) {
  background: var(--accent-subtle);
  box-shadow: 0 0 0 1px var(--accent);
}
.mode-card:has(input:focus-visible) {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}
@media (forced-colors: active) {
  .mode-card:has(input:checked) {
    border: 2px solid Highlight;
  }
  .mode-card:has(input:focus-visible) {
    outline-color: Highlight;
  }
  .admin-nav a.active {
    border-left: 3px solid Highlight;
  }
}
.mode-card:hover {
  box-shadow: 0 0 0 1px var(--border-strong);
}
.mode-card-inner {
  padding: 1.25rem;
  text-align: center;
}
.mode-card-icon {
  display: block;
  font-size: 2rem;
  margin-bottom: 0.625rem;
}
.mode-card-svg {
  color: var(--accent);
  height: 28px;
  width: 28px;
}
.mode-card-title {
  color: var(--ink);
  font-family: var(--font-display);
  font-size: 1rem;
  font-weight: 600;
  letter-spacing: -0.01em;
  line-height: 1.5rem;
  margin-bottom: 0.375rem;
}
.mode-card-desc {
  color: var(--muted);
  font-size: 0.8125rem;
  line-height: 1.625;
  margin: 0;
}
.progress-desc {
  background: var(--canvas);
  border-radius: 0.375rem;
  color: var(--body-text);
  font-size: 0.875rem;
  line-height: 1.25rem;
  line-height: 1.625;
  padding: 0.75rem 1rem;
}
.thread {
  display: flex;
  flex-direction: column;
  gap: 1.25rem;
}
.message {
  border-radius: var(--radius-card);
  max-width: 82%;
  padding: 1rem 1.25rem;
  position: relative;
}
/* The office's messages are neutral; the reporter's own keep the accent tint. */
.message-admin {
  align-self: flex-start;
  background: var(--surface-card);
  box-shadow: 0 0 0 1px var(--hairline);
  margin-right: auto;
}
.message-whistleblower {
  align-self: flex-end;
  background: var(--accent-subtle);
  margin-left: auto;
  text-align: left;
}
.message-meta {
  align-items: center;
  color: var(--muted);
  display: flex;
  flex-wrap: wrap;
  font-size: 0.8125rem;
  font-weight: 600;
  gap: 0.25rem 0.5rem;
  margin-bottom: 0.5rem;
}
.message-meta time {
  font-family: var(--font-mono);
  font-weight: 400;
}
/* The sender and its date wrap as whole items, never "·" alone; the date is part of the
   label, not an inline-code chip. */
.message-meta .mono {
  background: none;
  padding: 0;
}
.message-admin .message-meta {
  color: var(--ink);
}
.message-whistleblower .message-meta {
  color: var(--accent);
}
.message-meta-icon {
  align-items: center;
  border-radius: 9999px;
  display: inline-flex;
  flex-shrink: 0;
  font-size: 0.6rem;
  font-weight: 600;
  height: 1.2rem;
  justify-content: center;
  width: 1.2rem;
}
.message-admin .message-meta-icon {
  background: var(--border-strong);
  color: var(--ink);
}
.message-whistleblower .message-meta-icon {
  background: var(--accent);
  color: var(--canvas);
}
.message-content {
  color: var(--body-text);
  font-size: 0.875rem;
  line-height: 1.25rem;
  line-height: 1.65;
  white-space: pre-wrap;
}
.sla-ok {
  color: var(--success);
}
.sla-warning {
  color: var(--warning);
}
.sla-overdue {
  color: var(--danger);
  font-weight: 600;
}
.credential-display {
  align-items: center;
  background: var(--surface-card);
  border-radius: 8px;
  color: var(--ink);
  display: flex;
  font-family: var(--font-mono);
  font-size: clamp(0.82rem, 2vw, 1rem);
  gap: 1rem;
  justify-content: space-between;
  letter-spacing: 0.03em;
  margin-bottom: 0.75rem;
  padding: 1rem 1.25rem;
  box-shadow: 0 0 0 1px var(--hairline);
}
.credential-display > span {
  min-width: 0;
}
.credential-group {
  margin-bottom: 1rem;
}
.credential-label {
  color: var(--muted);
  font-family: var(--font-body);
  font-size: 0.8125rem;
  font-weight: 600;
  line-height: 1.25rem;
  margin-bottom: 0.375rem;
}
.credential-box {
  background: var(--surface-card);
  border-radius: 8px;
  font-family: var(--font-mono);
  margin-bottom: 0.75rem;
  margin-top: 0.75rem;
  padding: 1rem 1.25rem;
  box-shadow: 0 0 0 1px var(--hairline);
}
.copy-btn {
  background-color: transparent;
  border-radius: 0.375rem;
  border-style: none;
  color: var(--muted);
  cursor: pointer;
  flex-shrink: 0;
  font-size: 1rem;
  line-height: 1.5rem;
  padding: 0.25rem;
  transition-duration: 0.15s;
  transition-property: color, background-color, border-color, box-shadow, text-decoration-color, fill, stroke;
  transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
}
.copy-btn:hover {
  color: var(--accent);
}
.attachment-list {
  margin-bottom: 0.5rem;
}
.attachment-items {
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
  list-style-type: none;
  margin-top: 0.5rem;
  padding: 0;
}
.attachment-item {
  align-items: center;
  background: var(--surface-card);
  border-radius: 0.375rem;
  display: flex;
  font-size: 0.875rem;
  gap: 0.625rem;
  line-height: 1.25rem;
  padding: 0.5rem 0.75rem;
  box-shadow: 0 0 0 1px var(--hairline);
}
.attachment-icon {
  flex-shrink: 0;
  font-size: 1rem;
  line-height: 1.5rem;
  opacity: 0.7;
}
.attachment-name {
  color: var(--ink);
  flex: 1 1 0%;
  min-width: 0;
  overflow: hidden;
  text-decoration-line: none;
  text-overflow: ellipsis;
  white-space: nowrap;
}
a.attachment-name:hover {
  color: var(--accent);
  text-decoration-line: underline;
}
.attachment-size {
  color: var(--muted);
  flex-shrink: 0;
  font-family: var(--font-mono);
  font-size: 0.75rem;
  line-height: 1rem;
  white-space: nowrap;
}
.qr-wrapper {
  background: #fff;
  border-radius: var(--radius-card);
  display: flex;
  justify-content: center;
  margin-bottom: 1rem;
  margin-top: 1rem;
  padding: 1.5rem;
  box-shadow: 0 0 0 1px var(--hairline);
}
.qr-wrapper img {
  max-width: 200px;
}
.totp-secret-card {
  align-items: center;
  background: var(--surface-card);
  border-radius: var(--radius-card);
  display: flex;
  gap: 0.75rem;
  margin-top: 0.25rem;
  padding: 0.75rem 1rem;
  box-shadow: 0 0 0 1px var(--hairline);
}
.totp-secret-value {
  color: var(--ink);
  flex: 1 1 0%;
  font-size: 0.875rem;
  letter-spacing: 0.03em;
  line-height: 1.25rem;
  -webkit-user-select: all;
  -moz-user-select: all;
  user-select: all;
  word-break: break-all;
}
.totp-copy-btn {
  flex-shrink: 0;
}
.ip-warning-banner {
  align-items: flex-start;
  animation: fadeSlideIn 0.4s ease both;
  background: var(--danger-subtle);
  border-radius: var(--radius-card);
  display: flex;
  gap: 0.75rem;
  margin-bottom: 1.5rem;
  padding: 1rem 1.25rem;
}
.ip-warning-icon {
  flex-shrink: 0;
  font-size: 1.25rem;
  line-height: 1.75rem;
  margin-top: 0.125rem;
}
.ip-warning-text {
  color: var(--danger);
  flex: 1 1 0%;
  font-size: 0.875rem;
  line-height: 1.25rem;
}
.ip-warning-text strong {
  display: block;
  font-family: var(--font-body);
  font-size: 0.875rem;
  font-weight: 600;
  line-height: 1.25rem;
  margin-bottom: 0.25rem;
}
.submit-step-actions {
  gap: 0.75rem;
  justify-content: space-between;
  margin-top: 1.5rem;
}
.submit-step-actions {
  align-items: center;
  display: flex;
}
/* Label stacked over value, not side-by-side: a fixed label column cannot
   fit the longest label in every locale ("EINREICHUNGSMODUS" overlapped its
   value) without either wasting space for short labels or being wide for
   short ones — stacking fits every locale with no per-language tuning. */
.review-row {
  border-bottom-width: 1px;
  border-color: var(--hairline);
  display: flex;
  flex-direction: column;
  gap: 0.25rem;
  padding-bottom: 0.625rem;
  padding-top: 0.625rem;
}
.review-row:last-child {
  border-bottom-width: 0;
}
.review-label {
  color: var(--muted);
  font-size: 0.8125rem;
  font-weight: 600;
  line-height: 1.25rem;
}
.review-value {
  color: var(--body-text);
  font-size: 0.875rem;
  line-height: 1.25rem;
}
.auth-page {
  align-items: center;
  display: flex;
  flex: 1 1 0%;
  justify-content: center;
  padding: 2rem 1rem;
}
.auth-card {
  max-width: 400px;
  width: 100%;
}
.auth-heading {
  margin-bottom: 2rem;
}
.success-wrapper {
  padding: 3rem 1.5rem;
}
.success-header {
  margin-bottom: 2.5rem;
}
.success-check {
  align-items: center;
  background: var(--success-subtle);
  border-radius: 9999px;
  color: var(--success);
  display: inline-flex;
  font-size: 1.4rem;
  height: 3rem;
  justify-content: center;
  margin-bottom: 1rem;
  width: 3rem;
}
.saved-confirm-label {
  align-items: flex-start;
  background: var(--accent-subtle);
  border-radius: 8px;
  cursor: pointer;
  gap: 0.75rem;
  margin-top: 1.5rem;
  padding: 1rem;
  box-shadow: 0 0 0 1px var(--border-strong);
}
.demo-banner,
.saved-confirm-label {
  display: flex;
}
.demo-banner {
  align-items: center;
  background: var(--surface-card);
  border-bottom-width: 1px;
  border-color: var(--hairline);
  color: var(--body-text);
  font-size: 0.8rem;
  font-weight: 500;
  gap: 0.5rem;
  justify-content: center;
  padding: 0.45rem 1.5rem;
  text-align: center;
}
.demo-banner-badge {
  background: transparent;
  border-radius: var(--radius-sm);
  box-shadow: 0 0 0 1px var(--border-strong);
  color: var(--body-text);
  flex-shrink: 0;
  font-size: 0.75rem;
  font-weight: 600;
  padding: 0.15rem 0.45rem;
}
.demo-banner-link {
  color: var(--accent);
  font-weight: 600;
  text-decoration-line: none;
}
.demo-banner-link:hover {
  text-decoration-line: underline;
}
.demo-credentials {
  background: var(--surface-card);
  border-radius: var(--radius-card);
  margin-bottom: 1.25rem;
  padding: 1rem 1.1rem;
  box-shadow: 0 0 0 1px var(--hairline);
}
.demo-credentials-header {
  align-items: center;
  color: var(--body-text);
  display: flex;
  font-size: 0.8125rem;
  font-weight: 600;
  gap: 0.625rem;
  margin-bottom: 0.875rem;
}
.demo-badge {
  background: transparent;
  border-radius: var(--radius-sm);
  box-shadow: 0 0 0 1px var(--border-strong);
  color: var(--body-text);
  flex-shrink: 0;
  font-size: 0.75rem;
  font-weight: 600;
  padding: 0.12rem 0.4rem;
}
.demo-credentials-grid {
  -moz-column-gap: 1rem;
  column-gap: 1rem;
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  row-gap: 0.5rem;
}
.demo-cred-item {
  display: flex;
  flex-direction: column;
  gap: 0.18rem;
}
.demo-cred-full {
  grid-column: span 2 / span 2;
}
.demo-cred-label {
  color: var(--muted);
  font-size: 0.78rem;
}
.demo-cred-label,
.demo-cred-value {
  font-weight: 600;
}
.demo-cred-value {
  background: var(--canvas);
  border-radius: 0.375rem;
  color: var(--ink);
  cursor: pointer;
  font-family: var(--font-mono);
  font-size: 0.875rem;
  line-height: 1.25rem;
  padding: 0.375rem 0.625rem;
  text-align: left;
  transition-duration: 0.15s;
  transition-property: color, background-color, border-color, box-shadow, text-decoration-color, fill, stroke;
  transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
  box-shadow: 0 0 0 1px var(--hairline);
}
.demo-cred-value:hover {
  background: color-mix(in srgb,var(--warning) 8%,var(--canvas));
  box-shadow: 0 0 0 1px var(--warning);
}
.demo-cred-code {
  background: var(--surface-card);
  border-radius: 0.375rem;
  color: var(--ink);
  display: inline-block;
  font-family: var(--font-mono);
  font-size: 1rem;
  font-weight: 700;
  line-height: 1.5rem;
  padding: 0.375rem 0.625rem;
  box-shadow: 0 0 0 1px var(--hairline);
}
.demo-fill-btn {
  background: var(--surface-card);
  border-radius: 8px;
  border-style: none;
  box-shadow: 0 0 0 1px var(--border-strong);
  color: var(--ink);
  cursor: pointer;
  font-size: 0.8125rem;
  font-weight: 600;
  height: 2.25rem;
  margin-top: 0.75rem;
  padding-left: 1rem;
  padding-right: 1rem;
  transition-duration: 0.15s;
  transition-property: color, background-color, border-color, box-shadow, text-decoration-color, fill, stroke;
  transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
  width: 100%;
}
.demo-fill-btn:hover {
  box-shadow: 0 0 0 1px var(--ink);
}
.demo-reports-list {
  flex-direction: column;
  gap: 0.35rem;
}
.demo-report-row,
.demo-reports-list {
  display: flex;
}
.demo-report-row {
  align-items: center;
  background: var(--surface-card);
  border-radius: 0.375rem;
  cursor: pointer;
  font-size: 0.8125rem;
  gap: 0.75rem;
  padding: 0.45rem 0.75rem;
  text-align: left;
  transition-duration: 0.13s;
  transition-property: color, background-color, border-color, box-shadow, text-decoration-color, fill, stroke;
  transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
  width: 100%;
  box-shadow: 0 0 0 1px var(--hairline);
}
.demo-report-row:hover {
  background: color-mix(in srgb,var(--warning) 8%,var(--surface-card));
  box-shadow: 0 0 0 1px var(--warning);
}
.demo-report-status {
  font-size: 0.75rem;
  line-height: 1rem;
  margin-left: auto;
}
.session-expiry-banner {
  align-items: center;
  animation: slideInBanner 0.3s cubic-bezier(0.34, 1.56, 0.64, 1);
  background: var(--canvas);
  border-radius: var(--radius-hero);
  bottom: 1.5rem;
  box-shadow: 0 0 0 1px var(--warning), 0 6px 24px rgba(0, 0, 0, 0.15);
  display: flex;
  font-size: 0.875rem;
  gap: 0.75rem;
  line-height: 1.25rem;
  max-width: 420px;
  padding: 0.875rem 1rem;
  position: fixed;
  right: 1.5rem;
  z-index: 2000;
}
[data-theme="dark"] .session-expiry-banner {
  background: var(--surface-card);
}
.session-expiry-banner.session-expiry-expired-state {
  box-shadow: 0 0 0 1px var(--danger), 0 6px 24px rgba(0, 0, 0, 0.15);
}
.session-expiry-icon {
  color: var(--warning);
  flex-shrink: 0;
  font-size: 1.3rem;
  line-height: 1;
}
.session-expiry-expired-state .session-expiry-icon {
  color: var(--danger);
}
.session-expiry-body {
  align-items: center;
  color: var(--ink);
  display: flex;
  flex: 1 1 0%;
  flex-wrap: wrap;
  gap: 0.375rem;
  line-height: 1.375;
  min-width: 0;
}
.session-expiry-body p {
  color: var(--muted);
  font-size: 0.8125rem;
  margin: 0;
}
.session-expiry-countdown {
  color: var(--warning);
  display: inline-block;
  font-family: var(--font-mono);
  font-size: 1rem;
  font-weight: 700;
  letter-spacing: 0.04em;
  line-height: 1.5rem;
  min-width: 3.2ch;
}
.session-expiry-expired-state .session-expiry-countdown {
  color: var(--danger);
}
.session-expiry-actions {
  align-items: center;
  display: flex;
  flex-shrink: 0;
  gap: 0.5rem;
}
.session-expiry-extend {
  white-space: nowrap;
}
.session-expiry-dismiss {
  background-color: transparent;
  border-radius: var(--radius-sm);
  border-style: none;
  color: var(--muted);
  cursor: pointer;
  font-size: 0.9rem;
  line-height: 1;
  padding: 0.2rem 0.3rem;
  transition-duration: 0.15s;
  transition-property: color, background-color, border-color, box-shadow, text-decoration-color, fill, stroke;
  transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
}
.session-expiry-dismiss:hover {
  background: var(--surface-card);
  color: var(--ink);
}
.page-subtitle {
  color: var(--muted);
  font-size: 0.875rem;
  line-height: 1.25rem;
  line-height: 1.625;
  margin-top: 0.25rem;
}
.page-actions {
  align-items: center;
  border-color: var(--hairline);
  border-top-width: 1px;
  display: flex;
  flex-wrap: wrap;
  gap: 0.75rem;
  margin-top: 2rem;
  padding-top: 1.5rem;
}
/* A reference link sits next to a text label in flowing content: underline
   it so it is distinguishable without relying on color alone (WCAG 1.4.1). */
.refs-list a {
  text-decoration-line: underline;
}
.empty-state {
  color: var(--muted);
  padding-bottom: 3rem;
  padding-top: 3rem;
  text-align: center;
}
.empty-state,
.checklist {
  display: flex;
  flex-direction: column;
  gap: 0.625rem;
  list-style-type: none;
  margin: 0;
  padding: 0;
}
.checklist__item {
  align-items: flex-start;
  color: var(--body-text);
  display: flex;
  font-size: 0.875rem;
  gap: 0.75rem;
  line-height: 1.25rem;
}
.checklist__icon {
  color: var(--muted);
  flex-shrink: 0;
  font-size: 1rem;
  line-height: 1.5rem;
  margin-top: 0.125rem;
}
.content-grid-2 {
  display: grid;
  gap: 1.25rem;
  grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
}
.option-card {
  background: var(--surface-card);
  border-radius: var(--radius-card);
  padding: 1.5rem;
}
.option-card h3 {
  font-size: 1rem;
  line-height: 1.5rem;
  margin-bottom: 0.5rem;
}
.option-card p {
  color: var(--body-text);
  font-size: 0.875rem;
  line-height: 1.25rem;
  line-height: 1.625;
}
.option-card__note {
  color: var(--muted);
  font-size: 0.75rem;
  line-height: 1rem;
  margin-top: 0.5rem;
}
.legal-quote,
.option-card__note {
  font-style: italic;
}
.legal-quote {
  background: var(--surface-card);
  border-radius: 8px;
  color: var(--body-text);
  font-family: var(--font-body);
  font-size: 0.875rem;
  line-height: 1.25rem;
  line-height: 1.625;
  margin-bottom: 1rem;
  margin-top: 1rem;
  padding-bottom: 0.75rem;
  padding-left: 1.25rem;
  padding-top: 0.75rem;
}
.legal-grid {
  display: grid;
  gap: 1.25rem;
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
  margin-top: 0.75rem;
}
.legal-item {
  color: var(--body-text);
}
.legal-item,
.legal-item h3 {
  font-size: 0.875rem;
  line-height: 1.25rem;
}
.legal-item h3 {
  color: var(--ink);
  font-weight: 600;
  margin-bottom: 0.375rem;
}
.stats-row {
  display: grid;
  gap: 1rem;
  grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
  margin-bottom: 2rem;
}
.stat-card__label {
  color: var(--muted);
  font-size: 0.8125rem;
  line-height: 1.1rem;
  margin-bottom: 0.5rem;
  overflow-wrap: break-word;
}
.stat-card__label,
.stat-card__value {
  font-weight: 600;
}
.stat-card__value {
  color: var(--ink);
  font-size: 1.125rem;
  line-height: 1.75rem;
}
.stat-card__sub {
  color: var(--muted);
  font-size: 0.75rem;
  font-weight: 400;
  line-height: 1rem;
  margin-top: 0.125rem;
}
.form-row {
  align-items: end;
  display: grid;
  gap: 1rem;
  grid-template-columns: 1fr 1fr auto;
}
.p-note {
  background: var(--warning-subtle);
  border-radius: 6px;
  color: var(--body-text);
  margin-top: 0.75rem;
  padding: 0.5rem 0.75rem;
}
.p-note,
.skip-link {
  font-size: 0.875rem;
  line-height: 1.25rem;
}
.skip-link {
  background: var(--cta-bg);
  border-bottom-left-radius: 8px;
  border-bottom-right-radius: 8px;
  color: var(--cta-text);
  font-weight: 600;
  left: 0.5rem;
  padding: 0.5rem 1rem;
  position: absolute;
  text-decoration-line: none;
  top: -100%;
  transition-duration: 0.1s;
  transition-property: top;
  transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
  z-index: 9999;
}
.skip-link:focus {
  outline: 3px solid var(--accent);
  outline-offset: 2px;
  top: 0;
}
.sr-only {
  clip: rect(0,0,0,0);
  border-width: 0;
  border-width: 0;
  height: 1px;
  margin: -1px;
  overflow: hidden;
  padding: 0;
  padding: 0;
  position: absolute;
  white-space: nowrap;
  width: 1px;
}
.m-0 {
  margin: 0;
}
.mb-2 {
  margin-bottom: 0.5rem;
}
.mt-3 {
  margin-top: 0.75rem;
}
.flex {
  display: flex;
}
.grid {
  display: grid;
}
.hidden {
  display: none;
}
.flex-1 {
  flex: 1 1 0%;
}
.grid-cols-2 {
  grid-template-columns: repeat(2, minmax(0, 1fr));
}
.gap-2 {
  gap: 0.5rem;
}
.whitespace-nowrap {
  white-space: nowrap;
}
@media (max-width: 768px) {
  .split-sidebar .guarantee-list {
    display: grid;
    gap: 0;
    grid-template-columns: 1fr 1fr;
  }
  .filter-pills {
    flex-wrap: nowrap;
    overflow-x: auto;
    scrollbar-width: none;
  }
  .filter-pills::-webkit-scrollbar {
    display: none;
  }
}
.mobile-reassure { display: none; }
@media (max-width: 900px) {
  .split-layout { display: flex; flex-direction: column; gap: var(--space-8); padding: var(--space-6) var(--gutter); }
  .split-main { max-width: none; }
  .split-sidebar { padding: var(--space-6); position: static; }
  .mobile-reassure {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    color: var(--body-text);
    font-size: var(--text-body-sm);
    margin: 0 0 var(--space-4);
  }
}
/* No white-space: nowrap here: a case number or PIN must be free to wrap
   at the <wbr> the server inserts after each hyphen (wbr_after_hyphens in
   app/templating.py) rather than scroll behind the copy button. */
.token { overflow-wrap: normal; word-break: normal; }
#pin-value .token { font-size: clamp(0.95rem, 4.2vw, 1.25rem); }
@media (max-width: 540px) {
  h1 {
    font-size: 1.5rem;
  }
  /* A demo case number broke into two or three lines next to a long status badge. */
  .demo-cred-code {
    letter-spacing: 0.1em;
    white-space: nowrap;
  }
  .demo-report-row {
    flex-wrap: wrap;
  }
  .message {
    max-width: 100%;
  }
  .mode-cards,
  .split-sidebar .guarantee-list {
    grid-template-columns: 1fr;
  }
  .session-expiry-banner {
    border-bottom: none;
    border-left: none;
    border-radius: 12px 12px 0 0;
    border-right: none;
    bottom: 0;
    left: 0;
    max-width: 100%;
    right: 0;
  }
}
.admin-split-grid {
  align-items: start;
  display: grid;
  gap: 1.25rem;
  /* Halves: in a third, the account facts wrapped every value onto two or
     three lines ("Bei jeder Anmeldung erforderlich"). */
  grid-template-columns: repeat(2, minmax(0, 1fr));
}
.inline-form {
  display: inline;
}
.anim-in {
  animation: fadeSlideIn 0.5s ease both;
  opacity: 0;
  animation-fill-mode: forwards;
}
.delay-04 {
  animation-delay: 0.04s;
}
.delay-05 {
  animation-delay: 0.05s;
}
.delay-10 {
  animation-delay: 0.1s;
}
@media (prefers-reduced-motion: reduce) {
  *,
  :after,
  :before {
    animation-duration: 0.01ms !important;
    animation-delay: 0s !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
}
.form-control {
  border-color: color-mix(in srgb,var(--ink) 45%,var(--canvas));
}
.form-control:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 1px;
}
@media (max-width: 768px) {
  .nav {
    padding-bottom: var(--space-2);
    padding-top: var(--space-2);
    position: static;
  }
  .nav-links {
    flex-wrap: wrap;
    max-width: 100%;
  }
  .dashboard-panel-header > .dashboard-toolbar {
    flex: 1 1 100%;
    min-width: 0;
  }
  .filter-pills {
    max-width: 100%;
  }
}
.admin-split-grid > * {
  min-width: 0;
}
/* The grid gap spaces its columns; `.panel + .panel` would push the second one down. */
.admin-split-grid > .panel + .panel {
  margin-top: 0;
}
/* An admin list goes under its form, across the full width. In two thirds of
   the page the organisations (six columns, one a URL), users (a role select
   and up to three buttons), categories and locations lists all pushed their
   actions past a sideways scrollbar at 1920 px. */
.admin-stack {
  display: grid;
  gap: 1.25rem;
}
.admin-stack > * {
  min-width: 0;
}
.panel-narrow {
  max-width: 32rem;
}
@media (max-width: 900px) {
  .admin-split-grid {
    grid-template-columns: 1fr;
  }
}
/* ── Add dialog: a panel lifted into a modal ───────────────────────────────
   The list is the page; creating a row is a modal action off the heading, not
   a second form stacked above the table. Native <dialog>; the no-JS fallback
   (base.html) renders it inline as a panel. */
.page-header-actions {
  align-items: flex-end;
  display: flex;
  flex-wrap: wrap;
  gap: 1rem;
  justify-content: space-between;
}
.page-header-actions h1 {
  margin-bottom: 0;
}
dialog.dialog-panel {
  background: var(--surface-card);
  border: none;
  border-radius: var(--radius-card);
  box-shadow: 0 10px 40px rgba(0, 0, 0, 0.18);
  color: var(--body-text);
  /* The universal reset (*{margin:0}) zeroes the UA dialog:modal auto-centring. */
  margin: auto;
  max-width: 32rem;
  padding: 1.75rem;
  width: calc(100vw - 2rem);
}
[data-theme="dark"] dialog.dialog-panel {
  box-shadow: 0 10px 40px rgba(0, 0, 0, 0.5), 0 0 0 1px var(--hairline);
}
dialog.dialog-panel::backdrop {
  background: rgba(10, 10, 11, 0.45);
}
.dialog-head {
  align-items: center;
  border-bottom: 1px solid var(--hairline);
  display: flex;
  gap: 0.75rem;
  justify-content: space-between;
  margin-bottom: 1.25rem;
  padding-bottom: 0.75rem;
}
.dialog-head .panel-header-title {
  margin: 0;
}
.dialog-close {
  background: transparent;
  border: none;
  border-radius: 0.375rem;
  color: var(--muted);
  cursor: pointer;
  font-size: 1.5rem;
  line-height: 1;
  padding: 0.1rem 0.5rem;
}
.dialog-close:hover {
  background: var(--canvas);
  color: var(--ink);
}
.dialog-actions {
  display: flex;
  gap: 0.75rem;
  justify-content: flex-end;
  margin-top: 1.5rem;
}
/* Entry answers the open action, not a page load; silenced for reduced motion. */
@media (prefers-reduced-motion: no-preference) {
  dialog.dialog-panel[open] {
    animation: dialog-in 0.14s ease-out;
  }
  @keyframes dialog-in {
    from {
      opacity: 0;
      transform: translateY(0.5rem);
    }
  }
}
.note code {
  overflow-wrap: anywhere;
}
.field-error {
  color: var(--danger);
  font-family: var(--font-body);
  font-size: 0.8125rem;
  font-weight: 600;
  margin: 0.375rem 0 0;
}
.form-control[aria-invalid="true"] {
  border-color: var(--danger);
}
.dash-search {
  align-items: flex-end;
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  margin-bottom: 1rem;
}
.dash-search .form-group {
  flex: 1 1 16rem;
  margin: 0;
  min-width: 0;
}
.dash-search > .form-hint {
  flex-basis: 100%;
  margin-top: 0;
}
.audit-detail {
  display: flex;
  flex-wrap: wrap;
  gap: 0.125rem 0.75rem;
  margin: 0;
}
.audit-detail > div {
  display: flex;
  gap: 0.35rem;
  min-width: 0;
}
.audit-detail dt {
  color: var(--muted);
  font-weight: 600;
}
.audit-detail dd {
  margin: 0;
  overflow-wrap: anywhere;
}

/* ── Admin shell ─────────────────────────────────────────────────────────── */
.admin-shell {
  display: grid;
  grid-template-columns: 15rem minmax(0, 1fr);
  gap: var(--space-8);
  max-width: var(--frame);
  margin: 0 auto;
  padding: var(--space-6) var(--gutter) var(--space-12);
}
.admin-menu {
  position: sticky;
  top: calc(4rem + var(--space-6));
  align-self: start;
}
.admin-menu-toggle {
  display: none;
}
.admin-nav ul {
  list-style: none;
  margin: 0 0 var(--space-5);
  padding: 0;
}
/* The website's docs sidebar (openwhistle/website docs.css .sidebar-group, .sidebar-links). */
.admin-nav-group {
  color: var(--muted);
  font-size: 0.78rem;
  font-weight: 600;
  margin: 0 0 var(--space-2) var(--space-3);
}
.admin-nav a {
  border-left: 2px solid transparent;
  border-radius: 0 var(--radius-sm) var(--radius-sm) 0;
  color: var(--body-text);
  display: block;
  font-size: 0.875rem;
  padding: var(--space-2) var(--space-3);
  text-decoration: none;
  transition: color var(--duration-fast) ease, background-color var(--duration-fast) ease, border-left-color var(--duration-fast) ease;
  white-space: nowrap;
}
.admin-nav a:hover {
  background: var(--surface-card);
  color: var(--ink);
}
.admin-nav a.active {
  background: var(--accent-subtle);
  border-left-color: var(--accent);
  color: var(--accent);
}
.admin-nav-logout {
  border-top: 1px solid var(--hairline);
  margin: 0;
  padding-top: var(--space-3);
}
.admin-nav .admin-nav-account {
  border-top: 1px solid var(--hairline);
  margin-bottom: 0;
  padding-top: var(--space-3);
}
/* Alone in the menu during a forced password change: no rule above it. */
.admin-nav .admin-nav-account:first-child {
  border-top: 0;
  padding-top: 0;
}
.admin-nav-account + .admin-nav-logout {
  border-top: 0;
  padding-top: 0;
}
/* Log out is a form button, not a link: same box as the links above it. */
.admin-nav .nav-link-button {
  background: none;
  border: 0;
  border-left: 2px solid transparent;
  border-radius: 0 var(--radius-sm) var(--radius-sm) 0;
  color: var(--body-text);
  cursor: pointer;
  display: block;
  font: inherit;
  font-size: 0.875rem;
  padding: var(--space-2) var(--space-3);
  text-align: left;
  width: 100%;
}
.admin-nav .nav-link-button:hover {
  background: var(--surface-card);
  color: var(--ink);
}
.admin-main {
  min-width: 0;
}
.admin-main > .container {
  max-width: none;
  padding: 0;
}
@media (max-width: 1023px) {
  .admin-shell {
    grid-template-columns: minmax(0, 1fr);
    gap: var(--space-4);
    padding: var(--space-4);
  }
  .admin-menu {
    position: static;
    box-shadow: 0 0 0 1px var(--hairline);
    border-radius: var(--radius-card);
  }
  .admin-menu-toggle {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    min-height: 44px;
    padding: 0 var(--space-4);
    cursor: pointer;
    font-weight: 600;
    list-style: none;
  }
  .admin-menu-toggle::-webkit-details-marker {
    display: none;
  }
  .admin-menu[open] .admin-nav {
    padding: 0 var(--space-3) var(--space-3);
  }
  .admin-nav a {
    display: flex;
    align-items: center;
    min-height: 44px;
  }
}
.icon {
  /* svg is display:block in the reset above; without this override an icon
     placed next to inline text (e.g. an SLA value) renders on its own line
     — vertical-align has no effect on a block box. Flex parents (.btn,
     .badge, .stepper-dot, …) blockify this back, so they are unaffected. */
  display: inline-block;
  flex: none;
  vertical-align: -0.2em;
}
/* ── Footer: the website's look (openwhistle/website base.css) in one row ──
   The site's footer is a three-column grid; the app keeps one row so the
   wizard's first step still fits a Full HD window with the footer in view
   (tests/e2e/test_layout.py). Same fill, frame, mark and mono voice. */
/* One compact row: it was 87 px, taller than the 60 px nav, for a tagline, five
   links and a version string a visitor never needed. */
.footer {
  background: var(--surface-dark);
  color: var(--muted-on-dark);
  font-size: 0.8125rem;
  line-height: 1.25rem;
  margin-top: auto;
  padding: var(--space-3) 0;
}
.footer-inner {
  align-items: center;
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2) var(--space-6);
  justify-content: space-between;
  margin: 0 auto;
  max-width: var(--frame);
  padding: 0 var(--gutter);
}
.footer-links {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-1) var(--space-6);
}
.footer-links a,
.footer-powered a {
  color: var(--muted-on-dark);
  text-decoration-line: none;
  transition: color var(--duration-fast) ease;
}
.footer-links a:hover,
.footer-powered a:hover {
  color: var(--on-dark);
  text-decoration-line: none;
}
.footer-powered {
  align-items: center;
  color: var(--muted-on-dark);
  display: flex;
  gap: var(--space-2);
  margin: 0;
}
.footer-powered .mark {
  opacity: 0.5;
}
/* Admin pages only. Same size and line as the text beside it. */
.footer-version {
  font-family: var(--font-mono);
  font-size: inherit;
  line-height: inherit;
}
.demo-banner-short { display: none; }
@media (max-width: 640px) {
  .nav-links { order: 3; width: 100%; justify-content: flex-start; }
  .demo-banner { flex-wrap: nowrap; white-space: nowrap; }
  .demo-banner-text { display: none; }
  .demo-banner-short { display: inline; overflow: hidden; text-overflow: ellipsis; }
  .table-stack thead {
    position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%);
  }
  .table-stack, .table-stack tbody { display: block; }
  .table-stack tr {
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto;
    gap: var(--space-1) var(--space-3);
    padding: var(--space-3) 0;
    border-bottom: 1px solid var(--hairline);
  }
  .table-stack td { display: block; border: 0; padding: 0; }
  .table-stack td[data-label]::before {
    content: attr(data-label);
    display: block;
    color: var(--muted);
    font-size: var(--text-hint);
  }
  .table-stack .stack-primary { grid-column: 1; grid-row: 1; font-weight: 600; }
  .table-stack .stack-primary::before, .table-stack .stack-status::before { display: none; }
  .table-stack .stack-status { grid-column: 2; grid-row: 1; justify-self: end; }
  .table-stack .stack-action { grid-column: 1 / -1; }
  .table-stack .stack-action .btn { width: 100%; justify-content: center; }
  .table-stack td[colspan] { grid-column: 1 / -1; }
}

/* Borders are drawn as box-shadow rings (DESIGN.md "Rules"); forced colours drop shadows, so the edges come back. */
@media (forced-colors: active) {
  .btn, .btn-primary, .btn-danger, .btn-secondary, .panel-outline, .panel, .badge-received, .mode-card,
  .badge-in_review, .badge-pending_feedback, .badge-closed, .demo-badge, .demo-banner-badge, .message-admin, .split-sidebar,
  .demo-fill-btn, .credential-display, .credential-box, .attachment-item, .qr-wrapper, .totp-secret-card,
  .saved-confirm-label, .demo-credentials, .demo-cred-value, .demo-cred-code, .demo-report-row,
  .badge-admin, .badge-case_manager, .badge-superadmin, .badge-neutral, .filter-pills,
  .session-expiry-banner, .session-expiry-banner.session-expiry-expired-state, .card, .theme-toggle, .lang-picker-btn, .lang-picker-menu, .admin-menu,
  .panel-primary, .pagination-page, .pagination-page-current, dialog.dialog-panel {
    border: 1px solid CanvasText;
  }
  /* A disabled pagination button keeps its dashed edge as the border here. */
  .pagination-disabled { border-style: dashed; outline: none; }
}
