/* style.css — the IDE's own styling. Monaco brings its own.
   Two themes, switched by body[data-theme]; the pane colours follow. */

:root {
  --bg: #14161b; --bg2: #191c22; --fg: #dfe3ea; --muted: #8b94a6;
  --line: #2a2f3a; --accent: #6aa6ff; --ok: #4fbf78; --warn: #e0a33e; --err: #e35d6a;
  --menu-bg: #1d2028; --hover: #262b35; --input: #10131a;
}
body[data-theme="light"] {
  --bg: #f7f8fa; --bg2: #ffffff; --fg: #22262e; --muted: #667085;
  --line: #dfe3ea; --accent: #2563eb; --ok: #17803d; --warn: #a86500; --err: #b91c1c;
  --menu-bg: #eef0f4; --hover: #e3e7ee; --input: #ffffff;
}

* { box-sizing: border-box; }
html, body { height: 100%; margin: 0; }
body {
  background: var(--bg); color: var(--fg);
  font: 13px/1.45 system-ui, -apple-system, "Segoe UI", sans-serif;
  display: flex; flex-direction: column; overflow: hidden;
}
body.dragging { cursor: col-resize; user-select: none; }
button, select, input, textarea {
  background: var(--input); color: var(--fg); border: 1px solid var(--line);
  border-radius: 5px; padding: 3px 8px; font: inherit;
}
button { cursor: pointer; }
button:hover:not(:disabled) { background: var(--hover); }
button:disabled { opacity: .45; cursor: default; }
button.primary { background: var(--accent); border-color: var(--accent); color: #fff; }
.muted { color: var(--muted); }

/* ---- top bar and menus --------------------------------------------------- */
#topbar {
  display: flex; align-items: center; gap: 10px; padding: 6px 10px;
  background: var(--menu-bg); border-bottom: 1px solid var(--line); flex: 0 0 auto;
}
.brand { font-weight: 700; letter-spacing: .2px; }
.brand span { color: var(--accent); }
.spacer { flex: 1; }
.filename { color: var(--muted); }
.status { color: var(--muted); min-width: 12ch; text-align: right; }

/*  The top bar is the only control panel, so its contents are grouped rather
    than strung out: the run controls are one group, the two optional panels
    another, with a rule between them. Before this the controls were split
    between here and two docks in the opposite corner, and the first question
    every new reader asked was which of the two to use. */
.ctrlgroup {
  display: flex; align-items: center; gap: 6px;
  padding-left: 10px; border-left: 1px solid var(--line);
}
/*  Specific enough to beat `button:hover`, which otherwise repaints an open
    panel's button as closed for as long as the pointer rests on it. */
#topbar button.paneltoggle[aria-pressed="true"],
#topbar button.paneltoggle[aria-pressed="true"]:hover {
  background: var(--accent); border-color: var(--accent); color: #fff;
}

#menubar { display: flex; gap: 2px; }
.menu { position: relative; padding: 3px 9px; border-radius: 5px; cursor: default; }
.menu:hover { background: var(--hover); }
.menu-title { user-select: none; }
.menu .dropdown {
  display: none; position: absolute; top: 100%; left: 0; z-index: 40; min-width: 230px;
  background: var(--menu-bg); border: 1px solid var(--line); border-radius: 7px;
  box-shadow: 0 10px 28px rgba(0,0,0,.35); padding: 5px; margin-top: 4px;
}
.menu.open .dropdown { display: block; }
.menu .item {
  padding: 5px 10px; border-radius: 5px; cursor: pointer; white-space: nowrap;
  color: var(--fg); text-decoration: none; display: block;
}
.menu .item:hover { background: var(--hover); }
.menu .sep { height: 1px; background: var(--line); margin: 5px 4px; }

/* ---- workbench ----------------------------------------------------------- */
/*  minmax(0, 1fr) on the row, not `auto`: with an auto row the panes are as
    tall as whatever they contain, which is how a canvas that sizes itself
    from its parent ends up 2500 px tall — or 16. */
#workbench { flex: 1; display: grid; grid-template-columns: 50% 6px 1fr;
             grid-template-rows: minmax(0, 1fr); min-height: 0; }
