/* Aligned with MapConfig/public/styles.css */
/* Figtree, served from /fonts (SIL Open Font License, fonts/OFL.txt): one variable file per
   style and subset, weights 300–900. */
@font-face {
  font-family: "Figtree";
  font-style: normal;
  font-weight: 300 900;
  font-display: swap;
  src: url("/fonts/figtree-latin-ext.woff2") format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C4, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

@font-face {
  font-family: "Figtree";
  font-style: normal;
  font-weight: 300 900;
  font-display: swap;
  src: url("/fonts/figtree-latin.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
  font-family: "Figtree";
  font-style: italic;
  font-weight: 300 900;
  font-display: swap;
  src: url("/fonts/figtree-italic-latin-ext.woff2") format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C4, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

@font-face {
  font-family: "Figtree";
  font-style: italic;
  font-weight: 300 900;
  font-display: swap;
  src: url("/fonts/figtree-italic-latin.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

:root {
  --bg: #f6f6f7;
  --text: #111827;
  --muted: #4b5563;
  --muted-light: #6b7280;
  --border: #e5e7eb;
  --border-strong: #d1d5db;
  --surface: #ffffff;
  --surface-alt: #fafafa;
  --surface-code: #f4f4f5;
  /* Highlight color: the style project's blue (style/src/page/palette.js). */
  --accent: #1f53ff;
  --accent-hover: color-mix(in srgb, var(--accent) 82%, black);
  --success: #059669;
  --success-bg: #ecfdf5;
  --warn: #d97706;
  --error: #dc2626;
  --error-bg: #fef2f2;
  --json-key: #1d4ed8;
  --json-string: #166534;
  --json-number: #b45309;
  --json-bool: #7c3aed;
  --json-null: #6b7280;
  --shadow: 0 1px 3px rgba(0, 0, 0, 0.08);
  /* Corner rounding for every box and button, as in the style project (0.2 × its 16px unit).
     Circles and pills keep their own. */
  --radius: 3.2px;
  /* The style project's grid: --cell is one unit (a button's height), --gutter the gap between
     units, so n units are n × cell + (n − 1) × gutter. --u sizes things inside a unit. */
  --u: 16px;
  --cell: 40px;
  --gutter: calc(var(--cell) / 8);
  /* The style project's green (style/src/page/palette.js): finished, online, go. */
  --green: #1fff57;
}

* {
  box-sizing: border-box;
}

/* Reserve the scrollbar so pages with and without scrolling line up identically. */
html {
  scrollbar-gutter: stable;
}

body {
  margin: 0;
  font-family: "Figtree", Arial, sans-serif;
  background: var(--bg);
  color: var(--text);
  line-height: 1.45;
}

/* Inline code (branch names, paths) in Figtree too; logs, JSON and the payload editor stay
   monospace so their columns line up. */
code {
  font-family: inherit;
}

main {
  margin: 0 auto;
  padding: 1rem;
  max-width: 1200px;
}

h1 {
  margin: 0 0 0.2rem;
  font-size: 1.35rem;
  font-weight: 600;
}

.subtitle {
  margin: 0;
  color: var(--muted);
  font-size: 0.875rem;
}

.subtitle code {
  font-size: 0.8125rem;
  background: var(--surface-code);
  padding: 0.15rem 0.35rem;
  border-radius: var(--radius);
}

.entry-links {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 1.25rem;
  margin: 0.5rem 0 1rem;
}

.entry-links a {
  font-size: 0.875rem;
  font-weight: 600;
  color: var(--accent);
  text-decoration: none;
}

.entry-links a:hover {
  text-decoration: underline;
}

.entry-links span {
  font-size: 0.875rem;
  color: var(--muted);
}

.entry-links code {
  font-size: 0.8125rem;
  background: var(--surface-code);
  padding: 0.15rem 0.35rem;
  border-radius: var(--radius);
}

#git-branch {
  font-weight: 300;
  border-radius: 999px;
  padding: 0.15rem 0.55rem;
}

section {
  margin-bottom: 1rem;
}

.panel {
  background: var(--surface);
  border-radius: var(--radius);
  padding: 1rem;
  box-shadow: var(--shadow);
}

.panel-head,
.section-head {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: 0.75rem 1rem;
  margin-bottom: 0.75rem;
}

.panel-head h2,
.section-head h2,
section > h2 {
  margin: 0;
  font-size: 0.68rem;
  font-weight: 600;
  letter-spacing: 0.02em;
  text-transform: uppercase;
  color: var(--muted-light);
}

section > h2 {
  margin-bottom: 0.75rem;
}

.clients-panel {
  padding: 0.65rem 0.85rem;
}

.clients-fold-header {
  display: flex;
  align-items: center;
  gap: 0.35rem;
  width: 100%;
  padding: 0;
  margin: 0 0 0.5rem;
  border: 0;
  background: none;
  color: inherit;
  cursor: pointer;
  text-align: left;
  font: inherit;
  font-weight: inherit;
  border-radius: 0;
}

.clients-fold-header:hover {
  background: none;
}

.clients-panel.collapsed .clients-fold-header {
  margin-bottom: 0;
}

.clients-fold-title {
  font-size: 0.68rem;
  font-weight: 600;
  letter-spacing: 0.02em;
  text-transform: uppercase;
  color: var(--muted-light);
}

.panel-fold-icon {
  flex-shrink: 0;
  font-size: 0.65rem;
  line-height: 1;
  color: var(--muted-light);
  transition: transform 0.15s ease;
}

.clients-panel.collapsed .panel-fold-icon {
  transform: rotate(-90deg);
}

.clients-panel.collapsed .clients-body {
  display: none;
}

.clients-panel .clients-body {
  font-size: 0.72rem;
}

.clients-panel th,
.clients-panel td {
  padding: 0.3rem 0.55rem;
}

.clients-panel th {
  font-size: 0.62rem;
}

.clients-panel td code {
  font-size: 0.68rem;
}

.clients-panel .client-dot {
  width: 7px;
  height: 7px;
  margin-right: 0.3rem;
}

.clients-panel .empty {
  padding: 0.65rem;
  font-size: 0.72rem;
}

button,
.btn-primary {
  font: inherit;
  font-weight: 600;
  padding: 0.5rem 1.25rem;
  border: 0;
  border-radius: var(--radius);
  background: var(--accent);
  color: #fff;
  cursor: pointer;
}

button:hover:not(:disabled),
.btn-primary:hover:not(:disabled) {
  background: var(--accent-hover);
}

button:disabled {
  opacity: 0.45;
  cursor: not-allowed;
}

button.secondary,
#clear-btn {
  padding: 0.4rem 0.9rem;
  font-size: 0.8rem;
  background: #f3f4f6;
  color: #374151;
  border: 1px solid var(--border-strong);
}

button.secondary:hover,
#clear-btn:hover {
  background: #e5e7eb;
  border-color: #9ca3af;
  color: #111827;
}

table {
  width: 100%;
  border-collapse: collapse;
}

th,
td {
  padding: 0.65rem 1rem;
  text-align: left;
  border-bottom: 1px solid var(--border);
}

th {
  font-size: 0.68rem;
  text-transform: uppercase;
  letter-spacing: 0.02em;
  color: var(--muted-light);
  font-weight: 600;
  background: var(--surface-alt);
}

tr:last-child td {
  border-bottom: none;
}

td code {
  font-size: 0.8125rem;
  background: var(--surface-code);
  padding: 0.15rem 0.35rem;
  border-radius: var(--radius);
}

.empty {
  padding: 1.5rem;
  text-align: center;
  color: var(--muted-light);
  background: var(--surface-alt);
  border: 1px dashed var(--border-strong);
  border-radius: var(--radius);
}

.client-dot {
  display: inline-block;
  width: 10px;
  height: 10px;
  border-radius: 50%;
  margin-right: 0.5rem;
  vertical-align: middle;
  flex-shrink: 0;
  box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.08);
}

.packet-list {
  display: flex;
  flex-direction: column;
  gap: 0.75rem;
}

.packet {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  overflow: hidden;
  box-shadow: var(--shadow);
}

.packet-meta {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.75rem 1.25rem;
  padding: 0.5rem 1rem;
  font-size: 0.8rem;
  color: var(--muted);
  border-bottom: 1px solid var(--border);
  background: var(--surface-alt);
}

.packet-from {
  display: inline-flex;
  align-items: center;
}

.packet-meta .badge {
  padding: 0.1rem 0.45rem;
  border-radius: var(--radius);
  font-size: 0.7rem;
  font-weight: 600;
  text-transform: uppercase;
}

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

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

pre.json,
.payload-editor {
  margin: 0;
  padding: 1rem;
  overflow-x: auto;
  font-family: "Cascadia Code", "Fira Code", Consolas, monospace;
  font-size: 0.82rem;
  line-height: 1.5;
  white-space: pre-wrap;
  word-break: break-word;
  background: var(--surface-code);
}

.payload-editor {
  display: block;
  width: 100%;
  min-height: 16rem;
  border: 1px solid var(--border-strong);
  border-radius: var(--radius);
  resize: vertical;
  color: var(--text);
}

.payload-editor:focus {
  outline: none;
  border-color: color-mix(in srgb, var(--accent) 45%, white);
  box-shadow: 0 0 0 2px color-mix(in srgb, var(--accent) 20%, transparent);
}

.payload-editor.invalid {
  border-color: #fca5a5;
  background: var(--error-bg);
}

.json-key {
  color: var(--json-key);
}

.json-string {
  color: var(--json-string);
}

.json-number {
  color: var(--json-number);
}

.json-bool {
  color: var(--json-bool);
}

.json-null {
  color: var(--json-null);
}

.json-punct {
  color: var(--muted-light);
}

.json-invalid {
  color: #b91c1c;
}

#live-indicator {
  color: var(--success);
}

