/*
 * Components: icons, cards, buttons, forms, tables, badges, alerts, data views, live regions, CLI hints.
 * Only var(--…) from tokens.css. A state is never colour alone: symbol + text + colour.
 * Momentum geometry, shared by every theme: pill buttons (--radius-full), cards with --radius-xl and
 * --shadow-sm, uppercase table heads, underline tabs; the serif only at --font-weight-medium.
 * Never a coloured accent border or stripe at the left (border-left, border-inline-start, a pseudo-element):
 * the user's rule for Momentum Design Bronze, checked by test_css.py.
 */

/* ------------------------------------------------------------------ icons */

.icon {
  width: var(--pe-icon-size);
  height: var(--pe-icon-size);
  flex: none;
  fill: none;
  stroke: currentColor;
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.icon-large {
  width: var(--pe-icon-size-lg);
  height: var(--pe-icon-size-lg);
}

/* ------------------------------------------------------------------ cards */

.card {
  margin-bottom: var(--spacing-3xl);
  padding: var(--spacing-3xl);
  background: var(--pe-surface-card);
  border: var(--pe-border-width) solid var(--color-border-secondary);
  border-radius: var(--radius-xl);
  box-shadow: var(--shadow-sm);
}

.card-title {
  font-size: var(--text-lg);
  line-height: var(--leading-md);
}

/* A block that brings no distance of its own keeps one to what follows it in the same card: a row of pills, of
   buttons or of tiles would otherwise touch the tiles or the table below it (the user, 2026-10-13). */
.card > .grid:not(:last-child),
.card > .button-row:not(:last-child),
.card > .sim-actions:not(:last-child),
.card > .sim-inline-form:not(:last-child),
.card > .disclosure:not(:last-child) {
  margin-bottom: var(--spacing-xl);
}

.card > .sim-badges:not(:last-child) {
  margin-bottom: var(--spacing-lg);
}

.subcard {
  padding-block: var(--spacing-xl);
  border-top: var(--pe-border-width) solid var(--color-border-secondary);
}

.subcard:first-child {
  border-top: 0;
  padding-top: 0;
}

/* ------------------------------------------------------------------ buttons */

/* In a line of text a button is centred on it (vertical-align: middle), never set on its baseline: that
   is the lower edge of the symbol for a button with one and the text for a button without, so two buttons
   of one line - a download link and the button of a small form - would stand at different heights. */
.button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--spacing-sm);
  vertical-align: middle;
  min-height: var(--pe-control-height);
  padding: var(--pe-control-pad-block) var(--spacing-xl);
  border: var(--pe-border-width) solid transparent;
  border-radius: var(--radius-full);
  font: inherit;
  font-size: var(--text-sm);
  font-weight: var(--font-weight-semibold);
  line-height: var(--leading-sm);
  text-decoration: none;
  cursor: pointer;
  transition:
    background-color var(--pe-duration-fast) var(--pe-easing-standard),
    border-color var(--pe-duration-fast) var(--pe-easing-standard),
    box-shadow var(--pe-duration-fast) var(--pe-easing-standard),
    transform var(--pe-duration-fast) var(--pe-easing-standard);
}

.button:focus-visible {
  outline: var(--pe-focus-width) solid var(--color-border-brand);
  outline-offset: var(--pe-focus-offset);
  box-shadow: var(--pe-focus-shadow);
}

.button:disabled {
  cursor: not-allowed;
  background: var(--color-bg-disabled);
  color: var(--color-text-disabled);
  border-color: var(--color-border-secondary);
}

.button-small {
  min-height: var(--pe-control-height-sm);
  padding: var(--pe-control-pad-block-sm) var(--spacing-lg);
}

.button-primary {
  background: var(--button-primary-bg);
  color: var(--button-primary-fg);
  border-color: var(--button-primary-border);
}

.button-primary:hover {
  background: var(--button-primary-bg-hover);
  color: var(--button-primary-fg);
}

.button-secondary {
  background: var(--button-secondary-bg);
  color: var(--button-secondary-fg);
  border-color: var(--button-secondary-border);
}

.button-secondary:hover {
  background: var(--button-secondary-bg-hover);
  color: var(--button-secondary-fg);
}

.button-danger {
  background: var(--button-error-bg);
  color: var(--button-error-fg);
  border-color: var(--button-error-border);
}

.button-danger:hover {
  background: var(--button-error-bg-hover);
  color: var(--button-error-fg);
}

.button-primary:active,
.button-secondary:active,
.button-danger:active {
  transform: scale(0.98);
}

.button-ghost {
  background: var(--button-tertiary-bg);
  color: var(--button-tertiary-fg);
}

.button-ghost:hover {
  background: var(--button-tertiary-bg-hover);
  color: var(--color-text-primary);
}

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

.form {
  margin: 0;
}

.inline-form {
  display: inline-flex;
  vertical-align: middle;
  margin: 0;
}

.stack-form {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--spacing-xs);
}

.stack-form .field {
  width: 100%;
}