/*  A grid, not a flex column: the two docks are resizable, so their heights
    are set from JavaScript and the editor takes what is left. Rows are
    [tabs, editor, grip, assistant, grip, live]. */
#left { display: grid; grid-template-rows: auto 1fr 4px auto 4px auto;
        min-width: 0; min-height: 0; border-right: 1px solid var(--line); }
/*  `overflow: hidden`, and an opaque pane column, because Monaco lays its text
    out wider than its own container — `.view-lines` runs past the right edge of
    the editor by however long the longest line is — and relies on one
    `overflow: hidden` of its own to hide the surplus. When that clip is missing
    the source spills across the splitter and is painted under the visualisers,
    which are transparent, so the program appears *through* the scene. Two
    stops, either of which is enough on its own. */
#editor { min-height: 120px; overflow: hidden; }
.hsplit { background: var(--line); cursor: row-resize; }
.hsplit:hover { background: var(--accent); }
#splitter { background: var(--line); cursor: col-resize; }
#splitter:hover { background: var(--accent); }
#right { display: flex; flex-direction: column; min-width: 0; min-height: 0;
         background: var(--bg); }

/* ---- file tabs ----------------------------------------------------------- */
/*  Several files open at once, VS Code's shape. A tab owns its run as well as
    its text, so the panes on the right are always about the file that is lit. */
.filetabs {
  display: flex; align-items: stretch; gap: 1px; overflow-x: auto;
  background: var(--menu-bg); border-bottom: 1px solid var(--line); min-height: 30px;
}
.filetab {
  display: flex; align-items: center; gap: 6px; padding: 4px 8px 4px 12px;
  border-right: 1px solid var(--line); cursor: pointer; white-space: nowrap;
  color: var(--muted); border-top: 2px solid transparent; font-size: 12px;
}
.filetab:hover { background: var(--hover); }
.filetab.on { background: var(--bg); color: var(--fg); border-top-color: var(--accent); }
.filetab.dirty .ft-name::after { content: " •"; color: var(--warn); }
.filetab .ft-ran { color: var(--ok); }
.filetab .ft-close {
  border: none; background: none; padding: 0 4px; color: var(--muted); border-radius: 4px;
}
.filetab .ft-close:hover { background: var(--line); color: var(--fg); }
.ft-new { border: none; background: none; color: var(--muted); padding: 0 10px; }

/*  Diagnostics live in the editor — squiggle, hover, overview ruler — so the
    only thing left out here is the count, which doubles as a jump button. */
.status { cursor: pointer; }
.status.has-errors { color: var(--err); }
.status.has-warnings { color: var(--warn); }

/* ---- docked panels (assistant, live) ------------------------------------- */
/*  A closed panel takes up no room and shows no controls.
    It used to keep its whole toolbar on screen while closed — for the two
    panels together, twelve buttons of which nine were greyed out — so the
    corner of the screen furthest from the Run button was also the busiest.
    They are opened from the two buttons in the top bar. */
.dock { border-top: 1px solid var(--line); background: var(--bg2); display: flex; flex-direction: column; }
/*  `visibility: hidden` and not `display: none`: the two docks and their two
    grips are rows of the left column's grid, and a `display: none` item is
    taken out of the grid altogether, so hiding one silently moved every row
    below it up by one. This keeps the row and lets main.js set its height to
    zero, which is what actually makes the panel take up no space. */
.dock.collapsed { visibility: hidden; border-top: none; }
.dock-head { display: flex; align-items: center; gap: 6px; padding: 5px 8px; flex-wrap: wrap; }
.dock-head .dock-title { font-weight: 600; padding: 2px 4px; }
.dock-head .dock-close {
  background: none; border: none; color: var(--muted); font-size: 15px; line-height: 1; padding: 2px 7px;
}
.dock-head .dock-close:hover { background: var(--line); color: var(--fg); }
.dock-body { flex: 1; min-height: 0; overflow: auto; padding: 6px 10px; }
.dock { min-height: 0; overflow: hidden; }
.dock-foot { display: flex; gap: 6px; padding: 6px 8px; border-top: 1px solid var(--line); }
.dock-foot textarea, .dock-foot input { flex: 1; resize: vertical; }
.rate { display: flex; align-items: center; gap: 5px; white-space: nowrap; }
.rate input { width: 68px; }
/*  A checkbox is not a number field: 68px of it left its own label stranded
    three centimetres away. */
