/* Case-study pages. They reuse the header, type, controls, and diagrams of the home page.
   Load after interactions.css. */

/* Hero: name the project, state the outcome, show the real result. */
.case-hero { padding-block: 30px 76px; }
.breadcrumb { display: flex; align-items: center; gap: 12px; font-size: 12px; color: #4b6653; margin: 0 0 34px; }
.breadcrumb a { display: inline-flex; align-items: center; min-height: 44px; text-decoration: underline; text-decoration-color: #b4cdbb; text-underline-offset: 4px; }
.breadcrumb a:is(:hover, :focus-visible) { text-decoration-color: currentColor; }
.case-hero-grid { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 56px; align-items: start; }
.case-hero .project-category { margin-bottom: 30px; }
.case-hero h1 { font-size: clamp(56px, 5.6vw, 80px); line-height: 1.02; letter-spacing: -.05em; font-weight: 600; margin: 0 0 30px; }
.case-hero h1 .project-name { margin-bottom: 20px; }
.case-lede { font-size: 20px; line-height: 1.5; letter-spacing: -.01em; max-width: 540px; margin: 0 0 34px; }
.case-lede a, .case-section-body p a { text-decoration: underline; text-decoration-thickness: 1px; text-decoration-color: #7fbf92; text-underline-offset: 4px; }
.case-lede a:is(:hover, :focus-visible), .case-section-body p a:is(:hover, :focus-visible) { text-decoration-color: currentColor; }
.case-facts { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); max-width: 560px; margin: 0 0 20px; border-top: 1px dashed var(--line); }
.case-facts div { padding: 14px 16px 14px 0; border-bottom: 1px dashed var(--line); }
.case-facts dt { font: 11px var(--mono); text-transform: uppercase; letter-spacing: .035em; color: #4b6653; margin-bottom: 6px; }
.case-facts dd { margin: 0; font-size: 16px; line-height: 1.4; }

/* Input and output side by side. The images are the evidence, so they get the panel. */
.result-pair { margin: 0; padding: 22px; background: var(--pale); border: 1px dashed #c1d6c6; }
.result-pair-images { display: grid; grid-template-columns: minmax(0, 1fr) 36px minmax(0, 1fr); align-items: center; }
.result-pair-images img { display: block; width: 100%; height: auto; aspect-ratio: 1; background: #fff; }
.result-label { display: block; font-size: 11px; text-transform: uppercase; letter-spacing: .035em; color: #4b6653; margin-bottom: 10px; }
.result-arrow { justify-self: center; padding-top: 22px; color: #159351; font-size: 20px; }
.result-pair figcaption { margin-top: 16px; font-size: 13px; line-height: 1.6; color: #526859; }
.result-pair-compact { margin-top: 38px; max-width: 640px; }

/* Sections: a short label and heading on the left, the argument on the right. */
.case-section { display: grid; grid-template-columns: minmax(0, .8fr) minmax(0, 1.2fr); gap: 56px; padding-block: 76px; border-top: 1px dashed var(--line); }
.case-section-head { position: sticky; top: calc(var(--header-height) + 34px); align-self: start; }
.section-label { font-size: 12px; text-transform: uppercase; letter-spacing: .035em; color: #4b6653; margin: 0 0 16px; }
.case-section h2 { font-size: clamp(34px, 3.2vw, 46px); line-height: 1.08; letter-spacing: -.045em; font-weight: 600; margin: 0; max-width: 460px; text-wrap: balance; }
.case-section-body { min-width: 0; }
.case-section-body > p { font-size: 18px; line-height: 1.65; color: #415849; max-width: 640px; margin: 0 0 20px; text-wrap: pretty; }
.case-section-body > p:first-child { color: var(--ink); }
.case-section-body > .case-visual { margin: 34px 0 30px; }

/* Bar charts. One measure, reference lines for scale, the value at the bar tip. --max on .fit-plot sets the
   scale (24 by default, the Modly memory chart). The pale bar is the baseline; labels and a table carry the values. */
.fit-chart { margin: 36px 0 0; padding: 24px 24px 20px; border: 1px dashed var(--line); }
.js-ready .fit-chart.reveal { opacity: 1; transform: none; }
.fit-title { font-size: 12px; text-transform: uppercase; letter-spacing: .035em; color: #4b6653; margin: 0 0 18px; }
.fit-plot { position: relative; display: grid; grid-template-columns: 76px minmax(0, 1fr); row-gap: 14px; padding: 28px 70px 4px 0; }
.fit-scale { position: absolute; top: 0; bottom: 0; left: 76px; right: 70px; pointer-events: none; }
.fit-mark { position: absolute; top: 0; bottom: 0; left: calc(var(--at) / var(--max, 24) * 100%); transform: translateX(-50%); font: 11px var(--mono); color: #4b6653; white-space: nowrap; }
.fit-mark::before { content: ''; position: absolute; top: 20px; bottom: 0; left: 50%; width: 1px; background: #c9d9cc; }
.fit-mark-end { transform: translateX(-100%); }
.fit-mark-end::before { left: auto; right: 0; }
.fit-row { display: contents; }
.fit-label { grid-column: 1; align-self: center; font-size: 14px; color: #415849; }
.fit-track { grid-column: 2; position: relative; height: 24px; }
.fit-bar { position: absolute; left: 0; top: 2px; height: 20px; width: calc(var(--value) / var(--max, 24) * 100%); background: #93bea0; border-radius: 0 4px 4px 0; transform-origin: left; transition: transform .9s var(--ease-out) .15s; }
.fit-row-staged .fit-bar, .fit-row-strong .fit-bar { background: #0a8f45; transition-delay: .3s; }
/* A limit starts at its line, so a threshold near zero stays inside the plot. */
.fit-mark-start { transform: none; }
.fit-mark-start::before { left: 0; }
.fit-mark-limit { color: #7a3f70; }
.fit-mark-limit::before { width: 0; background: none; border-left: 2px dashed #c05fb4; }
/* A measure that fails its limit is not drawn in green, which reads as a pass. */
.fit-chart-neutral .fit-bar { background: #bccbbf; }
.fit-chart-neutral .fit-row-strong .fit-bar { background: #4f6b58; }
.fit-value { position: absolute; top: 0; left: calc(var(--value) / var(--max, 24) * 100% + 8px); font-weight: 600; font-size: 15px; line-height: 24px; white-space: nowrap; font-variant-numeric: tabular-nums; }
.js-ready .fit-chart.reveal:not(.visible) .fit-bar { transform: scaleX(0); }
html:is([data-motion="paused"], [data-motion="reduced"]) .fit-bar { transform: none; }
.fit-note { margin: 18px 0 0; font-size: 13px; line-height: 1.6; color: #526859; max-width: 560px; }

/* Benchmark table: numbers align in columns. */
.table-scroll { overflow-x: auto; }
.fit-chart + .table-scroll { margin-top: 36px; }
.bench-table { width: 100%; min-width: 420px; border-collapse: collapse; font-size: 16px; }
.bench-table caption { text-align: left; font: 12px var(--mono); text-transform: uppercase; letter-spacing: .035em; color: #4b6653; padding-bottom: 14px; }
.bench-table th, .bench-table td { text-align: left; padding: 14px 16px 14px 0; border-bottom: 1px dashed var(--line); }
.bench-table thead th { font: 11px var(--mono); text-transform: uppercase; letter-spacing: .035em; color: #4b6653; border-bottom-style: solid; border-color: #c9d9cc; }
.bench-table tbody th { font-weight: 600; }
.bench-table td { font-variant-numeric: tabular-nums; }
.bench-table :is(th, td):first-child { padding-left: 10px; }
.bench-staged { background: #edfaef; }
.case-section-body > .bench-method { margin: 18px 0 10px; font-size: 15px; }

/* Limits stay visible. A pink rule marks an open question, as it marks research elsewhere. */
.open-list { list-style: none; margin: 0; padding: 0; max-width: 680px; border-top: 1px dashed var(--line); }
.open-list li { position: relative; padding: 16px 0 16px 30px; border-bottom: 1px dashed var(--line); font-size: 17px; line-height: 1.55; color: #415849; }
.open-list li::before { content: ''; position: absolute; left: 2px; top: 29px; width: 14px; height: 2px; background: #d98ad0; }

/* One screenshot as the result. */
.case-shot { margin: 0; padding: 22px; background: var(--pale); border: 1px dashed #c1d6c6; }
.case-shot img { display: block; width: 100%; height: auto; border: 1px solid #d3e0d5; background: #fff; }
.case-shot figcaption { margin-top: 16px; font-size: 13px; line-height: 1.6; color: #526859; }
.case-hero .fit-chart { margin: 0; background: var(--pale); border-color: #c1d6c6; }
/* The two-slit concept drawing sits in the WaveGrating problem fold. */
.note-body .optics-diagram { height: auto; max-width: 620px; margin: 22px 0 8px; }

.case-section-body > .dgx-scene { background: #f2f8f1; }

/* WaveGrating: a CD's tracks. Angles, colors and band positions come from the grating equation for a 1.6 µm
   pitch and light at 50 degrees, for the positions drawn.
   A stage moves the eye first. The ray to the eye takes the color it now sees, then the disc's band and the
   reading follow. The case study adds the Rays and Summary stages with the story scenes at the end of this file. */
.cd-diagram{display:block;width:100%;height:auto;overflow:visible}
.cd-normal{fill:none;stroke:#b7cdbd;stroke-width:1;stroke-dasharray:4 4}
.cd-angle{fill:none;stroke:#7b9d85;stroke-width:1}
.cd-fan{opacity:.6}
.cd-light,.cd-mirror{fill:none;stroke:#8fa597;stroke-width:2}
.cd-lamp{fill:#fff;stroke:#456c51;stroke-width:1.6}
.cd-slab{fill:#e4efe6;stroke:#7b9d85;stroke-width:1}
.cd-tracks{fill:none;stroke:#7b9d85;stroke-width:1}
.cd-band,.cd-seen text[class]{opacity:0;transition:opacity .25s}
.cd-eye{transform-box:view-box;transform-origin:250px 286px;transform:rotate(29deg);transition:transform .6s cubic-bezier(.76,.08,.16,1)}
.cd-view-ray{fill:none;stroke:#5000f1;stroke-width:2.2;transition:stroke .6s cubic-bezier(.76,.08,.16,1)}
.cd-eye-lid{fill:#fff;stroke:#456c51;stroke-width:1.5}
.cd-eye-iris{fill:#101b14}
.cd-spot{fill:#fff;stroke:#101b14;stroke-width:1.4}
.cd-chip{fill:#5600ff;stroke:#456c51;stroke-width:1;transition:fill .3s .35s}
.cd-seen text,.cd-label text{font-size:12px;fill:#4b6653}
.cd-seen text[class]{font-size:16px;fill:#101b14}
.cd-scene[data-phase="0"] .cd-eye{transform:rotate(29deg)}.cd-scene[data-phase="0"] .cd-view-ray{stroke:#5000f1}.cd-scene[data-phase="0"] .cd-chip{fill:#5600ff}.cd-scene[data-phase="0"] :is(.cd-band-0,.cd-seen-0){opacity:1;transition:opacity .3s .35s}
.cd-scene[data-phase="1"] .cd-eye{transform:rotate(25deg)}.cd-scene[data-phase="1"] .cd-view-ray{stroke:#00f100}.cd-scene[data-phase="1"] .cd-chip{fill:#00ff00}.cd-scene[data-phase="1"] :is(.cd-band-1,.cd-seen-1){opacity:1;transition:opacity .3s .35s}
.cd-scene[data-phase="2"] .cd-eye{transform:rotate(21deg)}.cd-scene[data-phase="2"] .cd-view-ray{stroke:#f10000}.cd-scene[data-phase="2"] .cd-chip{fill:#ff0000}.cd-scene[data-phase="2"] :is(.cd-band-2,.cd-seen-2){opacity:1;transition:opacity .3s .35s}
.cd-scene .phase-notes{min-height:48px}
@media(max-width:480px){.cd-seen text,.cd-label text{font-size:17px}.cd-seen text[class]{font-size:21px}.cd-label text:nth-child(n+3):not(.cd-spot-label){display:none}}
/* End of the CD scene. */

/* Next and back. */
.case-next { display: grid; grid-template-columns: 1fr 1fr; margin-bottom: 76px; }
.case-next a { display: flex; flex-direction: column; gap: 8px; padding: 30px 0; border-block: 1px dashed var(--line); transition: background .25s; }
.case-next a + a { align-items: flex-end; text-align: right; padding-right: 0; border-left: 1px dashed var(--line); }
.case-next a:is(:hover, :focus-visible) { background: #f0faf2; }
.case-next small { font: 11px var(--mono); text-transform: uppercase; letter-spacing: .035em; color: #4b6653; padding-inline: 4px; }
.case-next strong { font-size: clamp(24px, 2.4vw, 34px); font-weight: 600; letter-spacing: -.035em; padding-inline: 4px; }
.case-contact h2 { margin: 0; }
.case-contact .contact { margin-top: 0; padding-top: 0; border-top: 0; }

@media (max-width: 1100px) {
  .case-hero-grid, .case-section { gap: 40px; }
  .case-section { grid-template-columns: minmax(0, .75fr) minmax(0, 1.25fr); padding-block: 62px; }
}
@media (max-width: 820px) {
  .case-hero-grid, .case-section { grid-template-columns: 1fr; }
  .case-hero-grid { gap: 36px; }
  .case-section { gap: 26px; padding-block: 52px; }
  .case-section-head { position: static; }
  .result-pair, .disc-scene { max-width: 620px; }
}
@media (max-width: 480px) {
  .case-hero { padding-bottom: 52px; }
  .breadcrumb { margin-bottom: 18px; font-size: 11px; }
  .case-hero h1 { font-size: clamp(44px, 12.4vw, 58px); line-height: 1.02; }
  .case-lede { font-size: 18px; }
  .case-facts dd { font-size: 15px; }
  .result-pair { padding: 14px; }
  .result-pair-images { grid-template-columns: minmax(0, 1fr) 24px minmax(0, 1fr); }
  .result-label { font-size: 11px; letter-spacing: 0; }
  .case-section { padding-block: 44px; }
  .case-section h2 { font-size: clamp(31px, 8.6vw, 38px); }
  .case-section-body > p { font-size: 17px; }
  .case-section-body > .case-visual { margin-inline: -9px; }
  .fit-chart { padding: 18px 14px 16px; }
  .fit-plot { grid-template-columns: 62px minmax(0, 1fr); padding-right: 62px; }
  .fit-scale { left: 62px; right: 62px; }
  .fit-label { font-size: 13px; }
  .fit-value { font-size: 14px; }
  .fit-mark .fit-unit { display: none; }
  .bench-table { min-width: 0; font-size: 14px; }
  .case-shot { padding: 14px; }
  .bench-table th, .bench-table td { padding: 12px 8px 12px 0; }
  .open-list li { font-size: 16px; }
  .case-next strong { font-size: 22px; }
  .case-next { margin-bottom: 52px; }
}

/* Story scenes: start. */
/* Story scenes. A scene plays its stages once when a third of it comes into view, then rests on its
   last stage, the finished drawing. Each change in a stage finishes within about 1 s of the stage start,
   and the stage holds as long as its caption takes to read. Each element's plain style is its finished drawing. A stage sets
   its own state with a rule on data-phase, and its animation runs once from the start of the stage.
   Pause, reduced motion and no JavaScript show the finished drawing of the current stage. Colors are
   set in rules; the keyframes only change opacity and transform, so the dark theme can follow them. */
.story-scene { position: relative; }
.story-art { color: var(--ink); }
.story-art p { margin: 0; }
.mem-name, .tile-name, .proof-title { font: 11px var(--mono); text-transform: uppercase; letter-spacing: .035em; color: #4b6653; }
/* All captions share one cell, so the scene keeps the height of its longest caption. */
:is(.story-scene, .sequence-scene) .phase-notes { display: grid; }
:is(.story-scene, .sequence-scene) .phase-notes p { grid-area: 1 / 1; }
:is(.story-scene, .sequence-scene) .phase-notes p[hidden] { display: block; visibility: hidden; }

/* A named part, such as a processor, wired down into the drawing. */
.chips { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; }
.story-art .chip { position: relative; justify-self: center; display: flex; align-items: center; gap: 8px; margin-bottom: 20px; padding: 8px 12px; background: #fff; border: 1px solid #83b595; font: 11px var(--mono); text-transform: uppercase; letter-spacing: .035em; color: #234a32; white-space: nowrap; }
.chip::before { content: ''; flex: none; width: 10px; height: 10px; background: #e1f9e9; border: 1px solid #5b9870; }
.wire { position: absolute; left: 50%; top: 100%; width: 2px; height: 21px; margin-left: -1px; background: #0a8f43; transform-origin: top; }

/* Memory as a row of equal blocks. Green is in use, grey is temporary file copies, white is free. */
.mem-box { position: relative; padding: 12px 12px 14px; background: #fff; border: 1px solid #afcfb8; }
.mem-box::after { content: ''; position: absolute; inset: -1px; border: 2px solid #19e76e; opacity: 0; pointer-events: none; }
.story-art .mem-name { margin-bottom: 10px; }
.mem-head { display: flex; justify-content: space-between; align-items: baseline; gap: 12px; margin-bottom: 4px; }
.story-art .mem-head .mem-name { margin: 0; }
.mem { display: grid; grid-template-columns: repeat(16, minmax(0, 1fr)); column-gap: 4px; }
.cell { grid-row: 2; position: relative; min-width: 0; height: 40px; background: #fff; border: 1px solid #b9c9bd; }
.cell::before, .cell::after { content: ''; position: absolute; inset: -1px; opacity: 0; }
.cell.m::before { opacity: 1; background: #19e76e; border: 1px solid #0a8f43; }
.cell.f::before { background: #cfd6d1; border: 1px solid #9aa69e; }
.cell.m::after { background: #b8ffd3; border: 1px solid #0a8f43; }
.cell.f::after { background: #fff; border: 2px solid #19e76e; }
.mem-legend { display: flex; flex-wrap: wrap; gap: 6px 16px; margin: 10px 0 14px; font-size: 12px; color: #526358; }
.story-art .mem-legend { margin: 10px 0 14px; }
.mem-legend span::before { content: ''; display: inline-block; width: 10px; height: 10px; margin-right: 6px; vertical-align: -1px; background: #19e76e; border: 1px solid #0a8f43; }
.mem-legend .lg-copies::before { background: #cfd6d1; border-color: #9aa69e; }
.mem-legend .lg-free::before { background: #fff; border-color: #b9c9bd; }
.mem-legend .lg-scale::before { content: none; }
.mem-legend .lg-over::before { background: repeating-linear-gradient(45deg, #fff 0 3px, #e9c9d7 3px 5px); border-color: #8a2f55; }

/* Result tiles. A tile stacks its states in one cell and shows one at a time. */
.tiles { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 8px; }
.tiles-2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.tile { display: flex; flex-direction: column; min-width: 0; min-height: 132px; padding: 10px 11px 12px; background: #fff; border: 1px solid #c9d6cc; transition: border-color .3s, box-shadow .3s; }
.story-art .tile-name { min-height: 28px; }
.tile-stack { display: grid; margin: 4px 0 10px; }
.tile-stack > p { grid-area: 1 / 1; }
.tile-stack b { display: block; font-size: 23px; font-weight: 600; line-height: 1.15; letter-spacing: -.03em; white-space: nowrap; }
.tile-stack span { display: block; margin-top: 3px; font-size: 12px; line-height: 1.35; color: #526358; }
.tile-before b, .tile-mid b { color: #6f7d73; }
.tile-stack .val-fail { color: #8a2f55; }
.tile-before, .tile-mid, .tile-mid2 { opacity: 0; }
.story-art .track { display: block; position: relative; height: 6px; margin-top: auto; overflow: hidden; background: #e3ebe4; }
.story-art .track b { position: absolute; inset: 0; transform-origin: left; }
.bar-go { background: #0a8f43; transform: scaleX(.7); }
.bar-stop { background: #8a2f55; transform: scaleX(.7); }
.runs { display: grid; gap: 9px; margin-top: 4px; }
.story-art .run { display: grid; grid-template-columns: minmax(0, 1fr) auto; align-items: baseline; gap: 3px 10px; font-size: 12px; color: #526358; }
.run em { font-style: normal; font-weight: 600; font-size: 15px; color: var(--ink); white-space: nowrap; }
.run .track { grid-column: 1 / -1; }
.run .track b { background: #9aa69e; }
.story-art .tile-foot { margin-top: auto; padding-top: 10px; font-size: 12px; line-height: 1.35; color: #526358; }
.pair-bars { display: grid; gap: 4px; margin-top: auto; }
.pair-bars .track { margin: 0; }
.pair-bars .old { background: #9aa69e; }
.pair-bars .new { right: auto; width: max(3px, 1.55%); background: #0a8f43; }

/* A board: five design choices as tiles, three on the first row and two on the second. */
.board { display: grid; grid-template-columns: repeat(6, minmax(0, 1fr)); gap: 8px; }
.board > .tile { grid-column: span 2; min-height: 172px; }
.board > .tile:nth-child(n + 4) { grid-column: span 3; }
.board .tile-stack { margin-bottom: 12px; }
.board .tile-stack b { font-size: 21px; }

/* Small drawings at the foot of a tile. */
.mv { margin-top: auto; font-size: 12px; line-height: 1.3; color: #526358; }
.mv-mark { flex: none; width: 12px; height: 12px; fill: none; stroke: #0a8f43; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }
/* A block that travels as one piece from one box to another. */
.mv-move { display: flex; align-items: center; gap: 6px; }
.mv-box { flex: none; padding: 3px 6px; border: 1px solid #b9c9bd; font: 10px var(--mono); text-transform: uppercase; letter-spacing: .03em; color: #4b6653; }
.mv-lane { position: relative; flex: 1; height: 14px; }
.mv-lane::before { content: ''; position: absolute; left: 0; right: 0; top: 50%; border-top: 1px dashed #9fb8a6; }
.mv-run { position: absolute; inset: 0; }
.mv-run i { position: absolute; right: 0; top: 1px; width: 22px; height: 12px; background: #19e76e; border: 1px solid #0a8f43; }
/* Two choices with a marker on the one in use. */
.mv-switch { position: relative; display: grid; grid-template-columns: 1fr 1fr; border: 1px solid #b9c9bd; }
.mv-switch span { position: relative; z-index: 1; padding: 5px 4px; font: 10px var(--mono); text-transform: uppercase; letter-spacing: .03em; text-align: center; color: #4b6653; white-space: nowrap; }
.mv-switch .on { color: #0b3b1f; }
.mv-pill { position: absolute; top: 2px; bottom: 2px; left: 50%; width: calc(50% - 2px); background: #c9fbdc; border: 1px solid #0a8f43; }
.mv-pill-left { left: 2px; }
/* A short list of checks. */
.mv-check { list-style: none; margin-top: auto; padding: 0; display: grid; gap: 4px; }
.mv-check li { display: flex; align-items: center; gap: 6px; min-width: 0; }
.mv-check .kept .mv-mark { stroke: #7a8a80; }
/* Bars that compare two values. */
.mv .mini-bars { margin: 0; grid-template-columns: auto minmax(0, 1fr) auto; }

/* Evidence: the measured results and where each change went. Links stay visible in every stage. */
.proof-art { display: grid; gap: 10px; }
.proof-group { padding: 12px 14px 14px; background: #fff; border: 1px solid #c9d6cc; transition: border-color .3s, box-shadow .3s; }
.story-art .proof-title { margin-bottom: 12px; }
.proof-tiles { list-style: none; margin: 0; padding: 0; display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 14px; }
.proof-tiles li { min-width: 0; }
.proof-tiles b { display: block; font-size: 30px; font-weight: 600; line-height: 1.05; letter-spacing: -.035em; white-space: nowrap; }
.proof-tiles span { display: block; margin-top: 6px; font-size: 13px; line-height: 1.4; color: #415849; }
.proof-tiles small { display: block; margin-top: 6px; font: 11px var(--mono); color: #4b6653; }
.pr-rows { list-style: none; margin: 0; padding: 0; }
.pr-rows li { display: grid; grid-template-columns: 88px minmax(0, 1fr); gap: 4px 12px; align-items: baseline; padding: 11px 0; border-top: 1px dashed var(--line); }
.pr-rows li:first-child { padding-top: 0; border-top: 0; }
.pr-rows li:last-child { padding-bottom: 0; }
.pr-rows .status-label { grid-row: 1 / span 3; justify-self: start; }
.pr-rows a { font-size: 17px; font-weight: 600; line-height: 1.35; letter-spacing: -.01em; text-decoration: underline; text-decoration-thickness: 1px; text-decoration-color: #b4cdbb; text-underline-offset: 4px; }
.pr-rows a:is(:hover, :focus-visible) { text-decoration-color: currentColor; }
.pr-rows small { grid-column: 2; font: 11px var(--mono); line-height: 1.5; color: #4b6653; }
.mini-bars { grid-column: 2; display: grid; grid-template-columns: auto minmax(0, 1fr) auto; align-items: center; gap: 5px 10px; margin-top: 6px; font-size: 12px; color: #526358; }
.mini-bars .track { margin: 0; }
.mini-bars .old { background: #9aa69e; }
.mini-bars .new { right: auto; width: 3px; background: #0a8f43; }
.proof-link { display: inline-flex; margin-top: 12px; }

/* My part and other people's work. */
.own-legend { display: flex; flex-wrap: wrap; justify-content: center; gap: 6px 22px; margin: 16px 0 0; font-size: 13px; color: #415849; transition: opacity .25s .6s; }
.own-legend span::before { content: ''; display: inline-block; width: 11px; height: 11px; margin-right: 7px; vertical-align: -1px; background: #19e76e; border: 1px solid #0a8f43; }
.own-legend .own-others::before { background: #ffa9fd; border-color: #c46cc0; }

/* The tile or group that the current stage is about: class s0 marks stage 0, s1 stage 1, and so on. */
.story-scene[data-phase="0"] .s0, .story-scene[data-phase="1"] .s1, .story-scene[data-phase="2"] .s2,
.story-scene[data-phase="3"] .s3, .story-scene[data-phase="4"] .s4, .story-scene[data-phase="5"] .s5 { border-color: #159351; box-shadow: inset 0 0 0 1px #159351; }

/* A board's tile shows its before state until its own stage, changes during it, and keeps the result. */
.scene-board[data-phase="0"] :is(.b1, .b2, .b3, .b4) .tile-before,
.scene-board[data-phase="1"] :is(.b2, .b3, .b4) .tile-before,
.scene-board[data-phase="2"] :is(.b3, .b4) .tile-before,
.scene-board[data-phase="3"] .b4 .tile-before { opacity: 1; }
.scene-board[data-phase="0"] :is(.b1, .b2, .b3, .b4) :is(.tile-after, .mv),
.scene-board[data-phase="1"] :is(.b2, .b3, .b4) :is(.tile-after, .mv),
.scene-board[data-phase="2"] :is(.b3, .b4) :is(.tile-after, .mv),
.scene-board[data-phase="3"] .b4 :is(.tile-after, .mv) { opacity: 0; }
.scene-board[data-phase="0"] .b0 .tile-before, .scene-board[data-phase="1"] .b1 .tile-before, .scene-board[data-phase="2"] .b2 .tile-before,
.scene-board[data-phase="3"] .b3 .tile-before, .scene-board[data-phase="4"] .b4 .tile-before { animation: story-lead .6s linear; }
.scene-board[data-phase="0"] .b0 .tile-after, .scene-board[data-phase="1"] .b1 .tile-after, .scene-board[data-phase="2"] .b2 .tile-after,
.scene-board[data-phase="3"] .b3 .tile-after, .scene-board[data-phase="4"] .b4 .tile-after { animation: story-in .25s ease-out .6s backwards; }
.scene-board[data-phase="0"] .b0 .mv, .scene-board[data-phase="1"] .b1 .mv, .scene-board[data-phase="2"] .b2 .mv,
.scene-board[data-phase="3"] .b3 .mv, .scene-board[data-phase="4"] .b4 .mv { animation: story-in .2s ease-out .05s backwards; }
/* The small drawing in the tile of the current stage plays once. */
.scene-board[data-phase="0"] .b0 .mv-run, .scene-board[data-phase="1"] .b1 .mv-run, .scene-board[data-phase="2"] .b2 .mv-run,
.scene-board[data-phase="3"] .b3 .mv-run, .scene-board[data-phase="4"] .b4 .mv-run { animation: mv-slide .5s cubic-bezier(.76, .08, .16, 1) .1s backwards; }
.scene-board[data-phase="0"] .b0 .mv-pill, .scene-board[data-phase="1"] .b1 .mv-pill, .scene-board[data-phase="2"] .b2 .mv-pill,
.scene-board[data-phase="3"] .b3 .mv-pill, .scene-board[data-phase="4"] .b4 .mv-pill { animation: mv-switch .4s cubic-bezier(.76, .08, .16, 1) .2s backwards; }
.scene-board[data-phase="0"] .b0 .mv-pill-left, .scene-board[data-phase="1"] .b1 .mv-pill-left, .scene-board[data-phase="2"] .b2 .mv-pill-left,
.scene-board[data-phase="3"] .b3 .mv-pill-left, .scene-board[data-phase="4"] .b4 .mv-pill-left { animation-name: mv-switch-back; }
.scene-board[data-phase="0"] .b0 .mv-check li, .scene-board[data-phase="1"] .b1 .mv-check li, .scene-board[data-phase="2"] .b2 .mv-check li,
.scene-board[data-phase="3"] .b3 .mv-check li, .scene-board[data-phase="4"] .b4 .mv-check li { animation: story-rise .3s cubic-bezier(.22, 1, .36, 1) calc(150ms + var(--k, 0) * 130ms) backwards; }
.scene-board[data-phase="0"] .b0 .mini-bars b, .scene-board[data-phase="1"] .b1 .mini-bars b, .scene-board[data-phase="2"] .b2 .mini-bars b,
.scene-board[data-phase="3"] .b3 .mini-bars b, .scene-board[data-phase="4"] .b4 .mini-bars b { animation: story-grow .45s cubic-bezier(.22, 1, .36, 1) calc(150ms + var(--k, 0) * 180ms) backwards; }

/* A stage picked by hand plays even while the automatic clock holds. Pause and reduced motion show
   the finished drawing of the stage. */
.story-scene[data-manual] *, .story-scene[data-manual] *::before, .story-scene[data-manual] *::after { animation-play-state: running !important; }
html:is([data-motion="paused"], [data-motion="reduced"]) .story-scene *,
html:is([data-motion="paused"], [data-motion="reduced"]) .story-scene *::before,
html:is([data-motion="paused"], [data-motion="reduced"]) .story-scene *::after { animation: none !important; transition-delay: 0s !important; }
@media (prefers-reduced-motion: reduce) {
  .story-scene *, .story-scene *::before, .story-scene *::after { animation: none !important; transition: none !important; }
}

@keyframes story-in { from { opacity: 0; } }
@keyframes story-rise { from { opacity: 0; transform: translateY(6px); } }
@keyframes story-lead { 0%, 82% { opacity: 1; } 100% { opacity: 0; } }
@keyframes story-show { 0% { opacity: 0; } 12%, 88% { opacity: 1; } 100% { opacity: 0; } }
@keyframes story-gone { 0% { opacity: 1; } 12%, 88% { opacity: 0; } 100% { opacity: 1; } }
@keyframes story-flash { 0% { opacity: 0; } 30%, 60% { opacity: 1; } 100% { opacity: 0; } }
@keyframes story-grow { from { transform: scaleX(0); } }
@keyframes story-drop { from { transform: scaleY(0); } }
@keyframes story-shrink { from { transform: scaleX(1); } }
@keyframes story-stamp { from { opacity: 0; transform: scale(.7); } }
@keyframes mv-slide { from { transform: translateX(calc(-100% + 22px)); } }
@keyframes mv-switch { from { transform: translateX(-100%); } }
@keyframes mv-switch-back { from { transform: translateX(100%); } }
@keyframes story-f0 { 0% { opacity: 0; } 10.353% { opacity: 0; } 12.706% { opacity: 1; } 44% { opacity: 1; } 44.118% { opacity: 0; } 57.412% { opacity: 0; } 59.765% { opacity: 1; } 91.059% { opacity: 1; } 91.176% { opacity: 0; } 100% { opacity: 0; } }
@keyframes story-f1 { 0% { opacity: 0; } 19.176% { opacity: 0; } 21.529% { opacity: 1; } 44% { opacity: 1; } 44.118% { opacity: 0; } 66.235% { opacity: 0; } 68.588% { opacity: 1; } 91.059% { opacity: 1; } 91.176% { opacity: 0; } 100% { opacity: 0; } }
@keyframes story-f2 { 0% { opacity: 0; } 28% { opacity: 0; } 30.353% { opacity: 1; } 44% { opacity: 1; } 44.118% { opacity: 0; } 75.059% { opacity: 0; } 77.412% { opacity: 1; } 91.059% { opacity: 1; } 91.176% { opacity: 0; } 100% { opacity: 0; } }
@keyframes story-f3 { 0% { opacity: 0; } 36.824% { opacity: 0; } 39.176% { opacity: 1; } 44% { opacity: 1; } 44.118% { opacity: 0; } 83.882% { opacity: 0; } 86.235% { opacity: 1; } 91.059% { opacity: 1; } 91.176% { opacity: 0; } 100% { opacity: 0; } }
@keyframes story-clear { 0% { opacity: 0; } 44.118% { opacity: 0; } 45.294% { opacity: 1; } 48% { opacity: 1; } 51.529% { opacity: 0; } 91.176% { opacity: 0; } 92.353% { opacity: 1; } 95.059% { opacity: 1; } 98.588% { opacity: 0; } 100% { opacity: 0; } }
@keyframes story-pulse { 0% { opacity: 0; } 41.176% { opacity: 0; } 44.118% { opacity: 1; } 47.059% { opacity: 1; } 51.529% { opacity: 0; } 88.235% { opacity: 0; } 91.176% { opacity: 1; } 94.118% { opacity: 1; } 98.588% { opacity: 0; } 100% { opacity: 0; } }

/* Local AI. The problem draws temporary file copies in grey that fill the free memory. */
.scene-problem .cell.f::before { opacity: 1; }
.scene-problem .cell.f::after { background: none; border-color: #8a2f55; }
.keep { grid-row: 1; grid-column: 14 / 17; position: relative; height: 28px; }
.keep::after { content: ''; position: absolute; left: 0; right: 0; bottom: 5px; height: 7px; border: 1px dashed #0a8f43; border-bottom: 0; }
.keep > span { position: absolute; right: 0; bottom: 15px; font: 10px var(--mono); color: #0a6b35; white-space: nowrap; }
.hold { grid-row: 2; grid-column: 13 / 17; z-index: 1; display: flex; align-items: center; justify-content: center; padding: 2px; background: repeating-linear-gradient(45deg, #eef1ee 0 5px, #c9d1cb 5px 7px); border: 1px solid #4f6b58; opacity: 0; }
.hold > span { padding: 1px 4px; background: #fff; font: 10px var(--mono); line-height: 1.25; text-align: center; color: #101612; }
/* The guard program's status light. It stops once the model is ready. */
.guard { display: grid; font: 11px var(--mono); text-transform: uppercase; letter-spacing: .035em; color: #4b6653; white-space: nowrap; }
.guard > span { grid-area: 1 / 1; justify-self: end; display: inline-flex; align-items: center; gap: 7px; }
.guard i { position: relative; width: 9px; height: 9px; border-radius: 50%; background: #0a8f43; }
.guard-off i { background: #b9c9bd; }
.guard-on i::after { content: ''; position: absolute; inset: -6px; border-radius: 50%; background: #19e76e59; opacity: 0; }
.guard-on { opacity: 0; }
.pw { background: #0a8f43; transform: scaleX(.622); }

/* Problem, Memory: the processor and the graphics chip connect to one memory. */
.scene-problem[data-phase="0"] .cell::before { opacity: 0; }
.scene-problem[data-phase="0"] .wire { animation: story-drop .35s var(--ease-out) .1s backwards; }
.scene-problem[data-phase="0"] .chip + .chip .wire { animation-delay: .25s; }
.scene-problem[data-phase="0"] .mem-box::after { animation: story-flash .6s ease-in-out .4s; }
/* Loading: the model and its file copies fill the memory. */
.scene-problem[data-phase="1"] .cell::before { animation: story-in .2s ease-out var(--d) backwards; }
/* The start and the repeats have not happened yet in the first stages. */
.scene-problem:is([data-phase="0"], [data-phase="1"]) .tp-start .tile-before { opacity: 1; }
.scene-problem:is([data-phase="0"], [data-phase="1"]) .tp-start .tile-after { opacity: 0; }
.scene-problem:is([data-phase="0"], [data-phase="1"]) .tp-start .track b { transform: scaleX(0); }
.scene-problem:is([data-phase="0"], [data-phase="1"], [data-phase="2"]) .tp-repeat :is(em, .tile-foot) { opacity: 0; }
.scene-problem:is([data-phase="0"], [data-phase="1"], [data-phase="2"]) .tp-repeat .track b { transform: scaleX(0); }
/* Stall: the start stops partway, with no free memory left. */
.scene-problem[data-phase="2"] .cell.f::after { opacity: 1; animation: story-in .25s ease-out .6s backwards; }
.scene-problem[data-phase="2"] .tp-start .tile-mid { animation: story-lead .6s linear; }
.scene-problem[data-phase="2"] .tp-start .tile-after { animation: story-in .25s ease-out .6s backwards; }
.scene-problem[data-phase="2"] .bar-go { animation: story-grow .5s cubic-bezier(.2, .7, .2, 1) .1s backwards; }
.scene-problem[data-phase="2"] .bar-stop { animation: story-in .25s ease-out .6s backwards; }
/* Repeats: the same request takes the full time again. */
.scene-problem[data-phase="3"] .run-1 .track b { animation: story-grow .35s linear .05s backwards; }
.scene-problem[data-phase="3"] .run-1 em { animation: story-in .2s ease-out .4s backwards; }
.scene-problem[data-phase="3"] .run-2 .track b { animation: story-grow .35s linear .45s backwards; }
.scene-problem[data-phase="3"] .run-2 em { animation: story-in .2s ease-out .8s backwards; }
.scene-problem[data-phase="3"] .tile-foot { animation: story-in .2s ease-out .8s backwards; }

/* Decisions, Guard: loading leaves file copies, and the guard clears them before they reach the 8 GiB
   that it keeps free. The model finishes loading and starts. */
.scene-choices:is([data-phase="0"], [data-phase="1"]) .guard-on { opacity: 1; }
.scene-choices:is([data-phase="0"], [data-phase="1"]) .guard-off { opacity: 0; }
.scene-choices[data-phase="0"] .cell.m::before { animation: story-in .2s ease-out var(--d) backwards; }
.scene-choices[data-phase="0"] .f0::before { animation: story-f0 .85s linear; }
.scene-choices[data-phase="0"] .f1::before { animation: story-f1 .85s linear; }
.scene-choices[data-phase="0"] .f2::before { animation: story-f2 .85s linear; }
.scene-choices[data-phase="0"] .f3::before { animation: story-f3 .85s linear; }
.scene-choices[data-phase="0"] :is(.f0, .f1, .f2, .f3)::after { animation: story-clear .85s linear; }
.scene-choices[data-phase="0"] .guard-on i::after { animation: story-pulse .85s linear; }
.scene-choices[data-phase="0"] .t1 .tile-mid { animation: story-lead .8s linear; }
.scene-choices[data-phase="0"] .t1 .tile-after { animation: story-in .2s ease-out .8s backwards; }
/* Default: holding memory back would hide 6.2 GiB from the startup check. The what-if state stays up
   for about 1 s so it can be read. */
.scene-choices[data-phase="1"] .hold { animation: story-show 1.5s ease-in-out .1s; }
.scene-choices[data-phase="1"] .t1 .tile-mid2 { animation: story-show 1.3s ease-in-out .25s; }
.scene-choices[data-phase="1"] .t1 .tile-after { animation: story-gone 1.3s ease-in-out .25s; }
/* Warm-up: the guard stops, and one practice request reads the whole model. */
.scene-choices[data-phase="2"] .guard-on { animation: story-lead .3s linear; }
.scene-choices[data-phase="2"] .guard-off { animation: story-in .2s ease-out .3s backwards; }
.scene-choices[data-phase="2"] .cell.m::after { animation: story-flash .25s ease-in-out calc(200ms + var(--i) * 45ms); }
.scene-choices:is([data-phase="0"], [data-phase="1"]) .t2 .tile-before { opacity: 1; }
.scene-choices:is([data-phase="0"], [data-phase="1"]) .t2 .tile-after { opacity: 0; }
.scene-choices[data-phase="2"] .t2 .tile-before { animation: story-lead .8s linear; }
.scene-choices[data-phase="2"] .t2 .tile-after { animation: story-in .2s ease-out .8s backwards; }
/* Cache: the first run takes 191.7 s, and the repeat starts in 2.98 s. */
.scene-choices:is([data-phase="0"], [data-phase="1"], [data-phase="2"]) .t3 .tile-before { opacity: 1; }
.scene-choices:is([data-phase="0"], [data-phase="1"], [data-phase="2"]) .t3 .tile-after { opacity: 0; }
.scene-choices:is([data-phase="0"], [data-phase="1"], [data-phase="2"]) .t3 .track b { transform: scaleX(0); }
.scene-choices[data-phase="3"] .t3 .tile-before { animation: story-lead .45s linear; }
.scene-choices[data-phase="3"] .t3 .tile-mid { animation: story-show .4s linear .45s; }
.scene-choices[data-phase="3"] .t3 .tile-after { animation: story-in .2s ease-out .8s backwards; }
.scene-choices[data-phase="3"] .t3 .old { animation: story-grow .4s linear .05s backwards; }
.scene-choices[data-phase="3"] .t3 .new { animation: story-grow .2s ease-out .65s backwards; }
/* Clock: the power bar shrinks while the speed stays the same. */
.scene-choices:is([data-phase="0"], [data-phase="1"], [data-phase="2"], [data-phase="3"]) .t4 .tile-before { opacity: 1; }
.scene-choices:is([data-phase="0"], [data-phase="1"], [data-phase="2"], [data-phase="3"]) .t4 .tile-after { opacity: 0; }
.scene-choices:is([data-phase="0"], [data-phase="1"], [data-phase="2"], [data-phase="3"]) .t4 .pw { transform: scaleX(1); background: #9aa69e; }
.scene-choices[data-phase="4"] .t4 .tile-before { animation: story-lead .6s linear; }
.scene-choices[data-phase="4"] .t4 .tile-after { animation: story-in .25s ease-out .6s backwards; }
.scene-choices[data-phase="4"] .t4 .pw { animation: story-shrink .5s cubic-bezier(.2, .7, .2, 1) .1s backwards; }

/* Evidence: each stage marks its group and plays once. */
.proof-local[data-phase="0"] .proof-tiles li { animation: story-rise .35s cubic-bezier(.22, 1, .36, 1) calc(100ms + var(--k) * 150ms) backwards; }
.proof-local[data-phase="1"] .pg-merged .status-label { animation: story-stamp .3s cubic-bezier(.22, 1, .36, 1) calc(150ms + var(--k) * 200ms) backwards; }
.proof-local[data-phase="2"] .mini-bars .old { animation: story-grow .45s cubic-bezier(.22, 1, .36, 1) .1s backwards; }
.proof-local[data-phase="2"] .mini-bars .new { animation: story-grow .25s ease-out .55s backwards; }

/* Approach, My part: my work in green, other people's work in pink. */
.dgx-scene[data-phase="3"] .a3-api-block > path:first-of-type { fill: #19e76e; transition: fill .35s .1s; }
.dgx-scene[data-phase="3"] .a3-api-mark { stroke: #101612; transition: stroke .35s .1s; }
.dgx-scene[data-phase="3"] .a3-worker-light { fill: #0a8f43; transition: fill .35s .35s; }
.dgx-scene[data-phase="3"] .a3-worker-top { fill: #ffa9fd; transition: fill .35s .55s; }
.dgx-scene:not([data-phase="3"]) .own-legend { opacity: 0; transition: opacity .2s; }
/* Approach on the case page: each packet and route finishes within 1 s of its stage start. The home page
   keeps the timing in diagrams.css. */
.dgx-scene[data-phase="0"] .a3-link-request { animation: a3-draw .5s cubic-bezier(.76, .08, .16, 1) .1s both; }
.dgx-scene[data-phase="0"] .a3-token-request { animation: a3-carry .5s cubic-bezier(.76, .08, .16, 1) .1s both, a3-deliver .15s ease-out .6s forwards; }
.dgx-scene[data-phase="0"] .a3-request-route { animation: a3-route-on .2s ease-out .6s both; }
.dgx-scene[data-phase="1"] .a3-link-node { animation: a3-draw .55s cubic-bezier(.76, .08, .16, 1) .1s both; }
.dgx-scene[data-phase="1"] :is(.a3-token-node-a, .a3-token-node-b) { animation: a3-carry .55s cubic-bezier(.76, .08, .16, 1) .1s both, a3-deliver .15s ease-out .65s forwards; }
.dgx-scene[data-phase="1"] .a3-compute-route { animation: a3-route-on .2s ease-out .65s both; }
.dgx-scene[data-phase="1"] .a3-worker-light { animation: a3-worker-on .2s ease-out .65s both, a3-worker-pulse 1.6s ease-in-out .85s infinite; }
.dgx-scene[data-phase="1"] .a3-worker-top { animation: a3-worker-top .3s ease-out .65s both; }
.dgx-scene[data-phase="2"] .a3-link-return { animation: a3-draw .5s cubic-bezier(.76, .08, .16, 1) .05s both; }
.dgx-scene[data-phase="2"] :is(.a3-token-return-a, .a3-token-return-b) { animation: a3-carry .5s cubic-bezier(.76, .08, .16, 1) .05s both, a3-deliver .1s ease-out .55s forwards; }
.dgx-scene[data-phase="2"] .a3-response-route { animation: a3-route-on .2s ease-out .55s both; }
.dgx-scene[data-phase="2"] .a3-response-route:last-child { animation-delay: .85s; }
.dgx-scene[data-phase="2"] .a3-link-client { animation: a3-draw .3s cubic-bezier(.76, .08, .16, 1) .55s both; }
.dgx-scene[data-phase="2"] .a3-token-return-client { animation: a3-carry .3s cubic-bezier(.76, .08, .16, 1) .55s both, a3-deliver .1s ease-out .85s forwards; }

/* Modly. A 16 GB graphics card drawn as 16 blocks of 1 GB. The texture pass reserved 20.4 GB, so the
   last blocks sit past the card's edge. */
.model-tags { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 14px; margin-bottom: 12px; font-size: 13px; color: #234a32; }
.model-tags .mem-name { margin-right: 2px; }
.model-tags span:not(.mem-name)::before { content: ''; display: inline-block; width: 10px; height: 10px; margin-right: 6px; vertical-align: -1px; background: #19e76e; border: 1px solid #0a8f43; }
.vram { display: grid; grid-template-columns: repeat(16, minmax(0, 1fr)) 10px repeat(5, minmax(0, 1fr)); grid-template-rows: auto 40px auto; column-gap: 4px; padding: 0 10px; }
.vram > .mem-name { position: relative; z-index: 1; white-space: nowrap; }
.story-art .vram-label { grid-row: 1; grid-column: 1 / 17; padding: 11px 0 9px; }
.story-art .over-label { grid-row: 3; grid-column: 1 / -1; justify-self: end; padding-top: 8px; color: #8a2f55; }
.card-frame, .over-frame { position: relative; grid-row: 1 / 3; margin: 0 -9px -10px -10px; }
.card-frame { grid-column: 1 / 17; background: #fff; border: 1px solid #afcfb8; }
.card-frame::after { content: ''; position: absolute; inset: -1px; border: 2px solid #19e76e; opacity: 0; }
.over-frame { grid-row: 2; grid-column: 18 / 23; margin: -5px -10px -5px -5px; border: 1px dashed #8a2f55; }
.vram .cell { grid-row: 2; z-index: 1; }
.cell.x { background: none; border-color: transparent; }
.cell.x::before { opacity: 1; background: repeating-linear-gradient(45deg, #fff 0 3px, #e9c9d7 3px 5px); border: 1px solid #8a2f55; }
.cell.x.part::before { right: auto; width: calc(40% + 1px); }

/* Card: the card and its sixteen empty blocks. */
.scene-vram[data-phase="0"] :is(.model-tags span:not(.mem-name), .over-frame, .over-label, .cell.x) { opacity: 0; }
.scene-vram[data-phase="0"] .cell.m::before { opacity: 0; }
.scene-vram[data-phase="0"] .card-frame::after { animation: story-flash .6s ease-in-out .2s; }
/* Models: the three models load and fill the card. */
.scene-vram[data-phase="1"] :is(.over-frame, .over-label, .cell.x) { opacity: 0; }
.scene-vram[data-phase="1"] .model-tags span:not(.mem-name) { animation: story-rise .3s cubic-bezier(.22, 1, .36, 1) calc(80ms + var(--k) * 120ms) backwards; }
.scene-vram[data-phase="1"] .cell.m::before { animation: story-in .2s ease-out var(--d) backwards; }
/* Too big: the reserved memory runs 4.4 GB past the card's edge. */
.scene-vram[data-phase="2"] .over-frame { animation: story-in .2s ease-out .05s backwards; }
.scene-vram[data-phase="2"] .cell.x { animation: story-in .2s ease-out var(--d) backwards; }
.scene-vram[data-phase="2"] .over-label { animation: story-in .2s ease-out .75s backwards; }
.scene-vram:is([data-phase="0"], [data-phase="1"]) .tile-before { opacity: 1; }
.scene-vram:is([data-phase="0"], [data-phase="1"]) .tile-after { opacity: 0; }
.scene-vram[data-phase="2"] .tile-before { animation: story-lead .8s linear; }
.scene-vram[data-phase="2"] .tile-after { animation: story-in .2s ease-out .8s backwards; }

/* Approach, Result: the same card with 13.0 GB reserved. */
.card-strip { max-width: 520px; margin: 18px auto 0; transition: opacity .3s; }
.card-strip .mem-head { margin-bottom: 8px; }
.story-art .strip-value, .card-strip .strip-value { color: #0a6b35; }
.card-strip p { margin: 0; }
.card-strip .mem { padding: 8px; background: #fff; border: 1px solid #afcfb8; }
.card-strip .cell { grid-row: 1; height: 26px; }
.modly-scene:not([data-phase="3"]) .card-strip { opacity: 0; transition: opacity .2s; }
.modly-scene[data-phase="3"] .card-strip .cell.m::before { animation: story-in .2s ease-out var(--d) backwards; }
.modly-scene:not([data-gsap])[data-phase="3"] .a3-component-encoder { transform: none; }
/* On the case page, modly-motion.js plays each move at twice the speed, so the memory transfer lights
   sooner to match. */
.modly-scene[data-gsap][data-phase="0"] .a3-transfer-encoder, .modly-scene[data-gsap][data-phase="1"] .a3-transfer-diffusion,
.modly-scene[data-gsap][data-phase="2"] .a3-transfer-vae { transition: opacity .25s .6s; }

/* Decisions: the note over the Auto switch. */
.story-art .mv-note { margin-bottom: 5px; font: 10px var(--mono); text-transform: uppercase; letter-spacing: .03em; color: #4b6653; }
.mv .mini-bars b { transform: scaleX(var(--v, 1)); }
.mini-bars .now { background: #0a8f43; }

/* Evidence: the results rise, then the tree and its model. */
.proof-modly[data-phase="0"] .proof-tiles li { animation: story-rise .35s cubic-bezier(.22, 1, .36, 1) calc(100ms + var(--k) * 150ms) backwards; }
.proof-modly[data-phase="1"] .result-pair-images > * { animation: story-rise .35s cubic-bezier(.22, 1, .36, 1) calc(100ms + var(--k) * 200ms) backwards; }
.proof-modly[data-phase="1"] .proof-note { animation: story-in .25s ease-out .6s backwards; }
.proof-art .result-pair-images { max-width: 520px; }
.proof-art .result-pair-images img { border: 1px solid #dce6de; }
.story-art .proof-note { margin-top: 12px; font-size: 13px; line-height: 1.5; color: #415849; }

@media (max-width: 480px) {
  .vram { grid-template-columns: repeat(16, minmax(0, 1fr)) 6px repeat(5, minmax(0, 1fr)); grid-template-rows: auto 30px auto; column-gap: 2px; padding: 0 8px; }
  .card-frame { margin: 0 -5px -8px -8px; }
  .over-frame { margin: -4px -8px -4px -3px; }
  .card-strip .cell { height: 22px; }
}

/* EARS Bridge. The problem: two microphones, one Dirac input, and two clocks. */
.rig { display: block; width: 100%; height: auto; overflow: visible; font-family: var(--mono); }
.rig text { font-size: 15px; letter-spacing: .02em; fill: #234a32; }
.rig .rig-label { fill: #4b6653; font-size: 13px; }
.rig-box { fill: #fff; stroke: #afcfb8; stroke-width: 1; }
.rig-mic rect { fill: #fff; stroke: #83b595; stroke-width: 1.2; }
.rig-mic-l rect { fill: #c9fbdc; stroke: #0a8f43; }
.rig-mic-r rect { fill: #fbeef4; stroke: #8a2f55; }
.rig-leak { fill: none; stroke: #8a2f55; stroke-width: 1.6; stroke-dasharray: 4 3; }
.rig .rig-leak-label, .rig .rig-status { fill: #8a2f55; }
.rig .rig-status { font-size: 16px; font-weight: 600; }
.rig-wire { fill: none; stroke: #8a2f55; stroke-width: 1.8; }
.rig-node { fill: #fbeef4; stroke: #8a2f55; stroke-width: 1.4; }
.rig .rig-plus { font-size: 22px; fill: #8a2f55; }
.rig .rig-node-label { fill: #8a2f55; font-size: 13px; }
.rig .rig-q { font-size: 24px; fill: #4b6653; opacity: 0; }
.rig-socket { fill: #fff; stroke: #4b6653; stroke-width: 1.4; }
.clocks { display: grid; gap: 6px; margin: 16px 0 14px; }
.story-art .clock { display: grid; grid-template-columns: 92px minmax(0, 1fr) 46px; align-items: center; gap: 12px; }
.ticks { display: flex; justify-content: space-between; height: 16px; }
.ticks i { width: 2px; background: #0a8f43; }
.clock-drift .ticks i { background: #8a2f55; transform: translateX(calc(var(--i) * 1px)); }
.clock em { padding-left: 4px; font: 11px var(--mono); font-style: normal; color: #8a2f55; }

/* Inputs: two microphones, one input, and nothing yet to join them. */
.scene-mics[data-phase="0"] :is(.rig-leak, .rig-leak-label, .rig-wire, .rig-node, .rig-plus, .rig-node-label, .rig-status) { opacity: 0; }
.scene-mics[data-phase="0"] .rig-mic rect { fill: #fff; stroke: #83b595; }
.scene-mics[data-phase="0"] .rig-q { opacity: 1; animation: story-in .25s ease-out .6s backwards; }
.scene-mics[data-phase="0"] .rig-mic { animation: story-in .25s ease-out .1s backwards; }
.scene-mics[data-phase="0"] .rig-mic-r { animation-delay: .25s; }
.scene-mics[data-phase="0"] .rig-socket { animation: story-flash .5s ease-in-out .35s; }
/* Mixing: sound in the left ear leaks into the right microphone, and the mix passes both on. */
.scene-mics[data-phase="1"] .rig-status { opacity: 0; }
.scene-mics[data-phase="1"] .rig-mic-l rect { animation: story-in .2s ease-out .05s backwards; }
.scene-mics[data-phase="1"] :is(.rig-leak, .rig-leak-label) { animation: story-in .2s ease-out .2s backwards; }
.scene-mics[data-phase="1"] .rig-mic-r rect { animation: story-in .2s ease-out .35s backwards; }
.scene-mics[data-phase="1"] :is(.rig-wire-l, .rig-wire-r) { animation: story-in .2s ease-out .5s backwards; }
.scene-mics[data-phase="1"] :is(.rig-node, .rig-plus, .rig-node-label) { animation: story-in .2s ease-out .65s backwards; }
.scene-mics[data-phase="1"] .rig-wire-out { animation: story-in .2s ease-out .8s backwards; }
/* Timing: the cable clock drifts away from the jig clock, and Dirac rejects the measurement. */
.scene-mics:is([data-phase="0"], [data-phase="1"]) .clock-drift .ticks i { transform: none; }
.scene-mics:is([data-phase="0"], [data-phase="1"]) .clock em { opacity: 0; }
.scene-mics[data-phase="2"] .clock-drift .ticks i { animation: tick-drift .6s linear .1s backwards; }
.scene-mics[data-phase="2"] .clock em { animation: story-in .2s ease-out .7s backwards; }
.scene-mics[data-phase="2"] .rig-status { animation: story-in .2s ease-out .8s backwards; }
.scene-mics[data-phase="0"] .tile-before { opacity: 1; }
.scene-mics[data-phase="0"] .tile-after { opacity: 0; }
.scene-mics[data-phase="1"] .s2 .tile-before { opacity: 1; }
.scene-mics[data-phase="1"] .s2 .tile-after { opacity: 0; }
.scene-mics[data-phase="1"] .s1 .tile-before { animation: story-lead .8s linear; }
.scene-mics[data-phase="1"] .s1 .tile-after { animation: story-in .2s ease-out .8s backwards; }
.scene-mics[data-phase="2"] .s2 .tile-before { animation: story-lead .8s linear; }
.scene-mics[data-phase="2"] .s2 .tile-after { animation: story-in .2s ease-out .8s backwards; }
@keyframes tick-drift { from { transform: none; } }

/* Approach, My part: the app is the part between the jig and Dirac Live. */
.ear-app { fill: none; stroke: #0a8f43; stroke-width: 1.6; stroke-dasharray: 6 4; opacity: 0; }
.ear-diagram .ear-app-label { font-size: 22px; fill: #0a6b35; opacity: 0; }
.ears-scene[data-phase="2"] :is(.ear-app, .ear-app-label) { opacity: 1; transition: opacity .3s .2s; }
.ears-scene[data-phase="2"] .ear-channel { opacity: 1; }
.ears-scene[data-phase="2"] :is(.ear-link, .ear-channel .ear-sweep) { opacity: 1; }
.ears-scene[data-phase="2"] .ear-channel-left .ear-contact { fill: #13b15a; }
.ears-scene[data-phase="2"] .ear-channel-right .ear-contact { fill: #ba6db1; }
.ears-scene[data-phase="2"] .ear-lever { transform: rotate(0deg); }
/* On the case page, each ear's path and sweeps finish within 1 s of its stage start. The home page keeps
   the timing in motion.css. */
.ears-scene[data-phase="0"] .ear-channel-left .ear-link, .ears-scene[data-phase="1"] .ear-channel-right .ear-link { animation: ear-draw .4s cubic-bezier(.22, 1, .36, 1) .1s both; }
.ears-scene[data-phase="0"] .ear-out-left .ear-out-wire, .ears-scene[data-phase="1"] .ear-out-right .ear-out-wire { animation: ear-draw .15s linear .45s both; }
.ears-scene[data-phase="0"] .ear-channel-left .ear-sweep, .ears-scene[data-phase="1"] .ear-channel-right .ear-sweep { animation: ear-draw .45s linear .5s both; }
.ears-scene[data-phase="0"] .ear-out-left .ear-sweep, .ears-scene[data-phase="1"] .ear-out-right .ear-sweep { animation: ear-draw .45s linear .55s both; }

/* Decisions: two clocks that stay in step while a test sound plays. */
.mv-ticks { position: relative; display: grid; gap: 5px; }
.story-art .mv-ticks p { display: grid; grid-template-columns: 38px minmax(0, 1fr); align-items: center; gap: 6px; font: 10px var(--mono); text-transform: uppercase; letter-spacing: .03em; color: #4b6653; }
.mv-ticks b { display: flex; justify-content: space-between; height: 12px; }
.mv-ticks b i { width: 2px; background: #0a8f43; }
.mv-band { position: absolute; top: -3px; bottom: -3px; left: calc(44px + 22%); width: 46%; background: #19e76e2e; border: 1px solid #0a8f43; transform-origin: left; }
.scene-board[data-phase="1"] .b1 .mv-band { animation: mv-sweep .6s cubic-bezier(.76, .08, .16, 1) .1s backwards; }
@keyframes mv-sweep { from { transform: scaleX(0); } }

/* Evidence: each audit row turns from its old behavior to the new one. */
.audit { display: grid; }
.audit-head, .audit-rows li { display: grid; grid-template-columns: minmax(0, 1.25fr) minmax(0, 1fr) minmax(0, 1.2fr); gap: 4px 14px; align-items: baseline; }
.story-art .audit-head { padding-bottom: 8px; border-bottom: 1px solid #dce6de; font: 10px var(--mono); text-transform: uppercase; letter-spacing: .035em; color: #4b6653; }
.audit-rows { list-style: none; margin: 0; padding: 0; }
.audit-rows li { padding: 9px 0; border-bottom: 1px dashed var(--line); font-size: 13px; line-height: 1.4; }
.audit-what { color: var(--ink); font-weight: 500; }
.audit-was { color: #6f7d73; text-decoration: line-through; text-decoration-color: #b9c9bd; }
.audit-now { display: flex; align-items: baseline; gap: 6px; color: #0b3b1f; }
.audit-now .mv-mark { transform: translateY(1px); }
.proof-tiles-2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.proof-ears[data-phase="0"] .audit-now { animation: story-rise .3s cubic-bezier(.22, 1, .36, 1) calc(150ms + var(--k) * 140ms) backwards; }
.proof-ears[data-phase="1"] .proof-tiles li { animation: story-rise .35s cubic-bezier(.22, 1, .36, 1) calc(100ms + var(--k) * 150ms) backwards; }
.proof-ears[data-phase="1"] .proof-note { animation: story-in .25s ease-out .5s backwards; }

@media (max-width: 620px) {
  .audit-head { display: none; }
  .audit-rows li { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); }
  .audit-what { grid-column: 1 / -1; }
}
@media (max-width: 480px) {
  .rig text { font-size: 24px; }
  .rig .rig-label, .rig .rig-node-label { font-size: 21px; }
  .rig .rig-status { font-size: 24px; }
  .story-art .clock { grid-template-columns: 84px minmax(0, 1fr) 38px; gap: 8px; }
  .clock .mem-name { font-size: 10px; letter-spacing: .02em; }
}

/* Hermes Classic Gold. The problem: the first version's tape lived inside the Hermes code as a patch. */
.story-art .mini-tape { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 18px; margin-bottom: 14px; padding: 10px 12px; background: #fff; border: 1px solid #78ba92; border-top: 2px solid #19e76e; }
.story-art .mini-tape span:not(.mem-name) { display: inline-flex; align-items: center; gap: 8px; font: 11px var(--mono); text-transform: uppercase; letter-spacing: .03em; color: #234a32; }
.mini-tape i { width: 34px; height: 6px; background: #3d624a; }
.code-box { position: relative; overflow: hidden; margin-bottom: 14px; padding: 12px 14px 14px; background: #fff; border: 1px solid #afcfb8; }
.story-art .code-note { color: #6f7d73; text-transform: none; letter-spacing: 0; font-size: 11px; }
.code-lines { list-style: none; display: grid; gap: 8px; margin: 10px 0 0; padding: 0; }
.code-lines li { height: 8px; width: calc(var(--w, 1) * 100%); background: #e3ebe4; }
.code-lines li:is(.patch-line, .undone-line) { grid-row: 3; grid-column: 1; width: 62%; height: 26px; display: flex; align-items: center; padding: 0 10px; font: 11px var(--mono); text-transform: uppercase; letter-spacing: .03em; }
.patch-line { background: #19e76e; border: 1px solid #0a8f43; color: #0b3b1f; opacity: 0; }
.code-lines .undone-line { background: none; border: 1px dashed #8a2f55; color: #8a2f55; }
.update-sweep { position: absolute; top: 0; bottom: 0; left: 0; width: 34%; display: flex; align-items: flex-end; justify-content: center; padding-bottom: 6px; background: linear-gradient(90deg, #ffffff00, #dbeee1 40%, #dbeee1 60%, #ffffff00); opacity: 0; pointer-events: none; }
.update-sweep span { font: 10px var(--mono); text-transform: uppercase; letter-spacing: .03em; color: #234a32; white-space: nowrap; }

/* Tape: the numbers a session needs, side by side. */
.scene-patch[data-phase="0"] .mini-tape span:not(.mem-name) { animation: story-rise .3s cubic-bezier(.22, 1, .36, 1) calc(100ms + var(--k) * 120ms) backwards; }
.scene-patch[data-phase="0"] .undone-line { opacity: 0; }
/* Patch: the tape goes into the Hermes code. */
.scene-patch[data-phase="1"] .patch-line { opacity: 1; animation: story-rise .35s cubic-bezier(.22, 1, .36, 1) .15s backwards; }
.scene-patch[data-phase="1"] .undone-line { opacity: 0; }
/* Update: an update replaces the code, and the patch goes with it. */
.scene-patch[data-phase="2"] .update-sweep { animation: patch-sweep .7s cubic-bezier(.45, 0, .2, 1) .1s; }
.scene-patch[data-phase="2"] .patch-line { animation: story-lead .45s linear; }
.scene-patch[data-phase="2"] .undone-line { animation: story-in .2s ease-out .5s backwards; }
.scene-patch[data-phase="0"] .tile-before { opacity: 1; }
.scene-patch[data-phase="0"] .tile-after { opacity: 0; }
.scene-patch[data-phase="1"] .s2 .tile-before { opacity: 1; }
.scene-patch[data-phase="1"] .s2 .tile-after { opacity: 0; }
.scene-patch[data-phase="1"] .s1 .tile-before { animation: story-lead .5s linear; }
.scene-patch[data-phase="1"] .s1 .tile-after { animation: story-in .2s ease-out .5s backwards; }
.scene-patch[data-phase="2"] .s2 .tile-before { animation: story-lead .8s linear; }
.scene-patch[data-phase="2"] .s2 .tile-after { animation: story-in .2s ease-out .8s backwards; }
@keyframes patch-sweep { 0% { opacity: 1; transform: translateX(-100%); } 100% { opacity: 1; transform: translateX(300%); } }

/* Approach, Summary: every source connected and every field filled. */
.hermes-scene[data-phase="3"] .a3-tape-fill-context { transform: scaleX(.62); }
.hermes-scene[data-phase="3"] .a3-tape-fill-ram { transform: scaleX(.58); }
.hermes-scene[data-phase="3"] .a3-tape-fill-vram { transform: scaleX(.74); }
.hermes-scene[data-phase="3"] .a3-tape-rule { transform: scaleX(1); }
.hermes-scene[data-phase="3"] :is(.a3-tape-cache, .a3-tape-cost) { opacity: 1; }
.hermes-scene[data-phase="3"] :is(.a3-tape-dash-cache, .a3-tape-dash-cost, .a3-tape-chip-light) { opacity: 0; }
.hermes-scene[data-phase="3"] :is(.a3-tape-record-lit, .a3-tape-trace-record, .a3-tape-link-session, .a3-tape-gpu-lit, .a3-tape-ram-lit, .a3-tape-trace-gpu, .a3-tape-trace-ram, .a3-tape-link-host, .a3-tape-chip-light-host) { opacity: 1; }
/* On the case page, each stage's menu, packet, and gauges finish within 1 s of its start. The home page
   keeps the timing in diagrams.css. */
.hermes-scene[data-phase="0"] .a3-tape-chevron { animation: a3-tape-flip .9s cubic-bezier(.22, 1, .36, 1) .05s both; }
.hermes-scene[data-phase="0"] .a3-tape-menu { animation: a3-tape-menu .9s cubic-bezier(.22, 1, .36, 1) .05s both; }
.hermes-scene[data-phase="0"] .a3-tape-menu-hover { animation: a3-tape-down .15s cubic-bezier(.22, 1, .36, 1) .35s both; }
.hermes-scene[data-phase="0"] .a3-tape-check { animation: a3-tape-down .1s ease-out .55s both; }
.hermes-scene[data-phase="0"] .a3-tape-model-a { animation: a3-tape-out .1s ease-out .85s both; }
.hermes-scene[data-phase="0"] .a3-tape-model-b { animation: a3-tape-in .15s ease-out .85s both; }
.hermes-scene[data-phase="1"] .a3-tape-record-lit { animation: a3-tape-in .25s ease-out both; }
.hermes-scene[data-phase="1"] .a3-tape-trace-record { animation: a3-draw .3s cubic-bezier(.76, .08, .16, 1) .05s both; }
.hermes-scene[data-phase="1"] .a3-tape-chip-light { animation: a3-light-on .2s ease-out .3s both; }
.hermes-scene[data-phase="1"] .a3-tape-link-session { animation: a3-draw .4s cubic-bezier(.76, .08, .16, 1) .35s both; }
.hermes-scene[data-phase="1"] .a3-tape-packet-session { animation: a3-carry .4s cubic-bezier(.76, .08, .16, 1) .35s both, a3-deliver .1s ease-out .75s forwards; }
.hermes-scene[data-phase="1"] .a3-tape-rule-session { animation: a3-tape-grow .15s cubic-bezier(.22, 1, .36, 1) .75s both; }
.hermes-scene[data-phase="1"] .a3-tape-fill-context { animation: a3-tape-grow .25s cubic-bezier(.22, 1, .36, 1) .75s both; }
.hermes-scene[data-phase="1"] .a3-tape-dash-cache { animation: a3-tape-out .1s ease-out .8s both; }
.hermes-scene[data-phase="1"] .a3-tape-cache { animation: a3-tape-in .15s ease-out .85s both; }
.hermes-scene[data-phase="1"] .a3-tape-dash-cost { animation: a3-tape-out .1s ease-out .85s both; }
.hermes-scene[data-phase="1"] .a3-tape-cost { animation: a3-tape-in .15s ease-out .85s both; }
.hermes-scene[data-phase="2"] :is(.a3-tape-gpu-lit, .a3-tape-ram-lit) { animation: a3-tape-in .25s ease-out both; }
.hermes-scene[data-phase="2"] :is(.a3-tape-trace-gpu, .a3-tape-trace-ram) { animation: a3-draw .3s cubic-bezier(.76, .08, .16, 1) .05s both; }
.hermes-scene[data-phase="2"] .a3-tape-chip-light-host { animation: a3-tape-in .2s ease-out .3s both; }
.hermes-scene[data-phase="2"] .a3-tape-link-host { animation: a3-draw .45s cubic-bezier(.76, .08, .16, 1) .35s both; }
.hermes-scene[data-phase="2"] .a3-tape-packet-host { animation: a3-carry .45s cubic-bezier(.76, .08, .16, 1) .35s both, a3-deliver .1s ease-out .8s forwards; }
.hermes-scene[data-phase="2"] .a3-tape-rule-host { animation: a3-tape-grow .15s cubic-bezier(.22, 1, .36, 1) .8s both; }
.hermes-scene[data-phase="2"] .a3-tape-fill-ram { animation: a3-tape-grow .2s cubic-bezier(.22, 1, .36, 1) .8s both; }
.hermes-scene[data-phase="2"] .a3-tape-fill-vram { animation: a3-tape-grow .2s cubic-bezier(.22, 1, .36, 1) .8s both; }

/* Decisions: a tape field with no known value, and the tape at three window widths. */
.story-art .mv-tape { display: flex; gap: 14px; padding: 6px 8px; border: 1px solid #78ba92; font: 10px var(--mono); text-transform: uppercase; letter-spacing: .03em; color: #4b6653; }
.mv-tape b { margin-left: 4px; color: #234a32; }
.mv-widths { display: grid; gap: 4px; }
.story-art .mv-widths p { display: grid; grid-template-columns: minmax(0, 1fr) 54px; align-items: center; gap: 8px; font: 10px var(--mono); color: #4b6653; }
.mv-widths b { display: block; height: 7px; width: calc(var(--w) * 100%); background: #fff; border: 1px solid #78ba92; border-top: 2px solid #19e76e; }
.mv-widths b.off { border: 1px dashed #9aa69e; border-top: 1px dashed #9aa69e; }
.scene-board[data-phase="3"] .b3 .mv-widths p { animation: story-rise .3s cubic-bezier(.22, 1, .36, 1) calc(150ms + var(--k) * 130ms) backwards; }

/* Evidence: the gauge added two requests together. */
.count-bars { display: grid; grid-template-columns: auto minmax(0, 1fr) auto; align-items: center; gap: 7px 12px; font-size: 13px; color: #415849; }
.count-bars .track { margin: 0; height: 8px; }
.count-bars b { transform: scaleX(var(--v)); }
.count-bars .now { background: #0a8f43; }
.count-bars .old { background: #9aa69e; }
.count-bars .bad { background: #8a2f55; }
.count-bars .val-fail { color: #8a2f55; font-weight: 600; }
.count-bars span:nth-child(3n) { font: 12px var(--mono); text-align: right; }
.proof-hermes[data-phase="0"] .count-bars b { animation: story-grow .4s cubic-bezier(.22, 1, .36, 1) calc(100ms + var(--k) * 150ms) backwards; }
.proof-hermes[data-phase="0"] .proof-note { animation: story-in .25s ease-out .75s backwards; }
.proof-hermes[data-phase="1"] .pr-rows .status-label { animation: story-stamp .3s cubic-bezier(.22, 1, .36, 1) calc(150ms + var(--k) * 150ms) backwards; }
.proof-hermes[data-phase="2"] .proof-tiles li { animation: story-rise .35s cubic-bezier(.22, 1, .36, 1) calc(100ms + var(--k) * 150ms) backwards; }
.proof-hermes[data-phase="2"] .proof-note { animation: story-in .25s ease-out .5s backwards; }

@media (max-width: 480px) {
  .story-art .mini-tape { gap: 8px 12px; }
  .mini-tape i { width: 22px; }
  .count-bars { grid-template-columns: minmax(0, 7.5em) minmax(0, 1fr) auto; column-gap: 10px; }
}

/* WaveGrating. The problem: the colors a CD sends to the eye, and what a ray renderer computes there. */
.cd-fan { transition: opacity .35s; }
.cd-mirror { transition: stroke .35s; }
.cd-label text { transition: opacity .3s; }
.cd-seen text.cd-seen-none { fill: #8a2f55; }
/* Rays: the rainbow goes, the mirror reflection stays, and the eye gets no color. */
.cd-scene[data-phase="3"] .cd-fan { opacity: 0; }
.cd-scene[data-phase="3"] .cd-label text:nth-child(5) { opacity: 0; }
.cd-scene[data-phase="3"] .cd-mirror { stroke: #234a32; }
.cd-scene[data-phase="3"] .cd-view-ray { stroke: #9aa69e; }
.cd-scene[data-phase="3"] .cd-chip { fill: #cfd6d1; }
.cd-scene[data-phase="3"] .cd-seen-none { opacity: 1; transition: opacity .3s .35s; }
/* Summary: the first view again, with the color the waves give. */
.cd-scene[data-phase="4"] :is(.cd-band-0, .cd-seen-0) { opacity: 1; transition: opacity .3s .35s; }

/* Approach: the scene travels from Blender to a separate worker program. */
.flow { display: grid; grid-template-columns: minmax(0, 1fr) 132px minmax(0, 1.6fr); align-items: center; gap: 10px; }
.flow-box { min-width: 0; padding: 12px 14px 14px; background: #fff; border: 1px solid #afcfb8; transition: border-color .3s, box-shadow .3s; }
.story-art .flow-note { margin-top: 8px; font-size: 14px; line-height: 1.4; color: #415849; }
.story-art .flow-tag { display: inline-block; margin-top: 12px; padding: 3px 7px; border: 1px dashed #9aa69e; font: 10px var(--mono); text-transform: uppercase; letter-spacing: .03em; color: #4b6653; }
.flow-pass { display: grid; justify-items: center; gap: 7px; min-width: 0; text-align: center; }
.flow-file { padding: 6px 9px; background: #c9fbdc; border: 1px solid #0a8f43; font: 11px var(--mono); text-transform: uppercase; letter-spacing: .03em; color: #0b3b1f; white-space: nowrap; transition: border-color .3s, box-shadow .3s; }
.flow-arrow { position: relative; display: block; width: 100%; height: 2px; background: #0a8f43; transform-origin: left; }
.flow-arrow::after { content: ''; position: absolute; right: 0; top: -4px; width: 8px; height: 8px; border-top: 2px solid #0a8f43; border-right: 2px solid #0a8f43; transform: rotate(45deg); }
.flow-sub { font: 10px var(--mono); text-transform: uppercase; letter-spacing: .03em; color: #4b6653; }
.flow-parts { list-style: none; display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 8px; margin: 10px 0 0; padding: 0; }
.flow-parts li { min-width: 0; padding: 8px 10px 9px; background: #fff; border: 1px solid #c9d6cc; transition: border-color .3s, box-shadow .3s; }
.flow-parts b { display: block; font-size: 14px; font-weight: 600; line-height: 1.25; }
.flow-parts span { display: block; margin-top: 3px; font-size: 12px; line-height: 1.35; color: #526358; }
/* Each stage adds its part, and the parts of later stages wait. */
.scene-flow[data-phase="0"] :is(.flow-pass, .flow-parts li),
.scene-flow[data-phase="1"] .flow-parts li,
.scene-flow[data-phase="2"] .flow-parts li.s3 { opacity: 0; }
.scene-flow[data-phase="0"] .fb-blender { animation: story-rise .35s cubic-bezier(.22, 1, .36, 1) .05s backwards; }
.scene-flow[data-phase="0"] .flow-tag { animation: story-in .25s ease-out .45s backwards; }
.scene-flow[data-phase="1"] .flow-file { animation: flow-carry .5s cubic-bezier(.76, .08, .16, 1) .05s backwards; }
.scene-flow[data-phase="1"] .flow-arrow { animation: story-grow .35s cubic-bezier(.22, 1, .36, 1) .5s backwards; }
.scene-flow[data-phase="1"] .flow-sub { animation: story-in .2s ease-out .75s backwards; }
.scene-flow[data-phase="2"] .flow-parts li.s2,
.scene-flow[data-phase="3"] .flow-parts li.s3 { animation: story-rise .35s cubic-bezier(.22, 1, .36, 1) calc(100ms + var(--k) * 200ms) backwards; }
@keyframes flow-carry { from { opacity: 0; transform: translateX(-60px); } }
@keyframes flow-carry-down { from { opacity: 0; transform: translateY(-40px); } }

/* Decisions: the order of steps, as the right and the wrong formula. */
.mv-rule li { gap: 8px; }
.mv-rule code { font: 12px var(--mono); color: var(--ink); white-space: nowrap; }
.mv-rule span { margin-left: auto; font: 10px var(--mono); text-transform: uppercase; letter-spacing: .03em; }
.mv-rule .wrong span { color: #8a2f55; }
.mv-cross { stroke: #8a2f55; }
:is(.mv-rule, .log-labels, .log-keys) :is(sub, sup) { font-size: .75em; line-height: 0; }

/* Evidence: the differences from two independent references on a scale of powers of ten. */
.log-strip { margin: 2px 8px 0; }
.log-axis { position: relative; height: 26px; }
.log-axis::before { content: ''; position: absolute; left: 0; right: 0; bottom: 0; border-top: 1px solid #9fb8a6; }
.log-axis i { position: absolute; bottom: 0; left: calc(var(--x) * 100%); width: 1px; height: 8px; background: #9fb8a6; }
.log-axis b { position: absolute; left: calc(var(--x) * 100%); background: #19e76e; border: 1px solid #0a8f43; }
.log-dot { bottom: 5px; width: 13px; height: 13px; margin-left: -6px; border-radius: 50%; }
.log-range { bottom: 7px; width: calc((var(--x2) - var(--x)) * 100%); height: 9px; transform-origin: left; }
.log-labels { position: relative; height: 16px; margin-top: 6px; font: 11px var(--mono); color: #4b6653; }
.log-labels span { position: absolute; left: calc(var(--x) * 100%); transform: translateX(-50%); white-space: nowrap; }
.log-labels span:first-child { transform: none; }
.log-keys { list-style: none; display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px 16px; margin: 14px 0 0; padding: 0; }
.log-keys li { position: relative; min-width: 0; padding-left: 22px; }
.log-keys li::before { content: ''; position: absolute; left: 0; top: 4px; background: #19e76e; border: 1px solid #0a8f43; }
.log-keys .lk-dot::before { width: 12px; height: 12px; border-radius: 50%; }
.log-keys .lk-range::before { top: 6px; width: 14px; height: 8px; }
.log-keys b { display: block; font-size: 15px; font-weight: 600; line-height: 1.3; }
.log-keys span { display: block; margin-top: 2px; font: 12px var(--mono); color: #415849; }
.proof-wave[data-phase="0"] .pt-checks { animation: story-stamp .35s cubic-bezier(.22, 1, .36, 1) .1s backwards; }
.proof-wave[data-phase="1"] .pt-speed { animation: story-rise .35s cubic-bezier(.22, 1, .36, 1) calc(100ms + var(--k) * 200ms) backwards; }
.proof-wave[data-phase="2"] .log-dot { animation: story-stamp .3s cubic-bezier(.22, 1, .36, 1) .1s backwards; }
.proof-wave[data-phase="2"] .log-range { animation: story-grow .4s cubic-bezier(.22, 1, .36, 1) .3s backwards; }
.proof-wave[data-phase="2"] .log-keys li { animation: story-rise .3s cubic-bezier(.22, 1, .36, 1) calc(300ms + var(--k) * 200ms) backwards; }
.proof-wave[data-phase="2"] .proof-note { animation: story-in .25s ease-out .7s backwards; }

@media (max-width: 620px) {
  .flow { grid-template-columns: minmax(0, 1fr); gap: 8px; }
  .flow-pass { grid-template-columns: auto auto; justify-content: center; align-items: center; column-gap: 12px; }
  .flow-arrow { grid-row: 1 / span 2; grid-column: 1; width: 2px; height: 58px; transform-origin: top; }
  .flow-arrow::after { right: -4px; top: auto; bottom: 0; transform: rotate(135deg); }
  .flow-file { justify-self: start; }
  .flow-sub { justify-self: start; }
  .scene-flow[data-phase="1"] .flow-arrow { animation-name: story-drop; }
  .scene-flow[data-phase="1"] .flow-file { animation-name: flow-carry-down; }
  .proof-wave .proof-tiles li { grid-template-columns: 124px minmax(0, 1fr); }
  .log-keys { grid-template-columns: minmax(0, 1fr); }
}
@media (max-width: 480px) {
  .flow-parts { grid-template-columns: minmax(0, 1fr); }
}

/* A title that says what the project is runs longer, so it spans the hero and keeps each line whole. */
.case-hero-split { row-gap: 0; }
.case-hero-split .case-hero-title { grid-column: 1 / -1; }
.case-hero-split .project-category { max-width: calc(50% - 28px); }
.case-hero-split h1 .title-line { text-wrap: balance; }
/* The hero chart names its rows in words, so its label column is wider. */
.fit-chart-labels .fit-plot { grid-template-columns: 104px minmax(0, 1fr); }
.fit-chart-labels .fit-scale { left: 104px; }
.case-notes .note-body strong { color: var(--ink); font-weight: 600; }
.case-notes .table-scroll { margin-top: 14px; }

@media (max-width: 820px) {
  .case-hero-split .project-category { max-width: none; }
}
@media (max-width: 620px) {
  .tiles { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .board { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .board > .tile, .board > .tile:nth-child(n + 4) { grid-column: span 1; }
  .board > .tile:last-child { grid-column: 1 / -1; }
  .proof-tiles { grid-template-columns: 1fr; gap: 12px; }
  .proof-tiles li { display: grid; grid-template-columns: 104px minmax(0, 1fr); column-gap: 12px; align-items: baseline; }
  .proof-tiles b { grid-row: 1 / span 2; font-size: 26px; }
  .proof-tiles span, .proof-tiles small { margin-top: 0; }
  .pr-rows li { grid-template-columns: minmax(0, 1fr); }
  .pr-rows .status-label { grid-row: auto; }
  .pr-rows small, .mini-bars { grid-column: 1; }
}
@media (max-width: 480px) {
  .story-art .chip { padding: 7px 9px; font-size: 10px; letter-spacing: .02em; }
  .mem { column-gap: 3px; }
  .cell { height: 34px; }
  .mem-box { padding: 10px 9px 12px; }
  .hold > span { font-size: 9px; padding-inline: 2px; }
  .tile { min-height: 124px; padding: 9px 9px 11px; }
  .tile-stack b { font-size: 21px; }
  .board > .tile { min-height: 158px; }
  .board .tile-stack b { font-size: 19px; }
  .fit-chart-labels .fit-plot { grid-template-columns: 90px minmax(0, 1fr); }
  .fit-chart-labels .fit-scale { left: 90px; }
}