#live-indicator.stale {
  color: var(--warn);
}

#ws-status {
  font-size: 0.875rem;
  color: var(--muted-light);
}

#ws-status.connected {
  color: var(--success);
}

#ws-status.error {
  color: var(--error);
}

.actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 1rem;
  margin-bottom: 1rem;
}

.sent-log {
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
}

.sent-entry {
  font-size: 0.8rem;
  color: var(--muted);
  padding: 0.35rem 0;
  border-bottom: 1px solid var(--border);
}

.sent-entry:last-child {
  border-bottom: none;
}

.store-overview {
  list-style: none;
  padding-left: 0;
  margin: 0 0 1rem;
}

.store-overview li {
  margin: 0.2rem 0;
}

.store-overview pre {
  margin: 0;
  font-size: 0.75rem;
}

.store-overview > li:nth-child(odd) pre {
  margin-top: 0.65rem;
}

.store-overview .pair-a pre {
  background: var(--surface-alt);
}

.store-overview .pair-b pre {
  background: var(--surface-code);
}

.store-field {
  margin-bottom: 0.75rem;
}

.store-field label {
  display: block;
  font-size: 0.875rem;
  color: var(--muted);
  margin-bottom: 0.25rem;
}

.store-field input,
.store-field textarea {
  width: 100%;
  font: inherit;
  padding: 0.5rem;
  border: 1px solid var(--border-strong);
  border-radius: var(--radius);
}

.store-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  margin-bottom: 0.75rem;
}

#ws-log {
  font-size: 0.75rem;
  max-height: 12rem;
  overflow: auto;
  border: 1px solid var(--border-strong);
  background: var(--surface-alt);
  padding: 0.35rem 0.45rem;
  border-radius: var(--radius);
}

.log-line {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  margin: 0 0 0.35rem;
  padding-bottom: 0.3rem;
  border-bottom: 1px solid var(--border);
  line-height: 1.4;
}

.log-line:last-child {
  margin-bottom: 0;
  padding-bottom: 0;
  border-bottom: none;
}

.log-line-meta {
  flex-shrink: 0;
  font-family: inherit;
  color: var(--muted);
}

.log-json-inline {
  flex: 1 1 0;
  min-width: 0;
  font-family: "Cascadia Code", "Fira Code", Consolas, monospace;
  word-break: break-word;
}

#ws-log .json-key {
  color: var(--json-key);
}

#ws-log .json-str {
  color: var(--json-string);
}

#ws-log .json-num {
  color: var(--json-number);
}

#ws-log .json-bool,
#ws-log .json-null {
  color: var(--json-bool);
}

#store-files-list {
  margin: 0;
  padding-left: 1.1rem;
}

#store-files-list li {
  margin: 0.35rem 0;
}

/* Shared header (_header.html, injected by Server/page.js) — identical on every page. Across the
   whole page: title and branch on the left, the tabs in the middle; the empty third column keeps
   the tabs centred. When the title and all tabs don't fit, the tabs give way and shrink. Title and
   tabs share one row of the grid, one unit tall, one unit from the top and left of the page (and
   from the right, so the tabs stay centred). It stays at the top while the page scrolls under it,
   with half of the unit below its row on its own background so the view never touches the tabs. */
.site-header {
  position: sticky;
  top: 0;
  z-index: 30;
  display: grid;
  grid-template-columns: 1fr minmax(0, auto) 1fr;
  align-items: center;
  gap: calc(2 * var(--gutter));
  padding: var(--cell) var(--cell) calc(var(--cell) / 2);
  width: 100%;
  background: var(--bg);
}

/* Too narrow for both on one row: the tabs go under the title, clear of its descenders. */
@media (max-width: 900px) {
  .site-header {
    grid-template-columns: minmax(0, 1fr);
    row-gap: var(--u);
  }
}

.site-title {
  /* One grid unit tall, like the tabs: the capitals run from the tabs' top edge to their bottom edge,
     which is the baseline. Figtree's capitals are 0.7 em tall, and in a line one unit high at this
     size its baseline falls on the bottom of the line (0.4px under it). */
  height: var(--cell);
  margin: 0;
  font-size: calc(var(--cell) / 0.7);
  /* Figtree's lightest weight. */
  font-weight: 300;
  line-height: var(--cell);
  white-space: nowrap;
  color: var(--accent);
}

/* A letter of the title that is still turning to its new one (segmented.js) is a little see-through. */
.site-title .is-turning {
  opacity: 0.55;
}

/* The branch pill sits next to the title, its bottom on the title's baseline: the bottom of the
   one-unit row, where the tabs end too. */
.site-title-row {
  display: flex;
  align-items: flex-end;
  height: var(--cell);
  gap: calc(2 * var(--gutter));
}

.site-title-row .site-branch {
  display: flex;
}

