/* Dark by default: this is a structure viewer, where a dark field is the
   convention and keeps the chain the brightest thing on screen. Light is
   available for printing, projectors and daylight. The viewport colours are
   tokens too, so the 3D scene follows the page instead of staying black. */
:root {
  color-scheme: dark;

  --bg: #0f1115;
  --panel: #171a21;
  --panel-2: #1e222b;
  --line: #2a2f3a;
  --text: #e6e9ef;
  --muted: #8b93a3;
  --accent: #5aa9ff;
  --ok: #4ec9a0;
  --warn: #e0a458;
  --bad: #e5696b;
  --helix: #e05f6a;
  --strand: #e3c05c;
  --loop: #7f8a9c;
  --sketch: #a888e8;

  --viewport-bg: #0f1115;
  --grid: #2a2f3a;
  --grid-centre: #1d212a;
  --ambient: 0.55;

  --hover: #252a35;
  --hover-line: #3b4252;
  --on-accent: #06121f;
  --selected: #1d2a3a;
}

/* Light values, defined once and applied both to an explicit choice and to a
   light system preference when no choice has been made. */
@media (prefers-color-scheme: light) {
  :root:not([data-theme='dark']) {
    color-scheme: light;

    --bg: #f4f5f7;
    --panel: #ffffff;
    --panel-2: #f0f2f5;
    --line: #d8dce3;
    --text: #1b1f27;
    --muted: #606a7b;
    --accent: #1f6fd0;
    --ok: #1f8a62;
    --warn: #a35c10;
    --bad: #c0392f;
    --helix: #d04452;
    --strand: #c79a1e;
    --loop: #6c7889;
    --sketch: #7b55c9;

    --viewport-bg: #e9ecf1;
    --grid: #c7cdd8;
    --grid-centre: #aeb6c4;
    --ambient: 0.85;

    --hover: #e6e9ef;
    --hover-line: #b4bcc9;
    --on-accent: #ffffff;
    --selected: #dde9fa;
  }
}

:root[data-theme='light'] {
  color-scheme: light;

  --bg: #f4f5f7;
  --panel: #ffffff;
  --panel-2: #f0f2f5;
  --line: #d8dce3;
  --text: #1b1f27;
  --muted: #606a7b;
  --accent: #1f6fd0;
  --ok: #1f8a62;
  --warn: #a35c10;
  --bad: #c0392f;
  --helix: #d04452;
  --strand: #c79a1e;
  --loop: #6c7889;
  --sketch: #7b55c9;

  --viewport-bg: #e9ecf1;
  --grid: #c7cdd8;
  --grid-centre: #aeb6c4;
  --ambient: 0.85;

  --hover: #e6e9ef;
  --hover-line: #b4bcc9;
  --on-accent: #ffffff;
  --selected: #dde9fa;
}

* {
  box-sizing: border-box;
}

/* A class that sets `display` beats the browser's own `[hidden]` rule, so an
   element toggled with the hidden attribute stays on screen. Make hidden win. */
[hidden] {
  display: none !important;
}

html,
body {
  margin: 0;
  height: 100%;
  background: var(--bg);
  color: var(--text);
  font: 13px/1.45 ui-sans-serif, system-ui, -apple-system, "Segoe UI", sans-serif;
  overflow: hidden;
}

button {
  font: inherit;
  color: var(--text);
  background: var(--panel-2);
  border: 1px solid var(--line);
  border-radius: 6px;
  padding: 5px 10px;
  cursor: pointer;
}
button:hover {
  border-color: var(--hover-line);
  background: var(--hover);
}
button.active {
  background: var(--accent);
  border-color: var(--accent);
  color: var(--on-accent);
  font-weight: 600;
}
button:disabled {
  opacity: 0.45;
  cursor: not-allowed;
}

