/* Whole-cell atlas. Colours are tokens: hue belongs to evolutionary age, on five steps of matplotlib's
   plasma, purple (oldest) to orange (youngest); everything else is neutral ink and surfaces. The steps
   are the stretch of plasma whose two ends clear 2:1 on both themes' surfaces, so an era has the same
   colour in both. The link overlay takes the one accent, aqua, a hue plasma never reaches. The colour
   menu swaps plasma for viridis or Blues, or turns age colour off (the data-palette rules below). */

:root {
  color-scheme: light;
  --page: #f9f9f7;
  --surface: #fcfcfb;
  --ink: #0b0b0b;
  --ink-2: #52514e;
  --muted: #898781;
  --grid: #e1e0d9;
  --baseline: #c3c2b7;
  --border: rgba(11, 11, 11, 0.10);
  /* the cell's own neutrals */
  --medium: #f9f9f7;
  --wall: #e8e7e1;
  --membrane: #deddd6;
  --cytosol: #f4f3ef;
  --organelle: #ecebe6;
  --nucleus: #e6e5df;
  --band: #dcdbd4;
  /* age, oldest to youngest: plasma at t = 0.25, 0.40, 0.53, 0.65, 0.77. Lightness rises
     monotonically in OKLab steps of about 0.08; the orange end is 2.07:1 on the light surface and
     the purple end 2.07:1 on the dark one. The same values serve both themes. */
  --age-0: #8004a8;
  --age-1: #b12a90;
  --age-2: #d24f71;
  --age-3: #eb7556;
  --age-4: #fa9c3c;
  --age-none: #898781;
  /* the reference palette's aqua (dark step): 3.3:1 on the light surface, 5.1:1 on the dark */
  --accent: #199e70;
  --font: system-ui, -apple-system, "Segoe UI", sans-serif;
}

@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    color-scheme: dark;
    --page: #0d0d0d;
    --surface: #1a1a19;
    --ink: #ffffff;
    --ink-2: #c3c2b7;
    --muted: #898781;
    --grid: #2c2c2a;
    --baseline: #383835;
    --border: rgba(255, 255, 255, 0.10);
    --medium: #141413;
    --wall: #262624;
    --membrane: #2e2e2b;
    --cytosol: #1f1f1e;
    --organelle: #252523;
    --nucleus: #282826;
    --band: #33332f;
  }
}

:root[data-theme="dark"] {
  color-scheme: dark;
  --page: #0d0d0d;
  --surface: #1a1a19;
  --ink: #ffffff;
  --ink-2: #c3c2b7;
  --muted: #898781;
  --grid: #2c2c2a;
  --baseline: #383835;
  --border: rgba(255, 255, 255, 0.10);
  --medium: #141413;
  --wall: #262624;
  --membrane: #2e2e2b;
  --cytosol: #1f1f1e;
  --organelle: #252523;
  --nucleus: #282826;
  --band: #33332f;
}

/* The other age scales of the header's colour menu (main.js sets data-palette on the root; the docs
   page sets it on an element to show a scale beside the others). Each is five steps picked as
   plasma's were: OKLab lightness rising about 0.08 a step from the oldest to
   the youngest, and both ends clearing 2:1 on both themes' surfaces, so one set serves both themes.
   Blues is one hue and passes every ordinal check of the dataviz validator; viridis, like plasma,
   spans several hues, so only the lightness and contrast checks apply to it. Viridis reaches the
   links' aqua, so under it links are deep orange: at least 10 OKLab dE (x100) from every step, also
   under protanopia and deuteranopia. Under "off" every gene is one neutral ink: age is not coloured. */
[data-palette="viridis"] {
  --age-0: #3f4889;
  --age-1: #2f6c8e;
  --age-2: #228d8d;
  --age-3: #26ad81;
  --age-4: #5cc863;
  --accent: #d9531e;
}

[data-palette="blues"] {
  --age-0: #084c95;
  --age-1: #1967ad;
  --age-2: #3484bf;
  --age-3: #549fcd;
  --age-4: #7fb9da;
}

[data-palette="off"] {
  --age-0: var(--ink-2);
  --age-1: var(--ink-2);
  --age-2: var(--ink-2);
  --age-3: var(--ink-2);
  --age-4: var(--ink-2);
  --age-none: var(--ink-2);
}

* { box-sizing: border-box; }

html, body { margin: 0; }

/* On a desktop the page is one screen: the header, the cell beside the inspector, then the timeline
   and what the cell holds. minmax(0, ...): no child (the timeline's svg is sized in pixels) may
   widen or lengthen the page, and nothing may push the timeline off it. */
