/* Chapter 1 · F1 engine-pipeline, the engine simulation (figures/engine-pipeline.js). Paper frame (fx.css), course tokens
   (javascript.css). Your code amber (a night code panel, the running line lit in amber); the engine purple (a frame: the
   interpreter, its call counter, the optimising compiler, machine code on night glass); the processor neutral, lit while
   something runs on it. One column on a phone (steps, code, engine, text, controls); the code beside the engine from
   780 px of figure. Nothing moves size between steps: the bytecode, the machine code and the counter keep their room from
   the start; the text panel's height is set by the script (its tallest text); Try it keeps its room beside or under the
   controls and shows at step 5 (on a phone it replaces Play and Next on the same row). States: flags on
   .es-board (.f-*), data-s="act|done" on the interpreter and the compiler. Every change is a transition, so a landed
   step snaps (.es--snap). */

.es code { font-family: var(--font-mono); font-size: inherit; background: none; border: 0; padding: 0; border-radius: 0; color: inherit; font-variant-ligatures: none; }
/* (0,1,0) after javascript.css: beats the page's `.article :where(p)` margins and list paddings. */
.es-wrap :where(p, ol, li) { margin: 0; }
.es-wrap :where(ol) { padding: 0; list-style: none; }
.es-wrap :where(li) { font-size: inherit; line-height: inherit; }
.es > .fx__kicker { margin-bottom: 12px; }

/* ---------- The step strip: five numbered steps, the current one marked ---------- */
.es-steps { display: grid; grid-template-columns: repeat(5, minmax(0, 1fr)); gap: 6px; margin: 0 0 18px; }
.es-step {
  display: flex; align-items: center; gap: 8px; width: 100%; min-height: 44px; padding: 6px 10px 6px 7px;
  border-radius: 12px; border: 1px solid var(--rule); background: color-mix(in srgb, var(--surface) 70%, transparent);
  font: 600 .86rem/1.2 var(--font-body); color: var(--ink-2); text-align: left; cursor: pointer; -webkit-tap-highlight-color: transparent;
  transition: background-color var(--fx-t-micro) ease, border-color var(--fx-t-micro) ease, color var(--fx-t-micro) ease;
}
.es-step:hover { border-color: var(--accent); color: var(--ink); }
.es-step:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.es-step__n {
  flex: none; display: inline-grid; place-items: center; width: 26px; height: 26px; border-radius: 50%;
  border: 1.5px solid var(--rule-strong); background: var(--surface); font: 700 .74rem/1 var(--font-mono); color: var(--ink-3);
  transition: background-color var(--fx-t-short) ease, border-color var(--fx-t-short) ease, color var(--fx-t-short) ease;
}
.es-step__t { min-width: 0; hyphens: manual; }
.es-step.is-done .es-step__n { border-color: var(--engine); color: var(--engine); }
.es-step[aria-current="step"] { border-color: color-mix(in srgb, var(--engine) 45%, transparent); background: var(--engine-soft); color: var(--ink); }
.es-step[aria-current="step"] .es-step__n { background: var(--engine); border-color: var(--engine); color: var(--surface); }

/* ---------- The board: code, then the engine and the processor ---------- */
.es-board { position: relative; display: grid; grid-template-columns: minmax(0, 1fr); gap: 34px; }
.es-wires { position: absolute; left: 0; top: 0; z-index: 2; overflow: visible; pointer-events: none; }

