/* SparkFlow AI, the public site's one stylesheet (DB-0304): the design direction of
   docs/site/DESIGN-DIRECTION-2026-11.md, section 2 the system, section 3 the homepage, section 6 the other pages,
   section 8 motion, accessibility and mobile.

   THE RULES THIS FILE KEEPS. One family, Inter, from Google Fonts; no monospace anywhere (identifiers are Inter at 500
   with tabular figures). The colours are the direction's fourteen tokens below, the AutoCAD frame's four (DB-0308),
   the SparkFlow palette's three (DB-0314) and the sample sheet's six AutoCAD index colours (DB-0330), and nothing else
   (the demonstrations' tints are mixed from them, DB-0305, DB-0308 and DB-0314); every other rule names a token. No gradient, no glow, no text shadow, and two soft shadows:
   --shadow-active, kept for a light card that is the active object (no rule uses it since DB-0308 put the proposal card
   in the frame's dark palette, where its border in the accent's tint marks it active), and --shadow-inset, the palette's
   Ask box's inner shadow (DB-0314). The demonstrations' AutoCAD frame, with the graphite drawing in it, is the only dark
   object on a page.
   Interface transitions run 150 to 250 ms (the story's own, sections 10 and 10b, 150 to 900 ms: a note's fade, the
   window's messages, the camera's pan, a scene's one motion, the change drawn at the sink) and none at all under
   prefers-reduced-motion. Three things move on their own, each
   declared under prefers-reduced-motion: no-preference alone (DB-0314): the hero's scroll cue fades in once, after
   1.2 s; and, as the plug-in's own do, the palette's thinking dots pulse and its applying ring turns, seen only while
   their beat is shown. Without that preference the cue and the dots are not shown and the ring stands still; nothing
   else moves but by the visitor's scroll or hand. The focus ring is never removed. */

/* ===== 1. Tokens ===== */
:root {
  --stone: #F7F7F3;
  --surface: #FFFFFF;
  --ink: #202321;
  --ink-soft: #626762;
  --rule: #DDE0DA;
  --rule-soft: #ECEEE8;
  --viewport: #202624;
  --viewport-line: #E6E4DC;
  --viewport-dim: #8E948F;
  --accent: #315D96;
  --accent-ink: #244772;
  --redline: #B8432B;
  --applied: #2F7D5B;
  --review: #9A6B12;
  /* The demonstrations' two tints (DB-0305), each mixed from two of the tokens above. The accent is 2.3:1 on graphite
     and 2.0:1 on the frame's chrome, the redline 2.4:1 on the chrome, under what words need, so the frame's accent is
     --accent-tint (5.6:1 on graphite, 4.8:1 on the chrome) and the markup's ink there --redline-tint (DB-0310: the note
     as SparkFlow read it, quoted in the panel, 5.1:1 on the chrome and 6.1:1 on the window; the traced circle it once
     drew on graphite is gone). The accent stays the buttons' fill on light surfaces, the redline its own token. */
  --accent-tint: color-mix(in srgb, var(--accent) 60%, var(--surface));
  --redline-tint: color-mix(in srgb, var(--redline) 60%, var(--surface));
  /* The demonstrations' AutoCAD frame (DB-0308), its four colours: the application window (the title strip, the tab
     words, the document tabs, the command line and status bar), the chrome (the ribbon, the dock, the active tab and
     the prompt field), its 1 px rules, and its light grey text (8.3:1 on the chrome, 10:1 on the window). Three tints
     for the words on that chrome are mixed from the tokens: --acad-dim, the dim words (5.1:1 on the chrome, 6.2:1 on
     the window); --applied-tint, the applied state's check marks; and --review-tint, the needs-review state's words
     (each 5.5:1 or more on the chrome). The accent's tint is the frame's accent as well (4.8:1 on the chrome, 5.8:1 on
     the window). */
  --acad-window: #1E2227;
  --acad-chrome: #2B3036;
  --acad-rule: #3A4047;
  --acad-text: #C9CDD2;
  --acad-dim: color-mix(in srgb, var(--acad-text) 72%, var(--acad-chrome));
  --applied-tint: color-mix(in srgb, var(--applied) 60%, var(--surface));
  --review-tint: color-mix(in srgb, var(--review) 60%, var(--surface));
  /* The SparkFlow palette's own (DB-0314). The plug-in draws its own content inside AutoCAD's dock, so the palette's
     interior is SparkFlow's, not the chrome's: its surface, its messages' bubbles and its words, the brief's three
     colours (the words 13.7:1 on the surface, 12.4:1 on a bubble and 7.5:1 on the engineer's bubble in --accent-ink);
     and two tints mixed from them: --sf-dim, the dim words (6.0:1 on the surface, 5.4:1 on a bubble), and --sf-line,
     its hairlines and the applying ring's track. Its accent words are --accent-tint (6.2:1 and 5.6:1), the quoted
     note's --redline-tint (6.6:1 and 5.9:1), the needs-review state's --review-tint (7.4:1 and 6.7:1). */
  --sf-surface: #151B26;
  --sf-bubble: #1C2432;
  --sf-text: #DDE6F2;
  --sf-dim: color-mix(in srgb, var(--sf-text) 62%, var(--sf-surface));
  --sf-line: color-mix(in srgb, var(--sf-text) 16%, var(--sf-surface));
  /* The sample sheet's own (DB-0330): AutoCAD's index colours, as model space draws an electrical plan on its dark
     ground; the drawing's colours, not the site's. Index 8 fills the walls and 9 draws their edges, the doors, the
     windows, the fixtures and the furniture (the architectural background, faded as a locked layer); 4 the electrical
     devices, their wiring and the home runs; 2 the text and the circuit tags; 1 the dimension strings and their ticks;
     7 the panel, the border and the title block. Every word on the sheet is in 2, 4 or 7 (14.7:1, 12.6:1 and 15.8:1
     on graphite) but the architectural background's own, the rooms' names and numbers and the fixtures' words, in 9
     and faded with that layer (DB-0341); index 1, 3.9:1, draws lines alone. */
  --acad-red: #FF0000; /* index 1 */
  --acad-yellow: #FFFF00; /* index 2 */
  --acad-cyan: #00FFFF; /* index 4 */
  --acad-white: #FFFFFF; /* index 7 */
  --acad-grey: #808080; /* index 8 */
  --acad-light-grey: #C0C0C0; /* index 9 */

  --font: "Inter", system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;

  --space-1: 4px;
  --space-2: 8px;
  --space-3: 12px;
  --space-4: 16px;
  --space-5: 24px;
  --space-6: 32px;
  --space-7: 48px;
  --space-8: 64px;
  --space-9: 96px;
  --space-10: 128px;

  --radius-control: 6px;
  --radius-card: 10px;
  --radius-viewport: 12px;

  --container: 1280px;
  --gutter: 24px;
  --header-height: 56px;
  --section-gap: var(--space-9);
  --part-gap: var(--space-10);
  --measure: 30em;
  --shadow-active: 0 8px 24px rgba(32, 35, 33, 0.08);
  --shadow-inset: inset 0 1px 3px rgba(0, 0, 0, 0.45);
  --ease: cubic-bezier(0.2, 0, 0, 1);
}

@media (max-width: 719.98px) {
  :root { --section-gap: var(--space-8); --part-gap: calc(var(--space-8) + var(--space-4)); }
}

@media (max-width: 479.98px) {
  :root { --gutter: 16px; }
}

/* ===== 2. Base ===== */
*,
*::before,
*::after { box-sizing: border-box; }

html {
  -webkit-text-size-adjust: 100%;
  text-size-adjust: 100%;
  scroll-padding-top: calc(var(--header-height) + var(--space-5));
}

body {
  margin: 0;
  min-width: 320px;
  background: var(--stone);
  color: var(--ink);
  font-family: var(--font);
  font-size: 1.0625rem;
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

@media (max-width: 479.98px) {
  body { font-size: 1rem; }
}

h1, h2, h3, h4, p, ul, ol, dl, dd, figure, blockquote, pre { margin: 0; }
ul, ol { padding: 0; }
img { display: block; max-width: 100%; height: auto; }
button, input, select, textarea { font: inherit; color: inherit; }
pre { font-family: inherit; white-space: pre-wrap; }
hr { border: 0; border-top: 1px solid var(--rule); margin: var(--space-5) 0; }
[hidden] { display: none !important; }

/* ===== 3. Type ===== */
h1 {
  font-size: clamp(2.3rem, 4.4vw, 3.5rem);
  font-weight: 650;
  line-height: 1.08;
  letter-spacing: -0.02em;
  text-wrap: balance;
}

h2 {
  font-size: clamp(1.7rem, 2.6vw, 2.3rem);
  font-weight: 600;
  line-height: 1.15;
  letter-spacing: -0.015em;
  text-wrap: balance;
}

h3 {
  font-size: 1.15rem;
  font-weight: 600;
  line-height: 1.35;
}

p, li, dd { max-width: var(--measure); }

.lead {
  font-size: 1.1875rem;
  line-height: 1.55;
}

.eyebrow {
  max-width: none;
  font-size: 0.8rem;
  font-weight: 600;
  line-height: 1.4;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink-soft);
}

/* A drawing identifier, a sheet number or a reference: the text face at 500, tabular figures. */
.ident {
  font-weight: 500;
  font-variant-numeric: tabular-nums;
  letter-spacing: 0.02em;
}

/* ===== 4. Links, focus, the skip link ===== */
a {
  color: var(--accent);
  text-decoration: none;
  text-decoration-thickness: 1px;
  text-underline-offset: 0.2em;
}

a:hover { color: var(--accent-ink); text-decoration: underline; }
p a, .prose li a, dd a { text-decoration: underline; }

:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

.skip-link {
  position: absolute;
  top: var(--space-2);
  left: var(--gutter);
  z-index: 100;
  padding: 10px 16px;
  border: 1px solid var(--rule);
  border-radius: var(--radius-control);
  background: var(--surface);
  color: var(--accent);
  font-weight: 600;
  transform: translateY(-200%);
}

.skip-link:focus,
.skip-link:focus-visible { transform: none; }

.sr-only {
  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;
}

/* ===== 5. Layout ===== */
.container {
  width: 100%;
  max-width: calc(var(--container) + 2 * var(--gutter));
  margin-inline: auto;
  padding-inline: var(--gutter);
}

main { display: block; padding-bottom: var(--section-gap); }
.section { padding-top: var(--section-gap); }

/* ===== 6. Buttons ===== */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  min-height: 44px;
  padding: 0 20px;
  border: 1px solid transparent;
  border-radius: var(--radius-control);
  font-size: 1rem;
  font-weight: 600;
  line-height: 1.2;
  text-align: center;
  text-decoration: none;
  white-space: nowrap;
  cursor: pointer;
  transition: background-color 150ms var(--ease), border-color 150ms var(--ease), color 150ms var(--ease);
}

.btn:hover { text-decoration: none; }

.btn-primary { background: var(--accent); color: var(--surface); }
.btn-primary:hover,
.btn-primary:active { background: var(--accent-ink); color: var(--surface); }

.btn-secondary { background: var(--surface); border-color: var(--rule); color: var(--ink); }
.btn-secondary:hover { border-color: var(--ink-soft); color: var(--ink); }

.btn-small { min-height: 40px; padding: 0 16px; font-size: 0.9375rem; }

/* A control waiting for its script (the demonstration's, DB-0305) or a request in flight (the form's): it reads as
   itself, never as broken; a submit in flight is the accent's pressed state. */
.btn:disabled { cursor: default; }
.btn-primary:disabled { background: var(--accent-ink); cursor: progress; }
.btn-secondary:disabled { border-color: var(--rule); color: var(--ink-soft); }

/* ===== 7. The header (direction 3.1) ===== */
.site-header {
  position: sticky;
  top: 0;
  z-index: 50;
  background: var(--surface);
  border-bottom: 1px solid var(--rule);
}

/* 56 px tall with its 1 px rule (direction 3.1). */
.header-inner {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  height: calc(var(--header-height) - 1px);
}

.brand {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  min-height: 44px;
  margin-right: auto;
  min-width: 0;
  color: var(--ink);
  font-size: 1.0625rem;
  font-weight: 600;
  letter-spacing: -0.01em;
  line-height: 1;
  text-decoration: none;
  white-space: nowrap;
}

.brand:hover { color: var(--ink); text-decoration: none; }
.brand img { width: auto; height: 28px; }

.nav-primary { display: flex; align-items: center; gap: var(--space-1); margin-right: var(--space-3); }

.nav-primary a,
.header-signin {
  display: inline-flex;
  align-items: center;
  min-height: 40px;
  padding: 0 var(--space-3);
  border-radius: var(--radius-control);
  color: var(--ink);
  font-size: 0.9375rem;
  font-weight: 500;
  text-decoration: none;
  white-space: nowrap;
}

.nav-primary a:hover,
.header-signin:hover { color: var(--ink); text-decoration: underline; }

.nav-primary a[aria-current="page"],
.nav-menu-panel a[aria-current="page"] {
  text-decoration: underline;
  text-decoration-color: var(--accent);
  text-decoration-thickness: 2px;
  text-underline-offset: 0.45em;
}

.header-signin { margin-right: var(--space-2); color: var(--accent); }
.header-signin:hover { color: var(--accent-ink); }

/* Five links (DB-0319 added Resources), the Sign in link and the button are a tight fit just above the fold: from 900
   to 1023 px the bar's links sit closer together, so the wordmark never runs into them. */
@media (min-width: 900px) and (max-width: 1023.98px) {
  .nav-primary { margin-right: var(--space-1); }
  .nav-primary a,
  .header-signin { padding: 0 var(--space-2); }
}

/* Under 900 px the links fold behind a native details disclosure, "Menu"; the primary button stays. */
.nav-menu { display: none; }

.nav-menu > summary {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  padding: 0 14px;
  border: 1px solid var(--rule);
  border-radius: var(--radius-control);
  background: var(--surface);
  color: var(--ink);
  font-size: 0.9375rem;
  font-weight: 500;
  list-style: none;
  cursor: pointer;
  transition: border-color 150ms var(--ease);
}

.nav-menu > summary::-webkit-details-marker { display: none; }
.nav-menu > summary:hover,
.nav-menu[open] > summary { border-color: var(--ink-soft); }

.nav-menu-panel {
  position: absolute;
  top: 100%;
  left: 0;
  right: 0;
  padding: var(--space-2) var(--gutter) var(--space-5);
  background: var(--surface);
  border-bottom: 1px solid var(--rule);
}

.nav-menu-panel a {
  display: flex;
  align-items: center;
  min-height: 48px;
  border-bottom: 1px solid var(--rule-soft);
  color: var(--ink);
  font-weight: 500;
  text-decoration: none;
}

.nav-menu-panel a:hover { color: var(--accent-ink); }

@media (max-width: 899.98px) {
  .nav-primary,
  .header-signin { display: none; }
  .nav-menu { display: block; }
  .site-header .btn-small { min-height: 44px; }
}

@media (max-width: 479.98px) {
  .site-header .btn-small { padding: 0 12px; font-size: 0.875rem; }
  .nav-menu > summary { padding: 0 12px; font-size: 0.875rem; }
  .brand { gap: 8px; font-size: 1rem; }
}

/* The narrowest phones: the mark carries the brand, the link keeps its name. */
@media (max-width: 379.98px) {
  .brand .wordmark { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }
}

/* ===== 8. The footer (direction 3.10) ===== */
.site-footer {
  padding: var(--space-8) 0 var(--space-6);
  background: var(--surface);
  border-top: 1px solid var(--rule);
}