body {
  display: grid;
  height: 100vh;
  height: 100dvh;
  grid-template-columns: minmax(0, 1fr) 340px;
  grid-template-rows: auto minmax(0, 1fr) auto auto;
  grid-template-areas: "bar bar" "stage inspector" "time time" "axis axis";
  background: var(--page);
  color: var(--ink);
  font: 14px/1.45 var(--font);
}

.first-screen { display: contents; }
.bar { grid-area: bar; }
.stage { grid-area: stage; }
.inspector { grid-area: inspector; }
.time { grid-area: time; }
.axis { grid-area: axis; }

.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
}

button, select, input { font: inherit; color: inherit; }

button, select {
  background: var(--surface);
  border: 1px solid var(--baseline);
  border-radius: 6px;
  padding: 3px 10px;
  cursor: pointer;
}

button:hover, select:hover { border-color: var(--muted); }

/* focus is neutral ink: a ramp colour would read as an age */
button:focus-visible, select:focus-visible, input:focus-visible {
  outline: 2px solid var(--ink);
  outline-offset: 2px;
}

/* ------------------------------------------------------------------ header */
.bar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px 20px;
  padding: 10px 16px;
  background: var(--surface);
  border-bottom: 1px solid var(--border);
}

.bar h1 {
  margin: 0;
  font-size: 16px;
  font-weight: 600;
}

.bar .sub {
  margin-left: 6px;
  color: var(--ink-2);
  font-weight: 400;
}

.search input {
  width: 240px;
  max-width: 60vw;
  padding: 4px 10px;
  background: var(--page);
  border: 1px solid var(--baseline);
  border-radius: 6px;
}

.controls {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 6px 14px;
  margin-left: auto;
  color: var(--ink-2);
}

.switch, .links {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  white-space: nowrap;
}

.switch label { display: inline-flex; align-items: center; gap: 4px; }

/* a link that looks like the header's buttons (the docs page) */
a.button {
  display: inline-block;
  padding: 3px 10px;
  background: var(--surface);
  border: 1px solid var(--baseline);
  border-radius: 6px;
  color: inherit;
  text-decoration: none;
}

a.button:hover { border-color: var(--muted); }
a.button:focus-visible { outline: 2px solid var(--ink); outline-offset: 2px; }

/* ------------------------------------------------------------------ stage + inspector */
.stage {
  position: relative;
  min-height: 0;
  overflow: hidden;
  background: var(--surface);
}

/* the canvas fills the stage and never sizes it: the stage's size comes from the layout alone */
.stage canvas {
  position: absolute;
  inset: 0;
  display: block;
  width: 100%;
  height: 100%;
  cursor: grab;
  touch-action: none;
}

.stage canvas.dragging { cursor: grabbing; }

.loading {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  color: var(--ink-2);
}

.tooltip {
  position: absolute;
  z-index: 5;
  max-width: 280px;
  padding: 6px 10px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 6px;
  box-shadow: 0 2px 10px rgba(0, 0, 0, 0.12);
  pointer-events: none;
  font-size: 13px;
}

.tooltip b { font-weight: 600; }
.tooltip .dim { color: var(--ink-2); }

/* the stage's two views: the drawing, and the systems list over it */
.view-tabs {
  position: absolute;
  top: 10px;
  left: 10px;
  z-index: 3;
  background: var(--surface);
}

.systems {
  position: absolute;
  inset: 0;
  z-index: 2;
  display: flex;
  flex-direction: column;
  background: var(--surface);
}

.systems[hidden] { display: none; }

/* the networks: a toolbar over its own canvas (networks.js) */
.networks {
  position: absolute;
  inset: 0;
  z-index: 2;
  display: flex;
  flex-direction: column;
  background: var(--surface);
}

.networks[hidden] { display: none; }

.net-tools {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px 12px;
  padding: 10px 16px 8px;
  border-bottom: 1px solid var(--border);
  color: var(--ink-2);
}

/* room for the view tabs, which sit over the toolbar's first line */
.net-tools::before { content: ""; flex: none; width: 214px; height: 30px; }
.net-kinds { display: flex; flex-wrap: wrap; gap: 4px; }
.net-kinds .chip-toggle { display: inline-flex; align-items: center; gap: 3px; padding: 0 8px; font-size: 12px; }
.net-stage { position: relative; flex: 1; min-height: 0; }

