/* Capsule 01 ("How does JavaScript run?") figures: the hero art (.jh-*), F2 engines-map (.em-*), F3 same-core (.sc-*).
   F1 engine-pipeline, the engine simulation, has its own sheet: engine-sim.css (.es-*). Design spec sections 2 and 8.
   Meaning colours: --engine purple, --host sky (the environment), --you amber; there = mint with the word; missing = a
   dashed outline in --control with the word, never red. Built on the course tokens (javascript.css). */

/* =========================================================================================================
   Hero · c01-hero (night art). The page owns the stage and its caption. The host group is centred across the box; the
   spec sits top left, outside it. Labels: 11 px or more on screen down to a 360 px viewport (9.6 px at 320).
   ========================================================================================================= */
[data-fx="c01-hero"] { --sa: 192 132 252; --sb: 125 211 252; --sc: 251 191 36; }
/* The page owns the art box (.stage--core > .fx-art, 640 x 470). The drawing ends near y 420 (y 440 on a phone): the
   band under it stays free for the page's caption, pulled up into it. */
[data-fx="c01-hero"] > .fx-art { perspective: 1500px; }
.jh {
  display: block; width: 100%; height: auto; overflow: visible;
  transform: rotateX(var(--lean-x, 0deg)) rotateY(var(--lean-y, 0deg)); transition: transform .9s var(--fx-ease-out, ease);
}
.jh :is(rect, path, ellipse, circle) { vector-effect: non-scaling-stroke; }
.jh text { font-family: var(--font-body); }
/* Label sizes: the drawn size, or 11.2 px on screen when the art is small (phones). --jh-k is the viewBox units per CSS
   pixel, set by c01-hero.js from the art's width; fit() then lays the pills, rows, core and tags out around the words. */
