/* The pskill viewer. One color per meaning: done, now, waiting for you, a problem, not visited, referenced.
   Blue also marks what you can act on: links, the main buttons, the switch, and the focus ring.
   Text colors reach 4.5:1 on their backgrounds, in both themes (a test checks it). */

:root {
  --ground: #f4f5f7;
  --dot: #d9dde3;
  --surface: #ffffff;
  --ink: #1c2127;
  --muted: #636d7c;
  --line: #e1e5eb;
  --done: #2d6ad4;
  --on-done: #ffffff; /* text on a blue button */
  --done-bg: #eef4ff;
  --now: #e8890c;
  --now-bg: #fff6e8;
  --now-ring: #fce7c5;
  --now-ink: #8c5406;
  --human: #7b4fd6;
  --human-bg: #f4eefe;
  --ref: #0a7d6d;
  --ref-bg: #e2f5f2;
  --bad: #b42318;
  --bad-bg: #fde7e4;
  --ghost: #b8c0cc;
  --ghost-ink: #6a717c;
  --cluster: #fafbfe;
  --cluster-line: #9db5e6;
  --code-bg: #f6f7f9;
  --font: "Manrope", system-ui, -apple-system, "Segoe UI", sans-serif;
  --mono: "IBM Plex Mono", ui-monospace, Consolas, "Liberation Mono", monospace;
  color-scheme: light dark;
}

@media (prefers-color-scheme: dark) {
  :root {
    --ground: #0f1216;
    --dot: #232932;
    --surface: #171b21;
    --ink: #e6e9ee;
    --muted: #98a2b3;
    --line: #2a313b;
    --done: #6c9ef8;
    --on-done: #0f1216;
    --done-bg: #16233d;
    --now: #f5a524;
    --now-bg: #2b2112;
    --now-ring: #4a3510;
    --now-ink: #f5c26b;
    --human: #a98bf0;
    --human-bg: #231b38;
    --ref: #3ccdb5;
    --ref-bg: #10302b;
    --bad: #ff7a6b;
    --bad-bg: #3a1714;
    --ghost: #4a5361;
    --ghost-ink: #7d8796;
    --cluster: #12161b;
    --cluster-line: #34507e;
    --code-bg: #10141a;
  }
}

* {
  box-sizing: border-box;
}

html,
body {
  height: 100%;
}

body {
  margin: 0;
  background: var(--ground);
  color: var(--ink);
  font: 14px/1.5 var(--font);
}

a {
  color: var(--done);
}

button {
  font: inherit;
  color: inherit;
}

/* One focus ring for the keyboard, on every control and link. */
:focus-visible {
  outline: 2px solid var(--done);
  outline-offset: 2px;
}

pre,
code,
.mono {
  font-family: var(--mono);
}

pre {
  margin: 0;
  padding: 10px 12px;
  background: var(--code-bg);
  border-radius: 8px;
  font-size: 12px;
  line-height: 1.55;
  white-space: pre-wrap;
  word-break: break-word;
}

.loading {
  padding: 32px;
  color: var(--muted);
}

/* --- shared pieces --------------------------------------------------------------------------- */

.topbar {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px 16px;
  background: var(--surface);
  border-bottom: 1px solid var(--line);
}

.brand {
  font-size: 18px;
  font-weight: 700;
  color: var(--ink);
  text-decoration: none;
  margin-right: 6px;
}

.spacer {
  flex-grow: 1;
}

.run-status {
  display: flex;
  align-items: center;
  gap: 10px;
}

.tool {
  border: 1px solid var(--line);
  background: var(--surface);
  border-radius: 8px;
  padding: 6px 12px;
  cursor: pointer;
  min-height: 34px;
}

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

.tool[aria-pressed="true"] {
  background: var(--ink);
  border-color: var(--ink);
  color: var(--surface);
}

/* An on and off switch in the top bar: when it is on, the track turns blue and the knob moves right. */
.switch {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  min-height: 34px;
  padding: 6px 4px;
  border: none;
  border-radius: 8px;
  background: none;
  color: var(--muted);
  font: inherit;
  cursor: pointer;
}

.switch[hidden] {
  display: none;
}

.switch:hover,
.switch[aria-checked="true"] {
  color: var(--ink);
}

.switch-track {
  position: relative;
  flex: 0 0 auto;
  width: 32px;
  height: 18px;
  border-radius: 999px;
  background: var(--ghost);
  transition: background 0.15s;
}

.switch-track::after {
  content: "";
  position: absolute;
  top: 2px;
  left: 2px;
  width: 14px;
  height: 14px;
  border-radius: 50%;
  background: var(--surface);
  box-shadow: 0 1px 2px rgb(0 0 0 / 25%);
  transition: transform 0.15s;
}

.switch[aria-checked="true"] .switch-track {
  background: var(--done);
}

.switch[aria-checked="true"] .switch-track::after {
  transform: translateX(14px);
}

.run-picker {
  font: inherit;
  font-weight: 600;
  max-width: 420px;
  padding: 6px 10px;
  border: 1px solid var(--line);
  border-radius: 8px;
  background: var(--surface);
  color: var(--ink);
  min-height: 34px;
}