.rate input[type=checkbox] { width: auto; }

/*  A control that cannot act on anything is not shown. `data-when` says what
    has to be true; live.js sets the class on the panel. */
#live [data-when] { display: none; }
#live.idle    [data-when="idle"]    { display: flex; }
#live.running [data-when="running"] { display: flex; }
#live.running:not(.paused) [data-when="ticking"] { display: flex; }
#live.paused  [data-when="paused"]  { display: flex; }
#play [data-when] { display: none; }
#play.idle    [data-when="idle"]    { display: flex; }
#play.running [data-when="running"] { display: flex; }
#play-feed .play-line { white-space: pre-wrap; margin: 2px 0; }
#play-feed .play-line.typed { color: var(--muted, #888); margin-top: 8px; }
#play-feed .play-line.why { font-family: monospace; font-size: 0.9em; opacity: 0.85; }
#play-feed .play-line.error { color: #d33; }
#play-feed .play-line.muted { opacity: 0.7; }
#play-feed .play-line.command { cursor: pointer; color: var(--accent, #2f6fdb); }
#play-feed .play-line.typed { cursor: pointer; }
#play-feed .play-line.current { background: var(--bg3, rgba(127,127,127,.15)); border-left: 3px solid var(--accent, #2f6fdb); padding-left: 4px; }
#play-feed .play-line.command:hover { text-decoration: underline; }
#play-auto-label { align-items: center; gap: 3px; margin-left: -4px; font-size: 0.85em; color: var(--muted, #888); cursor: pointer; white-space: nowrap; }
#play-feed .play-line.turnhead { color: var(--muted, #888); margin-top: 8px; cursor: pointer; }
#play-feed .play-turn { float: right; font-size: 0.8em; opacity: 0.6; margin-left: 8px; }

/*  The assistant with no key configured: one sentence and the button that
    fixes it, rather than a model list reading "no models" beside two buttons
    that cannot work. */
#assistant.unconfigured #assistant-model,
#assistant.unconfigured #animate-2d,
#assistant.unconfigured #animate-3d { display: none; }
#assistant-nokey { display: none; align-items: center; gap: 8px; color: var(--muted); }
#assistant.unconfigured #assistant-nokey { display: flex; }

.msg { margin: 6px 0; }
.msg .who { color: var(--muted); font-size: 11px; text-transform: uppercase; letter-spacing: .4px; }
.msg .body { white-space: pre-wrap; }
.msg.thinking .body { color: var(--muted); font-style: italic; }
.msg.error .body { color: var(--err); }
.msg .apply { margin-top: 5px; }
.key-row { display: flex; gap: 8px; align-items: center; margin: 5px 0; }
.key-row label { width: 12ch; color: var(--muted); }
.key-row input { flex: 1; }

.live-line { font-family: ui-monospace, monospace; font-size: 12px; padding: 1px 0; }
.live-line.sent { color: var(--accent); }
.live-line.ok { color: var(--ok); }
.live-line.error { color: var(--err); }
.live-line.proposal { display: flex; gap: 8px; align-items: center; color: var(--warn); }

/* ---- panes --------------------------------------------------------------- */
.tabs { display: flex; gap: 2px; padding: 6px 8px 0; border-bottom: 1px solid var(--line); }
.tabs button { border: none; border-bottom: 2px solid transparent; background: none; border-radius: 0; padding: 5px 10px; }
.tabs button.on { border-bottom-color: var(--accent); color: var(--accent); }
/*  One row, always the same height. The automaton's two checkboxes used to wrap
    onto a second line and push the diagram down as you switched to it and back
    up as you switched away — a pane whose contents jump when you arrive. */
.paneheader { display: flex; align-items: center; gap: 10px; padding: 6px 8px;
              min-height: 34px; overflow: hidden; white-space: nowrap; }