/* The buttons of one form side by side (the second may belong to another form: attribute form=). */
.button-row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--spacing-xs);
}

.field {
  display: flex;
  flex-direction: column;
  gap: var(--spacing-sm);
  max-width: var(--pe-field-max);
  margin-bottom: var(--spacing-xl);
}

.field label {
  font-size: var(--text-sm);
  font-weight: var(--font-weight-medium);
  color: var(--color-text-secondary);
}

.field-check {
  flex-direction: row;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--spacing-md);
}

.field-check .field-help {
  flex-basis: 100%;
}

.field-inline {
  margin-bottom: 0;
}

.required {
  color: var(--color-text-error);
}

/* One height for everything that stands in a form row: a text field, a select and a button are exactly
   --pe-control-height high (the small ones of the simulator --pe-control-height-sm), with the same frame
   width, so a row of them shares its top edge, its bottom edge and its baseline in every browser. */
.input {
  width: 100%;
  height: var(--pe-control-height);
  padding: var(--pe-control-pad-block) var(--spacing-lg);
  font: inherit;
  font-size: var(--text-sm);
  line-height: var(--leading-sm);
  color: var(--input-text);
  background: var(--input-bg);
  border: var(--pe-border-width) solid var(--input-border);
  border-radius: var(--radius-md);
  transition:
    border-color var(--pe-duration-fast) var(--pe-easing-standard),
    box-shadow var(--pe-duration-fast) var(--pe-easing-standard);
}

.input::placeholder {
  color: var(--input-placeholder);
}

.input:hover {
  border-color: var(--input-border-hover);
}

.input:focus,
.input:focus-visible {
  outline: none;
  border-color: var(--input-border-focus);
  box-shadow: var(--input-ring-focus);
}

.input:disabled,
.input[readonly] {
  background-color: var(--input-disabled-bg);
  color: var(--color-text-disabled);
}

/* A select is drawn like a text field, not as the control of the platform: that one has its own height,
   frame and baseline in every browser and would sit lower and thinner next to a field. The chevron is two
   diagonal strokes, each a band of a gradient in the colour of a symbol (follows theme and dark mode; no
   image file). */
.select {
  appearance: none;
  -webkit-appearance: none;
  padding-inline-end: var(--spacing-4xl);
  background-image:
    linear-gradient(45deg, transparent 38%, var(--color-fg-secondary) 38% 62%, transparent 62%),
    linear-gradient(135deg, transparent 38%, var(--color-fg-secondary) 38% 62%, transparent 62%);
  background-position:
    right calc(var(--spacing-lg) + var(--pe-select-arrow)) center,
    right var(--spacing-lg) center;
  background-size: var(--pe-select-arrow) var(--pe-select-arrow);
  background-repeat: no-repeat;
  text-overflow: ellipsis;
  cursor: pointer;
}

/* forced colours (contrast themes of the system) drop background images, and with them the chevron: there
   the platform draws the select again */
@media (forced-colors: active) {
  .select {
    appearance: auto;
    -webkit-appearance: auto;
  }
}

/* several lines, or the file button of the browser: at least the control height, growing with the content */
.textarea,
.input.file {
  height: auto;
  min-height: var(--pe-control-height);
}

.input.mono,
.textarea.mono {
  font-family: var(--font-family-mono);
  font-size: var(--text-sm);
}

/* 16px below 40em, mono fields included: iOS zooms into a focused field with a smaller font. The height of
   a one-line field stays the control height (a button next to it keeps its size, too); only a field of
   several lines gets the wider line. */
@media (max-width: 40em) {
  .input,
  .input.mono {
    font-size: var(--text-md);
  }

  .textarea {
    line-height: var(--leading-md);
  }
}

.textarea {
  resize: vertical;
}

.check {
  width: var(--pe-icon-size);
  height: var(--pe-icon-size);
  accent-color: var(--color-fg-brand-primary);
}

.field-invalid .input {
  border-color: var(--color-border-error);
}

.field-invalid .input:focus {
  box-shadow: var(--ring-error);
}

.field-help {
  margin: 0;
  font-size: var(--text-xs);
  line-height: var(--leading-xs);
  color: var(--color-text-tertiary);
}

.field-error {
  display: flex;
  align-items: center;
  gap: var(--spacing-xs);
  margin: 0;
  font-size: var(--text-sm);
  color: var(--color-text-error);
}

/* A filter row: label above control, the button last. The row is aligned at its bottom and no field has a
   margin or anything below its control, so the controls and the button of a line share their top and bottom
   edge - also on a wrapped line, where the button may stand alone. A hint is never part of a field here (it
   would lift the control above its neighbours; check_page refuses it): it is a line of its own below the
   controls. Every field is at least --pe-filter-field-width wide: a select of two short options is as wide
   as the text fields next to it. A checkbox with its label takes the height of a control and is centred on
   that line. */
.filter-bar {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  gap: var(--spacing-lg);
  margin-bottom: var(--spacing-xl);
}

.filter-bar .field {
  min-width: var(--pe-filter-field-width);
  margin-bottom: 0;
}