.pill {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 3px 10px;
  border-radius: 999px;
  font-size: 12px;
  font-weight: 700;
  background: var(--code-bg);
  color: var(--muted);
}

.dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: currentColor;
  flex-shrink: 0;
}

.state-done { color: var(--done); background: var(--done-bg); }
.state-now { color: var(--now-ink); background: var(--now-bg); }
.state-waiting { color: var(--human); background: var(--human-bg); }
.state-failed { color: var(--bad); background: var(--bad-bg); }
.state-idle { color: var(--muted); background: var(--code-bg); }

.note {
  color: var(--muted);
}

.errors {
  color: var(--bad);
}

/* --- the runs page ---------------------------------------------------------------------------- */

.runs-page {
  max-width: 1100px;
  margin: 0 auto;
  padding: 24px 20px 48px;
  display: flex;
  flex-direction: column;
  gap: 18px;
}

.filters {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}

/* The numbers of each skill, under the run cards: a heading with its note, then a table on a card like the
   run cards. The numbers align right, with digits of one width, so they line up. */
.totals-section {
  display: flex;
  flex-direction: column;
  gap: 10px;
  margin-top: 8px;
}

.totals-head {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 4px 12px;
}

.totals-head h2 {
  margin: 0;
}

.totals-head .note {
  font-size: 13px;
}

.totals-card {
  max-width: 640px;
  overflow-x: auto;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: 12px;
}

.skill-totals {
  width: 100%;
  border-collapse: collapse;
  font-size: 14px;
}

.skill-totals th,
.skill-totals td {
  padding: 10px 16px;
  text-align: left;
  white-space: nowrap;
}

.skill-totals th {
  font-size: 12px;
  font-weight: 600;
  color: var(--muted);
  border-bottom: 1px solid var(--line);
}

.skill-totals tbody tr + tr td {
  border-top: 1px solid var(--line);
}

.skill-totals .totals-skill {
  width: 100%;
  font-weight: 600;
}

.skill-totals .number {
  text-align: right;
  font-variant-numeric: tabular-nums;
}

/* On a phone, every column fits: less padding, a skill name that wraps, and no "x of y" after the rate. */
@media (max-width: 640px) {
  .skill-totals th,
  .skill-totals td {
    padding: 8px 10px;
  }

  .skill-totals .totals-skill {
    white-space: normal;
    overflow-wrap: anywhere;
  }

  .skill-totals .number .note {
    display: none;
  }
}

.run-cards {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
  gap: 10px;
}

.run-card {
  display: flex;
  flex-direction: column;
  gap: 6px;
  padding: 14px 16px;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: 12px;
  color: var(--ink);
  text-decoration: none;
}

.run-card:hover {
  border-color: var(--done);
}

.run-card-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  font-weight: 700;
}

.run-card-meta {
  font-size: 12px;
  color: var(--muted);
}

/* --- the run screen ---------------------------------------------------------------------------- */

.run-screen {
  display: grid;
  grid-template-columns: minmax(0, 1fr); /* no row can make the screen wider than the window */
  grid-template-rows: auto minmax(0, 1fr) auto;
  height: 100vh;
}

.workspace {
  display: grid;
  grid-template-columns: minmax(0, 1fr) var(--panel-width, 420px);
  grid-template-rows: minmax(0, 1fr);
  min-height: 0;
  position: relative;
}

.panel-handle {
  position: absolute;
  top: 0;
  bottom: 0;
  right: var(--panel-width, 420px);
  z-index: 2;
  width: 8px;
  margin-right: -4px;
  cursor: col-resize;
  touch-action: none;
}

.panel-handle:hover,
.panel-handle.dragging {
  background: var(--done);
  opacity: 0.35;
}

.canvas {
  position: relative;
  overflow: hidden;
  background-color: var(--ground);
  background-image: radial-gradient(var(--dot) 1px, transparent 1px);
  background-size: 20px 20px;
  cursor: grab;
  touch-action: none;
}

.canvas.dragging {
  cursor: grabbing;
}

.layer {
  position: absolute;
  left: 0;
  top: 0;
  transform-origin: 0 0;
}

.canvas-note {
  position: absolute;
  left: 16px;
  bottom: 12px;
  margin: 0;
  font-size: 12px;
  color: var(--muted);
}

/* The Mermaid SVG. Mermaid scopes its own styles by id, so these rules need !important. */

.layer svg {
  display: block;
}

.layer g.node {
  cursor: pointer;
}

.layer g.node rect,
.layer g.node polygon,
.layer g.node circle {
  fill: var(--surface) !important;
  stroke: var(--ghost) !important;
  stroke-width: 1.5px !important;
  rx: 10px;
  ry: 10px;
}

.layer g.node .nodeLabel,
.layer g.node .nodeLabel p {
  color: var(--muted) !important;
  font-family: var(--font) !important;
  font-size: 12px;
  line-height: 1.35;
}

.layer g.node .nodeLabel b {
  color: var(--ink);
  font-size: 13px;
}