/* The font's line box sits high in the short pill: 2px more on top centres the letters. */
.site-title-row #git-branch {
  padding: 2px 0.55rem 0;
}

.site-branch {
  margin: 0;
  font-size: 0.875rem;
  color: var(--muted);
}

/* A circle (up to two digits; a pill for "99+") with the number in the middle both ways. It keeps its size in the
   tab: no shrinking, and the tab labels' `min-width: 0` (.site-tabs a span) doesn't apply. Figtree's
   digits sit 0.08em above the middle of its line box; the top padding moves them down to it. */
.behind-badge,
.site-tabs a .behind-badge {
  display: inline-flex;
  flex: 0 0 auto;
  align-items: center;
  justify-content: center;
  min-width: 1.25rem;
  height: 1.25rem;
  margin-left: 0.35rem;
  padding: 0.155em 0.2rem 0;
  overflow: visible;
  box-sizing: border-box;
  border-radius: 999px;
  background: var(--accent);
  color: #fff;
  font-size: 0.6875rem;
  font-weight: 700;
  line-height: 1;
  text-decoration: none;
  vertical-align: middle;
}

/* On the blue fill of the current tab, the badge turns white so it still shows. */
.site-tabs a.lit .behind-badge {
  background: #fff;
  color: var(--accent);
}

.site-branch code {
  /* 0.4 of a grid unit tall, one and a half units wide (a longer branch name widens it). */
  display: inline-flex;
  align-items: center;
  justify-content: center;
  height: calc(0.4 * var(--cell));
  min-width: calc(1.5 * var(--cell) + 0.5 * var(--gutter));
  box-sizing: border-box;
  font-size: 0.6875rem;
  background: var(--surface-code);
  padding: 0 0.5rem;
  border-radius: var(--radius);
}

/* The page tabs: the style project's segmented control (style/src/ui/components.css
   `.ui-segmented`), one grid unit (--cell) tall, as wide as its tabs. segmented.js
   slides the accent fill (::before) to the current page. */
.site-tabs {
  --on-accent: #fff;
  /* Border and labels in the highlight color too; hover darkens a label. */
  --ink: var(--accent-hover);
  --dim: var(--accent);
  --line: var(--accent);
  position: relative;
  display: flex;
  align-items: stretch;
  width: fit-content;
  max-width: 100%;
  height: var(--cell);
  /* No inset: the fill of the current tab reaches the border. */
  padding: 0;
  box-sizing: border-box;
  overflow: hidden;
  border: 1px solid var(--line);
  border-radius: var(--radius);
}

.site-tabs::before {
  content: "";
  position: absolute;
  top: var(--fill-top, 0);
  height: var(--fill-height, 0);
  left: var(--fill-left, 0);
  right: var(--fill-right, 100%);
  border-radius: calc(var(--radius) - 1px);
  background: var(--accent);
}

.site-tabs a {
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  /* Every tab 8 × 18px (9 × --u) wide; never a scrollbar: on a narrow screen the tabs shrink and long
     labels end in an ellipsis. */
  flex: 0 1 auto;
  width: calc(9 * var(--u));
  min-width: 0;
  padding: 0 calc(0.6 * var(--u));
  border-radius: calc(var(--radius) - 1px);
  font-size: 0.9375rem;
  font-weight: 600;
  white-space: nowrap;
  color: var(--dim);
  text-decoration: none;
}

/* The test pages hide behind the plus at the end of the bar (segmented.js). */
.site-tabs:not(.is-expanded) [data-more] {
  display: none;
}

.site-tabs-more {
  position: relative;
  flex: 0 0 var(--cell);
  padding: 0;
  border: 0;
  /* A line in the border's color between the tabs and the plus (or minus). */
  border-left: 1px solid var(--line);
  border-radius: 0;
  background: none;
  color: var(--dim);
  cursor: pointer;
}

.site-tabs-more:hover:not(:disabled) {
  background: none;
  color: var(--ink);
}

/* A plus, or a minus while the test pages show: 3px strokes with round caps, like the overview's
   section headings. */
.site-tabs-more::before {
  content: "";
  position: absolute;
  inset: 0;
  margin: auto;
  width: 14px;
  height: 14px;
  background: currentColor;
  -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 14 14'%3E%3Cpath d='M2 7h10M7 2v10' stroke='%23000' stroke-width='3' stroke-linecap='round'/%3E%3C/svg%3E") center / contain no-repeat;
  mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 14 14'%3E%3Cpath d='M2 7h10M7 2v10' stroke='%23000' stroke-width='3' stroke-linecap='round'/%3E%3C/svg%3E") center / contain no-repeat;
}

.site-tabs.is-expanded .site-tabs-more::before {
  -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 14 14'%3E%3Cpath d='M2 7h10' stroke='%23000' stroke-width='3' stroke-linecap='round'/%3E%3C/svg%3E");
  mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 14 14'%3E%3Cpath d='M2 7h10' stroke='%23000' stroke-width='3' stroke-linecap='round'/%3E%3C/svg%3E");
}

.site-tabs a span {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
}

.site-tabs a:hover:not(.lit) {
  color: var(--ink);
}

/* Lit: the fill is behind this tab right now (set by segmented.js). The other tabs are light. */
.site-tabs a:not(.lit) {
  font-weight: 300;
}

.site-tabs a.lit {
  color: var(--on-accent);
}

.site-header ~ main,
.site-header ~ .site-frame {
  width: calc(100% - 2rem);
  max-width: calc(1200px - 2rem);
  margin: calc(2 * var(--gutter)) auto 1.5rem;
  background: var(--surface);
  border: 1px solid var(--border-strong);
  border-radius: var(--radius);
}

/* One grid unit between the header's row (the title's baseline) and the view: half in the header,
   half here. */
.site-header ~ main {
  margin-top: calc(var(--cell) / 2);
}

/* The views fill the page from side to side, one unit in from the left like the title. */
.site-header ~ main.landing,
.site-header ~ main.deploy,
.site-header ~ main.style,
.site-header ~ main.monitor,
.site-header ~ main.logs {
  width: auto;
  max-width: none;
  margin-left: var(--cell);
  margin-right: 1rem;
}

/* Deploy, WS monitor and Logs stop two units from the right edge of the page. */
.site-header ~ main.deploy,
.site-header ~ main.style,
.site-header ~ main.monitor,
.site-header ~ main.logs {
  margin-right: calc(2 * var(--cell) + var(--gutter));
}

/* Deploy, WS monitor and Logs sit straight on the page, no box around them: their content lines up
   with the title. */
.site-header ~ main.deploy,
.site-header ~ main.style,
.site-header ~ main.monitor,
.site-header ~ main.logs {
  padding: 0;
  background: none;
  border: 0;
  border-radius: 0;
}

/* The WebSocket addresses on WS monitor in medium weight, the words around them thin so they stand
   out. */
main.monitor .subtitle {
  font-weight: 300;
}

main.monitor .subtitle code {
  font-weight: 500;
}

/* One unit between the live status and the connected clients. */
main.monitor .monitor-status {
  gap: var(--gutter);
  margin: calc(var(--cell) / 2) 0 var(--cell);
}

/* RunKiosk pages shown under the header */
body.framed {
  display: flex;
  flex-direction: column;
  height: 100vh;
}

body.framed .site-frame {
  flex: 1;
  display: block;
  margin-bottom: 1rem;
}