.filter-bar .field-check {
  min-width: 0;
  min-height: var(--pe-control-height);
}

.filter-bar > .field-help {
  flex-basis: 100%;
  margin-top: calc(var(--spacing-sm) - var(--spacing-lg));
}

/* below 40em one field per line, each as wide as the row; the button below them at its own width */
@media (max-width: 40em) {
  .filter-bar {
    flex-direction: column;
    flex-wrap: nowrap;
    align-items: stretch;
  }

  .filter-bar .field {
    max-width: none;
  }

  .filter-bar > .button {
    align-self: flex-start;
  }
}

.divider {
  display: flex;
  align-items: center;
  gap: var(--spacing-lg);
  margin-block: var(--spacing-xl);
  color: var(--color-text-tertiary);
  font-size: var(--text-sm);
}

.divider::before,
.divider::after {
  content: "";
  flex: 1;
  border-top: var(--pe-border-width) solid var(--color-border-secondary);
}

.disclosure > summary {
  cursor: pointer;
  color: var(--pe-link);
  font-size: var(--text-sm);
}

.disclosure[open] > summary {
  margin-bottom: var(--spacing-md);
}

/* ------------------------------------------------------------------ tables */

/* The scroll frame is the containing block of what is positioned inside it: without position: relative an
   absolute, visually hidden column head ("Actions") escapes the overflow-x and widens the whole page. */
.table-wrap {
  position: relative;
  overflow-x: auto;
  margin-bottom: var(--spacing-xl);
  background: var(--pe-surface-card);
  border: var(--pe-border-width) solid var(--color-border-secondary);
  border-radius: var(--radius-lg);
}

.table {
  width: 100%;
  border-collapse: collapse;
  font-size: var(--text-sm);
  line-height: var(--leading-sm);
}

.table th,
.table td {
  text-align: start;
  vertical-align: top;
  border-bottom: var(--pe-border-width) solid var(--color-border-secondary);
}

.table th {
  padding: var(--spacing-lg) var(--spacing-xl);
  background: var(--color-bg-secondary);
  color: var(--color-text-tertiary);
  font-size: var(--text-xs);
  line-height: var(--leading-xs);
  font-weight: var(--font-weight-medium);
  text-transform: uppercase;
  letter-spacing: var(--pe-letter-spacing-caps);
  white-space: nowrap;
}

.table td {
  padding: var(--spacing-md) var(--spacing-xl);
}

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

.table tbody tr:hover td {
  background: var(--color-bg-secondary);
}

.row-note td {
  background: var(--color-bg-secondary);
}

.actions-cell {
  white-space: nowrap;
}

/* the buttons of a table row stay side by side: a table short of room would stack a wrapping row */
.actions-cell .button-row {
  flex-wrap: nowrap;
}

.actions-cell .disclosure[open] {
  display: grid;
  justify-items: start;
  gap: var(--spacing-xs);
  min-width: var(--pe-tile-min);
  white-space: normal;
}

.actions-cell .disclosure .field {
  margin-bottom: var(--spacing-xs);
}

/* The stored OCPP configuration of a station (CPMS): one table per category, all with the same column
   widths, so the categories line up below each other. A long key or value (a list without blanks) wraps in
   its column; a narrow screen scrolls the table in its frame. */
.config-table {
  table-layout: fixed;
  min-width: var(--pe-measure);
}

.config-table th:nth-child(1) {
  width: 33%;
}

.config-table th:nth-child(3) {
  width: 23%;
}

.config-table th:nth-child(4) {
  width: 12%;
}

.config-table code,
.wrap-code code {
  overflow-wrap: anywhere;
}

/* Up to eight independent snapshots remain columns; the shared table frame scrolls on narrow screens. */
.configuration-comparison th,
.configuration-comparison td {
  min-width: 13rem;
  max-width: 22rem;
}

.configuration-comparison pre {
  margin-top: var(--spacing-xs);
}

/* Every cell starts at its top with one line of text (--leading-sm). A pill is a little higher than that
   line: pulled in by the difference it counts as exactly one line and is centred on it - alone in its cell,
   next to a text or on top of a stack. So the pills of a row stand on one line, and the first line of text of
   the other cells is centred on the same line. */
.table td .badge {
  vertical-align: top;
  margin-block: calc((var(--leading-sm) - var(--pe-badge-height)) / 2);
}

/* a state with something to say about it (status.stack): the pill on the first line of the cell, the text
   below it - never before it, where it would push the pill down or to the side */
.pill-stack {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--spacing-xs);
}

.pill-stack + .pill-stack {
  margin-top: var(--spacing-md);
}

.pill-note {
  min-width: 0;
  overflow-wrap: anywhere;
}

/* several pills, or a text with its marks (status.pills): they wrap as whole items with air between the
   rows - as plain inline boxes pulled in to one line each, wrapped pills would lie into each other. The gap
   between the rows is larger than what a pill reaches beyond its line by the gap between two pills of a
   row (momentum-bronze; more in a theme with a lower badge). */