.layer g.node.is-unvisited rect,
.layer g.node.is-unvisited polygon {
  fill: transparent !important;
  stroke-dasharray: 5 4;
}

.layer g.node.is-unvisited .nodeLabel,
.layer g.node.is-unvisited .nodeLabel b {
  color: var(--ghost-ink) !important;
}

.layer g.node.is-done rect,
.layer g.node.is-done polygon,
.layer g.node.is-done circle {
  fill: var(--done-bg) !important;
  stroke: var(--done) !important;
}

.layer g.node.is-now rect,
.layer g.node.is-now polygon {
  fill: var(--now-bg) !important;
  stroke: var(--now) !important;
  stroke-width: 3px !important;
}

.layer g.node.is-waiting rect,
.layer g.node.is-waiting polygon {
  fill: var(--human-bg) !important;
  stroke: var(--human) !important;
  stroke-width: 3px !important;
}

.layer g.node.is-failed rect,
.layer g.node.is-failed polygon {
  fill: var(--bad-bg) !important;
  stroke: var(--bad) !important;
  stroke-width: 3px !important;
}

/* The node that the side panel shows: a ring in the ink color, outside the state frame, with a small gap.
   app.js draws the ring as one rounded rectangle around each node's box, so it has the same width on every
   side and around the corners. Mermaid scopes its own node styles by id, so the ring needs !important. */
.layer .selection-ring {
  display: none;
  fill: none !important;
  stroke: var(--ink) !important;
  stroke-width: 2.5px !important;
}

.layer g.node.is-selected .selection-ring {
  display: inline;
}

/* Mermaid's soft shadow under the box would show in the ring's gap as a thicker bottom and right edge. */
.layer g.node.is-selected > rect {
  filter: none !important;
}

.layer path.flowchart-link {
  stroke: var(--ghost) !important;
  stroke-width: 1.5px !important;
  stroke-dasharray: 5 4 !important;
}

/* The arrow tips: Mermaid paints them its own dark default, which the dark theme cannot show. All edges
   share one marker, so it takes the muted color; context-stroke then gives each tip its line's color. */
.layer .arrowMarkerPath {
  fill: var(--muted) !important;
  stroke: var(--muted) !important;
  fill: context-stroke !important;
  stroke: context-stroke !important;
}

.layer path.flowchart-link.is-taken {
  stroke: var(--done) !important;
  stroke-width: 2.2px !important;
  stroke-dasharray: none !important;
}

.layer .edgeLabel,
.layer .edgeLabel p,
.layer .edgeLabel span {
  background: var(--ground) !important;
  color: var(--muted) !important;
}

.layer .cluster rect {
  fill: var(--cluster) !important;
  stroke: var(--cluster-line) !important;
  rx: 14px;
  ry: 14px;
}

/* A child skill's frame is dashed; a parallel block's task frame stays solid. */
.layer .cluster:not([id$="_TASKS"]) rect {
  stroke-dasharray: 7 5;
}

/* A call block drawn as its child's frame: the whole frame selects it, and its title sits at the top left. */
.layer g.cluster.is-call-frame {
  cursor: pointer;
}

.layer g.cluster.is-call-frame.is-selected > rect,
.layer g.cluster.is-call-frame.is-exit-target > rect {
  stroke: var(--ink) !important;
  stroke-width: 2.5px !important;
}

.layer g.cluster.is-call-frame > .cluster-label div,
.layer g.cluster.is-call-frame > .cluster-label span,
.layer g.cluster.is-call-frame > .cluster-label p {
  text-align: left !important;
  font-weight: 400 !important;
  color: var(--muted) !important;
}

.layer g.cluster.is-call-frame > .cluster-label b {
  font-weight: 700;
  font-size: 14px;
  color: var(--ink);
}

.layer .cluster-label,
.layer .cluster-label span,
.layer .cluster-label p {
  color: var(--ink) !important;
  font-family: var(--font) !important;
  font-weight: 700;
  font-size: 12px;
}

/* The offline step list. */

.step-list {
  position: absolute;
  inset: 0;
  overflow: auto;
  padding: 20px;
  display: flex;
  flex-direction: column;
  gap: 8px;
  cursor: default;
}

.step-card {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  width: 320px;
  padding: 10px 14px;
  border: 1.5px solid var(--done);
  border-radius: 8px;
  background: var(--done-bg);
  text-align: left;
  cursor: pointer;
}

.step-card.is-now { border: 3px solid var(--now); background: var(--now-bg); }
.step-card.is-waiting { border: 3px solid var(--human); background: var(--human-bg); }
.step-card.is-failed { border: 3px solid var(--bad); background: var(--bad-bg); }
.step-card.is-selected { outline: 2.5px solid var(--ink); outline-offset: 2px; }

.step-card small,
.step-card .block-type {
  color: var(--muted);
  font-size: 12px;
}

/* --- the side panel ---------------------------------------------------------------------------- */

