/* ==========================================================================
   Algorithms & Data Structures — tokens.
   ==========================================================================

   The structural stylesheet is essay-kit's base.css, loaded first. Everything
   below is this site's identity and nothing else.

   Light mode is the warm off-white of a printed monograph; dark mode is a deep
   slate rather than a terminal black, because almost nothing here is code and a
   terminal palette would imply otherwise.

   The two principal roles carry the distinction the whole site rests on:
   **comparisons** and **cache misses**, the textbook count and the one the clock
   feels. They are independent quantities, several figures plot both on one pair
   of axes, and they are given two colours that stay separable in greyscale and
   under both common colour vision deficiencies. The accent set is Okabe–Ito,
   darkened where it carries text — a palette the sibling site
   colour-science-perception.com measures rather than assumes.
   ========================================================================== */

:root {
  --paper:   #f8f7f4;
  --paper-2: #f1efea;
  --paper-3: #e4e0d8;
  --ink:     #15202b;
  --ink-2:   #43505c;
  --ink-3:   #5b6874;
  --rule:    #d3ccc0;
  --rule-2:  #e9e5dd;
  --rule-3:  #e9e5dd;

  /* Semantic roles, contrast-safe against --paper. */
  --c-a: #0f5e7a;   /* a measured quantity, and the axes that carry one */
  --c-b: #9e4600;   /* the second series in any comparison */
  --c-c: #00695a;   /* a bound, a floor, a limit that cannot be crossed */
  --c-d: #7a5b00;   /* a fitted model laid over the measurements */
  --c-e: #8a4f86;   /* structure: trees, tables, the shape of a thing */
  --c-warn: #b3261e; /* a claim that failed its test */

  /* The two counts, kept apart deliberately — several figures plot both. */
  --q-compare: #0072b2;
  --q-cache:   #d55e00;

  /* Data series inside figures — canonical Okabe–Ito. Not for text. */
  --series-1: #0072b2;
  --series-2: #d55e00;
  --series-3: #009e73;
  --series-4: #e69f00;
  --series-5: #56b4e9;
  --series-6: #cc79a7;

  --fig-ink:   var(--ink);
  --fig-soft:  #6b7883;
  --fig-faint: #cec8bc;

  --tint: 15%;
  --tint-strong: 30%;

  --font-body: Georgia, "Nimbus Roman", "Liberation Serif", "Times New Roman", serif;
  --font-display: var(--font-body);
  --font-ui: ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
  --font-mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace;

  --measure: 34rem;
  --radius: 3px;
  --shadow: 0 1px 2px rgb(21 32 43 / 8%), 0 8px 24px -14px rgb(21 32 43 / 28%);

  color-scheme: light dark;
}

@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --paper:   #121a21;
    --paper-2: #18222b;
    --paper-3: #212e39;
    --ink:     #e8eef2;
    --ink-2:   #b4c0c9;
    --ink-3:   #9aa7b1;
    --rule:    #2e3d49;
    --rule-2:  #1c2831;
    --rule-3:  #1c2831;

    --c-a: #56b4e9;
    --c-b: #e69f00;
    --c-c: #3fcfa5;
    --c-d: #f0e442;
    --c-e: #cc79a7;
    --c-warn: #ff8a80;

    --fig-ink:   #e8eef2;
    --fig-soft:  #94a3ae;
    --fig-faint: #31404c;

    --tint: 22%;
    --tint-strong: 38%;
    --shadow: 0 1px 2px rgb(0 0 0 / 46%), 0 12px 34px -16px rgb(0 0 0 / 78%);
  }
}

:root[data-theme="dark"] {
  --paper:   #121a21;
  --paper-2: #18222b;
  --paper-3: #212e39;
  --ink:     #e8eef2;
  --ink-2:   #b4c0c9;
  --ink-3:   #9aa7b1;
  --rule:    #2e3d49;
  --rule-2:  #1c2831;
  --rule-3:  #1c2831;

  --c-a: #56b4e9;
  --c-b: #e69f00;
  --c-c: #3fcfa5;
  --c-d: #f0e442;
  --c-e: #cc79a7;
  --c-warn: #ff8a80;

  --fig-ink:   #e8eef2;
  --fig-soft:  #94a3ae;
  --fig-faint: #31404c;

  --tint: 22%;
  --tint-strong: 38%;
  --shadow: 0 1px 2px rgb(0 0 0 / 46%), 0 12px 34px -16px rgb(0 0 0 / 78%);
}

/* --- site-specific roles -------------------------------------------------- */

/* The two counts. Everything comparing them uses exactly these. */
.fig-svg .q-compare { stroke: var(--q-compare); stroke-width: 2.1; fill: none; }
.fig-svg .q-cache   { stroke: var(--q-cache);   stroke-width: 2.1; fill: none; }
.fig-svg .q-compare-fill { fill: color-mix(in oklab, var(--q-compare) var(--tint), var(--paper-2)); stroke: none; }
.fig-svg .q-cache-fill   { fill: color-mix(in oklab, var(--q-cache) var(--tint), var(--paper-2)); stroke: none; }
.fig-svg .dot-compare { fill: var(--q-compare); stroke: none; }
.fig-svg .dot-cache   { fill: var(--q-cache); stroke: none; }

/* A measurement, and the model fitted to it. The measurement is drawn as
   points because that is what it is; the fit is a line, and it is dashed so
   nobody mistakes it for data. */
.fig-svg .measured { fill: var(--c-a); stroke: none; }
.fig-svg .fitted   { stroke: var(--c-d); stroke-width: 1.8; fill: none; stroke-dasharray: 6 4; }
.fig-svg .measured-line { stroke: var(--c-a); stroke-width: 2.1; fill: none; }