.paneheader input[type=range] { width: 220px; }
.transport { display: flex; align-items: center; gap: 6px; }
.dfa-opts { display: none; gap: 10px; color: var(--muted); font-size: 12px; }
body:has(#pane-automaton.on) .dfa-opts { display: flex; }
.pane-hint { font-size: 12px; margin-left: auto; }

/*  Which run the panes belong to, said once where the panes are. */
.badge { font-size: 10px; letter-spacing: .5px; text-transform: uppercase;
         padding: 1px 6px; border-radius: 9px; border: 1px solid currentColor; }
.badge.live { color: var(--ok); }
.badge.stale { color: var(--warn); text-transform: none; letter-spacing: 0; font-size: 11px; }
#right.stale .panes { opacity: .72; }

/*  Landmarks under the cycle slider: one tick per cycle in which something
    changed, so scrubbing has somewhere to aim. */
.sliderwrap { position: relative; display: inline-flex; flex-direction: column; }
.cycle-marks { position: relative; height: 5px; display: block; }
.cycle-marks i { position: absolute; top: 0; width: 2px; height: 5px;
                 background: var(--accent); opacity: .75; cursor: pointer; }
.cycle-marks i:hover { opacity: 1; height: 7px; }
.panes { flex: 1; position: relative; min-height: 0; }
.pane { display: none; position: absolute; inset: 0; overflow: auto; padding: 8px; }
/*  The canvas panes get a host of fixed extent: a canvas sized from a
    scrollable parent, inside that parent, grows without bound. */
.scene-host { position: absolute; inset: 0; overflow: hidden; }
.pane.on { display: block; }
.empty { color: var(--muted); padding: 14px; }

/*  What to do first, said where the results will appear. "Run a program
    first." was true and unhelpful: it named neither the program nor the way to
    get one. Each step here carries the control that performs it. */
.start-here { padding: 26px 22px; max-width: 46em; }
.start-here h2 { margin: 0 0 4px; font-size: 16px; font-weight: 600; }
.start-here > p { color: var(--muted); margin: 0 0 18px; }
.start-here ol { margin: 0; padding: 0; list-style: none; counter-reset: step; }
.start-here li {
  counter-increment: step; position: relative; padding: 0 0 16px 34px;
  border-left: 1px solid var(--line); margin-left: 11px;
}
.start-here li:last-child { border-left-color: transparent; padding-bottom: 0; }
.start-here li::before {
  content: counter(step); position: absolute; left: -11px; top: 0;
  width: 22px; height: 22px; border-radius: 50%; display: grid; place-items: center;
  background: var(--menu-bg); border: 1px solid var(--line);
  color: var(--muted); font-size: 12px;
}
.start-here .what { margin: 2px 0 7px; }
.start-here .why { color: var(--muted); font-size: 12px; margin: 6px 0 0; }
.start-here .keys { color: var(--muted); font-size: 12px; margin-left: 8px; }

/* ---- viewport (shared zoom/pan) ------------------------------------------ */
/*  No `position` here: .pane is already absolutely positioned and is its own
    containing block, and setting position:relative on it undid inset:0 —
    which collapsed every pane to its padding and made the visualisers look
    like they had rendered nothing. */
.vp-host { overflow: hidden; touch-action: none; }
.vp-host:not(.pane) { position: relative; }
.vp-host.vp-grabbing { cursor: grabbing; }
.vp-content { position: absolute; top: 0; left: 0; will-change: transform; }
/*  Faint, not invisible. At `opacity: 0` the zoom controls did not exist for
    anyone who never happened to move the pointer into the pane — which is most
    people, most of the time, in a pane they are reading rather than driving. */
.vp-controls {
  position: absolute; right: 10px; bottom: 10px; display: flex; gap: 4px; z-index: 5;
  opacity: .4; transition: opacity .15s ease;
}
.vp-host:hover .vp-controls, .vp-controls:focus-within { opacity: 1; }
.vp-controls button { width: 28px; height: 28px; padding: 0; background: var(--menu-bg); }

/* ---- timeline ------------------------------------------------------------ */
.timeline .grid { stroke: var(--line); stroke-width: 1; }
.timeline .axis, .timeline .lane { fill: var(--muted); font-size: 11px; }
.timeline .lane.strong { fill: var(--fg); font-weight: 600; }
/*  LPS1's palette here too, so a fluent is the same colour in the picture as it
    is in the text: pale blue for a fluent's interval, amber for something that
    happened, dashed amber for a composite event
    (`legacy_lps1/swish/web/lps/lps.css` — `.vis-item.compositeEvent` is where
    the dashes come from). */
.timeline .hold { fill: var(--lps-fluent-bg); opacity: .95; }
.timeline .ev circle { fill: var(--lps-event-fg); }
.timeline .cp circle { fill: none; stroke: var(--lps-event-fg); stroke-width: 1.5; stroke-dasharray: 2 2; }
.timeline .ev .tick { fill: var(--lps-event-fg); }
.timeline .cp .tick { fill: var(--lps-event-fg); opacity: .85; }
.timeline .axis { fill: var(--lps-time-fg); }
.timeline .tick { fill: var(--fg); font-size: 10px; }
.timeline .cursor { stroke: var(--err); stroke-width: 1.5; stroke-dasharray: 4 3; }

/* ---- automaton ----------------------------------------------------------- */
.automaton .state rect { fill: var(--bg2); stroke: var(--line); stroke-width: 1.5; }
.automaton .state.initial rect { stroke: var(--accent); stroke-width: 3; }
.automaton .state text { fill: var(--fg); font-size: 11px; font-family: ui-monospace, monospace; }
.automaton .state text.muted { fill: var(--muted); font-style: italic; }
.automaton .state .cycles { fill: var(--muted); font-size: 9px; }
.automaton .edge { stroke-width: 1.6; }
.automaton .edge.dfa-action { stroke: var(--lps-event-fg); }
.automaton .edge.dfa-event { stroke: var(--lps-event-fg); opacity: .75; }
.automaton .edge.dfa-mixed { stroke: var(--warn); }
/*  A transition is labelled with an event or an action, so the label takes the
    event colour; a state box lists fluents, so its text takes the fluent's. */
.automaton .label.fg { fill: var(--lps-event-fg); }
.automaton .state text.fluent { fill: var(--lps-fluent-fg); }
.automaton .state .fluentbg { fill: var(--lps-fluent-bg); }
.automaton .label { font-size: 10px; font-family: ui-monospace, monospace; }
.automaton .label.halo { stroke: var(--bg); stroke-width: 3.5; fill: none; }
.automaton .label.fg { fill: var(--fg); stroke: none; }
.automaton .label.more.fg { fill: var(--muted); }

/* ---- changes, explanation, internal -------------------------------------- */
table.changes { border-collapse: collapse; width: 100%; font-size: 12px; }
table.changes th { text-align: left; color: var(--muted); font-weight: 500; border-bottom: 1px solid var(--line); padding: 4px 6px; }
table.changes td { padding: 3px 6px; border-bottom: 1px solid var(--line); font-family: ui-monospace, monospace; }
table.changes .kind { text-transform: uppercase; font-size: 10px; letter-spacing: .4px; }
table.changes td.fluent span { background: var(--lps-fluent-bg); color: var(--lps-fluent-fg); border-radius: 3px; padding: 0 3px; }
table.changes td.fluent span.muted { background: none; color: var(--muted); }
table.changes td.event { color: var(--lps-event-fg); }
table.changes tr.initiated .kind { color: var(--ok); }
table.changes tr.terminated .kind { color: var(--err); }
table.changes tr.updated .kind { color: var(--warn); }
.explanation .verdict { font-weight: 600; margin-bottom: 8px; }
.explanation .node { font-family: ui-monospace, monospace; font-size: 12px; padding: 1px 0; }
.explanation .detail { color: var(--muted); }
pre.internal { font-family: ui-monospace, monospace; font-size: 12px; white-space: pre-wrap; }

/* ---- dialog -------------------------------------------------------------- */
.dialog { display: none; position: fixed; inset: 0; background: rgba(0,0,0,.45); z-index: 100; }
.dialog.on { display: flex; align-items: center; justify-content: center; }
.dialog-box {
  background: var(--bg2); border: 1px solid var(--line); border-radius: 10px;
  min-width: 460px; max-width: 82vw; max-height: 80vh; display: flex; flex-direction: column;
  box-shadow: 0 20px 60px rgba(0,0,0,.5);
}
.dialog-head { display: flex; justify-content: space-between; align-items: center; padding: 10px 14px; border-bottom: 1px solid var(--line); font-weight: 600; }
.dialog-head button { background: none; border: none; font-size: 18px; }
.dialog-body { padding: 12px 14px; overflow: auto; }
.dialog-actions { display: flex; justify-content: flex-end; gap: 8px; padding: 10px 14px; border-top: 1px solid var(--line); }
.list { max-height: 52vh; overflow: auto; }
.list .row { padding: 4px 8px; border-radius: 5px; cursor: pointer; display: flex; gap: 12px; }
.list .row:hover { background: var(--hover); }
.ex-name { font-family: ui-monospace, monospace; min-width: 34ch; }
.ex-title { color: var(--muted); }
input.filter { width: 100%; margin-bottom: 8px; }
textarea.obs { width: 100%; font-family: ui-monospace, monospace; }

/* ---- the examples dialog, with a resizable name column -------------------- */
.exwrap { position: relative; }
.list.cols .row { display: grid; grid-template-columns: var(--ex-name-w, 300px) 1fr; gap: 12px; }
.list.cols .ex-name { min-width: 0; overflow: hidden; text-overflow: ellipsis; }
.colgrip {
  position: absolute; top: 0; bottom: 0; width: 7px; cursor: col-resize;
  left: calc(var(--ex-name-w, 300px) + 4px);
}
.colgrip::after { content: ""; position: absolute; inset: 0 3px; background: var(--line); }
.colgrip:hover::after { background: var(--accent); }

/* ---- "why did that happen?" ---------------------------------------------- */
/*  Every element a visualiser draws for a fluent or an event is askable: the
    cursor says so, and right-click opens the explanation for that term at that
    cycle. There is no explain pane any more — the question belongs where the
    thing is. */
.askable { cursor: context-menu; }
.askable:hover { filter: brightness(1.25); }
svg .askable:hover { filter: brightness(1.4); }
.why-q code { font-family: ui-monospace, monospace; color: var(--accent); }
.why-answer { margin: 10px 0; min-height: 60px; }
.why-notrow { display: flex; gap: 8px; align-items: center; border-top: 1px solid var(--line); padding-top: 10px; }
.why-notrow .why-not { flex: 1; font-family: ui-monospace, monospace; font-size: 12px; }

/* ---- the icon dialog ------------------------------------------------------ */
.iconlist { display: flex; flex-wrap: wrap; gap: 6px; max-height: 40vh; overflow: auto; }
.icontag { display: flex; align-items: center; gap: 4px; padding: 3px 6px;
           border: 1px solid var(--line); border-radius: 6px; font-size: 11px; }
.icontag img { width: 18px; height: 18px; }
.about h4 { margin: 12px 0 4px; }
.about ul { margin: 4px 0; padding-left: 20px; }
/*  A link in a dialog inherits the body colour, which makes it look like the
    sentence around it. These are the two the About panel exists to point at. */
.about a { color: var(--accent); text-decoration: none; border-bottom: 1px solid currentColor; }
.about a:hover { filter: brightness(1.2); }
.key-state { min-width: 9ch; text-align: right; font-size: 11px; }
.key-state.ok { color: var(--ok); }
.model-pick { flex: 1; }
pre.code {
  background: var(--input); border: 1px solid var(--line); border-radius: 6px;
  padding: 8px 10px; font-family: ui-monospace, monospace; font-size: 12px;
  white-space: pre; overflow: auto;
}

/* ---- the WASM dialog ------------------------------------------------------ */
.wasm-opt { display: flex; align-items: center; gap: 6px; margin: 10px 0; }
.wasm-opt input { width: auto; }
.wasm-desktop { border-top: 1px solid var(--line); margin-top: 14px; padding-top: 10px; }
.wasm-desktop a { color: var(--accent); }

/* an explanation node that names a clause is a place to go */
.explanation .node.has-source { cursor: pointer; border-radius: 4px; }
.explanation .node.has-source:hover { background: var(--hover); }
.why-kind { flex: 0 0 auto; }

/*  ---- LPS1's colours ------------------------------------------------------
 *
 *  `legacy_lps1/swish/web/lps/lps.css`, kept: a fluent literal is dark text on
 *  a pale blue chip, an event or action is amber, a time is a lighter amber,
 *  and a composite event is dashed amber. Anyone who has used LPS on SWISH
 *  reads a program by these colours, and the point of matching them is that
 *  they do not have to learn a second set.
 *
 *  The chip is a background, so it has to work on both themes: the blue is
 *  LPS1's own on light, and a translucent version of it on dark, where #D7DCF5
 *  behind #d4d4d4 text would be unreadable. */
:root {
  --lps-fluent-bg: #D7DCF5;
  --lps-fluent-fg: #1A1A1A;
  --lps-event-fg: #B36B10;
  --lps-time-fg: #C97F17;
}
body[data-theme="dark"] {
  --lps-fluent-bg: rgba(120, 140, 220, 0.30);
  --lps-fluent-fg: #cfd8ff;
  --lps-event-fg: #E19735;
  --lps-time-fg: #FDA428;
}

.monaco-editor .lps-fluent,
.pane .lps-fluent, .why .lps-fluent {
  background: var(--lps-fluent-bg); color: var(--lps-fluent-fg); border-radius: 3px;
}
.monaco-editor .lps-event, .monaco-editor .lps-action,
.pane .lps-event, .why .lps-event { color: var(--lps-event-fg); }
.pane .lps-time, .why .lps-time { color: var(--lps-time-fg); }
.pane .lps-composite {
  color: var(--lps-event-fg); border: 1px dashed var(--lps-event-fg);
  background: transparent; border-radius: 3px;
}

/*  A clause that fired in the last run, in the gutter. Faint on purpose: it is
 *  a background fact about the file, not a diagnostic. */
.monaco-editor .lps-fired {
  border-left: 3px solid var(--ok, #4ec9b0); margin-left: 2px; opacity: .75;
}

/* ---- cycle controls ------------------------------------------------------ */
.paneheader .cyc {
  padding: 1px 6px; min-width: 26px; font-size: 12px; line-height: 18px;
}
/*  When the header runs out of room the *hint* gives way, not the filename:
    the hint is a sentence anyone can finish from memory, and "g⋯" is not a
    file. */
.paneheader .pane-program { flex: 0 0 auto; max-width: 220px;
                            overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.paneheader .pane-hint { flex: 1 1 0; min-width: 0; overflow: hidden;
                         text-overflow: ellipsis; text-align: right; }
.paneheader .transport { flex: 0 0 auto; }
/*  A grey `?` among grey chrome reads as decoration. Give it the accent, which
    is the colour everything clickable in this IDE already uses. */
.paneheader .pane-help {
  text-decoration: none; border: 1px solid var(--accent); color: var(--accent);
  border-radius: 50%; flex: none;
  width: 17px; height: 17px; line-height: 15px; text-align: center; font-size: 11px;
}
.paneheader .pane-help:hover { background: var(--accent); color: #fff; }
/*  A pane with nothing to show is dimmed, and its tooltip says why. It used to
    also grow a "·", which at rest — before any run, when every pane is empty —
    made the whole strip look like it had been marked up.

    Two dimmings, because they mean different things and the reader can act on
    only one of them: `waiting` will fill as soon as you press Run, `empty-pane`
    will not, whatever you press. A pane that is *ready* is not dimmed at all —
    which is the whole point, and was not true until the marking stopped being
    driven by which tabs had been clicked. */
#tabs button.waiting { opacity: .5; }
#tabs button.empty-pane { opacity: .5; font-style: italic; }
#tabs button.unavailable.on { opacity: .85; }

.maxtime { font-size: 12px; opacity: .8; display: flex; align-items: center; gap: 4px; }
#live .dock-head { flex-wrap: wrap; row-gap: 4px; }
#live .dock-head label.rate { white-space: nowrap; }
.maxtime input { width: 56px; }

/* ---- examples dialog ----------------------------------------------------- */
.ex-folder {
  padding: 5px 8px 3px; font-weight: 600; opacity: .75; cursor: pointer;
  border-bottom: 1px solid var(--line); margin-top: 6px;
  display: flex; gap: 10px; align-items: baseline;
}
.ex-folder::before { content: "▸ "; }
.ex-folder.open::before { content: "▾ "; }
.ex-folder .ex-blurb { font-weight: 400; color: var(--muted); font-size: 12px; }
.ex-folder.start-here { cursor: default; color: var(--accent); opacity: 1; margin-top: 0; }
.ex-folder.start-here::before { content: ""; }
.list .row.sel { background: var(--accent); color: #fff; }
.ex-preview {
  max-height: 190px; overflow: auto; margin: 8px 0 0; padding: 8px;
  background: var(--panel, rgba(127,127,127,.08)); border-radius: 5px;
  font-size: 11px; white-space: pre; line-height: 1.35;
}

/* ---- the floating tooltip the canvas panes use --------------------------- */
.scene-tip {
  position: fixed; z-index: 60; pointer-events: none;
  background: var(--bg); color: var(--fg); border: 1px solid var(--line);
  border-radius: 5px; padding: 3px 7px; font-size: 12px;
  box-shadow: 0 3px 12px rgba(0,0,0,.35); max-width: 380px;
}
.scene-legend {
  position: absolute; right: 8px; bottom: 8px; z-index: 5;
  background: var(--bg); border: 1px solid var(--line); border-radius: 6px;
  padding: 6px 8px; font-size: 11px; max-height: 45%; overflow: auto; opacity: .92;
}
.scene-legend .row { display: flex; gap: 6px; align-items: center; padding: 1px 0; }
.scene-legend .sw { width: 11px; height: 11px; border-radius: 2px; flex: none; }
.pane .empty-actions { margin-top: 12px; display: flex; gap: 8px; justify-content: center; }

/* ---- docked documentation ------------------------------------------------ */
#docpane {
  border: 0; border-top: 1px solid var(--line); width: 100%; height: 42%;
  background: var(--bg);
}
#right:has(#docpane) .panes { height: 58%; }

.rundiff .diffrow { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; font-size: 12px; padding: 1px 0; }
.rundiff .diffrow.differs { background: rgba(255,180,0,.14); }
.rundiff .diffrow.head { border-bottom: 1px solid var(--line); margin-bottom: 4px; padding-bottom: 4px; }
.internal-head { display: flex; justify-content: space-between; align-items: center;
                 padding: 4px 6px; gap: 8px; }
.pane .empty.working { color: var(--accent); font-style: italic; }
.internal .iline { white-space: pre; }
.internal .iline.has-source:hover { background: var(--hover); cursor: pointer; }
.changes tr.lawgroup td { padding-top: 9px; opacity: .8; font-size: 11px; }
.changes tr.lawgroup .law.has-source { cursor: pointer; text-decoration: underline dotted; }
.why-history { margin: 8px 0; }
.why-prev summary { cursor: pointer; opacity: .7; font-size: 12px; }
.why-prev pre { font-size: 11px; opacity: .8; max-height: 140px; overflow: auto; }
.why-cycle { width: 60px; }
.why-forms { font-size: 11px; line-height: 1.7; }
.mouse-legend { font-size: 10px; margin-left: 8px; white-space: nowrap; }
.tl-legend .axis { font-size: 10px; opacity: .7; }
.ev-key { fill: var(--lps-event-fg); }
.cp-key { fill: none; stroke: var(--lps-event-fg); stroke-dasharray: 2 2; }

/* ---- scene tools --------------------------------------------------------- */
.scene-tools {
  position: absolute; left: 8px; bottom: 8px; z-index: 5; display: flex; gap: 4px;
  opacity: .35; transition: opacity .15s;
}
.pane:hover .scene-tools { opacity: 1; }
.scene-tools button { font-size: 11px; padding: 1px 6px; }
.compare { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; }
.compare figure { margin: 0; }
.compare img { width: 100%; border: 1px solid var(--line); border-radius: 4px; }
.compare figcaption { font-size: 11px; opacity: .7; text-align: center; padding-top: 4px; }
#assistant-log button.preview { font-size: 11px; margin-top: 6px; margin-right: 6px; }

/* ---- the generated program beside a Logical English document ------------- */
.internal.generated .iline .prov { font-size: 10px; opacity: .45; }
.internal.generated .iline.has-source:hover { background: var(--hover); cursor: pointer; }
