/* ==========================================================================
   Machine Kinematics — tokens.
   ==========================================================================

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

   The palette is designed from a functional constraint rather than a mood, and
   the constraint is that a mechanism figure has to keep four things apart at a
   glance: which link is the INPUT, which is the COUPLER carrying the motion,
   which is the OUTPUT, and what is FRAME. Those four are the reader's whole
   orientation, they appear in almost every figure, and a reader who loses track
   of which bar is driven has lost the argument.

   So they get four roles that stay distinguishable in greyscale and under both
   common colour vision deficiencies, and a fifth — the traced path — that must
   read as data rather than as structure.

   The register is machine-shop rather than laboratory: warm grey paper, oiled
   steel, and a single hot accent for the thing being driven.
   ========================================================================== */

:root {
  --paper:   #f6f4f0;
  --paper-2: #efece6;
  --paper-3: #e2ded5;
  --ink:     #1c2024;
  --ink-2:   #4a5158;
  --ink-3:   #646c74;
  --rule:    #cfc9be;
  --rule-2:  #e6e2da;
  --rule-3:  #e6e2da;

  /* Semantic roles, contrast-safe against --paper. */
  --c-a: #1c5f78;   /* a measured quantity, and the axes that carry one */
  --c-b: #a8480d;   /* the driven thing: the crank, the input */
  --c-c: #16695a;   /* a bound, a limit, a thing that cannot be crossed */
  --c-d: #7d5c07;   /* a prediction laid over a measurement */
  --c-e: #75508c;   /* structure: the frame, the ground */
  --c-warn: #ad2318; /* a claim that failed, or a configuration that cannot exist */

  /* The four things a mechanism figure must keep apart. */
  --l-input:   #a8480d;   /* the driven link */
  --l-coupler: #1c5f78;   /* the link that carries the motion across */
  --l-output:  #16695a;   /* the driven output */
  --l-frame:   #6b6459;   /* ground */
  --l-trace:   #75508c;   /* the path a point traces */

  /* Data series inside plots — Okabe–Ito, which the sibling colour site
     measures rather than assumes. 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:  #6f7780;
  --fig-faint: #cbc5b9;

  --tint: 16%;
  --tint-strong: 32%;

  --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(28 32 36 / 8%), 0 8px 24px -14px rgb(28 32 36 / 30%);

  color-scheme: light dark;
}

@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --paper:   #16191c;
    --paper-2: #1c2024;
    --paper-3: #262b30;
    --ink:     #e9ecef;
    --ink-2:   #b5bcc3;
    --ink-3:   #9aa2aa;
    --rule:    #333a41;
    --rule-2:  #20252a;
    --rule-3:  #20252a;

    --c-a: #56b4e9;
    --c-b: #ef8b3c;
    --c-c: #3fcfa5;
    --c-d: #edd94e;
    --c-e: #c193d8;
    --c-warn: #ff8a80;

    --l-input:   #ef8b3c;
    --l-coupler: #56b4e9;
    --l-output:  #3fcfa5;
    --l-frame:   #8d8578;
    --l-trace:   #c193d8;

    --fig-ink:   #e9ecef;
    --fig-soft:  #97a0a8;
    --fig-faint: #333a41;

    --tint: 24%;
    --tint-strong: 40%;
    --shadow: 0 1px 2px rgb(0 0 0 / 48%), 0 12px 34px -16px rgb(0 0 0 / 80%);
  }
}

:root[data-theme="dark"] {
  --paper:   #16191c;
  --paper-2: #1c2024;
  --paper-3: #262b30;
  --ink:     #e9ecef;
  --ink-2:   #b5bcc3;
  --ink-3:   #9aa2aa;
  --rule:    #333a41;
  --rule-2:  #20252a;
  --rule-3:  #20252a;

  --c-a: #56b4e9;
  --c-b: #ef8b3c;
  --c-c: #3fcfa5;
  --c-d: #edd94e;
  --c-e: #c193d8;
  --c-warn: #ff8a80;

  --l-input:   #ef8b3c;
  --l-coupler: #56b4e9;
  --l-output:  #3fcfa5;
  --l-frame:   #8d8578;
  --l-trace:   #c193d8;

  --fig-ink:   #e9ecef;
  --fig-soft:  #97a0a8;
  --fig-faint: #333a41;

  --tint: 24%;
  --tint-strong: 40%;
  --shadow: 0 1px 2px rgb(0 0 0 / 48%), 0 12px 34px -16px rgb(0 0 0 / 80%);
}

/* --- the mechanism itself -------------------------------------------------
   A link is drawn as a stroked bar with a lighter core, which reads as a
   machined part rather than as a line and keeps the four roles legible even
   when two links cross. */
.fig-svg .link        { stroke: var(--l-coupler); fill: none; stroke-linecap: round; }
.fig-svg .link-input  { stroke: var(--l-input); }
.fig-svg .link-coupler{ stroke: var(--l-coupler); }
.fig-svg .link-output { stroke: var(--l-output); }
.fig-svg .link-frame  { stroke: var(--l-frame); }
.fig-svg .link-core   { stroke: color-mix(in oklab, var(--paper) 72%, transparent); fill: none; stroke-linecap: round; }

.fig-svg .pin        { fill: var(--paper); stroke: var(--ink); stroke-width: 1.6; }
.fig-svg .pin-fixed  { fill: var(--ink); stroke: none; }
.fig-svg .ground-fill{ fill: color-mix(in oklab, var(--l-frame) var(--tint), var(--paper-2)); stroke: var(--l-frame); stroke-width: 1.2; }
.fig-svg .ground-line{ stroke: var(--l-frame); stroke-width: 1.8; }
.fig-svg .hatch      { stroke: var(--l-frame); stroke-width: 1.1; }
.fig-svg .slider     { fill: color-mix(in oklab, var(--l-output) var(--tint-strong), var(--paper-2)); stroke: var(--l-output); stroke-width: 1.4; }
.fig-svg .ghost      { stroke: var(--fig-faint); stroke-width: 2.4; fill: none; stroke-linecap: round; }

/* The path a point traces. Data, not structure. */
.fig-svg .trace      { stroke: var(--l-trace); stroke-width: 2; fill: none; }
.fig-svg .trace-soft { stroke: color-mix(in oklab, var(--l-trace) 45%, var(--paper-2)); stroke-width: 1.6; fill: none; }
.fig-svg .dot-trace  { fill: var(--l-trace); stroke: none; }

/* A limit nothing crosses; and a claim that failed. */
.fig-svg .bound      { stroke: var(--c-c); stroke-width: 2.4; 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; }
.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; }