.panel {
  min-height: 0;
  display: flex;
  flex-direction: column;
  gap: 16px;
  padding: 20px 22px;
  background: var(--surface);
  border-left: 1px solid var(--line);
  overflow-y: auto;
}

.panel-head {
  display: flex;
  flex-direction: column;
  gap: 6px;
}

.panel-title {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
}

.panel-title h2 {
  margin: 0;
  font-size: 20px;
}

.panel-hint {
  margin: 0;
  white-space: pre-line;
}

/* The type line of the panel head wraps as plain text: the icon and the "?" stay next to the words. */
.panel-head > .with-help,
.panel-head > .block-type {
  display: block;
  color: var(--muted);
}

.panel-head > .with-help > .block-type {
  display: inline;
}

.panel-head .block-type > .block-icon-svg {
  margin-right: 6px;
  vertical-align: -3px;
}

.panel-head > .with-help > .help-button {
  margin-left: 6px;
  vertical-align: 1px;
}

/* The block's own description: the ink color, so it stands apart from the muted type meaning above it. */
.panel-description {
  margin: 0;
  color: var(--ink);
  font-size: 15px;
  white-space: pre-line;
}

.panel section {
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.panel h3 {
  margin: 0;
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--muted);
}

.facts {
  display: grid;
  grid-template-columns: 110px minmax(0, 1fr);
  gap: 6px 12px;
  margin: 0;
  font-size: 13px;
}

.facts dt {
  color: var(--muted);
}

.facts dd {
  margin: 0;
  word-break: break-word;
}

.visits {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
}

.answer {
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding: 10px 12px;
  border: 1px solid var(--line);
  border-radius: 8px;
}

.answer.rejected {
  border-color: var(--bad);
  background: var(--bad-bg);
}

.answer-head {
  display: flex;
  align-items: center;
  gap: 8px;
  font-weight: 700;
  font-size: 13px;
}

.answer.rejected .answer-head {
  color: var(--bad);
}

details summary {
  cursor: pointer;
  color: var(--done);
  font-size: 13px;
}

details[open] summary {
  margin-bottom: 8px;
}

/* --- the replay bar ---------------------------------------------------------------------------- */

.replay {
  display: flex;
  align-items: center;
  gap: 16px;
  padding: 12px 20px;
  background: var(--surface);
  border-top: 1px solid var(--line);
}

.play {
  width: 44px;
  height: 44px;
  border-radius: 50%;
  border: 1px solid var(--line);
  background: var(--surface);
  cursor: pointer;
  flex-shrink: 0;
}

.replay-body {
  flex-grow: 1;
  display: flex;
  flex-direction: column;
  gap: 4px;
  min-width: 0;
}

.replay-track {
  position: relative;
  height: 28px;
}

.replay-track input[type="range"] {
  position: absolute;
  inset: 0;
  width: 100%;
  margin: 0;
  opacity: 0;
  cursor: pointer;
}

.replay-line {
  position: absolute;
  left: 0;
  right: 0;
  top: 13px;
  height: 3px;
  border-radius: 999px;
  background: var(--line);
}

.replay-progress {
  position: absolute;
  left: 0;
  top: 13px;
  height: 3px;
  border-radius: 999px;
  background: var(--done);
}

.mark {
  position: absolute;
  top: 8px;
  width: 12px;
  height: 12px;
  margin-left: -6px;
  border-radius: 50%;
  background: var(--done);
  pointer-events: none;
}

.mark.future {
  background: var(--ghost);
}

.mark.human {
  border-radius: 4px;
  background: var(--human);
}

.mark.rejected {
  background: var(--surface);
  border: 3px solid var(--bad);
}

.mark.at {
  top: 5px;
  width: 18px;
  height: 18px;
  margin-left: -9px;
  background: var(--now);
  border: none;
  box-shadow: 0 0 0 5px var(--now-ring);
}

.replay-labels {
  display: flex;
  justify-content: space-between;
  gap: 12px;
  font-size: 12px;
  color: var(--muted);
}

/* Block icons: on the canvas above each block name, and next to the type in the panel. */