.topbar {
  display: flex;
  align-items: center;
  gap: 16px;
  height: 48px;
  padding: 0 14px;
  background: var(--panel);
  border-bottom: 1px solid var(--line);
}
.brand {
  display: flex;
  align-items: baseline;
  gap: 8px;
}
.brand strong {
  letter-spacing: 0.2px;
}
.muted {
  color: var(--muted);
}
.spacer {
  flex: 1;
}
.toolgroup {
  display: flex;
  align-items: center;
  gap: 6px;
}
.toggle {
  display: flex;
  align-items: center;
  gap: 5px;
  color: var(--muted);
  cursor: pointer;
  user-select: none;
}

main {
  display: grid;
  grid-template-columns: 240px 1fr 300px;
  height: calc(100% - 48px);
}

.panel {
  background: var(--panel);
  display: flex;
  flex-direction: column;
  /* The column scrolls as a whole. Scrolling each section separately meant
     that adding a section squeezed the ones below it to nothing: the chain
     order list became unreachable once Shape and Fetch were above it. */
  overflow-y: auto;
  overflow-x: hidden;
}
.panel.left {
  border-right: 1px solid var(--line);
}
.panel.right {
  border-left: 1px solid var(--line);
}
.panel section {
  padding: 12px;
  border-bottom: 1px solid var(--line);
  /* Sections size to their content; the panel around them does the scrolling. */
  flex: 0 0 auto;
}
.panel section.grow {
  flex: 0 0 auto;
}
h2 {
  margin: 0 0 6px;
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--muted);
  font-weight: 600;
}
.hint {
  margin: 0 0 8px;
  color: var(--muted);
  font-size: 12px;
}

.palette {
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.palette button {
  display: flex;
  align-items: center;
  gap: 9px;
  text-align: left;
  padding: 8px 10px;
}
.swatch {
  width: 12px;
  height: 12px;
  border-radius: 3px;
  flex: none;
}
.palette .sub {
  color: var(--muted);
  margin-left: auto;
  font-size: 11px;
}

.chain-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 4px;
}
.chain-list li {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 7px 9px;
  background: var(--panel-2);
  border: 1px solid var(--line);
  border-radius: 6px;
  cursor: grab;
}
.chain-list li.selected {
  border-color: var(--accent);
  background: var(--selected);
}
.chain-list li.drop-target {
  border-top: 2px solid var(--accent);
}
.chain-list .name {
  flex: 1;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.chain-list .len {
  color: var(--muted);
  font-variant-numeric: tabular-nums;
}
.linker-row {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 2px 9px 2px 29px;
  color: var(--muted);
  font-size: 11px;
}
.linker-row input {
  width: 52px;
}

.stage {
  position: relative;
  min-width: 0;
  /* Nothing in the viewport may paint over the panels beside it. */
  overflow: hidden;
}
#viewport {
  position: absolute;
  inset: 0;
}
#viewport canvas {
  display: block;
  /* Belt and braces against the renderer handing back an oversized canvas. */
  width: 100%;
  height: 100%;
}
.stage.sketching #viewport {
  cursor: crosshair;
}

.overlay-hint {
  position: absolute;
  top: 12px;
  left: 50%;
  transform: translateX(-50%);
  max-width: 440px;
  padding: 8px 12px;
  background: var(--panel);
  border: 1px solid var(--accent);
  border-radius: 7px;
  color: var(--text);
  font-size: 12px;
  pointer-events: none;
}

.readout {
  position: absolute;
  left: 12px;
  bottom: 12px;
  padding: 7px 11px;
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: 7px;
  color: var(--muted);
  font-variant-numeric: tabular-nums;
  pointer-events: none;
}
.readout strong {
  color: var(--text);
}

.inspector label {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  margin-bottom: 7px;
}
.inspector input[type="number"],
.inspector select {
  width: 92px;
  background: var(--panel-2);
  color: var(--text);
  border: 1px solid var(--line);
  border-radius: 5px;
  padding: 3px 6px;
  font: inherit;
}
.inspector input[type="range"] {
  width: 92px;
}
.inspector .row-actions {
  display: flex;
  gap: 6px;
  margin-top: 10px;
}