/* The views of the shared page (views/*.js) are custom elements: block boxes inside <main>. */
overview-view,
project-details,
build-view,
style-view,
deploy-view,
monitor-view,
logs-view {
  display: block;
}

/* Landing page: a table of sections on the grid. A section's heading row is one and a half units
   tall (1.5 × cell + 0.5 × gutter), each link row one unit with a faint line above it. All lines run from edge
   to edge of the box. */
main.landing {
  --landing-inset: calc(0.75 * var(--cell));
  padding: 0;
  /* The grey heading rows follow the box's rounded corners. */
  overflow: hidden;
}

.landing-nav {
  display: flex;
  flex-direction: column;
}

.landing-group + .landing-group {
  border-top: 1px solid var(--border-strong);
}

.landing-group > summary {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  height: calc(1.5 * var(--cell) + 0.5 * var(--gutter));
  padding: 0 var(--landing-inset);
  box-sizing: border-box;
  background: #fafaff;
  font-size: 1.05rem;
  font-weight: 700;
  cursor: pointer;
  list-style: none;
  user-select: none;
}

.landing-group > summary::-webkit-details-marker {
  display: none;
}

.landing-group > summary:hover {
  color: var(--accent);
}

/* A plus on a folded section, a minus on an open one: 3px strokes with round caps, drawn as a
   mask so they take the heading's color. */
.landing-group > summary::before {
  content: "";
  flex-shrink: 0;
  width: 14px;
  height: 14px;
  background: currentColor;
  -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 14 14'%3E%3Cpath d='M2 7h10M7 2v10' stroke='%23000' stroke-width='3' stroke-linecap='round'/%3E%3C/svg%3E") center / contain no-repeat;
  mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 14 14'%3E%3Cpath d='M2 7h10M7 2v10' stroke='%23000' stroke-width='3' stroke-linecap='round'/%3E%3C/svg%3E") center / contain no-repeat;
}

.landing-group[open] > summary::before {
  -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 14 14'%3E%3Cpath d='M2 7h10' stroke='%23000' stroke-width='3' stroke-linecap='round'/%3E%3C/svg%3E");
  mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 14 14'%3E%3Cpath d='M2 7h10' stroke='%23000' stroke-width='3' stroke-linecap='round'/%3E%3C/svg%3E");
}

/* The rows reach the edges; their content keeps the headings' inset. */
.landing-group .landing-nav--group > .landing-link {
  padding: 0 var(--landing-inset);
  background: #fff;
  border-top: 1px solid var(--border);
  border-radius: 0;
}

.landing-group .landing-link span {
  color: #d97706;
}

.landing-group .landing-link:hover span {
  color: #b45309;
}

.landing-group .landing-link--screen span {
  color: #0014cc;
}


.landing-group .landing-link--kiosk span {
  color: #166534;
}


.landing-link {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  height: var(--cell);
  padding: 0 0.75rem;
  box-sizing: border-box;
  border-radius: var(--radius);
  font-size: 0.95rem;
  /* The items in Figtree's thin weight; the section headings keep theirs. */
  font-weight: 300;
  color: #000;
  text-decoration: none;
}

/* Mapconfig gets a pentagon outline, kiosks a ring, screens a square outline: 3px, no fill, in a
   1.1em slot. The pentagon is a clip path: a regular pentagon minus the same one 3px further in
   (each corner moves 3px / cos 36° = 3.708px towards the middle). */
.landing-link--config::before {
  content: "";
  flex-shrink: 0;
  width: 1em;
  height: 1em;
  margin: 0 0.05em;
  background: #d97706;
  clip-path: polygon(evenodd,
    50.00% 4.77%, 97.55% 39.32%, 79.39% 95.23%, 20.61% 95.23%, 2.45% 39.32%, 50.00% 4.77%,
    50.00% calc(4.77% + 3.708px),
    calc(97.55% - 3.527px) calc(39.32% + 1.146px),
    calc(79.39% - 2.180px) calc(95.23% - 3.000px),
    calc(20.61% + 2.180px) calc(95.23% - 3.000px),
    calc(2.45% + 3.527px) calc(39.32% + 1.146px),
    50.00% calc(4.77% + 3.708px));
}

.landing-link--config:hover::before {
  background: #b45309;
}

.landing-link--kiosk::before,
.landing-link--screen::before {
  content: "";
  flex-shrink: 0;
  width: 0.8em;
  height: 0.8em;
  margin: 0 0.15em;
  box-sizing: border-box;
  border: 3px solid;
}

/* Same colors as the names. */
.landing-link--screen::before {
  border-color: #0014cc;
}

.landing-link--kiosk::before {
  border-radius: 50%;
  border-color: #166534;
}

.landing-link:hover {
  background: #fff;
  color: #000;
}

/* Hovering a screen or kiosk turns the row black. */
.landing-group .landing-link--screen:hover span,
.landing-group .landing-link--kiosk:hover span,
.landing-group .landing-link--screen:hover .landing-num,
.landing-group .landing-link--kiosk:hover .landing-num {
  color: #000;
}

.landing-link--screen:hover::before,
.landing-link--kiosk:hover::before {
  border-color: #000;
}

.landing-num {
  min-width: 1.6rem;
  padding: 0.05rem 0.5rem;
  border-radius: 999px;
  background: var(--surface-code);
  color: var(--muted);
  font-size: 0.8rem;
  font-weight: 700;
  text-align: center;
}

.landing-num--user,
.landing-num--screen {
  background: none;
  color: color-mix(in srgb, var(--muted) 40%, white);
  font-size: 0.68rem;
}

/* Names get one fixed-width column (fits "Screen horizontal"), so the user and screen
   numbers line up in fixed-width columns right after it on every row. */
.landing-link > span {
  min-width: 8rem;
}

/* No user number: skip its column (its width plus the link's gap). */
.landing-link > span + .landing-num--screen {
  margin-left: 2.7rem;
}

.landing-num--user {
  display: inline-flex;
  align-items: center;
  justify-content: flex-end;
  gap: 0.2rem;
  width: 2.2rem;
  padding: 0 0.15rem;
}

.landing-num--user svg {
  width: 0.8em;
  height: 0.8em;
}

.landing-num--screen {
  display: inline-flex;
  align-items: center;
  justify-content: flex-end;
  gap: 0.3rem;
  width: 2.2rem;
  padding: 0 0.15rem;
}

.landing-num--screen::before {
  content: "\2192";
  font-weight: 400;
}

.landing-link:hover .landing-num {
  background: color-mix(in srgb, var(--accent) 12%, white);
  color: var(--accent);
}

.landing-link:hover .landing-num--user,
.landing-link:hover .landing-num--screen {
  background: none;
}

.deploy-meta {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.5rem;
  margin: 0 0 1rem;
  font-size: 0.875rem;
}

.meta-pill {
  display: inline-flex;
  align-items: center;
  padding: 0.2rem 0.55rem;
  border-radius: 999px;
  border: 1px solid var(--border-strong);
  background: var(--surface);
}

.meta-pill--icon {
  gap: 0.35rem;
}

.meta-pill-icon {
  width: 14px;
  height: 14px;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.5;
  stroke-linecap: round;
  stroke-linejoin: round;
}

/* Time zone picker on the logs page */
.tz-picker {
  position: relative;
}