.block-icon-svg {
  width: 15px;
  height: 15px;
  flex: none;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.6;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.layer .block-icon .block-icon-svg {
  display: inline-block; /* the canvas SVG rule makes every svg a block */
  width: 16px;
  height: 16px;
  vertical-align: -3px;
  stroke: var(--ghost-ink);
}

/* Mermaid styles every path in a node (fill and stroke); the icon's paths keep the icon's own stroke. */
.layer .block-icon-svg path {
  fill: none !important;
  stroke: inherit !important;
  stroke-width: 1.6px !important;
}

.layer g.node.is-done .block-icon-svg {
  stroke: var(--done);
}

.layer g.node.is-now .block-icon-svg {
  stroke: var(--now);
}

.layer g.node.is-waiting .block-icon-svg {
  stroke: var(--human);
}

.layer g.node.is-failed .block-icon-svg {
  stroke: var(--bad);
}

.block-type {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  color: var(--muted);
}

/* A selected chip in the panel: the blue of the viewer, not a block of black. */
.visits .tool[aria-pressed="true"] {
  background: var(--done-bg);
  border-color: var(--done);
  box-shadow: inset 0 0 0 1px var(--done);
  color: var(--done);
  font-weight: 700;
}

.visits .task-chip.is-rejected[aria-pressed="true"] {
  background: var(--bad-bg);
  border-color: var(--bad);
  box-shadow: inset 0 0 0 1px var(--bad);
  color: var(--bad);
}

/* The side panel: folded blocks, JSON trees, Markdown, and the tasks of a parallel block. */

.fold-body {
  max-height: calc(var(--fold-lines) * 1.55em + 20px);
  overflow: hidden;
}

.fold:not(.is-open):not(.fits) .fold-body {
  mask-image: linear-gradient(to bottom, black 55%, transparent);
}

.fold.is-open .fold-body {
  max-height: none;
}

.fold.fits .fold-toggle {
  display: none;
}

.fold.fits .fold-body {
  max-height: none;
}

.fold-toggle {
  padding: 4px 0 0;
  border: none;
  background: none;
  color: var(--done);
  font: inherit;
  font-size: 12px;
  cursor: pointer;
}

.panel h4 {
  margin: 4px 0 0;
  font-size: 12px;
  font-weight: 700;
  color: var(--muted);
}

.json {
  font-family: var(--mono);
  font-size: 12px;
  line-height: 1.55;
}

.json-root {
  padding: 8px 12px;
  background: var(--code-bg);
  border-radius: 8px;
}

.json summary.json-summary {
  color: var(--muted);
  font-size: 12px;
}

.json-children {
  margin-left: 4px;
  padding-left: 12px;
  border-left: 1px solid var(--line);
}

.json-row {
  display: flex;
  align-items: baseline;
  gap: 6px;
}

.json-row > .json {
  flex: 1;
  min-width: 0;
}

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

.json-string {
  white-space: pre-wrap;
  word-break: break-word;
}

.json-literal {
  color: var(--done);
}

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

.markdown {
  padding: 10px 12px;
  background: var(--code-bg);
  border-radius: 8px;
  font-size: 13px;
  line-height: 1.55;
  word-break: break-word;
}

.markdown > :first-child {
  margin-top: 0;
}

.markdown p {
  margin: 0 0 8px;
  white-space: pre-line;
}

.markdown h4,
.markdown h5,
.markdown h6 {
  margin: 12px 0 4px;
  color: var(--ink);
  font-weight: 700;
}

.markdown h4 {
  font-size: 14px;
}

.markdown h5 {
  font-size: 13px;
}

.markdown h6 {
  font-size: 12px;
}

.markdown ul,
.markdown ol {
  margin: 0 0 8px;
  padding-left: 20px;
}

.markdown code {
  padding: 0 4px;
  background: var(--surface);
  border-radius: 4px;
  font-size: 12px;
}

.markdown pre {
  margin: 0 0 8px;
  background: var(--surface);
}

.task-chip.is-done {
  border-color: var(--done);
  color: var(--done);
}

.task-chip.is-rejected {
  border-color: var(--bad);
  background: var(--bad-bg);
  color: var(--bad);
}

.task-chip.is-open {
  border-style: dashed;
  color: var(--ghost-ink);
}

.task-detail {
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding: 10px 12px;
  border: 1px solid var(--line);
  border-radius: 8px;
}

.layer g.node.is-task .nodeLabel {
  font-size: 12px;
}

@media (max-width: 900px) {
  .workspace {
    grid-template-columns: minmax(0, 1fr);
    grid-template-rows: minmax(0, 1fr) minmax(0, 45vh);
  }

  .panel {
    border-left: none;
    border-top: 1px solid var(--line);
  }

  .panel-handle {
    display: none;
  }
}

/* --- the skills page and the skill screen -------------------------------------------------------- */

.nav {
  display: flex;
  gap: 4px;
  margin-right: 8px;
}

.nav-link {
  padding: 6px 10px;
  border-radius: 8px;
  color: var(--muted);
  font-weight: 600;
  text-decoration: none;
}

.nav-link:hover {
  color: var(--ink);
}

.nav-link[aria-current="page"] {
  color: var(--ink);
  background: var(--code-bg);
}

a.tool {
  display: inline-flex;
  align-items: center;
  width: fit-content;
  color: var(--ink);
  text-decoration: none;
}

.skill-card-description {
  font-size: 13px;
  color: var(--ink);
}

.skill-card.has-error {
  border-color: var(--bad);
}

.errors-text {
  color: var(--bad);
  word-break: break-word;
}

/* The skill screen has no run: every block has the same solid frame, and every edge is a plain line. */
.layer.is-skill g.node.is-plain rect,
.layer.is-skill g.node.is-plain polygon,
.layer.is-skill g.node circle {
  stroke: var(--muted) !important;
}

.layer.is-skill g.node.is-plain .nodeLabel b {
  color: var(--ink) !important;
}

.layer.is-skill g.node.is-plain .block-icon-svg {
  stroke: var(--ink);
}

.layer.is-skill path.flowchart-link {
  stroke: var(--muted) !important;
  stroke-dasharray: none !important;
}

.layer.is-skill path.flowchart-link.edge-pattern-dotted {
  stroke-dasharray: 3 3 !important;
}

/* The main line: the usual way to a succeeded end (main_line in viewer_data.py). Its edges are thicker,
   and on the skill screen the side branches step back. */
.layer path.flowchart-link.is-main {
  stroke-width: 3px !important;
}

.layer.is-skill path.flowchart-link:not(.is-main):not(.is-hovered) {
  opacity: 0.5;
}

.layer.is-skill g.label.is-side:not(.is-hovered) {
  opacity: 0.75;
}

.problems,
/* Fields and exits: one card per item, so that the name, the chips, and the text read apart. */
.fields,
.exits {
  margin: 0;
  padding: 0;
  list-style: none;
  display: flex;
  flex-direction: column;
  gap: 8px;
  font-size: 13px;
}

.field,
.exit {
  padding: 8px 10px;
  border: 1px solid var(--line);
  border-radius: 8px;
  background: var(--surface);
}

/* Nested fields: a line on the left instead of a card in a card. */
.field .fields {
  margin-top: 8px;
  padding-left: 12px;
  border-left: 2px solid var(--line);
  gap: 8px;
}

.field .field {
  padding: 0;
  border: none;
  background: transparent;
}

.field-head,
.exit-head {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 6px;
}

.field-name {
  color: var(--ink);
  font-size: 13px;
  font-weight: 700;
}

/* The pskill version, at the bottom left of the list screens. */
.version-note {
  position: fixed;
  left: 16px;
  bottom: 12px;
  margin: 0;
  font-size: 12px;
  color: var(--muted);
}

.version-note a {
  color: inherit;
  text-decoration: none;
}

.version-note a:hover,
.brand:hover {
  text-decoration: underline;
}

.field .facts {
  margin-top: 6px;
}

.item-when {
  margin-top: 6px;
}

.item-when code {
  display: block;
  margin-top: 2px;
  white-space: pre-wrap;
  word-break: break-word;
}

.field-description {
  margin: 4px 0 0;
  color: var(--ink);
}

.field-values {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 4px;
  margin-top: 6px;
}

.chip {
  padding: 1px 8px;
  border: 1px solid var(--line);
  border-radius: 999px;
  background: var(--code-bg);
  color: var(--muted);
  font-family: var(--font);
  font-size: 12px;
  line-height: 18px;
  white-space: nowrap;
}

.chip.is-value {
  color: var(--ink);
  font-family: var(--mono);
}

.chip.is-if { border-color: transparent; background: var(--done-bg); color: var(--done); }
.chip.is-choice { border-color: transparent; background: var(--human-bg); color: var(--human); }
.chip.is-visit-cap { border-color: transparent; background: var(--bad-bg); color: var(--bad); }

.exit {
  display: flex;
  flex-direction: column;
  align-items: stretch;
  gap: 6px;
  width: 100%;
  color: var(--ink);
  font: inherit;
  text-align: left;
  cursor: pointer;
}

.exit:hover,
.exit:focus-visible {
  border-color: var(--ink);
}

.exit-arrow {
  color: var(--muted);
}

.exit-condition {
  display: block;
  padding: 6px 8px;
  border-radius: 8px;
  background: var(--code-bg);
  font-size: 12px;
  word-break: break-word;
}

.exit-text {
  color: var(--muted);
}

/* The edge and the target of the exit card under the pointer. */
.layer path.flowchart-link.is-hovered {
  stroke: var(--ink) !important;
  stroke-width: 3px !important;
  stroke-dasharray: none !important;
}

.layer g.label.is-hovered .edgeLabel,
.layer g.label.is-hovered .edgeLabel p,
.layer g.label.is-hovered .edgeLabel span {
  color: var(--ink) !important;
  font-weight: 700;
}

.layer g.node.is-exit-target rect,
.layer g.node.is-exit-target polygon,
.layer g.node.is-exit-target circle,
.layer.is-skill g.node.is-exit-target rect,
.layer.is-skill g.node.is-exit-target polygon,
.layer.is-skill g.node.is-exit-target circle {
  stroke: var(--ink) !important;
  stroke-width: 3px !important;
  stroke-dasharray: none !important;
}

/* A block that the text under the pointer names: a steps or history value, an edge condition, or a problem. */
.layer g.node.is-referenced rect,
.layer g.node.is-referenced polygon,
.layer g.node.is-referenced circle,
.layer.is-skill g.node.is-referenced rect,
.layer.is-skill g.node.is-referenced polygon,
.layer.is-skill g.node.is-referenced circle,
.layer g.cluster.is-referenced > rect {
  stroke: var(--ref) !important;
  stroke-width: 3px !important;
  stroke-dasharray: none !important;
}

.layer g.node.is-referenced,
.layer g.cluster.is-referenced > rect {
  filter: drop-shadow(0 0 6px var(--ref));
}

.step-card.is-referenced {
  outline: 2.5px solid var(--ref);
  outline-offset: 2px;
}

.block-ref {
  color: var(--ref);
  text-decoration: underline dotted;
  text-underline-offset: 3px;
  border-radius: 4px;
  cursor: pointer;
}

.block-ref:hover {
  background: var(--ref-bg);
}

/* The close button of the panel: it takes no room, and it stays at the top right while the panel scrolls. */
.panel-close {
  position: sticky;
  top: 8px;
  z-index: 2;
  flex: 0 0 auto;
  align-self: flex-end;
  width: 30px;
  height: 30px;
  margin: -8px -10px -38px 0;
  padding: 0;
  border: 1px solid var(--line);
  border-radius: 50%;
  background: var(--surface);
  color: var(--muted);
  font: 400 20px/1 var(--font);
  cursor: pointer;
}

.panel-close:hover,
.panel-close:focus-visible {
  border-color: var(--ink);
  color: var(--ink);
}

/* The title next to the close button keeps clear of it. */
.panel-close + .panel-head,
.panel-close + .panel-title,
.panel-close + .note,
.panel-close + .edit-form > .panel-head {
  padding-right: 34px;
}

.problem.is-error strong {
  color: var(--bad);
}

.problem.is-warning strong {
  color: var(--now-ink);
}

/* The start dot. */
.layer g.node[data-node="start"] circle {
  fill: var(--muted) !important;
  stroke: var(--muted) !important;
}

.layer g.node.is-done[data-node="start"] circle {
  fill: var(--done) !important;
  stroke: var(--done) !important;
}

/* --- the skill editor ------------------------------------------------------------------------------ */

.add-bar {
  display: flex;
  align-items: center;
  gap: 6px;
}

.add-bar[hidden] {
  display: none;
}

.edit-form {
  display: flex;
  flex-direction: column;
  gap: 14px;
}

.edit-fields {
  display: flex;
  flex-direction: column;
  gap: 12px;
}

.edit-row {
  display: flex;
  flex-direction: column;
  gap: 4px;
  font-size: 13px;
}

.edit-label {
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--muted);
}

