:root {
  color-scheme: light;
  /* Every patch table is this wide, on Mixer Channels, Inputs and Outputs alike.
     Fixed rather than stretching to fill, so a table looks the same whether the
     project has two mixers or six, and the sheet scrolls sideways once the tables
     no longer fit. Wide enough for the mixer's five columns; the I/O tables use
     the extra room on their four. Change this one value to resize them all. */
  --patch-table-width: 482px;
  /* The narrowest each patch-table column may be, and the one place those widths
     are written down: both virtual tables build their grid from these, and the
     phone breakpoint below only restates the numbers. A column can be made wider
     or narrower from its own header, which multiplies one of them by a factor in
     --patch-mixer-col-N / --patch-io-col-N and moves nothing else. */
  --patch-mixer-min-1: 56px;
  --patch-mixer-min-2: 120px;
  --patch-mixer-min-3: 110px;
  --patch-mixer-min-4: 100px;
  --patch-mixer-min-5: 96px;
  /* How the room left over is shared out, which a phone does differently. */
  --patch-mixer-fr-2: 1.25fr;
  --patch-mixer-fr-3: 1.15fr;
  --patch-mixer-fr-4: 1fr;
  --patch-mixer-fr-5: .9fr;
  --patch-io-min-1: 68px;
  --patch-io-min-2: 90px;
  --patch-io-min-3: 90px;
  --patch-io-min-4: 110px;
  --patch-io-fr-2: 1.25fr;
  --patch-io-fr-3: 1.25fr;
  --patch-io-fr-4: 1.6fr;
  --ink: #15171a;
  --muted: #68707c;
  --line: #d9dde3;
  --panel: #ffffff;
  --soft: #f4f6f8;
  --field: #fbfcfd;
  --brand: #126c6f;
  --brand-ink: #083d40;
  --accent: #c5542d;
  --focus: #2e7dd1;
  --ok: #237a48;
  --danger: #b53632;
  --shadow: 0 18px 45px rgba(22, 29, 37, 0.12);
  font-family:
    Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI",
    sans-serif;
}

* {
  box-sizing: border-box;
}

[hidden] {
  display: none !important;
}

body {
  margin: 0;
  min-height: 100vh;
  background:
    linear-gradient(180deg, rgba(255, 255, 255, 0.86), rgba(244, 246, 248, 0.96)),
    repeating-linear-gradient(
      90deg,
      rgba(18, 108, 111, 0.08) 0,
      rgba(18, 108, 111, 0.08) 1px,
      transparent 1px,
      transparent 72px
    );
  color: var(--ink);
}

body[data-environment="development"]::before {
  content: "DEV";
  position: fixed;
  z-index: 10000;
  right: 14px;
  bottom: 14px;
  padding: 7px 11px;
  border-radius: 999px;
  background: #7b2cbf;
  color: #fff;
  box-shadow: 0 6px 18px rgba(58, 20, 92, .28);
  font-size: .72rem;
  font-weight: 900;
  letter-spacing: .12em;
}

button,
input,
select,
textarea {
  font: inherit;
}

button {
  border: 0;
  cursor: pointer;
}

button:disabled,
select:disabled,
input:disabled {
  cursor: not-allowed;
  opacity: 0.55;
}

.app-shell {
  min-height: 100vh;
  display: flex;
  flex-direction: column;
}

.splash {
  min-height: 100vh;
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(360px, 520px);
  gap: 42px;
  align-items: center;
  padding: 44px clamp(22px, 6vw, 82px);
}

.splash-title {
  max-width: 780px;
}

.eyebrow {
  margin: 0 0 14px;
  color: var(--brand-ink);
  font-size: 0.82rem;
  font-weight: 800;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

h1 {
  margin: 0;
  font-size: clamp(3rem, 8vw, 7.25rem);
  line-height: 0.9;
  letter-spacing: 0;
}

.splash-title p {
  margin: 24px 0 0;
  max-width: 620px;
  color: #404852;
  font-size: 1.1rem;
  line-height: 1.6;
}

.splash-panel,
.panel,
.rack-card,
.channel-table,
.library-card,
.empty-state {
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: 8px;
  box-shadow: var(--shadow);
}

.splash-panel {
  padding: 24px;
}

.panel-header {
  display: flex;
  justify-content: space-between;
  gap: 16px;
  align-items: flex-start;
  margin-bottom: 18px;
}

.panel-header h2,
.panel-header h3 {
  margin: 0;
}

.panel-header p {
  margin: 6px 0 0;
  color: var(--muted);
  line-height: 1.45;
}

.project-list {
  display: grid;
  gap: 18px;
  margin: 18px 0 22px;
}

.project-browser-group {
  display: grid;
  gap: 10px;
}

.project-browser-group-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 0 2px;
}

.project-browser-group-header h3 {
  margin: 0;
  font-size: 0.95rem;
}

.project-browser-group-header span {
  color: var(--muted);
  font-size: 0.82rem;
  font-weight: 700;
}

.project-row {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  gap: 8px;
  align-items: stretch;
}

.project-button {
  display: flex;
  justify-content: space-between;
  gap: 14px;
  width: 100%;
  padding: 14px;
  text-align: left;
  color: var(--ink);
  background: var(--soft);
  border: 1px solid transparent;
  border-radius: 6px;
}

.project-button:hover,
.project-button:focus {
  border-color: var(--brand);
  outline: none;
}

.project-rename-button {
  align-self: stretch;
}

.project-row-actions {
  display: flex;
  gap: 8px;
}

.project-row-actions .button {
  align-self: stretch;
}

.project-name {
  font-weight: 800;
}

.project-meta,
.small-copy {
  color: var(--muted);
  font-size: 0.88rem;
}

.new-project-form,
.import-project-form {
  display: grid;
  gap: 12px;
  padding-top: 18px;
  border-top: 1px solid var(--line);
}

.import-project-form {
  margin-top: 16px;
}

.toolbar {
  min-height: 70px;
  display: flex;
  align-items: center;
  gap: 18px;
  padding: 14px 22px;
  background: #ffffff;
  border-bottom: 1px solid var(--line);
}

.brand-lockup {
  display: flex;
  align-items: center;
  gap: 12px;
}

.mark {
  width: 42px;
  height: 42px;
  flex: 0 0 42px;
}

.mark img {
  display: block;
  width: 100%;
  height: 100%;
}

.project-title {
  margin: 0;
  font-size: 1rem;
}

.save-state {
  color: var(--muted);
  font-size: 0.84rem;
}

.project-status-row {
  display: flex;
  align-items: center;
  gap: 8px;
}

.project-undo-controls {
  display: inline-flex;
  gap: 3px;
}

.project-undo-controls button {
  width: 24px;
  height: 22px;
  display: grid;
  place-items: center;
  padding: 0;
  color: var(--brand-ink);
  background: var(--soft);
  border: 1px solid var(--line);
  border-radius: 5px;
  font-size: 0.9rem;
  line-height: 1;
}

.project-undo-controls button:hover:not(:disabled) { border-color: var(--brand); }
.project-undo-controls button:disabled { color: var(--muted); opacity: 0.45; }

.tabs {
  display: flex;
  gap: 8px;
  padding: 12px 22px 0;
  overflow-x: auto;
  background: #fff;
}

.tab {
  padding: 11px 14px;
  color: #3d4651;
  background: transparent;
  border-bottom: 3px solid transparent;
  white-space: nowrap;
}

.tab.active {
  color: var(--brand-ink);
  border-color: var(--accent);
  font-weight: 800;
}

.workspace {
  width: min(1440px, 100%);
  margin: 0 auto;
  padding: 24px;
  flex: 1;
}

.panel {
  padding: 22px;
}

.grid-2 {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 16px;
}

.grid-3 {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 12px;
}

.field {
  display: grid;
  gap: 7px;
}

label {
  color: #333a43;
  font-size: 0.86rem;
  font-weight: 800;
}

input,
select,
textarea {
  width: 100%;
  min-height: 42px;
  padding: 9px 11px;
  color: var(--ink);
  background: var(--field);
  border: 1px solid #cfd5dc;
  border-radius: 6px;
}

textarea {
  min-height: 86px;
  resize: vertical;
}

input:focus,
select:focus,
textarea:focus {
  outline: 2px solid rgba(46, 125, 209, 0.28);
  border-color: var(--focus);
}

.button-row {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  align-items: center;
}

.toolbar-actions {
  margin-left: auto;
}

.toolbar-nav {
  margin-left: auto;
}

.toolbar-actions + .toolbar-nav {
  margin-left: 0;
}

.live-presence-stack {
  display: flex;
  align-items: center;
  padding-left: 8px;
}

.live-presence-avatar,
.live-presence-count {
  display: grid;
  place-items: center;
  width: 30px;
  height: 30px;
  margin-left: -8px;
  border: 2px solid var(--panel);
  border-radius: 50%;
  background: var(--brand);
  color: white;
  font-size: .68rem;
  font-weight: 700;
}

.live-presence-count { background: var(--ink); }

.history-workspace { display: grid; gap: 18px; }
.history-panel { padding: 22px; }
.history-grid { display: grid; grid-template-columns: minmax(0, .85fr) minmax(0, 1.15fr); gap: 18px; }
.history-list { display: grid; gap: 8px; margin-top: 12px; }
.history-row { display: flex; align-items: center; justify-content: space-between; gap: 16px; padding: 11px 12px; border: 1px solid var(--line); border-radius: 9px; background: var(--panel-soft); }
.history-row small { display: block; margin-top: 3px; color: var(--muted); }

.button {
  min-height: 40px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  padding: 9px 14px;
  color: #fff;
  background: var(--brand);
  border-radius: 6px;
  font-weight: 800;
}

.button.secondary {
  color: var(--brand-ink);
  background: #e8f2f2;
}

.toolbar .button.active:disabled {
  color: #fff;
  background: var(--brand);
  opacity: 1;
}

.button.warning {
  color: #fff;
  background: var(--danger);
}

.compact-button {
  justify-self: start;
  min-height: 34px;
  padding: 7px 10px;
  font-size: 0.84rem;
}

.icon-button {
  width: 38px;
  height: 38px;
  display: inline-grid;
  place-items: center;
  color: #3c4652;
  background: var(--soft);
  border: 1px solid var(--line);
  border-radius: 6px;
  font-weight: 900;
}

.icon-button.danger {
  color: #fff;
  background: var(--danger);
  border-color: var(--danger);
}

.icon-button.connect {
  color: var(--brand-ink);
  background: #e8f2f2;
}

.icon-button.connect.active {
  color: #fff;
  background: var(--accent);
  border-color: var(--accent);
}

.icon-button.mini {
  width: 24px;
  height: 24px;
  min-height: 24px;
  font-size: 0.72rem;
}

.system-map {
  position: relative;
}

.connection-canvas {
  position: absolute;
  inset: 0;
  z-index: 4;
  width: 100%;
  height: 100%;
  pointer-events: none;
}

/* The canvas is measured in screen pixels, so one user unit is one screen pixel at
   every zoom level - which left the lines and their labels at full size while the
   map they annotate shrank away underneath them. Multiplying by the zoom once more
   makes them part of the drawing instead of a layer floating over it. */
.connection-line {
  fill: none;
  stroke: var(--accent);
  stroke-width: calc(3px * var(--system-map-zoom, 1));
}

.connection-canvas marker path {
  fill: var(--accent);
}

.connection-label {
  fill: var(--brand-ink);
  paint-order: stroke;
  stroke: #fff;
  stroke-width: calc(5px * var(--system-map-zoom, 1));
  text-anchor: middle;
  font-size: calc(0.78rem * var(--system-map-zoom, 1));
  font-weight: 900;
}

.config-layout {
  position: relative;
  z-index: 1;
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 18px;
}

.system-column {
  min-width: 0;
}

.rack-list {
  display: grid;
  gap: 14px;
}

.add-system-row {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  gap: 10px;
  align-items: end;
  margin-bottom: 16px;
}

.rack-card {
  padding: 16px;
  box-shadow: none;
}

.system-node-card {
  position: relative;
  z-index: 2;
  min-height: 250px;
}

.system-node-card.connecting {
  border-color: var(--accent);
  box-shadow: 0 0 0 3px rgba(197, 84, 45, 0.16);
}

.connection-controls {
  display: grid;
  gap: 8px;
}

.endpoint-label-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
}

.endpoint-status {
  color: var(--brand-ink);
  font-size: 0.78rem;
  font-weight: 800;
}

.endpoint-status-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
}

.endpoint-status-list {
  display: grid;
  gap: 6px;
  margin-top: 10px;
}

.endpoint-port-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
  gap: 8px;
  margin: 12px 0;
}

.endpoint-port {
  padding: 9px;
  border: 1px solid var(--line);
  border-radius: 6px;
  background: var(--soft);
}

.endpoint-port strong,
.endpoint-port .small-copy {
  display: block;
}

.rack-card-head {
  display: flex;
  justify-content: space-between;
  gap: 12px;
  align-items: center;
  margin-bottom: 12px;
}

.rack-card-head strong {
  display: block;
}

.slot-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(210px, 1fr));
  gap: 12px;
}

.surface-channel-assignment {
  display: grid;
  gap: 7px;
  margin: 12px 0;
  padding: 11px 12px;
  border: 1px solid #c9d8d2;
  border-radius: 7px;
  background: #f4faf7;
}

.surface-channel-assignment.has-error {
  border-color: #d9a15c;
  background: #fff8ec;
}

.surface-channel-assignment-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
}

.surface-channel-assignment-head strong,
.surface-channel-assignment-head small {
  display: block;
}

.surface-channel-assignment-head small,
.surface-channel-assignment p {
  color: var(--muted);
  font-size: .74rem;
}

.surface-channel-assignment label {
  color: var(--brand-ink);
  font-size: .76rem;
  font-weight: 800;
}

.surface-channel-assignment input {
  min-width: 0;
}

.surface-channel-assignment p {
  margin: 0;
}

.surface-channel-assignment.has-error p {
  color: #8a541d;
  font-weight: 700;
}

.secondary-surface-card-note {
  display: grid;
  gap: 3px;
  margin-top: 12px;
  padding: 10px 12px;
  border: 1px dashed #c9b98b;
  border-radius: 7px;
  background: #fffaf0;
  color: #67531c;
  font-size: .76rem;
}

.secondary-surface-card-note span {
  color: var(--muted);
}

.nested-card-selector {
  display: grid;
  gap: 5px;
  margin-top: 8px;
  padding: 9px;
  border-left: 3px solid var(--brand);
  border-radius: 0 6px 6px 0;
  background: color-mix(in srgb, var(--brand) 7%, transparent);
}

.nested-card-selector label {
  color: var(--muted);
  font-size: 0.78rem;
}

.channel-table {
  overflow: hidden;
  box-shadow: none;
}

.requirements-mobile-tabs { display:none; }

.patch-subtabs {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin: 16px 0;
}

.subtab {
  border: 1px solid var(--line);
  background: #ffffff;
  color: var(--muted);
  border-radius: 6px;
  padding: 9px 12px;
  font-weight: 800;
  cursor: pointer;
}

.subtab.active {
  background: var(--brand-ink);
  border-color: var(--brand-ink);
  color: #ffffff;
}

.table-scroll {
  overflow-x: auto;
}

table {
  width: 100%;
  border-collapse: collapse;
  min-width: 920px;
}

th,
td {
  padding: 10px;
  border-bottom: 1px solid var(--line);
  text-align: left;
  vertical-align: top;
}

th {
  color: #3a414b;
  background: #eef2f4;
  font-size: 0.8rem;
  text-transform: uppercase;
}

td.channel-number {
  width: 70px;
  color: var(--brand-ink);
  font-weight: 900;
}

.compact-input {
  min-height: 36px;
}

.patch-mixer-select {
  min-width: 240px;
}

.io-inventory-table table {
  min-width: 760px;
}

.patch-block-scroll {
  overflow-x: auto;
  padding-bottom: 8px;
}

.patch-block-grid {
  display: grid;
  grid-auto-flow: column;
  /* Each block sets its own width, so the tracks follow their block and the spare
     room stays at the end rather than being spread between the tables. */
  grid-auto-columns: auto;
  justify-content: start;
  gap: 14px;
  align-items: start;
  width: max-content;
  min-width: 100%;
}

/* Every table is the same fixed width on Mixer Channels, Inputs and Outputs, and a
   project looks the same whether it has two desks or six. A table is never narrower
   than its own columns, though: a column sized from its header widens that one
   table - --patch-block-table-min is set on its block only - and the scroller takes
   it, rather than the block clipping it or every other table growing with it. */
.patch-block-grid > .patch-block {
  width: max(var(--patch-table-width), var(--patch-block-table-min, 0px));
}

.virtual-mixer-viewport,
.virtual-io-viewport {
  position: relative;
  max-height: min(68vh, 720px);
  min-height: min(52vh, 520px);
  overflow-y: auto;
  overflow-x: hidden;
  /* Contain the vertical axis only. Containing both stopped a sideways wheel or
     trackpad gesture from reaching the patch-sheet scroller, so with the pointer
     over a table you could scroll down but not across - which reads as the page
     being stuck rather than as a deliberate boundary. */
  overscroll-behavior-y: contain;
  overscroll-behavior-x: auto;
  background: #fff;
  /* The vertical bar sat on top of the row controls at the right edge of the
     source column. These viewports scroll vertically only, so hiding the bar
     costs nothing a wheel or trackpad does not already do; the patch sheet's
     horizontal bar is a different element and stays visible, because sideways
     is the axis where people need to see there is more. */
  scrollbar-width: none;
}

.virtual-mixer-viewport::-webkit-scrollbar,
.virtual-io-viewport::-webkit-scrollbar {
  display: none;
}

.virtual-mixer-header,
.virtual-mixer-canvas > [data-mixer-channel-row] {
  display: grid;
  /* Preserve the familiar production table proportions. Virtualization is a
     rendering optimization and must not redesign the patch sheet. */
  /* A column takes at least its minimum and then its weight of whatever room is
     left. Sizing one to its longest value from its header scales both of those by
     the same factor - the minimum alone would make every other column grow with it,
     and the weight alone stops mattering once the others are down to their own
     minimums. --patch-mixer-track-N carries the scaled pair. */
  grid-template-columns:
    var(--patch-mixer-track-1, var(--patch-mixer-min-1))
    var(--patch-mixer-track-2, minmax(var(--patch-mixer-min-2), var(--patch-mixer-fr-2)))
    var(--patch-mixer-track-3, minmax(var(--patch-mixer-min-3), var(--patch-mixer-fr-3)))
    var(--patch-mixer-track-4, minmax(var(--patch-mixer-min-4), var(--patch-mixer-fr-4)))
    var(--patch-mixer-track-5, minmax(var(--patch-mixer-min-5), var(--patch-mixer-fr-5)));
  width: 100%;
}

.virtual-mixer-header,
.virtual-io-column-header {
  position: sticky;
  z-index: 3;
  top: 0;
  min-height: 0;
  background: #eef2f4;
  border-bottom: 1px solid var(--line);
}