.footer-grid {
  display: grid;
  grid-template-columns: minmax(0, 2fr) minmax(0, 3fr);
  gap: var(--space-7) var(--space-8);
}

.footer-brand > * + * { margin-top: var(--space-3); }
.footer-brand .brand { margin-right: 0; margin-bottom: var(--space-2); }
.footer-brand p { max-width: 40em; color: var(--ink-soft); font-size: 0.875rem; line-height: 1.6; }

.footer-nav {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: var(--space-6);
}

.footer-heading {
  margin-bottom: var(--space-3);
  font-size: 0.8rem;
  font-weight: 600;
  letter-spacing: 0.08em;
  line-height: 1.4;
  text-transform: uppercase;
  color: var(--ink-soft);
}

.footer-nav ul { list-style: none; }
.footer-nav li + li { margin-top: var(--space-1); }

.footer-nav a {
  display: inline-flex;
  align-items: center;
  min-height: 32px;
  color: var(--ink);
  font-size: 0.9375rem;
}

.footer-nav a:hover { color: var(--accent-ink); }

.footer-bottom {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  gap: var(--space-2) var(--space-5);
  max-width: none;
  margin-top: var(--space-7);
  padding-top: var(--space-5);
  border-top: 1px solid var(--rule-soft);
  color: var(--ink-soft);
  font-size: 0.875rem;
}

@media (max-width: 899.98px) {
  .footer-grid { grid-template-columns: minmax(0, 1fr); }
  .footer-nav a { min-height: 44px; }
  .footer-nav li + li { margin-top: 0; }
}

@media (max-width: 559.98px) {
  .footer-nav { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

/* ===== 9. The hero (direction 3.2; DB-0311: text alone; DB-0312: the founder's words; DB-0314: a screen of its own) =====
   The eyebrow, the two-line headline (each sentence a line of its own), the lead, Request a demo and See it work (a
   link to the story, which lands on its first beat), the three facts: no frame, no sheet and nothing moving above the
   fold. DB-0314 (the founder: a section that shows the next one under it loses its weight): at every width the hero is
   a whole viewport tall, its copy at the middle of the screen under the header, so nothing of the story shows on the
   first screen; the headline 64 px at 1280 (40 on a phone), each sentence still a line of its own from 768 px; the
   lead 22 px, held to 32em. Its foot leaves the header's height more than its top, since the story's stage rises under
   it by the header's height (section 10): the copy's middle is the screen's middle under the header, and the scroll
   cue sits in that room. */
.hero {
  position: relative;
  display: flex;
  align-items: center;
  min-height: 100svh;
  padding: var(--space-9) 0 calc(var(--space-9) + var(--header-height));
}

.hero-copy { max-width: 60rem; }
.hero-copy > .eyebrow { margin-bottom: var(--space-4); }
.hero-copy h1 { font-size: clamp(2.5rem, 5vw, 4rem); }
.hero-copy h1 > span { display: block; }
.hero-copy .lead { max-width: 32em; margin-top: var(--space-5); font-size: 1.375rem; }

.hero-actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-3);
  margin-top: var(--space-6);
}

.facts {
  margin-top: var(--space-6);
  list-style: none;
  color: var(--ink);
  font-size: 0.9375rem;
}

.facts li {
  position: relative;
  padding-left: 26px;
}

.facts li + li { margin-top: var(--space-2); }

/* The check mark, drawn in --applied: a decorative mark, the sentence carries the meaning. */
.facts li::before {
  content: "";
  position: absolute;
  left: 3px;
  top: 0.42em;
  width: 11px;
  height: 6px;
  border-left: 2px solid var(--applied);
  border-bottom: 2px solid var(--applied);
  transform: rotate(-45deg);
}

/* On a phone, where the copy is about a screen tall, less room above it; the foot keeps the cue's room. */
@media (max-width: 719.98px) {
  .hero { padding-top: var(--space-7); }
  .hero-actions .btn { flex: 1 1 auto; }
}

/* The scroll cue (DB-0314): the word "Scroll" at 12 px, letter-spaced, over a 1 px line 40 px tall in the accent, at the
   hero's foot above the room the story's stage rises into. For the eye alone (hidden from assistive technology) and
   only where motion is welcome: it fades in once, after 1.2 s; under reduced motion it is not shown. */
.hero-cue { display: none; }

@media (prefers-reduced-motion: no-preference) {
  .hero-cue {
    position: absolute;
    right: 0;
    bottom: calc(var(--header-height) + var(--space-5));
    left: 0;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: var(--space-2);
    max-width: none;
    color: var(--ink-soft);
    font-size: 0.75rem;
    font-weight: 600;
    letter-spacing: 0.14em;
    line-height: 1.2;
    animation-name: cue-in;
    animation-duration: 600ms;
    animation-timing-function: var(--ease);
    animation-delay: 1.2s;
    animation-fill-mode: both;
  }
  .hero-cue::after {
    content: "";
    width: 1px;
    height: 40px;
    background: var(--accent);
  }
}

@keyframes cue-in {
  from { opacity: 0; }
  to { opacity: 1; }
}

/* ===== 10. The story (DB-0311; direction 4b; DB-0333: each beat its framing; DB-0341: panned; DB-0343: twelve beats, held) =====
   The landing page's demonstration, driven by the visitor's scroll and nothing else: one AutoCAD window (section 10c)
   held still in a stage of 100 svh while twelve beats of 100 svh scroll past it. js/demo.js turns it on (data-story on
   the section) and names the beat whose block crosses the middle of the viewport (data-beat); the window shows that
   beat's state (section 10b), that beat's note is shown, and the camera frames the beat's own subject (the drop zone,
   the guidance field, SparkFlow thinking, the palette's conversation for the beats its messages carry, the change on
   the sheet, or the whole window) by the window's transform alone. Where a beat's framing changes, the beat change is
   one eased pan and zoom to it (DB-0341; the founder: "I don't like the snapping; the animations still need to be
   smooth, just slightly faster"): 450 ms, 400 on a phone, never past its framing, the old note fading out as it starts
   and the new one fading in from 150 ms into it; where it does not, the window holds exactly where it is (DB-0343; the
   founder: "the camera needs to be steady and move properly only when it's time"); between beats nothing else moves.
   The notes and the leader are the site's own layer, outside the window: they never read as something SparkFlow
   drew. With no script the window shows beat 12 still and the twelve notes are a numbered list under it; the rail
   stays hidden. */
.story {
  position: relative;
  margin-top: calc(var(--header-height) * -1);
}

/* The play head of one of the story's scene motions (section 10b): a number eased from 0 to 1, or back, on the one
   element it is set on, never inherited: the drop zone's breath, the Accept button's press. Only the no-preference
   rules set it or ease it; a browser that cannot ease it shows each state at once. */
@property --story-play {
  syntax: "<number>";
  inherits: false;
  initial-value: 0;
}

/* The stage: the window under the header's height, the site's gutter round it. Its overflow is clipped, so the camera
   never widens the page. */
.story-stage {
  position: relative;
  height: 100svh;
  padding: calc(var(--header-height) + var(--space-4)) var(--gutter) var(--space-4);
  overflow: hidden;
}

/* The window, drawn at the stage's width up to 1280 px and its full height. The camera moves it as one piece by the
   script's three numbers (--story-x, --story-y, --story-scale), so its own layout never changes with the camera. */
.story-window {
  width: min(100%, var(--container));
  height: 100%;
  margin-inline: auto;
  transform-origin: 0 0;
  transform: translate(var(--story-x, 0px), var(--story-y, 0px)) scale(var(--story-scale, 1));
}

/* Its strips at their heights and its body taking the rest; the dock beside model space at every width, as on the
   desktop (the phone stack of section 10c is the close-up's); the sheet fitted inside model space, all of it in view
   with graphite round it, as a sheet zoomed to its extents. */
.story-window > .acad-frame {
  display: flex;
  flex-direction: column;
  height: 100%;
}

.story-window > .acad-frame > * { flex: none; }
.story .acad-body { flex: 1 1 auto; min-height: 0; }
.story .acad-model { min-height: 0; }
.story .demo-viewport { flex: 1 1 auto; min-height: 0; aspect-ratio: auto; }
.story .e101 { height: 100%; }

/* The leader: an overlay the size of the stage, a 1.5 px line in the accent from the note to the part it points at,
   a 6 px dot at that end; the script draws it once the camera has reached the part. */
.story-leader {
  display: none;
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  overflow: visible;
  pointer-events: none;
}

.story-leader line { stroke: var(--accent); stroke-width: 1.5; }
.story-leader circle { fill: var(--accent); }

/* The rail at the stage's right edge: twelve dots, the current one filled; each a button that brings its beat to the
   middle of the viewport, named by the beat's title: the keyboard's and the screen reader's way through. */
.story-rail {
  position: absolute;
  top: calc(var(--header-height) + var(--space-4));
  right: 0;
  bottom: var(--space-4);
  display: flex;
  flex-direction: column;
  justify-content: center;
  list-style: none;
}

.story-rail > li { display: flex; }

.story-dot {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 28px;
  min-height: 44px;
  padding: 0;
  border: 0;
  background: none;
  cursor: pointer;
}

.story-dot::before {
  content: "";
  width: 8px;
  height: 8px;
  border: 1.5px solid var(--ink-soft);
  border-radius: 50%;
  background: var(--surface);
}

.story-dot[aria-current="step"]::before { border-color: var(--accent); background: var(--accent); }

/* The notes. With no script: a numbered list of twelve cards under the window. */
.story-beats {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(min(100%, 17rem), 1fr));
  gap: var(--space-4);
  max-width: calc(var(--container) + 2 * var(--gutter));
  margin: var(--space-6) auto 0;
  padding-inline: var(--gutter);
  list-style: none;
}

/* A note is site chrome, never AutoCAD's: a card on the surface with the site's rule, its badge, its title and its
   line in the site's type. */
.story-note {
  max-width: 360px;
  padding: 20px;
  border: 1px solid var(--rule);
  border-radius: var(--radius-viewport);
  background: var(--surface);
}

.story-badge {
  display: inline-block;
  padding: 2px var(--space-2);
  border-radius: 999px;
  background: var(--stone);
  color: var(--ink-soft);
  font-size: 0.75rem;
  font-weight: 600;
  line-height: 1.5;
  font-variant-numeric: tabular-nums;
}

.story-note h3 { margin-top: var(--space-2); font-size: 1.25rem; font-weight: 600; line-height: 1.3; }
.story-note h3 + p { margin-top: 6px; color: var(--ink-soft); font-size: 1rem; line-height: 1.5; }
.story-note .btn { margin-top: var(--space-4); }

/* The story, live (js/demo.js sets data-story). The stage holds still at the top of the viewport while the beats,
   each 100 svh, scroll past it; the first starts half a stage in and the last ends half a stage before the stage moves
   on, so the stage holds through all twelve. See it work lands with the first beat at the middle of the viewport. */
.story[data-story] { scroll-margin-top: calc(-50svh - var(--header-height) - var(--space-5)); }
.story[data-story] .story-stage { position: sticky; top: 0; }
.story[data-story] .story-leader { display: block; opacity: 0; }
.story[data-story] .story-leader[data-shown="true"] { opacity: 1; }

.story[data-story] .story-beats {
  display: block;
  max-width: none;
  margin: -50svh 0 0;
  padding: 0 0 50svh;
}

.story[data-story] .beat { max-width: none; height: 100svh; }

/* Each note waits, unseen, at its place in the viewport; the current beat's is shown, over the stage and the window at
   every width (its own layer, above theirs, under the header's). */
.story[data-story] .story-note {
  position: fixed;
  z-index: 2;
  visibility: hidden;
  opacity: 0;
}

.story[data-story] .beat[aria-current="step"] .story-note { visibility: visible; opacity: 1; }

/* The pan's length (DB-0341): 450 ms; on a phone 400 (below). The camera's pan, the note's fade inside it and every
   scene's motion after it (section 10b) are timed from it. */
.story[data-story] { --story-pan: 450ms; }

/* Wide: in the viewport's right third, at the middle of the stage under the header, for every beat (DB-0314; DB-0333:
   the camera frames each subject in the room left of it, so the note never covers it). */
@media (min-width: 1024px) {
  .story[data-story] .story-note {
    top: calc(50% + var(--header-height) / 2);
    left: calc(200% / 3 + var(--space-4));
    width: min(360px, 100% / 3 - var(--space-4) - 48px);
    transform: translateY(-50%);
  }
}

/* Narrow: at the foot of the viewport, the camera's part above it; the rail from the header down. */
@media (max-width: 1023.98px) {
  .story[data-story] .story-note {
    right: var(--gutter);
    bottom: var(--space-4);
    left: var(--gutter);
    margin-inline: auto;
  }
  .story-rail { bottom: auto; }
}

/* On a phone the pan is a little quicker: 400 ms (DB-0341). */
@media (max-width: 719.98px) {
  .story[data-story] { --story-pan: 400ms; }
}

/* On a phone the window fills the screen's width, edge to edge, so the camera fills it with each beat's subject, the
   palette's fitted to the width (DB-0333); the palette then reaches the stage's edge, where the rail would lie over its
   words, so the rail is out of sight there until one of its buttons has the keyboard's focus, and the note's badge
   says how far the story has come. */
@media (max-width: 479.98px) {
  .story-stage { padding-inline: 0; }
  .story-window > .acad-frame { border-inline: 0; border-radius: 0; }
  .story-rail:not(:focus-within) {
    width: 1px;
    height: 1px;
    overflow: hidden;
    clip-path: inset(50%);
  }
}

/* In a narrow, short window the sheet fills model space's width and sits high in it, under the view cube and beside the
   UCS icon: there those parts give way with the navigation bar, as they do on a phone (section 10c). */
@media (max-width: 899.98px) and (max-height: 779.98px) {
  .story .acad-cube,
  .story .acad-nav,
  .story .acad-ucs { display: none; }
}

/* The pan (DB-0341; the founder: "when it's time to show the change on the drawing it should show the camera pan over,
   not an instant jump"), for a visitor who has not asked for less:
   (a) at a beat whose framing changes the window moves to the new framing in one pan and zoom of --story-pan (450 ms;
       400 on a phone), a cubic ease in and out that starts and ends gently and never passes its framing: no
       overshoot; at a beat whose framing is the one before's the script writes nothing and the window holds still
       (DB-0343), so the pans are into the palette, to the sink and back, and out to the whole window;
   (b) the note before fades out over 150 ms as the pan starts, and the new one fades in, in its place, over 200 ms
       from 150 ms into it: no rise, no slide;
   (c) the leader fades in once the camera is there.
   Between beats nothing else moves: no band round the stage, no flag for the move. Under reduced motion nothing here
   is declared: the beats still follow the scroll, each state and each framing at once. */
@media (prefers-reduced-motion: no-preference) {
  .story[data-story] .story-note {
    transition-property: opacity, visibility;
    transition-duration: 150ms, 0s;
    transition-delay: 0s, 150ms;
    transition-timing-function: var(--ease);
  }
  .story[data-story] .beat[aria-current="step"] .story-note {
    transition-duration: 200ms, 0s;
    transition-delay: 150ms, 0s;
  }
  .story[data-story] .story-window {
    transition-property: transform;
    transition-duration: var(--story-pan);
    transition-timing-function: cubic-bezier(0.65, 0, 0.35, 1);
  }
  .story[data-story] .story-leader {
    transition-property: opacity;
    transition-duration: 200ms;
    transition-timing-function: var(--ease);
  }
}