.jh { --jh-px: calc(var(--jh-k, 0) * 11.2px); }
.jh-w { font-size: clamp(16.5px, var(--jh-px), 25px); font-weight: 600; fill: #7dd3fc; }
.jh-k { font-size: clamp(15.5px, var(--jh-px), 25px); font-weight: 700; letter-spacing: .16em; text-transform: uppercase; fill: #c084fc; }
.jh-s { font-size: clamp(15.5px, var(--jh-px), 25px); font-weight: 500; fill: #c3c3d1; }
.jh text.jh-code { font: 600 clamp(16px, var(--jh-px), 25px)/1 var(--font-mono); fill: #fbbf24; }
.jh-you { font-size: clamp(15.5px, var(--jh-px), 25px); font-weight: 600; fill: #fbbf24; letter-spacing: .02em; }
.jh-tg { font-size: clamp(15px, var(--jh-px), 25px); font-weight: 700; letter-spacing: .1em; text-transform: uppercase; }
.jh text.jh-spec__t { font: 600 clamp(15px, var(--jh-px), 25px)/1 var(--font-mono); fill: #a3a4b8; letter-spacing: .03em; }
.jh text.jh-sect { font: 600 15px/1 var(--font-display); fill: #a3a4b8; }

/* The spec: paper and ink, no hue, quiet. */
.jh-sheet { fill: rgba(236, 235, 243, .08); stroke: rgba(236, 235, 243, .42); stroke-width: 1.2; stroke-linejoin: round; }
.jh-fold { fill: none; stroke: rgba(236, 235, 243, .42); stroke-width: 1.2; stroke-linejoin: round; }
.jh-rule { stroke: rgba(236, 235, 243, .26); stroke-width: 1.2; stroke-linecap: round; }
.jh-dots { fill: none; stroke: rgba(236, 235, 243, .34); stroke-width: 1.4; stroke-dasharray: 1.5 6; stroke-linecap: round; }

/* The host shell: a sky ring. The engine core: purple. Your code: amber. */
.jh-shell__halo { fill: none; stroke: #7dd3fc; stroke-opacity: .1; stroke-width: 9; }
.jh-shell { fill: rgba(125, 211, 252, .045); stroke: #7dd3fc; stroke-opacity: .62; stroke-width: 1.5; }
.jh-core { fill: rgba(192, 132, 252, .13); stroke: #c084fc; stroke-opacity: .8; stroke-width: 1.5; }
.jh-chip rect { fill: rgba(251, 191, 36, .1); stroke: #fbbf24; stroke-opacity: .85; stroke-width: 1.3; }

/* Plugs and their wires. On: a lit sky pill and wire (the lit layers). Off: dashed, dim, no wire. */
.jh-wire { fill: none; stroke: #7dd3fc; stroke-opacity: .7; stroke-width: 1.4; }
.jh-plug__box { stroke-width: 1.5; }
.jh-plug__ico { fill: none; stroke-width: 1.7; stroke-linecap: round; stroke-linejoin: round; }
.jh-plug--on .jh-plug__box { fill: #0f1729; stroke: #7dd3fc; filter: drop-shadow(0 0 6px rgba(125, 211, 252, .45)); }
.jh-plug--on .jh-plug__ico { stroke: #7dd3fc; }
.jh-plug--on .jh-fill { fill: #7dd3fc; stroke: none; }
.jh-plug--off .jh-plug__box { fill: #0d111d; stroke: #a3a4b8; stroke-opacity: .6; stroke-dasharray: 3 4; }
.jh-plug--off .jh-plug__ico { stroke: #a3a4b8; opacity: .55; }
.jh-plug--off .jh-fill { fill: #a3a4b8; stroke: none; }
.jh-plug--off .jh-w { fill: #a3a4b8; }

/* The two hosts under the shell. */
.jh-tag rect { stroke-width: 1.3; }
.jh-tag--dim rect { fill: none; stroke: #a3a4b8; stroke-opacity: .4; }
.jh-tag--dim .jh-tg { fill: #a3a4b8; }
.jh-tag--lit rect { fill: rgba(125, 211, 252, .2); stroke: #7dd3fc; filter: drop-shadow(0 0 8px rgba(125, 211, 252, .35)); }
.jh-tag--lit .jh-tg { fill: #ecebf3; }

/* The still = the Node state: "Node" lit with the files plug, the page plug empty. */
.jh-pagelit, .jh-taglit--page { opacity: 0; }
.jh-fileslit, .jh-taglit--node { opacity: 1; }
/* A pinned page frame (instance.set('page'), for the film): "a browser page" lit with the page plug, files empty. */
.jh--page .jh-pagelit, .jh--page .jh-taglit--page { opacity: 1; }
.jh--page .jh-fileslit, .jh--page .jh-taglit--node { opacity: 0; }
/* The loop: 9 s, page (0-4.2 s) then Node (4.8-8.7 s); opacity only. */
.jh--loop .jh-pagelit, .jh--loop .jh-taglit--page { animation: jh-page 9s var(--fx-ease-io, ease-in-out) infinite; }
.jh--loop .jh-fileslit, .jh--loop .jh-taglit--node { animation: jh-node 9s var(--fx-ease-io, ease-in-out) infinite; }
@keyframes jh-page { 0%, 46% { opacity: 1; } 53%, 96% { opacity: 0; } 100% { opacity: 1; } }
@keyframes jh-node { 0%, 46% { opacity: 0; } 53%, 96% { opacity: 1; } 100% { opacity: 0; } }

[data-teaching="true"] .jh { transform: none; }
@media (prefers-reduced-motion: reduce) { .jh--loop :is(.jh-pagelit, .jh-fileslit, .jh-taglit) { animation: none; } .jh { transition: none; } }
@media print { .jh { transform: none; } .jh--loop :is(.jh-pagelit, .jh-fileslit, .jh-taglit) { animation: none; } }


/* Code inside the paper figures: the page's inline-code chip stops here. */
:is(.em, .sc) code { font-family: var(--font-mono); font-size: inherit; background: none; border: 0; padding: 0; border-radius: 0; color: inherit; }
/* (0,1,0) after javascript.css: beats the page's `.article :where(p)` margin; each class rule below still wins. */
:is(.em-wrap, .sc-wrap) :where(p, ul, ol, li) { margin: 0; }
:where(.em-list, .sc-adds, .sc-core__l) > li { font-size: inherit; line-height: inherit; }

/* =========================================================================================================
   Chapter 1 · F2 engines-map (paper, animated once on screen). Environments: sky boxes; engines: purple chips with a
   dot; the former Chakra: a faded dashed chip. One idea: where each engine lives (what an environment adds is F3's).
   Panels side by side from 700 px of figure; inside each, two columns of boxes (VS Code takes the whole row), one
   column when a panel is narrow. An engine's name never breaks: the chips get smaller first.
   ========================================================================================================= */
.em-grid { display: grid; grid-template-columns: minmax(0, 1fr); gap: 16px; }
.em-panel { container: emp / inline-size; min-width: 0; padding: 14px 14px 16px; border-radius: 18px; border: 1px solid var(--rule); background: color-mix(in srgb, var(--surface) 72%, transparent); }
.em-panel__h { margin: 0 0 12px !important; font: 700 .72rem/1.3 var(--font-mono); letter-spacing: .1em; text-transform: uppercase; color: var(--ink-2); }
.em-list { list-style: none; padding: 0; display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 12px; }
.em-env {
  position: relative; min-width: 0; display: flex; flex-direction: column; align-items: flex-start; gap: 9px; padding: 10px 11px 12px;
  border-radius: 14px; border: 1.5px solid var(--host); background: color-mix(in srgb, var(--host) 5%, var(--surface));
  transition: opacity var(--fx-t-short) var(--fx-ease-out), transform var(--fx-t-short) var(--fx-ease-out);
}
.em-env--vscode { grid-column: 1 / -1; }
.em-env__h { display: flex; align-items: center; gap: 7px; font: 600 .95rem/1.25 var(--font-body); color: var(--ink); }
.em-env__h svg { flex: none; width: 18px; height: 18px; fill: none; stroke: var(--host); stroke-width: 1.7; stroke-linecap: round; stroke-linejoin: round; }
.em-env__h svg circle { fill: var(--host); stroke: none; }
.em-eng {
  display: inline-flex; align-items: center; gap: 6px; max-width: 100%; padding: 4px 10px 4px 8px; border-radius: 9px;
  border: 1.5px solid var(--rule-strong); background: var(--surface); font: 650 .88rem/1.25 var(--font-body); color: var(--ink-3);
  white-space: nowrap; overflow-wrap: normal;
  transition: background-color var(--fx-t-short) ease .18s, border-color var(--fx-t-short) ease .18s, color var(--fx-t-short) ease .18s, box-shadow var(--fx-t-med) ease;
}
.em-eng::before { content: ""; flex: none; width: 7px; height: 7px; border-radius: 50%; background: currentColor; }
.em-env.is-in .em-eng { border-color: var(--engine); background: var(--engine-soft); color: var(--engine); }
.em-env .em-eng--old, .em-env.is-in .em-eng--old {
  margin-top: -3px; border: 1.5px dashed var(--control); background: transparent; color: var(--ink-3); font-size: .76rem; font-weight: 600;
  white-space: normal;   /* "Chakra · until 2020" may wrap at its spaces */
}
.em-eng--old::before { display: none; }
.em-inner {
  align-self: stretch; display: flex; flex-wrap: wrap; align-items: center; gap: 8px 12px; padding: 8px 10px;
  border-radius: 11px; border: 1.5px dashed color-mix(in srgb, var(--host) 70%, transparent); background: color-mix(in srgb, var(--host) 6%, var(--surface));
}
.em-inner__h { font: 600 .82rem/1.3 var(--font-body); color: var(--host); }
.em--pre .em-env:not(.is-in) { opacity: 0; transform: translateY(10px); }
.em--done .em-eng--v8 { box-shadow: 0 0 0 3px color-mix(in srgb, var(--engine) 24%, transparent); animation: em-pulse 1.1s var(--fx-ease-out) 1; }
@keyframes em-pulse {
  0% { box-shadow: 0 0 0 0 color-mix(in srgb, var(--engine) 50%, transparent); }
  55% { box-shadow: 0 0 0 10px color-mix(in srgb, var(--engine) 0%, transparent); }
  100% { box-shadow: 0 0 0 3px color-mix(in srgb, var(--engine) 24%, transparent); }
}
.em-cap {
  margin: 18px 0 0 !important; max-width: 64ch; font: 600 1rem/1.45 var(--font-body); color: var(--ink); text-wrap: pretty;
  opacity: 0; transform: translateY(4px); transition: opacity var(--fx-t-short) ease, transform var(--fx-t-short) var(--fx-ease-out);
}
.em--done .em-cap { opacity: 1; transform: none; }
@container fx (min-width: 700px) { .em-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 20px; } }
@container fx (max-width: 380px) {
  .em-panel { padding: 12px 10px 14px; }
  .em-list { gap: 10px; }
  .em-env { padding: 9px 9px 11px; }
}
/* A panel's content box: two columns of boxes as long as "JavaScriptCore" fits whole, smaller chips first. */
@container emp (max-width: 350px) {
  .em-eng { font-size: .76rem; padding-inline: 8px; }
  .em-eng::before { display: none; }
}
@container emp (max-width: 272px) {
  .em-eng { font-size: .7rem; padding-inline: 7px; }
  .em-env__h { gap: 5px; font-size: .84rem; overflow-wrap: normal; }
  .em-env__h svg { width: 16px; height: 16px; }
}
@container emp (max-width: 258px) { .em-list { grid-template-columns: minmax(0, 1fr); } }
@media print { .em-env { opacity: 1 !important; transform: none !important; } .em-cap { opacity: 1; } }

/* =========================================================================================================
   Chapter 1 · F3 same-core (paper, animated once on screen, Replay). One purple core (the language) in two sky shells
   (Browser, Node.js). Names the environment adds: the name in sky + "there" on a mint tint; missing: a dashed
   --control outline and the word, ink-3, never red. data-sc on the stage: pre, split, n0, n1, n2, done.
   ========================================================================================================= */
.sc-envs { display: grid; grid-template-columns: minmax(0, 1fr); gap: 18px; }
.sc-env {
  min-width: 0; display: flex; flex-direction: column; gap: 12px; padding: 12px 14px 16px; border-radius: 22px;
  border: 1.5px solid var(--host); background: color-mix(in srgb, var(--host) 4%, transparent);
}
.sc-env__h { display: flex; align-items: center; gap: 7px; font: 700 .72rem/1.35 var(--font-mono); letter-spacing: .12em; text-transform: uppercase; color: var(--host); }
.sc-env__h svg { flex: none; width: 17px; height: 17px; fill: none; stroke: var(--host); stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; }
.sc-env__h svg circle { fill: var(--host); stroke: none; }
.sc-core {
  position: relative; z-index: 2; padding: 10px 12px 12px; border-radius: 16px; border: 1.5px solid var(--engine); background: var(--engine-soft);
  transition: transform var(--fx-t-med) var(--fx-ease-io), box-shadow var(--fx-t-med) ease;
}
.sc-env--web .sc-core { z-index: 3; }
.sc-core__h { margin: 0 0 8px !important; font: 700 .7rem/1.35 var(--font-body); letter-spacing: .1em; text-transform: uppercase; color: var(--engine); }
.sc-core__l { list-style: none; padding: 0; display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 6px; }
.sc-core__l li { min-width: 0; padding: 4px 8px; border-radius: 8px; border: 1px solid color-mix(in srgb, var(--engine) 30%, transparent); background: var(--surface); text-align: center; }
.sc-core__l code { font: 600 .84rem/1.35 var(--font-mono); color: var(--engine); white-space: nowrap; }
.sc[data-sc="pre"] .sc-core { box-shadow: 0 10px 30px -12px color-mix(in srgb, var(--engine) 55%, transparent); }
.sc-adds { list-style: none; padding: 0; display: flex; flex-wrap: wrap; gap: 8px; }
.sc-miss { display: flex; margin-top: -2px !important; }
.sc-name {
  display: inline-flex; align-items: stretch; border-radius: 999px; overflow: hidden; border: 1.5px solid var(--host);
  opacity: 0; transform: scale(.9); transition: opacity var(--fx-t-short) ease, transform var(--fx-t-short) var(--fx-ease-out);
}
.sc-name code { padding: 3px 9px 3px 11px; background: color-mix(in srgb, var(--host) 10%, var(--surface)); font: 600 .84rem/1.35 var(--font-mono); color: var(--host); }
.sc-w { padding: 3px 11px 3px 9px; border-left: 1.5px solid var(--host); background: var(--ok-soft); font: 600 .76rem/1.6 var(--font-body); color: var(--ok); }
.sc-name[data-st="missing"] { border: 1.5px dashed var(--control); }
.sc-name[data-st="missing"] code { background: transparent; color: var(--ink-3); }
.sc-name[data-st="missing"] .sc-w { background: transparent; border-left: 1.5px dashed var(--control); color: var(--ink-3); }
.sc[data-sc="n0"] .sc-name[data-i="0"], .sc[data-sc="n1"] .sc-name:is([data-i="0"], [data-i="1"]),
.sc:is([data-sc="n2"], [data-sc="done"]) .sc-name { opacity: 1; transform: none; }
.sc-foot { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 10px 16px; margin-top: 16px; }
.sc-cap { font: 600 1rem/1.45 var(--font-body); color: var(--ink); opacity: 0; transition: opacity var(--fx-t-short) ease; }
.sc[data-sc="done"] .sc-cap { opacity: 1; }
.sc-replay { margin-left: auto; }
.fx--still .sc-replay { display: none; }
.sc--snap *, .sc--snap { transition: none !important; }
@container fx (min-width: 600px) { .sc-envs { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 22px; } }
@container fx (min-width: 820px) { .sc-core__l { grid-template-columns: repeat(4, auto); justify-content: start; } }
@media print { .sc-name, .sc-cap { opacity: 1 !important; transform: none !important; } .sc-core { transform: none !important; } .sc-replay { display: none; } }
@media (forced-colors: active) { .sc-name[data-st="missing"] { border-color: GrayText; } }

/* The two figure captions never hyphenate (beats the French page's `.prose p` hyphens: auto). */
:root .fx p:is(.em-cap, .sc-cap) { hyphens: manual; -webkit-hyphens: manual; }

/* The font shorthands above reset ligatures: code never shows a ligature (() => stays three characters). */
:is(.em, .sc) code { font-variant-ligatures: none; }