/* what the network holds at the stop, over the drawing's foot */
.net-summary {
  position: absolute;
  right: 8px;
  bottom: 6px;
  left: 8px;
  z-index: 1;
  margin: 0;
  padding: 3px 8px;
  background: color-mix(in srgb, var(--surface) 88%, transparent);
  border-radius: 4px;
  color: var(--ink-2);
  font-size: 12px;
  pointer-events: none;
}

.net-stage canvas {
  position: absolute;
  inset: 0;
  display: block;
  width: 100%;
  height: 100%;
  cursor: grab;
  touch-action: none;
}

.net-stage canvas.dragging { cursor: grabbing; }

/* a link's head, in the one link colour; on a pressed switch it takes the switch's ink */
.link-icon { flex: none; color: var(--accent); vertical-align: middle; }
.chip-toggle[aria-pressed="true"] .link-icon { color: inherit; }
.switch[hidden], .net-tools [hidden] { display: none; }

/* a pool's makers, and the mass budget: bands as wide as their mass, in neutral ink */
.inspector ul.makers { margin: 6px 0; padding: 0; list-style: none; }
.inspector ul.makers li { margin: 3px 0; line-height: 1.45; }
.inspector ul.makers .swatch { margin-right: 4px; }
.budget { margin: 8px 0; }
.budget svg { display: block; width: 100%; height: auto; }
.budget path { fill: var(--ink-2); opacity: 0.22; }
.budget rect { fill: var(--ink-2); }
.budget text { fill: var(--ink-2); font: 10px var(--font); }
.budget line { stroke: var(--muted); stroke-width: 0.6; }

.sys-tools {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px 12px;
  padding: 10px 16px 8px;
  border-bottom: 1px solid var(--border);
}

/* room for the view tabs, which sit over the toolbar's first line */
.sys-tools::before { content: ""; flex: none; width: 214px; height: 30px; }

.sys-kinds { display: inline-flex; flex-wrap: wrap; gap: 6px; }

.chip-toggle {
  padding: 1px 10px;
  border-radius: 999px;
  font-size: 13px;
}

.chip-toggle[aria-pressed="true"] { background: var(--ink); color: var(--surface); }
.chip-toggle[aria-pressed="true"] .dim { color: inherit; opacity: 0.75; }
.chip-toggle .dim { color: var(--muted); }

.sys-find {
  flex: 1 1 140px;
  min-width: 0;
  max-width: 220px;
  padding: 3px 10px;
  background: var(--page);
  border: 1px solid var(--baseline);
  border-radius: 6px;
}

.sys-summary, .sys-help { flex-basis: 100%; margin: 0; }
.sys-help { font-size: 13px; }
.systems .dim { color: var(--ink-2); }

.sys-list {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  padding: 0 16px 16px;
}

/* a section waiting for a later stop is dimmed; so is each part that does not exist yet (--now is
   the chosen stop, set by systems.js; --core and --s are the section's and the part's stops) */
.sys-section { opacity: clamp(0.5, calc((var(--now, 99) - var(--core) + 1) * 1000), 1); }
.sys-section[hidden] { display: none; }

.sys-section h3 {
  position: sticky;
  top: 0;
  z-index: 1;
  display: flex;
  align-items: center;
  gap: 8px;
  margin: 0;
  padding: 12px 0 6px;
  background: var(--surface);
  font-size: 13px;
  font-weight: 600;
}

.sys-section h3 .dim { font-weight: 400; }
.sys-section ul { margin: 0; padding: 0; list-style: none; }

.sys-row {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto 3em minmax(100px, 36%);
  align-items: center;
  gap: 10px;
  width: 100%;
  padding: 3px 6px;
  background: none;
  border: 1px solid transparent;
  border-radius: 4px;
  text-align: left;
}

.sys-row:hover { background: var(--page); border-color: var(--border); }
.sys-row.on { border-color: var(--ink); }
.sys-name { overflow: hidden; white-space: nowrap; text-overflow: ellipsis; }
.sys-kind { color: var(--muted); font-size: 12px; }
.sys-n { color: var(--ink-2); font-size: 12px; font-variant-numeric: tabular-nums; text-align: right; }

.sys-bar {
  position: relative;
  display: flex;
  gap: 1px;
  height: 10px;
  border-radius: 2px;
  overflow: hidden;
}

/* halfway along the bar: the part there dates the system */
.sys-bar::after {
  content: "";
  position: absolute;
  top: 0;
  bottom: 0;
  left: 50%;
  width: 1px;
  background: var(--ink);
  opacity: 0.55;
}

.part { min-width: 2px; opacity: clamp(0.18, calc((var(--now, 99) - var(--s) + 1) * 1000), 1); }