.edit-input,
.edit-text {
  font: inherit;
  font-size: 13px;
  padding: 6px 8px;
  border: 1px solid var(--line);
  border-radius: 8px;
  background: var(--surface);
  color: var(--ink);
  min-width: 0;
}

.edit-input.narrow {
  flex: 0 0 110px;
}

.edit-text {
  resize: vertical;
  line-height: 1.45;
}

.edit-text.mono,
.edit-input.mono {
  font-family: var(--mono);
  font-size: 12px;
}

.edit-list {
  display: flex;
  flex-direction: column;
  gap: 6px;
}

.edit-list-row {
  display: flex;
  align-items: center;
  gap: 6px;
}

.edit-list-row .edit-input {
  flex: 1 1 auto;
}

.edit-choice-next {
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.edit-choice {
  display: flex;
  flex-direction: column;
  gap: 4px;
  padding-left: 8px;
  border-left: 2px solid var(--line);
}

.edit-actions {
  display: flex;
  align-items: center;
  gap: 8px;
}

.tool.small {
  min-height: 28px;
  padding: 3px 9px;
  width: fit-content;
}

.tool.primary {
  background: var(--done);
  border-color: var(--done);
  color: var(--on-done);
}

.tool.danger {
  color: var(--bad);
}

.edit-row > .edit-input,
.edit-row > .edit-text,
.edit-row > .run-picker {
  width: 100%;
  box-sizing: border-box;
  max-width: none;
}

/* The top bar is one row. No label in it wraps onto two lines: a row that runs out of room wraps whole items,
   and a long fact is cut with an ellipsis. On a detail screen, the logo carries a back arrow. */
.topbar {
  flex-wrap: wrap;
}

.brand-back {
  margin-right: 4px;
  color: var(--muted);
}

/* At most 400px, and on a phone, the room left next to the logo: a select does not shrink below its text. */
.topbar .run-picker {
  max-width: min(400px, calc(100vw - 140px));
}

.topbar .tool,
.topbar .nav-link,
.topbar .note,
.topbar .pill,
.canvas-tools .tool,
.canvas-tools .note {
  white-space: nowrap;
}

.topbar .run-status {
  flex: 1 1 240px;
  flex-wrap: wrap;
  min-width: 0;
}

/* The Details button of a run or skill, and its card: each fact with its name. */
.details-button {
  width: 28px;
  min-height: 28px;
  padding: 0;
  border-radius: 50%;
  font-family: var(--mono);
  font-weight: 600;
  color: var(--muted);
}

.details-card {
  position: fixed;
  inset: auto;
  margin: 0;
  width: max-content;
  max-width: 340px;
  padding: 12px 14px;
  grid-template-columns: auto 1fr;
  gap: 6px 12px;
  background: var(--surface);
  color: var(--ink);
  border: 1px solid var(--line);
  border-radius: 12px;
  box-shadow: 0 6px 24px rgb(0 0 0 / 0.12);
  font-size: 13px;
}

/* Only while open: a display rule on the closed card would beat the browser's rule that hides it. */
.details-card:popover-open {
  display: grid;
}

.details-card dt {
  color: var(--muted);
  font-weight: 600;
}

.details-card dd {
  margin: 0;
}

/* The canvas tools float in the canvas's top right corner, like the controls of a map. */
.canvas-tools {
  position: absolute;
  top: 12px;
  right: 12px;
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 4px;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: 12px;
  cursor: default;
}

.canvas-tools .tool {
  min-height: 30px;
  padding: 4px 10px;
}

/* The refresh control in the app bar: the live status, the automatic refresh choice, and the button. */
.refresh-control {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-left: auto; /* the right end of the top bar */
}

.refresh-status {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: 12px;
  white-space: nowrap;
  font-variant-numeric: tabular-nums;
}

.refresh-dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--muted);
}