/* Your code: night glass in both themes, as the page's code blocks. The running line: an amber band. */
.es-code {
  position: relative; z-index: 1; min-width: 0; align-self: start; overflow: hidden; border-radius: 14px;
  background: var(--code-bg); border: 1px solid var(--code-rule); box-shadow: inset 0 1px 0 rgba(255, 255, 255, .05), 0 18px 36px -26px rgba(12, 14, 30, .75);
}
.es-code__h {
  padding: 8px 14px; border-bottom: 1px solid var(--code-rule); background: rgba(255, 255, 255, .025);
  font: 700 .68rem/1.3 var(--font-body); letter-spacing: .1em; text-transform: uppercase; color: #fbbf24;
}
.es-code__h code { text-transform: none; letter-spacing: .02em; color: var(--code-dim); }
.es-pre {
  position: relative; margin: 0; padding: 10px 0 12px; overflow: hidden; background: none; border: 0;
  font: 500 .8rem/1.62 var(--font-mono); color: var(--code-ink); white-space: pre; tab-size: 2; font-variant-ligatures: none;
}
.es-pre code { white-space: inherit; }
.es-ln {
  display: block; padding: 0 14px 0 11px; border-left: 3px solid transparent;
  transition: background-color var(--fx-t-short) ease, border-color var(--fx-t-short) ease, opacity var(--fx-t-short) ease;
}
/* A comment line wraps under itself, never under the code. */
.es-ln.cm { white-space: pre-wrap; color: var(--code-dim); padding-left: calc(11px + 3ch); text-indent: -3ch; }
.es-pre .kw { color: #c4b5fd; }
.es-arg { color: #fbbf24; }
.es-arg--num { color: #7dd3fc; }
.es-pre.has-on .es-ln:not(.is-on) { opacity: .6; }
.es-pre.has-on .es-ln.cm:not(.is-on) { opacity: 1; }   /* comments are dim by colour already: dimming them again fails AA */
.es-ln.is-on { background: rgba(251, 191, 36, .13); border-left-color: #fbbf24; }
.es-ln.cm.is-on { color: #d6d9e4; }
/* 1 · the engine reads the file: a light band runs down the code once. */
.es-pre::after {
  content: ""; position: absolute; left: 0; right: 0; top: -2.6em; height: 2.6em; pointer-events: none; opacity: 0;
  background: linear-gradient(180deg, transparent, rgba(192, 132, 252, .22) 45%, rgba(192, 132, 252, .3) 55%, transparent);
}
.f-scan .es-pre::after { animation: es-scan 1.25s var(--fx-ease-io) both; }
@keyframes es-scan { 0% { top: -2.6em; opacity: 1; } 90% { opacity: 1; } 100% { top: 100%; opacity: 0; } }

/* The system: the engine frame, then the processor under it. */
.es-sys { position: relative; min-width: 0; display: grid; gap: 40px; }
.es-eng {
  position: relative; display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 28px 34px; align-items: center;
  padding: 24px 14px 14px; border-radius: 18px; border: 1.5px solid color-mix(in srgb, var(--engine) 26%, transparent);
  background: color-mix(in srgb, var(--engine) 3.5%, transparent);
  transition: border-color var(--fx-t-short) ease, background-color var(--fx-t-short) ease;
}
.f-eng .es-eng { border-color: color-mix(in srgb, var(--engine) 55%, transparent); background: color-mix(in srgb, var(--engine) 6%, transparent); }
.es-eng__h {
  position: absolute; top: -11px; right: 14px; padding: 1px 9px; border-radius: 999px; border: 1.5px solid color-mix(in srgb, var(--engine) 40%, transparent);
  background: var(--surface); font: 700 .66rem/1.45 var(--font-mono); letter-spacing: .14em; text-transform: uppercase; color: var(--engine); white-space: nowrap;
}

/* The interpreter and the compiler: idle (rule), reached (engine border), working (engine tint and a ring). */
.es-box {
  position: relative; z-index: 1; min-width: 0; display: flex; flex-direction: column; gap: 8px; padding: 10px 12px 12px;
  border-radius: 14px; border: 1.5px solid var(--rule-strong); background: var(--surface);
  transition: border-color var(--fx-t-short) ease, background-color var(--fx-t-short) ease, box-shadow var(--fx-t-short) ease;
}
.es-box__h { font: 650 .92rem/1.25 var(--font-body); color: var(--ink-2); hyphens: manual; overflow-wrap: normal; }
.es-box[data-s] { border-color: var(--engine); }
.es-box[data-s] .es-box__h { color: var(--ink); }
.es-box[data-s="act"] { background: var(--engine-soft); box-shadow: 0 0 0 4px color-mix(in srgb, var(--engine) 15%, transparent); }
.es-int { grid-column: 1; grid-row: 1 / 3; align-self: stretch; }
.es-opt { grid-column: 2; grid-row: 1; }

/* Step 1 · one small "bytecode" chip drops into the interpreter (the real instructions of add() in its title). */
.es-bc { display: flex; opacity: 0; transform: translateY(-6px); transition: opacity var(--fx-t-short) ease, transform var(--fx-t-short) var(--fx-ease-out); }
.f-bc .es-bc { opacity: 1; transform: none; }
.es-bc code {
  padding: 1px 7px; border-radius: 6px; border: 1px solid color-mix(in srgb, var(--engine) 38%, transparent);
  background: var(--surface); font: 600 .72rem/1.5 var(--font-mono); color: var(--engine); white-space: nowrap;
}

/* The call counter: secondary ink until the loop runs (colour, not opacity: it stays AA); a bar to 1,000; a flame after
   the number when add() is hot. */
.es-count { margin-top: auto; display: grid; gap: 5px; padding-top: 9px; border-top: 1px dashed var(--rule-strong); }
.es-count__k { font: 600 .78rem/1.3 var(--font-body); color: var(--ink-3); transition: color var(--fx-t-short) ease; }
.es-count__k code { font-weight: 700; color: inherit; }
.f-count .es-count__k { color: var(--ink-2); }
.f-count .es-count__k code { color: var(--you); }
.es-count__v { display: flex; align-items: center; gap: 6px; }
.es-bar { flex: 1 1 auto; min-width: 24px; height: 7px; border-radius: 4px; background: var(--rule); overflow: hidden; }
.es-bar i { display: block; width: 100%; height: 100%; border-radius: inherit; background: var(--engine); transform-origin: 0 50%; transform: scaleX(0); }
.f-hot .es-bar i { background: linear-gradient(90deg, var(--engine), var(--you)); }
.es-num { flex: none; min-width: 4.4ch; text-align: right; font: 700 .9rem/1 var(--font-body); font-variant-numeric: tabular-nums; color: var(--ink-3); }
.f-count .es-num { color: var(--ink); }
.es-hot { flex: none; display: inline-flex; color: var(--you); opacity: 0; transform: scale(.6); transition: opacity var(--fx-t-short) ease, transform var(--fx-t-short) var(--fx-ease-out); }
.es-hot svg { width: 15px; height: 15px; }
.f-hot .es-hot { opacity: 1; transform: none; }

/* Machine code: a dashed place until step 4 (it does not exist yet); night glass with its bet; 5 · the bet crossed, the
   block thrown away (dashed again, struck); Try it with 7 · the bet ticked. */
.es-mc {
  grid-column: 2; grid-row: 2; position: relative; z-index: 1; min-width: 0; display: flex; flex-direction: column; gap: 6px;
  padding: 9px 12px 10px; border-radius: 12px; border: 1.5px dashed var(--rule-strong); background: transparent; color: var(--ink-3);
  transition: background-color var(--fx-t-short) ease, border-color var(--fx-t-short) ease, color var(--fx-t-short) ease, transform var(--fx-t-short) var(--fx-ease-out);
}
.es-mc__h { font: 700 .82rem/1.3 var(--font-mono); }
.es-mc__row { display: flex; }
/* Under the bet, one place: the '7' that reached the machine code, then (5) "thrown away" in its stead. */
.es-mc__out { display: grid; justify-items: start; align-items: center; }
.es-mc__out > * { grid-area: 1 / 1; }
.es-bet {
  position: relative; padding: 1px 9px; border-radius: 10px; border: 1px solid rgba(255, 255, 255, .3);
  font: 600 .72rem/1.4 var(--font-body); color: #c3c3d1; text-decoration-thickness: 2px; visibility: hidden;
}
.es code.es-got {
  padding: 1px 7px; border-radius: 6px; border: 1.3px solid #fbbf24; font: 700 .74rem/1.35 var(--font-mono) !important; color: #fbbf24 !important;
  visibility: hidden;
}
.es-thrown { font: italic 600 .78rem/1.3 var(--font-body); color: var(--ink-2); visibility: hidden; }
.f-mc .es-mc { border: 1.5px solid var(--code-rule); background: var(--code-bg); color: var(--night-ink); }
.f-mc .es-bet { visibility: visible; }
.f-x .es-bet { text-decoration-line: line-through; }
.f-x .es-bet::after, .f-ok .es-bet::after {
  content: "\2715"; position: absolute; top: -8px; right: -8px; display: grid; place-items: center; width: 17px; height: 17px;
  border-radius: 50%; border: 1.5px solid var(--control); background: var(--surface); font: 700 .6rem/1 var(--font-body); color: var(--ink-2);
}
.f-x code.es-got, .f-ok code.es-got { visibility: visible; }
.f-ok .es-bet { border-color: #5fd3a0; color: #d9f7ea; }
.f-ok .es-bet::after { content: "\2713"; border-color: var(--ok); color: var(--ok); }
.f-ok code.es-got { border-color: #7dd3fc; color: #7dd3fc !important; }
.f-thrown .es-mc { background: transparent; border: 1.5px dashed var(--control); color: var(--ink-3); }
.f-thrown .es-mc__h { text-decoration: line-through; }
.f-thrown .es-bet { color: var(--ink-3); border-color: var(--control); }
.f-thrown code.es-got { visibility: hidden; }
.f-thrown .es-thrown { visibility: visible; }

/* The processor: neutral; lit while the interpreter or the machine code runs on it. */
.es-cpu {
  position: relative; z-index: 1; display: flex; align-items: center; justify-content: center; gap: 8px; min-height: 46px; padding: 8px 14px;
  border-radius: 12px; border: 1.5px solid var(--rule-strong); background: var(--surface); font: 600 .9rem/1.2 var(--font-body); color: var(--ink-2);
  transition: border-color var(--fx-t-short) ease, color var(--fx-t-short) ease, box-shadow var(--fx-t-short) ease;
}
.es-cpu svg { width: 20px; height: 20px; flex: none; }
.f-cpu .es-cpu { border-color: var(--ink); color: var(--ink); box-shadow: 0 0 0 4px color-mix(in srgb, var(--engine) 14%, transparent); }

/* Wires: a dashed path before the step, drawn in engine purple when it happens (the code's arrow in amber). The fast lane
   is thick; the interpreter's wire dims while the machine code runs. */
.es-w { fill: none; stroke-width: 2; stroke-linejoin: round; }
.es-w--base { stroke: var(--rule-strong); stroke-dasharray: 2 5; stroke-linecap: round; transition: opacity var(--fx-t-short) ease; }
.es-h--base { fill: var(--rule-strong); transition: opacity var(--fx-t-short) ease; }
.es-board:not(.f-mc) :is([data-w="mk"], [data-h="mk"], [data-w="fast"], [data-h="fast"]):is(.es-w--base, .es-h--base) { opacity: 0; }
.es-w--lit { stroke: var(--engine); stroke-linecap: butt; stroke-dasharray: 1 1; stroke-dashoffset: calc(1 - var(--on, 0)); transition: stroke-dashoffset .5s var(--fx-ease-io), opacity var(--fx-t-short) ease; }
.es-h--lit { fill: var(--engine); opacity: var(--on, 0); transition: opacity .2s ease calc(var(--on, 0) * .35s); }
.es-w--lit[data-w="in"] { stroke: var(--you); } .es-h--lit[data-h="in"] { fill: var(--you); }
.es-w--lit[data-w="fast"] { stroke-width: 4; }
.es-w--lit[data-w="back"] { stroke-width: 2.4; }
.f-w-in :is([data-w="in"], [data-h="in"]), .f-w-run :is([data-w="run"], [data-h="run"]), .f-w-hot :is([data-w="hot"], [data-h="hot"]),
.f-w-mk :is([data-w="mk"], [data-h="mk"]), .f-w-fast :is([data-w="fast"], [data-h="fast"]), .f-w-back :is([data-w="back"], [data-h="back"]) { --on: 1; }
.f-run-dim :is(.es-w--lit[data-w="run"], .es-h--lit[data-h="run"]) { opacity: .28; }
/* Pulses: one at a time down the interpreter's wire; quicker ones down the fast lane. Only while the figure is on screen. */
.es-pulse { fill: none; stroke: var(--engine); stroke-width: 5; stroke-linecap: round; stroke-dasharray: .14 .86; stroke-dashoffset: .14; opacity: 0; }
.es-pulse--fast { stroke-width: 8; stroke-dasharray: .2 .8; stroke-dashoffset: .2; }
.is-seen .f-run-go .es-pulse--run { animation: es-pulse 1.15s cubic-bezier(.4, 0, .6, 1) infinite; }
.is-seen .f-fast-go .es-pulse--fast { animation: es-pulse-f .55s linear .45s infinite; }
@keyframes es-pulse { 0% { stroke-dashoffset: .14; opacity: 1; } 100% { stroke-dashoffset: -.86; opacity: 1; } }
@keyframes es-pulse-f { 0% { stroke-dashoffset: .2; opacity: 1; } 100% { stroke-dashoffset: -.8; opacity: 1; } }

/* "fast lane", beside its wire (placed by the script). */
.es-flab {
  position: absolute; z-index: 3; left: 0; top: 0; transform: translate(-100%, -50%); padding: 1px 9px; border-radius: 999px;
  border: 1px solid color-mix(in srgb, var(--engine) 55%, transparent); background: var(--surface);
  font: 600 .72rem/1.35 var(--font-body); color: var(--engine); white-space: nowrap; opacity: 0; transition: opacity var(--fx-t-short) ease;
}
.f-w-fast .es-flab { opacity: 1; }

/* Travelling tokens (add(), '7'): only the Web Animations move them. */
.es-tok {
  position: absolute; z-index: 4; left: 0; top: 0; padding: 2px 8px; border-radius: 999px; pointer-events: none; opacity: 0;
  border: 1.5px solid var(--you); background: color-mix(in srgb, var(--you) 14%, var(--surface)); color: var(--you);
  font: 700 .74rem/1.3 var(--font-mono); white-space: nowrap; font-variant-ligatures: none;
  box-shadow: 0 6px 14px -6px color-mix(in srgb, var(--you) 60%, transparent);
}

/* ---------- The text: one panel of fixed height (set by the script) ---------- */
.es-panel {
  position: relative; margin-top: 24px; padding: 14px 18px 16px; overflow: hidden; border-radius: 16px;
  border: 1px solid var(--rule); background: var(--surface); box-shadow: var(--shadow-sm);
}
.es-panel__k { font: 700 .68rem/1.3 var(--font-mono); letter-spacing: .12em; text-transform: uppercase; color: var(--engine); }
.es-panel__t { margin-top: 5px; font: 600 1.2rem/1.3 var(--font-display); color: var(--ink); text-wrap: balance; }
.es-panel__t code { font-family: var(--font-mono); font-size: .86em; font-weight: 700; }
.es-panel__p { margin-top: 6px; max-width: 56ch; font: 400 1rem/1.55 var(--font-body); color: var(--ink-2); text-wrap: pretty; }
.es-panel__p code { font-size: .92em; font-weight: 600; color: var(--ink); }
.es-timer { position: absolute; left: 0; right: 0; bottom: 0; height: 3px; opacity: 0; transition: opacity var(--fx-t-short) ease; }
.es-timer i { display: block; height: 100%; background: var(--engine); transform-origin: 0 50%; transform: scaleX(0); }
.is-timing .es-timer { opacity: .75; }
.fx--still .es-timer { visibility: hidden; }

/* ---------- Controls; Try it at step 5 (beside the controls when it fits, else under them). It keeps its room at every
   step, hidden, so nothing moves when it appears; on a phone it takes the place of Play and Next instead. ---------- */
.es-foot { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 12px 18px; margin-top: 14px; }
.es-ctl { display: flex; gap: 8px; }
.es-play { min-width: 7.4em; background: var(--ink); border-color: var(--ink); color: var(--bg); }
.es-play:hover { border-color: var(--accent); }
.es-play__i { display: inline-flex; }
.es-play__i svg { width: 16px; height: 16px; }
.es-b--solo { padding-inline: 13px; }
.es-b--solo .es-b__t {
  position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0; overflow: hidden; clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap; border: 0;
}
.es-b[aria-disabled="true"] { opacity: .4; cursor: default; }
.es-b[aria-disabled="true"]:hover { border-color: var(--control); }
.es-b[aria-disabled="true"]:active { transform: none; }
.es-try { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; visibility: hidden; }
.es[data-step="5"] .es-try { visibility: visible; animation: fx-in var(--fx-t-short) var(--fx-ease-out) .15s both; }
.es-try__k { font: 600 .86rem/1.3 var(--font-body); color: var(--ink-2); }
.es-try .fx-btn { gap: 7px; padding: 8px 13px; }
.es-try .fx-btn code { font: 700 .92rem/1 var(--font-mono); }
.es-try small { font: 500 .76rem/1.2 var(--font-body); color: var(--ink-3); }
.es-try .fx-btn[aria-pressed="true"] small { color: color-mix(in srgb, var(--bg) 75%, var(--ink)); }

.es--snap *, .es--snap *::before, .es--snap *::after { transition: none !important; }

/* ---------- Widths ---------- */
/* Code beside the engine. */
@container fx (min-width: 780px) {
  .es-board { grid-template-columns: minmax(0, 1fr) minmax(0, 1.28fr); gap: 34px 40px; align-items: start; }
  .es-sys { gap: 44px; }
}
@container fx (min-width: 960px) {
  .es-pre { font-size: .84rem; }
  .es-eng { column-gap: 44px; padding-inline: 16px; }
}
/* A phone: the step strip shows its numbers (each title stays for screen readers; the panel shows it); Restart and
   Previous show their icons; tighter boxes. */
/* A phone: the whole figure fits one screen under the site header (about 760 px at 390 px), so Next and the line that
   runs are seen together. No kicker (the panel names the example); the step strip shows its numbers (each title stays
   for screen readers; the panel shows it); Restart and Previous show their icons; tighter gaps. The controls stay in
   reach (sticky) if the screen is shorter still. At step 5 the two Try it buttons take the place of Play and Next (Restart
   replays), on the same row: nothing grows. */
@container fx (max-width: 559px) {
  .es > .fx__kicker { display: none; }
  .es-steps { margin-bottom: 8px; gap: 5px; }
  .es-step { justify-content: center; padding: 6px; }
  .es-step__t, .es-b--icon .es-b__t, .es-try__k {
    position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0; overflow: hidden; clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap; border: 0;
  }
  [data-fx="engine-pipeline"] .fx__stage { padding: 12px; }
  .es-board { gap: 20px; }
  .es-code__h { padding-block: 6px; }
  .es-pre { font-size: .74rem; line-height: 1.45; padding: 7px 0 8px; }
  .es-ln { padding-right: 10px; }
  .es-eng { gap: 22px 26px; padding: 18px 10px 10px; }
  .es-box { padding: 8px 9px 9px; gap: 6px; }
  .es-box__h { font-size: .84rem; }
  .es-count { padding-top: 7px; gap: 4px; }
  .es-mc { padding: 7px 9px 8px; gap: 5px; }
  .es-mc__h { font-size: .76rem; }
  .es-sys { gap: 26px; }
  .es-cpu { min-height: 38px; padding-block: 6px; }
  .es-panel { margin-top: 12px; padding: 10px 14px 12px; }
  .es-panel__t { margin-top: 3px; font-size: 1.04rem; }
  .es-panel__p { margin-top: 4px; font-size: .95rem; line-height: 1.5; }
  .es-foot {
    position: sticky; bottom: 0; z-index: 5; flex-wrap: nowrap; gap: 8px; margin: 6px -6px 0; padding: 4px 6px;
    border-radius: 14px; background: var(--surface);   /* solid: the text it slides over never shows through */
  }
  .es-ctl { flex: 1 1 auto; min-width: 0; }
  .es-ctl .es-play, .es-ctl .es-b--next { flex: 1 1 0; min-width: 0; }
  .es-b--icon { padding-inline: 13px; }
  .es-try { display: none; }
  .es[data-step="5"] .es-ctl { flex: none; }
  .es[data-step="5"] :is(.es-play, .es-b--next) { display: none; }
  .es[data-step="5"] .es-try { display: flex; flex: 1 1 auto; flex-wrap: nowrap; gap: 8px; min-width: 0; }
  .es-try .fx-btn { flex: 1 1 0; min-width: 0; padding-inline: 8px; }
}
@container fx (max-width: 359px) {
  .es-pre { font-size: .7rem; }
  .es-eng { column-gap: 20px; }
}
/* A 360 px phone: a slightly smaller text (each step keeps to one title line and four lines); the French words keep
   their padding. */
@container fx (max-width: 340px) {
  .es-panel__t { font-size: .98rem; }
  .es-panel__p { font-size: .9rem; }
  .es-ctl { gap: 6px; }
  .es-ctl .es-play, .es-ctl .es-b--next { padding-inline: 10px; gap: 6px; }
  .es-try small { font-size: .72rem; }
}
/* A 320 px phone: the longest code line still fits; Next shows its icon too, Play takes the rest. */
@container fx (max-width: 299px) {
  .es-pre { font-size: .62rem; }
  .es-ln { padding-right: 6px; }
  .es-ctl { gap: 6px; }
  .es-ctl .es-b--next { flex: none; padding-inline: 13px; }
  .es-b--next .es-b__t {
    position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0; overflow: hidden; clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap; border: 0;
  }
  .es-ctl .es-play { padding-inline: 8px; gap: 6px; font-size: .86rem; }
  .es-try .fx-btn { padding-inline: 6px; gap: 4px; }
  .es-try small { font-size: .68rem; }
}

/* The frame clips like overflow: hidden but is no scroll box, so the phone's sticky controls stick to the screen. */
[data-fx="engine-pipeline"] .fx__stage { overflow: clip; }

/* Presentation: the figure takes the slide; the small labels grow about 15% (the slide is scaled down on a projector). */
[data-teaching="true"] [data-fx="engine-pipeline"] .fx__stage { padding: 14px 22px 16px; }
[data-teaching="true"] .es-pre { font-size: .96rem; }
[data-teaching="true"] .es-mc__h { font-size: .94rem; }
[data-teaching="true"] .es-bet { font-size: .83rem; }
[data-teaching="true"] .es code.es-got { font-size: .85rem !important; }
[data-teaching="true"] .es-thrown { font-size: .9rem; }
[data-teaching="true"] .es-bc code, [data-teaching="true"] .es-flab, [data-teaching="true"] .es-tok { font-size: .83rem; }
[data-teaching="true"] .es-count__k { font-size: .9rem; }
[data-teaching="true"] .es-hot svg { width: 18px; height: 18px; }

@media print {
  .es-foot, .es-timer, .es-tok, .es-pulse { display: none; }
  .es-panel { box-shadow: none; }
  .es-code, .f-mc .es-mc { -webkit-print-color-adjust: exact; print-color-adjust: exact; }
  /* the page prints its code on paper (javascript.css): the code's colours follow */
  .es-code__h { color: #9a5b00; }
  .es-pre, .es-ln { color: #16161f; }
  .es-ln.cm, .es-ln.cm.is-on { color: #5c5c6a; }
  .es-pre .kw { color: #6b21a8; }
  .es-arg { color: #9a5b00; }
  .es-pre.has-on .es-ln:not(.is-on) { opacity: .7; }
}
@media (forced-colors: active) {
  .es-step[aria-current="step"] .es-step__n { forced-color-adjust: none; background: Highlight; color: HighlightText; }
  .es-ln.is-on { forced-color-adjust: none; border-left-color: Highlight; }
}

/* ---------- Large screens (2026-10-25): in a wide frame the text panel splits in two, the kicker and the title on the left,
   the text on the right (56ch, at most about 80 characters a line in French); the controls keep Try it beside them. Not in presentation. ---------- */
@container fx (min-width: 1100px) {
  :root:not(.is-presenting) .es-panel { display: grid; grid-template-columns: minmax(12rem, 20rem) minmax(0, 56ch); grid-template-rows: auto 1fr; column-gap: clamp(28px, 2.6vw, 56px); justify-content: start; }
  :root:not(.is-presenting) .es-panel__k, :root:not(.is-presenting) .es-panel__t { grid-column: 1; }
  :root:not(.is-presenting) .es-panel__p { grid-column: 2; grid-row: 2; margin-top: 0; }
  :root:not(.is-presenting) :is(.es-panel__t, .es-panel__p) { align-self: baseline; }
  :root:not(.is-presenting) .es-foot { justify-content: flex-start; column-gap: 32px; }
}