/* ===== 10b. The window, beat by beat (DB-0311; DB-0310's honest stages; DB-0314; DB-0343's twelve) =====
   The section's data-beat (1 to 12; 12 as the page is committed, the still a page with no script shows) sets what the
   window shows. Beat 1: the sheet as drawn, the SparkFlow panel closed to its tab and the dock the Project Manager
   alone. Beat 2: the panel open on its empty state, the drop zone. Beat 3: the guidance step: before it reads a page,
   SparkFlow asks whether there is anything it should know, the engineer's line typed in its drawn field, Start and
   Skip under it. Beat 4: the line sent, the engineer's, and SparkFlow thinking, "Reading the markup", with what it is
   reading under it: "Reading page 1 of 1", "3 notes found", "Matched to E-101 Rev 3", "Checking 12 validators".
   Beat 5: the proposals as a list (DB-0343): "7 proposals from this markup", the sheet they are bound to, and the
   seven, one line each, the first opened as the card with its Accept, Reject and Teach. Beat 6: Accept pressed on the
   first: its three actions at half strength, an inactive control's look, the applying ring and "Applying in AutoCAD"
   under it, and the Ask box inactive too: one decision in flight. Beat 7: the toast, "Applied. Undo in one step.",
   the list's count "1 of 7 applied", and on the sheet the one change the native transaction leaves: the receptacle at
   the sink is the GFCI receptacle and its label reads "LP-4-12 GFCI" (the sheet's own receptacle and label hidden under
   it from then on). Beat 8: the list again, the first ticked and the second opened, ready. Beat 9: Teach on the third,
   the list showing that one alone: its actions spent, the engineer's correction typed in a drawn field with Send, the
   proposal read again ("Upsize the feeder breaker to LP-4 to 150 A") and SparkFlow's answer "Remembered for your
   firm. The next similar markup is read your firm's way." Beat 10: the review's finding. Beat 11: the engineer's code
   question and its answer. Beat 12: the engineer's line, the list decided (six ticked, the taught one marked) and the
   record, "7 proposals, 6 applied, 1 taught, every one recorded". NOTHING is drawn on the sheet before beat 7, because
   the plug-in draws nothing there before the accept; that change is the only mark, and it stays. A message, or a part
   of the list, takes no room and is out of the accessibility tree outside its beats; the conversation is held to the
   panel's foot, so the older messages scroll up out of view as a chat's do. Open, the panel takes all of the dock but
   the tree's first row on a wide screen (DB-0343: the list of seven, the card opened among them and Teach need its
   room at 1280 by 800), and on a narrow one all but the tree's first rows, the open drawing's among them (as the
   DB-0310 workflows' did). The panel opens and closes at once, as AutoCAD's palettes do. */
.story .acad-dock { grid-template-rows: 20px 24px 28px 0 minmax(0, 1fr); }
.story .acad-palette { visibility: hidden; }
.story .acad-palette-closed { display: block; }
.story:is([data-beat="2"], [data-beat="3"], [data-beat="4"], [data-beat="5"], [data-beat="6"], [data-beat="7"], [data-beat="8"], [data-beat="9"], [data-beat="10"], [data-beat="11"], [data-beat="12"]) .acad-dock { grid-template-rows: 20px 24px 28px minmax(0, 1fr) 26px; }

/* Narrow, where the note sits at the foot and the camera lifts the palette's subjects above it, the tree keeps its
   first rows as before (DB-0314): a taller panel would sink their feet under the note. */
@media (max-width: 1023.98px) {
  .story:is([data-beat="2"], [data-beat="3"], [data-beat="4"], [data-beat="5"], [data-beat="6"], [data-beat="7"], [data-beat="8"], [data-beat="9"], [data-beat="10"], [data-beat="11"], [data-beat="12"]) .acad-dock { grid-template-rows: 20px 24px 28px minmax(0, 1fr) 80px; }
}
.story:is([data-beat="2"], [data-beat="3"], [data-beat="4"], [data-beat="5"], [data-beat="6"], [data-beat="7"], [data-beat="8"], [data-beat="9"], [data-beat="10"], [data-beat="11"], [data-beat="12"]) .acad-palette { visibility: visible; }
.story:is([data-beat="2"], [data-beat="3"], [data-beat="4"], [data-beat="5"], [data-beat="6"], [data-beat="7"], [data-beat="8"], [data-beat="9"], [data-beat="10"], [data-beat="11"], [data-beat="12"]) .acad-palette-closed { display: none; }

/* The panel's empty state, before the markup is dropped: the drop zone filling the conversation (beat 2), a dashed box
   in the accent with SparkFlow's mark faint at its middle (DB-0314; the mark is the page's decoration, its words say
   what the zone is for). */
.demo-drop {
  display: grid;
  grid-template-rows: 1fr;
  min-height: 0;
}

.acad-palette-body > .demo-drop { flex: 1 1 auto; }

.demo-drop-in {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--space-3);
  min-height: 0;
  margin-top: 8px;
  overflow: hidden;
  border: 1.5px dashed var(--accent);
  border-radius: 10px;
  color: var(--sf-dim);
  text-align: center;
}

.sf-drop-mark { width: auto; height: 40px; opacity: 0.3; }

.story:is([data-beat="3"], [data-beat="4"], [data-beat="5"], [data-beat="6"], [data-beat="7"], [data-beat="8"], [data-beat="9"], [data-beat="10"], [data-beat="11"], [data-beat="12"]) .demo-drop {
  grid-template-rows: 0fr;
  visibility: hidden;
  opacity: 0;
}

/* A message outside its beats takes no room in the conversation and is out of the page and of the accessibility tree:
   its one row is closed (0fr), its content clipped to it. */
.demo-card {
  display: grid;
  grid-template-rows: 0fr;
  visibility: hidden;
  opacity: 0;
}

.demo-card > .acad-msg-in { min-height: 0; overflow: hidden; }

/* An identifier (a sheet, a circuit, a standard, a rule) is never broken at its hyphen. */
.demo-id { white-space: nowrap; }

/* Each message in its beats: the guidance step at 3; the engineer's line at 4, with SparkFlow thinking, and again at
   12; the list from 5 to 9 and again at 12, the applying line, inside it under the first proposal, at 6 alone; the
   toast at 7 (a toast goes, the list's tick says it after); what Teach remembered at 9; the record at 12; the review's
   finding at 10; the code question and its answer at 11. */
.story[data-beat="3"] .demo-card-guidance,
.story:is([data-beat="4"], [data-beat="12"]) .demo-card-line,
.story[data-beat="4"] .demo-card-thinking,
.story:is([data-beat="5"], [data-beat="6"], [data-beat="7"], [data-beat="8"], [data-beat="9"], [data-beat="12"]) .demo-card-proposal,
.story[data-beat="6"] .demo-card-applying,
.story[data-beat="7"] .demo-card-toast,
.story[data-beat="9"] .demo-card-taught,
.story[data-beat="12"] .demo-card-record,
.story[data-beat="10"] .demo-card-review,
.story[data-beat="11"] .demo-card-question,
.story[data-beat="11"] .demo-card-answer { grid-template-rows: 1fr; visibility: visible; opacity: 1; }

/* What SparkFlow reads, under its thinking (beat 4): one short line a step, in the dim words, each after a small dot
   in the thinking dots' own tint. */
.sf-steps { display: flex; flex-direction: column; gap: 2px; list-style: none; color: var(--sf-dim); }
.sf-steps > li { position: relative; padding-left: 12px; line-height: 1.3; }

.sf-steps > li::before {
  content: "";
  position: absolute;
  top: 0.45em;
  left: 1px;
  width: 4px;
  height: 4px;
  border-radius: 50%;
  background: var(--accent-tint);
}

/* The proposals as a list (DB-0343; the founder: "it should show a bunch of changes, you press one, that change gets
   implemented"): one message of SparkFlow's, its words on the palette's own surface as the card's actions are. Its
   title, and under it in the dim words the sheet the proposals are bound to and, once one is decided, the count;
   then the seven, one line each, the line cut short at the palette's width (the whole proposal is the page's words
   and is read out whole), a small ring before one not yet decided, the applied state's check before an applied one,
   a dot in the Teach action's tint before the taught one. The one being decided is opened as the card, the evidence
   in it and its Accept, Reject and Teach under it, its line giving way to it. A part opened or closed by a beat is
   closed as a message is, its one row at 0fr. */
.demo-card-proposal .acad-msg-body { gap: 0; padding: 0; background: none; }
.demo-list-head { font-weight: 600; }
.demo-list-sub { margin-top: 1px; color: var(--sf-dim); line-height: 1.3; }
.demo-list-count { display: none; margin-top: 0; }
.demo-list { display: flex; flex-direction: column; gap: 2px; margin-top: 5px; list-style: none; }

.demo-item-line {
  position: relative;
  overflow: hidden;
  padding-left: 15px;
  line-height: 1.2;
  white-space: nowrap;
  text-overflow: ellipsis;
}

.demo-item-line::before {
  content: "";
  position: absolute;
  top: 3px;
  left: 1px;
  width: 7px;
  height: 7px;
  border: 1.5px solid var(--sf-dim);
  border-radius: 50%;
}

.demo-item-open { display: grid; grid-template-rows: 0fr; visibility: hidden; opacity: 0; }
.demo-item-in { min-height: 0; overflow: hidden; }
.demo-item-in > .demo-card-actions { margin-top: 5px; }
.demo-item .sf-applying { padding-left: 0; }

/* A proposal's two readings, before and after Teach, in one place: the line shows the one its beat names, the card
   at Teach the new one, the old one gone (the scroll story fades one into the other, below). */
.demo-read-after { display: none; }
.demo-card-instruction:has(> .demo-read) { display: grid; }
.demo-card-instruction > .demo-read { display: block; grid-area: 1 / 1; }
.demo-card-instruction > .demo-read-before { opacity: 0; }

/* Teach's correction, under the taught proposal's actions: the engineer's words typed in a drawn field, as the guidance
   step's, and Send. */
.demo-teach { display: flex; flex-direction: column; gap: 5px; margin-top: 6px; }

/* The list, beat by beat: the first opened from 5 to 7, the second at 8, the third at 9, where the list shows it
   alone; the first ticked from 8, the rest but the third at 12, the third taught at 12 and read again from 9; the
   count from 7. */
.story:is([data-beat="5"], [data-beat="6"], [data-beat="7"]) .demo-item-1 > .demo-item-open,
.story[data-beat="8"] .demo-item-2 > .demo-item-open,
.story[data-beat="9"] .demo-item-3 > .demo-item-open { grid-template-rows: 1fr; visibility: visible; opacity: 1; }
.story:is([data-beat="5"], [data-beat="6"], [data-beat="7"]) .demo-item-1 > .demo-item-line,
.story[data-beat="8"] .demo-item-2 > .demo-item-line,
.story[data-beat="9"] .demo-item:not(.demo-item-3),
.story[data-beat="9"] .demo-item-3 > .demo-item-line { display: none; }
.story:is([data-beat="8"], [data-beat="9"], [data-beat="12"]) .demo-item-1 > .demo-item-line::before,
.story[data-beat="12"] :is(.demo-item-2, .demo-item-4, .demo-item-5, .demo-item-6, .demo-item-7) > .demo-item-line::before {
  top: 4px;
  width: 8px;
  height: 4px;
  border-width: 0 0 2px 2px;
  border-color: var(--applied-tint);
  border-radius: 0;
  transform: rotate(-45deg);
}
.story[data-beat="12"] .demo-item-3 > .demo-item-line::before { border-color: var(--accent-tint); background: var(--accent-tint); }
.story[data-beat="12"] .demo-item-3 .demo-read-before { display: none; }
.story[data-beat="12"] .demo-item-3 .demo-read-after { display: inline; }
.story:is([data-beat="7"], [data-beat="8"], [data-beat="9"]) .demo-list-one,
.story[data-beat="12"] .demo-list-all { display: block; }

/* The card being decided is the active object while it waits, as it is decided and as it is drawn, its border in the
   accent's tint. From the press its three actions are spent: Accept pressed and the three at half strength, an inactive
   control's look (the applying line under them says why). While it applies (beat 6) the Ask box is inactive too:
   nothing else can be asked or accepted until it is done (DB-0316's lock). At Teach (beat 9) the actions are spent
   by the Teach press and Send is pressed once the correction is typed. */
.story:is([data-beat="5"], [data-beat="6"], [data-beat="7"]) .demo-item-1 .acad-card,
.story[data-beat="8"] .demo-item-2 .acad-card,
.story[data-beat="9"] .demo-item-3 .acad-card { border-color: var(--accent-tint); }
.story:is([data-beat="6"], [data-beat="7"]) .demo-item-1 .mock-action-primary,
.story[data-beat="9"] .demo-teach .mock-action-primary {
  border-color: var(--accent-ink);
  background: var(--accent-ink);
}
.story:is([data-beat="6"], [data-beat="7"]) .demo-item-1 .demo-card-actions,
.story[data-beat="9"] .demo-item-3 .demo-card-actions { opacity: 0.5; }
.story[data-beat="6"] .acad-chat { opacity: 0.5; }

/* On the sheet, in its units: the one change, the GFCI receptacle the accepted proposal leaves in place of receptacle
   LP-4-12, after the drawing, drawn as every device on the sheet is (DB-0330): its symbol in index 4, its label
   "LP-4-12 GFCI" in the tags' index 2 with its GFCI marking in 4, as the sheet's other GFCI receptacles carry theirs;
   no highlight, the applied state told in the palette alone. Unseen before beat 7 and kept from then on; from then the
   sheet's own receptacle and label under it are hidden. Nothing else is drawn, at any beat.
   Its parts as a drafter draws them (DB-0341): before beat 7 its circle and its two lines are dashed at their own
   lengths (the circle's 2 pi 7 units, under 44; each line 22) and offset by the whole, so nothing of them is drawn,
   and its fill, its tag's leader and dot and its words are unseen; from beat 7 each stroke is drawn whole and the
   rest is there. The sheet's own receptacle, its tag and the tag's leader and dot carry its circuit, so they go
   together. The story draws the change in that order (below, the scroll story's scenes); anywhere else, and under
   reduced motion, the finished change is there at once. */
.e101 .demo-swap { opacity: 0; }
.story:is([data-beat="7"], [data-beat="8"], [data-beat="9"], [data-beat="10"], [data-beat="11"], [data-beat="12"]) .demo-swap { opacity: 1; }
.story:is([data-beat="7"], [data-beat="8"], [data-beat="9"], [data-beat="10"], [data-beat="11"], [data-beat="12"]) .e101 [data-circuit="LP-4-12"] { opacity: 0; }
.e101 .demo-swap-symbol > circle { stroke-dasharray: 44; stroke-dashoffset: 44; }
.e101 .demo-swap-symbol > path:not(.cf) { stroke-dasharray: 22; stroke-dashoffset: 22; }
.e101 .demo-swap-symbol > .cf,
.e101 .demo-swap > :not(.demo-swap-symbol) { opacity: 0; }
.story:is([data-beat="7"], [data-beat="8"], [data-beat="9"], [data-beat="10"], [data-beat="11"], [data-beat="12"]) .demo-swap-symbol > :not(.cf) { stroke-dashoffset: 0; }
.story:is([data-beat="7"], [data-beat="8"], [data-beat="9"], [data-beat="10"], [data-beat="11"], [data-beat="12"]) .demo-swap-symbol > .cf,
.story:is([data-beat="7"], [data-beat="8"], [data-beat="9"], [data-beat="10"], [data-beat="11"], [data-beat="12"]) .demo-swap > :not(.demo-swap-symbol) { opacity: 1; }