/* Gear teeth and the line of action. */
.fig-svg .tooth      { fill: color-mix(in oklab, var(--c-a) 22%, var(--paper-2)); stroke: var(--c-a); stroke-width: 1.2; }
.fig-svg .tooth-2    { fill: color-mix(in oklab, var(--c-c) 22%, var(--paper-2)); stroke: var(--c-c); stroke-width: 1.2; }
.fig-svg .pitch-circle { stroke: var(--c-d); stroke-width: 1.4; fill: none; stroke-dasharray: 7 5; }
.fig-svg .base-circle  { stroke: var(--fig-soft); stroke-width: 1.1; fill: none; stroke-dasharray: 3 4; }
.fig-svg .action-line  { stroke: var(--c-b); stroke-width: 2; fill: none; }

/* 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 .measured      { fill: var(--c-a); stroke: none; }
.fig-svg .measured-line { stroke: var(--c-a); stroke-width: 2.1; fill: none; }
.fig-svg .fitted        { stroke: var(--c-d); stroke-width: 1.8; fill: none; stroke-dasharray: 6 4; }
.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 .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; }

.section-head::after { border-top-style: solid; }

/* --- turning the crank ----------------------------------------------------
   The natural draggable parameter here is the input angle, and it is not a
   decoration: a mechanism is a relation between an input and an output, so
   moving the input IS the explanation.

   Every frame is produced at build time by the same generator that drew the
   static figure, which means every assertion the generator makes — loop closure
   above all — has been checked at every position the reader can reach. A
   configuration the mechanism cannot assemble cannot appear on the slider. */
.drag-row { margin: 0.6rem 0 0; display: grid; gap: 0.35rem; }
.drag-slider { width: min(28rem, 100%); accent-color: var(--c-b); cursor: ew-resize; }
.drag-slider:focus-visible { outline: 2px solid var(--c-b); 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); }