button.tz-button {
  font: inherit;
  font-weight: 400;
  color: var(--text);
  cursor: pointer;
}

button.tz-button:hover:not(:disabled),
button.tz-button[aria-expanded="true"] {
  background: var(--surface-code);
  border-color: var(--muted-light);
}

.tz-chevron {
  width: 12px;
  height: 12px;
  color: var(--muted-light);
}

.tz-popover {
  position: absolute;
  top: calc(100% + 6px);
  left: 0;
  z-index: 20;
  width: 20rem;
  max-width: calc(100vw - 32px);
  padding: 0.5rem;
  border-radius: var(--radius);
  border: 1px solid var(--border-strong);
  background: var(--surface);
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.14);
}

.tz-search {
  box-sizing: border-box;
  width: 100%;
  padding: 0.4rem 0.6rem;
  font: inherit;
  font-size: 0.85rem;
  border: 1px solid var(--border-strong);
  border-radius: var(--radius);
  background: var(--surface);
  color: var(--text);
}

.tz-search:focus {
  outline: 2px solid var(--accent);
  outline-offset: -1px;
}

.tz-list {
  position: relative;
  max-height: 18rem;
  margin-top: 0.4rem;
  overflow-y: auto;
}

.tz-group {
  position: sticky;
  top: 0;
  padding: 0.45rem 0.5rem 0.2rem;
  font-size: 0.68rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--muted-light);
  background: var(--surface);
}

.tz-option {
  display: flex;
  justify-content: space-between;
  gap: 0.75rem;
  padding: 0.3rem 0.5rem;
  border-radius: var(--radius);
  font-size: 0.85rem;
  cursor: pointer;
}

.tz-option.is-active {
  background: var(--surface-code);
}

.tz-option[aria-selected="true"] {
  font-weight: 700;
  color: var(--accent);
}

.tz-offset {
  flex-shrink: 0;
  color: var(--muted-light);
  font-variant-numeric: tabular-nums;
}

.tz-match,
.tz-local {
  font-size: 0.7rem;
  font-weight: 400;
  color: var(--muted-light);
}

.tz-list .empty {
  padding: 0.5rem;
  font-size: 0.8rem;
}

/* Deploy page, on the style project's grid: the box keeps the overview's inset, blocks sit two
   gutters apart, buttons are one unit tall and whole units wide (grid-snap.js), pills half a
   unit tall. */
/* Half a unit between the pills, the phase bar, the Deploy button and the log. */
main.deploy .deploy-meta {
  gap: var(--gutter);
  margin: 0 0 calc(var(--cell) / 2);
}

main.deploy .deploy-actions {
  margin-bottom: calc(var(--cell) / 2);
}

/* Half a unit under the phase bar too, and around the log's text. The caption under
   the bar takes no room while it is empty. */
main.deploy .deploy-progress {
  margin-bottom: calc(var(--cell) / 2);
}

main.deploy .deploy-progress-caption {
  min-height: 0;
}

main.deploy .deploy-progress-caption:has(> span:empty) {
  margin: 0;
}

main.deploy .deploy-log {
  padding: calc(var(--cell) / 2);
}

/* The status pills (Deploy, and live and updated on WS monitor) are three quarters of a unit tall. */
main.deploy .deploy-meta,
main.monitor .deploy-meta {
  height: calc(0.75 * var(--cell));
  line-height: calc(0.75 * var(--cell));
}

/* In every pill the label is medium and the value thin. A deploy target (the branch) other than
   main is in the highlight color. */
main.deploy .deploy-meta > *,
main.monitor .deploy-meta > * {
  gap: 0.35rem;
  font-weight: 300;
}

main.deploy .deploy-meta b,
main.monitor .deploy-meta b {
  font-weight: 500;
}

main.deploy .deploy-target-pill code.is-not-main {
  color: var(--accent);
}

main.deploy .server-status,
main.deploy .meta-pill,
main.monitor .meta-pill {
  height: calc(0.75 * var(--cell));
  padding: 0 calc(0.75 * var(--u));
  box-sizing: border-box;
}

main.deploy .panel {
  margin: 0;
  padding: 0;
  background: none;
  box-shadow: none;
}

.deploy-actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--gutter);
  margin-bottom: calc(2 * var(--gutter));
}

.deploy-btn,
.clear-log-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  height: var(--cell);
  padding: 0 calc(0.5 * var(--u));
  box-sizing: border-box;
  white-space: nowrap;
}

.deploy-btn {
  background: #0014cc;
  color: #fff;
}