/* The window's motion, for a visitor who has not asked for less, as the video's stage moves it (the scroll story pans
   instead, section 10, and shows each beat's messages at once, below: DB-0333, DB-0341): a step (data-move, one beat
   forward or back with the panel open) moves through, a message
   opening its row as it fades in, so the conversation scrolls up under it, while
   the message it follows stays in view; the card's actions fade to half strength at the press; and at beat 7 the change
   is drawn once the camera has reached the sink. A jump (any other move: a beat or more skipped, or the panel opening
   or closing) shows its panel's still at once, so the panel is never open with nothing in it; a still move (one the
   script's scroll check found, in a browser painting nothing to fade) shows all of it at once: the note, the camera,
   the leader and the panel. */
@media (prefers-reduced-motion: no-preference) {
  .story .demo-drop,
  .story .demo-card {
    transition-property: grid-template-rows, opacity, visibility;
    transition-duration: 300ms;
    transition-timing-function: var(--ease);
  }
  .story .demo-card-actions {
    transition-property: opacity;
    transition-duration: 200ms;
    transition-timing-function: var(--ease);
  }
  .story .demo-swap,
  .story .e101 [data-circuit="LP-4-12"] {
    transition-property: opacity;
    transition-duration: 300ms;
    transition-timing-function: var(--ease);
  }
  .story[data-beat="7"] :is(.demo-swap, .e101 [data-circuit="LP-4-12"]) { transition-delay: 450ms; }
  .story[data-move="jump"] :is(.demo-drop, .demo-card, .demo-card-actions, .demo-swap, .e101 [data-circuit="LP-4-12"]) { transition-property: none; }
  .story[data-move="still"] :is(.story-note, .story-window, .story-leader, .demo-drop, .demo-card, .demo-card-actions, .demo-swap, .e101 [data-circuit="LP-4-12"]) { transition-property: none; }
}

/* The scroll story's scenes (DB-0333; DB-0341: after the pan; DB-0343: the list and Teach), for a visitor who has not
   asked for less; the video's stage, which sets no data-story, keeps the steps above. A beat change is a pan where its
   framing changes and a hold where it does not (section 10): the beat's messages are there at once, laid out before
   the camera measures its frame. Then within the beat a small motion shows the subject, once the pan would have
   arrived (--story-pan) and each done within 1.2 s: the drop zone's dashed ring breathes once (2); the typed line's
   caret blinks three times (3); the dots pulse, as they always have (section 10c), and what is being read appears line
   by line (4); the first card's border lights and the other six proposals come in one by one (5); the Accept button
   presses, darkening as it goes down, the card's actions dimming after it (6); on the sheet the change is drawn, the
   one motion on the sheet (7, below); the first proposal's tick comes and the second card's border lights (8); Teach
   (9): Teach presses and the card's actions dim, the correction comes in its field, Send presses, then the proposal is
   read again, the old words giving way to the new, as SparkFlow's answer comes; the finding's two readings (10); the
   answer's reference (11); the record (12). A still move (the scroll check's) shows its scene at once. The fades are
   cue-in, the stylesheet's one fade (section 9), run backwards for the old words; a press or a breath is the
   element's own --story-play, eased once on the way into its beat and dropped on the way out.
   The change at the sink (7; the founder: "take the receptacle, delete it, then show the new GFCI drawn"), in three
   stages, 200 ms after the pan arrives: the sheet's own receptacle, its tag and the tag's leader fade out over 250 ms;
   then the GFCI receptacle draws itself over 500 ms, its circle and its two lines by their dash offsets over the
   first 350 and its two halves' fill over the last 150; then its tag, on its leader, and "GFCI" fade in over 150 ms:
   900 ms in all, on the sheet's own classes, with no highlight (the note says what happened). Leaving beat 7, or
   reaching it by a still move, all of it is at its end at once. */
@media (prefers-reduced-motion: no-preference) {
  .story[data-story] :is(.demo-drop, .demo-card, .demo-swap, .e101 [data-circuit="LP-4-12"]) { transition-property: none; }
  .story[data-story]:not([data-move="still"])[data-beat="2"] .demo-drop-in {
    --story-play: 1;
    scale: calc(1 + 0.03 * 4 * var(--story-play, 0) * (1 - var(--story-play, 0)));
    transition-property: --story-play;
    transition-duration: 900ms;
    transition-delay: var(--story-pan);
    transition-timing-function: ease-in-out;
  }
  .story[data-story]:not([data-move="still"])[data-beat="3"] .sf-field::after {
    animation-name: cue-in;
    animation-duration: 400ms;
    animation-delay: var(--story-pan);
    animation-timing-function: steps(2, jump-none);
    animation-iteration-count: 3;
  }
  .story[data-story]:not([data-move="still"])[data-beat="4"] .sf-steps > li,
  .story[data-story]:not([data-move="still"])[data-beat="5"] .demo-list > li:nth-child(n + 2) {
    animation-name: cue-in;
    animation-duration: 240ms;
    animation-delay: calc(var(--story-pan) + 40ms);
    animation-timing-function: var(--ease);
    animation-fill-mode: backwards;
  }
  .story[data-story]:not([data-move="still"])[data-beat="4"] .sf-steps > li:nth-child(2) { animation-delay: calc(var(--story-pan) + 200ms); }
  .story[data-story]:not([data-move="still"])[data-beat="4"] .sf-steps > li:nth-child(3) { animation-delay: calc(var(--story-pan) + 360ms); }
  .story[data-story]:not([data-move="still"])[data-beat="4"] .sf-steps > li:nth-child(4) { animation-delay: calc(var(--story-pan) + 520ms); }
  .story[data-story]:not([data-move="still"])[data-beat="5"] .demo-list > li:nth-child(3) { animation-delay: calc(var(--story-pan) + 100ms); }
  .story[data-story]:not([data-move="still"])[data-beat="5"] .demo-list > li:nth-child(4) { animation-delay: calc(var(--story-pan) + 160ms); }
  .story[data-story]:not([data-move="still"])[data-beat="5"] .demo-list > li:nth-child(5) { animation-delay: calc(var(--story-pan) + 220ms); }
  .story[data-story]:not([data-move="still"])[data-beat="5"] .demo-list > li:nth-child(6) { animation-delay: calc(var(--story-pan) + 280ms); }
  .story[data-story]:not([data-move="still"])[data-beat="5"] .demo-list > li:nth-child(7) { animation-delay: calc(var(--story-pan) + 340ms); }
  .story[data-story]:not([data-move="still"])[data-beat="5"] .demo-item-1 .acad-card,
  .story[data-story]:not([data-move="still"])[data-beat="8"] .demo-item-2 .acad-card {
    transition-property: border-color;
    transition-duration: 600ms;
    transition-delay: var(--story-pan);
    transition-timing-function: var(--ease);
  }
  .story[data-story]:not([data-move="still"])[data-beat="6"] .demo-item-1 .mock-action-primary {
    --story-play: 1;
    scale: calc(1 - 0.06 * 4 * var(--story-play, 0) * (1 - var(--story-play, 0)));
    transition-property: --story-play, border-color, background-color;
    transition-duration: 360ms, 120ms, 120ms;
    transition-delay: var(--story-pan), calc(var(--story-pan) + 120ms), calc(var(--story-pan) + 120ms);
    transition-timing-function: ease-in-out;
  }
  .story[data-story]:not([data-move="still"])[data-beat="6"] .demo-item-1 .demo-card-actions {
    transition-property: opacity;
    transition-delay: calc(var(--story-pan) + 380ms);
  }
  .story[data-story]:not([data-move="still"])[data-beat="8"] .demo-item-1 > .demo-item-line {
    animation-name: cue-in;
    animation-duration: 240ms;
    animation-delay: calc(var(--story-pan) + 40ms);
    animation-timing-function: var(--ease);
    animation-fill-mode: backwards;
  }
  .story[data-story]:not([data-move="still"])[data-beat="9"] .demo-item-3 .mock-action-text {
    --story-play: 1;
    scale: calc(1 - 0.06 * 4 * var(--story-play, 0) * (1 - var(--story-play, 0)));
    transition-property: --story-play;
    transition-duration: 360ms;
    transition-delay: var(--story-pan);
    transition-timing-function: ease-in-out;
  }
  .story[data-story]:not([data-move="still"])[data-beat="9"] .demo-item-3 .demo-card-actions {
    transition-property: opacity;
    transition-delay: calc(var(--story-pan) + 300ms);
  }
  .story[data-story]:not([data-move="still"])[data-beat="9"] .demo-teach {
    animation-name: cue-in;
    animation-duration: 240ms;
    animation-delay: calc(var(--story-pan) + 280ms);
    animation-timing-function: var(--ease);
    animation-fill-mode: backwards;
  }
  .story[data-story]:not([data-move="still"])[data-beat="9"] .demo-teach .mock-action-primary {
    --story-play: 1;
    scale: calc(1 - 0.06 * 4 * var(--story-play, 0) * (1 - var(--story-play, 0)));
    transition-property: --story-play, border-color, background-color;
    transition-duration: 360ms, 120ms, 120ms;
    transition-delay: calc(var(--story-pan) + 540ms), calc(var(--story-pan) + 660ms), calc(var(--story-pan) + 660ms);
    transition-timing-function: ease-in-out;
  }
  .story[data-story]:not([data-move="still"])[data-beat="9"] .demo-item-3 .demo-read-before {
    animation-name: cue-in;
    animation-direction: reverse;
    animation-duration: 150ms;
    animation-delay: calc(var(--story-pan) + 900ms);
    animation-timing-function: var(--ease);
    animation-fill-mode: both;
  }
  .story[data-story]:not([data-move="still"])[data-beat="9"] .demo-item-3 .demo-read-after {
    animation-name: cue-in;
    animation-duration: 150ms;
    animation-delay: calc(var(--story-pan) + 1050ms);
    animation-timing-function: var(--ease);
    animation-fill-mode: backwards;
  }
  .story[data-story]:not([data-move="still"])[data-beat="9"] .demo-card-taught .acad-msg-in {
    animation-name: cue-in;
    animation-duration: 240ms;
    animation-delay: calc(var(--story-pan) + 900ms);
    animation-timing-function: var(--ease);
    animation-fill-mode: backwards;
  }
  .story[data-story]:not([data-move="still"])[data-beat="7"] .e101 [data-circuit="LP-4-12"] {
    transition-property: opacity;
    transition-duration: 250ms;
    transition-delay: calc(var(--story-pan) + 200ms);
    transition-timing-function: var(--ease);
  }
  .story[data-story]:not([data-move="still"])[data-beat="7"] .demo-swap-symbol > :not(.cf) {
    transition-property: stroke-dashoffset;
    transition-duration: 350ms;
    transition-delay: calc(var(--story-pan) + 450ms);
    transition-timing-function: ease-in-out;
  }
  .story[data-story]:not([data-move="still"])[data-beat="7"] .demo-swap-symbol > .cf {
    transition-property: opacity;
    transition-duration: 150ms;
    transition-delay: calc(var(--story-pan) + 800ms);
    transition-timing-function: var(--ease);
  }
  .story[data-story]:not([data-move="still"])[data-beat="7"] .demo-swap > :not(.demo-swap-symbol) {
    transition-property: opacity;
    transition-duration: 150ms;
    transition-delay: calc(var(--story-pan) + 950ms);
    transition-timing-function: var(--ease);
  }
  .story[data-story]:not([data-move="still"])[data-beat="10"] .demo-card-review .readings > div,
  .story[data-story]:not([data-move="still"])[data-beat="11"] .demo-card-answer .source-panel,
  .story[data-story]:not([data-move="still"])[data-beat="12"] .demo-card-record .acad-msg-body {
    animation-name: cue-in;
    animation-duration: 240ms;
    animation-delay: calc(var(--story-pan) + 40ms);
    animation-timing-function: var(--ease);
    animation-fill-mode: backwards;
  }
  .story[data-story]:not([data-move="still"])[data-beat="10"] .demo-card-review .readings > div:nth-child(2) { animation-delay: calc(var(--story-pan) + 200ms); }
}

/* ===== 10c. The AutoCAD frame (DB-0308; the plug-in's own palette, DB-0309; the AutoCAD Electrical window, DB-0310) =====
   One structure, .acad-frame, for the story's window (section 10; DB-0311 retired the hero's frame, the three
   workflows' and the homepage's close-up) and the close-up on the how it works page (section 14), drawn from the
   AutoCAD Electrical window an engineer works in, every part generic. Top to bottom, 206 px of chrome round the body:
   (a) the quick access strip, 26 px: a plain square where the application's logo would be, six small glyphs (new,
       open, save, undo, redo, print), "AutoCAD Electrical" and "E-101.dwg" at its centre, and at its right a rounded
       search field, the person glyph with "engineer", a help glyph and the window's three controls;
   (b) the ribbon's tab words, 22 px, Schematic the active tab, joined to the ribbon; SparkFlow's kept at the end;
   (c) the ribbon, 88 px: six groups as the Schematic tab has them, each big button a 36 px glyph over a two-line
       caption, small glyphs in pairs and rows beside them, the group's caption under them in the dim words, a thin
       divider between groups;
   (d) the document tabs, 24 px: Start, E-001*, E-101* (active, lighter), E-102* and a plus, each named tab with its
       cross, the active one's brighter;
   (e) the body: the dock on the left, 236 px wide and the body's full height: the Project Manager's title bar with its
       grip, its seven glyphs and its project field; the SparkFlow panel docked in it, about 55 percent of the body's
       height, its title bar, its conversation and the Ask box last, its interior SparkFlow's own (DB-0314: its own
       surface, below); the project tree, dim, the open drawing lighter; the dock's two vertical tabs on its right edge;
   (f) model space beside it: the sheet with about 8 percent of graphite round it (section 10), the corner label, the
       viewport's three controls, the view cube, the navigation bar and the UCS icon, each where the drawing has
       nothing;
   (g) the command line, 24 px: a cell with a cross and a wrench, then the prompt field "Command:" with a dim caret;
   (h) the status bar, 22 px: MODEL, eight dim glyphs, "1:1" and "Decimal" with their carets, the isolate and customise
       glyphs.
   A row that cannot hold all its parts in a narrow frame lets the last of them go (a wrapping row with its second
   line clipped): the tab words and the ribbon's groups from the right, SparkFlow's tab kept; the quick access strip's
   right end from its left, the window's controls kept. Under 720 px the strips keep their heights and model space's
   own parts give way; the close-up's dock stacks under model space with the SparkFlow panel first and the tree
   hidden, while the story's window keeps the dock beside model space, its camera filling the width instead. Its
   colours are the frame's four tokens and the tints mixed from them, and inside the SparkFlow panel the palette's
   three and theirs (DB-0314), each word 4.5:1 or more on what it sits on. Its glyphs are generic shapes drawn here (a
   page, a folder, a wire, scissors): no logo, icon or screenshot of Autodesk's; its one image is SparkFlow's own mark.
   No form or field: the search field, the Ask box, the guidance field and the prompt are drawn, not inputs. Nothing in
   the chrome moves; inside the panel, SparkFlow's own thinking dots and applying ring do, where motion is welcome,
   and in the story each scene's one small motion (section 10b, DB-0333). */
.acad-frame {
  overflow: hidden;
  border: 1px solid var(--acad-rule);
  border-radius: var(--radius-viewport);
  background: var(--acad-window);
  color: var(--acad-text);
  font-size: 12px;
  line-height: 1.35;
}

.acad-frame :is(p, li, dd) { max-width: none; }