/* A bound: the floor nothing can get under. Drawn heavier than any data. */
.fig-svg .bound { stroke: var(--c-c); stroke-width: 2.6; fill: none; }
.fig-svg .bound-fill { fill: color-mix(in oklab, var(--c-c) 12%, var(--paper-2)); stroke: none; }
.fig-svg text.bound { fill: var(--c-c); stroke: none; }

/* A claim that failed its test. */
.fig-svg .failed { stroke: var(--c-warn); stroke-width: 2; fill: none; }
.fig-svg .failed-fill { fill: color-mix(in oklab, var(--c-warn) 18%, var(--paper-2)); stroke: var(--c-warn); stroke-width: 1.2; }
.fig-svg text.failed { fill: var(--c-warn); stroke: none; }
.fig-svg .passed-fill { fill: color-mix(in oklab, var(--c-c) 16%, var(--paper-2)); stroke: var(--c-c); stroke-width: 1.2; }

/* Array cells — the unit of every trace figure. */
/* Tints, not solids. The trace figures print a value inside each cell, and
   dark ink on a saturated fill measured 1.92:1 against WCAG AA's 4.5 — solid
   --c-b and --c-e are text-safe as foregrounds and not as backgrounds. Keeping
   every cell a tint of the paper keeps the label legible in both themes. */
.fig-svg .cell        { fill: color-mix(in oklab, var(--c-a) 24%, var(--paper-2)); stroke: none; }
.fig-svg .cell-active { fill: color-mix(in oklab, var(--c-b) 34%, var(--paper-2)); stroke: var(--c-b); stroke-width: 1.2; }
.fig-svg .cell-done   { fill: color-mix(in oklab, var(--c-c) 42%, var(--paper-2)); stroke: none; }
.fig-svg .cell-pivot  { fill: color-mix(in oklab, var(--c-e) 34%, var(--paper-2)); stroke: var(--c-e); stroke-width: 1.4; }
.fig-svg .cell-read   { fill: color-mix(in oklab, var(--q-cache) 40%, var(--paper-2)); stroke: none; }

/* Structures: trees, tables, the shape of a thing. */
.fig-svg .node   { fill: color-mix(in oklab, var(--c-e) 26%, var(--paper-2)); stroke: var(--c-e); stroke-width: 1.3; }
.fig-svg .edge   { stroke: var(--c-e); stroke-width: 1.4; fill: none; }
.fig-svg .slot   { fill: var(--paper-2); stroke: var(--rule); stroke-width: 1; }
.fig-svg .slot-full { fill: color-mix(in oklab, var(--c-e) 32%, var(--paper-2)); stroke: var(--c-e); stroke-width: 1; }

/* Axes and general furniture. */
.fig-svg .axis   { stroke: var(--fig-soft); stroke-width: 1.4; fill: none; }
.fig-svg .grid   { stroke: var(--fig-faint); stroke-width: 0.9; }
.fig-svg .soft   { stroke: var(--fig-soft); stroke-width: 1.2; fill: none; }
.fig-svg .faint  { stroke: var(--fig-faint); stroke-width: 1; fill: none; }
.fig-svg .dot-a  { fill: var(--c-a); stroke: none; }
.fig-svg .dot-b  { fill: var(--c-b); stroke: none; }
.fig-svg .dot-c  { fill: var(--c-c); stroke: none; }
.fig-svg .dot-d  { fill: var(--c-d); stroke: none; }
.fig-svg .dot-warn { fill: var(--c-warn); stroke: none; }
.fig-svg .fill-a { fill: color-mix(in oklab, var(--c-a) var(--tint), var(--paper-2)); }
.fig-svg .fill-b { fill: color-mix(in oklab, var(--c-b) var(--tint), var(--paper-2)); }
.fig-svg .fill-c { fill: color-mix(in oklab, var(--c-c) var(--tint), var(--paper-2)); }
.fig-svg .fill-d { fill: color-mix(in oklab, var(--c-d) var(--tint), var(--paper-2)); }
.fig-svg text.mono { font-family: var(--font-mono); }

/* A label over a filled region gets a real plate, not a stroke halo — svg_check
   samples the fill beneath the glyph and a halo is invisible to it. */
.fig-svg .plate { fill: var(--paper); stroke: none; opacity: 0.92; }

/* A diagram <text> must not inherit the root stroke, or every label is drawn
   twice and reads as bold mud. Fleet-wide gotcha, cheap to state. */
.fig-svg text { stroke: none; }

/* A rule under section headings. */
.section-head::after { border-top-style: solid; }

/* --- dragging a parameter -------------------------------------------------
   The natural draggable axis here is n, or a threshold: move it and the counts
   change. Every frame is produced at build time by the same generator, so every
   frame passed the same assertions.

   Page weight is controllable because a frame here is a handful of numbers and
   a few dozen rectangles, not a mesh. The molecular site's 7.7 MB lesson does
   not apply — but any new draggable figure must still be costed before drag is
   added to it. */
.drag-row { margin: 0.6rem 0 0; display: grid; gap: 0.35rem; }
.drag-slider { width: min(28rem, 100%); accent-color: var(--c-a); cursor: ew-resize; }
.drag-slider:focus-visible { outline: 2px solid var(--c-a); outline-offset: 3px; }
.drag-readout {
  margin: 0; font: 0.8rem/1.4 var(--font-ui); color: var(--ink-2);
  font-variant-numeric: tabular-nums;
}
.drag-note { margin: 0; font: 0.74rem/1.4 var(--font-ui); color: var(--ink-3); }