.inspector {
  min-height: 0;
  overflow-y: auto;
  padding: 14px 16px 24px;
  background: var(--page);
  border-left: 1px solid var(--border);
}

.inspector h2 {
  margin: 0 0 2px;
  font-size: 18px;
  font-weight: 600;
}

.inspector h3 {
  margin: 18px 0 6px;
  color: var(--ink-2);
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
}

.inspector p { margin: 4px 0; }
.inspector .dim { color: var(--ink-2); }
.inspector .note { color: var(--ink-2); font-size: 13px; }

.inspector ul {
  margin: 0;
  padding: 0;
  list-style: none;
}

.inspector li { margin: 3px 0; }

.inspector .more { color: var(--muted); font-size: 13px; }

.link-button {
  padding: 0;
  background: none;
  border: none;
  border-radius: 0;
  color: inherit;
  text-align: left;
  text-decoration: underline;
  text-decoration-color: var(--baseline);
  text-underline-offset: 2px;
  cursor: pointer;
}

.link-button:hover { text-decoration-color: var(--ink-2); }

.inspector a { color: inherit; text-underline-offset: 2px; }

.sources summary {
  margin-top: 8px;
  color: var(--ink-2);
  cursor: pointer;
}

.sources li {
  margin: 8px 0;
  font-size: 13px;
  line-height: 1.35;
}

.zoom {
  display: inline-flex;
  gap: 4px;
}

.zoom button {
  min-width: 30px;
  padding: 3px 0;
}

.chips {
  display: flex;
  flex-wrap: wrap;
  gap: 4px 6px;
  margin: 6px 0;
}

.chip {
  padding: 1px 8px;
  border: 1px solid var(--baseline);
  border-radius: 999px;
  color: var(--ink-2);
  font-size: 12px;
}

.age {
  display: inline-flex;
  align-items: center;
  gap: 6px;
}

.swatch {
  display: inline-block;
  width: 12px;
  height: 12px;
  border-radius: 50%;
  flex: none;
}

.swatch.rna { border-radius: 2px; transform: rotate(45deg) scale(0.85); }

.equation {
  font-size: 13px;
  line-height: 1.35;
}

.bars { margin: 6px 0; }

.bar-row {
  display: grid;
  grid-template-columns: 150px 1fr 44px;
  align-items: center;
  gap: 8px;
  margin: 3px 0;
  font-size: 13px;
}

.bar-track {
  height: 10px;
  background: var(--grid);
  border-radius: 0 4px 4px 0;
  overflow: hidden;
}

.bar-fill { height: 100%; border-radius: 0 4px 4px 0; }
.bar-row .num { color: var(--ink-2); text-align: right; font-variant-numeric: tabular-nums; }

/* each flow's shares by era: one bar per flow, a segment per era */
.flows { margin: 6px 0 12px; }
.flow-row {
  display: grid;
  grid-template-columns: 170px 1fr;
  align-items: center;
  gap: 8px;
  margin: 3px 0;
  font-size: 13px;
}
.flow-bar { display: flex; height: 10px; background: var(--grid); border-radius: 2px; overflow: hidden; }
.flow-bar span { display: block; height: 100%; }
.flows figcaption { display: flex; flex-wrap: wrap; gap: 2px 12px; margin-top: 6px; font-size: 12px; color: var(--ink-2); }

/* ------------------------------------------------------------------ the axis */
/* the timeline row, then what the cell holds at the chosen stop */
.time {
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 8px 16px 2px;
  background: var(--surface);
  border-top: 1px solid var(--border);
}

.axis {
  padding: 4px 16px 12px;
  background: var(--surface);
}

/* "play" and "pause" take the same width, so the timeline beside them never shifts */
#play { min-width: 4.6em; }

/* the timeline: stops at their dates, years ago underneath */
.timeline {
  flex: 1;
  min-width: 0;
  height: 72px;
  border-radius: 6px;
  cursor: pointer;
  touch-action: none;
}

.timeline:focus-visible { outline: 2px solid var(--ink); outline-offset: 2px; }
.timeline svg { display: block; overflow: visible; }