.pill-row {
  display: inline-flex;
  flex-wrap: wrap;
  align-items: flex-start;
  gap: var(--spacing-md) var(--spacing-xs);
  vertical-align: top;
}

.pagination {
  display: flex;
  justify-content: space-between;
  gap: var(--spacing-md);
}

/* ------------------------------------------------------------------ badges and status */

.badge {
  display: inline-flex;
  align-items: center;
  gap: var(--spacing-xs);
  padding: var(--spacing-xxs) var(--spacing-md);
  border: var(--pe-border-width) solid transparent;
  border-radius: var(--radius-full);
  font-size: var(--text-xs);
  font-weight: var(--font-weight-medium);
  line-height: var(--leading-xs);
  white-space: nowrap;
}

.badge-gray {
  background: var(--badge-gray-bg);
  color: var(--badge-gray-fg);
  border-color: var(--badge-gray-border);
}

.badge-brand {
  background: var(--badge-brand-bg);
  color: var(--badge-brand-fg);
  border-color: var(--badge-brand-border);
}

.badge-success {
  background: var(--badge-success-bg);
  color: var(--badge-success-fg);
  border-color: var(--badge-success-border);
}

.badge-warning {
  background: var(--badge-warning-bg);
  color: var(--badge-warning-fg);
  border-color: var(--badge-warning-border);
}

.badge-error {
  background: var(--badge-error-bg);
  color: var(--badge-error-fg);
  border-color: var(--badge-error-border);
}

.badge-status {
  background: var(--badge-gray-bg);
  color: var(--badge-gray-fg);
  border-color: var(--badge-gray-border);
}

.badge-status.status-ok {
  background: var(--badge-success-bg);
  color: var(--badge-success-fg);
  border-color: var(--badge-success-border);
}

.badge-status.status-degraded {
  background: var(--badge-warning-bg);
  color: var(--badge-warning-fg);
  border-color: var(--badge-warning-border);
}

.badge-status.status-critical {
  background: var(--badge-error-bg);
  color: var(--badge-error-fg);
  border-color: var(--badge-error-border);
}

.badge-status.status-paused {
  background: var(--badge-brand-bg);
  color: var(--badge-brand-fg);
  border-color: var(--badge-brand-border);
}

.badge-status .icon {
  width: var(--leading-xs);
  height: var(--leading-xs);
}

.dot {
  display: inline-block;
  flex: none;
  width: var(--pe-dot-size);
  height: var(--pe-dot-size);
  border-radius: var(--radius-full);
  background: var(--pe-status-unknown);
}

.dot.status-ok {
  background: var(--pe-status-ok);
}

.dot.status-degraded {
  background: var(--pe-status-degraded);
}

.dot.status-critical {
  background: var(--pe-status-critical);
}

.dot.status-offline {
  background: var(--pe-status-offline);
}

.dot.status-paused {
  background: var(--pe-status-paused);
}

/* a tile has one neutral frame all round; its state shows in the badge (symbol + text + colour), never as a
   coloured edge (the user's rule for Momentum Design Bronze, checked by test_css.py) */
.stat-tile {
  display: flex;
  flex-direction: column;
  gap: var(--spacing-xs);
  padding: var(--spacing-xl);
  background: var(--pe-surface-card);
  border: var(--pe-border-width) solid var(--color-border-secondary);
  border-radius: var(--radius-xl);
  box-shadow: var(--shadow-xs);
}

.stat-label {
  margin: 0;
  font-size: var(--text-xs);
  line-height: var(--leading-xs);
  font-weight: var(--font-weight-semibold);
  text-transform: uppercase;
  letter-spacing: var(--pe-letter-spacing-caps);
  color: var(--color-text-tertiary);
}

.stat-value {
  margin: 0;
  font-size: var(--display-xs);
  line-height: var(--leading-xl);
  font-weight: var(--font-weight-semibold);
  font-variant-numeric: tabular-nums;
}

.stat-detail,
.stat-facts {
  margin: 0;
  font-size: var(--text-sm);
  color: var(--color-text-tertiary);
}

.stat-facts div {
  display: flex;
  justify-content: space-between;
  gap: var(--spacing-md);
}

.stat-facts dt {
  color: var(--color-text-tertiary);
}

.stat-facts dd {
  color: var(--color-text-secondary);
}

.sparkline {
  width: var(--pe-sparkline-width);
  height: var(--pe-sparkline-height);
}

.sparkline-line {
  fill: none;
  stroke: var(--color-fg-brand-primary);
  stroke-width: var(--pe-sparkline-stroke);
  vector-effect: non-scaling-stroke;
}

.meter {
  width: var(--pe-sparkline-width);
}

/* ------------------------------------------------------------------ alerts, banners, empty states */

.flash-list {
  display: flex;
  flex-direction: column;
  gap: var(--spacing-md);
  margin-bottom: var(--spacing-xl);
}