/* The focus ring keeps its 2 px and its offset, drawn in the accent's tint on the dark chrome. */
.acad-frame :focus-visible { outline-color: var(--accent-tint); }

.acad-glyph {
  flex: none;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.25;
  stroke-linecap: round;
  stroke-linejoin: round;
}

/* A glyph's accent, in a tint the frame already carries: a wire's red, a symbol's blue, the refresh's green. */
.acad-glyph .acad-ink-red { stroke: var(--redline-tint); }
.acad-glyph .acad-ink-blue { stroke: var(--accent-tint); }
.acad-glyph .acad-ink-green { stroke: var(--applied-tint); }

/* A drop down's caret after its words: a small triangle, drawn in the words' own colour. */
.acad-dd::after {
  content: "";
  display: inline-block;
  flex: none;
  margin-left: 4px;
  vertical-align: 2px;
  border-top: 3px solid currentColor;
  border-right: 3px solid transparent;
  border-left: 3px solid transparent;
}

/* (a) The quick access strip: its two ends and the title at its centre. */
.acad-title {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr);
  align-items: center;
  gap: 12px;
  height: 26px;
  padding: 0 8px;
  font-size: 11px;
  line-height: 1;
  white-space: nowrap;
}

/* Each end is a wrapping row of 16 px parts whose first line alone is in view. */
.acad-qat,
.acad-account {
  display: flex;
  flex-wrap: wrap;
  align-content: flex-start;
  align-items: center;
  gap: 12px 9px;
  height: 26px;
  padding: 5px 0;
  overflow: hidden;
  color: var(--acad-dim);
}

/* The right end runs from the right edge, its parts in the reverse of the page's order: the window's controls stay
   and the search field is the first to go. */
.acad-account { flex-direction: row-reverse; }

/* Where the application's logo would be: a plain square, no letter. */
.acad-logo {
  flex: none;
  width: 16px;
  height: 16px;
  border: 1px solid var(--acad-dim);
  border-radius: 3px;
  background: var(--acad-chrome);
}

.acad-name { display: flex; gap: 14px; }
.acad-file { color: var(--acad-dim); }

.acad-user {
  display: flex;
  align-items: center;
  gap: 5px;
  height: 16px;
}

.acad-search {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  width: 168px;
  height: 16px;
  padding: 0 6px 0 9px;
  border: 1px solid var(--acad-rule);
  border-radius: 8px;
  background: var(--acad-chrome);
}

/* (b) The ribbon's tab words. The built-in tabs are a wrapping row whose second line is clipped, so the last of them
   go first in a narrow frame; SparkFlow's tab follows it and stays. */
.acad-tabs {
  display: flex;
  align-items: flex-end;
  height: 22px;
  padding: 0 8px;
  font-size: 11px;
  line-height: 1;
  white-space: nowrap;
}

.acad-tabs-run {
  display: flex;
  flex: 0 1 auto;
  flex-wrap: wrap;
  align-content: flex-start;
  min-width: 0;
  height: 22px;
  overflow: hidden;
}

.acad-tabs span {
  display: flex;
  flex: none;
  align-items: center;
  height: 22px;
  padding: 0 8px;
  border-radius: 3px 3px 0 0;
  color: var(--acad-dim);
}

.acad-tabs .acad-tab-on { background: var(--acad-chrome); color: var(--acad-text); font-weight: 600; }
.acad-tabs > .acad-glyph { align-self: center; margin-left: 6px; color: var(--acad-dim); }

/* (c) The ribbon: a wrapping row of groups whose second line is clipped, so the last groups go first. */
.acad-ribbon {
  display: flex;
  flex-wrap: wrap;
  align-content: flex-start;
  row-gap: 12px;
  height: 88px;
  padding: 0 2px;
  overflow: hidden;
  border-bottom: 1px solid var(--acad-rule);
  background: var(--acad-chrome);
  font-size: 11px;
  line-height: 12px;
  white-space: nowrap;
}

.acad-group {
  display: flex;
  flex: none;
  flex-direction: column;
  height: 87px;
  padding: 0 6px;
  border-right: 1px solid var(--acad-rule);
}

.acad-tools {
  display: flex;
  flex: 1 1 auto;
  align-items: flex-start;
  gap: 4px;
  padding-top: 5px;
}

.acad-group-name {
  height: 18px;
  color: var(--acad-dim);
  line-height: 16px;
  text-align: center;
}

/* A big button: its 36 px glyph over a two-line caption. */
.acad-big {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 2px;
  min-width: 38px;
  text-align: center;
}

.acad-big .acad-glyph { stroke-width: 1.5; }

/* The small glyphs: in pairs with their carets, three by three, or in rows with their words. */
.acad-pairs {
  display: grid;
  grid-template-columns: repeat(3, auto);
  gap: 6px 4px;
  padding-top: 3px;
}

.acad-rows {
  display: flex;
  flex-direction: column;
  gap: 6px;
  padding-top: 3px;
}

.acad-row {
  display: flex;
  align-items: center;
  gap: 5px;
}

/* (d) The document tabs, over the body: the active one lighter, its cross brighter; the plus after them. */
.acad-doc-tabs {
  display: flex;
  flex-wrap: wrap;
  align-content: flex-start;
  align-items: center;
  row-gap: 4px;
  height: 24px;
  overflow: hidden;
  border-bottom: 1px solid var(--acad-rule);
  font-size: 11px;
  line-height: 1;
  white-space: nowrap;
}

.acad-doc {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  height: 23px;
  padding: 0 9px 0 12px;
  border-right: 1px solid var(--acad-rule);
  color: var(--acad-dim);
}

.acad-doc .acad-glyph { color: var(--acad-dim); }
.acad-doc-tabs > .acad-doc-on { background: var(--acad-chrome); color: var(--acad-text); }
.acad-doc-tabs > .acad-doc-on .acad-glyph { color: var(--acad-text); }
.acad-doc-tabs > .acad-glyph { margin: 0 10px; color: var(--acad-dim); }

/* (e) The body: the dock on the left, model space beside it. The dock never sets the body's height (its size is
   contained); model space does, at least as tall as the dock's parts need. */
.acad-body {
  display: grid;
  grid-template-columns: 236px minmax(0, 1fr);
}

/* The dock, one grid: the Project Manager's title bar across it; its glyphs, its field, the SparkFlow panel (about
   55 percent of the dock's height, at least what the proposal's message needs: 280 px since DB-0314's title bar,
   bubbles and 32 px actions) and the tree down its main column; the two vertical tabs down its right edge. */
.acad-dock {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 18px;
  grid-template-rows: 20px 24px 28px max(55%, 280px) minmax(0, 1fr);
  grid-template-areas: "bar bar" "tools tabs" "field tabs" "panel tabs" "tree tabs";
  contain: size;
  border-right: 1px solid var(--acad-rule);
  background: var(--acad-chrome);
  font-size: 11px;
  line-height: 1.3;
}

/* The Project Manager's title bar: the palette's grip, then its name in small capitals. */
.acad-pm-bar {
  grid-area: bar;
  display: flex;
  align-items: center;
  gap: 7px;
  height: 20px;
  padding: 0 8px;
  border-bottom: 1px solid var(--acad-rule);
  background: var(--acad-window);
  font-weight: 600;
  letter-spacing: 0.04em;
  line-height: 1;
}

.acad-pm-bar .acad-glyph { color: var(--acad-dim); stroke-width: 1.5; }

/* Its row of seven glyphs, and the project field with its caret. */
.acad-pm-tools {
  grid-area: tools;
  display: flex;
  align-items: center;
  gap: 10px;
  height: 24px;
  padding: 0 8px;
  overflow: hidden;
  color: var(--acad-dim);
}

.acad-pm-field {
  grid-area: field;
  display: flex;
  align-items: center;
  justify-content: space-between;
  height: 20px;
  margin: 2px 6px 6px 8px;
  padding: 0 6px 0 7px;
  border: 1px solid var(--acad-rule);
  background: var(--acad-window);
  line-height: 1;
}

/* The SparkFlow panel, docked in the dock under the project field: its title bar, its conversation, the Ask box. Its
   interior is SparkFlow's own (DB-0314; the founder: a state of the art assistant, not a bland AutoCAD feature), as a
   plug-in draws its own content in an AutoCAD palette: its own surface, --sf-surface, with a 2 px top edge in the accent
   and 10 px corners set off from the dock's chrome, its words in --sf-text. The dock round it, the auto-hide and close
   glyphs and the closed panel's vertical tab stay AutoCAD's. */
.acad-palette {
  grid-area: panel;
  display: flex;
  flex-direction: column;
  min-height: 0;
  overflow: hidden;
  border-top: 2px solid var(--accent);
  border-radius: 10px;
  background: var(--sf-surface);
  color: var(--sf-text);
}

/* Its title bar: SparkFlow's mark at 24 px, "SparkFlow" at 13 px and 600 and the dim word "Assistant", then the
   auto-hide glyph (two small triangles) and the close glyph (a cross). */
.acad-palette-bar {
  display: flex;
  flex: none;
  align-items: center;
  gap: 6px;
  height: 36px;
  padding: 0 7px 0 9px;
  border-bottom: 1px solid var(--sf-line);
  font-size: 11px;
  line-height: 1;
}

.sf-logo { flex: none; width: auto; height: 24px; }
.sf-name { font-size: 13px; font-weight: 600; }
.sf-role { margin-right: auto; color: var(--sf-dim); font-size: 11px; font-weight: 500; }
.acad-palette-bar .acad-glyph { color: var(--sf-dim); }

/* The conversation, held to the panel's foot: what does not fit scrolls up out of view, as a chat's messages do. */
.acad-palette-body {
  display: flex;
  flex: 1 1 auto;
  flex-direction: column;
  justify-content: flex-end;
  min-height: 0;
  padding: 0 8px 6px;
  overflow: hidden;
  font-size: 11px;
  line-height: 1.35;
}

.acad-palette-body > * { flex: none; }

/* A message: the responder's carry SparkFlow's mark at their left, 20 px, and their words in a soft bubble
   (--sf-bubble, 10 px corners); the engineer's sit at the right on --accent-ink. The space above a message is its
   parts' own, so a message closed outside its beats (section 10b) takes none. */
.acad-msg-in {
  display: flex;
  align-items: flex-start;
  gap: 6px;
}

.acad-msg-in > * { margin-top: 8px; }

.acad-avatar { flex: none; width: 20px; height: 20px; object-fit: contain; }

.acad-msg-body {
  display: flex;
  flex: 1 1 auto;
  flex-direction: column;
  gap: 6px;
  min-width: 0;
  padding: 7px 10px;
  border-radius: 10px;
  background: var(--sf-bubble);
}

/* The proposal's card is a bubble of its own with its actions under it; SparkFlow thinking has no bubble, its dots and
   its words beside the mark. */
.acad-msg-body:has(> .acad-card),
.demo-card-thinking .acad-msg-body { padding: 0; background: none; }

.acad-msg-mine > .acad-msg-in { justify-content: flex-end; }

.acad-bubble {
  max-width: 88%;
  padding: 7px 10px;
  border-radius: 10px 10px 3px 10px;
  background: var(--accent-ink);
  color: var(--sf-text);
}

/* The note as SparkFlow read it from the markup, quoted in the markup's ink: its tint, at 500. */
.acad-quote {
  padding-left: 8px;
  border-left: 2px solid var(--redline-tint);
  color: var(--redline-tint);
  font-weight: 500;
}

/* The proposal's card: a bubble whose edge turns the accent's tint while it is the active object (section 10b). */
.acad-card {
  padding: 8px 10px;
  border: 1px solid transparent;
  border-radius: 10px;
  background: var(--sf-bubble);
}

.acad-card > * + * { margin-top: 3px; }

.demo-card-head,
.demo-card-ref { color: var(--sf-dim); font-size: 11px; line-height: 1.3; }
.demo-card-instruction { font-weight: 500; line-height: 1.35; }

/* The validators' line and the applied note carry the applied state's check mark, drawn: the words carry the
   meaning. */
.demo-card-check,
.demo-card-applied { position: relative; padding-left: 16px; font-size: 11px; line-height: 1.3; }

.demo-card-check::before,
.demo-card-applied::before {
  content: "";
  position: absolute;
  left: 1px;
  top: 0.4em;
  width: 8px;
  height: 4px;
  border-left: 2px solid var(--applied-tint);
  border-bottom: 2px solid var(--applied-tint);
  transform: rotate(-45deg);
}

.demo-card-applied { font-weight: 500; }

/* The palette's actions, drawn: words on shapes, not controls of this page, each 32 px tall with 8 px corners: the
   first filled in the accent (Accept, Start), the next outlined (Reject, Skip), Teach in words alone. */
.demo-card-actions,
.sf-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 5px;
}

.acad-palette .mock-action {
  min-height: 32px;
  padding: 0 10px;
  border: 1px solid var(--sf-dim);
  border-radius: 8px;
  color: var(--sf-text);
  font-size: 11px;
}

.acad-palette .mock-action-primary { border-color: var(--accent); background: var(--accent); color: var(--surface); }
.acad-palette .mock-action-text { padding: 0 6px; border-color: transparent; color: var(--accent-tint); }

.demo-record-head { font-weight: 600; }
.demo-card-record ul { padding-left: 1.1em; }
.demo-card-record li + li { margin-top: 2px; }

/* The guidance step's field (DB-0314, the story's beat 3): the engineer's one line as typed, drawn as a field and never
   one: a box darker than its bubble with an edge in the accent's tint, the line wrapping in the palette's width as a
   long line does in a field that grows with it, the caret after its last word. */
.sf-field {
  padding: 6px 8px;
  border: 1px solid var(--accent-tint);
  border-radius: 8px;
  background: var(--sf-surface);
}

.sf-field::after {
  content: "";
  display: inline-block;
  width: 1px;
  height: 12px;
  margin-left: 2px;
  vertical-align: -2px;
  background: var(--accent-tint);
}

/* Thinking (beat 4): three dots in the accent's tint beside "Reading the markup" in the dim words. The dots are shown,
   pulsing over 1.2 s, only where motion is welcome; without it the words alone say the state. */
.sf-thinking {
  display: flex;
  align-items: center;
  gap: 8px;
  min-height: 20px;
  color: var(--sf-dim);
}

.sf-dots { display: none; gap: 4px; }
.sf-dots > span { width: 5px; height: 5px; border-radius: 50%; background: var(--accent-tint); }

/* Applying (beat 6): under the card, in line with it, the 16 px ring (its track --sf-line, its arc the accent's tint)
   and "Applying in AutoCAD". The ring turns only where motion is welcome and stands still otherwise. */
.sf-applying {
  display: flex;
  align-items: center;
  gap: 8px;
  padding-left: 26px;
  font-weight: 500;
}

.sf-ring {
  flex: none;
  width: 16px;
  height: 16px;
  border: 2px solid var(--sf-line);
  border-top-color: var(--accent-tint);
  border-radius: 50%;
}

@media (prefers-reduced-motion: no-preference) {
  .sf-dots { display: inline-flex; }
  .sf-dots > span {
    animation-name: sf-pulse;
    animation-duration: 1.2s;
    animation-timing-function: ease-in-out;
    animation-iteration-count: infinite;
  }
  .sf-dots > span:nth-child(2) { animation-delay: 0.2s; }
  .sf-dots > span:nth-child(3) { animation-delay: 0.4s; }
  .sf-ring {
    animation-name: sf-turn;
    animation-duration: 800ms;
    animation-timing-function: linear;
    animation-iteration-count: infinite;
  }
}

