:root {
    --text: #1f2933;
    --muted: #616e7c;
    --line: #d9dee3;
    --accent: #1f5f8b;
    --danger: #a12b2b;
    --ok: #2e7d32;
    --nok-background: #fbe4e2;
    --background: #ffffff;
    --surface: #f5f7f9;
    --row-hover: #e1edfa;
    --nav-background: #12304f;
    --nav-text: #dfe8f1;
    --nav-hover: #1c4166;
    --nav-current: #2b6ca3;
    --nav-line: #2f5170;
    /* Categorical colors of chart series, in this fixed order (validated for color vision deficiency). */
    --series-1: #2a78d6;
    --series-2: #eb6834;
    --series-3: #1baf7a;
    --series-4: #eda100;
    --series-5: #e87ba4;
    --series-6: #008300;
    --series-7: #6250d6;
    --series-8: #e34948;
    --critical: #d03b3b;
    /* States of machines and sensors, always shown with a sign and a word as well. */
    --state-ok: #0ca30c;
    --state-warning: #fab219;
    --state-critical: #d03b3b;
    --state-no-data: #8a94a0;
    --chart-selection: rgba(31, 95, 139, .12);
    /* Periods of alarms and anomalies in the sensor charts, always with a label as well. */
    --period-alarm: rgba(208, 59, 59, .12);
    --period-anomaly: rgba(250, 178, 25, .2);
    --period-anomaly-line: #b7791f;
}
* { box-sizing: border-box; }
[hidden] { display: none !important; }
body { display: flex; margin: 0; font: 15px/1.5 system-ui, sans-serif; color: var(--text); background: var(--background); }
nav { flex: none; display: flex; flex-direction: column; gap: 2px; width: 200px; height: 100vh; position: sticky; top: 0; padding: 12px; overflow-y: auto; color: var(--nav-text); background: var(--nav-background); }
nav a, nav button.link { display: flex; align-items: center; gap: 10px; width: 100%; padding: 7px 10px; color: inherit; text-align: left; text-decoration: none; border-radius: 4px; }
nav a.sub { padding-left: 30px; font-size: 14px; }
nav a:hover, nav button.link:hover { background: var(--nav-hover); }
nav a[aria-current="page"] { color: #ffffff; font-weight: 600; background: var(--nav-current); }
nav a:focus-visible, nav button.link:focus-visible { outline: 2px solid #ffffff; outline-offset: 1px; }
nav form { margin: 0; }
nav .brand { padding: 4px 10px 12px; margin-bottom: 8px; font-size: 1.4em; font-weight: 700; color: #ffffff; border-bottom: 1px solid var(--nav-line); }
nav .account { display: flex; flex-direction: column; gap: 2px; margin-top: 12px; padding-top: 12px; border-top: 1px solid var(--nav-line); }
nav .brand { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
nav button.nav-toggle { display: inline-flex; padding: 6px; color: var(--nav-text); background: none; border-radius: 4px; }
nav button.nav-toggle:hover { background: var(--nav-hover); }
nav button.nav-toggle:focus-visible { outline: 2px solid #ffffff; outline-offset: 1px; }
/* Collapsed: only the icons; the names stay for screen readers and show as tooltip. */
nav.collapsed { width: 60px; padding: 12px 8px; }
nav.collapsed .brand { justify-content: center; padding: 0 0 12px; }
nav.collapsed .brand-name { display: none; }
nav.collapsed a, nav.collapsed button.link { justify-content: center; padding: 7px 0; }
nav.collapsed a span, nav.collapsed button.link span { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
.icon { flex: none; width: 18px; height: 18px; fill: none; stroke: currentColor; stroke-width: 1.6; stroke-linecap: round; stroke-linejoin: round; }
main { flex: 1; min-width: 0; padding: 16px; }
h1 { font-size: 22px; margin: 8px 0 16px; }
h2 { font-size: 17px; margin: 24px 0 8px; }
.table-wrap { overflow-x: auto; }
/* The list scrolls within itself (table-scroll.js); its header stays at the top. */
.table-wrap.scrolling { overflow: auto; border-bottom: 1px solid var(--line); }
/* Collapsed borders do not stick with the header, therefore its line is a shadow. */
.table-wrap.scrolling .data-table thead th { position: sticky; top: 0; z-index: 2; background: var(--background); border-bottom: 0; box-shadow: inset 0 -2px 0 var(--text); }
.game { display: block; width: 100%; height: calc(100vh - 110px); border: 0; }
table { width: 100%; border-collapse: collapse; }
th, td { padding: 6px 8px; border-bottom: 1px solid var(--line); text-align: left; vertical-align: middle; }
th { color: var(--muted); font-weight: 600; }
td form { display: inline; margin: 0; }
form.stacked { max-width: 480px; }
.field { margin-bottom: 12px; }
.field label { display: block; margin-bottom: 2px; color: var(--muted); }
.field.invalid input, .field.invalid select, .field.invalid textarea { border-color: var(--danger); box-shadow: 0 0 0 1px var(--danger); }
.field.invalid label, .field-error { color: var(--danger); }
.field-error { margin-top: 2px; font-size: 14px; }
.field.check label { display: inline; color: var(--text); }
.field .check label { display: inline; color: var(--text); }
input:not([type=checkbox]), select, textarea { width: 100%; padding: 6px 8px; font: inherit; border: 1px solid var(--line); border-radius: 4px; }
button, .button { display: inline-block; padding: 6px 12px; font: inherit; color: #fff; background: var(--accent); border: 0; border-radius: 4px; text-decoration: none; cursor: pointer; }
button.link { padding: 0; color: var(--accent); background: none; }
button.danger { background: var(--danger); }
.date-input { position: relative; display: flex; gap: 4px; }
.date-input input { flex: 1; min-width: 0; }
.date-input > button { flex: none; display: flex; align-items: center; padding: 6px 8px; }
.datepicker { position: absolute; top: 100%; left: 0; z-index: 20; width: 300px; max-width: calc(100vw - 16px); margin-top: 4px; padding: 8px; background: var(--background); border: 1px solid var(--line); border-radius: 6px; box-shadow: 0 4px 16px rgba(18, 48, 79, 0.25); }
.datepicker.above { top: auto; bottom: 100%; margin: 0 0 4px; }
.datepicker-header { display: flex; align-items: center; margin-bottom: 4px; }
.datepicker-title { flex: 1; font-weight: 600; text-align: center; }
.datepicker button.datepicker-nav { width: 36px; height: 36px; padding: 0; font-size: 20px; line-height: 1; color: var(--text); background: none; border-radius: 4px; }
.datepicker-table { table-layout: fixed; }
.datepicker-table th, .datepicker-table td { padding: 1px; border: 0; text-align: center; }
.datepicker-table .datepicker-week { width: 36px; font-size: 13px; color: var(--muted); font-weight: 400; background: var(--surface); }
.datepicker button.datepicker-day { width: 100%; height: 34px; padding: 0; color: var(--text); background: none; border: 1px solid transparent; border-radius: 4px; }
.datepicker button.datepicker-nav:hover, .datepicker button.datepicker-day:hover { background: var(--surface); }
.datepicker button.datepicker-day.outside { color: var(--muted); }
.datepicker button.datepicker-day.today { font-weight: 600; border-color: var(--accent); }
.datepicker button.datepicker-day.selected { color: #ffffff; background: var(--accent); }
.datepicker button:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
fieldset.field { min-width: 0; padding: 0; margin: 0 0 12px; border: 0; }
fieldset.field legend { padding: 0; margin-bottom: 2px; color: var(--muted); }
fieldset.field.invalid legend { color: var(--danger); }
.switch { position: relative; display: inline-flex; }
.switch input { position: absolute; width: 1px; height: 1px; margin: 0; opacity: 0; }
.switch label { display: block; min-width: 44px; padding: 6px 12px; margin: 0 0 0 -1px; color: var(--text); text-align: center; background: var(--background); border: 1px solid var(--line); cursor: pointer; }
.switch input:first-child + label { margin-left: 0; border-radius: 4px 0 0 4px; }
.switch label:last-child { border-radius: 0 4px 4px 0; }
.switch button { min-width: 44px; padding: 6px 12px; margin: 0 0 0 -1px; font: inherit; color: var(--text); background: var(--background); border: 1px solid var(--line); border-radius: 0; cursor: pointer; }
.switch button:first-child { margin-left: 0; border-radius: 4px 0 0 4px; }
.switch button:last-child { border-radius: 0 4px 4px 0; }
.switch button:hover { background: var(--surface); }
.switch button[aria-pressed="true"] { position: relative; color: #ffffff; font-weight: 600; background: var(--accent); border-color: var(--accent); }
.switch button:focus-visible { position: relative; outline: 2px solid var(--accent); outline-offset: 1px; }
.switch label:hover { background: var(--surface); }
.switch input:checked + label { position: relative; color: #ffffff; font-weight: 600; background: var(--accent); border-color: var(--accent); }
.switch input:focus-visible + label { position: relative; outline: 2px solid var(--accent); outline-offset: 1px; }
.field.invalid .switch label { border-color: var(--danger); }
.details { width: auto; min-width: 560px; }
.details th { width: 400px; font-weight: 400; color: var(--muted); }
.actions { display: flex; flex-wrap: wrap; align-items: center; gap: 16px; margin: 16px 0; }
.actions form { margin: 0; }
.field-row { display: flex; gap: 8px; }
.field-row .field:first-child { flex: 1; min-width: 0; }
.field-row .field:last-child { flex: none; width: 150px; }
.toolbar { display: flex; flex-wrap: wrap; align-items: flex-end; gap: 8px; margin-bottom: 12px; }
.toolbar .field { margin: 0; }
th.fit { width: 1%; white-space: nowrap; }
.icon-button { display: inline-flex; align-items: center; gap: 6px; }
.error { padding: 12px; margin-bottom: 16px; color: var(--danger); background: var(--surface); border-left: 3px solid var(--danger); }
.success { padding: 12px; margin-bottom: 16px; background: var(--surface); border-left: 3px solid var(--accent); }
a.sort { color: inherit; text-decoration: none; }
a.sort:hover { text-decoration: underline; }
.muted { color: var(--muted); }
.number { text-align: right; }
.nowrap { white-space: nowrap; }
.total td { font-weight: 600; border-top: 1px solid var(--text); }
.hint { margin-top: 8px; color: var(--danger); }
.data-table td.preview { max-width: 0; width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-family: ui-monospace, monospace; font-size: 13px; }
.data-table tbody tr:hover td { background: var(--row-hover); }
.page-size { display: flex; align-items: center; gap: 6px; margin: 0; }
.page-size label { display: inline; margin: 0; }
.page-size select { width: auto; padding: 3px 6px; }
.pager { display: flex; flex-wrap: wrap; align-items: center; gap: 16px; margin: 12px 0; }
.key-value { width: auto; min-width: 480px; }
.key-value th { width: 400px; font-weight: 400; color: var(--muted); white-space: nowrap; }
.key-value tr.branch th { font-weight: 600; color: var(--text); }
.key-value td { font-family: ui-monospace, monospace; font-size: 14px; word-break: break-word; }
pre.raw { padding: 12px; overflow-x: auto; background: var(--surface); border: 1px solid var(--line); border-radius: 4px; white-space: pre-wrap; word-break: break-all; }

@media (max-width: 640px) {
    body { flex-direction: column; }
    /* A bar at the top; the button opens the entries (nav.js). The collapsed state of wide screens does not apply. */
    nav, nav.collapsed { width: auto; height: auto; position: static; padding: 8px 12px; }
    nav .brand, nav.collapsed .brand { margin: 0; padding: 0; border-bottom: 0; }
    nav:not(.open) > :not(.brand) { display: none; }
    nav.open .brand { padding-bottom: 8px; margin-bottom: 4px; border-bottom: 1px solid var(--nav-line); }
    nav.collapsed a span, nav.collapsed button.link span { position: static; width: auto; height: auto; overflow: visible; clip: auto; }
    nav.collapsed .brand-name { display: inline; }
    nav.collapsed a, nav.collapsed button.link { justify-content: flex-start; padding: 7px 10px; }
}
[data-stale] { opacity: 0.5; }
tr[data-href] { cursor: pointer; position: relative; }
tr[data-href]:hover td { background: var(--row-hover); }
/* A link over the whole row (TableHtml.rowLink), invisible; the cells show no links. */
a.row-link { position: absolute; inset: 0; }
tr[data-href]:focus-visible { outline: 2px solid var(--nav-current); outline-offset: -2px; }
tr[data-live-key] td { transition: background 1s; }
tr.live-new td { background: #fff6d6; }
.tree-scroll { max-height: 70vh; overflow: auto; border: 1px solid var(--line); border-radius: 4px; }
.config-tree { padding: 4px 8px; }
.config-tree details { margin-left: 16px; }
.config-tree > details { margin-left: 0; }
.config-tree .changed { font-weight: 600; }
.config-tree summary { cursor: pointer; padding: 3px 0; font-weight: 600; }
.config-tree table.details { margin: 2px 0 6px; }
/* On narrow screens the label column of the detail views takes only the room it needs. */
@media (max-width: 700px) {
    .details, .key-value { min-width: 0; }
    .details th, .key-value th { width: auto; }
}
.warning { padding: 10px 14px; margin-bottom: 12px; border: 1px solid #e0b252; border-radius: 4px; background: #fff6d6; }
.warning p { margin: 0 0 4px; }
.warning ul { margin: 0; padding-left: 20px; }
.time-input { position: relative; display: flex; gap: 4px; max-width: 220px; }
.time-input input { flex: 1; min-width: 0; }
.time-input > button { flex: none; display: flex; align-items: center; padding: 6px 8px; }
.timepicker { position: absolute; top: 100%; left: 0; z-index: 20; width: 280px; max-width: calc(100vw - 16px); margin-top: 4px; padding: 8px; background: var(--background); border: 1px solid var(--line); border-radius: 6px; box-shadow: 0 4px 16px rgba(18, 48, 79, 0.25); }
.timepicker-label { margin: 4px 0 2px; font-size: 13px; color: var(--muted); }
.timepicker-grid { display: grid; grid-template-columns: repeat(6, 1fr); gap: 2px; }
.timepicker-halves { display: grid; grid-template-columns: 1fr 1fr; gap: 4px; margin-bottom: 4px; }
.timepicker button.timepicker-choice { padding: 6px 0; color: var(--text); background: var(--surface); border-radius: 4px; }
.timepicker button.timepicker-choice.selected { color: #ffffff; background: var(--nav-current); }
.error-text { color: var(--danger); }
/* Board of the start page */
.machine-board { margin-bottom: 28px; }
/* Production and IWall are half as wide as before; the events follow on the right. */
.board { display: grid; grid-template-columns: minmax(150px, 0.5fr) minmax(150px, 0.5fr) minmax(260px, 2fr) minmax(220px, 1fr); gap: 16px; align-items: start; }
@media (max-width: 1200px) { .board { grid-template-columns: minmax(150px, 1fr) minmax(150px, 1fr); } .board .stacking, .board .events { grid-column: 1 / -1; } }
@media (max-width: 600px) { .board { grid-template-columns: 1fr; } }
.board h3 { font-size: 15px; margin: 0 0 6px; }
.board h4 { font-size: 14px; font-weight: 600; margin: 0 0 4px; }
.pallets { display: grid; grid-template-columns: repeat(auto-fill, minmax(170px, 1fr)); gap: 12px; }
.wb-list { list-style: none; margin: 0; padding: 0; min-height: 36px; border: 1px solid var(--line); border-radius: 4px; background: var(--surface); }
.wb-list li { position: relative; background: var(--background); border-bottom: 1px solid var(--line); }
.wb-list li:last-child { border-bottom: 0; }
.wb-list li a { display: flex; align-items: center; gap: 6px; padding: 3px 8px; color: inherit; text-decoration: none; font-variant-numeric: tabular-nums; }
.wb-list li a:hover { background: var(--surface); }
/* The quality: a stripe on the left of the row, NOK rows tinted, the text on the right. */
.wb-list li { border-left: 4px solid var(--line); }
.wb-list li.ok { border-left-color: var(--ok); }
.wb-list li.nok { border-left-color: var(--danger); background: var(--nok-background); }
.wb-list li .tag { margin-left: auto; font-size: 12px; font-weight: 600; color: var(--muted); }
.wb-list li.ok .tag { color: var(--ok); }
.wb-list li.nok .tag { color: var(--danger); }
.wb-list li.moving { z-index: 2; box-shadow: 0 4px 12px rgba(0, 0, 0, 0.18); }
.wb-list li.moved { animation: wb-moved 2s ease-out; }
.wb-list li.entered { animation: wb-entered 0.6s ease-out; }
@keyframes wb-moved { from { background: #fff1b8; } }
@keyframes wb-entered { from { opacity: 0; } to { opacity: 1; } }
@media (prefers-reduced-motion: reduce) { .wb-list li.moved, .wb-list li.entered { animation: none; } }
.event-list { list-style: none; margin: 0; padding: 0; min-height: 36px; border: 1px solid var(--line); border-radius: 4px; background: var(--surface); }
.event-list li { background: var(--background); border-bottom: 1px solid var(--line); }
.event-list li:last-child { border-bottom: 0; }
.event-list li a { display: flex; flex-wrap: wrap; gap: 4px 8px; padding: 3px 8px; color: inherit; text-decoration: none; }
.event-list li a:hover { background: var(--surface); }
.event-list .event-time { font-variant-numeric: tabular-nums; color: var(--muted); }
.event-list li.entered { animation: wb-moved 2s ease-out; }
@media (prefers-reduced-motion: reduce) { .event-list li.entered { animation: none; } }
[data-board][data-stale] { opacity: 0.6; }
textarea.code { font: 13px/1.45 ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; white-space: pre; }
form.stacked:has(textarea.code) { max-width: 900px; }
/* Workspace of a drawing: toolbar on top, drawing in the middle, panel on the right, status line below. */
.workspace { display: grid; grid-template-columns: minmax(0, 1fr) 220px; grid-template-rows: auto minmax(0, 1fr) auto; height: max(360px, calc(100vh - 300px)); margin: 16px 0; border: 1px solid var(--line); border-radius: 6px; overflow: hidden; }
.workspace-toolbar { grid-column: 1 / -1; display: flex; flex-wrap: wrap; gap: 12px; padding: 6px 8px; background: var(--surface); border-bottom: 1px solid var(--line); }
.workspace .tool-group { display: flex; gap: 2px; }
.workspace .tool-group + .tool-group { padding-left: 12px; border-left: 1px solid var(--line); }
.workspace button.tool { display: inline-flex; align-items: center; gap: 6px; min-width: 34px; height: 32px; padding: 0 8px; color: var(--text); background: none; border: 1px solid transparent; border-radius: 4px; }
.workspace button.tool:hover { background: var(--background); border-color: var(--line); }
.workspace button.tool[aria-pressed="true"] { color: #ffffff; background: var(--accent); border-color: var(--accent); }
.workspace button.tool:focus-visible, .workspace-canvas:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }
.workspace-canvas { position: relative; min-width: 0; min-height: 0; background: #fbfcfd; touch-action: none; cursor: grab; }
.workspace-canvas.dragging { cursor: grabbing; }
.workspace-canvas svg { display: block; position: absolute; inset: 0; width: 100%; height: 100%; }
.workspace-canvas .grid-minor, .workspace-canvas .grid-major, .workspace-canvas .axis { fill: none; vector-effect: non-scaling-stroke; }
.workspace-canvas .grid-minor { stroke: #eceff2; stroke-width: 1; }
.workspace-canvas .grid-major { stroke: #d4dae0; stroke-width: 1; }
.workspace-canvas .axis { stroke: #9aa5b1; stroke-width: 1; }
.workspace-panel { grid-row: 2 / 4; grid-column: 2; padding: 10px 12px; overflow-y: auto; background: var(--surface); border-left: 1px solid var(--line); font-size: 14px; }
.workspace-panel-title { margin-bottom: 6px; font-weight: 600; }
.workspace-panel p { margin: 0; }
.workspace-status { display: flex; justify-content: space-between; gap: 16px; padding: 3px 8px; font-size: 13px; color: var(--muted); font-variant-numeric: tabular-nums; border-top: 1px solid var(--line); }
@media (max-width: 700px) {
    .workspace { grid-template-columns: minmax(0, 1fr); grid-template-rows: auto minmax(280px, 1fr) auto auto; height: auto; }
    .workspace-panel { grid-row: 4; grid-column: 1; border-left: 0; border-top: 1px solid var(--line); }
}
.workspace-canvas .marker circle, .workspace-canvas .marker path { fill: none; stroke: currentColor; stroke-width: 2; }
.workspace-canvas .marker text { font-size: 13px; font-weight: 600; fill: currentColor; paint-order: stroke; stroke: #fbfcfd; stroke-width: 3px; }
.workspace-canvas .marker.load { color: #1f7a3a; }
.workspace-canvas .marker.unload { color: #b3471d; }
.workspace-canvas .work-area { fill: none; stroke: #000000; stroke-width: 1.5; vector-effect: non-scaling-stroke; }
.workspace-panel .field { margin-bottom: 8px; }
.workspace-panel .work-area-fields { display: grid; grid-template-columns: 1fr 1fr; gap: 0 8px; }
.workspace-panel input[readonly] { background: var(--surface); }
.workspace-panel .error { padding: 8px; font-size: 13px; }
.workspace-canvas.moving { cursor: move; }
.workspace-canvas .seam-line { fill: none; stroke: #1f5f8b; stroke-width: 2; stroke-linejoin: round; vector-effect: non-scaling-stroke; }
.workspace-canvas .seam.selected .seam-line { stroke: #d9480f; stroke-width: 3; }
.workspace[data-mode="seams"] .seam-line { cursor: pointer; }
.workspace-canvas .seam-point rect { fill: #ffffff; stroke: #1f5f8b; stroke-width: 2; cursor: move; }
.workspace-canvas .seam.selected .seam-point rect { stroke: #d9480f; }
.workspace-canvas .seam-add { cursor: copy; }
.workspace-canvas .seam-add circle { fill: #ffffff; stroke: #1f5f8b; stroke-width: 1.5; }
.workspace-canvas .seam-add path { fill: none; stroke: #1f5f8b; stroke-width: 2; stroke-linecap: round; }
.workspace-canvas .seam-add:hover circle { fill: #1f5f8b; }
.workspace-canvas .seam-add:hover path { stroke: #ffffff; }
.workspace[data-editable="true"][data-mode="work-area"] .marker { cursor: move; }
.workspace-canvas .marker circle { fill: rgba(255, 255, 255, 0.7); }
.workspace button.tool.dirty { color: #ffffff; background: #d9480f; border-color: #d9480f; }
.workspace-panel .hint { margin-top: 8px; font-size: 13px; }
.workspace-panel .seam-list { margin: 0 0 8px; padding: 0; list-style: none; }
.workspace-panel .seam-item { display: flex; justify-content: space-between; gap: 8px; width: 100%; padding: 4px 6px; color: var(--text); text-align: left; background: none; border: 1px solid transparent; border-radius: 4px; }
.workspace-panel .seam-item:hover { background: var(--background); border-color: var(--line); }
.workspace-panel .seam-item[aria-pressed="true"] { border-color: #d9480f; background: var(--background); font-weight: 600; }
.workspace-panel .seam-new { margin-top: 4px; }
.workspace-canvas .seam-point.selected rect { fill: #d9480f; stroke: #d9480f; }
.workspace-panel .seam-actions { display: flex; flex-direction: column; align-items: flex-start; gap: 6px; }
.workspace-panel .seam-actions button[disabled] { opacity: 0.5; cursor: not-allowed; }
.workspace-panel-subtitle { margin: 6px 0 2px; font-weight: 600; }
.workspace-canvas .seam-tangent { stroke: #d9480f; stroke-width: 1; stroke-dasharray: 3 3; vector-effect: non-scaling-stroke; }
.workspace-canvas .seam-handle circle { fill: #ffffff; stroke: #d9480f; stroke-width: 1.5; cursor: move; }
.workspace-canvas .seam-handle:hover circle { fill: #d9480f; }
.workspace-canvas .graphic-frame { fill: none; stroke: #7048e8; stroke-width: 1; stroke-dasharray: 4 3; vector-effect: non-scaling-stroke; }
.workspace-canvas .graphic-handle rect { fill: #ffffff; stroke: #7048e8; stroke-width: 1.5; }
.workspace-canvas .graphic-handle[data-corner="nw"], .workspace-canvas .graphic-handle[data-corner="se"] { cursor: nwse-resize; }
.workspace-canvas .graphic-handle[data-corner="ne"], .workspace-canvas .graphic-handle[data-corner="sw"] { cursor: nesw-resize; }
.workspace:not([data-editable="true"]) .graphic-frame, .workspace:not([data-editable="true"]) .graphic-handle,
.workspace:not([data-mode="work-area"]) .graphic-frame, .workspace:not([data-mode="work-area"]) .graphic-handle { display: none; }
.workspace[data-editable="true"][data-mode="work-area"] .graphic image { cursor: move; }
.workspace-panel .graphic-name { margin: 0 0 4px; overflow-wrap: anywhere; }
.workspace-panel .graphic-file input[type=file] { width: 100%; margin-bottom: 6px; font-size: 13px; }
.workspace-panel .graphic-fields { margin-bottom: 8px; }
.workspace-panel .graphic-fields .icon-button { margin-top: 2px; }
.workspace { grid-template-rows: auto minmax(0, 1fr) auto auto; }
.workspace-panel { grid-row: 2 / 5; }
.workspace-simulation { display: flex; align-items: center; gap: 12px; padding: 4px 8px; background: var(--surface); border-top: 1px solid var(--line); }
.workspace:not([data-mode="simulation"]) .workspace-simulation { display: none; }
.workspace-simulation .simulation-time { flex: 1; min-width: 80px; padding: 0; border: 0; accent-color: var(--accent); }
.workspace-simulation .simulation-clock { flex: none; min-width: 110px; font-size: 13px; color: var(--muted); font-variant-numeric: tabular-nums; text-align: right; }
.workspace-simulation .speed { display: inline-flex; align-items: center; gap: 1px; font-size: 12px; font-weight: 600; }
.workspace:not([data-mode="simulation"]) g.simulation { display: none; }
.workspace-canvas .simulation-travel { fill: none; stroke: #868e96; stroke-width: 1.5; stroke-dasharray: 6 4; vector-effect: non-scaling-stroke; }
.workspace-canvas .simulation-weld { fill: none; stroke: #2f9e44; stroke-width: 3; vector-effect: non-scaling-stroke; opacity: 0.6; }
.workspace-canvas .weld-head circle { fill: none; stroke: #000000; stroke-width: 2.5; }
@media (max-width: 700px) {
    .workspace { grid-template-rows: auto minmax(280px, 1fr) auto auto auto; }
    .workspace-panel { grid-row: 5; }
}

/* Sensor charts (sensor-chart.js) */
.machine-choice { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; margin-bottom: 12px; }
.machine-choice .switch, fieldset.field .switch { flex-wrap: wrap; }
.sensor-chart .chart-toolbar { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; margin-bottom: 8px; }
.sensor-chart .chart-toolbar select { width: auto; }
.sensor-chart .chart-toolbar button { padding: 4px 10px; }
.sensor-chart .chart-toolbar .toggle { display: inline-flex; align-items: center; gap: 4px; color: var(--muted); cursor: pointer; }
.sensor-chart .chart-status { color: var(--muted); font-size: .9em; }
.sensor-chart[data-stale] .chart-status { color: var(--danger); }
.sensor-chart .chart-area { position: relative; height: min(460px, 60vh); border: 1px solid var(--line); border-radius: 4px; background: var(--background); }
.sensor-chart canvas { display: block; width: 100%; height: 100%; touch-action: none; }
.sensor-chart[data-sensor-chart="history"] canvas { cursor: crosshair; }
.sensor-chart .chart-tooltip { position: absolute; top: 8px; z-index: 2; max-width: 420px; padding: 6px 10px; font-size: .85em; pointer-events: none; color: var(--text); background: var(--background); border: 1px solid var(--line); border-radius: 4px; box-shadow: 0 2px 8px rgba(0, 0, 0, .12); }
.sensor-chart .chart-tooltip[hidden] { display: none; }
.sensor-chart .tooltip-time { margin-bottom: 2px; color: var(--muted); }
.sensor-chart .tooltip-row { white-space: nowrap; }
.sensor-legend { display: grid; grid-template-columns: repeat(auto-fill, minmax(260px, 1fr)); gap: 2px 16px; margin: 10px 0 0; padding: 0; list-style: none; }
.sensor-legend li { display: flex; align-items: baseline; gap: 6px; padding: 2px 0; }
.sensor-legend label { display: flex; flex-wrap: wrap; align-items: baseline; gap: 0 6px; cursor: pointer; }
.sensor-legend .range { color: var(--muted); font-size: .85em; }
.sensor-legend .current { font-variant-numeric: tabular-nums; font-weight: 600; }
.sensor-legend li.high .current, .sensor-legend li.low .current { color: var(--critical); }
.sensor-legend .forecast { color: var(--muted); font-size: .85em; }
.sensor-legend .forecast.soon { color: var(--danger); font-weight: 600; }
.key { display: inline-block; width: 16px; height: 0; margin-right: 4px; vertical-align: middle; border-top: 2px solid var(--series-1); }
.key.dashed { border-top-style: dashed; }
.key[data-slot="1"] { border-top-color: var(--series-2); }
.key[data-slot="2"] { border-top-color: var(--series-3); }
.key[data-slot="3"] { border-top-color: var(--series-4); }
.key[data-slot="4"] { border-top-color: var(--series-5); }
.key[data-slot="5"] { border-top-color: var(--series-6); }
.key[data-slot="6"] { border-top-color: var(--series-7); }
.key[data-slot="7"] { border-top-color: var(--series-8); }

/* Dashboard of a machine (machine-dashboard.js) */
.dashboard-head { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 8px 16px; margin-bottom: 12px; }
.dashboard-head > div { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 14px; }
.dashboard-head p { margin: 0; }
.machine-name { font-size: 1.15em; font-weight: 600; }
.machine-counts, .tile-counts { color: var(--muted); }
.operating { padding: 1px 8px; font-size: .9em; white-space: nowrap; border: 1px solid var(--line); border-radius: 4px; }
.machine-dashboard[data-stale] .machine-counts::after { content: " · keine Verbindung"; color: var(--danger); }
.health-badge { display: inline-flex; align-items: center; gap: 6px; padding: 2px 10px 2px 2px; font-weight: 600; white-space: nowrap; background: var(--surface); border: 1px solid var(--line); border-radius: 999px; }
.badge-symbol, .marker-symbol { display: inline-grid; place-items: center; flex: none; width: 22px; height: 22px; font-size: 13px; font-weight: 700; line-height: 1; color: #fff; border-radius: 50%; background: var(--state-no-data); }
.level-ok .badge-symbol, .level-ok .marker-symbol { background: var(--state-ok); }
.level-warning .badge-symbol, .level-warning .marker-symbol { color: #1f2933; background: var(--state-warning); }
.level-critical .badge-symbol, .level-critical .marker-symbol { background: var(--state-critical); }
.machine-stage { position: relative; max-width: 1200px; overflow: hidden; border: 1px solid var(--line); border-radius: 4px; }
.machine-image { display: block; width: 100%; height: auto; user-select: none; }
.sensor-marker { position: absolute; display: flex; align-items: flex-start; gap: 4px; color: var(--text); text-decoration: none; transform: translate(-15px, -15px); }
.sensor-marker .marker-symbol { width: 30px; height: 30px; font-size: 16px; border: 2px solid #fff; box-shadow: 0 1px 4px rgba(0, 0, 0, .35); }
.marker-text { display: flex; flex-direction: column; padding: 1px 6px; font-size: .75em; line-height: 1.3; white-space: nowrap; background: rgba(255, 255, 255, .93); border: 1px solid var(--line); border-radius: 4px; }
.marker-name { font-weight: 600; }
.marker-value { font-variant-numeric: tabular-nums; }
.marker-level { color: var(--muted); }
.level-critical .marker-level { color: var(--state-critical); font-weight: 600; }
.level-critical .marker-text { border-color: var(--state-critical); }
.level-warning .marker-text { border-color: var(--state-warning); }
.sensor-marker:hover .marker-text, .sensor-marker:focus .marker-text { border-color: var(--accent); }
.sensor-marker.level-critical .marker-symbol { animation: marker-pulse 1.6s ease-out infinite; }
@keyframes marker-pulse { 0% { box-shadow: 0 0 0 0 rgba(208, 59, 59, .55); } 100% { box-shadow: 0 0 0 12px rgba(208, 59, 59, 0); } }
@media (prefers-reduced-motion: reduce) { .sensor-marker.level-critical .marker-symbol { animation: none; } }
.sensor-marker.flip { flex-direction: row-reverse; transform: translate(calc(-100% + 15px), -15px); }
.unplaced { display: flex; flex-wrap: wrap; gap: 8px 16px; }
.unplaced .sensor-marker { position: static; flex-direction: row; transform: none; }
.dashboard-edit { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 12px; margin: 10px 0; }
.dashboard-edit .place-hint { display: none; }
.machine-dashboard.placing .place-hint { display: inline; }
.machine-dashboard.placing .sensor-marker { cursor: grab; touch-action: none; }
.machine-dashboard.placing .sensor-marker .marker-text { border-style: dashed; border-color: var(--accent); }
.sensor-marker.dragging { cursor: grabbing; z-index: 3; opacity: .85; }
.sensor-marker.unsaved .marker-text { border-color: var(--danger); }
/* State tiles of the machines on the start page */
.health-tiles { display: grid; grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); gap: 10px; margin: 0 0 20px; padding: 0; list-style: none; }
.health-tiles a { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 10px; height: 100%; padding: 10px 12px; color: var(--text); text-decoration: none; border: 1px solid var(--line); border-left-width: 5px; border-radius: 4px; }
.health-tiles a:hover { background: var(--surface); }
.health-tiles .tile-name { font-weight: 600; }
.health-tiles .tile-reason { flex-basis: 100%; color: var(--muted); font-size: .9em; }
/* Lists: the filter field below the name of each column, a menu per column, hidden columns behind a button. */
.table-toolbar { align-items: center; }
.table-toolbar form { display: flex; align-items: center; gap: 8px; margin: 0 0 0 auto; }
.data-table thead th { padding: 0; vertical-align: bottom; white-space: nowrap; color: var(--text); border-bottom: 2px solid var(--text); }
.data-table th .head { display: flex; align-items: center; gap: 2px; padding: 8px 2px 2px 8px; }
.data-table th .head a.sort { flex: 1; }
.data-table th.number .head a.sort { text-align: right; }
.data-table th.filtered a.sort { color: var(--accent); }
.data-table th .field { margin: 0; padding: 0 8px 6px; min-width: 90px; }
.data-table th .field input, .data-table th .field select { padding: 2px 4px; font-size: 14px; font-weight: 400; background: transparent; border: 0; border-bottom: 1px solid var(--line); border-radius: 0; }
.data-table th .field input:focus, .data-table th .field select:focus { outline: 0; border-bottom-color: var(--accent); box-shadow: 0 1px 0 var(--accent); }
.data-table th .field.invalid input, .data-table th .field.invalid select { border-bottom-color: var(--danger); box-shadow: 0 1px 0 var(--danger); }
.data-table th .field-error { white-space: normal; font-weight: 400; }
.data-table td { border-bottom-color: #e9edf1; }
button.column-menu-button { display: inline-flex; padding: 2px; color: var(--muted); background: none; border-radius: 4px; visibility: hidden; }
button.column-menu-button .icon { stroke-width: 3; }
.data-table th:hover .column-menu-button, .data-table th:focus-within .column-menu-button, .column-menu-button[aria-expanded="true"] { visibility: visible; }
button.column-menu-button:hover { color: var(--text); background: var(--surface); }
button.column-menu-button:focus-visible { outline: 2px solid var(--accent); outline-offset: 0; }
@media (hover: none) { button.column-menu-button { visibility: visible; } }
.column-menu, .column-chooser .popover { z-index: 30; min-width: 200px; padding: 6px; background: var(--background); border: 1px solid var(--line); border-radius: 6px; box-shadow: 0 6px 24px rgba(18, 48, 79, 0.16); }
.column-menu { position: absolute; }
.column-menu button { display: flex; width: 100%; padding: 6px 8px; color: var(--text); text-align: left; background: none; border-radius: 4px; }
.column-menu button:hover, .column-menu button:focus-visible { background: var(--surface); outline: 0; }
.column-menu button[disabled] { color: var(--muted); opacity: .5; cursor: default; background: none; }
.column-menu hr, .column-chooser hr { margin: 4px 0; border: 0; border-top: 1px solid var(--line); }
.column-chooser { position: relative; }
.column-chooser > summary { display: inline-flex; align-items: center; gap: 6px; padding: 4px 10px; font-size: 14px; color: var(--text); list-style: none; border: 1px solid var(--line); border-radius: 4px; cursor: pointer; }
.column-chooser > summary::-webkit-details-marker { display: none; }
.column-chooser > summary:hover, .column-chooser[open] > summary { border-color: var(--accent); }
.column-chooser > summary .icon { width: 16px; height: 16px; }
.column-chooser .popover { position: absolute; top: calc(100% + 4px); right: 0; }
.column-chooser .popover form, .column-chooser form { margin: 0; }
.column-chooser .popover { width: 300px; max-width: calc(100vw - 32px); padding: 10px; background: var(--surface); }
.column-chooser .column-hint { margin: 0 0 8px; font-size: 13px; }
.column-chooser .column-list { display: grid; gap: 3px; max-height: 60vh; margin: 0; padding: 0; overflow-y: auto; list-style: none; }
.column-chooser .column-list li { display: flex; align-items: center; gap: 8px; padding: 3px 6px; background: var(--background); border: 1px solid #e9edf1; border-radius: 4px; }
.column-chooser .column-list li[draggable="true"] { cursor: grab; }
.column-chooser .column-list li.off { opacity: .55; }
.column-chooser .column-list li.dragging { opacity: .3; }
.column-chooser .column-list .grip { color: var(--muted); letter-spacing: -2px; }
.column-chooser .column-list label { display: flex; flex: 1; align-items: center; gap: 6px; min-width: 0; margin: 0; color: var(--text); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; cursor: pointer; }
.column-chooser .column-list .move { display: flex; gap: 2px; }
.column-chooser .column-list .move button { padding: 0 4px; font-size: 12px; color: var(--muted); background: none; }
.column-chooser .column-list .move button:hover:not([disabled]) { color: var(--text); background: var(--surface); }
.column-chooser .column-list .move button[disabled] { opacity: .3; cursor: default; }
.column-chooser .column-actions { display: flex; justify-content: space-between; gap: 8px; padding: 6px 8px 2px; margin-top: 4px; border-top: 1px solid var(--line); }
.column-chooser .column-actions:empty { display: none; }
/* The filter of a time column: a button with the range, and its popup with beginning and end. */
.data-table th .range-field button.range-button { display: block; width: 100%; min-width: 120px; padding: 2px 4px; font-size: 14px; font-weight: 400; color: var(--text); text-align: left; background: transparent; border-bottom: 1px solid var(--line); border-radius: 0; }
.data-table th .range-field button.range-button.empty { color: var(--muted); }
.data-table th .range-field button.range-button:hover, .data-table th .range-field button.range-button[aria-expanded="true"] { border-bottom-color: var(--accent); }
.data-table th .range-field.invalid button.range-button { border-bottom-color: var(--danger); box-shadow: 0 1px 0 var(--danger); }
.range-popup { position: absolute; z-index: 30; width: 380px; max-width: calc(100vw - 16px); padding: 12px; background: var(--background); border: 1px solid var(--line); border-radius: 6px; box-shadow: 0 6px 24px rgba(18, 48, 79, 0.16); }
.range-popup .range-title { margin: 0 0 8px; font-weight: 600; }
.range-popup .range-row { display: grid; grid-template-columns: minmax(0, 1fr) 140px; gap: 8px; }
.range-popup .range-row .field { margin-bottom: 8px; }
.range-popup .range-hint { margin: 0 0 10px; font-size: 13px; }
.range-popup .range-actions { display: flex; align-items: center; gap: 16px; }

/* Reporting. The form shows only the fields of the chosen rhythm; without :has() it shows all, which still works. */
form.report-form { max-width: 640px; }
form.report-form fieldset.report-rhythm { margin: 0 0 12px; padding: 8px 12px 4px; border: 1px solid var(--line); border-radius: 4px; }
form.report-form fieldset.report-rhythm legend { padding: 0 4px; color: var(--muted); }
form.report-form .field-row .field, form.report-form .field-row .field:first-child, form.report-form .field-row .field:last-child { flex: 1; width: auto; min-width: 0; }
form.report-form:has(input[name=rhythm][value=ONCE]:checked) :is(.report-daily, .report-weekly, .report-recurring) { display: none; }
form.report-form:has(input[name=rhythm][value=DAILY]:checked) :is(.report-once, .report-weekly) { display: none; }
form.report-form:has(input[name=rhythm][value=WEEKLY]:checked) :is(.report-once, .report-daily) { display: none; }
form.report-mail { margin-top: 16px; }
.report-progress { display: flex; align-items: center; gap: 4px; }
.report-progress progress { width: 200px; }
@media (max-width: 600px) { form.report-form .field-row { flex-direction: column; gap: 0; } }
.button.secondary, button.secondary { color: var(--accent); background: var(--background); box-shadow: inset 0 0 0 1px var(--accent); }
/* Test-Data-Generator: the changes of state of a live generator, one small form per state */
.state-buttons { display: flex; flex-wrap: wrap; gap: 4px; }
.state-buttons form { margin: 0; }

/* HMI: the choice of machine and area as links in a switch, the live parts, the knob of the IWall. */
.hmi-choices { display: flex; flex-wrap: wrap; gap: 4px 24px; }
.switch a { display: block; min-width: 44px; padding: 6px 12px; margin: 0 0 0 -1px; color: var(--text); text-align: center; text-decoration: none; background: var(--background); border: 1px solid var(--line); }
.switch a:first-child { margin-left: 0; border-radius: 4px 0 0 4px; }
.switch a:last-child { border-radius: 0 4px 4px 0; }
.switch a:hover { background: var(--surface); }
.switch a[aria-current="page"] { position: relative; color: #ffffff; font-weight: 600; background: var(--accent); border-color: var(--accent); }
.notice { padding: 10px 14px; margin-bottom: 12px; border: 1px solid var(--line); border-left: 4px solid var(--ok); border-radius: 4px; background: var(--surface); }
.hmi-state { font-weight: 600; }
.hmi-setup input[type="text"] { width: 16em; max-width: 100%; }
.knob-form .field { display: flex; flex-wrap: wrap; align-items: center; gap: 12px; }
.knob-form .field > label { flex-basis: 100%; }
.knob { position: relative; width: 96px; height: 96px; }
.knob-dial { position: absolute; inset: 0; border: 2px solid var(--line); border-radius: 50%; background: radial-gradient(circle at 35% 35%, var(--background), var(--surface)); transform: rotate(var(--knob-angle, 0deg)); }
.knob-mark { position: absolute; top: 6px; left: calc(50% - 3px); width: 6px; height: 24px; border-radius: 3px; background: var(--accent); }
/* The range field lies invisibly over the dial: dragging sideways or the arrow keys turn it. */
.knob input[type="range"] { position: absolute; inset: 0; width: 100%; height: 100%; margin: 0; opacity: 0; cursor: ew-resize; }
.knob:focus-within .knob-dial { outline: 3px solid var(--accent); outline-offset: 2px; }
.knob-value { min-width: 4em; font-size: 1.25rem; font-weight: 600; font-variant-numeric: tabular-nums; }