.validation .status {
  display: flex;
  align-items: center;
  gap: 7px;
  font-weight: 600;
  margin-bottom: 6px;
}
.dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  flex: none;
}
.dot.ok {
  background: var(--ok);
}
.dot.bad {
  background: var(--bad);
}
.validation ul {
  margin: 0;
  padding-left: 16px;
  color: var(--warn);
}
.validation li {
  margin-bottom: 4px;
}
.metrics {
  display: grid;
  grid-template-columns: 1fr auto;
  gap: 2px 10px;
  margin-top: 8px;
  color: var(--muted);
  font-variant-numeric: tabular-nums;
}
.metrics span:nth-child(even) {
  color: var(--text);
  text-align: right;
}

.ss-strip {
  display: block;
  margin-top: 8px;
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 10px;
  line-height: 1.3;
  word-break: break-all;
  color: var(--muted);
}
.ss-strip b {
  color: var(--helix);
}
.ss-strip i {
  color: var(--strand);
  font-style: normal;
}

.export-buttons {
  display: flex;
  gap: 6px;
  margin-bottom: 10px;
}
.commands {
  margin: 0;
  padding: 9px;
  background: var(--panel-2);
  border: 1px solid var(--line);
  border-radius: 6px;
  color: var(--muted);
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 10.5px;
  white-space: pre-wrap;
  word-break: break-all;
  user-select: all;
}

.busy {
  position: absolute;
  top: 12px;
  right: 12px;
  padding: 5px 10px;
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: 6px;
  color: var(--muted);
}

/* Export output, used where the page cannot start a download of its own —
   inside an embedded viewer, for instance. The text is shown for copying
   rather than offered as a file that would silently fail to save. */
.export-output {
  margin-top: 10px;
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.export-output-head {
  display: flex;
  align-items: center;
  gap: 6px;
}
.export-output-head .name {
  flex: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 11px;
  color: var(--text);
}
.export-output textarea {
  width: 100%;
  min-width: 0;
  height: 180px;
  resize: vertical;
  background: var(--panel-2);
  color: var(--muted);
  border: 1px solid var(--line);
  border-radius: 6px;
  padding: 8px;
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 10.5px;
  white-space: pre;
}

/* Clear a system bar at the side or bottom without breaking the app shell:
   the three-pane layout is full-bleed by design, so the insets go on the
   elements that actually hold content rather than on body. */
.topbar {
  padding-left: max(14px, env(safe-area-inset-left, 0px));
  padding-right: max(14px, env(safe-area-inset-right, 0px));
}
.panel.left {
  padding-left: env(safe-area-inset-left, 0px);
}
.panel.right {
  padding-right: env(safe-area-inset-right, 0px);
}
.panel section:last-child {
  padding-bottom: calc(12px + env(safe-area-inset-bottom, 0px));
}

/* Narrow screens: stack the panes and let the page scroll. A pointer-driven
   3D builder is not really a phone tool, but it should still be readable and
   never scroll sideways. */
@media (max-width: 900px) {
  html,
  body {
    overflow: auto;
  }
  .topbar {
    height: auto;
    flex-wrap: wrap;
    gap: 8px 12px;
    padding-block: 8px;
  }
  .spacer {
    display: none;
  }
  main {
    grid-template-columns: 1fr;
    grid-template-rows: auto minmax(340px, 55vh) auto;
    height: auto;
  }
  .panel {
    overflow: visible;
  }
  .panel.left {
    border-right: none;
    border-bottom: 1px solid var(--line);
  }
  .panel.right {
    border-left: none;
    border-top: 1px solid var(--line);
  }
  .panel section.grow {
    flex: none;
  }
  .stage {
    min-height: 340px;
  }
}

/* Shown only when the app fails to boot — a blocked CDN or a module error
   would otherwise leave an unexplained empty viewport. */
.boot-error {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  width: min(420px, calc(100% - 32px));
  padding: 16px 18px;
  background: var(--panel);
  border: 1px solid var(--bad);
  border-radius: 9px;
  color: var(--text);
}
.boot-error p {
  margin: 8px 0 0;
  color: var(--muted);
  font-size: 12px;
}
.boot-error #boot-error-detail {
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 11px;
  color: var(--warn);
  word-break: break-word;
}