@keyframes sf-pulse {
  0%, 80%, 100% { opacity: 0.3; transform: scale(0.75); }
  40% { opacity: 1; transform: scale(1); }
}

@keyframes sf-turn {
  to { transform: rotate(360deg); }
}

/* At the very bottom of the panel, the Ask box, drawn: a pill on a bubble's ground with a soft inner shadow, its prompt
   in the dim words, the send button a circle in the accent with its arrow. Its prompt is the frame's one set of words
   under 11 px: at 10 px the whole sentence and the button fit the panel's 217 px, as a field's placeholder does. */
.acad-chat {
  display: flex;
  flex: none;
  align-items: center;
  justify-content: space-between;
  gap: 5px;
  height: 28px;
  margin: 0 3px 4px;
  padding: 0 4px 0 8px;
  border-radius: 14px;
  background: var(--sf-bubble);
  box-shadow: var(--shadow-inset);
  color: var(--sf-dim);
  font-size: 10px;
  line-height: 1;
  white-space: nowrap;
}

.sf-send {
  display: grid;
  flex: none;
  place-items: center;
  width: 20px;
  height: 20px;
  border-radius: 50%;
  background: var(--accent);
  color: var(--surface);
}

/* The project tree, dim: the project's folder and its drawings on dotted lines, the open one lighter. */
.acad-tree {
  grid-area: tree;
  display: flex;
  flex-direction: column;
  gap: 3px;
  min-height: 0;
  padding: 7px 8px;
  overflow: hidden;
  color: var(--acad-dim);
  line-height: 1;
  white-space: nowrap;
}

.acad-tree > span {
  display: flex;
  flex: none;
  align-items: center;
  gap: 5px;
  height: 15px;
}

.acad-tree > span + span {
  position: relative;
  margin-left: 4px;
  padding-left: 14px;
}

.acad-tree > span + span::before {
  content: "";
  position: absolute;
  top: -11px;
  left: 0;
  width: 9px;
  height: 18px;
  border-bottom: 1px dotted var(--acad-dim);
  border-left: 1px dotted var(--acad-dim);
}

.acad-tree > .acad-tree-on { color: var(--acad-text); font-weight: 600; }

/* The dock's two vertical tabs on its right edge, read from the foot up, as the Project Manager's are. */
.acad-dock-tabs {
  grid-area: tabs;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 10px;
  padding-top: 24px;
  overflow: hidden;
  border-left: 1px solid var(--acad-rule);
  background: var(--acad-window);
}

.acad-dock-tabs > span {
  padding: 8px 0;
  color: var(--acad-dim);
  line-height: 17px;
  white-space: nowrap;
  writing-mode: vertical-rl;
  transform: rotate(180deg);
}

.acad-dock-tabs > .acad-dock-tab-on { color: var(--acad-text); }

/* The panel closed, the story's beat 1 (section 10b): its vertical tab on model space's left edge, under the
   corner label, read from the foot up as the dock's tabs are. */
.acad-palette-closed {
  position: absolute;
  top: 24px;
  left: 0;
  z-index: 1;
  display: none;
  padding: 10px 0;
  border: 1px solid var(--acad-rule);
  background: var(--acad-chrome);
  color: var(--acad-text);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.02em;
  line-height: 16px;
  white-space: nowrap;
  writing-mode: vertical-rl;
  transform: rotate(180deg);
}

/* (f) Model space: graphite, the sheet's box at its middle (section 11), at least 420 px tall so the dock beside it has
   its room (the story's window sets its own height, section 10). Its own parts are in the viewport's dim tone (4.97:1 on graphite), each where the drawing has nothing:
   the corner label at its top left, the viewport's three controls at its top right, the view cube under them, the
   navigation bar under the cube on the right edge, the UCS icon at its bottom left, all in the graphite round the
   sheet. */
.acad-model {
  position: relative;
  display: flex;
  flex-direction: column;
  justify-content: center;
  min-height: 420px;
  overflow: hidden;
  background: var(--viewport);
  color: var(--viewport-dim);
}

.acad-view {
  position: absolute;
  top: 4px;
  left: 6px;
  font-size: 11px;
  line-height: 1;
  white-space: nowrap;
}

.acad-vpctl,
.acad-cube,
.acad-nav,
.acad-ucs {
  position: absolute;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.25;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.acad-vpctl { top: 5px; right: 8px; }
.acad-cube { top: 18px; right: 6px; }
.acad-nav { top: 96px; right: 7px; }
.acad-ucs { bottom: 6px; left: 6px; }

/* The view cube: a ring with N, E, S and W on it round the square TOP, and WCS under it. */
.acad-cube circle { stroke-width: 3; }

.acad-cube text,
.acad-ucs text { fill: currentColor; stroke: none; font-family: var(--font); font-size: 11px; font-weight: 600; }

/* The ring's four letters sit on it, the ring cut away behind each in model space's own graphite. */
.acad-cube .acad-cube-dir { stroke: var(--viewport); stroke-width: 4px; paint-order: stroke; }

/* (g) The command line: a cell with the cross and the wrench, then the prompt field in the chrome's colour,
   "Command:" and a dim caret after it. */
.acad-command {
  display: flex;
  align-items: center;
  gap: 8px;
  height: 24px;
  padding: 0 6px 0 8px;
  border-top: 1px solid var(--acad-rule);
  color: var(--acad-dim);
  font-size: 11px;
  line-height: 1;
  white-space: nowrap;
}

.acad-prompt {
  display: flex;
  flex: 1 1 auto;
  align-items: center;
  align-self: stretch;
  margin: 3px 0;
  padding: 0 8px;
  border: 1px solid var(--acad-rule);
  background: var(--acad-chrome);
  color: var(--acad-text);
}

.acad-prompt::after {
  content: "";
  height: 12px;
  margin-left: 5px;
  border-left: 1px solid var(--acad-dim);
}

/* (h) The status bar: MODEL, the eight glyphs, the scale and the units with their carets, the isolate and customise
   glyphs, set from its right edge as AutoCAD sets them; in a narrow frame the last of them go first. */
.acad-status {
  display: flex;
  flex-wrap: wrap;
  align-content: flex-start;
  align-items: center;
  justify-content: flex-end;
  gap: 12px 11px;
  height: 22px;
  padding: 3px 10px;
  overflow: hidden;
  border-top: 1px solid var(--acad-rule);
  color: var(--acad-dim);
  font-size: 11px;
  line-height: 14px;
  white-space: nowrap;
}

.acad-status-on { color: var(--acad-text); font-weight: 600; letter-spacing: 0.04em; }

/* The close-up's phone frame (direction 4, under 720 px; the story's window keeps the dock beside model space at
   every width, section 10): the strips at their heights, their parts going from the ends as in any narrow frame;
   model space at the view's own proportion; the dock stacked under it, the SparkFlow panel first, then the Project
   Manager's bar, glyphs and field; the tree and the dock's vertical tabs hidden. In every frame under 720 px model
   space's own parts give way, the sheet too small there to keep them clear of it. */
@media (max-width: 719.98px) {
  .acad-frame-closeup .acad-body {
    grid-template-columns: minmax(0, 1fr);
    grid-template-areas: "model" "dock";
  }
  .acad-frame-closeup .acad-model { grid-area: model; min-height: 0; }
  .acad-frame-closeup .acad-dock {
    grid-area: dock;
    grid-template-columns: minmax(0, 1fr);
    grid-template-rows: none;
    grid-template-areas: "panel" "bar" "tools" "field";
    contain: none;
    border-top: 1px solid var(--acad-rule);
    border-right: 0;
  }
  .acad-frame-closeup .acad-palette { border-top: 0; }
  .acad-frame-closeup .acad-tree,
  .acad-frame-closeup .acad-dock-tabs,
  .acad-view,
  .acad-vpctl,
  .acad-cube,
  .acad-nav,
  .acad-ucs { display: none; }
}

/* ===== 10d. The demonstration video's stage (DB-0331; DB-0334; DB-0342; DB-0344, a day with SparkFlow) =====
   video.html is the stage video/render.mjs renders, not a page of the site: 1920 by 1080 px, or 1080 by 1920
   (data-mode), on a dark desk. Its pane, in the window's px and moved by the story's camera (section 10): the desk's
   two screens with a plain chat window of the stage's own on the left (no product's look, name or colours) and the
   story's window on the right (sections 10b, 10c); over it the dragged PDF, a click, the cursor and the count beside a
   change. In the palette the stage's own parts, closed until js/video.js opens them. Over the pane, in the stage's px:
   the reading's fragments, the caption, the copy and the closing card. No gradient, no glow, the tokens alone;
   js/video.js sets every number of every frame. */
.video-page { overflow: hidden; }

.video-stage {
  --video-desk: color-mix(in srgb, var(--ink) 55%, var(--sf-surface));
  position: absolute;
  top: 0;
  left: 0;
  width: 1920px;
  height: 1080px;
  overflow: hidden;
  transform-origin: 0 0;
  background: var(--video-desk);
}

.video-stage[data-mode="9x16"] { width: 1080px; height: 1920px; }
.video-pane { position: absolute; top: 0; left: 0; width: 100%; height: 100%; overflow: hidden; }
.video-pane > .story { margin: 0; }
.video-pane .story-window { width: 1280px; height: 720px; margin: 0; }

.video-desk,
.video-world {
  position: absolute;
  top: 0;
  left: 0;
  width: 1280px;
  height: 720px;
  transform-origin: 0 0;
  transform: translate(var(--story-x, 0px), var(--story-y, 0px)) scale(var(--story-scale, 1));
  pointer-events: none;
}

.video-world { --video-shade: color-mix(in srgb, var(--ink) 34%, transparent); }
.video-desk > *,
.video-world > * { position: absolute; top: 0; left: 0; }
.video-stage :is(p, li) { max-width: none; }

/* The two screens, a gap between them. */
.video-screen { border: 1px solid var(--acad-rule); border-radius: 22px; background: var(--sf-surface); }
.video-screen-right { top: -16px; left: -16px; width: 1312px; height: 752px; }
.video-screen-left { top: 44px; left: -1136px; width: 1008px; height: 632px; }

/* The chat window, in the site's own light surfaces and words. */
.video-chat {
  top: 60px;
  left: -1120px;
  width: 976px;
  height: 600px;
  overflow: hidden;
  border-radius: 10px;
  background: var(--surface);
  color: var(--ink);
  font-size: 13px;
  line-height: 1.35;
}

.video-chat-bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  height: 34px;
  padding: 0 14px;
  border-bottom: 1px solid var(--rule);
  background: var(--stone);
  font-weight: 600;
}

.video-chat-glyph { fill: none; stroke: var(--ink-soft); stroke-width: 1.25; stroke-linecap: round; stroke-linejoin: round; }
.video-chat-side { position: absolute; top: 34px; bottom: 0; left: 0; width: 236px; padding: 12px 10px; border-right: 1px solid var(--rule); background: var(--stone); }
.video-chat-find { height: 30px; margin-bottom: 10px; padding: 0 10px; border: 1px solid var(--rule); border-radius: 8px; background: var(--surface); color: var(--ink-soft); line-height: 28px; }
.video-chat-row { display: flex; align-items: center; gap: 10px; height: 44px; padding: 0 8px; border-radius: 8px; font-weight: 500; }
.video-chat-on { background: var(--rule-soft); }

.video-chat-face {
  display: inline-flex;
  flex: none;
  align-items: center;
  justify-content: center;
  width: 28px;
  height: 28px;
  border-radius: 50%;
  background: var(--accent);
  color: var(--surface);
  font-size: 11px;
  font-weight: 600;
}

.video-chat-dot { width: 8px; height: 8px; margin-left: auto; border-radius: 50%; background: var(--accent); opacity: 0; }
.video-chat-main { position: absolute; top: 34px; right: 0; bottom: 0; left: 236px; display: flex; flex-direction: column; }
.video-chat-title { height: 52px; padding: 0 20px; border-bottom: 1px solid var(--rule); font-size: 15px; font-weight: 600; line-height: 52px; }
.video-chat-day { margin: auto 0 14px; color: var(--ink-soft); font-size: 11px; font-weight: 600; letter-spacing: 0.06em; text-align: center; text-transform: uppercase; }
.video-chat-msg { display: flex; gap: 12px; padding: 0 20px 18px; opacity: 0; }
.video-chat-msg > .video-chat-face { width: 36px; height: 36px; font-size: 12px; }
.video-chat-text { font-size: 15px; line-height: 1.45; }
.video-chat-who { font-size: 13px; font-weight: 600; }
.video-chat-who > span { margin-left: 6px; color: var(--ink-soft); font-size: 12px; font-weight: 400; }

.video-chat-file {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  margin-top: 8px;
  padding: 8px 14px 8px 8px;
  border: 1px solid var(--rule);
  border-radius: 10px;
  font-size: 13px;
  font-weight: 500;
}

.video-chat-write { height: 40px; margin: 0 20px 16px; padding: 0 14px; border: 1px solid var(--rule); border-radius: 10px; color: var(--ink-soft); line-height: 38px; }

/* The PDF's glyph; dragged, a copy of it under the cursor, its name in the accent, a soft shadow in the ink's tint. */
.video-file { display: flex; flex-direction: column; align-items: center; gap: 4px; width: 170px; opacity: 0; }
.video-file-glyph { overflow: visible; }
.video-file-page { fill: var(--surface); stroke: var(--ink-soft); stroke-width: 1.5; stroke-linejoin: round; }
.video-file-fold { fill: none; stroke: var(--ink-soft); stroke-width: 1.5; stroke-linejoin: round; }
.video-file-lines { fill: none; stroke: var(--rule); stroke-width: 2.5; stroke-linecap: round; }
.video-file-band { fill: var(--redline); }
.video-file-type { fill: var(--surface); font-family: var(--font); font-size: 10px; font-weight: 700; letter-spacing: 0.06em; }
.video-file-name { padding: 2px 7px; border-radius: var(--radius-control); background: var(--accent); color: var(--surface); font-size: 12px; font-weight: 500; line-height: 1.35; white-space: nowrap; }

/* A click's ring; the cursor; the desk's flat shade over model space under the fragments, so none reads as drawn on
   the sheet; the count beside a change, in the stage's px whatever the camera's scale. */
.video-click { overflow: visible; fill: none; stroke: var(--accent); stroke-width: 3; }
.video-cursor { overflow: visible; color: var(--ink); fill: var(--surface); stroke: var(--ink); stroke-width: 1.2; stroke-linejoin: round; }
.video-dim { background: var(--video-desk); opacity: 0; }
.video-beside { padding: 10px 22px; border: 1px solid var(--rule); border-radius: 999px; background: var(--surface); color: var(--ink); font-size: 30px; font-weight: 600; white-space: nowrap; opacity: 0; transform-origin: 0 0; }

/* The stage's own palette parts, closed (a row at 0fr) until opened; a quick card's actions under its line. */
.video-msg,
.video-quick { display: grid; grid-template-rows: 0fr; visibility: hidden; opacity: 0; }
.video-msg > .acad-msg-in,
.video-quick > * { min-height: 0; overflow: hidden; }
.video-actions { display: flex; flex-wrap: wrap; gap: 5px; }
.video-quick > .video-actions { padding-top: 4px; }

/* The list from the first decision on is the story's record (its beat 12: each applied one ticked, the taught one
   marked and read again); an item the video has not yet decided (no data-video) keeps its ring and first reading. */
.video-stage .demo-item:not([data-video]) > .demo-item-line::before { top: 3px; width: 7px; height: 7px; border: 1.5px solid var(--sf-dim); border-radius: 50%; background: none; transform: none; }
.video-stage .demo-item:not([data-video]) > .demo-item-line .demo-read-before { display: inline; }
.video-stage .demo-item:not([data-video]) > .demo-item-line .demo-read-after { display: none; }