.alert,
.banner {
  display: flex;
  align-items: flex-start;
  gap: var(--spacing-md);
  margin-bottom: var(--spacing-xl);
  padding: var(--spacing-lg) var(--spacing-xl);
  border: var(--pe-border-width) solid var(--badge-brand-border);
  border-radius: var(--radius-lg);
  background: var(--color-bg-brand-subtle);
  color: var(--color-text-primary);
}

.flash-list .alert {
  margin-bottom: 0;
}

.alert .icon,
.banner .icon {
  margin-top: var(--spacing-xxs);
  color: var(--color-fg-brand-primary);
}

.alert p,
.banner p {
  margin: 0;
}

.alert ul {
  margin: var(--spacing-xs) 0 0;
}

.alert-title {
  font-weight: var(--font-weight-semibold);
}

.alert-success {
  background: var(--color-bg-success-subtle);
  border-color: var(--badge-success-border);
}

.alert-success .icon {
  color: var(--color-fg-success-primary);
}

.alert-warning,
.banner-warning {
  background: var(--color-bg-warning-subtle);
  border-color: var(--badge-warning-border);
}

.alert-warning .icon,
.banner-warning .icon {
  color: var(--color-fg-warning-primary);
}

.alert-error {
  background: var(--color-bg-error-subtle);
  border-color: var(--badge-error-border);
}

.alert-error .icon {
  color: var(--color-fg-error-primary);
}

.empty-state {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--spacing-md);
  padding: var(--spacing-5xl) var(--spacing-3xl);
  color: var(--color-text-tertiary);
  text-align: center;
}

.empty-state > p {
  font-family: var(--font-family-serif);
  font-size: var(--text-lg);
  line-height: var(--leading-lg);
  font-weight: var(--font-weight-medium);
  color: var(--color-text-secondary);
}

/* ------------------------------------------------------------------ data views */

.key-value {
  display: grid;
  gap: var(--spacing-xs);
  margin-bottom: var(--spacing-xl);
}

.key-value-row {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 2fr);
  gap: var(--spacing-lg);
  padding-block: var(--spacing-xs);
  border-bottom: var(--pe-border-width) solid var(--color-border-secondary);
}

.key-value dt {
  color: var(--color-text-tertiary);
  font-size: var(--text-sm);
}

.code-block {
  max-height: var(--pe-scroll-max);
  overflow: auto;
  padding: var(--spacing-lg);
  margin-bottom: var(--spacing-xl);
  background: var(--pe-surface-code);
  border: var(--pe-border-width) solid var(--color-border-secondary);
  border-radius: var(--radius-lg);
  color: var(--color-text-primary);
}

.secret-value code {
  display: inline-block;
  padding: var(--spacing-md) var(--spacing-lg);
  font-size: var(--text-lg);
  letter-spacing: var(--pe-letter-spacing-code);
  background: var(--pe-surface-code);
  border: var(--pe-border-width) dashed var(--color-border-brand);
  border-radius: var(--radius-md);
  user-select: all;
}

.diff {
  margin-bottom: var(--spacing-xl);
  border: var(--pe-border-width) solid var(--color-border-secondary);
  border-radius: var(--radius-md);
  overflow-x: auto;
}

.diff-line {
  display: flex;
  gap: var(--spacing-md);
  padding-inline: var(--spacing-md);
}

.diff-op {
  flex: none;
  width: var(--pe-icon-size);
  font-family: var(--font-family-mono);
  color: var(--color-text-tertiary);
}

.diff-add {
  background: var(--pe-diff-add-bg);
}

.diff-remove {
  background: var(--pe-diff-remove-bg);
}

.timeline {
  list-style: none;
  margin: 0;
  padding: 0;
}

.timeline-item {
  display: flex;
  align-items: baseline;
  gap: var(--spacing-md);
  padding-block: var(--spacing-sm);
}

.timeline-title,
.timeline-meta {
  margin: 0;
}

.timeline-meta {
  font-size: var(--text-sm);
  color: var(--color-text-tertiary);
}

.breadcrumb ol {
  display: flex;
  flex-wrap: wrap;
  gap: var(--spacing-xs);
  list-style: none;
  margin: 0 0 var(--spacing-md);
  padding: 0;
  font-size: var(--text-sm);
}

.tabs ul {
  display: flex;
  flex-wrap: wrap;
  gap: var(--spacing-xs);
  list-style: none;
  margin: 0 0 var(--spacing-xl);
  padding: 0;
  border-bottom: var(--pe-border-width) solid var(--color-border-secondary);
}

.tab {
  display: inline-flex;
  padding: var(--spacing-md) var(--spacing-lg);
  margin-bottom: calc(var(--pe-border-width) * -1);
  font-size: var(--text-sm);
  line-height: var(--leading-sm);
  font-weight: var(--font-weight-medium);
  color: var(--color-text-secondary);
  text-decoration: none;
  border-bottom: var(--pe-focus-width) solid transparent;
}

.tab:hover {
  color: var(--color-text-primary);
}

.tab.active {
  color: var(--color-text-brand-primary);
  border-bottom-color: var(--color-border-brand);
  font-weight: var(--font-weight-semibold);
}

/* ------------------------------------------------------------------ live regions and CLI hints */