.virtual-mixer-header > span,
.virtual-io-column-header > span {
  display: block;
  min-width: 0;
  padding: 5px;
  border-right: 1px solid var(--line);
  color: var(--muted);
  font-size: .72rem;
  font-weight: 900;
  line-height: 1.2;
  text-transform: uppercase;
  text-align: left;
}

/* Tap a column header to size that column to its longest value, and again to put it
   back. The button fills the header cell so the whole label is the target, which is
   what a thumb needs, and it inherits the header's type so nothing about the row
   looks different. */
.column-width-handle {
  display: flex;
  align-items: center;
  gap: 4px;
  width: 100%;
  min-width: 0;
  min-height: 0;
  padding: 0;
  border: 0;
  background: none;
  color: inherit;
  font: inherit;
  letter-spacing: inherit;
  text-align: left;
  text-transform: inherit;
  cursor: pointer;
}

.column-width-handle > span:first-child {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.column-width-handle .column-width-mark {
  flex: 0 0 auto;
  opacity: .55;
  font-size: .62rem;
}

.column-width-handle.column-width-set .column-width-mark { color: var(--brand); opacity: 1; }
.column-width-handle:hover,
.column-width-handle:focus-visible { color: var(--brand-ink); }

.virtual-mixer-canvas {
  position: relative;
  min-width: 0;
}

.virtual-mixer-canvas > [data-mixer-channel-row] > td,
.virtual-io-canvas > tr > td {
  display: flex;
  min-width: 0;
  align-items: stretch;
  padding: 5px;
  border-right: 1px solid var(--line);
  border-bottom: 1px solid var(--line);
  background: #fff;
  font-size: 0.82rem;
}

/* The cell is a flex container, so a child only fills it if told to. This rule
   used to name `.patch-picker-trigger`, a class the markup stopped using, so the
   source picker sat at its content width in a cell far wider than itself while
   every text input beside it filled properly. */
.virtual-mixer-canvas > [data-mixer-channel-row] > td > .compact-input,
.virtual-mixer-canvas > [data-mixer-channel-row] > td > .patch-picker-control,
.virtual-io-canvas > tr > td > .compact-input,
.virtual-io-canvas > tr > td > .patch-picker-control {
  min-width: 0;
  width: 100%;
}

.virtual-io-canvas { position: relative; min-width: 0; }
.virtual-io-viewport.all-sections-collapsed {
  min-height: 0;
  overflow-y: hidden;
}
.virtual-io-canvas > [data-virtual-grid-id] { width: 100%; }
.virtual-io-canvas > tr,
.virtual-io-column-header {
  display: grid;
  grid-template-columns:
    var(--patch-io-track-1, var(--patch-io-min-1))
    var(--patch-io-track-2, minmax(var(--patch-io-min-2), var(--patch-io-fr-2)))
    var(--patch-io-track-3, minmax(var(--patch-io-min-3), var(--patch-io-fr-3)))
    var(--patch-io-track-4, minmax(var(--patch-io-min-4), var(--patch-io-fr-4)));
}
.virtual-mixer-canvas > [data-mixer-channel-row] .compact-input,
.virtual-io-canvas > tr .compact-input {
  min-height: 30px;
  padding: 5px 7px;
  font-size: 0.82rem;
}
.virtual-io-canvas > tr .patch-picker-value,
.virtual-io-canvas > tr .patch-picker-clear {
  min-height: 30px;
  font-size: 0.78rem;
}
.virtual-io-section-header {
  background: var(--patch-tint);
  border-bottom: 1px solid var(--line);
  color: var(--brand-ink);
  font-size: 0.74rem;
  font-weight: 900;
  letter-spacing: 0;
}
.virtual-io-section-header .patch-source-toggle {
  min-height: 0;
  padding: 5px;
  font-size: inherit;
  line-height: normal;
}

.patch-block {
  border: 1px solid var(--line);
  border-radius: 8px;
  overflow: hidden;
  background: #ffffff;
  --patch-tint: #eef2f4;
  --patch-tint-strong: #dfe7eb;
}

.patch-block-title {
  min-height: 36px;
  padding: 9px 11px;
  background: var(--patch-tint-strong);
  color: var(--brand-ink);
  font-weight: 900;
  font-size: 0.92rem;
}

.patch-block-subtitle {
  padding: 7px 11px;
  border-top: 1px solid var(--line);
  color: var(--muted);
  font-size: 0.78rem;
  text-align: center;
}

.patch-tone-0 {
  --patch-tint: #f3f7fb;
  --patch-tint-strong: #dfeaf5;
}

.patch-tone-1 {
  --patch-tint: #f4f8f1;
  --patch-tint-strong: #e2eed9;
}

.patch-tone-2 {
  --patch-tint: #fbf5ef;
  --patch-tint-strong: #f1e2d2;
}

.patch-tone-3 {
  --patch-tint: #f7f3fb;
  --patch-tint-strong: #e8def3;
}

.patch-tone-4 {
  --patch-tint: #f1f8f8;
  --patch-tint-strong: #d9eeee;
}

.patch-tone-5 {
  --patch-tint: #faf5f6;
  --patch-tint-strong: #efdfe4;
}

.patch-mini-table {
  min-width: 0;
  table-layout: auto;
}

.patch-mini-table th,
.patch-mini-table td {
  padding: 5px;
  font-size: 0.82rem;
}

.patch-mini-table th:first-child,
.patch-mini-table td:first-child {
  width: auto;
  max-width: none;
  text-align: center;
  white-space: nowrap;
}

.patch-mini-table th:nth-child(3),
.patch-mini-table td:nth-child(3) {
  width: auto;
  max-width: none;
  white-space: normal;
  overflow-wrap: anywhere;
}

.patch-mini-table th:nth-child(4),
.patch-mini-table td:nth-child(4) {
  width: auto;
  max-width: none;
  white-space: normal;
  overflow-wrap: anywhere;
}

.patch-mini-table .compact-input {
  min-height: 30px;
  font-size: 0.82rem;
  padding: 5px 7px;
}

.channel-move-cell {
  padding: 2px !important;
}

.channel-selection-toolbar {
  display: flex;
  gap: 12px;
  align-items: center;
  justify-content: flex-end;
  margin: 10px 0;
}

.keyboard-hint {
  display: inline-block;
  margin-left: 5px;
  padding: 1px 5px;
  border: 1px solid currentColor;
  border-radius: 4px;
  font-size: 0.68rem;
  line-height: 1.3;
  opacity: 0.65;
}

.channel-move-handle {
  display: inline-flex;
  gap: 5px;
  align-items: center;
  justify-content: center;
  width: auto;
  max-width: none;
  min-height: 28px;
  padding: 2px 4px;
  border: 0;
  border-radius: 5px;
  background: transparent;
  color: inherit;
  font: inherit;
  cursor: grab;
  touch-action: none;
}

.patch-picker-value {
  max-width: none;
  white-space: normal;
  overflow-wrap: anywhere;
}

.io-row-selected td {
  background: color-mix(in srgb, var(--brand) 13%, transparent);
}

.io-row-selected .channel-move-handle {
  background: var(--brand);
  color: #ffffff;
}

.io-row-selected .channel-grip {
  color: #ffffff;
  opacity: 0.8;
}

.io-row-drop-target td {
  border-top: 3px solid var(--brand);
}

.channel-move-handle:active {
  cursor: grabbing;
}

.channel-grip {
  display: inline-block;
  flex: 0 0 auto;
  color: var(--muted);
  font-size: 0.72rem;
  letter-spacing: -3px;
  opacity: 0.45;
}

.channel-move-handle:hover,
.channel-move-handle:focus-visible {
  background: color-mix(in srgb, var(--brand) 10%, transparent);
}

.mixer-channel-selected td {
  background: color-mix(in srgb, var(--brand) 13%, transparent);
}

.mixer-channel-selected .channel-move-handle {
  background: var(--brand);
  color: #ffffff;
}

.mixer-channel-selected .channel-grip {
  color: #ffffff;
  opacity: 0.8;
}

.mixer-channel-drop-target td {
  border-top: 3px solid var(--brand);
}

.patch-picker-control {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 28px;
  gap: 4px;
  align-items: stretch;
}

.patch-fill-cell {
  position: relative;
}

.patch-fill-cell:has(.double-patch-info) {
  padding-right: 29px;
}

.double-patch-info {
  position: absolute;
  top: 50%;
  right: 5px;
  z-index: 5;
  display: inline-flex;
  width: 18px;
  height: 18px;
  align-items: center;
  justify-content: center;
  transform: translateY(-50%);
  border: 1px solid color-mix(in srgb, var(--brand) 65%, transparent);
  border-radius: 50%;
  background: var(--panel);
  color: var(--brand);
  font-size: 0.7rem;
  font-weight: 700;
  cursor: help;
}

.double-patch-info::after {
  position: absolute;
  right: 0;
  bottom: calc(100% + 6px);
  width: max-content;
  max-width: min(280px, 70vw);
  padding: 6px 8px;
  border-radius: 6px;
  background: #20312c;
  color: #ffffff;
  box-shadow: 0 3px 10px rgba(20, 37, 32, 0.24);
  content: attr(data-tooltip);
  font-size: 0.72rem;
  font-weight: 500;
  line-height: 1.3;
  opacity: 0;
  overflow-wrap: anywhere;
  pointer-events: none;
  transform: translateY(2px);
  transition: opacity 45ms ease, transform 45ms ease;
  visibility: hidden;
}

.double-patch-info:hover::after,
.double-patch-info:focus-visible::after {
  opacity: 1;
  transform: translateY(0);
  visibility: visible;
}

.patch-fill-handle {
  position: absolute;
  right: 3px;
  bottom: 3px;
  z-index: 2;
  width: 11px;
  height: 11px;
  padding: 0;
  border: 0;
  border-right: 2px solid var(--brand);
  border-bottom: 2px solid var(--brand);
  border-radius: 0;
  background: transparent;
  box-shadow: none;
  cursor: ns-resize;
  touch-action: none;
  transition: transform 120ms ease, box-shadow 120ms ease;
}

.patch-fill-handle:hover,
.patch-fill-handle:focus-visible,
.config-fill-handle:hover,
.config-fill-handle:focus-visible {
  transform: scale(1.2);
  box-shadow: none;
}

.config-fill-cell {
  position: relative;
}

.config-fill-handle {
  position: absolute;
  right: 3px;
  bottom: 3px;
  z-index: 3;
  width: 9px;
  height: 9px;
  padding: 0;
  border: 0;
  border-right: 2px solid var(--brand);
  border-bottom: 2px solid var(--brand);
  border-radius: 0;
  background: transparent;
  box-shadow: none;
  cursor: ns-resize;
  opacity: 0.3;
  touch-action: none;
  transition: opacity 120ms ease, transform 120ms ease, box-shadow 120ms ease;
}

.config-fill-cell:hover .config-fill-handle,
.config-fill-cell:focus-within .config-fill-handle {
  opacity: 1;
}

/* Dragging a patched source down the Mixer Channels SOURCE column uses this set,
   not the config-fill one beside it. Same trap: the plain rule was
   `.patch-fill-target td`, which loses to the cell's own `background: #fff` at
   `.virtual-mixer-canvas > [data-mixer-channel-row] > td`, while the replace and
   remove modifiers happened to tie it and win on order. So dragging over empty
   channels showed nothing while changing or clearing them showed orange and red.
   Scoped the same way and in the right order now. */
.virtual-mixer-canvas > [data-mixer-channel-row].patch-fill-target > td {
  background: color-mix(in srgb, var(--brand) 14%, transparent);
  box-shadow: inset 3px 0 0 var(--brand);
}

.virtual-mixer-canvas > [data-mixer-channel-row].patch-fill-target.patch-fill-replace > td {
  background: color-mix(in srgb, #d99129 18%, transparent);
  box-shadow: inset 3px 0 0 #d99129;
}

.virtual-mixer-canvas > [data-mixer-channel-row].patch-fill-target.patch-fill-remove > td {
  background: rgba(181, 71, 58, 0.16);
  box-shadow: inset 3px 0 0 #b5473a;
}

/* The non-virtual mixer table renders plain rows, so keep the original weight for
   it - there the cell background does not out-specify these. */
.patch-fill-target td {
  background: color-mix(in srgb, var(--brand) 14%, transparent);
}

/* These have to out-weigh the cell's own `background: #fff`, which is written as
   `.virtual-mixer-canvas > [data-mixer-channel-row] > td`. The plain rule below
   used to be `.config-fill-target td` and lost that contest, while the replace and
   remove modifiers happened to tie and win on order - so dragging over empty
   channels showed no colour at all while changing or clearing them showed orange
   and red. All three are now scoped the same way and rank in the right order. */
/* The Busses tab is a plain table, not a virtual canvas, so it needs its own scope
   here or it matches none of these and a fill drag over it shows no colour at all.
   Scoped through .bus-table so it still out-weighs the tinted free and fixed rows. */
.virtual-mixer-canvas > [data-mixer-channel-row].config-fill-target > td,
.virtual-io-canvas > tr.config-fill-target > td,
.bus-table tr.config-fill-target > td {
  background: color-mix(in srgb, var(--brand) 14%, transparent);
  box-shadow: inset 3px 0 0 var(--brand);
}

.virtual-mixer-canvas > [data-mixer-channel-row].config-fill-target.config-fill-replace > td,
.virtual-io-canvas > tr.config-fill-target.config-fill-replace > td,
.bus-table tr.config-fill-target.config-fill-replace > td {
  background: color-mix(in srgb, #d99129 18%, transparent);
  box-shadow: inset 3px 0 0 #d99129;
}

.virtual-mixer-canvas > [data-mixer-channel-row].config-fill-target.config-fill-remove > td,
.virtual-io-canvas > tr.config-fill-target.config-fill-remove > td,
.bus-table tr.config-fill-target.config-fill-remove > td {
  background: rgba(181, 71, 58, 0.16);
  box-shadow: inset 3px 0 0 #b5473a;
}

.patch-picker-control:has(.patch-picker-value:only-child) {
  grid-template-columns: minmax(0, 1fr);
}

.patch-picker-value,
.patch-picker-clear {
  min-height: 30px;
  border: 1px solid var(--line);
  border-radius: 5px;
  background: #ffffff;
  color: var(--ink);
  font-size: 0.78rem;
}

.patch-picker-value {
  overflow: hidden;
  padding: 5px 7px;
  text-align: left;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.patch-picker-value.empty {
  color: var(--muted);
}

.patch-picker-clear {
  padding: 0;
  color: var(--muted);
  font-weight: 900;
}

.patch-picker-value:hover,
.patch-picker-value:focus,
.patch-picker-clear:hover,
.patch-picker-clear:focus {
  border-color: var(--brand-ink);
  outline: none;
}

.picker-backdrop {
  position: fixed;
  inset: 0;
  z-index: 30;
  display: grid;
  place-items: center;
  padding: 24px;
  background: rgba(27, 35, 43, 0.34);
  overflow: hidden;
  overscroll-behavior: contain;
}

.picker-panel {
  width: min(860px, calc(100vw - 32px));
  height: min(680px, calc(100dvh - 32px));
  min-height: min(520px, calc(100dvh - 32px));
  max-height: calc(100dvh - 32px);
  display: flex;
  flex-direction: column;
  gap: 12px;
  padding: 16px;
  border: 1px solid var(--line);
  border-radius: 8px;
  background: #ffffff;
  box-shadow: var(--shadow);
  overflow: hidden;
  overscroll-behavior: contain;
}

.picker-head {
  display: flex;
  justify-content: space-between;
  gap: 12px;
  align-items: flex-start;
}

.picker-head h3,
.picker-head p {
  margin: 0;
}

.picker-head p {
  margin-top: 4px;
  color: var(--muted);
  font-size: 0.85rem;
}

.picker-list {
  width: 100%;
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
  overflow-x: hidden;
  overscroll-behavior: contain;
  -webkit-overflow-scrolling: touch;
  display: grid;
  grid-auto-rows: max-content;
  align-content: start;
  gap: 12px;
  padding-right: 4px;
}

.picker-group {
  border: 1px solid var(--line);
  border-radius: 7px;
  overflow: hidden;
}

.picker-group-title {
  display: flex;
  justify-content: space-between;
  gap: 10px;
  align-items: center;
  padding: 8px 10px;
  background: #eef2f4;
  color: var(--brand-ink);
  font-size: 0.8rem;
  font-weight: 900;
  cursor: pointer;
  list-style: none;
}

.picker-group-title::-webkit-details-marker {
  display: none;
}

.picker-group-title::before {
  content: "+";
  width: 18px;
  color: var(--brand-ink);
  font-weight: 900;
}

.picker-group[open] > .picker-group-title::before {
  content: "-";
}

.picker-group-title > span {
  min-width: 0;
  display: grid;
  gap: 2px;
  margin-right: auto;
}

.picker-group-title strong {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.picker-group-title small {
  color: var(--muted);
  font-weight: 800;
}

.picker-option {
  width: 100%;
  display: grid;
  grid-template-columns: calc(6ch + 10px) minmax(0, 1fr) auto;
  gap: 8px;
  align-items: center;
  padding: 7px 10px;
  border: 0;
  border-top: 1px solid var(--line);
  border-radius: 0;
  background: #ffffff;
  color: var(--ink);
  text-align: left;
}

.picker-option:hover,
.picker-option:focus {
  background: var(--soft);
  outline: none;
}

.picker-option-channel {
  color: var(--brand-ink);
  font-weight: 900;
  text-align: center;
}

.picker-option strong,
.picker-option small {
  display: block;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.picker-option small {
  margin-top: 2px;
  color: var(--muted);
}

.patch-source-row td {
  background: var(--patch-tint);
  color: var(--brand-ink);
  font-weight: 900;
  letter-spacing: 0;
  font-size: 0.74rem;
}

.patch-source-toggle {
  width: 100%;
  display: grid;
  grid-template-columns: 18px 1fr;
  gap: 8px;
  align-items: center;
  padding: 0;
  background: transparent;
  color: inherit;
  text-align: left;
  font-weight: inherit;
}

.patch-source-title {
  display: block;
  text-transform: uppercase;
}

.patch-source-subtitle {
  display: block;
  margin-top: 2px;
  color: var(--muted);
  font-weight: 500;
  text-transform: none;
  text-align: left;
  white-space: pre-line;
}

.io-name-input,
.io-mic-input {
  min-width: 0;
}

.route-source-label {
  color: var(--brand-ink);
  font-weight: 800;
  margin-bottom: 4px;
}

.requirements-grid {
  display: grid;
  grid-template-columns: minmax(0, 1.4fr) minmax(300px, 0.8fr);
  gap: 18px;
  align-items: start;
}

.requirements-grid > .panel,
.requirements-list,
.requirements-card,
.requirements-section,
.requirements-rack,
.requirements-summary-grid {
  min-width: 0;
}

.requirements-list,
.requirements-card,
.requirements-section,
.requirements-rack,
.requirements-summary-grid {
  display: grid;
  gap: 12px;
}

.requirements-card {
  padding: 14px;
  border: 1px solid var(--line);
  border-radius: 8px;
  background: #ffffff;
  box-shadow: none;
}

.requirements-card.compact {
  gap: 10px;
}

.requirements-card h3 {
  margin: 0;
  color: var(--brand-ink);
}

.requirements-rack {
  padding: 10px;
  border: 1px solid var(--line);
  border-radius: 6px;
  background: var(--soft);
}

.requirements-list-compact {
  margin: 0;
  padding-left: 18px;
  color: #2f3944;
}

.requirements-table {
  width: 100%;
  min-width: 0;
  table-layout: fixed;
}

.requirements-table th,
.requirements-table td {
  padding: 7px 8px;
  overflow-wrap: anywhere;
}

.requirements-card .small-copy,
.requirements-list-compact,
.requirements-rack strong {
  min-width: 0;
  overflow-wrap: anywhere;
}

.requirements-table th:last-child,
.requirements-table td:last-child {
  width: 64px;
  text-align: right;
}

.library-card {
  padding: 0;
  box-shadow: none;
  overflow: hidden;
}

.library-list {
  display: grid;
  gap: 10px;
}

.library-instructions {
  display: grid;
  gap: 12px;
  margin-bottom: 18px;
}

.notice {
  padding: 10px 12px;
  border-radius: 6px;
  font-weight: 800;
}

.notice.success {
  color: #123f28;
  background: #dff3e8;
  border: 1px solid #a7d9bd;
}

.toast {
  position: fixed;
  right: 22px;
  bottom: 22px;
  z-index: 20;
  width: min(520px, calc(100vw - 32px));
  max-width: calc(100vw - 32px);
  padding: 15px 18px;
  border-radius: 8px;
  box-shadow: 0 16px 40px rgba(16, 24, 32, 0.18);
  font-weight: 900;
  line-height: 1.4;
  pointer-events: none;
  animation: toast-lifecycle 4.2s ease both;
}

.picker-availability-filters {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
}

.picker-availability-filters button {
  padding: 5px 9px;
  border: 1px solid var(--line);
  border-radius: 999px;
  background: #fff;
  color: var(--muted);
  font-size: 0.76rem;
  font-weight: 800;
}

.picker-availability-filters button.active {
  border-color: var(--brand);
  background: var(--soft);
  color: var(--brand-ink);
}

.picker-availability-filters span { opacity: 0.72; }

.picker-availability {
  padding: 3px 7px;
  border-radius: 999px;
  white-space: nowrap;
  font-size: 0.68rem;
  font-weight: 900;
}

.picker-availability.ready {
  background: #e1f3e8;
  color: #276544;
}

.picker-availability.automatic {
  background: #fff0d7;
  color: #8a5914;
}

.routing-update-toast {
  animation: none;
}

@keyframes toast-lifecycle {
  0% {
    opacity: 0;
    transform: translateY(8px);
  }
  5%, 88% {
    opacity: 1;
    transform: translateY(0);
  }
  100% {
    opacity: 0;
    transform: translateY(8px);
  }
}

.tour-intercept {
  position: fixed;
  inset: 0;
  z-index: 100;
  background: rgba(19, 43, 36, 0.72);
  backdrop-filter: blur(3px);
}

.tour-card {
  position: fixed;
  z-index: 102;
  width: min(390px, calc(100vw - 20px));
  max-height: calc(100vh - 20px);
  overflow-y: auto;
  padding: 18px;
  border: 1px solid color-mix(in srgb, var(--brand) 20%, var(--line));
  border-radius: 13px;
  background: var(--panel);
  box-shadow: 0 18px 50px rgba(13, 39, 31, 0.28);
}

.tour-card h2 {
  margin: 3px 0 8px;
  font-size: 1.15rem;
}

.tour-card p {
  margin: 0;
  color: var(--muted);
  font-size: 0.9rem;
  line-height: 1.5;
}

.tour-card-head,
.tour-actions {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
}

.tour-progress {
  color: var(--brand);
  font-size: 0.72rem;
  font-weight: 800;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

.tour-close {
  width: 28px;
  height: 28px;
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: var(--soft);
  color: var(--muted);
  font-size: 1.15rem;
  cursor: pointer;
}

.tour-actions {
  margin-top: 16px;
}

.tour-dismiss-choice {
  display: flex;
  gap: 8px;
  align-items: flex-start;
  margin-top: 15px;
  color: var(--ink);
  font-size: 0.84rem;
}

.toast.success {
  color: #123f28;
  background: #dff3e8;
  border: 1px solid #8dccaa;
}

.channel-move-cell[style*="--channel-color"] {
  background: color-mix(in srgb, var(--channel-color) 28%, var(--panel));
  box-shadow: inset 5px 0 var(--channel-color);
}

.io-color-panel {
  position: fixed;
  z-index: 80;
  left: 50%;
  bottom: 18px;
  width: min(620px, calc(100vw - 24px));
  display: grid;
  grid-template-columns: auto 52px 1fr 42px;
  gap: 14px;
  align-items: center;
  padding: 13px 15px;
  border: 1px solid var(--line);
  border-radius: 12px;
  background: var(--panel);
  box-shadow: 0 14px 38px rgba(13, 39, 31, .24);
  transform: translateX(-50%);
}
.io-color-panel > div:first-child { display:grid; gap:2px; }
.io-color-panel > div:first-child span, .io-used-colors small { color:var(--muted); font-size:.68rem; }
.io-color-panel input[type="color"] { width:52px; height:36px; padding:2px; border:1px solid var(--line); border-radius:7px; background:var(--soft); cursor:pointer; }
/* One row of its own, below the colour controls. Without the span these four
   buttons flowed into the panel's four-column grid and broke across two lines
   with three above and one below. */
.io-copy-actions { grid-column:1 / -1; display:flex; flex-wrap:nowrap; gap:8px; }
.io-copy-actions .button { flex:1 1 0; min-width:0; white-space:nowrap; }
.io-range-editor { grid-column:1 / -1; display:grid; grid-template-columns:minmax(180px,1fr) auto 38px; align-items:end; gap:8px; padding-top:8px; border-top:1px solid var(--line); }
.io-range-editor label { display:grid; gap:3px; }
.io-range-editor label > span { color:var(--muted); font-size:.68rem; }
.channel-number.io-range-member { position:relative; }
.channel-number.io-range-member::after { position:absolute; left:3px; top:0; bottom:0; width:6px; border-left:2px solid var(--brand); content:""; pointer-events:none; }
.channel-number.io-range-start::after { top:5px; border-top:2px solid var(--brand); }
.channel-number.io-range-end::after { bottom:5px; border-bottom:2px solid var(--brand); }
.channel-number.io-range-start.io-range-end::after { top:5px; bottom:5px; }
.io-used-colors { display:flex; gap:7px; align-items:center; overflow-x:auto; }
.io-used-colors button { flex:0 0 28px; width:28px; height:28px; border:2px solid #fff; border-radius:50%; background:var(--swatch); box-shadow:0 0 0 1px var(--line); }
.io-color-remove { width:38px; height:38px; border:1px solid #e3c5c1; border-radius:7px; background:#fff2f0; color:#9a382e; font-size:1rem; }

.mixer-paste-progress {
  position: fixed;
  z-index: 79;
  left: 50%;
  bottom: 18px;
  width: min(520px, calc(100vw - 24px));
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(150px, .8fr);
  gap: 16px;
  align-items: center;
  padding: 14px 16px;
  border: 1px solid var(--line);
  border-radius: 12px;
  background: var(--panel);
  box-shadow: 0 14px 38px rgba(13, 39, 31, .24);
  transform: translateX(-50%);
}
.mixer-paste-progress > div { display:grid; gap:3px; }
.mixer-paste-progress span { color:var(--muted); font-size:.72rem; }
.mixer-paste-progress progress { width:100%; accent-color:var(--brand); }

@media (max-width: 620px) {
  .io-color-panel { grid-template-columns:1fr 48px 40px; }
  .io-color-panel > div:first-child { grid-column:1 / -1; }
}

.library-path,
.schema-sample {
  overflow-x: auto;
  padding: 12px;
  color: #23303b;
  background: #eef2f4;
  border: 1px solid var(--line);
  border-radius: 6px;
  font-family: "SFMono-Regular", Consolas, "Liberation Mono", monospace;
  font-size: 0.86rem;
}

.schema-sample {
  margin: 16px 0 0;
  line-height: 1.45;
  white-space: pre;
}

.library-item {
  display: grid;
  gap: 4px;
  padding: 12px;
  background: var(--soft);
  border: 1px solid var(--line);
  border-radius: 6px;
}

.catalog-group-summary,
.catalog-manufacturer-summary {
  display: grid;
  grid-template-columns: 18px minmax(0, 1fr);
  gap: 9px;
  align-items: center;
  padding: 13px 15px;
  cursor: pointer;
  list-style: none;
}

.catalog-group-summary::-webkit-details-marker,
.catalog-manufacturer-summary::-webkit-details-marker {
  display: none;
}

.catalog-group-summary::before,
.catalog-manufacturer-summary::before {
  content: "+";
  color: var(--brand-ink);
  font-weight: 900;
  text-align: center;
}

.catalog-type-group[open] > .catalog-group-summary::before,
.catalog-manufacturer-group[open] > .catalog-manufacturer-summary::before {
  content: "−";
}

.catalog-group-summary > span,
.catalog-manufacturer-summary > span {
  min-width: 0;
  display: flex;
  justify-content: space-between;
  gap: 12px;
  align-items: center;
}

.catalog-group-summary small,
.catalog-manufacturer-summary small {
  color: var(--muted);
  font-size: .72rem;
  font-weight: 700;
}

.catalog-type-group[open] > .catalog-group-summary {
  border-bottom: 1px solid var(--line);
  background: var(--soft);
}

.catalog-manufacturer-list {
  display: grid;
  gap: 8px;
  padding: 10px;
}

.catalog-manufacturer-group {
  overflow: hidden;
  border: 1px solid var(--line);
  border-radius: 7px;
  background: #fff;
}

.catalog-series-list {
  display: grid;
  gap: 7px;
  padding: 8px;
}

.catalog-series-group {
  overflow: hidden;
  border: 1px solid var(--line);
  border-radius: 6px;
  background: #fff;
}

.catalog-series-summary {
  display: grid;
  grid-template-columns: 18px minmax(0, 1fr);
  gap: 8px;
  align-items: center;
  padding: 9px 11px;
  cursor: pointer;
  list-style: none;
}

.catalog-series-summary::-webkit-details-marker { display:none; }
.catalog-series-summary::before { content:"+"; color:var(--brand-ink); font-weight:900; text-align:center; }
.catalog-series-group[open] > .catalog-series-summary::before { content:"−"; }
.catalog-series-summary > span { min-width:0; display:flex; justify-content:space-between; align-items:center; gap:10px; }
.catalog-series-summary small { color:var(--muted); font-size:.7rem; font-weight:700; }
.catalog-series-group[open] > .catalog-series-summary { border-bottom:1px solid var(--line); background:#f8fafb; }
.catalog-series-group > .library-list { padding:8px; }

.catalog-manufacturer-summary {
  padding: 10px 12px;
  background: var(--soft);
}

.catalog-manufacturer-group[open] > .catalog-manufacturer-summary {
  border-bottom: 1px solid var(--line);
}

.catalog-manufacturer-group > .library-list {
  padding: 9px;
}

.library-item-head {
  display: flex;
  justify-content: space-between;
  gap: 10px;
  align-items: flex-start;
}

.library-actions {
  display: flex;
  flex: 0 0 auto;
  gap: 6px;
}

.library-actions .icon-button {
  width: 34px;
  height: 34px;
}

.tag-row {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
}

.tag {
  padding: 3px 8px;
  color: #2f3a44;
  background: #e7ecef;
  border-radius: 999px;
  font-size: 0.78rem;
  font-weight: 800;
}

.empty-state {
  display: grid;
  place-items: center;
  min-height: 170px;
  padding: 24px;
  color: var(--muted);
  text-align: center;
  box-shadow: none;
}

@media (max-width: 1100px) {
  .history-grid { grid-template-columns: 1fr; }
  .splash,
  .config-layout,
  .add-system-row,
  .grid-2,
  .grid-3 {
    grid-template-columns: 1fr;
  }

  .toolbar {
    align-items: flex-start;
    flex-direction: column;
  }

  .toolbar-actions,
  .toolbar-nav {
    margin-left: 0;
  }

  .toolbar-nav {
    align-self: flex-end;
  }

  .workspace {
    padding: 16px;
  }
}

@media (max-width: 700px) {
  /* A table is at least as wide as its own columns, so widening one from its
     header pushes the table out and the patch sheet scrolls sideways - the axis
     it already scrolls on - rather than the column being clipped by the block. */
  .mixer-channel-grid {
    justify-content: stretch;
  }

  .mixer-channel-grid > .patch-block {
    width: auto;
    min-width: max(343px, var(--patch-block-table-min, 0px));
  }

  /* The same columns, narrower, still in one place. */
  :root {
    --patch-mixer-min-1: 44px;
    --patch-mixer-min-2: 72px;
    --patch-mixer-min-3: 72px;
    --patch-mixer-min-4: 75px;
    --patch-mixer-min-5: 80px;
    --patch-mixer-fr-2: 1.1fr;
    --patch-mixer-fr-3: 1fr;
    --patch-mixer-fr-4: 1fr;
    --patch-mixer-fr-5: 1fr;
  }

  .toolbar {
    min-height: auto;
    display: flex;
    align-items: center;
    flex-flow: row wrap;
    gap: 9px;
    padding: 10px 12px;
  }

  .brand-lockup {
    min-width: 0;
    flex: 1 1 100%;
  }

  .brand-lockup > div:last-child {
    min-width: 0;
  }

  .project-title,
  .save-state {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }

  .mark {
    width: 36px;
    height: 36px;
    flex-basis: 36px;
  }

  .toolbar-actions,
  .toolbar-nav,
  .toolbar-actions + .toolbar-nav {
    width: 100%;
    margin-left: 0;
    align-self: stretch;
  }

  .toolbar .button-row.toolbar-actions,
  .toolbar .button-row.toolbar-nav {
    display: flex;
    flex-flow: row nowrap;
    gap: 7px;
  }

  .toolbar .toolbar-actions > *,
  .toolbar .toolbar-nav > .button {
    min-width: 0;
    flex: 1 1 0;
    width: auto;
  }

  .toolbar .toolbar-actions [data-live-presence]:empty {
    display: none;
  }

  .toolbar .button {
    padding: 8px 9px;
    font-size: .72rem;
  }

  .tabs {
    gap: 2px;
    padding: 7px 10px 0;
    scrollbar-width: none;
  }

  .tabs::-webkit-scrollbar { display: none; }
  .tab { padding: 9px 10px; font-size: .76rem; }

  .workspace { padding: 10px; }
}

@media (max-width: 560px) {
  .splash {
    display: flex;
    min-height: 100dvh;
    flex-direction: column;
    justify-content: flex-start;
    gap: 12px;
    padding: 12px;
  }

  .splash-title {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 8px;
    max-width: none;
  }

  .splash-title .eyebrow {
    flex: 1 1 auto;
    margin: 0;
  }

  .splash-title h1,
  .splash-title > p:not(.eyebrow) {
    display: none;
  }

  .splash-title .button {
    width: auto;
    padding: 8px 10px;
  }

  .splash-panel {
    width: 100%;
    min-width: 0;
  }

  .splash-panel,
  .panel {
    padding: 16px;
  }

  .button-row {
    align-items: stretch;
    flex-direction: column;
  }

  .button,
  .button-row > * {
    width: 100%;
  }

  .project-row {
    grid-template-columns: minmax(0, 1fr);
  }

  .project-button {
    gap: 8px;
    padding: 12px;
  }

  .project-row-actions {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(100px, 1fr));
  }

  .project-row-actions .button {
    width: 100%;
  }

  .profile-card {
    padding: 14px;
  }

  .profile-identity {
    align-items: flex-start;
    gap: 12px;
  }

  .profile-avatar {
    width: 58px;
    height: 58px;
  }

  .team-people-grid {
    grid-template-columns: 1fr;
  }

  .team-person-card {
    grid-template-columns: 42px minmax(0, 1fr) auto;
  }

  .team-person-avatar {
    width: 42px;
    height: 42px;
  }

  .team-person-role {
    grid-template-columns: auto minmax(0, 1fr);
    max-width: 170px;
  }

  .team-invite-form {
    grid-template-columns: 1fr;
    padding: 12px;
  }

  .picker-backdrop {
    align-items: stretch;
    padding: 0;
  }

  .picker-panel {
    width: 100%;
    height: 100dvh;
    min-height: 0;
    max-height: 100dvh;
    padding: 12px;
    border: 0;
    border-radius: 0;
  }

  .picker-head p {
    font-size: .76rem;
  }

  .picker-search {
    min-height: 44px;
    font-size: 16px;
  }

  .picker-group-title,
  .picker-option {
    min-height: 44px;
  }

  .toast {
    right: 12px;
    /* Clear the development DEV badge, which is also pinned bottom-right and
       sits at z-index 10000, so it covered the toast's right edge at this width.
       On production there is no badge and this is simply a slightly higher toast. */
    bottom: max(56px, calc(env(safe-area-inset-bottom) + 44px));
    width: auto;
    max-width: min(320px, calc(100vw - 24px));
    padding: 10px 12px;
    font-size: .82rem;
  }
}
.modal-backdrop {
  position: fixed;
  inset: 0;
  z-index: 120;
  background: rgba(16, 31, 47, 0.58);
  backdrop-filter: blur(5px);
}

.export-dialog {
  position: fixed;
  z-index: 121;
  top: 50%;
  left: 50%;
  width: min(620px, calc(100vw - 28px));
  transform: translate(-50%, -50%);
  padding: 26px;
  border-radius: 20px;
  background: var(--panel);
  box-shadow: 0 24px 80px rgba(10, 27, 43, 0.28);
}

.export-dialog-head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 18px;
}

.export-dialog h2 { margin: 3px 0 10px; }
.export-dialog .eyebrow { margin: 0; }

.export-format-grid {
  display: grid;
  gap: 10px;
  margin: 22px 0;
}

.export-format-card {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: 13px;
  align-items: start;
  padding: 14px;
  border: 1px solid var(--line);
  border-radius: 12px;
  background: var(--soft);
  cursor: pointer;
}

.export-format-card input { margin-top: 3px; accent-color: var(--accent); }
.export-format-card span { display: grid; gap: 3px; }
.export-format-card small { color: var(--muted); line-height: 1.35; }

.dante-network-control {
  display: grid;
  gap: 7px;
  margin-top: 8px;
  padding: 9px 10px;
  border: 1px solid #b7d9e8;
  border-radius: 7px;
  background: #eef8fc;
}

.dante-network-toggle { display: flex; align-items: center; gap: 8px; color: #24536a; font-size: .75rem; font-weight: 800; }
.dante-network-toggle input { accent-color: #247b9b; }
.dante-network-name { width: 100%; padding: 7px 8px; border: 1px solid #9dc8d9; border-radius: 5px; background: #fff; font-size: .75rem; }

.automatic-route-dialog {
  position: fixed;
  z-index: 121;
  top: 50%;
  left: 50%;
  width: min(640px, calc(100vw - 28px));
  max-height: calc(100vh - 30px);
  overflow-y: auto;
  transform: translate(-50%, -50%);
  padding: 24px;
  border-radius: 18px;
  background: var(--panel);
  box-shadow: 0 24px 80px rgba(10, 27, 43, .3);
}

.automatic-route-dialog h2 { margin: 3px 0 8px; }
.automatic-route-options { display: grid; gap: 10px; margin-top: 18px; }
.automatic-route-options > button { display: flex; align-items: center; justify-content: space-between; gap: 16px; width: 100%; padding: 14px; border: 1px solid var(--line); border-radius: 10px; background: var(--soft); color: var(--ink); text-align: left; }
.automatic-route-options > button:hover { border-color: var(--brand); background: #eef8f4; }
.automatic-route-options span { display: grid; gap: 4px; }.automatic-route-options small { color: var(--muted); }.automatic-route-options > button > b { flex: 0 0 auto; color: var(--brand); font-size: .75rem; }
.automatic-route-paste-actions { display: grid; gap: 8px; margin-top: 18px; padding-top: 14px; border-top: 1px solid var(--line); }
.automatic-route-paste-actions p { margin: 0 0 2px; }
.automatic-route-paste-actions button { width: 100%; padding: 10px 12px; border: 1px solid var(--brand); border-radius: 9px; background: var(--brand); color: white; font-weight: 700; }
.automatic-route-paste-actions button:hover { filter: brightness(.94); }

.route-inspector-dialog {
  position: fixed;
  z-index: 121;
  top: 50%;
  left: 50%;
  width: min(680px, calc(100vw - 28px));
  max-height: calc(100vh - 30px);
  overflow-y: auto;
  transform: translate(-50%, -50%);
  padding: 24px;
  border-radius: 18px;
  background: var(--panel);
  box-shadow: 0 24px 80px rgba(10, 27, 43, .3);
}
.route-inspector-dialog h2 { margin: 3px 0 8px; }
.route-inspector-status { display: flex; align-items: center; gap: 8px; margin: 12px 0 16px; font-size: .78rem; font-weight: 800; }
.route-inspector-status span { width: 9px; height: 9px; border-radius: 50%; background: #c74a4a; box-shadow: 0 0 0 4px rgba(199, 74, 74, .12); }
.route-inspector-status.is-valid { color: #17694d; }
.route-inspector-status.is-valid span { background: #26966d; box-shadow: 0 0 0 4px rgba(38, 150, 109, .13); }
.route-inspector-status.is-info { color: #67531c; }
.route-inspector-status.is-info span { background: #d39b28; box-shadow: 0 0 0 4px rgba(211, 155, 40, .14); }
.route-inspector-summary { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 10px; margin: 0 0 18px; }
.route-inspector-summary > div { min-width: 0; padding: 11px 12px; border: 1px solid var(--line); border-radius: 10px; background: var(--soft); }
.route-inspector-summary dt { color: var(--muted); font-size: .68rem; font-weight: 800; text-transform: uppercase; }
.route-inspector-summary dd { margin: 5px 0 0; font-size: .82rem; font-weight: 750; overflow-wrap: anywhere; }
.route-inspector-summary small { display: block; margin-top: 3px; color: var(--muted); font-weight: 600; }
.route-inspector-path { display: grid; gap: 8px; margin: 0; padding: 0; list-style: none; }
.route-inspector-hop { display: grid; grid-template-columns: 26px 1fr; gap: 10px; align-items: center; }
.route-hop-index { display: grid; place-items: center; width: 24px; height: 24px; border-radius: 50%; background: var(--brand); color: #fff; font-size: .68rem; font-weight: 900; }
.route-inspector-hop > div { display: grid; grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr); gap: 9px; align-items: center; padding: 10px 12px; border: 1px solid var(--line); border-radius: 10px; }
.route-inspector-hop strong { font-size: .76rem; overflow-wrap: anywhere; }
.route-inspector-hop strong:last-child { text-align: right; }
.route-inspector-hop div > span { color: var(--brand); font-size: .66rem; font-weight: 850; text-align: center; }
.route-inspector-hop div > span::before { content: "→ "; }
.route-inspector-hop.is-missing > div { border: 1px dashed #d68416; background: #fff7e8; }
.route-inspector-hop.is-missing .route-hop-index { background: #d68416; }
.route-inspector-hop.is-missing div > span { color: #a95d00; }
.route-inspector-issues { margin-top: 16px; padding: 12px 14px; border: 1px solid #e2b6b6; border-radius: 10px; background: #fff3f3; color: #863636; font-size: .78rem; }
.route-inspector-issues ul { margin: 7px 0 0; padding-left: 18px; }
.route-inspector-information { margin-top: 16px; padding: 12px 14px; border: 1px solid #ead9a9; border-radius: 10px; background: #fff9e9; color: #67531c; font-size: .78rem; }
.route-inspector-information ul { margin: 7px 0 0; padding-left: 18px; }
.route-repair-options { display: grid; gap: 12px; margin-top: 14px; padding: 14px; border: 1px solid #d8c184; border-radius: 12px; background: #fffaf0; }
.route-repair-options > div:first-child p { margin: 4px 0 0; color: var(--muted); font-size: .72rem; }
.route-repair-path { background: #fff; }
.route-repair-picker-option { cursor: pointer; }
.route-repair-picker-option:hover .picker-option-channel { color: var(--brand); }
.channel-move-cell.route-repair-highlight { position: relative; background: #fff5df; outline: 2px dashed #e58a22; outline-offset: -3px; }
/* The dashed orange outline carries the meaning on its own. The tiny "repair"
   label was too small to read comfortably and crowded the channel number. */
.route-inspector-hint { margin: 16px 0 0; color: var(--muted); font-size: .7rem; text-align: right; }

@media (max-width: 620px) {
  .route-inspector-summary { grid-template-columns: 1fr; }
  .route-inspector-hop > div { grid-template-columns: 1fr; }
  .route-inspector-hop strong:last-child { text-align: left; }
  .route-inspector-hop div > span { text-align: left; }
  .route-inspector-hop div > span::before { content: "↓ "; }
}

/* The welcome card that offers the guided tour */
.tour-step-copy { max-width: 780px; }
.tour-step-copy h2 { margin-bottom: 7px; }
.tour-step-copy p { margin: 0; font-size: .94rem; }

.automatic-route-paste-checkbox { display:flex; align-items:center; gap:7px; margin-top:10px; color:var(--muted); font-size:.74rem; }
.automatic-route-paste-checkbox input { width:15px; height:15px; }

.tour-finish-group { display:flex; align-items:center; gap:12px; }
.tour-finish-group .tour-dismiss-choice { margin:0; align-items:center; color:var(--muted); font-size:.72rem; white-space:nowrap; }
.tour-finish-group .tour-dismiss-choice input { width:14px; height:14px; margin:0; }

@media (max-width: 720px) {
  .tour-finish-group { gap:7px; }.tour-finish-group .tour-dismiss-choice { max-width:112px; white-space:normal; }
}

.tour-welcome-card {
  top: 50%;
  left: 50%;
  width: min(560px, calc(100vw - 32px));
  padding: 24px 26px;
  border-radius: 16px;
  transform: translate(-50%, -50%);
}
.tour-welcome-card .eyebrow { margin: 0 0 4px; }
.tour-welcome-chapters { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 8px; margin: 18px 0 4px; padding: 0; list-style: none; counter-reset: tour-chapter; }
.tour-welcome-chapters li { display: flex; align-items: center; gap: 9px; padding: 10px 12px; border: 1px solid var(--line); border-radius: 9px; background: var(--soft); color: var(--brand-ink); font-size: .84rem; font-weight: 750; counter-increment: tour-chapter; }
.tour-welcome-chapters li::before { content: counter(tour-chapter); display: grid; place-items: center; flex: 0 0 22px; height: 22px; border-radius: 50%; background: var(--brand); color: #fff; font-size: .72rem; }
.tour-welcome-card .tour-actions { flex-wrap: wrap; }
.tour-welcome-card .tour-dismiss-choice { margin: 0; align-items: center; color: var(--muted); font-size: .8rem; white-space: nowrap; }
.tour-welcome-card .tour-dismiss-choice input { flex: none; width: 16px; height: 16px; margin: 0; }
@media (max-width: 520px) {
  .tour-welcome-card { padding: 18px; }
  .tour-welcome-chapters { grid-template-columns: 1fr; }
}

/* The guided tour's coach: a ring on the control and a bubble beside it. The layer
   lets the page underneath be used; only the bubble and the pill take the pointer. */
.coach-layer { position: fixed; inset: 0; z-index: 130; pointer-events: none; }
.coach-ring {
  position: fixed;
  top: 0;
  left: 0;
  border: 3px solid #f0b34b;
  border-radius: 10px;
  box-shadow: 0 0 0 5px rgba(240, 179, 75, .22);
  animation: coach-ring-pulse 1.8s ease-in-out infinite;
  /* No transition: the ring is moved every frame while the page scrolls, and easing
     each move leaves it trailing behind the control. */
}
@keyframes coach-ring-pulse { 50% { box-shadow: 0 0 0 10px rgba(240, 179, 75, .08); } }
.coach-bubble {
  position: fixed;
  top: 0;
  left: 0;
  width: min(340px, calc(100vw - 24px));
  padding: 14px 16px 16px;
  border: 1px solid color-mix(in srgb, var(--brand) 30%, var(--line));
  border-radius: 13px;
  background: var(--panel);
  box-shadow: 0 16px 44px rgba(13, 39, 31, .26);
  pointer-events: auto;
}
.coach-head { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
.coach-eyebrow { color: var(--brand); font-size: .68rem; font-weight: 850; letter-spacing: .07em; text-transform: uppercase; }
.coach-head-buttons { display: flex; gap: 4px; }
.coach-icon { width: 26px; height: 26px; padding: 0; border: 0; border-radius: 50%; background: var(--soft); color: var(--muted); font-size: 1rem; line-height: 1; cursor: pointer; }
.coach-icon:hover { color: var(--ink); }
.coach-title { margin: 6px 0 6px; color: var(--brand-ink); font-size: 1.02rem; }
.coach-text { margin: 0; color: var(--ink); font-size: .87rem; line-height: 1.5; }
.coach-notice { margin: 9px 0 0; padding: 7px 9px; border-radius: 7px; background: #fff8e8; color: #7a5410; font-size: .78rem; }
.coach-progress { display: flex; gap: 5px; margin-top: 12px; }
.coach-progress i { flex: 1; height: 4px; border-radius: 2px; background: var(--line); }
.coach-progress i.done { background: var(--brand); }
.coach-progress i.current { background: #f0b34b; }
.coach-actions { display: flex; justify-content: flex-end; gap: 8px; margin-top: 12px; }
.coach-arrow { position: absolute; width: 14px; height: 14px; background: var(--panel); border: 1px solid color-mix(in srgb, var(--brand) 30%, var(--line)); transform: rotate(45deg); display: none; }
.coach-below .coach-arrow { display: block; top: -8px; left: calc(var(--coach-arrow-x, 50%) - 7px); border-right: 0; border-bottom: 0; }
.coach-above .coach-arrow { display: block; bottom: -8px; left: calc(var(--coach-arrow-x, 50%) - 7px); border-left: 0; border-top: 0; }
.coach-right .coach-arrow { display: block; left: -8px; top: calc(var(--coach-arrow-y, 24px) - 7px); border-right: 0; border-top: 0; }
.coach-left .coach-arrow { display: block; right: -8px; top: calc(var(--coach-arrow-y, 24px) - 7px); border-left: 0; border-bottom: 0; }
.coach-docked { right: 0; left: 0; width: auto; margin: 0 8px; border-radius: 14px; }
.coach-docked[data-edge="bottom"] { top: auto; bottom: calc(8px + env(safe-area-inset-bottom, 0px)); }
.coach-docked[data-edge="top"] { top: 8px; }
.coach-pill {
  position: fixed;
  right: 16px;
  bottom: calc(16px + env(safe-area-inset-bottom, 0px));
  padding: 9px 15px;
  border: 0;
  border-radius: 99px;
  background: var(--brand);
  color: #fff;
  font-size: .8rem;
  font-weight: 800;
  box-shadow: 0 10px 28px rgba(13, 39, 31, .28);
  pointer-events: auto;
  cursor: pointer;
}
@media (prefers-reduced-motion: reduce) {
  .coach-ring { animation: none; }
}

/* Authentication and profile */
.auth-splash { grid-template-columns:minmax(0,1fr) minmax(420px,560px); }
.auth-intro { display:grid; align-content:center; }
.auth-logo { width:72px; height:72px; margin-bottom:28px; }
.auth-intro h1 { max-width:840px; font-size:clamp(3rem,7vw,6.5rem); }
.auth-feature-list { display:grid; gap:10px; margin-top:36px; color:var(--brand-ink); font-weight:750; }
.auth-feature-list span { display:flex; align-items:center; gap:12px; }
.auth-feature-list i { display:grid; place-items:center; width:30px; height:30px; border:1px solid rgba(18,108,111,.3); border-radius:50%; color:var(--brand); font-size:.64rem; font-style:normal; }
.auth-panel { width:100%; max-height:calc(100vh - 64px); overflow:auto; }
.auth-panel-header { align-items:flex-start; margin-bottom:24px; }
.auth-panel-header h2 { margin:0 0 6px; font-size:1.75rem; }
.auth-panel-header p { margin:0; color:var(--muted); line-height:1.5; }
.auth-tabs { display:grid; grid-template-columns:1fr 1fr; gap:4px; margin-bottom:28px; padding:4px; border-radius:10px; background:var(--soft); }
.auth-tab { padding:10px 14px; border-radius:7px; background:transparent; color:var(--muted); font-weight:800; }
.auth-tab.active { background:var(--panel); color:var(--brand-ink); box-shadow:0 2px 8px rgba(22,29,37,.09); }
.auth-form { display:grid; gap:16px; }
.auth-form label { display:grid; gap:7px; color:var(--brand-ink); font-size:.78rem; font-weight:800; }
.auth-form input { min-width:0; width:100%; padding:12px 13px; border:1px solid var(--line); border-radius:8px; background:var(--field); color:var(--ink); outline:none; font-weight:500; }
.auth-form input:focus { border-color:var(--focus); box-shadow:0 0 0 3px rgba(46,125,209,.13); }
.auth-form label small { color:var(--muted); font-weight:500; }
.auth-submit { width:100%; margin-top:4px; padding:13px 18px; }
.turnstile-slot { min-height:65px; width:100%; overflow:hidden; }
.auth-form-row { display:flex; align-items:center; justify-content:space-between; gap:14px; }
.auth-form .auth-check { display:flex; grid-template-columns:none; flex-direction:row; align-items:center; gap:8px; color:var(--muted); font-weight:600; }
.auth-check input { width:16px; height:16px; padding:0; }
.auth-link { padding:0; background:none; color:var(--brand); font-size:.78rem; font-weight:800; text-decoration:underline; text-underline-offset:3px; }
.auth-back-link { justify-self:start; margin-top:4px; }
.auth-notice { margin:0 0 18px; padding:11px 13px; border:1px solid var(--line); border-radius:8px; font-size:.8rem; line-height:1.45; }
.auth-notice.error { border-color:#e7b8b5; background:#fff1f0; color:#8e2925; }
.auth-notice.success { border-color:#add7bf; background:#effaf4; color:#176037; }
.auth-notice.muted { margin:0; background:var(--soft); color:var(--muted); }
.auth-dev-note { margin:0; color:var(--muted); font-size:.72rem; line-height:1.5; }
.auth-loading { min-height:300px; display:grid; place-items:center; align-content:center; gap:16px; color:var(--muted); }
.auth-spinner { width:34px; height:34px; border:3px solid var(--line); border-top-color:var(--brand); border-radius:50%; animation:auth-spin .8s linear infinite; }
@keyframes auth-spin { to { transform:rotate(360deg); } }
.profile-sections { display:grid; gap:18px; }
.profile-section { padding:18px; border:1px solid var(--line); border-radius:10px; background:var(--soft); }
.profile-section h3 { margin:0 0 4px; color:var(--brand-ink); }
.profile-section > div > p { margin:0; color:var(--muted); font-size:.76rem; line-height:1.45; }
.profile-section .button { justify-self:start; }
.account-export-options { display:flex; flex-wrap:wrap; gap:10px 18px; }
.account-export-progress { padding:9px 11px; border-radius:6px; background:#fff; color:var(--muted); font-size:.82rem; }
.account-danger-zone { border-color:#e5b8b1; background:#fff9f8; }
.button.danger { background:#9f2f25; border-color:#9f2f25; color:#fff; }
.auth-help-row { flex-wrap:wrap; gap:8px 14px; }
.profile-identity { display:flex; align-items:center; gap:16px; margin-bottom:18px; }
.profile-identity h2, .profile-identity p { margin:0; }
.profile-avatar, .team-person-avatar { position:relative; display:grid; flex:0 0 auto; place-items:center; overflow:hidden; border:1px solid var(--line); border-radius:50%; background:var(--brand); color:#fff; font-weight:850; }
.profile-avatar { width:72px; height:72px; font-size:1.15rem; }
.team-person-avatar { width:46px; height:46px; font-size:.78rem; }
.profile-avatar img, .team-person-avatar img { position:absolute; inset:0; width:100%; height:100%; object-fit:cover; }
.subscription-level { display:inline-flex; margin-top:8px; padding:4px 8px; border-radius:999px; background:#e3f4e9; color:#176037; font-size:.67rem; font-weight:800; }
.profile-picture-form input[type="file"] { max-width:100%; padding:8px; border:1px dashed var(--line); border-radius:8px; background:var(--field); }
.profile-picture-editor { display:grid; justify-items:center; gap:10px; padding:14px; border:1px solid var(--line); border-radius:10px; background:var(--panel); }
.profile-picture-editor[hidden] { display:none; }
.profile-crop-frame { position:relative; width:min(280px, 100%); aspect-ratio:1; overflow:hidden; border-radius:12px; background:#10151d; box-shadow:inset 0 0 0 1px rgba(255,255,255,.08); }
.profile-crop-frame canvas { display:block; width:100%; height:100%; cursor:grab; touch-action:none; }
.profile-crop-frame canvas:active { cursor:grabbing; }
.profile-crop-guide { position:absolute; inset:7%; pointer-events:none; border:2px solid rgba(255,255,255,.9); border-radius:50%; box-shadow:0 0 0 999px rgba(4,10,18,.42); }
.profile-zoom-control { display:grid; grid-template-columns:auto minmax(150px, 240px); align-items:center; gap:12px; width:min(320px, 100%); }
.profile-zoom-control input { width:100%; padding:0 !important; }
.profile-picture-editor > p { margin:0; color:var(--muted); font-size:.75rem; }
.auth-signout { margin-top:20px; }
.auth-account-actions { display:flex; align-items:center; justify-content:space-between; gap:12px; margin-top:20px; }
.auth-account-actions .auth-signout { margin-top:0; }
.admin-search { display:grid; grid-template-columns:minmax(0,1fr) auto; gap:10px; margin-bottom:16px; }
.admin-search input, .admin-user select { min-width:0; padding:10px 12px; border:1px solid var(--line); border-radius:8px; background:var(--field); color:var(--ink); }
.admin-user-list { display:grid; gap:10px; }
.admin-user { display:grid; grid-template-columns:minmax(180px,1fr) auto 130px 150px; gap:14px; align-items:center; padding:14px; border:1px solid var(--line); border-radius:10px; background:var(--soft); }
.admin-user.disabled { opacity:.7; }
.admin-user-main { display:grid; gap:3px; min-width:0; }
.admin-user-main span, .admin-user-main small { overflow:hidden; color:var(--muted); text-overflow:ellipsis; white-space:nowrap; }
.admin-user-status { display:flex; align-items:center; gap:8px; color:var(--muted); font-size:.72rem; }
.admin-user > label { display:grid; gap:5px; color:var(--muted); font-size:.68rem; font-weight:750; }
.admin-user-actions { grid-column:1 / -1; display:flex; flex-wrap:wrap; gap:8px; }
.admin-user-actions .button { padding:7px 10px; font-size:.7rem; }
.status-badge { padding:4px 7px; border-radius:999px; background:#f4e7d6; color:#83531d; font-size:.65rem; font-weight:800; }
.status-badge.success { background:#e3f4e9; color:#176037; }
.admin-shell { min-height:100vh; }
.admin-workspace { width:100%; max-width:none; }
.admin-workspace > .panel { max-width:none; }
.admin-tabs { padding-inline:clamp(16px, 3vw, 42px); }
.team-panel { display:grid; gap:20px; }
.team-owner-card { display:flex; align-items:center; justify-content:space-between; gap:20px; padding:16px; border:1px solid var(--line); border-radius:10px; background:var(--soft); }
.team-owner-card > div { display:grid; gap:4px; }
.team-owner-card small { color:var(--muted); }
.team-owner-actions { display:flex; align-items:center; gap:10px; }
.subscription-lock { display:flex; align-items:center; justify-content:space-between; gap:20px; padding:18px; border:1px solid #e1bd78; border-radius:10px; background:#fff8e9; }
.subscription-lock h3, .subscription-lock p { margin:0; }
.subscription-lock .eyebrow { margin-bottom:6px; color:#8a5c16; }
.subscription-lock div > p:last-child { max-width:680px; margin-top:6px; color:var(--muted); line-height:1.5; }
.subscription-lock .button { flex:0 0 auto; }
.project-access-list { display:grid; gap:8px; }
.project-access-person { display:flex; align-items:center; justify-content:space-between; gap:14px; padding:12px 14px; border:1px solid var(--line); border-radius:9px; background:var(--soft); }
.project-access-person div { min-width:0; }
.project-access-person strong, .project-access-person small { display:block; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.project-access-person small { margin-top:3px; color:var(--muted); }
.subscription-workspace { width:100%; max-width:1080px; }
.subscription-panel { padding:24px; }
.subscription-grid { display:grid; grid-template-columns:repeat(2,minmax(0,1fr)); gap:14px; }
.subscription-card { padding:18px; border:1px solid var(--line); border-radius:11px; background:var(--soft); }
.subscription-card.current { border-color:var(--brand); box-shadow:inset 0 0 0 1px var(--brand); }
.subscription-card-head { display:flex; align-items:center; justify-content:space-between; gap:10px; }
.subscription-card-head > strong { color:var(--brand-ink); font-size:1.1rem; }
.subscription-card h3 { margin:16px 0 6px; }
.subscription-card p { margin:0; color:var(--muted); line-height:1.5; }
.project-invitations { display:grid; gap:8px; margin:16px 0; padding:14px; border:1px solid var(--brand); border-radius:10px; background:var(--soft); }
.project-invitation-row, .team-member-row { display:flex; align-items:center; justify-content:space-between; gap:12px; padding:10px 0; border-bottom:1px solid var(--line); }
.project-invitation-row:last-child, .team-member-row:last-child { border-bottom:0; }
.project-invitation-row small, .team-member-row small { display:block; margin-top:3px; color:var(--muted); }
.email-invitation-card { display:grid; gap:10px; margin:16px 0; padding:18px; border:1px solid var(--brand); border-radius:14px; background:linear-gradient(145deg,var(--soft),#fff); }
.email-invitation-card h3,.email-invitation-card p { margin:0; }
.email-invitation-card.error { border-color:var(--danger,#c5542d); }
.invitation-people { display:flex; align-items:center; gap:10px; color:var(--muted); }
.invitation-bubbles { display:flex; padding-left:7px; }
.invitation-person-bubble { position:relative; display:grid; place-items:center; flex:0 0 auto; width:34px; height:34px; margin-left:-7px; overflow:hidden; border:2px solid #fff; border-radius:50%; background:var(--brand); color:#fff; font-size:.68rem; font-weight:850; }
.invitation-person-bubble img { position:absolute; inset:0; width:100%; height:100%; object-fit:cover; }
.project-access-person { align-items:center; gap:10px; }
.project-people-overview { display:flex; align-items:center; gap:12px; padding:12px 7px; color:var(--muted); }
.team-invite-form { display:grid; grid-template-columns:minmax(220px, 1fr) 150px auto; align-items:end; gap:12px; margin-top:18px; padding:16px; border:1px solid var(--line); border-radius:10px; background:var(--soft); }
.team-invite-form label { display:grid; gap:6px; }
.team-member-list { margin-top:20px; }
.viewer-banner { margin-bottom:14px; padding:10px 14px; border:1px solid var(--brand); border-radius:9px; background:var(--soft); color:var(--brand); font-weight:700; }
/* Through a link there is nothing more to say than that it is view only: one tag in the
   header, big enough to be read at a glance, rather than a paragraph above the sheet. */
.status-badge.view-only-badge { padding:6px 12px; border:1px solid var(--brand); background:var(--soft); color:var(--brand); font-size:.8rem; }
/* A view-only link that does not open: one card on the page background, saying so
   plainly, with the way back to PatchBase. */
.link-closed { min-height:100vh; display:grid; place-items:center; padding:32px 16px; background:var(--soft); }
.link-closed-card { width:100%; max-width:480px; padding:40px 36px 36px; border:1px solid var(--line); border-radius:16px; background:var(--panel); box-shadow:0 18px 50px rgba(21, 23, 26, .08); text-align:center; }
.link-closed-logo { width:52px; height:52px; margin:0 auto 26px; display:block; }
.link-closed-icon { width:64px; height:64px; margin:0 auto 18px; display:grid; place-items:center; border-radius:50%; background:#fbe9e2; color:var(--accent); }
.link-closed-card .eyebrow { margin:0 0 6px; }
.link-closed-card h1 { margin:0 0 12px; font-size:1.6rem; line-height:1.25; color:var(--ink); }
.link-closed-card p { margin:0 0 10px; color:var(--muted); line-height:1.55; }
.link-closed-card .link-closed-hint { margin-bottom:26px; color:var(--ink); font-weight:600; }
.link-closed-card .button { display:inline-flex; text-decoration:none; }
@media (max-width: 520px) { .link-closed-card { padding:30px 20px 24px; } .link-closed-card h1 { font-size:1.35rem; } }
.share-link-current { display:flex; gap:8px; align-items:center; flex-wrap:wrap; }
.share-link-current input { flex:1 1 320px; min-width:0; font-family:ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; font-size:12px; }
.share-link-usage { display:block; margin-top:6px; color:var(--muted); }
.team-coming-soon { display:grid; grid-template-columns:minmax(0, 1fr) auto; gap:12px 16px; align-items:end; max-width:720px; padding:18px; border:1px dashed var(--line); border-radius:10px; }
.team-coming-soon h3, .team-coming-soon p, .team-coming-soon small { grid-column:1 / -1; margin:0; }
.team-coming-soon p, .team-coming-soon small { color:var(--muted); }
.team-coming-soon label { display:grid; gap:6px; }
.team-coming-soon input { padding:10px 12px; border:1px solid var(--line); border-radius:8px; background:var(--field); }
.profile-shell { min-height:100vh; }
.profile-workspace { display:grid; grid-template-columns:minmax(300px, .82fr) minmax(340px, 1fr); gap:20px; align-items:start; width:100%; max-width:1180px; margin:0 auto; }
.profile-card { min-width:0; padding:22px; }
.profile-card .profile-sections { gap:14px; }
.profile-card .profile-section { gap:11px; padding-top:14px; }
.profile-card .auth-form input { padding:9px 11px; }
.team-account-card { display:grid; gap:18px; }
.team-account-card .panel-header { align-items:flex-start; }
.team-empty-state { padding:16px; border:1px solid var(--line); border-radius:10px; background:var(--soft); }
.team-empty-state h3, .team-empty-state p { margin:0; }
.team-empty-state p { margin-top:6px; color:var(--muted); line-height:1.5; }
.team-create-preview { opacity:.72; }
.team-create-preview small { color:var(--muted); }
.account-team-card { display:grid; gap:14px; padding:16px; border:1px solid var(--line); border-radius:12px; background:var(--soft); }
.account-team-card .panel-header h3, .account-team-card .panel-header p, .account-team-card h4 { margin:0; }
.account-team-card .panel-header p, .account-team-card h4 { color:var(--muted); }
.team-people-grid { display:grid; grid-template-columns:repeat(auto-fit,minmax(230px,1fr)); gap:10px; }
.team-person-card { display:grid; grid-template-columns:auto minmax(0,1fr) auto; align-items:start; gap:11px; padding:11px; border:1px solid var(--line); border-radius:10px; background:var(--field); }
.team-person-copy { display:grid; gap:2px; min-width:0; }
.team-person-copy strong, .team-person-copy small { overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.team-person-copy small { color:var(--muted); }
.team-person-copy em { color:var(--brand); font-size:.66rem; font-style:normal; font-weight:800; text-transform:capitalize; }
.team-person-role { display:grid; grid-template-columns:auto minmax(0, 110px); align-items:center; gap:7px; margin-top:5px; color:var(--muted); font-size:.64rem; font-weight:750; }
.team-person-role select { min-width:0; padding:6px 7px; border:1px solid var(--line); border-radius:7px; background:var(--field); }
.team-person-actions { display:flex; align-items:center; gap:6px; padding-top:2px; }
.team-management-actions { justify-content:flex-end; }

@media (max-width: 980px) {
  .auth-splash { grid-template-columns:1fr; align-items:start; }
  .auth-intro { display:none; }
  .auth-panel { max-width:620px; max-height:none; margin:28px auto; }
}

@media (max-width: 620px) {
  .team-coming-soon { grid-template-columns:1fr; }
  .team-coming-soon .button { width:100%; }
}

@media (max-width: 560px) {
  .auth-splash { padding:12px; }
  .auth-panel { margin:0; padding:22px 18px; border-radius:14px; }
  .auth-name-grid { grid-template-columns:1fr; }
  .auth-form-row { align-items:flex-start; flex-direction:column; }
  .auth-panel-header { display:grid; gap:14px; }
  .admin-search, .admin-user { grid-template-columns:1fr; }
  .admin-user-actions { grid-column:1; }
  .profile-workspace { grid-template-columns:1fr; max-width:680px; }
  .subscription-grid { grid-template-columns:1fr; }
  .subscription-panel { padding:16px; }
  .subscription-lock { align-items:stretch; flex-direction:column; }
  .subscription-lock .button { width:100%; }
  .profile-card { padding:14px; }
  .profile-identity { align-items:flex-start; gap:12px; }
  .profile-avatar { width:58px; height:58px; }
  .team-people-grid { grid-template-columns:1fr; }
  .team-person-card { grid-template-columns:42px minmax(0,1fr) auto; }
  .team-person-avatar { width:42px; height:42px; }
  .team-person-role { grid-template-columns:auto minmax(0,1fr); max-width:170px; }
  .team-invite-form { grid-template-columns:1fr; padding:12px; }
  .toolbar { display:grid; grid-template-columns:repeat(3,minmax(0,1fr)); align-items:center; gap:8px; }
  .toolbar .brand-lockup { grid-column:1 / -1; }
  .toolbar .button-row.toolbar-actions,
  .toolbar .button-row.toolbar-nav { display:contents; }
  .toolbar .toolbar-actions > *,
  .toolbar .toolbar-nav > .button { min-width:0; flex:0 1 auto; }
  /* Each row starts its own line, so the three places to go always sit together
     as one row whether or not the page above them has actions of its own. */
  .toolbar .toolbar-actions > *:first-child,
  .toolbar .toolbar-nav > *:first-child { grid-column-start:1; }
  .toolbar .toolbar-actions [data-live-presence]:empty { display:none; }
  .toolbar .button { width:100%; }
  /* The wordmark and stray buttons the Projects page used as a header are now in
     the toolbar above it, so the hero only has to carry the copy. */
  .splash-shell .splash-title { display:none; }
  .patch-subtabs { display:grid; grid-template-columns:repeat(3,minmax(0,1fr)); }
  .patch-subtabs .subtab { min-width:0; padding:8px 5px; font-size:.72rem; text-align:center; }
  .patch-subtabs .subtab:first-child { grid-column:1 / -1; }
  .requirements-grid { display:block; }
  .requirements-mobile-tabs { display:grid; grid-template-columns:1fr 1fr; gap:6px; margin-bottom:10px; }
  .requirements-grid.requirements-system .requirements-inventory-panel,
  .requirements-grid.requirements-inventory .requirements-system-panel { display:none; }
  .requirements-grid > .panel { padding:14px; }
  .requirements-grid .panel-header { margin-bottom:12px; }
  .requirements-grid .panel-header h2 { font-size:1.15rem; }
  .history-panel { padding:14px; }
}
.output-card-owner {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: 0.4rem;
  margin-top: 0.25rem;
  color: var(--muted);
  font-size: 0.68rem;
  font-weight: 750;
}

.output-card-owner select {
  width: auto;
  min-width: 7.5rem;
  max-width: 11rem;
  padding: 0.28rem 1.7rem 0.28rem 0.45rem;
  font-size: 0.7rem;
}

.output-source-control {
  display: grid;
  gap: 0.2rem;
}

.output-control-owner {
  color: var(--brand-ink);
  font-size: 0.62rem;
  font-weight: 800;
  line-height: 1.1;
}

.output-control-lock {
  display: inline-flex;
  min-height: 1.8rem;
  align-items: center;
  padding: 0.35rem 0.55rem;
  border: 1px dashed var(--line, #cad4d6);
  border-radius: 0.45rem;
  background: var(--surface-muted, #f3f6f6);
}

/* System Config on a narrow screen ------------------------------------------
   Flattening the map into one column removed the thing that makes it a map: you
   could no longer see a mixer, a rack and the line between them at once, so the
   connection tool had nothing to point at. The layout now stays exactly what it
   is on a desk and the screen zooms out to fit it, which is the same thing a
   person does with a drawing that is bigger than the table. */
.system-map-viewport {
  position: relative;
}

.system-map-zoom {
  display: none;
}

.system-map-scroller {
  position: relative;
}

@media (max-width: 1100px) {
  .system-map-zoom {
    display: flex;
    position: sticky;
    z-index: 6;
    top: 6px;
    align-items: center;
    gap: 6px;
    /* Only as wide as the controls, and solid: the map scrolls underneath it. */
    width: fit-content;
    margin: 0 0 8px auto;
    padding: 4px 5px;
    background: var(--panel);
    border: 1px solid var(--line);
    border-radius: 999px;
    box-shadow: 0 4px 14px rgba(22, 29, 37, .12);
  }

  .system-map-zoom .button {
    width: auto;
    flex: 0 0 auto;
    padding: 6px 12px;
  }

  .system-map-zoom output {
    min-width: 52px;
    color: var(--muted);
    text-align: center;
    font-size: .8rem;
    font-weight: 800;
    font-variant-numeric: tabular-nums;
  }

  .system-map-scroller {
    overflow: auto;
    /* Sideways is the axis that has somewhere to go here; keep the page from
       rubber-banding underneath it. */
    overscroll-behavior-x: contain;
    -webkit-overflow-scrolling: touch;
  }

  /* zoom rather than transform: it changes layout, so the scroller gets a real
     scroll area and taps land where they look. */
  .system-map {
    zoom: var(--system-map-zoom, 1);
    /* Two columns need room to stay readable. A tablet that already has the room
       simply uses it and never zooms; a phone gets the same map, scaled down. */
    width: 100%;
    min-width: 880px;
  }

  .system-map .config-layout {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

/* Stop the page zooming when a text field is tapped ---------------------------
   iOS Safari zooms in on focus whenever the field's text is under 16px, which is
   what the dense patch-table inputs are. Sizing them at 16px on touch-sized
   screens removes the reason for the zoom, rather than taking pinch-zoom away
   from people who need it. Row heights are measured after mount, so the grid
   absorbs the extra pixels. */
@media (max-width: 820px) {
  input,
  select,
  textarea,
  .compact-input,
  .virtual-mixer-canvas > [data-mixer-channel-row] .compact-input,
  .virtual-io-canvas > tr .compact-input,
  .patch-picker-value,
  .virtual-io-canvas > tr .patch-picker-value {
    font-size: 16px;
  }
}

/* A named output carries two facts a showfile needs - which kind of bus, and
   which one - so the route-method cell holds both. The number stays narrow
   because bus numbers are one or two digits; the type takes the rest. */
.bus-type-control {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 52px;
  gap: 4px;
  align-items: stretch;
  width: 100%;
  min-width: 0;
}

.bus-type-control > select {
  min-width: 0;
}

.bus-number-input {
  min-width: 0;
  text-align: center;
}

.bus-number-input.has-error {
  border-color: var(--danger);
  background: rgba(181, 71, 58, 0.08);
}

/* The showfile export is announced before it is built, so it has to read as a
   promise rather than a broken control: visibly inert, and saying why. */
.export-format-card.is-upcoming {
  opacity: 0.62;
  cursor: default;
}

.export-format-card.is-upcoming input {
  cursor: default;
}

.export-format-badge {
  margin-left: 6px;
  padding: 2px 7px;
  border-radius: 999px;
  background: var(--patch-tint);
  color: var(--brand-ink);
  font-size: 0.62rem;
  font-style: normal;
  font-weight: 900;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  vertical-align: middle;
}

/* The Busses tab: a catalogue of what each system provides, not a list you build.
   It is built from the same parts as Inputs and Outputs - one .patch-block per
   system, in that system's own tone - so a console looks like itself wherever you
   are looking at it. Fixed buses and free capacity are facts of the console rather
   than things to edit, so they read differently from the rows you can name. */
.bus-block-title {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 10px;
}

.bus-usage {
  color: var(--brand-ink);
  font-size: 0.76rem;
  font-weight: 800;
  font-variant-numeric: tabular-nums;
  opacity: 0.72;
}

.bus-usage.is-full {
  color: var(--danger);
  opacity: 1;
}

/* A console's whole pool is 64 rows. The other tabs cap their tables the same way
   and virtualize; this one is short enough to mount whole, but it still has to stop
   at a height a person can see past. */
.bus-table-viewport {
  max-height: min(62vh, 640px);
  overflow-y: auto;
  overscroll-behavior-y: contain;
}

.bus-table-viewport .patch-column-row th {
  position: sticky;
  top: 0;
  z-index: 1;
}

.bus-table td {
  vertical-align: middle;
}

.bus-kind-cell {
  color: var(--muted);
}

.bus-row.is-empty .bus-kind-cell select {
  color: var(--muted);
}

/* The row being dropped onto during a bus move. */
.bus-row-drop-target td {
  box-shadow: inset 0 -2px 0 var(--brand-ink);
}

.bus-row[draggable="true"] .bus-row-label {
  cursor: grab;
}

/* Link/unlink sits with the slot number because that is what it acts on: this bus
   and the one it pairs with. Quiet until the row is under the pointer, so a column
   of them does not read as a column of buttons. */
.bus-link-toggle {
  margin-left: 6px;
  padding: 0 3px;
  border: 0;
  border-radius: 4px;
  background: transparent;
  color: var(--muted);
  font-size: 0.78rem;
  line-height: 1;
  cursor: pointer;
  opacity: 0.35;
}

.bus-row:hover .bus-link-toggle,
.bus-link-toggle:focus-visible {
  opacity: 1;
}

.bus-link-toggle.is-linked {
  color: var(--brand-ink);
  opacity: 0.85;
}

.bus-link-toggle:hover {
  background: var(--patch-tint-strong);
  opacity: 1;
}

/* A pool's heading, shown only on a console that has more than one. Its own count
   sits beside the name rather than under it. */
.bus-pool-row td {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 10px;
}

.bus-pool-row .bus-usage {
  font-size: 0.72rem;
}

/* The slot number needs only its own width - it is at most "63-64 st". Everything it
   does not use goes to "Carried by", which holds a system name and a socket per
   carrying output and is the column that actually runs out of room.
   .patch-mini-table centres its first column because there that column is a channel
   number; here it is a slot, so it reads left like the rest. */
.bus-table th:first-child,
.bus-table td:first-child {
  width: 1%;
  white-space: nowrap;
  text-align: left;
}

.bus-table th:nth-child(2),
.bus-table td:nth-child(2) {
  width: 21%;
}

.bus-table th:nth-child(3),
.bus-table td:nth-child(3) {
  width: 30%;
}

.bus-table th:last-child,
.bus-table td:last-child {
  color: var(--muted);
}

.bus-row-label {
  white-space: nowrap;
  color: var(--brand-ink);
  font-weight: 900;
}

.bus-stereo {
  margin-left: 5px;
  padding: 1px 6px;
  border-radius: 999px;
  /* The strong tint, not the light one: inside a toned block the light tint is
     almost the row's own background and the pill disappears. */
  background: var(--patch-tint-strong);
  color: var(--brand-ink);
  font-size: 0.62rem;
  font-weight: 900;
  letter-spacing: 0.04em;
  text-transform: uppercase;
}

.bus-row.is-unpatched .bus-row-label {
  color: var(--muted);
  font-weight: 800;
}

/* Capacity the console holds or has left. Tinted with the system's own colour so
   it belongs to the block rather than looking like a different kind of table. */
.bus-row.is-free td,
.bus-row.is-fixed td {
  color: var(--muted);
  background: var(--patch-tint);
  font-size: 0.8rem;
}

/* --- Admin System Files editor -------------------------------------------------
   One system per page, one column, top to bottom. The cards a spec sheet answers are
   all open, each heading carrying a one-line summary so a long system can be audited
   by scrolling; what only the routing engine needs is one Advanced card at the foot,
   shut. */
.sysedit {
  max-width: 1080px;
  margin: 0 auto;
}

.sysedit-top {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  margin-bottom: 14px;
}

.sysedit-error {
  color: var(--danger);
  font-size: 0.84rem;
  font-weight: 700;
}

.sysedit-grid {
  display: grid;
  gap: 14px;
}

.sysedit-head { padding: 2px 4px; }
.sysedit-head h2 { margin: 3px 0; font-size: 1.3rem; }

.sysedit-card {
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: 12px;
  padding: 16px 20px 18px;
}

.sysedit-card-head {
  display: flex;
  align-items: baseline;
  gap: 12px;
  flex-wrap: wrap;
  margin-bottom: 4px;
}

.sysedit-card-head h3 { margin: 0; font-size: 1rem; }

.sysedit-lead {
  margin: 0 0 12px;
  color: var(--muted);
  font-size: 0.84rem;
}

.sysedit-card-head + .sysedit-row-3,
.sysedit-card-head + .sysedit-row-2,
.sysedit-card-head + .sysedit-check-row,
.sysedit-card-head + .sysedit-field,
.sysedit-card-head + .sysedit-empty { margin-top: 10px; }

.sysedit-empty {
  display: flex;
  align-items: center;
  gap: 12px;
  flex-wrap: wrap;
  color: var(--muted);
  font-size: 0.86rem;
}

/* A quiet text button, for the choices most systems never make. */
.sysedit-link {
  margin-top: 10px;
  padding: 0;
  border: 0;
  background: none;
  color: var(--brand-ink);
  font: inherit;
  font-size: 0.82rem;
  font-weight: 700;
  cursor: pointer;
  text-decoration: underline;
  text-underline-offset: 2px;
}

.sysedit-cell-text {
  font-size: 0.86rem;
  font-weight: 700;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* The Advanced card is the one thing that folds. */
.sysedit-advanced { padding: 0; overflow: visible; }

.sysedit-sec-head {
  width: 100%;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  padding: 14px 20px;
  border: 0;
  border-radius: 12px;
  background: transparent;
  cursor: pointer;
  text-align: left;
  /* Stated rather than inherited: a bare <button> takes the platform's own control
     colour, which on iOS is link blue. Every section heading was rendering blue on a
     phone and black on a desktop. */
  color: var(--ink);
  font: inherit;
}

.sysedit-advanced.is-open .sysedit-sec-head { background: var(--soft); border-radius: 12px 12px 0 0; }
.sysedit-sec-title { display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap; }
.sysedit-sec-title strong { font-size: 1rem; }
.sysedit-sec-sum { color: var(--muted); font-size: 0.79rem; }
.sysedit-chev { color: var(--muted); font-size: 1rem; }
.sysedit-sec-body { padding: 4px 20px 18px; }
.sysedit-sec-body .sysedit-sub { margin-top: 16px; }

.sysedit-hint {
  margin: 6px 0 12px;
  color: var(--muted);
  font-size: 0.79rem;
}

.sysedit-sub {
  display: flex;
  align-items: center;
  min-height: 17px;
  margin: 4px 0 8px;
  font-size: 0.76rem;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--brand-ink);
}

.sysedit-row-2,
.sysedit-row-3,
.sysedit-row-4 { display: grid; gap: 12px; margin-bottom: 12px; }
.sysedit-row-2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.sysedit-row-3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.sysedit-row-4 { grid-template-columns: repeat(4, minmax(0, 1fr)); }

.sysedit-field { display: block; min-width: 0; }
.sysedit-field > span { display: block; font-size: 0.73rem; font-weight: 700; color: var(--muted); margin-bottom: 4px; }
.sysedit-field > small { display: block; margin-top: 4px; color: var(--muted); font-size: 0.71rem; }
.sysedit-field .compact-input { width: 100%; }

/* Controls are `font: inherit`, and a field is a <label>, which is 0.86rem/800 - so a
   control wrapped in its label came out small and heavy while the identical control in
   a repeat table inherited the body's 1rem/400. Half the form each way. iOS made it
   worse again by ignoring the inherited font on a <select> and using its own. Stated
   outright here so neither the wrapper nor the platform decides it: one size for every
   value in the form, and 1rem is also the threshold below which iOS zooms the page in
   when a field takes focus. */
.sysedit-grid input,
.sysedit-grid select,
.sysedit-grid textarea {
  font-size: 1rem;
  font-weight: 400;
}

/* A checkbox is not a text field, so it must not take the global `input` sizing - at
   width 100% it stretched into a big square and shoved its own caption to the far edge.
   The caption is then set like every other caption in the form rather than a size of
   its own. */
.sysedit-check-row { display: flex; align-items: center; gap: 4px; margin-bottom: 12px; }
.sysedit-check { display: inline-flex; align-items: center; gap: 8px; }
.sysedit-check > input[type="checkbox"] {
  width: auto;
  min-height: 0;
  flex: none;
  margin: 0;
  accent-color: var(--brand-ink);
}
.sysedit-check > span { font-size: 0.73rem; font-weight: 700; color: var(--muted); }

.sysedit-repeat { border: 1px solid var(--line); border-radius: 8px; overflow: hidden; }
.sysedit-repeat-row {
  display: grid;
  grid-template-columns: var(--cols);
  gap: 8px;
  padding: 6px 9px;
  align-items: center;
  border-bottom: 1px solid var(--line);
}
.sysedit-repeat-row.is-head {
  background: var(--soft);
  font-size: 0.67rem;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--muted);
  font-weight: 800;
}
.sysedit-repeat-extra {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 10px;
  padding: 0 9px 9px;
  border-bottom: 1px solid var(--line);
}
.sysedit-repeat-add { padding: 7px 9px; background: var(--soft); }

.sysedit-icon {
  border: 1px solid var(--line);
  background: var(--panel);
  border-radius: 6px;
  height: 28px;
  cursor: pointer;
  color: var(--muted);
}
.sysedit-icon:hover { color: var(--danger); border-color: var(--danger); }

.sysedit-pool {
  border: 1px solid var(--line);
  border-radius: 9px;
  padding: 12px;
  margin-bottom: 10px;
  background: #fcfdfd;
}
.sysedit-pool-head { display: flex; justify-content: space-between; align-items: center; margin-bottom: 10px; gap: 10px; }
.sysedit-pool-kinds { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }

/* A kind belongs to exactly one pool, so these read as a single allocation rather
   than as independent switches: the one held elsewhere is dimmed, and clicking it
   moves it here rather than adding a second claim. */
.sysedit-kind {
  font-size: 0.72rem;
  padding: 4px 10px;
  border-radius: 999px;
  border: 1px solid var(--line);
  background: var(--panel);
  color: var(--muted);
  cursor: pointer;
  font-weight: 700;
}
.sysedit-kind.on { background: #eef4f4; border-color: var(--brand); color: var(--brand-ink); font-weight: 800; }
.sysedit-kind.is-elsewhere { opacity: 0.45; border-style: dashed; }

.sysedit-save {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 12px;
  margin-top: 14px;
  padding: 12px 18px;
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: 12px;
}

@media (max-width: 900px) {
  .sysedit-row-2, .sysedit-row-3, .sysedit-row-4 { grid-template-columns: minmax(0, 1fr); }
}

/* The question mark beside a label, and what it folds away.
   Explanations sit behind these rather than under every field: the answer is wanted
   once, the first time a field is met, and a form that explains itself continuously
   is mostly prose. The bubble is a sibling rather than a floating layer, so there is
   no positioning to get wrong and it reads in order to a screen reader. */
.sysedit-help {
  position: relative;
  display: inline-flex;
  vertical-align: middle;
}

.sysedit-help-dot {
  width: 15px;
  height: 15px;
  margin-left: 5px;
  padding: 0;
  border: 1px solid var(--line);
  border-radius: 50%;
  background: var(--panel);
  color: var(--muted);
  font-size: 0.62rem;
  font-weight: 900;
  line-height: 1;
  cursor: pointer;
}

.sysedit-help-dot:hover,
.sysedit-help-dot[aria-expanded="true"] {
  border-color: var(--brand);
  background: var(--brand);
  color: #fff;
}

.sysedit-help-bubble {
  position: absolute;
  z-index: 5;
  top: calc(100% + 7px);
  left: -6px;
  width: 310px;
  max-width: 70vw;
  padding: 11px 13px;
  border: 1px solid var(--line);
  border-radius: 9px;
  background: var(--panel);
  box-shadow: var(--shadow);
  color: var(--ink);
  font-size: 0.79rem;
  font-weight: 400;
  line-height: 1.45;
  text-transform: none;
  letter-spacing: 0;
  white-space: normal;
}

.sysedit-help-bubble > span { display: block; }
.sysedit-help-bubble > span + span { margin-top: 8px; }

/* Near the right-hand edge the bubble would otherwise run off the panel. */
.sysedit-row-3 > *:last-child .sysedit-help-bubble,
.sysedit-row-4 > *:last-child .sysedit-help-bubble,
.sysedit-row-2 > *:last-child .sysedit-help-bubble {
  left: auto;
  right: -6px;
}

.sysedit-label {
  display: flex !important;
  align-items: center;
}

/* A card heading's explanation opens under the heading, left-aligned with it. */
.sysedit-card-head .sysedit-help-bubble { font-size: 0.79rem; }

.sysedit-pool-caption {
  font-size: 0.73rem;
  font-weight: 700;
  color: var(--muted);
  margin-right: 2px;
}

/* The editor on a phone.
   Held upright there is no arrangement of a six-column table worth using, so the form
   is held back and the phone is asked to turn. A media query rather than anything
   scripted: turning the phone shows the editor immediately, with nothing to dismiss
   and nothing remembered wrongly. */
.sysedit-rotate { display: none; }

@media (max-width: 860px) and (orientation: portrait) {
  .sysedit-grid { display: none; }
  .sysedit-save { display: none; }

  .sysedit-rotate {
    display: block;
    background: var(--panel);
    border: 1px solid var(--line);
    border-radius: 12px;
    padding: 22px 20px;
    text-align: center;
  }

  .sysedit-rotate strong {
    display: block;
    font-size: 1.05rem;
    margin-bottom: 8px;
    color: var(--brand-ink);
  }

  .sysedit-rotate p {
    margin: 0 auto 8px;
    max-width: 34em;
    color: var(--muted);
    font-size: 0.86rem;
    line-height: 1.5;
  }
}

/* Even in landscape a phone is narrow, so a table several columns across scrolls
   sideways inside its own box rather than crushing its fields to three characters. */
.sysedit-repeat {
  overflow-x: auto;
  overscroll-behavior-x: contain;
}

.sysedit-repeat-row,
.sysedit-repeat-extra,
.sysedit-repeat-add { min-width: 520px; }

/* A bubble opened near an edge must not leave the screen - the explanation is the
   whole point of the dot. */
.sysedit-help-bubble {
  max-width: min(310px, calc(100vw - 32px));
}

/* On a narrow screen an explanation anchored to its dot has nowhere to go - the one
   in the right-hand column opens leftwards and leaves the screen. There it becomes a
   sheet pinned to the bottom instead, which always fits and needs no measuring. */
@media (max-width: 860px) {
  /* The edge-column and card-heading rules above are two classes deep, and the
     edge-column ones pin a bubble to the right with `left: auto` - so a bare
     `.sysedit-help-bubble` here loses to them and the sheet silently stays a
     right-hand bubble. Matched selector for selector, later in the file, so the sheet
     actually wins. */
  .sysedit-help-bubble,
  .sysedit-card-head .sysedit-help-bubble,
  .sysedit-row-2 > *:last-child .sysedit-help-bubble,
  .sysedit-row-3 > *:last-child .sysedit-help-bubble,
  .sysedit-row-4 > *:last-child .sysedit-help-bubble {
    position: fixed;
    top: auto;
    left: 12px;
    right: 12px;
    bottom: max(12px, env(safe-area-inset-bottom));
    width: auto;
    max-width: none;
    /* A phone held sideways is only ~390px tall and some explanations run to two
       paragraphs, so the sheet is capped and scrolls rather than swallowing the form
       it is explaining. */
    max-height: 55vh;
    overflow-y: auto;
    overscroll-behavior: contain;
    font-size: 0.86rem;
  }

  /* The development DEV badge is pinned bottom-right at z-index 10000, so it sat on
     top of the sheet's last line. Same collision the toast already avoids at this
     width, and the same answer - but scoped to development, because on a phone in
     landscape the vertical space is worth too much to reserve for a badge that
     production does not have. */
  body[data-environment="development"] .sysedit-help-bubble {
    padding-bottom: 46px;
  }
}

/* A device being swapped for another model. The work is one long main-thread task -
   topology, every route, the whole workspace - so the card says it is working. The
   select is disabled while it runs, everywhere, so a second swap cannot start inside
   the first. */
.system-node-card.is-swapping { position: relative; }
.system-node-card.is-swapping::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  background: color-mix(in srgb, var(--panel) 72%, transparent);
  z-index: 3;
}
.system-node-card.is-swapping::before {
  content: "";
  position: absolute;
  top: 14px;
  right: 14px;
  width: 22px;
  height: 22px;
  border: 3px solid var(--line);
  border-top-color: var(--brand);
  border-radius: 50%;
  animation: auth-spin .8s linear infinite;
  z-index: 4;
}
.device-swap:disabled { opacity: .55; }

/* A page a viewer is reading - a collaborator with viewer access, or anyone holding a
   view-only link. Everything on it is already disabled - that is the viewer role,
   enforced server-side - but a disabled control still looks like a
   control, and a wall of greyed-out boxes reads as a broken page rather than as a patch
   sheet. So the chrome comes off: values read as text, and the parts that exist only to
   change something are not drawn at all. */
.app-shell.viewer-mode input:disabled,
.app-shell.viewer-mode select:disabled,
.app-shell.viewer-mode textarea:disabled {
  -webkit-appearance: none;
  appearance: none;
  background: transparent;
  border-color: transparent;
  box-shadow: none;
  color: var(--text);
  cursor: default;
  opacity: 1;
}
/* A reader is not being refused anything by hovering, so no "not allowed" cursor on
   whatever carries a tooltip. */
.app-shell.viewer-mode :disabled { cursor: default; }
.app-shell.viewer-mode select:disabled { background-image: none; padding-right: 8px; text-overflow: ellipsis; }
.app-shell.viewer-mode input:disabled::placeholder,
.app-shell.viewer-mode textarea:disabled::placeholder { color: transparent; }
.app-shell.viewer-mode .patch-picker-value:disabled { background: transparent; border-color: transparent; color: var(--text); }
.app-shell.viewer-mode .patch-picker-value.empty:disabled { color: var(--muted); }

/* The machinery of editing. None of it does anything through a link, so none of it is
   drawn: no add rows, no remove or connect buttons, no drag handles or fill corners, no
   colour and range panel, no swap picker. */
.app-shell.viewer-mode .add-system-row,
.app-shell.viewer-mode .io-color-panel,
.app-shell.viewer-mode .channel-selection-toolbar,
.app-shell.viewer-mode .config-fill-handle,
.app-shell.viewer-mode .patch-fill-handle,
.app-shell.viewer-mode .channel-grip,
.app-shell.viewer-mode .bus-link-toggle,
.app-shell.viewer-mode .io-color-remove,
.app-shell.viewer-mode [data-swap-device],
.app-shell.viewer-mode [data-remove-mixer],
.app-shell.viewer-mode [data-remove-rack],
.app-shell.viewer-mode [data-clear-rack-link],
.app-shell.viewer-mode [data-clear-rack-connections],
.app-shell.viewer-mode [data-clear-rack-rack-link],
.app-shell.viewer-mode [data-clear-mixer-link],
.app-shell.viewer-mode [data-clear-patch-picker],
.app-shell.viewer-mode [data-delete-project],
.app-shell.viewer-mode [data-create-snapshot] {
  display: none !important;
}

/* The connect buttons on System Config are where the connection lines begin and end, so
   they keep their place and lose only their look: with `display: none` a line has no
   end to draw to and runs off to the corner of the page. */
.app-shell.viewer-mode .icon-button.connect { visibility: hidden; }

/* A channel number is content, and it lives inside the button that drags it - so the
   button stays and loses its chrome, rather than being hidden with the number in it.
   Only the grip goes. */
.app-shell.viewer-mode .channel-number { cursor: default; }
.app-shell.viewer-mode .channel-move-handle {
  background: transparent;
  border-color: transparent;
  box-shadow: none;
  cursor: default;
  justify-content: center;
  padding-left: 4px;
  padding-right: 4px;
}

/* A value too long for its column ends in an ellipsis rather than mid-word: on a phone
   the columns are narrow and there is no cursor to scroll a disabled field with. */
.app-shell.viewer-mode input:disabled { text-overflow: ellipsis; }

/* The grid track owns the channel-number column, in both virtual tables.
   `td.channel-number { width: 70px }` predates virtualization: inside a grid row that
   fixed width fights the track - 56px on a desk, 44px on a phone - so the cell
   overflowed into the name column and took its right border with it, under the name
   field. What that looks like is a missing line between the number and the name, and
   columns that do not line up with their own header. */
.virtual-mixer-canvas > [data-mixer-channel-row] > td.channel-number,
.virtual-io-canvas > tr > td.channel-number {
  width: auto;
}

/* ---------------------------------------------------------------------------
   Front page (src/ui/landing.js)
   A dark stage that plays a sixty-second film in scenes, then the features and
   the sign-in panel on the ordinary light page. Every moving part is a CSS
   animation that runs only inside `.lp-scene.is-active`; the drawings in the
   demo windows are sized in em, so the cursor paths below land on the same
   cells at every screen size.
   --------------------------------------------------------------------------- */

.landing {
  --lp-bg: #07110f;
  --lp-bg-2: #0c1c18;
  --lp-panel: #0f211d;
  --lp-panel-2: #132a25;
  --lp-ink: #eef7f3;
  --lp-muted: #93aba3;
  --lp-mint: #83e2bc;
  --lp-green: #2d8a69;
  --lp-amber: #f3b749;
  --lp-bad: #ff8a7a;
  --lp-line: rgba(131, 226, 188, 0.18);
  --lp-ease: cubic-bezier(0.2, 0.7, 0.2, 1);
  min-height: 100vh;
}

.lp-sr {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

/* Navigation over the stage */

.lp-nav {
  position: absolute;
  z-index: 6;
  top: 0;
  left: 0;
  right: 0;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 16px clamp(16px, 4vw, 40px);
}

.lp-brand {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  color: var(--lp-ink);
  font-weight: 800;
  font-size: 1.12rem;
  text-decoration: none;
}

.lp-brand-mark {
  width: 32px;
  height: 32px;
}

.lp-brand em {
  padding: 2px 8px;
  border: 1px solid rgba(243, 183, 73, 0.5);
  border-radius: 999px;
  color: var(--lp-amber);
  font-size: 0.66rem;
  font-style: normal;
  letter-spacing: 0.12em;
  text-transform: uppercase;
}

.lp-nav-actions {
  display: flex;
  gap: 8px;
}

.lp-button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 38px;
  padding: 0 18px;
  border: 1px solid transparent;
  border-radius: 999px;
  background: var(--lp-mint);
  color: #06291f;
  font-weight: 750;
  font-size: 0.92rem;
  white-space: nowrap;
  transition: transform 0.15s ease, background 0.15s ease, box-shadow 0.15s ease;
}

.lp-button:hover {
  background: #a3ecd0;
  box-shadow: 0 0 0 4px rgba(131, 226, 188, 0.16);
}

.lp-button:focus-visible,
.lp-controls button:focus-visible,
.lp-brand:focus-visible {
  outline: 2px solid var(--lp-amber);
  outline-offset: 3px;
}

.lp-button.ghost {
  border-color: rgba(238, 247, 243, 0.28);
  background: transparent;
  color: var(--lp-ink);
}

.lp-button.ghost:hover {
  border-color: var(--lp-mint);
  background: rgba(131, 226, 188, 0.08);
}

.lp-button.big {
  min-height: 48px;
  padding: 0 26px;
  font-size: 1.02rem;
}

/* The stage */

.lp-stage {
  position: relative;
  overflow: hidden;
  height: max(580px, min(100svh, 940px));
  background:
    radial-gradient(ellipse 60% 55% at 50% 42%, rgba(45, 138, 105, 0.28), transparent 70%),
    radial-gradient(ellipse 40% 30% at 85% 100%, rgba(243, 183, 73, 0.07), transparent 70%),
    linear-gradient(180deg, var(--lp-bg) 0%, var(--lp-bg-2) 100%);
  color: var(--lp-ink);
  isolation: isolate;
}

.lp-stage::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background:
    repeating-linear-gradient(90deg, rgba(131, 226, 188, 0.045) 0 1px, transparent 1px 72px),
    repeating-linear-gradient(0deg, rgba(131, 226, 188, 0.03) 0 1px, transparent 1px 72px);
  mask-image: radial-gradient(ellipse 70% 60% at 50% 45%, #000 20%, transparent 80%);
}

.lp-scenes {
  position: absolute;
  inset: 0;
}

.lp-scene {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: clamp(18px, 3.2vh, 34px);
  padding: 76px 16px 76px;
  opacity: 0;
  visibility: hidden;
  transition: opacity 0.45s ease, visibility 0s linear 0.45s;
}

.lp-scene.is-active {
  opacity: 1;
  visibility: visible;
  transition: opacity 0.6s ease 0.1s, visibility 0s;
}

.lp-caption {
  max-width: 52rem;
  text-align: center;
}

.lp-caption h2,
.lp-hero-type h2 {
  margin: 0;
  font-size: clamp(1.65rem, 4.2vw, 3.3rem);
  font-weight: 800;
  line-height: 1.06;
  letter-spacing: -0.02em;
}

.lp-eyebrow {
  margin: 0 0 12px;
  color: var(--lp-mint);
  font-size: clamp(0.7rem, 1.1vw, 0.82rem);
  font-weight: 800;
  letter-spacing: 0.2em;
  text-transform: uppercase;
}

.lp-sub {
  max-width: 38rem;
  margin: 14px auto 0;
  color: var(--lp-muted);
  font-size: clamp(0.92rem, 1.35vw, 1.12rem);
  line-height: 1.55;
}

.lp-accent {
  color: var(--lp-mint);
}

.lp-hero-type {
  position: relative;
  z-index: 1;
  text-align: center;
}

.lp-hero-type h2.lp-giant {
  font-size: clamp(2.6rem, 9vw, 7rem);
  line-height: 0.98;
  letter-spacing: -0.03em;
  text-shadow: 0 0 60px rgba(131, 226, 188, 0.18);
}

.lp-hero-type h2.lp-giant-sm {
  font-size: clamp(2.2rem, 6.4vw, 5rem);
}

.lp-hero-type .lp-sub {
  font-size: clamp(1rem, 1.8vw, 1.35rem);
}

/* Motion vocabulary. `--d` is when an element starts, from the scene's start. */

.lp-scene .a {
  animation-delay: var(--d, 0s);
  animation-fill-mode: both;
  animation-timing-function: var(--lp-ease);
}

.lp-scene.is-active .rise { animation-name: lp-rise; animation-duration: 0.75s; }
.lp-scene.is-active .rise-sm { animation-name: lp-rise-sm; animation-duration: 0.35s; }
.lp-scene.is-active .fade { animation-name: lp-fade; animation-duration: 0.6s; }
.lp-scene.is-active .pop { animation-name: lp-pop; animation-duration: 0.6s; }
.lp-scene.is-active .pop-svg { animation-name: lp-pop; animation-duration: 0.55s; }
.lp-scene.is-active .strike { animation-name: lp-strike; animation-duration: 0.5s; }
.lp-scene.is-active .draw { animation-name: lp-draw; animation-duration: 1.1s; animation-timing-function: ease-in-out; }
.lp-scene.is-active .fill { animation-name: lp-fill; animation-duration: 0.7s; animation-timing-function: ease-out; }
.lp-scene.is-active .route { animation-name: lp-route; animation-duration: 0.6s; animation-timing-function: ease-out; }
.lp-scene.is-active .packet {
  animation-name: lp-packet;
  animation-duration: 1.8s;
  animation-timing-function: linear;
  animation-iteration-count: infinite;
  animation-fill-mode: backwards;
}

.pop-svg {
  transform-box: fill-box;
  transform-origin: center;
}

@keyframes lp-rise { from { opacity: 0; transform: translateY(18px); } to { opacity: 1; transform: none; } }
@keyframes lp-rise-sm { from { opacity: 0; transform: translateY(6px); } to { opacity: 1; transform: none; } }
@keyframes lp-fade { from { opacity: 0; } to { opacity: 1; } }
@keyframes lp-pop { from { opacity: 0; transform: scale(0.82); } 70% { opacity: 1; transform: scale(1.03); } to { opacity: 1; transform: none; } }
@keyframes lp-strike { from { transform: scaleX(0); } to { transform: scaleX(1); } }
@keyframes lp-draw { from { stroke-dashoffset: 100; } to { stroke-dashoffset: 0; } }
@keyframes lp-packet { from { stroke-dashoffset: 100; opacity: 1; } to { stroke-dashoffset: 0; opacity: 1; } }
@keyframes lp-route { from { clip-path: inset(0 100% 0 0); } to { clip-path: inset(0 0 0 0); } }
@keyframes lp-fill {
  from { opacity: 0; transform: translateX(-6px); background: rgba(131, 226, 188, 0.4); }
  30% { opacity: 1; transform: none; background: rgba(131, 226, 188, 0.4); }
  to { opacity: 1; transform: none; background: transparent; }
}

/* Scene 1: the opener. An isometric stage the camera pulls back from, then the
   name landing on it. The camera keyframes are written by landing.js. */

.lp-iso {
  position: absolute;
  inset: 0;
  transform-origin: 50% 45%;
}

.lp-iso-svg {
  position: absolute;
  inset: 70px 0 60px;
  width: 100%;
  height: calc(100% - 130px);
  overflow: visible;
}

.lp-floor {
  fill: none;
  stroke: rgba(131, 226, 188, 0.1);
  stroke-width: 1;
}

.lp-cable {
  fill: none;
  stroke: var(--lp-mint);
  stroke-opacity: 0.7;
  stroke-width: 2.5;
  stroke-linecap: round;
  stroke-linejoin: round;
  stroke-dasharray: 100;
  filter: drop-shadow(0 0 5px rgba(131, 226, 188, 0.6));
}

.lp-face-top { fill: #1f3d36; stroke: rgba(131, 226, 188, 0.45); stroke-width: 1; }
.lp-face-front { fill: #0f231f; stroke: rgba(131, 226, 188, 0.3); stroke-width: 1; }
.lp-face-side { fill: #0a1916; stroke: rgba(131, 226, 188, 0.25); stroke-width: 1; }

.lp-fader {
  stroke: rgba(238, 247, 243, 0.35);
  stroke-width: 1.4;
}

.lp-led {
  fill: var(--lp-mint);
  opacity: 0.35;
}

.lp-scene.is-active .lp-led {
  animation: lp-led 1.6s steps(1) var(--b) infinite;
}

@keyframes lp-led {
  0%, 100% { opacity: 0.35; }
  30% { opacity: 1; fill: var(--lp-amber); }
  60% { opacity: 0.9; }
}

.lp-iso-label {
  fill: var(--lp-ink);
  font-size: 13px;
  font-weight: 750;
  text-anchor: middle;
  letter-spacing: 0.02em;
}

.lp-scene.is-active .rise-iso {
  animation-name: lp-rise-iso;
  animation-duration: 0.9s;
}

@keyframes lp-rise-iso {
  from { opacity: 0; transform: translateY(40px); }
  to { opacity: 1; transform: none; }
}

.lp-opener-line {
  position: absolute;
  left: 16px;
  right: 16px;
  bottom: 17%;
  margin: 0;
  font-size: clamp(1.9rem, 5.2vw, 4rem);
  font-weight: 800;
  letter-spacing: -0.025em;
  text-align: center;
  text-shadow: 0 4px 30px rgba(0, 0, 0, 0.8);
  opacity: 0;
}

.lp-scene-opener .lp-brand-reveal {
  position: relative;
  z-index: 2;
}

/* The logo */

.lp-brand-reveal .lp-wordmark {
  margin-top: 18px;
  font-size: clamp(2.8rem, 8vw, 6rem);
  letter-spacing: -0.03em;
}

.lp-brand-reveal .lp-sub {
  margin-top: 6px;
}

.lp-logo-big {
  width: clamp(88px, 11vw, 136px);
  height: auto;
  filter: drop-shadow(0 0 40px rgba(131, 226, 188, 0.45));
}

/* Patch: the sheet and the system side by side */

.lp-scene-patch .lp-demo {
  font-size: clamp(5.5px, min(1.2vw, 1.62vh), 13px);
}

.lp-split {
  display: flex;
  align-items: center;
  gap: 2.4em;
  perspective: 1600px;
}

.lp-map {
  width: 18em;
  padding: 1em 1.1em 1.1em;
  border: 1px solid var(--lp-line);
  border-radius: 0.9em;
  background: rgba(12, 28, 24, 0.85);
  box-shadow: 0 24px 60px rgba(0, 0, 0, 0.45);
  text-align: left;
}

.lp-map-head {
  margin: 0 0 0.6em;
  color: var(--lp-muted);
  font-size: 0.8em;
  font-weight: 750;
  letter-spacing: 0.12em;
  text-transform: uppercase;
}

.lp-map svg {
  display: block;
  width: 100%;
  height: auto;
  overflow: visible;
}

.lp-map-link {
  fill: none;
  stroke: rgba(238, 247, 243, 0.16);
  stroke-width: 2;
}

.lp-map-route {
  fill: none;
  stroke-width: 3;
  opacity: 0;
  filter: drop-shadow(0 0 5px currentColor);
}

.lp-map-flow {
  stroke-width: 5;
}

.lp-map-label {
  fill: var(--lp-muted);
  font-size: 10px;
  font-weight: 650;
}

.lp-map-devices rect {
  fill: var(--lp-panel-2);
  stroke: rgba(238, 247, 243, 0.14);
}

.lp-map-name {
  fill: var(--lp-ink);
  font-size: 12px;
  font-weight: 750;
  text-anchor: middle;
}

.lp-map-glow {
  fill: none;
  stroke-width: 2;
  opacity: 0;
  filter: drop-shadow(0 0 6px rgba(255, 255, 255, 0.35));
}

.lp-map-legend {
  display: grid;
  gap: 0.45em;
  margin: 0.9em 0 0;
  padding: 0;
  list-style: none;
}

.lp-map-legend li {
  display: flex;
  align-items: center;
  gap: 0.5em;
  opacity: 0.25;
  white-space: nowrap;
}

.lp-map-legend i {
  width: 0.7em;
  height: 0.7em;
  flex: none;
  border-radius: 50%;
}

.lp-map-legend b {
  font-size: 0.9em;
}

.lp-map-legend span {
  color: var(--lp-muted);
  font-size: 0.8em;
}

/* The camera's zoom layer inside each app window */

.lp-zoom {
  position: absolute;
  inset: 0;
  transform-origin: 0 0;
}

.lp-scene-naming .lp-demo,
.lp-scene-buses .lp-demo {
  perspective: 1600px;
}

/* The whole show, counted */

@property --lp-count {
  syntax: "<integer>";
  initial-value: 0;
  inherits: false;
}

.lp-count {
  --lp-count: var(--to);
  counter-reset: lp-count var(--lp-count);
}

.lp-count::after {
  content: counter(lp-count);
}

.lp-scene.is-active .lp-count {
  animation: lp-count 1.4s cubic-bezier(0.2, 0.7, 0.2, 1) var(--d) both;
}

@keyframes lp-count {
  from { --lp-count: 0; }
  to { --lp-count: var(--to); }
}

.lp-numbers-lead {
  margin: 0;
  color: var(--lp-ink);
  font-size: clamp(1.3rem, 3vw, 2.2rem);
  font-weight: 700;
}

.lp-big {
  display: flex;
  align-items: baseline;
  justify-content: center;
  gap: 0.15em;
  margin: 0.05em 0 0.2em;
  line-height: 1;
}

.lp-big b {
  font-size: clamp(6rem, 19vw, 13rem);
  font-weight: 900;
  letter-spacing: -0.05em;
  background: linear-gradient(180deg, #d6fbea 10%, var(--lp-mint) 55%, #2d8a69 100%);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  filter: drop-shadow(0 0 40px rgba(131, 226, 188, 0.35));
  font-variant-numeric: tabular-nums;
}

.lp-big small {
  color: var(--lp-mint);
  font-size: clamp(1.6rem, 4vw, 3rem);
  font-weight: 800;
}

.lp-stats {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: clamp(10px, 2vw, 22px);
  max-width: 760px;
  margin: 0 auto;
}

.lp-stat {
  padding: 14px 10px;
  border: 1px solid var(--lp-line);
  border-radius: 12px;
  background: rgba(15, 33, 29, 0.7);
}

.lp-stat b {
  display: block;
  color: var(--lp-ink);
  font-size: clamp(1.6rem, 3.6vw, 2.6rem);
  font-weight: 850;
  font-variant-numeric: tabular-nums;
}

.lp-stat > span {
  color: var(--lp-muted);
  font-size: clamp(0.75rem, 1.2vw, 0.92rem);
}

.lp-numbers .lp-sub {
  margin-top: 22px;
}

@media (max-width: 760px) {
  /* A phone is too narrow for the whole stage; let it run off both sides. */
  .lp-iso-svg {
    left: -22%;
    width: 144%;
  }

  .lp-map {
    display: none;
  }

  .lp-scene-patch .lp-demo {
    font-size: clamp(6.6px, min(1.55vw, 1.62vh), 13px);
  }

  .lp-stats {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

.lp-logo-mid {
  width: 72px;
  height: 72px;
  margin-bottom: 18px;
  filter: drop-shadow(0 0 30px rgba(131, 226, 188, 0.3));
}

/* Demo area: everything inside is sized in em from this one font size. */

.lp-demo {
  position: relative;
  font-size: clamp(6.6px, min(1.55vw, 1.62vh), 13px);
}

/* Scene 3: the system */

.lp-system {
  display: block;
  width: min(62em, calc(100vw - 32px));
  height: auto;
  overflow: visible;
}

.lp-device {
  fill: var(--lp-panel);
  stroke: rgba(131, 226, 188, 0.4);
  stroke-width: 1.5;
}

.lp-ports rect {
  fill: rgba(131, 226, 188, 0.22);
}

.lp-device-title {
  fill: var(--lp-ink);
  font-size: 17px;
  font-weight: 750;
}

.lp-device-sub {
  fill: var(--lp-muted);
  font-size: 12.5px;
}

.lp-link {
  fill: none;
  stroke: var(--lp-mint);
  stroke-opacity: 0.55;
  stroke-width: 2.5;
  stroke-dasharray: 100;
}

.lp-packet {
  fill: none;
  stroke: var(--lp-amber);
  stroke-width: 4.5;
  stroke-linecap: round;
  stroke-dasharray: 5 95;
  opacity: 0;
  filter: drop-shadow(0 0 6px rgba(243, 183, 73, 0.9));
}

.lp-link-label {
  fill: var(--lp-mint);
  font-size: 12px;
  font-weight: 650;
  letter-spacing: 0.02em;
}

.lp-toast {
  position: absolute;
  z-index: 3;
  top: -1.2em;
  right: -1.2em;
  display: inline-flex;
  align-items: center;
  gap: 0.5em;
  padding: 0.6em 1.1em;
  border: 1px solid rgba(131, 226, 188, 0.5);
  border-radius: 999px;
  background: #0f2a22;
  box-shadow: 0 10px 30px rgba(0, 0, 0, 0.4), 0 0 24px rgba(131, 226, 188, 0.2);
  color: var(--lp-mint);
  font-size: max(11px, 1.05em);
  font-weight: 700;
  white-space: nowrap;
}

.lp-toast svg {
  width: 1.1em;
  height: 1.1em;
}

.lp-scene-system .lp-demo {
  margin-bottom: 2.8em;
}

.lp-scene-system .lp-toast {
  top: auto;
  right: 50%;
  bottom: -2.6em;
  translate: 50% 0;
}

/* The app window the naming, patch and bus scenes play in. Its rows, cursor paths
   and drag ranges are placed in em from src/ui/landing.js, which also writes each
   scene's keyframes, so geometry here and there has to agree. */

.lp-window {
  position: relative;
  width: 50em;
  height: 28em;
  overflow: hidden;
  border: 1px solid var(--lp-line);
  border-radius: 0.9em;
  background: linear-gradient(180deg, #102420, #0b1916);
  box-shadow: 0 30px 80px rgba(0, 0, 0, 0.55), 0 0 60px rgba(45, 138, 105, 0.22);
  color: var(--lp-ink);
  text-align: left;
}

.lp-titlebar {
  display: flex;
  align-items: center;
  gap: 0.45em;
  height: 2.2em;
  padding: 0 1em;
  background: rgba(0, 0, 0, 0.22);
}

.lp-titlebar i {
  width: 0.62em;
  height: 0.62em;
  border-radius: 50%;
  background: rgba(238, 247, 243, 0.18);
}

.lp-titlebar span {
  margin-left: 1em;
  color: var(--lp-muted);
  font-size: 0.82em;
}

.lp-tabs {
  display: flex;
  align-items: flex-end;
  gap: 0.3em;
  height: 2.2em;
  padding: 0 1em;
  overflow: hidden;
  border-bottom: 1px solid var(--lp-line);
}

.lp-tabs span {
  padding: 0.45em 0.95em;
  border-radius: 0.5em 0.5em 0 0;
  color: var(--lp-muted);
  font-size: 0.82em;
  font-weight: 650;
  white-space: nowrap;
}

.lp-tabs span.is-on {
  background: rgba(131, 226, 188, 0.12);
  color: var(--lp-mint);
  box-shadow: inset 0 -2px 0 var(--lp-mint);
}

.lp-table {
  padding: 0 1em;
}

.lp-row {
  display: grid;
  grid-template-columns: var(--cols);
  align-items: center;
  height: var(--row, 2.1em);
  border-bottom: 1px solid rgba(238, 247, 243, 0.06);
}

.lp-row.lp-head {
  height: var(--head, 1.8em);
  color: var(--lp-muted);
}

.lp-row > span {
  min-width: 0;
  padding: 0 0.5em;
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
}

.lp-row.lp-head > span {
  font-size: 0.72em;
  font-weight: 750;
  letter-spacing: 0.1em;
  text-transform: uppercase;
}

.lp-row > span:first-child,
.lp-row .lp-dim {
  color: var(--lp-muted);
}

/* The number column is narrow; its header needs the room the padding takes. */
.lp-row > span:first-child {
  padding: 0 0.3em;
}

.lp-row em {
  display: inline-block;
  padding: 0 0.3em;
  border-radius: 0.3em;
  font-style: normal;
  font-weight: 650;
}

.lp-row em.is-kind {
  color: var(--lp-mint);
}

.lp-row em.is-stereo {
  color: var(--lp-amber);
}

/* Typing: the text is uncovered one character at a time, `--n` characters long. */
.lp-scene.is-active .type {
  animation-name: lp-type;
  animation-duration: calc(var(--n, 6) * 0.07s);
  animation-timing-function: steps(var(--n, 6), end);
}

@keyframes lp-type { from { clip-path: inset(0 100% 0 0); } to { clip-path: inset(0 0 0 0); } }

/* A drag: the dashed range grows under the cursor while the fill handle rides
   its bottom edge. Both are timed from landing.js. */
.lp-range {
  position: absolute;
  z-index: 2;
  border: 2px dashed var(--lp-mint);
  border-radius: 0.3em;
  background: rgba(131, 226, 188, 0.08);
  opacity: 0;
  pointer-events: none;
}

.lp-handle {
  position: absolute;
  z-index: 3;
  width: 0.8em;
  height: 0.8em;
  border: 2px solid #07110f;
  border-radius: 0.15em;
  background: var(--lp-mint);
  opacity: 0;
}

/* Picker and menu */

.lp-picker,
.lp-menu {
  position: absolute;
  z-index: 4;
  padding: 0.35em;
  border: 1px solid rgba(131, 226, 188, 0.4);
  border-radius: 0.55em;
  background: var(--lp-panel-2);
  box-shadow: 0 18px 40px rgba(0, 0, 0, 0.55);
  opacity: 0;
}

.lp-picker > small,
.lp-menu > small {
  display: block;
  height: 2em;
  padding: 0 0.85em;
  overflow: hidden;
  color: var(--lp-muted);
  font-size: 0.7em;
  font-weight: 750;
  line-height: 2em;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  white-space: nowrap;
}

.lp-option {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.6em;
  height: 1.7em;
  padding: 0 0.6em;
  border-radius: 0.35em;
}

.lp-option span {
  font-weight: 650;
}

.lp-option small {
  color: var(--lp-mint);
  font-size: 0.8em;
}

.lp-menu span {
  display: block;
  height: 1.7em;
  padding: 0 0.6em;
  border-radius: 0.35em;
  line-height: 1.7em;
  font-weight: 650;
}

/* Cursor. Its tip is the element's top-left corner. */

.lp-cursor {
  position: absolute;
  z-index: 6;
  top: 0;
  left: 0;
  width: 1.35em;
  height: 1.6em;
  opacity: 0;
  pointer-events: none;
  transform-origin: 0 0;
}

.lp-cursor svg {
  display: block;
  width: 100%;
  height: 100%;
  fill: #fff;
  stroke: #07110f;
  stroke-width: 1.3;
  filter: drop-shadow(0 2px 4px rgba(0, 0, 0, 0.5));
}

.lp-click {
  position: absolute;
  left: -0.7em;
  top: -0.7em;
  width: 1.4em;
  height: 1.4em;
  border: 2px solid var(--lp-amber);
  border-radius: 50%;
  opacity: 0;
}

/* Patch: three desks side by side, as the Mixer Channels tab shows them. */

.lp-desks {
  position: absolute;
  top: 4.9em;
  left: 1em;
  display: grid;
  grid-template-columns: repeat(3, 15.4em);
  gap: 0.6em;
}

.lp-desk-title {
  display: flex;
  align-items: baseline;
  gap: 0.5em;
  height: 2em;
  padding: 0 0.5em;
  white-space: nowrap;
}

.lp-desk-title b {
  font-size: 1.05em;
}

.lp-desk-title span {
  color: var(--lp-mint);
  font-size: 0.78em;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

.lp-desk .lp-table {
  padding: 0;
  border: 1px solid rgba(238, 247, 243, 0.08);
  border-radius: 0.4em;
}

.lp-strip {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.3em;
  margin-top: 0.5em;
  font-size: 0.74em;
}

.lp-strip b {
  padding: 0.2em 0.55em;
  border-radius: 0.4em;
  background: rgba(131, 226, 188, 0.13);
  color: var(--lp-mint);
  font-weight: 650;
  white-space: nowrap;
}

.lp-strip b.is-link {
  background: rgba(243, 183, 73, 0.14);
  color: var(--lp-amber);
}

.lp-strip i {
  width: 0.8em;
  height: 1px;
  background: var(--lp-mint);
  opacity: 0.6;
}

/* What you no longer do */

.lp-chores ul {
  display: grid;
  gap: 0.45em;
  margin: 0;
  padding: 0;
  list-style: none;
  font-size: clamp(1.3rem, 3.3vw, 2.5rem);
  font-weight: 750;
  letter-spacing: -0.01em;
}

.lp-chores li {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 0.5em;
}

/* The strike runs behind the words, so they stay readable once crossed out. */
.lp-chores li > span {
  position: relative;
  z-index: 0;
  display: inline-block;
}

.lp-chores li > span > i {
  position: absolute;
  z-index: -1;
  left: -1%;
  right: -1%;
  top: 52%;
  height: 0.12em;
  border-radius: 999px;
  background: rgba(243, 183, 73, 0.55);
  transform-origin: left center;
}

.lp-x {
  display: grid;
  place-items: center;
  flex: none;
  width: 1.1em;
  height: 1.1em;
  border-radius: 50%;
  background: rgba(243, 183, 73, 0.16);
  color: var(--lp-amber);
  font-size: 0.6em;
  font-weight: 900;
}

.lp-chores .lp-sub {
  margin-top: 26px;
}

/* Coming soon: the showfile */

.lp-soon {
  display: inline-block;
  margin: 0 0 16px;
  padding: 7px 16px;
  border-radius: 999px;
  background: var(--lp-amber);
  box-shadow: 0 0 30px rgba(243, 183, 73, 0.4);
  color: #2b1d00;
  font-size: clamp(0.78rem, 1.2vw, 0.95rem);
  font-weight: 850;
  letter-spacing: 0.14em;
  text-transform: uppercase;
}

.lp-export {
  display: flex;
  align-items: center;
  gap: 2.6em;
  font-size: clamp(7.5px, min(1.8vw, 1.9vh), 15px);
}

.lp-doc,
.lp-file {
  position: relative;
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  border: 1px solid var(--lp-line);
  border-radius: 0.8em;
  background: var(--lp-panel);
  box-shadow: 0 20px 50px rgba(0, 0, 0, 0.45);
}

.lp-doc {
  width: 11em;
  height: 14em;
  padding: 1.2em;
}

.lp-doc-lines {
  display: grid;
  gap: 0.75em;
  margin-bottom: auto;
}

.lp-doc-lines i {
  height: 0.55em;
  border-radius: 999px;
  background: rgba(238, 247, 243, 0.14);
}

.lp-doc-lines i:nth-child(3n + 1) { width: 70%; background: rgba(131, 226, 188, 0.35); }
.lp-doc-lines i:nth-child(3n + 2) { width: 90%; }

.lp-doc b,
.lp-file b {
  font-size: 1.1em;
}

.lp-flow {
  display: flex;
  gap: 0.6em;
}

.lp-flow i {
  width: 0.7em;
  height: 0.7em;
  border-radius: 50%;
  background: var(--lp-mint);
  animation: lp-flow 1.2s ease-in-out infinite;
}

.lp-flow i:nth-child(2) { animation-delay: 0.2s; }
.lp-flow i:nth-child(3) { animation-delay: 0.4s; }

@keyframes lp-flow {
  0%, 100% { opacity: 0.25; transform: scale(0.8); }
  50% { opacity: 1; transform: scale(1.1); }
}

.lp-outputs {
  display: flex;
  gap: 1.4em;
}

.lp-file {
  width: 9em;
  height: 10.5em;
  padding: 1em;
}

.lp-file span {
  margin-bottom: auto;
  color: var(--lp-mint);
  font-size: 1.5em;
  font-weight: 800;
  letter-spacing: 0.04em;
}

.lp-file em {
  position: absolute;
  top: -0.9em;
  left: 50%;
  translate: -50% 0;
  padding: 0.3em 0.8em;
  border-radius: 999px;
  background: rgba(131, 226, 188, 0.18);
  color: var(--lp-mint);
  font-size: max(10px, 0.82em);
  font-style: normal;
  font-weight: 800;
  white-space: nowrap;
}

.lp-file.is-soon {
  border: 2px dashed rgba(243, 183, 73, 0.75);
  background: rgba(243, 183, 73, 0.06);
}

.lp-file.is-soon span {
  color: var(--lp-amber);
}

.lp-file.is-soon em {
  background: var(--lp-amber);
  color: #2b1d00;
}

.lp-scene-showfile.is-active .lp-file.is-soon {
  animation: lp-pop 0.6s var(--lp-ease) var(--d) both, lp-soon-glow 1.6s ease-in-out calc(var(--d) + 0.6s) infinite;
}

@keyframes lp-soon-glow {
  0%, 100% { box-shadow: 0 20px 50px rgba(0, 0, 0, 0.45), 0 0 20px rgba(243, 183, 73, 0.12); }
  50% { box-shadow: 0 20px 50px rgba(0, 0, 0, 0.45), 0 0 48px rgba(243, 183, 73, 0.4); }
}

/* Scene 9 */

.lp-cta .lp-sub {
  margin-top: 18px;
}

.lp-cta-buttons {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 12px;
  margin-top: 30px;
}

/* Controls */

.lp-controls {
  position: absolute;
  z-index: 5;
  left: 50%;
  bottom: 18px;
  display: flex;
  align-items: center;
  gap: 14px;
  width: min(680px, calc(100% - 32px));
  translate: -50% 0;
}

.lp-play {
  display: grid;
  flex: none;
  place-items: center;
  width: 36px;
  height: 36px;
  border: 1px solid rgba(238, 247, 243, 0.25);
  border-radius: 50%;
  background: rgba(7, 17, 15, 0.6);
  color: var(--lp-ink);
}

.lp-play:hover {
  border-color: var(--lp-mint);
  color: var(--lp-mint);
}

.lp-play svg {
  width: 14px;
  height: 14px;
  fill: currentColor;
}

.lp-progress {
  display: flex;
  flex: 1;
  gap: 5px;
  margin: 0;
  padding: 0;
  list-style: none;
}

.lp-progress button {
  display: flex;
  align-items: center;
  width: 100%;
  height: 22px;
  padding: 0;
  background: transparent;
}

.lp-progress button span {
  position: relative;
  width: 100%;
  height: 3px;
  overflow: hidden;
  border-radius: 999px;
  background: rgba(238, 247, 243, 0.16);
}

.lp-progress button span::after {
  content: "";
  position: absolute;
  inset: 0;
  background: var(--lp-mint);
  transform: scaleX(0);
  transform-origin: left center;
}

.lp-progress button:hover span {
  background: rgba(238, 247, 243, 0.32);
}

.lp-progress li.is-done span::after {
  transform: scaleX(1);
}

.lp-progress li.is-current span::after {
  animation: lp-progress linear both;
  animation-duration: inherit;
}

@keyframes lp-progress { from { transform: scaleX(0); } to { transform: scaleX(1); } }

.lp-chapter {
  flex: none;
  min-width: 8.5em;
  color: var(--lp-muted);
  font-size: 0.8rem;
  font-weight: 650;
}

.lp-stage.is-paused *,
.lp-stage.is-paused *::after {
  animation-play-state: paused !important;
}

/* Someone who asked for less motion sees each scene's finished state, and steps
   through the chapters with play or the progress bar. */
.lp-stage.is-still *,
.lp-stage.is-still *::after {
  animation-duration: 1ms !important;
  animation-delay: 0s !important;
  animation-iteration-count: 1 !important;
}

.lp-stage.is-still .lp-scene {
  transition: none;
}

/* Below the stage: features and sign-in, on the ordinary light page */

.lp-features {
  padding: clamp(48px, 7vw, 88px) clamp(16px, 6vw, 82px) 0;
}

.lp-features-grid {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 18px;
  max-width: 1180px;
  margin: 0 auto;
}

.lp-feature {
  padding: 22px;
  border: 1px solid var(--line);
  border-top: 3px solid var(--brand);
  border-radius: 8px;
  background: var(--panel);
  box-shadow: var(--shadow);
}

.lp-feature h3 {
  margin: 0 0 8px;
  font-size: 1.08rem;
}

.lp-feature p {
  margin: 0;
  color: var(--muted);
  line-height: 1.55;
}

.lp-auth {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(340px, 500px);
  gap: 42px;
  align-items: center;
  max-width: 1180px;
  margin: 0 auto;
  padding: clamp(48px, 7vw, 88px) clamp(16px, 6vw, 82px);
  scroll-margin-top: 12px;
}

.lp-auth-intro h2 {
  margin: 0;
  font-size: clamp(2rem, 4.6vw, 3.6rem);
  line-height: 1;
  letter-spacing: -0.02em;
}

.lp-auth-intro > p:last-child {
  max-width: 34rem;
  margin: 20px 0 0;
  color: #404852;
  font-size: 1.08rem;
  line-height: 1.6;
}

@media (max-width: 980px) {
  .lp-features-grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }

  .lp-auth {
    grid-template-columns: minmax(0, 1fr);
    gap: 24px;
  }
}

@media (max-width: 640px) {
  .lp-nav .lp-button {
    min-height: 34px;
    padding: 0 13px;
    font-size: 0.84rem;
  }

  .lp-brand em {
    display: none;
  }

  .lp-features-grid {
    grid-template-columns: minmax(0, 1fr);
  }

  .lp-chapter {
    display: none;
  }

  .lp-export {
    flex-direction: column;
    gap: 1.4em;
  }

  .lp-flow {
    rotate: 90deg;
  }

  .lp-doc {
    display: none;
  }

  .lp-toast {
    right: 0;
  }
}