.refresh-status[data-mode="off"] .refresh-dot {
  background: none;
  box-shadow: inset 0 0 0 1.5px var(--muted);
}

.refresh-status[data-mode="live"] .refresh-dot {
  background: var(--now);
  animation: refresh-pulse 1.6s ease-in-out infinite;
}

.refresh-choice {
  font-weight: 500;
}

.refresh-now {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 34px;
  padding: 0;
}

.refresh-now svg {
  width: 16px;
  height: 16px;
  fill: none;
  stroke: currentColor;
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.refresh-now[aria-busy="true"] svg {
  animation: refresh-turn 0.9s linear infinite;
}

@keyframes refresh-pulse {
  50% {
    opacity: 0.35;
  }
}

@keyframes refresh-turn {
  to {
    transform: rotate(360deg);
  }
}

@media (prefers-reduced-motion: reduce) {
  .refresh-status[data-mode="live"] .refresh-dot,
  .refresh-now[aria-busy="true"] svg {
    animation: none;
  }
}

/* On a phone, the app bar keeps the tabs and the refresh button: the status and the choice go. */
@media (max-width: 640px) {
  .refresh-status,
  .refresh-choice {
    display: none;
  }
}

/* The "?" button of a field, and the dialog that it opens. */
.with-help {
  display: inline-flex;
  align-items: center;
  gap: 6px;
}

.help-button {
  flex: 0 0 auto;
  width: 16px;
  height: 16px;
  padding: 0;
  border: 1px solid var(--ghost);
  border-radius: 50%;
  background: var(--surface);
  color: var(--muted);
  font-size: 11px;
  font-weight: 700;
  line-height: 14px;
  letter-spacing: 0;
  text-transform: none;
  text-align: center;
  cursor: pointer;
}

.help-button:hover,
.help-button:focus-visible {
  border-color: var(--done);
  color: var(--done);
}

.help-dialog {
  width: min(640px, calc(100vw - 32px));
  max-height: calc(100vh - 64px);
  padding: 0;
  border: 1px solid var(--line);
  border-radius: 12px;
  background: var(--surface);
  color: var(--ink);
  box-shadow: 0 16px 48px rgba(0, 0, 0, 0.25);
}

.help-dialog::backdrop {
  background: rgba(15, 18, 22, 0.45);
}

.help-body {
  display: flex;
  flex-direction: column;
  gap: 10px;
  padding: 18px 20px 20px;
}

.help-body p {
  margin: 0;
}

.help-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
}