.live-region[aria-busy="true"] {
  opacity: 0.6;
  transition: opacity var(--pe-duration-normal) var(--pe-easing-standard);
}

.cli-hint {
  margin-bottom: var(--spacing-xl);
}

/* below a form the hint follows its last button, which has no distance of its own */
.form + .cli-hint {
  margin-top: var(--spacing-xl);
}

.cli-hint-title {
  display: flex;
  align-items: center;
  gap: var(--spacing-sm);
  margin-bottom: var(--spacing-xs);
  font-size: var(--text-sm);
  color: var(--color-text-tertiary);
}

.cli-hint .code-block {
  margin-bottom: 0;
}

.error-page {
  max-width: var(--pe-measure);
}

/* ------------------------------------------------------------------ simulator: station cards */

/* a card has one neutral frame all round like every card; the state of the station and of each connector
   shows in badges (symbol + text + colour), never as a coloured edge */
.sim-grid {
  display: grid;
  gap: var(--spacing-xl);
  grid-template-columns: repeat(auto-fill, minmax(min(var(--pe-sim-card-min), 100%), 1fr));
  margin-bottom: var(--spacing-3xl);
}

.sim-card {
  display: flex;
  flex-direction: column;
  gap: var(--spacing-lg);
  min-width: 0;
  padding: var(--spacing-xl);
  background: var(--pe-surface-card);
  border: var(--pe-border-width) solid var(--color-border-secondary);
  border-radius: var(--radius-xl);
  box-shadow: var(--shadow-sm);
}

.sim-card-head {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--spacing-sm) var(--spacing-md);
}

.sim-card-title {
  margin: 0;
  font-size: var(--text-md);
  line-height: var(--leading-md);
  overflow-wrap: anywhere;
}

.sim-card-label {
  margin: 0;
  color: var(--color-text-secondary);
  overflow-wrap: anywhere;
}

.sim-badges {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--spacing-xs);
}

.sim-note {
  font-size: var(--text-xs);
  line-height: var(--leading-xs);
  overflow-wrap: anywhere;
}

.sim-metrics {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--spacing-md);
  margin: 0;
}

.sim-metrics dt {
  font-size: var(--text-xs);
  line-height: var(--leading-xs);
  font-weight: var(--font-weight-semibold);
  text-transform: uppercase;
  letter-spacing: var(--pe-letter-spacing-caps);
  color: var(--color-text-tertiary);
}

.sim-metrics dd {
  font-size: var(--display-xs);
  line-height: var(--leading-xl);
  font-weight: var(--font-weight-semibold);
  font-variant-numeric: tabular-nums;
}

.sim-facts {
  display: grid;
  gap: var(--spacing-xs);
  margin: 0;
  font-size: var(--text-xs);
  line-height: var(--leading-xs);
}

.sim-facts div {
  display: flex;
  gap: var(--spacing-md);
  min-width: 0;
}

.sim-facts dt {
  flex: none;
  color: var(--color-text-tertiary);
}

.sim-facts dd {
  min-width: 0;
  color: var(--color-text-secondary);
  overflow-wrap: anywhere;
}

.sim-connectors {
  display: flex;
  flex-direction: column;
  gap: var(--spacing-md);
  list-style: none;
  margin: 0;
  padding: 0;
}

.sim-connector {
  display: flex;
  flex-direction: column;
  gap: var(--spacing-sm);
  padding: var(--spacing-md) var(--spacing-lg);
  background: var(--color-bg-secondary);
  border: var(--pe-border-width) solid var(--color-border-secondary);
  border-radius: var(--radius-lg);
}

.sim-connector-head {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--spacing-xs) var(--spacing-md);
}

.sim-connector-name {
  font-weight: var(--font-weight-semibold);
}

.sim-connector-meter {
  margin-inline-start: auto;
  font-size: var(--text-xs);
  font-variant-numeric: tabular-nums;
}

.sim-session {
  display: grid;
  gap: var(--spacing-xs);
  font-size: var(--text-xs);
  line-height: var(--leading-xs);
  color: var(--color-text-secondary);
}

.sim-session-row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--spacing-xs) var(--spacing-md);
}

.sim-bar {
  display: grid;
  gap: var(--spacing-xxs);
}

.sim-bar-text {
  font-size: var(--text-xs);
  line-height: var(--leading-xs);
  color: var(--color-text-tertiary);
}

/* the bar of a target or a state of charge: brand colour on the secondary surface, in every browser */
.sim-progress {
  display: block;
  width: 100%;
  height: var(--pe-sim-bar-height);
  appearance: none;
  border: 0;
  border-radius: var(--radius-full);
  background: var(--color-bg-tertiary);
  accent-color: var(--color-fg-brand-primary);
  overflow: hidden;
}

.sim-progress::-webkit-progress-bar {
  background: var(--color-bg-tertiary);
  border-radius: var(--radius-full);
}

.sim-progress::-webkit-progress-value {
  background: var(--color-fg-brand-primary);
  border-radius: var(--radius-full);
}