.deploy-btn:hover:not(:disabled) {
  background: color-mix(in srgb, #0014cc 82%, black);
  color: #fff;
}

.clear-log-btn {
  background: transparent;
  color: var(--text);
  border: 1px solid var(--border-strong);
}

.clear-log-btn:hover:not(:disabled) {
  background: var(--accent);
  color: #fff;
  border-color: var(--accent);
}

.server-status {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  padding: 0.2rem 0.55rem;
  border-radius: 999px;
  border: 1px solid var(--border);
  background: var(--surface);
  font-weight: 600;
}

.server-status::before {
  content: "";
  width: 0.55rem;
  height: 0.55rem;
  border-radius: 50%;
  background: var(--muted-light);
}

.server-status--online {
  color: var(--text);
}

.server-status--online::before {
  background: var(--green);
}

.server-status--offline {
  color: var(--error);
  border-color: color-mix(in srgb, var(--error) 35%, var(--border));
}

.server-status--offline::before {
  background: var(--error);
}

.server-status--checking {
  color: var(--muted-light);
}

.deploy-log {
  margin: 0;
  min-height: 20rem;
  max-height: 70vh;
  overflow: auto;
  padding: var(--u);
  font-family: "Cascadia Code", "Fira Code", Consolas, monospace;
  font-size: 0.82rem;
  line-height: 1.5;
  white-space: pre-wrap;
  word-break: break-word;
  background: var(--surface-code);
  border: 1px solid var(--border-strong);
  border-radius: var(--radius);
  color: var(--text);
}

.deploy-progress {
  margin-bottom: calc(2 * var(--gutter));
}

.deploy-progress-bar {
  display: flex;
  gap: 3px;
  margin: 0;
  padding: 0;
  list-style: none;
}

.deploy-phase {
  flex: 1 1 0;
  min-width: 0;
}

.deploy-phase-btn {
  display: block;
  width: 100%;
  margin: 0;
  padding: 0 0 0.15rem;
  border: 0;
  border-radius: var(--radius);
  background: none;
  color: inherit;
  font: inherit;
  cursor: pointer;
}

.deploy-phase-btn:hover:not(:disabled) {
  background: none;
}

/* Keep the bar readable while a deploy runs (global button:disabled fades buttons). */
.deploy-phase-btn:disabled {
  opacity: 1;
  cursor: default;
}

.deploy-phase-btn:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

.deploy-phase-btn::before {
  content: "";
  display: block;
  height: 0.6rem;
  border-radius: var(--radius);
  background: var(--border-strong);
  transition: background-color 0.2s;
}

.deploy-phase:first-child .deploy-phase-btn::before {
  border-radius: 999px 2px 2px 999px;
}

.deploy-phase:last-child .deploy-phase-btn::before {
  border-radius: 2px 999px 999px 2px;
}

.deploy-phase--done .deploy-phase-btn::before {
  background: var(--green);
}

.deploy-phase--active .deploy-phase-btn::before {
  background: var(--accent);
  animation: deploy-phase-pulse 1.2s ease-in-out infinite;
}

.deploy-phase--failed .deploy-phase-btn::before {
  background: var(--error);
}

/* The animations below own the colours; the base colour fade would show through as grey. */
.deploy-phase--anim .deploy-phase-btn::before {
  transition: none;
}

/* Finished phase: green pushes the blue out to the right... */
.deploy-phase--anim.deploy-phase--done .deploy-phase-btn::before {
  background: linear-gradient(var(--accent), var(--accent)) right / 0% 100% no-repeat var(--green);
  animation: deploy-phase-out 0.6s cubic-bezier(0.76, 0, 0.24, 1);
}

/* ...and the blue slides into the next phase from the left, easing out slowly. */
.deploy-phase--anim.deploy-phase--active .deploy-phase-btn::before {
  background: linear-gradient(var(--accent), var(--accent)) left / 100% 100% no-repeat var(--border-strong);
  animation:
    deploy-phase-in 1.6s cubic-bezier(0.16, 1, 0.3, 1) backwards,
    deploy-phase-pulse 1.2s ease-in-out 1.6s infinite;
}

/* Handing over from a finished phase: the green leads, the blue follows a moment later. */
.deploy-phase--anim.deploy-phase--done + .deploy-phase--anim.deploy-phase--active .deploy-phase-btn::before {
  animation-delay: 0.15s, 1.75s;
}

/* The last phase has nothing to push into: it fades from blue to green instead. */
.deploy-phase--anim.deploy-phase--done:last-child .deploy-phase-btn::before {
  background: var(--green);
  animation: deploy-phase-fade 0.6s ease-in-out;
}

@keyframes deploy-phase-out {
  from {
    background-size: 100% 100%;
  }
}

@keyframes deploy-phase-fade {
  from {
    background-color: var(--accent);
  }
}

@keyframes deploy-phase-in {
  from {
    background-size: 0% 100%;
  }
}

.deploy-phase-label {
  display: block;
  margin-top: 0.3rem;
  overflow: hidden;
  font-size: 0.7rem;
  color: var(--muted-light);
  text-align: center;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.deploy-phase--active .deploy-phase-label {
  color: var(--accent);
  font-weight: 700;
}

/* Keep the label grey until the blue has filled the bar (timings match the fill above). */
.deploy-phase--anim.deploy-phase--active .deploy-phase-label {
  animation: deploy-phase-label-wait 1.6s step-end;
}

.deploy-phase--anim.deploy-phase--done + .deploy-phase--anim.deploy-phase--active .deploy-phase-label {
  animation-duration: 1.75s;
}

@keyframes deploy-phase-label-wait {
  from,
  to {
    color: var(--muted-light);
    font-weight: 400;
  }
}

.deploy-phase-btn:hover:not(:disabled) .deploy-phase-label {
  color: var(--text);
}

.deploy-phase-btn:hover:not(:disabled)::before {
  filter: brightness(0.85);
}

.deploy-phase--skipped .deploy-phase-btn::before {
  opacity: 0.4;
}

.deploy-phase--failed .deploy-phase-label {
  color: var(--error);
  font-weight: 700;
}

.deploy-progress-caption {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  gap: 0 1rem;
  margin: 0.35rem 0 0;
  font-size: 0.85rem;
  color: var(--muted);
  min-height: 1.3em;
}

/* Darken rather than fade, so the running phase never turns pale against the white panel. */
@keyframes deploy-phase-pulse {
  50% {
    filter: brightness(0.7);
  }
}

@media (prefers-reduced-motion: reduce) {
  .deploy-phase--active .deploy-phase-btn::before,
  .deploy-phase--anim .deploy-phase-btn::before,
  .deploy-phase--anim .deploy-phase-label {
    animation: none !important;
  }
}

@media (max-width: 640px) {
  .deploy-phase-label {
    display: none;
  }

  .deploy-phase-btn {
    padding: 0.5rem 0;
  }
}

/* ── Logs page ── */
.logs-toolbar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 0.75rem 1rem;
  margin-bottom: 1rem;
}

.logs-toolbar-filters {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
}

.logs-meta {
  margin: 0;
}

/* The Logs page has its own highlight color (the header keeps the site's). */
main.logs {
  --accent: #0014cc;
  --accent-hover: color-mix(in srgb, var(--accent) 82%, black);
}

.logs-filter {
  display: inline-flex;
  flex-wrap: wrap;
  max-width: 100%;
  padding: 2px;
  gap: 2px;
  border-radius: var(--radius);
  border: 1px solid var(--border-strong);
  background: var(--surface);
}

.logs-filter button {
  font: inherit;
  font-size: 0.85rem;
  font-weight: 600;
  padding: 0.35rem 0.9rem;
  border: 0;
  border-radius: var(--radius);
  background: transparent;
  color: var(--muted);
  cursor: pointer;
}

.logs-filter button:hover:not(:disabled) {
  background: var(--surface-code);
  color: var(--text);
}

.logs-filter button[aria-pressed="true"],
.logs-filter button[aria-pressed="true"]:hover:not(:disabled) {
  background: var(--accent);
  color: #fff;
}

.logs-kiosk .section-head {
  margin-bottom: 0.25rem;
}

.logs-kiosk-total {
  font-size: 0.8rem;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
}

.logs-chart-scroll {
  overflow-x: auto;
}

/* Thin thumb in the line colour that picks up the accent under the pointer, as in the style components. */
.logs-chart-scroll,
.logs-table-scroll {
  scrollbar-gutter: stable;
  scrollbar-width: thin;
  scrollbar-color: var(--border-strong) transparent;
}

.logs-chart-scroll:hover,
.logs-table-scroll:hover {
  scrollbar-color: var(--muted-light) transparent;
}

.logs-chart-scroll::-webkit-scrollbar,
.logs-table-scroll::-webkit-scrollbar {
  width: 8px;
  height: 8px;
}

.logs-chart-scroll::-webkit-scrollbar-track,
.logs-chart-scroll::-webkit-scrollbar-corner,
.logs-table-scroll::-webkit-scrollbar-track,
.logs-table-scroll::-webkit-scrollbar-corner {
  background: transparent;
}

.logs-chart-scroll::-webkit-scrollbar-thumb,
.logs-table-scroll::-webkit-scrollbar-thumb {
  background-color: var(--border-strong);
  border: 2px solid transparent;
  background-clip: padding-box;
  border-radius: 999px;
}

.logs-chart-scroll::-webkit-scrollbar-thumb:hover,
.logs-table-scroll::-webkit-scrollbar-thumb:hover {
  background-color: var(--accent);
}

.logs-chart {
  display: block;
  font-family: inherit;
}

.logs-chart-grid {
  stroke: var(--border);
  stroke-width: 1;
}

.logs-chart-baseline,
.logs-chart-hourtick {
  stroke: var(--border-strong);
  stroke-width: 1;
}

.logs-chart-tick {
  font-size: 10px;
  fill: var(--muted-light);
  font-variant-numeric: tabular-nums;
}

.logs-chart-hour {
  font-size: 10px;
  fill: var(--muted-light);
  font-variant-numeric: tabular-nums;
}

.logs-chart-day {
  font-size: 11px;
  fill: var(--muted);
}

.logs-chart-bar {
  fill: var(--accent);
}

.logs-chart-bar.is-hover {
  fill: var(--accent-hover);
}

.logs-chart-hit {
  fill: transparent;
}

.logs-tooltip {
  position: fixed;
  z-index: 10;
  min-width: 10rem;
  padding: 0.5rem 0.65rem;
  border-radius: var(--radius);
  background: var(--surface);
  border: 1px solid var(--border-strong);
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.12);
  font-size: 0.8rem;
  pointer-events: none;
}