/* The second change (tools/e101.mjs): unseen until drawn, its circle and lines dashed at their lengths. */
.video-add { opacity: 0; }
.video-add-symbol > circle { stroke-dasharray: 44; }
.video-add-symbol > path { stroke-dasharray: 22; }
.video-cloud { display: none; }

/* The reading's fragments: the palette's cards, the markup's notes in the redline's ink, a page of the PDF or sheet. */
.video-bits { position: absolute; top: 0; right: 0; bottom: 0; left: 0; pointer-events: none; }
.video-bits > * { position: absolute; top: 0; left: 0; opacity: 0; transform-origin: 50% 50%; }

.video-bit {
  padding: 7px 14px;
  border: 1px solid var(--sf-line);
  border-radius: 8px;
  background: var(--sf-bubble);
  color: var(--sf-text);
  font-size: 20px;
  font-weight: 500;
  line-height: 1.25;
  white-space: nowrap;
  list-style: none;
}

.video-bit span { font-weight: 650; }
.video-bit > :is(p, li) { font-size: inherit; line-height: inherit; }
.video-bit-note { display: flex; align-items: center; justify-content: center; width: 256px; height: 74px; border-color: var(--rule); border-radius: 4px; background: var(--surface); color: var(--redline); font-size: 18px; font-weight: 600; letter-spacing: 0.04em; }
.video-bit-note > svg { position: absolute; top: 0; left: 0; display: block; width: 100%; height: 100%; overflow: visible; fill: none; stroke: var(--redline); stroke-width: 1.5; }
.video-bit-page { display: flex; flex-direction: column; align-items: center; gap: 6px; padding: 10px; font-size: 16px; }
.video-bit-page > svg { width: 96px; height: 125px; }
.video-bit-sheet { fill: var(--surface); stroke: var(--rule); }
.video-bit-plan { fill: none; stroke: var(--ink-soft); stroke-width: 1; }
.video-bit-red { fill: none; stroke: var(--redline); stroke-width: 1.2; }
.video-bit-dark .video-bit-sheet { fill: var(--viewport); stroke: var(--sf-line); }
.video-bit-dark .video-bit-plan { stroke: var(--viewport-dim); }
.video-bit-dev { fill: none; stroke: var(--viewport-line); stroke-width: 2; }

/* The caption: one line, 48 px, on a pill of the surface at the stage's foot (above a phone's controls when tall). */
.video-captions { position: absolute; right: 0; bottom: 56px; left: 0; display: grid; justify-items: center; }
.video-stage[data-mode="9x16"] .video-captions { bottom: 260px; }

.video-caption {
  grid-area: 1 / 1;
  padding: 14px 34px 16px;
  border: 1px solid var(--rule);
  border-radius: 999px;
  background: var(--surface);
  color: var(--ink);
  font-size: 48px;
  font-weight: 600;
  line-height: 1.2;
  letter-spacing: -0.015em;
  white-space: nowrap;
  opacity: 0;
}

/* The copy: Inter at 64 px and 700 on the desk, a word at a time, SparkFlow's mark beside it (above, tall). */
.video-copy { position: absolute; top: 0; right: 0; bottom: 0; left: 0; display: flex; align-items: center; justify-content: center; gap: 48px; padding: 0 180px; background: var(--video-desk); opacity: 0; }
.video-copy-mark { flex: none; width: auto; height: 112px; }
.video-copy-lines { display: grid; }
.video-copy-line { grid-area: 1 / 1; width: 1180px; color: var(--stone); font-size: 64px; font-weight: 700; line-height: 1.15; letter-spacing: -0.02em; }
.video-copy-line > span { display: inline-block; opacity: 0; }
.video-stage[data-mode="9x16"] .video-copy { flex-direction: column; padding: 0 90px; text-align: center; }
.video-stage[data-mode="9x16"] .video-copy-line { width: 900px; }

/* The closing card, its foot the honest line: the sheet is a synthetic sample. */
.video-card { position: absolute; top: 0; right: 0; bottom: 0; left: 0; display: grid; place-items: center; background: var(--stone); color: var(--ink); text-align: center; opacity: 0; }
.video-card-in { display: flex; flex-direction: column; align-items: center; }
.video-card img { width: 176px; height: 176px; }
.video-card h1 { margin-top: 12px; font-size: 104px; font-weight: 700; line-height: 1.05; letter-spacing: -0.035em; }
.video-card-line { margin-top: 24px; font-size: 56px; font-weight: 650; line-height: 1.14; letter-spacing: -0.02em; }
.video-card-line > span { display: block; }
.video-card-address { margin-top: 36px; color: var(--accent); font-size: 36px; font-weight: 600; letter-spacing: 0.01em; }
.video-card-note { position: absolute; right: 0; bottom: 48px; left: 0; color: var(--ink-soft); font-size: 22px; font-weight: 500; }
.video-stage[data-mode="9x16"] .video-card img { width: 208px; height: 208px; }
.video-stage[data-mode="9x16"] .video-card h1 { font-size: 124px; }
.video-stage[data-mode="9x16"] .video-card-line { font-size: 52px; }
.video-stage[data-mode="9x16"] .video-card-note { bottom: 300px; font-size: 26px; }

/* ===== 11. The sample sheet E-101 (direction 4, "the drawing"; DB-0330, a real electrical plan) =====
   The sheet's box (DB-0309; DB-0310 its margin): the drawing zoomed so it sits with about 8 percent of graphite round
   it, as a sheet zoomed to its extents with a margin does in AutoCAD; the founder's "the drawing doesn't need to be so
   big". Its viewBox is the drawn objects' box (since DB-0330 the sheet's border, its zone strip the outer edge) with
   8 percent of the view on each side: -76 1 1352 790. A fixed aspect ratio box, so nothing shifts; it sits at the
   middle of the frame's model space (section 10c), and in the story's window it fills model space, the drawing fitted
   inside it (section 10).
   The drawing (DB-0330; the founder: "like an actual AutoCAD electrical drawing", "a normal construction floor plan",
   "not that olive green"): a synthetic power plan of a small commercial unit, 14 by 9 m at 1:50, in AutoCAD's own
   index colours (the --acad-* tokens of section 1), each class one colour. The architectural background is a locked
   layer, faded to 45 percent as electrical drawings show one: the walls (index 8 filled, 9 edged), the doors, the
   windows, the fixtures and the furniture (9), and its own words, the rooms' names and numbers and the fixtures' DW
   (DB-0341; the founder: "they are part of the xref, the background, a greyish colour"): ar-text, in the same 9 on
   the same faded layer, never the tags' yellow. Over it, at full strength: the devices, their wiring and the home runs
   in 4; the dimension strings in 1; the panel, the border, the zones and the title block in 7; the electrical words in
   2 (the circuit tags, the legend, the notes, the schedule, the title block, the dimensions' figures), a device's own
   marking (GFCI, EXIT, EM, the S and the J) in 4 and the border's and title block's fixed words in 7. Every word is
   14.5 units or more, 9 px or more at 1280 by 800. No rule paints the sheet in the site's own tokens. */
.demo-viewport {
  position: relative;
  overflow: hidden;
  aspect-ratio: 1352 / 790;
  background: var(--viewport);
}

.e101 {
  display: block;
  width: 100%;
  height: auto;
  font-family: var(--font);
}

.e101 .bg { fill: var(--viewport); }
.e101 .ar { opacity: 0.45; }
.e101 .ar-text { fill: var(--acad-light-grey); }
.e101 .wl { fill: var(--acad-grey); stroke: var(--acad-light-grey); stroke-width: 1.1; }
.e101 .lg { fill: none; stroke: var(--acad-light-grey); stroke-width: 1.1; }
.e101 .cy { fill: none; stroke: var(--acad-cyan); stroke-width: 1.3; }
.e101 .cf { fill: var(--acad-cyan); }
.e101 .rd { fill: none; stroke: var(--acad-red); stroke-width: 1; }
.e101 .wh { fill: none; stroke: var(--acad-white); stroke-width: 1.3; }
.e101 .wf { fill: var(--acad-white); }
.e101 .tx { fill: var(--acad-yellow); }
.e101 .tc { fill: var(--acad-cyan); }
.e101 .tw { fill: var(--acad-white); }
.e101 .num { font-variant-numeric: tabular-nums; }

/* ===== 12. The panel's review and code messages (direction 5; the story's beats 9 and 10, DB-0311, DB-0314) =====
   The review's finding is the responder's message under SparkFlow's mark; the code question is the engineer's, at
   the right, and its answer the responder's, with the source panel; each word in the palette's text or its dim tone
   (DB-0314: the palette's own, section 10c). */
.panel-group {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-2);
}

.status {
  display: inline-flex;
  align-items: center;
  min-height: 24px;
  padding: 0 10px;
  border: 1px solid currentColor;
  border-radius: 999px;
  font-size: 0.8125rem;
  font-weight: 600;
  line-height: 1.2;
  white-space: nowrap;
}

.status-review { color: var(--review); }
.status-in-place { color: var(--applied); }
.status-planned { color: var(--ink-soft); }

/* In the palette the needs-review state is its tint on a bubble (6.7:1), the pill at the palette's size. */
.acad-palette .status { min-height: 20px; padding: 0 8px; font-size: 11px; }
.acad-palette .status-review { color: var(--review-tint); }

.readings { display: grid; gap: var(--space-1); }
.readings div { display: flex; gap: var(--space-3); }
.readings dt { min-width: 7.5em; color: var(--sf-dim); }
.readings dd { font-weight: 500; font-variant-numeric: tabular-nums; }

.reference { color: var(--sf-dim); font-size: 11px; }

.standing {
  padding-top: 6px;
  border-top: 1px solid var(--sf-line);
  color: var(--sf-dim);
  font-size: 11px;
}

.source-panel {
  border: 1px solid var(--sf-line);
  border-radius: 8px;
  background: var(--sf-surface);
}

.source-panel > summary {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-2);
  min-height: 44px;
  padding: 6px 8px;
  font-size: 11px;
  font-weight: 500;
  font-variant-numeric: tabular-nums;
  list-style: none;
  cursor: pointer;
}

.source-panel > summary::-webkit-details-marker { display: none; }

/* The summary is a flex row (its words, then the chevron): the words are ONE item, so a long reference wraps as a
   sentence instead of splitting into columns (the founder's note of 2026-11-10). */
.source-panel > summary > .source-label { flex: 1 1 auto; min-width: 0; line-height: 1.35; }

.source-panel > summary::after {
  content: "";
  flex: none;
  width: 7px;
  height: 7px;
  margin-right: 2px;
  border-right: 1.5px solid var(--sf-dim);
  border-bottom: 1.5px solid var(--sf-dim);
  transform: translateY(-2px) rotate(45deg);
  transition: transform 200ms var(--ease);
}

.source-panel[open] > summary::after { transform: translateY(2px) rotate(-135deg); }
.source-body { padding: 0 8px 8px; font-size: 11px; }
.source-body > * + * { margin-top: var(--space-2); }
.source-body dl { display: grid; gap: 2px; }
.source-body dt { color: var(--sf-dim); font-size: 11px; }
.source-body hr { margin: var(--space-2) 0; border-top-color: var(--sf-line); }

/* The source panel opens with a 200 ms height transition where the browser can animate it; elsewhere it opens at once. */
@media (prefers-reduced-motion: no-preference) {
  .source-panel { interpolate-size: allow-keywords; }
  .source-panel::details-content {
    block-size: 0;
    overflow: hidden;
    transition: block-size 200ms var(--ease), content-visibility 200ms allow-discrete;
  }
  .source-panel[open]::details-content { block-size: auto; }
}

/* ===== 13. After the story: the three things, why now, the palette, For IT and Security (DB-0312, DB-0313, DB-0314) =====
   The founder: the landing page was "slightly too congested", its security section hard to tell from the
   administration section. Each part after the story is one calm column: a 1 px hairline across the container, the
   eyebrow in the accent at 13 px, a heading at 44 px and 700 (38 px on a phone), one or two sentences at 20 px held to
   32em, three short lines each after a check glyph in --applied, and one link into the page that goes deep, the arrow
   glyph after it. No card, no grid, no second column. The parts are the sections after the story (.story ~ .section),
   so the other pages' sections keep the section gap. The first part, the three things (DB-0313), keeps the hairline,
   the eyebrow and the heading, and its body is the row below them; the second, why now (DB-0314), has no link.
   DB-0314 (the founder: "if I've opened the website to that page, why is the next section showing?"): from 720 px each
   part, and the closing band after them (section 16), is at least 80 percent of the viewport's height with its content
   at the middle, so a part read with its heading in the screen's top third has the screen to itself; on a phone, where
   a part is about a screen tall already, 112 px above and below each instead. */
.story ~ :is(.section, .closing) {
  display: grid;
  align-content: center;
  min-height: 80svh;
}

.story ~ .section { padding-top: 0; }

@media (max-width: 719.98px) {
  .story ~ :is(.section, .closing) { min-height: 0; padding-block: calc(var(--space-9) + var(--space-4)); }
}

.part {
  padding-top: var(--space-6);
  border-top: 1px solid var(--rule);
}

.part .eyebrow {
  font-size: 0.8125rem;
  color: var(--accent);
}

/* The heading, the parts' and the closing band's on the landing page alike (section 16). */
.part h2,
.story ~ .closing h2 {
  font-size: 2.75rem;
  font-weight: 700;
  line-height: 1.1;
  letter-spacing: -0.02em;
  color: var(--ink);
}

.part h2 { margin-top: var(--space-3); }

.part-lead {
  max-width: 32em;
  margin-top: var(--space-5);
  color: var(--ink-soft);
  font-size: 1.25rem;
  text-wrap: pretty;
}

.part-checks {
  margin-top: var(--space-5);
  list-style: none;
}

.part-checks li {
  display: flex;
  align-items: flex-start;
  gap: var(--space-3);
  font-weight: 500;
}

.part-checks li + li { margin-top: var(--space-2); }

/* The check glyph, drawn in --applied: a decorative mark, the line carries the meaning. */
.part-check {
  flex: none;
  margin-top: 0.25em;
  fill: none;
  stroke: var(--applied);
  stroke-width: 2;
}

/* The link into the page that goes deep, the arrow glyph after its words in the link's own colour. */
.part-link {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  min-height: 44px;
  margin-top: var(--space-4);
  font-weight: 600;
}

.part-arrow {
  flex: none;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.75;
}

@media (max-width: 719.98px) {
  .part h2,
  .story ~ .closing h2 { font-size: 2.375rem; }
}

/* The three things (DB-0313; the founder: what SparkFlow does, in three): an ordered list under the heading, its items
   stacked 24 px apart on a phone or a tablet and a row of three from 900 px. Each item is the list's own numeral, drawn
   by the stylesheet from the list's count (the words name no number), in the accent at 40 px and 700, then its title
   at 22 px and 600 and its sentence at 18 px (DB-0314) in the soft ink. No link: the story above it is the
   demonstration. */
.part-things {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: var(--space-5);
  margin-top: var(--space-6);
  list-style: none;
  counter-reset: thing;
}

@media (min-width: 900px) {
  .part-things { grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--space-7); }
}

.part-things > li { counter-increment: thing; }

.part-things > li::before {
  content: counter(thing);
  display: block;
  color: var(--accent);
  font-size: 2.5rem;
  font-weight: 700;
  line-height: 1.1;
}