.sim-progress::-moz-progress-bar {
  background: var(--color-fg-brand-primary);
  border-radius: var(--radius-full);
}

/* a row of small forms and buttons (connect, autopilot, start, stop, ...) */
.sim-actions {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  gap: var(--spacing-sm);
}

.sim-actions > a {
  align-self: center;
}

.sim-inline-form {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  gap: var(--spacing-sm);
  margin: 0;
}

.sim-inline-form .field {
  flex: 0 1 auto;
  max-width: none;
  margin-bottom: 0;
}

/* the compact row of the simulator: field, select and the small button next to them share the small height */
.sim-inline-form .input {
  width: var(--pe-sim-field-width);
  height: var(--pe-control-height-sm);
  padding-block: var(--pe-control-pad-block-sm);
}

.sim-inline-form .select {
  width: auto;
  min-width: var(--pe-sim-field-width);
}

/* the field grid of a stacked form takes the whole width (a flex item would shrink to one column) */
.stack-form > .form-grid {
  width: 100%;
}

/* the value of a configuration key: one field and its button on one line, the label only for readers */
.sim-config-form {
  flex-wrap: nowrap;
  align-items: center;
}

.sim-config-form .input {
  width: var(--pe-sim-config-width);
}

.sim-inline-form .field label {
  font-size: var(--text-xs);
  line-height: var(--leading-xs);
}

.sim-card-foot {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--spacing-sm) var(--spacing-md);
  margin-top: auto;
  padding-top: var(--spacing-md);
  border-top: var(--pe-border-width) solid var(--color-border-secondary);
}

.sim-count {
  margin-bottom: var(--spacing-xl);
}

/* the detail of a station lists its connectors as the panels of the cards (no table: at 375 px nothing
   scrolls sideways); the name of a connector is a heading there, and its forms, fields and selects shrink
   to the width of the panel (at 320 px too) */
h3.sim-connector-name {
  margin: 0;
  font-size: var(--text-md);
  line-height: var(--leading-md);
}

.sim-connector .sim-inline-form .field {
  min-width: 0;
  max-width: 100%;
}

.sim-connector .sim-inline-form .select {
  max-width: 100%;
}

/* a form in a panel may shrink below the width of its longest option (a flex item does not by default) */
.sim-connector .sim-inline-form {
  min-width: 0;
}

/* ---------------------------------------------------------------- the infographic "Energie und Daten"
   (/server/flow). The figure chooses its composition by its own width (container query), not by the window:
   the wide one needs about 54rem to keep its labels near 12 px; below that the exploded view stands upright.
   The flows move by stroke-dashoffset; base.css stops every animation for "reduce motion". Faces, flows and
   labels take tokens only; a state shows as symbol and text as well, never by colour alone. */
.flow-head {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--spacing-md);
  margin-bottom: var(--spacing-lg);
}

.iso-frame {
  margin: 0;
  container-type: inline-size;
}

.iso {
  display: block;
  width: 100%;
  height: auto;
  font-family: var(--font-family);
}

.iso-wide {
  display: none;
  max-width: var(--pe-flow-wide-max);
  margin: 0 auto;
}

.iso-narrow {
  max-width: var(--pe-flow-narrow-max);
  margin: 0 auto;
}

@container (min-width: 54rem) {
  .iso-wide {
    display: block;
  }

  .iso-narrow {
    display: none;
  }
}

.iso-solid polygon {
  stroke: var(--pe-iso-edge);
  stroke-width: 1;
  stroke-linejoin: round;
}

.iso-solid .f-t { fill: var(--pe-iso-top); }
.iso-solid .f-l { fill: var(--pe-iso-left); }
.iso-solid .f-r { fill: var(--pe-iso-right); }
.plate .f-t { fill: var(--pe-iso-plate-top); }
.plate-net .f-t { fill: var(--pe-iso-net-top); }
.server-own .f-t { fill: var(--pe-iso-own-top); }
.bay-line { fill: var(--color-border-primary); }
.rack-slot { fill: none; stroke: var(--pe-iso-edge); stroke-width: 1; }
.rack-led { fill: var(--pe-status-ok); }
.grid-door { fill: var(--pe-iso-right); stroke: var(--pe-iso-edge); }
.grid-bolt { fill: var(--pe-flow-energy); }
.cp-screen { stroke: var(--pe-iso-edge); stroke-width: 1; }
.cp-screen-charging { fill: var(--pe-iso-charging); }
.cp-screen-connected { fill: var(--pe-iso-connected); }
.cp-screen-off { fill: var(--pe-iso-right); }
.cp-cap-charging .f-t, .mini-charging .f-t { fill: var(--pe-iso-charging); }
.cp-cap-connected .f-t, .mini-connected .f-t { fill: var(--pe-iso-connected); }
.cp-cap-off .f-t, .mini-off .f-t { fill: var(--pe-iso-off); }
.cp-off .f-t, .cp-off .f-l, .cp-off .f-r { fill-opacity: 0.55; }
.car .f-t, .car-cabin .f-t { fill: var(--pe-iso-car); }
.car .f-l, .car-cabin .f-l, .car .f-r, .car-cabin .f-r { fill: var(--pe-iso-car-side); }
.car-window { fill: var(--pe-iso-wheel); fill-opacity: 0.75; }
.iso-wheel { fill: var(--pe-iso-wheel); }

