@import url("./art-tokens.css");   /* the --rd-* palette of the scene art, shared with #/safety */
/* ============================================================================
   Concept illustrations (web/app/scenes.js) — palette, layout and in-scene animation. Every scene is
   a 400×180 inline SVG inside a <figure class="scene">; the sky/panel gradient lives here (not in
   <defs>) so 45 scenes can share the page without colliding on gradient ids. Animations are paused
   until the scene scrolls into view (.in), and disabled entirely under prefers-reduced-motion.
   ========================================================================== */
.scene {
  --sky1: #c3dcef; --sky2: #edf4f9;
  --grass: #98b78c; --hill: #b4cca8;  /* muted verge green, matched to the course figures (2026-09 polish) */
  --asph: #474d58; --asph2: #393e48; --lane: #f4c542; --edge: rgba(255,255,255,.7);
  --carA: #b8342f; --carB: #34609f; --carC: #cf8f28;  /* same hues as before, realistic paint */
  --glass: #cfe9ff; --metal: #9aa4b2; --ink: #1a1f28; --paper: #ffffff;
  --sun: #ffcf4d; --cloud: rgba(255,255,255,.95);
  --hi: var(--brand); --ok2: #1a7f37; --warn2: #e0a000;

  position: relative; display: block; margin: 0 0 1rem;
  border-radius: var(--r-lg); overflow: hidden; border: 1px solid var(--border);
  background: linear-gradient(180deg, var(--sky1), var(--sky2));
  box-shadow: 0 1px 2px rgba(16,24,40,.06), 0 10px 26px rgba(16,24,40,.07);
}
.scene--studio {
  background: linear-gradient(180deg, color-mix(in srgb, var(--surface-2) 70%, var(--surface)), var(--surface-2));
}
.sc-svg { display: block; width: 100%; height: auto; }
/* The caption sits BELOW the drawing, not over it: an overlaid scrim hid whatever
   was at road level (skid marks, waiting cars, roadside signs). */
.scene figcaption {
  padding: .4rem .7rem; font-size: .72rem; font-weight: 700; letter-spacing: .02em;
  color: var(--muted); background: var(--surface); border-top: 1px solid var(--border);
}
/* Wraps the drawing only, so a mounted sign is positioned against the 400×180
   artwork and never against the caption below it. */
.scene-art { position: relative; display: block; }
/* real sign image mounted on the roadside post of the `signpost` scene */
/* Sits on the signpost by default; a scene can move it to where that sign would
   really stand by setting --sign-x/--sign-y/--sign-w on the <figure>. */
.scene-sign {
  position: absolute; left: var(--sign-x, 75%); top: var(--sign-y, 19%);
  transform: translate(-50%, -50%) rotate(var(--sign-rot, 0));
  width: var(--sign-w, 21%); display: grid; place-items: center;
  filter: drop-shadow(0 4px 10px rgba(0,0,0,.28));
  animation: sc-mount .7s cubic-bezier(.2,1.4,.4,1) both;
}
.scene-sign .signimg { width: 100%; height: auto; }

:root[data-theme="dark"] .scene {
  --sky1: #16243c; --sky2: #101722;
  --grass: #2d4435; --hill: #24382b;
  --asph: #2a303c; --asph2: #22272f; --edge: rgba(255,255,255,.32);
  --glass: #7fb3e6; --metal: #6b7686; --ink: #e8eaed; --paper: #1d232c;
  --sun: #f2c14a; --cloud: rgba(255,255,255,.22);
}

/* ------------------------------------------------------------------- layout */
/* inside a question card the illustration is a compact banner, not a hero */
.qcard .scene { max-width: 460px; }
@media (max-width: 560px) { .qcard .scene { max-width: 100%; } }
/* three-up strip used on the landing page */
.scene-strip { display: grid; gap: 1rem; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); }
.scene-strip .scene { margin: 0; }
.scene:hover .sc-svg { transform: scale(1.02); }
.sc-svg { transition: transform .5s cubic-bezier(.2,.8,.3,1); }