.part-things h3 {
  margin-top: var(--space-3);
  color: var(--ink);
  font-size: 1.375rem;
  font-weight: 600;
  line-height: 1.3;
  text-wrap: balance;
}

.part-things p {
  margin-top: var(--space-2);
  color: var(--ink-soft);
  font-size: 1.125rem;
  text-wrap: pretty;
}

/* The resources page (DB-0319) keeps the parts' shape on a page of its own, with two rows the landing page has not:
   the "Sign in to download" button with its words beside it, wrapping under it on a narrow screen (the words alone
   while the build has written no sign-in address, the button hidden), and its guides' links in a row. */
.part-download {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-3) var(--space-5);
  margin-top: var(--space-6);
}

.part-download p { color: var(--ink-soft); }

.part-links {
  display: flex;
  flex-wrap: wrap;
  gap: 0 var(--space-6);
  margin-top: var(--space-4);
  list-style: none;
}

.part-links .part-link { margin-top: 0; }

/* The note of what it never does, on the how it works page. */
.never-note {
  margin-top: var(--space-6);
  padding: var(--space-5);
  border: 1px solid var(--rule);
  border-radius: var(--radius-card);
}

.never-note b { font-weight: 600; }

/* ===== 14. The close-up (the how it works page; DB-0308, DB-0309, DB-0310) =====
   The frame cut down to the document tabs, the body and the command line. The SparkFlow panel is open in the dock,
   the responder's proposal in it (its card, the three actions under it) over the Ask box; beside it is the sheet's
   east part, by its own viewBox (546 84 608 592, DB-0330: the servery kitchen from its west wall, the sink and its
   receptacle on LP-4-12 at the view's upper left, the general notes, the panel's schedule strip and the title block's
   upper rows, every word 9 px or more there at 1280 wide), as drawn: the proposal waits, so nothing is on the sheet.
   The document's paragraph spacing gives way to the card's. */
.acad-close {
  width: 100%;
  max-width: 640px;
  margin-inline: auto;
}

.acad-frame-closeup .demo-viewport { aspect-ratio: 608 / 592; }

.prose .acad-card > p + p { margin-top: 3px; }

/* The panel's three actions, drawn: words on shapes, not controls of this page. */
.mock-action {
  display: inline-flex;
  align-items: center;
  min-height: 32px;
  padding: 0 14px;
  border: 1px solid var(--rule);
  border-radius: var(--radius-control);
  color: var(--ink);
  font-size: 0.875rem;
  font-weight: 600;
}

.mock-action-primary { border-color: var(--accent); background: var(--accent); color: var(--surface); }
.mock-action-text { border-color: transparent; color: var(--accent); }

/* The close-up's caption, under its frame. */
.palette-caption {
  margin-top: var(--space-3);
  color: var(--ink-soft);
  font-size: 0.875rem;
  text-align: center;
  max-width: none;
}

/* ===== 15. Questions (the FAQ page; DB-0312: no longer on the homepage) ===== */
.faq-list { border-top: 1px solid var(--rule); }
.faq-list details { border-bottom: 1px solid var(--rule); }

.faq-list summary {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-5);
  min-height: 56px;
  padding: var(--space-4) 0;
  font-size: 1.0625rem;
  font-weight: 600;
  line-height: 1.4;
  list-style: none;
  cursor: pointer;
}

.faq-list summary::-webkit-details-marker { display: none; }

/* A chevron that turns as the answer opens: a decorative mark, the disclosure states itself. */
.faq-list summary::after {
  content: "";
  flex: none;
  width: 9px;
  height: 9px;
  margin-right: 4px;
  border-right: 2px solid var(--ink-soft);
  border-bottom: 2px solid var(--ink-soft);
  transform: translateY(-3px) rotate(45deg);
  transition: transform 200ms var(--ease);
}

.faq-list details[open] summary::after { transform: translateY(3px) rotate(-135deg); }
.faq-page { max-width: 820px; }
.faq-answer { padding: 0 0 var(--space-5); }
.faq-answer > * + * { margin-top: var(--space-3); }
.faq-answer p { color: var(--ink-soft); }

/* ===== 16. The closing call (direction 3.9) ===== */
.closing {
  margin-top: var(--section-gap);
  padding: var(--space-8) 0;
  border-top: 1px solid var(--rule);
  border-bottom: 1px solid var(--rule);
  background: var(--surface);
}

.closing-grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: var(--space-7);
}

@media (min-width: 900px) {
  .closing-grid { grid-template-columns: minmax(0, 3fr) minmax(0, 2fr); gap: var(--space-8); align-items: start; }
}

.closing-copy > * + * { margin-top: var(--space-4); }
.closing-copy .btn { margin-top: var(--space-6); }
.next-steps h3 { margin-bottom: var(--space-3); }
.next-steps ol { padding-left: 1.25em; }
.next-steps li + li { margin-top: var(--space-2); }
.next-steps li::marker { color: var(--ink-soft); font-variant-numeric: tabular-nums; }

/* On the landing page (DB-0312) the band after the story holds its heading at the parts' size (section 13), one
   sentence, the button and the help desk line: the parts' gap above it, no second column. Since DB-0314 it is a screen
   of its own like the parts (section 13), and its gap keeps its white edge under the fold while the Security part is
   read with its heading in the screen's top third. */
.story ~ .closing { margin-top: var(--part-gap); }

.closing-copy .closing-help {
  margin-top: var(--space-5);
  color: var(--ink-soft);
  font-size: 0.9375rem;
}

/* ===== 17. A page's head (the contact, help desk, FAQ and resources pages) ===== */
.page-head { padding-top: var(--space-8); }
.page-head > * + * { margin-top: var(--space-4); }

@media (max-width: 719.98px) {
  .page-head { padding-top: var(--space-7); }
}

/* ===== 18. The document template (direction 6) ===== */
.doc {
  display: grid;
  grid-template-columns: minmax(0, 720px);
  grid-template-areas: "head" "contents" "body";
  justify-content: center;
  row-gap: var(--space-6);
  padding-top: var(--space-8);
}

.doc-head { grid-area: head; }
.doc-head > * + * { margin-top: var(--space-3); }
.doc-head .lead { margin-top: var(--space-5); }

.doc-date {
  color: var(--ink-soft);
  font-size: 0.9375rem;
  font-variant-numeric: tabular-nums;
}

.doc-note {
  margin-top: var(--space-5);
  padding: var(--space-4) var(--space-5);
  border: 1px solid var(--rule);
  border-radius: var(--radius-control);
  background: var(--surface);
  font-size: 0.9375rem;
  max-width: none;
}

/* A page still waiting on a review (the founder's or counsel's): the needs-review state, in words and in --review. */
.doc-note-review { border-left: 3px solid var(--review); }

.doc-contents {
  grid-area: contents;
  border: 1px solid var(--rule);
  border-radius: var(--radius-control);
  background: var(--surface);
}

.doc-contents > summary {
  display: flex;
  align-items: center;
  min-height: 48px;
  padding: 0 var(--space-4);
  font-weight: 600;
  cursor: pointer;
}

.doc-contents ol { padding: 0 var(--space-4) var(--space-3) calc(var(--space-4) + 1.25em); }
.doc-contents li { padding: 2px 0; }

.doc-contents a {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  color: var(--ink);
}

.doc-rail { display: none; grid-area: rail; }
.doc-body { grid-area: body; }

@media (min-width: 1024px) {
  .doc {
    grid-template-columns: 200px minmax(0, 720px);
    grid-template-areas: ". head" "rail body";
    column-gap: var(--space-8);
  }
  .doc-contents { display: none; }
  .doc-rail { display: block; }
  .doc-rail ol {
    position: sticky;
    top: calc(var(--header-height) + var(--space-6));
    padding: 0;
    list-style: none;
    border-left: 1px solid var(--rule);
    scroll-target-group: auto;
  }
  .doc-rail a {
    display: block;
    margin-left: -1px;
    padding: 6px 0 6px var(--space-4);
    border-left: 2px solid transparent;
    color: var(--ink-soft);
    font-size: 0.9375rem;
    line-height: 1.4;
    text-decoration: none;
  }
  .doc-rail a:hover { color: var(--ink); }
}

/* The current section, marked where the browser tracks it (the rail's links as scroll markers). */
@media (min-width: 1024px) {
  .doc-rail a:target-current { border-left-color: var(--accent); color: var(--ink); }
}

.prose > section + section { margin-top: var(--space-7); }
.prose h2 { margin-bottom: var(--space-4); font-size: clamp(1.45rem, 2.2vw, 1.75rem); }
.prose h3 { margin: var(--space-5) 0 var(--space-2); }
.prose p + p,
.prose p + ul,
.prose ul + p,
.prose p + ol { margin-top: var(--space-3); }
.prose ul,
.prose ol { padding-left: 1.25em; }
.prose li + li { margin-top: var(--space-2); }
.prose .figure-block { margin-top: var(--space-6); }
.prose .steps-list > li + li { margin-top: var(--space-5); }
.prose .steps-list > li::marker { color: var(--ink-soft); font-weight: 600; font-variant-numeric: tabular-nums; }
.prose .steps-list h3 { margin: 0 0 var(--space-2); }
.prose .never-note { margin-top: 0; margin-bottom: var(--space-2); }
.doc-back { margin-top: var(--space-7); }
.doc-foot { margin-top: var(--space-3); font-size: 0.875rem; }

/* Controls with their state in words: in place, or planned, pending confirmation. */
.controls { list-style: none; padding-left: 0 !important; border-top: 1px solid var(--rule-soft); }

.controls > li {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  gap: var(--space-2) var(--space-5);
  align-items: start;
  margin: 0 !important;
  padding: var(--space-4) 0;
  border-bottom: 1px solid var(--rule-soft);
  max-width: none;
}

@media (max-width: 559.98px) {
  .controls > li { grid-template-columns: minmax(0, 1fr); }
  .controls .status { justify-self: start; grid-row: 1; }
}

.table-wrap {
  overflow-x: auto;
  border: 1px solid var(--rule);
  border-radius: var(--radius-card);
  background: var(--surface);
}

.data-table {
  width: 100%;
  min-width: 600px;
  border-collapse: collapse;
  font-size: 0.9375rem;
}

.data-table th,
.data-table td {
  padding: var(--space-3) var(--space-4);
  border-bottom: 1px solid var(--rule-soft);
  text-align: left;
  vertical-align: top;
}

.data-table thead th {
  color: var(--ink-soft);
  font-size: 0.8125rem;
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
}

.data-table tbody tr:last-child > * { border-bottom: 0; }
.data-table tbody th { font-weight: 600; }

/* The draft notice the privacy and terms pages carry until counsel's review. */
.draft {
  margin-top: var(--space-5);
  padding: var(--space-4) var(--space-5);
  border: 1px solid var(--rule);
  border-left: 3px solid var(--review);
  border-radius: var(--radius-control);
  background: var(--surface);
  font-size: 0.9375rem;
}

.draft b { font-weight: 600; }

/* ===== 19. The forms (the contact page, DB-0256, and the help desk, DB-0293) ===== */
.form-layout {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: var(--space-7);
  align-items: start;
}

@media (min-width: 900px) {
  .form-layout { grid-template-columns: minmax(0, 7fr) minmax(0, 5fr); gap: var(--space-8); }
}

.form-card {
  padding: var(--space-6);
  border: 1px solid var(--rule);
  border-radius: var(--radius-card);
  background: var(--surface);
}

@media (max-width: 479.98px) {
  .form-card { padding: var(--space-5) var(--space-4); }
}

.form-card > h2 { margin-bottom: var(--space-5); font-size: 1.5rem; }

.form-legend {
  margin-bottom: var(--space-5);
  color: var(--ink-soft);
  font-size: 0.875rem;
}

.form-row {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 0 var(--space-4);
}

@media (max-width: 619.98px) {
  .form-row { grid-template-columns: minmax(0, 1fr); }
}

.field {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  column-gap: var(--space-2);
  margin-bottom: var(--space-5);
}

.field > label {
  margin-bottom: 6px;
  font-size: 0.9375rem;
  font-weight: 600;
  line-height: 1.4;
}

.field > label small { color: var(--ink-soft); font-size: inherit; font-weight: 400; }

.field-required {
  color: var(--ink-soft);
  font-size: 0.8125rem;
  font-weight: 500;
}

.field > input,
.field > select,
.field > textarea {
  flex: 0 0 100%;
  width: 100%;
  min-height: 44px;
  padding: 10px 12px;
  border: 1px solid var(--rule);
  border-radius: var(--radius-control);
  background: var(--surface);
  color: var(--ink);
  font-size: 1rem;
  line-height: 1.4;
  transition: border-color 150ms var(--ease);
}

.field > input:hover,
.field > select:hover,
.field > textarea:hover { border-color: var(--ink-soft); }
.field > input:focus,
.field > select:focus,
.field > textarea:focus { border-color: var(--accent); }
.field > textarea { min-height: 128px; resize: vertical; }

.field-error { flex: 0 0 100%; }
.field .error-text { display: none; margin-top: 6px; color: var(--ink); font-size: 0.875rem; font-weight: 600; }
.field.has-error > input,
.field.has-error > select { border: 2px solid var(--ink); }
.field.has-error .error-text { display: block; }

.form-note {
  margin-bottom: var(--space-5);
  color: var(--ink-soft);
  font-size: 0.9375rem;
}

.form-actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-3) var(--space-5);
}

.form-data-use {
  flex: 1 1 16em;
  color: var(--ink-soft);
  font-size: 0.875rem;
}

.form-success {
  display: none;
  margin-top: var(--space-5);
  padding: var(--space-4) var(--space-5);
  border: 1px solid var(--rule);
  border-left: 3px solid var(--applied);
  border-radius: var(--radius-control);
  background: var(--stone);
  font-size: 0.9375rem;
}

.form-success.is-visible { display: block; }
.form-success b { font-weight: 600; }
.form-summary { margin-top: var(--space-3); }
.form-summary > summary { font-weight: 600; cursor: pointer; }
.form-summary pre { margin-top: var(--space-2); font-size: 0.875rem; }

.warning {
  margin-bottom: var(--space-5);
  padding: var(--space-4) var(--space-5);
  border: 1px solid var(--rule);
  border-left: 3px solid var(--ink);
  border-radius: var(--radius-control);
  background: var(--stone);
  font-size: 0.9375rem;
}

.warning > * + * { margin-top: var(--space-2); }
.warning b { font-weight: 600; }

.aside-stack > * + * { margin-top: var(--space-5); }

.aside-card {
  padding: var(--space-5);
  border: 1px solid var(--rule);
  border-radius: var(--radius-card);
  background: var(--surface);
}

.aside-card > * + * { margin-top: var(--space-3); }
.aside-card ul,
.aside-card ol { padding-left: 1.25em; }
.aside-card li + li { margin-top: var(--space-2); }
.aside-card p,
.aside-card li { font-size: 0.9375rem; }

/* The help desk's three lines (DB-0293): the number among them once the image's build writes one in. */
.help-line + .help-line { margin-top: 6px; }

.help-number {
  color: var(--ink);
  font-size: 1.375rem;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  text-decoration: none;
}

.help-number:hover { color: var(--ink); text-decoration: underline; }

/* ===== 20. Motion ===== */
@media (prefers-reduced-motion: no-preference) {
  html { scroll-behavior: smooth; }
}

/* Reduced motion: no transition anywhere, no smooth scrolling; every state is reached by a control. */
@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    transition-duration: 0s !important;
    animation-duration: 0s !important;
    animation-iteration-count: 1 !important;
    scroll-behavior: auto !important;
  }
}