.help-head h2 {
  margin: 0;
  font-size: 18px;
}

.help-lead {
  font-weight: 600;
}

.help-body h3 {
  margin: 6px 0 0;
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--muted);
}

/* --- links to another skill or agent, and the agent screen ------------------------------------ */

.entity-link {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  font-weight: 600;
  text-decoration: none;
}

.entity-link::after {
  content: "→";
  transition: transform 0.15s ease;
}

.entity-link:hover {
  text-decoration: underline;
}

.entity-link:hover::after {
  transform: translateX(2px);
}

.entity-links {
  display: flex;
  flex-wrap: wrap;
  gap: 6px 16px;
}

.entity-user {
  display: inline-flex;
  align-items: baseline;
  gap: 6px;
}

.agent-page {
  max-width: 860px;
}

.agent-page section h3,
.agent-text-head h3 {
  margin: 0 0 8px;
  font-size: 12px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--muted);
}

.agent-text-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 8px;
}

.agent-text-head h3 {
  margin: 0;
}

.agent-editor {
  width: 100%;
  min-height: 420px;
  box-sizing: border-box;
}

/* The hosted viewer: the project of each run, and the folders that the user picked. */
.run-card-place {
  color: var(--muted);
  font-family: var(--mono);
  font-size: 12px;
  overflow-wrap: anywhere;
}

.folder-card {
  display: flex;
  flex-direction: column;
  gap: 10px;
  margin-top: 16px;
  padding: 16px 18px;
  border: 1px solid var(--line);
  border-radius: 12px;
  background: var(--surface);
}

.folder-card .run-card-head {
  align-items: center;
}

.folder-card .edit-input {
  width: 100%;
  box-sizing: border-box;
}

.folder-places {
  margin: 0;
  padding-left: 20px;
  font-family: var(--mono);
  font-size: 13px;
}