.logs-tooltip-title {
  color: var(--muted);
}

.logs-tooltip-value {
  font-weight: 700;
  margin-bottom: 0.15rem;
}

.logs-tooltip-row {
  display: flex;
  justify-content: space-between;
  gap: 1rem;
  color: var(--muted);
}

.logs-tooltip-row b {
  color: var(--text);
}

/* Date range: a video-editor style trim over the daily activity strip. */
.logs-scenarios .section-head {
  align-items: center;
}

.logs-range-head {
  display: flex;
  justify-content: flex-end;
  margin-bottom: 0.5rem;
}

.logs-range-label {
  font-size: 0.875rem;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
}

.range-slider {
  --thumb: 14px;
  position: relative;
  height: 28px;
}

/* Inset by half a thumb so day boundaries line up with the native thumb centres. */
.range-track {
  position: absolute;
  inset: 0 calc(var(--thumb) / 2);
  border-radius: var(--radius);
  background: var(--surface-alt);
  box-shadow: inset 0 0 0 1px var(--border);
  overflow: hidden;
}

.range-strip {
  position: absolute;
  inset: 3px 0 0;
  width: 100%;
  height: calc(100% - 3px);
}

.range-strip-bar {
  fill: var(--accent);
}

.range-dim {
  position: absolute;
  top: 0;
  bottom: 0;
  background: rgba(246, 246, 247, 0.78);
}

.range-dim--start {
  left: 0;
}

.range-dim--end {
  right: 0;
}

.range-selection {
  position: absolute;
  top: 0;
  bottom: 0;
  border-top: 3px solid var(--accent);
  border-bottom: 3px solid var(--accent);
  cursor: grab;
  touch-action: none;
}

.range-selection.is-dragging {
  cursor: grabbing;
  background: color-mix(in srgb, var(--accent) 8%, transparent);
}

.range-input {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  margin: 0;
  background: transparent;
  pointer-events: none;
  -webkit-appearance: none;
  appearance: none;
}

.range-input:focus {
  outline: none;
}

.range-input::-webkit-slider-runnable-track {
  height: 100%;
  background: transparent;
}

.range-input::-moz-range-track {
  height: 100%;
  background: transparent;
}

.range-input::-webkit-slider-thumb {
  -webkit-appearance: none;
  appearance: none;
  width: var(--thumb);
  height: 28px;
  border: 0;
  border-radius: var(--radius);
  background: var(--accent) linear-gradient(90deg, transparent 5px, rgba(255, 255, 255, 0.85) 5px 6px, transparent 6px 8px, rgba(255, 255, 255, 0.85) 8px 9px, transparent 9px) no-repeat center / 100% 10px;
  cursor: ew-resize;
  pointer-events: auto;
}

.range-input::-moz-range-thumb {
  width: var(--thumb);
  height: 28px;
  border: 0;
  border-radius: var(--radius);
  background: var(--accent) linear-gradient(90deg, transparent 5px, rgba(255, 255, 255, 0.85) 5px 6px, transparent 6px 8px, rgba(255, 255, 255, 0.85) 8px 9px, transparent 9px) no-repeat center / 100% 10px;
  cursor: ew-resize;
  pointer-events: auto;
}

.range-input:focus-visible::-webkit-slider-thumb {
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 35%, transparent);
}

.range-input:focus-visible::-moz-range-thumb {
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 35%, transparent);
}

.range-ends {
  display: flex;
  justify-content: space-between;
  margin-top: 0.35rem;
  font-size: 0.75rem;
  color: var(--muted-light);
}

/* Scenario usage (Pulse) */
.logs-scenario-controls {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.5rem;
}

.logs-filter--small button {
  font-size: 0.8rem;
  padding: 0.25rem 0.7rem;
}

.logs-scenario-controls select {
  font: inherit;
  font-size: 0.85rem;
  max-width: 18rem;
  padding: 0.3rem 0.5rem;
  border: 1px solid var(--border-strong);
  border-radius: var(--radius);
  background: var(--surface);
  color: var(--text);
}

.logs-table-scroll {
  overflow-x: auto;
}