/* Residue-count control: slider for exploring, number box for an exact value. */
.slider-field {
  display: grid;
  grid-template-columns: 1fr;
  gap: 5px;
  margin-bottom: 10px;
}
.slider-field .slider-label {
  color: var(--muted);
}
.slider-field input[type='range'] {
  grid-column: 1;
  width: 100%;
  min-width: 0;
  margin: 0;
  accent-color: var(--accent);
}
.slider-field input[type='number'] {
  grid-column: 1;
  width: 72px;
  justify-self: end;
}
.inspector .slider-field {
  grid-template-columns: 1fr auto;
  align-items: center;
}
.inspector .slider-field .slider-label {
  grid-column: 1;
  grid-row: 1;
}
.inspector .slider-field input[type='number'] {
  grid-column: 2;
  grid-row: 1;
}
.inspector .slider-field input[type='range'] {
  grid-column: 1 / -1;
  grid-row: 2;
}

/* Delete control on each chain row. Dim until the row is hovered or focused so
   a column of crosses does not compete with the chain itself. */
.row-delete {
  flex: none;
  width: 20px;
  height: 20px;
  padding: 0;
  line-height: 1;
  font-size: 15px;
  color: var(--muted);
  background: transparent;
  border: 1px solid transparent;
  border-radius: 4px;
  opacity: 0.45;
  transition: opacity 120ms ease, color 120ms ease;
}
.chain-list li:hover .row-delete,
.chain-list li.selected .row-delete,
.row-delete:focus-visible {
  opacity: 1;
}
.row-delete:hover {
  color: var(--bad);
  border-color: var(--bad);
  background: color-mix(in srgb, var(--bad) 12%, transparent);
}

/* Shape mode controls. */
.shape-form {
  display: grid;
  grid-template-columns: 1fr auto;
  gap: 6px;
}
.shape-form input,
.shape-form select {
  min-width: 0;
  background: var(--panel-2);
  color: var(--text);
  border: 1px solid var(--line);
  border-radius: 5px;
  padding: 5px 7px;
  font: inherit;
}
.shape-form button {
  grid-column: 1 / -1;
}

.shape-size {
  grid-column: 1 / -1;
  display: flex;
  align-items: center;
  gap: 6px;
  color: var(--muted);
}
.shape-size input {
  width: 68px;
}
.shape-size .unit {
  font-size: 11px;
}

/* Clash list: the worst overlaps, matching the red markers in the viewport. */
.clash-caption {
  margin: 10px 0 4px;
}
.clash-list {
  margin: 0;
  padding-left: 16px;
  color: var(--bad);
  font-variant-numeric: tabular-nums;
}
.clash-list li {
  margin-bottom: 2px;
}
.clash-list span {
  color: var(--muted);
}
.clash-list .more {
  color: var(--muted);
  list-style: none;
  margin-left: -16px;
}

.link-button {
  background: none;
  border: none;
  padding: 0;
  margin-left: auto;
  color: var(--accent);
  text-decoration: underline;
  cursor: pointer;
  font-size: 11px;
}
.link-button:hover {
  background: none;
  border-color: transparent;
}
.shape-form select {
  min-width: 0;
}

.build {
  color: var(--muted);
  opacity: 0.55;
  font-size: 10.5px;
  font-variant-numeric: tabular-nums;
  letter-spacing: 0.02em;
}