.flow, .flow-bed, .flow-glow, .cable {
  fill: none;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.flow-bed { stroke: var(--pe-flow-energy-bed); stroke-width: 3; }
.flow-glow { stroke: var(--pe-flow-energy-glow); }
.cable { stroke: var(--pe-iso-wheel); stroke-width: 2.5; }
.flow-energy { stroke: var(--pe-flow-energy); }
.flow-energy.is-active { stroke-dasharray: 9 7; animation: pe-flow 0.9s linear infinite; }
.flow-data { stroke: var(--pe-flow-data); stroke-dasharray: 7 6; }
.flow-mirror { stroke: var(--pe-flow-data); stroke-dasharray: 1.5 6; stroke-width: 3; }
.flow-data.is-active, .flow-mirror.is-active { animation: pe-flow-slow 1.6s linear infinite; }
.flow-off { stroke: var(--pe-flow-off); stroke-width: 2; stroke-dasharray: 2 5; }
.break circle { fill: var(--color-bg-primary); stroke: var(--pe-flow-off); stroke-width: 1.5; }
.break path { stroke: var(--pe-flow-off); stroke-width: 1.8; stroke-linecap: round; }

@keyframes pe-flow {
  to { stroke-dashoffset: -16; }
}

@keyframes pe-flow-slow {
  to { stroke-dashoffset: -13; }
}

.iso text { fill: var(--color-text-secondary); }
.iso .t-head, .iso .t-id { fill: var(--color-text-primary); font-weight: var(--font-weight-semibold); }
.iso .t-mono { font-family: var(--font-family-mono); }
.iso .t-strong { fill: var(--color-text-primary); }
.iso-card .card-bg { fill: var(--color-bg-primary); stroke: var(--color-border-primary); stroke-width: 1; }
.leader { stroke: var(--color-text-tertiary); stroke-width: 1; }
.leader-dot { fill: var(--color-text-tertiary); }
.iso-tag .tag-base { fill: var(--color-bg-primary); }
.iso-tag .tag-face { fill: var(--color-bg-brand-subtle); stroke: var(--pe-flow-data); stroke-width: 1; }
.iso-tag text { fill: var(--color-text-brand-primary); font-weight: var(--font-weight-semibold); }
.tag-mirror .tag-face { stroke-dasharray: 2 3; }
.tag-charging .tag-face, .tag-connected .tag-face, .tag-off .tag-face { fill: var(--color-bg-primary); stroke: var(--color-border-primary); }
.iso-tag.tag-charging text, .iso-tag.tag-connected text, .iso-tag.tag-off text { fill: var(--color-text-primary); }
.tag-energy .tag-face { fill: var(--color-bg-warning-subtle); stroke: var(--pe-flow-energy); }
.iso-tag.tag-energy text { fill: var(--color-text-primary); }

.ico circle { stroke-width: 1; }
.ico path { fill: none; stroke-width: 1.6; stroke-linecap: round; stroke-linejoin: round; }
.ico-charging circle { fill: var(--pe-iso-charging); stroke: var(--pe-flow-energy); }
.ico-charging path { fill: var(--color-text-primary); stroke: none; }
.ico-connected circle { fill: var(--pe-iso-connected); stroke: var(--color-fg-success-primary); }
.ico-connected path { stroke: var(--color-bg-primary); }
.ico-off circle { fill: var(--color-bg-tertiary); stroke: var(--pe-flow-off); }
.ico-off path { stroke: var(--pe-flow-off); }
.ico-fault circle { fill: var(--color-bg-error-subtle); stroke: var(--color-fg-error-primary); }
.ico-fault path { stroke: var(--color-fg-error-primary); stroke-width: 2; }

.flow-legend {
  display: flex;
  flex-wrap: wrap;
  gap: var(--spacing-md) var(--spacing-2xl);
  margin-top: var(--spacing-lg);
  color: var(--color-text-secondary);
  font-size: var(--text-xs);
}

.flow-legend-item {
  display: inline-flex;
  align-items: center;
  gap: var(--spacing-md);
}

.flow-legend-item svg {
  width: calc(var(--pe-icon-size) * 2.25);
  height: calc(var(--pe-icon-size) * 0.75);
  overflow: visible;
}

.flow-legend-item svg.flow-legend-icon {
  width: calc(var(--pe-icon-size) * 0.875);
  height: calc(var(--pe-icon-size) * 0.875);
}

.flow-number {
  display: inline-block;
  min-width: calc(var(--pe-icon-size) * 1.5);
  color: var(--color-text-tertiary);
}

.flow-route {
  margin-top: var(--spacing-xs);
  color: var(--color-text-tertiary);
  font-size: var(--text-xs);
  line-height: var(--leading-xs);
}