.tl-line { stroke: var(--baseline); stroke-width: 2; }
.tl-break { stroke: var(--baseline); stroke-width: 2; stroke-dasharray: 2 4; }
.tl-tick { stroke: var(--baseline); stroke-width: 1; }
.tl-minor { stroke: var(--grid); stroke-width: 1; }
.tl-tick-label { fill: var(--muted); font: 11px var(--font); }
.tl-window { stroke-width: 3; stroke-dasharray: 5 4; opacity: 0.45; }
.tl-window.on { opacity: 1; }
.tl-ci { opacity: 0.35; }
.tl-ci.on { opacity: 0.9; }
.tl-stop { stroke: var(--surface); stroke-width: 1.5; }
.tl-stop.on { stroke: var(--ink); stroke-width: 2; }
.tl-label { fill: var(--ink-2); font: 11px var(--font); }
.tl-label.on { fill: var(--ink); font-weight: 600; }

/* a two-button switch */
.seg {
  display: inline-flex;
  border: 1px solid var(--baseline);
  border-radius: 6px;
  overflow: hidden;
}

.seg button {
  border: none;
  border-radius: 0;
  padding: 3px 10px;
}

.seg button + button { border-left: 1px solid var(--baseline); }

.seg button[aria-pressed="true"] {
  background: var(--ink);
  color: var(--surface);
}

/* The readout: the stop on one line, what the cell holds on the next, each with the full width to
   itself. Each line stacks every stop's version in one grid cell and shows only the current one
   (ui.js, showReadout), so it keeps the height of its longest version: playing the axis never
   changes the readout's height, and so never resizes or moves the cell. */
.readout {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: 3px;
  margin-top: 4px;
}

.readout p { margin: 0; }
.stop-text, .counts { display: grid; }
.stop-text > span, .counts > span { grid-area: 1 / 1; visibility: hidden; }
.stop-text > span.on, .counts > span.on { visibility: visible; }
.stop-text b { font-weight: 600; }
.counts { color: var(--ink-2); font-variant-numeric: tabular-nums; }

.legend {
  display: flex;
  flex-wrap: wrap;
  gap: 4px 16px;
  margin-top: 8px;
  color: var(--ink-2);
  font-size: 13px;
}

.legend .item {
  display: inline-flex;
  align-items: center;
  gap: 6px;
}

/* a kind of gene switched off in the header: still in the key, marked as not drawn */
.legend .item.off { opacity: 0.5; text-decoration: line-through; }

/* Phones, tablets and short windows: the page scrolls. The header, the cell and the timeline fill
   the first screen, measured in small-viewport units so a browser's toolbars never cover the
   timeline; the cell takes what the other two leave. What the cell holds, the legend and the
   inspector follow below. */
@media (max-width: 900px), (max-height: 560px) {
  body { display: block; height: auto; }
  .first-screen {
    display: flex;
    flex-direction: column;
    min-height: 100vh;
    min-height: 100svh;
  }
  .stage {
    flex: 1 1 auto;
    min-height: min(200px, 40vh);
    min-height: min(200px, 40svh);
  }
  .inspector { overflow: visible; border-left: none; border-top: 1px solid var(--border); }
  .bar-row { grid-template-columns: 110px 1fr 40px; }
  .flow-row { grid-template-columns: 130px 1fr; }
  /* the networks need room: their tools keep to one scrolling row, and the stage grows */
  .stage:has(.networks:not([hidden])) { min-height: min(520px, 75vh); min-height: min(520px, 75svh); }
  .net-tools { flex-wrap: nowrap; overflow-x: auto; padding: 8px 12px; }
  .net-tools > * { flex: none; }
  .net-kinds { flex-wrap: nowrap; }
}

/* phones: a compact header (the title and search share a row), and the timeline on a row of its own */
@media (max-width: 640px) {
  .bar { gap: 6px 10px; padding: 8px 12px; }
  .bar .sub { display: none; }
  .search { flex: 1 1 150px; min-width: 0; }
  .search input { width: 100%; max-width: none; }
  /* the docs link joins the title and the search on the first row; the controls wrap below */
  .controls { flex: 1 1 100%; margin-left: 0; gap: 6px 12px; order: 2; }
  .controls .long { display: none; }
  /* a select is as wide as its longest option; on a phone it shows the chosen one, clipped */
  .controls select { max-width: 8.5em; }
  .time { flex-wrap: wrap; gap: 4px 10px; padding: 6px 12px 2px; }
  .time .timeline { flex-basis: 100%; order: 3; }
  .time .seg { margin-left: auto; }
  .axis { padding: 4px 12px 12px; }
  /* a system's row: its name and size on one line, its bar under them */
  .sys-tools { padding: 8px 12px; }
  .sys-help, .sys-kind { display: none; }
  .sys-list { padding: 0 12px 12px; }
  .sys-row { grid-template-columns: minmax(0, 1fr) auto; row-gap: 4px; }
  .sys-bar { grid-column: 1 / -1; }
}