/* ---------------------------------------------------------------- landscape */
.sc-sun { fill: var(--sun); animation: sc-glow 4s ease-in-out infinite; }
.sc-cloud { fill: var(--cloud); }
.sc-cloud.c1 { animation: sc-drift 26s linear infinite; }
.sc-cloud.c2 { animation: sc-drift 38s linear infinite reverse; }
.sc-hill { fill: var(--hill); }
.sc-grass { fill: var(--grass); }
.sc-asph { fill: var(--asph); }
.sc-island { fill: var(--grass); }
.sc-edge { stroke: var(--edge); stroke-width: 2; }
.sc-edge-c { fill: none; stroke: var(--edge); stroke-width: 2; }
.sc-mid, .sc-mid line { stroke: var(--lane); stroke-width: 3; stroke-dasharray: 20 20; fill: none; }
.sc-flow, .sc-flow line { animation: sc-flow 1.1s linear infinite; }
.sc-solid { fill: #f5f7fa; }
.sc-kerb { fill: var(--metal); }
.sc-bikelane { fill: color-mix(in srgb, #e8767a 55%, var(--asph)); }  /* red-tinted, as on Norwegian roads and in the course figures */
.sc-bikelane.sc-bikelane-red { fill: color-mix(in srgb, #e8767a 55%, var(--asph)); }
.sc-snow-road { fill: #eaf1f8; }
.sc-track { fill: color-mix(in srgb, var(--asph) 78%, #eaf1f8); }
.sc-rails { fill: var(--metal); }
.sc-zebra rect { fill: #f4f7fb; }
.sc-stopline, .sc-yieldline, .sc-edgeline { stroke: #f4f7fb; stroke-width: 4; fill: none; }
.sc-edgeline { stroke-width: 3; opacity: .8; }
.sc-mid.sc-white { stroke: #f4f7fb; }
/* short-dashed line separating a bus lane from the adjacent lane (kort stipla
   linje — tighter dashes than the ordinary long-dashed lane divider), plus its
   vertical painted marking */
.sc-buslane-line { stroke: #f4f7fb; stroke-width: 5; fill: none; stroke-dasharray: 10 7; }
.sc-buslane-mark { fill: #f4f7fb; font: 800 13px var(--font); letter-spacing: .2em; opacity: .9; }
.sc-white-line, .sc-lane-end { stroke: #f4f7fb; stroke-width: 3; fill: none; }
.sc-merge-line { stroke: #f4f7fb; stroke-width: 3; stroke-dasharray: 10 8; fill: none; }
.sc-arrow-road { fill: none; stroke: #fff; stroke-width: 3.5; stroke-linecap: round; stroke-linejoin: round; }
/* painted lane arrow (2026-09 polish): a filled marking, not a diagram stroke */
.sc-arrow-road.paint { fill: #eef1f5; stroke: none; opacity: .92; }
.sc-cone { fill: #f07828; stroke: #fff; stroke-width: 2; }
.sc-hazard-ray, .sc-pressure { fill: none; stroke: var(--warn2); stroke-width: 3; stroke-linecap: round; stroke-linejoin: round; }
.sc-arrow-turn, .sc-arrow-head, .sc-arrow-drift { fill: none; stroke: var(--brand); stroke-width: 4; stroke-linecap: round; stroke-linejoin: round; }
.sc-passenger .sc-limb { stroke-width: 2.6; }
.sc-uneven { stroke: var(--bad); stroke-width: 4; stroke-linecap: round; }
.sc-bridge { fill: #697586; }
.sc-ice-sheen { fill: rgba(214,236,248,.62); }
.sc-thermo { fill: var(--surface); stroke: var(--brand); stroke-width: 4; }
.sc-tyre.wide { fill: #23282f; stroke: color-mix(in srgb, var(--muted) 40%, transparent); stroke-width: 2; }
/* The Norwegian L-merke is a plain RED "L" on a WHITE plate — it has no red
   border. The stroke that used to be here drew a sign that does not exist. */
.sc-learner-badge { fill: #ffffff; stroke: none; }
.sc-learner-text { fill: #d81f3a; font: 800 22px var(--font); }
.sc-groundbar { fill: var(--border); }
.sc-crosslights circle { fill: #e8262f; }
.sc-crosslights .a { animation: sc-blink 1s steps(1) infinite; }
.sc-crosslights .b { animation: sc-blink 1s steps(1) .5s infinite; }
.sc-yieldline { stroke-dasharray: 5 5; }
.sc-shoulder { fill: #3f5f8f; }
.sc-bikebody { fill: none; stroke: #4a515e; }
.sc-hair { fill: #3b2c20; }
.sc-helmet { fill: #eef1f5; stroke: #20252e; stroke-width: .7; }
.sc-btyre { fill: #20252e; }
.sc-bar { stroke: #20252e; stroke-width: 1.6; stroke-linecap: round; }
.sc-biketop .sc-shoulder { fill: #d99a1e; }
.sc-biketop .sc-arm { stroke: #d99a1e; stroke-width: 2; stroke-linecap: round; }
.sc-coat { fill: #3f5f8f; }
/* plan-view motorcycle: dark wheels, blue-grey body, darker seat */
.sc-moto-wheel { fill: #23282f; }
.sc-moto-body { fill: #3a4a66; }
.sc-moto-seat { fill: #1d2430; }
.sc-fog { fill: rgba(255,255,255,.72); animation: sc-fog 7s ease-in-out infinite; }
.sc-night { fill: rgba(14,20,38,.62); }
.sc-bus-body { fill: #2f7d5c; }
.sc-bus-roof { fill: rgba(255,255,255,.16); }
.sc-bus-hatch { fill: rgba(0,0,0,.22); }
.sc-bus-top-mirror { fill: #23282f; }
.sc-bus .sc-glass rect { fill: var(--glass); }
/* plan-view bus: same glass treatment as the side view and the plan-view car */
.sc-bus-top .sc-glass { fill: #26313e; }
.sc-bus-top .sc-cast { fill: rgba(16,24,40,.18); }

/* -------------------------------------------------------------------- cars */
.sc-cast { fill: rgba(10,15,25,.2); }
.sc-car .sc-shell { fill: var(--carA); stroke: rgba(0,0,0,.3); stroke-width: .7; }
.sc-car .sc-roof { fill: rgba(255,255,255,.1); }
.sc-car .sc-handle { fill: rgba(0,0,0,.4); }
.sc-side path.sc-trim { fill: none; stroke: rgba(0,0,0,.3); stroke-width: .9; }
.sc-hub { fill: #6b7482; }
.sc-car.b .sc-shell { fill: var(--carB); }
.sc-car.c .sc-shell { fill: var(--carC); }
.sc-car .sc-glass { fill: #26313e; stroke: #26313e; }
.sc-car .sc-trim { fill: rgba(0,0,0,.18); }
.sc-lamp { fill: #fff4c2; }
.sc-tail { fill: #d8392e; }
.sc-tyre { fill: #23282f; }
.sc-tyre.big { fill: #23282f; stroke: color-mix(in srgb, var(--muted) 40%, transparent); stroke-width: 2; }
.sc-rim { fill: #b9c0ca; }
.sc-rim.big { fill: #cbd3dd; }
.sc-spoke { stroke: #7d8794; stroke-width: 1.3; }
.sc-spoke.big { stroke: #8b95a3; stroke-width: 4; }
/* A wheel's spin direction states which way the vehicle travels, so it has to agree with the body it
   is under. `carSide` faces RIGHT, so the wheels turn CLOCKWISE. (Anti-clockwise said "this car is
   reversing" under every right-facing car in the bank — reported from the rendered cards, 2026-08-16.)
   One rule serves both orientations: a scene that mirrors its vehicle with `scale(-1,1)` renders this
   same +360 keyframe as anti-clockwise on screen, which is what a left-travelling vehicle needs. */
.sc-wheel { transform-box: fill-box; transform-origin: 50% 50%; animation: sc-spin .7s linear infinite; }
.sc-tread line { stroke: #737d8a; stroke-width: 5; }

/* A mirrored scene (`mirror: true`) flips its whole drawing, which would also flip
   every label in it. Counter-mirror each text node about its own centre so "?",
   "140 cm" and "kg ?" still read forwards while the picture stays flipped. */
.sc-mirror text { transform-box: fill-box; transform-origin: 50% 50%; transform: scaleX(-1); }

/* frontOverhang is the one side elevation NOT mirrored — it is drawn facing left
   already (the load has to project from the front). Its road markings therefore need
   reversing by hand to stream right like everyone else's. */
[data-scene="frontOverhang"] .sc-flow,
[data-scene="frontOverhang"] .sc-flow line { animation-direction: reverse; }

/* --------------------------------------------------------- people & bikes */
.sc-skin { fill: #d9a684; }
.sc-limb { stroke: #2b3240; stroke-width: 3.4; stroke-linecap: round; fill: none; }
.sc-ped .sc-leg { stroke: #2b303a; stroke-width: 2.8; }
.sc-ped .sc-arm { stroke: #3f5f8f; stroke-width: 2.2; }
.sc-frame { stroke: var(--carB); stroke-width: 3; fill: none; stroke-linecap: round; }
.sc-legA { transform-box: fill-box; transform-origin: 100% 0%; }
.sc-legB { transform-box: fill-box; transform-origin: 0% 0%; }
.sc-armA { transform-box: fill-box; transform-origin: 100% 0%; }
.sc-armB { transform-box: fill-box; transform-origin: 0% 0%; }
.sc-ped .sc-legA, .sc-bike .sc-legA { animation: sc-step .62s ease-in-out infinite alternate; }
.sc-ped .sc-legB, .sc-bike .sc-legB { animation: sc-step .62s ease-in-out infinite alternate-reverse; }
.sc-ped .sc-armA { animation: sc-step .62s ease-in-out infinite alternate-reverse; }
.sc-ped .sc-armB { animation: sc-step .62s ease-in-out infinite alternate; }
.sc-bike .sc-legA, .sc-bike .sc-legB { animation-duration: .5s; }

/* ------------------------------------------------------------------- signs */
.sc-post { fill: var(--metal); }
.sc-sign-face { stroke-width: 3.5; }
.sc-sign-face.sc-red { fill: #fff; stroke: #d81f3a; }
.sc-sign-face.sc-blue { fill: #00205b; stroke: #fff; }
.sc-sign-face.sc-plate { fill: #fff; stroke: #12151b; stroke-width: 1.6; }
/* neutral blank sign: used when the question asks what a sign looks like */
.sc-sign-face.sc-blank { fill: var(--paper); stroke: var(--metal); stroke-width: 4; }
.sc-bus-line { stroke: rgba(255,255,255,.5); stroke-width: 2; }
.sc-sign-bar { stroke: #d81f3a; stroke-width: 5; stroke-linecap: round; }
.sc-sign-txt { fill: #12151b; font: 700 15px var(--font); }
/* supplementary plate: black text and symbols on white, as on the real plates */
.sc-plate-txt { fill: #12151b; font: 700 11px var(--font); }
.sc-plate-ink { fill: #12151b; stroke: none; }
.sc-plate-ink.hollow, .sc-plate-ink .hollow { fill: none; stroke: #12151b; stroke-width: 1.8; }
.sc-plate-ink.hollow .solid { fill: #12151b; stroke: none; }
.sc-plate-ink.stroke { fill: none; stroke: #12151b; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }
.sc-warn polygon { fill: #f5c400; stroke: #d81f3a; stroke-width: 5; stroke-linejoin: round; }
.sc-warn-ink { stroke: #1a1f28; stroke-width: 3.4; stroke-linecap: round; }
.sc-warn-ink-dot { fill: #1a1f28; }
.sc-lightbox { fill: #22262e; }
.sc-bulb { fill: #4a505c; }
.sc-bulb.r { animation: sc-tl-red 6s steps(1) infinite; }
.sc-bulb.y { animation: sc-tl-amber 6s steps(1) infinite; }
.sc-bulb.g { animation: sc-tl-green 6s steps(1) infinite; }
.sc-tlights circle { fill: #ffe9a8; animation: sc-twinkle 2.4s ease-in-out infinite; }
.sc-tlights circle:nth-child(2) { animation-delay: .5s; }
.sc-tlights circle:nth-child(3) { animation-delay: 1s; }
.sc-ind { fill: var(--warn2); }
.sc-blink { animation: sc-blink 1s steps(1) infinite; }
.sc-blink.two .a { animation: sc-blink 1s steps(1) infinite; }
.sc-blink.two .b { animation: sc-blink 1s steps(1) .5s infinite; }
.sc-boom rect { fill: #d81f3a; transform-box: fill-box; transform-origin: 0% 50%;
  animation: sc-boom 5s ease-in-out infinite; }
.sc-officer .sc-uniform { fill: #20385f; }
.sc-officer .sc-arm-signal { stroke: #20385f; stroke-width: 5; stroke-linecap: round; fill: none; }
.sc-windscreen { fill: #759bbd; stroke: var(--metal); stroke-width: 5; stroke-linejoin: round; }
.sc-frost { fill: rgba(238,248,255,.82); }
.sc-scraper { fill: var(--brand); }
.sc-scraper-edge { fill: var(--metal); }

/* --------------------------------------------------------------- annotation */
.sc-ask circle { fill: color-mix(in srgb, var(--brand) 92%, #000); opacity: .95; }
.sc-ask text { fill: #fff; font-weight: 800; font-family: var(--font); }
.sc-ask { animation: sc-bounce 2.6s ease-in-out infinite; transform-box: fill-box; transform-origin: 50% 50%; }
.sc-measure path, .sc-mline { stroke: #fff; stroke-width: 2.4; fill: none; }
.sc-mspan { stroke-dasharray: 6 5; animation: sc-flow 1.4s linear infinite reverse; }
.sc-mtxt { fill: #fff; font: 800 13px var(--font); paint-order: stroke; stroke: rgba(0,0,0,.35); stroke-width: 3; }
.scene--studio .sc-measure path, .scene--studio .sc-mline, .scene--studio .sc-mspan { stroke: var(--muted); }
.scene--studio .sc-mtxt { fill: var(--text); stroke: none; }
.sc-trace { fill: none; stroke: #fff; stroke-width: 3; stroke-dasharray: 10 8; opacity: .85;
  animation: sc-flow 1.6s linear infinite reverse; }
.sc-skid path { stroke: #cdd6e2; stroke-width: 4; opacity: .8; fill: none; }
.sc-skid.soft path { opacity: .55; stroke: #8b9bb0; }
.sc-beam { fill: #fff6c8; opacity: .45; animation: sc-beam 3s ease-in-out infinite; }
.sc-beam.high { opacity: 0; animation: sc-beam-hi 4s ease-in-out infinite; }
.sc-stars circle { fill: #fff; animation: sc-twinkle 3s ease-in-out infinite; }
.sc-stars circle:nth-child(even) { animation-delay: 1.2s; }
.sc-rain line { stroke: #9fc6ee; stroke-width: 2.4; stroke-linecap: round;
  animation: sc-rain 1s linear infinite; }
.sc-rain .r1 { animation-duration: .8s; } .sc-rain .r2 { animation-duration: 1.2s; } .sc-rain .r3 { animation-duration: .95s; }
.sc-flakes circle { fill: #fff; animation: sc-fall 6s linear infinite; }
.sc-flakes .f1 { animation-duration: 7.5s; } .sc-flakes .f2 { animation-duration: 5.5s; }
.sc-flakes .f3 { animation-duration: 8.5s; } .sc-flakes .f4 { animation-duration: 6.5s; }
.sc-rock { fill: #6b7280; }
.sc-tunnel-mouth { fill: #14181f; }
.sc-radar path { fill: none; stroke: var(--blue); stroke-width: 3.4; stroke-linecap: round; opacity: 0;
  transform-box: fill-box; transform-origin: 0% 50%; }
.sc-radar .w1 { animation: sc-ping 1.8s ease-out infinite; }
.sc-radar .w2 { animation: sc-ping 1.8s ease-out .25s infinite; }
.sc-radar .w3 { animation: sc-ping 1.8s ease-out .5s infinite; }

/* ------------------------------------------------------------ studio props */
.sc-dial { fill: var(--surface); stroke: var(--border); stroke-width: 2; }
.sc-dial-in { fill: color-mix(in srgb, var(--brand) 6%, var(--surface)); }
.sc-tick { stroke: var(--muted); stroke-width: 2.4; }
.sc-tick.big { stroke: var(--text); stroke-width: 3; }
.sc-needle { transform-box: view-box; transform-origin: 200px 96px;
  animation: sc-sweep 4.5s cubic-bezier(.45,.05,.55,.95) infinite; }
.sc-needle path { stroke: var(--brand); stroke-width: 4; stroke-linecap: round; }
.sc-needle circle { fill: var(--brand); }
.sc-big { fill: var(--text); font: 800 20px var(--font); }
.sc-big.small { font-size: 16px; }
.sc-sweep { transform-box: view-box; transform-origin: 132px 92px; animation: sc-spin 3s linear infinite; }
.sc-sweep path { stroke: var(--brand); stroke-width: 3.4; stroke-linecap: round; }
.sc-hub { fill: var(--brand); }
.sc-axis { stroke: var(--muted); stroke-width: 2.4; fill: none; }
.sc-curve { stroke: var(--brand); stroke-width: 4; fill: none; stroke-linecap: round; }
.sc-draw { stroke-dasharray: 600; animation: sc-draw 3s ease-in-out infinite; }
/* The risk curve's pen: on sc-draw's 600 dash this 273-unit curve and its 4-point dot ran on different
   clocks. pathLength="1" + a dot sampled off the same curve at the same ease-in-out keeps the dot on
   the tip of the line every frame. Gap 2, not 1: a 1/1 dash leaves a round-capped dot at the end. */
.sc-draw1 { stroke-dasharray: 1 2; animation: sc-draw1 3s ease-in-out infinite; }
.sc-dot-run { fill: var(--brand); animation: sc-run 3s linear infinite; }
.sc-gauge rect:not(.sc-gauge-fill) { fill: var(--surface); stroke: var(--border); stroke-width: 2; }
.sc-gauge-fill { fill: var(--ok2); stroke: none !important; transform-box: fill-box; transform-origin: 50% 100%;
  animation: sc-fill 3.4s ease-in-out infinite; }
.sc-gauge-fill.h { transform-origin: 0% 50%; animation: sc-fill-h 3.4s ease-in-out infinite; }
.sc-limitbar rect { fill: var(--surface); stroke: var(--border); stroke-width: 2; }
.sc-limitbar .fill { fill: var(--bad); stroke: none; transform-box: fill-box; transform-origin: 50% 100%;
  animation: sc-fill 3s ease-in-out infinite; }
.sc-sway { transform-box: view-box; transform-origin: 132px 94px; animation: sc-sway 3.4s ease-in-out infinite; }
.sc-wheel-ring { fill: none; stroke: var(--ink); stroke-width: 9; opacity: .85; }
.sc-wheel-hub { fill: var(--ink); opacity: .85; }
.sc-wheel-spoke { stroke: var(--ink); stroke-width: 7; opacity: .85; stroke-linecap: round; }
.sc-glass-body { fill: rgba(190,220,245,.5); stroke: var(--metal); stroke-width: 2; }
.sc-glass-fill { fill: #c8102e; opacity: .75; }
.sc-glass-stem, .sc-glass-foot { fill: var(--metal); }
.sc-face { fill: #f7cfa6; }
.sc-eye { stroke: #2b3240; stroke-width: 4; fill: none; stroke-linecap: round;
  animation: sc-blinkeye 4s ease-in-out infinite; }
.sc-mouth { stroke: #2b3240; stroke-width: 3.4; fill: none; stroke-linecap: round; }
.sc-zzz text { fill: var(--muted); font: 800 22px var(--font); }
.sc-zzz .z1 { animation: sc-rise 3s ease-in-out infinite; }
.sc-zzz .z2 { animation: sc-rise 3s ease-in-out .5s infinite; }
.sc-zzz .z3 { animation: sc-rise 3s ease-in-out 1s infinite; }
.sc-cup path { fill: var(--surface); stroke: var(--muted); stroke-width: 2.4; }
.sc-cup .handle { fill: none; }
.sc-steam path { stroke: var(--muted); stroke-width: 2.6; fill: none; stroke-linecap: round;
  animation: sc-steam 2.6s ease-in-out infinite; }
.sc-steam path:nth-child(2) { animation-delay: .6s; }
.sc-seat { fill: #4b5464; }
.sc-seat-base { fill: #3b4250; }
.sc-belt { stroke: #e9edf3; stroke-width: 5; fill: none; stroke-linecap: round; }
.sc-buckle { fill: var(--metal); }
.sc-childseat rect { fill: var(--carB); opacity: .9; }
.sc-lift { fill: var(--metal); }
.sc-wrench path { fill: var(--metal); transform-box: fill-box; transform-origin: 50% 50%;
  animation: sc-wrench 3s ease-in-out infinite; }
.sc-checks path { fill: none; stroke: var(--ok2); stroke-width: 4; stroke-linecap: round; stroke-linejoin: round;
  stroke-dasharray: 60; animation: sc-draw 3s ease-in-out infinite; }
.sc-checks .c2 { animation-delay: .5s; }
.sc-checks line { stroke: color-mix(in srgb, var(--muted) 45%, transparent); stroke-width: 5; stroke-linecap: round; }
.sc-hover { animation: sc-hover 4s ease-in-out infinite; }
.sc-leaves path { fill: var(--ok2); opacity: 0; }
.sc-leaves .l1 { animation: sc-leaf 3s ease-out infinite; }
.sc-leaves .l2 { animation: sc-leaf 3s ease-out .4s infinite; }
.sc-leaves .l3 { animation: sc-leaf 3s ease-out .8s infinite; }
.sc-phone rect { fill: #22262e; stroke: color-mix(in srgb, var(--muted) 40%, transparent); stroke-width: 2; }
.sc-phone .screen { fill: var(--surface); }
.sc-doc rect { fill: var(--paper); stroke: color-mix(in srgb, var(--border) 70%, var(--muted)); stroke-width: 1.2; }
.sc-lines line { stroke: var(--border); stroke-width: 3.4; stroke-linecap: round; }
.lr-leg { fill: none; stroke: #2b303a; stroke-width: 2.8; stroke-linecap: round; }
.lr-arm { fill: none; stroke: #3f5f8f; stroke-width: 2.3; stroke-linecap: round; }
.ea-seam { fill: none; stroke: rgba(0,0,0,.18); stroke-width: 1.4; }
.sc-shield path { fill: color-mix(in srgb, var(--blue) 18%, var(--surface)); stroke: var(--blue); stroke-width: 3; }
.sc-shield .tick { fill: none; stroke: var(--ok2); stroke-width: 5; stroke-linecap: round; stroke-linejoin: round; }
.sc-book .cover { fill: var(--brand); }
.sc-book .page { fill: var(--paper); }
.sc-book .pR { transform-box: fill-box; transform-origin: 0% 50%; animation: sc-page 5s ease-in-out infinite; }
.sc-book .spine { stroke: color-mix(in srgb, var(--brand) 60%, #000); stroke-width: 2.4; }
.sc-para text { fill: var(--brand); font: 800 26px var(--font); opacity: .6; }
.sc-para .p1 { animation: sc-float 6s ease-in-out infinite; }
.sc-para .p2 { animation: sc-float 7s ease-in-out -2s infinite; }
.sc-para .p3 { animation: sc-float 8s ease-in-out -4s infinite; }
.sc-lightbar .bar { fill: #2b3240; stroke: color-mix(in srgb, var(--muted) 40%, transparent); stroke-width: 2; }
.sc-lightbar .roof { fill: #3b4250; stroke: none; }
.sc-lightbar .lampL { fill: #2f6fed; animation: sc-blink .55s steps(1) infinite; }
.sc-lightbar .lampR { fill: #2f6fed; animation: sc-blink .55s steps(1) .275s infinite; }
.sc-chart rect { fill: var(--paper); stroke: var(--border); stroke-width: 2; }
.sc-chart .row { fill: var(--text); font: 800 var(--font); }
.sc-chart .r1 { font-size: 26px; } .sc-chart .r2 { font-size: 18px; } .sc-chart .r3 { font-size: 13px; }
.sc-chart .r3 { animation: sc-fade 3.6s ease-in-out infinite; }
.sc-specs rect { fill: rgba(150,190,225,.22); stroke: var(--ink); stroke-width: 2.2; }
.sc-specs path { stroke: var(--ink); stroke-width: 2; fill: none; stroke-linecap: round; }
.sc-eyelid path { stroke: none; fill: none; }
.sc-mini { transform: scale(.7); transform-box: fill-box; }

/* ------------------------------------------------------------- motion paths */
.sc-idle { animation: sc-idle 2.6s ease-in-out infinite; }
.sc-golight { animation: sc-golight 6s linear infinite; }
/* Drive-through: starts and ends fully outside the 400-wide frame, so the loop
   restart is never visible. Keep base x within (-37 … 237) for a top-down car
   and (-60 … 162) for a side-view one. */
.sc-roll { animation: sc-roll 7s linear infinite -2.4s; }
.sc-roll-soft { animation: sc-roll 11s linear infinite -3.6s; }
.sc-creep-e { animation: sc-creep-e 4s ease-in-out infinite; }
.sc-creep-n { animation: sc-creep-n 4s ease-in-out infinite 1.2s; }
/* No stagger, unlike sc-creep-n above: the four cars of `crossing4` must read as
   arriving together, not one after another. */
.sc-creep4-e { animation: sc-creep-e 4s ease-in-out infinite; }
.sc-creep4-n { animation: sc-creep-n 4s ease-in-out infinite; }
.sc-creep4-w { animation: sc-creep-w 4s ease-in-out infinite; }
.sc-creep4-s { animation: sc-creep-s 4s ease-in-out infinite; }
.sc-cross-n { animation: sc-cross-n 9s linear infinite; }
.sc-convoy { animation: sc-convoy 13s linear infinite; }
.sc-crawl { animation: sc-crawl 16s linear infinite -4s; }
/* The passer rides the painted trace (the same smoothstep S, x = 0…150 out, 250…400 back) and
   yaws with it, so its nose leads every lane change. Origin = its drawn centre (-400,115). */
.sc-pass { transform-box: view-box; transform-origin: -400px 115px; animation: sc-pass 16s linear infinite -4s; }
.sc-slide { animation: sc-slip 4s ease-in-out infinite; transform-box: fill-box; transform-origin: 50% 100%; }
.sc-enter { animation: sc-enter 5s ease-in-out infinite -1s; }
.sc-turn { transform-box: view-box; animation: sc-turn-in 7s ease-out 1 forwards; }
.sc-oncoming { transform-box: view-box; animation: sc-straight-in 7s ease-out 1 forwards; }
/* Ring traffic: one animation, two delays — constant separation, never a crash. */
.sc-orbit { transform-box: view-box; transform-origin: 200px 90px; animation: sc-orbit 11s linear infinite; }
.sc-orbit.d2 { animation-delay: -3.6s; }
.sc-spin { transform-box: fill-box; transform-origin: 50% 50%; animation: sc-spin 2.4s linear infinite; }
.sc-pulse { transform-box: fill-box; transform-origin: 50% 50%; animation: sc-pulse 2.2s ease-in-out infinite; }
.sc-bus { transform: translate(30px, 96px); }   /* stopped at the kerb */

/* ------------------------------------------------------------------ keyframes */
@keyframes sc-spin { to { transform: rotate(360deg); } }
/* The road streams BACKWARDS past a car going forwards. Side elevations are drawn with a right-facing
   car and then mirrored as a whole (see `mirrored()` in scenes.js), so this keyframe is written for
   the UNMIRRORED drawing: a positive dash offset walks the pattern leftwards there, which the mirror
   renders as streaming to the RIGHT past a car travelling right-to-left. Flip this sign and every
   side elevation reads as reversing. */
@keyframes sc-flow { to { stroke-dashoffset: 40; } }
@keyframes sc-drift { from { transform: translateX(-60px); } to { transform: translateX(420px); } }
@keyframes sc-glow { 50% { opacity: .72; transform: scale(1.06); } }
@keyframes sc-step { from { transform: rotate(-26deg); } to { transform: rotate(26deg); } }
@keyframes sc-blink { 0%, 49% { opacity: 1; } 50%, 100% { opacity: .18; } }
@keyframes sc-blinkeye { 0%, 86%, 100% { transform: none; } 92% { transform: translateY(5px) scaleY(.2); } }
@keyframes sc-tl-red { 0%, 40% { fill: #ff3b30; } 41%, 100% { fill: #4a505c; } }
@keyframes sc-tl-amber { 0%, 39% { fill: #4a505c; } 40%, 48% { fill: #ffb020; } 88%, 100% { fill: #ffb020; } 49%, 87% { fill: #4a505c; } }
@keyframes sc-tl-green { 0%, 49% { fill: #4a505c; } 50%, 86% { fill: #34c759; } 87%, 100% { fill: #4a505c; } }
@keyframes sc-twinkle { 0%, 100% { opacity: .25; } 50% { opacity: 1; } }
@keyframes sc-bounce { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(-7px); } }
@keyframes sc-draw { 0% { stroke-dashoffset: 600; } 55%, 100% { stroke-dashoffset: 0; } }
@keyframes sc-draw1 { 0% { stroke-dashoffset: 1; } 55%, 100% { stroke-dashoffset: 0; } }
@keyframes sc-beam { 0%, 100% { opacity: .22; } 50% { opacity: .46; } }
@keyframes sc-beam-hi { 0%, 45% { opacity: 0; } 55%, 95% { opacity: .34; } 100% { opacity: 0; } }
@keyframes sc-rain { from { transform: translateY(0); } to { transform: translateY(190px); } }
@keyframes sc-fall { from { transform: translateY(0) translateX(0); } to { transform: translateY(220px) translateX(18px); } }
@keyframes sc-fog { 0%, 100% { opacity: .35; transform: translateX(-10px); } 50% { opacity: .62; transform: translateX(10px); } }
@keyframes sc-ping { 0% { opacity: 0; transform: scale(.7); } 30% { opacity: .9; } 100% { opacity: 0; transform: scale(1.25); } }
@keyframes sc-sweep { 0% { transform: rotate(-38deg); } 45% { transform: rotate(58deg); } 60% { transform: rotate(44deg); } 100% { transform: rotate(-38deg); } }
@keyframes sc-fill { 0%, 100% { transform: scaleY(.35); } 55% { transform: scaleY(1); } }
@keyframes sc-fill-h { 0%, 100% { transform: scaleX(.4); } 55% { transform: scaleX(1); } }
@keyframes sc-sway { 0%, 100% { transform: rotate(-7deg); } 50% { transform: rotate(7deg); } }
@keyframes sc-rise { 0% { opacity: 0; transform: translateY(6px) scale(.8); } 30% { opacity: .9; } 100% { opacity: 0; transform: translateY(-16px) scale(1.15); } }
@keyframes sc-steam { 0% { opacity: 0; transform: translateY(4px); } 40% { opacity: .8; } 100% { opacity: 0; transform: translateY(-12px); } }
@keyframes sc-wrench { 0%, 100% { transform: rotate(-12deg); } 50% { transform: rotate(16deg); } }
@keyframes sc-hover { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(-7px); } }
@keyframes sc-leaf { 0% { opacity: 0; transform: translate(0,0) rotate(0); } 25% { opacity: .9; } 100% { opacity: 0; transform: translate(-46px,-30px) rotate(-40deg); } }
@keyframes sc-page { 0%, 60%, 100% { transform: rotateY(0); } 30% { transform: rotateY(-42deg); } }
@keyframes sc-float { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(-12px); } }
@keyframes sc-fade { 0%, 100% { opacity: .35; } 50% { opacity: 1; } }
@keyframes sc-pulse { 0%, 100% { transform: scale(1); } 50% { transform: scale(1.09); } }
@keyframes sc-idle { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(-1.6px); } }
@keyframes sc-roll {
  0% { transform: translateX(-260px); }
  12% { transform: translateX(-150px); }
  88% { transform: translateX(350px); }
  100% { transform: translateX(460px); }
}
@keyframes sc-orbit { to { transform: rotate(-360deg); } }   /* negative = counter-clockwise */
@keyframes sc-golight {
  0%, 50% { transform: translateX(0); opacity: 1; }
  68% { transform: translateX(170px); opacity: 1; }
  78% { transform: translateX(250px); opacity: 0; }
  79%, 92% { transform: translateX(0); opacity: 0; }
  100% { transform: translateX(0); opacity: 1; }
}
@keyframes sc-creep-e { 0%, 55% { transform: translateX(0); } 78%, 100% { transform: translateX(10px); } }
@keyframes sc-creep-n { 0%, 55% { transform: translateY(0); } 78%, 100% { transform: translateY(-8px); } }
@keyframes sc-creep-w { 0%, 55% { transform: translateX(0); } 78%, 100% { transform: translateX(-10px); } }
@keyframes sc-creep-s { 0%, 55% { transform: translateY(0); } 78%, 100% { transform: translateY(8px); } }
@keyframes sc-cross-n { from { transform: translateY(0); } to { transform: translateY(-220px); } }
@keyframes sc-convoy {
  0% { transform: translateX(-350px); }
  14% { transform: translateX(-240px); }
  86% { transform: translateX(360px); }
  100% { transform: translateX(470px); }
}
@keyframes sc-crawl { from { transform: translateX(0); } to { transform: translateX(520px); } }
/* pull out, pass, pull back in at a constant 75 u/s; generated from the trace's curve, so the
   two cannot drift apart. The crawler's 520px keeps ≥17 units (mirrors included) while lanes overlap. */
@keyframes sc-pass {
  0% { transform: translate(0, 0) rotate(0deg); }
  33.33% { transform: translate(400px, 0px) rotate(0deg); }
  35.42% { transform: translate(425px, -3.4px) rotate(-14.3deg); }
  37.5% { transform: translate(450px, -11.9px) rotate(-22.2deg); }
  39.58% { transform: translate(475px, -23px) rotate(-24.7deg); }
  41.67% { transform: translate(500px, -34.1px) rotate(-22.2deg); }
  43.75% { transform: translate(525px, -42.6px) rotate(-14.3deg); }
  45.83% { transform: translate(550px, -46px) rotate(0deg); }
  54.17% { transform: translate(650px, -46px) rotate(0deg); }
  56.25% { transform: translate(675px, -42.6px) rotate(14.3deg); }
  58.33% { transform: translate(700px, -34.1px) rotate(22.2deg); }
  60.42% { transform: translate(725px, -23px) rotate(24.7deg); }
  62.5% { transform: translate(750px, -11.9px) rotate(22.2deg); }
  64.58% { transform: translate(775px, -3.4px) rotate(14.3deg); }
  66.67% { transform: translate(800px, 0px) rotate(0deg); }
  100% { transform: translate(1200px, 0) rotate(0deg); }
}
@keyframes sc-slip { 0%, 100% { transform: rotate(0); } 30% { transform: rotate(-2.6deg); } 65% { transform: rotate(1.8deg); } }
@keyframes sc-enter { 0% { transform: translateX(0); opacity: 1; } 70% { transform: translateX(150px); opacity: .25; } 71%, 100% { opacity: 0; } }
@keyframes sc-turn-in {
  0% { transform: translate(-60px,108px) rotate(90deg); }
  100% { transform: translate(108px,108px) rotate(90deg); }
}
@keyframes sc-straight-in {
  0% { transform: translate(420px,72px) rotate(270deg); }
  100% { transform: translate(292px,72px) rotate(270deg); }
}
@keyframes sc-boom { 0%, 20% { transform: rotate(-72deg); } 45%, 75% { transform: rotate(0deg); } 100% { transform: rotate(-72deg); } }
@keyframes sc-run {   /* sampled from the curve at ease-in-out(t / .55) — see .sc-draw1 */
  0% { transform: translate(0,0); } 3.44% { transform: translate(2.1px,-.1px); } 6.88% { transform: translate(8.5px,-.5px); }
  10.31% { transform: translate(19.5px,-1.4px); } 13.75% { transform: translate(35.1px,-3.1px); } 17.19% { transform: translate(55.2px,-6.1px); }
  20.63% { transform: translate(79px,-11.2px); } 24.06% { transform: translate(105.2px,-19.1px); } 27.5% { transform: translate(132.1px,-30.2px); }
  30.94% { transform: translate(157.4px,-44.6px); } 34.38% { transform: translate(179.2px,-61.3px); } 37.81% { transform: translate(198px,-76.6px); }
  41.25% { transform: translate(215.7px,-86.5px); } 44.69% { transform: translate(230.7px,-91.3px); } 48.13% { transform: translate(241.6px,-93.2px); }
  51.56% { transform: translate(247.9px,-93.8px); } 55%, 100% { transform: translate(250px,-94px); }
}
@keyframes sc-mount { 0% { opacity: 0; transform: translate(-50%,-90%) scale(.4) rotate(-14deg); } 100% { opacity: 1; transform: translate(-50%,-50%) scale(1) rotate(var(--sign-rot, 0)); } }

/* Scenes idle until scrolled into view — keeps 45 review cards cheap. */
.scene:not(.in) *, .scene:not(.in) { animation-play-state: paused; }

@media (prefers-reduced-motion: reduce) {
  .scene *, .scene { animation: none !important; }
  .sc-beam.high, .sc-radar path, .sc-leaves path { opacity: .3; }
  .sc-draw, .sc-draw1, .sc-skid path, .sc-checks path { stroke-dashoffset: 0; stroke-dasharray: none; }
  /* Both overtake cars start off-canvas; still, show the pass itself (passer half a length ahead). */
  .sc-pass { transform: translate(630px, -46px); }
  .sc-crawl { transform: translateX(273px); }
}
/* footway a driveway has to cross before the carriageway */
.sc-footway { fill: color-mix(in srgb, var(--metal) 45%, #e9edf3); }
/* blindcurve: the road as a band, and the sight line that stops at the obstruction */
.sc-asph-band { fill: none; stroke: var(--asph); stroke-width: 34; }
.sc-asph-band.wide { stroke-width: 42; }
.sc-mid.sc-bend-line { stroke-dasharray: 20 16; fill: none; }
.sc-thicket ellipse { fill: color-mix(in srgb, var(--hill) 70%, #2c5138); }
/* two-lane roundabout: the lane line inside the ring */
.sc-ring-lane { fill: none; stroke: #f4f7fb; stroke-width: 3; stroke-dasharray: 12 10; opacity: .85; }
/* tram: same plan-view body as the bus, in tram livery */
.sc-tramcar .sc-bus-body { fill: #8c3b6b; }
.sc-edgeline.strong { stroke-width: 4; opacity: 1; }
/* the plan-view cyclist also appears ON a tinted cycle lane, so it carries a thin
   light outline to stay readable against both asphalt and paint */
.sc-biketop .sc-bikebody { stroke: #4a515e; stroke-width: 2.2; }

/* ---- photo cards (data/photos.json) ------------------------------------------ */
/* A verified photograph replaces the drawing where a photo shows what a vector
   cannot. Same 400×180-ish footprint as a scene so cards stay uniform. */
.scene--photo { background: var(--surface-2); }
.scene--photo .scene-art { aspect-ratio: 20 / 9; overflow: hidden; }
.scene-photo { width: 100%; height: 100%; object-fit: cover; display: block;
  transition: transform .5s cubic-bezier(.2,.8,.3,1); }
.scene--photo:hover .scene-photo { transform: scale(1.02); }
/* portrait photo: the 20/9 cover band would zoom in on a slice, so fit whole.
   object-fit: contain (with the base 100%/100% box) scales the picture to fit
   and centres it — max-height:100% here does NOT work because the container's
   height comes from aspect-ratio, which is not a definite size. */
.scene--photo-contain .scene-art { background: var(--surface-2); }
.scene--photo-contain .scene-photo { object-fit: contain; }
/* A question's own photograph (web/question_photos/) is evidence, not decoration:
   the sign or hazard being asked about can sit anywhere in the frame, so it is shown
   whole. Cropping it to the uniform 20/9 band could cut the answer out of the card. */
.scene--qphoto .scene-art { aspect-ratio: 16 / 10; }
.scene--qphoto .scene-photo { object-fit: contain; }
/* Baked 3D clip (app/scene-clips.js) over the SVG: the SVG keeps the 20:9 box and is the fallback,
   so the clip only covers it once it has a frame (.scene--clip-on) and is removed on error. */
.scene-clip { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; display: block;
  opacity: 0; transition: opacity .24s ease-out; pointer-events: none; }
.scene--clip-on .scene-clip { opacity: 1; }
.scene--clip-on .sc-svg, .scene--clip-on .scene-sign { visibility: hidden; }
@media (prefers-reduced-motion: reduce) { .scene-clip { transition: none; } }

/* ==== BEGIN authored-2026-08-16 scenes ==== */
/* ---- lover-og-regler ---- */
/* ---- scenes for the lover-og-regler illustration pass ---------------------- */

/* towRope: the tow rope between the two cars. Deliberately plain — no flag, no
   tape — because what must be put on it is the question. A fixed light grey, not
   --metal: the rope hangs over the asphalt, which is dark in BOTH themes, and the
   dark-mode --metal washed out against it. */
.lr-rope { fill: none; stroke: #9aa4b2; stroke-width: 3.5; stroke-linecap: round; }

/* frontOverhang: the roof bars, the timber they carry, and the dashed guide that
   marks the car's foremost point. */
/* The rack feet are the only thing that says the load is CARRIED, not floating —
   they are 6px of sky between plank and roof, so they need real contrast against
   both, not --metal (which vanished into the light sky). */
.lr-rack { fill: #4a5260; }
:root[data-theme="dark"] .lr-rack { fill: #cbd2dc; }
/* --ink flips with the theme, so the guide stays visible against the sky it is
   drawn over (white would vanish on the light sky, black on the dark one). */
.lr-guide { fill: none; stroke: var(--ink); stroke-width: 2; stroke-dasharray: 5 5; opacity: .55; }
/* Same reason for the overhang bracket: the shared measure paint is white for use
   over asphalt, and this one sits in the sky. */
.lr-overhang .sc-measure path, .lr-overhang .sc-mline, .lr-overhang .sc-mspan { stroke: var(--ink); }
.lr-overhang .sc-mtxt { fill: var(--ink); stroke: rgba(255,255,255,.5); }

/* keyLend: the key mid-handover, and the bottle in the other person's hand. Both
   are held up against the sky, so they carry their own mid-tone fills rather than
   background-dependent ones. */
.lr-key rect, .lr-key .bow { fill: var(--metal); }
.lr-key .eye { fill: var(--sky2); }
:root[data-theme="dark"] .lr-key .eye { fill: #16243c; }
.lr-key path { fill: none; stroke: var(--metal); stroke-width: 2.6; stroke-linecap: round; }
.lr-bottle rect { fill: #4f9a63; stroke: rgba(0,0,0,.25); stroke-width: 1; }

/* parkedDark: an unlit car. The shared car primitive always paints a glowing lamp
   and tail light; here they must stay dark, or the picture answers the question
   about lights on a car parked in the dark. */
.lr-unlit .sc-lamp { fill: #4a505c; }
.lr-unlit .sc-tail { fill: #6b4a4a; }

/* phoneHand: the driver's right forearm running out of the bottom of the frame,
   and the hand gripping the phone. Skin is a real object colour in both themes,
   but it needs a hairline of its own: filled flat, the four fingertips lapping
   over the phone merged into one peach blob against the white screen. */
.ph-arm { fill: none; stroke: #f0b48a; stroke-width: 19; stroke-linecap: round; }
.ph-skin { fill: #f0b48a; stroke: #c4835c; stroke-width: 1.6; stroke-linejoin: round; }

/* flat-bed trailer: bare-metal deck, stanchions, drawbar and coupling */
.sc-fea-trailer { fill: var(--metal); }
.sc-fea-drawbar { fill: none; stroke: var(--metal); stroke-width: 5; stroke-linecap: round; }
.sc-fea-hitch { fill: var(--metal); }
/* axle centre line — an engineering guide, never a road marking, so it is ink
   rather than paint white and reads on grass, sky and asphalt alike */
.sc-fea-axis { fill: none; stroke: color-mix(in srgb, var(--ink) 55%, transparent);
  stroke-width: 2; stroke-dasharray: 6 5; }

/* the heavy crate on the trailer, and its strapping */
.sc-fea-crate { fill: #c08a52; stroke: rgba(0,0,0,.25); stroke-width: 2; }
.sc-fea-crate-band { fill: none; stroke: rgba(0,0,0,.3); stroke-width: 2.4; }

/* the wobbling track a snaking trailer leaves — static, unlike .sc-trace, so a
   scene that must not animate stays still */
.sc-fea-trace { fill: none; stroke: #f4f7fb; stroke-width: 3; stroke-dasharray: 10 8; opacity: .8; }

/* cut-away car body: a light shell so the boot interior reads inside it */
.sc-fea-body { fill: color-mix(in srgb, var(--metal) 22%, var(--surface)); stroke: var(--metal); stroke-width: 3; }
/* glass in the cut-away and studio scenes (the existing .sc-glass rules are all
   scoped under .sc-car / .sc-bus, so a bare class of our own is needed) */
.sc-fea-glass { fill: color-mix(in srgb, var(--glass) 72%, transparent); }

/* luggage standing loose in the boot: a hard case, a cardboard box and a soft
   holdall. Three plain luggage colours — the earlier purple disc read as
   confetti rather than as a bag. The line is only ever a pull-out handle or a
   box seam, never a band round an item: a band reads as the keyed answer. */
.sc-fea-bag { fill: #6d7f96; }
.sc-fea-bag.b { fill: #c08a52; }
.sc-fea-bag.c { fill: #4f7a6a; }
.sc-fea-bag-line { fill: none; stroke: var(--ink); stroke-width: 2.6; opacity: .5; }

/* flat-bed pickup carrying a plank: timber, straps, cab and bed */
.sc-fea-plank { fill: #cfa06a; stroke: rgba(0,0,0,.22); stroke-width: 1.6; }
.sc-fea-strap { fill: none; stroke: #2b3240; stroke-width: 3; opacity: .85; }
.sc-fea-bed { fill: color-mix(in srgb, var(--carB) 78%, var(--ink)); }
.sc-fea-cab { fill: var(--carB); }

/* dashboard, and the passenger airbag module behind its cover. Mixed from
   --asph, not --ink: a dashboard is dark charcoal in BOTH themes, and --ink
   flips to near-white in dark mode, which turned the dash into a white slab. */
.sc-fea-dash { fill: color-mix(in srgb, var(--asph) 88%, #000);
  /* the outline keeps the silhouette readable where a near-black dash sits on
     the dark studio panel */
  stroke: color-mix(in srgb, var(--metal) 55%, transparent); stroke-width: 2; }
.sc-fea-airbag { fill: none; stroke: color-mix(in srgb, var(--metal) 70%, transparent); stroke-width: 2.4; }
.sc-fea-label { fill: color-mix(in srgb, var(--metal) 85%, #fff); font: 800 10px var(--font); letter-spacing: .12em; }

/* rear-facing child seat: the shell is a FILLED C-section — the closed back
   panel leaning towards the windscreen, the pan lying on the cushion, the
   opening facing up and to the rear. Drawn as a bare arc it read as a hook, so
   it carries a real wall thickness and a darker rim line of its own. */
.sc-fea-shell { fill: color-mix(in srgb, var(--blue) 70%, var(--ink));
  stroke: color-mix(in srgb, var(--blue) 40%, #000); stroke-width: 2;
  stroke-linejoin: round; }
/* the child in it: a pale babygro needs a hairline, or it dissolves into the
   light studio panel wherever it laps over the shell's opening */
.sc-fea-child { fill: #eef3f9; stroke: #9aa7b8; stroke-width: 1.8; stroke-linejoin: round; }
/* harness webbing over the child: two straight straps, never crossed — an X
   over a child reads as a prohibition sign, which would answer the question */
.sc-fea-harness { fill: none; stroke: color-mix(in srgb, var(--ink) 55%, transparent);
  stroke-width: 2.6; stroke-linecap: round; }
/* the carry handle arcing over an infant carrier — without it the shell alone
   does not read as a child seat */
.sc-fea-handle { fill: none; stroke: color-mix(in srgb, var(--blue) 45%, var(--ink));
  stroke-width: 5; stroke-linecap: round; }

/* rear door seen from its shut face: panel, edge, latch and child-lock lever */
.sc-fea-door { fill: color-mix(in srgb, var(--carB) 82%, var(--ink)); }
.sc-fea-edge { fill: color-mix(in srgb, var(--ink) 45%, var(--metal)); }
.sc-fea-doorpull { fill: color-mix(in srgb, var(--metal) 70%, #fff); }

/* tunnel interior: lit concrete wall, ceiling line and ceiling lamps. The wall
   is mixed from --asph, so it darkens with the road in dark mode. */
.sc-fea-wall { fill: color-mix(in srgb, var(--asph) 55%, #cfd6e0); }
.sc-fea-vault-line { fill: none; stroke: color-mix(in srgb, var(--asph) 80%, #000); stroke-width: 2; opacity: .45; }
.sc-fea-lamp rect { fill: #ffe9a8; opacity: .92; }

/* crash damage: buckled sheet metal, and a starred windscreen */
.sc-fea-damage { fill: none; stroke: color-mix(in srgb, var(--ink) 70%, transparent);
  stroke-width: 2.6; stroke-linejoin: round; }
.sc-fea-crack { fill: none; stroke: color-mix(in srgb, var(--ink) 62%, transparent); stroke-width: 2.4; stroke-linejoin: round; }
/* the steering wheel seen edge-on, in front of the occupant */
.sc-fea-swheel { fill: none; stroke: var(--ink); stroke-width: 5; opacity: .85; }
/* the steering column that carries it out of the dashboard. Mid-grey rather
   than the dash's near-black: it crosses the open studio panel, where a
   near-black stroke disappeared in dark mode and the wheel read as floating. */
.sc-fea-column { fill: none; stroke: color-mix(in srgb, var(--metal) 60%, var(--asph));
  stroke-width: 10; stroke-linecap: round; }
/* the occupant left sitting in the seat. Legs are a shade darker than the
   torso, or thighs, hips and chest merge into one blue slab in profile. */
.sc-fea-torso { fill: #3f6ea8; }
.sc-fea-legs { fill: #2c517d; }

/* Cardboard, timber and the padded child shell are lit objects, not surfaces:
   left as they are they turn muddy against the dark panel, so lift them. */
:root[data-theme="dark"] .sc-fea-crate,
:root[data-theme="dark"] .sc-fea-bag.b { fill: #b9834e; }
:root[data-theme="dark"] .sc-fea-plank { fill: #c1935f; }
:root[data-theme="dark"] .sc-fea-child { fill: #c9d3e0; }
/* ---- kjoretoyet ---- */
/* ---- scenes authored for the `kjoretoyet` illustration pass ------------------ */
/* Every class here is prefixed kv- so it cannot collide with the existing sc- set.
   Physical objects (lamps, rubber, oil) keep their real colour in both themes;
   everything else is built from the scene tokens. */

/* treadWear: the moulded wear indicator standing in the groove floor — light
   enough to read against the black rubber blocks on either side of it */
.kv-groove { fill: color-mix(in srgb, #23282f 34%, transparent); }
/* The bar must stand out from the groove it sits in (.kv-groove), or the whole
   point of the picture — that the indicator is BELOW the tread surface — is lost. */
.kv-wearbar { fill: color-mix(in srgb, var(--metal) 95%, #23282f); }
/* leader from a "?" badge down to the detail it points at (studio panels only) */
.kv-lead { fill: none; stroke: var(--muted); stroke-width: 2.4; stroke-dasharray: 6 5; stroke-linecap: round; }

/* chainKit: a coiled set of snow chains lying on the snow — the dashes are the
   links, so the coil reads as chain and not as a rope or a tyre */
.kv-chain { fill: none; stroke: var(--metal); stroke-width: 3.4; stroke-dasharray: 5 4; stroke-linecap: round; }

/* dashLamps: the instrument cluster. Dark in both themes (it is a physical dark
   bezel), with a metal outline so the silhouette survives on the dark panel. */
.kv-panel { fill: #22262e; stroke: color-mix(in srgb, var(--metal) 55%, transparent); stroke-width: 2; }
.kv-face { fill: #2b3240; stroke: #454e5e; stroke-width: 2; }
.kv-tick { stroke: #9aa4b2; stroke-width: 2.4; stroke-linecap: round; }
.kv-needle { stroke: #cbd3dd; stroke-width: 3.4; stroke-linecap: round; fill: none; }
.kv-hub { fill: #9aa4b2; }
/* one telltale: a soft halo behind a coloured glyph, or a dark glyph when unlit */
.kv-lamp .halo { fill: none; }
.kv-lamp .ring { fill: none; stroke-width: 3.4; }
.kv-lamp .tri { fill: none; stroke-width: 3.4; stroke-linejoin: round; }
.kv-lamp .ink { stroke-width: 3; stroke-linecap: round; fill: none; }
.kv-lamp.red .halo { fill: rgba(255,59,48,.18); }
.kv-lamp.red .ring, .kv-lamp.red .ink { stroke: #ff3b30; }
.kv-lamp.red .dot { fill: #ff3b30; }
.kv-lamp.amber .halo { fill: rgba(255,176,32,.20); }
.kv-lamp.amber .tri, .kv-lamp.amber .ink { stroke: #ffb020; }
.kv-lamp.amber .dot { fill: #ffb020; }
.kv-lamp.off .ring { stroke: #4a505c; }

/* dipstick: steel stick, oil film, and the two level notches */
.kv-dip { stroke: #b8c1cc; stroke-width: 8; stroke-linecap: round; fill: none; }
.kv-dip-handle { fill: none; stroke: #b8c1cc; stroke-width: 5; }
.kv-oil { stroke: #7a5a1e; stroke-width: 10; stroke-linecap: round; fill: none; }
.kv-dip-mark { stroke: #5c6472; stroke-width: 3; stroke-linecap: round; fill: none; }
/* small neutral label on a studio prop (MIN / MAX) */
.kv-tag { fill: var(--muted); font: 700 11px var(--font); letter-spacing: .04em; }

/* brakeFluid: translucent reservoir, screw cap, pale amber fluid, level marks */
.kv-tank { fill: rgba(190,220,245,.42); stroke: var(--metal); stroke-width: 3; }
.kv-cap { fill: var(--metal); }
.kv-fluid { fill: color-mix(in srgb, var(--warn2) 55%, transparent); }
.kv-mark { stroke: var(--muted); stroke-width: 3; stroke-linecap: round; fill: none; }

/* roofLoad: the box and its rails, and the crates still standing on the road */
.kv-box { fill: color-mix(in srgb, var(--metal) 40%, var(--paper)); stroke: var(--metal); stroke-width: 2; }
/* Same reason as .lr-rack: the feet carry the box, so they must read against the
   sky between box and roof. --metal disappeared there. */
.kv-rack { stroke: #4a5260; stroke-width: 4; stroke-linecap: round; fill: none; }
:root[data-theme="dark"] .kv-rack { stroke: #cbd2dc; }
.kv-crate rect { fill: #c9a06a; stroke: rgba(0,0,0,.28); stroke-width: 2; }
.kv-strap { stroke: rgba(0,0,0,.3); stroke-width: 3; stroke-linecap: round; fill: none; }

/* trailerLamps: an unlit, unmarked trailer body and its drawbar */
.kv-body { fill: #8d97a5; stroke: rgba(0,0,0,.25); stroke-width: 2; }

/* beamOut / brakeLampOut: lamp housings seen head-on and from behind. `on` is a
   lit bulb plus a halo, `off` is the same housing with the bulb dead. */
.kv-beamlamp.on { fill: #fff4c2; stroke: rgba(255,255,255,.5); stroke-width: 2; }
.kv-beamlamp.off { fill: #4a505c; stroke: rgba(255,255,255,.22); stroke-width: 2; }
.kv-taillamp.on { fill: #ff3b30; stroke: rgba(255,255,255,.4); stroke-width: 2; }
.kv-taillamp.off { fill: #6b3a3f; stroke: rgba(255,255,255,.22); stroke-width: 2; }
.kv-glow { fill: rgba(255,244,194,.30); }
.kv-glow.red { fill: rgba(255,59,48,.26); }
/* the pool one working dipped beam throws on the tarmac ahead of the car */
.kv-pool { fill: rgba(255,246,200,.22); }
.kv-exhaust { fill: #6b7280; }
/* radiator grille — only the front view carries it, so the same body also reads
   as a rear when it is left off */
.kv-grille rect { fill: #2b3240; stroke: rgba(255,255,255,.14); stroke-width: 2; }
.kv-grille .slat { stroke: rgba(255,255,255,.22); stroke-width: 2; fill: none; }

/* headrestFit: the two posts between the seat back and the restraint */
.kv-seat-post { stroke: var(--metal); stroke-width: 6; stroke-linecap: round; fill: none; }
/* thin guides that carry a level out to a measuring bracket */
.kv-guide { fill: none; stroke: var(--muted); stroke-width: 1.6; stroke-dasharray: 5 5; opacity: .8; }

/* idleExhaust: exhaust drifting from the tailpipe of a car that has not moved */
.kv-fumes circle { fill: rgba(126,136,152,.55); transform-box: fill-box; transform-origin: 50% 50%;
  animation: kv-puff 3.6s ease-out infinite; }
.kv-fumes .p2 { animation-delay: .5s; }
.kv-fumes .p3 { animation-delay: 1s; }
@keyframes kv-puff {
  0% { opacity: 0; transform: translate(6px, 6px) scale(.5); }
  25% { opacity: .85; }
  100% { opacity: 0; transform: translate(-16px, -18px) scale(1.35); }
}

/* The cluster bezel, the rubber and the crate keep their real colour in the dark
   theme; only the see-through and glow surfaces need lifting to stay readable. */
:root[data-theme="dark"] .kv-tank { fill: rgba(150,190,225,.20); }
:root[data-theme="dark"] .kv-box { fill: color-mix(in srgb, var(--metal) 55%, var(--paper)); }
:root[data-theme="dark"] .kv-pool { fill: rgba(255,246,200,.16); }
:root[data-theme="dark"] .kv-wearbar { fill: color-mix(in srgb, var(--metal) 75%, #23282f); }

/* lorry: the plan-view bus body in a pale box-lorry livery, so a heavy vehicle
   is not mistaken for a bus and still reads against dark asphalt */
.ru-lorry .sc-bus-body { fill: #d9dee7; }
.ru-lorry .sc-bus-line { stroke: rgba(20,26,36,.28); }

/* green aspect of the plan-view signal head (lorryTurnRight); the other two
   bulbs use the existing unlit .sc-bulb */
.ru-green { fill: #34c759; }

/* dog on a lead (dogLead) */
.ru-dog .ru-fur { fill: #6f6257; }
.ru-dog .ru-limb2, .ru-dog .ru-tail { fill: none; stroke: #6f6257; stroke-width: 3; stroke-linecap: round; }
.ru-dog .ru-eye { fill: #12151b; }
.ru-lead { fill: none; stroke: #d81f3a; stroke-width: 2.2; stroke-linecap: round; }

/* walking frame and wheelchair (rollatorCross, wheelchairRoad). Bright
   aluminium rather than var(--metal): the frame has to stay legible on the dark
   asphalt of BOTH themes, and the dark-theme metal token is too close to it. */
.ru-frame { fill: none; stroke: #b9c3d0; stroke-width: 5; stroke-linecap: round; stroke-linejoin: round; }
.ru-wheelbar { fill: #23282f; }
.ru-seat { fill: #4b5464; stroke: rgba(255,255,255,.35); stroke-width: 1.2; }

/* standing e-scooter and a wheeled moped (footwayScooter, mopedAcross) */
.ru-swheel { fill: #23282f; }
.ru-bar { fill: none; stroke: var(--metal); stroke-width: 3; stroke-linecap: round; }
.ru-mopedbody { fill: #b8442f; }
.ru-mopedseat { fill: #1d2430; }
:root[data-theme="dark"] .ru-dog .ru-fur { fill: #8b7c6d; }
:root[data-theme="dark"] .ru-dog .ru-limb2, :root[data-theme="dark"] .ru-dog .ru-tail { stroke: #8b7c6d; }
:root[data-theme="dark"] .ru-lorry .sc-bus-body { fill: #c3cad6; }

/* Dark mode: every colour above is either a theme token (--ink, --lane, --glass,
   --metal, --paper) or a literal that is a light source or road paint, both of
   which stay the same colour after dark. No overrides needed. */
/* ---- r2 forer-og-eiers-ansvar ---- */
/* ==== round-2 scenes: førers og eiers ansvar (prefix .fb-) ================= */

/* Seat-belt webbing. Near-white like .sc-belt, but thinner: these belts run over
   a 22-unit shoulder from above, where .sc-belt's 5-unit stroke swallows the
   whole torso. `.wide` is the frontal rear-bench view, where the same strap is
   seen at twice the size. */
.fb-belt { fill: none; stroke: #20252e; stroke-width: 2.2; stroke-linecap: round; }
.fb-belt.wide { stroke-width: 4; }

/* Clothing on the drawn people: the jumper/jacket mass that turns a stick figure
   into a body. Same blue as .sc-shoulder so the plan-view and the frontal
   figures belong to one cast; `.b` is the second sibling, who would otherwise
   merge into the first. Fixed colours (not tokens) because they are clothing,
   and they sit on seats and asphalt that are dark in BOTH themes. */
.fb-torso { fill: #3f5f8f; stroke: rgba(0,0,0,.22); stroke-width: 1; stroke-linejoin: round; }
.fb-torso.b { fill: #b8743d; }
.fb-sleeve { fill: none; stroke: #3f5f8f; stroke-width: 7; stroke-linecap: round; }
.fb-sleeve.b { stroke: #b8743d; }
/* thighs seen end-on in the frontal bench view — a seated child without them
   looks like a torso sinking into the cushion */
.fb-legs { fill: #4a5263; stroke: rgba(0,0,0,.25); stroke-width: 1; }

/* Seats seen from ABOVE (the cut-away cabin) and the seams between the three
   places on a bench. Same greys as .sc-seat/.sc-seat-base so every seat in the
   bank is the same furniture. */
.fb-seat-top { fill: #4b5464; }
.fb-headrest { fill: #3b4250; }
.fb-seat-line { fill: none; stroke: rgba(255,255,255,.22); stroke-width: 2; }

/* Steering wheel seen from above, lying on a near-black dashboard: mixed light
   from --metal rather than --ink, which is dark in light mode and would vanish
   into the dash. */
.fb-wheel-top { fill: none; stroke: color-mix(in srgb, var(--metal) 75%, #fff); stroke-width: 5; }

/* rub rail along the pickup's bed side */
.fb-bed-line { fill: none; stroke: rgba(255,255,255,.25); stroke-width: 2; }

/* "Del 1" / "Del 2" on the two sheets of the registration document — a label,
   never a heading with content after it. */
.fb-doc-label { fill: var(--muted); font: 800 15px var(--font); letter-spacing: .02em; }

/* Wing mirrors on the cut-away cabin — without them a car seen from above with
   the roof off reads as a room rather than as a vehicle. */
.fb-mirror { fill: color-mix(in srgb, var(--metal) 70%, #fff); }
.fb-boot { fill: #1f242e; }
/* hub and spokes of the steering wheel seen from above */
.fb-wheel-hub-top { fill: color-mix(in srgb, var(--metal) 75%, #fff); }
.fb-wheel-top.thin { stroke-width: 3; }
:root[data-theme="dark"] .fb-boot { fill: #7d8797; }
:root[data-theme="dark"] .fb-seat-top { fill: #5a6474; }
:root[data-theme="dark"] .fb-headrest { fill: #4b5464; }
/* ---- r2 kjoretoyet ----
   Every class is prefixed vh- so it cannot collide with the sc- primitives or round 1's
   lr-/fea-/kv-/ru- sets. Interior and under-car parts are drawn in fixed dark greys (that is what the
   parts are) but always carry a light stroke, so they still separate from the studio panel in dark
   mode, exactly as .kv-panel does. */

/* ---- vhAutoControls: selector console + footwell ------------------------- */
.vh-panel, .vh-firewall { fill: #2b313b; stroke: color-mix(in srgb, var(--metal) 55%, transparent); stroke-width: 2; }
/* the gate is a RECESS: it has to be darker than the panel it is cut into, or it
   reads as a printed stripe instead of a channel the lever moves in */
.vh-gate { fill: #12161c; }
.vh-detent { fill: #6b7686; }
.vh-gearlabel { fill: #e6eaf0; font: 800 15px var(--font); letter-spacing: .04em; }
.vh-knob-stem { fill: var(--metal); }
.vh-knob { fill: #4a515e; stroke: #9aa4b2; stroke-width: 2; }
.vh-floor { fill: #1a1f26; stroke: color-mix(in srgb, var(--metal) 35%, transparent); stroke-width: 2; }
.vh-arm { fill: var(--metal); }
.vh-pedal { fill: #3b424e; stroke: #9aa4b2; stroke-width: 2; }
.vh-rib { fill: none; stroke: #9aa4b2; stroke-width: 2.4; stroke-linecap: round; }

/* ---- vhBeamAim: the bloom where a mis-aimed beam meets the other windscreen */
.vh-glare { fill: rgba(255,246,200,.5); }

/* ---- vhFordWater: standing water on the carriageway ---------------------- */
.vh-water { fill: rgba(96,164,214,.62); }
.vh-ripple { fill: none; stroke: rgba(255,255,255,.5); stroke-width: 2.4; stroke-linecap: round; }
.vh-spray path { fill: none; stroke: #eaf4fb; stroke-width: 3; stroke-linecap: round; }
.vh-spray circle { fill: #eaf4fb; }

/* ---- vhEvCharge: charging post, cable and the car's charge flap ---------- */
.vh-charger { fill: #3b424e; stroke: #9aa4b2; stroke-width: 2; }
.vh-screen { fill: #bfe7f5; }
.vh-led { fill: var(--ok2); }
/* the cable crosses grass, kerb and asphalt: dark in the light theme, light in
   the dark one (see below), because either fixed colour vanishes in one of them */
.vh-cable { fill: none; stroke: #1c2128; stroke-width: 5; stroke-linecap: round; }
.vh-plug, .vh-port { fill: #6b7686; stroke: rgba(0,0,0,.35); stroke-width: 1.5; }

/* ---- vhSidewall: a zoomed strip of tyre sidewall ------------------------- */
.vh-rubber { fill: #23282f; stroke: color-mix(in srgb, var(--muted) 40%, transparent); stroke-width: 2; }
.vh-shoulder { fill: #191d23; }
/* butt caps, not round: a round cap overshoots the shoulder edge and the grooves
   sprout out of the top of the tyre like teeth */
.vh-groove2 { fill: none; stroke: #0e1115; stroke-width: 5; stroke-linecap: butt; }
.vh-emboss { fill: #a7b1bf; font: 800 20px var(--font); letter-spacing: .05em; }
.vh-focus { fill: none; stroke: var(--hi); stroke-width: 3; }

/* ---- vhPressureCheck: valve, hose and dial gauge ------------------------- */
/* tread grooves cut into the wheel — lighter than the tyre itself, or they
   vanish into the black disc and it reads as a plain wheel */
.vh-tread { stroke: #464e5b; stroke-width: 3.4; stroke-linecap: round; }
.vh-valve { fill: none; stroke: #8b95a3; stroke-width: 7; stroke-linecap: round; }
.vh-valvecap { fill: #6b7686; }
.vh-hose { fill: none; stroke: #2f3641; stroke-width: 6; stroke-linecap: round; }
.vh-dial { fill: #2b313b; stroke: #9aa4b2; stroke-width: 2; }
.vh-dialface { fill: #f2f5f9; }
.vh-tick2 { stroke: #5c6472; stroke-width: 2.2; stroke-linecap: round; }
.vh-needle2 { fill: none; stroke: #d81f3a; stroke-width: 3.4; stroke-linecap: round; }
.vh-hub2 { fill: #5c6472; }
.vh-unit { fill: #5c6472; font: 700 12px var(--font); }
/* ---- dark theme ---------------------------------------------------------- */
:root[data-theme="dark"] .vh-water { fill: rgba(96,164,214,.42); }
:root[data-theme="dark"] .vh-hose { stroke: #7d8794; }
:root[data-theme="dark"] .vh-cable { stroke: #98a2b0; }
/* tyre black on a dark studio panel is a hole in the page: lift the sidewall
   strip (and its shoulder) just enough for the silhouette to read */
:root[data-theme="dark"] .vh-rubber { fill: #333a43; }
:root[data-theme="dark"] .vh-shoulder { fill: #262c34; }
/* ---- r2 forer-og-andre-trafikanter ---- */
/* ---- round 2: forer-og-andre-trafikanter ------------------------------- */

/* Plan-view panel van (otVanPasser). A white van, so it does not read as a
   third car colour; the class beats `.sc-car .sc-shell` on specificity. */
.sc-car.ot-van .sc-shell { fill: #e2e7ef; }
.sc-car.ot-van .sc-glass { fill: var(--glass); }
/* the cab/box seam and the rear door split — without them a white van from
   above is just a slab. Same ink weight as the lorry roof lines. */
.ot-vanline { fill: none; stroke: rgba(20, 26, 36, .38); stroke-width: 2.4; }
/* two roof ribs: without them a white box from above is a featureless slab */
.ot-vanrib { fill: none; stroke: rgba(20, 26, 36, .14); stroke-width: 1.8; }

/* Flashing headlamp of the car behind (otFlashBehind). Opacity only — the group
   carries no transform, and neither does anything it wraps. The cycle is timed
   so the lamp is LIT at 1200 ms, the phase tools/check-scenes.mjs freezes at. */
.ot-flash { animation: ot-flash 2.2s steps(1) infinite; }
@keyframes ot-flash {
  0%, 19% { opacity: 1; }
  20%, 39% { opacity: .07; }
  40%, 62% { opacity: 1; }
  63%, 100% { opacity: .07; }
}

/* Spruce (otDeerVerge, otTrailhead). Tied to --hill like .sc-thicket, so the
   trees darken with the landscape in dark mode instead of glowing. */
.ot-needles { fill: color-mix(in srgb, var(--hill) 62%, #1f4a2c); }
.ot-trunk { fill: color-mix(in srgb, var(--hill) 30%, #4a3524); }

/* Walking path at the trailhead (otTrailhead) — narrower than .sc-path, which
   is the 20-wide gang- og sykkelveg band and would read as a second road. */
.ot-trail { fill: none; stroke: #d7c4a1; stroke-width: 11; }
.ot-trail-mark { fill: none; stroke: rgba(255, 255, 255, .7); stroke-width: 1.6; stroke-dasharray: 7 7; }
/* the gravel path is a light band on a dark ground at night — take it down so it
   does not out-glare the road */
:root[data-theme="dark"] .ot-trail { stroke: #8f7f63; }
/* ==== END authored-2026-08-16b scenes ==== */

/* fbLooseLaptop: a cut-away body shell so the seats read as a car interior and not
   as furniture. Outline only — a filled body would bury the seats. */
.fb-cabin-shell { fill: color-mix(in srgb, var(--metal) 12%, transparent);
  stroke: color-mix(in srgb, var(--metal) 70%, transparent); stroke-width: 3; }
.fb-cabin-glass { fill: color-mix(in srgb, var(--glass) 55%, transparent); }

/* ==== BEGIN authored-2026-08-16c scenes ==== */
/* ---- r3 lover-og-regler ----
   Three scenes: the horn boss being pressed, the four tyres of one car from above, and a light
   rear-end shunt still standing in its lane. Everything that has to read against BOTH studio panels
   is mixed from a token (--ink flips with the theme); the rubber and the paint on it are real object
   colours and stay put, exactly as .sc-tyre / .sc-spoke do. */

/* lgHornPress: the sound leaving the horn. Three arcs of falling weight — --ink because they sit on
   the studio panel, which is near-white in light mode and near-black in dark, and a fixed colour
   would vanish in one of them. The bulb-horn symbol beside the wheel (flared bell, tube, finger loop,
   rubber bulb) is one solid ink silhouette with straight rays off the bell mouth; the loop and the
   rays are strokes, so they override the blanket fill above them. */
.lg-horn path, .lg-horn ellipse { fill: var(--ink); }
.lg-horn .tube { fill: none; stroke: var(--ink); stroke-width: 5; }
.lg-horn .ray path { fill: none; stroke: var(--ink); stroke-width: 5; stroke-linecap: round; }
/* ---- r3 forer-og-eiers-ansvar ---- */
/* Round-3 classes for the `forer-og-eiers-ansvar` scenes. Every class is prefixed
   ea- so it cannot collide with the sc-/fb-/vh-/ot- sets, and every colour is
   either a theme token or a mid tone that holds up in both themes. */

/* Front-view torso of a grown-up (eaLapChild). Green on purpose: the child torsos
   in the fb- set are blue and orange, so an adult holding a child never reads as a
   second child. */
.ea-torso { fill: #4d6b5c; stroke: rgba(0,0,0,.22); stroke-width: 1; stroke-linejoin: round; }
/* A bare arm laid around the child on the lap. Skin-toned and thinner than
   .fb-arm, whose 7-unit black stroke read as a bar clamped over the child. */
.ea-arm { fill: none; stroke: #e2a077; stroke-width: 6; stroke-linecap: round; }

:root[data-theme="dark"] .ea-torso { fill: #4b917c; }
/* ---- r3 kjoretoyet ---- */
/* ---- r3 kjoretoyet (mk-) ------------------------------------------------- */

/* Dashed "where that vehicle is going" route and its solid head (mkTurnSignals).
   White like the rest of the road paint, so it reads over asphalt in both themes. */
.mk-path { fill: none; stroke: #f4f7fb; stroke-width: 3; stroke-dasharray: 9 7;
  stroke-linecap: round; opacity: .92; }
.mk-head { fill: #f4f7fb; opacity: .92; }

/* One axle carrying two wheels (mkAxleMix). Drawn before the tyres so the hubs
   cover its ends — an axle that stops short of the wheel floats. */
.mk-axle { fill: var(--metal); }
/* Summer tread seen face-on: circumferential ribs, no studs. */
.mk-rib { fill: none; stroke: #7b8593; stroke-width: 3.4; }
/* Winter tread: radial sipes and the ring of studs. The studs are the light
   element on the dark rubber, which is what carries the difference at card size. */
.mk-sipe { stroke: #7b8593; stroke-width: 3; stroke-linecap: round; }
.mk-stud { fill: #d7dde6; }
/* Dark mode. The rubber fills stay dark (they match .sc-tyre.big, which is not
   re-tinted either); what has to lift is the light metal and the pad materials,
   or the section drawings glare against the dimmed panel. */
:root[data-theme="dark"] .mk-rib, :root[data-theme="dark"] .mk-sipe { stroke: #8d97a4; }
/* ---- r3 forer-og-andre-trafikanter ---- */
/* ---- round-3 scenes: forer-og-andre-trafikanter -------------------------- */

/* spBlockHeater: the snow-covered hill and verge behind the parking bay. Mixed
   against --hill rather than fixed white, so it darkens with the theme instead
   of burning a white slab into the dark-mode card the way a literal #eaf1f8
   would. The carriageway itself keeps the shared .sc-snow-road. */
.sp-snowhill { fill: color-mix(in srgb, #eaf1f8 86%, var(--hill)); }

/* spChildRuns: the running child's limbs. Heavier than the shared .sc-limb
   (3.4) because they are the only thing that says "running" — at card size a
   3.4 arm on a 30-unit figure disappears and the child reads as a dot. */
.sp-child .sc-limb { stroke-width: 3.8; }
/* …and repainted for dark mode: the shared .sc-limb ink (#2b3240) is within a
   hair of the dark-theme asphalt (#2a303c), so the child lost every limb and
   read as a blue dot. Only this figure needs it — it is the one place where the
   limbs, not the torso, carry the meaning. */
:root[data-theme="dark"] .sp-child .sc-limb { stroke: #c8d0dc; }
/* ==== END authored-2026-08-16c scenes ==== */

/* Cards whose vehicle is STOPPED. Every road scene inherits a spinning `.sc-wheel`
   and a flowing centre line, and both say "moving" — the one thing these cards must
   not say: a parked car, a car stopped behind a warning triangle, a crashed car at
   a casualty scene. Scoped per scene so no other card is affected. */
[data-scene="parkedDark"] .sc-wheel,
[data-scene="parkedDark"] .sc-flow,
[data-scene="parkedDark"] .sc-flow line,
[data-scene="warningtriangle"] .sc-wheel,
[data-scene="warningtriangle"] .sc-flow,
[data-scene="warningtriangle"] .sc-flow line,
[data-scene="roadsideCasualty"] .sc-wheel,
[data-scene="roadsideCasualty"] .sc-flow,
[data-scene="roadsideCasualty"] .sc-flow line,
[data-scene="accident"] .sc-wheel,
[data-scene="accident"] .sc-flow,
[data-scene="accident"] .sc-flow line,
[data-scene="fbRiderDown"] .sc-wheel,
[data-scene="fbRiderDown"] .sc-flow,
[data-scene="fbRiderDown"] .sc-flow line,
[data-scene="engineFire"] .sc-wheel,
[data-scene="engineFire"] .sc-flow,
[data-scene="engineFire"] .sc-flow line,
[data-scene="tunnelFireAhead"] .sc-wheel,
[data-scene="tunnelFireAhead"] .sc-flow,
[data-scene="tunnelFireAhead"] .sc-flow line,
[data-scene="eaTunnelStall"] .sc-wheel,
[data-scene="eaTunnelStall"] .sc-flow,
[data-scene="eaTunnelStall"] .sc-flow line,
[data-scene="eaVanLoad"] .sc-wheel,
[data-scene="fbTunnelQueue"] .sc-wheel,
[data-scene="fbTunnelQueue"] .sc-flow,
[data-scene="fbTunnelQueue"] .sc-flow line,
/* a car on the end of a charging cable is parked, by definition */
[data-scene="vhEvCharge"] .sc-wheel,
[data-scene="vhEvCharge"] .sc-flow,
[data-scene="vhEvCharge"] .sc-flow line { animation: none; }

/* debris shed by a crashed car — small shards on the tarmac beside the damage. */
.sc-debris path { fill: color-mix(in srgb, var(--ink) 55%, transparent); }

/* These four draw their vehicle inside a `scale(-1,1)` mirror (so the overhang, bed or load lands on
   the right). The mirror flips apparent rotation, so the shared +360 keyframe renders anti-clockwise
   here — correct for a vehicle travelling left. Since `.sc-wheel` became +360 for everyone they
   inherit it and the old override is gone. Do not "restore" a ccw keyframe for them. */

/* ==== BEGIN authored-2026-08-16d ==== */
/* ---- batch 1 — `fart-og-plassering` ----
   Every class is prefixed `fxa-` so it cannot collide with the rest of scenes.css. Anything that
   already had paint here (spray `.vh-spray`, cones `.sc-cone`, fog band `.sc-fog`, rain `.sc-rain`,
   zebra, measure, houses) is reused rather than re-invented. */

/* ---- fxRainGap: the downpour --------------------------------------------- */
/* An overcast wash over the WHOLE frame (landscape included), which is what
   turns the ordinary sunny roadSide() into a wet grey day. Cool grey rather
   than neutral: a neutral wash just looks like a dimmed screenshot. */
.fxa-overcast { fill: rgba(96,112,138,.30); }
/* Four phase offsets for the rain, on top of `.sc-rain`'s four durations, so the streaks scatter over
   the frame instead of falling as one band. The delays are negative (the loop is already running at
   t = 0, so nothing pops into existence) and the selector is qualified with `.sc-rain line` because
   the base rule sets the whole `animation` shorthand — an unqualified class would lose on specificity
   and the delay would be silently dropped. */
.sc-rain line.fxa-rd0 { animation-delay: 0s; }
.sc-rain line.fxa-rd1 { animation-delay: -.24s; }
.sc-rain line.fxa-rd2 { animation-delay: -.48s; }
.sc-rain line.fxa-rd3 { animation-delay: -.74s; }

/* ---- fxWetAsphalt: the water film ---------------------------------------- */
/* Wet tarmac is DARKER than dry tarmac, not bluer: the film is a dark wash, and
   the gloss is one pale sheen band under the car. Painted as a wash rather than
   as a colour so it works over `--asph` in both themes. */
.fxa-wetfilm { fill: rgba(12,18,32,.34); }
.fxa-sheen { fill: rgba(206,230,250,.24); }

/* ---- fxFogSpeed: the wall of fog ----------------------------------------- */
/* A fog DAY has no blue in the sky, so the scene's own sky gradient is covered
   before anything else is drawn. */
.fxa-greysky { fill: #d9dfe6; }
/* The wall THICKENS rather than beginning at a printed vertical border — a single opaque rect read as
   "half the picture is missing". The ramp is nine overlapping tall ellipses, not stacked rectangles:
   rectangles leave straight vertical seams that show as stripes across the tarmac, whereas the
   ellipses' arcs merge into a ragged front. The two core slabs behind them make the far side dense
   enough to hide the road completely. Static, unlike the drifting `.sc-fog` haze band. */
.fxa-fogwall { fill: #e9eef3; opacity: .2; }
.fxa-fogcore { fill: #e9eef3; opacity: .85; }
/* The dipped beam, warmer and denser than the shared `.sc-beam`: that one is a
   pale wash tuned for dark tarmac and simply disappears against fog-lit grey. */
.fxa-beam { fill: #ffe6a0; opacity: .8; }
:root[data-theme="dark"] .fxa-greysky { fill: #3a424e; }
:root[data-theme="dark"] .fxa-fogwall { fill: #aeb7c3; opacity: .18; }
:root[data-theme="dark"] .fxa-fogcore { fill: #aeb7c3; opacity: .7; }

/* ---- fxRoadworksLimit: the temporary speed limit ------------------------- */
/* A Norwegian temporary speed limit is the ordinary sign on an ORANGE face, which
   is the only thing that tells it from the permanent one beside it — same red ring,
   same numeral. Keep the ring `#d81f3a` so the two roundels stay the same sign in
   two states; the orange belongs to the face alone, nowhere else on the card. */
.fxa-tempface { fill: #f5a03c; stroke: #d81f3a; }

/* ---- batch 3 — round-4 scenes: road surface, glare and light (fxc…) ----
   Nine cards whose subject is what the road is covered in, or what the light is doing. Two rules:
   * every surface hazard must be legible as THAT hazard at 400×180 — slush is matt and grey-brown,
     grit discrete stones, wet leaves warm ellipses, standing water a cold gloss with a reflection.
     No two of them may share a fill.
   * nothing here animates. Where a shared class would have brought motion with it (.sc-sun pulses,
     .sc-fog drifts, .sc-stars twinkle) these define a static equivalent instead. */

/* --- fxDazzleOncoming: the blaze around an oncoming lamp. There are no <defs>,
   so a "glow" is two flat translucent ellipses (a wide one and a hot core) plus
   straight spikes drawn IN FRONT of the body — light in front of the car is the
   whole point of the card. */
.fxc-glow { fill: rgba(255,246,205,.34); }
.fxc-glow.hot { fill: rgba(255,252,235,.5); }
.fxc-glare { fill: none; stroke: rgba(255,248,214,.62); stroke-width: 3.4; stroke-linecap: round; }
/* Static stars — .sc-stars twinkles, and these cards are static. */
.fxc-star { fill: #fff; opacity: .7; }

/* --- fxNoTailLights. Own fog paint rather than .sc-fog, which drifts on a 7 s loop. Two weights, and
   the scene uses BOTH: the heavy one behind the car so the background really goes to fog, the `.thin`
   one over the top so the car is hazy while its two DARK tail lamps — the subject, with no lit lamp
   anywhere to compare them against — stay readable. The spill is the daytime running lamps throwing
   light forward past the car's flanks; warmer and far stronger than .kv-pool, which disappears
   completely under a fog veil. */
.fxc-fog { fill: rgba(238,243,249,.72); }
.fxc-fog.thin { fill: rgba(238,243,249,.26); }
.fxc-spill { fill: rgba(255,246,196,.62); }

/* --- fxSlushTracks. Matt, opaque and grey-brown: no sheen, no blue, nothing
   that could be read as standing water, and darker than snow so the scoured
   tracks of bare asphalt inside it are the LIGHT-to-dark step a wheel track is. */
.fxc-slush { fill: #a7a698; }
/* Lumps of thrown slush, a shade lighter than the layer. Without them the layer
   and its scoured tracks are three straight-edged rectangles, which is exactly
   what road paint looks like. */
.fxc-lump { fill: #b8b7a7; }

/* --- fxSpringGravel. Warm pale stones on dark asphalt. Drawn as ~310 separate
   circles rather than a tinted band: loose material has to look loose. */
.fxc-grit { fill: #dccca6; }

/* --- fxAquaplane. A SHALLOW film, so it is deliberately pale and thin: the asphalt tone and the
   yellow centre-line dashes have to read straight through it. An opaque blue drew the existing
   `vhFordWater` picture instead — a ford, with the wheels submerged, the wrong physics for
   aquaplaning. The bright leading edge and the long flat streaks are what make 30% of blue read as
   water lying on a road rather than as a tint; the spray is stroked arcs with a droplet at each tip,
   because a filled plume read as steam. */
.fxc-greysky { fill: rgba(148,159,176,.5); }
.fxc-film { fill: rgba(146,199,233,.4); }
.fxc-filmedge { fill: none; stroke: rgba(240,250,255,.8); stroke-width: 3; stroke-linecap: round; }
.fxc-streak { fill: none; stroke: rgba(240,250,255,.5); stroke-width: 2.6; stroke-linecap: round; }
.fxc-spray { fill: none; stroke: rgba(235,246,255,.85); stroke-width: 3; stroke-linecap: round; }
.fxc-drop { fill: rgba(235,246,255,.85); }

/* Dark mode. The snow whites are left alone — .sc-snow-road is not re-tinted
   either, so a winter road stays a winter road in both themes. What has to come
   down is every LIGHT veil laid over the whole frame: at dark-mode brightness a
   0.55 white fog or a warm sky wash burns a slab into the card. */
:root[data-theme="dark"] .fxc-fog { fill: rgba(152,165,182,.46); }
:root[data-theme="dark"] .fxc-fog.thin { fill: rgba(152,165,182,.2); }
:root[data-theme="dark"] .fxc-lump { fill: #7c7b70; }
:root[data-theme="dark"] .fxc-greysky { fill: rgba(58,66,80,.5); }
:root[data-theme="dark"] .fxc-film { fill: rgba(120,178,216,.3); }
:root[data-theme="dark"] .fxc-slush { fill: #6e6d63; }
:root[data-theme="dark"] .fxc-grit { fill: #b3a684; }

/* ---- batch 4 — round-4 `forer-og-eiers-ansvar` ----
   Every class is prefixed ana- so it cannot collide with the sc- primitives or the
   lr-/fea-/kv-/ru-/lw-/fb-/vh-/ot-/lg-/ea-/mk-/sp- sets. Colours are theme tokens wherever the object
   is chrome, and fixed mid tones where the object is a physical thing (rubber, sheet metal, skin, a
   wound) that does not change colour after dark. */

/* Limbs on the figures this batch adds: the person sitting hunched on the kerb
   and the casualty seen from above. Heavier than the shared .sc-limb (3.4) — on
   a 38-unit seated figure and on a body lying in the road, the limbs are what
   say "hunched" and "lying down", and a hairline stroke reads as a scribble.
   `.wide` is the plan-view casualty, drawn at s ≈ 0.75. */
.ana-limb { fill: none; stroke: #2b3240; stroke-width: 4.6; stroke-linecap: round; stroke-linejoin: round; }
/* A bare forearm, skin-toned and thinner, so it separates from the trouser leg it
   rests on — the same trick .ea-arm plays over the child on the lap. */
.ana-arm { fill: none; stroke: #e2a077; stroke-width: 4.4; stroke-linecap: round; stroke-linejoin: round; }

/* Body of the plan-view PEDESTRIAN (anaPedTop). Deliberately lighter than
   .sc-shoulder's #2f6fed: that dark body over two dark leg stubs is exactly the
   plan-view moped silhouette, and lightening it (plus real arms) is what tells
   the two apart at car-park size. `.b` is the second person, who would otherwise
   merge into the first. */
.ana-body { fill: #3f5f8f; stroke: rgba(0, 0, 0, .2); stroke-width: .8; }
/* green, not the warm orange tried first: at car-park size that orange body sat
   under an .sc-skin head (#f0b48a) and the two merged into one blob */
.ana-body.b { fill: #5d6b4e; }
.ana-limb.arm { stroke: #3f5f8f; stroke-width: 3.2; }
.ana-limb.arm.b { stroke: #5d6b4e; }
.ana-limb.wide.arm { stroke-width: 5; }
.fb-sarm { stroke: #3f5f8f; stroke-width: 3; }
.ana-limb.wide { stroke-width: 5.4; }
/* …and repainted after dark: the shared limb ink (#2b3240) is within a hair of
   the dark-theme asphalt (#2a303c), so a person lying in the road lost every
   limb and read as a blue blob. */
:root[data-theme="dark"] .ana-limb { stroke: #97a1b2; }

/* The car key passing between the two hands (anCarHandover). Pale metal with a
   dark hairline, so it separates both from the sky behind it and from the hands
   it touches; the bit is a stroke, because at 20 units a cut key profile is
   three teeth or nothing. */
.ana-key { fill: color-mix(in srgb, var(--metal) 55%, #fff); stroke: #1c2128; stroke-width: 1.4; }
/* the bow is HOLLOW: a filled disc on a filled blade read as a barbell */
.ana-key-bow { fill: none; stroke: #1c2128; stroke-width: 2.6; }
.ana-key-bit { fill: none; stroke: #1c2128; stroke-width: 2.2; stroke-linecap: round; }
/* After dark the bow and the teeth sit against a near-black sky, where a #1c2128
   outline disappears and the key reads as a plain white bar. */
:root[data-theme="dark"] .ana-key-bow,
:root[data-theme="dark"] .ana-key-bit { stroke: #cfd6e0; }
/* Same reason, for the two figures holding it: the shared .sc-limb ink (#2b3240)
   is all but the dark-theme sky, and a handover with no arms is not a handover.
   Scoped to this card only — everywhere else the figure stands on asphalt. */
:root[data-theme="dark"] [data-scene="anCarHandover"] .sc-limb { stroke: #c8d0dc; }

/* The "?" on the trailer's blank plate. The shared .sc-sign-txt is a fixed
   #12151b, which is invisible on .sc-blank's var(--paper) after dark — and this
   "?" is the whole card. Follows --text instead, so it inverts with the theme. */
.ana-qtxt { fill: var(--text); font: 700 15px var(--font); }

/* brøytestikke: the winter marker pole on the verge. Dark shaft with the orange
   reflective band near the top — the two together are what make it a marker pole
   and not a fence post at 44 units tall. */
.ana-pole { fill: #2b3240; }
.ana-pole-band { fill: #f07828; }
:root[data-theme="dark"] .ana-pole { fill: #7d8797; }

/* Tailgate seam on the box trailer (anTrailerPlate). A dark hairline on the
   fixed grey of .kv-body, so it holds in both themes without an override. */
.ana-seam { fill: none; stroke: rgba(0, 0, 0, .3); stroke-width: 3; }

/* Tyre tracks cut through fresh snow (anColdCasualty). Barely darker than the
   snow they are cut into — mixed from --asph so they follow the road in both
   themes. Without them a snow-covered side elevation is one flat pale slab and
   the carriageway disappears entirely. */
.ana-track { fill: color-mix(in srgb, var(--asph) 14%, #eaf1f8); }

/* Cards whose vehicle is STOPPED. Every road scene inherits a spinning
   `.sc-wheel` and a flowing centre line, and both say "moving": a car standing at
   the kerb during a handover, a wrecked car at a crash scene and a trailer on a
   studio ground line must all be still. Scoped per scene, like the existing
   stopped-vehicle block. */
[data-scene="anCarHandover"] .sc-wheel,
[data-scene="anCarHandover"] .sc-flow,
[data-scene="anCarHandover"] .sc-flow line,
[data-scene="anShockWitness"] .sc-wheel,
[data-scene="anShockWitness"] .sc-flow,
[data-scene="anShockWitness"] .sc-flow line,
/* anArriveFirst is a crash that has already happened: a casualty on the tarmac and a
   slewed wreck. A flowing centre line under them says the traffic is still running. */
[data-scene="anArriveFirst"] .sc-flow,
[data-scene="anArriveFirst"] .sc-flow line,
[data-scene="anTrailerPlate"] .sc-wheel { animation: none; }

/* ==== batch-5 scenes: førers og eiers ansvar (prefix .anb-) ================
   Only the paint these eight scenes introduce; everything else reuses the existing classes (.ph-skin,
   .sc-doc, .sc-lines, .sc-specs, .sc-cast, .sc-groundbar, .sc-seat, .fb-belt, .fb-mirror, .sc-fea-*,
   .vh-unit, …). Colours are either theme tokens or real object colours that must NOT flip with the
   theme — burnt skin is red in the dark too, and an LCD stays pale green. */

/* A burn on the back of the hand: a red wash over the skin plus a slightly
   deeper rim, so the patch has an edge instead of fading out into the peach.
   Not a token: it sits on .ph-skin, which is a fixed colour in both themes. */
.anb-burn { fill: #d2352b; opacity: .38; }
.anb-burn-edge { fill: none; stroke: rgba(140,40,30,.42); stroke-width: 3; }
/* Intact blisters. The light catch is what makes them read as raised domes —
   filled flat they read as holes punched in the skin, which is the opposite of
   what the picture must show. */
.anb-blister { fill: #f9e4d6; stroke: #c4835c; stroke-width: 1.8; }
.anb-blister-hi { fill: rgba(255,255,255,.72); }

/* The rear-facing seat's side wing — the padded flange beside the child's head,
   lighter than the shell so the backrest reads as a raised back with sides and
   not as a flat blade — and the empty harness slots moulded through it. The
   slots are bare openings: no webbing, no buckle, nothing threaded. */
.anb-cseat-wing { fill: color-mix(in srgb, var(--blue) 46%, #dbe6f4);
  stroke: color-mix(in srgb, var(--blue) 40%, #000); stroke-width: 2; }
.anb-cseat-slot { fill: color-mix(in srgb, var(--ink) 62%, var(--blue)); }

/* The padded lining hugging the INSIDE of the rear-facing seat, from the top of
   the backrest down and along the pan to the foot end. An empty shell drawn in
   one flat blue read as a kayak; this pale band along the inner corner is what
   makes the opening — and therefore which way the seat faces — legible. It is a
   lining, not an occupant: no head, no limbs, no harness. */
.anb-shell-in { fill: color-mix(in srgb, var(--blue) 22%, #eef3f9);
  stroke: color-mix(in srgb, var(--blue) 40%, #000); stroke-width: 1.6; stroke-linejoin: round; }

/* The ten-year-old's arms and shoes. The arms are skin, and heavier than
   .sc-limb (3.4): on a figure 138 units tall a hairline arm reads as a scribble.
   The shoes are dark so the contact with the ground bar is visible. */
.anb-arm { fill: none; stroke: #f0b48a; stroke-width: 9; stroke-linecap: round; }
.anb-shoe { fill: #2c323b; }

/* ---- batch 6 — `forer-og-eiers-ansvar` ----
   Every class is prefixed anc- so it cannot collide with the sc- primitives or the
   lr-/fea-/kv-/ru-/lw-/fb-/vh-/ot-/lg-/ea-/mk-/sp- sets. Cabin parts are drawn in fixed dark greys
   but always carry a light stroke, so they still separate from the studio panel in dark mode, exactly
   as .kv-panel and .vh-panel do. */

/* ---- anPhoneBuzz: the centre console between the seats ------------------- */
/* Same dark plastic as .vh-panel, so the console belongs to the same car as the
   selector console in the kjoretoyet scenes. */
.anc-console { fill: #2b313b; stroke: color-mix(in srgb, var(--metal) 55%, transparent); stroke-width: 2; }
/* Trim seam across the console. Without it the trapezoid reads as a slab. */
.anc-seam { fill: none; stroke: rgba(255,255,255,.14); stroke-width: 2.5; }
/* The seat bolsters cropped at the bottom corners: they are what says the console
   sits BETWEEN two seats. Same greys as .sc-seat, one shade darker at the edge. */
.anc-bolster { fill: #3b4250; stroke: rgba(255,255,255,.12); stroke-width: 2; }
/* The open tray and the cup holes are RECESSES, so they have to be darker than the
   console they are cut into or they read as printed panels. */
.anc-tray, .anc-hole { fill: #12161c; }
.anc-holder { fill: #454d5a; stroke: rgba(255,255,255,.14); stroke-width: 2; }
/* Gear lever: gaiter, its stitching and the knob. Without the stitching the gaiter
   is the same dark plastic as the console it stands on and the knob reads as a
   grey disc floating on a slab; the knob's highlight is what makes it round. */
.anc-gaiter { fill: #363e4a; stroke: rgba(255,255,255,.2); stroke-width: 2; }
/* Two folds across the gaiter. Drawn as ribs, not as side stitching: a dashed line
   down each edge of the trapezoid read as a dotted rectangle, not as leather. */
.anc-stitch { fill: none; stroke: rgba(255,255,255,.22); stroke-width: 2; }
/* The shaft is what turns a disc on a slab into a LEVER, so it must be visible
   between the knob and the gaiter, overlapping both. */
.anc-shaft { fill: #8d97a4; }
.anc-knob { fill: #6b7686; stroke: rgba(0,0,0,.38); stroke-width: 2; }
.anc-knob-hi { fill: none; stroke: rgba(255,255,255,.45); stroke-width: 3; stroke-linecap: round; }

/* The phone. Body as .sc-phone's, but the screen is LIT — that is the whole point
   of the card — with one notification card and two grey bars on it. No readable
   text anywhere: what the notification says is never what the question turns on. */
.anc-phone { fill: #22262e; stroke: color-mix(in srgb, var(--muted) 40%, transparent); stroke-width: 2; }
.anc-screen { fill: #cfe0f4; }
.anc-earpiece { stroke: #7d8798; stroke-width: 2.4; stroke-linecap: round; }
.anc-notif { fill: #ffffff; stroke: #9aa4b2; stroke-width: 1.4; }
.anc-notifbar { fill: none; stroke: #9aa4b2; stroke-width: 3; stroke-linecap: round; }
/* The phone is going off: two arcs over it, in the shared warning amber. */
.anc-buzz path { fill: none; stroke: var(--warn2); stroke-width: 3.4; stroke-linecap: round; }

/* ---- anFoodBag: the passenger seat and the door beside it --------------- */
/* The cushion's TOP face, one shade lighter than .sc-seat's backrest so the lit
   surface the food stands on separates from the seat back behind it and from the
   darker .sc-seat-base front lip below it. Without those three tones the seat read
   as a flat shelf. */
.anc-cushion { fill: #5b6576; }
/* The backrest's centre panel, inset inside its side bolsters — that is what turns
   a rounded slab into upholstery. Tried three vertical seam LINES first: where the
   bag did not cover them they read as thin rods standing behind the food. */
.anc-seatinset { fill: #565f70; }
/* The door card beside the seat: window sill, pull and armrest. The panel itself
   reuses .sc-fea-body/.sc-fea-glass, so the door belongs to the same car as every
   other cut-away in the bank. */
.anc-sill { fill: #3b4250; }
.anc-pull { fill: var(--metal); }
.anc-armrest { fill: #5c6674; stroke: rgba(0,0,0,.25); stroke-width: 1.6; }

/* ---- anFoodBag: the takeaway on the passenger seat ----
   Kraft paper, with the rolled top a shade darker so the fold reads as a fold and not as a lid. Fixed
   colours, not tokens: paper is paper in both themes, and it sits on a seat that is dark grey in both.
   The twisted HANDLE over it is what finally stopped the bag reading as a cardboard box — a plain
   rectangle with a band on top is a box, whatever colour it is. */
.anc-bag { fill: #d2a468; stroke: rgba(0,0,0,.3); stroke-width: 2; stroke-linejoin: round; }
.anc-bagfold { fill: #b7873f; stroke: rgba(0,0,0,.3); stroke-width: 2; stroke-linejoin: round; }
.anc-bagcrease { fill: none; stroke: rgba(0,0,0,.18); stroke-width: 2.5; }
.anc-handle { fill: none; stroke: #8a6534; stroke-width: 5; stroke-linecap: round; }
/* Lidded cup: pale body, dark lid, cardboard sleeve — the lid and the sleeve are
   what tell a takeaway cup from a drinking glass at card size. */
.anc-cup { fill: #f1f4f9; stroke: #8b95a3; stroke-width: 2; stroke-linejoin: round; }
.anc-cupband { fill: #b7873f; stroke: rgba(0,0,0,.28); stroke-width: 1.6; }
.anc-cuplid { fill: #5c6674; stroke: rgba(0,0,0,.3); stroke-width: 1.6; }

/* ---- anPortalDark: the shade the portal casts on the road --------------- */
/* A translucent wash, never a fill: the asphalt and its edge line have to stay
   visible through it, or the band reads as a hole in the road. */
.anc-shade { fill: rgba(10,15,25,.32); }

/* ---- anBlowout: the collapsed front tyre -------------------------------- */
/* Same rubber as .sc-tyre.big, with the same hairline, so a flat tyre is made of
   the same material as every other tyre in the bank. */
.anc-flat { fill: #23282f; stroke: color-mix(in srgb, var(--muted) 40%, transparent); stroke-width: 2; }

/* Dark mode. The rubber fills stay dark (they match .sc-tyre, which is not
   re-tinted either); what has to lift is the seat plastic and the shade wash, or
   the studio panel and the dark-mode asphalt swallow them. */
:root[data-theme="dark"] .anc-bolster { fill: #4b5464; }
:root[data-theme="dark"] .anc-shade { fill: rgba(0,0,0,.38); }

/* ==== BEGIN authored-2026-08-16 batch7 (lover-og-regler, r4) ====
   Every class is prefixed `lra2-` so it cannot collide with the existing `.lr-…` family (a different
   round) or any other batch. Colours come from the scene custom properties where the object should
   follow the theme, and from fixed object colours where it must not — a matte red lens is dark red in
   dark mode too, and a recess must stay darker than its surroundings in BOTH themes. */

/* ---- lr2InspectionHall: the test bay ------------------------------------- */
/* Roller shutter behind the car — a mid tone, so the car reads against it in
   both themes, with the slats as separate strokes rather than a pattern. */
.lra2-door { fill: color-mix(in srgb, var(--metal) 45%, var(--surface)); stroke: var(--metal); stroke-width: 2; }
.lra2-slat { stroke: color-mix(in srgb, var(--ink) 22%, transparent); stroke-width: 2.4; }
/* The roof beam the drop lamp hangs from. Without it the lamp's flex starts in
   mid-air and the whole fitting floats. */
.lra2-beam { fill: color-mix(in srgb, var(--metal) 55%, var(--surface)); }
/* The workshop floor. A real band, not the hairline `.sc-groundbar`: without a
   floor to be sunk INTO, the roller bed read as a dark plinth the car stood on
   top of, which is the opposite of what a brake tester is. */
.lra2-floor { fill: color-mix(in srgb, var(--metal) 34%, var(--surface)); }
/* The brake-tester recess. A fixed dark slate with a light rim, NOT a token mix:
   in dark mode an --ink-based fill inverts to a pale slab and the hole in the
   floor reads as a raised block. The rollers must stay lighter than it or the
   bed reads as a comb (docs/illustrations.md, "drawing faults"). */
.lra2-pit { fill: #1b2029; stroke: #6b7686; stroke-width: 2; }
.lra2-roller { fill: #8b95a3; stroke: #2b3240; stroke-width: 1.5; }
/* The drop lamp, hanging and UNLIT: a lit lamp over the engine bay would start
   to look like a fault being found, which is the outcome these stems ask about. */
.lra2-cord { fill: none; stroke: var(--ink); stroke-width: 2; }
.lra2-lamp { fill: #6b7686; stroke: rgba(0,0,0,.3); stroke-width: 1.5; }
/* The clip on the inspector's clipboard (the board itself reuses .sc-doc). */
.lra2-clip { fill: var(--metal); }

/* ---- lr2Weighbridge: the pads, the readout ------------------------------- */
/* Portable axle-weigh pads, lying on the asphalt. The pale hairline is what
   separates them from the tarmac — a flat dark rect vanished into it. */
.lra2-pad { fill: #3b424e; stroke: #cbd3dd; stroke-width: 1.5; }
/* Their cable. Mid grey, unlike .sp-cable's near-black: that one runs over snow,
   this one over asphalt that is dark in both themes. */
.lra2-cable { fill: none; stroke: #9aa4b2; stroke-width: 3; stroke-linecap: round; }
.lra2-box { fill: #3b424e; stroke: #9aa4b2; stroke-width: 2; }
.lra2-leg { fill: #6b7686; }
/* The display. It reads "kg ?" and nothing else, ever: a number on this screen
   would answer both stems at once. */
.lra2-screen { fill: #10151c; stroke: #6b7686; stroke-width: 1.5; }
.lra2-readout { fill: #7fe0a8; font: 800 16px var(--font); }

/* ---- lr2MorningAfter: the alarm clock ------------------------------------ */
.lra2-bell { fill: #9aa4b2; stroke: #5b6472; stroke-width: 1.5; }
/* The hands need a class of their own: .sc-needle carries a sweep animation with
   transform-origin 200px 96px, which would swing a clock hand off its own hub. */
.lra2-hand { fill: none; stroke: var(--text); stroke-width: 4; stroke-linecap: round; }
.lra2-hand.hour { stroke-width: 5; }
.lra2-hub { fill: var(--text); }
.lra2-clockfoot { fill: #6b7686; }

/* Cards whose vehicle is STOPPED. Every scene built from `wheel()` inherits the
   spinning `.sc-wheel`, and every road scene the flowing centre line; both say
   "moving", which is the one thing a car on a brake tester, a car standing on
   weigh pads and a bus parked at its depot stand must not say. */
[data-scene="lr2InspectionHall"] .sc-wheel,
[data-scene="lr2Weighbridge"] .sc-wheel,
[data-scene="lr2Weighbridge"] .sc-flow,
[data-scene="lr2Weighbridge"] .sc-flow line,
[data-scene="lr2ShiftStart"] .sc-wheel,
[data-scene="lr2ShiftStart"] .sc-flow,
[data-scene="lr2ShiftStart"] .sc-flow line { animation: none; }
/* ==== END authored-2026-08-16 batch7 ==== */

/* ==== BEGIN authored-2026-08-16 batch 8 (lover-og-regler) ====
   Every class is prefixed `lr2-` so it cannot collide with the existing `lr-…` pack (a different
   batch). Colours come from the .scene custom properties wherever a thing has no colour of its own,
   and from real object colours (a yellow enforcement wallet, amber beer, an amber lamp) where it has
   one — those must NOT flip with the theme. */

/* lr2Alcometer: the hand-held breath tester. The body is a mid-grey instrument
   case, so it needs its own value rather than --metal, which is nearly the
   colour of the studio panel in dark mode. */
.lr2-dev { fill: #4c5666; stroke: rgba(0,0,0,.28); stroke-width: 2; }

/* lr2Alcometer / lr2ParkingTicket: a dark instrument screen. Shared by the two
   scenes so a screen is a screen across the bank. It is DARK in both themes —
   a screen that inverts reads as a white sign face in dark mode. */
.lr2-screen { fill: #14181f; stroke: #2f3540; stroke-width: 2; }
/* The reading on that screen. `sc-big` is var(--text), i.e. near-black in the light
   theme, which would vanish on the dark screen — hence its own light ink. Sized to
   fit "0,5 ‰" inside the 76-unit screen, not just a single glyph. */
.lr2-devtxt { fill: #dfe6ee; font: 800 19px var(--font); }
.lr2-devline { fill: none; stroke: rgba(0,0,0,.3); stroke-width: 2; stroke-linecap: round; }
.lr2-btn { fill: #aab3c0; }
.lr2-btn.big { fill: #c3ccd8; stroke: rgba(0,0,0,.25); stroke-width: 1.6; }
/* the disposable mouthpiece: pale plastic against the dark case, so the joint at
   the top of the body is visible rather than merging into it */
.lr2-mouth { fill: #eef3f8; stroke: #9aa4b2; stroke-width: 2; stroke-linejoin: round; }

/* lr2LicenceSeized: the card and the officer's sleeve. The card is a pale plastic
   slab that must read against the studio panel in both themes, so it is mixed
   from --paper rather than being flat white — and mixed with --blue rather than
   --brand, whose pink washed the card into the panel's own pink corner. */
.lr2-card { fill: color-mix(in srgb, var(--blue) 10%, var(--paper)); stroke: var(--border); stroke-width: 2.5; }
.lr2-photo { fill: color-mix(in srgb, var(--metal) 35%, var(--paper)); }
/* Neutral grey on purpose: a coloured rectangle in the corner of a licence reads
   as a national or EU emblem, and this card must read as a licence without ever
   posing as one. */
.lr2-badge { fill: color-mix(in srgb, var(--metal) 55%, var(--paper)); stroke: var(--border); stroke-width: 1.5; }

/* lr2AmberFlash: the one animated scene in this batch. OPACITY ONLY, on a node carrying no transform
   attribute, at 1 s — and deliberately NOT `.sc-bulb.y`, whose shared 6 s red/amber/green phase cycle
   would turn a flashing amber into an ordinary changing signal. The low step is .3, not 0: an amber
   lens is amber glass even when the lamp is out, and at 0 a still frame (or a reduced-motion viewer)
   would read as three DEAD lamps — "signalet er ute av drift" is one of the distractors. */
.lr2-amber { fill: #f0a020; animation: lr2-blink 1s steps(1) infinite; }
@keyframes lr2-blink {
  0%, 49.9% { opacity: 1; }
  50%, 100% { opacity: .3; }
}

/* ---- f5HorseCartMeeting: horse in harness + light two-wheeled trap ------- */
.r5a-hide { fill: #8a5a36; }
.r5a-hleg { fill: none; stroke: #8a5a36; stroke-width: 5; stroke-linecap: round; }
/* hooves are the visible contact with the road, so they are drawn last and dark */
.r5a-hoof { fill: none; stroke: #2b2018; stroke-width: 5.4; }
.r5a-hmane { fill: none; stroke: #4a3220; stroke-width: 3.4; stroke-linecap: round; }
.r5a-heye { fill: #1a1f28; }
.r5a-harness { fill: none; stroke: #3a2a1c; stroke-width: 3; stroke-linecap: round; }
/* shafts run OVER the horse's flank, as they do in life — hidden behind the
   barrel they left the trap reading as a detached trailer */
.r5a-shaft { fill: none; stroke: #b98b52; stroke-width: 3; stroke-linecap: round; }
.r5a-rein { fill: none; stroke: #3a2a1c; stroke-width: 2.2; }
.r5a-cartbody { fill: #7d6039; }
.r5a-cartwheel { fill: none; stroke: #3d3428; stroke-width: 3.4; }
.r5a-cartwheel.far { stroke: #2c261d; stroke-width: 3; }
.r5a-cartspoke { fill: none; stroke: #6b5a41; stroke-width: 2; }
.r5a-carthub { fill: #3d3428; }
.r5a-driver { fill: #2f6fed; }
.r5a-driver-limb { fill: none; stroke: #2b3240; stroke-width: 3.2; stroke-linecap: round; }
.r5a-bush { fill: #3f7a4a; }
.r5a-bush-stem { fill: none; stroke: #5a4630; stroke-width: 3; }
:root[data-theme="dark"] .r5a-hide { fill: #9a6640; }
:root[data-theme="dark"] .r5a-bush { fill: #2c5138; }
/* the queue is stopped: a flowing centre line would say the street is moving */
[data-scene="l5QueueRailBox"] .sc-flow,
[data-scene="l5QueueRailBox"] .sc-flow line { animation: none; }
/* opacity only, on plain circles that carry NO transform attribute — a CSS
   transform there would fight the attribute and snap them to the origin */
.r5a-beacon { fill: #2b6df0; animation: r5a-beacon 1s steps(1) infinite; }
.r5a-beacon.b { animation-delay: .5s; }
@keyframes r5a-beacon { 0%, 49% { opacity: 1; } 50%, 100% { opacity: .16; } }
.r5a-amber { fill: #ffb020; animation: r5a-amber-blink 1s steps(1) infinite; }
@keyframes r5a-amber-blink { 0%, 49% { opacity: 1; } 50%, 100% { opacity: .14; } }

/* ==== BEGIN authored round-5 batch r5b ====================================
   Ten scenes: e5TunnelTwoWay, f5MirrorDazzle, f5WindGustOpen, s5PathSplit, v5BusStopDepart,
   v5EmergencySideRoad, v5MopedFromRight, v5RingExitZebra, v5StationExit, v5ZebraByJunction. All
   carry the `r5b` prefix so eight parallel authoring batches cannot collide. Reduced motion is
   handled once globally (`.scene *, .scene { animation: none !important }`). */

/* ---- e5TunnelTwoWay: a driver's-eye view of a two-way bore ---------------- */
/* The two lane markings are drawn as WEDGES, not strokes, because they run away
   from the viewer to a vanishing point — a constant-width line would read as a
   painted bar lying across the road. Yellow separates the opposing directions { fill: var(--lane); }

/* ---- f5MirrorDazzle: the interior mirror at night ------------------------- */
/* Same construction as `lr2MirrorView`'s interior mirror — stub mount at the top
   edge, housing, then the glass inset inside it — so the two cards read as the
   same object. The glass is a fixed near-black in BOTH themes: it is a night
   cabin reflection, not a surface that should follow the page. */
.r5b-mm-mount, .r5b-mm-frame { fill: var(--metal); }
.r5b-mm-glass { fill: #0d1119; }
/* The following car's body, just visible behind the lamps. Without it the two
   discs read as two blobs rather than as a vehicle; kept dark enough that it never
   competes with the glare. */
.r5b-mm-ghost { fill: #1e2634; }
.r5b-mm-halo { fill: rgba(255,250,222,.28); }
.r5b-mm-spike { fill: none; stroke: rgba(255,250,222,.55); stroke-width: 3; stroke-linecap: round; }
.r5b-mm-lamp { fill: #fffdf0; }
/* Wind streaks. They drift southwards and fade in AND out inside one cycle, so the
   loop restart is never visible, and they are confined to the two grass bands: a
   pale streak on the asphalt would read as a lane marking. The drift is a CSS
   transform on a wrapper <g> that carries no transform attribute. */
.r5b-gust path { fill: none; stroke: rgba(255,255,255,.6); stroke-width: 2.6; stroke-linecap: round; }
.r5b-gust {
  animation-name: r5b-gustdrift; animation-timing-function: ease-in-out;
  animation-iteration-count: infinite; opacity: 0;
}
@keyframes r5b-gustdrift {
  0% { transform: translateY(0); opacity: 0; }
  30% { opacity: .9; }
  70% { opacity: .55; }
  100% { transform: translateY(8px); opacity: 0; }
}
/* -- crosswind (f5WindLorryPass) ------------------------------------------- */
/* Streaks drift NORTHWARDS and fade at both ends of their travel, so the loop
   seam is never visible; the base opacity is high enough that a frozen frame
   (reduced motion, or a scene not yet scrolled into view) still shows wind. */
.r5c-gust { fill: rgba(255,255,255,.55); animation: r5c-blow 2.6s linear infinite; }
.r5c-gust.g2 { animation-delay: -.9s; }
.r5c-gust.g3 { animation-delay: -1.8s; }
@keyframes r5c-blow {
  0%   { opacity: 0; transform: translateY(16px); }
  22%  { opacity: .9; }
  78%  { opacity: .9; }
  100% { opacity: 0; transform: translateY(-16px); }
}

/* -- gatetun (v5GatetunExit) ------------------------------------------------ */
/* A pale block-paved surface laid OVER an `sc-asph` rect: the geometry checker
   only counts asphalt / cycle lane / snow road / track / zebra as drivable, so a
   car standing on this fill alone would be reported off-road. The joint grid is
   what makes it read as paving rather than as a lighter patch of road. */
.r5c-paving { fill: #ddd3c4; }
.r5c-pavejoint { fill: none; stroke: rgba(60,52,40,.22); stroke-width: 1.6; }
:root[data-theme="dark"] .r5c-paving { fill: #4a453d; }
:root[data-theme="dark"] .r5c-pavejoint { stroke: rgba(255,255,255,.12); }
.r5c-planter { fill: #a9764c; }
.r5c-leaf { fill: #4f9a55; }
.r5c-bench { fill: #b98f5e; }
.r5c-benchline { fill: none; stroke: rgba(40,28,14,.38); stroke-width: 1.6; }
.r5c-crown { fill: #4f9a55; }
.r5c-trunk { fill: #6b4c30; }
.r5c-ball { fill: #e8483f; }
:root[data-theme="dark"] .r5c-planter { fill: #7d5637; }
:root[data-theme="dark"] .r5c-bench { fill: #8a6942; }
:root[data-theme="dark"] .r5c-leaf,
:root[data-theme="dark"] .r5c-crown { fill: #3d7a45; }

/* No `[data-scene=…] .sc-wheel { animation: none }` overrides are needed in this batch: every scene is
   a plan view, `carTop` draws no wheels, and the two scenes with a waiting vehicle (v5GatetunExit,
   v5RingIndicatorRight) either put the waiting car on an unmarked mouth or draw their arm centre lines
   with `sc-mid` and no `sc-flow`.
   ==== END authored round-5 batch r5c ====================================== */

/* ---- r5d ---- */
/* ---- round-5 batch r5d (planovergang, vinterveg, tåke, vikeplikt) ---------- */
/* Everything here is prefixed `r5d-`; shared `sc-*` paint is reused wherever it
   fits (asphalt, grass, kerb, zebra, rails, snow road, wheel tracks, ring lane,
   officer uniform, unlit bulb, glass). */

/* --- f5CrossingNoBoom. The gap between the two rails needs a DARKER backing or
   the sleeper bars read as paint on a solid road surface rather than as timber in
   a recess. Mixed against --asph so it follows the theme instead of burning a
   fixed black slot into the light-mode card. */
.r5d-ballast { fill: color-mix(in srgb, var(--asph) 62%, #12151b); }
.r5d-sleeper rect { fill: color-mix(in srgb, #8a6f4c 78%, var(--asph)); }
/* The car is STOPPED. A spinning wheel and a flowing centre line both say
   "moving", and this card is about a vehicle that has come to a halt. */
[data-scene="g5FogBreakdown"] .sc-wheel,
[data-scene="g5FogBreakdown"] .sc-flow,
[data-scene="g5FogBreakdown"] .sc-flow line { animation: none; }

/* --- s5SnowStakes. The snowbank heaped along the verge: bright white with a cold
   rim, because white bank against white carriageway has no other separation. The
   snow whites are NOT re-tinted for dark mode — a winter road stays a winter road
   in both themes, the way .sc-snow-road does. */
.r5d-bank { fill: #fbfdff; stroke: rgba(120,142,170,.45); stroke-width: 2; }
/* The rig. ONE colour for both units: a pale trailer against a blue cab rendered as "a blue car parked
   beside a white slab" — two vehicles, and the apparent car stood exactly where both keyed answers
   forbid anyone to be. Tractor and trailer are the same lorry blue and the trailer is told apart by
   its lighter roof panel and ribs. Not .sc-bus-body green: a vogntog must not be mistaken for the bus
   in the kollektivfelt scenes.
   The dark running gear is what makes it a VEHICLE: as a plain box with two rib lines the trailer
   rendered as a sheet of paper lying on the roundabout. Wheel bars are inset inside the flanks so
   they add no width to the swept path. */
.r5d-rig { fill: #3f6189; stroke: rgba(0,0,0,.4); stroke-width: .9; }
:root[data-theme="dark"] .r5d-sleeper rect { fill: color-mix(in srgb, #b08a5c 70%, var(--asph)); }
/* The car ahead, seen through falling snow. Opacity on the wrapper <g> the car
   primitive's `cls` lands on, never on the node carrying the transform. */
.r5e-faint { opacity: .5; }
/* Snowfall. Own keyframe, not `sc-fall`: every flake is authored ABOVE the frame
   and travels further than the canvas is tall, so the loop seam happens
   off-canvas. Six phase offsets on top of six durations scatter them. */
.r5e-snow circle { fill: #fff; animation: r5e-snowfall 6.4s linear infinite; }
.r5e-snow .s1 { animation-duration: 5.6s; animation-delay: -.4s; }
.r5e-snow .s2 { animation-duration: 6.4s; animation-delay: -1.7s; }
.r5e-snow .s3 { animation-duration: 7.2s; animation-delay: -2.9s; }
.r5e-snow .s4 { animation-duration: 6s; animation-delay: -4.1s; }
.r5e-snow .s5 { animation-duration: 8s; animation-delay: -5.3s; }
.r5e-snow .s6 { animation-duration: 6.8s; animation-delay: -6.2s; }
@keyframes r5e-snowfall { to { transform: translate(22px, 250px); } }
/* This car is STOPPED. Every road scene inherits a spinning `.sc-wheel` and a
   flowing centre line, and both say "moving" — the one thing a broken-down car
   must not say. Same treatment as [data-scene="parkedDark"]. */
[data-scene="g5PunctureVerge"] .sc-wheel,
[data-scene="g5PunctureVerge"] .sc-flow,
[data-scene="g5PunctureVerge"] .sc-flow line { animation: none; }
/* Per card instead of per scene: a ledger `still: true` stops a shared scene for one stem ("du står stille i kø"). */
[data-still] .sc-wheel,
[data-still] .sc-flow,
[data-still] .sc-flow line { animation: none; }

/* ---- v5VanReverseBlind: the van and the zone behind it -------------------- */
/* A white panel van, so the rear third can be read as a DARKER solid panel: the
   missing window is the subject of the card and it has to be visible as an
   absence, which needs contrast against the rest of the body. */
.r5e-vanbody { fill: #e6eaf0; }
.r5e-vanrear { fill: #b9c1cd; }
.r5e-vanline { fill: none; stroke: rgba(0,0,0,.22); stroke-width: 2; }
.r5e-vantail { fill: #d81f3a; }
:root[data-theme="dark"] .r5e-vanbody { fill: #aeb7c3; }
:root[data-theme="dark"] .r5e-vanrear { fill: #79828f; }
/* The zone the mirrors do not cover. A tint plus RIBS across the wedge — not
   cross-hatching and not dashed rays, either of which could be misread as
   painted road marking or as a sight-line diagram. */
.r5e-blind polygon { fill: rgba(255,255,255,.09); }
.r5e-blind-rib path { fill: none; stroke: rgba(255,255,255,.17); stroke-width: 2.2; }
/* ==== END authored-2026-08-16 batch r5e ==== */

/* ---- r5f ---- */
/* ---- round-5 batch r5f -------------------------------------------------- */

/* f5DirtyScreenGlare — the windscreen from INSIDE. What lies BEYOND the pane is
   painted in the shared road tokens (sky over verge over asphalt), so the view
   through the glass follows the theme exactly the way a road scene does; only the
   film and the two dried wiper arcs sit ON the glass. */
.r5f-thru-sky { fill: var(--sky1); }
.r5f-thru-verge { fill: var(--hill); }
.r5f-thru-road { fill: var(--asph); }
.r5f-thru-line { fill: none; stroke: var(--lane); stroke-width: 3.4; }
/* Flat and unanimated on purpose: the shared .sc-sun pulses, and a pulsing sun
   behind a dirty screen would read as the glare the question asks about. */
.r5f-sun { fill: var(--sun); }
/* One EVEN veil over the whole pane. It must stay faint and uniform: a stronger
   wash would be the luminous slør that is the keyed answer, and a gradient would
   make the glass visibly darker in one place, which is a distractor. */
.r5f-film { fill: rgba(236,241,247,.13); }
/* Road-salt film gathering towards the edges — a wide soft stroke run along the
   pane's own outline, so it fades inwards from all four sides at once. No filters
   and no gradients are available here (no <defs>, ids would collide), so the
   fade is built from two strokes of different width and opacity. */
.r5f-film-edge { fill: none; stroke: rgba(232,238,245,.20); stroke-width: 24; }
.r5f-film-edge.thin { stroke: rgba(232,238,245,.26); stroke-width: 10; }
.r5f-dust { fill: rgba(232,238,245,.16); }
/* The two dried wiper arcs: broad, low-contrast smears. They are deliberately
   BROAD — thin bright lines would read as the scratches ("riper") that only one
   option names, and drawing that option's noun hands the answer over. */
.r5f-arc { fill: none; stroke: rgba(233,239,246,.34); stroke-width: 10; stroke-linecap: round; }
/* The car around the glass: A-pillars, roof rail, mirror and dashboard top. These
   are what fix the scale (the pane is car-sized between them) and what stop the
   trapezoid reading as a laptop screen, so in dark mode they are lifted well clear
   of the panel instead of sinking into it. */
.r5f-pillar, .r5f-rail, .r5f-dash { fill: #2b313b; }
.r5f-mirror { fill: #232830; }
.r5f-mirror-face { fill: #8f9aa8; }
:root[data-theme="dark"] .r5f-pillar,
:root[data-theme="dark"] .r5f-rail,
:root[data-theme="dark"] .r5f-dash { fill: #454c58; }
:root[data-theme="dark"] .r5f-mirror { fill: #363c47; }
/* Dark mode: everything ON the glass is a light translucent layer, and the view
   through it is now dark — at the light-theme opacities the pane turned into one
   bright grey slab, which is exactly the luminous veil the card must not draw.
   Every film layer is therefore roughly halved against a dark background. */
:root[data-theme="dark"] .r5f-film { fill: rgba(236,241,247,.07); }
:root[data-theme="dark"] .r5f-film-edge { stroke: rgba(232,238,245,.11); }
:root[data-theme="dark"] .r5f-film-edge.thin { stroke: rgba(232,238,245,.15); }
:root[data-theme="dark"] .r5f-dust { fill: rgba(232,238,245,.09); }
:root[data-theme="dark"] .r5f-arc { stroke: rgba(233,239,246,.20); }

/* g5WhiteCane: the cane itself. White over a dark edging stroke, because plain
   white on the light .sc-footway band disappears; the band near the tip is the
   red collar a Norwegian white cane carries. */
.r5h-cane-edge { fill: none; stroke: #454c58; stroke-width: 5.4; stroke-linecap: round; }
.r5h-cane { fill: none; stroke: #ffffff; stroke-width: 3.2; stroke-linecap: round; }
.r5h-cane-band { fill: none; stroke: #d81f3a; stroke-width: 3.2; stroke-linecap: butt; }

/* g5DeerGone's car is STOPPED at the roadside after the collision. Every road
   scene inherits a spinning `.sc-wheel` and a flowing centre line, and both say
   "moving" — the one thing this card must not say. Same treatment as
   [data-scene="parkedDark"]. */
[data-scene="g5DeerGone"] .sc-wheel,
[data-scene="g5DeerGone"] .sc-flow,
[data-scene="g5DeerGone"] .sc-flow line { animation: none; }
:root[data-theme="dark"] .r5h-cane-edge { stroke: #23272e; }
/* ==== END authored-2026-08-16 batch r5h ==== */

/* ==== BEGIN authored-2026-08-16 batch r5i ====
   Eight scenes, all STATIC — nothing here defines a keyframe. Everything reuses a shared class where
   one fits (sc-asph, sc-grass, sc-kerb, sc-footway, sc-rails, sc-post, sc-skin, sc-tail, sc-edge,
   sc-mid, sc-white-line, kv-exhaust, ot-trunk); the classes below are only the ones nothing shared
   covers, or the two places where the shared paint measurably failed to read. */

/* g5BusStopFront: the doors on the bus's kerb side. Light on the fixed green
   `.sc-bus-body`, so it needs no theme nudge — but it must stay a plain flank
   rectangle: anything round or amber here would read as the hazard light the
   scene deliberately does not show. */
.r5i-door { fill: #e7eef5; opacity: .92; }

/* h5ArmOneSide. The shared `.sc-officer .sc-arm-signal` is navy (#20385f) on navy asphalt (#444b5a)
   and the extended arm all but disappeared on the rendered card — and that arm is the entire subject
   here. So the arms are a white sleeve laid over a dark halo: two paths, the dark one first and wider,
   which reads at card size against asphalt in both themes. The halo also keeps the arm off the yellow
   centre line it runs beside. */
.r5i-armdark { fill: none; stroke: #101a2e; stroke-width: 15; stroke-linecap: round; }
.r5i-arm { fill: none; stroke: #f2f6fb; stroke-width: 9; stroke-linecap: round; }
/* the resting left arm. Same sleeve so it reads as an arm, but drawn a third of
   the length and tucked down the side of the body — an arm hanging at the side is
   almost entirely foreshortened from above, and at full length it read as a second
   arm held out, which is the one statement this card may not make. */
.r5i-arm.short { stroke-width: 7; }
/* the shoulders, in the shared uniform navy but outlined so the body does not
   melt into the asphalt the way the generic officer's does, with a hi-vis band
   across them: the torso has to read as a torso at 34 units across. */
.r5i-uniform { fill: #20385f; stroke: #e8eef6; stroke-width: 2; }
.r5i-hivis { fill: none; stroke: #f1cf20; stroke-width: 4; stroke-linecap: round; }
/* the head, and the shaded BACK half of it. Seen from above the back half and the
   skin nose wedge over it are the only things that say which way the officer faces
   — and the sign is read from the body, not from where the arm points. The back
   half is HAIR brown, not the uniform navy it used to be: navy on navy shoulders
   merged the two and the head rendered as a half-moon floating on the torso. The
   head carries a light rim for the same reason. */
.r5i-head { fill: #f0b48a; stroke: #f2f6fb; stroke-width: 1.6; }
.r5i-headback { fill: #6b452c; }
/* nothing moves in this scene — no vehicle at all — so the inherited flowing
   centre line would be the only motion on the card, saying "traffic is running"
   in a junction the officer is regulating. */
[data-scene="h5ArmOneSide"] .sc-flow,
[data-scene="h5ArmOneSide"] .sc-flow line { animation: none; }

/* The ONLY animation in this batch: the forearm and the lantern swinging about
   the elbow. `transform-box: fill-box` with a 100%/100% origin puts the pivot on
   the elbow, which is the wrapper's bottom-right bbox corner — and unlike a
   view-box origin it stays correct inside the `mirror: true` flip. The wrapper
   carries no transform attribute of its own, which is the trap this file warns
   about. Symmetric ±14°, returning to where it started, so there is no seam on
   the loop restart. */
.r5j-swing {
  transform-box: fill-box; transform-origin: 100% 100%;
  animation: r5j-wave 2s ease-in-out infinite;
}
@keyframes r5j-wave {
  0%, 100% { transform: rotate(-14deg); }
  50% { transform: rotate(14deg); }
}

/* h5KerbDropOff — the town facade behind the footway. Drawn against the sky, so
   all three need a dark-mode nudge the way `.lr-plank` and `.sp-cable` do. */
.r5j-wall { fill: #c3ccd8; stroke: rgba(16, 24, 40, .22); stroke-width: 1.6; }
.r5j-win { fill: #7fb0dc; stroke: rgba(16, 24, 40, .25); stroke-width: 1.4; }
.r5j-door { fill: #6a5340; stroke: rgba(16, 24, 40, .3); stroke-width: 1.4; }

/* The person on the footway is STANDING. `ped` animates its limbs, and a walking
   figure beside a kerb reads as someone stepping out into the road — which is the
   one thing this card must not show. The car keeps its rolling wheels: it is
   driving past, not parked. */
[data-scene="h5KerbDropOff"] .sc-ped .sc-limb { animation: none; }

:root[data-theme="dark"] .r5j-wall { fill: #4a5364; stroke: rgba(0, 0, 0, .45); }
:root[data-theme="dark"] .r5j-win { fill: #2b4b6b; }
:root[data-theme="dark"] .r5j-door { fill: #4a3a2c; }
/* Contact shadow, always drawn AFTER the object it belongs to: a load whose
   feet are covered floats, which is fault 1 in the docs' legibility list. */
.r5k-contact { fill: rgba(10,15,25,.30); }
/* Dark instrument-cluster surround, used cropped by the frame edge in
   `k5EcoColdGauge` and `k5EcoCruiseSet` so it reads as a fragment of a car and
   not as a second panel. Same near-black as `.kv-panel`, kept as its own class
   so the two can never drift apart by accident. */
.r5k-cluster { fill: #22262e; stroke: color-mix(in srgb, var(--metal) 55%, transparent); stroke-width: 2; }

/* ---- k5FocusHandsFree: both hands on the rim, phone in a cradle ----------- */
/* The windscreen band. Its own sky/grass rather than the shared road tokens,
   because this is a small inset seen through glass, not the scene's own sky. */
.r5k-wind-sky { fill: #bcdff6; }
.r5k-wind-grass { fill: #86c98a; }
.r5k-wind-road { fill: #4a5162; }
.r5k-wind-mid { fill: var(--lane); }
.r5k-wind-edge { fill: #f4f7fb; }
.r5k-wind-frame { fill: none; stroke: #2b303a; stroke-width: 4; }
/* Dash and wheel seen from the driver's seat. Heavier than `.sc-wheel-ring`
   because this rim is 190 units across and carries two hands. */
.r5k-dash { fill: #2b303a; }
.r5k-rim { fill: none; stroke: #14181f; stroke-width: 13; }
.r5k-spoke { stroke: #14181f; stroke-width: 11; stroke-linecap: round; fill: none; }
.r5k-hub { fill: #14181f; }
/* Same skin paint as `.ph-skin` in `phoneHand`, so a hand is a hand across the
   bank; kept as its own class because that card's hand is off the rim and this
   one is on it. */
.r5k-skin { fill: #f0b48a; stroke: #c4835c; stroke-width: 1.6; stroke-linejoin: round; }
/* Forearm running off the bottom edge. Same weight as `.ph-arm` in `phoneHand`:
   without it the hand is a floating fist with a raised thumb, i.e. a thumbs-up. */
.r5k-arm { fill: none; stroke: #f0b48a; stroke-width: 19; stroke-linecap: round; }
/* The phone: a third of the wheel's diameter, which is real scale. */
.r5k-phone { fill: #22262e; stroke: color-mix(in srgb, var(--muted) 40%, transparent); stroke-width: 2; }
.r5k-screen { fill: #eef2f7; }
.r5k-namebar { fill: #b6c0cc; }
.r5k-endcall { fill: #d81f3a; }
/* Cradle arm, jaws and foot, inked dark so the phone visibly rests on something. */
.r5k-cradle { fill: #3b414c; }
.r5k-glyph { fill: none; stroke: #e4e9ef; stroke-width: 2.4; stroke-linecap: round; stroke-linejoin: round; }

/* ---- k5EcoCruiseSet: the left wheel spoke and its pad --------------------- */
/* The rim entering from the lower-left corner. Same ink as `.r5k-rim`, its own
   class because this one is an arc that leaves the frame on both ends. */
.r5k-rim2 { fill: none; stroke: #14181f; stroke-width: 14; stroke-linecap: round; }
.r5k-spokebar { fill: #1d222b; }
.r5k-pad { fill: #2b303a; stroke: rgba(255,255,255,.10); stroke-width: 2; }
.r5k-btnr { fill: #3b414c; stroke: rgba(255,255,255,.12); stroke-width: 1.5; }
.r5k-rocker { fill: #3b414c; stroke: rgba(255,255,255,.12); stroke-width: 1.5; }
.r5k-key-txt { fill: #e4e9ef; font: 800 14px var(--font); letter-spacing: .04em; }
/* Green cruise telltale: dial and needle, lit. */
.r5k-lamp-halo { fill: rgba(40,190,110,.20); }
.r5k-lamp-ring { fill: none; stroke: #28be6e; stroke-width: 3.2; }
.r5k-lamp-ink { fill: none; stroke: #28be6e; stroke-width: 3; stroke-linecap: round; }
.r5k-lamp-dot { fill: #28be6e; }

/* ---- k5ChainsBareRoad: chains on a dry carriageway ------------------------ */
/* Just enough bodywork above the wheel to set the scale: a sill band with the
   arch bitten out of it. */
.r5k-body { fill: #2f6fed; }
.r5k-arch { fill: none; stroke: #1e4fae; stroke-width: 5; }
.r5k-sill { fill: none; stroke: rgba(0,0,0,.30); stroke-width: 5; }
/* A swage crease and one door shut-line. A plain colour field across the top of
   the frame reads as a band of sky; two panel lines make it bodywork. */
.r5k-crease { fill: none; stroke: rgba(255,255,255,.22); stroke-width: 3; }
.r5k-shut { fill: none; stroke: rgba(0,0,0,.28); stroke-width: 2.6; }
/* Bare, dry, unbroken asphalt with a fine speckle. No gouge, no scratch, no
   damage mark anywhere: the wear claim is one of the four options. */
.r5k-bare { fill: #3a3f47; }
.r5k-speck circle { fill: rgba(255,255,255,.10); }
.r5k-tyre { fill: #1d2229; }
.r5k-sidewall { fill: #262c34; }
.r5k-hubcap { fill: #9aa4b2; }
.r5k-hubspoke { fill: none; stroke: #6f7784; stroke-width: 3; }
.r5k-nut { fill: #6f7784; }
/* The chain. Side rings just inside the tyre's outer circumference and radial
   cross-links between them: drawn across the wheel DISC it would read as a wire
   wheel. The highlight is a second, thinner pass so a link reads as steel. */
.r5k-chain-ring { fill: none; stroke: #7c8590; stroke-width: 3.4; }
.r5k-chain-link { fill: none; stroke: #4d545e; stroke-width: 7; stroke-linecap: round; }
.r5k-chain-hi { fill: none; stroke: #aeb7c3; stroke-width: 2.4; stroke-linecap: round; }
/* Packed snow banked on the verge only — the running surface stays bare. The
   foot line is what makes it sit ON the asphalt instead of hovering: white on a
   pale studio panel has almost no edge of its own. */
.r5k-snow { fill: #f4f9fe; stroke: #b9cbdb; stroke-width: 2; }
.r5k-snow-sh { fill: none; stroke: #c3d4e2; stroke-width: 3; }
.r5k-snow-foot { fill: none; stroke: rgba(10,15,25,.35); stroke-width: 3; }
/* ONE brief pulse per loop, matching the stem's "blinking med fjernlys en gang".
   Opacity only: nothing moves, so the loop seam cannot be seen and no vehicle
   can teleport. */
.r5k-flash { animation: r5k-flash 1.8s ease-in-out infinite; }
@keyframes r5k-flash {
  0%, 56% { opacity: 0; }
  62%, 72% { opacity: .95; }
  80%, 100% { opacity: 0; }
}
:root[data-theme="dark"] .r5k-wind-sky { fill: #21354b; }
:root[data-theme="dark"] .r5k-wind-grass { fill: #33553a; }
:root[data-theme="dark"] .r5k-snow { fill: #cfdae5; }
:root[data-theme="dark"] .r5k-snow-sh { stroke: #9fb3c4; }
/* ==== END authored round-5 batch r5k ====================================== */
/* ==== END authored-2026-08-17 ==== */
/* ==========================================================================
   Round-6 batch r6va (`kjoretoyet`): the spare wheel, the handbrake console, an exhaust plume, the
   rear lamp clusters, the front-corner fog lamp and the hazard switch. Every class is prefixed r6va-
   so it cannot collide with the sc- primitives or the kv-/vh-/anc-/r5k- sets. Interior plastics are
   fixed dark greys with a light stroke — the same contract as .kv-panel / .vh-panel / .anc-console —
   so they separate from the studio wash in dark mode without an override.
   ========================================================================== */

/* ---- r6vSpareWheel: two wheels drawn as three-quarter cylinders ------------ */
/* The CROWN is one tone across both the barrel rect and the far ellipse, so the
   single curved surface has no seam down the middle of it; it is deliberately
   LIGHTER than the face, because the crown is the width the card is about and the
   lightest shape in the wheel is the one the eye measures. The far ellipse adds a
   dark stroke, which survives only on the back shoulder (everything else is
   overpainted) and is what shades the surface away from the viewer. */
.r6va-tyre-crown { fill: #303743; }
.r6va-tyre-crown.far { stroke: rgba(0,0,0,.5); stroke-width: 3; }
.r6va-tyre-face { fill: #191d24; stroke: rgba(255,255,255,.16); stroke-width: 1.6; }
/* Lateral tread grooves across the crown: identical count, spacing and weight on
   both wheels, so the picture states the WIDTH and says nothing about wear. Darker
   than the crown they are cut into — a groove lighter than its surface is a rib. */
.r6va-tread { fill: none; stroke: #14181e; stroke-width: 2.6; stroke-linecap: round; }
/* The sidewall ring inside the tread shoulder: without its own tone the shoulder
   band merges into the face and the wheel flattens out again. */
.r6va-sidewall { fill: #2a3038; stroke: rgba(0,0,0,.45); stroke-width: 1.6; }
/* Alloy road wheel (wide bright face over its own rim flange) vs the spare's small
   flat STEEL disc: together with the 62-against-22 crown this is what says
   "nødhjul". Fixed metal greys on black rubber, so no dark-mode nudge (as .sc-rim). */
.r6va-rimlip { fill: #7d8794; stroke: rgba(0,0,0,.30); stroke-width: 1.4; }
.r6va-alloy { fill: #cbd3dd; stroke: rgba(0,0,0,.30); stroke-width: 2; }
.r6va-steel { fill: #dfe4ea; stroke: rgba(0,0,0,.28); stroke-width: 2; }
.r6va-hub { fill: #aeb7c3; stroke: rgba(0,0,0,.28); stroke-width: 1.6; }
.r6va-nut { fill: #8d959f; }
/* The vent holes ARE holes, so they are darker than the disc they are cut into —
   painted in the disc tone they read as printed dots. */
.r6va-vent { fill: #4d535b; }
/* Contact shadow, drawn last and overlapping the rubber so neither wheel floats.
   In dark mode a .42 black over the dark studio wash still reads as darker. */
.r6va-contact { fill: rgba(10,15,25,.42); }

/* ---- r6vHandbrakeLever: the centre console -------------------------------- */
/* Three planes in three tones — one flat rectangle read as a slab and turned the
   lever on it into a blade. Lightest on top (facing the light), the front face mid,
   the side face away from the light darkest; the top and side carry the light stroke
   that inks the folds between the planes. */
.r6va-console { fill: #2b313b; stroke: color-mix(in srgb, var(--metal) 55%, transparent); stroke-width: 2; }
.r6va-console-top { fill: #3d4655; stroke: color-mix(in srgb, var(--metal) 45%, transparent); stroke-width: 1.6; }
.r6va-console-side { fill: #22272f; stroke: color-mix(in srgb, var(--metal) 45%, transparent); stroke-width: 1.6; }
.r6va-console-seam { fill: none; stroke: rgba(255,255,255,.12); stroke-width: 2; }
/* The gaiter the lever pivots out of, sunk in the top surface: black rubber ring
   with a light stroke against the console, and a near-black hole inside it — the
   darker backing a recess needs, or the opening reads as a painted oval. */
.r6va-boot { fill: #191e25; stroke: rgba(255,255,255,.16); stroke-width: 1.8; }
.r6va-slot { fill: #0d1015; }
/* Shaft and grip are both drawn over a dark casing pass, so a metal bar and a dark
   plastic handle each keep an edge against the console AND the studio wash. The
   grip is 36 units against the shaft's 19: at 15-against-13 it read as one bar. */
.r6va-shaft-case, .r6va-grip-case { fill: #171b21; }
.r6va-shaft { fill: var(--metal); }
.r6va-grip { fill: #333b47; stroke: rgba(255,255,255,.14); stroke-width: 1.6; }
.r6va-grip-rib { fill: none; stroke: rgba(255,255,255,.30); stroke-width: 2.2; stroke-linecap: round; }
/* The end FACE of the grip, lighter than the handle, with the release button on it. */
.r6va-grip-end { fill: #4a5462; stroke: rgba(0,0,0,.35); stroke-width: 1.6; }
.r6va-release { fill: #c8d0da; stroke: rgba(0,0,0,.35); stroke-width: 1.8; }

/* ---- r6vSmokePlume: dense exhaust off a moving car ------------------------ */
/* A mid grey at full opacity with a PALE OUTLINE on every ellipse. The outline,
   not the lightness, is what separates the plume from `.sc-hill` (which is a light
   green in light mode): a grey light enough to beat the hill on luminance would be
   lighter than the translucent `.kv-fumes` puffs of `idleExhaust`, and this plume
   has to read as denser than those, not thinner. */
.r6va-plume ellipse { fill: #7d8591; stroke: none; }
/* Darker core on the two nearest the tailpipe: the plume is dense at its source. */
.r6va-plume .core { fill: #5f6773; stroke: none; }
/* Opacity steps down along the run so the far end dissolves instead of being cut. */
.r6va-plume .p1 { opacity: .95; }
.r6va-plume .p2 { opacity: .88; }
.r6va-plume .p3 { opacity: .78; }
.r6va-plume .p4 { opacity: .66; }
/* Drift in NEGATIVE authored x — the scene is mirrored, so that is rearward on
   screen. `alternate` means there is no loop seam at all, so nothing can teleport;
   the class sits on a plain <g> that carries no transform attribute. */
.r6va-plume { animation: r6va-plume 5s ease-in-out infinite alternate; }
@keyframes r6va-plume {
  from { transform: translateX(0); opacity: 1; }
  to   { transform: translateX(-7px); opacity: .78; }
}

/* ---- r6vFogLampFront: the front corner in close-up ----------------------- */
/* Bodywork in the shared car tone. Deliberately NOT `.sc-car .sc-shell`: this is a
   studio panel, and the geometry checker measures anything wearing `.sc-car`.
   The three body planes are all MIXED OFF the same token, so a corner reads as one
   painted body under one light and still follows the theme: the nose panel is the
   token, the bonnet's top surface is lifted towards white, the side plane (turned
   away from the light) is knocked back towards black. */
.r6va-body { fill: var(--carA); stroke: rgba(0,0,0,.28); stroke-width: 2; }
.r6va-bonnet { fill: color-mix(in srgb, var(--carA) 82%, #ffffff); }
.r6va-side { fill: color-mix(in srgb, var(--carA) 72%, #000000); }
/* The bonnet's LEADING EDGE: the shut line between the top surface and the nose,
   re-inked pale, because a fill boundary between two mixes of one token is too
   soft to read at card scale and the top surface is the whole perspective cue. */
.r6va-bonnet-edge { fill: none; stroke: rgba(255,255,255,.42); stroke-width: 2.2; }
/* Wheel arch at the outboard lower corner: the tyre shows through a notch cut in
   the side plane, and the lip is inked in a lifted body tone — a dark tyre against
   a dark side plane has no visible edge otherwise (fault 1's contact rule). */
.r6va-tyre { fill: #1a1e25; }
.r6va-tyre-shoulder { fill: none; stroke: #333a44; stroke-width: 7; stroke-linecap: round; }
.r6va-arch { fill: none; stroke: color-mix(in srgb, var(--carA) 86%, #ffffff);
  stroke-width: 4.5; stroke-linecap: round; }
/* The grille, inboard of the headlamp: near-black recess with light slats. Slats
   painted over a body-coloured panel read as stripes, so the recess comes first. */
.r6va-grille { fill: #14181e; stroke: rgba(0,0,0,.35); stroke-width: 1.6; }
.r6va-slat { fill: #3c434e; }
/* The bumper is a separate BODY PART, not a shaded region of the panel above it:
   its own plastic tone (the body token knocked towards neutral grey, which is what
   an unpainted or contrast-painted bumper looks like) plus a real panel gap — a
   dark shut line with a pale highlight under it. 22 % black on the same shape was
   read as "a slightly darker red", i.e. as nothing. */
.r6va-bumper { fill: color-mix(in srgb, var(--carA) 62%, #2c3138); }
.r6va-shut { fill: none; stroke: rgba(0,0,0,.55); stroke-width: 2.6; }
.r6va-shut-hi { fill: none; stroke: rgba(255,255,255,.22); stroke-width: 1.4; }
.r6va-hl-housing { fill: #2b313b; stroke: rgba(255,255,255,.18); stroke-width: 2; }
.r6va-hl-lens { fill: var(--glass); stroke: rgba(0,0,0,.25); stroke-width: 1.6; }
.r6va-hl-refl { fill: #f2f8fe; stroke: rgba(0,0,0,.22); stroke-width: 1.4; }
/* The recess ring behind the fog lens. Drawn first and much darker: a circle laid
   straight on a bumper reads as a sticker, not as a lamp sunk into it. */
.r6va-fog-recess { fill: #14181e; }
.r6va-fog-lens { fill: var(--glass); stroke: rgba(0,0,0,.30); stroke-width: 1.8; }

/* ---- r6vHazardSwitch: the middle of the fascia ---------------------------- */
.r6va-dash { fill: #22262e; stroke: color-mix(in srgb, var(--metal) 55%, transparent); stroke-width: 2; }
.r6va-dash-seam { fill: rgba(255,255,255,.16); }
/* Raised button: lighter than the fascia, with a dark bezel around it. */
.r6va-hazbtn { fill: #4a515e; stroke: rgba(0,0,0,.50); stroke-width: 2.4; }
/* The moulded triangle is a SWITCH ICON, not a sign: its own class, never
   `.sc-warn` or `.sc-sign-face`, and hollow so it does not fill in at card scale. */
.r6va-haztri { fill: none; stroke: #e0342c; stroke-width: 4; stroke-linejoin: round; }
.r6va-knob { fill: #3b424e; stroke: #9aa4b2; stroke-width: 2; }
.r6va-knob-mark { fill: none; stroke: #cfd6de; stroke-width: 2.4; stroke-linecap: round; }
.r6va-blankbtn { fill: #3b424e; stroke: rgba(255,255,255,.14); stroke-width: 1.6; }

/* ---- dark mode ----------------------------------------------------------- */
/* Theme tokens and real object colours (rubber, steel, tail-light red, clear
   lens) look after themselves; only the contact shadow needs a nudge, because a
   .42 black over the dark studio wash barely separates from it. */
:root[data-theme="dark"] .r6va-contact { fill: rgba(0,0,0,.55); }
/* RENDER REVIEW FIX (dark mode). `r6vHazardSwitch`'s fascia is a dark plastic (#22262e) chosen against
   the LIGHT studio wash. On the dark wash it collapsed into the background and the card read as an
   empty outlined box with a red triangle floating in it. Real object colour is no defence here: a dark
   dash on a dark ground has no contrast whichever way you paint it, so the whole cluster is lifted a
   few steps in dark mode (fascia, knobs, buttons, seam) while keeping their relative order, which is
   what carries "one panel, several controls". The hazard triangle's red is untouched. */
:root[data-theme="dark"] .r6va-dash { fill: #3a414d; stroke: color-mix(in srgb, var(--metal) 75%, transparent); }
:root[data-theme="dark"] .r6va-dash-seam { fill: rgba(255,255,255,.24); }
:root[data-theme="dark"] .r6va-hazbtn { fill: #626a78; }
:root[data-theme="dark"] .r6va-knob { fill: #545c69; stroke: #b6bfcb; }
:root[data-theme="dark"] .r6va-blankbtn { fill: #545c69; stroke: rgba(255,255,255,.22); }
/* ==== END authored round-6 batch r6va ===================================== */
/* ==== authored round-6 batch r6vb ========================================== */
/* r6wStuddedTread — a macro of the tread's running surface. The rubber tones are
   the same family as `vh-rubber`/`vh-shoulder` so the two tyre close-ups read as
   one subject; the groove is near-black rather than "a bit darker", because a
   recess without a darker backing reads as a painted line (docs fault 4), and the
   lip beside it is the only light edge in the band so the recess has a rim. */
.r6vb-band { fill: #23282f; stroke: color-mix(in srgb, var(--muted) 40%, transparent); stroke-width: 2; }
.r6vb-shoulder { fill: #171b21; }
.r6vb-groove { fill: #05080b; }
.r6vb-lip { fill: #3c444e; }
/* The seating ring is the same near-black as the groove, not "a bit darker than the
   rubber": at #0d1014 the ring was there in the geometry and invisible on the
   rendered card, so the pin read as a pale dot printed on the tread. */
.r6vb-seat { fill: #06090c; }
/* dome the head: a white sheen on its upper left, a shadow arc on its lower right.
   A flat light disc reads as a sticker, not as a metal pin. */
.r6vb-stud { fill: color-mix(in srgb, var(--metal) 40%, #f4f8fc); }
.r6vb-stud-hi { fill: none; stroke: rgba(255,255,255,.8); stroke-width: 3; stroke-linecap: round; }
.r6vb-stud-sh { fill: none; stroke: rgba(10,15,25,.35); stroke-width: 3; stroke-linecap: round; }

/* ---- dark mode ---- */
:root[data-theme="dark"] .r6vb-band { fill: #333a43; }
:root[data-theme="dark"] .r6vb-shoulder { fill: #262c34; }
:root[data-theme="dark"] .r6vb-groove { fill: #0f1318; }
:root[data-theme="dark"] .r6vb-lip { fill: #545e6a; }
:root[data-theme="dark"] .r6vb-seat { fill: #0f1318; }

/* r7aArm — a signalling arm seen from above. Two coloured strokes rather than one, because a single
   uniform limb out of a car window reads as an aerial or a wiper: the sleeve is clothing blue (the
   same #5b9ce8 `.ana-body` uses, so the arm belongs to the same population of drawn people) and the
   forearm is bare skin, and the colour break at the elbow is what makes the shape read as a human arm
   at card scale. The forearm is deliberately NARROWER than the sleeve so the limb tapers outward; the
   palm disc terminating it is `.r5d-palm` (r = 4.6, skin), twice the forearm's width, which keeps the
   hand visible as a hand. Round caps, so sleeve and forearm meet with no notch at the elbow.
   The CASING under both is not decoration. An arm must start inside the vehicle it comes out of, and
   `.r7a-sleeve`'s blue is within a few percent of the tone 'b' `carTop` these drivers sit in — the
   first render of s7fWaveAtZebra and s7fWaveAtYield lost the shoulder entirely into the bodywork. A
   dark stroke 2.4 units wider than the sleeve, and a dark disc 1.4 units wider than the palm, separate
   the limb from ANY body colour without a per-tone rule. */
.r7a-limb-case { fill: none; stroke: #1b2029; stroke-width: 7.8; stroke-linecap: round; }
/* The running surface: one continuous grade line that runs flat at the wheel line,
   lifts over the hump and comes back down. This is what says "the ROAD rises here"
   rather than "an object sits here". Deliberately a grey mixed off --asph and not
   white: at white it became a third horizontal line beside `sc-edge` and `sc-mid` and
   read as lane paint. It is also cut short of both frame edges for the same reason. */
.r7d-surface { fill: none; stroke: color-mix(in srgb, var(--asph) 48%, #e9edf3); stroke-width: 2.4; stroke-linejoin: round; stroke-linecap: round; }
:root[data-theme="dark"] .r7d-surface { stroke: color-mix(in srgb, var(--asph) 34%, #e9edf3); }

/* ---- s7kHillPark: facade seams ------------------------------------------- */
/* The party wall between two shop fronts. Without it a 520-unit `.r5j-wall`
   band is one enormous building and the street stops reading as a street; with
   it the frontage is four (daylight) or three (night) premises. Dark and thin —
   a wide or pale line would read as a pillar rather than as a joint. */
.r7b-seam { fill: none; stroke: rgba(16, 24, 40, .34); stroke-width: 2; }
/* Night variant, kept for the next night scene that needs it: seams drawn OVER `.sc-night`
   (a dark line under a 62 % wash is invisible), so they invert: a low-alpha cool
   white, which is what the edge of a lit shop front actually looks like at
   night. Kept under .3 alpha — brighter and it competes with the signage, which
   is the subject. */
.r7b-seam.night { stroke: rgba(226, 236, 248, .26); }

/* ---- s7v2BusStopZone: the datum line tying the bracket to the sign ----
   The 20 m bracket's east tick has to land on the 512 plate or the picture measures 20 m from nothing.
   Colour and width come from the bracket's own `.sc-measure path` / `.sc-mline` rule, deliberately NOT
   from `.sc-stopline` or `.sc-white-line`: a solid 4-unit white bar drawn across a carriageway is a
   stop line, and this card must not paint a marking. This class adds only the dash, which is what
   separates a dimension leader from a road marking; it is NOT `.sc-mspan`, so it never animates. */
.r7b-datum { stroke-dasharray: 4 3.5; opacity: .8; }

/* ---- scenes whose vehicle is STOPPED ----
   Every road scene inherits a spinning `.sc-wheel` and a flowing centre line, and both say "moving" —
   exactly what these two cards must not say. `s7kHillPark` is a car PARKED on a gradient, and a
   spinning wheel would state the opposite of the premise. `s7v2BusStopZone` is a car STANDING at the
   kerb inside the bus-stop zone; its `roadPlan()` divider would otherwise stream past a stationary
   vehicle. Scoped per scene, and the bracket's own `.sc-mspan` is a different class, so the 20 m
   dimension still draws itself in. `s7kHillPark` needs no `.sc-flow` rule: it has no centre line. */
[data-scene="s7kHillPark"] .sc-wheel { animation: none; }
[data-scene="s7v2BusStopZone"] .sc-flow,
[data-scene="s7v2BusStopZone"] .sc-flow line { animation: none; }

:root[data-theme="dark"] .r7b-seam { stroke: rgba(0, 0, 0, .45); }
/* ==== END r7b ============================================================= */

/* ==== r8t: round-8 batch F — lights/redFarBack, gas tank, first rain ======== */

/* `lights` variant 'redFarBack'. A STEADY red aspect, deliberately NOT `.sc-bulb.r`,
   which runs the shared 6 s phase cycle — on a card whose stem says the light IS red,
   a head that cycled to green would contradict the stem two seconds in. Same reasoning
   `v5ZebraAmberFlash` and `.r5d-red` already record. Both lens colours are literal, not
   theme-mixed, because they sit on `.sc-lightbox` (#22262e), which is the same dark
   housing in both themes — mixing them against a theme token would make the unlit
   lenses vanish in dark mode. */
.r8t-lens-red { fill: #e8262f; }
.r8t-lens-off { fill: #4a505c; }

/* --- r8kGasTank. Three compartment planes, and the FLOOR is the darkest of them. That inversion is
   deliberate: a pale metal barrel on a pale floor merges into it, and the barrel's silhouette is the
   whole picture. Mixed against `--surface-2`, the studio panel's own ground, so all three track the
   theme.
   NOTE, because it cost a render cycle: there is no `--panel` token. An undefined token makes the
   whole `color-mix()` invalid, and an invalid `fill` falls back to BLACK — the first version rendered
   as one solid black slab with the tank floating on it, and the geometry gate saw nothing wrong. Only
   mix against tokens that exist: --surface, --surface-2, --brand, --blue, --text, --muted, --border. */
.r8t-seatback { fill: color-mix(in srgb, var(--surface-2) 40%, #6a7480); }
.r8t-bootwall { fill: color-mix(in srgb, var(--surface-2) 28%, #4a535e); }
.r8t-bootfloor { fill: color-mix(in srgb, var(--surface-2) 16%, #2f3742); }
/* The rear head restraints and the split between the two seat halves. These are the
   ONLY cues that the compartment belongs to a car: without them the scene read as a
   pressure cylinder in a shed. Darker than the seat back so they read as objects in
   front of it rather than as a notch cut out of it. */
.r8t-headrest { fill: color-mix(in srgb, var(--surface-2) 22%, #5a636e); }
.r8t-seatsplit { stroke: color-mix(in srgb, var(--surface-2) 10%, #3d4550); stroke-width: 2.5; fill: none; }
/* One crease across the floor. Enough to say "moulded boot liner", not a carpet
   texture — texture at this zoom reads as dirt. */
.r8t-floorcrease { stroke: rgba(255, 255, 255, .10); stroke-width: 3; fill: none; }

/* The cylinder: one pale tone for the barrel, with a lighter band along the top and a
   darker one along the underside, which is what makes a flat rect read as ROUND. The
   end face is a shade darker again so the barrel reads as receding rather than as a
   capsule seen flat on. */
.r8t-tank { fill: #b9c2cc; }
.r8t-tank-sheen { fill: #dfe6ee; }
.r8t-tank-under { fill: #8d97a3; }
.r8t-tank-end { fill: #9aa4b0; }
/* The contact shadow where the barrel rests on the floor, drawn AFTER the barrel so
   nothing covers it (docs fault 1: where one object rests on another the contact must
   be visible). Not a tone of the floor — a shadow has to be darker than both. */
.r8t-tank-cast { fill: rgba(0, 0, 0, .34); }
.r8t-valve { fill: #5b6570; }
.r8t-pipe { stroke: #5b6570; stroke-width: 6; fill: none; stroke-linecap: round; }
/* The two hold-down straps, drawn over the barrel, and their floor brackets drawn LAST.
   The brackets are near-black on purpose: they are the only thing proving the strap
   reaches the floor instead of stopping on the tank's face. */
.r8t-strap { fill: #6f7a86; }
.r8t-bracket rect { fill: #23282f; }

/* --- r8hZebraForewarn. Flat building blocks beyond the footways, there only to say
   «tettbygd strøk». Deliberately featureless: a window or a door turns them into
   objects the eye stops on, and the subject of the card is the sign and the paint. */
.r9a-block { fill: #a9b3c1; }
:root:not([data-theme="light"]) .r9a-block { fill: #4a5261; }
:root[data-theme="dark"] .r9a-block { fill: #4a5261; }

/* --- r8jRumbleRib. A profiled rib seen in 3/4 view is TWO faces. The top catches the
   light and is the same white as the line it straddles; the front face is the same
   white knocked back, which is what makes the block read as standing PROUD of the
   surface rather than painted on it. Do not equalise them. */
.r9a-rib-top { fill: #f5f7fa; }
.r9a-rib-face { fill: #b9c2cd; }
:root:not([data-theme="light"]) .r9a-rib-face { fill: #8e97a3; }
:root[data-theme="dark"] .r9a-rib-face { fill: #8e97a3; }

/* r8jRumbleRib, macro version. A thin cast shadow off each block's near-right corner:
   at macro scale the top/front pair alone still reads as a flat two-tone shape, and
   the shadow is what puts the block ON the road rather than in it. Kept dark and
   narrow — anything wider reads as a second, dirty rib. */
.r9a-rib-cast { fill: rgba(10, 15, 25, .30); }

/* --- r9d: the driver's-eye scenes. The sky is painted explicitly here rather than
   inherited from `.scene--road`, because these scenes draw their own horizon; both
   of them are therefore `kind: studio`, and this wash needs its own dark-mode rule
   or it sits on the dark card like a lit panel (round-8 trap 10). */
.r9a-dvsky { fill: #cfe3f5; }
:root:not([data-theme="light"]) .r9a-dvsky { fill: #2a3546; }
:root[data-theme="dark"] .r9a-dvsky { fill: #2a3546; }
/* Windscreen furniture. The pillars and header fix the viewpoint as the driver's seat
   and the scale as car-sized — `f5DirtyScreenGlare`'s own reason for its frame. */
.r9a-dvpillar { fill: #2b3240; }
.r9a-dvdash { fill: #363d4b; }
/* In dark mode the pillars and the painted sky converge and the windscreen frame
   disappears, which is the one cue that fixes the viewpoint as the driver's seat. */
:root:not([data-theme="light"]) .r9a-dvpillar { fill: #12161d; }
:root[data-theme="dark"] .r9a-dvpillar { fill: #12161d; }
:root:not([data-theme="light"]) .r9a-dvdash { fill: #1b202a; }
:root[data-theme="dark"] .r9a-dvdash { fill: #1b202a; }

/* r8eTachoGear. A MID-dark dial face inside an explicit pale bezel ring: a near-black
   face (the first brief) loses its silhouette entirely against the dark studio wash. */
.r9a-dial-bezel { fill: #c9d2dd; }
.r9a-dial-face { fill: #2c323d; }
.r9a-tick { stroke: #e7edf5; stroke-width: 3; stroke-linecap: round; }
.r9a-redzone { fill: none; stroke: #d81f3a; stroke-width: 5; }
.r9a-dial-num { fill: #e7edf5; font: 700 13px var(--font); }
.r9a-dial-tag { fill: #9aa5b4; font: 600 10px var(--font); }
.r9a-needle { fill: #e8563f; }
.r9a-hub { fill: #cbd3dd; }
/* The lever. The knob's top face is the one surface the H-gate can be read on, so it
   is the widest thing in the object; the gaiter's dark mouth carries a pale rim for
   the same dark-mode reason as the dial. */
.r9a-gaiter { fill: #3a4150; }
.r9a-gaiter-mouth { fill: #1b1f27; stroke: #7b8593; stroke-width: 2; }
.r9a-gaiter-rib { fill: none; stroke: #4c5464; stroke-width: 3; }
.r9a-shaft { fill: #b9c2cd; }
.r9a-knob-body { fill: #2f3540; }
.r9a-knob-top { fill: #4d5666; }
.r9a-knob-rim { fill: none; stroke: #1b1f27; stroke-width: 2; }
.r9a-gate { fill: none; stroke: #e7edf5; stroke-width: 3; stroke-linecap: round; }
/* ==== END r9a ============================================================= */

/* --- r9d ground paint. These are POLYGONS laid by the driver's-eye camera, so they
   must be FILLED, never stroked. Put them in `.sc-mid` or `.sc-zebra` — the obvious
   move — and `.sc-mid`'s dashed yellow stroke turns each quad into a zigzag outline,
   while `.sc-zebra`'s rule only targets `rect` children and leaves a polygon with no
   fill at all, i.e. BLACK. Both shipped in the first render of this batch. */
.r9a-dvlane { fill: var(--lane); }

/* --- r9aGagateStreet. Bollards across the entry: the one prop that says «vehicles do
   not simply drive through here» without drawing a sign or a barrier. Pale on the
   paving with a dark rim so they do not merge into it in either theme. */
.r9a-bollard circle { fill: #c9d2dd; stroke: rgba(20, 24, 32, .45); stroke-width: 2; }
:root:not([data-theme="light"]) .r9a-bollard circle { fill: #7d8794; }
:root[data-theme="dark"] .r9a-bollard circle { fill: #7d8794; }

/* ==== BEGIN r10 (round 10, 2026-08-19) ====================================
   Nine scenes. Every fill is an explicit colour with an explicit dark-mode
   override where the light value would collapse into the dark studio wash —
   the r6vHazardSwitch fault. No color-mix() against a token that may not
   exist: an invalid color-mix renders BLACK and scenes:check cannot see it. */

/* --- r10MirrorTrinket. The mirror is the scale reference for the pendant, so it
   needs a hard silhouette in both themes: a dark body inside a pale rim. */
.r10-mirror { fill: #2f3540; stroke: #aab4c1; stroke-width: 2; }
.r10-mirror-stem { fill: #454e5d; }
.r10-cord { fill: none; stroke: #9aa5b4; stroke-width: 2.4; }
.r10-cord-ring { fill: none; stroke: #c9d2dd; stroke-width: 2; }
/* Warm, saturated and opaque: the pendant hangs against sky at the top and
   asphalt at the bottom, and a translucent one would vanish across the seam. */
.r10-trinket { fill: #d9642f; stroke: rgba(20, 24, 32, .45); stroke-width: 2; }
.r10-trinket-in { fill: #f0a561; opacity: .85; }
:root:not([data-theme="light"]) .r10-trinket { fill: #b34f22; }
:root[data-theme="dark"] .r10-trinket { fill: #b34f22; }
/* The swing lives on a wrapper <g> with NO transform attribute — CSS transform on
   a node that carries one wins and snaps the group to the origin. */
.r10-swing { transform-box: view-box; transform-origin: 200px 44px; animation: r10-swing 3.8s ease-in-out infinite; }
@keyframes r10-swing { 0%, 100% { transform: rotate(-5deg); } 50% { transform: rotate(5deg); } }

/* --- r10ChildDoorLock. The shut face has to read LIGHTER than the outer skin or the
   door loses its edge; the recess has to read DARKER than the face or the lever looks
   printed on (drawing fault 4). */
.r10-door-skin { fill: #8f9bab; stroke: rgba(20, 24, 32, .35); stroke-width: 2; }
.r10-door-glass { fill: rgba(190, 220, 245, .55); stroke: #6f7b8b; stroke-width: 2; }
.r10-handle { fill: #d3dae3; stroke: rgba(20, 24, 32, .4); stroke-width: 1.6; }
.r10-hinge { fill: #4b5464; }
.r10-door-edge { fill: #d3dae3; }
.r10-notch { fill: #3a4150; }
.r10-door-seam { fill: none; stroke: #6f7b8b; stroke-width: 2; }
/* The waistline crease. Without it the leaf is a plain rounded rectangle and reads as a
   toolbox lid; one horizontal body line under the glass is what makes it a car door. */
.r10-door-crease { fill: none; stroke: rgba(20, 24, 32, .28); stroke-width: 2.5; }
.r10-rubstrip { fill: rgba(20, 24, 32, .30); }
.r10-zoom { fill: none; stroke: #d9642f; stroke-width: 2; opacity: .65; }
.r10-latch { fill: none; stroke: #4b5464; stroke-width: 6; stroke-linecap: round; }
.r10-recess { fill: #3a4150; }
.r10-mark { fill: #cbd3dd; }
.r10-lever { fill: #e7edf5; stroke: #2f3540; stroke-width: 2; }
.r10-lever-pivot { fill: #2f3540; }
/* The magnifier needs its own opaque plate: without one the enlarged detail floats on
   the studio wash and the two taper lines read as an arrow rather than a zoom. */
.r10-callout-fill { fill: var(--surface-2); stroke: none; }
.r10-callout { fill: none; stroke: #d9642f; stroke-width: 2.5; opacity: .8; }
:root:not([data-theme="light"]) .r10-door-skin { fill: #46505f; }
:root[data-theme="dark"] .r10-door-skin { fill: #46505f; }
:root:not([data-theme="light"]) .r10-door-edge { fill: #7d8794; }
:root[data-theme="dark"] .r10-door-edge { fill: #7d8794; }
:root:not([data-theme="light"]) .r10-handle { fill: #7d8794; }
:root[data-theme="dark"] .r10-handle { fill: #7d8794; }

/* --- r10Catalyst. The cut-away window and its honeycomb are the only thing that says
   "catalyst" rather than "silencer", so the cells must stay clearly darker than the
   window they sit in and the window clearly darker than the shell. */
.r10-underbody { fill: #6f7b8b; }
.r10-sill { fill: none; stroke: rgba(20, 24, 32, .4); stroke-width: 3; }
/* The two tyres are what make this frame read as the underside of a car, so in dark
   mode they must not sink into the studio wash: at #2b3038 only the pale rims showed
   and they read as two floating discs. Lifted, with a rim line on the tread. */
.r10-tyre { fill: #2b3038; stroke: rgba(200, 212, 228, .35); stroke-width: 2; }
.r10-rim { fill: #aab4c1; }
:root:not([data-theme="light"]) .r10-tyre { fill: #545c68; }
:root[data-theme="dark"] .r10-tyre { fill: #545c68; }
:root:not([data-theme="light"]) .r10-rim { fill: #cbd3dd; }
:root[data-theme="dark"] .r10-rim { fill: #cbd3dd; }
.r10-hanger { fill: none; stroke: #4b5464; stroke-width: 4; }
.r10-pipe { fill: #aab4c1; }
.r10-cat-shell { fill: #c9d2dd; stroke: rgba(20, 24, 32, .35); stroke-width: 2; }
.r10-cat-cone { fill: #aab4c1; }
.r10-cat-cut { fill: #3a4150; }
.r10-cell rect { fill: #8b96a5; }
.r10-cat-seam { fill: none; stroke: rgba(20, 24, 32, .35); stroke-width: 2; }
:root:not([data-theme="light"]) .r10-underbody { fill: #3f4854; }
:root[data-theme="dark"] .r10-underbody { fill: #3f4854; }
:root:not([data-theme="light"]) .r10-cat-shell { fill: #8b96a5; }
:root[data-theme="dark"] .r10-cat-shell { fill: #8b96a5; }
:root:not([data-theme="light"]) .r10-pipe { fill: #79838f; }
:root[data-theme="dark"] .r10-pipe { fill: #79838f; }

/* --- r10EngineHeater. Frost is a pale wash over the verge, never over the asphalt:
   a white carriageway would turn the card into a winter-grip question. */
.r10-frost { fill: rgba(232, 242, 252, .72); }
.r10-rime circle { fill: #ffffff; opacity: .85; }
.r10-socketbox { fill: #d9dfe7; stroke: #4b5464; stroke-width: 2; }
.r10-socket { fill: #2f3540; }
.r10-cable { fill: none; stroke: #2f3540; stroke-width: 3; stroke-linecap: round; }
.r10-inlet { fill: #2f3540; }
:root:not([data-theme="light"]) .r10-frost { fill: rgba(196, 214, 232, .40); }
:root[data-theme="dark"] .r10-frost { fill: rgba(196, 214, 232, .40); }
:root:not([data-theme="light"]) .r10-cable { stroke: #cbd3dd; }
:root[data-theme="dark"] .r10-cable { stroke: #cbd3dd; }
:root:not([data-theme="light"]) .r10-socketbox { fill: #7d8794; }
:root[data-theme="dark"] .r10-socketbox { fill: #7d8794; }
/* A car on the end of a heater cable is parked, by definition — the same reason
   vhEvCharge freezes its wheels and its road flow. */
[data-scene="r10EngineHeater"] .sc-wheel,
[data-scene="r10EngineHeater"] .sc-flow,
[data-scene="r10EngineHeater"] .sc-flow line { animation: none; }

/* --- r10OncomingFlash. A PULSE, not a steady blaze: the steady one is
   fxDazzleOncoming's, and this card is about reading a brief signal. */
/* A faint glow is always present so the headlamps read at every animation phase — the
   first version dropped to opacity 0 for 70 % of the cycle, and scene-check froze it
   there, i.e. the card would often show a plain night meeting and say nothing at all. */
.r10-flash circle { fill: #fff4c2; animation: r10-flash 1.7s linear infinite; }
@keyframes r10-flash {
  0%, 18% { opacity: .95; } 24%, 32% { opacity: .18; }
  38%, 56% { opacity: .95; } 62%, 100% { opacity: .18; }
}
/* ==== END r10 ============================================================= */

/* ==== BEGIN r11 (round 11, 2026-08-22) ====================================
   Ten scenes, ten cards. Only r11WheelShake needs paint of its own: the road
   scenes are built entirely from shared primitives, and the four telltale
   scenes reuse the kv-lamp/kvCluster system dashLamps established. */

/* --- r11WheelShake. The tremor is a small rotate oscillation on a wrapper <g>
   that carries NO transform attribute (the shared rule), pivoting on the rim's
   own centre. The arcs are static, so a reduced-motion reader still sees a
   trembling wheel rather than a parked one. The needle is deliberately NOT
   sc-needle, which sweeps — this dial's whole job is a STEADY speed. */
.r11-shake { transform-box: view-box; transform-origin: 140px 94px; animation: r11-shake .3s ease-in-out infinite; }
@keyframes r11-shake { 0%, 100% { transform: rotate(-1.7deg); } 50% { transform: rotate(1.7deg); } }
/* ==== END r11 ============================================================= */

/* the new badge draws its own ring, so it can be smaller than the old one */
.scene .sc-ask circle + circle { fill: color-mix(in srgb, var(--brand) 92%, #000); }

/* Question cards (exam, practice, review): hovering the picture widens it 50 % (460 → 690 px) to the right, in the
   layout, so its taller box pushes the question below it down. Mouse/trackpad only. */
@media (hover: hover) and (pointer: fine) {
  .qcard .scene { position: relative; z-index: 1;
    transition: max-width .28s cubic-bezier(.2,.8,.3,1), box-shadow .28s ease, opacity .65s cubic-bezier(.22,.61,.36,1), transform .65s cubic-bezier(.22,.61,.36,1); }
  .qcard .scene:hover { max-width: min(690px, 92vw); z-index: 20;   /* 460 px (the card cap above) × 1.5 */ box-shadow: 0 18px 48px rgba(16,24,40,.28); }
  .qcard .scene:hover .sc-svg, .qcard .scene--photo:hover .scene-photo { transform: none; }
}
@media (hover: hover) and (pointer: fine) and (prefers-reduced-motion: reduce) {
  .qcard .scene { transition: none; }
}