.scenario-table th,
.scenario-table td {
  padding: 0.45rem 0.75rem;
  font-size: 0.85rem;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

.scenario-table th {
  font-size: 0.68rem;
}

.scenario-table .num {
  text-align: right;
}

.scenario-table td.is-zero {
  color: var(--muted-light);
}

.scenario-table tbody tr {
  cursor: pointer;
}

.scenario-table tbody tr:hover td {
  background: var(--surface-alt);
}

.scenario-table tr[aria-selected="true"] td {
  background: color-mix(in srgb, var(--accent) 7%, white);
}

.scenario-table tr[aria-selected="true"] td:first-child {
  box-shadow: inset 3px 0 0 var(--accent);
}

.scenario-link {
  font: inherit;
  font-weight: 600;
  padding: 0;
  border: 0;
  background: none;
  color: var(--text);
  cursor: pointer;
  text-align: left;
}

.scenario-link:hover:not(:disabled) {
  background: none;
  color: var(--accent);
}

.scenario-starts {
  display: flex;
  align-items: center;
  gap: 0.5rem;
}

.scenario-bar {
  display: inline-block;
  height: 10px;
  min-width: 2px;
  border-radius: 0 var(--radius) var(--radius) 0;
  background: var(--accent);
}

/* ── CXC ── */

/* Overview: one section of project rows, its heading like a folded section's but fixed. */
.landing-head {
  display: flex;
  align-items: center;
  height: calc(1.5 * var(--cell) + 0.5 * var(--gutter));
  margin: 0;
  padding: 0 var(--landing-inset);
  background: #fafaff;
  font-size: 1.05rem;
  font-weight: 700;
}

.landing-empty {
  margin: 0;
  padding: var(--u) var(--landing-inset);
  color: var(--error);
}

/* Name, resolution and screen type in fixed columns. */
.project-row > span {
  min-width: 12rem;
}

.project-row em {
  font-style: normal;
  font-size: 0.85rem;
  color: var(--muted-light);
}

.project-row .project-res {
  min-width: 11rem;
  font-variant-numeric: tabular-nums;
}

.project-row:hover em {
  color: var(--text);
}

/* A project row folds open like a section: no disclosure triangle, the square marker filled while
   open. */
.project-item > summary {
  cursor: pointer;
  list-style: none;
  user-select: none;
}

.project-item > summary::-webkit-details-marker {
  display: none;
}

.project-item[open] > summary::before {
  background: #0014cc;
}

.project-item[open] > summary:hover::before {
  background: #000;
}

/* The details: the specs as a two-column list, the actions and the build log under it, in line
   with the row's name. */
project-details {
  padding: calc(var(--cell) / 4) var(--landing-inset) calc(var(--cell) / 2) calc(var(--landing-inset) + 1.1em + 0.5rem);
  background: #fff;
}

.project-specs {
  display: grid;
  grid-template-columns: 8rem 1fr;
  gap: var(--gutter) var(--u);
  margin: 0 0 calc(var(--cell) / 2);
  font-size: 0.95rem;
}

.project-specs dt {
  font-weight: 500;
  color: var(--muted-light);
}

.project-specs dd {
  display: flex;
  flex-wrap: wrap;
  gap: 0 var(--u);
  margin: 0;
  font-weight: 300;
}

/* The project's Wires boxes drawn as in Wires: screens blue, LEDs orange, each panel a box, a
   curved LED a ribbon. */
.project-shapes {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  gap: var(--u) var(--cell);
  margin: calc(var(--cell) / 4) 0 calc(var(--cell) / 2);
}

.project-shape {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: calc(var(--gutter) * 2);
  max-width: 100%;
  margin: 0;
}

.project-shape figcaption {
  font-size: 0.75rem;
  font-weight: 300;
  color: var(--muted-light);
}

.shape {
  --shape-tint: 46, 54, 217;
  display: flex;
  gap: 3px;
  max-width: 100%;
}

.shape--led {
  --shape-tint: 255, 111, 0;
}

.shape i {
  flex: 1 1 0;
  min-width: 0;
  border-radius: 2px;
  background: rgba(var(--shape-tint), 0.18);
  box-shadow: inset 0 0 0 1.5px rgba(var(--shape-tint), 0.6);
}

.shape--curve {
  height: auto;
  overflow: visible;
}

.shape--curve path {
  fill: rgba(255, 111, 0, 0.35);
  stroke: rgba(255, 111, 0, 0.75);
  stroke-width: 1.5;
}

/* One line per Wires box: the name, then its group and place on the grid. */
.project-specs dd.project-boxes {
  flex-direction: column;
  gap: var(--gutter);
}

.project-box {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 0.25rem var(--u);
}

.project-box-name {
  min-width: 14rem;
}

.project-box-prop {
  font-size: 0.875rem;
  color: var(--muted);
}

.project-box-prop b {
  font-weight: 500;
  color: var(--muted-light);
}

.project-specs code {
  font-size: 0.875rem;
}

.project-figma {
  color: var(--accent);
  font-weight: 500;
  text-decoration: none;
}

.project-figma:hover {
  text-decoration: underline;
}

project-details .deploy-actions {
  margin-bottom: 0;
}

project-details a.deploy-btn {
  text-decoration: none;
  border-radius: var(--radius);
}

project-details .project-unbuilt {
  height: var(--cell);
  color: var(--muted-light);
}

.project-log {
  margin-top: calc(var(--cell) / 2);
}

.project-log.is-failed {
  border-color: var(--error);
}

/* Style page: a category switch, then each group as a dark canvas showing the CXC styles. */
.style-cats {
  display: flex;
  gap: var(--gutter);
  margin-bottom: calc(var(--cell) / 2);
}

.style-cats a {
  display: inline-flex;
  align-items: center;
  height: var(--cell);
  padding: 0 calc(0.75 * var(--u));
  border: 1px solid var(--border-strong);
  border-radius: var(--radius);
  color: var(--text);
  text-decoration: none;
}

.style-cats a:hover {
  border-color: var(--accent);
  color: var(--accent);
}

.style-cats a.is-current {
  background: var(--accent);
  border-color: var(--accent);
  color: #fff;
}

.style-group {
  margin-bottom: var(--cell);
}

.style-group > h2 {
  margin: 0 0 calc(var(--cell) / 4);
  font-size: 1.05rem;
  font-weight: 700;
  letter-spacing: 0;
  text-transform: none;
  color: var(--text);
}

.style-group > h2 small {
  margin-left: var(--u);
  font-size: 0.8rem;
  font-weight: 300;
  color: var(--muted-light);
}

.style-canvas {
  padding: var(--cell);
  border-radius: var(--radius);
  background: var(--gradient-background);
  color: var(--text-primary);
}

.style-canvas + .style-canvas {
  margin-top: var(--gutter);
}

.style-canvas p {
  margin: 0;
}

.type-row {
  display: grid;
  grid-template-columns: 1fr 12rem 12rem;
  align-items: baseline;
  gap: var(--u);
  padding: calc(var(--cell) / 4) 0;
  border-bottom: 1px solid var(--border-grid);
}

.type-row:last-child {
  border-bottom: 0;
}

.type-row > code,
.type-row > span {
  font-size: 0.8rem;
  color: var(--text-tertiary);
}

.type-row > code {
  color: var(--text-primary);
}

.swatches {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(9rem, 1fr));
  gap: var(--cell) var(--u);
}

.swatches--wide {
  grid-template-columns: repeat(auto-fill, minmax(14rem, 1fr));
}

.swatch {
  margin: 0;
}

.swatch-chip {
  height: 5rem;
  border: 1px solid var(--border-glass);
  border-radius: 10px;
}

.swatches--wide .swatch-chip {
  height: 6rem;
}

.swatch figcaption {
  display: flex;
  flex-direction: column;
  margin-top: var(--gutter);
  font-size: 0.8rem;
}

.swatch figcaption span {
  color: var(--text-tertiary);
}

@media (max-width: 700px) {
  .type-row {
    grid-template-columns: 1fr;
    gap: 0;
  }
}

/* Style page, Components: each element on a stage at Figma size (440 × 260), scaled down. */
.comps {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(264px, 1fr));
  gap: calc(var(--cell) / 2) var(--u);
}

.comps--wide {
  grid-template-columns: 1fr;
}

.comp {
  margin: 0;
}

.comp-stage {
  position: relative;
  width: 440px;
  height: 260px;
  zoom: 0.6;
  overflow: hidden;
}

.comps--wide .comp-stage {
  width: 1376px;
  height: 240px;
  zoom: 0.5;
}

.comp figcaption {
  display: flex;
  flex-direction: column;
  margin-top: var(--gutter);
  font-size: 0.8rem;
}

.comp figcaption code {
  color: var(--text-tertiary);
}

/* More specific than the elements' own position: relative (elements.css loads after this file). */
.comp-stage > .comp-box {
  position: absolute;
  left: 40px;
  top: 20px;
  width: 360px;
  height: 220px;
}

.comp-stage > .comp-box--half {
  width: 170px;
}

.comp-orb {
  position: absolute;
  width: 180px;
  height: 130px;
  border-radius: 50%;
  background: var(--gradient-glow-soft);
  filter: blur(20px);
}

.comp-orb--wide {
  width: 260px;
  height: 170px;
}

.comp-stage > .comp-glass {
  position: absolute;
  top: 60px;
  width: 240px;
  height: 160px;
}

.comp-corners {
  display: flex;
  gap: 24px;
  padding-top: 84px;
}

.comp-corners span {
  width: 92px;
  height: 92px;
  background: var(--surface-glass);
  border: 2px solid var(--border-glass);
}

/* The pulse runs along its line. */
.comp-pulse-run {
  animation: comp-pulse-run 2.4s linear infinite;
}

@keyframes comp-pulse-run {
  from { transform: translateX(-380px) scaleX(-1); }
  to { transform: translateX(380px) scaleX(-1); }
}

@media (prefers-reduced-motion: reduce) {
  .comp-pulse-run {
    animation: none;
  }
}
